From 041b39d230f492f8f5f2059928cdfd151a938fb5 Mon Sep 17 00:00:00 2001 From: Ximin Luo Date: Tue, 19 Sep 2017 12:59:56 +0200 Subject: [PATCH] New upstream version 1.20.0+dfsg1 --- CONTRIBUTING.md | 1 + COPYRIGHT | 6 - README.md | 9 +- configure | 2 + src/Cargo.lock | 749 +-- src/Cargo.toml | 1 + src/bootstrap/bin/rustc.rs | 67 +- src/bootstrap/bin/rustdoc.rs | 10 +- src/bootstrap/bootstrap.py | 55 +- src/bootstrap/cc.rs | 14 +- src/bootstrap/channel.rs | 10 +- src/bootstrap/check.rs | 149 +- src/bootstrap/compile.rs | 71 +- src/bootstrap/config.rs | 39 +- src/bootstrap/config.toml.example | 11 + src/bootstrap/dist.rs | 78 +- src/bootstrap/doc.rs | 43 +- src/bootstrap/flags.rs | 63 +- src/bootstrap/install.rs | 2 +- src/bootstrap/lib.rs | 189 +- src/bootstrap/metadata.rs | 2 +- src/bootstrap/mk/Makefile.in | 2 +- src/bootstrap/native.rs | 16 +- src/bootstrap/sanity.rs | 163 +- src/bootstrap/step.rs | 197 +- src/bootstrap/util.rs | 15 +- src/build_helper/lib.rs | 5 +- src/ci/docker/arm-android/Dockerfile | 25 +- src/ci/docker/armhf-gnu/Dockerfile | 11 +- src/ci/docker/asmjs/Dockerfile | 39 + src/ci/docker/cross/Dockerfile | 2 - .../disabled/dist-aarch64-android/Dockerfile | 24 +- .../disabled/dist-armv7-android/Dockerfile | 22 +- .../disabled/dist-i686-android/Dockerfile | 22 +- .../disabled/dist-x86_64-android/Dockerfile | 24 +- src/ci/docker/disabled/wasm32-exp/Dockerfile | 42 + src/ci/docker/disabled/wasm32-exp/node.sh | 18 + src/ci/docker/disabled/wasm32/Dockerfile | 40 + src/ci/docker/disabled/wasm32/node.sh | 18 + src/ci/docker/dist-aarch64-linux/Dockerfile | 64 +- src/ci/docker/dist-android/Dockerfile | 22 +- src/ci/docker/dist-arm-linux/Dockerfile | 64 +- src/ci/docker/dist-armhf-linux/Dockerfile | 64 +- src/ci/docker/dist-armv7-linux/Dockerfile | 64 +- src/ci/docker/dist-fuchsia/Dockerfile | 11 +- .../docker/dist-i586-gnu-i686-musl/Dockerfile | 11 +- src/ci/docker/dist-i686-freebsd/Dockerfile | 11 +- src/ci/docker/dist-i686-linux/Dockerfile | 8 +- src/ci/docker/dist-mips-linux/Dockerfile | 12 +- src/ci/docker/dist-mips64-linux/Dockerfile | 11 +- src/ci/docker/dist-mips64el-linux/Dockerfile | 12 +- src/ci/docker/dist-mipsel-linux/Dockerfile | 11 +- src/ci/docker/dist-powerpc-linux/Dockerfile | 64 +- src/ci/docker/dist-powerpc64-linux/Dockerfile | 64 +- .../docker/dist-powerpc64le-linux/Dockerfile | 64 +- src/ci/docker/dist-s390x-linux/Dockerfile | 64 +- src/ci/docker/dist-x86_64-freebsd/Dockerfile | 11 +- src/ci/docker/dist-x86_64-linux/Dockerfile | 8 +- src/ci/docker/dist-x86_64-musl/Dockerfile | 11 +- src/ci/docker/dist-x86_64-netbsd/Dockerfile | 64 +- src/ci/docker/emscripten/Dockerfile | 41 - src/ci/docker/emscripten/build-emscripten.sh | 53 - src/ci/docker/i686-gnu-nopt/Dockerfile | 12 +- src/ci/docker/i686-gnu/Dockerfile | 12 +- src/ci/docker/run.sh | 1 - src/ci/docker/scripts/android-base-apt-get.sh | 27 + src/ci/docker/scripts/cross-apt-packages.sh | 36 + src/ci/docker/scripts/crosstool-ng.sh | 20 + src/ci/docker/scripts/emscripten-wasm.sh | 47 + src/ci/docker/scripts/emscripten.sh | 53 + src/ci/docker/scripts/make3.sh | 19 + src/ci/docker/scripts/rustbuild-setup.sh | 14 + src/ci/docker/x86_64-gnu-aux/Dockerfile | 11 +- src/ci/docker/x86_64-gnu-debug/Dockerfile | 11 +- src/ci/docker/x86_64-gnu-distcheck/Dockerfile | 11 +- .../x86_64-gnu-full-bootstrap/Dockerfile | 11 +- .../docker/x86_64-gnu-incremental/Dockerfile | 11 +- src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile | 11 +- src/ci/docker/x86_64-gnu-nopt/Dockerfile | 11 +- src/ci/docker/x86_64-gnu/Dockerfile | 13 +- src/ci/init_repo.sh | 49 +- src/doc/book/second-edition/dictionary.txt | 3 +- .../book/second-edition/nostarch/chapter05.md | 73 +- .../book/second-edition/nostarch/chapter11.md | 359 +- .../book/second-edition/nostarch/chapter12.md | 1453 ++--- .../second-edition/nostarch/odt/chapter02.doc | Bin 218624 -> 0 bytes .../nostarch/odt/chapter03.docx | Bin 71651 -> 0 bytes .../nostarch/odt/chapter04.docx | Bin 325348 -> 0 bytes .../nostarch/odt/chapter05.docx | Bin 44509 -> 0 bytes .../nostarch/odt/chapter06.docx | Bin 49580 -> 0 bytes .../nostarch/odt/chapter07.docx | Bin 48867 -> 0 bytes .../nostarch/odt/chapter08.docx | Bin 41633 -> 0 bytes .../nostarch/odt/chapter09.docx | Bin 47156 -> 0 bytes src/doc/book/second-edition/src/SUMMARY.md | 6 +- .../src/appendix-06-translation.md | 8 +- .../src/ch01-01-installation.md | 13 + .../src/ch04-01-what-is-ownership.md | 2 +- .../src/ch05-01-defining-structs.md | 47 +- .../src/ch05-02-example-structs.md | 20 +- .../src/ch05-03-method-syntax.md | 16 +- .../book/second-edition/src/ch06-02-match.md | 6 +- .../second-edition/src/ch08-02-strings.md | 2 +- .../second-edition/src/ch11-00-testing.md | 29 +- .../src/ch11-01-writing-tests.md | 173 +- .../src/ch11-02-running-tests.md | 53 +- .../src/ch11-03-test-organization.md | 78 +- .../src/ch12-00-an-io-project.md | 85 +- ...h12-01-accepting-command-line-arguments.md | 151 +- .../src/ch12-02-reading-a-file.md | 88 +- ...improving-error-handling-and-modularity.md | 530 +- ...2-04-testing-the-librarys-functionality.md | 197 +- ...2-05-working-with-environment-variables.md | 204 +- ...-06-writing-to-stderr-instead-of-stdout.md | 152 +- .../src/ch15-05-interior-mutability.md | 10 +- .../src/ch17-03-oo-design-patterns.md | 4 +- .../src/ch19-02-advanced-lifetimes.md | 60 +- .../src/ch19-04-advanced-types.md | 8 +- src/doc/book/second-edition/theme/index.hbs | 1 + .../book/second-edition/tools/docx-to-md.xsl | 15 +- src/doc/grammar.md | 26 +- src/doc/nomicon/src/SUMMARY.md | 1 + src/doc/nomicon/src/aliasing.md | 135 + src/doc/nomicon/src/destructors.md | 43 +- src/doc/nomicon/src/dropck.md | 30 +- src/doc/nomicon/src/references.md | 172 +- src/doc/nomicon/src/vec-final.md | 35 +- src/doc/reference/src/attributes.md | 8 +- .../src/behavior-considered-undefined.md | 2 +- .../src/behavior-not-considered-unsafe.md | 50 +- src/doc/reference/src/expressions.md | 22 +- src/doc/reference/src/items.md | 88 +- src/doc/reference/src/linkage.md | 4 +- src/doc/reference/src/statements.md | 7 +- src/doc/reference/src/tokens.md | 3 +- src/doc/reference/src/undocumented.md | 2 - src/doc/rustdoc/src/SUMMARY.md | 8 + src/doc/rustdoc/src/command-line-arguments.md | 348 ++ src/doc/rustdoc/src/documentation-tests.md | 3 + src/doc/rustdoc/src/in-source-directives.md | 3 + src/doc/rustdoc/src/passes.md | 3 + src/doc/rustdoc/src/plugins.md | 3 + src/doc/rustdoc/src/what-is-rustdoc.md | 131 + src/doc/unstable-book/src/SUMMARY.md | 218 - .../src/compiler-flags/profile.md | 21 + .../src/language-features/abi-sysv64.md | 7 - .../src/language-features/abi-unadjusted.md | 6 - .../src/language-features/abi-vectorcall.md | 7 - .../language-features/abi-x86-interrupt.md | 7 - .../language-features/allocator-internals.md | 7 + .../src/language-features/allocator.md | 119 - .../allow-internal-unstable.md | 6 - .../src/language-features/asm.md | 2 +- .../language-features/associated-consts.md | 85 - .../associated-type-defaults.md | 10 - .../language-features/cfg-target-feature.md | 10 - .../cfg-target-has-atomic.md | 10 - .../cfg-target-thread-local.md | 10 - .../language-features/cfg-target-vendor.md | 10 - .../src/language-features/custom-attribute.md | 10 - .../src/language-features/custom-derive.md | 10 - .../src/language-features/decl-macro.md | 10 - .../default-type-parameter-fallback.md | 10 - .../language-features/drop-types-in-const.md | 10 - .../src/language-features/dropck-eyepatch.md | 10 - .../language-features/dropck-parametricity.md | 10 - .../exclusive-range-pattern.md | 10 - .../src/language-features/fundamental.md | 10 - .../language-features/generic-param-attrs.md | 10 - .../src/language-features/global-allocator.md | 71 + .../{global_asm.md => global-asm.md} | 0 .../src/language-features/lang-items.md | 6 +- .../src/language-features/link-cfg.md | 10 - .../language-features/link-llvm-intrinsics.md | 10 - .../src/language-features/linkage.md | 10 - .../src/language-features/log-syntax.md | 10 - .../src/language-features/macro-reexport.md | 10 - .../src/language-features/main.md | 10 - .../src/language-features/naked-functions.md | 10 - .../src/language-features/needs-allocator.md | 10 - .../language-features/needs-panic-runtime.md | 10 - .../src/language-features/never-type.md | 10 - .../src/language-features/no-core.md | 10 - .../src/language-features/no-debug.md | 10 - .../omit-gdb-pretty-printer-section.md | 6 - .../language-features/optin-builtin-traits.md | 9 - .../overlapping-marker-traits.md | 7 - .../src/language-features/panic-runtime.md | 10 - .../language-features/placement-in-syntax.md | 10 - .../language-features/platform-intrinsics.md | 10 - .../src/language-features/prelude-import.md | 6 - .../src/language-features/profiler-runtime.md | 5 + .../src/language-features/quote.md | 10 - .../src/language-features/repr-align.md | 11 - .../src/language-features/repr-simd.md | 10 - .../src/language-features/rustc-attrs.md | 10 - .../rustc-diagnostic-macros.md | 6 - .../language-features/sanitizer-runtime.md | 6 - .../src/language-features/simd-ffi.md | 10 - .../src/language-features/simd.md | 10 - .../src/language-features/specialization.md | 10 - .../src/language-features/staged-api.md | 6 - .../src/language-features/start.md | 10 - .../src/language-features/static-nobundle.md | 10 - .../language-features/stmt-expr-attributes.md | 10 - .../struct-field-attributes.md | 10 - .../src/language-features/structural-match.md | 10 - .../src/language-features/target-feature.md | 6 - .../src/language-features/thread-local.md | 10 - .../src/language-features/trace-macros.md | 10 - .../src/language-features/type-ascription.md | 10 - .../src/language-features/unboxed-closures.md | 10 - .../unsized-tuple-coercion.md | 27 + .../src/language-features/untagged-unions.md | 10 - .../language-features/unwind-attributes.md | 6 - .../language-features/use-extern-macros.md | 10 - .../src/library-features/alloc.md | 7 - .../src/library-features/allocator-api.md | 15 + .../src/library-features/as-c-str.md | 8 - .../src/library-features/ascii-ctype.md | 5 - .../src/library-features/box-heap.md | 7 - .../library-features/char-error-internals.md | 5 + .../src/library-features/char-escape-debug.md | 7 - .../src/library-features/coerce-unsized.md | 7 - .../library-features/collection-placement.md | 7 - .../src/library-features/collections-range.md | 7 - .../library-features/compiler-builtins-lib.md | 35 - .../library-features/concat-idents-macro.md | 7 - .../src/library-features/core-char-ext.md | 7 - .../src/library-features/core-float.md | 7 - .../src/library-features/core-slice-ext.md | 7 - .../src/library-features/core-str-ext.md | 7 - .../src/library-features/decode-utf8.md | 7 - .../library-features/discriminant-value.md | 7 - .../src/library-features/error-type-id.md | 7 - .../library-features/exact-size-is-empty.md | 7 - .../src/library-features/fixed-size-array.md | 7 - .../src/library-features/float-bits-conv.md | 7 - .../src/library-features/fmt-flags-align.md | 7 - .../src/library-features/fn-traits.md | 7 - .../src/library-features/fnbox.md | 7 - .../from_utf8_error_as_bytes.md | 7 - .../src/library-features/fused.md | 7 - .../src/library-features/get-type-id.md | 7 - .../src/library-features/heap-api.md | 7 - .../src/library-features/i128.md | 7 - .../src/library-features/inclusive-range.md | 7 - .../src/library-features/integer-atomics.md | 7 - .../src/library-features/into-boxed-c-str.md | 7 - .../src/library-features/into-boxed-os-str.md | 7 - .../src/library-features/into-boxed-path.md | 7 - .../unstable-book/src/library-features/io.md | 7 - .../unstable-book/src/library-features/ip.md | 7 - .../src/library-features/iter-rfind.md | 7 - .../src/library-features/iterator-for-each.md | 17 + .../src/library-features/iterator-step-by.md | 7 - .../library-features/linked-list-extras.md | 7 - .../src/library-features/lookup-host.md | 7 - .../library-features/more-io-inner-methods.md | 11 - .../src/library-features/mpsc-select.md | 5 - .../src/library-features/needs-drop.md | 7 - .../src/library-features/never-type-impls.md | 7 - .../src/library-features/nonzero.md | 7 - .../src/library-features/offset-to.md | 7 - .../src/library-features/once-poison.md | 7 - .../unstable-book/src/library-features/oom.md | 7 - .../src/library-features/option-entry.md | 7 - .../src/library-features/panic-abort.md | 7 - .../src/library-features/panic-unwind.md | 7 - .../src/library-features/pattern.md | 7 - .../src/library-features/placement-in.md | 7 - .../placement-new-protocol.md | 7 - .../library-features/proc-macro-internals.md | 7 - .../src/library-features/proc-macro.md | 7 + .../library-features/profiler-runtime-lib.md | 5 + .../library-features/question-mark-carrier.md | 13 - .../src/library-features/range-contains.md | 7 - .../unstable-book/src/library-features/raw.md | 7 - .../src/library-features/read-initializer.md | 7 + .../src/library-features/rustc-private.md | 7 - .../src/library-features/shared.md | 7 - .../src/library-features/sip-hash-13.md | 7 - .../src/library-features/slice-concat-ext.md | 7 - .../src/library-features/slice-get-slice.md | 7 - .../src/library-features/slice-rotate.md | 7 - .../src/library-features/sort-unstable.md | 40 - .../src/library-features/step-by.md | 7 - .../src/library-features/step-trait.md | 7 - .../src/library-features/str-box-extras.md | 9 - .../library-features/str-checked-slicing.md | 7 - .../src/library-features/str-escape.md | 7 - .../src/library-features/str-mut-extras.md | 8 - .../library-features/thread-local-state.md | 7 - .../library-features/toowned-clone-into.md | 7 - .../src/library-features/trusted-len.md | 7 - .../src/library-features/try-from.md | 7 - .../src/library-features/unicode.md | 7 - .../src/library-features/unique.md | 7 - .../src/library-features/unsize.md | 7 - .../library-features/utf8-error-error-len.md | 7 - .../src/library-features/vec-remove-item.md | 7 - .../library-features/vec-resize-default.md | 7 - src/etc/debugger_pretty_printers_common.py | 14 + src/etc/gdb_rust_pretty_printing.py | 39 +- ...{libcollections.natvis => liballoc.natvis} | 14 +- src/etc/platform-intrinsics/arm.json | 2 +- src/etc/rust-windbg.cmd | 2 +- src/grammar/lexer.l | 2 +- src/liballoc/Cargo.toml | 9 + src/liballoc/allocator.rs | 1078 ++++ src/liballoc/arc.rs | 18 +- .../benches/btree/map.rs | 0 .../benches/btree/mod.rs | 0 .../benches/lib.rs | 2 +- .../benches/linked_list.rs | 0 .../benches/slice.rs | 54 +- .../benches/str.rs | 0 .../benches/string.rs | 0 .../benches/vec.rs | 0 .../benches/vec_deque.rs | 0 .../binary_heap.rs | 0 src/{libcollections => liballoc}/borrow.rs | 0 src/liballoc/boxed.rs | 37 +- src/{libcollections => liballoc}/btree/map.rs | 8 +- src/{libcollections => liballoc}/btree/mod.rs | 0 .../btree/node.rs | 26 +- .../btree/search.rs | 0 src/{libcollections => liballoc}/btree/set.rs | 0 src/{libcollections => liballoc}/fmt.rs | 10 +- src/liballoc/heap.rs | 347 +- src/liballoc/lib.rs | 161 +- .../linked_list.rs | 2 +- src/liballoc/macros.rs | 83 + src/liballoc/oom.rs | 61 - src/{libcollections => liballoc}/range.rs | 16 +- src/liballoc/raw_vec.rs | 360 +- src/liballoc/rc.rs | 23 +- src/{libcollections => liballoc}/slice.rs | 35 +- src/liballoc/str.rs | 1981 ++++++- src/{libcollections => liballoc}/string.rs | 137 +- .../tests/binary_heap.rs | 0 .../tests/btree/map.rs | 0 .../tests/btree/mod.rs | 0 .../tests/btree/set.rs | 0 .../tests/cow_str.rs | 0 src/{libcollections => liballoc}/tests/fmt.rs | 0 src/{libcollections => liballoc}/tests/lib.rs | 5 +- .../tests/linked_list.rs | 0 .../tests/slice.rs | 50 +- src/{libcollections => liballoc}/tests/str.rs | 42 + .../tests/string.rs | 0 src/{libcollections => liballoc}/tests/vec.rs | 5 + .../tests/vec_deque.rs | 3 +- src/{libcollections => liballoc}/vec.rs | 35 +- src/{libcollections => liballoc}/vec_deque.rs | 2 +- src/liballoc_jemalloc/Cargo.toml | 4 + src/liballoc_jemalloc/build.rs | 7 +- src/liballoc_jemalloc/lib.rs | 201 +- src/liballoc_system/Cargo.toml | 3 + src/liballoc_system/lib.rs | 479 +- src/liballoc_system/old.rs | 268 + src/libarena/lib.rs | 2 - src/libcollections/Cargo.toml | 9 - src/libcollections/lib.rs | 194 +- src/libcollections/macros.rs | 92 - src/libcollections/str.rs | 1997 ------- src/libcompiler_builtins/.travis.yml | 58 + src/libcompiler_builtins/Cargo.toml | 46 +- src/libcompiler_builtins/LICENSE.TXT | 91 + src/libcompiler_builtins/README.md | 397 ++ src/libcompiler_builtins/appveyor.yml | 45 + src/libcompiler_builtins/build.rs | 4770 +++++++++++++++-- .../aarch64-unknown-linux-gnu/Dockerfile | 9 + .../arm-unknown-linux-gnueabi/Dockerfile | 9 + .../arm-unknown-linux-gnueabihf/Dockerfile | 8 + .../armv7-unknown-linux-gnueabihf/Dockerfile | 8 + .../docker/i586-unknown-linux-gnu/Dockerfile | 4 + .../docker/i686-unknown-linux-gnu/Dockerfile | 4 + .../docker/mips-unknown-linux-gnu/Dockerfile | 11 + .../mips64-unknown-linux-gnuabi64/Dockerfile | 14 + .../Dockerfile | 13 + .../mipsel-unknown-linux-gnu/Dockerfile | 11 + .../powerpc-unknown-linux-gnu/Dockerfile | 11 + .../powerpc64-unknown-linux-gnu/Dockerfile | 12 + .../powerpc64le-unknown-linux-gnu/Dockerfile | 12 + .../ci/docker/thumbv6m-linux-eabi/Dockerfile | 9 + .../ci/docker/thumbv7em-linux-eabi/Dockerfile | 9 + .../docker/thumbv7em-linux-eabihf/Dockerfile | 9 + .../ci/docker/thumbv7m-linux-eabi/Dockerfile | 9 + .../x86_64-unknown-linux-gnu/Dockerfile | 4 + src/libcompiler_builtins/ci/run-docker.sh | 36 + src/libcompiler_builtins/ci/run.sh | 132 + .../compiler-rt/.arcconfig | 0 .../compiler-rt/CMakeLists.txt | 0 .../compiler-rt/CODE_OWNERS.TXT | 0 .../compiler-rt/CREDITS.TXT | 0 .../compiler-rt/LICENSE.TXT | 0 .../compiler-rt/README.txt | 0 .../cmake/Modules/AddCompilerRT.cmake | 0 .../cmake/Modules/BuiltinTests.cmake | 0 .../cmake/Modules/CompilerRTCompile.cmake | 0 .../cmake/Modules/CompilerRTDarwinUtils.cmake | 0 .../cmake/Modules/CompilerRTLink.cmake | 0 .../cmake/Modules/CompilerRTUtils.cmake | 0 .../cmake/Modules/SanitizerUtils.cmake | 0 .../compiler-rt/cmake/base-config-ix.cmake | 0 .../compiler-rt/cmake/builtin-config-ix.cmake | 0 .../compiler-rt/cmake/caches/Apple.cmake | 0 .../compiler-rt/cmake/config-ix.cmake | 0 .../compiler-rt/docs/TestingGuide.rst | 0 .../compiler-rt/include/CMakeLists.txt | 0 .../include/sanitizer/allocator_interface.h | 0 .../include/sanitizer/asan_interface.h | 0 .../include/sanitizer/common_interface_defs.h | 0 .../include/sanitizer/coverage_interface.h | 0 .../include/sanitizer/dfsan_interface.h | 0 .../include/sanitizer/esan_interface.h | 0 .../include/sanitizer/linux_syscall_hooks.h | 0 .../include/sanitizer/lsan_interface.h | 0 .../include/sanitizer/msan_interface.h | 0 .../include/sanitizer/tsan_interface_atomic.h | 0 .../compiler-rt/include/xray/xray_interface.h | 0 .../compiler-rt/include/xray/xray_records.h | 0 .../compiler-rt/lib/BlocksRuntime/Block.h | 0 .../lib/BlocksRuntime/Block_private.h | 0 .../compiler-rt/lib/BlocksRuntime/data.c | 0 .../compiler-rt/lib/BlocksRuntime/runtime.c | 0 .../compiler-rt/lib/CMakeLists.txt | 0 .../compiler-rt/lib/asan/.clang-format | 0 .../compiler-rt/lib/asan/CMakeLists.txt | 0 .../compiler-rt/lib/asan/README.txt | 0 .../compiler-rt/lib/asan/asan.syms.extra | 0 .../compiler-rt/lib/asan/asan_activation.cc | 0 .../compiler-rt/lib/asan/asan_activation.h | 0 .../lib/asan/asan_activation_flags.inc | 0 .../compiler-rt/lib/asan/asan_allocator.cc | 0 .../compiler-rt/lib/asan/asan_allocator.h | 0 .../compiler-rt/lib/asan/asan_blacklist.txt | 0 .../compiler-rt/lib/asan/asan_debugging.cc | 0 .../compiler-rt/lib/asan/asan_descriptions.cc | 0 .../compiler-rt/lib/asan/asan_descriptions.h | 0 .../compiler-rt/lib/asan/asan_errors.cc | 0 .../compiler-rt/lib/asan/asan_errors.h | 0 .../compiler-rt/lib/asan/asan_fake_stack.cc | 0 .../compiler-rt/lib/asan/asan_fake_stack.h | 0 .../compiler-rt/lib/asan/asan_flags.cc | 0 .../compiler-rt/lib/asan/asan_flags.h | 0 .../compiler-rt/lib/asan/asan_flags.inc | 0 .../compiler-rt/lib/asan/asan_globals.cc | 0 .../compiler-rt/lib/asan/asan_globals_win.cc | 0 .../compiler-rt/lib/asan/asan_globals_win.h | 0 .../compiler-rt/lib/asan/asan_init_version.h | 0 .../compiler-rt/lib/asan/asan_interceptors.cc | 0 .../compiler-rt/lib/asan/asan_interceptors.h | 0 .../lib/asan/asan_interface_internal.h | 0 .../compiler-rt/lib/asan/asan_internal.h | 0 .../compiler-rt/lib/asan/asan_linux.cc | 0 .../compiler-rt/lib/asan/asan_lock.h | 0 .../compiler-rt/lib/asan/asan_mac.cc | 0 .../compiler-rt/lib/asan/asan_malloc_linux.cc | 0 .../compiler-rt/lib/asan/asan_malloc_mac.cc | 0 .../compiler-rt/lib/asan/asan_malloc_win.cc | 0 .../compiler-rt/lib/asan/asan_mapping.h | 0 .../lib/asan/asan_memory_profile.cc | 0 .../compiler-rt/lib/asan/asan_new_delete.cc | 0 .../compiler-rt/lib/asan/asan_poisoning.cc | 0 .../compiler-rt/lib/asan/asan_poisoning.h | 0 .../compiler-rt/lib/asan/asan_posix.cc | 0 .../compiler-rt/lib/asan/asan_preinit.cc | 0 .../compiler-rt/lib/asan/asan_report.cc | 0 .../compiler-rt/lib/asan/asan_report.h | 0 .../compiler-rt/lib/asan/asan_rtl.cc | 0 .../lib/asan/asan_scariness_score.h | 0 .../compiler-rt/lib/asan/asan_stack.cc | 0 .../compiler-rt/lib/asan/asan_stack.h | 0 .../compiler-rt/lib/asan/asan_stats.cc | 0 .../compiler-rt/lib/asan/asan_stats.h | 0 .../compiler-rt/lib/asan/asan_suppressions.cc | 0 .../compiler-rt/lib/asan/asan_suppressions.h | 0 .../compiler-rt/lib/asan/asan_thread.cc | 0 .../compiler-rt/lib/asan/asan_thread.h | 0 .../compiler-rt/lib/asan/asan_win.cc | 0 .../lib/asan/asan_win_dll_thunk.cc | 0 .../asan/asan_win_dynamic_runtime_thunk.cc | 0 .../lib/asan/scripts/CMakeLists.txt | 0 .../lib/asan/scripts/asan_device_setup | 0 .../lib/asan/scripts/asan_symbolize.py | 0 .../compiler-rt/lib/asan/tests/CMakeLists.txt | 0 .../lib/asan/tests/asan_asm_test.cc | 0 .../lib/asan/tests/asan_benchmarks_test.cc | 0 .../lib/asan/tests/asan_exceptions_test.cc | 0 .../lib/asan/tests/asan_fake_stack_test.cc | 0 .../lib/asan/tests/asan_globals_test.cc | 0 .../lib/asan/tests/asan_interface_test.cc | 0 .../tests/asan_internal_interface_test.cc | 0 .../lib/asan/tests/asan_mac_test.cc | 0 .../lib/asan/tests/asan_mac_test.h | 0 .../lib/asan/tests/asan_mac_test_helpers.mm | 0 .../lib/asan/tests/asan_mem_test.cc | 0 .../lib/asan/tests/asan_noinst_test.cc | 0 .../lib/asan/tests/asan_oob_test.cc | 0 .../asan/tests/asan_racy_double_free_test.cc | 0 .../lib/asan/tests/asan_str_test.cc | 0 .../compiler-rt/lib/asan/tests/asan_test.cc | 0 .../lib/asan/tests/asan_test.ignore | 0 .../lib/asan/tests/asan_test_config.h | 0 .../lib/asan/tests/asan_test_main.cc | 0 .../lib/asan/tests/asan_test_utils.h | 0 .../compiler-rt/lib/asan/weak_symbols.txt | 0 .../compiler-rt/lib/builtins/CMakeLists.txt | 0 .../lib/builtins/Darwin-excludes/10.4.txt | 0 .../builtins/Darwin-excludes/CMakeLists.txt | 0 .../lib/builtins/Darwin-excludes/README.TXT | 0 .../builtins/Darwin-excludes/ios-armv7.txt | 0 .../builtins/Darwin-excludes/ios-armv7s.txt | 0 .../lib/builtins/Darwin-excludes/ios.txt | 0 .../builtins/Darwin-excludes/ios6-armv7.txt | 0 .../builtins/Darwin-excludes/ios6-armv7s.txt | 0 .../builtins/Darwin-excludes/ios7-arm64.txt | 0 .../builtins/Darwin-excludes/iossim-i386.txt | 0 .../Darwin-excludes/iossim-x86_64.txt | 0 .../lib/builtins/Darwin-excludes/iossim.txt | 0 .../lib/builtins/Darwin-excludes/osx-i386.txt | 0 .../lib/builtins/Darwin-excludes/osx.txt | 0 .../compiler-rt/lib/builtins/README.txt | 0 .../compiler-rt/lib/builtins/absvdi2.c | 0 .../compiler-rt/lib/builtins/absvsi2.c | 0 .../compiler-rt/lib/builtins/absvti2.c | 0 .../compiler-rt/lib/builtins/adddf3.c | 0 .../compiler-rt/lib/builtins/addsf3.c | 0 .../compiler-rt/lib/builtins/addtf3.c | 0 .../compiler-rt/lib/builtins/addvdi3.c | 0 .../compiler-rt/lib/builtins/addvsi3.c | 0 .../compiler-rt/lib/builtins/addvti3.c | 0 .../lib/builtins/apple_versioning.c | 0 .../compiler-rt/lib/builtins/arm/adddf3vfp.S | 0 .../compiler-rt/lib/builtins/arm/addsf3vfp.S | 0 .../lib/builtins/arm/aeabi_cdcmp.S | 0 .../builtins/arm/aeabi_cdcmpeq_check_nan.c | 0 .../lib/builtins/arm/aeabi_cfcmp.S | 0 .../builtins/arm/aeabi_cfcmpeq_check_nan.c | 0 .../compiler-rt/lib/builtins/arm/aeabi_dcmp.S | 0 .../compiler-rt/lib/builtins/arm/aeabi_div0.c | 0 .../lib/builtins/arm/aeabi_drsub.c | 0 .../compiler-rt/lib/builtins/arm/aeabi_fcmp.S | 0 .../lib/builtins/arm/aeabi_frsub.c | 0 .../lib/builtins/arm/aeabi_idivmod.S | 0 .../lib/builtins/arm/aeabi_ldivmod.S | 0 .../lib/builtins/arm/aeabi_memcmp.S | 0 .../lib/builtins/arm/aeabi_memcpy.S | 0 .../lib/builtins/arm/aeabi_memmove.S | 0 .../lib/builtins/arm/aeabi_memset.S | 0 .../lib/builtins/arm/aeabi_uidivmod.S | 0 .../lib/builtins/arm/aeabi_uldivmod.S | 0 .../compiler-rt/lib/builtins/arm/bswapdi2.S | 0 .../compiler-rt/lib/builtins/arm/bswapsi2.S | 0 .../compiler-rt/lib/builtins/arm/clzdi2.S | 0 .../compiler-rt/lib/builtins/arm/clzsi2.S | 0 .../compiler-rt/lib/builtins/arm/comparesf2.S | 0 .../compiler-rt/lib/builtins/arm/divdf3vfp.S | 0 .../compiler-rt/lib/builtins/arm/divmodsi4.S | 0 .../compiler-rt/lib/builtins/arm/divsf3vfp.S | 0 .../compiler-rt/lib/builtins/arm/divsi3.S | 0 .../compiler-rt/lib/builtins/arm/eqdf2vfp.S | 0 .../compiler-rt/lib/builtins/arm/eqsf2vfp.S | 0 .../lib/builtins/arm/extendsfdf2vfp.S | 0 .../compiler-rt/lib/builtins/arm/fixdfsivfp.S | 0 .../compiler-rt/lib/builtins/arm/fixsfsivfp.S | 0 .../lib/builtins/arm/fixunsdfsivfp.S | 0 .../lib/builtins/arm/fixunssfsivfp.S | 0 .../lib/builtins/arm/floatsidfvfp.S | 0 .../lib/builtins/arm/floatsisfvfp.S | 0 .../lib/builtins/arm/floatunssidfvfp.S | 0 .../lib/builtins/arm/floatunssisfvfp.S | 0 .../compiler-rt/lib/builtins/arm/gedf2vfp.S | 0 .../compiler-rt/lib/builtins/arm/gesf2vfp.S | 0 .../compiler-rt/lib/builtins/arm/gtdf2vfp.S | 0 .../compiler-rt/lib/builtins/arm/gtsf2vfp.S | 0 .../compiler-rt/lib/builtins/arm/ledf2vfp.S | 0 .../compiler-rt/lib/builtins/arm/lesf2vfp.S | 0 .../compiler-rt/lib/builtins/arm/ltdf2vfp.S | 0 .../compiler-rt/lib/builtins/arm/ltsf2vfp.S | 0 .../compiler-rt/lib/builtins/arm/modsi3.S | 0 .../compiler-rt/lib/builtins/arm/muldf3vfp.S | 0 .../compiler-rt/lib/builtins/arm/mulsf3vfp.S | 0 .../compiler-rt/lib/builtins/arm/nedf2vfp.S | 0 .../compiler-rt/lib/builtins/arm/negdf2vfp.S | 0 .../compiler-rt/lib/builtins/arm/negsf2vfp.S | 0 .../compiler-rt/lib/builtins/arm/nesf2vfp.S | 0 .../builtins/arm/restore_vfp_d8_d15_regs.S | 0 .../lib/builtins/arm/save_vfp_d8_d15_regs.S | 0 .../lib/builtins/arm/softfloat-alias.list | 0 .../compiler-rt/lib/builtins/arm/subdf3vfp.S | 0 .../compiler-rt/lib/builtins/arm/subsf3vfp.S | 0 .../compiler-rt/lib/builtins/arm/switch16.S | 0 .../compiler-rt/lib/builtins/arm/switch32.S | 0 .../compiler-rt/lib/builtins/arm/switch8.S | 0 .../compiler-rt/lib/builtins/arm/switchu8.S | 0 .../compiler-rt/lib/builtins/arm/sync-ops.h | 0 .../lib/builtins/arm/sync_fetch_and_add_4.S | 0 .../lib/builtins/arm/sync_fetch_and_add_8.S | 0 .../lib/builtins/arm/sync_fetch_and_and_4.S | 0 .../lib/builtins/arm/sync_fetch_and_and_8.S | 0 .../lib/builtins/arm/sync_fetch_and_max_4.S | 0 .../lib/builtins/arm/sync_fetch_and_max_8.S | 0 .../lib/builtins/arm/sync_fetch_and_min_4.S | 0 .../lib/builtins/arm/sync_fetch_and_min_8.S | 0 .../lib/builtins/arm/sync_fetch_and_nand_4.S | 0 .../lib/builtins/arm/sync_fetch_and_nand_8.S | 0 .../lib/builtins/arm/sync_fetch_and_or_4.S | 0 .../lib/builtins/arm/sync_fetch_and_or_8.S | 0 .../lib/builtins/arm/sync_fetch_and_sub_4.S | 0 .../lib/builtins/arm/sync_fetch_and_sub_8.S | 0 .../lib/builtins/arm/sync_fetch_and_umax_4.S | 0 .../lib/builtins/arm/sync_fetch_and_umax_8.S | 0 .../lib/builtins/arm/sync_fetch_and_umin_4.S | 0 .../lib/builtins/arm/sync_fetch_and_umin_8.S | 0 .../lib/builtins/arm/sync_fetch_and_xor_4.S | 0 .../lib/builtins/arm/sync_fetch_and_xor_8.S | 0 .../lib/builtins/arm/sync_synchronize.S | 0 .../lib/builtins/arm/truncdfsf2vfp.S | 0 .../compiler-rt/lib/builtins/arm/udivmodsi4.S | 0 .../compiler-rt/lib/builtins/arm/udivsi3.S | 0 .../compiler-rt/lib/builtins/arm/umodsi3.S | 0 .../lib/builtins/arm/unorddf2vfp.S | 0 .../lib/builtins/arm/unordsf2vfp.S | 0 .../compiler-rt/lib/builtins/ashldi3.c | 0 .../compiler-rt/lib/builtins/ashlti3.c | 0 .../compiler-rt/lib/builtins/ashrdi3.c | 0 .../compiler-rt/lib/builtins/ashrti3.c | 0 .../compiler-rt/lib/builtins/assembly.h | 0 .../compiler-rt/lib/builtins/atomic.c | 0 .../lib/builtins/atomic_flag_clear.c | 0 .../lib/builtins/atomic_flag_clear_explicit.c | 0 .../lib/builtins/atomic_flag_test_and_set.c | 0 .../atomic_flag_test_and_set_explicit.c | 0 .../lib/builtins/atomic_signal_fence.c | 0 .../lib/builtins/atomic_thread_fence.c | 0 .../compiler-rt/lib/builtins/clear_cache.c | 0 .../compiler-rt/lib/builtins/clzdi2.c | 0 .../compiler-rt/lib/builtins/clzsi2.c | 0 .../compiler-rt/lib/builtins/clzti2.c | 0 .../compiler-rt/lib/builtins/cmpdi2.c | 0 .../compiler-rt/lib/builtins/cmpti2.c | 0 .../compiler-rt/lib/builtins/comparedf2.c | 0 .../compiler-rt/lib/builtins/comparesf2.c | 0 .../compiler-rt/lib/builtins/comparetf2.c | 0 .../compiler-rt/lib/builtins/cpu_model.c | 0 .../compiler-rt/lib/builtins/ctzdi2.c | 0 .../compiler-rt/lib/builtins/ctzsi2.c | 0 .../compiler-rt/lib/builtins/ctzti2.c | 0 .../compiler-rt/lib/builtins/divdc3.c | 0 .../compiler-rt/lib/builtins/divdf3.c | 0 .../compiler-rt/lib/builtins/divdi3.c | 0 .../compiler-rt/lib/builtins/divmoddi4.c | 0 .../compiler-rt/lib/builtins/divmodsi4.c | 0 .../compiler-rt/lib/builtins/divsc3.c | 0 .../compiler-rt/lib/builtins/divsf3.c | 0 .../compiler-rt/lib/builtins/divsi3.c | 0 .../compiler-rt/lib/builtins/divtc3.c | 0 .../compiler-rt/lib/builtins/divtf3.c | 0 .../compiler-rt/lib/builtins/divti3.c | 0 .../compiler-rt/lib/builtins/divxc3.c | 0 .../compiler-rt/lib/builtins/emutls.c | 0 .../lib/builtins/enable_execute_stack.c | 0 .../compiler-rt/lib/builtins/eprintf.c | 0 .../compiler-rt/lib/builtins/extenddftf2.c | 0 .../compiler-rt/lib/builtins/extendhfsf2.c | 0 .../compiler-rt/lib/builtins/extendsfdf2.c | 0 .../compiler-rt/lib/builtins/extendsftf2.c | 0 .../compiler-rt/lib/builtins/ffsdi2.c | 0 .../compiler-rt/lib/builtins/ffsti2.c | 0 .../compiler-rt/lib/builtins/fixdfdi.c | 0 .../compiler-rt/lib/builtins/fixdfsi.c | 0 .../compiler-rt/lib/builtins/fixdfti.c | 0 .../compiler-rt/lib/builtins/fixsfdi.c | 0 .../compiler-rt/lib/builtins/fixsfsi.c | 0 .../compiler-rt/lib/builtins/fixsfti.c | 0 .../compiler-rt/lib/builtins/fixtfdi.c | 0 .../compiler-rt/lib/builtins/fixtfsi.c | 0 .../compiler-rt/lib/builtins/fixtfti.c | 0 .../compiler-rt/lib/builtins/fixunsdfdi.c | 0 .../compiler-rt/lib/builtins/fixunsdfsi.c | 0 .../compiler-rt/lib/builtins/fixunsdfti.c | 0 .../compiler-rt/lib/builtins/fixunssfdi.c | 0 .../compiler-rt/lib/builtins/fixunssfsi.c | 0 .../compiler-rt/lib/builtins/fixunssfti.c | 0 .../compiler-rt/lib/builtins/fixunstfdi.c | 0 .../compiler-rt/lib/builtins/fixunstfsi.c | 0 .../compiler-rt/lib/builtins/fixunstfti.c | 0 .../compiler-rt/lib/builtins/fixunsxfdi.c | 0 .../compiler-rt/lib/builtins/fixunsxfsi.c | 0 .../compiler-rt/lib/builtins/fixunsxfti.c | 0 .../compiler-rt/lib/builtins/fixxfdi.c | 0 .../compiler-rt/lib/builtins/fixxfti.c | 0 .../compiler-rt/lib/builtins/floatdidf.c | 0 .../compiler-rt/lib/builtins/floatdisf.c | 0 .../compiler-rt/lib/builtins/floatditf.c | 0 .../compiler-rt/lib/builtins/floatdixf.c | 0 .../compiler-rt/lib/builtins/floatsidf.c | 0 .../compiler-rt/lib/builtins/floatsisf.c | 0 .../compiler-rt/lib/builtins/floatsitf.c | 0 .../compiler-rt/lib/builtins/floattidf.c | 0 .../compiler-rt/lib/builtins/floattisf.c | 0 .../compiler-rt/lib/builtins/floattitf.c | 0 .../compiler-rt/lib/builtins/floattixf.c | 0 .../compiler-rt/lib/builtins/floatundidf.c | 0 .../compiler-rt/lib/builtins/floatundisf.c | 0 .../compiler-rt/lib/builtins/floatunditf.c | 0 .../compiler-rt/lib/builtins/floatundixf.c | 0 .../compiler-rt/lib/builtins/floatunsidf.c | 0 .../compiler-rt/lib/builtins/floatunsisf.c | 0 .../compiler-rt/lib/builtins/floatunsitf.c | 0 .../compiler-rt/lib/builtins/floatuntidf.c | 0 .../compiler-rt/lib/builtins/floatuntisf.c | 0 .../compiler-rt/lib/builtins/floatuntitf.c | 0 .../compiler-rt/lib/builtins/floatuntixf.c | 0 .../compiler-rt/lib/builtins/fp_add_impl.inc | 0 .../compiler-rt/lib/builtins/fp_extend.h | 0 .../lib/builtins/fp_extend_impl.inc | 0 .../lib/builtins/fp_fixint_impl.inc | 0 .../lib/builtins/fp_fixuint_impl.inc | 0 .../compiler-rt/lib/builtins/fp_lib.h | 0 .../compiler-rt/lib/builtins/fp_mul_impl.inc | 0 .../compiler-rt/lib/builtins/fp_trunc.h | 0 .../lib/builtins/fp_trunc_impl.inc | 0 .../lib/builtins/gcc_personality_v0.c | 0 .../compiler-rt/lib/builtins/i386/ashldi3.S | 0 .../compiler-rt/lib/builtins/i386/ashrdi3.S | 0 .../compiler-rt/lib/builtins/i386/chkstk.S | 0 .../compiler-rt/lib/builtins/i386/chkstk2.S | 0 .../compiler-rt/lib/builtins/i386/divdi3.S | 0 .../compiler-rt/lib/builtins/i386/floatdidf.S | 0 .../compiler-rt/lib/builtins/i386/floatdisf.S | 0 .../compiler-rt/lib/builtins/i386/floatdixf.S | 0 .../lib/builtins/i386/floatundidf.S | 0 .../lib/builtins/i386/floatundisf.S | 0 .../lib/builtins/i386/floatundixf.S | 0 .../compiler-rt/lib/builtins/i386/lshrdi3.S | 0 .../compiler-rt/lib/builtins/i386/moddi3.S | 0 .../compiler-rt/lib/builtins/i386/muldi3.S | 0 .../compiler-rt/lib/builtins/i386/udivdi3.S | 0 .../compiler-rt/lib/builtins/i386/umoddi3.S | 0 .../compiler-rt/lib/builtins/int_endianness.h | 0 .../compiler-rt/lib/builtins/int_lib.h | 0 .../compiler-rt/lib/builtins/int_math.h | 0 .../compiler-rt/lib/builtins/int_types.h | 0 .../compiler-rt/lib/builtins/int_util.c | 0 .../compiler-rt/lib/builtins/int_util.h | 0 .../compiler-rt/lib/builtins/lshrdi3.c | 0 .../compiler-rt/lib/builtins/lshrti3.c | 0 .../builtins/macho_embedded/CMakeLists.txt | 0 .../lib/builtins/macho_embedded/arm.txt | 0 .../lib/builtins/macho_embedded/common.txt | 0 .../lib/builtins/macho_embedded/i386.txt | 0 .../lib/builtins/macho_embedded/thumb2-64.txt | 0 .../lib/builtins/macho_embedded/thumb2.txt | 0 .../compiler-rt/lib/builtins/mingw_fixfloat.c | 0 .../compiler-rt/lib/builtins/moddi3.c | 0 .../compiler-rt/lib/builtins/modsi3.c | 0 .../compiler-rt/lib/builtins/modti3.c | 0 .../compiler-rt/lib/builtins/muldc3.c | 0 .../compiler-rt/lib/builtins/muldf3.c | 0 .../compiler-rt/lib/builtins/muldi3.c | 0 .../compiler-rt/lib/builtins/mulodi4.c | 0 .../compiler-rt/lib/builtins/mulosi4.c | 0 .../compiler-rt/lib/builtins/muloti4.c | 0 .../compiler-rt/lib/builtins/mulsc3.c | 0 .../compiler-rt/lib/builtins/mulsf3.c | 0 .../compiler-rt/lib/builtins/multc3.c | 0 .../compiler-rt/lib/builtins/multf3.c | 0 .../compiler-rt/lib/builtins/multi3.c | 0 .../compiler-rt/lib/builtins/mulvdi3.c | 0 .../compiler-rt/lib/builtins/mulvsi3.c | 0 .../compiler-rt/lib/builtins/mulvti3.c | 0 .../compiler-rt/lib/builtins/mulxc3.c | 0 .../compiler-rt/lib/builtins/negdf2.c | 0 .../compiler-rt/lib/builtins/negdi2.c | 0 .../compiler-rt/lib/builtins/negsf2.c | 0 .../compiler-rt/lib/builtins/negti2.c | 0 .../compiler-rt/lib/builtins/negvdi2.c | 0 .../compiler-rt/lib/builtins/negvsi2.c | 0 .../compiler-rt/lib/builtins/negvti2.c | 0 .../compiler-rt/lib/builtins/paritydi2.c | 0 .../compiler-rt/lib/builtins/paritysi2.c | 0 .../compiler-rt/lib/builtins/parityti2.c | 0 .../compiler-rt/lib/builtins/popcountdi2.c | 0 .../compiler-rt/lib/builtins/popcountsi2.c | 0 .../compiler-rt/lib/builtins/popcountti2.c | 0 .../compiler-rt/lib/builtins/powidf2.c | 0 .../compiler-rt/lib/builtins/powisf2.c | 0 .../compiler-rt/lib/builtins/powitf2.c | 0 .../compiler-rt/lib/builtins/powixf2.c | 0 .../compiler-rt/lib/builtins/ppc/DD.h | 0 .../compiler-rt/lib/builtins/ppc/divtc3.c | 0 .../compiler-rt/lib/builtins/ppc/fixtfdi.c | 0 .../compiler-rt/lib/builtins/ppc/fixunstfdi.c | 0 .../compiler-rt/lib/builtins/ppc/floatditf.c | 0 .../lib/builtins/ppc/floatunditf.c | 0 .../compiler-rt/lib/builtins/ppc/gcc_qadd.c | 0 .../compiler-rt/lib/builtins/ppc/gcc_qdiv.c | 0 .../compiler-rt/lib/builtins/ppc/gcc_qmul.c | 0 .../compiler-rt/lib/builtins/ppc/gcc_qsub.c | 0 .../compiler-rt/lib/builtins/ppc/multc3.c | 0 .../compiler-rt/lib/builtins/ppc/restFP.S | 0 .../compiler-rt/lib/builtins/ppc/saveFP.S | 0 .../compiler-rt/lib/builtins/subdf3.c | 0 .../compiler-rt/lib/builtins/subsf3.c | 0 .../compiler-rt/lib/builtins/subtf3.c | 0 .../compiler-rt/lib/builtins/subvdi3.c | 0 .../compiler-rt/lib/builtins/subvsi3.c | 0 .../compiler-rt/lib/builtins/subvti3.c | 0 .../lib/builtins/trampoline_setup.c | 0 .../compiler-rt/lib/builtins/truncdfhf2.c | 0 .../compiler-rt/lib/builtins/truncdfsf2.c | 0 .../compiler-rt/lib/builtins/truncsfhf2.c | 0 .../compiler-rt/lib/builtins/trunctfdf2.c | 0 .../compiler-rt/lib/builtins/trunctfsf2.c | 0 .../compiler-rt/lib/builtins/ucmpdi2.c | 0 .../compiler-rt/lib/builtins/ucmpti2.c | 0 .../compiler-rt/lib/builtins/udivdi3.c | 0 .../compiler-rt/lib/builtins/udivmoddi4.c | 0 .../compiler-rt/lib/builtins/udivmodsi4.c | 0 .../compiler-rt/lib/builtins/udivmodti4.c | 0 .../compiler-rt/lib/builtins/udivsi3.c | 0 .../compiler-rt/lib/builtins/udivti3.c | 0 .../compiler-rt/lib/builtins/umoddi3.c | 0 .../compiler-rt/lib/builtins/umodsi3.c | 0 .../compiler-rt/lib/builtins/umodti3.c | 0 .../lib/builtins/unwind-ehabi-helpers.h | 0 .../compiler-rt/lib/builtins/x86_64/chkstk.S | 0 .../compiler-rt/lib/builtins/x86_64/chkstk2.S | 0 .../lib/builtins/x86_64/floatdidf.c | 0 .../lib/builtins/x86_64/floatdisf.c | 0 .../lib/builtins/x86_64/floatdixf.c | 0 .../lib/builtins/x86_64/floatundidf.S | 0 .../lib/builtins/x86_64/floatundisf.S | 0 .../lib/builtins/x86_64/floatundixf.S | 0 .../compiler-rt/lib/cfi/CMakeLists.txt | 0 .../compiler-rt/lib/cfi/cfi.cc | 0 .../compiler-rt/lib/cfi/cfi_blacklist.txt | 0 .../compiler-rt/lib/dfsan/.clang-format | 0 .../compiler-rt/lib/dfsan/CMakeLists.txt | 0 .../compiler-rt/lib/dfsan/dfsan.cc | 0 .../compiler-rt/lib/dfsan/dfsan.h | 0 .../compiler-rt/lib/dfsan/dfsan.syms.extra | 0 .../compiler-rt/lib/dfsan/dfsan_custom.cc | 0 .../compiler-rt/lib/dfsan/dfsan_flags.inc | 0 .../lib/dfsan/dfsan_interceptors.cc | 0 .../compiler-rt/lib/dfsan/dfsan_platform.h | 0 .../compiler-rt/lib/dfsan/done_abilist.txt | 0 .../lib/dfsan/libc_ubuntu1404_abilist.txt | 0 .../lib/dfsan/scripts/build-libc-list.py | 0 .../dfsan/scripts/check_custom_wrappers.sh | 0 .../compiler-rt/lib/esan/CMakeLists.txt | 0 .../compiler-rt/lib/esan/cache_frag.cpp | 0 .../compiler-rt/lib/esan/cache_frag.h | 0 .../compiler-rt/lib/esan/esan.cpp | 0 .../compiler-rt/lib/esan/esan.h | 0 .../compiler-rt/lib/esan/esan.syms.extra | 0 .../lib/esan/esan_circular_buffer.h | 0 .../compiler-rt/lib/esan/esan_flags.cpp | 0 .../compiler-rt/lib/esan/esan_flags.h | 0 .../compiler-rt/lib/esan/esan_flags.inc | 0 .../compiler-rt/lib/esan/esan_hashtable.h | 0 .../lib/esan/esan_interceptors.cpp | 0 .../compiler-rt/lib/esan/esan_interface.cpp | 0 .../lib/esan/esan_interface_internal.h | 0 .../compiler-rt/lib/esan/esan_linux.cpp | 0 .../compiler-rt/lib/esan/esan_shadow.h | 0 .../compiler-rt/lib/esan/esan_sideline.h | 0 .../lib/esan/esan_sideline_linux.cpp | 0 .../compiler-rt/lib/esan/working_set.cpp | 0 .../compiler-rt/lib/esan/working_set.h | 0 .../lib/esan/working_set_posix.cpp | 0 .../lib/interception/.clang-format | 0 .../lib/interception/CMakeLists.txt | 0 .../lib/interception/interception.h | 0 .../lib/interception/interception_linux.cc | 0 .../lib/interception/interception_linux.h | 0 .../lib/interception/interception_mac.cc | 0 .../lib/interception/interception_mac.h | 0 .../interception/interception_type_test.cc | 0 .../lib/interception/interception_win.cc | 0 .../lib/interception/interception_win.h | 0 .../lib/interception/tests/CMakeLists.txt | 0 .../tests/interception_linux_test.cc | 0 .../tests/interception_test_main.cc | 0 .../tests/interception_win_test.cc | 0 .../compiler-rt/lib/lsan/.clang-format | 0 .../compiler-rt/lib/lsan/CMakeLists.txt | 0 .../compiler-rt/lib/lsan/lsan.cc | 0 .../compiler-rt/lib/lsan/lsan.h | 0 .../compiler-rt/lib/lsan/lsan_allocator.cc | 0 .../compiler-rt/lib/lsan/lsan_allocator.h | 0 .../compiler-rt/lib/lsan/lsan_common.cc | 0 .../compiler-rt/lib/lsan/lsan_common.h | 0 .../compiler-rt/lib/lsan/lsan_common_linux.cc | 0 .../compiler-rt/lib/lsan/lsan_flags.inc | 0 .../compiler-rt/lib/lsan/lsan_interceptors.cc | 0 .../compiler-rt/lib/lsan/lsan_preinit.cc | 0 .../compiler-rt/lib/lsan/lsan_thread.cc | 0 .../compiler-rt/lib/lsan/lsan_thread.h | 0 .../compiler-rt/lib/msan/.clang-format | 0 .../compiler-rt/lib/msan/CMakeLists.txt | 0 .../compiler-rt/lib/msan/msan.cc | 0 .../compiler-rt/lib/msan/msan.h | 0 .../compiler-rt/lib/msan/msan.syms.extra | 0 .../compiler-rt/lib/msan/msan_allocator.cc | 0 .../compiler-rt/lib/msan/msan_allocator.h | 0 .../compiler-rt/lib/msan/msan_blacklist.txt | 0 .../lib/msan/msan_chained_origin_depot.cc | 0 .../lib/msan/msan_chained_origin_depot.h | 0 .../compiler-rt/lib/msan/msan_flags.h | 0 .../compiler-rt/lib/msan/msan_flags.inc | 0 .../compiler-rt/lib/msan/msan_interceptors.cc | 0 .../lib/msan/msan_interface_internal.h | 0 .../compiler-rt/lib/msan/msan_linux.cc | 0 .../compiler-rt/lib/msan/msan_new_delete.cc | 0 .../compiler-rt/lib/msan/msan_origin.h | 0 .../compiler-rt/lib/msan/msan_poisoning.cc | 0 .../compiler-rt/lib/msan/msan_poisoning.h | 0 .../compiler-rt/lib/msan/msan_report.cc | 0 .../compiler-rt/lib/msan/msan_thread.cc | 0 .../compiler-rt/lib/msan/msan_thread.h | 0 .../compiler-rt/lib/msan/tests/CMakeLists.txt | 0 .../lib/msan/tests/msan_loadable.cc | 0 .../compiler-rt/lib/msan/tests/msan_test.cc | 0 .../lib/msan/tests/msan_test_config.h | 0 .../lib/msan/tests/msan_test_main.cc | 0 .../compiler-rt/lib/profile/CMakeLists.txt | 0 .../compiler-rt/lib/profile/GCDAProfiling.c | 0 .../compiler-rt/lib/profile/InstrProfData.inc | 0 .../compiler-rt/lib/profile/InstrProfiling.c | 0 .../compiler-rt/lib/profile/InstrProfiling.h | 0 .../lib/profile/InstrProfilingBuffer.c | 0 .../lib/profile/InstrProfilingFile.c | 0 .../lib/profile/InstrProfilingInternal.h | 0 .../lib/profile/InstrProfilingMerge.c | 0 .../lib/profile/InstrProfilingMergeFile.c | 0 .../profile/InstrProfilingPlatformDarwin.c | 0 .../lib/profile/InstrProfilingPlatformLinux.c | 0 .../lib/profile/InstrProfilingPlatformOther.c | 0 .../lib/profile/InstrProfilingPort.h | 0 .../lib/profile/InstrProfilingRuntime.cc | 0 .../lib/profile/InstrProfilingUtil.c | 0 .../lib/profile/InstrProfilingUtil.h | 0 .../lib/profile/InstrProfilingValue.c | 0 .../lib/profile/InstrProfilingWriter.c | 0 .../compiler-rt/lib/profile/WindowsMMap.c | 0 .../compiler-rt/lib/profile/WindowsMMap.h | 0 .../compiler-rt/lib/safestack/.clang-format | 0 .../compiler-rt/lib/safestack/CMakeLists.txt | 0 .../compiler-rt/lib/safestack/safestack.cc | 0 .../lib/sanitizer_common/.clang-format | 0 .../lib/sanitizer_common/.clang-tidy | 0 .../lib/sanitizer_common/CMakeLists.txt | 0 .../lib/sanitizer_common/sancov_flags.cc | 0 .../lib/sanitizer_common/sancov_flags.h | 0 .../lib/sanitizer_common/sancov_flags.inc | 0 .../sanitizer_common/sanitizer_addrhashmap.h | 0 .../sanitizer_common/sanitizer_allocator.cc | 0 .../sanitizer_common/sanitizer_allocator.h | 0 .../sanitizer_allocator_bytemap.h | 0 .../sanitizer_allocator_combined.h | 0 .../sanitizer_allocator_interface.h | 0 .../sanitizer_allocator_internal.h | 0 .../sanitizer_allocator_local_cache.h | 0 .../sanitizer_allocator_primary32.h | 0 .../sanitizer_allocator_primary64.h | 0 .../sanitizer_allocator_secondary.h | 0 .../sanitizer_allocator_size_class_map.h | 0 .../sanitizer_allocator_stats.h | 0 .../lib/sanitizer_common/sanitizer_asm.h | 0 .../lib/sanitizer_common/sanitizer_atomic.h | 0 .../sanitizer_common/sanitizer_atomic_clang.h | 0 .../sanitizer_atomic_clang_other.h | 0 .../sanitizer_atomic_clang_x86.h | 0 .../sanitizer_common/sanitizer_atomic_msvc.h | 0 .../sanitizer_common/sanitizer_bitvector.h | 0 .../lib/sanitizer_common/sanitizer_bvgraph.h | 0 .../lib/sanitizer_common/sanitizer_common.cc | 0 .../lib/sanitizer_common/sanitizer_common.h | 0 .../sanitizer_common_interceptors.inc | 0 .../sanitizer_common_interceptors_format.inc | 0 .../sanitizer_common_interceptors_ioctl.inc | 0 .../sanitizer_common_libcdep.cc | 0 .../sanitizer_common_nolibc.cc | 0 .../sanitizer_common_syscalls.inc | 0 .../sanitizer_coverage_libcdep.cc | 0 .../sanitizer_coverage_libcdep_new.cc | 0 .../sanitizer_coverage_mapping_libcdep.cc | 0 .../lib/sanitizer_common/sanitizer_dbghelp.h | 0 .../sanitizer_deadlock_detector.h | 0 .../sanitizer_deadlock_detector1.cc | 0 .../sanitizer_deadlock_detector2.cc | 0 .../sanitizer_deadlock_detector_interface.h | 0 .../sanitizer_common/sanitizer_flag_parser.cc | 0 .../sanitizer_common/sanitizer_flag_parser.h | 0 .../lib/sanitizer_common/sanitizer_flags.cc | 0 .../lib/sanitizer_common/sanitizer_flags.h | 0 .../lib/sanitizer_common/sanitizer_flags.inc | 0 .../lib/sanitizer_common/sanitizer_freebsd.h | 0 .../sanitizer_interface_internal.h | 0 .../sanitizer_internal_defs.h | 0 .../lib/sanitizer_common/sanitizer_lfstack.h | 0 .../lib/sanitizer_common/sanitizer_libc.cc | 0 .../lib/sanitizer_common/sanitizer_libc.h | 0 .../sanitizer_common/sanitizer_libignore.cc | 0 .../sanitizer_common/sanitizer_libignore.h | 0 .../lib/sanitizer_common/sanitizer_linux.cc | 0 .../lib/sanitizer_common/sanitizer_linux.h | 0 .../sanitizer_linux_libcdep.cc | 0 .../sanitizer_common/sanitizer_linux_mips64.S | 0 .../sanitizer_common/sanitizer_linux_s390.cc | 0 .../sanitizer_common/sanitizer_linux_x86_64.S | 0 .../lib/sanitizer_common/sanitizer_list.h | 0 .../lib/sanitizer_common/sanitizer_mac.cc | 0 .../lib/sanitizer_common/sanitizer_mac.h | 0 .../sanitizer_common/sanitizer_malloc_mac.inc | 0 .../lib/sanitizer_common/sanitizer_mutex.h | 0 .../sanitizer_persistent_allocator.cc | 0 .../sanitizer_persistent_allocator.h | 0 .../sanitizer_placement_new.h | 0 .../lib/sanitizer_common/sanitizer_platform.h | 0 .../sanitizer_platform_interceptors.h | 0 .../sanitizer_platform_limits_linux.cc | 0 .../sanitizer_platform_limits_posix.cc | 0 .../sanitizer_platform_limits_posix.h | 0 .../lib/sanitizer_common/sanitizer_posix.cc | 0 .../lib/sanitizer_common/sanitizer_posix.h | 0 .../sanitizer_posix_libcdep.cc | 0 .../lib/sanitizer_common/sanitizer_printf.cc | 0 .../lib/sanitizer_common/sanitizer_procmaps.h | 0 .../sanitizer_procmaps_common.cc | 0 .../sanitizer_procmaps_freebsd.cc | 0 .../sanitizer_procmaps_linux.cc | 0 .../sanitizer_procmaps_mac.cc | 0 .../sanitizer_common/sanitizer_quarantine.h | 0 .../sanitizer_report_decorator.h | 0 .../sanitizer_common/sanitizer_stackdepot.cc | 0 .../sanitizer_common/sanitizer_stackdepot.h | 0 .../sanitizer_stackdepotbase.h | 0 .../sanitizer_common/sanitizer_stacktrace.cc | 0 .../sanitizer_common/sanitizer_stacktrace.h | 0 .../sanitizer_stacktrace_libcdep.cc | 0 .../sanitizer_stacktrace_printer.cc | 0 .../sanitizer_stacktrace_printer.h | 0 .../sanitizer_common/sanitizer_stoptheworld.h | 0 .../sanitizer_stoptheworld_linux_libcdep.cc | 0 .../sanitizer_suppressions.cc | 0 .../sanitizer_common/sanitizer_suppressions.h | 0 .../sanitizer_common/sanitizer_symbolizer.cc | 0 .../sanitizer_common/sanitizer_symbolizer.h | 0 .../sanitizer_symbolizer_internal.h | 0 .../sanitizer_symbolizer_libbacktrace.cc | 0 .../sanitizer_symbolizer_libbacktrace.h | 0 .../sanitizer_symbolizer_libcdep.cc | 0 .../sanitizer_symbolizer_mac.cc | 0 .../sanitizer_symbolizer_mac.h | 0 .../sanitizer_symbolizer_posix_libcdep.cc | 0 .../sanitizer_symbolizer_win.cc | 0 .../sanitizer_syscall_generic.inc | 0 .../sanitizer_syscall_linux_aarch64.inc | 0 .../sanitizer_syscall_linux_x86_64.inc | 0 .../sanitizer_common/sanitizer_termination.cc | 0 .../sanitizer_thread_registry.cc | 0 .../sanitizer_thread_registry.h | 0 .../sanitizer_tls_get_addr.cc | 0 .../sanitizer_common/sanitizer_tls_get_addr.h | 0 .../sanitizer_unwind_linux_libcdep.cc | 0 .../lib/sanitizer_common/sanitizer_win.cc | 0 .../sanitizer_common/scripts/check_lint.sh | 0 .../lib/sanitizer_common/scripts/cpplint.py | 0 .../scripts/gen_dynamic_list.py | 0 .../lib/sanitizer_common/scripts/litlint.py | 0 .../sanitizer_common/scripts/litlint_test.py | 0 .../lib/sanitizer_common/scripts/sancov.py | 0 .../symbolizer/sanitizer_symbolize.cc | 0 .../symbolizer/sanitizer_wrappers.cc | 0 .../symbolizer/scripts/build_symbolizer.sh | 0 .../symbolizer/scripts/global_symbols.txt | 0 .../lib/sanitizer_common/tests/CMakeLists.txt | 0 .../tests/malloc_stress_transfer_test.cc | 0 .../tests/sanitizer_allocator_test.cc | 0 .../tests/sanitizer_allocator_testlib.cc | 0 .../tests/sanitizer_atomic_test.cc | 0 .../tests/sanitizer_bitvector_test.cc | 0 .../tests/sanitizer_bvgraph_test.cc | 0 .../tests/sanitizer_common_test.cc | 0 .../tests/sanitizer_deadlock_detector_test.cc | 0 .../tests/sanitizer_flags_test.cc | 0 .../sanitizer_format_interceptor_test.cc | 0 .../tests/sanitizer_ioctl_test.cc | 0 .../tests/sanitizer_libc_test.cc | 0 .../tests/sanitizer_linux_test.cc | 0 .../tests/sanitizer_list_test.cc | 0 .../tests/sanitizer_mutex_test.cc | 0 .../tests/sanitizer_nolibc_test.cc | 0 .../tests/sanitizer_nolibc_test_main.cc | 0 .../tests/sanitizer_posix_test.cc | 0 .../tests/sanitizer_printf_test.cc | 0 .../tests/sanitizer_procmaps_test.cc | 0 .../tests/sanitizer_pthread_wrappers.h | 0 .../tests/sanitizer_stackdepot_test.cc | 0 .../sanitizer_stacktrace_printer_test.cc | 0 .../tests/sanitizer_stacktrace_test.cc | 0 .../tests/sanitizer_stoptheworld_test.cc | 0 .../tests/sanitizer_stoptheworld_testlib.cc | 0 .../tests/sanitizer_suppressions_test.cc | 0 .../tests/sanitizer_symbolizer_test.cc | 0 .../tests/sanitizer_test_config.h | 0 .../tests/sanitizer_test_main.cc | 0 .../tests/sanitizer_test_utils.h | 0 .../tests/sanitizer_thread_registry_test.cc | 0 .../tests/standalone_malloc_test.cc | 0 .../lib/sanitizer_common/weak_symbols.txt | 0 .../compiler-rt/lib/scudo/CMakeLists.txt | 0 .../compiler-rt/lib/scudo/scudo_allocator.cpp | 0 .../compiler-rt/lib/scudo/scudo_allocator.h | 0 .../lib/scudo/scudo_allocator_secondary.h | 0 .../compiler-rt/lib/scudo/scudo_crc32.cpp | 0 .../compiler-rt/lib/scudo/scudo_crc32.h | 0 .../compiler-rt/lib/scudo/scudo_flags.cpp | 0 .../compiler-rt/lib/scudo/scudo_flags.h | 0 .../compiler-rt/lib/scudo/scudo_flags.inc | 0 .../lib/scudo/scudo_interceptors.cpp | 0 .../lib/scudo/scudo_new_delete.cpp | 0 .../lib/scudo/scudo_termination.cpp | 0 .../compiler-rt/lib/scudo/scudo_utils.cpp | 0 .../compiler-rt/lib/scudo/scudo_utils.h | 0 .../compiler-rt/lib/stats/CMakeLists.txt | 0 .../compiler-rt/lib/stats/stats.cc | 0 .../compiler-rt/lib/stats/stats.h | 0 .../compiler-rt/lib/stats/stats_client.cc | 0 .../compiler-rt/lib/tsan/.clang-format | 0 .../compiler-rt/lib/tsan/CMakeLists.txt | 0 .../compiler-rt/lib/tsan/analyze_libtsan.sh | 0 .../lib/tsan/benchmarks/mini_bench_local.cc | 0 .../lib/tsan/benchmarks/mini_bench_shared.cc | 0 .../lib/tsan/benchmarks/start_many_threads.cc | 0 .../tsan/benchmarks/vts_many_threads_bench.cc | 0 .../compiler-rt/lib/tsan/check_analyze.sh | 0 .../compiler-rt/lib/tsan/check_cmake.sh | 0 .../compiler-rt/lib/tsan/dd/CMakeLists.txt | 0 .../lib/tsan/dd/dd_interceptors.cc | 0 .../compiler-rt/lib/tsan/dd/dd_rtl.cc | 0 .../compiler-rt/lib/tsan/dd/dd_rtl.h | 0 .../compiler-rt/lib/tsan/go/build.bat | 0 .../compiler-rt/lib/tsan/go/buildgo.sh | 0 .../compiler-rt/lib/tsan/go/test.c | 0 .../compiler-rt/lib/tsan/go/tsan_go.cc | 0 .../compiler-rt/lib/tsan/rtl/tsan.syms.extra | 0 .../compiler-rt/lib/tsan/rtl/tsan_clock.cc | 0 .../compiler-rt/lib/tsan/rtl/tsan_clock.h | 0 .../lib/tsan/rtl/tsan_debugging.cc | 0 .../compiler-rt/lib/tsan/rtl/tsan_defs.h | 0 .../lib/tsan/rtl/tsan_dense_alloc.h | 0 .../compiler-rt/lib/tsan/rtl/tsan_fd.cc | 0 .../compiler-rt/lib/tsan/rtl/tsan_fd.h | 0 .../compiler-rt/lib/tsan/rtl/tsan_flags.cc | 0 .../compiler-rt/lib/tsan/rtl/tsan_flags.h | 0 .../compiler-rt/lib/tsan/rtl/tsan_flags.inc | 0 .../lib/tsan/rtl/tsan_ignoreset.cc | 0 .../compiler-rt/lib/tsan/rtl/tsan_ignoreset.h | 0 .../lib/tsan/rtl/tsan_interceptors.cc | 0 .../lib/tsan/rtl/tsan_interceptors.h | 0 .../lib/tsan/rtl/tsan_interceptors_mac.cc | 0 .../lib/tsan/rtl/tsan_interface.cc | 0 .../compiler-rt/lib/tsan/rtl/tsan_interface.h | 0 .../lib/tsan/rtl/tsan_interface_ann.cc | 0 .../lib/tsan/rtl/tsan_interface_ann.h | 0 .../lib/tsan/rtl/tsan_interface_atomic.cc | 0 .../lib/tsan/rtl/tsan_interface_inl.h | 0 .../lib/tsan/rtl/tsan_interface_java.cc | 0 .../lib/tsan/rtl/tsan_interface_java.h | 0 .../lib/tsan/rtl/tsan_libdispatch_mac.cc | 0 .../lib/tsan/rtl/tsan_malloc_mac.cc | 0 .../compiler-rt/lib/tsan/rtl/tsan_md5.cc | 0 .../compiler-rt/lib/tsan/rtl/tsan_mman.cc | 0 .../compiler-rt/lib/tsan/rtl/tsan_mman.h | 0 .../compiler-rt/lib/tsan/rtl/tsan_mutex.cc | 0 .../compiler-rt/lib/tsan/rtl/tsan_mutex.h | 0 .../compiler-rt/lib/tsan/rtl/tsan_mutexset.cc | 0 .../compiler-rt/lib/tsan/rtl/tsan_mutexset.h | 0 .../lib/tsan/rtl/tsan_new_delete.cc | 0 .../compiler-rt/lib/tsan/rtl/tsan_platform.h | 0 .../lib/tsan/rtl/tsan_platform_linux.cc | 0 .../lib/tsan/rtl/tsan_platform_mac.cc | 0 .../lib/tsan/rtl/tsan_platform_posix.cc | 0 .../lib/tsan/rtl/tsan_platform_windows.cc | 0 .../compiler-rt/lib/tsan/rtl/tsan_ppc_regs.h | 0 .../compiler-rt/lib/tsan/rtl/tsan_preinit.cc | 0 .../compiler-rt/lib/tsan/rtl/tsan_report.cc | 0 .../compiler-rt/lib/tsan/rtl/tsan_report.h | 0 .../compiler-rt/lib/tsan/rtl/tsan_rtl.cc | 0 .../compiler-rt/lib/tsan/rtl/tsan_rtl.h | 0 .../lib/tsan/rtl/tsan_rtl_aarch64.S | 0 .../compiler-rt/lib/tsan/rtl/tsan_rtl_amd64.S | 0 .../lib/tsan/rtl/tsan_rtl_mips64.S | 0 .../lib/tsan/rtl/tsan_rtl_mutex.cc | 0 .../compiler-rt/lib/tsan/rtl/tsan_rtl_ppc64.S | 0 .../compiler-rt/lib/tsan/rtl/tsan_rtl_proc.cc | 0 .../lib/tsan/rtl/tsan_rtl_report.cc | 0 .../lib/tsan/rtl/tsan_rtl_thread.cc | 0 .../lib/tsan/rtl/tsan_stack_trace.cc | 0 .../lib/tsan/rtl/tsan_stack_trace.h | 0 .../compiler-rt/lib/tsan/rtl/tsan_stat.cc | 0 .../compiler-rt/lib/tsan/rtl/tsan_stat.h | 0 .../lib/tsan/rtl/tsan_suppressions.cc | 0 .../lib/tsan/rtl/tsan_suppressions.h | 0 .../lib/tsan/rtl/tsan_symbolize.cc | 0 .../compiler-rt/lib/tsan/rtl/tsan_symbolize.h | 0 .../compiler-rt/lib/tsan/rtl/tsan_sync.cc | 0 .../compiler-rt/lib/tsan/rtl/tsan_sync.h | 0 .../compiler-rt/lib/tsan/rtl/tsan_trace.h | 0 .../tsan/rtl/tsan_update_shadow_word_inl.h | 0 .../compiler-rt/lib/tsan/rtl/tsan_vector.h | 0 .../compiler-rt/lib/tsan/tests/CMakeLists.txt | 0 .../lib/tsan/tests/rtl/CMakeLists.txt | 0 .../lib/tsan/tests/rtl/tsan_bench.cc | 0 .../lib/tsan/tests/rtl/tsan_mop.cc | 0 .../lib/tsan/tests/rtl/tsan_mutex.cc | 0 .../lib/tsan/tests/rtl/tsan_posix.cc | 0 .../lib/tsan/tests/rtl/tsan_posix_util.h | 0 .../lib/tsan/tests/rtl/tsan_string.cc | 0 .../lib/tsan/tests/rtl/tsan_test.cc | 0 .../lib/tsan/tests/rtl/tsan_test_util.h | 0 .../tsan/tests/rtl/tsan_test_util_posix.cc | 0 .../lib/tsan/tests/rtl/tsan_thread.cc | 0 .../lib/tsan/tests/unit/CMakeLists.txt | 0 .../lib/tsan/tests/unit/tsan_clock_test.cc | 0 .../tsan/tests/unit/tsan_dense_alloc_test.cc | 0 .../lib/tsan/tests/unit/tsan_flags_test.cc | 0 .../lib/tsan/tests/unit/tsan_mman_test.cc | 0 .../lib/tsan/tests/unit/tsan_mutex_test.cc | 0 .../lib/tsan/tests/unit/tsan_mutexset_test.cc | 0 .../lib/tsan/tests/unit/tsan_shadow_test.cc | 0 .../lib/tsan/tests/unit/tsan_stack_test.cc | 0 .../lib/tsan/tests/unit/tsan_sync_test.cc | 0 .../tsan/tests/unit/tsan_unit_test_main.cc | 0 .../lib/tsan/tests/unit/tsan_vector_test.cc | 0 .../compiler-rt/lib/ubsan/CMakeLists.txt | 0 .../compiler-rt/lib/ubsan/ubsan.syms.extra | 0 .../compiler-rt/lib/ubsan/ubsan_checks.inc | 0 .../compiler-rt/lib/ubsan/ubsan_diag.cc | 0 .../compiler-rt/lib/ubsan/ubsan_diag.h | 0 .../compiler-rt/lib/ubsan/ubsan_flags.cc | 0 .../compiler-rt/lib/ubsan/ubsan_flags.h | 0 .../compiler-rt/lib/ubsan/ubsan_flags.inc | 0 .../compiler-rt/lib/ubsan/ubsan_handlers.cc | 0 .../compiler-rt/lib/ubsan/ubsan_handlers.h | 0 .../lib/ubsan/ubsan_handlers_cxx.cc | 0 .../lib/ubsan/ubsan_handlers_cxx.h | 0 .../compiler-rt/lib/ubsan/ubsan_init.cc | 0 .../compiler-rt/lib/ubsan/ubsan_init.h | 0 .../lib/ubsan/ubsan_init_standalone.cc | 0 .../compiler-rt/lib/ubsan/ubsan_platform.h | 0 .../compiler-rt/lib/ubsan/ubsan_type_hash.cc | 0 .../compiler-rt/lib/ubsan/ubsan_type_hash.h | 0 .../lib/ubsan/ubsan_type_hash_itanium.cc | 0 .../lib/ubsan/ubsan_type_hash_win.cc | 0 .../compiler-rt/lib/ubsan/ubsan_value.cc | 0 .../compiler-rt/lib/ubsan/ubsan_value.h | 0 .../compiler-rt/lib/ubsan/weak_symbols.txt | 0 .../compiler-rt/lib/xray/CMakeLists.txt | 0 .../compiler-rt/lib/xray/tests/CMakeLists.txt | 0 .../lib/xray/tests/unit/CMakeLists.txt | 0 .../lib/xray/tests/unit/buffer_queue_test.cc | 0 .../xray/tests/unit/xray_unit_test_main.cc | 0 .../compiler-rt/lib/xray/xray_AArch64.cc | 0 .../compiler-rt/lib/xray/xray_arm.cc | 0 .../compiler-rt/lib/xray/xray_buffer_queue.cc | 0 .../compiler-rt/lib/xray/xray_buffer_queue.h | 0 .../compiler-rt/lib/xray/xray_defs.h | 0 .../compiler-rt/lib/xray/xray_emulate_tsc.h | 0 .../compiler-rt/lib/xray/xray_flags.cc | 0 .../compiler-rt/lib/xray/xray_flags.h | 0 .../compiler-rt/lib/xray/xray_flags.inc | 0 .../compiler-rt/lib/xray/xray_init.cc | 0 .../compiler-rt/lib/xray/xray_inmemory_log.cc | 0 .../compiler-rt/lib/xray/xray_interface.cc | 0 .../lib/xray/xray_interface_internal.h | 0 .../lib/xray/xray_trampoline_AArch64.S | 0 .../lib/xray/xray_trampoline_arm.S | 0 .../lib/xray/xray_trampoline_x86_64.S | 0 .../compiler-rt/lib/xray/xray_x86_64.cc | 0 .../compiler-rt/lib/xray/xray_x86_64.h | 0 .../test/BlocksRuntime/block-static.c | 0 .../test/BlocksRuntime/blockimport.c | 0 .../test/BlocksRuntime/byrefaccess.c | 0 .../test/BlocksRuntime/byrefcopy.c | 0 .../test/BlocksRuntime/byrefcopycopy.c | 0 .../test/BlocksRuntime/byrefcopyinner.c | 0 .../test/BlocksRuntime/byrefcopyint.c | 0 .../test/BlocksRuntime/byrefcopystack.c | 0 .../test/BlocksRuntime/byrefsanity.c | 0 .../test/BlocksRuntime/byrefstruct.c | 0 .../compiler-rt/test/BlocksRuntime/c99.c | 0 .../compiler-rt/test/BlocksRuntime/cast.c | 0 .../test/BlocksRuntime/constassign.c | 0 .../copy-block-literal-rdar6439600.c | 0 .../test/BlocksRuntime/copyconstructor.C | 0 .../compiler-rt/test/BlocksRuntime/copynull.c | 0 .../test/BlocksRuntime/dispatch_async.c | 0 .../dispatch_call_Block_with_release.c | 0 .../compiler-rt/test/BlocksRuntime/fail.c | 0 .../compiler-rt/test/BlocksRuntime/flagsisa.c | 0 .../test/BlocksRuntime/globalexpression.c | 0 .../compiler-rt/test/BlocksRuntime/goto.c | 0 .../test/BlocksRuntime/hasdescriptor.c | 0 .../compiler-rt/test/BlocksRuntime/josh.C | 0 .../compiler-rt/test/BlocksRuntime/k-and-r.c | 0 .../test/BlocksRuntime/large-struct.c | 0 .../test/BlocksRuntime/localisglobal.c | 0 .../compiler-rt/test/BlocksRuntime/macro.c | 0 .../compiler-rt/test/BlocksRuntime/makefile | 0 .../test/BlocksRuntime/modglobal.c | 0 .../test/BlocksRuntime/nestedimport.c | 0 .../test/BlocksRuntime/nullblockisa.c | 0 .../test/BlocksRuntime/objectRRGC.c | 0 .../test/BlocksRuntime/objectassign.c | 0 .../compiler-rt/test/BlocksRuntime/orbars.c | 0 .../test/BlocksRuntime/rdar6396238.c | 0 .../test/BlocksRuntime/rdar6405500.c | 0 .../test/BlocksRuntime/rdar6414583.c | 0 .../test/BlocksRuntime/recursive-block.c | 0 .../test/BlocksRuntime/recursive-test.c | 0 .../test/BlocksRuntime/recursiveassign.c | 0 .../test/BlocksRuntime/reference.C | 0 .../test/BlocksRuntime/rettypepromotion.c | 0 .../test/BlocksRuntime/returnfunctionptr.c | 0 .../test/BlocksRuntime/shorthandexpression.c | 0 .../compiler-rt/test/BlocksRuntime/sizeof.c | 0 .../test/BlocksRuntime/small-struct.c | 0 .../test/BlocksRuntime/structmember.c | 0 .../test/BlocksRuntime/testfilerunner.h | 0 .../test/BlocksRuntime/testfilerunner.m | 0 .../test/BlocksRuntime/varargs-bad-assign.c | 0 .../compiler-rt/test/BlocksRuntime/varargs.c | 0 .../compiler-rt/test/BlocksRuntime/variadic.c | 0 .../compiler-rt/test/BlocksRuntime/voidarg.c | 0 .../compiler-rt/test/CMakeLists.txt | 0 .../compiler-rt/test/asan/CMakeLists.txt | 0 .../TestCases/Android/coverage-android.cc | 0 .../test/asan/TestCases/Android/lit.local.cfg | 0 .../asan/TestCases/Darwin/abort_on_error.cc | 0 .../TestCases/Darwin/address-range-limit.mm | 0 .../TestCases/Darwin/asan_gen_prefixes.cc | 0 .../Darwin/atos-symbolizer-dyld-root-path.cc | 0 .../asan/TestCases/Darwin/atos-symbolizer.cc | 0 .../TestCases/Darwin/crashlog-stacktraces.c | 0 .../Darwin/cstring_literals_regtest.mm | 0 .../asan/TestCases/Darwin/cstring_section.c | 0 .../test/asan/TestCases/Darwin/dead-strip.c | 0 .../TestCases/Darwin/dladdr-demangling.cc | 0 .../asan/TestCases/Darwin/dump_registers.cc | 0 .../Darwin/dyld_insert_libraries_reexec.cc | 0 .../Darwin/dyld_insert_libraries_remove.cc | 0 .../asan/TestCases/Darwin/empty-section.cc | 0 .../TestCases/Darwin/haswell-symbolication.cc | 0 .../Darwin/interface_symbols_darwin.c | 0 .../test/asan/TestCases/Darwin/linked-only.cc | 0 .../test/asan/TestCases/Darwin/lit.local.cfg | 0 .../TestCases/Darwin/malloc_destroy_zone.cc | 0 .../Darwin/malloc_set_zone_name-mprotect.cc | 0 .../TestCases/Darwin/malloc_size_crash.mm | 0 .../TestCases/Darwin/malloc_zone-protected.cc | 0 .../Darwin/mixing-global-constructors.cc | 0 .../test/asan/TestCases/Darwin/objc-odr.mm | 0 .../test/asan/TestCases/Darwin/odr-lto.cc | 0 .../Darwin/reexec-insert-libraries-env.cc | 0 .../TestCases/Darwin/sandbox-symbolizer.cc | 0 .../asan/TestCases/Darwin/segv_read_write.c | 0 .../TestCases/Darwin/suppressions-darwin.cc | 0 .../TestCases/Darwin/suppressions-sandbox.cc | 0 .../Darwin/unset-insert-libraries-on-exec.cc | 0 .../test/asan/TestCases/Darwin/uuid.cc | 0 .../asan/TestCases/Helpers/blacklist-extra.cc | 0 .../test/asan/TestCases/Helpers/echo-env.cc | 0 .../Helpers/init-order-atexit-extra.cc | 0 .../Helpers/initialization-blacklist-extra.cc | 0 .../initialization-blacklist-extra2.cc | 0 .../Helpers/initialization-blacklist.txt | 0 .../Helpers/initialization-bug-extra.cc | 0 .../Helpers/initialization-bug-extra2.cc | 0 .../Helpers/initialization-constexpr-extra.cc | 0 .../Helpers/initialization-nobug-extra.cc | 0 .../test/asan/TestCases/Helpers/lit.local.cfg | 0 .../asan/TestCases/Linux/abort_on_error.cc | 0 .../TestCases/Linux/activation-options.cc | 0 .../Linux/asan-asm-stacktrace-test.cc | 0 .../Linux/asan_default_suppressions.cc | 0 .../asan/TestCases/Linux/asan_dlopen_test.cc | 0 .../asan/TestCases/Linux/asan_prelink_test.cc | 0 .../TestCases/Linux/asan_preload_test-1.cc | 0 .../TestCases/Linux/asan_preload_test-2.cc | 0 .../TestCases/Linux/asan_rt_confict_test-1.cc | 0 .../TestCases/Linux/asan_rt_confict_test-2.cc | 0 .../Linux/auto_memory_profile_test.cc | 0 .../asan/TestCases/Linux/calloc-preload.c | 0 .../asan/TestCases/Linux/clang_gcc_abi.cc | 0 .../test/asan/TestCases/Linux/clone_test.cc | 0 .../asan/TestCases/Linux/coverage-missing.cc | 0 .../test/asan/TestCases/Linux/cuda_test.cc | 0 .../Linux/function-sections-are-bad.cc | 0 .../TestCases/Linux/globals-gc-sections.cc | 0 .../asan/TestCases/Linux/init-order-dlopen.cc | 0 .../TestCases/Linux/init_fini_sections.cc | 0 .../Linux/initialization-bug-any-order.cc | 0 .../Linux/interception_malloc_test.cc | 0 .../Linux/interception_readdir_r_test.cc | 0 .../asan/TestCases/Linux/interception_test.cc | 0 .../TestCases/Linux/interface_symbols_linux.c | 0 .../test/asan/TestCases/Linux/kernel-area.cc | 0 .../test/asan/TestCases/Linux/leak.cc | 0 .../asan/TestCases/Linux/leak_check_segv.cc | 0 .../test/asan/TestCases/Linux/lit.local.cfg | 0 .../test/asan/TestCases/Linux/local_alias.cc | 0 .../asan/TestCases/Linux/malloc-in-qsort.cc | 0 .../TestCases/Linux/malloc_delete_mismatch.cc | 0 .../test/asan/TestCases/Linux/memmem_test.cc | 0 .../test/asan/TestCases/Linux/mincore.cc | 0 .../TestCases/Linux/new_delete_mismatch.cc | 0 .../asan/TestCases/Linux/nohugepage_test.cc | 0 .../asan/TestCases/Linux/odr-violation.cc | 0 .../test/asan/TestCases/Linux/odr_c_test.c | 0 .../asan/TestCases/Linux/overflow-in-qsort.cc | 0 .../test/asan/TestCases/Linux/preinit_test.cc | 0 .../Linux/print_memory_profile_test.cc | 0 .../Linux/pthread_create_from_constructor.cc | 0 .../TestCases/Linux/pthread_create_version.cc | 0 .../test/asan/TestCases/Linux/ptrace.cc | 0 .../TestCases/Linux/quarantine_size_mb.cc | 0 .../Linux/read_binary_name_regtest.c | 0 .../test/asan/TestCases/Linux/recvfrom.cc | 0 .../TestCases/Linux/release_to_os_test.cc | 0 .../asan/TestCases/Linux/rlimit_mmap_test.cc | 0 .../asan/TestCases/Linux/segv_read_write.c | 0 .../test/asan/TestCases/Linux/shmctl.cc | 0 .../Linux/signal_during_stop_the_world.cc | 0 .../asan/TestCases/Linux/sized_delete_test.cc | 0 .../Linux/stack-overflow-recovery-mode.cc | 0 .../TestCases/Linux/stack-overflow-sigbus.cc | 0 .../TestCases/Linux/stack-trace-dlclose.cc | 0 .../test/asan/TestCases/Linux/static_tls.cc | 0 .../test/asan/TestCases/Linux/stress_dtls.c | 0 .../TestCases/Linux/swapcontext_annotation.cc | 0 .../asan/TestCases/Linux/swapcontext_test.cc | 0 .../test/asan/TestCases/Linux/syscalls.cc | 0 .../Linux/thread_local_quarantine_size_kb.cc | 0 .../test/asan/TestCases/Linux/uar_signals.cc | 0 .../test/asan/TestCases/Linux/unpoison_tls.cc | 0 .../asan/TestCases/Posix/allow_user_segv.cc | 0 .../Posix/asan-symbolize-bad-path.cc | 0 .../Posix/asan-symbolize-sanity-test.cc | 0 .../test/asan/TestCases/Posix/asprintf.cc | 0 .../Posix/assign_large_valloc_to_global.cc | 0 .../test/asan/TestCases/Posix/closed-fds.cc | 0 .../TestCases/Posix/coverage-caller-callee.cc | 0 .../Posix/coverage-direct-activation.cc | 0 .../TestCases/Posix/coverage-direct-large.cc | 0 .../asan/TestCases/Posix/coverage-direct.cc | 0 .../TestCases/Posix/coverage-fork-direct.cc | 0 .../asan/TestCases/Posix/coverage-fork.cc | 0 .../Posix/coverage-maybe-open-file.cc | 0 .../Posix/coverage-module-unloaded.cc | 0 .../TestCases/Posix/coverage-sandboxing.cc | 0 .../test/asan/TestCases/Posix/coverage.cc | 0 .../Posix/current_allocated_bytes.cc | 0 .../asan/TestCases/Posix/deep_call_stack.cc | 0 .../asan/TestCases/Posix/deep_thread_stack.cc | 0 .../test/asan/TestCases/Posix/dlclose-test.cc | 0 .../TestCases/Posix/dump_instruction_bytes.cc | 0 .../asan/TestCases/Posix/free_hook_realloc.cc | 0 .../test/asan/TestCases/Posix/freopen.cc | 0 .../test/asan/TestCases/Posix/gc-test.cc | 0 .../test/asan/TestCases/Posix/glob.cc | 0 .../asan/TestCases/Posix/glob_test_root/aa | 0 .../asan/TestCases/Posix/glob_test_root/ab | 0 .../asan/TestCases/Posix/glob_test_root/ba | 0 .../TestCases/Posix/global-registration.c | 0 .../TestCases/Posix/halt_on_error-signals.c | 0 .../TestCases/Posix/halt_on_error-torture.cc | 0 .../Posix/halt_on_error_suppress_equal_pcs.cc | 0 .../TestCases/Posix/handle_abort_on_error.cc | 0 .../Posix/init-order-pthread-create.cc | 0 .../Posix/interception-in-shared-lib-test.cc | 0 .../test/asan/TestCases/Posix/ioctl.cc | 0 .../large_allocator_unpoisons_on_free.cc | 0 .../test/asan/TestCases/Posix/lit.local.cfg | 0 .../Posix/log_path_fork_test.cc.disabled | 0 .../asan/TestCases/Posix/mmap_limit_mb.cc | 0 .../TestCases/Posix/new_array_cookie_test.cc | 0 .../Posix/new_array_cookie_uaf_test.cc | 0 .../new_array_cookie_with_new_from_class.cc | 0 .../TestCases/Posix/no_asan_gen_globals.c | 0 .../asan/TestCases/Posix/print_cmdline.cc | 0 .../test/asan/TestCases/Posix/readv.cc | 0 .../asan/TestCases/Posix/shared-lib-test.cc | 0 .../asan/TestCases/Posix/stack-overflow.cc | 0 .../TestCases/Posix/stack-use-after-return.cc | 0 .../asan/TestCases/Posix/start-deactivated.cc | 0 .../asan/TestCases/Posix/strerror_r_test.cc | 0 .../asan/TestCases/Posix/tsd_dtor_leak.cc | 0 .../test/asan/TestCases/Posix/wait.cc | 0 .../test/asan/TestCases/Posix/wait3.cc | 0 .../test/asan/TestCases/Posix/wait4.cc | 0 .../test/asan/TestCases/Posix/waitid.cc | 0 .../asan/TestCases/Windows/aligned_mallocs.cc | 0 .../TestCases/Windows/allocators_sanity.cc | 0 .../asan/TestCases/Windows/beginthreadex.cc | 0 .../Windows/bind_io_completion_callback.cc | 0 .../test/asan/TestCases/Windows/bitfield.cc | 0 .../asan/TestCases/Windows/bitfield_uaf.cc | 0 .../asan/TestCases/Windows/calloc_left_oob.cc | 0 .../TestCases/Windows/calloc_right_oob.cc | 0 .../test/asan/TestCases/Windows/calloc_uaf.cc | 0 .../asan/TestCases/Windows/coverage-basic.cc | 0 .../TestCases/Windows/coverage-dll-stdio.cc | 0 .../TestCases/Windows/crash_read_write.cc | 0 .../TestCases/Windows/crt_initializers.cc | 0 .../asan/TestCases/Windows/delay_dbghelp.cc | 0 .../asan/TestCases/Windows/demangled_names.cc | 0 .../TestCases/Windows/dll_aligned_mallocs.cc | 0 .../Windows/dll_allocators_sanity.cc | 0 .../asan/TestCases/Windows/dll_and_lib.cc | 0 .../test/asan/TestCases/Windows/dll_cerr.cc | 0 .../asan/TestCases/Windows/dll_control_c.cc | 0 .../TestCases/Windows/dll_global_dead_strip.c | 0 .../test/asan/TestCases/Windows/dll_host.cc | 0 .../TestCases/Windows/dll_intercept_memchr.cc | 0 .../TestCases/Windows/dll_intercept_memcpy.cc | 0 .../Windows/dll_intercept_memcpy_indirect.cc | 0 .../TestCases/Windows/dll_intercept_memset.cc | 0 .../TestCases/Windows/dll_intercept_strlen.cc | 0 .../TestCases/Windows/dll_large_function.cc | 0 .../TestCases/Windows/dll_malloc_left_oob.cc | 0 .../asan/TestCases/Windows/dll_malloc_uaf.cc | 0 .../asan/TestCases/Windows/dll_noreturn.cc | 0 .../asan/TestCases/Windows/dll_null_deref.cc | 0 .../dll_operator_array_new_left_oob.cc | 0 ...l_operator_array_new_with_dtor_left_oob.cc | 0 .../TestCases/Windows/dll_poison_unpoison.cc | 0 ...report_globals_symbolization_at_startup.cc | 0 .../test/asan/TestCases/Windows/dll_seh.cc | 0 .../Windows/dll_stack_use_after_return.cc | 0 .../dll_thread_stack_array_left_oob.cc | 0 .../asan/TestCases/Windows/double_free.cc | 0 .../Windows/double_operator_delete.cc | 0 .../TestCases/Windows/free_hook_realloc.cc | 0 .../test/asan/TestCases/Windows/fuse-lld.cc | 0 .../TestCases/Windows/global_const_string.cc | 0 .../Windows/global_const_string_oob.cc | 0 .../TestCases/Windows/global_dead_strip.c | 0 .../asan/TestCases/Windows/hello_world.cc | 0 .../TestCases/Windows/intercept_memcpy.cc | 0 .../TestCases/Windows/intercept_strdup.cc | 0 .../TestCases/Windows/intercept_strlen.cc | 0 .../asan/TestCases/Windows/iostream_sbo.cc | 0 .../test/asan/TestCases/Windows/lit.local.cfg | 0 .../test/asan/TestCases/Windows/longjmp.cc | 0 .../asan/TestCases/Windows/malloc_left_oob.cc | 0 .../TestCases/Windows/malloc_right_oob.cc | 0 .../test/asan/TestCases/Windows/malloc_uaf.cc | 0 .../test/asan/TestCases/Windows/null_deref.cc | 0 .../Windows/null_deref_multiple_dlls.cc | 0 .../test/asan/TestCases/Windows/oom.cc | 0 .../Windows/operator_array_new_left_oob.cc | 0 .../Windows/operator_array_new_right_oob.cc | 0 .../Windows/operator_array_new_uaf.cc | 0 .../operator_array_new_with_dtor_left_oob.cc | 0 .../Windows/operator_delete_wrong_argument.cc | 0 .../Windows/operator_new_left_oob.cc | 0 .../Windows/operator_new_right_oob.cc | 0 .../TestCases/Windows/operator_new_uaf.cc | 0 .../TestCases/Windows/queue_user_work_item.cc | 0 .../Windows/queue_user_work_item_report.cc | 0 .../TestCases/Windows/realloc_left_oob.cc | 0 .../TestCases/Windows/realloc_right_oob.cc | 0 .../asan/TestCases/Windows/realloc_uaf.cc | 0 .../Windows/report_after_syminitialize.cc | 0 .../Windows/report_globals_reload_dll.cc | 0 .../Windows/report_globals_vs_freelibrary.cc | 0 .../test/asan/TestCases/Windows/seh.cc | 0 .../TestCases/Windows/shadow_conflict_32.cc | 0 .../Windows/shadow_mapping_failure.cc | 0 .../TestCases/Windows/stack_array_left_oob.cc | 0 .../Windows/stack_array_right_oob.cc | 0 .../TestCases/Windows/stack_array_sanity.cc | 0 .../Windows/stack_use_after_return.cc | 0 .../asan/TestCases/Windows/symbols_path.cc | 0 .../asan/TestCases/Windows/thread_simple.cc | 0 .../Windows/thread_stack_array_left_oob.cc | 0 .../Windows/thread_stack_array_right_oob.cc | 0 .../TestCases/Windows/thread_stack_reuse.cc | 0 .../asan/TestCases/Windows/thread_stress.cc | 0 .../TestCases/Windows/thread_suspended.cc | 0 .../test/asan/TestCases/Windows/tls_init.cc | 0 .../asan/TestCases/Windows/unsymbolized.cc | 0 .../TestCases/Windows/use_after_realloc.cc | 0 .../Windows/use_after_return_linkage.cc | 0 .../test/asan/TestCases/Windows/windows_h.cc | 0 .../Windows/wrong_downcast_on_heap.cc | 0 .../Windows/wrong_downcast_on_stack.cc | 0 .../asan/TestCases/alloca_big_alignment.cc | 0 .../asan/TestCases/alloca_constant_size.cc | 0 .../TestCases/alloca_detect_custom_size_.cc | 0 .../alloca_instruments_all_paddings.cc | 0 .../asan/TestCases/alloca_loop_unpoisoning.cc | 0 .../asan/TestCases/alloca_overflow_partial.cc | 0 .../asan/TestCases/alloca_overflow_right.cc | 0 .../test/asan/TestCases/alloca_safe_access.cc | 0 .../asan/TestCases/alloca_underflow_left.cc | 0 .../asan/TestCases/alloca_vla_interact.cc | 0 .../asan/TestCases/allocator_returns_null.cc | 0 .../TestCases/asan_and_llvm_coverage_test.cc | 0 .../test/asan/TestCases/asan_options-help.cc | 0 .../test/asan/TestCases/atexit_stats.cc | 0 .../test/asan/TestCases/atoi_strict.c | 0 .../test/asan/TestCases/atol_strict.c | 0 .../test/asan/TestCases/atoll_strict.c | 0 .../test/asan/TestCases/blacklist.cc | 0 .../asan/TestCases/contiguous_container.cc | 0 .../TestCases/contiguous_container_crash.cc | 0 .../test/asan/TestCases/coverage-and-lsan.cc | 0 .../coverage-caller-callee-total-count.cc | 0 .../test/asan/TestCases/coverage-disabled.cc | 0 .../test/asan/TestCases/coverage-levels.cc | 0 .../test/asan/TestCases/coverage-order-pcs.cc | 0 .../test/asan/TestCases/coverage-reset.cc | 0 .../test/asan/TestCases/coverage-trace-pc.cc | 0 .../test/asan/TestCases/coverage-tracing.cc | 0 .../test/asan/TestCases/debug_double_free.cc | 0 .../test/asan/TestCases/debug_locate.cc | 0 .../test/asan/TestCases/debug_mapping.cc | 0 .../asan/TestCases/debug_ppc64_mapping.cc | 0 .../test/asan/TestCases/debug_report.cc | 0 .../test/asan/TestCases/debug_stacks.cc | 0 .../test/asan/TestCases/deep_stack_uaf.cc | 0 .../test/asan/TestCases/deep_tail_call.cc | 0 .../test/asan/TestCases/default_blacklist.cc | 0 .../test/asan/TestCases/default_options.cc | 0 .../test/asan/TestCases/describe_address.cc | 0 .../test/asan/TestCases/double-free.cc | 0 .../test/asan/TestCases/exitcode.cc | 0 .../test/asan/TestCases/force_inline_opt0.cc | 0 .../test/asan/TestCases/frexp_interceptor.cc | 0 .../test/asan/TestCases/global-address.cpp | 0 .../test/asan/TestCases/global-demangle.cc | 0 .../test/asan/TestCases/global-location.cc | 0 .../test/asan/TestCases/global-overflow.cc | 0 .../test/asan/TestCases/halt_on_error-1.c | 0 .../asan/TestCases/heap-overflow-large.cc | 0 .../test/asan/TestCases/heap-overflow.cc | 0 .../test/asan/TestCases/heavy_uar_test.cc | 0 .../asan/TestCases/huge_negative_hea_oob.cc | 0 .../compiler-rt/test/asan/TestCases/ill.cc | 0 .../test/asan/TestCases/init-order-atexit.cc | 0 .../TestCases/initialization-blacklist.cc | 0 .../test/asan/TestCases/initialization-bug.cc | 0 .../TestCases/initialization-constexpr.cc | 0 .../asan/TestCases/initialization-nobug.cc | 0 .../compiler-rt/test/asan/TestCases/inline.cc | 0 .../TestCases/interception_failure_test.cc | 0 .../test/asan/TestCases/interface_test.cc | 0 .../asan/TestCases/intra-object-overflow.cc | 0 .../test/asan/TestCases/invalid-free.cc | 0 .../asan/TestCases/invalid-pointer-pairs.cc | 0 .../test/asan/TestCases/large_func_test.cc | 0 .../test/asan/TestCases/log-path_test.cc | 0 .../test/asan/TestCases/longjmp.cc | 0 .../test/asan/TestCases/lsan_annotations.cc | 0 .../test/asan/TestCases/malloc-no-intercept.c | 0 .../asan/TestCases/malloc_context_size.cc | 0 .../test/asan/TestCases/malloc_fill.cc | 0 .../test/asan/TestCases/max_redzone.cc | 0 .../test/asan/TestCases/memcmp_strict_test.cc | 0 .../test/asan/TestCases/memcmp_test.cc | 0 .../test/asan/TestCases/memset_test.cc | 0 .../test/asan/TestCases/null_deref.cc | 0 .../test/asan/TestCases/on_error_callback.cc | 0 .../test/asan/TestCases/partial_right.cc | 0 .../test/asan/TestCases/poison_partial.cc | 0 .../test/asan/TestCases/print_summary.cc | 0 .../test/asan/TestCases/printf-1.c | 0 .../test/asan/TestCases/printf-2.c | 0 .../test/asan/TestCases/printf-3.c | 0 .../test/asan/TestCases/printf-4.c | 0 .../test/asan/TestCases/printf-5.c | 0 .../test/asan/TestCases/printf-m.c | 0 .../test/asan/TestCases/sanity_check_pure_c.c | 0 .../asan/TestCases/scariness_score_test.cc | 0 .../test/asan/TestCases/set_shadow_test.c | 0 .../test/asan/TestCases/sleep_before_dying.c | 0 .../test/asan/TestCases/speculative_load.cc | 0 .../test/asan/TestCases/speculative_load2.cc | 0 .../stack-buffer-overflow-with-position.cc | 0 .../asan/TestCases/stack-buffer-overflow.cc | 0 .../asan/TestCases/stack-frame-demangle.cc | 0 .../test/asan/TestCases/stack-oob-frames.cc | 0 .../test/asan/TestCases/strcasestr-1.c | 0 .../test/asan/TestCases/strcasestr-2.c | 0 .../test/asan/TestCases/strcasestr_strict.c | 0 .../test/asan/TestCases/strcat_strict.c | 0 .../test/asan/TestCases/strchr_strict.c | 0 .../test/asan/TestCases/strcmp_strict.c | 0 .../test/asan/TestCases/strcspn-1.c | 0 .../test/asan/TestCases/strcspn-2.c | 0 .../test/asan/TestCases/strcspn_strict.c | 0 .../test/asan/TestCases/strdup_oob_test.cc | 0 .../test/asan/TestCases/strip_path_prefix.c | 0 .../test/asan/TestCases/strncasecmp_strict.c | 0 .../test/asan/TestCases/strncat_strict.c | 0 .../test/asan/TestCases/strncmp_strict.c | 0 .../test/asan/TestCases/strncpy-overflow.cc | 0 .../test/asan/TestCases/strpbrk-1.c | 0 .../test/asan/TestCases/strpbrk-2.c | 0 .../test/asan/TestCases/strpbrk_strict.c | 0 .../test/asan/TestCases/strspn-1.c | 0 .../test/asan/TestCases/strspn-2.c | 0 .../test/asan/TestCases/strspn_strict.c | 0 .../test/asan/TestCases/strstr-1.c | 0 .../test/asan/TestCases/strstr-2.c | 0 .../test/asan/TestCases/strstr_strict.c | 0 .../test/asan/TestCases/strtol_strict.c | 0 .../test/asan/TestCases/strtoll_strict.c | 0 .../suppressions-exec-relative-location.cc | 0 .../asan/TestCases/suppressions-function.cc | 0 .../TestCases/suppressions-interceptor.cc | 0 .../asan/TestCases/suppressions-library.cc | 0 .../test/asan/TestCases/throw_call_test.cc | 0 .../test/asan/TestCases/throw_catch.cc | 0 .../test/asan/TestCases/throw_invoke_test.cc | 0 .../test/asan/TestCases/time_interceptor.cc | 0 .../test/asan/TestCases/uar_and_exceptions.cc | 0 .../TestCases/unaligned_loads_and_stores.cc | 0 .../test/asan/TestCases/use-after-delete.cc | 0 .../asan/TestCases/use-after-free-right.cc | 0 .../test/asan/TestCases/use-after-free.cc | 0 .../test/asan/TestCases/use-after-poison.cc | 0 .../asan/TestCases/use-after-scope-capture.cc | 0 .../TestCases/use-after-scope-dtor-order.cc | 0 .../asan/TestCases/use-after-scope-goto.cc | 0 .../test/asan/TestCases/use-after-scope-if.cc | 0 .../asan/TestCases/use-after-scope-inlined.cc | 0 .../TestCases/use-after-scope-loop-bug.cc | 0 .../TestCases/use-after-scope-loop-removed.cc | 0 .../asan/TestCases/use-after-scope-loop.cc | 0 .../asan/TestCases/use-after-scope-nobug.cc | 0 .../asan/TestCases/use-after-scope-temp.cc | 0 .../asan/TestCases/use-after-scope-temp2.cc | 0 .../asan/TestCases/use-after-scope-types.cc | 0 .../test/asan/TestCases/use-after-scope.cc | 0 .../asan/TestCases/verbose-log-path_test.cc | 0 .../asan/TestCases/vla_chrome_testcase.cc | 0 .../asan/TestCases/vla_condition_overflow.cc | 0 .../test/asan/TestCases/vla_loop_overfow.cc | 0 .../test/asan/TestCases/zero_page_pc.cc | 0 .../test/asan/Unit/lit.site.cfg.in | 0 .../asan/android_commands/android_common.py | 0 .../asan/android_commands/android_compile.py | 0 .../test/asan/android_commands/android_run.py | 0 .../compiler-rt/test/asan/lit.cfg | 0 .../compiler-rt/test/asan/lit.site.cfg.in | 0 .../test/builtins/Unit/absvdi2_test.c | 0 .../test/builtins/Unit/absvsi2_test.c | 0 .../test/builtins/Unit/absvti2_test.c | 0 .../test/builtins/Unit/adddf3vfp_test.c | 0 .../test/builtins/Unit/addsf3vfp_test.c | 0 .../test/builtins/Unit/addtf3_test.c | 0 .../test/builtins/Unit/addvdi3_test.c | 0 .../test/builtins/Unit/addvsi3_test.c | 0 .../test/builtins/Unit/addvti3_test.c | 0 .../builtins/Unit/arm/aeabi_cdcmpeq_test.c | 0 .../builtins/Unit/arm/aeabi_cdcmple_test.c | 0 .../builtins/Unit/arm/aeabi_cfcmpeq_test.c | 0 .../builtins/Unit/arm/aeabi_cfcmple_test.c | 0 .../test/builtins/Unit/arm/aeabi_drsub_test.c | 0 .../test/builtins/Unit/arm/aeabi_frsub_test.c | 0 .../test/builtins/Unit/arm/call_apsr.S | 0 .../test/builtins/Unit/arm/call_apsr.h | 0 .../test/builtins/Unit/ashldi3_test.c | 0 .../test/builtins/Unit/ashlti3_test.c | 0 .../test/builtins/Unit/ashrdi3_test.c | 0 .../test/builtins/Unit/ashrti3_test.c | 0 .../test/builtins/Unit/bswapdi2_test.c | 0 .../test/builtins/Unit/bswapsi2_test.c | 0 .../test/builtins/Unit/clear_cache_test.c | 0 .../test/builtins/Unit/clzdi2_test.c | 0 .../test/builtins/Unit/clzsi2_test.c | 0 .../test/builtins/Unit/clzti2_test.c | 0 .../test/builtins/Unit/cmpdi2_test.c | 0 .../test/builtins/Unit/cmpti2_test.c | 0 .../test/builtins/Unit/comparedf2_test.c | 0 .../test/builtins/Unit/comparesf2_test.c | 0 .../test/builtins/Unit/cpu_model_test.c | 0 .../test/builtins/Unit/ctzdi2_test.c | 0 .../test/builtins/Unit/ctzsi2_test.c | 0 .../test/builtins/Unit/ctzti2_test.c | 0 .../test/builtins/Unit/divdc3_test.c | 0 .../test/builtins/Unit/divdf3vfp_test.c | 0 .../test/builtins/Unit/divdi3_test.c | 0 .../test/builtins/Unit/divmodsi4_test.c | 0 .../test/builtins/Unit/divsc3_test.c | 0 .../test/builtins/Unit/divsf3vfp_test.c | 0 .../test/builtins/Unit/divsi3_test.c | 0 .../test/builtins/Unit/divtc3_test.c | 0 .../test/builtins/Unit/divtf3_test.c | 0 .../test/builtins/Unit/divti3_test.c | 0 .../test/builtins/Unit/divxc3_test.c | 0 .../builtins/Unit/enable_execute_stack_test.c | 0 .../test/builtins/Unit/endianness.h | 0 .../test/builtins/Unit/eqdf2vfp_test.c | 0 .../test/builtins/Unit/eqsf2vfp_test.c | 0 .../test/builtins/Unit/eqtf2_test.c | 0 .../test/builtins/Unit/extebdsfdf2vfp_test.c | 0 .../test/builtins/Unit/extenddftf2_test.c | 0 .../test/builtins/Unit/extendhfsf2_test.c | 0 .../test/builtins/Unit/extendsftf2_test.c | 0 .../test/builtins/Unit/ffsdi2_test.c | 0 .../test/builtins/Unit/ffsti2_test.c | 0 .../test/builtins/Unit/fixdfdi_test.c | 0 .../test/builtins/Unit/fixdfsivfp_test.c | 0 .../test/builtins/Unit/fixdfti_test.c | 0 .../test/builtins/Unit/fixsfdi_test.c | 0 .../test/builtins/Unit/fixsfsivfp_test.c | 0 .../test/builtins/Unit/fixsfti_test.c | 0 .../test/builtins/Unit/fixtfdi_test.c | 0 .../test/builtins/Unit/fixtfsi_test.c | 0 .../test/builtins/Unit/fixtfti_test.c | 0 .../test/builtins/Unit/fixunsdfdi_test.c | 0 .../test/builtins/Unit/fixunsdfsi_test.c | 0 .../test/builtins/Unit/fixunsdfsivfp_test.c | 0 .../test/builtins/Unit/fixunsdfti_test.c | 0 .../test/builtins/Unit/fixunssfdi_test.c | 0 .../test/builtins/Unit/fixunssfsi_test.c | 0 .../test/builtins/Unit/fixunssfsivfp_test.c | 0 .../test/builtins/Unit/fixunssfti_test.c | 0 .../test/builtins/Unit/fixunstfdi_test.c | 0 .../test/builtins/Unit/fixunstfsi_test.c | 0 .../test/builtins/Unit/fixunstfti_test.c | 0 .../test/builtins/Unit/fixunsxfdi_test.c | 0 .../test/builtins/Unit/fixunsxfsi_test.c | 0 .../test/builtins/Unit/fixunsxfti_test.c | 0 .../test/builtins/Unit/fixxfdi_test.c | 0 .../test/builtins/Unit/fixxfti_test.c | 0 .../test/builtins/Unit/floatdidf_test.c | 0 .../test/builtins/Unit/floatdisf_test.c | 0 .../test/builtins/Unit/floatditf_test.c | 0 .../test/builtins/Unit/floatdixf_test.c | 0 .../test/builtins/Unit/floatsidfvfp_test.c | 0 .../test/builtins/Unit/floatsisfvfp_test.c | 0 .../test/builtins/Unit/floatsitf_test.c | 0 .../test/builtins/Unit/floattidf_test.c | 0 .../test/builtins/Unit/floattisf_test.c | 0 .../test/builtins/Unit/floattitf_test.c | 0 .../test/builtins/Unit/floattixf_test.c | 0 .../test/builtins/Unit/floatundidf_test.c | 0 .../test/builtins/Unit/floatundisf_test.c | 0 .../test/builtins/Unit/floatunditf_test.c | 0 .../test/builtins/Unit/floatundixf_test.c | 0 .../test/builtins/Unit/floatunsitf_test.c | 0 .../test/builtins/Unit/floatunssidfvfp_test.c | 0 .../test/builtins/Unit/floatunssisfvfp_test.c | 0 .../test/builtins/Unit/floatuntidf_test.c | 0 .../test/builtins/Unit/floatuntisf_test.c | 0 .../test/builtins/Unit/floatuntitf_test.c | 0 .../test/builtins/Unit/floatuntixf_test.c | 0 .../compiler-rt/test/builtins/Unit/fp_test.h | 0 .../test/builtins/Unit/gcc_personality_test.c | 0 .../Unit/gcc_personality_test_helper.cxx | 0 .../test/builtins/Unit/gedf2vfp_test.c | 0 .../test/builtins/Unit/gesf2vfp_test.c | 0 .../test/builtins/Unit/getf2_test.c | 0 .../test/builtins/Unit/gtdf2vfp_test.c | 0 .../test/builtins/Unit/gtsf2vfp_test.c | 0 .../test/builtins/Unit/gttf2_test.c | 0 .../test/builtins/Unit/ledf2vfp_test.c | 0 .../test/builtins/Unit/lesf2vfp_test.c | 0 .../test/builtins/Unit/letf2_test.c | 0 .../test/builtins/Unit/lshrdi3_test.c | 0 .../test/builtins/Unit/lshrti3_test.c | 0 .../test/builtins/Unit/ltdf2vfp_test.c | 0 .../test/builtins/Unit/ltsf2vfp_test.c | 0 .../test/builtins/Unit/lttf2_test.c | 0 .../test/builtins/Unit/moddi3_test.c | 0 .../test/builtins/Unit/modsi3_test.c | 0 .../test/builtins/Unit/modti3_test.c | 0 .../test/builtins/Unit/muldc3_test.c | 0 .../test/builtins/Unit/muldf3vfp_test.c | 0 .../test/builtins/Unit/muldi3_test.c | 0 .../test/builtins/Unit/mulodi4_test.c | 0 .../test/builtins/Unit/mulosi4_test.c | 0 .../test/builtins/Unit/muloti4_test.c | 0 .../test/builtins/Unit/mulsc3_test.c | 0 .../test/builtins/Unit/mulsf3vfp_test.c | 0 .../test/builtins/Unit/multc3_test.c | 0 .../test/builtins/Unit/multf3_test.c | 0 .../test/builtins/Unit/multi3_test.c | 0 .../test/builtins/Unit/mulvdi3_test.c | 0 .../test/builtins/Unit/mulvsi3_test.c | 0 .../test/builtins/Unit/mulvti3_test.c | 0 .../test/builtins/Unit/mulxc3_test.c | 0 .../test/builtins/Unit/nedf2vfp_test.c | 0 .../test/builtins/Unit/negdf2vfp_test.c | 0 .../test/builtins/Unit/negdi2_test.c | 0 .../test/builtins/Unit/negsf2vfp_test.c | 0 .../test/builtins/Unit/negti2_test.c | 0 .../test/builtins/Unit/negvdi2_test.c | 0 .../test/builtins/Unit/negvsi2_test.c | 0 .../test/builtins/Unit/negvti2_test.c | 0 .../test/builtins/Unit/nesf2vfp_test.c | 0 .../test/builtins/Unit/netf2_test.c | 0 .../test/builtins/Unit/paritydi2_test.c | 0 .../test/builtins/Unit/paritysi2_test.c | 0 .../test/builtins/Unit/parityti2_test.c | 0 .../test/builtins/Unit/popcountdi2_test.c | 0 .../test/builtins/Unit/popcountsi2_test.c | 0 .../test/builtins/Unit/popcountti2_test.c | 0 .../test/builtins/Unit/powidf2_test.c | 0 .../test/builtins/Unit/powisf2_test.c | 0 .../test/builtins/Unit/powitf2_test.c | 0 .../test/builtins/Unit/powixf2_test.c | 0 .../compiler-rt/test/builtins/Unit/ppc/DD.h | 0 .../test/builtins/Unit/ppc/fixtfdi_test.c | 0 .../test/builtins/Unit/ppc/floatditf_test.c | 0 .../test/builtins/Unit/ppc/floatditf_test.h | 0 .../test/builtins/Unit/ppc/floatunditf_test.c | 0 .../test/builtins/Unit/ppc/floatunditf_test.h | 0 .../test/builtins/Unit/ppc/qadd_test.c | 0 .../test/builtins/Unit/ppc/qdiv_test.c | 0 .../test/builtins/Unit/ppc/qmul_test.c | 0 .../test/builtins/Unit/ppc/qsub_test.c | 0 .../compiler-rt/test/builtins/Unit/ppc/test | 0 .../test/builtins/Unit/subdf3vfp_test.c | 0 .../test/builtins/Unit/subsf3vfp_test.c | 0 .../test/builtins/Unit/subtf3_test.c | 0 .../test/builtins/Unit/subvdi3_test.c | 0 .../test/builtins/Unit/subvsi3_test.c | 0 .../test/builtins/Unit/subvti3_test.c | 0 .../compiler-rt/test/builtins/Unit/test | 0 .../builtins/Unit/trampoline_setup_test.c | 0 .../test/builtins/Unit/truncdfhf2_test.c | 0 .../test/builtins/Unit/truncdfsf2_test.c | 0 .../test/builtins/Unit/truncdfsf2vfp_test.c | 0 .../test/builtins/Unit/truncsfhf2_test.c | 0 .../test/builtins/Unit/trunctfdf2_test.c | 0 .../test/builtins/Unit/trunctfsf2_test.c | 0 .../test/builtins/Unit/ucmpdi2_test.c | 0 .../test/builtins/Unit/ucmpti2_test.c | 0 .../test/builtins/Unit/udivdi3_test.c | 0 .../test/builtins/Unit/udivmoddi4_test.c | 0 .../test/builtins/Unit/udivmodsi4_test.c | 0 .../test/builtins/Unit/udivmodti4_test.c | 0 .../test/builtins/Unit/udivsi3_test.c | 0 .../test/builtins/Unit/udivti3_test.c | 0 .../test/builtins/Unit/umoddi3_test.c | 0 .../test/builtins/Unit/umodsi3_test.c | 0 .../test/builtins/Unit/umodti3_test.c | 0 .../test/builtins/Unit/unorddf2vfp_test.c | 0 .../test/builtins/Unit/unordsf2vfp_test.c | 0 .../test/builtins/Unit/unordtf2_test.c | 0 .../test/builtins/timing/ashldi3.c | 0 .../test/builtins/timing/ashrdi3.c | 0 .../compiler-rt/test/builtins/timing/divdi3.c | 0 .../test/builtins/timing/floatdidf.c | 0 .../test/builtins/timing/floatdisf.c | 0 .../test/builtins/timing/floatdixf.c | 0 .../test/builtins/timing/floatundidf.c | 0 .../test/builtins/timing/floatundisf.c | 0 .../test/builtins/timing/floatundixf.c | 0 .../test/builtins/timing/lshrdi3.c | 0 .../compiler-rt/test/builtins/timing/moddi3.c | 0 .../compiler-rt/test/builtins/timing/modsi3.c | 0 .../compiler-rt/test/builtins/timing/muldi3.c | 0 .../compiler-rt/test/builtins/timing/negdi2.c | 0 .../compiler-rt/test/builtins/timing/time | 0 .../compiler-rt/test/builtins/timing/timing.h | 0 .../test/builtins/timing/udivdi3.c | 0 .../test/builtins/timing/umoddi3.c | 0 .../compiler-rt/test/cfi/CMakeLists.txt | 0 .../compiler-rt/test/cfi/README.txt | 0 .../compiler-rt/test/cfi/anon-namespace.cpp | 0 .../compiler-rt/test/cfi/bad-cast.cpp | 0 .../test/cfi/base-derived-destructor.cpp | 0 .../compiler-rt/test/cfi/create-derivers.test | 0 .../compiler-rt/test/cfi/cross-dso/dlopen.cpp | 0 .../test/cfi/cross-dso/icall/diag.cpp | 0 .../cfi/cross-dso/icall/icall-from-dso.cpp | 0 .../test/cfi/cross-dso/icall/icall.cpp | 0 .../test/cfi/cross-dso/icall/lit.local.cfg | 0 .../test/cfi/cross-dso/lit.local.cfg | 0 .../cfi/cross-dso/shadow_is_read_only.cpp | 0 .../test/cfi/cross-dso/simple-fail.cpp | 0 .../test/cfi/cross-dso/simple-pass.cpp | 0 .../compiler-rt/test/cfi/cross-dso/stats.cpp | 0 .../cfi/cross-dso/target_out_of_bounds.cpp | 0 .../test/cfi/icall/bad-signature.c | 0 .../test/cfi/icall/external-call.c | 0 .../compiler-rt/test/cfi/icall/lit.local.cfg | 0 .../compiler-rt/test/cfi/icall/weak.c | 0 .../compiler-rt/test/cfi/lit.cfg | 0 .../compiler-rt/test/cfi/lit.site.cfg.in | 0 .../test/cfi/multiple-inheritance.cpp | 0 .../compiler-rt/test/cfi/nvcall.cpp | 0 .../compiler-rt/test/cfi/overwrite.cpp | 0 .../compiler-rt/test/cfi/sibling.cpp | 0 .../compiler-rt/test/cfi/simple-fail.cpp | 0 .../compiler-rt/test/cfi/simple-pass.cpp | 0 .../compiler-rt/test/cfi/stats.cpp | 0 .../test/cfi/target_uninstrumented.cpp | 0 .../compiler-rt/test/cfi/two-vcalls.cpp | 0 .../compiler-rt/test/cfi/utils.h | 0 .../compiler-rt/test/cfi/vdtor.cpp | 0 .../compiler-rt/test/dfsan/CMakeLists.txt | 0 .../test/dfsan/Inputs/flags_abilist.txt | 0 .../compiler-rt/test/dfsan/basic.c | 0 .../compiler-rt/test/dfsan/custom.cc | 0 .../compiler-rt/test/dfsan/dump_labels.c | 0 .../compiler-rt/test/dfsan/flags.c | 0 .../compiler-rt/test/dfsan/fncall.c | 0 .../compiler-rt/test/dfsan/label_count.c | 0 .../compiler-rt/test/dfsan/lit.cfg | 0 .../compiler-rt/test/dfsan/lit.site.cfg.in | 0 .../compiler-rt/test/dfsan/propagate.c | 0 .../compiler-rt/test/dfsan/vararg.c | 0 .../compiler-rt/test/dfsan/write_callback.c | 0 .../compiler-rt/test/esan/CMakeLists.txt | 0 .../test/esan/TestCases/large-stack-linux.c | 0 .../test/esan/TestCases/libc-intercept.c | 0 .../esan/TestCases/mmap-shadow-conflict.c | 0 .../test/esan/TestCases/struct-simple.cpp | 0 .../test/esan/TestCases/verbose-simple.c | 0 .../esan/TestCases/workingset-early-fault.c | 0 .../test/esan/TestCases/workingset-memset.cpp | 0 .../esan/TestCases/workingset-midreport.cpp | 0 .../esan/TestCases/workingset-samples.cpp | 0 .../TestCases/workingset-signal-posix.cpp | 0 .../test/esan/TestCases/workingset-simple.cpp | 0 .../test/esan/Unit/circular_buffer.cpp | 0 .../compiler-rt/test/esan/Unit/hashtable.cpp | 0 .../compiler-rt/test/esan/lit.cfg | 0 .../compiler-rt/test/esan/lit.site.cfg.in | 0 .../test/interception/CMakeLists.txt | 0 .../test/interception/Unit/lit.site.cfg.in | 0 .../compiler-rt/test/lit.common.cfg | 0 .../compiler-rt/test/lit.common.configured.in | 0 .../compiler-rt/test/lsan/CMakeLists.txt | 0 .../TestCases/cleanup_in_tsd_destructor.c | 0 .../test/lsan/TestCases/disabler.c | 0 .../test/lsan/TestCases/disabler.cc | 0 .../TestCases/disabler_in_tsd_destructor.c | 0 .../lsan/TestCases/do_leak_check_override.cc | 0 .../compiler-rt/test/lsan/TestCases/fork.cc | 0 .../test/lsan/TestCases/fork_threaded.cc | 0 .../test/lsan/TestCases/guard-page.c | 0 .../TestCases/high_allocator_contention.cc | 0 .../test/lsan/TestCases/ignore_object.c | 0 .../lsan/TestCases/ignore_object_errors.cc | 0 .../lsan/TestCases/large_allocation_leak.cc | 0 .../test/lsan/TestCases/leak_check_at_exit.cc | 0 .../leak_check_before_thread_started.cc | 0 .../test/lsan/TestCases/link_turned_off.cc | 0 .../lsan/TestCases/new_array_with_dtor_0.cc | 0 .../test/lsan/TestCases/pointer_to_self.cc | 0 .../test/lsan/TestCases/print_suppressions.cc | 0 .../lsan/TestCases/recoverable_leak_check.cc | 0 .../lsan/TestCases/register_root_region.cc | 0 .../test/lsan/TestCases/sanity_check_pure_c.c | 0 .../test/lsan/TestCases/stale_stack_leak.cc | 0 .../test/lsan/TestCases/strace_test.cc | 0 .../lsan/TestCases/suppressions_default.cc | 0 .../test/lsan/TestCases/suppressions_file.cc | 0 .../test/lsan/TestCases/swapcontext.cc | 0 .../test/lsan/TestCases/use_after_return.cc | 0 .../lsan/TestCases/use_globals_initialized.cc | 0 .../TestCases/use_globals_uninitialized.cc | 0 .../test/lsan/TestCases/use_poisoned_asan.cc | 0 .../test/lsan/TestCases/use_registers.cc | 0 .../test/lsan/TestCases/use_stacks.cc | 0 .../lsan/TestCases/use_stacks_threaded.cc | 0 .../test/lsan/TestCases/use_tls_dynamic.cc | 0 .../use_tls_pthread_specific_dynamic.cc | 0 .../use_tls_pthread_specific_static.cc | 0 .../test/lsan/TestCases/use_tls_static.cc | 0 .../test/lsan/TestCases/use_unaligned.cc | 0 .../compiler-rt/test/lsan/lit.common.cfg | 0 .../compiler-rt/test/lsan/lit.site.cfg.in | 0 .../compiler-rt/test/msan/CMakeLists.txt | 0 .../compiler-rt/test/msan/Linux/cmsghdr.cc | 0 .../compiler-rt/test/msan/Linux/eventfd.cc | 0 .../test/msan/Linux/fopencookie.cc | 0 .../compiler-rt/test/msan/Linux/forkpty.cc | 0 .../compiler-rt/test/msan/Linux/getresid.cc | 0 .../compiler-rt/test/msan/Linux/glob.cc | 0 .../test/msan/Linux/glob_altdirfunc.cc | 0 .../test/msan/Linux/glob_nomatch.cc | 0 .../test/msan/Linux/glob_test_root/aa | 0 .../test/msan/Linux/glob_test_root/ab | 0 .../test/msan/Linux/glob_test_root/ba | 0 .../test/msan/Linux/ioctl_sound.cc | 0 .../compiler-rt/test/msan/Linux/lit.local.cfg | 0 .../compiler-rt/test/msan/Linux/mallinfo.cc | 0 .../compiler-rt/test/msan/Linux/mincore.cc | 0 .../compiler-rt/test/msan/Linux/obstack.cc | 0 .../test/msan/Linux/process_vm_readv.cc | 0 .../compiler-rt/test/msan/Linux/sendmsg.cc | 0 .../compiler-rt/test/msan/Linux/sunrpc.cc | 0 .../test/msan/Linux/sunrpc_bytes.cc | 0 .../test/msan/Linux/sunrpc_string.cc | 0 .../compiler-rt/test/msan/Linux/syscalls.cc | 0 .../test/msan/Linux/syscalls_sigaction.cc | 0 .../compiler-rt/test/msan/Linux/tcgetattr.cc | 0 .../compiler-rt/test/msan/Linux/xattr.cc | 0 .../test/msan/Linux/xattr_test_root/a | 0 .../test/msan/Unit/lit.site.cfg.in | 0 .../test/msan/allocator_mapping.cc | 0 .../test/msan/allocator_returns_null.cc | 0 .../compiler-rt/test/msan/backtrace.cc | 0 .../compiler-rt/test/msan/c-strdup.c | 0 .../compiler-rt/test/msan/chained_origin.cc | 0 .../test/msan/chained_origin_empty_stack.cc | 0 .../test/msan/chained_origin_limits.cc | 0 .../test/msan/chained_origin_memcpy.cc | 0 .../test/msan/chained_origin_with_signals.cc | 0 .../test/msan/check_mem_is_initialized.cc | 0 .../compiler-rt/test/msan/coverage-levels.cc | 0 .../compiler-rt/test/msan/ctermid.cc | 0 .../compiler-rt/test/msan/cxa_atexit.cc | 0 .../compiler-rt/test/msan/death-callback.cc | 0 .../test/msan/default_blacklist.cc | 0 .../compiler-rt/test/msan/dlerror.cc | 0 .../test/msan/dlopen_executable.cc | 0 .../compiler-rt/test/msan/dso-origin.cc | 0 .../compiler-rt/test/msan/dtls_test.c | 0 .../compiler-rt/test/msan/dtor-base-access.cc | 0 .../compiler-rt/test/msan/dtor-bit-fields.cc | 0 .../test/msan/dtor-derived-class.cc | 0 .../compiler-rt/test/msan/dtor-member.cc | 0 ...le-inheritance-nontrivial-class-members.cc | 0 .../test/msan/dtor-multiple-inheritance.cc | 0 .../test/msan/dtor-trivial-class-members.cc | 0 .../compiler-rt/test/msan/dtor-trivial.cpp | 0 .../msan/dtor-vtable-multiple-inheritance.cc | 0 .../compiler-rt/test/msan/dtor-vtable.cc | 0 .../compiler-rt/test/msan/errno.cc | 0 .../compiler-rt/test/msan/fork.cc | 0 .../compiler-rt/test/msan/ftime.cc | 0 .../test/msan/getaddrinfo-positive.cc | 0 .../compiler-rt/test/msan/getaddrinfo.cc | 0 .../compiler-rt/test/msan/getc_unlocked.c | 0 .../compiler-rt/test/msan/getline.cc | 0 .../compiler-rt/test/msan/getutent.cc | 0 .../compiler-rt/test/msan/heap-origin.cc | 0 .../compiler-rt/test/msan/icmp_slt_allones.cc | 0 .../compiler-rt/test/msan/iconv.cc | 0 .../compiler-rt/test/msan/if_indextoname.cc | 0 .../compiler-rt/test/msan/ifaddrs.cc | 0 .../compiler-rt/test/msan/initgroups.cc | 0 .../compiler-rt/test/msan/inline.cc | 0 .../test/msan/insertvalue_origin.cc | 0 .../compiler-rt/test/msan/ioctl.cc | 0 .../compiler-rt/test/msan/ioctl_custom.cc | 0 .../compiler-rt/test/msan/lit.cfg | 0 .../compiler-rt/test/msan/lit.site.cfg.in | 0 .../compiler-rt/test/msan/memcmp_test.cc | 0 .../compiler-rt/test/msan/mktime.cc | 0 .../compiler-rt/test/msan/mmap.cc | 0 .../test/msan/mmap_below_shadow.cc | 0 .../msan/msan_check_mem_is_initialized.cc | 0 .../compiler-rt/test/msan/msan_copy_shadow.cc | 0 .../compiler-rt/test/msan/msan_dump_shadow.cc | 0 .../test/msan/msan_print_shadow.cc | 0 .../test/msan/msan_print_shadow2.cc | 0 .../test/msan/msan_print_shadow3.cc | 0 .../compiler-rt/test/msan/mul_by_const.cc | 0 .../test/msan/no_sanitize_memory.cc | 0 .../test/msan/no_sanitize_memory_prop.cc | 0 .../test/msan/origin-store-long.cc | 0 .../compiler-rt/test/msan/param_tls_limit.cc | 0 .../compiler-rt/test/msan/poison_in_free.cc | 0 .../compiler-rt/test/msan/print_stats.cc | 0 .../test/msan/pthread_getattr_np_deadlock.cc | 0 .../test/msan/pthread_setcancelstate.cc | 0 .../compiler-rt/test/msan/rand_r.cc | 0 .../compiler-rt/test/msan/readdir64.cc | 0 .../test/msan/realloc-large-origin.cc | 0 .../compiler-rt/test/msan/realloc-origin.cc | 0 .../compiler-rt/test/msan/recover-dso.cc | 0 .../compiler-rt/test/msan/recover.cc | 0 .../test/msan/report-demangling.cc | 0 .../compiler-rt/test/msan/scandir.cc | 0 .../compiler-rt/test/msan/scandir_null.cc | 0 .../test/msan/scandir_test_root/aaa | 0 .../test/msan/scandir_test_root/aab | 0 .../test/msan/scandir_test_root/bbb | 0 .../compiler-rt/test/msan/select.cc | 0 .../test/msan/select_float_origin.cc | 0 .../compiler-rt/test/msan/select_origin.cc | 0 .../compiler-rt/test/msan/sem_getvalue.cc | 0 .../compiler-rt/test/msan/setlocale.cc | 0 .../test/msan/signal_stress_test.cc | 0 .../compiler-rt/test/msan/sigwait.cc | 0 .../compiler-rt/test/msan/sigwaitinfo.cc | 0 .../compiler-rt/test/msan/stack-origin.cc | 0 .../compiler-rt/test/msan/stack-origin2.cc | 0 .../test/msan/strerror_r-non-gnu.c | 0 .../compiler-rt/test/msan/strlen_of_shadow.cc | 0 .../compiler-rt/test/msan/strxfrm.cc | 0 .../test/msan/sync_lock_set_and_test.cc | 0 .../compiler-rt/test/msan/test.h | 0 .../compiler-rt/test/msan/textdomain.cc | 0 .../compiler-rt/test/msan/times.cc | 0 .../compiler-rt/test/msan/tls_reuse.cc | 0 .../compiler-rt/test/msan/tsearch.cc | 0 .../compiler-rt/test/msan/tzset.cc | 0 .../test/msan/unaligned_read_origin.cc | 0 .../compiler-rt/test/msan/unpoison_string.cc | 0 .../compiler-rt/test/msan/use-after-dtor.cc | 0 .../compiler-rt/test/msan/use-after-free.cc | 0 .../compiler-rt/test/msan/vector_cvt.cc | 0 .../compiler-rt/test/msan/vector_select.cc | 0 .../compiler-rt/test/profile/CMakeLists.txt | 0 .../test/profile/Inputs/comdat_rename.h | 0 .../test/profile/Inputs/comdat_rename_1.cc | 0 .../test/profile/Inputs/comdat_rename_2.cc | 0 .../test/profile/Inputs/extern_template.cpp | 0 .../test/profile/Inputs/extern_template.h | 0 .../test/profile/Inputs/extern_template1.cpp | 0 .../test/profile/Inputs/extern_template2.cpp | 0 .../profile/Inputs/gcc-flag-compatibility.c | 0 .../test/profile/Inputs/instrprof-alloc.c | 0 .../profile/Inputs/instrprof-comdat-1.cpp | 0 .../profile/Inputs/instrprof-comdat-2.cpp | 0 .../test/profile/Inputs/instrprof-comdat.h | 0 .../profile/Inputs/instrprof-dlopen-func.c | 0 .../profile/Inputs/instrprof-dlopen-func2.c | 0 .../profile/Inputs/instrprof-dlopen-main.c | 0 .../profile/Inputs/instrprof-dynamic-a.cpp | 0 .../profile/Inputs/instrprof-dynamic-b.cpp | 0 .../profile/Inputs/instrprof-dynamic-header.h | 0 .../profile/Inputs/instrprof-dynamic-main.cpp | 0 .../test/profile/Inputs/instrprof-file_ex.c | 0 .../profile/Inputs/instrprof-icall-promo.h | 0 .../profile/Inputs/instrprof-icall-promo_1.cc | 0 .../profile/Inputs/instrprof-icall-promo_2.cc | 0 .../Inputs/instrprof-merge-match-lib.c | 0 .../profile/Inputs/instrprof-merge-match.c | 0 .../profile/Inputs/instrprof-shared-lib.c | 0 .../profile/Inputs/instrprof-shared-main.c | 0 .../Inputs/instrprof-value-prof-evict.c | 0 .../Inputs/instrprof-value-prof-real.c | 0 .../Inputs/instrprof-visibility-helper.cpp | 0 .../test/profile/Linux/comdat_rename.test | 0 .../test/profile/Linux/coverage_ctors.cpp | 0 .../test/profile/Linux/coverage_dtor.cpp | 0 .../test/profile/Linux/coverage_shared.test | 0 .../test/profile/Linux/coverage_test.cpp | 0 .../test/profile/Linux/extern_template.test | 0 .../test/profile/Linux/instrprof-alloc.test | 0 .../test/profile/Linux/instrprof-basic.c | 0 .../test/profile/Linux/instrprof-comdat.test | 0 .../test/profile/Linux/instrprof-cs.c | 0 .../test/profile/Linux/instrprof-dlopen.test | 0 .../Linux/instrprof-dynamic-one-shared.test | 0 .../Linux/instrprof-dynamic-two-shared.test | 0 .../test/profile/Linux/instrprof-file_ex.test | 0 .../test/profile/Linux/instrprof-merge-vp.c | 0 .../Linux/instrprof-value-prof-warn.test | 0 .../test/profile/Linux/lit.local.cfg | 0 .../test/profile/gcc-flag-compatibility.test | 0 .../test/profile/instrprof-basic.c | 0 .../test/profile/instrprof-bufferio.c | 0 .../profile/instrprof-darwin-dead-strip.c | 0 .../test/profile/instrprof-dlopen.test | 0 .../compiler-rt/test/profile/instrprof-dump.c | 0 .../profile/instrprof-dynamic-one-shared.test | 0 .../profile/instrprof-dynamic-two-shared.test | 0 .../test/profile/instrprof-error.c | 0 .../test/profile/instrprof-hostname.c | 0 .../test/profile/instrprof-icall-promo.test | 0 .../test/profile/instrprof-merge-match.test | 0 .../test/profile/instrprof-merge.c | 0 ...rof-override-filename-then-reset-default.c | 0 .../instrprof-override-filename-with-env.c | 0 .../profile/instrprof-override-filename.c | 0 .../compiler-rt/test/profile/instrprof-path.c | 0 .../test/profile/instrprof-reset-counters.c | 0 .../instrprof-set-filename-shared.test | 0 ...nstrprof-set-filename-then-reset-default.c | 0 .../test/profile/instrprof-set-filename.c | 0 .../test/profile/instrprof-shared.test | 0 .../test/profile/instrprof-value-prof-2.c | 0 .../profile/instrprof-value-prof-evict.test | 0 .../test/profile/instrprof-value-prof-reset.c | 0 .../profile/instrprof-value-prof-shared.test | 0 .../test/profile/instrprof-value-prof.c | 0 .../test/profile/instrprof-value-prof.test | 0 .../test/profile/instrprof-version-mismatch.c | 0 .../profile/instrprof-visibility-kinds.inc | 0 .../test/profile/instrprof-visibility.cpp | 0 .../test/profile/instrprof-without-libc.c | 0 .../instrprof-write-file-atexit-explicitly.c | 0 .../test/profile/instrprof-write-file-only.c | 0 .../test/profile/instrprof-write-file.c | 0 .../compiler-rt/test/profile/lit.cfg | 0 .../compiler-rt/test/profile/lit.site.cfg.in | 0 .../compiler-rt/test/safestack/CMakeLists.txt | 0 .../test/safestack/buffer-copy-vla.c | 0 .../compiler-rt/test/safestack/buffer-copy.c | 0 .../compiler-rt/test/safestack/canary.c | 0 .../compiler-rt/test/safestack/init.c | 0 .../compiler-rt/test/safestack/lit.cfg | 0 .../test/safestack/lit.site.cfg.in | 0 .../compiler-rt/test/safestack/lto.c | 0 .../compiler-rt/test/safestack/overflow.c | 0 .../test/safestack/pthread-cleanup.c | 0 .../compiler-rt/test/safestack/pthread.c | 0 .../compiler-rt/test/safestack/utils.h | 0 .../test/sanitizer_common/CMakeLists.txt | 0 .../TestCases/Darwin/abort_on_error.cc | 0 .../TestCases/Darwin/lit.local.cfg | 0 .../TestCases/Linux/abort_on_error.cc | 0 .../TestCases/Linux/aligned_alloc.c | 0 .../TestCases/Linux/assert.cc | 0 .../TestCases/Linux/clock_gettime.c | 0 .../TestCases/Linux/closedir.c | 0 .../TestCases/Linux/decorate_proc_maps.cc | 0 .../sanitizer_common/TestCases/Linux/fpe.cc | 0 .../Linux/getpwnam_r_invalid_user.cc | 0 .../TestCases/Linux/hard_rss_limit_mb_test.cc | 0 .../sanitizer_common/TestCases/Linux/ill.cc | 0 .../TestCases/Linux/lit.local.cfg | 0 .../TestCases/Linux/mlock_test.cc | 0 .../TestCases/Linux/open_memstream.cc | 0 .../TestCases/Linux/ptrace.cc | 0 .../TestCases/Linux/recv_msg_trunc.cc | 0 .../TestCases/Linux/sched_getparam.cc | 0 .../TestCases/Linux/sem_init_glibc.cc | 0 .../TestCases/Linux/signal_segv_handler.cc | 0 .../TestCases/Linux/soft_rss_limit_mb_test.cc | 0 .../TestCases/Linux/timerfd.cc | 0 .../TestCases/Linux/weak_hook_test.cc | 0 .../Posix/dedup_token_length_test.cc | 0 .../TestCases/Posix/getpass.cc | 0 .../TestCases/Posix/lit.local.cfg | 0 .../sanitizer_set_death_callback_test.cc | 0 .../Posix/sanitizer_set_report_fd_test.cc | 0 .../sanitizer_common/TestCases/corelimit.cc | 0 .../TestCases/fopen_nullptr.c | 0 .../TestCases/get_module_and_offset_for_pc.cc | 0 .../sanitizer_common/TestCases/malloc_hook.cc | 0 .../TestCases/options-help.cc | 0 .../TestCases/options-include.cc | 0 .../TestCases/options-invalid.cc | 0 .../TestCases/print-stack-trace.cc | 0 .../sanitizer_common/TestCases/printf-ldbl.c | 0 .../TestCases/pthread_mutexattr_get.cc | 0 .../TestCases/sanitizer_coverage_symbolize.cc | 0 .../sanitizer_coverage_trace_pc_guard-dso.cc | 0 .../sanitizer_coverage_trace_pc_guard.cc | 0 .../sanitizer_common/TestCases/scanf-ldbl.c | 0 .../sanitizer_common/TestCases/strcasestr.c | 0 .../test/sanitizer_common/TestCases/strcspn.c | 0 .../test/sanitizer_common/TestCases/strnlen.c | 0 .../test/sanitizer_common/TestCases/strpbrk.c | 0 .../test/sanitizer_common/TestCases/strspn.c | 0 .../test/sanitizer_common/TestCases/strstr.c | 0 .../TestCases/symbolize_pc.cc | 0 .../sanitizer_common/Unit/lit.site.cfg.in | 0 .../test/sanitizer_common/lit.common.cfg | 0 .../test/sanitizer_common/lit.site.cfg.in | 0 .../test/sanitizer_common/print_address.h | 0 .../compiler-rt/test/scudo/CMakeLists.txt | 0 .../compiler-rt/test/scudo/alignment.cpp | 0 .../compiler-rt/test/scudo/double-free.cpp | 0 .../compiler-rt/test/scudo/interface.cpp | 0 .../compiler-rt/test/scudo/lit.cfg | 0 .../compiler-rt/test/scudo/lit.site.cfg.in | 0 .../compiler-rt/test/scudo/malloc.cpp | 0 .../compiler-rt/test/scudo/memalign.cpp | 0 .../compiler-rt/test/scudo/mismatch.cpp | 0 .../compiler-rt/test/scudo/options.cpp | 0 .../compiler-rt/test/scudo/overflow.cpp | 0 .../compiler-rt/test/scudo/preinit.cpp | 0 .../compiler-rt/test/scudo/quarantine.cpp | 0 .../compiler-rt/test/scudo/random_shuffle.cpp | 0 .../compiler-rt/test/scudo/realloc.cpp | 0 .../compiler-rt/test/scudo/secondary.cpp | 0 .../compiler-rt/test/scudo/sized-delete.cpp | 0 .../compiler-rt/test/scudo/sizes.cpp | 0 .../compiler-rt/test/tsan/CMakeLists.txt | 0 .../test/tsan/Darwin/dispatch_main.mm | 0 .../tsan/Darwin/dispatch_once_deadlock.mm | 0 .../compiler-rt/test/tsan/Darwin/dlopen.cc | 0 .../compiler-rt/test/tsan/Darwin/gcd-after.mm | 0 .../test/tsan/Darwin/gcd-apply-race.mm | 0 .../compiler-rt/test/tsan/Darwin/gcd-apply.mm | 0 .../test/tsan/Darwin/gcd-async-norace.mm | 0 .../test/tsan/Darwin/gcd-async-race.mm | 0 .../test/tsan/Darwin/gcd-barrier-race.mm | 0 .../test/tsan/Darwin/gcd-barrier.mm | 0 .../test/tsan/Darwin/gcd-blocks.mm | 0 .../compiler-rt/test/tsan/Darwin/gcd-data.mm | 0 .../compiler-rt/test/tsan/Darwin/gcd-fd.mm | 0 .../test/tsan/Darwin/gcd-groups-destructor.mm | 0 .../test/tsan/Darwin/gcd-groups-leave.mm | 0 .../test/tsan/Darwin/gcd-groups-norace.mm | 0 .../test/tsan/Darwin/gcd-groups-stress.mm | 0 .../test/tsan/Darwin/gcd-io-barrier-race.mm | 0 .../test/tsan/Darwin/gcd-io-barrier.mm | 0 .../test/tsan/Darwin/gcd-io-cleanup.mm | 0 .../test/tsan/Darwin/gcd-io-race.mm | 0 .../compiler-rt/test/tsan/Darwin/gcd-io.mm | 0 .../compiler-rt/test/tsan/Darwin/gcd-once.mm | 0 .../test/tsan/Darwin/gcd-semaphore-norace.mm | 0 .../tsan/Darwin/gcd-serial-queue-norace.mm | 0 .../test/tsan/Darwin/gcd-source-cancel.mm | 0 .../test/tsan/Darwin/gcd-source-cancel2.mm | 0 .../test/tsan/Darwin/gcd-source-event.mm | 0 .../test/tsan/Darwin/gcd-source-event2.mm | 0 .../tsan/Darwin/gcd-source-registration.mm | 0 .../tsan/Darwin/gcd-source-registration2.mm | 0 .../test/tsan/Darwin/gcd-source-serial.mm | 0 .../test/tsan/Darwin/gcd-suspend.mm | 0 .../test/tsan/Darwin/gcd-sync-norace.mm | 0 .../test/tsan/Darwin/gcd-sync-race.mm | 0 .../tsan/Darwin/gcd-target-queue-norace.mm | 0 .../tsan/Darwin/ignore-noninstrumented.mm | 0 .../test/tsan/Darwin/ignored-interceptors.mm | 0 .../test/tsan/Darwin/libcxx-call-once.mm | 0 .../test/tsan/Darwin/libcxx-future.mm | 0 .../Darwin/libcxx-shared-ptr-recursive.mm | 0 .../tsan/Darwin/libcxx-shared-ptr-stress.mm | 0 .../test/tsan/Darwin/libcxx-shared-ptr.mm | 0 .../test/tsan/Darwin/lit.local.cfg | 0 .../test/tsan/Darwin/malloc-stack-logging.cc | 0 .../test/tsan/Darwin/malloc_size.mm | 0 .../tsan/Darwin/norace-objcxx-run-time.mm | 0 .../test/tsan/Darwin/objc-double-property.mm | 0 .../compiler-rt/test/tsan/Darwin/objc-race.mm | 0 .../test/tsan/Darwin/objc-simple.mm | 0 .../test/tsan/Darwin/osatomics-add.mm | 0 .../test/tsan/Darwin/osatomics-bitops.mm | 0 .../test/tsan/Darwin/osatomics-list.mm | 0 .../test/tsan/Darwin/osspinlock-norace.cc | 0 .../test/tsan/Darwin/realloc-zero.cc | 0 .../test/tsan/Darwin/symbolizer-atos.cc | 0 .../test/tsan/Darwin/symbolizer-dladdr.cc | 0 .../compiler-rt/test/tsan/Darwin/xpc-race.mm | 0 .../compiler-rt/test/tsan/Darwin/xpc.mm | 0 .../test/tsan/Linux/check_memcpy.cc | 0 .../test/tsan/Linux/check_preinit.cc | 0 .../compiler-rt/test/tsan/Linux/lit.local.cfg | 0 .../test/tsan/Linux/mutex_robust.cc | 0 .../test/tsan/Linux/mutex_robust2.cc | 0 .../compiler-rt/test/tsan/Linux/user_fopen.cc | 0 .../test/tsan/Linux/user_malloc.cc | 0 .../test/tsan/Unit/lit.site.cfg.in | 0 .../test/tsan/aligned_vs_unaligned_race.cc | 0 .../test/tsan/allocator_returns_null.cc | 0 .../test/tsan/annotate_happens_before.cc | 0 .../compiler-rt/test/tsan/atexit.cc | 0 .../compiler-rt/test/tsan/atexit2.cc | 0 .../compiler-rt/test/tsan/atomic_free.cc | 0 .../compiler-rt/test/tsan/atomic_free2.cc | 0 .../compiler-rt/test/tsan/atomic_free3.cc | 0 .../compiler-rt/test/tsan/atomic_norace.cc | 0 .../compiler-rt/test/tsan/atomic_race.cc | 0 .../compiler-rt/test/tsan/atomic_stack.cc | 0 .../compiler-rt/test/tsan/atomic_store.cc | 0 .../compiler-rt/test/tsan/barrier.cc | 0 .../compiler-rt/test/tsan/bench.h | 0 .../test/tsan/bench_acquire_only.cc | 0 .../test/tsan/bench_acquire_release.cc | 0 .../test/tsan/bench_local_mutex.cc | 0 .../compiler-rt/test/tsan/bench_mutex.cc | 0 .../test/tsan/bench_release_only.cc | 0 .../compiler-rt/test/tsan/bench_rwmutex.cc | 0 .../test/tsan/bench_shadow_flush.cc | 0 .../test/tsan/bench_single_writer.cc | 0 .../test/tsan/bench_ten_mutexes.cc | 0 .../compiler-rt/test/tsan/benign_race.cc | 0 .../compiler-rt/test/tsan/blacklist.cc | 0 .../compiler-rt/test/tsan/blacklist2.cc | 0 .../compiler-rt/test/tsan/cond.c | 0 .../compiler-rt/test/tsan/cond_cancel.c | 0 .../compiler-rt/test/tsan/cond_destruction.cc | 0 .../compiler-rt/test/tsan/cond_race.cc | 0 .../compiler-rt/test/tsan/cond_version.c | 0 .../tsan/deadlock_detector_stress_test.cc | 0 .../test/tsan/debug_alloc_stack.cc | 0 .../compiler-rt/test/tsan/debug_locate.cc | 0 .../compiler-rt/test/tsan/debugging.cc | 0 .../compiler-rt/test/tsan/deep_stack1.cc | 0 .../compiler-rt/test/tsan/default_options.cc | 0 .../compiler-rt/test/tsan/deflake.bash | 0 .../compiler-rt/test/tsan/dl_iterate_phdr.cc | 0 .../compiler-rt/test/tsan/dlclose.cc | 0 .../compiler-rt/test/tsan/dtls.c | 0 .../compiler-rt/test/tsan/exceptions.cc | 0 .../compiler-rt/test/tsan/fd_close_norace.cc | 0 .../compiler-rt/test/tsan/fd_close_norace2.cc | 0 .../compiler-rt/test/tsan/fd_dup_norace.cc | 0 .../compiler-rt/test/tsan/fd_dup_norace2.cc | 0 .../compiler-rt/test/tsan/fd_dup_race.cc | 0 .../compiler-rt/test/tsan/fd_location.cc | 0 .../compiler-rt/test/tsan/fd_pipe_norace.cc | 0 .../compiler-rt/test/tsan/fd_pipe_race.cc | 0 .../test/tsan/fd_socket_connect_norace.cc | 0 .../compiler-rt/test/tsan/fd_socket_norace.cc | 0 .../test/tsan/fd_socketpair_norace.cc | 0 .../compiler-rt/test/tsan/fd_stdout_race.cc | 0 .../compiler-rt/test/tsan/fd_tid_recycled.cc | 0 .../compiler-rt/test/tsan/fork_atexit.cc | 0 .../compiler-rt/test/tsan/fork_deadlock.cc | 0 .../test/tsan/fork_multithreaded.cc | 0 .../test/tsan/fork_multithreaded3.cc | 0 .../compiler-rt/test/tsan/free_race.c | 0 .../compiler-rt/test/tsan/free_race.c.supp | 0 .../compiler-rt/test/tsan/free_race2.c | 0 .../compiler-rt/test/tsan/getline_nohang.cc | 0 .../compiler-rt/test/tsan/global_race.cc | 0 .../compiler-rt/test/tsan/global_race2.cc | 0 .../compiler-rt/test/tsan/global_race3.cc | 0 .../compiler-rt/test/tsan/halt_on_error.cc | 0 .../compiler-rt/test/tsan/heap_race.cc | 0 .../compiler-rt/test/tsan/ignore_free.cc | 0 .../compiler-rt/test/tsan/ignore_lib0.cc | 0 .../compiler-rt/test/tsan/ignore_lib0.cc.supp | 0 .../compiler-rt/test/tsan/ignore_lib1.cc | 0 .../compiler-rt/test/tsan/ignore_lib1.cc.supp | 0 .../compiler-rt/test/tsan/ignore_lib2.cc | 0 .../compiler-rt/test/tsan/ignore_lib2.cc.supp | 0 .../compiler-rt/test/tsan/ignore_lib3.cc | 0 .../compiler-rt/test/tsan/ignore_lib3.cc.supp | 0 .../compiler-rt/test/tsan/ignore_lib4.cc | 0 .../compiler-rt/test/tsan/ignore_lib5.cc | 0 .../compiler-rt/test/tsan/ignore_lib5.cc.supp | 0 .../compiler-rt/test/tsan/ignore_lib_lib.h | 0 .../compiler-rt/test/tsan/ignore_malloc.cc | 0 .../compiler-rt/test/tsan/ignore_race.cc | 0 .../compiler-rt/test/tsan/ignore_sync.cc | 0 .../test/tsan/ignored-interceptors-mmap.cc | 0 .../test/tsan/inlined_memcpy_race.cc | 0 .../test/tsan/inlined_memcpy_race2.cc | 0 .../test/tsan/interface_atomic_test.c | 0 .../compiler-rt/test/tsan/java.h | 0 .../compiler-rt/test/tsan/java_alloc.cc | 0 .../compiler-rt/test/tsan/java_finalizer.cc | 0 .../compiler-rt/test/tsan/java_heap_init.cc | 0 .../compiler-rt/test/tsan/java_lock.cc | 0 .../compiler-rt/test/tsan/java_lock_move.cc | 0 .../compiler-rt/test/tsan/java_lock_rec.cc | 0 .../test/tsan/java_lock_rec_race.cc | 0 .../test/tsan/java_move_overlap.cc | 0 .../test/tsan/java_move_overlap_race.cc | 0 .../compiler-rt/test/tsan/java_race.cc | 0 .../compiler-rt/test/tsan/java_race_move.cc | 0 .../compiler-rt/test/tsan/java_race_pc.cc | 0 .../compiler-rt/test/tsan/java_rwlock.cc | 0 .../test/tsan/java_symbolization.cc | 0 .../compiler-rt/test/tsan/java_volatile.cc | 0 .../test/tsan/large_malloc_meta.cc | 0 .../test/tsan/libcxx/lit.local.cfg | 0 .../test/tsan/libcxx/std_shared_ptr.cc | 0 .../compiler-rt/test/tsan/lit.cfg | 0 .../compiler-rt/test/tsan/lit.site.cfg.in | 0 .../compiler-rt/test/tsan/load_shared_lib.cc | 0 .../compiler-rt/test/tsan/longjmp.cc | 0 .../compiler-rt/test/tsan/longjmp2.cc | 0 .../compiler-rt/test/tsan/longjmp3.cc | 0 .../compiler-rt/test/tsan/longjmp4.cc | 0 .../compiler-rt/test/tsan/lots_of_threads.c | 0 .../compiler-rt/test/tsan/malloc_overflow.cc | 0 .../compiler-rt/test/tsan/malloc_stack.cc | 0 .../compiler-rt/test/tsan/map32bit.cc | 0 .../compiler-rt/test/tsan/memcmp_race.cc | 0 .../compiler-rt/test/tsan/memcpy_race.cc | 0 .../compiler-rt/test/tsan/mmap_large.cc | 0 .../compiler-rt/test/tsan/mmap_stress.cc | 0 .../compiler-rt/test/tsan/mop1.c | 0 .../compiler-rt/test/tsan/mop_with_offset.cc | 0 .../compiler-rt/test/tsan/mop_with_offset2.cc | 0 .../compiler-rt/test/tsan/must_deadlock.cc | 0 .../test/tsan/mutex_annotations.cc | 0 .../test/tsan/mutex_bad_read_lock.cc | 0 .../test/tsan/mutex_bad_read_unlock.cc | 0 .../compiler-rt/test/tsan/mutex_bad_unlock.cc | 0 .../compiler-rt/test/tsan/mutex_cycle2.c | 0 .../compiler-rt/test/tsan/mutex_cycle_long.c | 0 .../test/tsan/mutex_destroy_locked.cc | 0 .../test/tsan/mutex_double_lock.cc | 0 .../test/tsan/mutex_lock_destroyed.cc | 0 .../compiler-rt/test/tsan/mutexset1.cc | 0 .../compiler-rt/test/tsan/mutexset2.cc | 0 .../compiler-rt/test/tsan/mutexset3.cc | 0 .../compiler-rt/test/tsan/mutexset4.cc | 0 .../compiler-rt/test/tsan/mutexset5.cc | 0 .../compiler-rt/test/tsan/mutexset6.cc | 0 .../compiler-rt/test/tsan/mutexset7.cc | 0 .../compiler-rt/test/tsan/mutexset8.cc | 0 .../compiler-rt/test/tsan/pie_test.cc | 0 .../compiler-rt/test/tsan/printf-1.c | 0 .../test/tsan/pthread_atfork_deadlock.c | 0 .../compiler-rt/test/tsan/pthread_key.cc | 0 .../compiler-rt/test/tsan/race_on_barrier.c | 0 .../compiler-rt/test/tsan/race_on_barrier2.c | 0 .../compiler-rt/test/tsan/race_on_heap.cc | 0 .../compiler-rt/test/tsan/race_on_mutex.c | 0 .../compiler-rt/test/tsan/race_on_mutex2.c | 0 .../compiler-rt/test/tsan/race_on_puts.cc | 0 .../compiler-rt/test/tsan/race_on_read.cc | 0 .../test/tsan/race_on_speculative_load.cc | 0 .../compiler-rt/test/tsan/race_on_write.cc | 0 .../compiler-rt/test/tsan/race_stress.cc | 0 .../test/tsan/race_top_suppression.cc | 0 .../test/tsan/race_top_suppression1.cc | 0 .../test/tsan/race_with_finished_thread.cc | 0 .../real_deadlock_detector_stress_test.cc | 0 .../compiler-rt/test/tsan/restore_stack.cc | 0 .../compiler-rt/test/tsan/setuid.c | 0 .../compiler-rt/test/tsan/setuid2.c | 0 .../compiler-rt/test/tsan/signal_block.cc | 0 .../compiler-rt/test/tsan/signal_cond.cc | 0 .../compiler-rt/test/tsan/signal_errno.cc | 0 .../compiler-rt/test/tsan/signal_longjmp.cc | 0 .../compiler-rt/test/tsan/signal_malloc.cc | 0 .../compiler-rt/test/tsan/signal_recursive.cc | 0 .../compiler-rt/test/tsan/signal_reset.cc | 0 .../compiler-rt/test/tsan/signal_sync.cc | 0 .../compiler-rt/test/tsan/signal_sync2.cc | 0 .../compiler-rt/test/tsan/signal_thread.cc | 0 .../compiler-rt/test/tsan/signal_write.cc | 0 .../compiler-rt/test/tsan/sigsuspend.cc | 0 .../compiler-rt/test/tsan/simple_race.c | 0 .../compiler-rt/test/tsan/simple_race.cc | 0 .../compiler-rt/test/tsan/simple_stack.c | 0 .../compiler-rt/test/tsan/simple_stack2.cc | 0 .../compiler-rt/test/tsan/sleep_sync.cc | 0 .../compiler-rt/test/tsan/sleep_sync2.cc | 0 .../compiler-rt/test/tsan/stack_race.cc | 0 .../compiler-rt/test/tsan/stack_race2.cc | 0 .../compiler-rt/test/tsan/stack_sync_reuse.cc | 0 .../compiler-rt/test/tsan/static_init1.cc | 0 .../compiler-rt/test/tsan/static_init2.cc | 0 .../compiler-rt/test/tsan/static_init3.cc | 0 .../compiler-rt/test/tsan/static_init4.cc | 0 .../compiler-rt/test/tsan/static_init5.cc | 0 .../compiler-rt/test/tsan/static_init6.cc | 0 .../compiler-rt/test/tsan/sunrpc.cc | 0 .../test/tsan/suppress_same_address.cc | 0 .../test/tsan/suppress_same_stacks.cc | 0 .../test/tsan/suppressions_global.cc | 0 .../test/tsan/suppressions_global.cc.supp | 0 .../test/tsan/suppressions_race.cc | 0 .../test/tsan/suppressions_race.cc.supp | 0 .../test/tsan/suppressions_race2.cc | 0 .../test/tsan/suppressions_race2.cc.supp | 0 .../compiler-rt/test/tsan/test.h | 0 .../compiler-rt/test/tsan/thread_detach.c | 0 .../compiler-rt/test/tsan/thread_detach2.c | 0 .../test/tsan/thread_end_with_ignore.cc | 0 .../test/tsan/thread_end_with_ignore2.cc | 0 .../test/tsan/thread_end_with_ignore3.cc | 0 .../compiler-rt/test/tsan/thread_leak.c | 0 .../compiler-rt/test/tsan/thread_leak2.c | 0 .../compiler-rt/test/tsan/thread_leak3.c | 0 .../compiler-rt/test/tsan/thread_leak4.c | 0 .../compiler-rt/test/tsan/thread_leak5.c | 0 .../compiler-rt/test/tsan/thread_name.cc | 0 .../compiler-rt/test/tsan/thread_name2.cc | 0 .../compiler-rt/test/tsan/tiny_race.c | 0 .../compiler-rt/test/tsan/tls_race.cc | 0 .../compiler-rt/test/tsan/tls_race2.cc | 0 .../compiler-rt/test/tsan/tsan-vs-gvn.cc | 0 .../compiler-rt/test/tsan/unaligned_norace.cc | 0 .../compiler-rt/test/tsan/unaligned_race.cc | 0 .../compiler-rt/test/tsan/vfork.cc | 0 .../tsan/virtual_inheritance_compile_bug.cc | 0 .../compiler-rt/test/tsan/vptr_benign_race.cc | 0 .../test/tsan/vptr_harmful_race.cc | 0 .../test/tsan/vptr_harmful_race2.cc | 0 .../test/tsan/vptr_harmful_race3.cc | 0 .../test/tsan/vptr_harmful_race4.cc | 0 .../test/tsan/write_in_reader_lock.cc | 0 .../compiler-rt/test/ubsan/CMakeLists.txt | 0 .../ubsan/TestCases/Float/cast-overflow.cpp | 0 .../ubsan/TestCases/Integer/add-overflow.cpp | 0 .../ubsan/TestCases/Integer/div-overflow.cpp | 0 .../test/ubsan/TestCases/Integer/div-zero.cpp | 0 .../TestCases/Integer/incdec-overflow.cpp | 0 .../ubsan/TestCases/Integer/mul-overflow.cpp | 0 .../TestCases/Integer/negate-overflow.cpp | 0 .../ubsan/TestCases/Integer/no-recover.cpp | 0 .../test/ubsan/TestCases/Integer/shift.cpp | 0 .../ubsan/TestCases/Integer/sub-overflow.cpp | 0 .../test/ubsan/TestCases/Integer/summary.cpp | 0 .../ubsan/TestCases/Integer/suppressions.cpp | 0 .../ubsan/TestCases/Integer/uadd-overflow.cpp | 0 .../TestCases/Integer/uincdec-overflow.cpp | 0 .../ubsan/TestCases/Integer/umul-overflow.cpp | 0 .../ubsan/TestCases/Integer/usub-overflow.cpp | 0 .../ubsan/TestCases/Misc/Linux/lit.local.cfg | 0 .../TestCases/Misc/Linux/ubsan_options.cc | 0 .../test/ubsan/TestCases/Misc/bool.cpp | 0 .../test/ubsan/TestCases/Misc/bounds.cpp | 0 .../ubsan/TestCases/Misc/coverage-levels.cc | 0 .../ubsan/TestCases/Misc/deduplication.cpp | 0 .../test/ubsan/TestCases/Misc/enum.cpp | 0 .../ubsan/TestCases/Misc/log-path_test.cc | 0 .../ubsan/TestCases/Misc/missing_return.cpp | 0 .../test/ubsan/TestCases/Misc/nonnull-arg.cpp | 0 .../test/ubsan/TestCases/Misc/nonnull.cpp | 0 .../test/ubsan/TestCases/Misc/unreachable.cpp | 0 .../test/ubsan/TestCases/Misc/vla.c | 0 .../TestCases/TypeCheck/Function/function.cpp | 0 .../TypeCheck/Function/lit.local.cfg | 0 .../ubsan/TestCases/TypeCheck/misaligned.cpp | 0 .../test/ubsan/TestCases/TypeCheck/null.cpp | 0 .../vptr-corrupted-vtable-itanium.cpp | 0 .../TypeCheck/vptr-non-unique-typeinfo.cpp | 0 .../vptr-virtual-base-construction.cpp | 0 .../TestCases/TypeCheck/vptr-virtual-base.cpp | 0 .../test/ubsan/TestCases/TypeCheck/vptr.cpp | 0 .../compiler-rt/test/ubsan/lit.common.cfg | 0 .../compiler-rt/test/ubsan/lit.site.cfg.in | 0 .../compiler-rt/test/xray/CMakeLists.txt | 0 .../TestCases/Linux/argv0-log-file-name.cc | 0 .../xray/TestCases/Linux/fixedsize-logging.cc | 0 .../TestCases/Linux/optional-inmemory-log.cc | 0 .../TestCases/Linux/patching-unpatching.cc | 0 .../test/xray/Unit/lit.site.cfg.in | 0 .../compiler-rt/test/xray/lit.cfg | 0 .../compiler-rt/test/xray/lit.site.cfg.in | 0 .../compiler-rt/unittests/CMakeLists.txt | 0 .../compiler-rt/unittests/lit.common.unit.cfg | 0 .../unittests/lit.common.unit.configured.in | 0 .../compiler-rt/www/content.css | 0 .../compiler-rt/www/index.html | 0 .../compiler-rt/www/menu.css | 0 .../compiler-rt/www/menu.html.incl | 0 .../examples/intrinsics.rs | 467 ++ src/libcompiler_builtins/lib.rs | 721 --- src/libcompiler_builtins/src/arm.rs | 170 + src/libcompiler_builtins/src/float/add.rs | 194 + src/libcompiler_builtins/src/float/conv.rs | 251 + src/libcompiler_builtins/src/float/mod.rs | 156 + src/libcompiler_builtins/src/float/pow.rs | 36 + src/libcompiler_builtins/src/float/sub.rs | 13 + src/libcompiler_builtins/src/int/mod.rs | 246 + src/libcompiler_builtins/src/int/mul.rs | 97 + src/libcompiler_builtins/src/int/sdiv.rs | 99 + src/libcompiler_builtins/src/int/shift.rs | 97 + src/libcompiler_builtins/src/int/udiv.rs | 262 + src/libcompiler_builtins/src/lib.rs | 57 + src/libcompiler_builtins/src/macros.rs | 282 + src/libcompiler_builtins/src/mem.rs | 66 + src/libcompiler_builtins/src/probestack.rs | 116 + src/libcompiler_builtins/src/x86_64.rs | 69 + src/libcompiler_builtins/tests/adddf3.rs | 8 + src/libcompiler_builtins/tests/addsf3.rs | 8 + .../tests/aeabi_memclr.rs | 58 + .../tests/aeabi_memcpy.rs | 69 + .../tests/aeabi_memset.rs | 274 + src/libcompiler_builtins/tests/ashldi3.rs | 8 + src/libcompiler_builtins/tests/ashlti3.rs | 8 + src/libcompiler_builtins/tests/ashrdi3.rs | 8 + src/libcompiler_builtins/tests/ashrti3.rs | 8 + src/libcompiler_builtins/tests/divdi3.rs | 8 + src/libcompiler_builtins/tests/divmoddi4.rs | 8 + src/libcompiler_builtins/tests/divmodsi4.rs | 8 + src/libcompiler_builtins/tests/divsi3.rs | 8 + src/libcompiler_builtins/tests/divti3.rs | 10 + src/libcompiler_builtins/tests/fixdfdi.rs | 8 + src/libcompiler_builtins/tests/fixdfsi.rs | 8 + src/libcompiler_builtins/tests/fixdfti.rs | 8 + src/libcompiler_builtins/tests/fixsfdi.rs | 8 + src/libcompiler_builtins/tests/fixsfsi.rs | 8 + src/libcompiler_builtins/tests/fixsfti.rs | 8 + src/libcompiler_builtins/tests/fixunsdfdi.rs | 8 + src/libcompiler_builtins/tests/fixunsdfsi.rs | 8 + src/libcompiler_builtins/tests/fixunsdfti.rs | 8 + src/libcompiler_builtins/tests/fixunssfdi.rs | 8 + src/libcompiler_builtins/tests/fixunssfsi.rs | 8 + src/libcompiler_builtins/tests/fixunssfti.rs | 8 + src/libcompiler_builtins/tests/floatdidf.rs | 8 + src/libcompiler_builtins/tests/floatsidf.rs | 8 + src/libcompiler_builtins/tests/floatsisf.rs | 8 + src/libcompiler_builtins/tests/floattidf.rs | 8 + src/libcompiler_builtins/tests/floattisf.rs | 8 + src/libcompiler_builtins/tests/floatundidf.rs | 8 + src/libcompiler_builtins/tests/floatunsidf.rs | 8 + src/libcompiler_builtins/tests/floatunsisf.rs | 8 + src/libcompiler_builtins/tests/floatuntidf.rs | 8 + src/libcompiler_builtins/tests/floatuntisf.rs | 8 + src/libcompiler_builtins/tests/lshrdi3.rs | 8 + src/libcompiler_builtins/tests/lshrti3.rs | 8 + src/libcompiler_builtins/tests/moddi3.rs | 8 + src/libcompiler_builtins/tests/modsi3.rs | 8 + src/libcompiler_builtins/tests/modti3.rs | 10 + src/libcompiler_builtins/tests/muldi3.rs | 8 + src/libcompiler_builtins/tests/mulodi4.rs | 8 + src/libcompiler_builtins/tests/mulosi4.rs | 8 + src/libcompiler_builtins/tests/muloti4.rs | 10 + src/libcompiler_builtins/tests/multi3.rs | 8 + src/libcompiler_builtins/tests/powidf2.rs | 8 + src/libcompiler_builtins/tests/powisf2.rs | 8 + src/libcompiler_builtins/tests/subdf3.rs | 8 + src/libcompiler_builtins/tests/subsf3.rs | 8 + src/libcompiler_builtins/tests/udivdi3.rs | 8 + src/libcompiler_builtins/tests/udivmoddi4.rs | 8 + src/libcompiler_builtins/tests/udivmodsi4.rs | 8 + src/libcompiler_builtins/tests/udivmodti4.rs | 10 + src/libcompiler_builtins/tests/udivsi3.rs | 8 + src/libcompiler_builtins/tests/udivti3.rs | 10 + src/libcompiler_builtins/tests/umoddi3.rs | 8 + src/libcompiler_builtins/tests/umodsi3.rs | 8 + src/libcompiler_builtins/tests/umodti3.rs | 10 + .../thumbv6m-linux-eabi.json | 27 + .../thumbv7em-linux-eabi.json | 26 + .../thumbv7em-linux-eabihf.json | 27 + .../thumbv7m-linux-eabi.json | 26 + src/libcore/Cargo.toml | 3 + src/libcore/benches/iter.rs | 47 + src/libcore/borrow.rs | 2 +- src/libcore/cell.rs | 24 +- src/libcore/char.rs | 69 +- src/libcore/cmp.rs | 54 +- src/libcore/convert.rs | 4 +- src/libcore/default.rs | 37 +- src/libcore/fmt/builders.rs | 139 +- src/libcore/fmt/mod.rs | 20 +- src/libcore/hash/mod.rs | 9 +- src/libcore/intrinsics.rs | 48 +- src/libcore/iter/iterator.rs | 49 +- src/libcore/iter/mod.rs | 16 +- src/libcore/iter/range.rs | 493 +- src/libcore/iter/traits.rs | 24 +- src/libcore/lib.rs | 13 +- src/libcore/macros.rs | 76 +- src/libcore/marker.rs | 8 +- src/libcore/mem.rs | 47 +- src/libcore/num/f32.rs | 47 +- src/libcore/num/f64.rs | 45 +- src/libcore/num/mod.rs | 60 +- src/libcore/ops.rs | 3021 ----------- src/libcore/ops/arith.rs | 873 +++ src/libcore/ops/bit.rs | 839 +++ src/libcore/ops/deref.rs | 119 + src/libcore/ops/drop.rs | 99 + src/libcore/ops/function.rs | 194 + src/libcore/ops/index.rs | 158 + src/libcore/ops/mod.rs | 196 + src/libcore/ops/place.rs | 140 + src/libcore/ops/range.rs | 367 ++ src/libcore/ops/try.rs | 49 + src/libcore/ops/unsize.rs | 79 + src/libcore/option.rs | 8 +- src/libcore/panicking.rs | 45 +- src/libcore/ptr.rs | 99 +- src/libcore/result.rs | 9 +- src/libcore/slice/mod.rs | 27 +- src/libcore/slice/rotate.rs | 9 +- src/libcore/slice/sort.rs | 4 +- src/libcore/str/mod.rs | 141 +- src/libcore/str/pattern.rs | 5 +- src/libcore/tests/char.rs | 11 + src/libcore/tests/cmp.rs | 10 + src/libcore/tests/iter.rs | 111 +- src/libcore/tests/lib.rs | 7 +- src/libcore/tests/num/dec2flt/mod.rs | 2 + src/libcore/tests/num/dec2flt/rawfp.rs | 3 + .../tests/num/flt2dec/strategy/dragon.rs | 1 + .../tests/num/flt2dec/strategy/grisu.rs | 1 + src/libcore/tests/num/mod.rs | 55 + src/libcore/tuple.rs | 14 +- src/libflate/lib.rs | 168 - src/libfmt_macros/lib.rs | 4 - src/libgetopts/Cargo.toml | 9 - src/libgetopts/lib.rs | 4 - src/libgraphviz/lib.rs | 4 +- src/liblibc/.travis.yml | 4 + src/liblibc/Cargo.lock | 42 +- src/liblibc/Cargo.toml | 2 +- src/liblibc/ci/android-sysimage.sh | 52 + .../ci/docker/x86_64-linux-android/Dockerfile | 34 +- src/liblibc/ci/run.sh | 5 +- src/liblibc/libc-test/build.rs | 50 +- src/liblibc/src/dox.rs | 3 + src/liblibc/src/unix/bsd/apple/mod.rs | 34 +- src/liblibc/src/unix/bsd/freebsdlike/mod.rs | 4 + src/liblibc/src/unix/bsd/mod.rs | 2 + .../src/unix/bsd/netbsdlike/netbsd/mod.rs | 11 + .../unix/bsd/netbsdlike/openbsdlike/mod.rs | 1 + src/liblibc/src/unix/haiku/mod.rs | 1 + src/liblibc/src/unix/mod.rs | 38 +- src/liblibc/src/unix/notbsd/android/mod.rs | 1 + .../src/unix/notbsd/linux/mips/mips32.rs | 53 - .../src/unix/notbsd/linux/mips/mips64.rs | 23 +- src/liblibc/src/unix/notbsd/linux/mips/mod.rs | 67 + src/liblibc/src/unix/notbsd/linux/mod.rs | 30 + .../src/unix/notbsd/linux/other/b32/x86.rs | 65 + .../src/unix/notbsd/linux/other/b64/x86_64.rs | 65 + src/liblibc/src/unix/notbsd/mod.rs | 28 + src/liblibc/src/unix/uclibc/mips/mips32.rs | 269 + src/liblibc/src/unix/uclibc/mips/mips64.rs | 209 + src/liblibc/src/unix/uclibc/mips/mod.rs | 476 ++ src/liblibc/src/unix/uclibc/mod.rs | 1769 ++++++ src/liblibc/src/unix/uclibc/x86_64/mod.rs | 312 ++ src/libpanic_unwind/dwarf/eh.rs | 55 +- src/libpanic_unwind/gcc.rs | 14 +- src/libpanic_unwind/seh64_gnu.rs | 9 +- src/libproc_macro/Cargo.toml | 1 + src/libproc_macro/lib.rs | 595 +- src/libproc_macro/quote.rs | 263 + src/libproc_macro_plugin/lib.rs | 106 - src/libproc_macro_plugin/quote.rs | 230 - .../Cargo.toml | 14 +- src/libprofiler_builtins/build.rs | 60 + src/libprofiler_builtins/lib.rs | 20 + src/librand/lib.rs | 2 +- src/librustc/Cargo.toml | 30 + src/librustc/cfg/construct.rs | 12 +- src/librustc/dep_graph/README.md | 141 +- src/librustc/dep_graph/debug.rs | 11 +- src/librustc/dep_graph/dep_node.rs | 913 +++- src/librustc/dep_graph/dep_tracking_map.rs | 35 +- src/librustc/dep_graph/edges.rs | 285 +- src/librustc/dep_graph/graph.rs | 160 +- src/librustc/dep_graph/mod.rs | 6 +- src/librustc/dep_graph/query.rs | 34 +- src/librustc/dep_graph/raii.rs | 43 +- src/librustc/dep_graph/shadow.rs | 152 - src/librustc/dep_graph/thread.rs | 179 - src/librustc/diagnostics.rs | 159 +- src/librustc/hir/check_attr.rs | 29 +- src/librustc/hir/def.rs | 23 +- src/librustc/hir/def_id.rs | 3 + src/librustc/hir/intravisit.rs | 5 +- src/librustc/hir/lowering.rs | 198 +- src/librustc/hir/map/blocks.rs | 14 +- src/librustc/hir/map/collector.rs | 2 +- src/librustc/hir/map/def_collector.rs | 45 +- src/librustc/hir/map/definitions.rs | 235 +- src/librustc/hir/map/hir_id_validator.rs | 4 +- src/librustc/hir/map/mod.rs | 119 +- src/librustc/hir/mod.rs | 19 +- src/librustc/hir/print.rs | 434 +- src/librustc/ich/caching_codemap_view.rs | 6 +- src/librustc/ich/fingerprint.rs | 11 + src/librustc/ich/hcx.rs | 78 +- src/librustc/ich/impls_hir.rs | 159 +- src/librustc/ich/impls_mir.rs | 81 +- src/librustc/ich/impls_syntax.rs | 47 +- src/librustc/ich/impls_ty.rs | 160 +- src/librustc/infer/README.md | 2 +- src/librustc/infer/combine.rs | 2 +- src/librustc/infer/error_reporting/mod.rs | 48 +- .../error_reporting/named_anon_conflict.rs | 192 + .../infer/error_reporting/need_type_info.rs | 151 + src/librustc/infer/freshen.rs | 2 +- src/librustc/infer/fudge.rs | 2 +- src/librustc/infer/higher_ranked/mod.rs | 2 +- src/librustc/infer/mod.rs | 299 +- .../infer/region_inference/graphviz.rs | 1 - src/librustc/infer/region_inference/mod.rs | 146 +- src/librustc/infer/type_variable.rs | 6 +- src/librustc/lib.rs | 15 +- src/librustc/lint/builtin.rs | 19 +- src/librustc/lint/context.rs | 138 +- src/librustc/lint/mod.rs | 2 +- src/librustc/macros.rs | 16 +- src/librustc/middle/allocator.rs | 26 + src/librustc/middle/cstore.rs | 35 +- src/librustc/middle/dataflow.rs | 19 +- src/librustc/middle/dead.rs | 13 +- src/librustc/middle/dependency_format.rs | 69 +- src/librustc/middle/effect.rs | 30 +- src/librustc/middle/entry.rs | 2 +- src/librustc/middle/expr_use_visitor.rs | 91 +- src/librustc/middle/intrinsicck.rs | 55 +- src/librustc/middle/lang_items.rs | 6 +- src/librustc/middle/liveness.rs | 10 +- src/librustc/middle/mem_categorization.rs | 314 +- src/librustc/middle/reachable.rs | 8 +- src/librustc/middle/resolve_lifetime.rs | 25 +- src/librustc/middle/stability.rs | 13 +- src/librustc/mir/cache.rs | 4 +- src/librustc/mir/mod.rs | 120 +- src/librustc/mir/tcx.rs | 47 +- src/librustc/mir/traversal.rs | 10 +- src/librustc/mir/visit.rs | 1 + src/librustc/session/code_stats.rs | 4 +- src/librustc/session/config.rs | 176 +- src/librustc/session/filesearch.rs | 8 +- src/librustc/session/mod.rs | 141 +- src/librustc/traits/coherence.rs | 4 +- src/librustc/traits/error_reporting.rs | 301 +- src/librustc/traits/fulfill.rs | 28 +- src/librustc/traits/mod.rs | 69 +- src/librustc/traits/object_safety.rs | 4 +- src/librustc/traits/project.rs | 98 +- src/librustc/traits/select.rs | 110 +- src/librustc/traits/specialize/mod.rs | 7 +- .../traits/specialize/specialization_graph.rs | 2 +- src/librustc/traits/structural_impls.rs | 79 +- src/librustc/traits/trans/mod.rs | 23 +- src/librustc/traits/util.rs | 12 +- src/librustc/ty/context.rs | 44 +- src/librustc/ty/error.rs | 12 +- src/librustc/ty/fast_reject.rs | 3 +- src/librustc/ty/flags.rs | 7 +- src/librustc/ty/fold.rs | 16 +- .../ty/inhabitedness/def_id_forest.rs | 2 +- src/librustc/ty/instance.rs | 21 - src/librustc/ty/item_path.rs | 15 +- src/librustc/ty/layout.rs | 73 +- src/librustc/ty/maps.rs | 231 +- src/librustc/ty/mod.rs | 107 +- src/librustc/ty/relate.rs | 46 +- src/librustc/ty/structural_impls.rs | 151 +- src/librustc/ty/sty.rs | 104 +- src/librustc/ty/subst.rs | 6 +- src/librustc/ty/trait_def.rs | 168 +- src/librustc/ty/util.rs | 98 +- src/librustc/ty/walk.rs | 7 +- src/librustc/ty/wf.rs | 14 +- src/librustc/util/common.rs | 6 +- src/librustc/util/ppaux.rs | 50 +- .../Cargo.toml | 6 +- src/librustc_allocator/expand.rs | 498 ++ src/librustc_allocator/lib.rs | 101 + src/librustc_asan/Cargo.toml | 1 + src/librustc_asan/build.rs | 1 + src/librustc_asan/lib.rs | 9 + src/librustc_back/lib.rs | 4 - .../target/aarch64_unknown_freebsd.rs | 2 +- .../target/aarch64_unknown_linux_gnu.rs | 2 +- src/librustc_back/target/bitrig_base.rs | 1 - src/librustc_back/target/fuchsia_base.rs | 1 - src/librustc_back/target/i386_apple_ios.rs | 1 + src/librustc_back/target/i686_apple_darwin.rs | 1 + .../target/i686_linux_android.rs | 1 + .../target/i686_unknown_dragonfly.rs | 1 + .../target/i686_unknown_freebsd.rs | 1 + .../target/i686_unknown_haiku.rs | 1 + .../target/i686_unknown_linux_gnu.rs | 1 + .../target/i686_unknown_linux_musl.rs | 1 + .../target/i686_unknown_netbsd.rs | 1 + .../target/i686_unknown_openbsd.rs | 1 + .../target/mips64_unknown_linux_gnuabi64.rs | 2 +- .../target/mips64el_unknown_linux_gnuabi64.rs | 2 +- .../target/mips_unknown_linux_gnu.rs | 2 +- .../target/mips_unknown_linux_musl.rs | 2 +- .../target/mips_unknown_linux_uclibc.rs | 2 +- .../target/mipsel_unknown_linux_gnu.rs | 2 +- .../target/mipsel_unknown_linux_musl.rs | 2 +- .../target/mipsel_unknown_linux_uclibc.rs | 2 +- src/librustc_back/target/mod.rs | 59 +- src/librustc_back/target/msp430_none_elf.rs | 53 + src/librustc_back/target/openbsd_base.rs | 1 - .../target/powerpc64_unknown_linux_gnu.rs | 2 +- .../target/powerpc64le_unknown_linux_gnu.rs | 2 +- .../target/powerpc_unknown_linux_gnu.rs | 2 +- src/librustc_back/target/redox_base.rs | 2 - .../target/s390x_unknown_linux_gnu.rs | 2 +- .../target/sparc64_unknown_linux_gnu.rs | 2 +- .../target/wasm32_experimental_emscripten.rs | 54 + src/librustc_back/target/windows_msvc_base.rs | 1 - .../target/x86_64_apple_darwin.rs | 1 + src/librustc_back/target/x86_64_apple_ios.rs | 1 + .../target/x86_64_linux_android.rs | 1 + .../target/x86_64_pc_windows_msvc.rs | 1 + .../target/x86_64_rumprun_netbsd.rs | 3 +- .../target/x86_64_sun_solaris.rs | 1 + .../target/x86_64_unknown_bitrig.rs | 1 + .../target/x86_64_unknown_dragonfly.rs | 1 + .../target/x86_64_unknown_freebsd.rs | 1 + .../target/x86_64_unknown_fuchsia.rs | 1 + .../target/x86_64_unknown_haiku.rs | 1 + .../target/x86_64_unknown_linux_gnu.rs | 1 + .../target/x86_64_unknown_linux_musl.rs | 1 + .../target/x86_64_unknown_netbsd.rs | 1 + .../target/x86_64_unknown_openbsd.rs | 1 + .../target/x86_64_unknown_redox.rs | 1 + src/librustc_bitflags/lib.rs | 6 +- src/librustc_borrowck/borrowck/check_loans.rs | 15 +- .../borrowck/gather_loans/mod.rs | 9 +- src/librustc_borrowck/borrowck/mod.rs | 29 +- src/librustc_borrowck/diagnostics.rs | 46 +- src/librustc_borrowck/lib.rs | 8 +- src/librustc_const_eval/_match.rs | 49 +- src/librustc_const_eval/check_match.rs | 17 +- src/librustc_const_eval/diagnostics.rs | 8 +- src/librustc_const_eval/eval.rs | 4 +- src/librustc_const_eval/lib.rs | 4 - src/librustc_const_eval/pattern.rs | 6 +- src/librustc_const_math/lib.rs | 4 - src/librustc_data_structures/fnv.rs | 2 +- src/librustc_data_structures/fx.rs | 2 +- src/librustc_data_structures/lib.rs | 8 +- src/librustc_data_structures/stable_hasher.rs | 37 + src/librustc_driver/Cargo.toml | 2 +- src/librustc_driver/driver.rs | 59 +- src/librustc_driver/lib.rs | 171 +- src/librustc_driver/pretty.rs | 78 +- src/librustc_driver/test.rs | 2 +- src/librustc_errors/diagnostic.rs | 16 + src/librustc_errors/emitter.rs | 94 +- src/librustc_errors/lib.rs | 50 +- src/librustc_errors/snippet.rs | 4 - src/librustc_errors/styled_buffer.rs | 6 - src/librustc_incremental/assert_dep_graph.rs | 71 +- src/librustc_incremental/calculate_svh/mod.rs | 88 +- src/librustc_incremental/lib.rs | 5 - src/librustc_incremental/persist/data.rs | 32 +- .../persist/dirty_clean.rs | 68 +- .../persist/file_format.rs | 6 +- src/librustc_incremental/persist/fs.rs | 4 +- src/librustc_incremental/persist/hash.rs | 76 +- src/librustc_incremental/persist/load.rs | 303 +- src/librustc_incremental/persist/preds/mod.rs | 34 +- src/librustc_incremental/persist/save.rs | 89 +- .../persist/work_product.rs | 4 +- src/librustc_lint/builtin.rs | 55 +- src/librustc_lint/lib.rs | 8 +- src/librustc_lint/types.rs | 4 +- src/librustc_lint/unused.rs | 13 +- src/librustc_llvm/build.rs | 3 +- src/librustc_llvm/ffi.rs | 13 +- src/librustc_llvm/lib.rs | 10 +- src/librustc_lsan/Cargo.toml | 1 + src/librustc_lsan/build.rs | 1 + src/librustc_lsan/lib.rs | 9 + src/librustc_metadata/Cargo.toml | 2 +- src/librustc_metadata/creader.rs | 276 +- src/librustc_metadata/cstore.rs | 46 +- src/librustc_metadata/cstore_impl.rs | 111 +- src/librustc_metadata/decoder.rs | 67 +- src/librustc_metadata/diagnostics.rs | 9 +- src/librustc_metadata/encoder.rs | 106 +- src/librustc_metadata/index_builder.rs | 2 +- src/librustc_metadata/isolated_encoder.rs | 12 +- src/librustc_metadata/lib.rs | 6 +- src/librustc_metadata/locator.rs | 9 +- src/librustc_metadata/schema.rs | 56 +- src/librustc_mir/build/block.rs | 59 +- src/librustc_mir/build/cfg.rs | 11 + src/librustc_mir/build/expr/as_lvalue.rs | 2 +- src/librustc_mir/build/expr/as_operand.rs | 2 + src/librustc_mir/build/expr/as_rvalue.rs | 3 +- src/librustc_mir/build/expr/as_temp.rs | 6 +- src/librustc_mir/build/expr/into.rs | 16 +- src/librustc_mir/build/expr/stmt.rs | 8 +- src/librustc_mir/build/matches/mod.rs | 3 +- src/librustc_mir/build/matches/test.rs | 2 +- src/librustc_mir/build/mod.rs | 16 +- src/librustc_mir/build/scope.rs | 93 +- .../dataflow/drop_flag_effects.rs} | 149 +- .../mir => librustc_mir}/dataflow/graphviz.rs | 13 +- .../dataflow/impls/mod.rs} | 30 +- .../mir => librustc_mir}/dataflow/mod.rs | 36 +- .../dataflow/move_paths}/abs_domain.rs | 0 .../dataflow/move_paths/mod.rs} | 13 +- src/librustc_mir/diagnostics.rs | 8 +- src/librustc_mir/hair/cx/block.rs | 11 + src/librustc_mir/hair/cx/expr.rs | 13 +- src/librustc_mir/hair/cx/mod.rs | 6 +- src/librustc_mir/hair/mod.rs | 2 + src/librustc_mir/lib.rs | 8 +- src/librustc_mir/shim.rs | 17 +- .../transform/clean_end_regions.rs | 84 + src/librustc_mir/transform/copy_prop.rs | 3 +- .../transform}/elaborate_drops.rs | 48 +- src/librustc_mir/transform/erase_regions.rs | 10 + src/librustc_mir/transform/inline.rs | 9 +- src/librustc_mir/transform/mod.rs | 3 + src/librustc_mir/transform/qualify_consts.rs | 31 +- .../transform/rustc_peek.rs} | 83 +- src/librustc_mir/transform/type_check.rs | 5 +- src/librustc_mir/util/patch.rs | 1 + src/librustc_msan/Cargo.toml | 1 + src/librustc_msan/build.rs | 1 + src/librustc_msan/lib.rs | 9 + src/librustc_passes/ast_validation.rs | 58 + src/librustc_passes/consts.rs | 18 +- src/librustc_passes/diagnostics.rs | 8 +- src/librustc_passes/lib.rs | 4 - src/librustc_passes/mir_stats.rs | 1 + src/librustc_passes/static_recursion.rs | 7 +- src/librustc_platform_intrinsics/arm.rs | 780 +-- src/librustc_platform_intrinsics/lib.rs | 2 - src/librustc_plugin/lib.rs | 24 +- src/librustc_privacy/diagnostics.rs | 10 +- src/librustc_privacy/lib.rs | 529 +- src/librustc_resolve/build_reduced_graph.rs | 9 +- src/librustc_resolve/diagnostics.rs | 108 +- src/librustc_resolve/lib.rs | 108 +- src/librustc_resolve/macros.rs | 12 +- src/librustc_resolve/resolve_imports.rs | 18 +- src/librustc_save_analysis/Cargo.toml | 2 +- src/librustc_save_analysis/csv_dumper.rs | 436 -- src/librustc_save_analysis/data.rs | 446 -- src/librustc_save_analysis/dump.rs | 40 - src/librustc_save_analysis/dump_visitor.rs | 1056 ++-- src/librustc_save_analysis/external_data.rs | 775 --- src/librustc_save_analysis/json_api_dumper.rs | 312 +- src/librustc_save_analysis/json_dumper.rs | 434 +- src/librustc_save_analysis/lib.rs | 740 ++- src/librustc_save_analysis/sig.rs | 925 ++++ src/librustc_save_analysis/span_utils.rs | 129 +- src/librustc_trans/Cargo.toml | 6 +- src/librustc_trans/allocator.rs | 117 + src/librustc_trans/attributes.rs | 30 +- src/librustc_trans/back/link.rs | 136 +- src/librustc_trans/back/lto.rs | 114 +- src/librustc_trans/back/symbol_export.rs | 3 +- src/librustc_trans/back/symbol_names.rs | 7 + src/librustc_trans/back/write.rs | 640 ++- src/librustc_trans/base.rs | 63 +- src/librustc_trans/collector.rs | 20 +- src/librustc_trans/common.rs | 6 +- src/librustc_trans/context.rs | 12 +- src/librustc_trans/debuginfo/metadata.rs | 60 +- src/librustc_trans/debuginfo/mod.rs | 32 +- src/librustc_trans/debuginfo/namespace.rs | 17 +- src/librustc_trans/debuginfo/type_names.rs | 4 +- src/librustc_trans/debuginfo/utils.rs | 12 +- src/librustc_trans/declare.rs | 11 - src/librustc_trans/diagnostics.rs | 2 +- src/librustc_trans/glue.rs | 12 +- src/librustc_trans/intrinsic.rs | 15 +- src/librustc_trans/lib.rs | 14 +- src/librustc_trans/mir/block.rs | 57 +- src/librustc_trans/mir/constant.rs | 7 +- src/librustc_trans/mir/lvalue.rs | 2 +- src/librustc_trans/mir/operand.rs | 16 +- src/librustc_trans/mir/rvalue.rs | 2 +- src/librustc_trans/mir/statement.rs | 1 + src/librustc_trans/monomorphize.rs | 10 +- src/librustc_trans/partitioning.rs | 17 +- src/librustc_trans/trans_item.rs | 81 +- src/librustc_tsan/build.rs | 1 + src/librustc_typeck/astconv.rs | 41 +- src/librustc_typeck/check/_match.rs | 6 +- src/librustc_typeck/check/callee.rs | 27 +- src/librustc_typeck/check/cast.rs | 122 +- src/librustc_typeck/check/closure.rs | 6 +- src/librustc_typeck/check/coercion.rs | 126 +- src/librustc_typeck/check/compare_method.rs | 32 +- src/librustc_typeck/check/demand.rs | 34 +- src/librustc_typeck/check/dropck.rs | 4 +- src/librustc_typeck/check/intrinsic.rs | 46 +- src/librustc_typeck/check/method/confirm.rs | 28 +- src/librustc_typeck/check/method/mod.rs | 13 +- src/librustc_typeck/check/method/probe.rs | 13 +- src/librustc_typeck/check/method/suggest.rs | 2 +- src/librustc_typeck/check/mod.rs | 648 ++- src/librustc_typeck/check/op.rs | 2 +- src/librustc_typeck/check/regionck.rs | 92 +- src/librustc_typeck/check/upvar.rs | 207 +- src/librustc_typeck/check/wfcheck.rs | 19 +- src/librustc_typeck/check/writeback.rs | 7 +- src/librustc_typeck/coherence/builtin.rs | 4 +- .../coherence/inherent_impls.rs | 5 +- .../coherence/inherent_impls_overlap.rs | 2 +- src/librustc_typeck/coherence/overlap.rs | 4 - src/librustc_typeck/collect.rs | 126 +- .../constrained_type_params.rs | 13 +- src/librustc_typeck/diagnostics.rs | 714 ++- src/librustc_typeck/impl_wf_check.rs | 2 +- src/librustc_typeck/lib.rs | 43 +- src/librustc_typeck/variance/constraints.rs | 396 +- src/librustc_typeck/variance/mod.rs | 89 +- src/librustc_typeck/variance/solve.rs | 73 +- src/librustc_typeck/variance/terms.rs | 160 +- src/librustdoc/clean/inline.rs | 16 +- src/librustdoc/clean/mod.rs | 44 +- src/librustdoc/core.rs | 7 +- src/librustdoc/html/format.rs | 48 +- src/librustdoc/html/highlight.rs | 4 +- src/librustdoc/html/markdown.rs | 55 +- src/librustdoc/html/render.rs | 162 +- src/librustdoc/html/static/main.js | 65 +- src/librustdoc/html/static/rustdoc.css | 5 + src/librustdoc/lib.rs | 221 +- src/librustdoc/passes/mod.rs | 24 +- src/librustdoc/test.rs | 87 +- src/librustdoc/visit_ast.rs | 24 +- src/librustdoc/visit_lib.rs | 2 +- src/libserialize/collection_impls.rs | 2 +- src/libserialize/json.rs | 2 +- src/libserialize/lib.rs | 7 - src/libstd/Cargo.toml | 4 +- src/libstd/build.rs | 4 + src/libstd/collections/hash/map.rs | 8 +- src/libstd/collections/hash/table.rs | 11 +- src/libstd/collections/mod.rs | 12 +- src/libstd/env.rs | 149 +- src/libstd/error.rs | 27 + src/libstd/f32.rs | 60 +- src/libstd/f64.rs | 54 +- src/libstd/ffi/c_str.rs | 226 +- src/libstd/ffi/os_str.rs | 34 +- src/libstd/fs.rs | 53 +- src/libstd/heap.rs | 165 + src/libstd/io/buffered.rs | 28 +- src/libstd/io/cursor.rs | 7 +- src/libstd/io/impls.rs | 17 +- src/libstd/io/mod.rs | 181 +- src/libstd/io/stdio.rs | 23 +- src/libstd/io/util.rs | 26 +- src/libstd/lib.rs | 41 +- src/libstd/macros.rs | 47 +- src/libstd/memchr.rs | 4 +- src/libstd/net/tcp.rs | 47 +- src/libstd/num.rs | 5 +- src/libstd/panic.rs | 2 +- src/libstd/panicking.rs | 84 +- src/libstd/path.rs | 93 +- src/libstd/prelude/mod.rs | 13 +- src/libstd/primitive_docs.rs | 6 +- src/libstd/process.rs | 61 +- src/libstd/rand/mod.rs | 2 +- src/libstd/rt.rs | 2 +- src/libstd/sync/condvar.rs | 66 +- src/libstd/sync/mpsc/mod.rs | 5 - src/libstd/sync/mutex.rs | 7 + src/libstd/sync/rwlock.rs | 14 + src/libstd/sys/redox/args.rs | 6 + src/libstd/sys/redox/backtrace.rs | 15 +- src/libstd/sys/redox/condvar.rs | 4 +- src/libstd/sys/redox/ext/fs.rs | 67 +- src/libstd/sys/redox/fast_thread_local.rs | 6 +- src/libstd/sys/redox/fd.rs | 5 - src/libstd/sys/redox/fs.rs | 39 +- src/libstd/sys/redox/mod.rs | 20 +- src/libstd/sys/redox/net/tcp.rs | 9 +- src/libstd/sys/redox/os.rs | 2 +- src/libstd/sys/redox/os_str.rs | 27 +- src/libstd/sys/redox/pipe.rs | 8 +- src/libstd/sys/redox/process.rs | 12 + src/libstd/sys/redox/stdio.rs | 7 - src/libstd/sys/redox/syscall/flag.rs | 3 + src/libstd/sys/unix/args.rs | 6 + src/libstd/sys/unix/condvar.rs | 34 +- src/libstd/sys/unix/ext/fs.rs | 22 +- src/libstd/sys/unix/ext/net.rs | 12 +- src/libstd/sys/unix/fast_thread_local.rs | 111 +- src/libstd/sys/unix/fd.rs | 5 - src/libstd/sys/unix/fs.rs | 4 - src/libstd/sys/unix/mod.rs | 20 - src/libstd/sys/unix/net.rs | 71 +- src/libstd/sys/unix/os_str.rs | 27 +- src/libstd/sys/unix/pipe.rs | 4 - src/libstd/sys/unix/process/process_common.rs | 12 + src/libstd/sys/unix/stdio.rs | 7 - src/libstd/sys/unix/thread.rs | 44 +- src/libstd/sys/windows/args.rs | 31 + src/libstd/sys/windows/c.rs | 27 + src/libstd/sys/windows/ext/fs.rs | 10 +- .../sys/windows/fast_thread_local.rs} | 14 +- src/libstd/sys/windows/fs.rs | 4 - src/libstd/sys/windows/handle.rs | 5 - src/libstd/sys/windows/mod.rs | 19 +- src/libstd/sys/windows/net.rs | 66 +- src/libstd/sys/windows/os_str.rs | 26 +- src/libstd/sys/windows/pipe.rs | 4 - src/libstd/sys/windows/process.rs | 30 +- src/libstd/sys/windows/stdio.rs | 5 - src/libstd/sys_common/io.rs | 129 - src/libstd/sys_common/mod.rs | 3 +- src/libstd/sys_common/net.rs | 12 +- src/libstd/sys_common/thread_info.rs | 11 +- src/libstd/sys_common/thread_local.rs | 43 +- src/libstd/sys_common/wtf8.rs | 50 +- src/libstd/thread/local.rs | 203 +- src/libstd/thread/mod.rs | 18 +- src/libstd_unicode/Cargo.toml | 4 + src/libstd_unicode/char.rs | 15 +- src/libstd_unicode/lib.rs | 5 +- src/libstd_unicode/lossy.rs | 212 + src/libstd_unicode/tables.rs | 323 +- .../tests/lib.rs} | 11 +- src/libstd_unicode/tests/lossy.rs | 91 + src/libstd_unicode/u_str.rs | 2 +- src/libsyntax/ast.rs | 32 +- src/libsyntax/attr.rs | 14 +- src/libsyntax/codemap.rs | 86 +- src/libsyntax/config.rs | 28 - src/libsyntax/diagnostic_list.rs | 6 +- src/libsyntax/diagnostics/macros.rs | 11 + src/libsyntax/ext/base.rs | 21 +- src/libsyntax/ext/build.rs | 22 +- src/libsyntax/ext/expand.rs | 70 +- src/libsyntax/ext/quote.rs | 40 +- src/libsyntax/ext/source_util.rs | 21 +- src/libsyntax/ext/tt/macro_parser.rs | 138 +- src/libsyntax/ext/tt/macro_rules.rs | 43 +- src/libsyntax/ext/tt/quoted.rs | 20 +- src/libsyntax/ext/tt/transcribe.rs | 77 +- src/libsyntax/feature_gate.rs | 114 +- src/libsyntax/fold.rs | 18 +- src/libsyntax/json.rs | 4 +- src/libsyntax/lib.rs | 4 - src/libsyntax/parse/attr.rs | 4 +- src/libsyntax/parse/lexer/mod.rs | 53 +- src/libsyntax/parse/lexer/tokentrees.rs | 12 +- src/libsyntax/parse/mod.rs | 15 +- src/libsyntax/parse/parser.rs | 272 +- src/libsyntax/parse/token.rs | 173 +- src/libsyntax/print/pp.rs | 114 +- src/libsyntax/print/pprust.rs | 658 ++- src/libsyntax/ptr.rs | 5 +- src/libsyntax/test.rs | 15 +- src/libsyntax/test_snippet.rs | 43 + src/libsyntax/tokenstream.rs | 228 +- src/libsyntax/util/parser_testing.rs | 2 +- src/libsyntax/util/rc_slice.rs | 10 +- src/libsyntax/visit.rs | 5 +- src/libsyntax_ext/compile_error.rs | 30 + src/libsyntax_ext/concat_idents.rs | 7 +- src/libsyntax_ext/deriving/clone.rs | 2 +- src/libsyntax_ext/deriving/custom.rs | 15 +- src/libsyntax_ext/deriving/debug.rs | 2 +- src/libsyntax_ext/deriving/encodable.rs | 14 +- src/libsyntax_ext/deriving/generic/mod.rs | 21 +- src/libsyntax_ext/deriving/hash.rs | 2 +- src/libsyntax_ext/format.rs | 16 +- src/libsyntax_ext/lib.rs | 7 +- src/libsyntax_ext/proc_macro_impl.rs | 4 +- src/libsyntax_pos/Cargo.toml | 1 + src/libsyntax_pos/hygiene.rs | 24 +- src/libsyntax_pos/lib.rs | 168 +- src/libsyntax_pos/symbol.rs | 127 +- src/libterm/lib.rs | 3 - src/libtest/Cargo.toml | 2 +- src/libtest/lib.rs | 111 +- src/rt/miniz.c | 1890 ------- src/rustc/compiler_builtins_shim/Cargo.toml | 24 + .../compiler_builtins_shim}/build.rs | 10 +- src/rustllvm/.editorconfig | 6 + src/rustllvm/PassWrapper.cpp | 128 +- src/rustllvm/RustWrapper.cpp | 4 + src/rustllvm/llvm-rebuild-trigger | 2 +- src/stage0.txt | 6 +- src/test/COMPILER_TESTS.md | 73 +- .../item-collection/function-as-argument.rs | 4 +- .../trait-method-as-argument.rs | 12 +- src/test/codegen/alloc-optimisation.rs | 22 + src/test/codegen/dealloc-no-unwind.rs | 32 + src/test/codegen/drop.rs | 2 +- src/test/codegen/function-arguments.rs | 2 +- src/test/codegen/issue-37945.rs | 36 + src/test/codegen/mir_zst_stores.rs | 10 +- .../stack-probes.rs} | 21 +- src/test/codegen/vec-optimizes-away.rs | 21 + .../auxiliary/use_from_trait_xc.rs | 1 - .../derive-no-std-not-supported.rs | 1 - .../proc-macro/auxiliary/bang_proc_macro2.rs | 23 + .../proc-macro/lints_in_proc_macros.rs | 26 + .../proc-macro/shadow.rs | 2 +- src/test/compile-fail/E0164.rs | 1 - src/test/compile-fail/E0254.rs | 13 +- src/test/compile-fail/E0259.rs | 11 +- src/test/compile-fail/E0260.rs | 13 +- src/test/compile-fail/E0428.rs | 5 +- src/test/compile-fail/E0429.rs | 1 - src/test/compile-fail/E0435.rs | 2 +- src/test/compile-fail/E0438.rs | 1 - src/test/compile-fail/E0512.rs | 1 - src/test/compile-fail/E0602.rs | 16 + src/test/compile-fail/E0604.rs | 13 + src/test/compile-fail/E0605.rs | 19 + src/test/compile-fail/E0606.rs | 13 + src/test/compile-fail/E0607.rs | 14 + src/test/compile-fail/E0608.rs | 13 + src/test/compile-fail/E0609.rs | 22 + src/test/compile-fail/E0610.rs | 14 + src/test/compile-fail/E0611.rs | 22 + src/test/compile-fail/E0612.rs | 16 + src/test/compile-fail/E0614.rs | 14 + src/test/compile-fail/E0615.rs | 22 + src/test/compile-fail/E0616.rs | 24 + src/test/compile-fail/E0617.rs | 32 + .../E0618.rs} | 15 +- src/test/compile-fail/E0619.rs | 19 + src/test/compile-fail/E0620.rs | 13 + .../E0621-does-not-trigger-for-closures.rs | 28 + .../{invalid-intrinsic.rs => E0622.rs} | 4 +- .../compile-fail/allocator-dylib-is-system.rs | 41 - .../allocator-rust-dylib-is-jemalloc.rs | 41 - .../auxiliary/system-allocator.rs} | 10 +- .../allocator/auxiliary/system-allocator2.rs | 19 + .../allocator/function-allocator.rs | 16 + .../allocator/not-an-allocator.rs | 26 + .../compile-fail/allocator/two-allocators.rs | 22 + .../compile-fail/allocator/two-allocators2.rs | 25 + .../compile-fail/allocator/two-allocators3.rs | 21 + src/test/compile-fail/asm-out-assign-imm.rs | 1 - .../compile-fail/asm-src-loc-codegen-units.rs | 5 +- .../associated-const-ambiguity-report.rs | 1 - .../associated-const-array-len.rs | 1 - .../associated-const-dead-code.rs | 1 - .../associated-const-generic-obligations.rs | 1 - .../associated-const-impl-wrong-lifetime.rs | 1 - .../associated-const-impl-wrong-type.rs | 1 - .../compile-fail/associated-const-no-item.rs | 1 - .../associated-const-private-impl.rs | 1 - .../associated-const-type-parameter-arms.rs | 1 - ...ssociated-const-type-parameter-arrays-2.rs | 1 - .../associated-const-type-parameter-arrays.rs | 1 - .../associated-const-upper-case-lint.rs | 1 - .../associated-item-duplicate-names-2.rs | 1 - .../associated-item-duplicate-names.rs | 1 - ...ed-types-ICE-when-projecting-out-of-err.rs | 2 +- .../associated-types-overridden-default.rs | 1 - .../compile-fail/associated-types-path-2.rs | 2 + .../attempted-access-non-fatal.rs | 4 +- .../compile-fail/auxiliary/issue-36881-aux.rs | 11 + .../compile-fail/auxiliary/issue_41549.rs | 1 - ...-dylib.rs => lint_unused_extern_crate2.rs} | 6 +- .../auxiliary/lint_unused_extern_crate3.rs | 11 + .../auxiliary/lint_unused_extern_crate4.rs | 9 + .../auxiliary/private-inferred-type.rs | 44 + .../auxiliary/use_from_trait_xc.rs | 1 - .../blind-item-block-item-shadow.rs | 2 +- .../compile-fail/blind-item-item-shadow.rs | 7 +- src/test/compile-fail/cast-from-nil.rs | 2 +- src/test/compile-fail/cast-to-bare-fn.rs | 4 +- src/test/compile-fail/cast-to-nil.rs | 2 +- ...cast-to-unsized-trait-object-suggestion.rs | 20 - src/test/compile-fail/closure-no-fn-3.rs | 2 +- src/test/compile-fail/coerce-to-bang-cast.rs | 2 +- src/test/compile-fail/compile_error_macro.rs | 13 + .../compile-fail/defaulted-unit-warning.rs | 5 +- .../dep-graph-assoc-type-trans.rs | 1 - .../compile-fail/dep-graph-caller-callee.rs | 2 - .../dep-graph-struct-signature.rs | 36 +- src/test/compile-fail/dep-graph-trait-impl.rs | 5 - src/test/compile-fail/dep-graph-type-alias.rs | 22 +- .../backcompat-warnings.rs | 4 - ...tors-2.rs => dollar-crate-is-keyword-2.rs} | 18 +- .../compile-fail/dollar-crate-is-keyword.rs | 24 + src/test/compile-fail/double-import.rs | 7 +- src/test/compile-fail/double-type-import.rs | 2 +- src/test/compile-fail/dst-bad-assign-3.rs | 50 + src/test/compile-fail/dst-bad-coerce1.rs | 14 + src/test/compile-fail/dst-bad-coerce2.rs | 10 + src/test/compile-fail/dst-bad-coerce3.rs | 12 + src/test/compile-fail/dst-bad-coerce4.rs | 10 + .../bar.rs => compile-fail/dst-bad-deep-2.rs} | 24 +- .../compile-fail/empty-struct-unit-expr.rs | 4 +- .../enum-and-module-in-same-scope.rs | 7 +- .../compile-fail/extern-wrong-value-type.rs | 1 - src/test/compile-fail/fail-simple.rs | 2 +- src/test/compile-fail/fat-ptr-cast.rs | 2 +- .../feature-gate-allocator_internals.rs} | 7 +- .../feature-gate-allow_fail.rs} | 12 +- .../feature-gate-global_allocator.rs | 14 + .../feature-gate-profiler-runtime.rs | 13 + .../feature-gate-unsized_tuple_coercion.rs | 14 + src/test/compile-fail/fn-trait-formatting.rs | 1 - src/test/compile-fail/gated-link-args.rs | 18 +- .../hygiene/auxiliary/intercrate.rs | 0 .../hygiene/fields.rs | 8 +- .../hygiene/impl_items.rs | 2 +- .../hygiene/intercrate.rs | 2 + src/test/compile-fail/import-ty-params.rs | 2 +- src/test/compile-fail/imports/duplicate.rs | 7 +- .../imports/rfc-1560-warning-cycle.rs | 8 +- src/test/compile-fail/index-bot.rs | 2 +- src/test/compile-fail/index_message.rs | 2 +- src/test/compile-fail/issue-10991.rs | 2 +- src/test/compile-fail/issue-11740.rs | 38 + src/test/compile-fail/issue-13853-5.rs | 2 +- .../compile-fail/issue-17718-const-borrow.rs | 6 +- src/test/compile-fail/issue-18400.rs | 4 +- src/test/compile-fail/issue-19498.rs | 21 +- src/test/compile-fail/issue-19601.rs | 19 + src/test/compile-fail/issue-20831-debruijn.rs | 2 +- src/test/compile-fail/issue-21174.rs | 2 +- src/test/compile-fail/issue-21546.rs | 42 +- src/test/compile-fail/issue-22034.rs | 1 - src/test/compile-fail/issue-22289.rs | 2 +- src/test/compile-fail/issue-22312.rs | 2 +- src/test/compile-fail/issue-22603.rs | 23 + src/test/compile-fail/issue-22789.rs | 17 + src/test/compile-fail/issue-23046.rs | 4 +- src/test/compile-fail/issue-23966.rs | 1 - src/test/compile-fail/issue-24081.rs | 35 +- src/test/compile-fail/issue-24363.rs | 2 +- src/test/compile-fail/issue-25396.rs | 8 +- ...{dep-graph-unrelated.rs => issue-26614.rs} | 23 +- src/test/compile-fail/issue-26638.rs | 2 +- src/test/compile-fail/issue-26886.rs | 14 +- src/test/compile-fail/issue-27842.rs | 4 +- src/test/compile-fail/issue-28472.rs | 4 +- src/test/compile-fail/issue-28625.rs | 2 +- src/test/compile-fail/issue-28992-empty.rs | 1 - src/test/compile-fail/issue-2995.rs | 2 +- src/test/compile-fail/issue-30255.rs | 6 +- src/test/compile-fail/issue-3099-a.rs | 2 +- src/test/compile-fail/issue-3099-b.rs | 2 +- src/test/compile-fail/issue-3099.rs | 2 +- src/test/compile-fail/issue-31910.rs | 1 - src/test/compile-fail/issue-32377.rs | 2 +- src/test/compile-fail/issue-32995-2.rs | 9 +- src/test/compile-fail/issue-32995.rs | 17 +- src/test/compile-fail/issue-34222-1.rs | 13 + src/test/compile-fail/issue-34222.rs | 18 + src/test/compile-fail/issue-34373.rs | 21 + src/test/compile-fail/issue-35570.rs | 40 + src/test/compile-fail/issue-35675.rs | 6 +- src/test/compile-fail/issue-35869.rs | 6 +- src/test/compile-fail/issue-36839.rs | 32 + src/test/compile-fail/issue-36881.rs | 6 +- src/test/compile-fail/issue-37051.rs | 29 + src/test/compile-fail/issue-37323.rs | 28 + src/test/compile-fail/issue-37366.rs | 26 + src/test/compile-fail/issue-37510.rs | 25 + src/test/compile-fail/issue-37515.rs | 18 + src/test/compile-fail/issue-38293.rs | 1 - src/test/compile-fail/issue-38381.rs | 18 + src/test/compile-fail/issue-38954.rs | 6 +- src/test/compile-fail/issue-39404.rs | 4 +- src/test/compile-fail/issue-40861.rs | 2 +- src/test/compile-fail/issue-41549.rs | 1 - src/test/compile-fail/issue-41998.rs | 20 + src/test/compile-fail/issue-42312.rs | 21 + src/test/compile-fail/issue-42755.rs | 17 + src/test/compile-fail/issue-42880.rs | 18 + src/test/compile-fail/issue-43250.rs | 23 + src/test/compile-fail/issue-43424.rs | 22 + src/test/compile-fail/issue-6936.rs | 8 +- src/test/compile-fail/issue-7044.rs | 2 +- src/test/compile-fail/issue-8640.rs | 2 +- ...-return-type-requires-explicit-lifetime.rs | 2 +- .../compile-fail/lint-unused-extern-crate.rs | 22 +- src/test/compile-fail/macro-context.rs | 2 +- .../compile-fail/method-call-type-binding.rs | 13 + .../compile-fail/no-patterns-in-args-2.rs | 1 + src/test/compile-fail/no-std-inject.rs | 2 +- ...at.rs => non-constant-expr-for-arr-len.rs} | 4 +- src/test/compile-fail/nonscalar-cast.rs | 4 +- src/test/compile-fail/not-sync.rs | 4 +- .../object-safety-associated-consts.rs | 1 - .../packed-struct-generic-transmute.rs | 2 +- .../compile-fail/packed-struct-transmute.rs | 2 +- src/test/compile-fail/parse-error-correct.rs | 2 +- .../compile-fail/patkind-litrange-no-expr.rs | 36 + src/test/compile-fail/privacy-sanity.rs | 1 - .../privacy/restricted/ty-params.rs | 2 +- .../compile-fail/private-in-public-warn.rs | 1 - src/test/compile-fail/private-in-public.rs | 1 - .../compile-fail/private-inferred-type-1.rs | 28 + .../compile-fail/private-inferred-type-2.rs | 29 + .../compile-fail/private-inferred-type-3.rs | 26 + .../compile-fail/private-inferred-type.rs | 139 + .../compile-fail/private-type-in-interface.rs | 41 + .../pub-reexport-priv-extern-crate.rs | 1 - src/test/compile-fail/range-1.rs | 1 - src/test/compile-fail/range_traits-1.rs | 31 +- src/test/compile-fail/repr-align.rs | 2 +- ...e-conflict-extern-crate-vs-extern-crate.rs | 2 +- ...resolve-conflict-import-vs-extern-crate.rs | 2 +- .../resolve-conflict-import-vs-import.rs | 2 +- .../resolve-conflict-item-vs-extern-crate.rs | 2 +- .../resolve-conflict-item-vs-import.rs | 7 +- .../resolve-conflict-type-vs-import.rs | 2 +- .../compile-fail/resolve_self_super_hint.rs | 28 +- .../rust-unstable-column-gated.rs | 14 + .../compile-fail/safe-extern-statics-mut.rs | 3 - src/test/compile-fail/safe-extern-statics.rs | 1 - src/test/compile-fail/slice-2.rs | 8 +- .../stmt_expr_attrs_no_feature.rs | 1 - src/test/compile-fail/str-mut-idx.rs | 3 +- src/test/compile-fail/struct-field-cfg.rs | 2 - src/test/compile-fail/struct-field-privacy.rs | 2 +- .../tag-variant-cast-non-nullary.rs | 4 +- .../compile-fail/trait-duplicate-methods.rs | 7 +- ...rait-impl-can-not-have-untraitful-items.rs | 1 - src/test/compile-fail/trait-item-privacy.rs | 1 - .../compile-fail/transmute-different-sizes.rs | 6 +- .../compile-fail/transmute-fat-pointers.rs | 8 +- src/test/compile-fail/transmute-impl.rs | 2 +- .../compile-fail/tuple-index-not-tuple.rs | 4 +- src/test/compile-fail/two-allocators-3.rs | 23 - .../type-parameter-invalid-lint.rs | 1 - .../type-params-in-different-spaces-2.rs | 2 +- .../unboxed-closures-unsafe-extern-fn.rs | 2 - .../unboxed-closures-wrong-abi.rs | 2 - ...boxed-closures-wrong-arg-type-extern-fn.rs | 2 - .../compile-fail/uninhabited-enum-cast.rs | 2 +- .../unresolved-extern-mod-suggestion.rs | 2 +- src/test/compile-fail/unsized3.rs | 1 + src/test/compile-fail/unsized6.rs | 12 +- src/test/compile-fail/unused-result.rs | 8 +- src/test/compile-fail/use-from-trait.rs | 1 - src/test/compile-fail/use-keyword.rs | 5 +- src/test/compile-fail/use-mod-4.rs | 3 + src/test/compile-fail/use-mod.rs | 7 +- src/test/compile-fail/use-paths-as-items.rs | 2 +- src/test/compile-fail/use-self-type.rs | 21 + src/test/compile-fail/variadic-ffi-3.rs | 12 +- src/test/compile-fail/variadic-ffi.rs | 1 + .../compile-fail/variance-trait-bounds.rs | 22 +- .../compile-fail/variance-types-bounds.rs | 27 +- src/test/compile-fail/variant-namespacing.rs | 12 +- .../compile-fail/vec-macro-with-comma-only.rs | 2 +- src/test/debuginfo/pretty-std.rs | 13 + src/test/incremental/dirty_clean.rs | 8 +- src/test/incremental/hashes/trait_defs.rs | 1 - src/test/incremental/issue-42602.rs | 45 + src/test/incremental/krate-inlined.rs | 14 +- .../incremental/remapped_paths_cc/main.rs | 4 - .../incremental/spans_in_type_debuginfo.rs | 63 + src/test/incremental/string_constant.rs | 3 - src/test/mir-opt/README.md | 27 +- src/test/mir-opt/basic_assignment.rs | 22 +- src/test/mir-opt/end_region_1.rs | 38 + src/test/mir-opt/end_region_2.rs | 66 + src/test/mir-opt/end_region_3.rs | 69 + src/test/mir-opt/end_region_4.rs | 75 + src/test/mir-opt/end_region_5.rs | 80 + src/test/mir-opt/end_region_6.rs | 83 + src/test/mir-opt/end_region_7.rs | 97 + src/test/mir-opt/end_region_8.rs | 86 + src/test/mir-opt/end_region_9.rs | 85 + src/test/parse-fail/macro-keyword.rs | 2 +- .../type-parameters-in-field-exprs.rs | 2 +- .../underscore-suffix-for-string.rs | 20 + src/test/run-fail/assert-eq-macro-panic.rs | 4 +- .../assert-ne-macro-panic.rs} | 18 +- src/test/run-make/llvm-phase/test.rs | 2 +- src/test/run-make/no-duplicate-libs/Makefile | 4 +- .../no-duplicate-libs/bar.c} | 11 +- src/test/run-make/no-duplicate-libs/foo.c | 11 + src/test/run-make/no-duplicate-libs/main.rs | 6 +- src/test/run-make/profile/Makefile | 9 + src/test/run-make/profile/test.rs | 11 + .../run-make/rustdoc-output-path/Makefile | 4 + src/test/run-make/rustdoc-output-path/foo.rs | 11 + .../run-make/sanitizer-address/overflow.rs | 2 +- .../run-make/sanitizer-cdylib-link/Makefile | 19 + .../run-make/sanitizer-cdylib-link/library.rs | 15 + .../run-make/sanitizer-cdylib-link/program.rs | 17 + .../run-make/sanitizer-dylib-link/Makefile | 19 + .../run-make/sanitizer-dylib-link/library.rs | 15 + .../run-make/sanitizer-dylib-link/program.rs | 17 + src/test/run-make/sanitizer-dylib/Makefile | 8 - .../sanitizer-invalid-cratetype/Makefile | 18 + .../hello.rs | 0 .../sanitizer-staticlib-link/Makefile | 18 + .../sanitizer-staticlib-link/library.rs | 15 + .../sanitizer-staticlib-link/program.c | 8 + src/test/run-make/save-analysis-fail/foo.rs | 2 - src/test/run-make/save-analysis/Makefile | 1 - src/test/run-make/save-analysis/foo.rs | 2 - .../type-mismatch-same-crate-name/Makefile | 19 + .../type-mismatch-same-crate-name/crateA.rs | 26 + .../type-mismatch-same-crate-name/crateB.rs | 14 + .../type-mismatch-same-crate-name/crateC.rs | 35 + src/test/run-make/windows-spawn/Makefile | 14 + src/test/run-make/windows-spawn/hello.rs | 13 + src/test/run-make/windows-spawn/spawn.rs | 22 + .../auxiliary/cond_plugin.rs | 43 +- .../auxiliary/hello_macro.rs | 23 +- .../auxiliary/proc_macro_def.rs | 50 +- .../auxiliary/procedural_mbe_matching.rs | 2 +- src/test/run-pass-fulldeps/issue-2804.rs | 2 - src/test/run-pass-fulldeps/macro-quote-1.rs | 40 - .../run-pass-fulldeps/macro-quote-cond.rs | 8 +- .../run-pass-fulldeps/macro-quote-test.rs | 8 +- .../proc-macro/auxiliary/attr-args.rs | 2 +- .../auxiliary/count_compound_ops.rs | 36 + .../proc-macro/auxiliary/hygiene_example.rs | 19 + .../auxiliary/hygiene_example_codegen.rs | 36 + .../proc-macro/count_compound_ops.rs | 20 + .../proc-macro/hygiene_example.rs | 27 + src/test/run-pass-fulldeps/proc_macro.rs | 7 +- .../run-pass-fulldeps/regions-mock-tcx.rs | 3 +- src/test/run-pass-fulldeps/stdio-from.rs | 83 + .../dst-dtor-3.rs} | 33 +- src/test/run-pass-valgrind/dst-dtor-4.rs | 31 + src/test/run-pass/align-struct.rs | 19 + src/test/run-pass/allocator-alloc-one.rs | 24 + src/test/run-pass/allocator-override.rs | 29 - .../allocator/auxiliary/custom-as-global.rs | 27 + .../run-pass/allocator/auxiliary/custom.rs | 31 + .../allocator/auxiliary/helper.rs} | 11 +- src/test/run-pass/allocator/custom.rs | 68 + src/test/run-pass/allocator/xcrate-use.rs | 44 + src/test/run-pass/allocator/xcrate-use2.rs | 57 + src/test/run-pass/asm-concat-src.rs | 2 +- .../run-pass/associated-const-const-eval.rs | 1 - ...associated-const-cross-crate-const-eval.rs | 1 - .../associated-const-cross-crate-defaults.rs | 1 - .../run-pass/associated-const-cross-crate.rs | 1 - .../associated-const-in-global-const.rs | 1 - .../associated-const-inherent-impl.rs | 1 - .../associated-const-marks-live-code.rs | 1 - .../associated-const-match-patterns.rs | 1 - .../associated-const-outer-ty-refs.rs | 1 - .../associated-const-overwrite-default.rs | 1 - .../run-pass/associated-const-public-impl.rs | 1 - .../associated-const-range-match-patterns.rs | 1 - .../associated-const-resolution-order.rs | 1 - .../run-pass/associated-const-self-type.rs | 1 - .../associated-const-type-parameters.rs | 1 - .../associated-const-ufcs-infer-trait.rs | 1 - .../run-pass/associated-const-use-default.rs | 1 - ...associated-const-use-impl-of-same-trait.rs | 1 - src/test/run-pass/associated-const.rs | 1 - ...ociated-types-projection-in-object-type.rs | 2 +- .../run-pass/associated-types-sugar-path.rs | 2 - .../run-pass/auxiliary/allocator-dummy.rs | 21 +- .../auxiliary/associated-const-cc-lib.rs | 1 - .../run-pass/auxiliary/issue_3979_traits.rs | 2 +- .../auxiliary/xcrate-trait-lifetime-param.rs | 2 +- src/test/run-pass/conditional-compile-arch.rs | 3 + src/test/run-pass/deriving-hash.rs | 13 +- .../run-pass/drop-with-type-ascription-2.rs | 2 - src/test/run-pass/dropck_legal_cycles.rs | 8 +- src/test/run-pass/dst-irrefutable-bind.rs | 12 + src/test/run-pass/dst-raw.rs | 34 + src/test/run-pass/dst-trait-tuple.rs | 111 + src/test/run-pass/dst-tuple-sole.rs | 85 + src/test/run-pass/dst-tuple.rs | 129 + src/test/run-pass/dynamic-drop.rs | 15 + src/test/run-pass/env.rs | 98 + src/test/run-pass/for-loop-no-std.rs | 4 +- ...xternal-iterators-hashmap-break-restart.rs | 4 - .../foreach-external-iterators-hashmap.rs | 4 - src/test/run-pass/format-no-std.rs | 6 +- src/test/run-pass/getopts_ref.rs | 28 - src/test/run-pass/i128-ffi.rs | 7 +- src/test/run-pass/i128.rs | 4 + .../run-pass/impl-trait/example-calendar.rs | 18 +- src/test/run-pass/intrinsics-integer.rs | 37 + src/test/run-pass/issue-12860.rs | 4 - src/test/run-pass/issue-13105.rs | 1 + src/test/run-pass/issue-13775.rs | 1 + src/test/run-pass/issue-14919.rs | 2 +- src/test/run-pass/issue-1696.rs | 4 - src/test/run-pass/issue-19098.rs | 2 +- .../run-pass/issue-19811-escape-unicode.rs | 2 - src/test/run-pass/issue-21726.rs | 2 +- src/test/run-pass/issue-23808.rs | 1 - src/test/run-pass/issue-2383.rs | 3 - src/test/run-pass/issue-24947.rs | 1 - src/test/run-pass/issue-25145.rs | 1 - src/test/run-pass/issue-26095.rs | 1 - src/test/run-pass/issue-27859.rs | 2 + src/test/run-pass/issue-2804-2.rs | 4 - src/test/run-pass/issue-3026.rs | 5 +- src/test/run-pass/issue-30490.rs | 4 +- src/test/run-pass/issue-31260.rs | 5 +- src/test/run-pass/issue-31267-additional.rs | 1 - src/test/run-pass/issue-31267.rs | 1 - src/test/run-pass/issue-34074.rs | 3 +- src/test/run-pass/issue-3559.rs | 4 - src/test/run-pass/issue-37725.rs | 14 + src/test/run-pass/issue-3979-generics.rs | 2 +- src/test/run-pass/issue-3979.rs | 2 +- src/test/run-pass/issue-40136.rs | 1 - .../issue-40847.rs} | 20 +- src/test/run-pass/issue-40883.rs | 102 + src/test/run-pass/issue-4107.rs | 2 +- src/test/run-pass/issue-41696.rs | 1 - src/test/run-pass/issue-42679.rs | 31 + src/test/run-pass/issue-42747.rs | 55 + src/test/run-pass/issue-43057.rs | 23 + src/test/run-pass/issue-43923.rs | 19 + src/test/run-pass/issue-6128.rs | 10 +- src/test/run-pass/issue-6157.rs | 2 +- src/test/run-pass/issue-7660.rs | 4 - src/test/run-pass/issue-9129.rs | 2 +- src/test/run-pass/istr.rs | 2 - src/test/run-pass/lib-defaults.rs | 9 +- src/test/run-pass/linkage1.rs | 8 +- src/test/run-pass/macro-first-set.rs | 245 + src/test/run-pass/macro-pat-neg-lit.rs | 35 + src/test/run-pass/new-unicode-escapes.rs | 2 - src/test/run-pass/option-ext.rs | 2 - src/test/run-pass/out-of-stack.rs | 2 +- src/test/run-pass/overloaded-autoderef.rs | 2 +- src/test/run-pass/overloaded-deref.rs | 2 - src/test/run-pass/range_inclusive.rs | 2 +- src/test/run-pass/realloc-16687.rs | 75 +- .../regions-early-bound-trait-param.rs | 2 +- src/test/run-pass/rfc1717/library-override.rs | 7 +- src/test/run-pass/rfc1857-drop-order.rs | 231 + .../rustc-rust-log.rs} | 4 +- src/test/run-pass/smallest-hello-world.rs | 35 +- src/test/run-pass/stack-probes-lto.rs | 20 + src/test/run-pass/stack-probes.rs | 68 + .../run-pass/supertrait-default-generics.rs | 2 +- .../sync-send-iterators-in-libcollections.rs | 15 +- .../sync-send-iterators-in-libcore.rs | 2 +- src/test/run-pass/test-allow-fail-attr.rs | 24 + .../run-pass/thread-local-extern-static.rs | 4 +- src/test/run-pass/thread-local-syntax.rs | 22 +- src/test/run-pass/tls-try-with.rs | 37 + src/test/run-pass/trait-inheritance-static.rs | 2 +- .../run-pass/trait-inheritance-static2.rs | 2 +- src/test/run-pass/trait-object-generics.rs | 2 +- src/test/run-pass/u128.rs | 4 + src/test/run-pass/unsized-tuple-impls.rs | 29 + src/test/run-pass/utf8_chars.rs | 2 +- src/test/run-pass/vec-macro-no-std.rs | 8 +- src/test/run-pass/vector-sort-panic-safe.rs | 168 +- src/test/run-pass/weird-exprs.rs | 33 + .../where-clause-bounds-inconsistency.rs | 8 +- src/test/run-pass/while-prelude-drop.rs | 2 - src/test/rustdoc/assoc-consts.rs | 80 +- src/test/rustdoc/assoc-types.rs | 7 + src/test/rustdoc/auxiliary/issue-36031.rs | 1 - src/test/rustdoc/const-doc.rs | 1 - src/test/rustdoc/empty-mod-private.rs | 27 + src/test/rustdoc/empty-mod-public.rs | 24 + src/test/rustdoc/issue-28478.rs | 1 - src/test/rustdoc/issue-31808.rs | 2 - src/test/rustdoc/issue-33302.rs | 1 - src/test/rustdoc/issue-35169-2.rs | 6 + src/test/rustdoc/issue-35169.rs | 6 + src/test/rustdoc/issue-35488.rs | 23 + src/test/rustdoc/issue-42875.rs | 23 + .../issue-43153.rs} | 21 +- src/test/rustdoc/typedef.rs | 35 + .../ui-fulldeps/auxiliary/attr_proc_macro.rs | 23 + .../ui-fulldeps/auxiliary/bang_proc_macro.rs | 23 + .../ui-fulldeps/auxiliary/derive-clona.rs | 23 + src/test/ui-fulldeps/auxiliary/derive-foo.rs | 23 + .../resolve-error.rs | 17 - src/test/ui-fulldeps/resolve-error.stderr | 62 + src/test/ui/README.md | 31 - .../block-must-not-have-result-do.rs | 0 .../block-must-not-have-result-do.stderr | 11 + .../block-must-not-have-result-res.rs | 0 .../block-must-not-have-result-res.stderr | 11 + .../block-must-not-have-result-while.rs | 0 .../block-must-not-have-result-while.stderr | 11 + .../consider-removing-last-semi.rs | 0 .../consider-removing-last-semi.stderr | 30 + .../block-result}/issue-11714.rs | 0 src/test/ui/block-result/issue-11714.stderr | 17 + .../block-result}/issue-13428.rs | 0 src/test/ui/block-result/issue-13428.stderr | 33 + .../block-result}/issue-13624.rs | 0 src/test/ui/block-result/issue-13624.stderr | 20 + .../block-result}/issue-20862.rs | 0 src/test/ui/block-result/issue-20862.stderr | 19 + .../block-result}/issue-22645.rs | 0 src/test/ui/block-result/issue-22645.stderr | 21 + .../block-result}/issue-3563.rs | 0 src/test/ui/block-result/issue-3563.stderr | 19 + .../block-result}/issue-5500.rs | 0 src/test/ui/block-result/issue-5500.stderr | 11 + .../block-result/unexpected-return-on-unit.rs | 24 + .../unexpected-return-on-unit.stderr | 19 + .../ui/borrowck/borrowck-in-static.stderr | 2 +- ...ove-upvar-from-non-once-ref-closure.stderr | 2 +- ...ast-to-unsized-trait-object-suggestion.rs} | 6 +- ...-to-unsized-trait-object-suggestion.stderr | 18 + src/test/ui/check_match/issue-35609.stderr | 2 +- src/test/ui/check_match/issue-43253.rs | 51 + src/test/ui/check_match/issue-43253.stderr | 20 + .../ui/closure_context/issue-26046-fn-mut.rs | 21 + .../closure_context/issue-26046-fn-mut.stderr | 20 + .../closure_context/issue-26046-fn-once.rs} | 14 +- .../issue-26046-fn-once.stderr | 20 + .../issue-42065.rs} | 0 .../issue-42065.stderr} | 6 +- .../ui/codemap_tests/bad-format-args.stderr | 2 +- ...nce-overlapping-inherent-impl-trait.stderr | 2 +- src/test/ui/codemap_tests/empty_span.stderr | 2 +- .../huge_multispan_highlight.stderr | 2 +- src/test/ui/codemap_tests/issue-11715.stderr | 2 +- src/test/ui/codemap_tests/issue-28308.stderr | 2 +- src/test/ui/codemap_tests/one_line.stderr | 2 +- .../overlapping_inherent_impls.stderr | 2 +- .../ui/codemap_tests/overlapping_spans.stderr | 2 +- src/test/ui/codemap_tests/tab.stderr | 2 +- src/test/ui/codemap_tests/unicode.stderr | 2 +- .../ui/coercion-missing-tail-expected-type.rs | 4 + ...coercion-missing-tail-expected-type.stderr | 19 +- .../ui/compare-method/proj-outlives-region.rs | 3 - .../proj-outlives-region.stderr | 8 +- .../ui/compare-method/region-extra-2.stderr | 2 +- src/test/ui/compare-method/region-extra.rs | 3 - .../ui/compare-method/region-extra.stderr | 8 +- .../ui/compare-method/region-unrelated.rs | 3 - .../ui/compare-method/region-unrelated.stderr | 8 +- .../reordered-type-param.stderr | 2 +- .../trait-bound-on-type-parameter.stderr | 2 +- .../traits-misc-mismatch-1.stderr | 2 +- .../traits-misc-mismatch-2.stderr | 2 +- .../cross-crate-macro-backtrace/main.stderr | 2 +- src/test/ui/did_you_mean/E0178.stderr | 2 +- ...e-21659-show-relevant-trait-impls-1.stderr | 2 +- ...e-21659-show-relevant-trait-impls-2.stderr | 2 +- src/test/ui/did_you_mean/issue-31424.stderr | 2 +- src/test/ui/did_you_mean/issue-34126.stderr | 2 +- src/test/ui/did_you_mean/issue-34337.stderr | 2 +- src/test/ui/did_you_mean/issue-35937.stderr | 2 +- src/test/ui/did_you_mean/issue-36798.stderr | 4 +- .../issue-36798_unknown_field.stderr | 4 +- src/test/ui/did_you_mean/issue-37139.stderr | 2 +- ...-38054-do-not-show-unresolved-names.stderr | 2 +- src/test/ui/did_you_mean/issue-38147-1.stderr | 2 +- src/test/ui/did_you_mean/issue-38147-2.stderr | 2 +- src/test/ui/did_you_mean/issue-38147-3.stderr | 2 +- src/test/ui/did_you_mean/issue-38147-4.stderr | 2 +- src/test/ui/did_you_mean/issue-39544.stderr | 2 +- .../issue-39802-show-5-trait-impls.stderr | 2 +- src/test/ui/did_you_mean/issue-40006.stderr | 2 +- src/test/ui/did_you_mean/issue-40396.stderr | 2 +- src/test/ui/did_you_mean/issue-40823.stderr | 2 +- src/test/ui/did_you_mean/issue-41679.stderr | 2 +- .../ui/did_you_mean/recursion_limit.stderr | 2 +- .../did_you_mean/recursion_limit_deref.stderr | 2 +- ...reference-without-parens-suggestion.stderr | 2 +- .../dropck-eyepatch-extern-crate.stderr | 2 +- ...dropck-eyepatch-implies-unsafe-impl.stderr | 2 +- .../ui/dropck/dropck-eyepatch-reorder.stderr | 2 +- src/test/ui/dropck/dropck-eyepatch.stderr | 2 +- src/test/ui/enum-size-variance.rs | 18 +- src/test/ui/enum-size-variance.stderr | 10 +- src/test/ui/explain.rs | 11 + src/test/ui/explain.stdout | 63 + src/test/ui/fmt/format-string-error.stderr | 2 +- src/test/ui/impl-trait/equality.stderr | 2 +- ...e-21659-show-relevant-trait-impls-3.stderr | 2 +- .../method-suggestion-no-duplication.stderr | 2 +- .../no-method-suggested-traits.stderr | 2 +- src/test/ui/impl-trait/trait_type.stderr | 2 +- .../interior-mutability.rs | 16 + .../interior-mutability.stderr | 14 + .../invalid-module-declaration.stderr | 2 +- src/test/ui/issue-22644.rs | 39 + src/test/ui/issue-22644.stderr | 104 + src/test/ui/issue-26548.stderr | 2 +- src/test/ui/issue-33525.rs | 15 + src/test/ui/issue-33525.stderr | 20 + src/test/ui/issue-35675.rs | 51 + src/test/ui/issue-35675.stderr | 51 + .../issue-37311.stderr | 2 +- .../ui/issue-38875/auxiliary/issue_38875_b.rs | 11 + src/test/ui/issue-38875/issue_38875.rs | 17 + src/test/ui/issue-38875/issue_38875.stderr | 14 + .../issue-40402-1.stderr | 4 +- .../issue-40402-2.stderr | 2 +- src/test/ui/issue-41652/issue_41652.stderr | 7 +- src/test/ui/issue-42954.rs | 20 + src/test/ui/issue-42954.stderr | 18 + .../ex1-return-one-existing-name-if-else-2.rs | 15 + ...-return-one-existing-name-if-else-2.stderr | 10 + .../ex1-return-one-existing-name-if-else-3.rs | 15 + ...-return-one-existing-name-if-else-3.stderr | 10 + ...-one-existing-name-if-else-using-impl-2.rs | 18 + ...-existing-name-if-else-using-impl-2.stderr | 10 + ...-one-existing-name-if-else-using-impl-3.rs | 24 + ...-existing-name-if-else-using-impl-3.stderr | 11 + ...rn-one-existing-name-if-else-using-impl.rs | 27 + ...ne-existing-name-if-else-using-impl.stderr | 27 + ...x1-return-one-existing-name-if-else.stderr | 23 +- ...n-one-existing-name-return-type-is-anon.rs | 24 + ...e-existing-name-return-type-is-anon.stderr | 27 + ...1-return-one-existing-name-self-is-anon.rs | 23 + ...turn-one-existing-name-self-is-anon.stderr | 27 + .../ex1b-return-no-names-if-else.stderr | 2 +- .../ex2a-push-one-existing-name-2.rs | 19 + .../ex2a-push-one-existing-name-2.stderr | 10 + .../ex2a-push-one-existing-name.stderr | 25 +- .../ex2b-push-no-existing-names.stderr | 2 +- .../ex2c-push-inference-variable.stderr | 2 +- .../ex2d-push-inference-variable-2.stderr | 2 +- .../ex2e-push-inference-variable-3.stderr | 2 +- .../lifetimes/borrowck-let-suggestion.stderr | 2 +- .../lint/command-line-lint-group-deny.stderr | 2 +- .../command-line-lint-group-forbid.stderr | 2 +- src/test/ui/lint/lint-group-style.stderr | 12 +- src/test/ui/lint/outer-forbid.rs | 22 + src/test/ui/lint/outer-forbid.stderr | 29 + src/test/ui/loop-break-value-no-repeat.stderr | 2 +- src/test/ui/macros/bad_hello.stderr | 2 +- src/test/ui/macros/format-foreign.stderr | 2 +- .../macro-backtrace-invalid-internals.stderr | 10 +- .../ui/macros/macro-backtrace-nested.stderr | 2 +- .../ui/macros/macro-backtrace-println.stderr | 2 +- .../macros}/macro-name-typo.rs | 2 - src/test/ui/macros/macro-name-typo.stderr | 8 + .../macros}/macro_undefined.rs | 4 - src/test/ui/macros/macro_undefined.stderr | 16 + src/test/ui/mismatched_types/E0053.stderr | 2 +- src/test/ui/mismatched_types/E0281.stderr | 13 +- src/test/ui/mismatched_types/E0409.stderr | 2 +- src/test/ui/mismatched_types/abridged.rs | 10 +- src/test/ui/mismatched_types/abridged.stderr | 26 +- src/test/ui/mismatched_types/binops.stderr | 10 +- .../ui/mismatched_types/cast-rfc0401.stderr | 72 +- .../mismatched_types/closure-arg-count.stderr | 26 +- .../mismatched_types/closure-mismatch.stderr | 2 +- .../mismatched_types/const-fn-in-trait.stderr | 2 +- .../ui/mismatched_types/fn-variance-1.stderr | 2 +- .../for-loop-has-unit-body.rs | 0 .../for-loop-has-unit-body.stderr | 11 + .../ui/mismatched_types/issue-19109.stderr | 4 +- .../ui/mismatched_types/issue-26480.stderr | 6 +- .../ui/mismatched_types/issue-35030.stderr | 2 +- .../ui/mismatched_types/issue-36053-2.stderr | 11 +- .../ui/mismatched_types/issue-38371.stderr | 2 +- src/test/ui/mismatched_types/main.stderr | 2 +- .../method-help-unsatisfied-bound.stderr | 2 +- .../overloaded-calls-bad.stderr | 2 +- .../trait-bounds-cant-coerce.stderr | 2 +- .../trait-impl-fn-incompatibility.stderr | 2 +- .../unboxed-closures-vtable-mismatch.rs | 1 - .../unboxed-closures-vtable-mismatch.stderr | 16 +- src/test/ui/missing-items/auxiliary/m1.rs | 1 - src/test/ui/missing-items/issue-40221.stderr | 2 +- src/test/ui/missing-items/m2.rs | 1 - src/test/ui/missing-items/m2.stderr | 8 +- .../missing-type-parameter.stderr | 2 +- .../on-unimplemented/bad-annotation.rs | 0 .../ui/on-unimplemented/bad-annotation.stderr | 22 + .../on-unimplemented/multiple-impls.rs | 6 + .../ui/on-unimplemented/multiple-impls.stderr | 53 + .../on-unimplemented/on-impl.rs | 2 + src/test/ui/on-unimplemented/on-impl.stderr | 19 + .../on-unimplemented/on-trait.rs | 9 +- src/test/ui/on-unimplemented/on-trait.stderr | 20 + .../on-unimplemented/slice-index.rs | 0 .../ui/on-unimplemented/slice-index.stderr | 20 + src/test/ui/path-lookahead.stderr | 2 - .../ui/pub/pub-restricted-error-fn.stderr | 2 +- src/test/ui/pub/pub-restricted-error.stderr | 2 +- .../ui/pub/pub-restricted-non-path.stderr | 2 +- src/test/ui/pub/pub-restricted.stderr | 2 +- src/test/ui/reachable/expr_add.stderr | 2 +- src/test/ui/reachable/expr_again.stderr | 2 +- src/test/ui/reachable/expr_array.stderr | 2 +- src/test/ui/reachable/expr_assign.stderr | 2 +- src/test/ui/reachable/expr_block.stderr | 2 +- src/test/ui/reachable/expr_box.stderr | 2 +- src/test/ui/reachable/expr_call.stderr | 2 +- src/test/ui/reachable/expr_cast.stderr | 2 +- src/test/ui/reachable/expr_if.stderr | 2 +- src/test/ui/reachable/expr_loop.stderr | 2 +- src/test/ui/reachable/expr_match.stderr | 2 +- src/test/ui/reachable/expr_method.stderr | 2 +- src/test/ui/reachable/expr_repeat.stderr | 2 +- src/test/ui/reachable/expr_return.stderr | 2 +- src/test/ui/reachable/expr_struct.stderr | 2 +- src/test/ui/reachable/expr_tup.stderr | 2 +- src/test/ui/reachable/expr_type.stderr | 2 +- src/test/ui/reachable/expr_unary.stderr | 2 +- src/test/ui/reachable/expr_while.stderr | 2 +- .../regions-fn-subtyping-return-static.stderr | 2 +- src/test/ui/resolve-error.stderr | 62 + .../ui/resolve/enums-are-namespaced-xc.stderr | 14 +- src/test/ui/resolve/issue-14254.stderr | 40 +- src/test/ui/resolve/issue-16058.stderr | 12 +- src/test/ui/resolve/issue-17518.stderr | 6 +- src/test/ui/resolve/issue-18252.stderr | 2 +- src/test/ui/resolve/issue-19452.stderr | 2 +- src/test/ui/resolve/issue-21221-1.stderr | 27 +- src/test/ui/resolve/issue-21221-2.stderr | 4 +- src/test/ui/resolve/issue-21221-3.stderr | 4 +- src/test/ui/resolve/issue-21221-4.stderr | 4 +- src/test/ui/resolve/issue-23305.stderr | 2 +- src/test/ui/resolve/issue-2356.stderr | 14 +- src/test/ui/resolve/issue-24968.stderr | 2 +- src/test/ui/resolve/issue-33876.stderr | 2 +- src/test/ui/resolve/issue-3907-2.stderr | 2 +- src/test/ui/resolve/issue-3907.stderr | 4 +- src/test/ui/resolve/issue-39226.stderr | 2 +- src/test/ui/resolve/issue-5035-2.stderr | 2 +- src/test/ui/resolve/issue-6702.stderr | 2 +- src/test/ui/resolve/levenshtein.stderr | 2 +- .../ui/resolve/privacy-struct-ctor.stderr | 14 +- .../resolve/resolve-assoc-suggestions.stderr | 8 +- src/test/ui/resolve/resolve-hint-macro.stderr | 2 +- .../resolve-speculative-adjustment.stderr | 6 +- ...uggest-path-instead-of-mod-dot-item.stderr | 2 +- .../ui/resolve/token-error-correct-2.stderr | 2 +- .../ui/resolve/token-error-correct-3.stderr | 6 +- .../ui/resolve/token-error-correct.stderr | 2 +- src/test/ui/resolve/tuple-struct-alias.stderr | 2 +- .../unresolved_static_type_field.stderr | 4 +- .../shadowed-type-parameter.rs | 0 src/test/ui/shadowed-type-parameter.stderr | 28 + src/test/ui/span/E0046.stderr | 2 +- src/test/ui/span/E0057.stderr | 2 +- src/test/ui/span/E0072.stderr | 2 +- src/test/ui/span/E0204.stderr | 2 +- src/test/ui/span/E0493.stderr | 2 +- src/test/ui/span/E0535.stderr | 2 +- src/test/ui/span/E0536.stderr | 2 +- src/test/ui/span/E0537.stderr | 2 +- ...ck-borrow-overloaded-auto-deref-mut.stderr | 2 +- ...orrowck-borrow-overloaded-deref-mut.stderr | 2 +- ...borrowck-call-is-borrow-issue-12224.stderr | 2 +- ...owck-call-method-from-mut-aliasable.stderr | 2 +- .../ui/span/borrowck-fn-in-const-b.stderr | 2 +- .../borrowck-let-suggestion-suffixes.stderr | 2 +- .../ui/span/borrowck-object-mutability.stderr | 2 +- .../ui/span/borrowck-ref-into-rvalue.stderr | 2 +- src/test/ui/span/coerce-suggestions.stderr | 2 +- .../ui/span/destructor-restrictions.stderr | 2 +- src/test/ui/span/dropck-object-cycle.stderr | 2 +- .../ui/span/dropck_arr_cycle_checked.stderr | 2 +- .../span/dropck_direct_cycle_with_drop.stderr | 2 +- src/test/ui/span/dropck_misc_variants.stderr | 2 +- .../ui/span/dropck_vec_cycle_checked.stderr | 2 +- src/test/ui/span/impl-wrong-item-for-trait.rs | 1 - .../ui/span/impl-wrong-item-for-trait.stderr | 78 +- src/test/ui/span/issue-11925.stderr | 2 +- src/test/ui/span/issue-15480.stderr | 2 +- ...338-locals-die-before-temps-of-body.stderr | 2 +- src/test/ui/span/issue-23729.stderr | 2 +- src/test/ui/span/issue-23827.stderr | 2 +- src/test/ui/span/issue-24356.stderr | 2 +- src/test/ui/span/issue-24690.stderr | 8 +- ...5-dropck-child-has-items-via-parent.stderr | 2 +- .../issue-24805-dropck-trait-has-items.stderr | 2 +- .../span/issue-24895-copy-clone-dropck.stderr | 2 +- src/test/ui/span/issue-25199.stderr | 2 +- src/test/ui/span/issue-26656.stderr | 2 +- src/test/ui/span/issue-27522.stderr | 2 +- src/test/ui/span/issue-29106.stderr | 2 +- src/test/ui/span/issue-29595.rs | 1 - src/test/ui/span/issue-29595.stderr | 6 +- src/test/ui/span/issue-33884.stderr | 2 +- src/test/ui/span/issue-34264.stderr | 2 +- src/test/ui/span/issue-35987.stderr | 4 +- src/test/ui/span/issue-36530.stderr | 2 +- src/test/ui/span/issue-36537.stderr | 2 +- src/test/ui/span/issue-37767.stderr | 2 +- src/test/ui/span/issue-39018.stderr | 8 +- src/test/ui/span/issue-39698.stderr | 2 +- src/test/ui/span/issue-40157.stderr | 2 +- src/test/ui/span/issue-7575.rs | 8 +- src/test/ui/span/issue-7575.stderr | 14 +- src/test/ui/span/issue28498-reject-ex1.stderr | 2 +- .../issue28498-reject-lifetime-param.stderr | 2 +- .../issue28498-reject-passed-to-fn.stderr | 2 +- .../span/issue28498-reject-trait-bound.stderr | 2 +- src/test/ui/span/lint-unused-unsafe.stderr | 2 +- src/test/ui/span/loan-extend.stderr | 2 +- src/test/ui/span/move-closure.stderr | 2 +- src/test/ui/span/multiline-span-E0072.stderr | 2 +- src/test/ui/span/multiline-span-simple.stderr | 2 +- src/test/ui/span/mut-arg-hint.stderr | 2 +- .../ui/span/mut-ptr-cant-outlive-ref.stderr | 2 +- src/test/ui/span/pub-struct-field.stderr | 2 +- src/test/ui/span/range-2.stderr | 2 +- src/test/ui/span/recursive-type-field.stderr | 2 +- .../regionck-unboxed-closure-lifetimes.stderr | 2 +- ...ions-close-over-borrowed-ref-in-obj.stderr | 2 +- ...regions-close-over-type-parameter-2.stderr | 2 +- .../regions-escape-loop-via-variable.stderr | 2 +- .../span/regions-escape-loop-via-vec.stderr | 2 +- ...ions-infer-borrow-scope-within-loop.stderr | 2 +- .../send-is-not-static-ensures-scoping.stderr | 2 +- .../span/send-is-not-static-std-sync-2.stderr | 2 +- .../span/send-is-not-static-std-sync.stderr | 2 +- src/test/ui/span/slice-borrow.stderr | 2 +- src/test/ui/span/suggestion-non-ascii.stderr | 6 +- src/test/ui/span/type-binding.stderr | 2 +- src/test/ui/span/typo-suggestion.stderr | 2 +- .../vec-must-not-hide-type-from-dropck.stderr | 2 +- .../vec_refs_data_with_early_death.stderr | 2 +- .../span/wf-method-late-bound-regions.stderr | 2 +- src/test/ui/static-lifetime.stderr | 2 +- .../issue-18343.stderr | 2 +- .../issue-2392.stderr | 2 +- .../issue-32128.stderr | 2 +- .../issue-33784.stderr | 2 +- .../private-field.stderr | 2 +- .../ui/suggestions/try-operator-on-main.rs | 13 + .../suggestions/try-operator-on-main.stderr | 14 + .../ui/suggestions/tuple-float-index.stderr | 4 +- src/test/ui/token/bounds-obj-parens.stderr | 2 +- src/test/ui/token/issue-10636-2.stderr | 2 +- src/test/ui/token/issue-41155.stderr | 2 +- src/test/ui/token/macro-incomplete-parse.rs | 2 +- .../ui/token/macro-incomplete-parse.stderr | 5 +- .../ui/token/trailing-plus-in-bounds.stderr | 2 +- src/test/ui/transmute/main.rs | 42 + src/test/ui/transmute/main.stderr | 38 + .../transmute-from-fn-item-types-error.rs | 6 +- .../transmute-from-fn-item-types-error.stderr | 90 + .../transmute}/transmute-type-parameters.rs | 31 +- .../transmute-type-parameters.stderr | 56 + .../type-check/assignment-in-if.rs} | 22 +- .../ui/type-check/assignment-in-if.stderr | 59 + .../cannot_infer_local_or_array.stderr | 2 +- .../cannot_infer_local_or_vec.stderr | 2 +- ...cannot_infer_local_or_vec_in_tuples.stderr | 2 +- src/test/ui/type-check/issue-22897.stderr | 2 +- src/test/ui/type-check/issue-40294.stderr | 8 +- .../unknown_type_for_closure.stderr | 2 +- src/tools/build-manifest/src/main.rs | 5 + src/tools/compiletest/Cargo.toml | 8 +- src/tools/compiletest/src/common.rs | 3 + src/tools/compiletest/src/errors.rs | 6 +- src/tools/compiletest/src/header.rs | 141 +- src/tools/compiletest/src/json.rs | 2 +- src/tools/compiletest/src/main.rs | 125 +- src/tools/compiletest/src/procsrv.rs | 3 +- src/tools/compiletest/src/runtest.rs | 129 +- src/tools/compiletest/src/util.rs | 8 + src/tools/linkchecker/main.rs | 10 +- .../test/rust-installer-v1/README.md | 30 + .../rust-installer-v1/gen-install-script.sh | 253 + .../test/rust-installer-v1/gen-installer.sh | 303 ++ .../rust-installer-v1/install-template.sh | 554 ++ .../test/rust-installer-v2/.travis.yml | 2 + .../test/rust-installer-v2/README.md | 74 + .../rust-installer-v2/combine-installers.sh | 347 ++ .../rust-installer-v2/gen-install-script.sh | 261 + .../test/rust-installer-v2/gen-installer.sh | 332 ++ .../rust-installer-v2/install-template.sh | 743 +++ .../rust-installer-v2/rust-installer-version | 1 + .../test/rust-installer-v2/test.sh | 588 ++ .../rust-installer-v2/test/image1/bin/bad-bin | 1 + .../rust-installer-v2/test/image1/bin/program | 1 + .../test/image1/bin/program2 | 1 + .../test/image1/dir-to-install/foo} | 0 .../test/image1/dir-to-not-install/foo} | 0 .../test/image1/something-to-install} | 0 .../test/image1/something-to-not-install} | 0 .../test/image2/bin/oldprogram | 1 + .../test/image2/dir-to-install/bar} | 0 .../test/image2/something-to-install} | 0 .../rust-installer-v2/test/image3/bin/cargo | 1 + .../test/rust-installer-v2/test/image4/baz} | 0 .../test/image4/dir-to-install/qux/bar} | 0 .../test/image5/dir-to-install/foo} | 0 .../test/rust-installer-v1/README.md | 30 + .../rust-installer-v1/gen-install-script.sh | 253 + .../test/rust-installer-v1/gen-installer.sh | 303 ++ .../rust-installer-v1/install-template.sh | 554 ++ src/tools/rustbook/Cargo.toml | 4 +- src/tools/tidy/src/cargo.rs | 8 - src/tools/tidy/src/deps.rs | 1 - src/tools/tidy/src/features.rs | 149 +- src/tools/tidy/src/lib.rs | 89 + src/tools/tidy/src/main.rs | 80 +- src/tools/tidy/src/style.rs | 22 +- src/tools/tidy/src/unstable_book.rs | 85 +- src/tools/unstable-book-gen/Cargo.toml | 9 + src/tools/unstable-book-gen/src/SUMMARY.md | 8 + src/tools/unstable-book-gen/src/main.rs | 148 + src/tools/unstable-book-gen/src/stub-issue.md | 7 + .../unstable-book-gen/src/stub-no-issue.md | 5 + src/vendor/atty/.cargo-checksum.json | 1 + src/vendor/{toml-0.3.2 => atty}/.cargo-ok | 0 src/vendor/atty/.gitignore | 3 + src/vendor/atty/.travis.yml | 44 + src/vendor/atty/CHANGELOG.md | 25 + src/vendor/atty/Cargo.toml | 17 + src/vendor/atty/LICENSE | 20 + src/vendor/atty/README.md | 78 + src/vendor/atty/appveyor.yml | 17 + src/vendor/atty/examples/atty.rs | 9 + src/vendor/atty/src/lib.rs | 183 + src/vendor/backtrace-sys/.cargo-checksum.json | 2 +- src/vendor/backtrace-sys/Cargo.toml | 2 +- src/vendor/backtrace-sys/build.rs | 8 +- src/vendor/backtrace/.cargo-checksum.json | 2 +- src/vendor/backtrace/.travis.yml | 18 +- src/vendor/backtrace/Cargo.toml | 27 +- src/vendor/backtrace/README.md | 5 +- src/vendor/backtrace/build.rs | 51 - src/vendor/backtrace/src/capture.rs | 27 +- src/vendor/backtrace/src/dylib.rs | 17 +- src/vendor/backtrace/src/lib.rs | 17 +- .../src/symbolize/coresymbolication.rs | 13 + .../backtrace/src/symbolize/libbacktrace.rs | 2 - src/vendor/backtrace/src/symbolize/mod.rs | 133 +- src/vendor/backtrace/tests/smoke.rs | 6 +- .../bitflags-0.5.0/.cargo-checksum.json | 1 - src/vendor/bitflags-0.5.0/.travis.yml | 30 - src/vendor/bitflags-0.5.0/Cargo.toml | 17 - src/vendor/bitflags-0.5.0/README.md | 25 - src/vendor/bitflags-0.5.0/src/lib.rs | 771 --- src/vendor/bitflags-0.5.0/tests/external.rs | 22 - .../bitflags-0.5.0/tests/external_no_std.rs | 24 - .../bitflags-0.7.0/.cargo-checksum.json | 1 - src/vendor/bitflags-0.7.0/.gitignore | 2 - src/vendor/bitflags-0.7.0/.travis.yml | 24 - src/vendor/bitflags-0.7.0/Cargo.toml | 13 - src/vendor/bitflags/.cargo-checksum.json | 1 + .../valid/empty.toml => bitflags/.cargo-ok} | 0 .../{bitflags-0.5.0 => bitflags}/.gitignore | 0 src/vendor/bitflags/.travis.yml | 29 + src/vendor/bitflags/Cargo.toml | 31 + src/vendor/bitflags/Cargo.toml.orig | 26 + .../LICENSE-APACHE | 0 .../{bitflags-0.5.0 => bitflags}/LICENSE-MIT | 0 .../{bitflags-0.7.0 => bitflags}/README.md | 4 +- src/vendor/bitflags/src/example_generated.rs | 16 + .../{bitflags-0.7.0 => bitflags}/src/lib.rs | 658 ++- .../bitflags/tests/conflicting_trait_impls.rs | 20 + .../tests/external.rs | 10 +- .../tests/external_no_std.rs | 10 +- src/vendor/bitflags/tests/i128_bitflags.rs | 30 + src/vendor/cfg-if/.cargo-checksum.json | 2 +- src/vendor/cfg-if/.travis.yml | 20 +- src/vendor/cfg-if/Cargo.toml | 2 +- .../{bitflags-0.7.0 => cfg-if}/LICENSE-APACHE | 0 src/vendor/{toml-0.3.2 => cfg-if}/LICENSE-MIT | 0 src/vendor/cfg-if/src/lib.rs | 34 +- src/vendor/clap/.appveyor.yml | 17 + src/vendor/clap/.cargo-checksum.json | 2 +- src/vendor/clap/.clog.toml | 4 +- src/vendor/clap/.github/CONTRIBUTING.md | 65 +- src/vendor/clap/.mention-bot | 9 + src/vendor/clap/.travis.yml | 2 +- src/vendor/clap/CHANGELOG.md | 358 ++ src/vendor/clap/CONTRIBUTORS.md | 67 +- src/vendor/clap/Cargo.toml | 149 +- src/vendor/clap/Cargo.toml.orig | 84 + src/vendor/clap/README.md | 186 +- src/vendor/clap/appveyor.yml | 12 - src/vendor/clap/clap-test.rs | 184 +- src/vendor/clap/justfile | 7 +- src/vendor/clap/src/app/help.rs | 455 +- src/vendor/clap/src/app/macros.rs | 199 +- src/vendor/clap/src/app/meta.rs | 51 +- src/vendor/clap/src/app/mod.rs | 368 +- src/vendor/clap/src/app/parser.rs | 2304 ++++---- src/vendor/clap/src/app/settings.rs | 298 +- src/vendor/clap/src/app/usage.rs | 439 ++ src/vendor/clap/src/app/validator.rs | 456 ++ src/vendor/clap/src/args/any_arg.rs | 14 +- src/vendor/clap/src/args/arg.rs | 1519 ++++-- src/vendor/clap/src/args/arg_builder/base.rs | 50 +- src/vendor/clap/src/args/arg_builder/flag.rs | 37 +- .../clap/src/args/arg_builder/option.rs | 64 +- .../clap/src/args/arg_builder/positional.rs | 81 +- .../clap/src/args/arg_builder/switched.rs | 11 +- .../clap/src/args/arg_builder/valued.rs | 37 +- src/vendor/clap/src/args/arg_matcher.rs | 52 +- src/vendor/clap/src/args/arg_matches.rs | 88 +- src/vendor/clap/src/args/group.rs | 9 +- src/vendor/clap/src/args/macros.rs | 64 +- src/vendor/clap/src/args/matched_arg.rs | 7 +- src/vendor/clap/src/args/mod.rs | 10 - src/vendor/clap/src/args/settings.rs | 52 +- src/vendor/clap/src/completions/bash.rs | 59 +- src/vendor/clap/src/completions/fish.rs | 4 + src/vendor/clap/src/completions/mod.rs | 23 +- src/vendor/clap/src/completions/powershell.rs | 34 +- src/vendor/clap/src/completions/zsh.rs | 54 +- src/vendor/clap/src/errors.rs | 176 +- src/vendor/clap/src/fmt.rs | 65 +- src/vendor/clap/src/lib.rs | 19 +- src/vendor/clap/src/macros.rs | 469 +- src/vendor/clap/src/osstringext.rs | 5 +- src/vendor/clap/src/suggestions.rs | 62 +- src/vendor/clap/src/usage_parser.rs | 934 ++-- src/vendor/cmake/.cargo-checksum.json | 2 +- src/vendor/cmake/Cargo.toml | 4 +- src/vendor/cmake/src/lib.rs | 58 +- src/vendor/cmake/src/registry.rs | 80 - src/vendor/crossbeam/.cargo-checksum.json | 1 + src/vendor/crossbeam/.cargo-ok | 0 src/vendor/crossbeam/.gitignore | 13 + src/vendor/crossbeam/.travis.yml | 36 + src/vendor/crossbeam/CHANGELOG.md | 11 + src/vendor/crossbeam/Cargo.toml | 15 + .../LICENSE-APACHE | 0 src/vendor/crossbeam/LICENSE-MIT | 25 + src/vendor/crossbeam/README.md | 38 + src/vendor/crossbeam/scala-bench/bench.scala | 195 + src/vendor/crossbeam/src/bin/bench.rs | 165 + .../crossbeam/src/bin/extra_impls/mod.rs | 1 + .../src/bin/extra_impls/mpsc_queue.rs | 155 + src/vendor/crossbeam/src/bin/stress-msq.rs | 36 + src/vendor/crossbeam/src/lib.rs | 54 + src/vendor/crossbeam/src/mem/cache_padded.rs | 149 + src/vendor/crossbeam/src/mem/epoch/atomic.rs | 181 + src/vendor/crossbeam/src/mem/epoch/garbage.rs | 144 + src/vendor/crossbeam/src/mem/epoch/global.rs | 95 + src/vendor/crossbeam/src/mem/epoch/guard.rs | 56 + src/vendor/crossbeam/src/mem/epoch/local.rs | 38 + src/vendor/crossbeam/src/mem/epoch/mod.rs | 265 + .../crossbeam/src/mem/epoch/participant.rs | 133 + .../crossbeam/src/mem/epoch/participants.rs | 120 + src/vendor/crossbeam/src/mem/mod.rs | 9 + src/vendor/crossbeam/src/scoped.rs | 275 + src/vendor/crossbeam/src/sync/arc_cell.rs | 90 + .../crossbeam/src/sync/atomic_option.rs | 38 + src/vendor/crossbeam/src/sync/chase_lev.rs | 602 +++ src/vendor/crossbeam/src/sync/mod.rs | 14 + src/vendor/crossbeam/src/sync/ms_queue.rs | 511 ++ src/vendor/crossbeam/src/sync/seg_queue.rs | 251 + .../crossbeam/src/sync/treiber_stack.rs | 98 + src/vendor/env_logger/.cargo-checksum.json | 2 +- src/vendor/env_logger/Cargo.toml | 35 +- src/vendor/env_logger/Cargo.toml.orig | 24 + src/vendor/env_logger/src/lib.rs | 26 +- .../.cargo-checksum.json | 0 src/vendor/error-chain-0.10.0/.cargo-ok | 0 .../.gitignore | 0 .../.travis.yml | 0 .../CHANGELOG.md | 0 .../Cargo.toml | 0 .../README.md | 0 .../examples/all.rs | 0 .../examples/doc.rs | 0 .../examples/quickstart.rs | 0 .../examples/size.rs | 0 .../src/error_chain.rs | 0 .../src/example_generated.rs | 0 .../src/lib.rs | 0 .../src/quick_error.rs | 0 .../src/quick_main.rs | 0 .../tests/quick_main.rs | 0 .../tests/tests.rs | 0 src/vendor/gcc/.cargo-checksum.json | 2 +- src/vendor/gcc/Cargo.toml | 2 +- src/vendor/gcc/src/lib.rs | 39 +- src/vendor/gcc/tests/test.rs | 28 + src/vendor/handlebars/.cargo-checksum.json | 2 +- src/vendor/handlebars/.travis.yml | 7 +- src/vendor/handlebars/CHANGELOG.md | 10 + src/vendor/handlebars/Cargo.toml | 16 +- src/vendor/handlebars/README.md | 13 +- src/vendor/handlebars/benches/bench.rs | 15 +- src/vendor/handlebars/examples/decorator.rs | 31 +- src/vendor/handlebars/examples/error.rs | 30 +- src/vendor/handlebars/examples/partials.rs | 10 +- src/vendor/handlebars/examples/render-cli.rs | 10 +- src/vendor/handlebars/examples/render.rs | 30 +- src/vendor/handlebars/examples/render_file.rs | 26 +- src/vendor/handlebars/src/context.rs | 233 +- .../handlebars/src/directives/inline.rs | 12 - src/vendor/handlebars/src/directives/mod.rs | 5 +- src/vendor/handlebars/src/grammar.rs | 7 +- .../handlebars/src/helpers/helper_each.rs | 11 +- .../handlebars/src/helpers/helper_if.rs | 6 +- .../handlebars/src/helpers/helper_lookup.rs | 11 - .../handlebars/src/helpers/helper_with.rs | 26 +- src/vendor/handlebars/src/lib.rs | 41 +- src/vendor/handlebars/src/registry.rs | 17 +- src/vendor/handlebars/src/render.rs | 30 +- src/vendor/handlebars/src/template.rs | 4 - src/vendor/jobserver/.appveyor.yml | 18 + src/vendor/jobserver/.cargo-checksum.json | 1 + src/vendor/jobserver/.cargo-ok | 0 src/vendor/jobserver/.gitignore | 3 + src/vendor/jobserver/.travis.yml | 25 + src/vendor/jobserver/Cargo.toml | 47 + .../LICENSE-APACHE | 0 src/vendor/jobserver/LICENSE-MIT | 25 + src/vendor/jobserver/README.md | 34 + src/vendor/jobserver/src/lib.rs | 894 +++ .../jobserver/tests/client-of-myself.rs | 60 + src/vendor/jobserver/tests/client.rs | 191 + src/vendor/jobserver/tests/helper.rs | 44 + .../jobserver/tests/make-as-a-client.rs | 61 + src/vendor/jobserver/tests/server.rs | 145 + src/vendor/libc/.cargo-checksum.json | 2 +- src/vendor/libc/.travis.yml | 91 +- src/vendor/libc/Cargo.toml | 2 +- src/vendor/libc/README.md | 19 + src/vendor/libc/ci/android-install-ndk.sh | 9 +- src/vendor/libc/ci/android-sysimage.sh | 52 + .../docker/i686-unknown-linux-musl/Dockerfile | 9 +- .../docker/s390x-unknown-linux-gnu/Dockerfile | 9 + .../ci/docker/x86_64-linux-android/Dockerfile | 34 +- .../x86_64-unknown-linux-musl/Dockerfile | 9 +- src/vendor/libc/ci/run-docker.sh | 1 - src/vendor/libc/ci/run.sh | 10 +- src/vendor/libc/src/dox.rs | 3 + src/vendor/libc/src/unix/bsd/apple/b32.rs | 1 + src/vendor/libc/src/unix/bsd/apple/b64.rs | 1 + src/vendor/libc/src/unix/bsd/apple/mod.rs | 73 +- .../src/unix/bsd/freebsdlike/dragonfly/mod.rs | 22 +- .../src/unix/bsd/freebsdlike/freebsd/mod.rs | 18 + .../libc/src/unix/bsd/freebsdlike/mod.rs | 156 +- src/vendor/libc/src/unix/bsd/mod.rs | 27 +- .../libc/src/unix/bsd/netbsdlike/mod.rs | 32 +- .../src/unix/bsd/netbsdlike/netbsd/mod.rs | 124 +- .../unix/bsd/netbsdlike/openbsdlike/mod.rs | 141 +- src/vendor/libc/src/unix/haiku/mod.rs | 56 + src/vendor/libc/src/unix/mod.rs | 61 +- src/vendor/libc/src/unix/newlib/arm/mod.rs | 5 + src/vendor/libc/src/unix/newlib/mod.rs | 604 +++ .../libc/src/unix/notbsd/android/b32/mod.rs | 3 + .../libc/src/unix/notbsd/android/b32/x86.rs | 2 + .../src/unix/notbsd/android/b64/aarch64.rs | 3 + .../libc/src/unix/notbsd/android/b64/mod.rs | 2 +- .../src/unix/notbsd/android/b64/x86_64.rs | 5 + .../libc/src/unix/notbsd/android/mod.rs | 102 +- .../libc/src/unix/notbsd/linux/mips/mips32.rs | 57 +- .../libc/src/unix/notbsd/linux/mips/mips64.rs | 27 +- .../libc/src/unix/notbsd/linux/mips/mod.rs | 164 +- src/vendor/libc/src/unix/notbsd/linux/mod.rs | 271 +- .../src/unix/notbsd/linux/musl/b32/arm.rs | 12 + .../src/unix/notbsd/linux/musl/b32/asmjs.rs | 12 + .../src/unix/notbsd/linux/musl/b32/mips.rs | 12 + .../src/unix/notbsd/linux/musl/b32/mod.rs | 1 + .../src/unix/notbsd/linux/musl/b32/x86.rs | 12 + .../src/unix/notbsd/linux/musl/b64/aarch64.rs | 1 + .../src/unix/notbsd/linux/musl/b64/mod.rs | 12 + .../unix/notbsd/linux/musl/b64/powerpc64.rs | 1 + .../src/unix/notbsd/linux/musl/b64/x86_64.rs | 1 + .../libc/src/unix/notbsd/linux/musl/mod.rs | 24 +- .../src/unix/notbsd/linux/other/b32/arm.rs | 13 + .../src/unix/notbsd/linux/other/b32/mod.rs | 13 +- .../unix/notbsd/linux/other/b32/powerpc.rs | 11 +- .../src/unix/notbsd/linux/other/b32/x86.rs | 78 +- .../unix/notbsd/linux/other/b64/aarch64.rs | 14 +- .../src/unix/notbsd/linux/other/b64/mod.rs | 1 + .../unix/notbsd/linux/other/b64/powerpc64.rs | 12 +- .../unix/notbsd/linux/other/b64/sparc64.rs | 19 + .../src/unix/notbsd/linux/other/b64/x86_64.rs | 79 +- .../libc/src/unix/notbsd/linux/other/mod.rs | 94 +- .../libc/src/unix/notbsd/linux/s390x.rs | 120 +- src/vendor/libc/src/unix/notbsd/mod.rs | 50 + src/vendor/libc/src/unix/solaris/mod.rs | 212 +- .../libc/src/unix/uclibc/mips/mips32.rs | 269 + .../libc/src/unix/uclibc/mips/mips64.rs | 209 + src/vendor/libc/src/unix/uclibc/mips/mod.rs | 476 ++ src/vendor/libc/src/unix/uclibc/mod.rs | 1782 ++++++ src/vendor/libc/src/unix/uclibc/x86_64/mod.rs | 361 ++ src/vendor/libc/src/windows.rs | 12 + src/vendor/log/.cargo-checksum.json | 2 +- src/vendor/log/Cargo.toml | 56 +- src/vendor/log/Cargo.toml.orig | 41 + src/vendor/log/README.md | 17 + src/vendor/log/src/lib.rs | 85 +- src/vendor/log/src/macros.rs | 88 + src/vendor/lzma-sys/.cargo-checksum.json | 2 +- src/vendor/lzma-sys/Cargo.toml | 2 +- src/vendor/lzma-sys/build.rs | 43 +- src/vendor/mdbook/.cargo-checksum.json | 2 +- src/vendor/mdbook/.gitignore | 10 +- src/vendor/mdbook/.travis.yml | 9 - src/vendor/mdbook/CONTRIBUTING.md | 84 + src/vendor/mdbook/Cargo.toml | 16 +- src/vendor/mdbook/LICENSE | 724 +-- src/vendor/mdbook/README.md | 11 +- src/vendor/mdbook/appveyor.yml | 120 +- src/vendor/mdbook/build.rs | 3 +- src/vendor/mdbook/ci/before_deploy.sh | 64 +- src/vendor/mdbook/ci/install.sh | 116 +- src/vendor/mdbook/ci/script.sh | 90 +- src/vendor/mdbook/deploy.sh | 84 +- src/vendor/mdbook/rustfmt.toml | 1 + src/vendor/mdbook/src/bin/mdbook.rs | 63 +- src/vendor/mdbook/src/book/bookconfig.rs | 31 +- src/vendor/mdbook/src/book/bookconfig_test.rs | 22 + src/vendor/mdbook/src/book/bookitem.rs | 13 +- src/vendor/mdbook/src/book/mod.rs | 146 +- src/vendor/mdbook/src/lib.rs | 3 +- src/vendor/mdbook/src/parse/mod.rs | 6 +- src/vendor/mdbook/src/parse/summary.rs | 22 +- .../renderer/html_handlebars/hbs_renderer.rs | 250 +- .../renderer/html_handlebars/helpers/mod.rs | 6 +- .../html_handlebars/helpers/navigation.rs | 18 +- .../html_handlebars/helpers/playpen.rs | 33 +- .../renderer/html_handlebars/helpers/toc.rs | 91 +- .../src/renderer/html_handlebars/mod.rs | 8 +- src/vendor/mdbook/src/renderer/mod.rs | 18 +- src/vendor/mdbook/src/theme/book.js | 4 +- src/vendor/mdbook/src/theme/index.hbs | 15 +- src/vendor/mdbook/src/theme/mod.rs | 9 +- src/vendor/mdbook/src/theme/stylus/book.styl | 20 +- src/vendor/mdbook/src/theme/stylus/menu.styl | 78 +- .../mdbook/src/theme/stylus/nav-icons.styl | 46 +- src/vendor/mdbook/src/theme/stylus/page.styl | 110 +- src/vendor/mdbook/src/theme/stylus/print.styl | 104 +- .../mdbook/src/theme/stylus/sidebar.styl | 128 +- .../mdbook/src/theme/stylus/theme-popup.styl | 112 +- .../mdbook/src/theme/stylus/variables.styl | 2 +- .../mdbook/src/theme/tomorrow-night.css | 192 +- src/vendor/mdbook/src/utils/fs.rs | 64 +- src/vendor/mdbook/src/utils/mod.rs | 40 +- src/vendor/num-traits/.cargo-checksum.json | 2 +- src/vendor/num-traits/Cargo.toml | 2 +- src/vendor/num-traits/src/bounds.rs | 28 + src/vendor/num-traits/src/cast.rs | 61 + src/vendor/num-traits/src/identities.rs | 44 + src/vendor/num-traits/src/lib.rs | 166 +- src/vendor/num-traits/src/ops/checked.rs | 1 + src/vendor/num-traits/src/ops/wrapping.rs | 39 + src/vendor/num-traits/src/sign.rs | 43 + src/vendor/num_cpus/.appveyor.yml | 16 + src/vendor/num_cpus/.cargo-checksum.json | 2 +- src/vendor/num_cpus/Cargo.toml | 26 +- src/vendor/num_cpus/Cargo.toml.orig | 14 + src/vendor/num_cpus/README.md | 4 + src/vendor/num_cpus/src/lib.rs | 189 +- .../pulldown-cmark-0.0.8/.cargo-checksum.json | 1 - .../pulldown-cmark-0.0.8/CONTRIBUTING.md | 24 - src/vendor/pulldown-cmark-0.0.8/Cargo.toml | 15 - src/vendor/pulldown-cmark-0.0.8/README.md | 108 - .../pulldown-cmark-0.0.8/specs/footnotes.txt | 154 - .../pulldown-cmark-0.0.8/specs/table.txt | 215 - .../pulldown-cmark-0.0.8/src/entities.rs | 4284 --------------- src/vendor/pulldown-cmark-0.0.8/src/escape.rs | 120 - src/vendor/pulldown-cmark-0.0.8/src/html.rs | 237 - src/vendor/pulldown-cmark-0.0.8/src/lib.rs | 37 - src/vendor/pulldown-cmark-0.0.8/src/main.rs | 193 - src/vendor/pulldown-cmark-0.0.8/src/parse.rs | 1675 ------ src/vendor/pulldown-cmark-0.0.8/src/passes.rs | 102 - .../pulldown-cmark-0.0.8/src/puncttable.rs | 348 -- .../pulldown-cmark-0.0.8/src/scanners.rs | 666 --- src/vendor/pulldown-cmark-0.0.8/src/utils.rs | 53 - .../pulldown-cmark-0.0.8/tools/mk_entities.py | 72 - .../tools/mk_puncttable.py | 130 - src/vendor/rand/.cargo-checksum.json | 1 + src/vendor/rand/.cargo-ok | 0 src/vendor/{toml-0.3.2 => rand}/.gitignore | 0 src/vendor/rand/.travis.yml | 24 + src/vendor/rand/Cargo.toml | 20 + .../{toml-0.3.2 => rand}/LICENSE-APACHE | 0 .../{bitflags-0.7.0 => rand}/LICENSE-MIT | 0 src/vendor/rand/README.md | 52 + src/vendor/rand/appveyor.yml | 17 + src/vendor/rand/benches/bench.rs | 88 + .../rand/benches/distributions/exponential.rs | 18 + .../rand/benches/distributions/gamma.rs | 31 + src/vendor/rand/benches/distributions/mod.rs | 3 + .../rand/benches/distributions/normal.rs | 18 + src/vendor/rand/src/chacha.rs | 318 ++ .../rand/src/distributions/exponential.rs | 124 + src/vendor/rand/src/distributions/gamma.rs | 384 ++ src/vendor/rand/src/distributions/mod.rs | 399 ++ src/vendor/rand/src/distributions/normal.rs | 201 + src/vendor/rand/src/distributions/range.rs | 231 + .../rand/src/distributions/ziggurat_tables.rs | 280 + src/vendor/rand/src/isaac.rs | 623 +++ src/vendor/rand/src/lib.rs | 1242 +++++ src/vendor/rand/src/os.rs | 584 ++ src/vendor/rand/src/rand_impls.rs | 283 + src/vendor/rand/src/read.rs | 122 + src/vendor/rand/src/reseeding.rs | 228 + src/vendor/regex-syntax/.cargo-checksum.json | 2 +- src/vendor/regex-syntax/Cargo.toml | 4 +- src/vendor/regex-syntax/src/lib.rs | 157 +- src/vendor/regex-syntax/src/literals.rs | 8 +- src/vendor/regex-syntax/src/parser.rs | 733 ++- src/vendor/regex-syntax/src/properties.rs | 23 + src/vendor/regex/.cargo-checksum.json | 2 +- src/vendor/regex/CHANGELOG.md | 37 + src/vendor/regex/Cargo.toml | 5 +- src/vendor/regex/README.md | 8 +- src/vendor/regex/ci/run-kcov | 2 +- src/vendor/regex/examples/bug347.rs | 9 + .../regex/examples/shootout-regex-redux-1.rs | 86 + .../examples/shootout-regex-redux-chunked.rs | 82 + .../regex/examples/shootout-regex-redux.rs | 103 + src/vendor/regex/src/backtrack.rs | 2 +- src/vendor/regex/src/compile.rs | 27 +- src/vendor/regex/src/exec.rs | 20 +- src/vendor/regex/src/lib.rs | 34 +- src/vendor/regex/src/re_builder.rs | 4 - src/vendor/regex/src/re_bytes.rs | 43 +- src/vendor/regex/src/re_unicode.rs | 40 +- src/vendor/regex/src/utf8.rs | 20 + src/vendor/regex/tests/macros.rs | 3 +- src/vendor/regex/tests/regression.rs | 8 + src/vendor/regex/tests/set.rs | 2 + src/vendor/regex/tests/test_default_bytes.rs | 15 + src/vendor/rls-data/.cargo-checksum.json | 2 +- src/vendor/rls-data/Cargo.toml | 27 +- src/vendor/rls-data/Cargo.toml.orig | 15 + src/vendor/rls-data/src/lib.rs | 105 +- src/vendor/serde-0.9.15/.cargo-checksum.json | 1 - src/vendor/serde-0.9.15/Cargo.toml | 35 - src/vendor/serde-0.9.15/src/bytes.rs | 315 -- src/vendor/serde-0.9.15/src/de/content.rs | 1338 ----- .../serde-0.9.15/src/de/from_primitive.rs | 409 -- src/vendor/serde-0.9.15/src/de/impls.rs | 1635 ------ src/vendor/serde-0.9.15/src/de/private.rs | 44 - src/vendor/serde-0.9.15/src/de/value.rs | 1107 ---- src/vendor/serde-0.9.15/src/error.rs | 17 - src/vendor/serde-0.9.15/src/export.rs | 36 - src/vendor/serde-0.9.15/src/iter.rs | 73 - src/vendor/serde-0.9.15/src/lib.rs | 155 - src/vendor/serde-0.9.15/src/macros.rs | 207 - src/vendor/serde-0.9.15/src/ser/content.rs | 607 --- src/vendor/serde-0.9.15/src/ser/impls.rs | 818 --- src/vendor/serde-0.9.15/src/ser/impossible.rs | 156 - src/vendor/serde-0.9.15/src/ser/mod.rs | 919 ---- src/vendor/serde-0.9.15/src/ser/private.rs | 315 -- src/vendor/serde-0.9.15/src/utils.rs | 74 - src/vendor/serde/.cargo-checksum.json | 1 + src/vendor/serde/.cargo-ok | 0 src/vendor/serde/Cargo.toml | 44 + src/vendor/serde/Cargo.toml.orig | 68 + src/vendor/serde/LICENSE-APACHE | 201 + .../{serde-0.9.15 => serde}/LICENSE-MIT | 0 src/vendor/{serde-0.9.15 => serde}/README.md | 7 +- src/vendor/serde/src/de/from_primitive.rs | 116 + src/vendor/serde/src/de/ignored_any.rs | 215 + src/vendor/serde/src/de/impls.rs | 1769 ++++++ .../{serde-0.9.15 => serde}/src/de/mod.rs | 1594 ++++-- src/vendor/serde/src/de/utf8.rs | 54 + src/vendor/serde/src/de/value.rs | 1281 +++++ src/vendor/serde/src/export.rs | 41 + src/vendor/serde/src/lib.rs | 260 + src/vendor/serde/src/macros.rs | 242 + src/vendor/serde/src/private/de.rs | 1952 +++++++ src/vendor/serde/src/private/macros.rs | 148 + src/vendor/serde/src/private/mod.rs | 12 + src/vendor/serde/src/private/ser.rs | 1019 ++++ src/vendor/serde/src/ser/impls.rs | 632 +++ src/vendor/serde/src/ser/impossible.rs | 227 + src/vendor/serde/src/ser/mod.rs | 1816 +++++++ .../serde_json-0.9.10/.cargo-checksum.json | 1 - src/vendor/serde_json-0.9.10/src/number.rs | 235 - src/vendor/serde_json-0.9.10/src/value.rs | 2267 -------- src/vendor/serde_json/.cargo-checksum.json | 1 + src/vendor/serde_json/.cargo-ok | 0 .../Cargo.toml | 27 +- src/vendor/serde_json/LICENSE-APACHE | 201 + .../LICENSE-MIT | 0 .../README.md | 147 +- .../src/de.rs | 910 ++-- .../src/error.rs | 203 +- src/vendor/serde_json/src/iter.rs | 78 + .../src/lib.rs | 176 +- .../src/macros.rs | 25 +- .../src/map.rs | 189 +- src/vendor/serde_json/src/number.rs | 379 ++ .../src/read.rs | 364 +- .../src/ser.rs | 1161 ++-- src/vendor/serde_json/src/value/de.rs | 909 ++++ src/vendor/serde_json/src/value/from.rs | 268 + src/vendor/serde_json/src/value/index.rs | 259 + src/vendor/serde_json/src/value/mod.rs | 1029 ++++ src/vendor/serde_json/src/value/partial_eq.rs | 82 + src/vendor/serde_json/src/value/ser.rs | 419 ++ src/vendor/strsim-0.5.2/.cargo-checksum.json | 1 - src/vendor/strsim-0.5.2/Vagrantfile | 5 - src/vendor/strsim-0.5.2/bootstrap.sh | 6 - src/vendor/strsim/.cargo-checksum.json | 1 + src/vendor/strsim/.cargo-ok | 0 .../{strsim-0.5.2 => strsim}/.editorconfig | 0 .../{strsim-0.5.2 => strsim}/.gitignore | 0 .../{strsim-0.5.2 => strsim}/.travis.yml | 0 .../{strsim-0.5.2 => strsim}/CHANGELOG.md | 13 +- .../{strsim-0.5.2 => strsim}/Cargo.toml | 2 +- src/vendor/{strsim-0.5.2 => strsim}/LICENSE | 0 src/vendor/{strsim-0.5.2 => strsim}/README.md | 38 +- .../{strsim-0.5.2 => strsim}/appveyor.yml | 0 src/vendor/strsim/dev | 14 + .../{strsim-0.5.2 => strsim}/src/lib.rs | 222 +- .../{strsim-0.5.2 => strsim}/tests/lib.rs | 30 +- src/vendor/term_size/.cargo-checksum.json | 2 +- src/vendor/term_size/CHANGELOG.md | 10 + src/vendor/term_size/Cargo.toml | 4 +- src/vendor/term_size/README.md | 2 +- src/vendor/term_size/rustfmt.toml | 2 +- src/vendor/term_size/src/lib.rs | 144 +- src/vendor/textwrap/.appveyor.yml | 38 + src/vendor/textwrap/.cargo-checksum.json | 1 + src/vendor/textwrap/.cargo-ok | 0 src/vendor/textwrap/.gitignore | 5 + src/vendor/textwrap/.travis.yml | 25 + src/vendor/textwrap/Cargo.toml | 27 + .../license-mit => textwrap/LICENSE} | 4 +- src/vendor/textwrap/README.md | 255 + src/vendor/textwrap/benches/linear.rs | 92 + src/vendor/textwrap/examples/layout.rs | 41 + src/vendor/textwrap/examples/termwidth.rs | 18 + src/vendor/textwrap/src/lib.rs | 891 +++ src/vendor/thread-id/.appveyor.yml | 50 - src/vendor/thread-id/.cargo-checksum.json | 1 - src/vendor/thread-id/.gitignore | 7 - src/vendor/thread-id/.travis.yml | 15 - src/vendor/thread-id/Cargo.toml | 16 - src/vendor/thread-id/changelog.md | 30 - src/vendor/thread-id/readme.md | 53 - src/vendor/thread-id/src/lib.rs | 67 - src/vendor/thread_local/.cargo-checksum.json | 2 +- src/vendor/thread_local/.travis.yml | 1 + src/vendor/thread_local/Cargo.toml | 27 +- src/vendor/thread_local/Cargo.toml.orig | 14 + .../thread_local/benches/thread_local.rs | 18 + src/vendor/thread_local/src/lib.rs | 126 +- src/vendor/thread_local/src/thread_id.rs | 61 + src/vendor/toml-0.3.2/.cargo-checksum.json | 1 - src/vendor/toml-0.3.2/src/value/display.rs | 134 - src/vendor/toml/.cargo-checksum.json | 1 + src/vendor/toml/.cargo-ok | 0 .../{pulldown-cmark-0.0.8 => toml}/.gitignore | 3 +- src/vendor/{toml-0.3.2 => toml}/.travis.yml | 1 + src/vendor/{toml-0.3.2 => toml}/Cargo.toml | 8 +- src/vendor/toml/LICENSE-APACHE | 201 + src/vendor/toml/LICENSE-MIT | 25 + src/vendor/{toml-0.3.2 => toml}/README.md | 5 +- .../{toml-0.3.2 => toml}/examples/decode.rs | 3 +- .../examples/toml2json.rs | 0 .../{toml-0.3.2 => toml}/src/datetime.rs | 77 +- src/vendor/{toml-0.3.2 => toml}/src/de.rs | 256 +- src/vendor/{toml-0.3.2 => toml}/src/lib.rs | 11 +- src/vendor/{toml-0.3.2 => toml}/src/ser.rs | 147 +- src/vendor/{toml-0.3.2 => toml}/src/tokens.rs | 6 +- src/vendor/{toml-0.3.2 => toml}/src/value.rs | 198 +- .../{toml-0.3.2 => toml}/tests/README.md | 0 .../{toml-0.3.2 => toml}/tests/backcompat.rs | 0 .../{toml-0.3.2 => toml}/tests/datetime.rs | 0 .../tests/display-tricky.rs | 0 .../{toml-0.3.2 => toml}/tests/display.rs | 0 .../{toml-0.3.2 => toml}/tests/formatting.rs | 0 src/vendor/toml/tests/invalid-encoder-misc.rs | 14 + .../array-mixed-types-ints-and-floats.json | 0 .../tests/invalid-misc.rs | 4 + .../{toml-0.3.2 => toml}/tests/invalid.rs | 0 .../array-mixed-types-arrays-and-ints.toml | 0 .../array-mixed-types-ints-and-floats.toml | 0 .../array-mixed-types-strings-and-ints.toml | 0 .../invalid/datetime-malformed-no-leads.toml | 0 .../invalid/datetime-malformed-no-secs.toml | 0 .../invalid/datetime-malformed-no-t.toml | 0 .../datetime-malformed-with-milli.toml | 0 .../tests/invalid/duplicate-key-table.toml | 0 .../tests/invalid/duplicate-keys.toml | 0 .../tests/invalid/duplicate-tables.toml | 0 .../tests/invalid/empty-implicit-table.toml | 0 .../tests/invalid/empty-table.toml | 0 .../tests/invalid/float-no-leading-zero.toml | 0 .../invalid/float-no-trailing-digits.toml | 0 .../tests/invalid/key-after-array.toml | 0 .../tests/invalid/key-after-table.toml | 0 .../tests/invalid/key-empty.toml | 0 .../tests/invalid/key-hash.toml | 0 .../tests/invalid/key-newline.toml | 0 .../tests/invalid/key-open-bracket.toml | 0 .../invalid/key-single-open-bracket.toml | 0 .../tests/invalid/key-space.toml | 0 .../tests/invalid/key-start-bracket.toml | 0 .../tests/invalid/key-two-equals.toml | 0 .../tests/invalid/string-bad-byte-escape.toml | 0 .../tests/invalid/string-bad-escape.toml | 0 .../tests/invalid/string-byte-escapes.toml | 0 .../tests/invalid/string-no-close.toml | 0 .../tests/invalid/table-array-implicit.toml | 0 .../table-array-malformed-bracket.toml | 0 .../invalid/table-array-malformed-empty.toml | 0 .../tests/invalid/table-empty.toml | 0 .../invalid/table-nested-brackets-close.toml | 0 .../invalid/table-nested-brackets-open.toml | 0 .../tests/invalid/table-whitespace.toml | 0 .../tests/invalid/table-with-pound.toml | 0 .../invalid/text-after-array-entries.toml | 0 .../tests/invalid/text-after-integer.toml | 0 .../tests/invalid/text-after-string.toml | 0 .../tests/invalid/text-after-table.toml | 0 .../invalid/text-before-array-separator.toml | 0 .../tests/invalid/text-in-array.toml | 0 .../{toml-0.3.2 => toml}/tests/parser.rs | 2 +- .../{toml-0.3.2 => toml}/tests/serde.rs | 27 +- .../{toml-0.3.2 => toml}/tests/tables-last.rs | 0 .../{toml-0.3.2 => toml}/tests/valid.rs | 12 +- .../tests/valid/array-empty.json | 0 .../tests/valid/array-empty.toml | 0 .../tests/valid/array-nospaces.json | 0 .../tests/valid/array-nospaces.toml | 0 .../tests/valid/arrays-hetergeneous.json | 0 .../tests/valid/arrays-hetergeneous.toml | 0 .../tests/valid/arrays-nested.json | 0 .../tests/valid/arrays-nested.toml | 0 .../tests/valid/arrays.json | 0 .../tests/valid/arrays.toml | 0 .../tests/valid/bool.json | 0 .../tests/valid/bool.toml | 0 .../tests/valid/comments-everywhere.json | 0 .../tests/valid/comments-everywhere.toml | 0 .../toml/tests/valid/datetime-truncate.json | 6 + .../toml/tests/valid/datetime-truncate.toml | 1 + .../tests/valid/datetime.json | 0 .../tests/valid/datetime.toml | 0 .../tests/valid/empty.json | 0 src/vendor/toml/tests/valid/empty.toml | 0 .../tests/valid/example-bom.toml | 0 .../tests/valid/example-v0.3.0.json | 0 .../tests/valid/example-v0.3.0.toml | 0 .../tests/valid/example-v0.4.0.json | 0 .../tests/valid/example-v0.4.0.toml | 0 .../tests/valid/example.json | 0 .../tests/valid/example.toml | 0 .../tests/valid/example2.json | 0 .../tests/valid/example2.toml | 0 .../tests/valid/float.json | 0 .../tests/valid/float.toml | 0 .../tests/valid/hard_example.json | 0 .../tests/valid/hard_example.toml | 0 .../valid/implicit-and-explicit-after.json | 0 .../valid/implicit-and-explicit-after.toml | 0 .../valid/implicit-and-explicit-before.json | 0 .../valid/implicit-and-explicit-before.toml | 0 .../tests/valid/implicit-groups.json | 0 .../tests/valid/implicit-groups.toml | 0 .../tests/valid/integer.json | 0 .../tests/valid/integer.toml | 0 .../tests/valid/key-equals-nospace.json | 0 .../tests/valid/key-equals-nospace.toml | 0 .../toml/tests/valid/key-quote-newline.json | 3 + .../toml/tests/valid/key-quote-newline.toml | 1 + .../tests/valid/key-space.json | 0 .../tests/valid/key-space.toml | 0 .../tests/valid/key-special-chars.json | 0 .../tests/valid/key-special-chars.toml | 0 .../tests/valid/key-with-pound.json | 0 .../tests/valid/key-with-pound.toml | 0 .../tests/valid/long-float.json | 0 .../tests/valid/long-float.toml | 0 .../tests/valid/long-integer.json | 0 .../tests/valid/long-integer.toml | 0 .../tests/valid/multiline-string.json | 0 .../tests/valid/multiline-string.toml | 0 .../tests/valid/raw-multiline-string.json | 0 .../tests/valid/raw-multiline-string.toml | 0 .../tests/valid/raw-string.json | 0 .../tests/valid/raw-string.toml | 0 .../tests/valid/string-empty.json | 0 .../tests/valid/string-empty.toml | 0 .../tests/valid/string-escapes.json | 0 .../tests/valid/string-escapes.toml | 0 .../tests/valid/string-simple.json | 0 .../tests/valid/string-simple.toml | 0 .../tests/valid/string-with-pound.json | 0 .../tests/valid/string-with-pound.toml | 0 .../tests/valid/table-array-implicit.json | 0 .../tests/valid/table-array-implicit.toml | 0 .../tests/valid/table-array-many.json | 0 .../tests/valid/table-array-many.toml | 0 .../tests/valid/table-array-nest-no-keys.json | 14 + .../tests/valid/table-array-nest-no-keys.toml | 6 + .../tests/valid/table-array-nest.json | 0 .../tests/valid/table-array-nest.toml | 0 .../tests/valid/table-array-one.json | 0 .../tests/valid/table-array-one.toml | 0 .../tests/valid/table-empty.json | 0 .../tests/valid/table-empty.toml | 0 .../tests/valid/table-sub-empty.json | 0 .../tests/valid/table-sub-empty.toml | 0 .../tests/valid/table-whitespace.json | 0 .../tests/valid/table-whitespace.toml | 0 .../tests/valid/table-with-pound.json | 0 .../tests/valid/table-with-pound.toml | 0 .../tests/valid/unicode-escape.json | 1 + .../tests/valid/unicode-escape.toml | 1 + .../tests/valid/unicode-literal.json | 0 .../tests/valid/unicode-literal.toml | 0 .../unicode-segmentation/.cargo-checksum.json | 2 +- src/vendor/unicode-segmentation/.gitignore | 1 + src/vendor/unicode-segmentation/.travis.yml | 6 +- src/vendor/unicode-segmentation/Cargo.toml | 7 +- src/vendor/unicode-segmentation/README.md | 20 +- .../unicode-segmentation/scripts/unicode.py | 1 - .../unicode-segmentation/src/grapheme.rs | 184 +- src/vendor/unicode-segmentation/src/lib.rs | 8 +- src/vendor/unicode-segmentation/src/tables.rs | 1116 ++-- src/vendor/unicode-segmentation/src/test.rs | 136 +- .../unicode-segmentation/src/testdata.rs | 1286 +++-- src/vendor/unicode-segmentation/src/word.rs | 186 +- src/vendor/unreachable/.cargo-checksum.json | 2 +- src/vendor/unreachable/Cargo.toml | 4 +- .../LICENSE-APACHE} | 6 +- .../LICENSE => unreachable/LICENSE-MIT} | 12 +- src/vendor/unreachable/README.md | 13 +- src/vendor/vec_map/.cargo-checksum.json | 2 +- src/vendor/vec_map/Cargo.toml | 8 +- src/vendor/vec_map/src/lib.rs | 117 +- version | 2 +- 5078 files changed, 108516 insertions(+), 62162 deletions(-) create mode 100644 src/ci/docker/asmjs/Dockerfile create mode 100644 src/ci/docker/disabled/wasm32-exp/Dockerfile create mode 100755 src/ci/docker/disabled/wasm32-exp/node.sh create mode 100644 src/ci/docker/disabled/wasm32/Dockerfile create mode 100755 src/ci/docker/disabled/wasm32/node.sh delete mode 100644 src/ci/docker/emscripten/Dockerfile delete mode 100755 src/ci/docker/emscripten/build-emscripten.sh create mode 100644 src/ci/docker/scripts/android-base-apt-get.sh create mode 100644 src/ci/docker/scripts/cross-apt-packages.sh create mode 100644 src/ci/docker/scripts/crosstool-ng.sh create mode 100644 src/ci/docker/scripts/emscripten-wasm.sh create mode 100644 src/ci/docker/scripts/emscripten.sh create mode 100644 src/ci/docker/scripts/make3.sh create mode 100644 src/ci/docker/scripts/rustbuild-setup.sh delete mode 100644 src/doc/book/second-edition/nostarch/odt/chapter02.doc delete mode 100644 src/doc/book/second-edition/nostarch/odt/chapter03.docx delete mode 100644 src/doc/book/second-edition/nostarch/odt/chapter04.docx delete mode 100644 src/doc/book/second-edition/nostarch/odt/chapter05.docx delete mode 100644 src/doc/book/second-edition/nostarch/odt/chapter06.docx delete mode 100644 src/doc/book/second-edition/nostarch/odt/chapter07.docx delete mode 100644 src/doc/book/second-edition/nostarch/odt/chapter08.docx delete mode 100644 src/doc/book/second-edition/nostarch/odt/chapter09.docx create mode 100644 src/doc/nomicon/src/aliasing.md create mode 100644 src/doc/rustdoc/src/SUMMARY.md create mode 100644 src/doc/rustdoc/src/command-line-arguments.md create mode 100644 src/doc/rustdoc/src/documentation-tests.md create mode 100644 src/doc/rustdoc/src/in-source-directives.md create mode 100644 src/doc/rustdoc/src/passes.md create mode 100644 src/doc/rustdoc/src/plugins.md create mode 100644 src/doc/rustdoc/src/what-is-rustdoc.md delete mode 100644 src/doc/unstable-book/src/SUMMARY.md create mode 100644 src/doc/unstable-book/src/compiler-flags/profile.md delete mode 100644 src/doc/unstable-book/src/language-features/abi-sysv64.md delete mode 100644 src/doc/unstable-book/src/language-features/abi-unadjusted.md delete mode 100644 src/doc/unstable-book/src/language-features/abi-vectorcall.md delete mode 100644 src/doc/unstable-book/src/language-features/abi-x86-interrupt.md create mode 100644 src/doc/unstable-book/src/language-features/allocator-internals.md delete mode 100644 src/doc/unstable-book/src/language-features/allocator.md delete mode 100644 src/doc/unstable-book/src/language-features/allow-internal-unstable.md delete mode 100644 src/doc/unstable-book/src/language-features/associated-consts.md delete mode 100644 src/doc/unstable-book/src/language-features/associated-type-defaults.md delete mode 100644 src/doc/unstable-book/src/language-features/cfg-target-feature.md delete mode 100644 src/doc/unstable-book/src/language-features/cfg-target-has-atomic.md delete mode 100644 src/doc/unstable-book/src/language-features/cfg-target-thread-local.md delete mode 100644 src/doc/unstable-book/src/language-features/cfg-target-vendor.md delete mode 100644 src/doc/unstable-book/src/language-features/custom-attribute.md delete mode 100644 src/doc/unstable-book/src/language-features/custom-derive.md delete mode 100644 src/doc/unstable-book/src/language-features/decl-macro.md delete mode 100644 src/doc/unstable-book/src/language-features/default-type-parameter-fallback.md delete mode 100644 src/doc/unstable-book/src/language-features/drop-types-in-const.md delete mode 100644 src/doc/unstable-book/src/language-features/dropck-eyepatch.md delete mode 100644 src/doc/unstable-book/src/language-features/dropck-parametricity.md delete mode 100644 src/doc/unstable-book/src/language-features/exclusive-range-pattern.md delete mode 100644 src/doc/unstable-book/src/language-features/fundamental.md delete mode 100644 src/doc/unstable-book/src/language-features/generic-param-attrs.md create mode 100644 src/doc/unstable-book/src/language-features/global-allocator.md rename src/doc/unstable-book/src/language-features/{global_asm.md => global-asm.md} (100%) delete mode 100644 src/doc/unstable-book/src/language-features/link-cfg.md delete mode 100644 src/doc/unstable-book/src/language-features/link-llvm-intrinsics.md delete mode 100644 src/doc/unstable-book/src/language-features/linkage.md delete mode 100644 src/doc/unstable-book/src/language-features/log-syntax.md delete mode 100644 src/doc/unstable-book/src/language-features/macro-reexport.md delete mode 100644 src/doc/unstable-book/src/language-features/main.md delete mode 100644 src/doc/unstable-book/src/language-features/naked-functions.md delete mode 100644 src/doc/unstable-book/src/language-features/needs-allocator.md delete mode 100644 src/doc/unstable-book/src/language-features/needs-panic-runtime.md delete mode 100644 src/doc/unstable-book/src/language-features/never-type.md delete mode 100644 src/doc/unstable-book/src/language-features/no-core.md delete mode 100644 src/doc/unstable-book/src/language-features/no-debug.md delete mode 100644 src/doc/unstable-book/src/language-features/omit-gdb-pretty-printer-section.md delete mode 100644 src/doc/unstable-book/src/language-features/optin-builtin-traits.md delete mode 100644 src/doc/unstable-book/src/language-features/overlapping-marker-traits.md delete mode 100644 src/doc/unstable-book/src/language-features/panic-runtime.md delete mode 100644 src/doc/unstable-book/src/language-features/placement-in-syntax.md delete mode 100644 src/doc/unstable-book/src/language-features/platform-intrinsics.md delete mode 100644 src/doc/unstable-book/src/language-features/prelude-import.md create mode 100644 src/doc/unstable-book/src/language-features/profiler-runtime.md delete mode 100644 src/doc/unstable-book/src/language-features/quote.md delete mode 100644 src/doc/unstable-book/src/language-features/repr-align.md delete mode 100644 src/doc/unstable-book/src/language-features/repr-simd.md delete mode 100644 src/doc/unstable-book/src/language-features/rustc-attrs.md delete mode 100644 src/doc/unstable-book/src/language-features/rustc-diagnostic-macros.md delete mode 100644 src/doc/unstable-book/src/language-features/sanitizer-runtime.md delete mode 100644 src/doc/unstable-book/src/language-features/simd-ffi.md delete mode 100644 src/doc/unstable-book/src/language-features/simd.md delete mode 100644 src/doc/unstable-book/src/language-features/specialization.md delete mode 100644 src/doc/unstable-book/src/language-features/staged-api.md delete mode 100644 src/doc/unstable-book/src/language-features/start.md delete mode 100644 src/doc/unstable-book/src/language-features/static-nobundle.md delete mode 100644 src/doc/unstable-book/src/language-features/stmt-expr-attributes.md delete mode 100644 src/doc/unstable-book/src/language-features/struct-field-attributes.md delete mode 100644 src/doc/unstable-book/src/language-features/structural-match.md delete mode 100644 src/doc/unstable-book/src/language-features/target-feature.md delete mode 100644 src/doc/unstable-book/src/language-features/thread-local.md delete mode 100644 src/doc/unstable-book/src/language-features/trace-macros.md delete mode 100644 src/doc/unstable-book/src/language-features/type-ascription.md delete mode 100644 src/doc/unstable-book/src/language-features/unboxed-closures.md create mode 100644 src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md delete mode 100644 src/doc/unstable-book/src/language-features/untagged-unions.md delete mode 100644 src/doc/unstable-book/src/language-features/unwind-attributes.md delete mode 100644 src/doc/unstable-book/src/language-features/use-extern-macros.md delete mode 100644 src/doc/unstable-book/src/library-features/alloc.md create mode 100644 src/doc/unstable-book/src/library-features/allocator-api.md delete mode 100644 src/doc/unstable-book/src/library-features/as-c-str.md delete mode 100644 src/doc/unstable-book/src/library-features/ascii-ctype.md delete mode 100644 src/doc/unstable-book/src/library-features/box-heap.md create mode 100644 src/doc/unstable-book/src/library-features/char-error-internals.md delete mode 100644 src/doc/unstable-book/src/library-features/char-escape-debug.md delete mode 100644 src/doc/unstable-book/src/library-features/coerce-unsized.md delete mode 100644 src/doc/unstable-book/src/library-features/collection-placement.md delete mode 100644 src/doc/unstable-book/src/library-features/collections-range.md delete mode 100644 src/doc/unstable-book/src/library-features/compiler-builtins-lib.md delete mode 100644 src/doc/unstable-book/src/library-features/concat-idents-macro.md delete mode 100644 src/doc/unstable-book/src/library-features/core-char-ext.md delete mode 100644 src/doc/unstable-book/src/library-features/core-float.md delete mode 100644 src/doc/unstable-book/src/library-features/core-slice-ext.md delete mode 100644 src/doc/unstable-book/src/library-features/core-str-ext.md delete mode 100644 src/doc/unstable-book/src/library-features/decode-utf8.md delete mode 100644 src/doc/unstable-book/src/library-features/discriminant-value.md delete mode 100644 src/doc/unstable-book/src/library-features/error-type-id.md delete mode 100644 src/doc/unstable-book/src/library-features/exact-size-is-empty.md delete mode 100644 src/doc/unstable-book/src/library-features/fixed-size-array.md delete mode 100644 src/doc/unstable-book/src/library-features/float-bits-conv.md delete mode 100644 src/doc/unstable-book/src/library-features/fmt-flags-align.md delete mode 100644 src/doc/unstable-book/src/library-features/fn-traits.md delete mode 100644 src/doc/unstable-book/src/library-features/fnbox.md delete mode 100644 src/doc/unstable-book/src/library-features/from_utf8_error_as_bytes.md delete mode 100644 src/doc/unstable-book/src/library-features/fused.md delete mode 100644 src/doc/unstable-book/src/library-features/get-type-id.md delete mode 100644 src/doc/unstable-book/src/library-features/heap-api.md delete mode 100644 src/doc/unstable-book/src/library-features/i128.md delete mode 100644 src/doc/unstable-book/src/library-features/inclusive-range.md delete mode 100644 src/doc/unstable-book/src/library-features/integer-atomics.md delete mode 100644 src/doc/unstable-book/src/library-features/into-boxed-c-str.md delete mode 100644 src/doc/unstable-book/src/library-features/into-boxed-os-str.md delete mode 100644 src/doc/unstable-book/src/library-features/into-boxed-path.md delete mode 100644 src/doc/unstable-book/src/library-features/io.md delete mode 100644 src/doc/unstable-book/src/library-features/ip.md delete mode 100644 src/doc/unstable-book/src/library-features/iter-rfind.md create mode 100644 src/doc/unstable-book/src/library-features/iterator-for-each.md delete mode 100644 src/doc/unstable-book/src/library-features/iterator-step-by.md delete mode 100644 src/doc/unstable-book/src/library-features/linked-list-extras.md delete mode 100644 src/doc/unstable-book/src/library-features/lookup-host.md delete mode 100644 src/doc/unstable-book/src/library-features/more-io-inner-methods.md delete mode 100644 src/doc/unstable-book/src/library-features/mpsc-select.md delete mode 100644 src/doc/unstable-book/src/library-features/needs-drop.md delete mode 100644 src/doc/unstable-book/src/library-features/never-type-impls.md delete mode 100644 src/doc/unstable-book/src/library-features/nonzero.md delete mode 100644 src/doc/unstable-book/src/library-features/offset-to.md delete mode 100644 src/doc/unstable-book/src/library-features/once-poison.md delete mode 100644 src/doc/unstable-book/src/library-features/oom.md delete mode 100644 src/doc/unstable-book/src/library-features/option-entry.md delete mode 100644 src/doc/unstable-book/src/library-features/panic-abort.md delete mode 100644 src/doc/unstable-book/src/library-features/panic-unwind.md delete mode 100644 src/doc/unstable-book/src/library-features/pattern.md delete mode 100644 src/doc/unstable-book/src/library-features/placement-in.md delete mode 100644 src/doc/unstable-book/src/library-features/placement-new-protocol.md delete mode 100644 src/doc/unstable-book/src/library-features/proc-macro-internals.md create mode 100644 src/doc/unstable-book/src/library-features/proc-macro.md create mode 100644 src/doc/unstable-book/src/library-features/profiler-runtime-lib.md delete mode 100644 src/doc/unstable-book/src/library-features/question-mark-carrier.md delete mode 100644 src/doc/unstable-book/src/library-features/range-contains.md delete mode 100644 src/doc/unstable-book/src/library-features/raw.md create mode 100644 src/doc/unstable-book/src/library-features/read-initializer.md delete mode 100644 src/doc/unstable-book/src/library-features/rustc-private.md delete mode 100644 src/doc/unstable-book/src/library-features/shared.md delete mode 100644 src/doc/unstable-book/src/library-features/sip-hash-13.md delete mode 100644 src/doc/unstable-book/src/library-features/slice-concat-ext.md delete mode 100644 src/doc/unstable-book/src/library-features/slice-get-slice.md delete mode 100644 src/doc/unstable-book/src/library-features/slice-rotate.md delete mode 100644 src/doc/unstable-book/src/library-features/sort-unstable.md delete mode 100644 src/doc/unstable-book/src/library-features/step-by.md delete mode 100644 src/doc/unstable-book/src/library-features/step-trait.md delete mode 100644 src/doc/unstable-book/src/library-features/str-box-extras.md delete mode 100644 src/doc/unstable-book/src/library-features/str-checked-slicing.md delete mode 100644 src/doc/unstable-book/src/library-features/str-escape.md delete mode 100644 src/doc/unstable-book/src/library-features/str-mut-extras.md delete mode 100644 src/doc/unstable-book/src/library-features/thread-local-state.md delete mode 100644 src/doc/unstable-book/src/library-features/toowned-clone-into.md delete mode 100644 src/doc/unstable-book/src/library-features/trusted-len.md delete mode 100644 src/doc/unstable-book/src/library-features/try-from.md delete mode 100644 src/doc/unstable-book/src/library-features/unicode.md delete mode 100644 src/doc/unstable-book/src/library-features/unique.md delete mode 100644 src/doc/unstable-book/src/library-features/unsize.md delete mode 100644 src/doc/unstable-book/src/library-features/utf8-error-error-len.md delete mode 100644 src/doc/unstable-book/src/library-features/vec-remove-item.md delete mode 100644 src/doc/unstable-book/src/library-features/vec-resize-default.md rename src/etc/natvis/{libcollections.natvis => liballoc.natvis} (81%) create mode 100644 src/liballoc/allocator.rs rename src/{libcollections => liballoc}/benches/btree/map.rs (100%) rename src/{libcollections => liballoc}/benches/btree/mod.rs (100%) rename src/{libcollections => liballoc}/benches/lib.rs (96%) rename src/{libcollections => liballoc}/benches/linked_list.rs (100%) rename src/{libcollections => liballoc}/benches/slice.rs (86%) rename src/{libcollections => liballoc}/benches/str.rs (100%) rename src/{libcollections => liballoc}/benches/string.rs (100%) rename src/{libcollections => liballoc}/benches/vec.rs (100%) rename src/{libcollections => liballoc}/benches/vec_deque.rs (100%) rename src/{libcollections => liballoc}/binary_heap.rs (100%) rename src/{libcollections => liballoc}/borrow.rs (100%) rename src/{libcollections => liballoc}/btree/map.rs (99%) rename src/{libcollections => liballoc}/btree/mod.rs (100%) rename src/{libcollections => liballoc}/btree/node.rs (98%) rename src/{libcollections => liballoc}/btree/search.rs (100%) rename src/{libcollections => liballoc}/btree/set.rs (100%) rename src/{libcollections => liballoc}/fmt.rs (98%) rename src/{libcollections => liballoc}/linked_list.rs (99%) delete mode 100644 src/liballoc/oom.rs rename src/{libcollections => liballoc}/range.rs (92%) rename src/{libcollections => liballoc}/slice.rs (98%) rename src/{libcollections => liballoc}/string.rs (93%) rename src/{libcollections => liballoc}/tests/binary_heap.rs (100%) rename src/{libcollections => liballoc}/tests/btree/map.rs (100%) rename src/{libcollections => liballoc}/tests/btree/mod.rs (100%) rename src/{libcollections => liballoc}/tests/btree/set.rs (100%) rename src/{libcollections => liballoc}/tests/cow_str.rs (100%) rename src/{libcollections => liballoc}/tests/fmt.rs (100%) rename src/{libcollections => liballoc}/tests/lib.rs (93%) rename src/{libcollections => liballoc}/tests/linked_list.rs (100%) rename src/{libcollections => liballoc}/tests/slice.rs (95%) rename src/{libcollections => liballoc}/tests/str.rs (97%) rename src/{libcollections => liballoc}/tests/string.rs (100%) rename src/{libcollections => liballoc}/tests/vec.rs (98%) rename src/{libcollections => liballoc}/tests/vec_deque.rs (99%) rename src/{libcollections => liballoc}/vec.rs (99%) rename src/{libcollections => liballoc}/vec_deque.rs (99%) create mode 100644 src/liballoc_system/old.rs delete mode 100644 src/libcollections/macros.rs delete mode 100644 src/libcollections/str.rs create mode 100644 src/libcompiler_builtins/.travis.yml create mode 100644 src/libcompiler_builtins/LICENSE.TXT create mode 100644 src/libcompiler_builtins/README.md create mode 100644 src/libcompiler_builtins/appveyor.yml create mode 100644 src/libcompiler_builtins/ci/docker/aarch64-unknown-linux-gnu/Dockerfile create mode 100644 src/libcompiler_builtins/ci/docker/arm-unknown-linux-gnueabi/Dockerfile create mode 100644 src/libcompiler_builtins/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile create mode 100644 src/libcompiler_builtins/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile create mode 100644 src/libcompiler_builtins/ci/docker/i586-unknown-linux-gnu/Dockerfile create mode 100644 src/libcompiler_builtins/ci/docker/i686-unknown-linux-gnu/Dockerfile create mode 100644 src/libcompiler_builtins/ci/docker/mips-unknown-linux-gnu/Dockerfile create mode 100644 src/libcompiler_builtins/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile create mode 100644 src/libcompiler_builtins/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile create mode 100644 src/libcompiler_builtins/ci/docker/mipsel-unknown-linux-gnu/Dockerfile create mode 100644 src/libcompiler_builtins/ci/docker/powerpc-unknown-linux-gnu/Dockerfile create mode 100644 src/libcompiler_builtins/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile create mode 100644 src/libcompiler_builtins/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile create mode 100644 src/libcompiler_builtins/ci/docker/thumbv6m-linux-eabi/Dockerfile create mode 100644 src/libcompiler_builtins/ci/docker/thumbv7em-linux-eabi/Dockerfile create mode 100644 src/libcompiler_builtins/ci/docker/thumbv7em-linux-eabihf/Dockerfile create mode 100644 src/libcompiler_builtins/ci/docker/thumbv7m-linux-eabi/Dockerfile create mode 100644 src/libcompiler_builtins/ci/docker/x86_64-unknown-linux-gnu/Dockerfile create mode 100644 src/libcompiler_builtins/ci/run-docker.sh create mode 100755 src/libcompiler_builtins/ci/run.sh rename src/{ => libcompiler_builtins}/compiler-rt/.arcconfig (100%) rename src/{ => libcompiler_builtins}/compiler-rt/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/CODE_OWNERS.TXT (100%) rename src/{ => libcompiler_builtins}/compiler-rt/CREDITS.TXT (100%) rename src/{ => libcompiler_builtins}/compiler-rt/LICENSE.TXT (100%) rename src/{ => libcompiler_builtins}/compiler-rt/README.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/cmake/Modules/AddCompilerRT.cmake (100%) rename src/{ => libcompiler_builtins}/compiler-rt/cmake/Modules/BuiltinTests.cmake (100%) rename src/{ => libcompiler_builtins}/compiler-rt/cmake/Modules/CompilerRTCompile.cmake (100%) rename src/{ => libcompiler_builtins}/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake (100%) rename src/{ => libcompiler_builtins}/compiler-rt/cmake/Modules/CompilerRTLink.cmake (100%) rename src/{ => libcompiler_builtins}/compiler-rt/cmake/Modules/CompilerRTUtils.cmake (100%) rename src/{ => libcompiler_builtins}/compiler-rt/cmake/Modules/SanitizerUtils.cmake (100%) rename src/{ => libcompiler_builtins}/compiler-rt/cmake/base-config-ix.cmake (100%) rename src/{ => libcompiler_builtins}/compiler-rt/cmake/builtin-config-ix.cmake (100%) rename src/{ => libcompiler_builtins}/compiler-rt/cmake/caches/Apple.cmake (100%) rename src/{ => libcompiler_builtins}/compiler-rt/cmake/config-ix.cmake (100%) rename src/{ => libcompiler_builtins}/compiler-rt/docs/TestingGuide.rst (100%) rename src/{ => libcompiler_builtins}/compiler-rt/include/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/include/sanitizer/allocator_interface.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/include/sanitizer/asan_interface.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/include/sanitizer/common_interface_defs.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/include/sanitizer/coverage_interface.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/include/sanitizer/dfsan_interface.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/include/sanitizer/esan_interface.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/include/sanitizer/linux_syscall_hooks.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/include/sanitizer/lsan_interface.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/include/sanitizer/msan_interface.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/include/sanitizer/tsan_interface_atomic.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/include/xray/xray_interface.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/include/xray/xray_records.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/BlocksRuntime/Block.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/BlocksRuntime/Block_private.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/BlocksRuntime/data.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/BlocksRuntime/runtime.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/.clang-format (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/README.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan.syms.extra (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_activation.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_activation.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_activation_flags.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_allocator.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_allocator.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_blacklist.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_debugging.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_descriptions.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_descriptions.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_errors.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_errors.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_fake_stack.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_fake_stack.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_flags.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_flags.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_flags.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_globals.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_globals_win.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_globals_win.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_init_version.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_interceptors.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_interceptors.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_interface_internal.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_internal.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_linux.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_lock.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_mac.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_malloc_linux.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_malloc_mac.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_malloc_win.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_mapping.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_memory_profile.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_new_delete.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_poisoning.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_poisoning.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_posix.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_preinit.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_report.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_report.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_rtl.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_scariness_score.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_stack.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_stack.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_stats.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_stats.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_suppressions.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_suppressions.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_thread.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_thread.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_win.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_win_dll_thunk.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/asan_win_dynamic_runtime_thunk.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/scripts/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/scripts/asan_device_setup (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/scripts/asan_symbolize.py (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/tests/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/tests/asan_asm_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/tests/asan_benchmarks_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/tests/asan_exceptions_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/tests/asan_fake_stack_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/tests/asan_globals_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/tests/asan_interface_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/tests/asan_internal_interface_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/tests/asan_mac_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/tests/asan_mac_test.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/tests/asan_mac_test_helpers.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/tests/asan_mem_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/tests/asan_noinst_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/tests/asan_oob_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/tests/asan_racy_double_free_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/tests/asan_str_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/tests/asan_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/tests/asan_test.ignore (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/tests/asan_test_config.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/tests/asan_test_main.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/tests/asan_test_utils.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/asan/weak_symbols.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/Darwin-excludes/10.4.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/Darwin-excludes/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/Darwin-excludes/README.TXT (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/Darwin-excludes/ios-armv7.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/Darwin-excludes/ios-armv7s.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/Darwin-excludes/ios.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/Darwin-excludes/ios6-armv7.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/Darwin-excludes/ios6-armv7s.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/Darwin-excludes/ios7-arm64.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/Darwin-excludes/iossim-i386.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/Darwin-excludes/iossim-x86_64.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/Darwin-excludes/iossim.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/Darwin-excludes/osx-i386.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/Darwin-excludes/osx.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/README.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/absvdi2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/absvsi2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/absvti2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/adddf3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/addsf3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/addtf3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/addvdi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/addvsi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/addvti3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/apple_versioning.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/adddf3vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/addsf3vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/aeabi_cdcmp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/aeabi_cdcmpeq_check_nan.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/aeabi_cfcmp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/aeabi_cfcmpeq_check_nan.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/aeabi_dcmp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/aeabi_div0.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/aeabi_drsub.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/aeabi_fcmp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/aeabi_frsub.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/aeabi_idivmod.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/aeabi_ldivmod.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/aeabi_memcmp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/aeabi_memcpy.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/aeabi_memmove.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/aeabi_memset.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/aeabi_uidivmod.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/aeabi_uldivmod.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/bswapdi2.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/bswapsi2.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/clzdi2.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/clzsi2.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/comparesf2.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/divdf3vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/divmodsi4.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/divsf3vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/divsi3.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/eqdf2vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/eqsf2vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/extendsfdf2vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/fixdfsivfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/fixsfsivfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/fixunsdfsivfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/fixunssfsivfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/floatsidfvfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/floatsisfvfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/floatunssidfvfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/floatunssisfvfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/gedf2vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/gesf2vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/gtdf2vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/gtsf2vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/ledf2vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/lesf2vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/ltdf2vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/ltsf2vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/modsi3.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/muldf3vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/mulsf3vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/nedf2vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/negdf2vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/negsf2vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/nesf2vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/restore_vfp_d8_d15_regs.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/save_vfp_d8_d15_regs.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/softfloat-alias.list (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/subdf3vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/subsf3vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/switch16.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/switch32.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/switch8.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/switchu8.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/sync-ops.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/sync_fetch_and_add_4.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/sync_fetch_and_add_8.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/sync_fetch_and_and_4.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/sync_fetch_and_and_8.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/sync_fetch_and_max_4.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/sync_fetch_and_max_8.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/sync_fetch_and_min_4.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/sync_fetch_and_min_8.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_4.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_8.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/sync_fetch_and_or_4.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/sync_fetch_and_or_8.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_4.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_8.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_4.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_8.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_4.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_8.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_4.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_8.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/sync_synchronize.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/truncdfsf2vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/udivmodsi4.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/udivsi3.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/umodsi3.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/unorddf2vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/arm/unordsf2vfp.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ashldi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ashlti3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ashrdi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ashrti3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/assembly.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/atomic.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/atomic_flag_clear.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/atomic_flag_clear_explicit.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/atomic_flag_test_and_set.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/atomic_flag_test_and_set_explicit.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/atomic_signal_fence.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/atomic_thread_fence.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/clear_cache.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/clzdi2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/clzsi2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/clzti2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/cmpdi2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/cmpti2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/comparedf2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/comparesf2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/comparetf2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/cpu_model.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ctzdi2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ctzsi2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ctzti2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/divdc3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/divdf3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/divdi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/divmoddi4.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/divmodsi4.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/divsc3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/divsf3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/divsi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/divtc3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/divtf3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/divti3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/divxc3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/emutls.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/enable_execute_stack.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/eprintf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/extenddftf2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/extendhfsf2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/extendsfdf2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/extendsftf2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ffsdi2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ffsti2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixdfdi.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixdfsi.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixdfti.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixsfdi.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixsfsi.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixsfti.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixtfdi.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixtfsi.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixtfti.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixunsdfdi.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixunsdfsi.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixunsdfti.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixunssfdi.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixunssfsi.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixunssfti.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixunstfdi.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixunstfsi.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixunstfti.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixunsxfdi.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixunsxfsi.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixunsxfti.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixxfdi.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fixxfti.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/floatdidf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/floatdisf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/floatditf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/floatdixf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/floatsidf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/floatsisf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/floatsitf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/floattidf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/floattisf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/floattitf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/floattixf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/floatundidf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/floatundisf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/floatunditf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/floatundixf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/floatunsidf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/floatunsisf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/floatunsitf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/floatuntidf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/floatuntisf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/floatuntitf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/floatuntixf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fp_add_impl.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fp_extend.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fp_extend_impl.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fp_fixint_impl.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fp_fixuint_impl.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fp_lib.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fp_mul_impl.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fp_trunc.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/fp_trunc_impl.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/gcc_personality_v0.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/i386/ashldi3.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/i386/ashrdi3.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/i386/chkstk.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/i386/chkstk2.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/i386/divdi3.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/i386/floatdidf.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/i386/floatdisf.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/i386/floatdixf.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/i386/floatundidf.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/i386/floatundisf.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/i386/floatundixf.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/i386/lshrdi3.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/i386/moddi3.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/i386/muldi3.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/i386/udivdi3.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/i386/umoddi3.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/int_endianness.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/int_lib.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/int_math.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/int_types.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/int_util.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/int_util.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/lshrdi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/lshrti3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/macho_embedded/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/macho_embedded/arm.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/macho_embedded/common.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/macho_embedded/i386.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/macho_embedded/thumb2-64.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/macho_embedded/thumb2.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/mingw_fixfloat.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/moddi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/modsi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/modti3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/muldc3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/muldf3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/muldi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/mulodi4.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/mulosi4.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/muloti4.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/mulsc3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/mulsf3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/multc3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/multf3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/multi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/mulvdi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/mulvsi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/mulvti3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/mulxc3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/negdf2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/negdi2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/negsf2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/negti2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/negvdi2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/negvsi2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/negvti2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/paritydi2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/paritysi2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/parityti2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/popcountdi2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/popcountsi2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/popcountti2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/powidf2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/powisf2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/powitf2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/powixf2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ppc/DD.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ppc/divtc3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ppc/fixtfdi.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ppc/fixunstfdi.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ppc/floatditf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ppc/floatunditf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ppc/gcc_qadd.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ppc/gcc_qdiv.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ppc/gcc_qmul.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ppc/gcc_qsub.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ppc/multc3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ppc/restFP.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ppc/saveFP.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/subdf3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/subsf3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/subtf3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/subvdi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/subvsi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/subvti3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/trampoline_setup.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/truncdfhf2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/truncdfsf2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/truncsfhf2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/trunctfdf2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/trunctfsf2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ucmpdi2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/ucmpti2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/udivdi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/udivmoddi4.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/udivmodsi4.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/udivmodti4.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/udivsi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/udivti3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/umoddi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/umodsi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/umodti3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/unwind-ehabi-helpers.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/x86_64/chkstk.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/x86_64/chkstk2.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/x86_64/floatdidf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/x86_64/floatdisf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/x86_64/floatdixf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/x86_64/floatundidf.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/x86_64/floatundisf.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/builtins/x86_64/floatundixf.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/cfi/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/cfi/cfi.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/cfi/cfi_blacklist.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/dfsan/.clang-format (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/dfsan/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/dfsan/dfsan.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/dfsan/dfsan.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/dfsan/dfsan.syms.extra (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/dfsan/dfsan_custom.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/dfsan/dfsan_flags.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/dfsan/dfsan_interceptors.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/dfsan/dfsan_platform.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/dfsan/done_abilist.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/dfsan/libc_ubuntu1404_abilist.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/dfsan/scripts/build-libc-list.py (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/dfsan/scripts/check_custom_wrappers.sh (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/esan/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/esan/cache_frag.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/esan/cache_frag.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/esan/esan.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/esan/esan.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/esan/esan.syms.extra (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/esan/esan_circular_buffer.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/esan/esan_flags.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/esan/esan_flags.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/esan/esan_flags.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/esan/esan_hashtable.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/esan/esan_interceptors.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/esan/esan_interface.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/esan/esan_interface_internal.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/esan/esan_linux.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/esan/esan_shadow.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/esan/esan_sideline.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/esan/esan_sideline_linux.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/esan/working_set.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/esan/working_set.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/esan/working_set_posix.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/interception/.clang-format (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/interception/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/interception/interception.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/interception/interception_linux.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/interception/interception_linux.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/interception/interception_mac.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/interception/interception_mac.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/interception/interception_type_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/interception/interception_win.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/interception/interception_win.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/interception/tests/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/interception/tests/interception_linux_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/interception/tests/interception_test_main.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/interception/tests/interception_win_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/lsan/.clang-format (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/lsan/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/lsan/lsan.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/lsan/lsan.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/lsan/lsan_allocator.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/lsan/lsan_allocator.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/lsan/lsan_common.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/lsan/lsan_common.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/lsan/lsan_common_linux.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/lsan/lsan_flags.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/lsan/lsan_interceptors.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/lsan/lsan_preinit.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/lsan/lsan_thread.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/lsan/lsan_thread.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/.clang-format (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/msan.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/msan.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/msan.syms.extra (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/msan_allocator.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/msan_allocator.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/msan_blacklist.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/msan_chained_origin_depot.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/msan_chained_origin_depot.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/msan_flags.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/msan_flags.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/msan_interceptors.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/msan_interface_internal.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/msan_linux.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/msan_new_delete.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/msan_origin.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/msan_poisoning.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/msan_poisoning.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/msan_report.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/msan_thread.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/msan_thread.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/tests/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/tests/msan_loadable.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/tests/msan_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/tests/msan_test_config.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/msan/tests/msan_test_main.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/profile/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/profile/GCDAProfiling.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/profile/InstrProfData.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/profile/InstrProfiling.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/profile/InstrProfiling.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/profile/InstrProfilingBuffer.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/profile/InstrProfilingFile.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/profile/InstrProfilingInternal.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/profile/InstrProfilingMerge.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/profile/InstrProfilingMergeFile.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/profile/InstrProfilingPlatformDarwin.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/profile/InstrProfilingPlatformOther.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/profile/InstrProfilingPort.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/profile/InstrProfilingRuntime.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/profile/InstrProfilingUtil.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/profile/InstrProfilingUtil.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/profile/InstrProfilingValue.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/profile/InstrProfilingWriter.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/profile/WindowsMMap.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/profile/WindowsMMap.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/safestack/.clang-format (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/safestack/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/safestack/safestack.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/.clang-format (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/.clang-tidy (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sancov_flags.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sancov_flags.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sancov_flags.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_addrhashmap.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_allocator_bytemap.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_allocator_combined.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_allocator_interface.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_allocator_local_cache.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary32.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_allocator_secondary.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_allocator_size_class_map.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_allocator_stats.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_asm.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_atomic.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_other.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_x86.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_atomic_msvc.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_bitvector.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_bvgraph.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_common.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_common.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_format.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_common_nolibc.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_dbghelp.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector1.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_flag_parser.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_flag_parser.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_flags.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_flags.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_freebsd.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_interface_internal.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_lfstack.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_libc.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_libc.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_libignore.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_libignore.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_linux.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_linux_mips64.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_linux_s390.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_linux_x86_64.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_list.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_mac.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_malloc_mac.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_mutex.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_persistent_allocator.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_persistent_allocator.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_placement_new.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_platform.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_posix.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_printf.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_common.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_freebsd.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_linux.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_mac.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_quarantine.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_report_decorator.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_stackdepotbase.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_internal.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_syscall_linux_aarch64.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_termination.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/sanitizer_win.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/scripts/check_lint.sh (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/scripts/cpplint.py (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/scripts/gen_dynamic_list.py (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/scripts/litlint.py (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/scripts/litlint_test.py (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/scripts/sancov.py (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_symbolize.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_wrappers.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/symbolizer/scripts/global_symbols.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/malloc_stress_transfer_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_testlib.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_atomic_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_bitvector_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_bvgraph_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_deadlock_detector_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_flags_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_format_interceptor_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_ioctl_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_libc_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_linux_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_list_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_mutex_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_nolibc_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_nolibc_test_main.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_printf_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_procmaps_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_pthread_wrappers.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_stackdepot_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_printer_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_stoptheworld_testlib.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_symbolizer_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_test_config.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_test_main.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_test_utils.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/tests/standalone_malloc_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/sanitizer_common/weak_symbols.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/scudo/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/scudo/scudo_allocator.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/scudo/scudo_allocator.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/scudo/scudo_allocator_secondary.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/scudo/scudo_crc32.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/scudo/scudo_crc32.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/scudo/scudo_flags.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/scudo/scudo_flags.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/scudo/scudo_flags.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/scudo/scudo_interceptors.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/scudo/scudo_new_delete.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/scudo/scudo_termination.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/scudo/scudo_utils.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/scudo/scudo_utils.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/stats/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/stats/stats.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/stats/stats.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/stats/stats_client.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/.clang-format (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/analyze_libtsan.sh (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/benchmarks/mini_bench_local.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/benchmarks/mini_bench_shared.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/benchmarks/start_many_threads.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/benchmarks/vts_many_threads_bench.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/check_analyze.sh (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/check_cmake.sh (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/dd/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/dd/dd_interceptors.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/dd/dd_rtl.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/dd/dd_rtl.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/go/build.bat (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/go/buildgo.sh (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/go/test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/go/tsan_go.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan.syms.extra (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_clock.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_clock.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_debugging.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_defs.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_dense_alloc.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_fd.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_fd.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_flags.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_flags.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_flags.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_ignoreset.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_ignoreset.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_interceptors.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_interface.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_interface.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_interface_ann.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_interface_inl.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_interface_java.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_interface_java.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_libdispatch_mac.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_malloc_mac.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_md5.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_mman.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_mman.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_mutex.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_mutex.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_mutexset.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_mutexset.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_new_delete.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_platform.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_platform_windows.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_ppc_regs.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_preinit.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_report.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_report.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_rtl.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_rtl.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_rtl_aarch64.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_rtl_amd64.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_rtl_mips64.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_rtl_ppc64.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_rtl_proc.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_stack_trace.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_stack_trace.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_stat.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_stat.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_suppressions.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_symbolize.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_symbolize.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_sync.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_sync.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_trace.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_update_shadow_word_inl.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/rtl/tsan_vector.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/rtl/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/rtl/tsan_bench.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/rtl/tsan_mop.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/rtl/tsan_mutex.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/rtl/tsan_posix.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/rtl/tsan_posix_util.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/rtl/tsan_string.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/rtl/tsan_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/rtl/tsan_test_util.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/rtl/tsan_test_util_posix.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/rtl/tsan_thread.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/unit/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/unit/tsan_clock_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/unit/tsan_dense_alloc_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/unit/tsan_flags_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/unit/tsan_mman_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/unit/tsan_mutex_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/unit/tsan_mutexset_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/unit/tsan_shadow_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/unit/tsan_stack_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/unit/tsan_sync_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/unit/tsan_unit_test_main.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/tsan/tests/unit/tsan_vector_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/ubsan.syms.extra (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/ubsan_checks.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/ubsan_diag.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/ubsan_diag.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/ubsan_flags.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/ubsan_flags.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/ubsan_flags.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/ubsan_handlers.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/ubsan_handlers.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/ubsan_handlers_cxx.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/ubsan_init.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/ubsan_init.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/ubsan_init_standalone.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/ubsan_platform.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/ubsan_type_hash.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/ubsan_type_hash.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/ubsan_type_hash_itanium.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/ubsan_type_hash_win.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/ubsan_value.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/ubsan_value.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/ubsan/weak_symbols.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/tests/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/tests/unit/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/tests/unit/buffer_queue_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/tests/unit/xray_unit_test_main.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/xray_AArch64.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/xray_arm.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/xray_buffer_queue.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/xray_buffer_queue.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/xray_defs.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/xray_emulate_tsc.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/xray_flags.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/xray_flags.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/xray_flags.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/xray_init.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/xray_inmemory_log.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/xray_interface.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/xray_interface_internal.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/xray_trampoline_AArch64.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/xray_trampoline_arm.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/xray_trampoline_x86_64.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/xray_x86_64.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/lib/xray/xray_x86_64.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/block-static.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/blockimport.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/byrefaccess.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/byrefcopy.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/byrefcopycopy.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/byrefcopyinner.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/byrefcopyint.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/byrefcopystack.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/byrefsanity.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/byrefstruct.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/c99.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/cast.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/constassign.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/copy-block-literal-rdar6439600.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/copyconstructor.C (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/copynull.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/dispatch_async.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/dispatch_call_Block_with_release.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/fail.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/flagsisa.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/globalexpression.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/goto.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/hasdescriptor.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/josh.C (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/k-and-r.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/large-struct.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/localisglobal.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/macro.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/makefile (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/modglobal.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/nestedimport.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/nullblockisa.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/objectRRGC.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/objectassign.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/orbars.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/rdar6396238.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/rdar6405500.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/rdar6414583.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/recursive-block.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/recursive-test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/recursiveassign.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/reference.C (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/rettypepromotion.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/returnfunctionptr.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/shorthandexpression.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/sizeof.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/small-struct.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/structmember.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/testfilerunner.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/testfilerunner.m (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/varargs-bad-assign.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/varargs.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/variadic.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/BlocksRuntime/voidarg.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Android/coverage-android.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Android/lit.local.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/abort_on_error.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/address-range-limit.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/asan_gen_prefixes.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/atos-symbolizer-dyld-root-path.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/atos-symbolizer.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/crashlog-stacktraces.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/cstring_literals_regtest.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/cstring_section.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/dead-strip.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/dladdr-demangling.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/dump_registers.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/dyld_insert_libraries_reexec.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/dyld_insert_libraries_remove.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/empty-section.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/haswell-symbolication.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/interface_symbols_darwin.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/linked-only.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/lit.local.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/malloc_destroy_zone.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/malloc_set_zone_name-mprotect.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/malloc_size_crash.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/malloc_zone-protected.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/mixing-global-constructors.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/objc-odr.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/odr-lto.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/reexec-insert-libraries-env.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/sandbox-symbolizer.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/segv_read_write.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/suppressions-darwin.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/suppressions-sandbox.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/unset-insert-libraries-on-exec.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Darwin/uuid.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Helpers/blacklist-extra.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Helpers/echo-env.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Helpers/init-order-atexit-extra.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Helpers/initialization-blacklist-extra.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Helpers/initialization-blacklist-extra2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Helpers/initialization-blacklist.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Helpers/initialization-bug-extra.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Helpers/initialization-bug-extra2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Helpers/initialization-constexpr-extra.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Helpers/initialization-nobug-extra.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Helpers/lit.local.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/abort_on_error.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/activation-options.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/asan-asm-stacktrace-test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/asan_default_suppressions.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/asan_dlopen_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/asan_prelink_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/asan_preload_test-1.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/asan_preload_test-2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/asan_rt_confict_test-1.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/asan_rt_confict_test-2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/auto_memory_profile_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/calloc-preload.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/clang_gcc_abi.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/clone_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/coverage-missing.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/cuda_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/function-sections-are-bad.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/globals-gc-sections.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/init-order-dlopen.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/init_fini_sections.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/initialization-bug-any-order.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/interception_malloc_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/interception_readdir_r_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/interception_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/kernel-area.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/leak.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/leak_check_segv.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/lit.local.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/local_alias.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/malloc-in-qsort.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/malloc_delete_mismatch.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/memmem_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/mincore.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/new_delete_mismatch.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/nohugepage_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/odr-violation.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/odr_c_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/overflow-in-qsort.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/preinit_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/print_memory_profile_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/pthread_create_from_constructor.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/pthread_create_version.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/ptrace.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/quarantine_size_mb.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/read_binary_name_regtest.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/recvfrom.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/release_to_os_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/rlimit_mmap_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/segv_read_write.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/shmctl.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/signal_during_stop_the_world.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/sized_delete_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/stack-overflow-recovery-mode.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/stack-overflow-sigbus.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/stack-trace-dlclose.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/static_tls.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/stress_dtls.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/swapcontext_annotation.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/swapcontext_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/syscalls.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/thread_local_quarantine_size_kb.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/uar_signals.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Linux/unpoison_tls.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/allow_user_segv.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/asan-symbolize-bad-path.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/asprintf.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/assign_large_valloc_to_global.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/closed-fds.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/coverage-caller-callee.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/coverage-direct-activation.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/coverage-direct-large.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/coverage-direct.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/coverage-fork-direct.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/coverage-fork.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/coverage-maybe-open-file.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/coverage-module-unloaded.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/coverage-sandboxing.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/coverage.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/current_allocated_bytes.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/deep_call_stack.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/deep_thread_stack.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/dlclose-test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/dump_instruction_bytes.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/free_hook_realloc.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/freopen.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/gc-test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/glob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/glob_test_root/aa (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/glob_test_root/ab (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/glob_test_root/ba (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/global-registration.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/halt_on_error-signals.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/halt_on_error-torture.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/handle_abort_on_error.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/init-order-pthread-create.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/interception-in-shared-lib-test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/ioctl.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/large_allocator_unpoisons_on_free.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/lit.local.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/log_path_fork_test.cc.disabled (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/mmap_limit_mb.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/new_array_cookie_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/no_asan_gen_globals.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/print_cmdline.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/readv.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/shared-lib-test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/stack-overflow.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/stack-use-after-return.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/start-deactivated.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/strerror_r_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/tsd_dtor_leak.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/wait.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/wait3.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/wait4.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Posix/waitid.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/aligned_mallocs.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/allocators_sanity.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/beginthreadex.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/bind_io_completion_callback.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/bitfield.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/bitfield_uaf.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/calloc_left_oob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/calloc_right_oob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/calloc_uaf.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/coverage-basic.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/coverage-dll-stdio.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/crash_read_write.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/crt_initializers.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/delay_dbghelp.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/demangled_names.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_aligned_mallocs.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_allocators_sanity.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_and_lib.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_cerr.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_control_c.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_global_dead_strip.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_host.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_intercept_memchr.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_intercept_memcpy.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_intercept_memcpy_indirect.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_intercept_memset.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_intercept_strlen.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_large_function.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_malloc_left_oob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_malloc_uaf.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_noreturn.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_null_deref.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_operator_array_new_left_oob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_operator_array_new_with_dtor_left_oob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_poison_unpoison.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_report_globals_symbolization_at_startup.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_seh.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_stack_use_after_return.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/dll_thread_stack_array_left_oob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/double_free.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/double_operator_delete.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/free_hook_realloc.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/fuse-lld.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/global_const_string.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/global_const_string_oob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/global_dead_strip.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/hello_world.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/intercept_memcpy.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/intercept_strdup.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/intercept_strlen.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/iostream_sbo.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/lit.local.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/longjmp.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/malloc_left_oob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/malloc_right_oob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/malloc_uaf.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/null_deref.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/null_deref_multiple_dlls.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/oom.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/operator_array_new_left_oob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/operator_array_new_right_oob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/operator_array_new_uaf.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/operator_delete_wrong_argument.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/operator_new_left_oob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/operator_new_right_oob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/operator_new_uaf.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/queue_user_work_item.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/queue_user_work_item_report.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/realloc_left_oob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/realloc_right_oob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/realloc_uaf.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/report_after_syminitialize.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/report_globals_reload_dll.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/report_globals_vs_freelibrary.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/seh.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/shadow_conflict_32.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/shadow_mapping_failure.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/stack_array_left_oob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/stack_array_right_oob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/stack_array_sanity.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/stack_use_after_return.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/symbols_path.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/thread_simple.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/thread_stack_array_left_oob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/thread_stack_array_right_oob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/thread_stack_reuse.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/thread_stress.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/thread_suspended.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/tls_init.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/unsymbolized.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/use_after_realloc.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/use_after_return_linkage.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/windows_h.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/wrong_downcast_on_heap.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/Windows/wrong_downcast_on_stack.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/alloca_big_alignment.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/alloca_constant_size.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/alloca_detect_custom_size_.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/alloca_instruments_all_paddings.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/alloca_loop_unpoisoning.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/alloca_overflow_partial.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/alloca_overflow_right.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/alloca_safe_access.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/alloca_underflow_left.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/alloca_vla_interact.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/allocator_returns_null.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/asan_and_llvm_coverage_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/asan_options-help.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/atexit_stats.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/atoi_strict.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/atol_strict.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/atoll_strict.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/blacklist.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/contiguous_container.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/contiguous_container_crash.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/coverage-and-lsan.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/coverage-caller-callee-total-count.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/coverage-disabled.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/coverage-levels.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/coverage-order-pcs.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/coverage-reset.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/coverage-trace-pc.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/coverage-tracing.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/debug_double_free.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/debug_locate.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/debug_mapping.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/debug_ppc64_mapping.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/debug_report.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/debug_stacks.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/deep_stack_uaf.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/deep_tail_call.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/default_blacklist.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/default_options.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/describe_address.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/double-free.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/exitcode.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/force_inline_opt0.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/frexp_interceptor.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/global-address.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/global-demangle.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/global-location.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/global-overflow.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/halt_on_error-1.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/heap-overflow-large.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/heap-overflow.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/heavy_uar_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/huge_negative_hea_oob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/ill.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/init-order-atexit.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/initialization-blacklist.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/initialization-bug.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/initialization-constexpr.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/initialization-nobug.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/inline.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/interception_failure_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/interface_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/intra-object-overflow.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/invalid-free.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/invalid-pointer-pairs.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/large_func_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/log-path_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/longjmp.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/lsan_annotations.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/malloc-no-intercept.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/malloc_context_size.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/malloc_fill.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/max_redzone.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/memcmp_strict_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/memcmp_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/memset_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/null_deref.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/on_error_callback.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/partial_right.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/poison_partial.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/print_summary.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/printf-1.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/printf-2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/printf-3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/printf-4.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/printf-5.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/printf-m.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/sanity_check_pure_c.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/scariness_score_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/set_shadow_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/sleep_before_dying.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/speculative_load.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/speculative_load2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/stack-buffer-overflow-with-position.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/stack-buffer-overflow.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/stack-frame-demangle.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/stack-oob-frames.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strcasestr-1.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strcasestr-2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strcasestr_strict.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strcat_strict.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strchr_strict.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strcmp_strict.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strcspn-1.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strcspn-2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strcspn_strict.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strdup_oob_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strip_path_prefix.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strncasecmp_strict.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strncat_strict.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strncmp_strict.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strncpy-overflow.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strpbrk-1.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strpbrk-2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strpbrk_strict.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strspn-1.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strspn-2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strspn_strict.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strstr-1.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strstr-2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strstr_strict.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strtol_strict.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/strtoll_strict.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/suppressions-exec-relative-location.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/suppressions-function.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/suppressions-interceptor.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/suppressions-library.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/throw_call_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/throw_catch.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/throw_invoke_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/time_interceptor.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/uar_and_exceptions.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/unaligned_loads_and_stores.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/use-after-delete.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/use-after-free-right.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/use-after-free.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/use-after-poison.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/use-after-scope-capture.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/use-after-scope-dtor-order.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/use-after-scope-goto.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/use-after-scope-if.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/use-after-scope-inlined.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/use-after-scope-loop-bug.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/use-after-scope-loop-removed.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/use-after-scope-loop.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/use-after-scope-nobug.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/use-after-scope-temp.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/use-after-scope-temp2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/use-after-scope-types.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/use-after-scope.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/verbose-log-path_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/vla_chrome_testcase.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/vla_condition_overflow.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/vla_loop_overfow.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/TestCases/zero_page_pc.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/Unit/lit.site.cfg.in (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/android_commands/android_common.py (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/android_commands/android_compile.py (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/android_commands/android_run.py (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/lit.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/asan/lit.site.cfg.in (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/absvdi2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/absvsi2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/absvti2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/adddf3vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/addsf3vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/addtf3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/addvdi3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/addvsi3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/addvti3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/arm/aeabi_cdcmpeq_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/arm/aeabi_cdcmple_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/arm/aeabi_cfcmpeq_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/arm/aeabi_cfcmple_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/arm/aeabi_drsub_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/arm/aeabi_frsub_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/arm/call_apsr.S (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/arm/call_apsr.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ashldi3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ashlti3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ashrdi3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ashrti3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/bswapdi2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/bswapsi2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/clear_cache_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/clzdi2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/clzsi2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/clzti2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/cmpdi2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/cmpti2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/comparedf2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/comparesf2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/cpu_model_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ctzdi2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ctzsi2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ctzti2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/divdc3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/divdf3vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/divdi3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/divmodsi4_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/divsc3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/divsf3vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/divsi3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/divtc3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/divtf3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/divti3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/divxc3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/enable_execute_stack_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/endianness.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/eqdf2vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/eqsf2vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/eqtf2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/extebdsfdf2vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/extenddftf2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/extendhfsf2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/extendsftf2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ffsdi2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ffsti2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixdfdi_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixdfsivfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixdfti_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixsfdi_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixsfsivfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixsfti_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixtfdi_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixtfsi_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixtfti_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixunsdfdi_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixunsdfsi_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixunsdfsivfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixunsdfti_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixunssfdi_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixunssfsi_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixunssfsivfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixunssfti_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixunstfdi_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixunstfsi_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixunstfti_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixunsxfdi_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixunsxfsi_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixunsxfti_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixxfdi_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fixxfti_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/floatdidf_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/floatdisf_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/floatditf_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/floatdixf_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/floatsidfvfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/floatsisfvfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/floatsitf_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/floattidf_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/floattisf_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/floattitf_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/floattixf_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/floatundidf_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/floatundisf_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/floatunditf_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/floatundixf_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/floatunsitf_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/floatunssidfvfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/floatunssisfvfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/floatuntidf_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/floatuntisf_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/floatuntitf_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/floatuntixf_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/fp_test.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/gcc_personality_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/gcc_personality_test_helper.cxx (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/gedf2vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/gesf2vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/getf2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/gtdf2vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/gtsf2vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/gttf2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ledf2vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/lesf2vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/letf2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/lshrdi3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/lshrti3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ltdf2vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ltsf2vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/lttf2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/moddi3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/modsi3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/modti3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/muldc3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/muldf3vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/muldi3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/mulodi4_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/mulosi4_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/muloti4_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/mulsc3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/mulsf3vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/multc3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/multf3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/multi3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/mulvdi3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/mulvsi3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/mulvti3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/mulxc3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/nedf2vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/negdf2vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/negdi2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/negsf2vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/negti2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/negvdi2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/negvsi2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/negvti2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/nesf2vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/netf2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/paritydi2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/paritysi2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/parityti2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/popcountdi2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/popcountsi2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/popcountti2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/powidf2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/powisf2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/powitf2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/powixf2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ppc/DD.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ppc/fixtfdi_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ppc/floatditf_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ppc/floatditf_test.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ppc/floatunditf_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ppc/floatunditf_test.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ppc/qadd_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ppc/qdiv_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ppc/qmul_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ppc/qsub_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ppc/test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/subdf3vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/subsf3vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/subtf3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/subvdi3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/subvsi3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/subvti3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/trampoline_setup_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/truncdfhf2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/truncdfsf2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/truncdfsf2vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/truncsfhf2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/trunctfdf2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/trunctfsf2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ucmpdi2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/ucmpti2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/udivdi3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/udivmoddi4_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/udivmodsi4_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/udivmodti4_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/udivsi3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/udivti3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/umoddi3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/umodsi3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/umodti3_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/unorddf2vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/unordsf2vfp_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/Unit/unordtf2_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/timing/ashldi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/timing/ashrdi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/timing/divdi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/timing/floatdidf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/timing/floatdisf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/timing/floatdixf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/timing/floatundidf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/timing/floatundisf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/timing/floatundixf.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/timing/lshrdi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/timing/moddi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/timing/modsi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/timing/muldi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/timing/negdi2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/timing/time (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/timing/timing.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/timing/udivdi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/builtins/timing/umoddi3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/README.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/anon-namespace.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/bad-cast.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/base-derived-destructor.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/create-derivers.test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/cross-dso/dlopen.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/cross-dso/icall/diag.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/cross-dso/icall/icall-from-dso.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/cross-dso/icall/icall.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/cross-dso/icall/lit.local.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/cross-dso/lit.local.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/cross-dso/shadow_is_read_only.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/cross-dso/simple-fail.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/cross-dso/simple-pass.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/cross-dso/stats.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/cross-dso/target_out_of_bounds.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/icall/bad-signature.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/icall/external-call.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/icall/lit.local.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/icall/weak.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/lit.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/lit.site.cfg.in (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/multiple-inheritance.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/nvcall.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/overwrite.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/sibling.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/simple-fail.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/simple-pass.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/stats.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/target_uninstrumented.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/two-vcalls.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/utils.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/cfi/vdtor.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/dfsan/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/dfsan/Inputs/flags_abilist.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/dfsan/basic.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/dfsan/custom.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/dfsan/dump_labels.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/dfsan/flags.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/dfsan/fncall.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/dfsan/label_count.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/dfsan/lit.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/dfsan/lit.site.cfg.in (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/dfsan/propagate.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/dfsan/vararg.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/dfsan/write_callback.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/esan/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/esan/TestCases/large-stack-linux.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/esan/TestCases/libc-intercept.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/esan/TestCases/mmap-shadow-conflict.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/esan/TestCases/struct-simple.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/esan/TestCases/verbose-simple.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/esan/TestCases/workingset-early-fault.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/esan/TestCases/workingset-memset.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/esan/TestCases/workingset-midreport.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/esan/TestCases/workingset-samples.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/esan/TestCases/workingset-signal-posix.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/esan/TestCases/workingset-simple.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/esan/Unit/circular_buffer.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/esan/Unit/hashtable.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/esan/lit.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/esan/lit.site.cfg.in (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/interception/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/interception/Unit/lit.site.cfg.in (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lit.common.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lit.common.configured.in (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/cleanup_in_tsd_destructor.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/disabler.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/disabler.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/disabler_in_tsd_destructor.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/do_leak_check_override.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/fork.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/fork_threaded.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/guard-page.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/high_allocator_contention.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/ignore_object.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/ignore_object_errors.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/large_allocation_leak.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/leak_check_at_exit.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/leak_check_before_thread_started.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/link_turned_off.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/new_array_with_dtor_0.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/pointer_to_self.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/print_suppressions.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/recoverable_leak_check.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/register_root_region.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/sanity_check_pure_c.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/stale_stack_leak.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/strace_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/suppressions_default.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/suppressions_file.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/swapcontext.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/use_after_return.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/use_globals_initialized.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/use_globals_uninitialized.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/use_poisoned_asan.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/use_registers.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/use_stacks.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/use_stacks_threaded.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/use_tls_dynamic.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/use_tls_pthread_specific_dynamic.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/use_tls_pthread_specific_static.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/use_tls_static.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/TestCases/use_unaligned.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/lit.common.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/lsan/lit.site.cfg.in (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/cmsghdr.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/eventfd.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/fopencookie.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/forkpty.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/getresid.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/glob.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/glob_altdirfunc.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/glob_nomatch.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/glob_test_root/aa (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/glob_test_root/ab (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/glob_test_root/ba (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/ioctl_sound.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/lit.local.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/mallinfo.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/mincore.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/obstack.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/process_vm_readv.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/sendmsg.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/sunrpc.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/sunrpc_bytes.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/sunrpc_string.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/syscalls.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/syscalls_sigaction.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/tcgetattr.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/xattr.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Linux/xattr_test_root/a (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/Unit/lit.site.cfg.in (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/allocator_mapping.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/allocator_returns_null.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/backtrace.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/c-strdup.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/chained_origin.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/chained_origin_empty_stack.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/chained_origin_limits.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/chained_origin_memcpy.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/chained_origin_with_signals.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/check_mem_is_initialized.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/coverage-levels.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/ctermid.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/cxa_atexit.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/death-callback.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/default_blacklist.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/dlerror.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/dlopen_executable.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/dso-origin.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/dtls_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/dtor-base-access.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/dtor-bit-fields.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/dtor-derived-class.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/dtor-member.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/dtor-multiple-inheritance-nontrivial-class-members.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/dtor-multiple-inheritance.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/dtor-trivial-class-members.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/dtor-trivial.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/dtor-vtable-multiple-inheritance.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/dtor-vtable.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/errno.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/fork.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/ftime.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/getaddrinfo-positive.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/getaddrinfo.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/getc_unlocked.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/getline.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/getutent.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/heap-origin.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/icmp_slt_allones.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/iconv.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/if_indextoname.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/ifaddrs.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/initgroups.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/inline.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/insertvalue_origin.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/ioctl.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/ioctl_custom.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/lit.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/lit.site.cfg.in (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/memcmp_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/mktime.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/mmap.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/mmap_below_shadow.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/msan_check_mem_is_initialized.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/msan_copy_shadow.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/msan_dump_shadow.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/msan_print_shadow.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/msan_print_shadow2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/msan_print_shadow3.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/mul_by_const.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/no_sanitize_memory.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/no_sanitize_memory_prop.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/origin-store-long.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/param_tls_limit.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/poison_in_free.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/print_stats.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/pthread_getattr_np_deadlock.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/pthread_setcancelstate.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/rand_r.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/readdir64.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/realloc-large-origin.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/realloc-origin.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/recover-dso.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/recover.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/report-demangling.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/scandir.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/scandir_null.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/scandir_test_root/aaa (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/scandir_test_root/aab (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/scandir_test_root/bbb (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/select.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/select_float_origin.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/select_origin.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/sem_getvalue.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/setlocale.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/signal_stress_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/sigwait.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/sigwaitinfo.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/stack-origin.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/stack-origin2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/strerror_r-non-gnu.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/strlen_of_shadow.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/strxfrm.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/sync_lock_set_and_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/test.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/textdomain.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/times.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/tls_reuse.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/tsearch.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/tzset.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/unaligned_read_origin.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/unpoison_string.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/use-after-dtor.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/use-after-free.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/vector_cvt.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/msan/vector_select.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/comdat_rename.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/comdat_rename_1.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/comdat_rename_2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/extern_template.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/extern_template.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/extern_template1.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/extern_template2.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/gcc-flag-compatibility.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/instrprof-alloc.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/instrprof-comdat-1.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/instrprof-comdat-2.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/instrprof-comdat.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/instrprof-dlopen-func.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/instrprof-dlopen-func2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/instrprof-dlopen-main.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/instrprof-dynamic-a.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/instrprof-dynamic-b.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/instrprof-dynamic-header.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/instrprof-dynamic-main.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/instrprof-file_ex.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/instrprof-icall-promo.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/instrprof-icall-promo_1.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/instrprof-icall-promo_2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/instrprof-merge-match-lib.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/instrprof-merge-match.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/instrprof-shared-lib.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/instrprof-shared-main.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/instrprof-value-prof-evict.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/instrprof-value-prof-real.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Inputs/instrprof-visibility-helper.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Linux/comdat_rename.test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Linux/coverage_ctors.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Linux/coverage_dtor.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Linux/coverage_shared.test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Linux/coverage_test.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Linux/extern_template.test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Linux/instrprof-alloc.test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Linux/instrprof-basic.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Linux/instrprof-comdat.test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Linux/instrprof-cs.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Linux/instrprof-dlopen.test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Linux/instrprof-dynamic-one-shared.test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Linux/instrprof-dynamic-two-shared.test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Linux/instrprof-file_ex.test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Linux/instrprof-merge-vp.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Linux/instrprof-value-prof-warn.test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/Linux/lit.local.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/gcc-flag-compatibility.test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-basic.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-bufferio.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-darwin-dead-strip.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-dlopen.test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-dump.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-dynamic-one-shared.test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-dynamic-two-shared.test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-error.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-hostname.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-icall-promo.test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-merge-match.test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-merge.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-override-filename-then-reset-default.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-override-filename-with-env.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-override-filename.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-path.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-reset-counters.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-set-filename-shared.test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-set-filename-then-reset-default.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-set-filename.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-shared.test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-value-prof-2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-value-prof-evict.test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-value-prof-reset.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-value-prof-shared.test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-value-prof.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-value-prof.test (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-version-mismatch.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-visibility-kinds.inc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-visibility.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-without-libc.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-write-file-atexit-explicitly.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-write-file-only.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/instrprof-write-file.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/lit.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/profile/lit.site.cfg.in (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/safestack/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/safestack/buffer-copy-vla.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/safestack/buffer-copy.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/safestack/canary.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/safestack/init.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/safestack/lit.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/safestack/lit.site.cfg.in (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/safestack/lto.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/safestack/overflow.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/safestack/pthread-cleanup.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/safestack/pthread.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/safestack/utils.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Darwin/abort_on_error.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Darwin/lit.local.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Linux/abort_on_error.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Linux/aligned_alloc.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Linux/assert.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Linux/clock_gettime.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Linux/closedir.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Linux/decorate_proc_maps.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Linux/fpe.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Linux/hard_rss_limit_mb_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Linux/ill.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Linux/lit.local.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Linux/mlock_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Linux/open_memstream.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Linux/ptrace.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Linux/recv_msg_trunc.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Linux/sched_getparam.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Linux/timerfd.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Linux/weak_hook_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Posix/dedup_token_length_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Posix/getpass.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Posix/lit.local.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_death_callback_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_fd_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/corelimit.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/fopen_nullptr.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/malloc_hook.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/options-help.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/options-include.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/options-invalid.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/print-stack-trace.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/pthread_mutexattr_get.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_symbolize.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/strcasestr.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/strcspn.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/strnlen.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/strpbrk.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/strspn.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/strstr.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/TestCases/symbolize_pc.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/Unit/lit.site.cfg.in (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/lit.common.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/lit.site.cfg.in (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/sanitizer_common/print_address.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/scudo/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/scudo/alignment.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/scudo/double-free.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/scudo/interface.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/scudo/lit.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/scudo/lit.site.cfg.in (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/scudo/malloc.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/scudo/memalign.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/scudo/mismatch.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/scudo/options.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/scudo/overflow.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/scudo/preinit.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/scudo/quarantine.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/scudo/random_shuffle.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/scudo/realloc.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/scudo/secondary.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/scudo/sized-delete.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/scudo/sizes.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/dispatch_main.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/dispatch_once_deadlock.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/dlopen.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-after.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-apply-race.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-apply.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-async-norace.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-async-race.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-barrier-race.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-barrier.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-blocks.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-data.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-fd.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-groups-destructor.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-groups-leave.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-groups-norace.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-groups-stress.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-io-barrier-race.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-io-barrier.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-io-cleanup.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-io-race.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-io.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-once.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-semaphore-norace.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-serial-queue-norace.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-source-cancel.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-source-cancel2.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-source-event.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-source-event2.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-source-registration.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-source-registration2.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-source-serial.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-suspend.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-sync-norace.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-sync-race.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/gcd-target-queue-norace.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/ignore-noninstrumented.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/ignored-interceptors.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/libcxx-call-once.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/libcxx-future.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/libcxx-shared-ptr-recursive.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/libcxx-shared-ptr-stress.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/libcxx-shared-ptr.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/lit.local.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/malloc-stack-logging.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/malloc_size.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/norace-objcxx-run-time.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/objc-double-property.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/objc-race.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/objc-simple.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/osatomics-add.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/osatomics-bitops.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/osatomics-list.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/osspinlock-norace.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/realloc-zero.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/symbolizer-atos.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/symbolizer-dladdr.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/xpc-race.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Darwin/xpc.mm (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Linux/check_memcpy.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Linux/check_preinit.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Linux/lit.local.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Linux/mutex_robust.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Linux/mutex_robust2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Linux/user_fopen.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Linux/user_malloc.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/Unit/lit.site.cfg.in (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/aligned_vs_unaligned_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/allocator_returns_null.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/annotate_happens_before.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/atexit.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/atexit2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/atomic_free.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/atomic_free2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/atomic_free3.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/atomic_norace.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/atomic_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/atomic_stack.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/atomic_store.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/barrier.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/bench.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/bench_acquire_only.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/bench_acquire_release.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/bench_local_mutex.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/bench_mutex.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/bench_release_only.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/bench_rwmutex.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/bench_shadow_flush.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/bench_single_writer.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/bench_ten_mutexes.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/benign_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/blacklist.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/blacklist2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/cond.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/cond_cancel.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/cond_destruction.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/cond_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/cond_version.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/deadlock_detector_stress_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/debug_alloc_stack.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/debug_locate.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/debugging.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/deep_stack1.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/default_options.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/deflake.bash (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/dl_iterate_phdr.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/dlclose.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/dtls.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/exceptions.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/fd_close_norace.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/fd_close_norace2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/fd_dup_norace.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/fd_dup_norace2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/fd_dup_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/fd_location.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/fd_pipe_norace.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/fd_pipe_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/fd_socket_connect_norace.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/fd_socket_norace.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/fd_socketpair_norace.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/fd_stdout_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/fd_tid_recycled.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/fork_atexit.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/fork_deadlock.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/fork_multithreaded.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/fork_multithreaded3.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/free_race.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/free_race.c.supp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/free_race2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/getline_nohang.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/global_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/global_race2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/global_race3.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/halt_on_error.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/heap_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/ignore_free.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/ignore_lib0.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/ignore_lib0.cc.supp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/ignore_lib1.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/ignore_lib1.cc.supp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/ignore_lib2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/ignore_lib2.cc.supp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/ignore_lib3.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/ignore_lib3.cc.supp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/ignore_lib4.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/ignore_lib5.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/ignore_lib5.cc.supp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/ignore_lib_lib.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/ignore_malloc.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/ignore_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/ignore_sync.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/ignored-interceptors-mmap.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/inlined_memcpy_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/inlined_memcpy_race2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/interface_atomic_test.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/java.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/java_alloc.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/java_finalizer.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/java_heap_init.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/java_lock.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/java_lock_move.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/java_lock_rec.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/java_lock_rec_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/java_move_overlap.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/java_move_overlap_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/java_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/java_race_move.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/java_race_pc.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/java_rwlock.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/java_symbolization.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/java_volatile.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/large_malloc_meta.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/libcxx/lit.local.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/libcxx/std_shared_ptr.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/lit.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/lit.site.cfg.in (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/load_shared_lib.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/longjmp.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/longjmp2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/longjmp3.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/longjmp4.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/lots_of_threads.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/malloc_overflow.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/malloc_stack.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/map32bit.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/memcmp_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/memcpy_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/mmap_large.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/mmap_stress.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/mop1.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/mop_with_offset.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/mop_with_offset2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/must_deadlock.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/mutex_annotations.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/mutex_bad_read_lock.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/mutex_bad_read_unlock.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/mutex_bad_unlock.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/mutex_cycle2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/mutex_cycle_long.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/mutex_destroy_locked.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/mutex_double_lock.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/mutex_lock_destroyed.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/mutexset1.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/mutexset2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/mutexset3.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/mutexset4.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/mutexset5.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/mutexset6.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/mutexset7.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/mutexset8.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/pie_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/printf-1.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/pthread_atfork_deadlock.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/pthread_key.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/race_on_barrier.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/race_on_barrier2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/race_on_heap.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/race_on_mutex.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/race_on_mutex2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/race_on_puts.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/race_on_read.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/race_on_speculative_load.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/race_on_write.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/race_stress.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/race_top_suppression.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/race_top_suppression1.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/race_with_finished_thread.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/real_deadlock_detector_stress_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/restore_stack.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/setuid.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/setuid2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/signal_block.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/signal_cond.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/signal_errno.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/signal_longjmp.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/signal_malloc.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/signal_recursive.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/signal_reset.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/signal_sync.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/signal_sync2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/signal_thread.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/signal_write.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/sigsuspend.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/simple_race.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/simple_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/simple_stack.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/simple_stack2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/sleep_sync.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/sleep_sync2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/stack_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/stack_race2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/stack_sync_reuse.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/static_init1.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/static_init2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/static_init3.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/static_init4.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/static_init5.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/static_init6.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/sunrpc.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/suppress_same_address.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/suppress_same_stacks.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/suppressions_global.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/suppressions_global.cc.supp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/suppressions_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/suppressions_race.cc.supp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/suppressions_race2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/suppressions_race2.cc.supp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/test.h (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/thread_detach.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/thread_detach2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/thread_end_with_ignore.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/thread_end_with_ignore2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/thread_end_with_ignore3.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/thread_leak.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/thread_leak2.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/thread_leak3.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/thread_leak4.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/thread_leak5.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/thread_name.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/thread_name2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/tiny_race.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/tls_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/tls_race2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/tsan-vs-gvn.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/unaligned_norace.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/unaligned_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/vfork.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/virtual_inheritance_compile_bug.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/vptr_benign_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/vptr_harmful_race.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/vptr_harmful_race2.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/vptr_harmful_race3.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/vptr_harmful_race4.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/tsan/write_in_reader_lock.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Integer/add-overflow.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Integer/div-overflow.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Integer/div-zero.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Integer/incdec-overflow.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Integer/mul-overflow.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Integer/negate-overflow.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Integer/no-recover.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Integer/shift.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Integer/sub-overflow.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Integer/summary.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Integer/suppressions.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Integer/uadd-overflow.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Integer/uincdec-overflow.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Integer/umul-overflow.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Integer/usub-overflow.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Misc/Linux/lit.local.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Misc/Linux/ubsan_options.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Misc/bool.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Misc/bounds.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Misc/coverage-levels.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Misc/deduplication.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Misc/enum.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Misc/missing_return.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Misc/nonnull-arg.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Misc/nonnull.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Misc/unreachable.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/Misc/vla.c (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/TypeCheck/Function/lit.local.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/TypeCheck/misaligned.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/TypeCheck/null.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-corrupted-vtable-itanium.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-non-unique-typeinfo.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-virtual-base-construction.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr.cpp (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/lit.common.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/ubsan/lit.site.cfg.in (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/xray/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/xray/TestCases/Linux/argv0-log-file-name.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/xray/TestCases/Linux/fixedsize-logging.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/xray/TestCases/Linux/optional-inmemory-log.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/xray/TestCases/Linux/patching-unpatching.cc (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/xray/Unit/lit.site.cfg.in (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/xray/lit.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/test/xray/lit.site.cfg.in (100%) rename src/{ => libcompiler_builtins}/compiler-rt/unittests/CMakeLists.txt (100%) rename src/{ => libcompiler_builtins}/compiler-rt/unittests/lit.common.unit.cfg (100%) rename src/{ => libcompiler_builtins}/compiler-rt/unittests/lit.common.unit.configured.in (100%) rename src/{ => libcompiler_builtins}/compiler-rt/www/content.css (100%) rename src/{ => libcompiler_builtins}/compiler-rt/www/index.html (100%) rename src/{ => libcompiler_builtins}/compiler-rt/www/menu.css (100%) rename src/{ => libcompiler_builtins}/compiler-rt/www/menu.html.incl (100%) create mode 100644 src/libcompiler_builtins/examples/intrinsics.rs delete mode 100644 src/libcompiler_builtins/lib.rs create mode 100644 src/libcompiler_builtins/src/arm.rs create mode 100644 src/libcompiler_builtins/src/float/add.rs create mode 100644 src/libcompiler_builtins/src/float/conv.rs create mode 100644 src/libcompiler_builtins/src/float/mod.rs create mode 100644 src/libcompiler_builtins/src/float/pow.rs create mode 100644 src/libcompiler_builtins/src/float/sub.rs create mode 100644 src/libcompiler_builtins/src/int/mod.rs create mode 100644 src/libcompiler_builtins/src/int/mul.rs create mode 100644 src/libcompiler_builtins/src/int/sdiv.rs create mode 100644 src/libcompiler_builtins/src/int/shift.rs create mode 100644 src/libcompiler_builtins/src/int/udiv.rs create mode 100644 src/libcompiler_builtins/src/lib.rs create mode 100644 src/libcompiler_builtins/src/macros.rs create mode 100644 src/libcompiler_builtins/src/mem.rs create mode 100644 src/libcompiler_builtins/src/probestack.rs create mode 100644 src/libcompiler_builtins/src/x86_64.rs create mode 100644 src/libcompiler_builtins/tests/adddf3.rs create mode 100644 src/libcompiler_builtins/tests/addsf3.rs create mode 100644 src/libcompiler_builtins/tests/aeabi_memclr.rs create mode 100644 src/libcompiler_builtins/tests/aeabi_memcpy.rs create mode 100644 src/libcompiler_builtins/tests/aeabi_memset.rs create mode 100644 src/libcompiler_builtins/tests/ashldi3.rs create mode 100644 src/libcompiler_builtins/tests/ashlti3.rs create mode 100644 src/libcompiler_builtins/tests/ashrdi3.rs create mode 100644 src/libcompiler_builtins/tests/ashrti3.rs create mode 100644 src/libcompiler_builtins/tests/divdi3.rs create mode 100644 src/libcompiler_builtins/tests/divmoddi4.rs create mode 100644 src/libcompiler_builtins/tests/divmodsi4.rs create mode 100644 src/libcompiler_builtins/tests/divsi3.rs create mode 100644 src/libcompiler_builtins/tests/divti3.rs create mode 100644 src/libcompiler_builtins/tests/fixdfdi.rs create mode 100644 src/libcompiler_builtins/tests/fixdfsi.rs create mode 100644 src/libcompiler_builtins/tests/fixdfti.rs create mode 100644 src/libcompiler_builtins/tests/fixsfdi.rs create mode 100644 src/libcompiler_builtins/tests/fixsfsi.rs create mode 100644 src/libcompiler_builtins/tests/fixsfti.rs create mode 100644 src/libcompiler_builtins/tests/fixunsdfdi.rs create mode 100644 src/libcompiler_builtins/tests/fixunsdfsi.rs create mode 100644 src/libcompiler_builtins/tests/fixunsdfti.rs create mode 100644 src/libcompiler_builtins/tests/fixunssfdi.rs create mode 100644 src/libcompiler_builtins/tests/fixunssfsi.rs create mode 100644 src/libcompiler_builtins/tests/fixunssfti.rs create mode 100644 src/libcompiler_builtins/tests/floatdidf.rs create mode 100644 src/libcompiler_builtins/tests/floatsidf.rs create mode 100644 src/libcompiler_builtins/tests/floatsisf.rs create mode 100644 src/libcompiler_builtins/tests/floattidf.rs create mode 100644 src/libcompiler_builtins/tests/floattisf.rs create mode 100644 src/libcompiler_builtins/tests/floatundidf.rs create mode 100644 src/libcompiler_builtins/tests/floatunsidf.rs create mode 100644 src/libcompiler_builtins/tests/floatunsisf.rs create mode 100644 src/libcompiler_builtins/tests/floatuntidf.rs create mode 100644 src/libcompiler_builtins/tests/floatuntisf.rs create mode 100644 src/libcompiler_builtins/tests/lshrdi3.rs create mode 100644 src/libcompiler_builtins/tests/lshrti3.rs create mode 100644 src/libcompiler_builtins/tests/moddi3.rs create mode 100644 src/libcompiler_builtins/tests/modsi3.rs create mode 100644 src/libcompiler_builtins/tests/modti3.rs create mode 100644 src/libcompiler_builtins/tests/muldi3.rs create mode 100644 src/libcompiler_builtins/tests/mulodi4.rs create mode 100644 src/libcompiler_builtins/tests/mulosi4.rs create mode 100644 src/libcompiler_builtins/tests/muloti4.rs create mode 100644 src/libcompiler_builtins/tests/multi3.rs create mode 100644 src/libcompiler_builtins/tests/powidf2.rs create mode 100644 src/libcompiler_builtins/tests/powisf2.rs create mode 100644 src/libcompiler_builtins/tests/subdf3.rs create mode 100644 src/libcompiler_builtins/tests/subsf3.rs create mode 100644 src/libcompiler_builtins/tests/udivdi3.rs create mode 100644 src/libcompiler_builtins/tests/udivmoddi4.rs create mode 100644 src/libcompiler_builtins/tests/udivmodsi4.rs create mode 100644 src/libcompiler_builtins/tests/udivmodti4.rs create mode 100644 src/libcompiler_builtins/tests/udivsi3.rs create mode 100644 src/libcompiler_builtins/tests/udivti3.rs create mode 100644 src/libcompiler_builtins/tests/umoddi3.rs create mode 100644 src/libcompiler_builtins/tests/umodsi3.rs create mode 100644 src/libcompiler_builtins/tests/umodti3.rs create mode 100644 src/libcompiler_builtins/thumbv6m-linux-eabi.json create mode 100644 src/libcompiler_builtins/thumbv7em-linux-eabi.json create mode 100644 src/libcompiler_builtins/thumbv7em-linux-eabihf.json create mode 100644 src/libcompiler_builtins/thumbv7m-linux-eabi.json delete mode 100644 src/libcore/ops.rs create mode 100644 src/libcore/ops/arith.rs create mode 100644 src/libcore/ops/bit.rs create mode 100644 src/libcore/ops/deref.rs create mode 100644 src/libcore/ops/drop.rs create mode 100644 src/libcore/ops/function.rs create mode 100644 src/libcore/ops/index.rs create mode 100644 src/libcore/ops/mod.rs create mode 100644 src/libcore/ops/place.rs create mode 100644 src/libcore/ops/range.rs create mode 100644 src/libcore/ops/try.rs create mode 100644 src/libcore/ops/unsize.rs delete mode 100644 src/libflate/lib.rs delete mode 100644 src/libgetopts/Cargo.toml create mode 100644 src/liblibc/ci/android-sysimage.sh create mode 100644 src/liblibc/src/unix/uclibc/mips/mips32.rs create mode 100644 src/liblibc/src/unix/uclibc/mips/mips64.rs create mode 100644 src/liblibc/src/unix/uclibc/mips/mod.rs create mode 100644 src/liblibc/src/unix/uclibc/mod.rs create mode 100644 src/liblibc/src/unix/uclibc/x86_64/mod.rs create mode 100644 src/libproc_macro/quote.rs delete mode 100644 src/libproc_macro_plugin/lib.rs delete mode 100644 src/libproc_macro_plugin/quote.rs rename src/{libflate => libprofiler_builtins}/Cargo.toml (51%) create mode 100644 src/libprofiler_builtins/build.rs create mode 100644 src/libprofiler_builtins/lib.rs delete mode 100644 src/librustc/dep_graph/shadow.rs delete mode 100644 src/librustc/dep_graph/thread.rs create mode 100644 src/librustc/infer/error_reporting/named_anon_conflict.rs create mode 100644 src/librustc/infer/error_reporting/need_type_info.rs create mode 100644 src/librustc/middle/allocator.rs rename src/{libproc_macro_plugin => librustc_allocator}/Cargo.toml (64%) create mode 100644 src/librustc_allocator/expand.rs create mode 100644 src/librustc_allocator/lib.rs create mode 100644 src/librustc_back/target/msp430_none_elf.rs create mode 100644 src/librustc_back/target/wasm32_experimental_emscripten.rs rename src/{librustc_borrowck/borrowck/mir/mod.rs => librustc_mir/dataflow/drop_flag_effects.rs} (67%) rename src/{librustc_borrowck/borrowck/mir => librustc_mir}/dataflow/graphviz.rs (97%) rename src/{librustc_borrowck/borrowck/mir/dataflow/impls.rs => librustc_mir/dataflow/impls/mod.rs} (96%) rename src/{librustc_borrowck/borrowck/mir => librustc_mir}/dataflow/mod.rs (95%) rename src/{librustc_borrowck/borrowck/mir => librustc_mir/dataflow/move_paths}/abs_domain.rs (100%) rename src/{librustc_borrowck/borrowck/mir/gather_moves.rs => librustc_mir/dataflow/move_paths/mod.rs} (98%) create mode 100644 src/librustc_mir/transform/clean_end_regions.rs rename src/{librustc_borrowck/borrowck/mir => librustc_mir/transform}/elaborate_drops.rs (93%) rename src/{librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs => librustc_mir/transform/rustc_peek.rs} (69%) delete mode 100644 src/librustc_save_analysis/csv_dumper.rs delete mode 100644 src/librustc_save_analysis/data.rs delete mode 100644 src/librustc_save_analysis/dump.rs delete mode 100644 src/librustc_save_analysis/external_data.rs create mode 100644 src/librustc_save_analysis/sig.rs create mode 100644 src/librustc_trans/allocator.rs create mode 100644 src/libstd/heap.rs rename src/{test/compile-fail/non-constant-expr-for-fixed-len-vec.rs => libstd/sys/windows/fast_thread_local.rs} (58%) create mode 100644 src/libstd_unicode/lossy.rs rename src/{test/compile-fail/auxiliary/allocator2.rs => libstd_unicode/tests/lib.rs} (72%) create mode 100644 src/libstd_unicode/tests/lossy.rs create mode 100644 src/libsyntax_ext/compile_error.rs delete mode 100644 src/rt/miniz.c create mode 100644 src/rustc/compiler_builtins_shim/Cargo.toml rename src/{libflate => rustc/compiler_builtins_shim}/build.rs (74%) create mode 100644 src/rustllvm/.editorconfig create mode 100644 src/test/codegen/alloc-optimisation.rs create mode 100644 src/test/codegen/dealloc-no-unwind.rs create mode 100644 src/test/codegen/issue-37945.rs rename src/test/{compile-fail/allocator-depends-on-needs-allocators.rs => codegen/stack-probes.rs} (53%) create mode 100644 src/test/codegen/vec-optimizes-away.rs create mode 100644 src/test/compile-fail-fulldeps/proc-macro/auxiliary/bang_proc_macro2.rs create mode 100644 src/test/compile-fail-fulldeps/proc-macro/lints_in_proc_macros.rs create mode 100644 src/test/compile-fail/E0602.rs create mode 100644 src/test/compile-fail/E0604.rs create mode 100644 src/test/compile-fail/E0605.rs create mode 100644 src/test/compile-fail/E0606.rs create mode 100644 src/test/compile-fail/E0607.rs create mode 100644 src/test/compile-fail/E0608.rs create mode 100644 src/test/compile-fail/E0609.rs create mode 100644 src/test/compile-fail/E0610.rs create mode 100644 src/test/compile-fail/E0611.rs create mode 100644 src/test/compile-fail/E0612.rs create mode 100644 src/test/compile-fail/E0614.rs create mode 100644 src/test/compile-fail/E0615.rs create mode 100644 src/test/compile-fail/E0616.rs create mode 100644 src/test/compile-fail/E0617.rs rename src/test/{run-pass/allocator-default.rs => compile-fail/E0618.rs} (58%) create mode 100644 src/test/compile-fail/E0619.rs create mode 100644 src/test/compile-fail/E0620.rs create mode 100644 src/test/compile-fail/E0621-does-not-trigger-for-closures.rs rename src/test/compile-fail/{invalid-intrinsic.rs => E0622.rs} (86%) delete mode 100644 src/test/compile-fail/allocator-dylib-is-system.rs delete mode 100644 src/test/compile-fail/allocator-rust-dylib-is-jemalloc.rs rename src/test/compile-fail/{auxiliary/allocator3.rs => allocator/auxiliary/system-allocator.rs} (71%) create mode 100644 src/test/compile-fail/allocator/auxiliary/system-allocator2.rs create mode 100644 src/test/compile-fail/allocator/function-allocator.rs create mode 100644 src/test/compile-fail/allocator/not-an-allocator.rs create mode 100644 src/test/compile-fail/allocator/two-allocators.rs create mode 100644 src/test/compile-fail/allocator/two-allocators2.rs create mode 100644 src/test/compile-fail/allocator/two-allocators3.rs create mode 100644 src/test/compile-fail/auxiliary/issue-36881-aux.rs rename src/test/compile-fail/auxiliary/{allocator-dylib.rs => lint_unused_extern_crate2.rs} (78%) create mode 100644 src/test/compile-fail/auxiliary/lint_unused_extern_crate3.rs create mode 100644 src/test/compile-fail/auxiliary/lint_unused_extern_crate4.rs create mode 100644 src/test/compile-fail/auxiliary/private-inferred-type.rs delete mode 100644 src/test/compile-fail/cast-to-unsized-trait-object-suggestion.rs create mode 100644 src/test/compile-fail/compile_error_macro.rs rename src/test/compile-fail/{two-allocators-2.rs => dollar-crate-is-keyword-2.rs} (56%) create mode 100644 src/test/compile-fail/dollar-crate-is-keyword.rs create mode 100644 src/test/compile-fail/dst-bad-assign-3.rs rename src/test/{run-make/no-duplicate-libs/bar.rs => compile-fail/dst-bad-deep-2.rs} (50%) rename src/test/{run-pass/auxiliary/clibrary.rs => compile-fail/feature-gate-allocator_internals.rs} (81%) rename src/test/{run-pass/allocator-system.rs => compile-fail/feature-gate-allow_fail.rs} (75%) create mode 100644 src/test/compile-fail/feature-gate-global_allocator.rs create mode 100644 src/test/compile-fail/feature-gate-profiler-runtime.rs create mode 100644 src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs rename src/test/{run-pass => compile-fail}/hygiene/auxiliary/intercrate.rs (100%) rename src/test/{run-pass => compile-fail}/hygiene/fields.rs (78%) rename src/test/{run-pass => compile-fail}/hygiene/impl_items.rs (91%) rename src/test/{run-pass => compile-fail}/hygiene/intercrate.rs (89%) create mode 100644 src/test/compile-fail/issue-11740.rs create mode 100644 src/test/compile-fail/issue-19601.rs create mode 100644 src/test/compile-fail/issue-22603.rs create mode 100644 src/test/compile-fail/issue-22789.rs rename src/test/compile-fail/{dep-graph-unrelated.rs => issue-26614.rs} (57%) create mode 100644 src/test/compile-fail/issue-34222-1.rs create mode 100644 src/test/compile-fail/issue-34222.rs create mode 100644 src/test/compile-fail/issue-34373.rs create mode 100644 src/test/compile-fail/issue-35570.rs create mode 100644 src/test/compile-fail/issue-36839.rs create mode 100644 src/test/compile-fail/issue-37051.rs create mode 100644 src/test/compile-fail/issue-37323.rs create mode 100644 src/test/compile-fail/issue-37366.rs create mode 100644 src/test/compile-fail/issue-37510.rs create mode 100644 src/test/compile-fail/issue-37515.rs create mode 100644 src/test/compile-fail/issue-38381.rs create mode 100644 src/test/compile-fail/issue-41998.rs create mode 100644 src/test/compile-fail/issue-42312.rs create mode 100644 src/test/compile-fail/issue-42755.rs create mode 100644 src/test/compile-fail/issue-42880.rs create mode 100644 src/test/compile-fail/issue-43250.rs create mode 100644 src/test/compile-fail/issue-43424.rs create mode 100644 src/test/compile-fail/method-call-type-binding.rs rename src/test/compile-fail/{non-constant-expr-for-vec-repeat.rs => non-constant-expr-for-arr-len.rs} (84%) create mode 100644 src/test/compile-fail/patkind-litrange-no-expr.rs create mode 100644 src/test/compile-fail/private-inferred-type-1.rs create mode 100644 src/test/compile-fail/private-inferred-type-2.rs create mode 100644 src/test/compile-fail/private-inferred-type-3.rs create mode 100644 src/test/compile-fail/private-inferred-type.rs create mode 100644 src/test/compile-fail/private-type-in-interface.rs create mode 100644 src/test/compile-fail/rust-unstable-column-gated.rs delete mode 100644 src/test/compile-fail/two-allocators-3.rs create mode 100644 src/test/compile-fail/use-self-type.rs create mode 100644 src/test/incremental/issue-42602.rs create mode 100644 src/test/incremental/spans_in_type_debuginfo.rs create mode 100644 src/test/mir-opt/end_region_1.rs create mode 100644 src/test/mir-opt/end_region_2.rs create mode 100644 src/test/mir-opt/end_region_3.rs create mode 100644 src/test/mir-opt/end_region_4.rs create mode 100644 src/test/mir-opt/end_region_5.rs create mode 100644 src/test/mir-opt/end_region_6.rs create mode 100644 src/test/mir-opt/end_region_7.rs create mode 100644 src/test/mir-opt/end_region_8.rs create mode 100644 src/test/mir-opt/end_region_9.rs create mode 100644 src/test/parse-fail/underscore-suffix-for-string.rs rename src/test/{compile-fail/variance-region-bounds.rs => run-fail/assert-ne-macro-panic.rs} (66%) rename src/test/{compile-fail/auxiliary/allocator1.rs => run-make/no-duplicate-libs/bar.c} (72%) create mode 100644 src/test/run-make/no-duplicate-libs/foo.c create mode 100644 src/test/run-make/profile/Makefile create mode 100644 src/test/run-make/profile/test.rs create mode 100644 src/test/run-make/rustdoc-output-path/Makefile create mode 100644 src/test/run-make/rustdoc-output-path/foo.rs create mode 100644 src/test/run-make/sanitizer-cdylib-link/Makefile create mode 100644 src/test/run-make/sanitizer-cdylib-link/library.rs create mode 100644 src/test/run-make/sanitizer-cdylib-link/program.rs create mode 100644 src/test/run-make/sanitizer-dylib-link/Makefile create mode 100644 src/test/run-make/sanitizer-dylib-link/library.rs create mode 100644 src/test/run-make/sanitizer-dylib-link/program.rs delete mode 100644 src/test/run-make/sanitizer-dylib/Makefile create mode 100644 src/test/run-make/sanitizer-invalid-cratetype/Makefile rename src/test/run-make/{sanitizer-dylib => sanitizer-invalid-cratetype}/hello.rs (100%) create mode 100644 src/test/run-make/sanitizer-staticlib-link/Makefile create mode 100644 src/test/run-make/sanitizer-staticlib-link/library.rs create mode 100644 src/test/run-make/sanitizer-staticlib-link/program.c create mode 100644 src/test/run-make/type-mismatch-same-crate-name/Makefile create mode 100644 src/test/run-make/type-mismatch-same-crate-name/crateA.rs create mode 100644 src/test/run-make/type-mismatch-same-crate-name/crateB.rs create mode 100644 src/test/run-make/type-mismatch-same-crate-name/crateC.rs create mode 100644 src/test/run-make/windows-spawn/Makefile create mode 100644 src/test/run-make/windows-spawn/hello.rs create mode 100644 src/test/run-make/windows-spawn/spawn.rs delete mode 100644 src/test/run-pass-fulldeps/macro-quote-1.rs create mode 100644 src/test/run-pass-fulldeps/proc-macro/auxiliary/count_compound_ops.rs create mode 100644 src/test/run-pass-fulldeps/proc-macro/auxiliary/hygiene_example.rs create mode 100644 src/test/run-pass-fulldeps/proc-macro/auxiliary/hygiene_example_codegen.rs create mode 100644 src/test/run-pass-fulldeps/proc-macro/count_compound_ops.rs create mode 100644 src/test/run-pass-fulldeps/proc-macro/hygiene_example.rs create mode 100644 src/test/run-pass-fulldeps/stdio-from.rs rename src/test/{run-make/no-duplicate-libs/foo.rs => run-pass-valgrind/dst-dtor-3.rs} (51%) create mode 100644 src/test/run-pass-valgrind/dst-dtor-4.rs create mode 100644 src/test/run-pass/allocator-alloc-one.rs delete mode 100644 src/test/run-pass/allocator-override.rs create mode 100644 src/test/run-pass/allocator/auxiliary/custom-as-global.rs create mode 100644 src/test/run-pass/allocator/auxiliary/custom.rs rename src/test/{compile-fail/auxiliary/needs_allocator.rs => run-pass/allocator/auxiliary/helper.rs} (77%) create mode 100644 src/test/run-pass/allocator/custom.rs create mode 100644 src/test/run-pass/allocator/xcrate-use.rs create mode 100644 src/test/run-pass/allocator/xcrate-use2.rs create mode 100644 src/test/run-pass/dst-trait-tuple.rs create mode 100644 src/test/run-pass/dst-tuple-sole.rs create mode 100644 src/test/run-pass/dst-tuple.rs create mode 100644 src/test/run-pass/env.rs delete mode 100644 src/test/run-pass/getopts_ref.rs create mode 100644 src/test/run-pass/issue-37725.rs rename src/test/{compile-fail/struct-field-attr-feature-gate.rs => run-pass/issue-40847.rs} (60%) create mode 100644 src/test/run-pass/issue-40883.rs create mode 100644 src/test/run-pass/issue-42679.rs create mode 100644 src/test/run-pass/issue-42747.rs create mode 100644 src/test/run-pass/issue-43057.rs create mode 100644 src/test/run-pass/issue-43923.rs create mode 100644 src/test/run-pass/macro-first-set.rs create mode 100644 src/test/run-pass/macro-pat-neg-lit.rs create mode 100644 src/test/run-pass/rfc1857-drop-order.rs rename src/test/{compile-fail/feature-gate-allocator.rs => run-pass/rustc-rust-log.rs} (79%) create mode 100644 src/test/run-pass/stack-probes-lto.rs create mode 100644 src/test/run-pass/stack-probes.rs create mode 100644 src/test/run-pass/test-allow-fail-attr.rs create mode 100644 src/test/run-pass/tls-try-with.rs create mode 100644 src/test/run-pass/unsized-tuple-impls.rs create mode 100644 src/test/rustdoc/empty-mod-private.rs create mode 100644 src/test/rustdoc/empty-mod-public.rs create mode 100644 src/test/rustdoc/issue-35488.rs create mode 100644 src/test/rustdoc/issue-42875.rs rename src/test/{compile-fail/gated-associated_consts.rs => rustdoc/issue-43153.rs} (58%) create mode 100644 src/test/rustdoc/typedef.rs create mode 100644 src/test/ui-fulldeps/auxiliary/attr_proc_macro.rs create mode 100644 src/test/ui-fulldeps/auxiliary/bang_proc_macro.rs create mode 100644 src/test/ui-fulldeps/auxiliary/derive-clona.rs create mode 100644 src/test/ui-fulldeps/auxiliary/derive-foo.rs rename src/test/{compile-fail-fulldeps/proc-macro => ui-fulldeps}/resolve-error.rs (57%) create mode 100644 src/test/ui-fulldeps/resolve-error.stderr delete mode 100644 src/test/ui/README.md rename src/test/{compile-fail => ui/block-result}/block-must-not-have-result-do.rs (100%) create mode 100644 src/test/ui/block-result/block-must-not-have-result-do.stderr rename src/test/{compile-fail => ui/block-result}/block-must-not-have-result-res.rs (100%) create mode 100644 src/test/ui/block-result/block-must-not-have-result-res.stderr rename src/test/{compile-fail => ui/block-result}/block-must-not-have-result-while.rs (100%) create mode 100644 src/test/ui/block-result/block-must-not-have-result-while.stderr rename src/test/{compile-fail => ui/block-result}/consider-removing-last-semi.rs (100%) create mode 100644 src/test/ui/block-result/consider-removing-last-semi.stderr rename src/test/{compile-fail => ui/block-result}/issue-11714.rs (100%) create mode 100644 src/test/ui/block-result/issue-11714.stderr rename src/test/{compile-fail => ui/block-result}/issue-13428.rs (100%) create mode 100644 src/test/ui/block-result/issue-13428.stderr rename src/test/{compile-fail => ui/block-result}/issue-13624.rs (100%) create mode 100644 src/test/ui/block-result/issue-13624.stderr rename src/test/{compile-fail => ui/block-result}/issue-20862.rs (100%) create mode 100644 src/test/ui/block-result/issue-20862.stderr rename src/test/{compile-fail => ui/block-result}/issue-22645.rs (100%) create mode 100644 src/test/ui/block-result/issue-22645.stderr rename src/test/{compile-fail => ui/block-result}/issue-3563.rs (100%) create mode 100644 src/test/ui/block-result/issue-3563.stderr rename src/test/{compile-fail => ui/block-result}/issue-5500.rs (100%) create mode 100644 src/test/ui/block-result/issue-5500.stderr create mode 100644 src/test/ui/block-result/unexpected-return-on-unit.rs create mode 100644 src/test/ui/block-result/unexpected-return-on-unit.stderr rename src/test/{compile-fail/auxiliary/allocator-dylib2.rs => ui/cast-to-unsized-trait-object-suggestion.rs} (89%) create mode 100644 src/test/ui/cast-to-unsized-trait-object-suggestion.stderr create mode 100644 src/test/ui/check_match/issue-43253.rs create mode 100644 src/test/ui/check_match/issue-43253.stderr create mode 100644 src/test/ui/closure_context/issue-26046-fn-mut.rs create mode 100644 src/test/ui/closure_context/issue-26046-fn-mut.stderr rename src/test/{compile-fail/two-allocators.rs => ui/closure_context/issue-26046-fn-once.rs} (65%) create mode 100644 src/test/ui/closure_context/issue-26046-fn-once.stderr rename src/test/ui/{fn_once-moved.rs => closure_context/issue-42065.rs} (100%) rename src/test/ui/{fn_once-moved.stderr => closure_context/issue-42065.stderr} (78%) create mode 100644 src/test/ui/explain.rs create mode 100644 src/test/ui/explain.stdout create mode 100644 src/test/ui/interior-mutability/interior-mutability.rs create mode 100644 src/test/ui/interior-mutability/interior-mutability.stderr create mode 100644 src/test/ui/issue-22644.rs create mode 100644 src/test/ui/issue-22644.stderr create mode 100644 src/test/ui/issue-33525.rs create mode 100644 src/test/ui/issue-33525.stderr create mode 100644 src/test/ui/issue-35675.rs create mode 100644 src/test/ui/issue-35675.stderr create mode 100644 src/test/ui/issue-38875/auxiliary/issue_38875_b.rs create mode 100644 src/test/ui/issue-38875/issue_38875.rs create mode 100644 src/test/ui/issue-38875/issue_38875.stderr create mode 100644 src/test/ui/issue-42954.rs create mode 100644 src/test/ui/issue-42954.stderr create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.rs create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr create mode 100644 src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.rs create mode 100644 src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr create mode 100644 src/test/ui/lint/outer-forbid.rs create mode 100644 src/test/ui/lint/outer-forbid.stderr rename src/test/{compile-fail => ui/macros}/macro-name-typo.rs (87%) create mode 100644 src/test/ui/macros/macro-name-typo.stderr rename src/test/{compile-fail => ui/macros}/macro_undefined.rs (74%) create mode 100644 src/test/ui/macros/macro_undefined.stderr rename src/test/{compile-fail => ui/mismatched_types}/for-loop-has-unit-body.rs (100%) create mode 100644 src/test/ui/mismatched_types/for-loop-has-unit-body.stderr rename src/test/{compile-fail => ui}/on-unimplemented/bad-annotation.rs (100%) create mode 100644 src/test/ui/on-unimplemented/bad-annotation.stderr rename src/test/{compile-fail => ui}/on-unimplemented/multiple-impls.rs (90%) create mode 100644 src/test/ui/on-unimplemented/multiple-impls.stderr rename src/test/{compile-fail => ui}/on-unimplemented/on-impl.rs (95%) create mode 100644 src/test/ui/on-unimplemented/on-impl.stderr rename src/test/{compile-fail => ui}/on-unimplemented/on-trait.rs (90%) create mode 100644 src/test/ui/on-unimplemented/on-trait.stderr rename src/test/{compile-fail => ui}/on-unimplemented/slice-index.rs (100%) create mode 100644 src/test/ui/on-unimplemented/slice-index.stderr create mode 100644 src/test/ui/resolve-error.stderr rename src/test/{compile-fail => ui}/shadowed-type-parameter.rs (100%) create mode 100644 src/test/ui/shadowed-type-parameter.stderr create mode 100644 src/test/ui/suggestions/try-operator-on-main.rs create mode 100644 src/test/ui/suggestions/try-operator-on-main.stderr create mode 100644 src/test/ui/transmute/main.rs create mode 100644 src/test/ui/transmute/main.stderr rename src/test/{compile-fail => ui/transmute}/transmute-from-fn-item-types-error.rs (92%) create mode 100644 src/test/ui/transmute/transmute-from-fn-item-types-error.stderr rename src/test/{compile-fail => ui/transmute}/transmute-type-parameters.rs (69%) create mode 100644 src/test/ui/transmute/transmute-type-parameters.stderr rename src/test/{compile-fail/issue-17283.rs => ui/type-check/assignment-in-if.rs} (71%) create mode 100644 src/test/ui/type-check/assignment-in-if.stderr create mode 100644 src/tools/rust-installer/test/rust-installer-v1/README.md create mode 100755 src/tools/rust-installer/test/rust-installer-v1/gen-install-script.sh create mode 100755 src/tools/rust-installer/test/rust-installer-v1/gen-installer.sh create mode 100644 src/tools/rust-installer/test/rust-installer-v1/install-template.sh create mode 100644 src/tools/rust-installer/test/rust-installer-v2/.travis.yml create mode 100644 src/tools/rust-installer/test/rust-installer-v2/README.md create mode 100644 src/tools/rust-installer/test/rust-installer-v2/combine-installers.sh create mode 100755 src/tools/rust-installer/test/rust-installer-v2/gen-install-script.sh create mode 100755 src/tools/rust-installer/test/rust-installer-v2/gen-installer.sh create mode 100644 src/tools/rust-installer/test/rust-installer-v2/install-template.sh create mode 100644 src/tools/rust-installer/test/rust-installer-v2/rust-installer-version create mode 100755 src/tools/rust-installer/test/rust-installer-v2/test.sh create mode 100644 src/tools/rust-installer/test/rust-installer-v2/test/image1/bin/bad-bin create mode 100755 src/tools/rust-installer/test/rust-installer-v2/test/image1/bin/program create mode 100755 src/tools/rust-installer/test/rust-installer-v2/test/image1/bin/program2 rename src/{doc/unstable-book/src/library-features/manually-drop.md => tools/rust-installer/test/rust-installer-v2/test/image1/dir-to-install/foo} (100%) rename src/{vendor/bitflags-0.5.0/.cargo-ok => tools/rust-installer/test/rust-installer-v2/test/image1/dir-to-not-install/foo} (100%) rename src/{vendor/bitflags-0.7.0/.cargo-ok => tools/rust-installer/test/rust-installer-v2/test/image1/something-to-install} (100%) rename src/{vendor/error-chain/.cargo-ok => tools/rust-installer/test/rust-installer-v2/test/image1/something-to-not-install} (100%) create mode 100755 src/tools/rust-installer/test/rust-installer-v2/test/image2/bin/oldprogram rename src/{vendor/pulldown-cmark-0.0.8/.cargo-ok => tools/rust-installer/test/rust-installer-v2/test/image2/dir-to-install/bar} (100%) rename src/{vendor/serde-0.9.15/.cargo-ok => tools/rust-installer/test/rust-installer-v2/test/image2/something-to-install} (100%) create mode 100755 src/tools/rust-installer/test/rust-installer-v2/test/image3/bin/cargo rename src/{vendor/serde_json-0.9.10/.cargo-ok => tools/rust-installer/test/rust-installer-v2/test/image4/baz} (100%) rename src/{vendor/strsim-0.5.2/.cargo-ok => tools/rust-installer/test/rust-installer-v2/test/image4/dir-to-install/qux/bar} (100%) rename src/{vendor/thread-id/.cargo-ok => tools/rust-installer/test/rust-installer-v2/test/image5/dir-to-install/foo} (100%) create mode 100644 src/tools/rust-installer/test/rust-installer-v2/test/rust-installer-v1/README.md create mode 100755 src/tools/rust-installer/test/rust-installer-v2/test/rust-installer-v1/gen-install-script.sh create mode 100755 src/tools/rust-installer/test/rust-installer-v2/test/rust-installer-v1/gen-installer.sh create mode 100644 src/tools/rust-installer/test/rust-installer-v2/test/rust-installer-v1/install-template.sh create mode 100644 src/tools/tidy/src/lib.rs create mode 100644 src/tools/unstable-book-gen/Cargo.toml create mode 100644 src/tools/unstable-book-gen/src/SUMMARY.md create mode 100644 src/tools/unstable-book-gen/src/main.rs create mode 100644 src/tools/unstable-book-gen/src/stub-issue.md create mode 100644 src/tools/unstable-book-gen/src/stub-no-issue.md create mode 100644 src/vendor/atty/.cargo-checksum.json rename src/vendor/{toml-0.3.2 => atty}/.cargo-ok (100%) create mode 100644 src/vendor/atty/.gitignore create mode 100644 src/vendor/atty/.travis.yml create mode 100644 src/vendor/atty/CHANGELOG.md create mode 100644 src/vendor/atty/Cargo.toml create mode 100644 src/vendor/atty/LICENSE create mode 100644 src/vendor/atty/README.md create mode 100644 src/vendor/atty/appveyor.yml create mode 100644 src/vendor/atty/examples/atty.rs create mode 100644 src/vendor/atty/src/lib.rs delete mode 100644 src/vendor/backtrace/build.rs delete mode 100644 src/vendor/bitflags-0.5.0/.cargo-checksum.json delete mode 100644 src/vendor/bitflags-0.5.0/.travis.yml delete mode 100644 src/vendor/bitflags-0.5.0/Cargo.toml delete mode 100644 src/vendor/bitflags-0.5.0/README.md delete mode 100644 src/vendor/bitflags-0.5.0/src/lib.rs delete mode 100644 src/vendor/bitflags-0.5.0/tests/external.rs delete mode 100644 src/vendor/bitflags-0.5.0/tests/external_no_std.rs delete mode 100644 src/vendor/bitflags-0.7.0/.cargo-checksum.json delete mode 100644 src/vendor/bitflags-0.7.0/.gitignore delete mode 100644 src/vendor/bitflags-0.7.0/.travis.yml delete mode 100644 src/vendor/bitflags-0.7.0/Cargo.toml create mode 100644 src/vendor/bitflags/.cargo-checksum.json rename src/vendor/{toml-0.3.2/tests/valid/empty.toml => bitflags/.cargo-ok} (100%) rename src/vendor/{bitflags-0.5.0 => bitflags}/.gitignore (100%) create mode 100644 src/vendor/bitflags/.travis.yml create mode 100644 src/vendor/bitflags/Cargo.toml create mode 100644 src/vendor/bitflags/Cargo.toml.orig rename src/vendor/{bitflags-0.5.0 => bitflags}/LICENSE-APACHE (100%) rename src/vendor/{bitflags-0.5.0 => bitflags}/LICENSE-MIT (100%) rename src/vendor/{bitflags-0.7.0 => bitflags}/README.md (84%) create mode 100644 src/vendor/bitflags/src/example_generated.rs rename src/vendor/{bitflags-0.7.0 => bitflags}/src/lib.rs (52%) create mode 100644 src/vendor/bitflags/tests/conflicting_trait_impls.rs rename src/vendor/{bitflags-0.7.0 => bitflags}/tests/external.rs (51%) rename src/vendor/{bitflags-0.7.0 => bitflags}/tests/external_no_std.rs (52%) create mode 100644 src/vendor/bitflags/tests/i128_bitflags.rs rename src/vendor/{bitflags-0.7.0 => cfg-if}/LICENSE-APACHE (100%) rename src/vendor/{toml-0.3.2 => cfg-if}/LICENSE-MIT (100%) create mode 100644 src/vendor/clap/.appveyor.yml create mode 100644 src/vendor/clap/.mention-bot create mode 100644 src/vendor/clap/Cargo.toml.orig delete mode 100644 src/vendor/clap/appveyor.yml create mode 100644 src/vendor/clap/src/app/usage.rs create mode 100644 src/vendor/clap/src/app/validator.rs delete mode 100644 src/vendor/cmake/src/registry.rs create mode 100644 src/vendor/crossbeam/.cargo-checksum.json create mode 100644 src/vendor/crossbeam/.cargo-ok create mode 100644 src/vendor/crossbeam/.gitignore create mode 100644 src/vendor/crossbeam/.travis.yml create mode 100644 src/vendor/crossbeam/CHANGELOG.md create mode 100644 src/vendor/crossbeam/Cargo.toml rename src/vendor/{serde-0.9.15 => crossbeam}/LICENSE-APACHE (100%) create mode 100644 src/vendor/crossbeam/LICENSE-MIT create mode 100644 src/vendor/crossbeam/README.md create mode 100644 src/vendor/crossbeam/scala-bench/bench.scala create mode 100755 src/vendor/crossbeam/src/bin/bench.rs create mode 100644 src/vendor/crossbeam/src/bin/extra_impls/mod.rs create mode 100644 src/vendor/crossbeam/src/bin/extra_impls/mpsc_queue.rs create mode 100644 src/vendor/crossbeam/src/bin/stress-msq.rs create mode 100644 src/vendor/crossbeam/src/lib.rs create mode 100644 src/vendor/crossbeam/src/mem/cache_padded.rs create mode 100644 src/vendor/crossbeam/src/mem/epoch/atomic.rs create mode 100644 src/vendor/crossbeam/src/mem/epoch/garbage.rs create mode 100644 src/vendor/crossbeam/src/mem/epoch/global.rs create mode 100644 src/vendor/crossbeam/src/mem/epoch/guard.rs create mode 100644 src/vendor/crossbeam/src/mem/epoch/local.rs create mode 100644 src/vendor/crossbeam/src/mem/epoch/mod.rs create mode 100644 src/vendor/crossbeam/src/mem/epoch/participant.rs create mode 100644 src/vendor/crossbeam/src/mem/epoch/participants.rs create mode 100644 src/vendor/crossbeam/src/mem/mod.rs create mode 100644 src/vendor/crossbeam/src/scoped.rs create mode 100644 src/vendor/crossbeam/src/sync/arc_cell.rs create mode 100644 src/vendor/crossbeam/src/sync/atomic_option.rs create mode 100644 src/vendor/crossbeam/src/sync/chase_lev.rs create mode 100644 src/vendor/crossbeam/src/sync/mod.rs create mode 100644 src/vendor/crossbeam/src/sync/ms_queue.rs create mode 100644 src/vendor/crossbeam/src/sync/seg_queue.rs create mode 100644 src/vendor/crossbeam/src/sync/treiber_stack.rs create mode 100644 src/vendor/env_logger/Cargo.toml.orig rename src/vendor/{error-chain => error-chain-0.10.0}/.cargo-checksum.json (100%) create mode 100644 src/vendor/error-chain-0.10.0/.cargo-ok rename src/vendor/{error-chain => error-chain-0.10.0}/.gitignore (100%) rename src/vendor/{error-chain => error-chain-0.10.0}/.travis.yml (100%) rename src/vendor/{error-chain => error-chain-0.10.0}/CHANGELOG.md (100%) rename src/vendor/{error-chain => error-chain-0.10.0}/Cargo.toml (100%) rename src/vendor/{error-chain => error-chain-0.10.0}/README.md (100%) rename src/vendor/{error-chain => error-chain-0.10.0}/examples/all.rs (100%) rename src/vendor/{error-chain => error-chain-0.10.0}/examples/doc.rs (100%) rename src/vendor/{error-chain => error-chain-0.10.0}/examples/quickstart.rs (100%) rename src/vendor/{error-chain => error-chain-0.10.0}/examples/size.rs (100%) rename src/vendor/{error-chain => error-chain-0.10.0}/src/error_chain.rs (100%) rename src/vendor/{error-chain => error-chain-0.10.0}/src/example_generated.rs (100%) rename src/vendor/{error-chain => error-chain-0.10.0}/src/lib.rs (100%) rename src/vendor/{error-chain => error-chain-0.10.0}/src/quick_error.rs (100%) rename src/vendor/{error-chain => error-chain-0.10.0}/src/quick_main.rs (100%) rename src/vendor/{error-chain => error-chain-0.10.0}/tests/quick_main.rs (100%) rename src/vendor/{error-chain => error-chain-0.10.0}/tests/tests.rs (100%) create mode 100644 src/vendor/jobserver/.appveyor.yml create mode 100644 src/vendor/jobserver/.cargo-checksum.json create mode 100644 src/vendor/jobserver/.cargo-ok create mode 100644 src/vendor/jobserver/.gitignore create mode 100644 src/vendor/jobserver/.travis.yml create mode 100644 src/vendor/jobserver/Cargo.toml rename src/vendor/{serde_json-0.9.10 => jobserver}/LICENSE-APACHE (100%) create mode 100644 src/vendor/jobserver/LICENSE-MIT create mode 100644 src/vendor/jobserver/README.md create mode 100644 src/vendor/jobserver/src/lib.rs create mode 100644 src/vendor/jobserver/tests/client-of-myself.rs create mode 100644 src/vendor/jobserver/tests/client.rs create mode 100644 src/vendor/jobserver/tests/helper.rs create mode 100644 src/vendor/jobserver/tests/make-as-a-client.rs create mode 100644 src/vendor/jobserver/tests/server.rs create mode 100644 src/vendor/libc/ci/android-sysimage.sh create mode 100644 src/vendor/libc/ci/docker/s390x-unknown-linux-gnu/Dockerfile mode change 100644 => 100755 src/vendor/libc/ci/run-docker.sh create mode 100644 src/vendor/libc/src/unix/newlib/arm/mod.rs create mode 100644 src/vendor/libc/src/unix/newlib/mod.rs create mode 100644 src/vendor/libc/src/unix/uclibc/mips/mips32.rs create mode 100644 src/vendor/libc/src/unix/uclibc/mips/mips64.rs create mode 100644 src/vendor/libc/src/unix/uclibc/mips/mod.rs create mode 100644 src/vendor/libc/src/unix/uclibc/mod.rs create mode 100644 src/vendor/libc/src/unix/uclibc/x86_64/mod.rs create mode 100644 src/vendor/log/Cargo.toml.orig create mode 100644 src/vendor/mdbook/CONTRIBUTING.md create mode 100644 src/vendor/num_cpus/.appveyor.yml create mode 100644 src/vendor/num_cpus/Cargo.toml.orig delete mode 100644 src/vendor/pulldown-cmark-0.0.8/.cargo-checksum.json delete mode 100644 src/vendor/pulldown-cmark-0.0.8/CONTRIBUTING.md delete mode 100644 src/vendor/pulldown-cmark-0.0.8/Cargo.toml delete mode 100644 src/vendor/pulldown-cmark-0.0.8/README.md delete mode 100644 src/vendor/pulldown-cmark-0.0.8/specs/footnotes.txt delete mode 100644 src/vendor/pulldown-cmark-0.0.8/specs/table.txt delete mode 100644 src/vendor/pulldown-cmark-0.0.8/src/entities.rs delete mode 100644 src/vendor/pulldown-cmark-0.0.8/src/escape.rs delete mode 100644 src/vendor/pulldown-cmark-0.0.8/src/html.rs delete mode 100644 src/vendor/pulldown-cmark-0.0.8/src/lib.rs delete mode 100644 src/vendor/pulldown-cmark-0.0.8/src/main.rs delete mode 100644 src/vendor/pulldown-cmark-0.0.8/src/parse.rs delete mode 100644 src/vendor/pulldown-cmark-0.0.8/src/passes.rs delete mode 100644 src/vendor/pulldown-cmark-0.0.8/src/puncttable.rs delete mode 100644 src/vendor/pulldown-cmark-0.0.8/src/scanners.rs delete mode 100644 src/vendor/pulldown-cmark-0.0.8/src/utils.rs delete mode 100644 src/vendor/pulldown-cmark-0.0.8/tools/mk_entities.py delete mode 100644 src/vendor/pulldown-cmark-0.0.8/tools/mk_puncttable.py create mode 100644 src/vendor/rand/.cargo-checksum.json create mode 100644 src/vendor/rand/.cargo-ok rename src/vendor/{toml-0.3.2 => rand}/.gitignore (100%) create mode 100644 src/vendor/rand/.travis.yml create mode 100644 src/vendor/rand/Cargo.toml rename src/vendor/{toml-0.3.2 => rand}/LICENSE-APACHE (100%) rename src/vendor/{bitflags-0.7.0 => rand}/LICENSE-MIT (100%) create mode 100644 src/vendor/rand/README.md create mode 100644 src/vendor/rand/appveyor.yml create mode 100644 src/vendor/rand/benches/bench.rs create mode 100644 src/vendor/rand/benches/distributions/exponential.rs create mode 100644 src/vendor/rand/benches/distributions/gamma.rs create mode 100644 src/vendor/rand/benches/distributions/mod.rs create mode 100644 src/vendor/rand/benches/distributions/normal.rs create mode 100644 src/vendor/rand/src/chacha.rs create mode 100644 src/vendor/rand/src/distributions/exponential.rs create mode 100644 src/vendor/rand/src/distributions/gamma.rs create mode 100644 src/vendor/rand/src/distributions/mod.rs create mode 100644 src/vendor/rand/src/distributions/normal.rs create mode 100644 src/vendor/rand/src/distributions/range.rs create mode 100644 src/vendor/rand/src/distributions/ziggurat_tables.rs create mode 100644 src/vendor/rand/src/isaac.rs create mode 100644 src/vendor/rand/src/lib.rs create mode 100644 src/vendor/rand/src/os.rs create mode 100644 src/vendor/rand/src/rand_impls.rs create mode 100644 src/vendor/rand/src/read.rs create mode 100644 src/vendor/rand/src/reseeding.rs create mode 100644 src/vendor/regex/examples/bug347.rs create mode 100644 src/vendor/regex/examples/shootout-regex-redux-1.rs create mode 100644 src/vendor/regex/examples/shootout-regex-redux-chunked.rs create mode 100644 src/vendor/regex/examples/shootout-regex-redux.rs create mode 100644 src/vendor/rls-data/Cargo.toml.orig delete mode 100644 src/vendor/serde-0.9.15/.cargo-checksum.json delete mode 100644 src/vendor/serde-0.9.15/Cargo.toml delete mode 100644 src/vendor/serde-0.9.15/src/bytes.rs delete mode 100644 src/vendor/serde-0.9.15/src/de/content.rs delete mode 100644 src/vendor/serde-0.9.15/src/de/from_primitive.rs delete mode 100644 src/vendor/serde-0.9.15/src/de/impls.rs delete mode 100644 src/vendor/serde-0.9.15/src/de/private.rs delete mode 100644 src/vendor/serde-0.9.15/src/de/value.rs delete mode 100644 src/vendor/serde-0.9.15/src/error.rs delete mode 100644 src/vendor/serde-0.9.15/src/export.rs delete mode 100644 src/vendor/serde-0.9.15/src/iter.rs delete mode 100644 src/vendor/serde-0.9.15/src/lib.rs delete mode 100644 src/vendor/serde-0.9.15/src/macros.rs delete mode 100644 src/vendor/serde-0.9.15/src/ser/content.rs delete mode 100644 src/vendor/serde-0.9.15/src/ser/impls.rs delete mode 100644 src/vendor/serde-0.9.15/src/ser/impossible.rs delete mode 100644 src/vendor/serde-0.9.15/src/ser/mod.rs delete mode 100644 src/vendor/serde-0.9.15/src/ser/private.rs delete mode 100644 src/vendor/serde-0.9.15/src/utils.rs create mode 100644 src/vendor/serde/.cargo-checksum.json create mode 100644 src/vendor/serde/.cargo-ok create mode 100644 src/vendor/serde/Cargo.toml create mode 100644 src/vendor/serde/Cargo.toml.orig create mode 100644 src/vendor/serde/LICENSE-APACHE rename src/vendor/{serde-0.9.15 => serde}/LICENSE-MIT (100%) rename src/vendor/{serde-0.9.15 => serde}/README.md (88%) create mode 100644 src/vendor/serde/src/de/from_primitive.rs create mode 100644 src/vendor/serde/src/de/ignored_any.rs create mode 100644 src/vendor/serde/src/de/impls.rs rename src/vendor/{serde-0.9.15 => serde}/src/de/mod.rs (50%) create mode 100644 src/vendor/serde/src/de/utf8.rs create mode 100644 src/vendor/serde/src/de/value.rs create mode 100644 src/vendor/serde/src/export.rs create mode 100644 src/vendor/serde/src/lib.rs create mode 100644 src/vendor/serde/src/macros.rs create mode 100644 src/vendor/serde/src/private/de.rs create mode 100644 src/vendor/serde/src/private/macros.rs create mode 100644 src/vendor/serde/src/private/mod.rs create mode 100644 src/vendor/serde/src/private/ser.rs create mode 100644 src/vendor/serde/src/ser/impls.rs create mode 100644 src/vendor/serde/src/ser/impossible.rs create mode 100644 src/vendor/serde/src/ser/mod.rs delete mode 100644 src/vendor/serde_json-0.9.10/.cargo-checksum.json delete mode 100644 src/vendor/serde_json-0.9.10/src/number.rs delete mode 100644 src/vendor/serde_json-0.9.10/src/value.rs create mode 100644 src/vendor/serde_json/.cargo-checksum.json create mode 100644 src/vendor/serde_json/.cargo-ok rename src/vendor/{serde_json-0.9.10 => serde_json}/Cargo.toml (50%) create mode 100644 src/vendor/serde_json/LICENSE-APACHE rename src/vendor/{serde_json-0.9.10 => serde_json}/LICENSE-MIT (100%) rename src/vendor/{serde_json-0.9.10 => serde_json}/README.md (62%) rename src/vendor/{serde_json-0.9.10 => serde_json}/src/de.rs (51%) rename src/vendor/{serde_json-0.9.10 => serde_json}/src/error.rs (64%) create mode 100644 src/vendor/serde_json/src/iter.rs rename src/vendor/{serde_json-0.9.10 => serde_json}/src/lib.rs (66%) rename src/vendor/{serde_json-0.9.10 => serde_json}/src/macros.rs (94%) rename src/vendor/{serde_json-0.9.10 => serde_json}/src/map.rs (85%) create mode 100644 src/vendor/serde_json/src/number.rs rename src/vendor/{serde_json-0.9.10 => serde_json}/src/read.rs (67%) rename src/vendor/{serde_json-0.9.10 => serde_json}/src/ser.rs (54%) create mode 100644 src/vendor/serde_json/src/value/de.rs create mode 100644 src/vendor/serde_json/src/value/from.rs create mode 100644 src/vendor/serde_json/src/value/index.rs create mode 100644 src/vendor/serde_json/src/value/mod.rs create mode 100644 src/vendor/serde_json/src/value/partial_eq.rs create mode 100644 src/vendor/serde_json/src/value/ser.rs delete mode 100644 src/vendor/strsim-0.5.2/.cargo-checksum.json delete mode 100644 src/vendor/strsim-0.5.2/Vagrantfile delete mode 100644 src/vendor/strsim-0.5.2/bootstrap.sh create mode 100644 src/vendor/strsim/.cargo-checksum.json create mode 100644 src/vendor/strsim/.cargo-ok rename src/vendor/{strsim-0.5.2 => strsim}/.editorconfig (100%) rename src/vendor/{strsim-0.5.2 => strsim}/.gitignore (100%) rename src/vendor/{strsim-0.5.2 => strsim}/.travis.yml (100%) rename src/vendor/{strsim-0.5.2 => strsim}/CHANGELOG.md (84%) rename src/vendor/{strsim-0.5.2 => strsim}/Cargo.toml (96%) rename src/vendor/{strsim-0.5.2 => strsim}/LICENSE (100%) rename src/vendor/{strsim-0.5.2 => strsim}/README.md (74%) rename src/vendor/{strsim-0.5.2 => strsim}/appveyor.yml (100%) create mode 100755 src/vendor/strsim/dev rename src/vendor/{strsim-0.5.2 => strsim}/src/lib.rs (77%) rename src/vendor/{strsim-0.5.2 => strsim}/tests/lib.rs (71%) create mode 100644 src/vendor/textwrap/.appveyor.yml create mode 100644 src/vendor/textwrap/.cargo-checksum.json create mode 100644 src/vendor/textwrap/.cargo-ok create mode 100644 src/vendor/textwrap/.gitignore create mode 100644 src/vendor/textwrap/.travis.yml create mode 100644 src/vendor/textwrap/Cargo.toml rename src/vendor/{thread-id/license-mit => textwrap/LICENSE} (95%) create mode 100644 src/vendor/textwrap/README.md create mode 100644 src/vendor/textwrap/benches/linear.rs create mode 100644 src/vendor/textwrap/examples/layout.rs create mode 100644 src/vendor/textwrap/examples/termwidth.rs create mode 100644 src/vendor/textwrap/src/lib.rs delete mode 100644 src/vendor/thread-id/.appveyor.yml delete mode 100644 src/vendor/thread-id/.cargo-checksum.json delete mode 100644 src/vendor/thread-id/.gitignore delete mode 100644 src/vendor/thread-id/.travis.yml delete mode 100644 src/vendor/thread-id/Cargo.toml delete mode 100644 src/vendor/thread-id/changelog.md delete mode 100644 src/vendor/thread-id/readme.md delete mode 100644 src/vendor/thread-id/src/lib.rs create mode 100644 src/vendor/thread_local/Cargo.toml.orig create mode 100644 src/vendor/thread_local/benches/thread_local.rs create mode 100644 src/vendor/thread_local/src/thread_id.rs delete mode 100644 src/vendor/toml-0.3.2/.cargo-checksum.json delete mode 100644 src/vendor/toml-0.3.2/src/value/display.rs create mode 100644 src/vendor/toml/.cargo-checksum.json create mode 100644 src/vendor/toml/.cargo-ok rename src/vendor/{pulldown-cmark-0.0.8 => toml}/.gitignore (94%) rename src/vendor/{toml-0.3.2 => toml}/.travis.yml (98%) rename src/vendor/{toml-0.3.2 => toml}/Cargo.toml (90%) create mode 100644 src/vendor/toml/LICENSE-APACHE create mode 100644 src/vendor/toml/LICENSE-MIT rename src/vendor/{toml-0.3.2 => toml}/README.md (93%) rename src/vendor/{toml-0.3.2 => toml}/examples/decode.rs (95%) rename src/vendor/{toml-0.3.2 => toml}/examples/toml2json.rs (100%) rename src/vendor/{toml-0.3.2 => toml}/src/datetime.rs (87%) rename src/vendor/{toml-0.3.2 => toml}/src/de.rs (83%) rename src/vendor/{toml-0.3.2 => toml}/src/lib.rs (96%) rename src/vendor/{toml-0.3.2 => toml}/src/ser.rs (91%) rename src/vendor/{toml-0.3.2 => toml}/src/tokens.rs (99%) rename src/vendor/{toml-0.3.2 => toml}/src/value.rs (83%) rename src/vendor/{toml-0.3.2 => toml}/tests/README.md (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/backcompat.rs (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/datetime.rs (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/display-tricky.rs (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/display.rs (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/formatting.rs (100%) create mode 100644 src/vendor/toml/tests/invalid-encoder-misc.rs rename src/vendor/{toml-0.3.2 => toml}/tests/invalid-encoder/array-mixed-types-ints-and-floats.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid-misc.rs (69%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid.rs (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/array-mixed-types-arrays-and-ints.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/array-mixed-types-ints-and-floats.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/array-mixed-types-strings-and-ints.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/datetime-malformed-no-leads.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/datetime-malformed-no-secs.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/datetime-malformed-no-t.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/datetime-malformed-with-milli.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/duplicate-key-table.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/duplicate-keys.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/duplicate-tables.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/empty-implicit-table.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/empty-table.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/float-no-leading-zero.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/float-no-trailing-digits.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/key-after-array.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/key-after-table.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/key-empty.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/key-hash.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/key-newline.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/key-open-bracket.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/key-single-open-bracket.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/key-space.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/key-start-bracket.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/key-two-equals.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/string-bad-byte-escape.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/string-bad-escape.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/string-byte-escapes.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/string-no-close.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/table-array-implicit.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/table-array-malformed-bracket.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/table-array-malformed-empty.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/table-empty.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/table-nested-brackets-close.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/table-nested-brackets-open.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/table-whitespace.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/table-with-pound.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/text-after-array-entries.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/text-after-integer.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/text-after-string.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/text-after-table.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/text-before-array-separator.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/invalid/text-in-array.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/parser.rs (99%) rename src/vendor/{toml-0.3.2 => toml}/tests/serde.rs (95%) rename src/vendor/{toml-0.3.2 => toml}/tests/tables-last.rs (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid.rs (93%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/array-empty.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/array-empty.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/array-nospaces.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/array-nospaces.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/arrays-hetergeneous.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/arrays-hetergeneous.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/arrays-nested.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/arrays-nested.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/arrays.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/arrays.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/bool.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/bool.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/comments-everywhere.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/comments-everywhere.toml (100%) create mode 100644 src/vendor/toml/tests/valid/datetime-truncate.json create mode 100644 src/vendor/toml/tests/valid/datetime-truncate.toml rename src/vendor/{toml-0.3.2 => toml}/tests/valid/datetime.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/datetime.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/empty.json (100%) create mode 100644 src/vendor/toml/tests/valid/empty.toml rename src/vendor/{toml-0.3.2 => toml}/tests/valid/example-bom.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/example-v0.3.0.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/example-v0.3.0.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/example-v0.4.0.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/example-v0.4.0.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/example.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/example.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/example2.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/example2.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/float.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/float.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/hard_example.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/hard_example.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/implicit-and-explicit-after.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/implicit-and-explicit-after.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/implicit-and-explicit-before.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/implicit-and-explicit-before.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/implicit-groups.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/implicit-groups.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/integer.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/integer.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/key-equals-nospace.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/key-equals-nospace.toml (100%) create mode 100644 src/vendor/toml/tests/valid/key-quote-newline.json create mode 100644 src/vendor/toml/tests/valid/key-quote-newline.toml rename src/vendor/{toml-0.3.2 => toml}/tests/valid/key-space.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/key-space.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/key-special-chars.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/key-special-chars.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/key-with-pound.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/key-with-pound.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/long-float.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/long-float.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/long-integer.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/long-integer.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/multiline-string.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/multiline-string.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/raw-multiline-string.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/raw-multiline-string.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/raw-string.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/raw-string.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/string-empty.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/string-empty.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/string-escapes.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/string-escapes.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/string-simple.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/string-simple.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/string-with-pound.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/string-with-pound.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/table-array-implicit.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/table-array-implicit.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/table-array-many.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/table-array-many.toml (100%) create mode 100644 src/vendor/toml/tests/valid/table-array-nest-no-keys.json create mode 100644 src/vendor/toml/tests/valid/table-array-nest-no-keys.toml rename src/vendor/{toml-0.3.2 => toml}/tests/valid/table-array-nest.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/table-array-nest.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/table-array-one.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/table-array-one.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/table-empty.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/table-empty.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/table-sub-empty.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/table-sub-empty.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/table-whitespace.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/table-whitespace.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/table-with-pound.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/table-with-pound.toml (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/unicode-escape.json (68%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/unicode-escape.toml (70%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/unicode-literal.json (100%) rename src/vendor/{toml-0.3.2 => toml}/tests/valid/unicode-literal.toml (100%) rename src/vendor/{thread-id/license-apache => unreachable/LICENSE-APACHE} (99%) rename src/vendor/{pulldown-cmark-0.0.8/LICENSE => unreachable/LICENSE-MIT} (86%) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8f121f8d6e..370cf6c0b4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -232,6 +232,7 @@ Some common invocations of `x.py` are: guidelines as of yet, but basic rules like 4 spaces for indentation and no more than 99 characters in a single line should be kept in mind when writing code. +- `rustup toolchain link build//` - Use the custom compiler build via [rustup](https://github.com/rust-lang-nursery/rustup.rs#working-with-custom-toolchains-and-local-builds). ## Pull Requests diff --git a/COPYRIGHT b/COPYRIGHT index abe8998030..3c2786b8f8 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -22,12 +22,6 @@ The Rust Project includes packages written by third parties. The following third party packages are included, and carry their own copyright notices and license terms: -* The src/rt/miniz.c file, carrying an implementation of - RFC1950/RFC1951 DEFLATE, by Rich Geldreich - . All uses of this file are - permitted by the embedded "unlicense" notice - (effectively: public domain with warranty disclaimer). - * LLVM. Code for this package is found in src/llvm. Copyright (c) 2003-2013 University of Illinois at diff --git a/README.md b/README.md index dbb5bf9ce3..a1f0186107 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ standard library, and documentation. ## Quick Start -Read ["Installing Rust"] from [The Book]. +Read ["Installation"] from [The Book]. -["Installing Rust"]: https://doc.rust-lang.org/book/getting-started.html#installing-rust +["Installation"]: https://doc.rust-lang.org/book/second-edition/ch01-01-installation.html [The Book]: https://doc.rust-lang.org/book/index.html ## Building from Source @@ -40,8 +40,9 @@ Read ["Installing Rust"] from [The Book]. > ***Note:*** Install locations can be adjusted by copying the config file > from `./src/bootstrap/config.toml.example` to `./config.toml`, and - > adjusting the `prefix` option under `[install]`. Various other options are - > also supported, and are documented in the config file. + > adjusting the `prefix` option under `[install]`. Various other options, such + > as enabling debug information, are also supported, and are documented in + > the config file. When complete, `sudo ./x.py install` will place several programs into `/usr/local/bin`: `rustc`, the Rust compiler, and `rustdoc`, the diff --git a/configure b/configure index af59d5b0bb..e08bcc0282 100755 --- a/configure +++ b/configure @@ -452,6 +452,7 @@ opt vendor 0 "enable usage of vendored Rust crates" opt sanitizers 0 "build the sanitizer runtimes (asan, lsan, msan, tsan)" opt dist-src 1 "when building tarballs enables building a source tarball" opt cargo-openssl-static 0 "static openssl in cargo" +opt profiler 0 "build the profiler runtime" # Optimization and debugging options. These may be overridden by the release channel, etc. opt_nosave optimize 1 "build optimized rust code" @@ -489,6 +490,7 @@ valopt musl-root-armhf "" "arm-unknown-linux-musleabihf install directory" valopt musl-root-armv7 "" "armv7-unknown-linux-musleabihf install directory" valopt extra-filename "" "Additional data that is hashed and passed to the -C extra-filename flag" valopt qemu-armhf-rootfs "" "rootfs in qemu testing, you probably don't want to use this" +valopt experimental-targets "" "experimental LLVM targets to build" if [ -e ${CFG_SRC_DIR}.git ] then diff --git a/src/Cargo.lock b/src/Cargo.lock index dcda218ff4..bcec823403 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -36,15 +36,18 @@ name = "alloc" version = "0.0.0" dependencies = [ "core 0.0.0", + "std_unicode 0.0.0", ] [[package]] name = "alloc_jemalloc" version = "0.0.0" dependencies = [ + "alloc 0.0.0", + "alloc_system 0.0.0", "build_helper 0.1.0", "core 0.0.0", - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.0.0", ] @@ -52,6 +55,7 @@ dependencies = [ name = "alloc_system" version = "0.0.0" dependencies = [ + "alloc 0.0.0", "core 0.0.0", "libc 0.0.0", ] @@ -65,39 +69,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "arena" version = "0.0.0" +[[package]] +name = "atty" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "backtrace" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "bitflags" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bitflags" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "bitflags" version = "0.8.2" @@ -113,12 +117,12 @@ name = "bootstrap" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -145,46 +149,47 @@ dependencies = [ [[package]] name = "cargo" -version = "0.20.0" +version = "0.21.0" dependencies = [ "advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "cargotest 0.1.0", - "crates-io 0.9.0", + "crates-io 0.10.0", "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "fs2 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", "psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "serde_ignored 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -193,21 +198,20 @@ name = "cargotest" version = "0.1.0" dependencies = [ "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo 0.20.0", + "cargo 0.21.0", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -217,31 +221,32 @@ version = "0.1.0" [[package]] name = "cfg-if" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "clap" -version = "2.19.3" +version = "2.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cmake" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -250,16 +255,14 @@ version = "0.0.0" dependencies = [ "alloc 0.0.0", "core 0.0.0", - "std_unicode 0.0.0", ] [[package]] name = "compiler_builtins" version = "0.0.0" dependencies = [ - "build_helper 0.1.0", "core 0.0.0", - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -267,26 +270,31 @@ name = "compiletest" version = "0.0.0" dependencies = [ "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "core" version = "0.0.0" +dependencies = [ + "rand 0.0.0", +] [[package]] name = "crates-io" -version = "0.9.0" +version = "0.10.0" dependencies = [ - "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -296,26 +304,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "curl" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "curl-sys 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "curl-sys" -version = "0.3.11" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -335,12 +345,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "docopt" -version = "0.7.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -351,11 +362,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "env_logger" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -363,7 +374,15 @@ name = "error-chain" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "error-chain" +version = "0.11.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -375,15 +394,7 @@ name = "filetime" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "flate" -version = "0.0.0" -dependencies = [ - "build_helper 0.1.0", - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -391,7 +402,7 @@ name = "flate2" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -406,32 +417,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "fs2" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "gcc" -version = "0.3.50" +version = "0.3.51" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "gdi32-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "getopts" -version = "0.0.0" - [[package]] name = "getopts" version = "0.2.14" @@ -443,11 +441,11 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -455,10 +453,10 @@ name = "git2-curl" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -475,39 +473,44 @@ name = "hamcrest" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "handlebars" -version = "0.25.3" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hex" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "idna" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "installer" version = "0.0.0" dependencies = [ - "clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.25.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -528,7 +531,7 @@ name = "jobserver" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -555,7 +558,7 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.22" +version = "0.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -563,13 +566,13 @@ name = "libgit2-sys" version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", - "curl-sys 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", + "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -578,21 +581,22 @@ name = "libssh2-sys" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libz-sys" -version = "1.0.13" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -601,39 +605,39 @@ version = "0.1.0" [[package]] name = "log" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lzma-sys" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "matches" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "mdbook" -version = "0.0.21" +version = "0.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "handlebars 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.25.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "handlebars 0.26.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -641,7 +645,7 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -649,7 +653,7 @@ name = "memchr" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -657,8 +661,8 @@ name = "miniz-sys" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -677,43 +681,43 @@ name = "net2" version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num" -version = "0.1.37" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-bigint 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "num-complex 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-complex 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-rational 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-bigint" -version = "0.1.37" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-complex" -version = "0.1.37" +version = "0.1.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -722,7 +726,7 @@ name = "num-integer" version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -731,31 +735,31 @@ version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-rational" -version = "0.1.36" +version = "0.1.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-bigint 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.1.37" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num_cpus" -version = "1.4.0" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -765,14 +769,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl" -version = "0.9.12" +version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -782,14 +786,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.12" +version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", - "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -818,6 +820,11 @@ dependencies = [ "unwind 0.0.0", ] +[[package]] +name = "percent-encoding" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "pest" version = "0.3.3" @@ -833,15 +840,15 @@ name = "proc_macro" version = "0.0.0" dependencies = [ "syntax 0.0.0", + "syntax_pos 0.0.0", ] [[package]] -name = "proc_macro_plugin" +name = "profiler_builtins" version = "0.0.0" dependencies = [ - "rustc_plugin 0.0.0", - "syntax 0.0.0", - "syntax_pos 0.0.0", + "core 0.0.0", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -853,21 +860,13 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "pulldown-cmark" -version = "0.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "pulldown-cmark" version = "0.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -892,7 +891,7 @@ name = "rand" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -909,13 +908,13 @@ dependencies = [ [[package]] name = "regex" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -926,7 +925,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "regex-syntax" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -939,7 +938,7 @@ version = "0.1.0" [[package]] name = "rls-data" -version = "0.3.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -958,8 +957,8 @@ dependencies = [ name = "rustbook" version = "0.1.0" dependencies = [ - "clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)", - "mdbook 0.0.21 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.25.0 (registry+https://github.com/rust-lang/crates.io-index)", + "mdbook 0.0.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -967,9 +966,11 @@ name = "rustc" version = "0.0.0" dependencies = [ "arena 0.0.0", + "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "fmt_macros 0.0.0", "graphviz 0.0.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_back 0.0.0", "rustc_bitflags 0.0.0", @@ -1000,13 +1001,24 @@ name = "rustc-serialize" version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc_allocator" +version = "0.0.0" +dependencies = [ + "rustc 0.0.0", + "rustc_errors 0.0.0", + "syntax 0.0.0", + "syntax_pos 0.0.0", +] + [[package]] name = "rustc_asan" version = "0.0.0" dependencies = [ + "alloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -1014,7 +1026,7 @@ dependencies = [ name = "rustc_back" version = "0.0.0" dependencies = [ - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", "syntax 0.0.0", ] @@ -1028,7 +1040,7 @@ name = "rustc_borrowck" version = "0.0.0" dependencies = [ "graphviz 0.0.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", @@ -1042,7 +1054,7 @@ name = "rustc_const_eval" version = "0.0.0" dependencies = [ "arena 0.0.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_back 0.0.0", "rustc_const_math 0.0.0", @@ -1064,7 +1076,7 @@ dependencies = [ name = "rustc_data_structures" version = "0.0.0" dependencies = [ - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", ] @@ -1073,11 +1085,11 @@ name = "rustc_driver" version = "0.0.0" dependencies = [ "arena 0.0.0", - "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "proc_macro_plugin 0.0.0", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", + "rustc_allocator 0.0.0", "rustc_back 0.0.0", "rustc_borrowck 0.0.0", "rustc_const_eval 0.0.0", @@ -1113,7 +1125,7 @@ name = "rustc_incremental" version = "0.0.0" dependencies = [ "graphviz 0.0.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "serialize 0.0.0", @@ -1125,7 +1137,7 @@ dependencies = [ name = "rustc_lint" version = "0.0.0" dependencies = [ - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_back 0.0.0", "rustc_const_eval 0.0.0", @@ -1138,7 +1150,7 @@ name = "rustc_llvm" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_bitflags 0.0.0", ] @@ -1146,9 +1158,10 @@ dependencies = [ name = "rustc_lsan" version = "0.0.0" dependencies = [ + "alloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -1156,8 +1169,8 @@ dependencies = [ name = "rustc_metadata" version = "0.0.0" dependencies = [ - "flate 0.0.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "proc_macro 0.0.0", "rustc 0.0.0", @@ -1176,7 +1189,7 @@ name = "rustc_mir" version = "0.0.0" dependencies = [ "graphviz 0.0.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_bitflags 0.0.0", "rustc_const_eval 0.0.0", @@ -1190,9 +1203,10 @@ dependencies = [ name = "rustc_msan" version = "0.0.0" dependencies = [ + "alloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -1200,7 +1214,7 @@ dependencies = [ name = "rustc_passes" version = "0.0.0" dependencies = [ - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_const_eval 0.0.0", "rustc_const_math 0.0.0", @@ -1239,7 +1253,7 @@ name = "rustc_resolve" version = "0.0.0" dependencies = [ "arena 0.0.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_errors 0.0.0", "syntax 0.0.0", @@ -1250,8 +1264,8 @@ dependencies = [ name = "rustc_save_analysis" version = "0.0.0" dependencies = [ - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-data 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-data 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1264,11 +1278,15 @@ dependencies = [ name = "rustc_trans" version = "0.0.0" dependencies = [ - "flate 0.0.0", - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", + "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_allocator 0.0.0", "rustc_back 0.0.0", "rustc_bitflags 0.0.0", "rustc_const_math 0.0.0", @@ -1288,7 +1306,7 @@ version = "0.0.0" dependencies = [ "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -1298,7 +1316,7 @@ version = "0.0.0" dependencies = [ "arena 0.0.0", "fmt_macros 0.0.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_back 0.0.0", "rustc_const_math 0.0.0", @@ -1315,9 +1333,9 @@ version = "0.0.0" dependencies = [ "arena 0.0.0", "build_helper 0.1.0", - "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_back 0.0.0", @@ -1354,7 +1372,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1364,27 +1382,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "0.9.15" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde" -version = "1.0.6" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.6" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive_internals" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1396,18 +1409,7 @@ name = "serde_ignored" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_json" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1417,8 +1419,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1430,6 +1432,18 @@ name = "shell-escape" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "socket2" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "stable_deref_trait" version = "1.0.0" @@ -1446,10 +1460,11 @@ dependencies = [ "collections 0.0.0", "compiler_builtins 0.0.0", "core 0.0.0", - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.0.0", "panic_abort 0.0.0", "panic_unwind 0.0.0", + "profiler_builtins 0.0.0", "rand 0.0.0", "rustc_asan 0.0.0", "rustc_lsan 0.0.0", @@ -1466,11 +1481,6 @@ dependencies = [ "core 0.0.0", ] -[[package]] -name = "strsim" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "strsim" version = "0.6.0" @@ -1499,7 +1509,7 @@ name = "syntax" version = "0.0.0" dependencies = [ "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "serialize 0.0.0", @@ -1511,7 +1521,7 @@ name = "syntax_ext" version = "0.0.0" dependencies = [ "fmt_macros 0.0.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "proc_macro 0.0.0", "rustc_errors 0.0.0", "syntax 0.0.0", @@ -1522,6 +1532,7 @@ dependencies = [ name = "syntax_pos" version = "0.0.0" dependencies = [ + "rustc_data_structures 0.0.0", "serialize 0.0.0", ] @@ -1531,7 +1542,7 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1548,48 +1559,47 @@ name = "term" version = "0.0.0" [[package]] -name = "term" -version = "0.4.5" +name = "term_size" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "term_size" -version = "0.2.3" +name = "termcolor" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "wincolor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "test" version = "0.0.0" dependencies = [ - "getopts 0.0.0", + "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.0.0", ] [[package]] -name = "thread-id" -version = "2.0.0" +name = "textwrap" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "thread-id" -version = "3.1.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1602,11 +1612,11 @@ dependencies = [ [[package]] name = "thread_local" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1623,36 +1633,28 @@ dependencies = [ [[package]] name = "toml" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "toml" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "unicode-bidi" -version = "0.2.5" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "unicode-normalization" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicode-segmentation" -version = "0.1.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1667,28 +1669,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unreachable" -version = "0.1.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "url" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "unstable-book-gen" +version = "0.1.0" dependencies = [ - "idna 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tidy 0.1.0", ] [[package]] -name = "user32-sys" -version = "0.2.0" +name = "url" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1701,9 +1702,14 @@ name = "utf8-ranges" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "vcpkg" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "vec_map" -version = "0.6.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1731,6 +1737,15 @@ name = "winapi-build" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "wincolor" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ws2_32-sys" version = "0.2.1" @@ -1745,7 +1760,7 @@ name = "xattr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1753,7 +1768,7 @@ name = "xz2" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lzma-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "lzma-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1766,81 +1781,81 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" -"checksum backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f551bc2ddd53aea015d453ef0b635af89444afa5ed2405dd0b2062ad5d600d80" -"checksum backtrace-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d192fd129132fbc97497c1f2ec2c2c5174e376b95f535199ef4fe0a293d33842" -"checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23" -"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" +"checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159" +"checksum backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72f9b4182546f4b04ebc4ab7f84948953a118bd6021a1b6a6c909e3e94f6be76" +"checksum backtrace-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3a0d842ea781ce92be2bf78a9b38883948542749640b8378b3b2f03d1fd9f1ff" "checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32" -"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c" -"checksum clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)" = "95b78f3fe0fc94c13c731714363260e04b557a637166f33a4570d3189d642374" -"checksum cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "92278eb79412c8f75cfc89e707a1bb3a6490b68f7f2e78d15c774f30fe701122" +"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" +"checksum clap 2.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "867a885995b4184be051b70a592d4d70e32d7a188db6e8dff626af286a962771" +"checksum cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ebbb35d3dc9cd09497168f33de1acb79b265d350ab0ac34133b98f8509af1f" "checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97" -"checksum curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c90e1240ef340dd4027ade439e5c7c2064dd9dc652682117bd50d1486a3add7b" -"checksum curl-sys 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "23e7e544dc5e1ba42c4a4a678bd47985e84b9c3f4d3404c29700622a029db9c3" +"checksum curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6689276ab61f97c660669a5ecc117c36875dfc1ba301c986b16c653415bdf9d7" +"checksum curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d5481162dc4f424d088581db2f979fa7d4c238fe9794595de61d8d7522e277de" "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" "checksum diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0a515461b6c8c08419850ced27bc29e86166dcdcde8fbe76f8b1f0589bb49472" -"checksum docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab32ea6e284d87987066f21a9e809a73c14720571ef34516f0890b3d355ccfd8" +"checksum docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b5b93718f8b3e5544fcc914c43de828ca6c6ace23e0332c6080a2977b49787a" "checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90" -"checksum env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e3856f1697098606fc6cb97a93de88ca3f3bc35bb878c725920e6e82ecf05e83" +"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" "checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8" +"checksum error-chain 0.11.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)" = "38d3a55d9a7a456748f2a3912c0941a5d9a68006eb15b3c3c9836b8420dc102d" "checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922" "checksum flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "36df0166e856739905cd3d7e0b210fe818592211a008862599845e012d8d304c" "checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d" -"checksum fs2 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34edaee07555859dc13ca387e6ae05686bb4d0364c95d649b6dab959511f4baf" -"checksum gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)" = "5f837c392f2ea61cb1576eac188653df828c861b7137d74ea4a5caa89621f9e6" -"checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518" +"checksum fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ab76cfd2aaa59b7bf6688ad9ba15bbae64bff97f04ea02144cfd3443e5c2866" +"checksum gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)" = "120d07f202dcc3f72859422563522b66fe6463a4c513df062874daad05f85f0a" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" "checksum git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aa01936ac96555c083c0e8553f672616274408d9d3fc5b8696603fbf63ff43ee" "checksum git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "68676bc784bf0bef83278898929bf64a251e87c0340723d0b93fa096c9c5bf8e" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bf088f042a467089e9baa4972f57f9247e42a0cc549ba264c7a04fbb8ecb89d4" -"checksum handlebars 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)" = "15bdf598fc3c2de40c6b340213028301c0d225eea55a2294e6cc148074e557a1" -"checksum idna 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac85ec3f80c8e4e99d9325521337e14ec7555c458a14e377d189659a427f375" +"checksum handlebars 0.26.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fbba80e74e9591a5f6a4ffff6b7f9d645759a896e431cfbdc853e9184370294a" +"checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa" +"checksum idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2233d4940b1f19f0418c158509cd7396b8d70a5db5705ce410914dc8fa603b37" "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" "checksum jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "443ae8bc0af6c106e6e8b77e04684faecc1a5ce94e058f4c2b0a037b0ea1b133" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" -"checksum libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "babb8281da88cba992fa1f4ddec7d63ed96280a1a53ec9b919fd37b53d71e502" +"checksum libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "30885bcb161cf67054244d10d4a7f4835ffd58773bc72e07d35fecf472295503" "checksum libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "df18a822100352d9863b302faf6f8f25c0e77f0e60feb40e5dbe1238b7f13b1d" "checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75" -"checksum libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e5ee912a45d686d393d5ac87fac15ba0ba18daae14e8e7543c63ebf7fb7e970c" -"checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad" -"checksum lzma-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fedff6a5cbb24494ec6ee4784e9ac5c187161fede04c7767d49bf87544013afa" -"checksum matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efd7622e3022e1a6eaa602c4cea8912254e5582c9c692e9167714182244801b1" -"checksum mdbook 0.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "f1e2e9d848514dcfad4195788d0d42ae5153a477c191d75d5b84fab10f222fbd" +"checksum libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd64ef8ee652185674455c1d450b83cbc8ad895625d543b5324d923f82e4d8" +"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" +"checksum lzma-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "013fa6506eb7d26040c46dab9ecb7ccb4e2896b5bf24a9d65932501ea9f67af8" +"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" +"checksum mdbook 0.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "22911d86cde6f80fa9f0fb2a68bbbde85d97af4fe0ce267141c83a4187d28700" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" "checksum miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "28eaee17666671fa872e567547e8428e83308ebe5808cdf6a0e28397dbe2c726" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "bc01404e7568680f1259aa5729539f221cb1e6d047a0d9053cab4be8a73b5d67" -"checksum num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "98b15ba84e910ea7a1973bccd3df7b31ae282bf9d8bd2897779950c9b8303d40" -"checksum num-bigint 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "ba6d838b16e56da1b6c383d065ff1ec3c7d7797f65a3e8f6ba7092fd87820bac" -"checksum num-complex 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "148eb324ca772230853418731ffdf13531738b50f89b30692a01fcdcb0a64677" +"checksum num 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "2c3a3dc9f30bf824141521b30c908a859ab190b76e20435fcd89f35eb6583887" +"checksum num-bigint 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "6361748d02e5291c72a422dc8ed4d8464a80cb1e618971f6fffe6d52d97e3286" +"checksum num-complex 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "412dfc143c56579aa6a22c574e38ddbf724522f1280ae2b257498cccff3fb6af" "checksum num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "ef1a4bf6f9174aa5783a9b4cc892cacd11aebad6c69ad027a0b65c6ca5f8aa37" "checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e" -"checksum num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "c2dc5ea04020a8f18318ae485c751f8cfa1c0e69dcf465c29ddaaa64a313cc44" -"checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99" -"checksum num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca313f1862c7ec3e0dfe8ace9fa91b1d9cb5c84ace3d00f5ec4216238e93c167" +"checksum num-rational 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "33c881e104a26e1accc09449374c095ff2312c8e0c27fab7bbefe16eac7c776d" +"checksum num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "1708c0628602a98b52fad936cf3edb9a107af06e52e49fdf0707e884456a6af6" +"checksum num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aec53c34f2d0247c5ca5d32cca1478762f301740468ee9ee6dcb7a0dd7a0c584" "checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842" -"checksum openssl 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bb5d1663b73d10c6a3eda53e2e9d0346f822394e7b858d7257718f65f61dfbe2" +"checksum openssl 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f776f1d8af832fd2c637ee182c801e8f7ea8895718a2be9914cca001f6e2c40a" "checksum openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d98df0270d404ccd3c050a41d579c52d1db15375168bb3471e04ec0f5f378daf" -"checksum openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)" = "3a5886d87d3e2a0d890bf62dc8944f5e3769a405f7e1e9ef6e517e47fd7a0897" +"checksum openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "ad95f8160d1c150c4f44d4c4959732e048ac046c37f597fe362f8bf57561ffb4" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" +"checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356" "checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8" "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" "checksum psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "abcd5d1a07d360e29727f757a9decb3ce8bc6e0efa8969cfaad669a8317a2478" "checksum pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9ab1e588ef8efd702c7ed9d2bd774db5e6f4d878bb5a1a9f371828fbdff6973" -"checksum pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1058d7bb927ca067656537eec4e02c2b4b70eaaa129664c5b90c111e20326f41" "checksum quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c36987d4978eb1be2e422b1e0423a557923a5c3e7e6f31d5699e9aafaefa469" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d" "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" -"checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01" +"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" -"checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457" -"checksum rls-data 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fc4277ce3c57f456b11fe3145b181a844a25201bab5cbaa1978457e6e2f27d47" +"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" +"checksum rls-data 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e502ac679bc35e023e982506c32d0278ef89e29af1e4ad21cb70c44b525b87a9" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" "checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" @@ -1848,45 +1863,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" "checksum semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd61b85a0fa777f7fb7c454b9189b2941b110d1385ce84d7f76efdf1606a85" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34b623917345a631dc9608d5194cc206b3fe6c3554cd1c75b937e55e285254af" -"checksum serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "38a3db3a5757f68069aba764b793823ea9fb9717c42c016f8903f8add50f508a" -"checksum serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e46ef71ee001a4279a4513e79a6ebbb59da3a4987bf77a6df2e5534cd6f21d82" -"checksum serde_derive_internals 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "021c338d22c7e30f957a6ab7e388cb6098499dda9fd4ba1661ee074ca7a180d1" +"checksum serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "433d7d9f8530d5a939ad5e0e72a6243d2e42a24804f70bf592c679363dcacb2f" +"checksum serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7b707cf0d4cab852084f573058def08879bb467fda89d99052485e7d00edd624" +"checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a" "checksum serde_ignored 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c10e798e4405d7dcec3658989e35ee6706f730a9ed7c1184d5ebd84317e82f46" -"checksum serde_json 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ad8bcf487be7d2e15d3d543f04312de991d631cfe1b43ea0ade69e6a8a5b16a1" "checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" "checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8" +"checksum socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "12cdbddbaa27bf94cc194b8e37f5811db6fe83cea96cf99cf1f8e92b65a41371" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" -"checksum strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "67f84c44fbb2f91db7fef94554e6b2ac05909c9c0b0bc23bb98d3a1aebfe7f7c" "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "281285b717926caa919ad905ef89c63d75805c7d89437fb873100925a53f2b1b" "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" -"checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989" -"checksum term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "07b6c1ac5b3fffd75073276bca1ceed01f67a28537097a2a9539e116e50fb21a" +"checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209" +"checksum termcolor 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9a5193a56b8d82014662c4b933dea6bec851daf018a2b01722e007daaf5f9dca" +"checksum textwrap 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f86300c3e7416ee233abd7cda890c492007a3980f941f79185c753a701257167" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" -"checksum thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df7875b676fddfadffd96deea3b1124e5ede707d4884248931077518cf1f773" "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" -"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" +"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" "checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796" -"checksum toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd86ad9ebee246fdedd610e0f6d0587b754a3d81438db930a244d0480ed7878f" -"checksum toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4cc5dbfb20a481e64b99eb7ae280859ec76730c7191570ba5edaa962394edb0a" -"checksum unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a078ebdd62c0e71a709c3d53d2af693fe09fe93fbff8344aebe289b78f9032" -"checksum unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e28fa37426fceeb5cf8f41ee273faa7c82c47dc8fba5853402841e665fcd86ff" -"checksum unicode-segmentation 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c3bc443ded17b11305ffffe6b37e2076f328a5a8cb6aa877b1b98f77699e98b5" +"checksum toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0601da6c97135c8d330c7a13a013ca6cd4143221b01de2f8d4edc50a9e551c7" +"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" +"checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" -"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" -"checksum url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5ba8a749fb4479b043733416c244fa9d1d3af3d7c23804944651c8a448cb87e" -"checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47" +"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb819346883532a271eb626deb43c4a1bb4c4dd47c519bd78137c3e72a4fe27" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" -"checksum vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cac5efe5cb0fa14ec2f84f83c701c562ee63f6dcc680861b21d65c682adfb05f" +"checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b" +"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum wincolor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a39ee4464208f6430992ff20154216ab2357772ac871d994c51628d60e58b8b0" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "5f04de8a1346489a2f9e9bd8526b73d135ec554227b17568456e86aa35b6f3fc" "checksum xz2 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e9510bdf100731599107c61f77daf46713a69a568f75458999c1f9dbf6ba25b0" diff --git a/src/Cargo.toml b/src/Cargo.toml index 015d658d22..dd775280f4 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -9,6 +9,7 @@ members = [ "tools/error_index_generator", "tools/linkchecker", "tools/rustbook", + "tools/unstable-book-gen", "tools/tidy", "tools/build-manifest", "tools/remote-test-client", diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index d048645d4d..134406b1ac 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -75,16 +75,11 @@ fn main() { 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 - // executable. Otherwise we just use the standard compiler we're - // bootstrapping with. - // - // Also note that cargo will detect the version of the compiler to trigger - // a rebuild when the compiler changes. If this happens, we want to make - // sure to use the actual compiler instead of the snapshot compiler becase - // that's the one that's actually changing. + // Use a different compiler for build scripts, since there may not yet be a + // libstd for the real compiler to use. However, if Cargo is attempting to + // determine the version of the compiler, the real compiler needs to be + // used. Currently, these two states are differentiated based on whether + // --target and -vV is/isn't passed. let (rustc, libdir) = if target.is_none() && version.is_none() { ("RUSTC_SNAPSHOT", "RUSTC_SNAPSHOT_LIBDIR") } else { @@ -118,13 +113,6 @@ fn main() { cmd.arg("-Cprefer-dynamic"); } - // Pass the `rustbuild` feature flag to crates which rustbuild is - // building. See the comment in bootstrap/lib.rs where this env var is - // set for more details. - if env::var_os("RUSTBUILD_UNSTABLE").is_some() { - cmd.arg("--cfg").arg("rustbuild"); - } - // Help the libc crate compile by assisting it in finding the MUSL // native libraries. if let Some(s) = env::var_os("MUSL_ROOT") { @@ -149,6 +137,11 @@ fn main() { } } + let crate_name = args.windows(2) + .find(|a| &*a[0] == "--crate-name") + .unwrap(); + let crate_name = &*crate_name[1]; + // 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 @@ -157,9 +150,12 @@ fn main() { // This... is a bit of a hack how we detect this. Ideally this // information should be encoded in the crate I guess? Would likely // require an RFC amendment to RFC 1513, however. - let is_panic_abort = args.windows(2) - .any(|a| &*a[0] == "--crate-name" && &*a[1] == "panic_abort"); - if is_panic_abort { + // + // `compiler_builtins` are unconditionally compiled with panic=abort to + // workaround undefined references to `rust_eh_unwind_resume` generated + // otherwise, see issue https://github.com/rust-lang/rust/issues/43095. + if crate_name == "panic_abort" || + crate_name == "compiler_builtins" && stage != "0" { cmd.arg("-C").arg("panic=abort"); } @@ -174,7 +170,15 @@ fn main() { Ok(s) => if s == "true" { "y" } else { "n" }, Err(..) => "n", }; - cmd.arg("-C").arg(format!("debug-assertions={}", debug_assertions)); + + // The compiler builtins are pretty sensitive to symbols referenced in + // libcore and such, so we never compile them with debug assertions. + if crate_name == "compiler_builtins" { + cmd.arg("-C").arg("debug-assertions=no"); + } else { + cmd.arg("-C").arg(format!("debug-assertions={}", debug_assertions)); + } + if let Ok(s) = env::var("RUSTC_CODEGEN_UNITS") { cmd.arg("-C").arg(format!("codegen-units={}", s)); } @@ -218,11 +222,7 @@ fn main() { // do that we pass a weird flag to the compiler to get it to do // so. Note that this is definitely a hack, and we should likely // flesh out rpath support more fully in the future. - // - // FIXME: remove condition after next stage0 - if stage != "0" { - cmd.arg("-Z").arg("osx-rpath-install-name"); - } + cmd.arg("-Z").arg("osx-rpath-install-name"); Some("-Wl,-rpath,@loader_path/../lib") } else if !target.contains("windows") { Some("-Wl,-rpath,$ORIGIN/../lib") @@ -242,15 +242,20 @@ fn main() { // Force all crates compiled by this compiler to (a) be unstable and (b) // allow the `rustc_private` feature to link to other unstable crates // also in the sysroot. - // - // FIXME: remove condition after next stage0 if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() { - if stage != "0" { - cmd.arg("-Z").arg("force-unstable-if-unmarked"); - } + cmd.arg("-Z").arg("force-unstable-if-unmarked"); } } + let color = match env::var("RUSTC_COLOR") { + Ok(s) => usize::from_str(&s).expect("RUSTC_COLOR should be an integer"), + Err(_) => 0, + }; + + if color != 0 { + cmd.arg("--color=always"); + } + if verbose > 1 { writeln!(&mut io::stderr(), "rustc command: {:?}", cmd).unwrap(); } diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index 3a1a9c3e40..d7d72d5dd5 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -41,11 +41,11 @@ fn main() { .env(bootstrap::util::dylib_path_var(), env::join_paths(&dylib_path).unwrap()); - // Pass the `rustbuild` feature flag to crates which rustbuild is - // building. See the comment in bootstrap/lib.rs where this env var is - // set for more details. - if env::var_os("RUSTBUILD_UNSTABLE").is_some() { - cmd.arg("--cfg").arg("rustbuild"); + // Force all crates compiled by this compiler to (a) be unstable and (b) + // allow the `rustc_private` feature to link to other unstable crates + // also in the sysroot. + if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() { + cmd.arg("-Z").arg("force-unstable-if-unmarked"); } std::process::exit(match cmd.status() { diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 971064fe9f..ebc4c2fdf7 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -25,10 +25,11 @@ from time import time def get(url, path, verbose=False): - sha_url = url + ".sha256" + suffix = '.sha256' + sha_url = url + suffix with tempfile.NamedTemporaryFile(delete=False) as temp_file: temp_path = temp_file.name - with tempfile.NamedTemporaryFile(suffix=".sha256", delete=False) as sha_file: + with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as sha_file: sha_path = sha_file.name try: @@ -55,6 +56,7 @@ def get(url, path, verbose=False): def delete_if_present(path, verbose): + """Remove the given file if present""" if os.path.isfile(path): if verbose: print("removing " + path) @@ -92,12 +94,13 @@ def _download(path, url, probably_big, verbose, exception): def verify(path, sha_path, verbose): + """Check if the sha256 sum of the given path is valid""" if verbose: print("verifying " + path) - with open(path, "rb") as f: - found = hashlib.sha256(f.read()).hexdigest() - with open(sha_path, "r") as f: - expected = f.readline().split()[0] + with open(path, "rb") as source: + found = hashlib.sha256(source.read()).hexdigest() + with open(sha_path, "r") as sha256sum: + expected = sha256sum.readline().split()[0] verified = found == expected if not verified: print("invalid checksum:\n" @@ -107,6 +110,7 @@ def verify(path, sha_path, verbose): def unpack(tarball, dst, verbose=False, match=None): + """Unpack the given tarball file""" print("extracting " + tarball) fname = os.path.basename(tarball).replace(".tar.gz", "") with contextlib.closing(tarfile.open(tarball)) as tar: @@ -128,6 +132,7 @@ def unpack(tarball, dst, verbose=False, match=None): shutil.move(tp, fp) shutil.rmtree(os.path.join(dst, fname)) + def run(args, verbose=False, exception=False, **kwargs): if verbose: print("running: " + ' '.join(args)) @@ -245,7 +250,8 @@ class RustBuild(object): return # At this point we're pretty sure the user is running NixOS - print("info: you seem to be running NixOS. Attempting to patch " + fname) + nix_os_msg = "info: you seem to be running NixOS. Attempting to patch" + print(nix_os_msg, fname) try: interpreter = subprocess.check_output( @@ -293,18 +299,22 @@ class RustBuild(object): return self._cargo_channel def rustc_stamp(self): + """Return the path for .rustc-stamp""" return os.path.join(self.bin_root(), '.rustc-stamp') def cargo_stamp(self): + """Return the path for .cargo-stamp""" return os.path.join(self.bin_root(), '.cargo-stamp') def rustc_out_of_date(self): + """Check if rustc is out of date""" if not os.path.exists(self.rustc_stamp()) or self.clean: return True with open(self.rustc_stamp(), 'r') as f: return self.stage0_date() != f.read() def cargo_out_of_date(self): + """Check if cargo is out of date""" if not os.path.exists(self.cargo_stamp()) or self.clean: return True with open(self.cargo_stamp(), 'r') as f: @@ -357,8 +367,7 @@ class RustBuild(object): def exe_suffix(self): if sys.platform == 'win32': return '.exe' - else: - return '' + return '' def print_what_it_means_to_bootstrap(self): if hasattr(self, 'printed'): @@ -366,7 +375,7 @@ class RustBuild(object): self.printed = True if os.path.exists(self.bootstrap_binary()): return - if not '--help' in sys.argv or len(sys.argv) == 1: + if '--help' not in sys.argv or len(sys.argv) == 1: return print('info: the build system for Rust is written in Rust, so this') @@ -385,6 +394,7 @@ class RustBuild(object): if self.clean and os.path.exists(build_dir): shutil.rmtree(build_dir) env = os.environ.copy() + env["RUSTC_BOOTSTRAP"] = '1' env["CARGO_TARGET_DIR"] = build_dir env["RUSTC"] = self.rustc() env["LD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \ @@ -460,8 +470,8 @@ class RustBuild(object): # always emit 'i386' on x86/amd64 systems). As such, isainfo -k # must be used instead. try: - cputype = subprocess.check_output(['isainfo', - '-k']).strip().decode(default_encoding) + cputype = subprocess.check_output( + ['isainfo', '-k']).strip().decode(default_encoding) except (subprocess.CalledProcessError, OSError): err = "isainfo not found" if self.verbose: @@ -561,21 +571,26 @@ class RustBuild(object): default_encoding = sys.getdefaultencoding() run(["git", "submodule", "-q", "sync"], cwd=self.rust_root) submodules = [s.split(' ', 1)[1] for s in subprocess.check_output( - ["git", "config", "--file", os.path.join(self.rust_root, ".gitmodules"), + ["git", "config", "--file", + os.path.join(self.rust_root, ".gitmodules"), "--get-regexp", "path"] ).decode(default_encoding).splitlines()] submodules = [module for module in submodules if not ((module.endswith("llvm") and - (self.get_toml('llvm-config') or self.get_mk('CFG_LLVM_ROOT'))) or + (self.get_toml('llvm-config') or + self.get_mk('CFG_LLVM_ROOT'))) or (module.endswith("jemalloc") and - (self.get_toml('jemalloc') or self.get_mk('CFG_JEMALLOC_ROOT')))) - ] + (self.get_toml('jemalloc') or + self.get_mk('CFG_JEMALLOC_ROOT'))))] run(["git", "submodule", "update", - "--init"] + submodules, cwd=self.rust_root, verbose=self.verbose) + "--init", "--recursive"] + submodules, + cwd=self.rust_root, verbose=self.verbose) run(["git", "submodule", "-q", "foreach", "git", - "reset", "-q", "--hard"], cwd=self.rust_root, verbose=self.verbose) + "reset", "-q", "--hard"], + cwd=self.rust_root, verbose=self.verbose) run(["git", "submodule", "-q", "foreach", "git", - "clean", "-qdfx"], cwd=self.rust_root, verbose=self.verbose) + "clean", "-qdfx"], + cwd=self.rust_root, verbose=self.verbose) def bootstrap(): @@ -667,6 +682,7 @@ def bootstrap(): env["BUILD"] = rb.build env["SRC"] = rb.rust_root env["BOOTSTRAP_PARENT_ID"] = str(os.getpid()) + env["BOOTSTRAP_PYTHON"] = sys.executable run(args, env=env, verbose=rb.verbose) @@ -690,5 +706,6 @@ def main(): format_build_time(time() - start_time)) sys.exit(exit_code) + if __name__ == '__main__': main() diff --git a/src/bootstrap/cc.rs b/src/bootstrap/cc.rs index 54c8194678..7c7161916e 100644 --- a/src/bootstrap/cc.rs +++ b/src/bootstrap/cc.rs @@ -42,10 +42,13 @@ use config::Target; pub fn find(build: &mut Build) { // For all targets we're going to need a C compiler for building some shims // and such as well as for being a linker for Rust code. - for target in build.config.target.iter() { + // + // This includes targets that aren't necessarily passed on the commandline + // (FIXME: Perhaps it shouldn't?) + for target in &build.config.target { let mut cfg = gcc::Config::new(); cfg.cargo_metadata(false).opt_level(0).debug(false) - .target(target).host(&build.config.build); + .target(target).host(&build.build); let config = build.config.target_config.get(target); if let Some(cc) = config.and_then(|c| c.cc.as_ref()) { @@ -64,10 +67,13 @@ pub fn find(build: &mut Build) { } // For all host triples we need to find a C++ compiler as well - for host in build.config.host.iter() { + // + // This includes hosts that aren't necessarily passed on the commandline + // (FIXME: Perhaps it shouldn't?) + for host in &build.config.host { let mut cfg = gcc::Config::new(); cfg.cargo_metadata(false).opt_level(0).debug(false).cpp(true) - .target(host).host(&build.config.build); + .target(host).host(&build.build); let config = build.config.target_config.get(host); if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) { cfg.compiler(cxx); diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index 6309adf54b..16a7aa8b0a 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -23,12 +23,12 @@ use build_helper::output; use Build; // The version number -pub const CFG_RELEASE_NUM: &'static str = "1.19.0"; +pub const CFG_RELEASE_NUM: &str = "1.20.0"; // An optional number to put after the label, e.g. '.2' -> '-beta.2' // Be sure to make this starts with a dot to conform to semver pre-release // versions (section 9) -pub const CFG_PRERELEASE_VERSION: &'static str = ".4"; +pub const CFG_PRERELEASE_VERSION: &str = ".3"; pub struct GitInfo { inner: Option, @@ -99,6 +99,10 @@ impl GitInfo { version.push_str(&inner.commit_date); version.push_str(")"); } - return version + version + } + + pub fn is_git(&self) -> bool { + self.inner.is_some() } } diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 5483b6a914..e4b0e2fb9c 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -13,22 +13,23 @@ //! This file implements the various regression test suites that we execute on //! our CI. -extern crate build_helper; - use std::collections::HashSet; use std::env; +use std::ffi::OsString; +use std::iter; use std::fmt; -use std::fs; +use std::fs::{self, File}; use std::path::{PathBuf, Path}; use std::process::Command; +use std::io::Read; -use build_helper::output; +use build_helper::{self, output}; use {Build, Compiler, Mode}; use dist; use util::{self, dylib_path, dylib_path_var, exe}; -const ADB_TEST_DIR: &'static str = "/data/tmp/work"; +const ADB_TEST_DIR: &str = "/data/tmp/work"; /// The two modes of the test runner; tests or benchmarks. #[derive(Copy, Clone)] @@ -59,7 +60,7 @@ impl fmt::Display for TestKind { } fn try_run(build: &Build, cmd: &mut Command) { - if build.flags.cmd.no_fail_fast() { + if !build.fail_fast { if !build.try_run(cmd) { let failures = build.delayed_failures.get(); build.delayed_failures.set(failures + 1); @@ -70,7 +71,7 @@ fn try_run(build: &Build, cmd: &mut Command) { } fn try_run_quiet(build: &Build, cmd: &mut Command) { - if build.flags.cmd.no_fail_fast() { + if !build.fail_fast { if !build.try_run_quiet(cmd) { let failures = build.delayed_failures.get(); build.delayed_failures.set(failures + 1); @@ -98,7 +99,7 @@ pub fn linkcheck(build: &Build, host: &str) { /// This tool in `src/tools` will check out a few Rust projects and run `cargo /// test` to ensure that we don't regress the test suites there. pub fn cargotest(build: &Build, stage: u32, host: &str) { - let ref compiler = Compiler::new(stage, host); + let compiler = Compiler::new(stage, host); // Note that this is a short, cryptic, and not scoped directory name. This // is currently to minimize the length of path on Windows where we otherwise @@ -108,28 +109,20 @@ pub fn cargotest(build: &Build, stage: u32, host: &str) { let _time = util::timeit(); let mut cmd = Command::new(build.tool(&Compiler::new(0, host), "cargotest")); - build.prepare_tool_cmd(compiler, &mut cmd); - try_run(build, cmd.arg(&build.cargo) + build.prepare_tool_cmd(&compiler, &mut cmd); + try_run(build, cmd.arg(&build.initial_cargo) .arg(&out_dir) - .env("RUSTC", build.compiler_path(compiler)) - .env("RUSTDOC", build.rustdoc(compiler))); + .env("RUSTC", build.compiler_path(&compiler)) + .env("RUSTDOC", build.rustdoc(&compiler))); } /// Runs `cargo test` for `cargo` packaged with Rust. pub fn cargo(build: &Build, stage: u32, host: &str) { - let ref compiler = Compiler::new(stage, host); - - // Configure PATH to find the right rustc. NB. we have to use PATH - // and not RUSTC because the Cargo test suite has tests that will - // fail if rustc is not spelled `rustc`. - let path = build.sysroot(compiler).join("bin"); - let old_path = ::std::env::var("PATH").expect(""); - let sep = if cfg!(windows) { ";" } else {":" }; - let ref newpath = format!("{}{}{}", path.display(), sep, old_path); + let compiler = &Compiler::new(stage, host); let mut cargo = build.cargo(compiler, Mode::Tool, host, "test"); cargo.arg("--manifest-path").arg(build.src.join("src/tools/cargo/Cargo.toml")); - if build.flags.cmd.no_fail_fast() { + if !build.fail_fast { cargo.arg("--no-fail-fast"); } @@ -140,7 +133,31 @@ pub fn cargo(build: &Build, stage: u32, host: &str) { // available. cargo.env("CFG_DISABLE_CROSS_TESTS", "1"); - try_run(build, cargo.env("PATH", newpath)); + try_run(build, cargo.env("PATH", &path_for_cargo(build, compiler))); +} + +/// Runs `cargo test` for the rls. +pub fn rls(build: &Build, stage: u32, host: &str) { + let compiler = &Compiler::new(stage, host); + + let mut cargo = build.cargo(compiler, Mode::Tool, host, "test"); + cargo.arg("--manifest-path").arg(build.src.join("src/tools/rls/Cargo.toml")); + + // Don't build tests dynamically, just a pain to work with + cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); + + build.add_rustc_lib_path(compiler, &mut cargo); + + try_run(build, &mut cargo); +} + +fn path_for_cargo(build: &Build, compiler: &Compiler) -> OsString { + // Configure PATH to find the right rustc. NB. we have to use PATH + // and not RUSTC because the Cargo test suite has tests that will + // fail if rustc is not spelled `rustc`. + let path = build.sysroot(compiler).join("bin"); + let old_path = env::var_os("PATH").unwrap_or_default(); + env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("") } /// Runs the `tidy` tool as compiled in `stage` by the `host` compiler. @@ -197,9 +214,9 @@ pub fn compiletest(build: &Build, cmd.arg("--mode").arg(mode); cmd.arg("--target").arg(target); cmd.arg("--host").arg(compiler.host); - cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.config.build)); + cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.build)); - if let Some(nodejs) = build.config.nodejs.as_ref() { + if let Some(ref nodejs) = build.config.nodejs { cmd.arg("--nodejs").arg(nodejs); } @@ -223,7 +240,7 @@ pub fn compiletest(build: &Build, cmd.arg("--docck-python").arg(build.python()); - if build.config.build.ends_with("apple-darwin") { + if build.build.ends_with("apple-darwin") { // Force /usr/bin/python on macOS for LLDB tests because we're loading the // LLDB plugin's compiled module which only works with the system python // (namely not Homebrew-installed python) @@ -244,10 +261,13 @@ pub fn compiletest(build: &Build, let llvm_config = build.llvm_config(target); let llvm_version = output(Command::new(&llvm_config).arg("--version")); cmd.arg("--llvm-version").arg(llvm_version); + if !build.is_rust_llvm(target) { + cmd.arg("--system-llvm"); + } cmd.args(&build.flags.cmd.test_args()); - if build.config.verbose() || build.flags.verbose() { + if build.is_verbose() { cmd.arg("--verbose"); } @@ -261,7 +281,7 @@ pub fn compiletest(build: &Build, let llvm_components = output(Command::new(&llvm_config).arg("--components")); let llvm_cxxflags = output(Command::new(&llvm_config).arg("--cxxflags")); cmd.arg("--cc").arg(build.cc(target)) - .arg("--cxx").arg(build.cxx(target)) + .arg("--cxx").arg(build.cxx(target).unwrap()) .arg("--cflags").arg(build.cflags(target).join(" ")) .arg("--llvm-components").arg(llvm_components.trim()) .arg("--llvm-cxxflags").arg(llvm_cxxflags.trim()); @@ -275,7 +295,7 @@ pub fn compiletest(build: &Build, if build.remote_tested(target) { cmd.arg("--remote-test-client") - .arg(build.tool(&Compiler::new(0, &build.config.build), + .arg(build.tool(&Compiler::new(0, &build.build), "remote-test-client")); } @@ -298,6 +318,10 @@ pub fn compiletest(build: &Build, cmd.env("SANITIZER_SUPPORT", "1"); } + if build.config.profiler { + cmd.env("PROFILER_SUPPORT", "1"); + } + cmd.arg("--adb-path").arg("adb"); cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR); if target.contains("android") { @@ -333,20 +357,15 @@ pub fn docs(build: &Build, compiler: &Compiler) { } if p.extension().and_then(|s| s.to_str()) != Some("md") { - continue + continue; } - // The nostarch directory in the book is for no starch, and so isn't guaranteed to build. - // we don't care if it doesn't build, so skip it. - use std::ffi::OsStr; - let path: &OsStr = p.as_ref(); - if let Some(path) = path.to_str() { - if path.contains("nostarch") { - continue; - } + // The nostarch directory in the book is for no starch, and so isn't + // guaranteed to build. We don't care if it doesn't build, so skip it. + if p.to_str().map_or(false, |p| p.contains("nostarch")) { + continue; } - println!("doc tests for: {}", p.display()); markdown_test(build, compiler, &p); } } @@ -370,12 +389,20 @@ pub fn error_index(build: &Build, compiler: &Compiler) { "error_index_generator") .arg("markdown") .arg(&output) - .env("CFG_BUILD", &build.config.build)); + .env("CFG_BUILD", &build.build)); markdown_test(build, compiler, &output); } fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) { + let mut file = t!(File::open(markdown)); + let mut contents = String::new(); + t!(file.read_to_string(&mut contents)); + if !contents.contains("```") { + return; + } + + println!("doc tests for: {}", markdown.display()); let mut cmd = Command::new(build.rustdoc(compiler)); build.add_rustc_lib_path(compiler, &mut cmd); build.add_rust_test_threads(&mut cmd); @@ -444,7 +471,7 @@ pub fn krate(build: &Build, cargo.arg("--manifest-path") .arg(build.src.join(path).join("Cargo.toml")) .arg("--features").arg(features); - if test_kind.subcommand() == "test" && build.flags.cmd.no_fail_fast() { + if test_kind.subcommand() == "test" && !build.fail_fast { cargo.arg("--no-fail-fast"); } @@ -514,16 +541,14 @@ fn krate_emscripten(build: &Build, compiler: &Compiler, target: &str, mode: Mode) { - let mut tests = Vec::new(); let out_dir = build.cargo_out(compiler, mode, target); - find_tests(&out_dir.join("deps"), target, &mut tests); + let tests = find_tests(&out_dir.join("deps"), target); + let nodejs = build.config.nodejs.as_ref().expect("nodejs not configured"); for test in tests { - let test_file_name = test.to_string_lossy().into_owned(); - println!("running {}", test_file_name); - let nodejs = build.config.nodejs.as_ref().expect("nodejs not configured"); + println!("running {}", test.display()); let mut cmd = Command::new(nodejs); - cmd.arg(&test_file_name); + cmd.arg(&test); if build.config.quiet_tests { cmd.arg("--quiet"); } @@ -535,11 +560,10 @@ fn krate_remote(build: &Build, compiler: &Compiler, target: &str, mode: Mode) { - let mut tests = Vec::new(); let out_dir = build.cargo_out(compiler, mode, target); - find_tests(&out_dir.join("deps"), target, &mut tests); + let tests = find_tests(&out_dir.join("deps"), target); - let tool = build.tool(&Compiler::new(0, &build.config.build), + let tool = build.tool(&Compiler::new(0, &build.build), "remote-test-client"); for test in tests { let mut cmd = Command::new(&tool); @@ -553,9 +577,8 @@ fn krate_remote(build: &Build, } } -fn find_tests(dir: &Path, - target: &str, - dst: &mut Vec) { +fn find_tests(dir: &Path, target: &str) -> Vec { + let mut dst = Vec::new(); for e in t!(dir.read_dir()).map(|e| t!(e)) { let file_type = t!(e.file_type()); if !file_type.is_file() { @@ -564,10 +587,13 @@ fn find_tests(dir: &Path, let filename = e.file_name().into_string().unwrap(); if (target.contains("windows") && filename.ends_with(".exe")) || (!target.contains("windows") && !filename.contains(".")) || - (target.contains("emscripten") && filename.ends_with(".js")) { + (target.contains("emscripten") && + filename.ends_with(".js") && + !filename.ends_with(".asm.js")) { dst.push(e.path()); } } + dst } pub fn remote_copy_libs(build: &Build, compiler: &Compiler, target: &str) { @@ -582,7 +608,7 @@ pub fn remote_copy_libs(build: &Build, compiler: &Compiler, target: &str) { .join(exe("remote-test-server", target)); // Spawn the emulator and wait for it to come online - let tool = build.tool(&Compiler::new(0, &build.config.build), + let tool = build.tool(&Compiler::new(0, &build.build), "remote-test-client"); let mut cmd = Command::new(&tool); cmd.arg("spawn-emulator") @@ -608,7 +634,7 @@ pub fn remote_copy_libs(build: &Build, compiler: &Compiler, target: &str) { /// Run "distcheck", a 'make check' from a tarball pub fn distcheck(build: &Build) { - if build.config.build != "x86_64-unknown-linux-gnu" { + if build.build != "x86_64-unknown-linux-gnu" { return } if !build.config.host.iter().any(|s| s == "x86_64-unknown-linux-gnu") { @@ -633,7 +659,7 @@ pub fn distcheck(build: &Build) { .args(&build.config.configure_args) .arg("--enable-vendor") .current_dir(&dir)); - build.run(Command::new(build_helper::make(&build.config.build)) + build.run(Command::new(build_helper::make(&build.build)) .arg("check") .current_dir(&dir)); @@ -651,7 +677,7 @@ pub fn distcheck(build: &Build) { build.run(&mut cmd); let toml = dir.join("rust-src/lib/rustlib/src/rust/src/libstd/Cargo.toml"); - build.run(Command::new(&build.cargo) + build.run(Command::new(&build.initial_cargo) .arg("generate-lockfile") .arg("--manifest-path") .arg(&toml) @@ -660,12 +686,13 @@ pub fn distcheck(build: &Build) { /// Test the build system itself pub fn bootstrap(build: &Build) { - let mut cmd = Command::new(&build.cargo); + let mut cmd = Command::new(&build.initial_cargo); cmd.arg("test") .current_dir(build.src.join("src/bootstrap")) .env("CARGO_TARGET_DIR", build.out.join("bootstrap")) - .env("RUSTC", &build.rustc); - if build.flags.cmd.no_fail_fast() { + .env("RUSTC_BOOTSTRAP", "1") + .env("RUSTC", &build.initial_rustc); + if !build.fail_fast { cmd.arg("--no-fail-fast"); } cmd.arg("--").args(&build.flags.cmd.test_args()); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 9946c93913..5a3106c7d5 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -50,7 +50,7 @@ pub fn std(build: &Build, target: &str, compiler: &Compiler) { let mut cargo = build.cargo(compiler, Mode::Libstd, target, "build"); let mut features = build.std_features(); - if let Ok(target) = env::var("MACOSX_STD_DEPLOYMENT_TARGET") { + if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { cargo.env("MACOSX_DEPLOYMENT_TARGET", target); } @@ -158,7 +158,7 @@ pub fn build_startup_objects(build: &Build, for_compiler: &Compiler, target: &st return } - let compiler = Compiler::new(0, &build.config.build); + let compiler = Compiler::new(0, &build.build); let compiler_path = build.compiler_path(&compiler); let src_dir = &build.src.join("src/rtstartup"); let dst_dir = &build.native_dir(target).join("rtstartup"); @@ -199,7 +199,7 @@ pub fn test(build: &Build, target: &str, compiler: &Compiler) { let out_dir = build.cargo_out(compiler, Mode::Libtest, target); build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target)); let mut cargo = build.cargo(compiler, Mode::Libtest, target, "build"); - if let Ok(target) = env::var("MACOSX_STD_DEPLOYMENT_TARGET") { + if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { cargo.env("MACOSX_DEPLOYMENT_TARGET", target); } cargo.arg("--manifest-path") @@ -247,7 +247,7 @@ pub fn rustc(build: &Build, target: &str, compiler: &Compiler) { cargo.env("CFG_RELEASE", build.rust_release()) .env("CFG_RELEASE_CHANNEL", &build.config.channel) .env("CFG_VERSION", build.rust_version()) - .env("CFG_PREFIX", build.config.prefix.clone().unwrap_or(PathBuf::new())); + .env("CFG_PREFIX", build.config.prefix.clone().unwrap_or_default()); if compiler.stage == 0 { cargo.env("CFG_LIBDIR_RELATIVE", "lib"); @@ -287,7 +287,7 @@ pub fn rustc(build: &Build, target: &str, compiler: &Compiler) { !target.contains("windows") && !target.contains("apple") { cargo.env("LLVM_STATIC_STDCPP", - compiler_file(build.cxx(target), "libstdc++.a")); + compiler_file(build.cxx(target).unwrap(), "libstdc++.a")); } if build.config.llvm_link_shared { cargo.env("LLVM_LINK_SHARED", "1"); @@ -351,7 +351,7 @@ pub fn create_sysroot(build: &Build, compiler: &Compiler) { /// Prepare a new compiler from the artifacts in `stage` /// /// This will assemble a compiler in `build/$host/stage$stage`. The compiler -/// must have been previously produced by the `stage - 1` build.config.build +/// must have been previously produced by the `stage - 1` build.build /// compiler. pub fn assemble_rustc(build: &Build, stage: u32, host: &str) { // nothing to do in stage0 @@ -365,7 +365,7 @@ pub fn assemble_rustc(build: &Build, stage: u32, host: &str) { 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); + let build_compiler = Compiler::new(stage - 1, &build.build); // Link in all dylibs to the libdir let sysroot = build.sysroot(&target_compiler); @@ -385,7 +385,7 @@ pub fn assemble_rustc(build: &Build, stage: u32, host: &str) { let rustc = out_dir.join(exe("rustc", host)); let bindir = sysroot.join("bin"); t!(fs::create_dir_all(&bindir)); - let compiler = build.compiler_path(&Compiler::new(stage, host)); + let compiler = build.compiler_path(&target_compiler); let _ = fs::remove_file(&compiler); copy(&rustc, &compiler); @@ -407,6 +407,8 @@ fn add_to_sysroot(sysroot_dst: &Path, stamp: &Path) { t!(fs::create_dir_all(&sysroot_dst)); let mut contents = Vec::new(); t!(t!(File::open(stamp)).read_to_end(&mut contents)); + // This is the method we use for extracting paths from the stamp file passed to us. See + // run_cargo for more information (in this file). for part in contents.split(|b| *b == 0) { if part.is_empty() { continue @@ -421,7 +423,7 @@ fn add_to_sysroot(sysroot_dst: &Path, stamp: &Path) { /// This will build the specified tool with the specified `host` compiler in /// `stage` into the normal cargo output directory. pub fn maybe_clean_tools(build: &Build, stage: u32, target: &str, mode: Mode) { - let compiler = Compiler::new(stage, &build.config.build); + let compiler = Compiler::new(stage, &build.build); let stamp = match mode { Mode::Libstd => libstd_stamp(build, &compiler, target), @@ -441,7 +443,7 @@ pub fn tool(build: &Build, stage: u32, target: &str, tool: &str) { let _folder = build.fold_output(|| format!("stage{}-{}", stage, tool)); println!("Building stage{} tool {} ({})", stage, tool, target); - let compiler = Compiler::new(stage, &build.config.build); + let compiler = Compiler::new(stage, &build.build); let mut cargo = build.cargo(&compiler, Mode::Tool, target, "build"); let dir = build.src.join("src/tools").join(tool); @@ -473,11 +475,43 @@ pub fn tool(build: &Build, stage: u32, target: &str, tool: &str) { build.run(&mut cargo); } + +// Avoiding a dependency on winapi to keep compile times down +#[cfg(unix)] +fn stderr_isatty() -> bool { + use libc; + unsafe { libc::isatty(libc::STDERR_FILENO) != 0 } +} +#[cfg(windows)] +fn stderr_isatty() -> bool { + type DWORD = u32; + type BOOL = i32; + type HANDLE = *mut u8; + const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD; + extern "system" { + fn GetStdHandle(which: DWORD) -> HANDLE; + fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: *mut DWORD) -> BOOL; + } + unsafe { + let handle = GetStdHandle(STD_ERROR_HANDLE); + let mut out = 0; + GetConsoleMode(handle, &mut out) != 0 + } +} + fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path) { // Instruct Cargo to give us json messages on stdout, critically leaving // stderr as piped so we can get those pretty colors. cargo.arg("--message-format").arg("json") .stdout(Stdio::piped()); + + if stderr_isatty() { + // since we pass message-format=json to cargo, we need to tell the rustc + // wrapper to give us colored output if necessary. This is because we + // only want Cargo's JSON output, not rustcs. + cargo.env("RUSTC_COLOR", "1"); + } + build.verbose(&format!("running: {:?}", cargo)); let mut child = match cargo.spawn() { Ok(child) => child, @@ -525,23 +559,24 @@ fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path) { // If this was an output file in the "host dir" we don't actually // worry about it, it's not relevant for us. if filename.starts_with(&host_root_dir) { - continue + continue; + } // If this was output in the `deps` dir then this is a precise file // name (hash included) so we start tracking it. - } else if filename.starts_with(&target_deps_dir) { + if filename.starts_with(&target_deps_dir) { deps.push(filename.to_path_buf()); + continue; + } // Otherwise this was a "top level artifact" which right now doesn't // have a hash in the name, but there's a version of this file in // the `deps` folder which *does* have a hash in the name. That's // the one we'll want to we'll probe for it later. - } else { - toplevel.push((filename.file_stem().unwrap() - .to_str().unwrap().to_string(), - filename.extension().unwrap().to_owned() - .to_str().unwrap().to_string())); - } + toplevel.push((filename.file_stem().unwrap() + .to_str().unwrap().to_string(), + filename.extension().unwrap().to_owned() + .to_str().unwrap().to_string())); } } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index af10a58258..34628852ab 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -50,6 +50,7 @@ pub struct Config { pub full_bootstrap: bool, pub extended: bool, pub sanitizers: bool, + pub profiler: bool, // llvm codegen options pub llvm_assertions: bool, @@ -59,6 +60,7 @@ pub struct Config { pub llvm_static_stdcpp: bool, pub llvm_link_shared: bool, pub llvm_targets: Option, + pub llvm_experimental_targets: Option, pub llvm_link_jobs: Option, pub llvm_clean_rebuild: bool, @@ -79,8 +81,6 @@ pub struct Config { pub build: String, pub host: Vec, pub target: Vec, - pub rustc: Option, - pub cargo: Option, pub local_rebuild: bool, // dist misc @@ -112,11 +112,18 @@ pub struct Config { pub python: Option, pub configure_args: Vec, pub openssl_static: bool, + + + // These are either the stage0 downloaded binaries or the locally installed ones. + pub initial_cargo: PathBuf, + pub initial_rustc: PathBuf, + } /// Per-target configuration stored in the global configuration structure. #[derive(Default)] pub struct Target { + /// Some(path to llvm-config) if using an external LLVM. pub llvm_config: Option, pub jemalloc: Option, pub cc: Option, @@ -162,6 +169,7 @@ struct Build { extended: Option, verbose: Option, sanitizers: Option, + profiler: Option, openssl_static: Option, } @@ -187,6 +195,7 @@ struct Llvm { version_check: Option, static_libstdcpp: Option, targets: Option, + experimental_targets: Option, link_jobs: Option, clean_rebuild: Option, } @@ -303,8 +312,6 @@ impl Config { config.target.push(target.clone()); } } - config.rustc = build.rustc.map(PathBuf::from); - config.cargo = build.cargo.map(PathBuf::from); config.nodejs = build.nodejs.map(PathBuf::from); config.gdb = build.gdb.map(PathBuf::from); config.python = build.python.map(PathBuf::from); @@ -318,6 +325,7 @@ impl Config { set(&mut config.extended, build.extended); set(&mut config.verbose, build.verbose); set(&mut config.sanitizers, build.sanitizers); + set(&mut config.profiler, build.profiler); set(&mut config.openssl_static, build.openssl_static); if let Some(ref install) = toml.install { @@ -347,6 +355,7 @@ impl Config { set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp); set(&mut config.llvm_clean_rebuild, llvm.clean_rebuild); config.llvm_targets = llvm.targets.clone(); + config.llvm_experimental_targets = llvm.experimental_targets.clone(); config.llvm_link_jobs = llvm.link_jobs; } @@ -404,13 +413,25 @@ impl Config { set(&mut config.rust_dist_src, t.src_tarball); } + let cwd = t!(env::current_dir()); + let out = cwd.join("build"); + + let stage0_root = out.join(&config.build).join("stage0/bin"); + config.initial_rustc = match build.rustc { + Some(s) => PathBuf::from(s), + None => stage0_root.join(exe("rustc", &config.build)), + }; + config.initial_cargo = match build.cargo { + Some(s) => PathBuf::from(s), + None => stage0_root.join(exe("cargo", &config.build)), + }; // compat with `./configure` while we're still using that if fs::metadata("config.mk").is_ok() { config.update_with_config_mk(); } - return config + config } /// "Temporary" routine to parse `config.mk` into this configuration. @@ -477,6 +498,7 @@ impl Config { ("FULL_BOOTSTRAP", self.full_bootstrap), ("EXTENDED", self.extended), ("SANITIZERS", self.sanitizers), + ("PROFILER", self.profiler), ("DIST_SRC", self.rust_dist_src), ("CARGO_OPENSSL_STATIC", self.openssl_static), } @@ -490,6 +512,9 @@ impl Config { "CFG_TARGET" if value.len() > 0 => { self.target.extend(value.split(" ").map(|s| s.to_string())); } + "CFG_EXPERIMENTAL_TARGETS" if value.len() > 0 => { + self.llvm_experimental_targets = Some(value.to_string()); + } "CFG_MUSL_ROOT" if value.len() > 0 => { self.musl_root = Some(parse_configure_path(value)); } @@ -599,8 +624,8 @@ impl Config { } "CFG_LOCAL_RUST_ROOT" if value.len() > 0 => { let path = parse_configure_path(value); - self.rustc = Some(push_exe_path(path.clone(), &["bin", "rustc"])); - self.cargo = Some(push_exe_path(path, &["bin", "cargo"])); + self.initial_rustc = push_exe_path(path.clone(), &["bin", "rustc"]); + self.initial_cargo = push_exe_path(path, &["bin", "cargo"]); } "CFG_PYTHON" if value.len() > 0 => { let path = parse_configure_path(value); diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example index 0eb6c4c82c..7a52222e46 100644 --- a/src/bootstrap/config.toml.example +++ b/src/bootstrap/config.toml.example @@ -53,6 +53,14 @@ # Rust team and file an issue if you need assistance in porting! #targets = "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX;Hexagon" +# LLVM experimental targets to build support for. These targets are specified in +# the same format as above, but since these targets are experimental, they are +# not built by default and the experimental Rust compilation targets that depend +# on them will not work unless the user opts in to building them. Possible +# experimental LLVM targets include WebAssembly for the +# wasm32-experimental-emscripten Rust target. +#experimental-targets = "" + # Cap the number of parallel linker invocations when compiling LLVM. # This can be useful when building LLVM with debug info, which significantly # increases the size of binaries and consequently the memory required by @@ -147,6 +155,9 @@ # Build the sanitizer runtimes #sanitizers = false +# Build the profiler runtime +#profiler = false + # Indicates whether the OpenSSL linked into Cargo will be statically linked or # not. If static linkage is specified then the build system will download a # known-good version of OpenSSL, compile it, and link it to Cargo. diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 6d696dfe5b..807e878eda 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -50,7 +50,7 @@ pub fn tmpdir(build: &Build) -> PathBuf { } fn rust_installer(build: &Build) -> Command { - build.tool_cmd(&Compiler::new(0, &build.config.build), "rust-installer") + build.tool_cmd(&Compiler::new(0, &build.build), "rust-installer") } /// Builds the `rust-docs` installer component. @@ -89,7 +89,7 @@ pub fn docs(build: &Build, stage: u32, host: &str) { // As part of this step, *also* copy the docs directory to a directory which // buildbot typically uploads. - if host == build.config.build { + if host == build.build { let dst = distdir(build).join("doc").join(build.rust_package_vers()); t!(fs::create_dir_all(&dst)); cp_r(&src, &dst); @@ -97,7 +97,7 @@ pub fn docs(build: &Build, stage: u32, host: &str) { } fn find_files(files: &[&str], path: &[PathBuf]) -> Vec { - let mut found = Vec::new(); + let mut found = Vec::with_capacity(files.len()); for file in files { let file_path = @@ -119,17 +119,9 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: //Ask gcc where it keeps its stuff let mut cmd = Command::new(build.cc(target_triple)); cmd.arg("-print-search-dirs"); - build.run_quiet(&mut cmd); - let gcc_out = - String::from_utf8( - cmd - .output() - .expect("failed to execute gcc") - .stdout).expect("gcc.exe output was not utf8"); - - let mut bin_path: Vec<_> = - env::split_paths(&env::var_os("PATH").unwrap_or_default()) - .collect(); + let gcc_out = output(&mut cmd); + + let mut bin_path: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect(); let mut lib_path = Vec::new(); for line in gcc_out.lines() { @@ -140,7 +132,7 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: line[(idx + 1)..] .trim_left_matches(trim_chars) .split(';') - .map(|s| PathBuf::from(s)); + .map(PathBuf::from); if key == "programs" { bin_path.extend(value); @@ -149,7 +141,7 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: } } - let target_tools = vec!["gcc.exe", "ld.exe", "ar.exe", "dlltool.exe", "libwinpthread-1.dll"]; + let target_tools = ["gcc.exe", "ld.exe", "ar.exe", "dlltool.exe", "libwinpthread-1.dll"]; let mut rustc_dlls = vec!["libstdc++-6.dll", "libwinpthread-1.dll"]; if target_triple.starts_with("i686-") { rustc_dlls.push("libgcc_s_dw2-1.dll"); @@ -157,7 +149,7 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: rustc_dlls.push("libgcc_s_seh-1.dll"); } - let target_libs = vec![ //MinGW libs + let target_libs = [ //MinGW libs "libgcc.a", "libgcc_eh.a", "libgcc_s.a", @@ -203,7 +195,7 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: let target_libs = find_files(&target_libs, &lib_path); fn copy_to_folder(src: &Path, dest_folder: &Path) { - let file_name = src.file_name().unwrap().to_os_string(); + let file_name = src.file_name().unwrap(); let dest = dest_folder.join(file_name); copy(src, &dest); } @@ -234,8 +226,6 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: /// /// This contains all the bits and pieces to run the MinGW Windows targets /// without any extra installed software (e.g. we bundle gcc, libraries, etc). -/// Currently just shells out to a python script, but that should be rewritten -/// in Rust. pub fn mingw(build: &Build, host: &str) { println!("Dist mingw ({})", host); let name = pkgname(build, "rust-mingw"); @@ -366,9 +356,9 @@ pub fn rustc(build: &Build, stage: u32, host: &str) { pub fn debugger_scripts(build: &Build, sysroot: &Path, host: &str) { + let dst = sysroot.join("lib/rustlib/etc"); + t!(fs::create_dir_all(&dst)); let cp_debugger_script = |file: &str| { - let dst = sysroot.join("lib/rustlib/etc"); - t!(fs::create_dir_all(&dst)); install(&build.src.join("src/etc/").join(file), &dst, 0o644); }; if host.contains("windows-msvc") { @@ -376,8 +366,8 @@ pub fn debugger_scripts(build: &Build, install(&build.src.join("src/etc/rust-windbg.cmd"), &sysroot.join("bin"), 0o755); + cp_debugger_script("natvis/liballoc.natvis"); cp_debugger_script("natvis/libcore.natvis"); - cp_debugger_script("natvis/libcollections.natvis"); } else { cp_debugger_script("debugger_pretty_printers_common.py"); @@ -404,7 +394,7 @@ pub fn std(build: &Build, compiler: &Compiler, target: &str) { // The only true set of target libraries came from the build triple, so // let's reduce redundant work by only producing archives from that host. - if compiler.host != build.config.build { + if compiler.host != build.build { println!("\tskipping, not a build host"); return } @@ -415,8 +405,9 @@ pub fn std(build: &Build, compiler: &Compiler, target: &str) { let dst = image.join("lib/rustlib").join(target); t!(fs::create_dir_all(&dst)); - let src = build.sysroot(compiler).join("lib/rustlib"); - cp_r(&src.join(target), &dst); + let mut src = build.sysroot_libdir(compiler, target); + src.pop(); // Remove the trailing /lib folder from the sysroot_libdir + cp_r(&src, &dst); let mut cmd = rust_installer(build); cmd.arg("generate") @@ -450,7 +441,7 @@ pub fn analysis(build: &Build, compiler: &Compiler, target: &str) { assert!(build.config.extended); println!("Dist analysis"); - if compiler.host != build.config.build { + if compiler.host != build.build { println!("\tskipping, not a build host"); return; } @@ -498,12 +489,11 @@ fn copy_src_dirs(build: &Build, src_dirs: &[&str], exclude_dirs: &[&str], dst_di if spath.ends_with("~") || spath.ends_with(".pyc") { return false } - if spath.contains("llvm/test") || spath.contains("llvm\\test") { - if spath.ends_with(".ll") || - spath.ends_with(".td") || - spath.ends_with(".s") { - return false - } + if (spath.contains("llvm/test") || spath.contains("llvm\\test")) && + (spath.ends_with(".ll") || + spath.ends_with(".td") || + spath.ends_with(".s")) { + return false } let full_path = Path::new(dir).join(path); @@ -564,12 +554,12 @@ pub fn rust_src(build: &Build) { "src/libstd", "src/libstd_unicode", "src/libunwind", + "src/rustc/compiler_builtins_shim", "src/rustc/libc_shim", "src/libtest", "src/libterm", - "src/libgetopts", - "src/compiler-rt", "src/jemalloc", + "src/libprofiler_builtins", ]; let std_src_dirs_exclude = [ "src/compiler-rt/test", @@ -595,7 +585,7 @@ pub fn rust_src(build: &Build) { t!(fs::remove_dir_all(&image)); } -const CARGO_VENDOR_VERSION: &'static str = "0.1.4"; +const CARGO_VENDOR_VERSION: &str = "0.1.4"; /// Creates the plain source tarball pub fn plain_source_tarball(build: &Build) { @@ -634,26 +624,26 @@ pub fn plain_source_tarball(build: &Build) { write_file(&plain_dst_src.join("version"), build.rust_version().as_bytes()); // If we're building from git sources, we need to vendor a complete distribution. - if build.src_is_git { + if build.rust_info.is_git() { // Get cargo-vendor installed, if it isn't already. let mut has_cargo_vendor = false; - let mut cmd = Command::new(&build.cargo); + let mut cmd = Command::new(&build.initial_cargo); for line in output(cmd.arg("install").arg("--list")).lines() { has_cargo_vendor |= line.starts_with("cargo-vendor "); } if !has_cargo_vendor { - let mut cmd = Command::new(&build.cargo); + let mut cmd = Command::new(&build.initial_cargo); cmd.arg("install") .arg("--force") .arg("--debug") .arg("--vers").arg(CARGO_VENDOR_VERSION) .arg("cargo-vendor") - .env("RUSTC", &build.rustc); + .env("RUSTC", &build.initial_rustc); build.run(&mut cmd); } // Vendor all Cargo dependencies - let mut cmd = Command::new(&build.cargo); + let mut cmd = Command::new(&build.initial_cargo); cmd.arg("vendor") .current_dir(&plain_dst_src.join("src")); build.run(&mut cmd); @@ -716,7 +706,7 @@ fn write_file(path: &Path, data: &[u8]) { pub fn cargo(build: &Build, stage: u32, target: &str) { println!("Dist cargo stage{} ({})", stage, target); - let compiler = Compiler::new(stage, &build.config.build); + let compiler = Compiler::new(stage, &build.build); let src = build.src.join("src/tools/cargo"); let etc = src.join("src/etc"); @@ -777,7 +767,7 @@ pub fn cargo(build: &Build, stage: u32, target: &str) { pub fn rls(build: &Build, stage: u32, target: &str) { assert!(build.config.extended); println!("Dist RLS stage{} ({})", stage, target); - let compiler = Compiler::new(stage, &build.config.build); + let compiler = Compiler::new(stage, &build.build); let src = build.src.join("src/tools/rls"); let release_num = build.release_num("rls"); @@ -1160,7 +1150,7 @@ fn add_env(build: &Build, cmd: &mut Command, target: &str) { } pub fn hash_and_sign(build: &Build) { - let compiler = Compiler::new(0, &build.config.build); + let compiler = Compiler::new(0, &build.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") diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index baee1ada50..7dbc3e5553 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -27,18 +27,26 @@ use {Build, Compiler, Mode}; use util::{cp_r, symlink_dir}; use build_helper::up_to_date; -/// Invoke `rustbook` as compiled in `stage` for `target` for the doc book -/// `name` into the `out` path. +/// Invoke `rustbook` for `target` for the doc book `name`. /// /// This will not actually generate any documentation if the documentation has /// already been generated. pub fn rustbook(build: &Build, target: &str, name: &str) { + let src = build.src.join("src/doc"); + rustbook_src(build, target, name, &src); +} + +/// Invoke `rustbook` for `target` for the doc book `name` from the `src` path. +/// +/// This will not actually generate any documentation if the documentation has +/// already been generated. +pub fn rustbook_src(build: &Build, target: &str, name: &str, src: &Path) { let out = build.doc_out(target); t!(fs::create_dir_all(&out)); let out = out.join(name); - let compiler = Compiler::new(0, &build.config.build); - let src = build.src.join("src/doc").join(name); + let compiler = Compiler::new(0, &build.build); + let src = src.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) { @@ -87,7 +95,7 @@ pub fn book(build: &Build, target: &str, name: &str) { fn invoke_rustdoc(build: &Build, target: &str, markdown: &str) { let out = build.doc_out(target); - let compiler = Compiler::new(0, &build.config.build); + let compiler = Compiler::new(0, &build.build); let path = build.src.join("src/doc").join(markdown); @@ -142,7 +150,7 @@ pub fn standalone(build: &Build, target: &str) { let out = build.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = Compiler::new(0, &build.config.build); + let compiler = Compiler::new(0, &build.build); let favicon = build.src.join("src/doc/favicon.inc"); let footer = build.src.join("src/doc/footer.inc"); @@ -209,7 +217,7 @@ pub fn std(build: &Build, stage: u32, target: &str) { println!("Documenting stage{} std ({})", stage, 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(stage, &build.build); let compiler = if build.force_use_stage1(&compiler, target) { Compiler::new(1, compiler.host) } else { @@ -268,7 +276,7 @@ pub fn test(build: &Build, stage: u32, target: &str) { println!("Documenting stage{} test ({})", stage, 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(stage, &build.build); let compiler = if build.force_use_stage1(&compiler, target) { Compiler::new(1, compiler.host) } else { @@ -298,7 +306,7 @@ pub fn rustc(build: &Build, stage: u32, target: &str) { println!("Documenting stage{} compiler ({})", stage, 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(stage, &build.build); let compiler = if build.force_use_stage1(&compiler, target) { Compiler::new(1, compiler.host) } else { @@ -343,17 +351,30 @@ 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(0, &build.config.build); + let compiler = Compiler::new(0, &build.build); let mut index = build.tool_cmd(&compiler, "error_index_generator"); index.arg("html"); index.arg(out.join("error-index.html")); // FIXME: shouldn't have to pass this env var - index.env("CFG_BUILD", &build.config.build); + index.env("CFG_BUILD", &build.build); build.run(&mut index); } +pub fn unstable_book_gen(build: &Build, target: &str) { + println!("Generating unstable book md files ({})", target); + let out = build.md_doc_out(target).join("unstable-book"); + t!(fs::create_dir_all(&out)); + t!(fs::remove_dir_all(&out)); + let compiler = Compiler::new(0, &build.build); + let mut cmd = build.tool_cmd(&compiler, "unstable-book-gen"); + cmd.arg(build.src.join("src")); + cmd.arg(out); + + build.run(&mut cmd); +} + fn symlink_dir_force(src: &Path, dst: &Path) -> io::Result<()> { if let Ok(m) = fs::symlink_metadata(dst) { if m.file_type().is_dir() { diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 68b1dd11a4..5804df34e8 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -35,22 +35,12 @@ pub struct Flags { pub host: Vec, pub target: Vec, pub config: Option, - pub src: Option, + pub src: PathBuf, 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 { Build { paths: Vec, @@ -61,7 +51,7 @@ pub enum Subcommand { Test { paths: Vec, test_args: Vec, - no_fail_fast: bool, + fail_fast: bool, }, Bench { paths: Vec, @@ -122,16 +112,15 @@ To learn more about a subcommand, run `./x.py -h`"); // the subcommand. Therefore we must manually identify the subcommand first, so that we can // complete the definition of the options. Then we can use the getopt::Matches object from // there on out. - let mut possible_subcommands = args.iter().collect::>(); - possible_subcommands.retain(|&s| - (s == "build") - || (s == "test") - || (s == "bench") - || (s == "doc") - || (s == "clean") - || (s == "dist") - || (s == "install")); - let subcommand = match possible_subcommands.first() { + let subcommand = args.iter().find(|&s| + (s == "build") + || (s == "test") + || (s == "bench") + || (s == "doc") + || (s == "clean") + || (s == "dist") + || (s == "install")); + let subcommand = match subcommand { Some(s) => s, None => { // No subcommand -- show the general usage and subcommand help @@ -164,7 +153,7 @@ To learn more about a subcommand, run `./x.py -h`"); let mut pass_sanity_check = true; match matches.free.get(0) { Some(check_subcommand) => { - if &check_subcommand != subcommand { + if check_subcommand != subcommand { pass_sanity_check = false; } }, @@ -196,9 +185,14 @@ Arguments: ./x.py build ./x.py build --stage 1 - For a quick build with a usable compile, you can pass: + For a quick build of a usable compiler, you can pass: + + ./x.py build --stage 1 src/libtest - ./x.py build --stage 1 src/libtest"); + This will first build everything once (like --stage 0 without further + arguments would), and then use the compiler built in stage 0 to build + src/libtest and its dependencies. + Once this is done, build/$ARCH/stage1 contains a usable compiler."); } "test" => { subcommand_help.push_str("\n @@ -274,7 +268,7 @@ Arguments: Subcommand::Test { paths: paths, test_args: matches.opt_strs("test-args"), - no_fail_fast: matches.opt_present("no-fail-fast"), + fail_fast: !matches.opt_present("no-fail-fast"), } } "bench" => { @@ -311,12 +305,15 @@ Arguments: let mut stage = matches.opt_str("stage").map(|j| j.parse().unwrap()); - if matches.opt_present("incremental") { - if stage.is_none() { - stage = Some(1); - } + if matches.opt_present("incremental") && stage.is_none() { + stage = Some(1); } + let cwd = t!(env::current_dir()); + let src = matches.opt_str("src").map(PathBuf::from) + .or_else(|| env::var_os("SRC").map(PathBuf::from)) + .unwrap_or(cwd); + Flags { verbose: matches.opt_count("verbose"), stage: stage, @@ -328,7 +325,7 @@ Arguments: host: split(matches.opt_strs("host")), target: split(matches.opt_strs("target")), config: cfg_file, - src: matches.opt_str("src").map(PathBuf::from), + src: src, jobs: matches.opt_str("jobs").map(|j| j.parse().unwrap()), cmd: cmd, incremental: matches.opt_present("incremental"), @@ -347,9 +344,9 @@ impl Subcommand { } } - pub fn no_fail_fast(&self) -> bool { + pub fn fail_fast(&self) -> bool { match *self { - Subcommand::Test { no_fail_fast, .. } => no_fail_fast, + Subcommand::Test { fail_fast, .. } => fail_fast, _ => false, } } diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 21e21628dc..8e2ef527b1 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -146,5 +146,5 @@ fn add_destdir(path: &Path, destdir: &Option) -> PathBuf { _ => {} } } - return ret + ret } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 00cbc589ae..032231582e 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -161,25 +161,35 @@ pub struct Build { flags: Flags, // Derived properties from the above two configurations - cargo: PathBuf, - rustc: PathBuf, src: PathBuf, out: PathBuf, rust_info: channel::GitInfo, cargo_info: channel::GitInfo, rls_info: channel::GitInfo, local_rebuild: bool, + fail_fast: bool, + verbosity: usize, + + // Targets for which to build. + build: String, + hosts: Vec, + targets: Vec, + + // Stage 0 (downloaded) compiler and cargo or their local rust equivalents. + initial_rustc: PathBuf, + initial_cargo: PathBuf, // Probed tools at runtime lldb_version: Option, lldb_python_dir: Option, // Runtime state filled in later on + // target -> (cc, ar) cc: HashMap)>, + // host -> (cc, ar) cxx: HashMap, crates: HashMap, is_sudo: bool, - src_is_git: bool, ci_env: CiEnv, delayed_failures: Cell, } @@ -202,20 +212,16 @@ struct Crate { /// build system, with each mod generating output in a different directory. #[derive(Clone, Copy, PartialEq, Eq)] pub enum Mode { - /// This cargo is going to build the standard library, placing output in the - /// "stageN-std" directory. + /// Build the standard library, placing output in the "stageN-std" directory. Libstd, - /// This cargo is going to build libtest, placing output in the - /// "stageN-test" directory. + /// Build libtest, placing output in the "stageN-test" directory. Libtest, - /// This cargo is going to build librustc and compiler libraries, placing - /// output in the "stageN-rustc" directory. + /// Build librustc and compiler libraries, placing output in the "stageN-rustc" directory. Librustc, - /// This cargo is going to build some tool, placing output in the - /// "stageN-tools" directory. + /// Build some tool, placing output in the "stageN-tools" directory. Tool, } @@ -226,22 +232,9 @@ impl Build { /// By default all build output will be placed in the current directory. pub fn new(flags: Flags, config: Config) -> Build { let cwd = t!(env::current_dir()); - let src = flags.src.clone().or_else(|| { - env::var_os("SRC").map(|x| x.into()) - }).unwrap_or(cwd.clone()); + let src = flags.src.clone(); let out = cwd.join("build"); - let stage0_root = out.join(&config.build).join("stage0/bin"); - let rustc = match config.rustc { - Some(ref s) => PathBuf::from(s), - None => stage0_root.join(exe("rustc", &config.build)), - }; - let cargo = match config.cargo { - Some(ref s) => PathBuf::from(s), - None => stage0_root.join(exe("cargo", &config.build)), - }; - let local_rebuild = config.local_rebuild; - let is_sudo = match env::var_os("SUDO_USER") { Some(sudo_user) => { match env::var_os("USER") { @@ -254,32 +247,64 @@ impl Build { let rust_info = channel::GitInfo::new(&src); let cargo_info = channel::GitInfo::new(&src.join("src/tools/cargo")); let rls_info = channel::GitInfo::new(&src.join("src/tools/rls")); - let src_is_git = src.join(".git").exists(); + + let hosts = if !flags.host.is_empty() { + for host in flags.host.iter() { + if !config.host.contains(host) { + panic!("specified host `{}` is not in configuration", host); + } + } + flags.host.clone() + } else { + config.host.clone() + }; + let targets = if !flags.target.is_empty() { + for target in flags.target.iter() { + if !config.target.contains(target) { + panic!("specified target `{}` is not in configuration", target); + } + } + flags.target.clone() + } else { + config.target.clone() + }; Build { + initial_rustc: config.initial_rustc.clone(), + initial_cargo: config.initial_cargo.clone(), + local_rebuild: config.local_rebuild, + fail_fast: flags.cmd.fail_fast(), + verbosity: cmp::max(flags.verbose, config.verbose), + + build: config.host[0].clone(), + hosts: hosts, + targets: targets, + flags: flags, config: config, - cargo: cargo, - rustc: rustc, src: src, out: out, rust_info: rust_info, cargo_info: cargo_info, rls_info: rls_info, - local_rebuild: local_rebuild, cc: HashMap::new(), cxx: HashMap::new(), crates: HashMap::new(), lldb_version: None, lldb_python_dir: None, is_sudo: is_sudo, - src_is_git: src_is_git, ci_env: CiEnv::current(), delayed_failures: Cell::new(0), } } + fn build_slice(&self) -> &[String] { + unsafe { + std::slice::from_raw_parts(&self.build, 1) + } + } + /// Executes the entire build, as configured by the flags and configuration. pub fn build(&mut self) { unsafe { @@ -296,7 +321,7 @@ impl Build { sanity::check(self); // If local-rust is the same major.minor as the current version, then force a local-rebuild let local_version_verbose = output( - Command::new(&self.rustc).arg("--version").arg("--verbose")); + Command::new(&self.initial_rustc).arg("--version").arg("--verbose")); let local_release = local_version_verbose .lines().filter(|x| x.starts_with("release:")) .next().unwrap().trim_left_matches("release:").trim(); @@ -338,7 +363,7 @@ impl Build { mode: Mode, target: &str, cmd: &str) -> Command { - let mut cargo = Command::new(&self.cargo); + let mut cargo = Command::new(&self.initial_cargo); let out_dir = self.stage_out(compiler, mode); cargo.env("CARGO_TARGET_DIR", out_dir) .arg(cmd) @@ -422,36 +447,13 @@ impl Build { // library up and running, so we can use the normal compiler to compile // build scripts in that situation. if mode == Mode::Libstd { - cargo.env("RUSTC_SNAPSHOT", &self.rustc) + cargo.env("RUSTC_SNAPSHOT", &self.initial_rustc) .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir()); } else { cargo.env("RUSTC_SNAPSHOT", self.compiler_path(compiler)) .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_libdir(compiler)); } - // There are two invariants we must maintain: - // * stable crates cannot depend on unstable crates (general Rust rule), - // * crates that end up in the sysroot must be unstable (rustbuild rule). - // - // In order to do enforce the latter, we pass the env var - // `RUSTBUILD_UNSTABLE` down the line for any crates which will end up - // in the sysroot. We read this in bootstrap/bin/rustc.rs and if it is - // set, then we pass the `rustbuild` feature to rustc when building the - // the crate. - // - // In turn, crates that can be used here should recognise the `rustbuild` - // feature and opt-in to `rustc_private`. - // - // We can't always pass `rustbuild` because crates which are outside of - // the compiler, libs, and tests are stable and we don't want to make - // their deps unstable (since this would break the first invariant - // above). - // - // FIXME: remove this after next stage0 - if mode != Mode::Tool && stage == 0 { - cargo.env("RUSTBUILD_UNSTABLE", "1"); - } - // Ignore incremental modes except for stage0, since we're // not guaranteeing correctness across builds if the compiler // is changing under your feet.` @@ -464,8 +466,7 @@ impl Build { cargo.env("RUSTC_ON_FAIL", on_fail); } - let verbose = cmp::max(self.config.verbose, self.flags.verbose); - cargo.env("RUSTC_VERBOSE", format!("{}", verbose)); + cargo.env("RUSTC_VERBOSE", format!("{}", self.verbosity)); // Specify some various options for build scripts used throughout // the build. @@ -475,9 +476,15 @@ impl Build { cargo.env(format!("CC_{}", target), self.cc(target)) .env(format!("AR_{}", target), self.ar(target).unwrap()) // only msvc is None .env(format!("CFLAGS_{}", target), self.cflags(target).join(" ")); + + if let Ok(cxx) = self.cxx(target) { + cargo.env(format!("CXX_{}", target), cxx); + } } - if self.config.extended && compiler.is_final_stage(self) { + if mode == Mode::Libstd && + self.config.extended && + compiler.is_final_stage(self) { cargo.env("RUSTC_SAVE_ANALYSIS", "api".to_string()); } @@ -499,7 +506,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.is_verbose() { cargo.arg("-v"); } // FIXME: cargo bench does not accept `--release` @@ -515,13 +522,13 @@ impl Build { self.ci_env.force_coloring_in_ci(&mut cargo); - return cargo + cargo } /// Get a path to the compiler specified. fn compiler_path(&self, compiler: &Compiler) -> PathBuf { if compiler.is_snapshot(self) { - self.rustc.clone() + self.initial_rustc.clone() } else { self.sysroot(compiler).join("bin").join(exe("rustc", compiler.host)) } @@ -538,7 +545,7 @@ impl Build { let mut rustdoc = self.compiler_path(compiler); rustdoc.pop(); rustdoc.push(exe("rustdoc", compiler.host)); - return rustdoc + rustdoc } /// Get a `Command` which is ready to run `tool` in `stage` built for @@ -546,7 +553,7 @@ impl Build { 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 + cmd } /// Prepares the `cmd` provided to be able to run the `compiler` provided. @@ -594,7 +601,10 @@ impl Build { if self.config.backtrace { features.push_str(" backtrace"); } - return features + if self.config.profiler { + features.push_str(" profiler"); + } + features } /// Get the space-separated set of activated features for the compiler. @@ -603,7 +613,7 @@ impl Build { if self.config.use_jemalloc { features.push_str(" jemalloc"); } - return features + features } /// Component directory that Cargo will produce output into (e.g. @@ -635,8 +645,14 @@ impl Build { /// 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 { - self.sysroot(compiler).join("lib").join("rustlib") - .join(target).join("lib") + if compiler.stage >= 2 { + if let Some(ref libdir_relative) = self.config.libdir_relative { + return self.sysroot(compiler).join(libdir_relative) + .join("rustlib").join(target).join("lib") + } + } + self.sysroot(compiler).join("lib").join("rustlib") + .join(target).join("lib") } /// Returns the root directory for all output generated in a particular @@ -677,6 +693,11 @@ impl Build { self.out.join(target).join("doc") } + /// Output directory for some generated md crate documentation for a target (temporary) + fn md_doc_out(&self, target: &str) -> PathBuf { + self.out.join(target).join("md-doc") + } + /// Output directory for all crate documentation for a target (temporary) /// /// The artifacts here are then copied into `doc_out` above. @@ -771,7 +792,7 @@ impl Build { /// Returns the libdir of the snapshot compiler. fn rustc_snapshot_libdir(&self) -> PathBuf { - self.rustc.parent().unwrap().parent().unwrap() + self.initial_rustc.parent().unwrap().parent().unwrap() .join(libdir(&self.config.build)) } @@ -803,9 +824,17 @@ impl Build { try_run_suppressed(cmd) } + pub fn is_verbose(&self) -> bool { + self.verbosity > 0 + } + + pub fn is_very_verbose(&self) -> bool { + self.verbosity > 1 + } + /// 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.is_verbose() { println!("{}", msg); } } @@ -813,7 +842,7 @@ impl Build { /// Returns the number of parallel jobs that have been configured for this /// build. fn jobs(&self) -> u32 { - self.flags.jobs.unwrap_or(num_cpus::get() as u32) + self.flags.jobs.unwrap_or_else(|| num_cpus::get() as u32) } /// Returns the path to the C compiler for the target specified. @@ -845,7 +874,7 @@ impl Build { if target == "i686-pc-windows-gnu" { base.push("-fno-omit-frame-pointer".into()); } - return base + base } /// Returns the path to the `ar` archive utility for the target specified. @@ -853,13 +882,13 @@ impl Build { self.cc[target].1.as_ref().map(|p| &**p) } - /// Returns the path to the C++ compiler for the target specified, may panic - /// if no C++ compiler was configured for the target. - fn cxx(&self, target: &str) -> &Path { + /// Returns the path to the C++ compiler for the target specified. + fn cxx(&self, target: &str) -> Result<&Path, String> { match self.cxx.get(target) { - Some(p) => p.path(), - None => panic!("\n\ntarget `{}` is not configured as a host, - only as a target\n\n", target), + Some(p) => Ok(p.path()), + None => Err(format!( + "target `{}` is not configured as a host, only as a target", + target)) } } @@ -877,7 +906,7 @@ impl Build { !target.contains("emscripten") { base.push(format!("-Clinker={}", self.cc(target).display())); } - return base + base } /// Returns the "musl root" for this `target`, if defined @@ -1058,7 +1087,7 @@ impl<'a> Compiler<'a> { /// Returns whether this is a snapshot compiler for `build`'s configuration fn is_snapshot(&self, build: &Build) -> bool { - self.stage == 0 && self.host == build.config.build + self.stage == 0 && self.host == build.build } /// Returns if this compiler should be treated as a final stage one in the diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs index 7b6b01655d..9326bb7129 100644 --- a/src/bootstrap/metadata.rs +++ b/src/bootstrap/metadata.rs @@ -56,7 +56,7 @@ fn build_krate(build: &mut Build, krate: &str) { // of packages we're going to have to know what `-p` arguments to pass it // to know what crates to test. Here we run `cargo metadata` to learn about // the dependency graph and what `-p` arguments there are. - let mut cargo = Command::new(&build.cargo); + let mut cargo = Command::new(&build.initial_cargo); cargo.arg("metadata") .arg("--format-version").arg("1") .arg("--manifest-path").arg(build.src.join(krate).join("Cargo.toml")); diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 47c792a510..d329630269 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -55,7 +55,7 @@ check: check-aux: $(Q)$(BOOTSTRAP) test \ src/tools/cargotest \ - cargo \ + src/tools/cargo \ src/test/pretty \ src/test/run-pass/pretty \ src/test/run-fail/pretty \ diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 6b9a6347d2..20eec97d8e 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -86,14 +86,20 @@ pub fn llvm(build: &Build, target: &str) { None => "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX;Hexagon", }; + let llvm_exp_targets = match build.config.llvm_experimental_targets { + Some(ref s) => s, + None => "", + }; + let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"}; cfg.target(target) - .host(&build.config.build) + .host(&build.build) .out_dir(&out_dir) .profile(profile) .define("LLVM_ENABLE_ASSERTIONS", assertions) .define("LLVM_TARGETS_TO_BUILD", llvm_targets) + .define("LLVM_EXPERIMENTAL_TARGETS_TO_BUILD", llvm_exp_targets) .define("LLVM_INCLUDE_EXAMPLES", "OFF") .define("LLVM_INCLUDE_TESTS", "OFF") .define("LLVM_INCLUDE_DOCS", "OFF") @@ -123,11 +129,11 @@ pub fn llvm(build: &Build, target: &str) { } // http://llvm.org/docs/HowToCrossCompileLLVM.html - if target != build.config.build { + if target != build.build { // FIXME: if the llvm root for the build triple is overridden then we // should use llvm-tblgen from there, also should verify that it // actually exists most of the time in normal installs of LLVM. - let host = build.llvm_out(&build.config.build).join("bin/llvm-tblgen"); + let host = build.llvm_out(&build.build).join("bin/llvm-tblgen"); cfg.define("CMAKE_CROSSCOMPILING", "True") .define("LLVM_TABLEGEN", &host); } @@ -149,7 +155,7 @@ pub fn llvm(build: &Build, target: &str) { } let cc = build.cc(target); - let cxx = build.cxx(target); + let cxx = build.cxx(target).unwrap(); // Handle msvc + ninja + ccache specially (this is what the bots use) if target.contains("msvc") && @@ -237,7 +243,7 @@ pub fn test_helpers(build: &Build, target: &str) { cfg.cargo_metadata(false) .out_dir(&dst) .target(target) - .host(&build.config.build) + .host(&build.build) .opt_level(0) .debug(false) .file(build.src.join("src/rt/rust_test_helpers.c")) diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index df6378a970..a9c1b023dd 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -18,55 +18,70 @@ //! In theory if we get past this phase it's a bug if a build fails, but in //! practice that's likely not true! -use std::collections::HashSet; +use std::collections::HashMap; use std::env; -use std::ffi::{OsStr, OsString}; +use std::ffi::{OsString, OsStr}; use std::fs; use std::process::Command; +use std::path::PathBuf; use build_helper::output; use Build; +struct Finder { + cache: HashMap>, + path: OsString, +} + +impl Finder { + fn new() -> Self { + Self { + cache: HashMap::new(), + path: env::var_os("PATH").unwrap_or_default() + } + } + + fn maybe_have>(&mut self, cmd: S) -> Option { + let cmd: OsString = cmd.as_ref().into(); + let path = self.path.clone(); + self.cache.entry(cmd.clone()).or_insert_with(|| { + for path in env::split_paths(&path) { + let target = path.join(&cmd); + let mut cmd_alt = cmd.clone(); + cmd_alt.push(".exe"); + if target.is_file() || // some/path/git + target.with_extension("exe").exists() || // some/path/git.exe + target.join(&cmd_alt).exists() { // some/path/git/git.exe + return Some(target); + } + } + None + }).clone() + } + + fn must_have>(&mut self, cmd: S) -> PathBuf { + self.maybe_have(&cmd).unwrap_or_else(|| { + panic!("\n\ncouldn't find required command: {:?}\n\n", cmd.as_ref()); + }) + } +} + pub fn check(build: &mut Build) { - let mut checked = HashSet::new(); - let path = env::var_os("PATH").unwrap_or(OsString::new()); + let path = env::var_os("PATH").unwrap_or_default(); // On Windows, quotes are invalid characters for filename paths, and if // one is present as part of the PATH then that can lead to the system // being unable to identify the files properly. See // https://github.com/rust-lang/rust/issues/34959 for more details. - if cfg!(windows) { - if path.to_string_lossy().contains("\"") { - panic!("PATH contains invalid character '\"'"); - } + if cfg!(windows) && path.to_string_lossy().contains("\"") { + panic!("PATH contains invalid character '\"'"); } - let have_cmd = |cmd: &OsStr| { - for path in env::split_paths(&path) { - let target = path.join(cmd); - let mut cmd_alt = cmd.to_os_string(); - cmd_alt.push(".exe"); - if target.is_file() || - target.with_extension("exe").exists() || - target.join(cmd_alt).exists() { - return Some(target); - } - } - return None; - }; - - let mut need_cmd = |cmd: &OsStr| { - if !checked.insert(cmd.to_owned()) { - return - } - if have_cmd(cmd).is_none() { - panic!("\n\ncouldn't find required command: {:?}\n\n", cmd); - } - }; + let mut cmd_finder = Finder::new(); // If we've got a git directory we're gona need git to update // submodules and learn about various other aspects. - if build.src_is_git { - need_cmd("git".as_ref()); + if build.rust_info.is_git() { + cmd_finder.must_have("git"); } // We need cmake, but only if we're actually building LLVM or sanitizers. @@ -74,51 +89,32 @@ pub fn check(build: &mut Build) { .filter_map(|host| build.config.target_config.get(host)) .any(|config| config.llvm_config.is_none()); if building_llvm || build.config.sanitizers { - need_cmd("cmake".as_ref()); + cmd_finder.must_have("cmake"); } // Ninja is currently only used for LLVM itself. - if building_llvm && build.config.ninja { - // 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()); - } + // Some Linux distros rename `ninja` to `ninja-build`. + // CMake can work with either binary name. + if building_llvm && build.config.ninja && cmd_finder.maybe_have("ninja-build").is_none() { + cmd_finder.must_have("ninja"); } - if build.config.python.is_none() { - build.config.python = have_cmd("python2.7".as_ref()); - } - if build.config.python.is_none() { - build.config.python = have_cmd("python2".as_ref()); - } - if build.config.python.is_none() { - need_cmd("python".as_ref()); - build.config.python = Some("python".into()); - } - need_cmd(build.config.python.as_ref().unwrap().as_ref()); - + build.config.python = build.config.python.take().map(|p| cmd_finder.must_have(p)) + .or_else(|| env::var_os("BOOTSTRAP_PYTHON").map(PathBuf::from)) // set by bootstrap.py + .or_else(|| cmd_finder.maybe_have("python2.7")) + .or_else(|| cmd_finder.maybe_have("python2")) + .or_else(|| Some(cmd_finder.must_have("python"))); - if let Some(ref s) = build.config.nodejs { - need_cmd(s.as_ref()); - } else { - // Look for the nodejs command, needed for emscripten testing - if let Some(node) = have_cmd("node".as_ref()) { - build.config.nodejs = Some(node); - } else if let Some(node) = have_cmd("nodejs".as_ref()) { - build.config.nodejs = Some(node); - } - } + build.config.nodejs = build.config.nodejs.take().map(|p| cmd_finder.must_have(p)) + .or_else(|| cmd_finder.maybe_have("node")) + .or_else(|| cmd_finder.maybe_have("nodejs")); - if let Some(ref gdb) = build.config.gdb { - need_cmd(gdb.as_ref()); - } else { - build.config.gdb = have_cmd("gdb".as_ref()); - } + build.config.gdb = build.config.gdb.take().map(|p| cmd_finder.must_have(p)) + .or_else(|| cmd_finder.maybe_have("gdb")); // We're gonna build some custom C code here and there, host triples // also build some C++ shims for LLVM so we need a C++ compiler. - for target in build.config.target.iter() { + for target in &build.config.target { // On emscripten we don't actually need the C compiler to just // build the target artifacts, only for testing. For the sake // of easier bot configuration, just skip detection. @@ -126,33 +122,32 @@ pub fn check(build: &mut Build) { continue; } - need_cmd(build.cc(target).as_ref()); + cmd_finder.must_have(build.cc(target)); if let Some(ar) = build.ar(target) { - need_cmd(ar.as_ref()); + cmd_finder.must_have(ar); } } - for host in build.config.host.iter() { - need_cmd(build.cxx(host).as_ref()); - } - // The msvc hosts don't use jemalloc, turn it off globally to - // avoid packaging the dummy liballoc_jemalloc on that platform. for host in build.config.host.iter() { + cmd_finder.must_have(build.cxx(host).unwrap()); + + // The msvc hosts don't use jemalloc, turn it off globally to + // avoid packaging the dummy liballoc_jemalloc on that platform. if host.contains("msvc") { build.config.use_jemalloc = false; } } // Externally configured LLVM requires FileCheck to exist - let filecheck = build.llvm_filecheck(&build.config.build); + let filecheck = build.llvm_filecheck(&build.build); if !filecheck.starts_with(&build.out) && !filecheck.exists() && build.config.codegen_tests { panic!("FileCheck executable {:?} does not exist", filecheck); } - for target in build.config.target.iter() { + for target in &build.config.target { // Can't compile for iOS unless we're on macOS if target.contains("apple-ios") && - !build.config.build.contains("apple-darwin") { + !build.build.contains("apple-darwin") { panic!("the iOS target is only supported on macOS"); } @@ -199,18 +194,6 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake } } - for host in build.flags.host.iter() { - if !build.config.host.contains(host) { - panic!("specified host `{}` is not in the ./configure list", host); - } - } - for target in build.flags.target.iter() { - if !build.config.target.contains(target) { - panic!("specified target `{}` is not in the ./configure list", - target); - } - } - let run = |cmd: &mut Command| { cmd.output().map(|output| { String::from_utf8_lossy(&output.stdout) @@ -224,6 +207,6 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake } if let Some(ref s) = build.config.ccache { - need_cmd(s.as_ref()); + cmd_finder.must_have(s); } } diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index 3a2dcb02e6..e35031b3c9 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -28,6 +28,7 @@ use std::collections::{BTreeMap, HashSet, HashMap}; use std::mem; +use std::path::PathBuf; use std::process; use check::{self, TestKind}; @@ -104,10 +105,10 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.build("llvm", "src/llvm") .host(true) .dep(move |s| { - if s.target == build.config.build { + if s.target == build.build { Step::noop() } else { - s.target(&build.config.build) + s.target(&build.build) } }) .run(move |s| native::llvm(build, s.target)); @@ -124,7 +125,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { Step::noop() } else { s.name("librustc") - .host(&build.config.build) + .host(&build.build) .stage(s.stage - 1) } }) @@ -148,7 +149,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { } } } - return ret + ret }; // ======================================================================== @@ -215,29 +216,29 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { 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.host(&build.build).stage(1) + } else if s.host == build.build { s.name(dep) } else { - s.host(&build.config.build) + s.host(&build.build) } }) .run(move |s| { if build.force_use_stage1(&s.compiler(), s.target) { link(build, - &s.stage(1).host(&build.config.build).compiler(), + &s.stage(1).host(&build.build).compiler(), &s.compiler(), s.target) - } else if s.host == build.config.build { + } else if s.host == build.build { link(build, &s.compiler(), &s.compiler(), s.target) } else { link(build, - &s.host(&build.config.build).compiler(), + &s.host(&build.build).compiler(), &s.compiler(), s.target) } }); - return rule + rule } // Similar to the `libstd`, `libtest`, and `librustc` rules above, except @@ -269,7 +270,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { for (krate, path, _default) in krates("std") { 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| s.name("rustc").host(&build.build).target(s.host)) .run(move |s| compile::std(build, s.target, &s.compiler())); } for (krate, path, _default) in krates("test") { @@ -280,7 +281,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { for (krate, path, _default) in krates("rustc-main") { rules.build(&krate.build_step, path) .dep(|s| s.name("libtest-link")) - .dep(move |s| s.name("llvm").host(&build.config.build).stage(0)) + .dep(move |s| s.name("llvm").host(&build.build).stage(0)) .dep(|s| s.name("may-run-build-script")) .run(move |s| compile::rustc(build, s.target, &s.compiler())); } @@ -291,8 +292,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.build("may-run-build-script", "path/to/nowhere") .dep(move |s| { s.name("libstd-link") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) }); rules.build("startup-objects", "src/rtstartup") .dep(|s| s.name("create-sysroot").target(s.host)) @@ -332,7 +333,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { "incremental"); } - if build.config.build.contains("msvc") { + if build.build.contains("msvc") { // nothing to do for debuginfo tests } else { rules.test("check-debuginfo-lldb", "src/test/debuginfo-lldb") @@ -352,7 +353,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { "debuginfo-gdb", "debuginfo")); let mut rule = rules.test("check-debuginfo", "src/test/debuginfo"); rule.default(true); - if build.config.build.contains("apple") { + if build.build.contains("apple") { rule.dep(|s| s.name("check-debuginfo-lldb")); } else { rule.dep(|s| s.name("check-debuginfo-gdb")); @@ -463,7 +464,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.test("check-linkchecker", "src/tools/linkchecker") .dep(|s| s.name("tool-linkchecker").stage(0)) .dep(|s| s.name("default:doc")) - .default(true) + .default(build.config.docs) .host(true) .run(move |s| check::linkcheck(build, s.target)); rules.test("check-cargotest", "src/tools/cargotest") @@ -471,10 +472,14 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .dep(|s| s.name("librustc")) .host(true) .run(move |s| check::cargotest(build, s.stage, s.target)); - rules.test("check-cargo", "cargo") + rules.test("check-cargo", "src/tools/cargo") .dep(|s| s.name("tool-cargo")) .host(true) .run(move |s| check::cargo(build, s.stage, s.target)); + rules.test("check-rls", "src/tools/rls") + .dep(|s| s.name("tool-rls")) + .host(true) + .run(move |s| check::rls(build, s.stage, s.target)); rules.test("check-tidy", "src/tools/tidy") .dep(|s| s.name("tool-tidy").stage(0)) .default(true) @@ -548,6 +553,10 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .dep(|s| s.name("maybe-clean-tools")) .dep(|s| s.name("librustc-tool")) .run(move |s| compile::tool(build, s.stage, s.target, "error_index_generator")); + rules.build("tool-unstable-book-gen", "src/tools/unstable-book-gen") + .dep(|s| s.name("maybe-clean-tools")) + .dep(|s| s.name("libstd-tool")) + .run(move |s| compile::tool(build, s.stage, s.target, "unstable-book-gen")); rules.build("tool-tidy", "src/tools/tidy") .dep(|s| s.name("maybe-clean-tools")) .dep(|s| s.name("libstd-tool")) @@ -590,8 +599,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { // Cargo depends on procedural macros, which requires a full host // compiler to be available, so we need to depend on that. s.name("librustc-link") - .target(&build.config.build) - .host(&build.config.build) + .target(&build.build) + .host(&build.build) }) .run(move |s| compile::tool(build, s.stage, s.target, "cargo")); rules.build("tool-rls", "src/tools/rls") @@ -601,8 +610,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .dep(move |s| { // rls, like cargo, uses procedural macros s.name("librustc-link") - .target(&build.config.build) - .host(&build.config.build) + .target(&build.build) + .host(&build.build) }) .run(move |s| compile::tool(build, s.stage, s.target, "rls")); @@ -630,8 +639,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.doc("doc-book", "src/doc/book") .dep(move |s| { s.name("tool-rustbook") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) .stage(0) }) .default(build.config.docs) @@ -639,8 +648,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.doc("doc-nomicon", "src/doc/nomicon") .dep(move |s| { s.name("tool-rustbook") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) .stage(0) }) .default(build.config.docs) @@ -648,8 +657,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.doc("doc-reference", "src/doc/reference") .dep(move |s| { s.name("tool-rustbook") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) .stage(0) }) .default(build.config.docs) @@ -657,27 +666,42 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.doc("doc-unstable-book", "src/doc/unstable-book") .dep(move |s| { s.name("tool-rustbook") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) .stage(0) }) + .dep(move |s| s.name("doc-unstable-book-gen")) .default(build.config.docs) - .run(move |s| doc::rustbook(build, s.target, "unstable-book")); + .run(move |s| doc::rustbook_src(build, + s.target, + "unstable-book", + &build.md_doc_out(s.target))); rules.doc("doc-standalone", "src/doc") .dep(move |s| { s.name("rustc") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) .stage(0) }) .default(build.config.docs) .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).stage(0)) + .dep(move |s| s.name("tool-error-index").target(&build.build).stage(0)) .dep(move |s| s.name("librustc-link")) .default(build.config.docs) .host(true) .run(move |s| doc::error_index(build, s.target)); + rules.doc("doc-unstable-book-gen", "src/tools/unstable-book-gen") + .dep(move |s| { + s.name("tool-unstable-book-gen") + .host(&build.build) + .target(&build.build) + .stage(0) + }) + .dep(move |s| s.name("libstd-link")) + .default(build.config.docs) + .host(true) + .run(move |s| doc::unstable_book_gen(build, s.target)); for (krate, path, default) in krates("std") { rules.doc(&krate.doc_step, path) .dep(|s| s.name("libstd-link")) @@ -705,7 +729,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { // ======================================================================== // Distribution targets rules.dist("dist-rustc", "src/librustc") - .dep(move |s| s.name("rustc").host(&build.config.build)) + .dep(move |s| s.name("rustc").host(&build.build)) .host(true) .only_host_build(true) .default(true) @@ -790,7 +814,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .host(true) .only_build(true) .only_host_build(true) - .dep(move |s| s.name("tool-build-manifest").target(&build.config.build).stage(0)) + .dep(move |s| s.name("tool-build-manifest").target(&build.build).stage(0)) .run(move |_| dist::hash_and_sign(build)); rules.install("install-docs", "src/doc") @@ -839,8 +863,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { /// Helper to depend on a stage0 build-only rust-installer tool. fn tool_rust_installer<'a>(build: &'a Build, step: &Step<'a>) -> Step<'a> { step.name("tool-rust-installer") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) .stage(0) } } @@ -1036,8 +1060,8 @@ impl<'a> Rules<'a> { build: build, sbuild: Step { stage: build.flags.stage.unwrap_or(2), - target: &build.config.build, - host: &build.config.build, + target: &build.build, + host: &build.build, name: "", }, rules: BTreeMap::new(), @@ -1187,25 +1211,26 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? if paths.len() == 0 && rule.default { Some((rule, 0)) } else { - paths.iter().position(|path| path.ends_with(rule.path)) + paths.iter() + .position(|path| path.ends_with(rule.path)) .map(|priority| (rule, priority)) } }).collect(); + if rules.is_empty() && + !paths.get(0).unwrap_or(&PathBuf::new()) + .ends_with("nonexistent/path/to/trigger/cargo/metadata") { + println!("\nNothing to run...\n"); + process::exit(1); + } + rules.sort_by_key(|&(_, priority)| priority); rules.into_iter().flat_map(|(rule, _)| { 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 + self.build.build_slice() } else { - &self.build.config.host - }; - let targets = if self.build.flags.target.len() > 0 { - &self.build.flags.target - } else { - &self.build.config.target + &self.build.hosts }; // Determine the actual targets participating in this rule. // NOTE: We should keep the full projection from build triple to @@ -1214,19 +1239,18 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? // the original non-shadowed hosts array is used below. let arr = if rule.host { // 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`. + // don't run any host-only tests. if self.build.flags.host.len() > 0 { - &self.build.flags.host[..] + &self.build.hosts } else if self.build.flags.target.len() > 0 { &[] } else if rule.only_build { - &self.build.config.host[..1] + self.build.build_slice() } else { - &self.build.config.host[..] + &self.build.hosts } } else { - targets + &self.build.targets }; hosts.iter().flat_map(move |host| { @@ -1304,7 +1328,7 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? for idx in 0..nodes.len() { self.topo_sort(idx, &idx_to_node, &edges, &mut visited, &mut order); } - return order + order } /// Builds the dependency graph rooted at `step`. @@ -1343,7 +1367,7 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? } edges.entry(idx).or_insert(HashSet::new()).extend(deps); - return idx + idx } /// Given a dependency graph with a finished list of `nodes`, fill out more @@ -1404,13 +1428,20 @@ mod tests { fn build(args: &[&str], extra_host: &[&str], extra_target: &[&str]) -> Build { + build_(args, extra_host, extra_target, true) + } + + fn build_(args: &[&str], + extra_host: &[&str], + extra_target: &[&str], + docs: bool) -> 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.docs = docs; config.build = "A".to_string(); config.host = vec![config.build.clone()]; config.host.extend(extra_host.iter().map(|s| s.to_string())); @@ -1465,8 +1496,8 @@ mod tests { let step = super::Step { name: "", stage: 2, - host: &build.config.build, - target: &build.config.build, + host: &build.build, + target: &build.build, }; assert!(plan.contains(&step.name("dist-docs"))); @@ -1488,8 +1519,8 @@ mod tests { let step = super::Step { name: "", stage: 2, - host: &build.config.build, - target: &build.config.build, + host: &build.build, + target: &build.build, }; assert!(plan.contains(&step.name("dist-docs"))); @@ -1516,8 +1547,8 @@ mod tests { let step = super::Step { name: "", stage: 2, - host: &build.config.build, - target: &build.config.build, + host: &build.build, + target: &build.build, }; assert!(!plan.iter().any(|s| s.host == "B")); @@ -1546,8 +1577,8 @@ mod tests { let step = super::Step { name: "", stage: 2, - host: &build.config.build, - target: &build.config.build, + host: &build.build, + target: &build.build, }; assert!(!plan.iter().any(|s| s.host == "B")); @@ -1583,8 +1614,8 @@ mod tests { let step = super::Step { name: "", stage: 2, - host: &build.config.build, - target: &build.config.build, + host: &build.build, + target: &build.build, }; assert!(!plan.iter().any(|s| s.target == "A")); @@ -1610,8 +1641,8 @@ mod tests { let step = super::Step { name: "", stage: 2, - host: &build.config.build, - target: &build.config.build, + host: &build.build, + target: &build.build, }; assert!(!plan.iter().any(|s| s.target == "A")); @@ -1654,8 +1685,8 @@ mod tests { let step = super::Step { name: "", stage: 2, - host: &build.config.build, - target: &build.config.build, + host: &build.build, + target: &build.build, }; // rustc built for all for of (A, B) x (A, B) @@ -1765,4 +1796,22 @@ mod tests { assert!(!plan.iter().any(|s| s.name.contains("tidy"))); assert!(plan.iter().any(|s| s.name.contains("valgrind"))); } + + #[test] + fn test_disable_docs() { + let build = build_(&["test"], &[], &[], false); + let rules = super::build_rules(&build); + let plan = rules.plan(); + println!("rules: {:#?}", plan); + assert!(!plan.iter().any(|s| { + s.name.contains("doc-") || s.name.contains("default:doc") + })); + // none of the dependencies should be a doc rule either + assert!(!plan.iter().any(|s| { + rules.rules[s.name].deps.iter().any(|dep| { + let dep = dep(&rules.sbuild.name(s.name)); + dep.name.contains("doc-") || dep.name.contains("default:doc") + }) + })); + } } diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 61bd85e76c..092fb04637 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -14,7 +14,6 @@ //! not a lot of interesting happenings here unfortunately. use std::env; -use std::ffi::OsString; use std::fs; use std::io::{self, Write}; use std::path::{Path, PathBuf}; @@ -32,16 +31,9 @@ pub fn staticlib(name: &str, target: &str) -> String { } } -/// Copies a file from `src` to `dst`, attempting to use hard links and then -/// falling back to an actually filesystem copy if necessary. +/// Copies a file from `src` to `dst` pub fn copy(src: &Path, dst: &Path) { - // A call to `hard_link` will fail if `dst` exists, so remove it if it - // already exists so we can try to help `hard_link` succeed. let _ = fs::remove_file(&dst); - - // Attempt to "easy copy" by creating a hard link (symlinks don't work on - // windows), but if that fails just fall back to a slow `copy` operation. - // let res = fs::hard_link(src, dst); let res = fs::copy(src, dst); if let Err(e) = res { panic!("failed to copy `{}` to `{}`: {}", src.display(), @@ -149,8 +141,7 @@ pub fn dylib_path_var() -> &'static str { /// Parses the `dylib_path_var()` environment variable, returning a list of /// paths that are members of this lookup path. pub fn dylib_path() -> Vec { - env::split_paths(&env::var_os(dylib_path_var()).unwrap_or(OsString::new())) - .collect() + env::split_paths(&env::var_os(dylib_path_var()).unwrap_or_default()).collect() } /// `push` all components to `buf`. On windows, append `.exe` to the last component. @@ -422,4 +413,4 @@ impl CiEnv { cmd.env("TERM", "xterm").args(&["--color", "always"]); } } -} \ No newline at end of file +} diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index ea6a822e36..7011261ab6 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -239,7 +239,10 @@ pub fn sanitizer_lib_boilerplate(sanitizer_name: &str) -> Result return Err(()), }; - native_lib_boilerplate("compiler-rt", sanitizer_name, &link_name, search_path) + native_lib_boilerplate("libcompiler_builtins/compiler-rt", + sanitizer_name, + &link_name, + search_path) } fn dir_up_to_date(src: &Path, threshold: &FileTime) -> bool { diff --git a/src/ci/docker/arm-android/Dockerfile b/src/ci/docker/arm-android/Dockerfile index 2a928c5ec7..6cdaf6acfe 100644 --- a/src/ci/docker/arm-android/Dockerfile +++ b/src/ci/docker/arm-android/Dockerfile @@ -1,31 +1,15 @@ FROM ubuntu:16.04 -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - ca-certificates \ - cmake \ - curl \ - file \ - g++ \ - git \ - libssl-dev \ - make \ - pkg-config \ - python2.7 \ - sudo \ - unzip \ - xz-utils - -# dumb-init +COPY scripts/android-base-apt-get.sh /scripts/ +RUN sh /scripts/android-base-apt-get.sh + COPY scripts/dumb-init.sh /scripts/ RUN sh /scripts/dumb-init.sh -# ndk COPY scripts/android-ndk.sh /scripts/ RUN . /scripts/android-ndk.sh && \ download_and_make_toolchain android-ndk-r13b-linux-x86_64.zip arm 9 -# sdk RUN dpkg --add-architecture i386 && \ apt-get update && \ apt-get install -y --no-install-recommends \ @@ -39,7 +23,6 @@ COPY scripts/android-sdk.sh /scripts/ RUN . /scripts/android-sdk.sh && \ download_and_create_avd tools_r25.2.5-linux.zip armeabi-v7a 18 -# env ENV PATH=$PATH:/android/sdk/tools ENV PATH=$PATH:/android/sdk/platform-tools @@ -51,10 +34,8 @@ ENV RUST_CONFIGURE_ARGS \ ENV SCRIPT python2.7 ../x.py test --target $TARGETS -# sccache COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -# init COPY scripts/android-start-emulator.sh /scripts/ ENTRYPOINT ["/usr/bin/dumb-init", "--", "/scripts/android-start-emulator.sh"] diff --git a/src/ci/docker/armhf-gnu/Dockerfile b/src/ci/docker/armhf-gnu/Dockerfile index 03e0b78ba8..d289a93c35 100644 --- a/src/ci/docker/armhf-gnu/Dockerfile +++ b/src/ci/docker/armhf-gnu/Dockerfile @@ -73,13 +73,12 @@ RUN arm-linux-gnueabihf-gcc addentropy.c -o rootfs/addentropy -static # TODO: What is this?! RUN curl -O http://ftp.nl.debian.org/debian/dists/jessie/main/installer-armhf/current/images/device-tree/vexpress-v2p-ca15-tc1.dtb -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.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 RUST_CONFIGURE_ARGS \ diff --git a/src/ci/docker/asmjs/Dockerfile b/src/ci/docker/asmjs/Dockerfile new file mode 100644 index 0000000000..1c39e8523d --- /dev/null +++ b/src/ci/docker/asmjs/Dockerfile @@ -0,0 +1,39 @@ +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 + +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/emscripten.sh /scripts/ +RUN bash /scripts/emscripten.sh + +ENV PATH=$PATH:/emsdk-portable +ENV PATH=$PATH:/emsdk-portable/clang/e1.37.13_64bit/ +ENV PATH=$PATH:/emsdk-portable/emscripten/1.37.13/ +ENV PATH=$PATH:/emsdk-portable/node/4.1.1_64bit/bin/ +ENV EMSCRIPTEN=/emsdk-portable/emscripten/1.37.13/ +ENV BINARYEN_ROOT=/emsdk-portable/clang/e1.37.13_64bit/binaryen/ +ENV EM_CONFIG=/emsdk-portable/.emscripten + +ENV TARGETS=asmjs-unknown-emscripten + +ENV RUST_CONFIGURE_ARGS --target=$TARGETS + +ENV SCRIPT python2.7 ../x.py test --target $TARGETS + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/cross/Dockerfile b/src/ci/docker/cross/Dockerfile index b4399a8d53..70dfbb53da 100644 --- a/src/ci/docker/cross/Dockerfile +++ b/src/ci/docker/cross/Dockerfile @@ -21,7 +21,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libssl-dev \ pkg-config -# dumb-init COPY scripts/dumb-init.sh /scripts/ RUN sh /scripts/dumb-init.sh @@ -68,5 +67,4 @@ ENV SCRIPT python2.7 ../x.py dist --target $TARGETS COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -# init ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/disabled/dist-aarch64-android/Dockerfile b/src/ci/docker/disabled/dist-aarch64-android/Dockerfile index 918d2911ae..1c9e036f09 100644 --- a/src/ci/docker/disabled/dist-aarch64-android/Dockerfile +++ b/src/ci/docker/disabled/dist-aarch64-android/Dockerfile @@ -1,31 +1,15 @@ FROM ubuntu:16.04 -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - ca-certificates \ - cmake \ - curl \ - file \ - g++ \ - git \ - libssl-dev \ - make \ - pkg-config \ - python2.7 \ - sudo \ - unzip \ - xz-utils - -# dumb-init +COPY scripts/android-base-apt-get.sh /scripts/ +RUN sh /scripts/android-base-apt-get.sh + COPY scripts/dumb-init.sh /scripts/ RUN sh /scripts/dumb-init.sh -# ndk COPY scripts/android-ndk.sh /scripts/ RUN . /scripts/android-ndk.sh && \ download_and_make_toolchain android-ndk-r13b-linux-x86_64.zip arm64 21 -# env ENV PATH=$PATH:/android/ndk/arm64-21/bin ENV DEP_Z_ROOT=/android/ndk/arm64-21/sysroot/usr/ @@ -42,9 +26,7 @@ ENV RUST_CONFIGURE_ARGS \ ENV SCRIPT python2.7 ../x.py dist --target $HOSTS --host $HOSTS -# sccache COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -# init ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/disabled/dist-armv7-android/Dockerfile b/src/ci/docker/disabled/dist-armv7-android/Dockerfile index aed82e6c13..326e00548b 100644 --- a/src/ci/docker/disabled/dist-armv7-android/Dockerfile +++ b/src/ci/docker/disabled/dist-armv7-android/Dockerfile @@ -1,26 +1,11 @@ FROM ubuntu:16.04 -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - ca-certificates \ - cmake \ - curl \ - file \ - g++ \ - git \ - libssl-dev \ - make \ - pkg-config \ - python2.7 \ - sudo \ - unzip \ - xz-utils +COPY scripts/android-base-apt-get.sh /scripts/ +RUN sh /scripts/android-base-apt-get.sh -# dumb-init COPY scripts/dumb-init.sh /scripts/ RUN sh /scripts/dumb-init.sh -# ndk COPY scripts/android-ndk.sh /scripts/ RUN . /scripts/android-ndk.sh && \ download_ndk android-ndk-r13b-linux-x86_64.zip && \ @@ -31,7 +16,6 @@ RUN . /scripts/android-ndk.sh && \ RUN chmod 777 /android/ndk && \ ln -s /android/ndk/arm-21 /android/ndk/arm -# env ENV PATH=$PATH:/android/ndk/arm-9/bin ENV DEP_Z_ROOT=/android/ndk/arm-9/sysroot/usr/ @@ -60,9 +44,7 @@ ENV SCRIPT \ ln -s /android/ndk/arm-9 /android/ndk/arm && \ python2.7 ../x.py dist --host $HOSTS --target $HOSTS) -# sccache COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -# init ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/disabled/dist-i686-android/Dockerfile b/src/ci/docker/disabled/dist-i686-android/Dockerfile index f012e869e7..d01648e2b9 100644 --- a/src/ci/docker/disabled/dist-i686-android/Dockerfile +++ b/src/ci/docker/disabled/dist-i686-android/Dockerfile @@ -1,26 +1,11 @@ FROM ubuntu:16.04 -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - ca-certificates \ - cmake \ - curl \ - file \ - g++ \ - git \ - libssl-dev \ - make \ - pkg-config \ - python2.7 \ - sudo \ - unzip \ - xz-utils +COPY scripts/android-base-apt-get.sh /scripts/ +RUN sh /scripts/android-base-apt-get.sh -# dumb-init COPY scripts/dumb-init.sh /scripts/ RUN sh /scripts/dumb-init.sh -# ndk COPY scripts/android-ndk.sh /scripts/ RUN . /scripts/android-ndk.sh && \ download_ndk android-ndk-r13b-linux-x86_64.zip && \ @@ -31,7 +16,6 @@ RUN . /scripts/android-ndk.sh && \ RUN chmod 777 /android/ndk && \ ln -s /android/ndk/x86-21 /android/ndk/x86 -# env ENV PATH=$PATH:/android/ndk/x86-9/bin ENV DEP_Z_ROOT=/android/ndk/x86-9/sysroot/usr/ @@ -60,9 +44,7 @@ ENV SCRIPT \ ln -s /android/ndk/x86-9 /android/ndk/x86 && \ python2.7 ../x.py dist --host $HOSTS --target $HOSTS) -# sccache COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -# init ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/disabled/dist-x86_64-android/Dockerfile b/src/ci/docker/disabled/dist-x86_64-android/Dockerfile index 0c58645284..2622b4b3fa 100644 --- a/src/ci/docker/disabled/dist-x86_64-android/Dockerfile +++ b/src/ci/docker/disabled/dist-x86_64-android/Dockerfile @@ -1,31 +1,15 @@ FROM ubuntu:16.04 -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - ca-certificates \ - cmake \ - curl \ - file \ - g++ \ - git \ - libssl-dev \ - make \ - pkg-config \ - python2.7 \ - sudo \ - unzip \ - xz-utils - -# dumb-init +COPY scripts/android-base-apt-get.sh /scripts/ +RUN sh /scripts/android-base-apt-get.sh + COPY scripts/dumb-init.sh /scripts/ RUN sh /scripts/dumb-init.sh -# ndk COPY scripts/android-ndk.sh /scripts/ RUN . /scripts/android-ndk.sh && \ download_and_make_toolchain android-ndk-r13b-linux-x86_64.zip x86_64 21 -# env ENV PATH=$PATH:/android/ndk/x86_64-21/bin ENV DEP_Z_ROOT=/android/ndk/x86_64-21/sysroot/usr/ @@ -42,9 +26,7 @@ ENV RUST_CONFIGURE_ARGS \ ENV SCRIPT python2.7 ../x.py dist --target $HOSTS --host $HOSTS -# sccache COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -# init ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/disabled/wasm32-exp/Dockerfile b/src/ci/docker/disabled/wasm32-exp/Dockerfile new file mode 100644 index 0000000000..4e33788316 --- /dev/null +++ b/src/ci/docker/disabled/wasm32-exp/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 \ + python \ + git \ + cmake \ + sudo \ + gdb \ + xz-utils \ + jq \ + bzip2 + +# dumb-init +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +# emscripten +COPY scripts/emscripten-wasm.sh /scripts/ +COPY disabled/wasm32-exp/node.sh /usr/local/bin/node +RUN bash /scripts/emscripten-wasm.sh + +# cache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +# env +ENV PATH=/wasm-install/emscripten:/wasm-install/bin:$PATH +ENV EM_CONFIG=/root/.emscripten + +ENV TARGETS=wasm32-experimental-emscripten + +ENV RUST_CONFIGURE_ARGS --target=$TARGETS --experimental-targets=WebAssembly + +ENV SCRIPT python2.7 ../x.py test --target $TARGETS + +# init +ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/disabled/wasm32-exp/node.sh b/src/ci/docker/disabled/wasm32-exp/node.sh new file mode 100755 index 0000000000..dfa7f221ff --- /dev/null +++ b/src/ci/docker/disabled/wasm32-exp/node.sh @@ -0,0 +1,18 @@ +#!/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. + +path="$(dirname $1)" +file="$(basename $1)" + +shift + +cd "$path" +exec /node-v8.0.0-linux-x64/bin/node "$file" "$@" diff --git a/src/ci/docker/disabled/wasm32/Dockerfile b/src/ci/docker/disabled/wasm32/Dockerfile new file mode 100644 index 0000000000..60b15d7afb --- /dev/null +++ b/src/ci/docker/disabled/wasm32/Dockerfile @@ -0,0 +1,40 @@ +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 + +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +# emscripten +COPY scripts/emscripten.sh /scripts/ +RUN bash /scripts/emscripten.sh +COPY disabled/wasm32/node.sh /usr/local/bin/node + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +ENV PATH=$PATH:/emsdk-portable +ENV PATH=$PATH:/emsdk-portable/clang/e1.37.13_64bit/ +ENV PATH=$PATH:/emsdk-portable/emscripten/1.37.13/ +ENV EMSCRIPTEN=/emsdk-portable/emscripten/1.37.13/ +ENV BINARYEN_ROOT=/emsdk-portable/clang/e1.37.13_64bit/binaryen/ +ENV EM_CONFIG=/emsdk-portable/.emscripten + +ENV TARGETS=wasm32-unknown-emscripten + +ENV RUST_CONFIGURE_ARGS --target=$TARGETS + +ENV SCRIPT python2.7 ../x.py test --target $TARGETS + +ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/disabled/wasm32/node.sh b/src/ci/docker/disabled/wasm32/node.sh new file mode 100755 index 0000000000..dfa7f221ff --- /dev/null +++ b/src/ci/docker/disabled/wasm32/node.sh @@ -0,0 +1,18 @@ +#!/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. + +path="$(dirname $1)" +file="$(basename $1)" + +shift + +cd "$path" +exec /node-v8.0.0-linux-x64/bin/node "$file" "$@" diff --git a/src/ci/docker/dist-aarch64-linux/Dockerfile b/src/ci/docker/dist-aarch64-linux/Dockerfile index 0134a54079..cc3b6b8c69 100644 --- a/src/ci/docker/dist-aarch64-linux/Dockerfile +++ b/src/ci/docker/dist-aarch64-linux/Dockerfile @@ -1,58 +1,23 @@ 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 \ - libssl-dev \ - pkg-config +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.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", "--"] -# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# Ubuntu 16.04 (this container) 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 +COPY scripts/make3.sh /scripts/ +RUN sh /scripts/make3.sh -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 +COPY scripts/crosstool-ng.sh /scripts/ +RUN sh /scripts/crosstool-ng.sh -RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild -RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +COPY scripts/rustbuild-setup.sh /scripts/ +RUN sh /scripts/rustbuild-setup.sh USER rustbuild WORKDIR /tmp @@ -61,9 +26,8 @@ RUN ./build-toolchains.sh USER root -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV PATH=$PATH:/x-tools/aarch64-unknown-linux-gnueabi/bin diff --git a/src/ci/docker/dist-android/Dockerfile b/src/ci/docker/dist-android/Dockerfile index 31389dd148..f3beddfae0 100644 --- a/src/ci/docker/dist-android/Dockerfile +++ b/src/ci/docker/dist-android/Dockerfile @@ -1,22 +1,8 @@ FROM ubuntu:16.04 -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - ca-certificates \ - cmake \ - curl \ - file \ - g++ \ - git \ - libssl-dev \ - make \ - pkg-config \ - python2.7 \ - sudo \ - unzip \ - xz-utils - -# dumb-init +COPY scripts/android-base-apt-get.sh /scripts/ +RUN sh /scripts/android-base-apt-get.sh + COPY scripts/dumb-init.sh /scripts/ RUN sh /scripts/dumb-init.sh @@ -48,9 +34,7 @@ ENV RUST_CONFIGURE_ARGS \ ENV SCRIPT python2.7 ../x.py dist --target $TARGETS -# cache COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -# init ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/dist-arm-linux/Dockerfile b/src/ci/docker/dist-arm-linux/Dockerfile index 862818a7c9..590d6eb98b 100644 --- a/src/ci/docker/dist-arm-linux/Dockerfile +++ b/src/ci/docker/dist-arm-linux/Dockerfile @@ -1,58 +1,23 @@ 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 \ - libssl-dev \ - pkg-config +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.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", "--"] -# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# Ubuntu 16.04 (this container) 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 +COPY scripts/make3.sh /scripts/ +RUN sh /scripts/make3.sh -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 +COPY scripts/crosstool-ng.sh /scripts/ +RUN sh /scripts/crosstool-ng.sh -RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild -RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +COPY scripts/rustbuild-setup.sh /scripts/ +RUN sh /scripts/rustbuild-setup.sh USER rustbuild WORKDIR /tmp @@ -61,9 +26,8 @@ RUN ./build-toolchains.sh USER root -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV PATH=$PATH:/x-tools/arm-unknown-linux-gnueabi/bin diff --git a/src/ci/docker/dist-armhf-linux/Dockerfile b/src/ci/docker/dist-armhf-linux/Dockerfile index 7f1f91f844..b3dedc4b7f 100644 --- a/src/ci/docker/dist-armhf-linux/Dockerfile +++ b/src/ci/docker/dist-armhf-linux/Dockerfile @@ -1,58 +1,23 @@ 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 \ - libssl-dev \ - pkg-config +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.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", "--"] -# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# Ubuntu 16.04 (this container) 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 +COPY scripts/make3.sh /scripts/ +RUN sh /scripts/make3.sh -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 +COPY scripts/crosstool-ng.sh /scripts/ +RUN sh /scripts/crosstool-ng.sh -RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild -RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +COPY scripts/rustbuild-setup.sh /scripts/ +RUN sh /scripts/rustbuild-setup.sh USER rustbuild WORKDIR /tmp @@ -61,9 +26,8 @@ RUN ./build-toolchains.sh USER root -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV PATH=$PATH:/x-tools/arm-unknown-linux-gnueabihf/bin diff --git a/src/ci/docker/dist-armv7-linux/Dockerfile b/src/ci/docker/dist-armv7-linux/Dockerfile index 030fd24ebc..82536b68bb 100644 --- a/src/ci/docker/dist-armv7-linux/Dockerfile +++ b/src/ci/docker/dist-armv7-linux/Dockerfile @@ -1,58 +1,23 @@ 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 \ - libssl-dev \ - pkg-config +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.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", "--"] -# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# Ubuntu 16.04 (this container) 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 +COPY scripts/make3.sh /scripts/ +RUN sh /scripts/make3.sh -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 +COPY scripts/crosstool-ng.sh /scripts/ +RUN sh /scripts/crosstool-ng.sh -RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild -RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +COPY scripts/rustbuild-setup.sh /scripts/ +RUN sh /scripts/rustbuild-setup.sh USER rustbuild WORKDIR /tmp @@ -61,9 +26,8 @@ RUN ./build-toolchains.sh USER root -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV PATH=$PATH:/x-tools/armv7-unknown-linux-gnueabihf/bin diff --git a/src/ci/docker/dist-fuchsia/Dockerfile b/src/ci/docker/dist-fuchsia/Dockerfile index d1d9767d35..24ad12a490 100644 --- a/src/ci/docker/dist-fuchsia/Dockerfile +++ b/src/ci/docker/dist-fuchsia/Dockerfile @@ -24,14 +24,13 @@ WORKDIR /tmp COPY dist-fuchsia/shared.sh dist-fuchsia/build-toolchain.sh dist-fuchsia/compiler-rt-dso-handle.patch /tmp/ RUN /tmp/build-toolchain.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 +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + ENTRYPOINT ["/usr/bin/dumb-init", "--"] -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV \ AR_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-ar \ diff --git a/src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile b/src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile index 805d238de1..036dce2a73 100644 --- a/src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile +++ b/src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile @@ -20,14 +20,13 @@ WORKDIR /build/ COPY dist-i586-gnu-i686-musl/musl-libunwind-patch.patch dist-i586-gnu-i686-musl/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 +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + ENTRYPOINT ["/usr/bin/dumb-init", "--"] -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS \ --target=i686-unknown-linux-musl,i586-unknown-linux-gnu \ diff --git a/src/ci/docker/dist-i686-freebsd/Dockerfile b/src/ci/docker/dist-i686-freebsd/Dockerfile index 9c4d43bfa9..c40881332a 100644 --- a/src/ci/docker/dist-i686-freebsd/Dockerfile +++ b/src/ci/docker/dist-i686-freebsd/Dockerfile @@ -19,14 +19,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ COPY dist-i686-freebsd/build-toolchain.sh /tmp/ 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 +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + ENTRYPOINT ["/usr/bin/dumb-init", "--"] -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV \ AR_i686_unknown_freebsd=i686-unknown-freebsd10-ar \ diff --git a/src/ci/docker/dist-i686-linux/Dockerfile b/src/ci/docker/dist-i686-linux/Dockerfile index a3c08e93ed..beb53783ba 100644 --- a/src/ci/docker/dist-i686-linux/Dockerfile +++ b/src/ci/docker/dist-i686-linux/Dockerfile @@ -81,16 +81,16 @@ RUN curl -Lo /rustroot/dumb-init \ chmod +x /rustroot/dumb-init ENTRYPOINT ["/rustroot/dumb-init", "--"] -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV HOSTS=i686-unknown-linux-gnu ENV RUST_CONFIGURE_ARGS \ --host=$HOSTS \ --enable-extended \ - --enable-sanitizers + --enable-sanitizers \ + --enable-profiler ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS # This is the only builder which will create source tarballs diff --git a/src/ci/docker/dist-mips-linux/Dockerfile b/src/ci/docker/dist-mips-linux/Dockerfile index c23240f0c7..81997e0508 100644 --- a/src/ci/docker/dist-mips-linux/Dockerfile +++ b/src/ci/docker/dist-mips-linux/Dockerfile @@ -16,13 +16,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libssl-dev \ pkg-config -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache -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 +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV HOSTS=mips-unknown-linux-gnu diff --git a/src/ci/docker/dist-mips64-linux/Dockerfile b/src/ci/docker/dist-mips64-linux/Dockerfile index 415dca99d9..646cb4d256 100644 --- a/src/ci/docker/dist-mips64-linux/Dockerfile +++ b/src/ci/docker/dist-mips64-linux/Dockerfile @@ -16,13 +16,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libssl-dev \ pkg-config -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.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 HOSTS=mips64-unknown-linux-gnuabi64 diff --git a/src/ci/docker/dist-mips64el-linux/Dockerfile b/src/ci/docker/dist-mips64el-linux/Dockerfile index 2aba5f615b..1abb04fd8b 100644 --- a/src/ci/docker/dist-mips64el-linux/Dockerfile +++ b/src/ci/docker/dist-mips64el-linux/Dockerfile @@ -16,13 +16,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libssl-dev \ pkg-config -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache -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 +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV HOSTS=mips64el-unknown-linux-gnuabi64 diff --git a/src/ci/docker/dist-mipsel-linux/Dockerfile b/src/ci/docker/dist-mipsel-linux/Dockerfile index d15e301086..a78e39e7d7 100644 --- a/src/ci/docker/dist-mipsel-linux/Dockerfile +++ b/src/ci/docker/dist-mipsel-linux/Dockerfile @@ -16,13 +16,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libssl-dev \ pkg-config -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.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 HOSTS=mipsel-unknown-linux-gnu diff --git a/src/ci/docker/dist-powerpc-linux/Dockerfile b/src/ci/docker/dist-powerpc-linux/Dockerfile index 0074665f34..ed9f883cc8 100644 --- a/src/ci/docker/dist-powerpc-linux/Dockerfile +++ b/src/ci/docker/dist-powerpc-linux/Dockerfile @@ -1,58 +1,23 @@ 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 \ - libssl-dev \ - pkg-config +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.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", "--"] -# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# Ubuntu 16.04 (this container) 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 +COPY scripts/make3.sh /scripts/ +RUN sh /scripts/make3.sh -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 +COPY scripts/crosstool-ng.sh /scripts/ +RUN sh /scripts/crosstool-ng.sh -RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild -RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +COPY scripts/rustbuild-setup.sh /scripts/ +RUN sh /scripts/rustbuild-setup.sh USER rustbuild WORKDIR /tmp @@ -62,9 +27,8 @@ RUN ./build-powerpc-toolchain.sh USER root -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV PATH=$PATH:/x-tools/powerpc-unknown-linux-gnu/bin diff --git a/src/ci/docker/dist-powerpc64-linux/Dockerfile b/src/ci/docker/dist-powerpc64-linux/Dockerfile index bd38ee0c11..523211498f 100644 --- a/src/ci/docker/dist-powerpc64-linux/Dockerfile +++ b/src/ci/docker/dist-powerpc64-linux/Dockerfile @@ -1,58 +1,23 @@ 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 \ - libssl-dev \ - pkg-config +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.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", "--"] -# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# Ubuntu 16.04 (this container) 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 +COPY scripts/make3.sh /scripts/ +RUN sh /scripts/make3.sh -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 +COPY scripts/crosstool-ng.sh /scripts/ +RUN sh /scripts/crosstool-ng.sh -RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild -RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +COPY scripts/rustbuild-setup.sh /scripts/ +RUN sh /scripts/rustbuild-setup.sh USER rustbuild WORKDIR /tmp @@ -62,9 +27,8 @@ RUN ./build-powerpc64-toolchain.sh USER root -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV PATH=$PATH:/x-tools/powerpc64-unknown-linux-gnu/bin diff --git a/src/ci/docker/dist-powerpc64le-linux/Dockerfile b/src/ci/docker/dist-powerpc64le-linux/Dockerfile index cbded156b4..06b262c515 100644 --- a/src/ci/docker/dist-powerpc64le-linux/Dockerfile +++ b/src/ci/docker/dist-powerpc64le-linux/Dockerfile @@ -1,58 +1,23 @@ 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 \ - libssl-dev \ - pkg-config +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.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", "--"] -# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# Ubuntu 16.04 (this container) 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 +COPY scripts/make3.sh /scripts/ +RUN sh /scripts/make3.sh -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 +COPY scripts/crosstool-ng.sh /scripts/ +RUN sh /scripts/crosstool-ng.sh -RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild -RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +COPY scripts/rustbuild-setup.sh /scripts/ +RUN sh /scripts/rustbuild-setup.sh USER rustbuild WORKDIR /tmp @@ -62,9 +27,8 @@ RUN apt-get install -y --no-install-recommends rpm2cpio cpio COPY dist-powerpc64le-linux/shared.sh dist-powerpc64le-linux/build-powerpc64le-toolchain.sh /tmp/ RUN ./build-powerpc64le-toolchain.sh -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV \ AR_powerpc64le_unknown_linux_gnu=powerpc64le-linux-gnu-ar \ diff --git a/src/ci/docker/dist-s390x-linux/Dockerfile b/src/ci/docker/dist-s390x-linux/Dockerfile index 5c00287107..84769af12b 100644 --- a/src/ci/docker/dist-s390x-linux/Dockerfile +++ b/src/ci/docker/dist-s390x-linux/Dockerfile @@ -1,58 +1,23 @@ 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 \ - libssl-dev \ - pkg-config +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.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", "--"] -# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# Ubuntu 16.04 (this container) 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 +COPY scripts/make3.sh /scripts/ +RUN sh /scripts/make3.sh -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 +COPY scripts/crosstool-ng.sh /scripts/ +RUN sh /scripts/crosstool-ng.sh -RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild -RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +COPY scripts/rustbuild-setup.sh /scripts/ +RUN sh /scripts/rustbuild-setup.sh USER rustbuild WORKDIR /tmp @@ -62,9 +27,8 @@ RUN ./build-s390x-toolchain.sh USER root -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV PATH=$PATH:/x-tools/s390x-ibm-linux-gnu/bin diff --git a/src/ci/docker/dist-x86_64-freebsd/Dockerfile b/src/ci/docker/dist-x86_64-freebsd/Dockerfile index a6c4eee5e8..b62b46701a 100644 --- a/src/ci/docker/dist-x86_64-freebsd/Dockerfile +++ b/src/ci/docker/dist-x86_64-freebsd/Dockerfile @@ -19,14 +19,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ COPY dist-x86_64-freebsd/build-toolchain.sh /tmp/ RUN /tmp/build-toolchain.sh x86_64 -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 +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + ENTRYPOINT ["/usr/bin/dumb-init", "--"] -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV \ AR_x86_64_unknown_freebsd=x86_64-unknown-freebsd10-ar \ diff --git a/src/ci/docker/dist-x86_64-linux/Dockerfile b/src/ci/docker/dist-x86_64-linux/Dockerfile index e2e42836dc..d0ab47ad3d 100644 --- a/src/ci/docker/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/dist-x86_64-linux/Dockerfile @@ -81,16 +81,16 @@ RUN curl -Lo /rustroot/dumb-init \ chmod +x /rustroot/dumb-init ENTRYPOINT ["/rustroot/dumb-init", "--"] -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV HOSTS=x86_64-unknown-linux-gnu ENV RUST_CONFIGURE_ARGS \ --host=$HOSTS \ --enable-extended \ - --enable-sanitizers + --enable-sanitizers \ + --enable-profiler ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS # This is the only builder which will create source tarballs diff --git a/src/ci/docker/dist-x86_64-musl/Dockerfile b/src/ci/docker/dist-x86_64-musl/Dockerfile index 2eea5ab146..eebc283e96 100644 --- a/src/ci/docker/dist-x86_64-musl/Dockerfile +++ b/src/ci/docker/dist-x86_64-musl/Dockerfile @@ -20,14 +20,13 @@ WORKDIR /build/ COPY dist-x86_64-musl/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 +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + ENTRYPOINT ["/usr/bin/dumb-init", "--"] -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS \ --target=x86_64-unknown-linux-musl \ diff --git a/src/ci/docker/dist-x86_64-netbsd/Dockerfile b/src/ci/docker/dist-x86_64-netbsd/Dockerfile index f76e6271f4..0c14050026 100644 --- a/src/ci/docker/dist-x86_64-netbsd/Dockerfile +++ b/src/ci/docker/dist-x86_64-netbsd/Dockerfile @@ -1,58 +1,23 @@ 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 \ - libssl-dev \ - pkg-config +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.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", "--"] -# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# Ubuntu 16.04 (this container) 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 +COPY scripts/make3.sh /scripts/ +RUN sh /scripts/make3.sh -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 +COPY scripts/crosstool-ng.sh /scripts/ +RUN sh /scripts/crosstool-ng.sh -RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild -RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +COPY scripts/rustbuild-setup.sh /scripts/ +RUN sh /scripts/rustbuild-setup.sh USER rustbuild WORKDIR /tmp @@ -61,9 +26,8 @@ RUN ./build-netbsd-toolchain.sh USER root -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV PATH=$PATH:/x-tools/x86_64-unknown-netbsd/bin diff --git a/src/ci/docker/emscripten/Dockerfile b/src/ci/docker/emscripten/Dockerfile deleted file mode 100644 index 0f0e5b69c3..0000000000 --- a/src/ci/docker/emscripten/Dockerfile +++ /dev/null @@ -1,41 +0,0 @@ -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 - -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache - -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 emscripten/build-emscripten.sh /tmp/ -RUN ./build-emscripten.sh -ENV PATH=$PATH:/tmp/emsdk_portable -ENV PATH=$PATH:/tmp/emsdk_portable/clang/tag-e1.37.10/build_tag-e1.37.10_32/bin -ENV PATH=$PATH:/tmp/emsdk_portable/node/4.1.1_32bit/bin -ENV PATH=$PATH:/tmp/emsdk_portable/emscripten/tag-1.37.10 -ENV EMSCRIPTEN=/tmp/emsdk_portable/emscripten/tag-1.37.10 - -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 deleted file mode 100755 index 8d6a28f418..0000000000 --- a/src/ci/docker/emscripten/build-emscripten.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/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 - - -# Some versions of the EMSDK archive have their contents in .emsdk-portable -# and others in emsdk_portable. Make sure the EMSDK ends up in a fixed path. -if [ -d emsdk-portable ]; then - mv emsdk-portable emsdk_portable -fi - -if [ ! -d emsdk_portable ]; then - echo "ERROR: Invalid emsdk archive. Dumping working directory." >&2 - ls -l - exit 1 -fi - -# Some versions of the EMSDK set the permissions of the root directory to -# 0700. Ensure the directory is readable by all users. -chmod 755 emsdk_portable - -source emsdk_portable/emsdk_env.sh -hide_output emsdk update -hide_output emsdk install --build=Release sdk-tag-1.37.10-32bit -hide_output emsdk activate --build=Release sdk-tag-1.37.10-32bit diff --git a/src/ci/docker/i686-gnu-nopt/Dockerfile b/src/ci/docker/i686-gnu-nopt/Dockerfile index 076be8f429..56ff9922ae 100644 --- a/src/ci/docker/i686-gnu-nopt/Dockerfile +++ b/src/ci/docker/i686-gnu-nopt/Dockerfile @@ -13,13 +13,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache -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 +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests diff --git a/src/ci/docker/i686-gnu/Dockerfile b/src/ci/docker/i686-gnu/Dockerfile index 5fac057357..1c1333cd7c 100644 --- a/src/ci/docker/i686-gnu/Dockerfile +++ b/src/ci/docker/i686-gnu/Dockerfile @@ -13,13 +13,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache -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 +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 4f34a7214c..da74ffb41f 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -82,7 +82,6 @@ exec docker \ --env TRAVIS_BRANCH \ --volume "$HOME/.cargo:/cargo" \ --volume "$HOME/rustsrc:$HOME/rustsrc" \ - --privileged \ --rm \ rust-ci \ /checkout/src/ci/run.sh diff --git a/src/ci/docker/scripts/android-base-apt-get.sh b/src/ci/docker/scripts/android-base-apt-get.sh new file mode 100644 index 0000000000..7ae3bf39a3 --- /dev/null +++ b/src/ci/docker/scripts/android-base-apt-get.sh @@ -0,0 +1,27 @@ +# 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 + +apt-get update +apt-get install -y --no-install-recommends \ + ca-certificates \ + cmake \ + curl \ + file \ + g++ \ + git \ + libssl-dev \ + make \ + pkg-config \ + python2.7 \ + sudo \ + unzip \ + xz-utils diff --git a/src/ci/docker/scripts/cross-apt-packages.sh b/src/ci/docker/scripts/cross-apt-packages.sh new file mode 100644 index 0000000000..f6c9cc960c --- /dev/null +++ b/src/ci/docker/scripts/cross-apt-packages.sh @@ -0,0 +1,36 @@ +# 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. + +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 \ + libssl-dev \ + libtool-bin \ + make \ + patch \ + pkg-config \ + python2.7 \ + sudo \ + texinfo \ + wget \ + xz-utils diff --git a/src/ci/docker/scripts/crosstool-ng.sh b/src/ci/docker/scripts/crosstool-ng.sh new file mode 100644 index 0000000000..8b2747cf21 --- /dev/null +++ b/src/ci/docker/scripts/crosstool-ng.sh @@ -0,0 +1,20 @@ +# 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 + +url="http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.22.0.tar.bz2" +curl $url | tar xjf - +cd crosstool-ng +./configure --prefix=/usr/local +make -j$(nproc) +make install +cd .. +rm -rf crosstool-ng diff --git a/src/ci/docker/scripts/emscripten-wasm.sh b/src/ci/docker/scripts/emscripten-wasm.sh new file mode 100644 index 0000000000..0e7da45907 --- /dev/null +++ b/src/ci/docker/scripts/emscripten-wasm.sh @@ -0,0 +1,47 @@ +# 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 -f /tmp/build.log + set -x +} + +# Download last known good emscripten from WebAssembly waterfall +BUILD=$(curl -L https://storage.googleapis.com/wasm-llvm/builds/linux/lkgr.json | \ + jq '.build | tonumber') +curl -L https://storage.googleapis.com/wasm-llvm/builds/linux/$BUILD/wasm-binaries.tbz2 | \ + hide_output tar xvkj + +# node 8 is required to run wasm +cd / +curl -L https://nodejs.org/dist/v8.0.0/node-v8.0.0-linux-x64.tar.xz | \ + tar -xJ + +# Make emscripten use wasm-ready node and LLVM tools +echo "EMSCRIPTEN_ROOT = '/wasm-install/emscripten'" >> /root/.emscripten +echo "NODE_JS='/usr/local/bin/node'" >> /root/.emscripten +echo "LLVM_ROOT='/wasm-install/bin'" >> /root/.emscripten +echo "BINARYEN_ROOT = '/wasm-install'" >> /root/.emscripten +echo "COMPILER_ENGINE = NODE_JS" >> /root/.emscripten +echo "JS_ENGINES = [NODE_JS]" >> /root/.emscripten diff --git a/src/ci/docker/scripts/emscripten.sh b/src/ci/docker/scripts/emscripten.sh new file mode 100644 index 0000000000..cf5eecbdb6 --- /dev/null +++ b/src/ci/docker/scripts/emscripten.sh @@ -0,0 +1,53 @@ +# 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 -f /tmp/build.log + set -x +} + +cd / +curl -L https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz | \ + tar -xz + +cd /emsdk-portable +./emsdk update +hide_output ./emsdk install sdk-1.37.13-64bit +./emsdk activate sdk-1.37.13-64bit + +# Compile and cache libc +source ./emsdk_env.sh +echo "main(){}" > a.c +HOME=/emsdk-portable/ emcc a.c +HOME=/emsdk-portable/ emcc -s BINARYEN=1 a.c +rm -f a.* + +# Make emsdk usable by any user +cp /root/.emscripten /emsdk-portable +chmod a+rxw -R /emsdk-portable + +# node 8 is required to run wasm +cd / +curl -L https://nodejs.org/dist/v8.0.0/node-v8.0.0-linux-x64.tar.xz | \ + tar -xJ diff --git a/src/ci/docker/scripts/make3.sh b/src/ci/docker/scripts/make3.sh new file mode 100644 index 0000000000..8a7845cb8f --- /dev/null +++ b/src/ci/docker/scripts/make3.sh @@ -0,0 +1,19 @@ +# 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 + +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 diff --git a/src/ci/docker/scripts/rustbuild-setup.sh b/src/ci/docker/scripts/rustbuild-setup.sh new file mode 100644 index 0000000000..96efccfdff --- /dev/null +++ b/src/ci/docker/scripts/rustbuild-setup.sh @@ -0,0 +1,14 @@ +# 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 + +groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild +mkdir /x-tools && chown rustbuild:rustbuild /x-tools diff --git a/src/ci/docker/x86_64-gnu-aux/Dockerfile b/src/ci/docker/x86_64-gnu-aux/Dockerfile index 06c7c2824f..a449526efc 100644 --- a/src/ci/docker/x86_64-gnu-aux/Dockerfile +++ b/src/ci/docker/x86_64-gnu-aux/Dockerfile @@ -14,13 +14,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ xz-utils \ pkg-config -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.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 RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu diff --git a/src/ci/docker/x86_64-gnu-debug/Dockerfile b/src/ci/docker/x86_64-gnu-debug/Dockerfile index 6ea54ac4db..8111118ad3 100644 --- a/src/ci/docker/x86_64-gnu-debug/Dockerfile +++ b/src/ci/docker/x86_64-gnu-debug/Dockerfile @@ -13,13 +13,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.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 RUST_CONFIGURE_ARGS \ diff --git a/src/ci/docker/x86_64-gnu-distcheck/Dockerfile b/src/ci/docker/x86_64-gnu-distcheck/Dockerfile index e24c660a8c..c3fe8ea51c 100644 --- a/src/ci/docker/x86_64-gnu-distcheck/Dockerfile +++ b/src/ci/docker/x86_64-gnu-distcheck/Dockerfile @@ -15,13 +15,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libssl-dev \ pkg-config -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.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 RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu diff --git a/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile b/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile index 78035c7fe3..377e086955 100644 --- a/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile +++ b/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile @@ -13,13 +13,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.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 RUST_CONFIGURE_ARGS \ diff --git a/src/ci/docker/x86_64-gnu-incremental/Dockerfile b/src/ci/docker/x86_64-gnu-incremental/Dockerfile index 0aaed64e38..a21a99e965 100644 --- a/src/ci/docker/x86_64-gnu-incremental/Dockerfile +++ b/src/ci/docker/x86_64-gnu-incremental/Dockerfile @@ -13,13 +13,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.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 RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu 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 7c136fa39b..1a9f1d2d73 100644 --- a/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile +++ b/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile @@ -16,13 +16,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ zlib1g-dev \ xz-utils -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.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 RUST_CONFIGURE_ARGS \ diff --git a/src/ci/docker/x86_64-gnu-nopt/Dockerfile b/src/ci/docker/x86_64-gnu-nopt/Dockerfile index 4499736967..e008b21f66 100644 --- a/src/ci/docker/x86_64-gnu-nopt/Dockerfile +++ b/src/ci/docker/x86_64-gnu-nopt/Dockerfile @@ -13,13 +13,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.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 RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --disable-optimize-tests diff --git a/src/ci/docker/x86_64-gnu/Dockerfile b/src/ci/docker/x86_64-gnu/Dockerfile index de85e1ff36..3a6760b476 100644 --- a/src/ci/docker/x86_64-gnu/Dockerfile +++ b/src/ci/docker/x86_64-gnu/Dockerfile @@ -13,14 +13,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.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 RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --enable-sanitizers +ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --enable-sanitizers --enable-profiler ENV SCRIPT python2.7 ../x.py test diff --git a/src/ci/init_repo.sh b/src/ci/init_repo.sh index 282da009ea..7ffe00a807 100755 --- a/src/ci/init_repo.sh +++ b/src/ci/init_repo.sh @@ -22,9 +22,6 @@ REPO_DIR="$1" CACHE_DIR="$2" cache_src_dir="$CACHE_DIR/src" -# If the layout of the cache directory changes, bump the number here -# (and anywhere else this file is referenced) so the cache is wiped -cache_valid_file="$CACHE_DIR/cache_valid1" if [ ! -d "$REPO_DIR" -o ! -d "$REPO_DIR/.git" ]; then echo "Error: $REPO_DIR does not exist or is not a git repo" @@ -36,47 +33,19 @@ if [ ! -d "$CACHE_DIR" ]; then exit 1 fi -# Wipe the cache if it's not valid, or mark it as invalid while we update it -if [ ! -f "$cache_valid_file" ]; then - echo "Invalid cache, wiping ($cache_valid_file missing)" - rm -rf "$CACHE_DIR" - mkdir "$CACHE_DIR" -else - # Ignore errors while gathering information about the possible brokenness - # of the git repo since our gathered info will tell us something is wrong - set +o errexit - stat_lines=$(cd "$cache_src_dir" && git status --porcelain | wc -l) - stat_ec=$(cd "$cache_src_dir" && git status >/dev/null 2>&1; echo $?) - set -o errexit - if [ ! -d "$cache_src_dir/.git" -o $stat_lines != 0 -o $stat_ec != 0 ]; then - # Something is badly wrong - the cache valid file is here, but something - # about the git repo is fishy. Nuke it all, just in case - echo "WARNING: $cache_valid_file exists but bad repo: l:$stat_lines, ec:$stat_ec" - rm -rf "$CACHE_DIR" - mkdir "$CACHE_DIR" - else - echo "Valid cache ($cache_valid_file exists)" - rm "$cache_valid_file" - fi -fi +rm -rf "$CACHE_DIR" +mkdir "$CACHE_DIR" travis_fold start update_cache travis_time_start # Update the cache (a pristine copy of the rust source master) -if [ ! -d "$cache_src_dir/.git" ]; then - retry sh -c "rm -rf $cache_src_dir && mkdir -p $cache_src_dir && \ - git clone https://github.com/rust-lang/rust.git $cache_src_dir" -fi -retry sh -c "cd $cache_src_dir && git reset --hard && git pull" +retry sh -c "rm -rf $cache_src_dir && mkdir -p $cache_src_dir && \ + git clone --depth 1 https://github.com/rust-lang/rust.git $cache_src_dir" (cd $cache_src_dir && git rm src/llvm) retry sh -c "cd $cache_src_dir && \ git submodule deinit -f . && git submodule sync && git submodule update --init" -# Cache was updated without errors, mark it as valid -echo "Refreshed cache (touch $cache_valid_file)" -touch "$cache_valid_file" - travis_fold end update_cache travis_time_finish @@ -92,19 +61,21 @@ for module in $modules; do if [ "$module" = src/llvm ]; then commit="$(git ls-tree HEAD src/llvm | awk '{print $3}')" git rm src/llvm - curl -sSL -O "https://github.com/rust-lang/llvm/archive/$commit.tar.gz" + retry sh -c "rm -f $commit.tar.gz && \ + curl -sSL -O https://github.com/rust-lang/llvm/archive/$commit.tar.gz" tar -C src/ -xf "$commit.tar.gz" rm "$commit.tar.gz" mv "src/llvm-$commit" src/llvm continue fi - if [ ! -d "$cache_src_dir/$module" ]; then + if [ ! -e "$cache_src_dir/$module/.git" ]; then echo "WARNING: $module not found in pristine repo" - retry sh -c "git submodule deinit -f $module && git submodule update --init $module" + retry sh -c "git submodule deinit -f $module && \ + git submodule update --init --recursive $module" continue fi retry sh -c "git submodule deinit -f $module && \ - git submodule update --init --reference $cache_src_dir/$module $module" + git submodule update --init --recursive --reference $cache_src_dir/$module $module" done travis_fold end update_submodules diff --git a/src/doc/book/second-edition/dictionary.txt b/src/doc/book/second-edition/dictionary.txt index 2aeba696c1..3a9c7dcc0a 100644 --- a/src/doc/book/second-edition/dictionary.txt +++ b/src/doc/book/second-edition/dictionary.txt @@ -102,6 +102,7 @@ Enum enums enum's Enums +eprintln ErrorKind Executables extern @@ -127,7 +128,6 @@ GitHub gitignore grapheme Grapheme -greprs growable gzip hardcode @@ -192,6 +192,7 @@ Metadata metaprogramming mibbit Mibbit +minigrep mixup mkdir modifiability diff --git a/src/doc/book/second-edition/nostarch/chapter05.md b/src/doc/book/second-edition/nostarch/chapter05.md index 70fbf49bec..b6f35856b8 100644 --- a/src/doc/book/second-edition/nostarch/chapter05.md +++ b/src/doc/book/second-edition/nostarch/chapter05.md @@ -62,14 +62,27 @@ Listing 5-2: Creating an instance of the `User` struct To get a specific value from a struct, we can use dot notation. If we wanted just this user’s email address, we can use `user1.email` wherever we want to use this value. To change a value in a struct, if the instance is mutable, we -can use the dot notation and assign into a particular field, such as -`user1.email = String::from("someone-else@example.com");`. +can use the dot notation and assign into a particular field. Listing 5-3 shows +how to change the value in the `email` field of a mutable `User` instance: + +``` +let mut user1 = User { + email: String::from("someone@example.com"), + username: String::from("someusername123"), + active: true, + sign_in_count: 1, +}; + +user1.email = String::from("anotheremail@example.com"); +``` + +Listing 5-3: Changing the value in the `email` field of a `User` instance ### Field Init Shorthand when Variables Have the Same Name as Fields If you have variables with the same names as struct fields, you can use *field init shorthand*. This can make functions that create new instances of structs -more concise. The function named `build_user` shown here in Listing 5-3 has +more concise. The function named `build_user` shown here in Listing 5-4 has parameters named `email` and `username`. The function creates and returns a `User` instance: @@ -84,13 +97,13 @@ fn build_user(email: String, username: String) -> User { } ``` -Listing 5-3: A `build_user` function that takes an email and username and +Listing 5-4: A `build_user` function that takes an email and username and returns a `User` instance Because the parameter names `email` and `username` are the same as the `User` struct's field names `email` and `username`, we can write `build_user` without -the repetition of `email` and `username` as shown in Listing 5-4. This version -of `build_user` behaves the same way as the one in Listing 5-3. The field init +the repetition of `email` and `username` as shown in Listing 5-5. This version +of `build_user` behaves the same way as the one in Listing 5-4. The field init syntax can make cases like this shorter to write, especially when structs have many fields. @@ -105,13 +118,13 @@ fn build_user(email: String, username: String) -> User { } ``` -Listing 5-4: A `build_user` function that uses field init syntax since the +Listing 5-5: A `build_user` function that uses field init syntax since the `email` and `username` parameters have the same name as struct fields ### Creating Instances From Other Instances With Struct Update Syntax It's often useful to create a new instance from an old instance, using most of -the old instance's values but changing some. Listing 5-5 shows an example of +the old instance's values but changing some. Listing 5-6 shows an example of creating a new `User` instance in `user2` by setting the values of `email` and `username` but using the same values for the rest of the fields from the `user1` instance we created in Listing 5-2: @@ -125,13 +138,13 @@ let user2 = User { }; ``` -Listing 5-5: Creating a new `User` instance, `user2`, and setting some fields +Listing 5-6: Creating a new `User` instance, `user2`, and setting some fields to the values of the same fields from `user1` The *struct update syntax* achieves the same effect as the code in Listing -5-5 using less code. The struct update syntax uses `..` to specify that the +5-6 using less code. The struct update syntax uses `..` to specify that the remaining fields not set explicitly should have the same value as the fields in -the given instance. The code in Listing 5-6 also creates an instance in `user2` +the given instance. The code in Listing 5-7 also creates an instance in `user2` that has a different value for `email` and `username` but has the same values for the `active` and `sign_in_count` fields that `user1` has: @@ -143,7 +156,7 @@ let user2 = User { }; ``` -Listing 5-6: Using struct update syntax to set a new `email` and `username` +Listing 5-7: Using struct update syntax to set a new `email` and `username` values for a `User` instance but use the rest of the values from the fields of the instance in the `user1` variable @@ -242,7 +255,7 @@ refactor the program until we’re using structs instead. Let’s make a new binary project with Cargo called *rectangles* that will take the length and width of a rectangle specified in pixels and will calculate the -area of the rectangle. Listing 5-7 shows a short program with one way of doing +area of the rectangle. Listing 5-8 shows a short program with one way of doing just that in our project’s *src/main.rs*: Filename: src/main.rs @@ -263,7 +276,7 @@ fn area(length: u32, width: u32) -> u32 { } ``` -Listing 5-7: Calculating the area of a rectangle specified by its length and +Listing 5-8: Calculating the area of a rectangle specified by its length and width in separate variables Now, run this program using `cargo run`: @@ -274,7 +287,7 @@ The area of the rectangle is 1500 square pixels. ### Refactoring with Tuples -Even though Listing 5-7 works and figures out the area of the rectangle by +Even though Listing 5-8 works and figures out the area of the rectangle by calling the `area` function with each dimension, we can do better. The length and the width are related to each other because together they describe one rectangle. @@ -290,7 +303,7 @@ function we wrote has two parameters. The parameters are related, but that’s not expressed anywhere in our program. It would be more readable and more manageable to group length and width together. We’ve already discussed one way we might do that in the Grouping Values into Tuples section of Chapter 3 on -page XX: by using tuples. Listing 5-8 shows another version of our program that +page XX: by using tuples. Listing 5-9 shows another version of our program that uses tuples: Filename: src/main.rs @@ -329,7 +342,7 @@ our code. We use structs to add meaning by labeling the data. We can transform the tuple we’re using into a data type with a name for the whole as well as names for the -parts, as shown in Listing 5-9: +parts, as shown in Listing 5-10: Filename: src/main.rs @@ -353,7 +366,7 @@ fn area(rectangle: &Rectangle) -> u32 { } ``` -Listing 5-9: Defining a `Rectangle` struct +Listing 5-10: Defining a `Rectangle` struct Here we’ve defined a struct and named it `Rectangle`. Inside the `{}` we defined the fields as `length` and `width`, both of which have type `u32`. Then @@ -378,7 +391,7 @@ of `0` and `1`—a win for clarity. It would be helpful to be able to print out an instance of the `Rectangle` while we’re debugging our program in order to see the values for all its -fields. Listing 5-10 uses the `println!` macro as we have been in earlier +fields. Listing 5-11 uses the `println!` macro as we have been in earlier chapters: Filename: src/main.rs @@ -396,7 +409,7 @@ fn main() { } ``` -Listing 5-10: Attempting to print a `Rectangle` instance +Listing 5-11: Attempting to print a `Rectangle` instance When we run this code, we get an error with this core message: @@ -443,7 +456,7 @@ crate, add `#[derive(Debug)]` or manually implement it Rust *does* include functionality to print out debugging information, but we have to explicitly opt-in to make that functionality available for our struct. To do that, we add the annotation `#[derive(Debug)]` just before the struct -definition, as shown in Listing 5-11: +definition, as shown in Listing 5-12: Filename: src/main.rs @@ -461,7 +474,7 @@ fn main() { } ``` -Listing 5-11: Adding the annotation to derive the `Debug` trait and printing +Listing 5-12: Adding the annotation to derive the `Debug` trait and printing the `Rectangle` instance using debug formatting Now when we run the program, we won’t get any errors and we’ll see the @@ -498,7 +511,7 @@ continue to refactor this code by turning the `area` function into an `area` ## Method Syntax *Methods* are similar to functions: they’re declared with the `fn` keyword and -their name, they can have parameters and return values, and they contain some +their name, they can have parameters and a return value, and they contain some code that is run when they’re called from somewhere else. However, methods are different from functions in that they’re defined within the context of a struct (or an enum or a trait object, which we cover in Chapters 6 and 17, @@ -509,7 +522,7 @@ instance of the struct the method is being called on. Let’s change the `area` function that has a `Rectangle` instance as a parameter and instead make an `area` method defined on the `Rectangle` struct, as shown -in Listing 5-12: +in Listing 5-13: Filename: src/main.rs @@ -536,7 +549,7 @@ fn main() { } ``` -Listing 5-12: Defining an `area` method on the `Rectangle` struct +Listing 5-13: Defining an `area` method on the `Rectangle` struct To define the function within the context of `Rectangle`, we start an `impl` (*implementation*) block. Then we move the `area` function within the `impl` @@ -608,7 +621,7 @@ Let’s practice using methods by implementing a second method on the `Rectangle struct. This time, we want an instance of `Rectangle` to take another instance of `Rectangle` and return `true` if the second `Rectangle` can fit completely within `self`; otherwise it should return `false`. That is, we want to be able -to write the program shown in Listing 5-13, once we’ve defined the `can_hold` +to write the program shown in Listing 5-14, once we’ve defined the `can_hold` method: Filename: src/main.rs @@ -624,7 +637,7 @@ fn main() { } ``` -Listing 5-13: Demonstration of using the as-yet-unwritten `can_hold` method +Listing 5-14: Demonstration of using the as-yet-unwritten `can_hold` method And the expected output would look like the following, because both dimensions of `rect2` are smaller than the dimensions of `rect1`, but `rect3` is wider @@ -647,7 +660,7 @@ calling the `can_hold` method. The return value of `can_hold` will be a boolean, and the implementation will check whether the length and width of `self` are both greater than the length and width of the other `Rectangle`, respectively. Let’s add the new `can_hold` method to the `impl` block from -Listing 5-12, shown in Listing 5-14: +Listing 5-13, shown in Listing 5-15: Filename: src/main.rs @@ -663,10 +676,10 @@ impl Rectangle { } ``` -Listing 5-14: Implementing the `can_hold` method on `Rectangle` that takes +Listing 5-15: Implementing the `can_hold` method on `Rectangle` that takes another `Rectangle` instance as a parameter -When we run this code with the `main` function in Listing 5-13, we’ll get our +When we run this code with the `main` function in Listing 5-14, we’ll get our desired output. Methods can take multiple parameters that we add to the signature after the `self` parameter, and those parameters work just like parameters in functions. diff --git a/src/doc/book/second-edition/nostarch/chapter11.md b/src/doc/book/second-edition/nostarch/chapter11.md index 1922e394d5..459fe0ef1d 100644 --- a/src/doc/book/second-edition/nostarch/chapter11.md +++ b/src/doc/book/second-edition/nostarch/chapter11.md @@ -1,53 +1,52 @@ [TOC] -# Testing +# Writing Automated Tests > Program testing can be a very effective way to show the presence of bugs, but > it is hopelessly inadequate for showing their absence. -> -> Edsger W. Dijkstra, "The Humble Programmer" (1972) +> Edsger W. Dijkstra, “The Humble Programmer” (1972) Correctness in our programs means that our code does what we intend for it to do. Rust is a programming language that cares a lot about correctness, but -correctness is a complex topic and isn't easy to prove. Rust's type system +correctness is a complex topic and isn’t easy to prove. Rust’s type system shoulders a huge part of this burden, but the type system cannot catch every kind of incorrectness. As such, Rust includes support for writing software tests within the language itself. -As an example, say we write a function called `add_two` that adds two to a -number passed to it. This function's signature accepts an integer as a -parameter and returns an integer as a result. When we implement and compile -that function, Rust will do all the type checking and borrow checking that -we've seen so far. Those checks will make sure that, for instance, we aren't -passing a `String` value or an invalid reference to this function. What Rust -*can't* check is that this function will do precisely what we intend: return -the parameter plus two, rather than, say, the parameter plus 10 or the -parameter minus 50! That's where tests come in. +As an example, say we write a function called `add_two` that adds two to +whatever number is passed to it. This function’s signature accepts an integer +as a parameter and returns an integer as a result. When we implement and +compile that function, Rust will do all the type checking and borrow checking +that we’ve seen so far to make sure that, for instance, we aren’t passing a +`String` value or an invalid reference to this function. What Rust *can’t* +check is that this function will do precisely what we intend: return the +parameter plus two, rather than, say, the parameter plus 10 or the parameter +minus 50! That’s where tests come in. We can write tests that assert, for example, that when we pass `3` to the `add_two` function, we get `5` back. We can run these tests whenever we make changes to our code to make sure any existing correct behavior has not changed. Testing is a complex skill, and we cannot hope to cover everything about how to -write good tests in one chapter of a book, so here we'll just discuss the -mechanics of Rust's testing facilities. We'll talk about the annotations and +write good tests in one chapter of a book, so here we’ll just discuss the +mechanics of Rust’s testing facilities. We’ll talk about the annotations and macros available to you when writing your tests, the default behavior and options provided for running your tests, and how to organize tests into unit tests and integration tests. ## How to Write Tests -Tests are Rust functions that verify non-test code is functioning in the -program in the expected manner. The bodies of test functions typically contain -some setup, running the code we want to test, then asserting that the results -are what we expect. Let's look at the features Rust provides specifically for -writing tests: the `test` attribute, a few macros, and the `should_panic` -attribute. +Tests are Rust functions that verify that the non-test code in the program is +functioning in the expected manner. The bodies of test functions typically run +some setup code, then run the code we want to test, then assert whether the +results are what we expect. Let’s look at the features Rust provides +specifically for writing tests: the `test` attribute, a few macros, and the +`should_panic` attribute. ### The Anatomy of a Test Function -At its simplest, a test in Rust is a function that's annotated with the `test` +At its simplest, a test in Rust is a function that’s annotated with the `test` attribute. Attributes are metadata about pieces of Rust code: the `derive` attribute that we used with structs in Chapter 5 is one example. To make a function into a test function, we add `#[test]` on the line before `fn`. When @@ -55,28 +54,19 @@ we run our tests with the `cargo test` command, Rust will build a test runner binary that runs the functions annotated with the `test` attribute and reports on whether each test function passes or fails. - - - We saw in Chapter 7 that when you make a new library project with Cargo, a test module with a test function in it is automatically generated for us. This is to -help us get started writing our tests, since we don't have to go look up the +help us get started writing our tests, since we don’t have to go look up the exact structure and syntax of test functions every time we start a new project. We can add as many additional test functions and as many test modules as we want, though! -We're going to explore some aspects of how tests work by experimenting with the -template test generated for us, without actually testing any code. Then we'll -write some real-world tests that call some code that we've written and assert +We’re going to explore some aspects of how tests work by experimenting with the +template test generated for us, without actually testing any code. Then we’ll +write some real-world tests that call some code that we’ve written and assert that its behavior is correct. -Let's create a new library project called `adder`: +Let’s create a new library project called `adder`: ``` $ cargo new adder @@ -101,7 +91,7 @@ mod tests { Listing 11-1: The test module and function generated automatically for us by `cargo new` -For now, let's ignore the top two lines and focus on the function to see how it +For now, let’s ignore the top two lines and focus on the function to see how it works. Note the `#[test]` annotation before the `fn` line: this attribute indicates this is a test function, so that the test runner knows to treat this function as a test. We could also have non-test functions in the `tests` module @@ -109,7 +99,7 @@ to help set up common scenarios or perform common operations, so we need to indicate which functions are tests with the `#[test]` attribute. The function currently has no body, which means there is no code to fail the -test; an empty test is a passing test! Let's run it and see that this test +test; an empty test is a passing test! Let’s run it and see that this test passes. The `cargo test` command runs all tests we have in our project, as shown in @@ -118,7 +108,7 @@ Listing 11-2: ``` $ cargo test Compiling adder v0.1.0 (file:///projects/adder) - Finished debug [unoptimized + debuginfo] target(s) in 0.22 secs + Finished dev [unoptimized + debuginfo] target(s) in 0.22 secs Running target/debug/deps/adder-ce99bcc2479f4607 running 1 test @@ -142,30 +132,21 @@ that test, `ok`. Then we see the overall summary of running the tests: `test result: ok.` means all the tests passed. `1 passed; 0 failed` adds up the number of tests that passed or failed. -We don't have any tests we've marked as ignored, so the summary says `0 -ignored`. We're going to talk about ignoring tests in the next section on +We don’t have any tests we’ve marked as ignored, so the summary says `0 +ignored`. We’re going to talk about ignoring tests in the next section on different ways to run tests. The `0 measured` statistic is for benchmark tests that measure performance. Benchmark tests are, as of this writing, only available in nightly Rust. See Appendix D for more information about nightly Rust. The next part of the test output that starts with `Doc-tests adder` is for the -results of any documentation tests. We don't have any documentation tests yet, +results of any documentation tests. We don’t have any documentation tests yet, but Rust can compile any code examples that appear in our API documentation. -This feature helps us keep our docs and our code in sync! We'll be talking -about how to write documentation tests in the "Documentation Comments" section -of Chapter 14. We're going to ignore the `Doc-tests` output for now. - - - - -Let's change the name of our test and see how that changes the test output. +This feature helps us keep our docs and our code in sync! We’ll be talking +about how to write documentation tests in the “Documentation Comments” section +of Chapter 14. We’re going to ignore the `Doc-tests` output for now. + +Let’s change the name of our test and see how that changes the test output. Give the `it_works` function a different name, such as `exploration`, like so: Filename: src/lib.rs @@ -179,7 +160,7 @@ mod tests { } ``` -And run `cargo test` again. In the output, we'll now see `exploration` instead +And run `cargo test` again. In the output, we’ll now see `exploration` instead of `it_works`: ``` @@ -189,7 +170,7 @@ test tests::exploration ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured ``` -Let's add another test, but this time we'll make a test that fails! Tests fail +Let’s add another test, but this time we’ll make a test that fails! Tests fail when something in the test function panics. We talked about the simplest way to cause a panic in Chapter 9: call the `panic!` macro! Type in the new test so that your `src/lib.rs` now looks like Listing 11-3: @@ -244,14 +225,14 @@ failed because it `panicked at 'Make this test fail'`, which happened on *src/lib.rs* line 9. The next section lists just the names of all the failing tests, which is useful when there are lots of tests and lots of detailed failing test output. We can use the name of a failing test to run just that -test in order to more easily debug it; we'll talk more about ways to run tests +test in order to more easily debug it; we’ll talk more about ways to run tests in the next section. Finally, we have the summary line: overall, our test result is `FAILED`. We had 1 test pass and 1 test fail. -Now that we've seen what the test results look like in different scenarios, -let's look at some macros other than `panic!` that are useful in tests. +Now that we’ve seen what the test results look like in different scenarios, +let’s look at some macros other than `panic!` that are useful in tests. ### Checking Results with the `assert!` Macro @@ -262,24 +243,11 @@ to ensure that some condition in a test evaluates to `true`. We give the calls the `panic!` macro, which causes the test to fail. This is one macro that helps us check that our code is functioning in the way we intend. - - - Remember all the way back in Chapter 5, Listing 5-9, where we had a `Rectangle` -struct and a `can_hold` method, repeated here in Listing 11-5. Let's put this +struct and a `can_hold` method, repeated here in Listing 11-5. Let’s put this code in *src/lib.rs* instead of *src/main.rs* and write some tests for it using the `assert!` macro. - - Filename: src/lib.rs ``` @@ -298,8 +266,8 @@ impl Rectangle { Listing 11-5: The `Rectangle` struct and its `can_hold` method from Chapter 5 -The `can_hold` method returns a boolean, which means it's a perfect use case -for the `assert!` macro. In Listing 11-6, let's write a test that exercises the +The `can_hold` method returns a boolean, which means it’s a perfect use case +for the `assert!` macro. In Listing 11-6, let’s write a test that exercises the `can_hold` method by creating a `Rectangle` instance that has a length of 8 and a width of 7, and asserting that it can hold another `Rectangle` instance that has a length of 5 and a width of 1: @@ -324,17 +292,17 @@ mod tests { Listing 11-6: A test for `can_hold` that checks that a larger rectangle indeed holds a smaller rectangle -Note that we've added a new line inside the `tests` module: `use super::*;`. +Note that we’ve added a new line inside the `tests` module: `use super::*;`. The `tests` module is a regular module that follows the usual visibility rules -we covered in Chapter 7. Because we're in an inner module, we need to bring the -code under test in the outer module into the scope of the inner module. We've +we covered in Chapter 7. Because we’re in an inner module, we need to bring the +code under test in the outer module into the scope of the inner module. We’ve chosen to use a glob here so that anything we define in the outer module is available to this `tests` module. -We've named our test `larger_can_hold_smaller`, and we've created the two +We’ve named our test `larger_can_hold_smaller`, and we’ve created the two `Rectangle` instances that we need. Then we called the `assert!` macro and passed it the result of calling `larger.can_hold(&smaller)`. This expression is -supposed to return `true`, so our test should pass. Let's find out! +supposed to return `true`, so our test should pass. Let’s find out! ``` running 1 test @@ -343,7 +311,7 @@ test tests::larger_can_hold_smaller ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured ``` -It does pass! Let's add another test, this time asserting that a smaller +It does pass! Let’s add another test, this time asserting that a smaller rectangle cannot hold a larger rectangle: Filename: src/lib.rs @@ -362,7 +330,7 @@ mod tests { } #[test] - fn smaller_can_hold_larger() { + fn smaller_cannot_hold_larger() { let larger = Rectangle { length: 8, width: 7 }; let smaller = Rectangle { length: 5, width: 1 }; @@ -377,15 +345,15 @@ way, our test will pass if `can_hold` returns `false`: ``` running 2 tests -test tests::smaller_can_hold_larger ... ok +test tests::smaller_cannot_hold_larger ... ok test tests::larger_can_hold_smaller ... ok test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured ``` -Two passing tests! Now let's see what happens to our test results if we -introduce a bug in our code. Let's change the implementation of the `can_hold` -method to have a less-than sign when it compares the lengths where it's +Two passing tests! Now let’s see what happens to our test results if we +introduce a bug in our code. Let’s change the implementation of the `can_hold` +method to have a less-than sign when it compares the lengths where it’s supposed to have a greater-than sign: ``` @@ -406,7 +374,7 @@ Running the tests now produces: ``` running 2 tests -test tests::smaller_can_hold_larger ... ok +test tests::smaller_cannot_hold_larger ... ok test tests::larger_can_hold_smaller ... FAILED failures: @@ -429,18 +397,18 @@ less than 5. ### Testing Equality with the `assert_eq!` and `assert_ne!` Macros A common way to test functionality is to take the result of the code under test -and the value we expect the code to return and check that they're equal. We +and the value we expect the code to return and check that they’re equal. We could do this using the `assert!` macro and passing it an expression using the `==` operator. However, this is such a common test that the standard library provides a pair of macros to perform this test more conveniently: `assert_eq!` and `assert_ne!`. These macros compare two arguments for equality or -inequality, respectively. They'll also print out the two values if the -assertion fails, so that it's easier to see *why* the test failed, while the +inequality, respectively. They’ll also print out the two values if the +assertion fails, so that it’s easier to see *why* the test failed, while the `assert!` macro only tells us that it got a `false` value for the `==` expression, not the values that lead to the `false` value. -In Listing 11-7, let's write a function named `add_two` that adds two to its -parameter and returns the result. Then let's test this function using the +In Listing 11-7, let’s write a function named `add_two` that adds two to its +parameter and returns the result. Then let’s test this function using the `assert_eq!` macro: Filename: src/lib.rs @@ -463,7 +431,7 @@ mod tests { Listing 11-7: Testing the function `add_two` using the `assert_eq!` macro -Let's check that it passes! +Let’s check that it passes! ``` running 1 test @@ -476,7 +444,7 @@ The first argument we gave to the `assert_eq!` macro, 4, is equal to the result of calling `add_two(2)`. We see a line for this test that says `test tests::it_adds_two ... ok`, and the `ok` text indicates that our test passed! -Let's introduce a bug into our code to see what it looks like when a test that +Let’s introduce a bug into our code to see what it looks like when a test that uses `assert_eq!` fails. Change the implementation of the `add_two` function to instead add 3: @@ -513,16 +481,16 @@ useful and helps us get started debugging: it says the `left` argument to Note that in some languages and test frameworks, the parameters to the functions that assert two values are equal are called `expected` and `actual` and the order in which we specify the arguments matters. However, in Rust, -they're called `left` and `right` instead, and the order in which we specify -the value we expect and the value that the code under test produces doesn't +they’re called `left` and `right` instead, and the order in which we specify +the value we expect and the value that the code under test produces doesn’t matter. We could have written the assertion in this test as `assert_eq!(add_two(2), 4)`, which would result in a failure message that says `` assertion failed: `(left == right)` (left: `5`, right: `4`) ``. The `assert_ne!` macro will pass if the two values we give to it are not equal -and fail if they are equal. This macro is most useful for cases when we're not +and fail if they are equal. This macro is most useful for cases when we’re not sure exactly what a value *will* be, but we know what the value definitely -*won't* be, if our code is functioning as we intend. For example, if we have a +*won’t* be, if our code is functioning as we intend. For example, if we have a function that is guaranteed to change its input in some way, but the way in which the input is changed depends on the day of the week that we run our tests, the best thing to assert might be that the output of the function is not @@ -533,8 +501,8 @@ Under the surface, the `assert_eq!` and `assert_ne!` macros use the operators arguments using debug formatting, which means the values being compared must implement the `PartialEq` and `Debug` traits. All of the primitive types and most of the standard library types implement these traits. For structs and -enums that you define, you'll need to implement `PartialEq` in order to be able -to assert that values of those types are equal or not equal. You'll need to +enums that you define, you’ll need to implement `PartialEq` in order to be able +to assert that values of those types are equal or not equal. You’ll need to implement `Debug` in order to be able to print out the values in the case that the assertion fails. Because both of these traits are derivable traits, as we mentioned in Chapter 5, this is usually as straightforward as adding the @@ -552,7 +520,7 @@ contains `{}` placeholders and values to go in the placeholders. Custom messages are useful in order to document what an assertion means, so that when the test fails, we have a better idea of what the problem is with the code. -For example, let's say we have a function that greets people by name, and we +For example, let’s say we have a function that greets people by name, and we want to test that the name we pass into the function appears in the output: Filename: src/lib.rs @@ -574,14 +542,14 @@ mod tests { } ``` -The requirements for this program haven't been agreed upon yet, and we're +The requirements for this program haven’t been agreed upon yet, and we’re pretty sure the `Hello` text at the beginning of the greeting will change. We -decided we don't want to have to update the test for the name when that +decided we don’t want to have to update the test for the name when that happens, so instead of checking for exact equality to the value returned from -the `greeting` function, we're just going to assert that the output contains +the `greeting` function, we’re just going to assert that the output contains the text of the input parameter. -Let's introduce a bug into this code to see what this test failure looks like, +Let’s introduce a bug into this code to see what this test failure looks like, by changing `greeting` to not include `name`: ``` @@ -609,7 +577,7 @@ failures: This just tells us that the assertion failed and which line the assertion is on. A more useful failure message in this case would print the value we did get -from the `greeting` function. Let's change the test function to have a custom +from the `greeting` function. Let’s change the test function to have a custom failure message made from a format string with a placeholder filled in with the actual value we got from the `greeting` function: @@ -624,11 +592,11 @@ fn greeting_contains_name() { } ``` -Now if we run the test again, we'll get a much more informative error message: +Now if we run the test again, we’ll get a much more informative error message: ``` ---- tests::greeting_contains_name stdout ---- - thread 'tests::greeting_contains_name' panicked at 'Result did not contain + thread 'tests::greeting_contains_name' panicked at 'Greeting did not contain name, value was `Hello`', src/lib.rs:12 note: Run with `RUST_BACKTRACE=1` for a backtrace. ``` @@ -639,7 +607,7 @@ debug what happened instead of what we were expecting to happen. ### Checking for Panics with `should_panic` In addition to checking that our code returns the correct values we expect, -it's also important to check that our code handles error conditions as we +it’s also important to check that our code handles error conditions as we expect. For example, consider the `Guess` type that we created in Chapter 9 in Listing 9-8. Other code that uses `Guess` is depending on the guarantee that `Guess` instances will only contain values between 1 and 100. We can write a @@ -648,9 +616,9 @@ outside that range panics. We can do this by adding another attribute, `should_panic`, to our test function. This attribute makes a test pass if the code inside the function -panics, and the test will fail if the code inside the function does non panic. +panics, and the test will fail if the code inside the function doesn't panic. -Listing 11-8 shows how we'd write a test that checks the error conditions of +Listing 11-8 shows how we’d write a test that checks the error conditions of `Guess::new` happen when we expect: Filename: src/lib.rs @@ -667,7 +635,7 @@ impl Guess { } Guess { - value: value, + value } } } @@ -687,7 +655,7 @@ mod tests { Listing 11-8: Testing that a condition will cause a `panic!` The `#[should_panic]` attribute goes after the `#[test]` attribute and before -the test function it applies to. Let's see what it looks like when this test +the test function it applies to. Let’s see what it looks like when this test passes: ``` @@ -697,7 +665,7 @@ test tests::greater_than_100 ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured ``` -Looks good! Now let's introduce a bug in our code, by removing the condition +Looks good! Now let’s introduce a bug in our code, by removing the condition that the `new` function will panic if the value is greater than 100: ``` @@ -708,7 +676,7 @@ impl Guess { } Guess { - value: value, + value } } } @@ -728,8 +696,8 @@ failures: test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured ``` -We don't get a very helpful message in this case, but once we look at the test -function, we can see that it's annotated with `#[should_panic]`. The failure we +We don’t get a very helpful message in this case, but once we look at the test +function, we can see that it’s annotated with `#[should_panic]`. The failure we got means that the code in the function, `Guess::new(200)`, did not cause a panic. @@ -760,7 +728,7 @@ impl Guess { } Guess { - value: value, + value } } } @@ -790,7 +758,7 @@ substring of the panic message is enough to ensure that the code in the function that gets run is the `else if value > 100` case. To see what happens when a `should_panic` test with an `expected` message -fails, let's again introduce a bug into our code by swapping the bodies of the +fails, let’s again introduce a bug into our code by swapping the bodies of the `if value < 1` and the `else if value > 100` blocks: ``` @@ -828,7 +796,7 @@ less than or equal to 100'`. We can see the panic message that we did get, which in this case was `Guess value must be greater than or equal to 1, got 200.` We could then start figuring out where our bug was! -Now that we've gone over ways to write tests, let's look at what is happening +Now that we’ve gone over ways to write tests, let’s look at what is happening when we run our tests and talk about the different options we can use with `cargo test`. @@ -853,10 +821,6 @@ separator `--`. ### Running Tests in Parallel or Consecutively - - - When multiple tests are run, by default they run in parallel using threads. This means the tests will finish running faster, so that we can get faster feedback on whether or not our code is working. Since the tests are running at @@ -868,13 +832,13 @@ For example, say each of your tests runs some code that creates a file on disk named `test-output.txt` and writes some data to that file. Then each test reads the data in that file and asserts that the file contains a particular value, which is different in each test. Because the tests are all run at the same -time, one test might overrwrite the file between when another test writes and +time, one test might overwrite the file between when another test writes and reads the file. The second test will then fail, not because the code is incorrect, but because the tests have interfered with each other while running in parallel. One solution would be to make sure each test writes to a different file; another solution is to run the tests one at a time. -If you don't want to run the tests in parallel, or if you want more +If you don’t want to run the tests in parallel, or if you want more fine-grained control over the number of threads used, you can send the `--test-threads` flag and the number of threads you want to use to the test binary. For example: @@ -885,14 +849,14 @@ $ cargo test -- --test-threads=1 We set the number of test threads to 1, telling the program not to use any parallelism. This will take longer than running them in parallel, but the tests -won't be potentially interfering with each other if they share state. +won’t be potentially interfering with each other if they share state. ### Showing Function Output -By default, if a test passes, Rust's test library captures anything printed to +By default, if a test passes, Rust’s test library captures anything printed to standard output. For example, if we call `println!` in a test and the test -passes, we won't see the `println!` output in the terminal: we'll only see the -line that says the test passed. If a test fails, we'll see whatever was printed +passes, we won’t see the `println!` output in the terminal: we’ll only see the +line that says the test passed. If a test fails, we’ll see whatever was printed to standard output with the rest of the failure message. For example, Listing 11-10 has a silly function that prints out the value of @@ -927,7 +891,7 @@ mod tests { Listing 11-10: Tests for a function that calls `println!` -The output we'll see when we run these tests with `cargo test` is: +The output we’ll see when we run these tests with `cargo test` is: ``` running 2 tests @@ -988,12 +952,12 @@ function and see what the output looks like then! ### Running a Subset of Tests by Name -Sometimes, running a full test suite can take a long time. If you're working on +Sometimes, running a full test suite can take a long time. If you’re working on code in a particular area, you might want to run only the tests pertaining to that code. You can choose which tests to run by passing `cargo test` the name or names of the test/s you want to run as an argument. -To demonstrate how to run a subset of tests, we'll create three tests for our +To demonstrate how to run a subset of tests, we’ll create three tests for our `add_two` function as shown in Listing 11-11 and choose which ones to run: Filename: src/lib.rs @@ -1026,7 +990,7 @@ mod tests { Listing 11-11: Three tests with a variety of names -If we run the tests without passing any arguments, as we've already seen, all +If we run the tests without passing any arguments, as we’ve already seen, all the tests will run in parallel: ``` @@ -1044,7 +1008,7 @@ We can pass the name of any test function to `cargo test` to run only that test: ``` $ cargo test one_hundred - Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs + Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs Running target/debug/deps/adder-06a75b4a1f2515e9 running 1 test @@ -1053,18 +1017,18 @@ test tests::one_hundred ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured ``` -We can't specify the names of multiple tests in this way, only the first value +We can’t specify the names of multiple tests in this way, only the first value given to `cargo test` will be used. #### Filtering to Run Multiple Tests However, we can specify part of a test name, and any test whose name matches -that value will get run. For example, since two of our tests' names contain +that value will get run. For example, since two of our tests’ names contain `add`, we can run those two by running `cargo test add`: ``` $ cargo test add - Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs + Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs Running target/debug/deps/adder-06a75b4a1f2515e9 running 2 tests @@ -1075,16 +1039,8 @@ test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured ``` This ran all tests with `add` in the name. Also note that the module in which -tests appear becomes part of the test's name, so we can run all the tests in a -module by filtering on the module's name. - - - +tests appear becomes part of the test’s name, so we can run all the tests in a +module by filtering on the module’s name. ### Ignore Some Tests Unless Specifically Requested @@ -1109,13 +1065,13 @@ fn expensive_test() { ``` We add the `#[ignore]` line to the test we want to exclude, after `#[test]`. -Now if we run our tests, we'll see `it_works` runs, but `expensive_test` does +Now if we run our tests, we’ll see `it_works` runs, but `expensive_test` does not: ``` $ cargo test Compiling adder v0.1.0 (file:///projects/adder) - Finished debug [unoptimized + debuginfo] target(s) in 0.24 secs + Finished dev [unoptimized + debuginfo] target(s) in 0.24 secs Running target/debug/deps/adder-ce99bcc2479f4607 running 2 tests @@ -1134,20 +1090,9 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured `expensive_test` is listed as `ignored`. If we want to run only the ignored tests, we can ask for them to be run with `cargo test -- --ignored`: - - - - - - ``` $ cargo test -- --ignored - Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs + Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs Running target/debug/deps/adder-ce99bcc2479f4607 running 1 test @@ -1157,7 +1102,7 @@ test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured ``` By controlling which tests run, you can make sure your `cargo test` results -will be fast. When you're at a point that it makes sense to check the results +will be fast. When you’re at a point that it makes sense to check the results of the `ignored` tests and you have time to wait for the results, you can choose to run `cargo test -- --ignored` instead. @@ -1180,7 +1125,7 @@ doing what you expect them to separately and together. The purpose of unit tests is to test each unit of code in isolation from the rest of the code, in order to be able to quickly pinpoint where code is and is not working as expected. We put unit tests in the *src* directory, in each file -with the code that they're testing. The convention is that we create a module +with the code that they’re testing. The convention is that we create a module named `tests` in each file to contain the test functions, and we annotate the module with `cfg(test)`. @@ -1189,8 +1134,8 @@ module with `cfg(test)`. The `#[cfg(test)]` annotation on the tests module tells Rust to compile and run the test code only when we run `cargo test`, and not when we run `cargo build`. This saves compile time when we only want to build the library, and saves space -in the resulting compiled artifact since the tests are not included. We'll see -that since integration tests go in a different directory, they don't need the +in the resulting compiled artifact since the tests are not included. We’ll see +that since integration tests go in a different directory, they don’t need the `#[cfg(test)]` annotation. Because unit tests go in the same files as the code, though, we use `#[cfg(test)]`to specify that they should not be included in the compiled result. @@ -1210,19 +1155,19 @@ mod tests { ``` This is the automatically generated test module. The attribute `cfg` stands for -*configruation*, and tells Rust that the following item should only be included -given a certain configuration. In this case, the configuration is `test`, -provided by Rust for compiling and running tests. By using this attribute, -Cargo only compiles our test code if we actively run the tests with `cargo -test`. This includes any helper functions that might be within this module, in -addition to the functions annotated with `#[test]`. +*configuration*, and tells Rust that the following item should only be included +given a certain configuration option. In this case, the configuration option is +`test`, provided by Rust for compiling and running tests. By using this +attribute, Cargo only compiles our test code if we actively run the tests with +`cargo test`. This includes any helper functions that might be within this +module, in addition to the functions annotated with `#[test]`. #### Testing Private Functions -There's debate within the testing community about whether private functions +There’s debate within the testing community about whether private functions should be tested directly or not, and other languages make it difficult or impossible to test private functions. Regardless of which testing ideology you -adhere to, Rust's privacy rules do allow you to test private functions. +adhere to, Rust’s privacy rules do allow you to test private functions. Consider the code in Listing 11-12 with the private function `internal_adder`: Filename: src/lib.rs @@ -1249,25 +1194,17 @@ mod tests { Listing 11-12: Testing a private function - - - Note that the `internal_adder` function is not marked as `pub`, but because tests are just Rust code and the `tests` module is just another module, we can -import and call `internal_adder` in a test just fine. If you don't think -private functions should be tested, there's nothing in Rust that will compel +import and call `internal_adder` in a test just fine. If you don’t think +private functions should be tested, there’s nothing in Rust that will compel you to do so. ### Integration Tests In Rust, integration tests are entirely external to your library. They use your library in the same way any other code would, which means they can only call -functions that are part of your library's public API. Their purpose is to test +functions that are part of your library’s public API. Their purpose is to test that many parts of your library work correctly together. Units of code that work correctly by themselves could have problems when integrated, so test coverage of the integrated code is important as well. To create integration @@ -1278,10 +1215,10 @@ tests, you first need a *tests* directory. To write integration tests for our code, we need to make a *tests* directory at the top level of our project directory, next to *src*. Cargo knows to look for integration test files in this directory. We can then make as many test files -as we'd like in this directory, and Cargo will compile each of the files as an +as we’d like in this directory, and Cargo will compile each of the files as an individual crate. -Let's give it a try! Keep the code from Listing 11-12 in *src/lib.rs*. Make a +Let’s give it a try! Keep the code from Listing 11-12 in *src/lib.rs*. Make a *tests* directory, then make a new file named *tests/integration_test.rs*, and enter the code in Listing 11-13. @@ -1298,21 +1235,21 @@ fn it_adds_two() { Listing 11-13: An integration test of a function in the `adder` crate -We've added `extern crate adder` at the top, which we didn't need in the unit +We’ve added `extern crate adder` at the top, which we didn’t need in the unit tests. This is because each test in the `tests` directory is an entirely separate crate, so we need to import our library into each of them. Integration tests use the library like any other consumer of it would, by importing the crate and using only the public API. -We don't need to annotate any code in *tests/integration_test.rs* with +We don’t need to annotate any code in *tests/integration_test.rs* with `#[cfg(test)]`. Cargo treats the `tests` directory specially and will only -compile files in this directory if we run `cargo test`. Let's try running +compile files in this directory if we run `cargo test`. Let’s try running `cargo test` now: ``` cargo test Compiling adder v0.1.0 (file:///projects/adder) - Finished debug [unoptimized + debuginfo] target(s) in 0.31 secs + Finished dev [unoptimized + debuginfo] target(s) in 0.31 secs Running target/debug/deps/adder-abcabcabc running 1 test @@ -1334,11 +1271,6 @@ running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ``` - - - Now we have three sections of output: the unit tests, the integration test, and the doc tests. The first section for the unit tests is the same as we have been seeing: one line for each unit test (we have one named `internal` that we added @@ -1346,7 +1278,7 @@ in Listing 11-12), then a summary line for the unit tests. The integration tests section starts with the line that says `Running target/debug/deps/integration-test-ce99bcc2479f4607` (the hash at the end of -your output will be different). Then there's a line for each test function in +your output will be different). Then there’s a line for each test function in that integration test, and a summary line for the results of the integration test just before the `Doc-tests adder` section starts. @@ -1357,13 +1289,13 @@ section. Each integration test file gets its own section, so if we add more files in the *tests* directory, there will be more integration test sections. We can still run a particular integration test function by specifying the test -function's name as an argument to `cargo test`. To run all of the tests in a +function’s name as an argument to `cargo test`. To run all of the tests in a particular integration test file, use the `--test` argument of `cargo test` followed by the name of the file: ``` $ cargo test --test integration_test - Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs + Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs Running target/debug/integration_test-952a27e0126bb565 running 1 test @@ -1378,12 +1310,12 @@ This tests only the file that we specified from the *tests* directory. As you add more integration tests, you may want to make more than one file in the *tests* directory to help organize them; for example, to group the test -functions by the functionality they're testing. As we mentioned, each file in +functions by the functionality they’re testing. As we mentioned, each file in the *tests* directory is compiled as its own separate crate. Treating each integration test file as its own crate is useful to create separate scopes that are more like the way end users will be using your crate. -However, this means files in the *tests* directory don't share the same +However, this means files in the *tests* directory don’t share the same behavior as files in *src* do that we learned about in Chapter 7 regarding how to separate code into modules and files. @@ -1403,8 +1335,8 @@ pub fn setup() { } ``` -If we run the tests again, we'll see a new section in the test output for the -*common.rs* file, even though this file doesn't contain any test functions, nor +If we run the tests again, we’ll see a new section in the test output for the +*common.rs* file, even though this file doesn’t contain any test functions, nor are we calling the `setup` function from anywhere: ``` @@ -1433,23 +1365,20 @@ running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ``` - - Having `common` show up in the test results with `running 0 tests` displayed for it is not what we wanted; we just wanted to be able to share some code with the other integration test files. In order to not have `common` show up in the test output, we need to use the other method of extracting code into a file that we learned about in Chapter 7: -instead of creating *tests/common.rs*, we'll create *tests/common/mod.rs*. When +instead of creating *tests/common.rs*, we’ll create *tests/common/mod.rs*. When we move the `setup` function code into *tests/common/mod.rs* and get rid of the *tests/common.rs* file, the section in the test output will no longer show up. Files in subdirectories of the *tests* directory do not get compiled as separate crates or have sections in the test output. Once we have *tests/common/mod.rs*, we can use it from any of the integration -test files as a module. Here's an example of calling the `setup` function from +test files as a module. Here’s an example of calling the `setup` function from the `it_adds_two` test in *tests/integration_test.rs*: Filename: tests/integration_test.rs @@ -1473,7 +1402,7 @@ function. #### Integration Tests for Binary Crates If our project is a binary crate that only contains a *src/main.rs* and does -not have a *src/lib.rs*, we aren't able to create integration tests in the +not have a *src/lib.rs*, we aren’t able to create integration tests in the *tests* directory and use `extern crate` to import functions defined in *src/main.rs*. Only library crates expose functions that other crates are able to call and use; binary crates are meant to be run on their own. @@ -1487,14 +1416,14 @@ small amount of code does not need to be tested. ## Summary -Rust's testing features provide a way to specify how code should function to +Rust’s testing features provide a way to specify how code should function to ensure it continues to work as we expect even as we make changes. Unit tests exercise different parts of a library separately and can test private implementation details. Integration tests cover the use of many parts of the -library working together, and they use the library's public API to test the -code in the same way external code will use it. Even though Rust's type system +library working together, and they use the library’s public API to test the +code in the same way external code will use it. Even though Rust’s type system and ownership rules help prevent some kinds of bugs, tests are still important to help reduce logic bugs having to do with how your code is expected to behave. -Let's put together the knowledge from this chapter and other previous chapters +Let’s put together the knowledge from this chapter and other previous chapters and work on a project in the next chapter! diff --git a/src/doc/book/second-edition/nostarch/chapter12.md b/src/doc/book/second-edition/nostarch/chapter12.md index ec789020ea..7ca8e763d4 100644 --- a/src/doc/book/second-edition/nostarch/chapter12.md +++ b/src/doc/book/second-edition/nostarch/chapter12.md @@ -1,73 +1,60 @@ [TOC] -# An I/O Project Building a Small Grep - - - - - -This chapter is both a recap of the many skills you've learned so far and an -exploration of a few more standard library features. We're going to build a -command-line tool that interacts with file and command line input/output to +# An I/O Project: Building a Command Line Program + +This chapter is both a recap of the many skills you’ve learned so far and an +exploration of a few more standard library features. We’re going to build a +command line tool that interacts with file and command line input/output to practice some of the Rust you now have under your belt. -Rust's speed, safety, 'single binary' output, and cross-platform support make -it a good language for creating command line tools, so for our project we'll +Rust’s speed, safety, *single binary* output, and cross-platform support make +it a good language for creating command line tools, so for our project we’ll make our own version of the classic command line tool `grep`. Grep is an -acronym for "Globally search a Regular Expression and Print." In the simplest -use case, `grep` searches a specified file for a specified string using the -following steps: - -- Take as arguments a filename and a string. -- Read the file. -- Find lines in the file that contain the string argument. -- Print out those lines. - -We'll also show how to use environment variables and print to standard error -instead of standard out; these techniques are commonly used in command line -tools. +acronym for “Globally search a Regular Expression and Print.” In the simplest +use case, `grep` searches a specified file for a specified string. To do so, +`grep` takes a filename and a string as its arguments, then reads the file and +finds lines in that file that contain the string argument. It’ll then print out +those lines. + +Along the way, we’ll show how to make our command line tool use features of the +terminal that many command line tools use. We'll read the value of an +environment variable in order to allow the user to configure the behavior of +our tool. We'll print to the standard error console stream (`stderr`) instead +of standard output (`stdout`) so that, for example, the user can choose to +redirect successful output to a file while still seeing error messages on the +screen. One Rust community member, Andrew Gallant, has already created a fully-featured, very fast version of `grep`, called `ripgrep`. By comparison, -our version of `grep` will be fairly simple, this chapter will give you some of -the background knowledge to help you understand a real-world project like -`ripgrep`. +our version of `grep` will be fairly simple, but this chapter will give you +some of the background knowledge to help you understand a real-world project +like `ripgrep`. -This project will bring together a number of concepts you've learned so far: +This project will bring together a number of concepts you’ve learned so far: -- Organizing code (using what we learned in modules, Chapter 7) -- Using vectors and strings (collections, Chapter 8) -- Handling errors (Chapter 9) -- Using traits and lifetimes where appropriate (Chapter 10) -- Writing tests (Chapter 11) +* Organizing code (using what we learned in modules, Chapter 7) +* Using vectors and strings (collections, Chapter 8) +* Handling errors (Chapter 9) +* Using traits and lifetimes where appropriate (Chapter 10) +* Writing tests (Chapter 11) -We'll also briefly introduce closures, iterators, and trait objects, which +We’ll also briefly introduce closures, iterators, and trait objects, which Chapters 13 and 17 will cover in detail. -Let's create a new project with, as always, `cargo new`. We're calling our -project `greprs` to distinguish from the `grep` tool that you may already have -on your system: +Let’s create a new project with, as always, `cargo new`. We’re calling our +project `minigrep` to distinguish from the `grep` tool that you may already +have on your system: ``` -$ cargo new --bin greprs - Created binary (application) `greprs` project -$ cd greprs +$ cargo new --bin minigrep + Created binary (application) `minigrep` project +$ cd minigrep ``` ## Accepting Command Line Arguments -Our first task is to make `greprs` able to accept its two command line +Our first task is to make `minigrep` able to accept its two command line arguments: the filename and a string to search for. That is, we want to be able to run our program with `cargo run`, a string to search for, and a path to a file to search in, like so: @@ -76,40 +63,26 @@ file to search in, like so: $ cargo run searchstring example-filename.txt ``` -Right now, the program generated by `cargo new` ignores any arguments we give -it. There are some existing libraries on crates.io that can help us accept -command line arguments, but since we're learning, let's implement this +Right now, the program generated by `cargo new` cannot process arguments we +give it. There are some existing libraries on crates.io that can help us accept +command line arguments, but since you’re learning, let’s implement this ourselves. - - - ### Reading the Argument Values -In order to be able to get the values of command line arguments passed to our -program, we'll need to call a function provided in Rust's standard library: -`std::env::args`. This function returns an *iterator* of the command line -arguments that were given to our program. We haven't discussed iterators yet, -and we'll cover them fully in Chapter 13, but for our purposes now we only need -to know two things about iterators: - -1. Iterators produce a series of values. -2. We can call the `collect` function on an iterator to turn it into a vector - containing all of the elements the iterator produces. +We first need to make sure our program is able to get the values of command +line arguments we pass to it, for which we’ll need a function provided in +Rust’s standard library: `std::env::args`. This function returns an *iterator* +of the command line arguments that were given to our program. We haven’t +discussed iterators yet, and we’ll cover them fully in Chapter 13, but for our +purposes now we only need to know two things about iterators: Iterators produce +a series of values, and we can call the `collect` function on an iterator to +turn it into a collection, such as a vector, containing all of the elements the +iterator produces. -Let's give it a try: use the code in Listing 12-1 to read any command line -arguments passed to our `greprs` program and collect them into a vector. - - - +Let’s give it a try: use the code in Listing 12-1 to allow your `minigrep` +program to read any command line arguments passed it and then collect the +values into a vector. Filename: src/main.rs @@ -125,82 +98,59 @@ fn main() { Listing 12-1: Collect the command line arguments into a vector and print them out - - First, we bring the `std::env` module into scope with a `use` statement so that we can use its `args` function. Notice the `std::env::args` function is nested in two levels of modules. As we talked about in Chapter 7, in cases where the -desired function is nested in more than one module, it's conventional to bring +desired function is nested in more than one module, it’s conventional to bring the parent module into scope, rather than the function itself. This lets us -easily use other functions from `std::env`. It's also less ambiguous than +easily use other functions from `std::env`. It’s also less ambiguous than adding `use std::env::args;` then calling the function with just `args`; that -might look like a function that's defined in the current module. - - - - +might easily be mistaken for a function that’s defined in the current module. -> Note: `std::env::args` will panic if any argument contains invalid Unicode. -> If you need to accept arguments containing invalid Unicode, use +> ### The `args` Function and Invalid Unicode +> +> Note that `std::env::args` will panic if any argument contains invalid +> Unicode. If you need to accept arguments containing invalid Unicode, use > `std::env::args_os` instead. That function returns `OsString` values instead -> of `String` values. We've chosen to use `std::env::args` here for simplicity +> of `String` values. We’ve chosen to use `std::env::args` here for simplicity > because `OsString` values differ per-platform and are more complex to work > with than `String` values. - - - - - On the first line of `main`, we call `env::args`, and immediately use `collect` -to turn the iterator into a vector containing all of the iterator's values. The -`collect` function can be used to create many kinds of collections, so we -explicitly annotate the type of `args` to specify that we want a vector of -strings. Though we very rarely need to annotate types in Rust, `collect` is one -function you do often need to annotate because Rust isn't able to infer what -kind of collection you want. - -Finally, we print out the vector with the debug formatter, `:?`. Let's try +to turn the iterator into a vector containing all of the values produced by the +iterator. The `collect` function can be used to create many kinds of +collections, so we explicitly annotate the type of `args` to specify that we +want a vector of strings. Though we very rarely need to annotate types in Rust, +`collect` is one function you do often need to annotate because Rust isn’t able +to infer what kind of collection you want. + +Finally, we print out the vector with the debug formatter, `:?`. Let’s try running our code with no arguments, and then with two arguments: ``` $ cargo run -["target/debug/greprs"] +["target/debug/minigrep"] $ cargo run needle haystack ...snip... -["target/debug/greprs", "needle", "haystack"] +["target/debug/minigrep", "needle", "haystack"] ``` - - - -You may notice that the first value in the vector is "target/debug/greprs", -which is the name of our binary. The reasons for this are out of the scope of -this chapter, but we'll need to remember this as we save the two arguments we -need. +You may notice that the first value in the vector is `"target/debug/minigrep"`, +which is the name of our binary. This matches the behavior of the arguments +list in C, and lets programs use the name by which they were invoked in their +execution. It's convenient to have access to the program name in case we want +to print it in messages or change behavior of the program based on what command +line alias was used to invoke the program, but for the purposes of this chapter +we're going to ignore it and only save the two arguments we need. ### Saving the Argument Values in Variables -Printing out the value of the vector of arguments just illustrated that we're -able to access the values specified as command line arguments from our program. -That's not what we actually want to do, though, we want to save the values of -the two arguments in variables so that we can use the values in our program. -Let's do that as shown in Listing 12-2: - - - +Printing out the value of the vector of arguments has illustrated that the +program is able to access the values specified as command line arguments. +That’s not actually our end goal, though: we want to save the values of the two +arguments in variables so that we can use the values in our program. Let’s do +that as shown in Listing 12-2: Filename: src/main.rs @@ -220,48 +170,48 @@ fn main() { Listing 12-2: Create variables to hold the query argument and filename argument - - -As we saw when we printed out the vector, the program's name takes up the first -value in the vector at `args[0]`, so we're starting at index `1`. The first -argument `greprs` takes is the string we're searching for, so we put a +As we saw when we printed out the vector, the program’s name takes up the first +value in the vector at `args[0]`, so that we’re starting at index `1`. The +first argument `minigrep` takes is the string we’re searching for, so we put a reference to the first argument in the variable `query`. The second argument will be the filename, so we put a reference to the second argument in the variable `filename`. -We're temporarily printing out the values of these variables, again to prove to -ourselves that our code is working as we intend. Let's try running this program +We’re temporarily printing out the values of these variables, again to prove to +ourselves that our code is working as we intend. Let’s try running this program again with the arguments `test` and `sample.txt`: ``` $ cargo run test sample.txt - Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs - Running `target/debug/greprs test sample.txt` + Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs + Running `target/debug/minigrep test sample.txt` Searching for test In file sample.txt ``` -Great, it's working! We're saving the values of the arguments that we need into -the right variables. Later we'll add some error handling to deal with -situations such as when the user provides no arguments, but for now we'll -ignore that and work on adding file reading capabilities instead. +Great, it’s working! The values of the arguments we need are being saved into +the right variables. Later we’ll add some error handling to deal with certain +potential erroneous situations, such as when the user provides no arguments, +but for now we’ll ignore that and work on adding file reading capabilities +instead. ## Reading a File -Next, we're going to read the file that we specify in the filename command line -argument. First, we need a sample file to test it with---the best kind of file -to use to make sure that `greprs` is working is one with a small amount of text -over multiple lines with some repeated words. Listing 12-3 has an Emily -Dickinson poem that will work well! Create a file called `poem.txt` at the root -level of your project, and enter the poem "I'm nobody! Who are you?": +Next, we’re going to add functionality to read the file that specified in the +`filename` command line argument. First, we need a sample file to test it +with—the best kind of file to use to make sure that `minigrep` is working is +one with a small amount of text over multiple lines with some repeated words. +Listing 12-3 has an Emily Dickinson poem that will work well! Create a file +called `poem.txt` at the root level of your project, and enter the poem “I’m +nobody! Who are you?”: Filename: poem.txt ``` -I'm nobody! Who are you? +I’m nobody! Who are you? Are you nobody, too? -Then there's a pair of us — don't tell! -They'd banish us, you know. +Then there’s a pair of us — don’t tell! +They’d banish us, you know. How dreary to be somebody! How public, like a frog @@ -269,16 +219,9 @@ To tell your name the livelong day To an admiring bog! ``` -Listing 12-3: The poem "I'm nobody! Who are you?" by Emily Dickinson that will +Listing 12-3: The poem “I’m nobody! Who are you?” by Emily Dickinson that will make a good test case - - - - With that in place, edit *src/main.rs* and add code to open the file as shown in Listing 12-4: @@ -290,18 +233,13 @@ use std::fs::File; use std::io::prelude::*; fn main() { - let args: Vec = env::args().collect(); - - let query = &args[1]; - let filename = &args[2]; - - println!("Searching for {}", query); + // ...snip... println!("In file {}", filename); - let mut f = File::open(filename).expect("file not found"); let mut contents = String::new(); - f.read_to_string(&mut contents).expect("something went wrong reading the file"); + f.read_to_string(&mut contents) + .expect("something went wrong reading the file"); println!("With text:\n{}", contents); } @@ -309,42 +247,40 @@ fn main() { Listing 12-4: Reading the contents of the file specified by the second argument - - First, we add some more `use` statements to bring in relevant parts of the standard library: we need `std::fs::File` for dealing with files, and `std::io::prelude::*` contains various traits that are useful when doing I/O, including file I/O. In the same way that Rust has a general prelude that brings certain things into scope automatically, the `std::io` module has its own -prelude of common things you'll need when working with I/O. Unlike the default -prelude, we must explicitly `use` the prelude in `std::io`. +prelude of common things you’ll need when working with I/O. Unlike the default +prelude, we must explicitly `use` the prelude from `std::io`. -In `main`, we've added three things: first, we get a mutable handle to the file +In `main`, we’ve added three things: first, we get a mutable handle to the file by calling the `File::open` function and passing it the value of the `filename` variable. Second, we create a variable called `contents` and set it to a mutable, empty `String`. This will hold the content of the file after we read it in. Third, we call `read_to_string` on our file handle and pass a mutable reference to `contents` as an argument. -After those lines, we've again added temporary `println!` that prints out the -value in `contents` after we've read the file so we can check that our program -is working so far. +After those lines, we’ve again added a temporary `println!` statement that +prints out the value of `contents` after the file is read, so that we can check +that our program is working so far. -Let's try running this code with any string as the first command line argument -(since we haven't implemented the searching part yet) and our *poem.txt* file +Let’s try running this code with any string as the first command line argument +(since we haven’t implemented the searching part yet) and our *poem.txt* file as the second argument: ``` $ cargo run the poem.txt - Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs - Running `target/debug/greprs the poem.txt` + Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs + Running `target/debug/minigrep the poem.txt` Searching for the In file poem.txt With text: -I'm nobody! Who are you? +I’m nobody! Who are you? Are you nobody, too? -Then there's a pair of us — don't tell! -They'd banish us, you know. +Then there’s a pair of us — don’t tell! +They’d banish us, you know. How dreary to be somebody! How public, like a frog @@ -352,89 +288,86 @@ To tell your name the livelong day To an admiring bog! ``` -Great! Our code read in and printed out the content of the file. We've got a -few flaws though: the `main` function has multiple responsibilities, and we're -not handling errors as well as we could be. While our program is still small, -these flaws aren't a big problem, but as our program grows, it will be harder -to fix them cleanly. It's good practice to begin refactoring early on when -developing a program, as it's much easier to refactor smaller amounts of code, -so we'll do that now. +Great! Our code read in and printed out the content of the file. We’ve got a +few flaws though. The `main` function has multiple responsibilities; generally +functions are clearer and easier to maintain if each function is responsible +for only one idea. The other problem is that we’re not handling errors as well +as we could be. While our program is still small, these flaws aren’t a big +problem, but as our program grows, it will be harder to fix them cleanly. It’s +good practice to begin refactoring early on when developing a program, as it’s +much easier to refactor smaller amounts of code, so we’ll do that now. ## Refactoring to Improve Modularity and Error Handling -There are four problems that we'd like to fix to improve our program, and they -have to do with the way the program is structured and how it's handling +There are four problems that we’d like to fix to improve our program, and they +have to do with the way the program is structured and how it’s handling potential errors. First, our `main` function now performs two tasks: it parses arguments and -opens up files. For such a small function, this isn't a huge problem. However, +opens up files. For such a small function, this isn’t a huge problem. However, if we keep growing our program inside of `main`, the number of separate tasks the `main` function handles will grow. As a function gains responsibilities, it gets harder to reason about, harder to test, and harder to change without -breaking one of its parts. It's better to separate out functionality so that +breaking one of its parts. It’s better to separate out functionality so that each function is responsible for one task. This also ties into our second problem: while `query` and `filename` are configuration variables to our program, variables like `f` and `contents` are -used to perform our program's logic. The longer `main` gets, the more variables -we're going to need to bring into scope; the more variables we have in scope, -the harder it is to keep track of the purpose of each. It's better to group the +used to perform our program’s logic. The longer `main` gets, the more variables +we’re going to need to bring into scope; the more variables we have in scope, +the harder it is to keep track of the purpose of each. It’s better to group the configuration variables into one structure to make their purpose clear. -The third problem is that we've used `expect` to print out an error message if -opening the file fails, but the error message only says `file not found`. There -are a number of ways that opening a file can fail besides a missing file: for -example, the file might exist, but we might not have permission to open it. -Right now, if we're in that situation, we'd print the `file not found` error -message that would give the user the wrong advice! +The third problem is that we’ve used `expect` to print out an error message +when opening the file fails, but the error message only says `file not found`. +There are a number of ways that opening a file can fail besides the file being +missing: for example, the file might exist, but we might not have permission to +open it. Right now, if we’re in that situation, we’d print the `file not found` +error message that would give the user the wrong advice! Fourth, we use `expect` repeatedly to deal with different errors, and if the -user runs our programs without specifying enough arguments, they'll get an -"index out of bounds" error from Rust that doesn't clearly explain the problem. +user runs our programs without specifying enough arguments, they’ll get an +“index out of bounds” error from Rust that doesn’t clearly explain the problem. It would be better if all our error handling code was in one place so that future maintainers only have one place to consult in the code if the error handling logic needs to change. Having all the error handling code in one place -will also help us to ensure that we're printing messages that will be +will also help us to ensure that we’re printing messages that will be meaningful to our end users. -Let's address these problems by refactoring our project. +Let’s address these problems by refactoring our project. ### Separation of Concerns for Binary Projects -The organizational problem of having the `main` function responsible for -multiple tasks is common to many binary projects, so the Rust community has -developed a kind of guideline process for splitting up the separate concerns of -a binary program when `main` starts getting large. The process has the -following steps: - -1. Split your program into both a *main.rs* and a *lib.rs* and move your - program's logic into *lib.rs*. -2. While your command line parsing logic is small, it can remain in *main.rs*. -3. When the command line parsing logic starts getting complicated, extract it - from *main.rs* into *lib.rs* as well. -4. The responsibilities that remain in the `main` function after this process - should be: - * Calling the command line parsing logic with the argument values - * Setting up any other configuration - * Calling a `run` function in *lib.rs* - * If `run` returns an error, handling that error +The organizational problem of allocating responsibility for multiple tasks to +the `main` function responsible is common to many binary projects, so the Rust +community has developed a kind of guideline process for splitting up the +separate concerns of a binary program when `main` starts getting large. The +process has the following steps: + +* Split your program into both a *main.rs* and a *lib.rs* and move your +program’s logic into *lib.rs*. +* While your command line parsing logic is small, it can remain in *main.rs*. +* When the command line parsing logic starts getting complicated, extract it +from *main.rs* into *lib.rs* as well. +* The responsibilities that remain in the `main` function after this process +should be limited to: + * Calling the command line parsing logic with the argument values + * Setting up any other configuration + * Calling a `run` function in *lib.rs* + * If `run` returns an error, handling that error This pattern is all about separating concerns: *main.rs* handles running the program, and *lib.rs* handles all of the logic of the task at hand. Because we -can't test the `main` function directly, this structure lets us test all of our -program's logic by moving it into functions in *lib.rs*. The only code that +can’t test the `main` function directly, this structure lets us test all of our +program’s logic by moving it into functions in *lib.rs*. The only code that remains in *main.rs* will be small enough to verify its correctness by reading -it. Let's re-work our program by following this process. - - - +it. Let’s re-work our program by following this process. -### Extracting the Argument Parser +#### Extracting the Argument Parser -First, we'll extract the functionality for parsing arguments. Listing 12-5 +First, we’ll extract the functionality for parsing arguments. Listing 12-5 shows the new start of `main` that calls a new function `parse_config`, which -we're still going to define in *src/main.rs* for the moment: +we’re still going to define in *src/main.rs* for the moment: Filename: src/main.rs @@ -457,55 +390,42 @@ fn parse_config(args: &[String]) -> (&str, &str) { Listing 12-5: Extract a `parse_config` function from `main` - - -We're still collecting the command line arguments into a vector, but instead of -assigning the argument value at index 1 to the variable `query` and the -argument value at index 2 to the variable `filename` within the `main` +We’re still collecting the command line arguments into a vector, but instead of +assigning the argument value at index `1` to the variable `query` and the +argument value at index `2` to the variable `filename` within the `main` function, we pass the whole vector to the `parse_config` function. The -`parse_config` function then holds the logic that knows which argument goes in -which variable, and passes the values back to `main`. We still create the -`query` and `filename` variables in `main`, but `main` no longer has the -responsibility of knowing how the command line arguments and variables +`parse_config` function then holds the logic that determines which argument +goes in which variable, and passes the values back to `main`. We still create +the `query` and `filename` variables in `main`, but `main` no longer has the +responsibility of determining how the command line arguments and variables correspond. -This may seem like overkill for our small program, but we're refactoring in +This may seem like overkill for our small program, but we’re refactoring in small, incremental steps. After making this change, run the program again to -verify that the argument parsing still works. It's good to check your progress +verify that the argument parsing still works. It’s good to check your progress often, as that will help you identify the cause of problems when they occur. #### Grouping Configuration Values We can take another small step to improve this function further. At the moment, -we're returning a tuple, but then we immediately break that tuple up into -individual parts again. This is a sign that perhaps we don't have the right +we’re returning a tuple, but then we immediately break that tuple up into +individual parts again. This is a sign that perhaps we don’t have the right abstraction yet. -Another indicator that there's room for improvement is the `config` part of +Another indicator that there’s room for improvement is the `config` part of `parse_config`, which implies that the two values we return are related and are -both part of one configuration value. We're not currently conveying this +both part of one configuration value. We’re not currently conveying this meaning in the structure of the data other than grouping the two values into a tuple: we could put the two values into one struct and give each of the struct fields a meaningful name. This will make it easier for future maintainers of this code to understand how the different values relate to each other and what their purpose is. - - > Note: some people call this anti-pattern of using primitive values when a > complex type would be more appropriate *primitive obsession*. - - - Listing 12-6 shows the addition of a struct named `Config` defined to have -fields named `query` and `filename`. We've also changed the `parse_config` +fields named `query` and `filename`. We’ve also changed the `parse_config` function to return an instance of the `Config` struct, and updated `main` to use the struct fields rather than having separate variables: @@ -534,24 +454,19 @@ fn parse_config(args: &[String]) -> Config { let query = args[1].clone(); let filename = args[2].clone(); - Config { - query: query, - filename: filename, - } + Config { query, filename } } ``` Listing 12-6: Refactoring `parse_config` to return an instance of a `Config` struct - - The signature of `parse_config` now indicates that it returns a `Config` value. In the body of `parse_config`, where we used to return string slices that -reference `String` values in `args`, we've now chosen to define `Config` to +reference `String` values in `args`, we’ve now chosen to define `Config` to contain owned `String` values. The `args` variable in `main` is the owner of the argument values and is only letting the `parse_config` function borrow -them, though, which means we'd violate Rust's borrowing rules if `Config` tried +them, though, which means we’d violate Rust’s borrowing rules if `Config` tried to take ownership of the values in `args`. There are a number of different ways we could manage the `String` data, and the @@ -559,59 +474,39 @@ easiest, though somewhat inefficient, route is to call the `clone` method on the values. This will make a full copy of the data for the `Config` instance to own, which does take more time and memory than storing a reference to the string data. However, cloning the data also makes our code very straightforward -since we don't have to manage the lifetimes of the references, so in this +since we don’t have to manage the lifetimes of the references, so in this circumstance giving up a little performance to gain simplicity is a worthwhile trade-off. - - - - -> #### The Tradeoffs of Using `clone` +> ### The Tradeoffs of Using `clone` > -> There's a tendency amongst many Rustaceans to avoid using `clone` to fix +> There’s a tendency among many Rustaceans to avoid using `clone` to fix > ownership problems because of its runtime cost. In Chapter 13 on iterators, -> you'll learn how to use more efficient methods in this kind of situation, but -> for now, it's okay to copy a few strings to keep making progress since we'll +> you’ll learn how to use more efficient methods in this kind of situation, but +> for now, it’s okay to copy a few strings to keep making progress since we’ll > only make these copies once, and our filename and query string are both very -> small. It's better to have a working program that's a bit inefficient than -> try to hyper-optimize code on your first pass. As you get more experienced -> with Rust, it'll be easier to go straight to the desirable method, but for -> now it's perfectly acceptable to call `clone`. - - +> small. It’s better to have a working program that’s a bit inefficient than try +> to hyper-optimize code on your first pass. As you get more experienced with +> Rust, it’ll be easier to go straight to the desirable method, but for now it’s +> perfectly acceptable to call `clone`. -We've updated `main` so that it places the instance of `Config` that -`parse_config` returns into a variable named `config`, and updated the code -that previously used the separate `query` and `filename` variables so that is -now uses the fields on the `Config` struct instead. +We’ve updated `main` so that it places the instance of `Config` returned by +`parse_config` into a variable named `config`, and updated the code that +previously used the separate `query` and `filename` variables so that it now +uses the fields on the `Config` struct instead. -Our code now more clearly conveys our intent that `query` and `filename` are -related and their purpose is to configure how the program will work. Any code -that uses these values knows to find them in the `config` instance in the -fields named for their purpose. +Our code now more clearly conveys that `query` and `filename` are related and +their purpose is to configure how the program will work. Any code that uses +these values knows to find them in the `config` instance in the fields named +for their purpose. #### Creating a Constructor for `Config` - - - -So far, we've extracted the logic responsible for parsing the command line +So far, we’ve extracted the logic responsible for parsing the command line arguments from `main` into the `parse_config` function, which helped us to see that the `query` and `filename` values were related and that relationship should be conveyed in our code. We then added a `Config` struct to name the -related purpose of `query` and `filename`, and to be able to return the values' +related purpose of `query` and `filename`, and to be able to return the values’ names as struct field names from the `parse_config` function. So now that the purpose of the `parse_config` function is to create a `Config` @@ -619,9 +514,9 @@ instance, we can change `parse_config` from being a plain function into a function named `new` that is associated with the `Config` struct. Making this change will make our code more idiomatic: we can create instances of types in the standard library like `String` by calling `String::new`, and by changing -`parse_config` to be a `new` function associated with `Config`, we'll be able -to create instances of `Config` by calling `Config::new`. Listing 12-7 shows -the changes we'll need to make: +`parse_config` into a `new` function associated with `Config`, we’ll be able to +create instances of `Config` by calling `Config::new`. Listing 12-7 shows the +changes we’ll need to make: Filename: src/main.rs @@ -641,49 +536,44 @@ impl Config { let query = args[1].clone(); let filename = args[2].clone(); - Config { - query: query, - filename: filename, - } + Config { query, filename } } } ``` Listing 12-7: Changing `parse_config` into `Config::new` - - -We've updated `main` where we were calling `parse_config` to instead call -`Config::new`. We've changed the name of `parse_config` to `new` and moved it +We’ve updated `main` where we were calling `parse_config` to instead call +`Config::new`. We’ve changed the name of `parse_config` to `new` and moved it within an `impl` block, which makes the `new` function associated with `Config`. Try compiling this again to make sure it works. ### Fixing the Error Handling -Now we'll work on fixing our error handling. Recall that we mentioned -attempting to access the values in the `args` vector at index 1 or index 2 will -cause the program to panic if the vector contains fewer than 3 items. Try +Now we’ll work on fixing our error handling. Recall that we mentioned that +attempting to access the values in the `args` vector at index `1` or index `2` +will cause the program to panic if the vector contains fewer than 3 items. Try running the program without any arguments; it will look like this: ``` $ cargo run - Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs - Running `target/debug/greprs` + Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs + Running `target/debug/minigrep` thread 'main' panicked at 'index out of bounds: the len is 1 -but the index is 1', /stable-dist-rustc/build/src/libcollections/vec.rs:1307 +but the index is 1', /stable-dist-rustc/build/src/libcollections/vec.rs:1307 note: Run with `RUST_BACKTRACE=1` for a backtrace. ``` -`index out of bounds: the len is 1 but the index is 1` is an error message that -is intended for programmers, and won't really help our end users understand -what happened and what they should do instead. Let's fix that now. +The line that states `index out of bounds: the len is 1 but the index is 1` is +an error message intended for programmers, and won’t really help our end users +understand what happened and what they should do instead. Let’s fix that now. #### Improving the Error Message -In Listing 12-8, we're adding a check in the `new` function to check that the -slice is long enough before accessing index 1 and 2. If the slice isn't long -enough, we panic with a better error message than the `index out of bounds` -message: +In Listing 12-8, we’re adding a check in the `new` function that will check +that the slice is long enough before accessing index `1` and `2`. If the slice +isn’t long enough, the program panics, with a better error message than the +`index out of bounds` message: Filename: src/main.rs @@ -698,51 +588,45 @@ fn new(args: &[String]) -> Config { Listing 12-8: Adding a check for the number of arguments - - -This is similar to the `Guess::new` function we wrote in Listing 9-8, where we -called `panic!` if the `value` argument was out of the range of valid values. -Instead of checking for a range of values, we're checking that the length of -`args` is at least 3, and the rest of the function can operate under the -assumption that this condition has been met. If `args` has fewer than 3 items, -this condition will be true, and we call the `panic!` macro to end the program -immediately. +This is similar to the `Guess::new` function we wrote in Listing 9-8, where +`panic!` was called when the `value` argument was out of the range of valid +values. Instead of checking for a range of values here, we’re checking that the +length of `args` is at least 3, and the rest of the function can operate under +the assumption that this condition has been met. If `args` has fewer than 3 +items, this condition will be true, and we call the `panic!` macro to end the +program immediately. -With these extra few lines of code in `new`, let's try running our program +With these extra few lines of code in `new`, let’s try running our program without any arguments again and see what the error looks like now: ``` $ cargo run - Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs - Running `target/debug/greprs` + Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs + Running `target/debug/minigrep` thread 'main' panicked at 'not enough arguments', src/main.rs:29 note: Run with `RUST_BACKTRACE=1` for a backtrace. ``` This output is better, we now have a reasonable error message. However, we also -have a bunch of extra information we don't want to give to our users. So -perhaps using the technique we used in Listing 9-8 isn't the best to use here; +have a bunch of extra information we don’t want to give to our users. So +perhaps using the technique we used in Listing 9-8 isn’t the best to use here; a call to `panic!` is more appropriate for a programming problem rather than a -usage problem anyway, as we discussed in Chapter 9. Instead, we can use the -other technique we learned about in that chapter: returning a `Result` that can +usage problem, as we discussed in Chapter 9. Instead, we can use the other +technique you also learned about in Chapter 9: returning a `Result` that can indicate either success or an error. - - - #### Returning a `Result` from `new` Instead of Calling `panic!` We can choose to instead return a `Result` value that will contain a `Config` instance in the successful case, and will describe the problem in the error -case. When `Config::new` is communicating to `main`, we can use Rust's way of -signaling that there was a problem using the `Result` type. Then we can change -`main` to convert an `Err` variant into a nicer error for our users, without -the surrounding text about `thread 'main'` and `RUST_BACKTRACE` that a call to +case. When `Config::new` is communicating to `main`, we can use the `Result` +type to signal that there was a problem. Then we can change `main` to convert +an `Err` variant into a more practical error for our users, without the +surrounding text about `thread 'main'` and `RUST_BACKTRACE` that a call to `panic!` causes. -Listing 12-9 shows the changes to the return value of `Config::new` and the -body of the function needed to return a `Result`: +Listing 12-9 shows the changes you need to make to the return value of +`Config::new` and the body of the function needed to return a `Result`: Filename: src/main.rs @@ -756,30 +640,21 @@ impl Config { let query = args[1].clone(); let filename = args[2].clone(); - Ok(Config { - query: query, - filename: filename, - }) + Ok(Config { query, filename }) } } ``` Listing 12-9: Return a `Result` from `Config::new` - - - - - Our `new` function now returns a `Result`, with a `Config` instance in the -success case and a `&'static str` in the error case. Recall from "The Static -Lifetime" section in Chapter 10 that `&'static str` is the type of string +success case and a `&'static str` in the error case. Recall from “The Static +Lifetime” section in Chapter 10 that `&'static str` is the type of string literals, which is our error message type for now. -We've made two changes in the body of the `new` function: instead of calling -`panic!` when the user doesn't pass enough arguments, we now return an `Err` -value, and we've wrapped the `Config` return value in an `Ok`. These changes +We’ve made two changes in the body of the `new` function: instead of calling +`panic!` when the user doesn’t pass enough arguments, we now return an `Err` +value, and we’ve wrapped the `Config` return value in an `Ok`. These changes make the function conform to its new type signature. By having `Config::new` return an `Err` value, it allows the `main` function to @@ -789,11 +664,11 @@ more cleanly in the error case. #### Calling `Config::new` and Handling Errors In order to handle the error case and print a user-friendly message, we need to -update `main` to handle the `Result` that `Config::new` is now returning as -shown in Listing 12-10. We're also going to implement by hand something that -`panic!` handled for us: exiting the command line tool with an error code of 1. -A nonzero exit status is a convention to signal to the process that called our -program that our program ended with an error state. +update `main` to handle the `Result` being returned by `Config::new`, as shown +in Listing 12-10. We’re also going to take the responsibility of exiting the +command line tool with a nonzero error code from `panic!` and implement it by +hand. A nonzero exit status is a convention to signal to the process that +called our program that our program ended with an error state. Filename: src/main.rs @@ -813,73 +688,49 @@ fn main() { Listing 12-10: Exiting with an error code if creating a new `Config` fails - - - - - - -In this listing, we're using a method we haven't covered before: +In this listing, we’re using a method we haven’t covered before: `unwrap_or_else`, which is defined on `Result` by the standard library. Using `unwrap_or_else` allows us to define some custom, non-`panic!` error -handling. If the `Result` is an `Ok` value, this method's behavior is similar +handling. If the `Result` is an `Ok` value, this method’s behavior is similar to `unwrap`: it returns the inner value `Ok` is wrapping. However, if the value is an `Err` value, this method calls the code in the *closure*, which is an -anonymous function we define and pass as an argument to `unwrap_or_else`. We'll +anonymous function we define and pass as an argument to `unwrap_or_else`. We’ll be covering closures in more detail in Chapter 13. What you need to know for now is that `unwrap_or_else` will pass the inner value of the `Err`, which in this case is the static string `not enough arguments` that we added in Listing 12-9, to our closure in the argument `err` that appears between the vertical pipes. The code in the closure can then use the `err` value when it runs. - - - -We've added a new `use` line to import `process` from the standard library. The +We’ve added a new `use` line to import `process` from the standard library. The code in the closure that will get run in the error case is only two lines: we -print out the `err` value, then call `std::process::exit` (we've added a new -`use` line at the top to import `process` from the standard library). -`process::exit` will stop the program immediately and return the number that -was passed as the exit status code. This is similar to the `panic!`-based -handling we used in Listing 12-8, with the exception that we no longer get all -the extra output. Let's try it: +print out the `err` value, then call `process::exit`. The `process::exit` +function will stop the program immediately and return the number that was +passed as the exit status code. This is similar to the `panic!`-based handling +we used in Listing 12-8, with the exception that we no longer get all the extra +output. Let’s try it: ``` $ cargo run - Compiling greprs v0.1.0 (file:///projects/greprs) - Finished debug [unoptimized + debuginfo] target(s) in 0.48 secs - Running `target/debug/greprs` + Compiling minigrep v0.1.0 (file:///projects/minigrep) + Finished dev [unoptimized + debuginfo] target(s) in 0.48 secs + Running `target/debug/minigrep` Problem parsing arguments: not enough arguments ``` Great! This output is much friendlier for our users. -### Extracting a `run` Function - -Now we're done refactoring our configuration parsing; let's turn to our -program's logic. As we laid out in the process we discussed in the "Separation -of Concerns for Binary Projects" section, we're going to extract a function -named `run` that will hold all of the logic currently in the `main` function -that isn't setting up configuration or handling errors. Once we're done, `main` -will be concise and easy to verify by inspection, and we'll be able to write -tests for all of the other logic. - - - - -Listing 12-11 shows the extracted `run` function. For now, we're making only -the small, incremental improvement of extracting the function and still +### Extracting Logic from `main` + +Now we’re done refactoring our configuration parsing; let’s turn to our +program’s logic. As we laid out in the “Separation of Concerns for Binary +Projects” section, we’re going to extract a function named `run` that will hold +all of the logic currently in the `main` function not involved with setting up +configuration or handling errors. Once we’re done, `main` will be concise and +easy to verify by inspection, and we’ll be able to write tests for all of the +other logic. + +Listing 12-11 shows the extracted `run` function. For now, we’re making only +the small, incremental improvement of extracting the function. We’re still defining the function in *src/main.rs*: Filename: src/main.rs @@ -898,7 +749,8 @@ fn run(config: Config) { let mut f = File::open(config.filename).expect("file not found"); let mut contents = String::new(); - f.read_to_string(&mut contents).expect("something went wrong reading the file"); + f.read_to_string(&mut contents) + .expect("something went wrong reading the file"); println!("With text:\n{}", contents); } @@ -909,21 +761,19 @@ fn run(config: Config) { Listing 12-11: Extracting a `run` function containing the rest of the program logic - - The `run` function now contains all the remaining logic from `main` starting from reading the file. The `run` function takes the `Config` instance as an argument. #### Returning Errors from the `run` Function -With the remaining program logic separated into the `run` function rather than -being in `main`, we can improve the error handling like we did with -`Config::new` in Listing 12-9. Instead of allowing the program to panic by -calling `expect`, the `run` function will return a `Result` when -something goes wrong. This will let us further consolidate the logic around -handling errors in a user-friendly way into `main`. Listing 12-12 shows the -changes to the signature and body of `run`: +With the remaining program logic separated into the `run` function, we can +improve the error handling like we did with `Config::new` in Listing 12-9. +Instead of allowing the program to panic by calling `expect`, the `run` +function will return a `Result` when something goes wrong. This will let +us further consolidate the logic around handling errors in a user-friendly way +into `main`. Listing 12-12 shows the changes you need to make to the signature +and body of `run`: Filename: src/main.rs @@ -946,39 +796,34 @@ fn run(config: Config) -> Result<(), Box> { Listing 12-12: Changing the `run` function to return `Result` - - -We've made three big changes here. First, we're changing the return type of the +We’ve made three big changes here. First, we’re changing the return type of the `run` function to `Result<(), Box>`. This function previously returned the unit type, `()`, and we keep that as the value returned in the `Ok` case. - - - -For our error type, we're using the *trait object* `Box` (and we've +For our error type, we’re using the *trait object* `Box` (and we’ve brought `std::error::Error` into scope with a `use` statement at the top). -We'll be covering trait objects in Chapter 17. For now, just know that +We’ll be covering trait objects in Chapter 17. For now, just know that `Box` means the function will return a type that implements the `Error` -trait, but we don't have to specify what particular type the return value will +trait, but we don’t have to specify what particular type the return value will be. This gives us flexibility to return error values that may be of different types in different error cases. -The second change we're making is removing the calls to `expect` in favor of +The second change we’re making is removing the calls to `expect` in favor of `?`, like we talked about in Chapter 9. Rather than `panic!` on an error, this will return the error value from the current function for the caller to handle. -Thirdly, this function now returns an `Ok` value in the success case. We've -declared the `run` function's success type as `()` in the signature, which +Thirdly, this function now returns an `Ok` value in the success case. We’ve +declared the `run` function’s success type as `()` in the signature, which means we need to wrap the unit type value in the `Ok` value. This `Ok(())` syntax may look a bit strange at first, but using `()` like this is the -idiomatic way to indicate that we're calling `run` for its side effects only; -it doesn't return a value we need. +idiomatic way to indicate that we’re calling `run` for its side effects only; +it doesn’t return a value we need. When you run this, it will compile, but with a warning: ``` -warning: unused result which must be used, #[warn(unused_must_use)] on by default +warning: unused result which must be used, #[warn(unused_must_use)] on by +default --> src/main.rs:39:5 | 39 | run(config); @@ -986,14 +831,14 @@ warning: unused result which must be used, #[warn(unused_must_use)] on by defaul ``` Rust is telling us that our code ignores the `Result` value, which might be -indicating that there was an error. We're not checking to see if there was an +indicating that there was an error. We’re not checking to see if there was an error or not, though, and the compiler is reminding us that we probably meant -to have some error handling code here! Let's rectify that now. +to have some error handling code here! Let’s rectify that now. #### Handling Errors Returned from `run` in `main` -We'll check for errors and handle them nicely using a similar technique to the -way we handled errors with `Config::new` in Listing 12-10, but with a slight +We’ll check for errors and handle them using a similar technique to the way we +handled errors with `Config::new` in Listing 12-10, but with a slight difference: Filename: src/main.rs @@ -1013,33 +858,32 @@ fn main() { } ``` - - We use `if let` to check whether `run` returns an `Err` value, rather than -`unwrap_or_else`, and call `process::exit(1)` if it does. `run` doesn't return +`unwrap_or_else`, and call `process::exit(1)` if it does. `run` doesn’t return a value that we want to `unwrap` like `Config::new` returns the `Config` instance. Because `run` returns a `()` in the success case, we only care about -detecting an error, so we don't need `unwrap_or_else` to return the unwrapped +detecting an error, so we don’t need `unwrap_or_else` to return the unwrapped value as it would only be `()`. The bodies of the `if let` and the `unwrap_or_else` functions are the same in both cases though: we print out the error and exit. -### Split Code into a Library Crate +### Splitting Code into a Library Crate -This is looking pretty good so far! Now we're going to split the *src/main.rs* +This is looking pretty good so far! Now we’re going to split the *src/main.rs* file up and put some code into *src/lib.rs* so that we can test it and have a -small `main` function. +*src/main.rs* file with fewer responsibilities. -Let's move the following pieces of code from *src/main.rs* to a new file, -*src/lib.rs*: +Let’s move everything that isn't the `main` function from *src/main.rs* to a +new file, *src/lib.rs*: -- The `run` function definition -- The relevant `use` statements -- The definition of `Config` -- The `Config::new` function definition +* The `run` function definition +* The relevant `use` statements +* The definition of `Config` +* The `Config::new` function definition -The contents of *src/lib.rs* should now look like Listing 12-13: +The contents of *src/lib.rs* should have the signatures shown in Listing 12-13 +(we've omitted the bodies of the functions for brevity): Filename: src/lib.rs @@ -1055,132 +899,95 @@ pub struct Config { impl Config { pub fn new(args: &[String]) -> Result { - if args.len() < 3 { - return Err("not enough arguments"); - } - - let query = args[1].clone(); - let filename = args[2].clone(); - - Ok(Config { - query: query, - filename: filename, - }) + // ...snip... } } -pub fn run(config: Config) -> Result<(), Box>{ - let mut f = File::open(config.filename)?; - - let mut contents = String::new(); - f.read_to_string(&mut contents)?; - - println!("With text:\n{}", contents); - - Ok(()) +pub fn run(config: Config) -> Result<(), Box> { + // ...snip... } ``` Listing 12-13: Moving `Config` and `run` into *src/lib.rs* - - -We've made liberal use of `pub` here: on `Config`, its fields and its `new` +We’ve made liberal use of `pub` here: on `Config`, its fields and its `new` method, and on the `run` function. We now have a library crate that has a -public API that we can test. - -#### Calling the Library Crate from the Binary Crate +public API that we can test! Now we need to bring the code we moved to *src/lib.rs* into the scope of the -binary crate in *src/main.rs* by using `extern crate greprs`. Then we'll add a -`use greprs::Config` line to bring the `Config` type into scope, and prefix the -`run` function with our crate name as shown in Listing 12-14: +binary crate in *src/main.rs* by using `extern crate minigrep`. Then we’ll add +a `use minigrep::Config` line to bring the `Config` type into scope, and prefix +the `run` function with our crate name as shown in Listing 12-14: Filename: src/main.rs ``` -extern crate greprs; +extern crate minigrep; use std::env; use std::process; -use greprs::Config; +use minigrep::Config; fn main() { - let args: Vec = env::args().collect(); - - let config = Config::new(&args).unwrap_or_else(|err| { - println!("Problem parsing arguments: {}", err); - process::exit(1); - }); - - println!("Searching for {}", config.query); - println!("In file {}", config.filename); - - if let Err(e) = greprs::run(config) { - println!("Application error: {}", e); - - process::exit(1); + // ...snip... + if let Err(e) = minigrep::run(config) { + // ...snip... } } ``` -Listing 12-14: Bringing the `greprs` crate into the scope of *src/main.rs* - - - -With that, all the functionality should be connected and should work. Give it a -`cargo run` and make sure everything is wired up correctly. +Listing 12-14: Bringing the `minigrep` crate into the scope of *src/main.rs* - - +To bring the library crate into the binary crate, we use `extern crate` +`minigrep`. Then we’ll add a `use` `minigrep``::Config` line to bring the +`Config` type into scope, and we'll prefix the `run` function with our crate +name. With that, all the functionality should be connected and should work. +Give it a `cargo run` and make sure everything is wired up correctly. -Whew! That was a lot of work, but we've set ourselves up for success in the -future. Now it's much easier to handle errors, and we've made our code more +Whew! That was a lot of work, but we’ve set ourselves up for success in the +future. Now it’s much easier to handle errors, and we’ve made our code more modular. Almost all of our work will be done in *src/lib.rs* from here on out. -Let's take advantage of this newfound modularity by doing something that would +Let’s take advantage of this newfound modularity by doing something that would have been hard with our old code, but is easy with our new code: write some tests! -## Testing the Library's Functionality +## Testing the Library’s Functionality -Now that we've extracted the logic into *src/lib.rs* and left all the argument -parsing and error handling in *src/main.rs*, it's much easier for us to write +Now that we’ve extracted the logic into *src/lib.rs* and left all the argument +parsing and error handling in *src/main.rs*, it’s much easier for us to write tests for the core functionality of our code. We can call our functions directly with various arguments and check return values without having to call our binary from the command line. -In this section, we're going to follow the Test Driven Development (TDD) +In this section, we’re going to follow the Test Driven Development (TDD) process. This is a software development technique that follows this set of steps: -1. Write a test that fails, and run it to make sure it fails for the reason - you expected. -2. Write or modify just enough code to make the new test pass. -3. Refactor the code you just added or changed, and make sure the tests - continue to pass. -4. Repeat! +* Write a test that fails, and run it to make sure it fails for the reason you +expected. +* Write or modify just enough code to make the new test pass. +* Refactor the code you just added or changed, and make sure the tests continue +to pass. +* Repeat! This is just one of many ways to write software, but TDD can help drive the -design of code. Writing the test before writing the code that makes the test +design of code. Writing the test before you write the code that makes the test pass helps to maintain high test coverage throughout the process. -We're going to test drive the implementation of the part of our `greprs` -program that will actually do the searching for the query string in the file -contents and produce a list of lines that match the query. We're going to add -this functionality in a function called `search`. +We’re going to test drive the implementation of the functionality that will +actually do the searching for the query string in the file contents and produce +a list of lines that match the query. We’re going to add this functionality in +a function called `search`. ### Writing a Failing Test -First, since we don't really need them any more, let's remove the `println!` -statements from both *src/lib.rs* and *src/main.rs*. Then we'll add a `test` -module with a test function, like we did in Chapter 11. The test function -specifies the behavior we'd like the `search` function to have: it will take -a query and the text to search for the query in, and will return only the lines +First, since we don’t really need them any more, let’s remove the `println!` +statements from both *src/lib.rs* and *src/main.rs*. Then we’ll add a `test` +module with a test function like we did in Chapter 11. The test function +specifies the behavior we’d like the `search` function to have: it will take a +query and the text to search for the query in, and will return only the lines from the text that contain the query. Listing 12-15 shows this test: Filename: src/lib.rs @@ -1208,39 +1015,36 @@ Pick three."; Listing 12-15: Creating a failing test for the `search` function we wish we had -We've chosen to use "duct" as the string we're looking for in this test. The -text we're searching in is three lines, only one of which contains "duct". We -assert that the value returned from the `search` function contains only the one -line we expect. +The string we are searching for is “duct” in this test. The text we’re +searching is three lines, only one of which contains “duct”. We assert that the +value returned from the `search` function contains only the line we expect. -We aren't able to run this test and watch it fail though, since this test -doesn't even compile yet! We're going to add just enough code to get it to -compile: a definition of the `search` function that always returns an empty -vector, as shown in Listing 12-16. Once we have this, the test should compile -and fail because an empty vector doesn't match a vector containing the one -line `"safe, fast, productive."`. +We aren’t able to run this test and watch it fail though, since this test +doesn’t even compile–the search function doesn't exist yet! So now we’ll add +just enough code to get the tests to compile and run: a definition of the +`search` function that always returns an empty vector, as shown in Listing +12-16. Once we have this, the test should compile and fail because an empty +vector doesn’t match a vector containing the line `"safe, fast, productive."`. Filename: src/lib.rs ``` -fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { - vec![] +pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { + vec![] } ``` -Listing 12-16: Defining just enough of the `search` function that our test will -compile - - +Listing 12-16: Defining just enough of the `search` function so that our test +will compile Notice that we need an explicit lifetime `'a` defined in the signature of `search` and used with the `contents` argument and the return value. Remember from Chapter 10 that the lifetime parameters specify which argument lifetime is -connected to the lifetime of the return value. In this case, we're indicating +connected to the lifetime of the return value. In this case, we’re indicating that the returned vector should contain string slices that reference slices of the argument `contents` (rather than the argument `query`). -In other words, we're telling Rust that the data returned by the `search` +In other words, we’re telling Rust that the data returned by the `search` function will live as long as the data passed into the `search` function in the `contents` argument. This is important! The data referenced *by* a slice needs to be valid in order for the reference to be valid; if the compiler assumed we @@ -1260,23 +1064,23 @@ error[E0106]: missing lifetime specifier signature does not say whether it is borrowed from `query` or `contents` ``` -Rust can't possibly know which of the two arguments we need, so we need to tell +Rust can’t possibly know which of the two arguments we need, so we need to tell it. Because `contents` is the argument that contains all of our text and we want to return the parts of that text that match, we know `contents` is the argument that should be connected to the return value using the lifetime syntax. -Other programming languages don't require you to connect arguments to return +Other programming languages don’t require you to connect arguments to return values in the signature, so this may still feel strange, but will get easier over time. You may want to compare this example with the Lifetime Syntax section in Chapter 10. -Now let's try running our test: +Now let’s try running our test: ``` $ cargo test ...warnings... - Finished debug [unoptimized + debuginfo] target(s) in 0.43 secs - Running target/debug/deps/greprs-abcabcabc + Finished dev [unoptimized + debuginfo] target(s) in 0.43 secs + Running target/debug/deps/minigrep-abcabcabc running 1 test test test::one_result ... FAILED @@ -1284,7 +1088,7 @@ test test::one_result ... FAILED failures: ---- test::one_result stdout ---- - thread 'test::one_result' panicked at 'assertion failed: `(left == right)` + thread 'test::one_result' panicked at 'assertion failed: `(left == right)` (left: `["safe, fast, productive."]`, right: `[]`)', src/lib.rs:16 note: Run with `RUST_BACKTRACE=1` for a backtrace. @@ -1297,22 +1101,22 @@ test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured error: test failed ``` -Great, our test fails, exactly as we expected. Let's get the test to pass! +Great, our test fails, exactly as we expected. Let’s get the test to pass! -### Writing Code that Gets the Test to Pass +### Writing Code to Pass the Test Currently, our test is failing because we always return an empty vector. To fix that and implement `search`, our program needs to follow these steps: -1. Iterate through each line of the contents. -2. Check if the line contains our query string. - * If it does, add it to the list of values we're returning. - * If it doesn't, do nothing. -3. Return the list of results that match. +* Iterate through each line of the contents. +* Check if the line contains our query string. +* If it does, add it to the list of values we’re returning. +* If it doesn’t, do nothing. +* Return the list of results that match. -Let's take each step at a time, starting with iterating through lines. +Let’s take each step at a time, starting with iterating through lines. -#### Iterating Through Lines with the `lines` method +#### Iterating Through Lines with the `lines` Method Rust has a helpful method to handle line-by-line iteration of strings, conveniently named `lines`, that works as shown in Listing 12-17: @@ -1320,7 +1124,7 @@ conveniently named `lines`, that works as shown in Listing 12-17: Filename: src/lib.rs ``` -fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { +pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { for line in contents.lines() { // do something with line } @@ -1329,23 +1133,14 @@ fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { Listing 12-17: Iterating through each line in `contents` - - -The `lines` method returns an iterator. We'll be talking about iterators in -depth in Chapter 13, but we've already seen this way of using an iterator in +The `lines` method returns an iterator. We’ll be talking about iterators in +depth in Chapter 13, but we’ve already seen this way of using an iterator in Listing 3-6, where we used a `for` loop with an iterator to run some code on each item in a collection. - - - #### Searching Each Line for the Query -Next, we'll add functionality to check if the current line contains the query +Next, we’ll add functionality to check if the current line contains the query string. Luckily, strings have another helpful method named `contains` that does this for us! Add the `contains` method to the `search` function as shown in Listing 12-18: @@ -1353,7 +1148,7 @@ Listing 12-18: Filename: src/lib.rs ``` -fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { +pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { for line in contents.lines() { if line.contains(query) { // do something with line @@ -1365,8 +1160,6 @@ fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { Listing 12-18: Adding functionality to see if the line contains the string in `query` - - #### Storing Matching Lines Finally, we need a way to store the lines that contain our query string. For @@ -1377,7 +1170,7 @@ vector, as shown in Listing 12-19: Filename: src/lib.rs ``` -fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { +pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { let mut results = Vec::new(); for line in contents.lines() { @@ -1392,10 +1185,8 @@ fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { Listing 12-19: Storing the lines that match so that we can return them - - Now the `search` function should be returning only the lines that contain -`query`, and our test should pass. Let's run the tests: +`query`, and our test should pass. Let’s run the tests: ``` $ cargo test @@ -1403,39 +1194,16 @@ running 1 test test test::one_result ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured - - Running target/debug/greprs-2f55ee8cd1721808 - -running 0 tests - -test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured - - Doc-tests greprs - -running 0 tests - -test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ``` Our test passed, great, it works! Now that our test is passing, we could consider opportunities for refactoring -the implementation of the `search` function while keeping the tests passing in -order to maintain the same functionality while we do so. This code isn't bad, -but it isn't taking advantage of some useful features of iterators. We'll be -coming back to this example in Chapter 13 where we'll explore iterators in -detail and see how to improve it. - - - +the implementation of the `search` function while keeping the code that passes +the tests, in order to maintain the same functionality. The code in the +`search` function isn’t too bad, but it isn’t taking advantage of some useful +features of iterators. We’ll be coming back to this example in Chapter 13 where +we’ll explore iterators in detail and see how to improve it. #### Using the `search` Function in the `run` Function @@ -1461,77 +1229,67 @@ pub fn run(config: Config) -> Result<(), Box> { } ``` - +We’re still using a `for` loop to get each line returned from `search` and +printing out each line. -We're again using a `for` loop to get each line returned from `search`, and -the code that we run for each line prints it out. - -Now our whole program should be working! Let's try it out, first with a word -that should return exactly one line from the Emily Dickinson poem, "frog": +Now our whole program should be working! Let’s try it out, first with a word +that should return exactly one line from the Emily Dickinson poem, “frog”: ``` $ cargo run frog poem.txt - Compiling greprs v0.1.0 (file:///projects/greprs) - Finished debug [unoptimized + debuginfo] target(s) in 0.38 secs - Running `target/debug/greprs frog poem.txt` + Compiling minigrep v0.1.0 (file:///projects/minigrep) + Finished dev [unoptimized + debuginfo] target(s) in 0.38 secs + Running `target/debug/minigrep frog poem.txt` How public, like a frog ``` -Cool! Next, how about a word that will match multiple lines, like "the": +Cool! Next, how about a word that will match multiple lines, like “the”: ``` $ cargo run the poem.txt - Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs - Running `target/debug/greprs the poem.txt` -Then there's a pair of us — don't tell! + Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs + Running `target/debug/minigrep the poem.txt` +Then there’s a pair of us — don’t tell! To tell your name the livelong day ``` -And finally, let's make sure that we don't get any lines when we search for a -word that isn't anywhere in the poem, like "monomorphization": +And finally, let’s make sure that we don’t get any lines when we search for a +word that isn’t anywhere in the poem, like “monomorphization”: ``` $ cargo run monomorphization poem.txt - Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs - Running `target/debug/greprs monomorphization poem.txt` + Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs + Running `target/debug/minigrep monomorphization poem.txt` ``` -Excellent! We've built our own version of a classic tool, and learned a lot -about how to structure applications. We've also learned a bit about file input -and output, lifetimes, testing, and command line parsing. +Excellent! We’ve built our own mini version of a classic tool, and learned a +lot about how to structure applications. We’ve also learned a bit about file +input and output, lifetimes, testing, and command line parsing. -Feel free to move on to Chapter 13 if you'd like at this point. To round out -this project chapter, though, we're going to briefly demonstrate how to work -with environment variables and printing to standard error, both of which are -useful when writing command line programs. +To round out this project chapter, we’re going to briefly demonstrate how to +work with environment variables and how to print to standard error, both of +which are useful when writing command line programs. Feel free to move on to +Chapter 13 if you’d like at this point. ## Working with Environment Variables -We're going to improve our tool with an extra feature: an option for case -insensitive searching turned on via an environment variable. We could make this -a command line option and require that users enter it each time they want it to -apply, but instead we're going to use an environment variable. This allows our -users to set the environment variable once and have all their searches be case -insensitive in that terminal session. +We’re going to improve our tool with an extra feature: an option for case +insensitive searching that the user can turn on via an environment variable. We +could make this a command line option and require that users enter it each time +they want it to apply, but instead we’re going to use an environment variable. +This allows our users to set the environment variable once and have all their +searches be case insensitive in that terminal session. ### Writing a Failing Test for the Case-Insensitive `search` Function -First, let's add a new function that we will call when the environment variable -is on. - - - +We want to add a new `search_case_insensitive` function that we will call when +the environment variable is on. -We're going to continue following the TDD process that we started doing in the -last section, and the first step is again to write a failing test. We'll add a -new test for the new case insensitive search function, and rename our old test -from `one_result` to `case_sensitive` to be clearer about the differences -between the two tests, as shown in Listing 12-20: +We’re going to continue following the TDD process, so the first step is again +to write a failing test. We’ll add a new test for the new case-insensitive +search function, and rename our old test from `one_result` to `case_sensitive` +to be clearer about the differences between the two tests, as shown in Listing +12-20: Filename: src/lib.rs @@ -1572,37 +1330,32 @@ Trust me."; } ``` - - Listing 12-20: Adding a new failing test for the case insensitive function -we're about to add - -Note that we've edited the old test's `query` and `contents` too: we changed -the query to "duct", which will match the line with the word "productive". -We've added a new line with the text "Duct tape", with a capital D, that -shouldn't match the query "duct" when we're searching for the query in a case -sensitive manner. We've changed this test to ensure that we don't accidentally -break the case sensitive search functionality that we've already implemented; -this test should pass now and should continue to pass as we work on the case -insensitive search. - -The new test for the case insensitive search uses "rUsT" with some capital -letters as its query. The expected return value from the -`search_case_insensitive` function we're going to add is that the query "rust" -will match both the line containing "Rust:" with a capital R and also the line -"Trust me." that contains "rust" with a lowercase r. This test will fail to -compile right now since we haven't yet defined the `search_case_insensitive` -function; feel free to add a skeleton implementation that always returns an -empty array in the same way that we did for the `search` function in Listing -12-16 in order to see the test compile and fail. +we’re about to add + +Note that we’ve edited the old test’s `contents` too. We've added a new line +with the text “Duct tape”, with a capital D, that shouldn’t match the query +“duct” when we’re searching in a case sensitive manner. Changing the old test +in this way helps ensure that we don’t accidentally break the case sensitive +search functionality that we’ve already implemented; this test should pass now +and should continue to pass as we work on the case insensitive search. + +The new test for the case *insensitive* search uses “rUsT” as its query. In the +`search_case_insensitive` function we’re going to add, the query “rUsT” should +match both the line containing “Rust:” with a capital R and also the line +“Trust me.” even though both of those have different casing than the query. +This is our failing test, and it will fail to compile because we haven’t yet +defined the `search_case_insensitive` function. Feel free to add a skeleton +implementation that always returns an empty vector in the same way that we did +for the `search` function in Listing 12-16 in order to see the test compile and +fail. ### Implementing the `search_case_insensitive` Function The `search_case_insensitive` function, shown in Listing 12-21, will be almost -the same as the `search` function. The difference is that we'll lowercase the -`query` function and each `line` so that whatever the case of the input -arguments, they will be the same case when we check whether the line contains -the query. +the same as the `search` function. The only difference is that we’ll lowercase +the `query` and each `line` so that whatever the case of the input arguments, +they will be the same case when we check whether the line contains the query. Filename: src/lib.rs @@ -1624,64 +1377,36 @@ fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { Listing 12-21: Defining the `search_case_insensitive` function to lowercase both the query and the line before comparing them - - - - - First, we lowercase the `query` string, and store it in a shadowed variable with the same name. Calling `to_lowercase` on the query is necessary so that no -matter if the user's query is "rust", "RUST", "Rust", or "rUsT", we'll treat -the query as if it was "rust" and be insensitive to the case. +matter if the user’s query is “rust”, “RUST”, “Rust”, or “rUsT”, we’ll treat +the query as if it was “rust” and be insensitive to the case. Note that `query` is now a `String` rather than a string slice, because calling -`to_lowercase` is creating new data, not referencing existing data. If the -query is "rUsT", that string slice does not contain a lowercase u or t for us -to use, so we have to allocate a new `String` containing "rust". Because -`query` is now a `String`, when we pass `query` as an argument to the -`contains` method, we need to add an ampersand since the signature of -`contains` is defined to take a string slice. +`to_lowercase` creates new data rather than referencing existing data. Say the +query is “rUsT”, as an example: that string slice does not contain a lowercase +“u” or “t” for us to use, so we have to allocate a new `String` containing +“rust”. When we pass `query` as an argument to the `contains` method now, we +need to add an ampersand because the signature of `contains` is defined to take +a string slice. Next, we add a call to `to_lowercase` on each `line` before we check if it -contains `query`. This will turn "Rust:" into "rust:" and "Trust me." into -"trust me." Now that we've converted both `line` and `query` to all lowercase, -we'll find matches no matter what case the text in the file has or the user -entered in the query. +contains `query` to lowercase all characters. Now that we’ve converted both +`line` and `query` to lowercase, we’ll find matches no matter what the case of +the query. -Let's see if this implementation passes the tests: +Let’s see if this implementation passes the tests: ``` - Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs - Running target/debug/deps/greprs-e58e9b12d35dc861 - running 2 tests test test::case_insensitive ... ok test test::case_sensitive ... ok test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured - - Running target/debug/greprs-8a7faa2662b5030a - -running 0 tests - -test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured - - Doc-tests greprs - -running 0 tests - -test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ``` -Great! Now, let's actually call the new `search_case_insensitive` function from -the `run` function. First, we're going to add a configuration option for +Great! Now, let’s actually call the new `search_case_insensitive` function from +the `run` function. First, we’re going to add a configuration option for switching between case sensitive and case insensitive search to the `Config` struct: @@ -1695,10 +1420,8 @@ pub struct Config { } ``` - - We add the `case_sensitive` field that holds a boolean. Then we need our `run` -function to check the `case_sensitive` field's value and use that to decide +function to check the `case_sensitive` field’s value and use that to decide whether to call the `search` function or the `search_case_insensitive` function as shown in Listing 12-22: @@ -1728,14 +1451,12 @@ pub fn run(config: Config) -> Result<(), Box>{ Listing 12-22: Calling either `search` or `search_case_insensitive` based on the value in `config.case_sensitive` - - Finally, we need to actually check for the environment variable. The functions for working with environment variables are in the `env` module in the standard -library, so we want to bring that module into scope with a `use std::env;` -line at the top of *src/lib.rs*. Then we're going to use the `var` method -from the `env` module in `Config::new` to check for an environment variable -named `CASE_INSENSITIVE`, as shown in Listing 12-23: +library, so we want to bring that module into scope with a `use std::env;` line +at the top of *src/lib.rs*. Then we’re going to use the `var` method from the +`env` module to check for an environment variable named `CASE_INSENSITIVE`, as +shown in Listing 12-23: Filename: src/lib.rs @@ -1755,62 +1476,59 @@ impl Config { let case_sensitive = env::var("CASE_INSENSITIVE").is_err(); - Ok(Config { - query: query, - filename: filename, - case_sensitive: case_sensitive, - }) + Ok(Config { query, filename, case_sensitive }) } } ``` Listing 12-23: Checking for an environment variable named `CASE_INSENSITIVE` - - Here, we create a new variable `case_sensitive`. In order to set its value, we -call the `env::var` function and pass it the name of the environment variable -we're looking for, `CASE_INSENSITIVE`. `env::var` returns a `Result` that will -be the `Ok` variant containing the value if the environment variable is set, -and will be the `Err` variant if the environment variable is not set. We're -using the `is_err` method on the `Result` to check to see if it's an error (and -therefore unset), which means we *should* do a case sensitive search. If the -`CASE_INSENSITIVE` environment variable is set to anything, `is_err` will -return false and we will do a case insensitive search. We don't care about the -value that the environment variable is set to, just whether it's set or unset, -so we're checking `is_err` rather than `unwrap`, `expect`, or any of the other -methods we've seen on `Result`. We pass the value in the `case_sensitive` -variable to the `Config` instance so that the `run` function can read that -value and decide whether to call `search` or `search_case_insensitive` as we -implemented in Listing 12-22. - -Let's give it a try! First, we'll run our program without the environment -variable set and with the query "to", which should match any line that contains -the word "to" in all lowercase: +call the `env::var` function and pass it the name of the `CASE_INSENSITIVE` +environment variable. The `env::var` method returns a `Result` that will be the +successful `Ok` variant that contains the value of the environment variable if +the environment variable is set. It will return the `Err` variant if the +environment variable is not set. + +We’re using the `is_err` method on the `Result` to check to see if it’s an +error, and therefore unset, which means it *should* do a case sensitive search. +If the `CASE_INSENSITIVE` environment variable is set to anything, `is_err` +will return false and it will perform a case insensitive search. We don’t care +about the *value* of the environment variable, just whether it’s set or unset, +so we’re checking `is_err` rather than `unwrap`, `expect`, or any of the other +methods we’ve seen on `Result`. + +We pass the value in the `case_sensitive` variable to the `Config` instance so +that the `run` function can read that value and decide whether to call `search` +or `search_case_insensitive` as we implemented in Listing 12-22. + +Let’s give it a try! First, we’ll run our program without the environment +variable set and with the query “to”, which should match any line that contains +the word “to” in all lowercase: ``` $ cargo run to poem.txt - Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs - Running `target/debug/greprs to poem.txt` + Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs + Running `target/debug/minigrep to poem.txt` Are you nobody, too? How dreary to be somebody! ``` -Looks like that still works! Now, let's run the program with `CASE_INSENSITIVE` -set to 1 but with the same query "to", and we should get lines that contain -"to" that might have capital letters: +Looks like that still works! Now, let’s run the program with `CASE_INSENSITIVE` +set to 1 but with the same query “to”, and we should get lines that contain +“to” that might have uppercase letters: ``` $ CASE_INSENSITIVE=1 cargo run to poem.txt - Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs - Running `target/debug/greprs to poem.txt` + Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs + Running `target/debug/minigrep to poem.txt` Are you nobody, too? How dreary to be somebody! To tell your name the livelong day To an admiring bog! ``` -Excellent, we also got lines containing "To"! Our `greprs` program can now do +Excellent, we also got lines containing “To”! Our `minigrep` program can now do case insensitive searching, controlled by an environment variable. Now you know how to manage options set using either command line arguments or environment variables! @@ -1819,140 +1537,108 @@ Some programs allow both arguments *and* environment variables for the same configuration. In those cases, the programs decide that one or the other takes precedence. For another exercise on your own, try controlling case insensitivity through a command line argument as well as through the -environment variable, and decide which should take precedence the program is +environment variable, and decide which should take precedence if the program is run with contradictory values. The `std::env` module contains many more useful features for dealing with -environment variables; check out its documentation to see what's available. - -## Write to `stderr` Instead of `stdout` - -Right now, we're writing all of our output to the terminal with `println!`. -Most terminals provide two kinds of output: "standard out" for general -information, and "standard error" for error messages. This distinction is the -behavior that's expected of command line programs: it enables users to choose -to direct a program's successful output to a file but still print error -messages to the screen, for example. `println!` is only capable of printing to -standard out, though, so we have to use something else in order to print to -standard error. - -We can verify that, the way we've written `greprs` so far, everything is being -written to standard out, including error messages that should be written to -standard error instead. We'll do that by intentionally causing an error, the -one that happens when we run the program without any arguments. We're going to -redirect standard output to a file, but not standard error. The way command -line programs are expected to work is that, because the output is an error -message, it should be shown on the screen rather than being redirected to the -file. Let's see that our program is not currently meeting this expectation by -using `>` and specifying a filename, *output.txt*, that we want to redirect -standard out to: +environment variables; check out its documentation to see what’s available. + +## Writing Error Messages to `stderr` Instead of `stdout` + +At the moment we’re writing all of our output to the terminal with the +`println!` function. Most terminals provide two kinds of output: *standard out* +for general information, and *standard error* for error messages. This +distinction enables users to choose whether to direct a the successful output +of a program to a file but still print error messages to the screen. + +The `println!` function is only capable of printing to standard out, though, so +we have to use something else in order to print to standard error. + +### Checking Where Errors are Written to + +First, let’s observe how all content printed by `minigrep` is currently being +written to standard out, including error messages that we want to write to +standard error instead. We’ll do that by redirecting the standard output stream +to a file while we also intentionally cause an error. We won't redirect the +standard error stream, so any content sent to standard error will continue to +display on the screen. Command line programs are expected to send error +messages to the standard error stream so that we can still see error messages +on the screen even if we choose to redirect the standard output stream to a +file. Our program is not currently well-behaved; we're about to see that it +saves the error message output to the file instead! + +The way to demonstrate this behavior is by running the program with `>` and the +filename, *output.txt*, that we want to redirect the standard output stream to. +We're not going to pass any arguments, which should cause an error: ``` $ cargo run > output.txt ``` - - - The `>` syntax tells the shell to write the contents of standard out to -*output.txt* instead of the screen. We didn't see the error message we were +*output.txt* instead of the screen. We didn’t see the error message we were expecting printed on the screen, so that means it must have ended up in the -file. Let's see what *output.txt* contains: +file. Let’s see what *output.txt* contains: ``` -Application error: No search string or filename found +Problem parsing arguments: not enough arguments ``` - - +Yup, our error message is being printed to standard out. It’s much more useful +for error messages like this to be printed to standard error, and have only +data from a successful run end up in the file when we redirect standard out in +this way. We’ll change that. + +### Printing Errors to Standard Error -Yup, there's our error message, which means it's being printed to standard out. -This isn't what's expected from command line programs. It's much more useful -for error messages like this to be printed to standard error, and only have -data printed to standard out from a successful run end up in the file when we -redirect standard out in this way. Let's change how error messages are printed -as shown in Listing 12-23. Because of the refactoring we did earlier in this -chapter, all of the code that prints error messages is in one place, in `main`: +Let’s change how error messages are printed using the code in Listing 12-24. +Because of the refactoring we did earlier in this chapter, all the code that +prints error messages is in one function, in `main`. The standard library +provides the `eprintln!` macro that prints to the standard error stream, so +let's change the two places we were calling `println!` to print errors so that +these spots use `eprintln!` instead: Filename: src/main.rs ``` -extern crate greprs; - -use std::env; -use std::process; -use std::io::prelude::*; - -use greprs::Config; - fn main() { let args: Vec = env::args().collect(); - let mut stderr = std::io::stderr(); let config = Config::new(&args).unwrap_or_else(|err| { - writeln!( - &mut stderr, - "Problem parsing arguments: {}", - err - ).expect("Could not write to stderr"); + eprintln!("Problem parsing arguments: {}", err); process::exit(1); }); - if let Err(e) = greprs::run(config) { - writeln!( - &mut stderr, - "Application error: {}", - e - ).expect("Could not write to stderr"); + if let Err(e) = minigrep::run(config) { + eprintln!("Application error: {}", e); process::exit(1); } } ``` -Listing 12-23: Writing error messages to `stderr` instead of `stdout` using -`writeln!` +Listing 12-24: Writing error messages to `stderr` instead of `stdout` using +`eprintln!` - - -Rust does not have a convenient function like `println!` for writing to -standard error. Instead, we use the `writeln!` macro, which is like `println!` -but takes an extra argument. The first thing we pass to it is what to write to. -We can acquire a handle to standard error through the `std::io::stderr` -function. We give a mutable reference to `stderr` to `writeln!`; we need it to -be mutable so we can write to it! The second and third arguments to `writeln!` -are like the first and second arguments to `println!`: a format string and any -variables we're interpolating. - -Let's try running the program again in the same way, without any arguments and -redirecting `stdout` with `>`: +After changing `println!` to `eprintln!`, let’s try running the program again +in the same way, without any arguments and redirecting `stdout` with `>`: ``` $ cargo run > output.txt -Application error: No search string or filename found +Problem parsing arguments: not enough arguments ``` -Now we see our error on the screen, and `output.txt` contains nothing, which is -the behavior that's expected of command line programs. +Now we see our error on the screen and `output.txt` contains nothing, which is +the behavior expected of command line programs. -If we run the program again with arguments that don't cause an error, but still -redirecting standard out to a file: +If we run the program again with arguments that don’t cause an error, but still +redirect standard out to a file: ``` $ cargo run to poem.txt > output.txt ``` -We won't see any output to our terminal, and `output.txt` will contain our +We won’t see any output to our terminal, and `output.txt` will contain our results: Filename: output.txt @@ -1962,18 +1648,19 @@ Are you nobody, too? How dreary to be somebody! ``` -This demonstrates that we're now using standard out for successful output and -standard error for error output as appropriate. +This demonstrates that we’re now using `stdout` for successful output and +`stderr` for error output as appropriate. ## Summary -In this chapter, we've recapped on some of the major concepts so far and +In this chapter, we’ve recapped on some of the major concepts so far and covered how to do common I/O operations in a Rust context. By using command -line arguments, files, environment variables, and the `writeln!` macro with -`stderr`, you're now prepared to write command line applications. By using the +line arguments, files, environment variables, and the `eprintln!` macro with +`stderr`, you’re now prepared to write command line applications. By using the concepts from previous chapters, your code will be well-organized, be able to store data effectively in the appropriate data structures, handle errors nicely, and be well tested. -Next, let's explore some functional-language influenced Rust features: closures +Next, let’s explore some functional-language influenced Rust features: closures and iterators. + diff --git a/src/doc/book/second-edition/nostarch/odt/chapter02.doc b/src/doc/book/second-edition/nostarch/odt/chapter02.doc deleted file mode 100644 index 2aef420a916320aedade9d955c66fab32417ce45..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 218624 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%0D*T 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

n}q? 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%0AjMdtFHPo42 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 Y=^YekRQjv&VFAoQ4bkQTbj<<(2ZDk}8UO$Q diff --git a/src/doc/book/second-edition/nostarch/odt/chapter05.docx b/src/doc/book/second-edition/nostarch/odt/chapter05.docx deleted file mode 100644 index f657e777ede2410cbe191cc678993ce56e2e8cdb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44509 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 Y2PME_2B~B$1Hm5ZG|N!#K0VzgX+j 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 lKYuv>eS8P;{|tve=cJk?@|B& diff --git a/src/doc/book/second-edition/nostarch/odt/chapter06.docx b/src/doc/book/second-edition/nostarch/odt/chapter06.docx deleted file mode 100644 index bf34988ed76ab96126148bd4091b725141f38110..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49580 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 diff --git a/src/doc/book/second-edition/nostarch/odt/chapter07.docx b/src/doc/book/second-edition/nostarch/odt/chapter07.docx deleted file mode 100644 index f9e677974fcab98a2a4c92d6dbb607fc18148de1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48867 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

LxTNNV!65ly&U7Dp69UMr)RI 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 QAORmJ!0GPn`0LaE0qq^a3;+NC diff --git a/src/doc/book/second-edition/nostarch/odt/chapter08.docx b/src/doc/book/second-edition/nostarch/odt/chapter08.docx deleted file mode 100644 index 8cb9fd6f28962b41930d1b660c99ef678bc11fe7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41633 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 YU%;9w2vC^-00wlGgxalI_}9_@0W2pmhX4Qo diff --git a/src/doc/book/second-edition/nostarch/odt/chapter09.docx b/src/doc/book/second-edition/nostarch/odt/chapter09.docx deleted file mode 100644 index 4bf599b2b5ea6f1149f64be24590b8e365847bb8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47156 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%0D!oC?6MbdW{IiHqOeV_a`7H9@ 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 diff --git a/src/doc/book/second-edition/src/SUMMARY.md b/src/doc/book/second-edition/src/SUMMARY.md index e55a670227..0880bab937 100644 --- a/src/doc/book/second-edition/src/SUMMARY.md +++ b/src/doc/book/second-edition/src/SUMMARY.md @@ -57,13 +57,13 @@ - [Running tests](ch11-02-running-tests.md) - [Test Organization](ch11-03-test-organization.md) -- [An I/O Project](ch12-00-an-io-project.md) +- [An I/O Project: Building a Command Line Program](ch12-00-an-io-project.md) - [Accepting Command Line Arguments](ch12-01-accepting-command-line-arguments.md) - [Reading a File](ch12-02-reading-a-file.md) - - [Improving Error Handling and Modularity](ch12-03-improving-error-handling-and-modularity.md) + - [Refactoring to Improve Modularity and Error Handling](ch12-03-improving-error-handling-and-modularity.md) - [Testing the Library's Functionality](ch12-04-testing-the-librarys-functionality.md) - [Working with Environment Variables](ch12-05-working-with-environment-variables.md) - - [Writing to `stderr` instead of `stdout`](ch12-06-writing-to-stderr-instead-of-stdout.md) + - [Writing Error Messages to `stderr` Instead of `stdout`](ch12-06-writing-to-stderr-instead-of-stdout.md) ## Thinking in Rust diff --git a/src/doc/book/second-edition/src/appendix-06-translation.md b/src/doc/book/second-edition/src/appendix-06-translation.md index 5500004dd7..7c3d197b0f 100644 --- a/src/doc/book/second-edition/src/appendix-06-translation.md +++ b/src/doc/book/second-edition/src/appendix-06-translation.md @@ -6,8 +6,12 @@ For resources in languages other than English. Most are still in progress; see [label]: https://github.com/rust-lang/book/issues?q=is%3Aopen+is%3Aissue+label%3ATranslations - [Português](https://coreh.github.io/rust-book-pt-br/) -- [Tiếng việt](https://rust-vietnam.github.io/book/) +- [Tiếng việt](https://github.com/hngnaig/rust-lang-book/tree/vi-VN) - [简体中文](http://www.broadview.com.cn/article/144), [alternate](https://github.com/KaiserY/trpl-zh-cn) - [українська мова](https://github.com/pavloslav/rust-book-uk-ua) - [Español](https://github.com/z1mvader/book) -- [Italiano](https://github.com/CodelessFuture/trpl2-it) \ No newline at end of file +- [Italiano](https://github.com/CodelessFuture/trpl2-it) +- [Русский](https://github.com/iDeBugger/rust-book-ru) +- [한국어](https://github.com/rinthel/rust-lang-book-ko) +- [日本語](https://github.com/hazama-yuinyan/book) +- [Français](https://github.com/quadrifoglio/rust-book-fr) diff --git a/src/doc/book/second-edition/src/ch01-01-installation.md b/src/doc/book/second-edition/src/ch01-01-installation.md index 6a6f27240f..4be5ed6a35 100644 --- a/src/doc/book/second-edition/src/ch01-01-installation.md +++ b/src/doc/book/second-edition/src/ch01-01-installation.md @@ -30,6 +30,19 @@ Rust is installed now. Great! Of course, if you disapprove of the `curl | sh` pattern, you can download, inspect and run the script however you like. +The installation script automatically adds Rust to your system PATH after your next login. +If you want to start using Rust right away, run the following command in your shell: + +```text +$ source $HOME/.cargo/env +``` + +Alternatively, add the following line to your `~/.bash_profile`: + +```text +$ export PATH="$HOME/.cargo/bin:$PATH" +``` + ### Installing on Windows On Windows, go to [https://rustup.rs](https://rustup.rs/) and diff --git a/src/doc/book/second-edition/src/ch04-01-what-is-ownership.md b/src/doc/book/second-edition/src/ch04-01-what-is-ownership.md index c427ccd1cc..31cf4004b0 100644 --- a/src/doc/book/second-edition/src/ch04-01-what-is-ownership.md +++ b/src/doc/book/second-edition/src/ch04-01-what-is-ownership.md @@ -327,7 +327,7 @@ use `s1` after `s2` is created: let s1 = String::from("hello"); let s2 = s1; -println!("{}", s1); +println!("{}, world!", s1); ``` You’ll get an error like this because Rust prevents you from using the diff --git a/src/doc/book/second-edition/src/ch05-01-defining-structs.md b/src/doc/book/second-edition/src/ch05-01-defining-structs.md index e75255bfdd..c67419b940 100644 --- a/src/doc/book/second-edition/src/ch05-01-defining-structs.md +++ b/src/doc/book/second-edition/src/ch05-01-defining-structs.md @@ -55,14 +55,35 @@ struct To get a specific value from a struct, we can use dot notation. If we wanted just this user’s email address, we can use `user1.email` wherever we want to use this value. To change a value in a struct, if the instance is mutable, we -can use the dot notation and assign into a particular field, such as -`user1.email = String::from("someone-else@example.com");`. +can use the dot notation and assign into a particular field. Listing 5-3 shows +how to change the value in the `email` field of a mutable `User` instance: + +```rust +# struct User { +# username: String, +# email: String, +# sign_in_count: u64, +# active: bool, +# } +# +let mut user1 = User { + email: String::from("someone@example.com"), + username: String::from("someusername123"), + active: true, + sign_in_count: 1, +}; + +user1.email = String::from("anotheremail@example.com"); +``` + +Listing 5-3: Changing the value in the `email` field of a +`User` instance ### Field Init Shorthand when Variables Have the Same Name as Fields If you have variables with the same names as struct fields, you can use *field init shorthand*. This can make functions that create new instances of structs -more concise. The function named `build_user` shown here in Listing 5-3 has +more concise. The function named `build_user` shown here in Listing 5-4 has parameters named `email` and `username`. The function creates and returns a `User` instance: @@ -84,13 +105,13 @@ fn build_user(email: String, username: String) -> User { } ``` -Listing 5-3: A `build_user` function that takes an email +Listing 5-4: A `build_user` function that takes an email and username and returns a `User` instance Because the parameter names `email` and `username` are the same as the `User` struct's field names `email` and `username`, we can write `build_user` without -the repetition of `email` and `username` as shown in Listing 5-4. This version -of `build_user` behaves the same way as the one in Listing 5-3. The field init +the repetition of `email` and `username` as shown in Listing 5-5. This version +of `build_user` behaves the same way as the one in Listing 5-4. The field init syntax can make cases like this shorter to write, especially when structs have many fields. @@ -112,14 +133,14 @@ fn build_user(email: String, username: String) -> User { } ``` -Listing 5-4: A `build_user` function that uses field init +Listing 5-5: A `build_user` function that uses field init syntax since the `email` and `username` parameters have the same name as struct fields ### Creating Instances From Other Instances With Struct Update Syntax It's often useful to create a new instance from an old instance, using most of -the old instance's values but changing some. Listing 5-5 shows an example of +the old instance's values but changing some. Listing 5-6 shows an example of creating a new `User` instance in `user2` by setting the values of `email` and `username` but using the same values for the rest of the fields from the `user1` instance we created in Listing 5-2: @@ -147,13 +168,13 @@ let user2 = User { }; ``` -Listing 5-5: Creating a new `User` instance, `user2`, and +Listing 5-6: Creating a new `User` instance, `user2`, and setting some fields to the values of the same fields from `user1` - The *struct update syntax* achieves the same effect as the code in Listing -5-5 using less code. The struct update syntax uses `..` to specify that the +The *struct update syntax* achieves the same effect as the code in Listing 5-6 +using less code. The struct update syntax uses `..` to specify that the remaining fields not set explicitly should have the same value as the fields in -the given instance. The code in Listing 5-6 also creates an instance in `user2` +the given instance. The code in Listing 5-7 also creates an instance in `user2` that has a different value for `email` and `username` but has the same values for the `active` and `sign_in_count` fields that `user1` has: @@ -179,7 +200,7 @@ let user2 = User { }; ``` -Listing5-6: Using struct update syntax to set a new +Listing 5-7: Using struct update syntax to set a new `email` and `username` values for a `User` instance but use the rest of the values from the fields of the instance in the `user1` variable diff --git a/src/doc/book/second-edition/src/ch05-02-example-structs.md b/src/doc/book/second-edition/src/ch05-02-example-structs.md index 6ce3b85b0d..09f37dbfd0 100644 --- a/src/doc/book/second-edition/src/ch05-02-example-structs.md +++ b/src/doc/book/second-edition/src/ch05-02-example-structs.md @@ -6,7 +6,7 @@ refactor the program until we’re using structs instead. Let’s make a new binary project with Cargo called *rectangles* that will take the length and width of a rectangle specified in pixels and will calculate the -area of the rectangle. Listing 5-7 shows a short program with one way of doing +area of the rectangle. Listing 5-8 shows a short program with one way of doing just that in our project’s *src/main.rs*: Filename: src/main.rs @@ -27,7 +27,7 @@ fn area(length: u32, width: u32) -> u32 { } ``` -Listing 5-7: Calculating the area of a rectangle +Listing 5-8: Calculating the area of a rectangle specified by its length and width in separate variables Now, run this program using `cargo run`: @@ -38,7 +38,7 @@ The area of the rectangle is 1500 square pixels. ### Refactoring with Tuples -Even though Listing 5-7 works and figures out the area of the rectangle by +Even though Listing 5-8 works and figures out the area of the rectangle by calling the `area` function with each dimension, we can do better. The length and the width are related to each other because together they describe one rectangle. @@ -54,7 +54,7 @@ function we wrote has two parameters. The parameters are related, but that’s not expressed anywhere in our program. It would be more readable and more manageable to group length and width together. We’ve already discussed one way we might do that in the Grouping Values into Tuples section of Chapter 3 on -page XX: by using tuples. Listing 5-8 shows another version of our program that +page XX: by using tuples. Listing 5-9 shows another version of our program that uses tuples: Filename: src/main.rs @@ -94,7 +94,7 @@ our code. We use structs to add meaning by labeling the data. We can transform the tuple we’re using into a data type with a name for the whole as well as names for the -parts, as shown in Listing 5-9: +parts, as shown in Listing 5-10: Filename: src/main.rs @@ -118,7 +118,7 @@ fn area(rectangle: &Rectangle) -> u32 { } ``` -Listing 5-9: Defining a `Rectangle` struct +Listing 5-10: Defining a `Rectangle` struct Here we’ve defined a struct and named it `Rectangle`. Inside the `{}` we defined the fields as `length` and `width`, both of which have type `u32`. Then @@ -143,7 +143,7 @@ and `1`—a win for clarity. It would be helpful to be able to print out an instance of the `Rectangle` while we’re debugging our program in order to see the values for all its -fields. Listing 5-10 uses the `println!` macro as we have been in earlier +fields. Listing 5-11 uses the `println!` macro as we have been in earlier chapters: Filename: src/main.rs @@ -161,7 +161,7 @@ fn main() { } ``` -Listing 5-10: Attempting to print a `Rectangle` +Listing 5-11: Attempting to print a `Rectangle` instance When we run this code, we get an error with this core message: @@ -209,7 +209,7 @@ crate, add `#[derive(Debug)]` or manually implement it Rust *does* include functionality to print out debugging information, but we have to explicitly opt-in to make that functionality available for our struct. To do that, we add the annotation `#[derive(Debug)]` just before the struct -definition, as shown in Listing 5-11: +definition, as shown in Listing 5-12: Filename: src/main.rs @@ -227,7 +227,7 @@ fn main() { } ``` -Listing5-11: Adding the annotation to derive the `Debug` +Listing 5-12: Adding the annotation to derive the `Debug` trait and printing the `Rectangle` instance using debug formatting Now when we run the program, we won’t get any errors and we’ll see the diff --git a/src/doc/book/second-edition/src/ch05-03-method-syntax.md b/src/doc/book/second-edition/src/ch05-03-method-syntax.md index b12b1f95ed..6f3d02bc94 100644 --- a/src/doc/book/second-edition/src/ch05-03-method-syntax.md +++ b/src/doc/book/second-edition/src/ch05-03-method-syntax.md @@ -1,7 +1,7 @@ ## Method Syntax *Methods* are similar to functions: they’re declared with the `fn` keyword and -their name, they can have parameters and return values, and they contain some +their name, they can have parameters and a return value, and they contain some code that is run when they’re called from somewhere else. However, methods are different from functions in that they’re defined within the context of a struct (or an enum or a trait object, which we cover in Chapters 6 and 17, @@ -12,7 +12,7 @@ instance of the struct the method is being called on. Let’s change the `area` function that has a `Rectangle` instance as a parameter and instead make an `area` method defined on the `Rectangle` struct, as shown -in Listing 5-12: +in Listing 5-13: Filename: src/main.rs @@ -39,7 +39,7 @@ fn main() { } ``` -Listing 5-12: Defining an `area` method on the +Listing 5-13: Defining an `area` method on the `Rectangle` struct To define the function within the context of `Rectangle`, we start an `impl` @@ -124,7 +124,7 @@ Let’s practice using methods by implementing a second method on the `Rectangle struct. This time, we want an instance of `Rectangle` to take another instance of `Rectangle` and return `true` if the second `Rectangle` can fit completely within `self`; otherwise it should return `false`. That is, we want to be able -to write the program shown in Listing 5-13, once we’ve defined the `can_hold` +to write the program shown in Listing 5-14, once we’ve defined the `can_hold` method: Filename: src/main.rs @@ -140,7 +140,7 @@ fn main() { } ``` -Listing 5-13: Demonstration of using the as-yet-unwritten +Listing 5-14: Demonstration of using the as-yet-unwritten `can_hold` method And the expected output would look like the following, because both dimensions @@ -164,7 +164,7 @@ calling the `can_hold` method. The return value of `can_hold` will be a boolean, and the implementation will check whether the length and width of `self` are both greater than the length and width of the other `Rectangle`, respectively. Let’s add the new `can_hold` method to the `impl` block from -Listing 5-12, shown in Listing 5-14: +Listing 5-13, shown in Listing 5-15: Filename: src/main.rs @@ -186,10 +186,10 @@ impl Rectangle { } ``` -Listing 5-14: Implementing the `can_hold` method on +Listing 5-15: Implementing the `can_hold` method on `Rectangle` that takes another `Rectangle` instance as a parameter -When we run this code with the `main` function in Listing 5-13, we’ll get our +When we run this code with the `main` function in Listing 5-14, we’ll get our desired output. Methods can take multiple parameters that we add to the signature after the `self` parameter, and those parameters work just like parameters in functions. diff --git a/src/doc/book/second-edition/src/ch06-02-match.md b/src/doc/book/second-edition/src/ch06-02-match.md index 92c1df1744..b7ce42ea7d 100644 --- a/src/doc/book/second-edition/src/ch06-02-match.md +++ b/src/doc/book/second-edition/src/ch06-02-match.md @@ -27,7 +27,7 @@ enum Coin { Quarter, } -fn value_in_cents(coin: Coin) -> i32 { +fn value_in_cents(coin: Coin) -> u32 { match coin { Coin::Penny => 1, Coin::Nickel => 5, @@ -76,7 +76,7 @@ with a `Coin::Penny` but would still return the last value of the block, `1`: # Quarter, # } # -fn value_in_cents(coin: Coin) -> i32 { +fn value_in_cents(coin: Coin) -> u32 { match coin { Coin::Penny => { println!("Lucky penny!"); @@ -145,7 +145,7 @@ quarter’s state. Then we can use `state` in the code for that arm, like so: # Quarter(UsState), # } # -fn value_in_cents(coin: Coin) -> i32 { +fn value_in_cents(coin: Coin) -> u32 { match coin { Coin::Penny => 1, Coin::Nickel => 5, diff --git a/src/doc/book/second-edition/src/ch08-02-strings.md b/src/doc/book/second-edition/src/ch08-02-strings.md index a43d99aa52..e47c176e65 100644 --- a/src/doc/book/second-edition/src/ch08-02-strings.md +++ b/src/doc/book/second-edition/src/ch08-02-strings.md @@ -410,4 +410,4 @@ of strings than other programming languages do, but this will prevent you from having to handle errors involving non-ASCII characters later in your development lifecycle. -Let’s switch to something a bit less complex: hash map! +Let’s switch to something a bit less complex: hash maps! diff --git a/src/doc/book/second-edition/src/ch11-00-testing.md b/src/doc/book/second-edition/src/ch11-00-testing.md index 7e453a2a88..e766f288ae 100644 --- a/src/doc/book/second-edition/src/ch11-00-testing.md +++ b/src/doc/book/second-edition/src/ch11-00-testing.md @@ -1,34 +1,33 @@ -# Testing +# Writing Automated Tests > Program testing can be a very effective way to show the presence of bugs, but > it is hopelessly inadequate for showing their absence. -> -> Edsger W. Dijkstra, "The Humble Programmer" (1972) +> Edsger W. Dijkstra, “The Humble Programmer” (1972) Correctness in our programs means that our code does what we intend for it to do. Rust is a programming language that cares a lot about correctness, but -correctness is a complex topic and isn't easy to prove. Rust's type system +correctness is a complex topic and isn’t easy to prove. Rust’s type system shoulders a huge part of this burden, but the type system cannot catch every kind of incorrectness. As such, Rust includes support for writing software tests within the language itself. -As an example, say we write a function called `add_two` that adds two to a -number passed to it. This function's signature accepts an integer as a -parameter and returns an integer as a result. When we implement and compile -that function, Rust will do all the type checking and borrow checking that -we've seen so far. Those checks will make sure that, for instance, we aren't -passing a `String` value or an invalid reference to this function. What Rust -*can't* check is that this function will do precisely what we intend: return -the parameter plus two, rather than, say, the parameter plus 10 or the -parameter minus 50! That's where tests come in. +As an example, say we write a function called `add_two` that adds two to +whatever number is passed to it. This function’s signature accepts an integer +as a parameter and returns an integer as a result. When we implement and +compile that function, Rust will do all the type checking and borrow checking +that we’ve seen so far to make sure that, for instance, we aren’t passing a +`String` value or an invalid reference to this function. What Rust *can’t* +check is that this function will do precisely what we intend: return the +parameter plus two, rather than, say, the parameter plus 10 or the parameter +minus 50! That’s where tests come in. We can write tests that assert, for example, that when we pass `3` to the `add_two` function, we get `5` back. We can run these tests whenever we make changes to our code to make sure any existing correct behavior has not changed. Testing is a complex skill, and we cannot hope to cover everything about how to -write good tests in one chapter of a book, so here we'll just discuss the -mechanics of Rust's testing facilities. We'll talk about the annotations and +write good tests in one chapter of a book, so here we’ll just discuss the +mechanics of Rust’s testing facilities. We’ll talk about the annotations and macros available to you when writing your tests, the default behavior and options provided for running your tests, and how to organize tests into unit tests and integration tests. diff --git a/src/doc/book/second-edition/src/ch11-01-writing-tests.md b/src/doc/book/second-edition/src/ch11-01-writing-tests.md index 0605c31283..1cb49f0d53 100644 --- a/src/doc/book/second-edition/src/ch11-01-writing-tests.md +++ b/src/doc/book/second-edition/src/ch11-01-writing-tests.md @@ -1,15 +1,15 @@ ## How to Write Tests -Tests are Rust functions that verify non-test code is functioning in the -program in the expected manner. The bodies of test functions typically contain -some setup, running the code we want to test, then asserting that the results -are what we expect. Let's look at the features Rust provides specifically for -writing tests: the `test` attribute, a few macros, and the `should_panic` -attribute. +Tests are Rust functions that verify that the non-test code in the program is +functioning in the expected manner. The bodies of test functions typically run +some setup code, then run the code we want to test, then assert whether the +results are what we expect. Let’s look at the features Rust provides +specifically for writing tests: the `test` attribute, a few macros, and the +`should_panic` attribute. ### The Anatomy of a Test Function -At its simplest, a test in Rust is a function that's annotated with the `test` +At its simplest, a test in Rust is a function that’s annotated with the `test` attribute. Attributes are metadata about pieces of Rust code: the `derive` attribute that we used with structs in Chapter 5 is one example. To make a function into a test function, we add `#[test]` on the line before `fn`. When @@ -17,28 +17,19 @@ we run our tests with the `cargo test` command, Rust will build a test runner binary that runs the functions annotated with the `test` attribute and reports on whether each test function passes or fails. - - - We saw in Chapter 7 that when you make a new library project with Cargo, a test module with a test function in it is automatically generated for us. This is to -help us get started writing our tests, since we don't have to go look up the +help us get started writing our tests, since we don’t have to go look up the exact structure and syntax of test functions every time we start a new project. We can add as many additional test functions and as many test modules as we want, though! -We're going to explore some aspects of how tests work by experimenting with the -template test generated for us, without actually testing any code. Then we'll -write some real-world tests that call some code that we've written and assert +We’re going to explore some aspects of how tests work by experimenting with the +template test generated for us, without actually testing any code. Then we’ll +write some real-world tests that call some code that we’ve written and assert that its behavior is correct. -Let's create a new library project called `adder`: +Let’s create a new library project called `adder`: ```text $ cargo new adder @@ -63,7 +54,7 @@ mod tests { Listing 11-1: The test module and function generated automatically for us by `cargo new` -For now, let's ignore the top two lines and focus on the function to see how it +For now, let’s ignore the top two lines and focus on the function to see how it works. Note the `#[test]` annotation before the `fn` line: this attribute indicates this is a test function, so that the test runner knows to treat this function as a test. We could also have non-test functions in the `tests` module @@ -71,7 +62,7 @@ to help set up common scenarios or perform common operations, so we need to indicate which functions are tests with the `#[test]` attribute. The function currently has no body, which means there is no code to fail the -test; an empty test is a passing test! Let's run it and see that this test +test; an empty test is a passing test! Let’s run it and see that this test passes. The `cargo test` command runs all tests we have in our project, as shown in @@ -105,30 +96,21 @@ that test, `ok`. Then we see the overall summary of running the tests: `test result: ok.` means all the tests passed. `1 passed; 0 failed` adds up the number of tests that passed or failed. -We don't have any tests we've marked as ignored, so the summary says `0 -ignored`. We're going to talk about ignoring tests in the next section on +We don’t have any tests we’ve marked as ignored, so the summary says `0 +ignored`. We’re going to talk about ignoring tests in the next section on different ways to run tests. The `0 measured` statistic is for benchmark tests that measure performance. Benchmark tests are, as of this writing, only available in nightly Rust. See Appendix D for more information about nightly Rust. The next part of the test output that starts with `Doc-tests adder` is for the -results of any documentation tests. We don't have any documentation tests yet, +results of any documentation tests. We don’t have any documentation tests yet, but Rust can compile any code examples that appear in our API documentation. -This feature helps us keep our docs and our code in sync! We'll be talking -about how to write documentation tests in the "Documentation Comments" section -of Chapter 14. We're going to ignore the `Doc-tests` output for now. - - - - -Let's change the name of our test and see how that changes the test output. +This feature helps us keep our docs and our code in sync! We’ll be talking +about how to write documentation tests in the “Documentation Comments” section +of Chapter 14. We’re going to ignore the `Doc-tests` output for now. + +Let’s change the name of our test and see how that changes the test output. Give the `it_works` function a different name, such as `exploration`, like so: Filename: src/lib.rs @@ -142,7 +124,7 @@ mod tests { } ``` -And run `cargo test` again. In the output, we'll now see `exploration` instead +And run `cargo test` again. In the output, we’ll now see `exploration` instead of `it_works`: ```text @@ -152,7 +134,7 @@ test tests::exploration ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured ``` -Let's add another test, but this time we'll make a test that fails! Tests fail +Let’s add another test, but this time we’ll make a test that fails! Tests fail when something in the test function panics. We talked about the simplest way to cause a panic in Chapter 9: call the `panic!` macro! Type in the new test so that your `src/lib.rs` now looks like Listing 11-3: @@ -208,14 +190,14 @@ failed because it `panicked at 'Make this test fail'`, which happened on *src/lib.rs* line 9. The next section lists just the names of all the failing tests, which is useful when there are lots of tests and lots of detailed failing test output. We can use the name of a failing test to run just that -test in order to more easily debug it; we'll talk more about ways to run tests +test in order to more easily debug it; we’ll talk more about ways to run tests in the next section. Finally, we have the summary line: overall, our test result is `FAILED`. We had 1 test pass and 1 test fail. -Now that we've seen what the test results look like in different scenarios, -let's look at some macros other than `panic!` that are useful in tests. +Now that we’ve seen what the test results look like in different scenarios, +let’s look at some macros other than `panic!` that are useful in tests. ### Checking Results with the `assert!` Macro @@ -226,24 +208,11 @@ to ensure that some condition in a test evaluates to `true`. We give the calls the `panic!` macro, which causes the test to fail. This is one macro that helps us check that our code is functioning in the way we intend. - - - Remember all the way back in Chapter 5, Listing 5-9, where we had a `Rectangle` -struct and a `can_hold` method, repeated here in Listing 11-5. Let's put this +struct and a `can_hold` method, repeated here in Listing 11-5. Let’s put this code in *src/lib.rs* instead of *src/main.rs* and write some tests for it using the `assert!` macro. - - Filename: src/lib.rs ```rust @@ -263,8 +232,8 @@ impl Rectangle { Listing 11-5: The `Rectangle` struct and its `can_hold` method from Chapter 5 -The `can_hold` method returns a boolean, which means it's a perfect use case -for the `assert!` macro. In Listing 11-6, let's write a test that exercises the +The `can_hold` method returns a boolean, which means it’s a perfect use case +for the `assert!` macro. In Listing 11-6, let’s write a test that exercises the `can_hold` method by creating a `Rectangle` instance that has a length of 8 and a width of 7, and asserting that it can hold another `Rectangle` instance that has a length of 5 and a width of 1: @@ -289,17 +258,17 @@ mod tests { Listing 11-6: A test for `can_hold` that checks that a larger rectangle indeed holds a smaller rectangle -Note that we've added a new line inside the `tests` module: `use super::*;`. +Note that we’ve added a new line inside the `tests` module: `use super::*;`. The `tests` module is a regular module that follows the usual visibility rules -we covered in Chapter 7. Because we're in an inner module, we need to bring the -code under test in the outer module into the scope of the inner module. We've +we covered in Chapter 7. Because we’re in an inner module, we need to bring the +code under test in the outer module into the scope of the inner module. We’ve chosen to use a glob here so that anything we define in the outer module is available to this `tests` module. -We've named our test `larger_can_hold_smaller`, and we've created the two +We’ve named our test `larger_can_hold_smaller`, and we’ve created the two `Rectangle` instances that we need. Then we called the `assert!` macro and passed it the result of calling `larger.can_hold(&smaller)`. This expression is -supposed to return `true`, so our test should pass. Let's find out! +supposed to return `true`, so our test should pass. Let’s find out! ```text running 1 test @@ -308,7 +277,7 @@ test tests::larger_can_hold_smaller ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured ``` -It does pass! Let's add another test, this time asserting that a smaller +It does pass! Let’s add another test, this time asserting that a smaller rectangle cannot hold a larger rectangle: Filename: src/lib.rs @@ -327,7 +296,7 @@ mod tests { } #[test] - fn smaller_can_not_hold_larger() { + fn smaller_cannot_hold_larger() { let larger = Rectangle { length: 8, width: 7 }; let smaller = Rectangle { length: 5, width: 1 }; @@ -342,15 +311,15 @@ way, our test will pass if `can_hold` returns `false`: ```text running 2 tests -test tests::smaller_can_not_hold_larger ... ok +test tests::smaller_cannot_hold_larger ... ok test tests::larger_can_hold_smaller ... ok test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured ``` -Two passing tests! Now let's see what happens to our test results if we -introduce a bug in our code. Let's change the implementation of the `can_hold` -method to have a less-than sign when it compares the lengths where it's +Two passing tests! Now let’s see what happens to our test results if we +introduce a bug in our code. Let’s change the implementation of the `can_hold` +method to have a less-than sign when it compares the lengths where it’s supposed to have a greater-than sign: ```rust @@ -371,7 +340,7 @@ Running the tests now produces: ```text running 2 tests -test tests::smaller_can_not_hold_larger ... ok +test tests::smaller_cannot_hold_larger ... ok test tests::larger_can_hold_smaller ... FAILED failures: @@ -394,18 +363,18 @@ less than 5. ### Testing Equality with the `assert_eq!` and `assert_ne!` Macros A common way to test functionality is to take the result of the code under test -and the value we expect the code to return and check that they're equal. We +and the value we expect the code to return and check that they’re equal. We could do this using the `assert!` macro and passing it an expression using the `==` operator. However, this is such a common test that the standard library provides a pair of macros to perform this test more conveniently: `assert_eq!` and `assert_ne!`. These macros compare two arguments for equality or -inequality, respectively. They'll also print out the two values if the -assertion fails, so that it's easier to see *why* the test failed, while the +inequality, respectively. They’ll also print out the two values if the +assertion fails, so that it’s easier to see *why* the test failed, while the `assert!` macro only tells us that it got a `false` value for the `==` expression, not the values that lead to the `false` value. -In Listing 11-7, let's write a function named `add_two` that adds two to its -parameter and returns the result. Then let's test this function using the +In Listing 11-7, let’s write a function named `add_two` that adds two to its +parameter and returns the result. Then let’s test this function using the `assert_eq!` macro: Filename: src/lib.rs @@ -429,7 +398,7 @@ mod tests { Listing 11-7: Testing the function `add_two` using the `assert_eq!` macro -Let's check that it passes! +Let’s check that it passes! ```text running 1 test @@ -442,7 +411,7 @@ The first argument we gave to the `assert_eq!` macro, 4, is equal to the result of calling `add_two(2)`. We see a line for this test that says `test tests::it_adds_two ... ok`, and the `ok` text indicates that our test passed! -Let's introduce a bug into our code to see what it looks like when a test that +Let’s introduce a bug into our code to see what it looks like when a test that uses `assert_eq!` fails. Change the implementation of the `add_two` function to instead add 3: @@ -479,16 +448,16 @@ useful and helps us get started debugging: it says the `left` argument to Note that in some languages and test frameworks, the parameters to the functions that assert two values are equal are called `expected` and `actual` and the order in which we specify the arguments matters. However, in Rust, -they're called `left` and `right` instead, and the order in which we specify -the value we expect and the value that the code under test produces doesn't +they’re called `left` and `right` instead, and the order in which we specify +the value we expect and the value that the code under test produces doesn’t matter. We could have written the assertion in this test as `assert_eq!(add_two(2), 4)`, which would result in a failure message that says `` assertion failed: `(left == right)` (left: `5`, right: `4`) ``. The `assert_ne!` macro will pass if the two values we give to it are not equal -and fail if they are equal. This macro is most useful for cases when we're not +and fail if they are equal. This macro is most useful for cases when we’re not sure exactly what a value *will* be, but we know what the value definitely -*won't* be, if our code is functioning as we intend. For example, if we have a +*won’t* be, if our code is functioning as we intend. For example, if we have a function that is guaranteed to change its input in some way, but the way in which the input is changed depends on the day of the week that we run our tests, the best thing to assert might be that the output of the function is not @@ -499,8 +468,8 @@ Under the surface, the `assert_eq!` and `assert_ne!` macros use the operators arguments using debug formatting, which means the values being compared must implement the `PartialEq` and `Debug` traits. All of the primitive types and most of the standard library types implement these traits. For structs and -enums that you define, you'll need to implement `PartialEq` in order to be able -to assert that values of those types are equal or not equal. You'll need to +enums that you define, you’ll need to implement `PartialEq` in order to be able +to assert that values of those types are equal or not equal. You’ll need to implement `Debug` in order to be able to print out the values in the case that the assertion fails. Because both of these traits are derivable traits, as we mentioned in Chapter 5, this is usually as straightforward as adding the @@ -518,7 +487,7 @@ contains `{}` placeholders and values to go in the placeholders. Custom messages are useful in order to document what an assertion means, so that when the test fails, we have a better idea of what the problem is with the code. -For example, let's say we have a function that greets people by name, and we +For example, let’s say we have a function that greets people by name, and we want to test that the name we pass into the function appears in the output: Filename: src/lib.rs @@ -540,14 +509,14 @@ mod tests { } ``` -The requirements for this program haven't been agreed upon yet, and we're +The requirements for this program haven’t been agreed upon yet, and we’re pretty sure the `Hello` text at the beginning of the greeting will change. We -decided we don't want to have to update the test for the name when that +decided we don’t want to have to update the test for the name when that happens, so instead of checking for exact equality to the value returned from -the `greeting` function, we're just going to assert that the output contains +the `greeting` function, we’re just going to assert that the output contains the text of the input parameter. -Let's introduce a bug into this code to see what this test failure looks like, +Let’s introduce a bug into this code to see what this test failure looks like, by changing `greeting` to not include `name`: ```rust @@ -575,7 +544,7 @@ failures: This just tells us that the assertion failed and which line the assertion is on. A more useful failure message in this case would print the value we did get -from the `greeting` function. Let's change the test function to have a custom +from the `greeting` function. Let’s change the test function to have a custom failure message made from a format string with a placeholder filled in with the actual value we got from the `greeting` function: @@ -590,7 +559,7 @@ fn greeting_contains_name() { } ``` -Now if we run the test again, we'll get a much more informative error message: +Now if we run the test again, we’ll get a much more informative error message: ```text ---- tests::greeting_contains_name stdout ---- @@ -605,7 +574,7 @@ debug what happened instead of what we were expecting to happen. ### Checking for Panics with `should_panic` In addition to checking that our code returns the correct values we expect, -it's also important to check that our code handles error conditions as we +it’s also important to check that our code handles error conditions as we expect. For example, consider the `Guess` type that we created in Chapter 9 in Listing 9-8. Other code that uses `Guess` is depending on the guarantee that `Guess` instances will only contain values between 1 and 100. We can write a @@ -614,9 +583,9 @@ outside that range panics. We can do this by adding another attribute, `should_panic`, to our test function. This attribute makes a test pass if the code inside the function -panics, and the test will fail if the code inside the function does not panic. +panics, and the test will fail if the code inside the function doesn't panic. -Listing 11-8 shows how we'd write a test that checks the error conditions of +Listing 11-8 shows how we’d write a test that checks the error conditions of `Guess::new` happen when we expect: Filename: src/lib.rs @@ -654,7 +623,7 @@ mod tests { `panic!` The `#[should_panic]` attribute goes after the `#[test]` attribute and before -the test function it applies to. Let's see what it looks like when this test +the test function it applies to. Let’s see what it looks like when this test passes: ```text @@ -664,7 +633,7 @@ test tests::greater_than_100 ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured ``` -Looks good! Now let's introduce a bug in our code, by removing the condition +Looks good! Now let’s introduce a bug in our code, by removing the condition that the `new` function will panic if the value is greater than 100: ```rust @@ -699,8 +668,8 @@ failures: test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured ``` -We don't get a very helpful message in this case, but once we look at the test -function, we can see that it's annotated with `#[should_panic]`. The failure we +We don’t get a very helpful message in this case, but once we look at the test +function, we can see that it’s annotated with `#[should_panic]`. The failure we got means that the code in the function, `Guess::new(200)`, did not cause a panic. @@ -761,7 +730,7 @@ substring of the panic message is enough to ensure that the code in the function that gets run is the `else if value > 100` case. To see what happens when a `should_panic` test with an `expected` message -fails, let's again introduce a bug into our code by swapping the bodies of the +fails, let’s again introduce a bug into our code by swapping the bodies of the `if value < 1` and the `else if value > 100` blocks: ```rust,ignore @@ -799,6 +768,6 @@ less than or equal to 100'`. We can see the panic message that we did get, which in this case was `Guess value must be greater than or equal to 1, got 200.` We could then start figuring out where our bug was! -Now that we've gone over ways to write tests, let's look at what is happening +Now that we’ve gone over ways to write tests, let’s look at what is happening when we run our tests and talk about the different options we can use with `cargo test`. diff --git a/src/doc/book/second-edition/src/ch11-02-running-tests.md b/src/doc/book/second-edition/src/ch11-02-running-tests.md index 7af6472cd2..489f2fcabc 100644 --- a/src/doc/book/second-edition/src/ch11-02-running-tests.md +++ b/src/doc/book/second-edition/src/ch11-02-running-tests.md @@ -19,10 +19,6 @@ separator `--`. ### Running Tests in Parallel or Consecutively - - - When multiple tests are run, by default they run in parallel using threads. This means the tests will finish running faster, so that we can get faster feedback on whether or not our code is working. Since the tests are running at @@ -40,7 +36,7 @@ incorrect, but because the tests have interfered with each other while running in parallel. One solution would be to make sure each test writes to a different file; another solution is to run the tests one at a time. -If you don't want to run the tests in parallel, or if you want more +If you don’t want to run the tests in parallel, or if you want more fine-grained control over the number of threads used, you can send the `--test-threads` flag and the number of threads you want to use to the test binary. For example: @@ -51,14 +47,14 @@ $ cargo test -- --test-threads=1 We set the number of test threads to 1, telling the program not to use any parallelism. This will take longer than running them in parallel, but the tests -won't be potentially interfering with each other if they share state. +won’t be potentially interfering with each other if they share state. ### Showing Function Output -By default, if a test passes, Rust's test library captures anything printed to +By default, if a test passes, Rust’s test library captures anything printed to standard output. For example, if we call `println!` in a test and the test -passes, we won't see the `println!` output in the terminal: we'll only see the -line that says the test passed. If a test fails, we'll see whatever was printed +passes, we won’t see the `println!` output in the terminal: we’ll only see the +line that says the test passed. If a test fails, we’ll see whatever was printed to standard output with the rest of the failure message. For example, Listing 11-10 has a silly function that prints out the value of @@ -94,7 +90,7 @@ mod tests { Listing 11-10: Tests for a function that calls `println!` -The output we'll see when we run these tests with `cargo test` is: +The output we’ll see when we run these tests with `cargo test` is: ```text running 2 tests @@ -155,12 +151,12 @@ function and see what the output looks like then! ### Running a Subset of Tests by Name -Sometimes, running a full test suite can take a long time. If you're working on +Sometimes, running a full test suite can take a long time. If you’re working on code in a particular area, you might want to run only the tests pertaining to that code. You can choose which tests to run by passing `cargo test` the name or names of the test/s you want to run as an argument. -To demonstrate how to run a subset of tests, we'll create three tests for our +To demonstrate how to run a subset of tests, we’ll create three tests for our `add_two` function as shown in Listing 11-11 and choose which ones to run: Filename: src/lib.rs @@ -193,7 +189,7 @@ mod tests { Listing 11-11: Three tests with a variety of names -If we run the tests without passing any arguments, as we've already seen, all +If we run the tests without passing any arguments, as we’ve already seen, all the tests will run in parallel: ```text @@ -220,13 +216,13 @@ test tests::one_hundred ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured ``` -We can't specify the names of multiple tests in this way, only the first value +We can’t specify the names of multiple tests in this way, only the first value given to `cargo test` will be used. #### Filtering to Run Multiple Tests However, we can specify part of a test name, and any test whose name matches -that value will get run. For example, since two of our tests' names contain +that value will get run. For example, since two of our tests’ names contain `add`, we can run those two by running `cargo test add`: ```text @@ -242,16 +238,8 @@ test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured ``` This ran all tests with `add` in the name. Also note that the module in which -tests appear becomes part of the test's name, so we can run all the tests in a -module by filtering on the module's name. - - - +tests appear becomes part of the test’s name, so we can run all the tests in a +module by filtering on the module’s name. ### Ignore Some Tests Unless Specifically Requested @@ -276,7 +264,7 @@ fn expensive_test() { ``` We add the `#[ignore]` line to the test we want to exclude, after `#[test]`. -Now if we run our tests, we'll see `it_works` runs, but `expensive_test` does +Now if we run our tests, we’ll see `it_works` runs, but `expensive_test` does not: ```text @@ -301,17 +289,6 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured `expensive_test` is listed as `ignored`. If we want to run only the ignored tests, we can ask for them to be run with `cargo test -- --ignored`: - - - - - - ```text $ cargo test -- --ignored Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs @@ -324,6 +301,6 @@ test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured ``` By controlling which tests run, you can make sure your `cargo test` results -will be fast. When you're at a point that it makes sense to check the results +will be fast. When you’re at a point that it makes sense to check the results of the `ignored` tests and you have time to wait for the results, you can choose to run `cargo test -- --ignored` instead. diff --git a/src/doc/book/second-edition/src/ch11-03-test-organization.md b/src/doc/book/second-edition/src/ch11-03-test-organization.md index 2d3314f054..b25f863ff4 100644 --- a/src/doc/book/second-edition/src/ch11-03-test-organization.md +++ b/src/doc/book/second-edition/src/ch11-03-test-organization.md @@ -17,7 +17,7 @@ doing what you expect them to separately and together. The purpose of unit tests is to test each unit of code in isolation from the rest of the code, in order to be able to quickly pinpoint where code is and is not working as expected. We put unit tests in the *src* directory, in each file -with the code that they're testing. The convention is that we create a module +with the code that they’re testing. The convention is that we create a module named `tests` in each file to contain the test functions, and we annotate the module with `cfg(test)`. @@ -26,8 +26,8 @@ module with `cfg(test)`. The `#[cfg(test)]` annotation on the tests module tells Rust to compile and run the test code only when we run `cargo test`, and not when we run `cargo build`. This saves compile time when we only want to build the library, and saves space -in the resulting compiled artifact since the tests are not included. We'll see -that since integration tests go in a different directory, they don't need the +in the resulting compiled artifact since the tests are not included. We’ll see +that since integration tests go in a different directory, they don’t need the `#[cfg(test)]` annotation. Because unit tests go in the same files as the code, though, we use `#[cfg(test)]`to specify that they should not be included in the compiled result. @@ -48,18 +48,18 @@ mod tests { This is the automatically generated test module. The attribute `cfg` stands for *configuration*, and tells Rust that the following item should only be included -given a certain configuration. In this case, the configuration is `test`, -provided by Rust for compiling and running tests. By using this attribute, -Cargo only compiles our test code if we actively run the tests with `cargo -test`. This includes any helper functions that might be within this module, in -addition to the functions annotated with `#[test]`. +given a certain configuration option. In this case, the configuration option is +`test`, provided by Rust for compiling and running tests. By using this +attribute, Cargo only compiles our test code if we actively run the tests with +`cargo test`. This includes any helper functions that might be within this +module, in addition to the functions annotated with `#[test]`. #### Testing Private Functions -There's debate within the testing community about whether private functions +There’s debate within the testing community about whether private functions should be tested directly or not, and other languages make it difficult or impossible to test private functions. Regardless of which testing ideology you -adhere to, Rust's privacy rules do allow you to test private functions. +adhere to, Rust’s privacy rules do allow you to test private functions. Consider the code in Listing 11-12 with the private function `internal_adder`: Filename: src/lib.rs @@ -86,25 +86,17 @@ mod tests { Listing 11-12: Testing a private function - - - Note that the `internal_adder` function is not marked as `pub`, but because tests are just Rust code and the `tests` module is just another module, we can -import and call `internal_adder` in a test just fine. If you don't think -private functions should be tested, there's nothing in Rust that will compel +import and call `internal_adder` in a test just fine. If you don’t think +private functions should be tested, there’s nothing in Rust that will compel you to do so. ### Integration Tests In Rust, integration tests are entirely external to your library. They use your library in the same way any other code would, which means they can only call -functions that are part of your library's public API. Their purpose is to test +functions that are part of your library’s public API. Their purpose is to test that many parts of your library work correctly together. Units of code that work correctly by themselves could have problems when integrated, so test coverage of the integrated code is important as well. To create integration @@ -115,10 +107,10 @@ tests, you first need a *tests* directory. To write integration tests for our code, we need to make a *tests* directory at the top level of our project directory, next to *src*. Cargo knows to look for integration test files in this directory. We can then make as many test files -as we'd like in this directory, and Cargo will compile each of the files as an +as we’d like in this directory, and Cargo will compile each of the files as an individual crate. -Let's give it a try! Keep the code from Listing 11-12 in *src/lib.rs*. Make a +Let’s give it a try! Keep the code from Listing 11-12 in *src/lib.rs*. Make a *tests* directory, then make a new file named *tests/integration_test.rs*, and enter the code in Listing 11-13. @@ -136,15 +128,15 @@ fn it_adds_two() { Listing 11-13: An integration test of a function in the `adder` crate -We've added `extern crate adder` at the top, which we didn't need in the unit +We’ve added `extern crate adder` at the top, which we didn’t need in the unit tests. This is because each test in the `tests` directory is an entirely separate crate, so we need to import our library into each of them. Integration tests use the library like any other consumer of it would, by importing the crate and using only the public API. -We don't need to annotate any code in *tests/integration_test.rs* with +We don’t need to annotate any code in *tests/integration_test.rs* with `#[cfg(test)]`. Cargo treats the `tests` directory specially and will only -compile files in this directory if we run `cargo test`. Let's try running +compile files in this directory if we run `cargo test`. Let’s try running `cargo test` now: ```text @@ -172,11 +164,6 @@ running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ``` - - - Now we have three sections of output: the unit tests, the integration test, and the doc tests. The first section for the unit tests is the same as we have been seeing: one line for each unit test (we have one named `internal` that we added @@ -184,7 +171,7 @@ in Listing 11-12), then a summary line for the unit tests. The integration tests section starts with the line that says `Running target/debug/deps/integration-test-ce99bcc2479f4607` (the hash at the end of -your output will be different). Then there's a line for each test function in +your output will be different). Then there’s a line for each test function in that integration test, and a summary line for the results of the integration test just before the `Doc-tests adder` section starts. @@ -195,7 +182,7 @@ section. Each integration test file gets its own section, so if we add more files in the *tests* directory, there will be more integration test sections. We can still run a particular integration test function by specifying the test -function's name as an argument to `cargo test`. To run all of the tests in a +function’s name as an argument to `cargo test`. To run all of the tests in a particular integration test file, use the `--test` argument of `cargo test` followed by the name of the file: @@ -216,12 +203,12 @@ This tests only the file that we specified from the *tests* directory. As you add more integration tests, you may want to make more than one file in the *tests* directory to help organize them; for example, to group the test -functions by the functionality they're testing. As we mentioned, each file in +functions by the functionality they’re testing. As we mentioned, each file in the *tests* directory is compiled as its own separate crate. Treating each integration test file as its own crate is useful to create separate scopes that are more like the way end users will be using your crate. -However, this means files in the *tests* directory don't share the same +However, this means files in the *tests* directory don’t share the same behavior as files in *src* do that we learned about in Chapter 7 regarding how to separate code into modules and files. @@ -241,8 +228,8 @@ pub fn setup() { } ``` -If we run the tests again, we'll see a new section in the test output for the -*common.rs* file, even though this file doesn't contain any test functions, nor +If we run the tests again, we’ll see a new section in the test output for the +*common.rs* file, even though this file doesn’t contain any test functions, nor are we calling the `setup` function from anywhere: ```text @@ -271,23 +258,20 @@ running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ``` - - Having `common` show up in the test results with `running 0 tests` displayed for it is not what we wanted; we just wanted to be able to share some code with the other integration test files. In order to not have `common` show up in the test output, we need to use the other method of extracting code into a file that we learned about in Chapter 7: -instead of creating *tests/common.rs*, we'll create *tests/common/mod.rs*. When +instead of creating *tests/common.rs*, we’ll create *tests/common/mod.rs*. When we move the `setup` function code into *tests/common/mod.rs* and get rid of the *tests/common.rs* file, the section in the test output will no longer show up. Files in subdirectories of the *tests* directory do not get compiled as separate crates or have sections in the test output. Once we have *tests/common/mod.rs*, we can use it from any of the integration -test files as a module. Here's an example of calling the `setup` function from +test files as a module. Here’s an example of calling the `setup` function from the `it_adds_two` test in *tests/integration_test.rs*: Filename: tests/integration_test.rs @@ -311,7 +295,7 @@ function. #### Integration Tests for Binary Crates If our project is a binary crate that only contains a *src/main.rs* and does -not have a *src/lib.rs*, we aren't able to create integration tests in the +not have a *src/lib.rs*, we aren’t able to create integration tests in the *tests* directory and use `extern crate` to import functions defined in *src/main.rs*. Only library crates expose functions that other crates are able to call and use; binary crates are meant to be run on their own. @@ -325,14 +309,14 @@ small amount of code does not need to be tested. ## Summary -Rust's testing features provide a way to specify how code should function to +Rust’s testing features provide a way to specify how code should function to ensure it continues to work as we expect even as we make changes. Unit tests exercise different parts of a library separately and can test private implementation details. Integration tests cover the use of many parts of the -library working together, and they use the library's public API to test the -code in the same way external code will use it. Even though Rust's type system +library working together, and they use the library’s public API to test the +code in the same way external code will use it. Even though Rust’s type system and ownership rules help prevent some kinds of bugs, tests are still important to help reduce logic bugs having to do with how your code is expected to behave. -Let's put together the knowledge from this chapter and other previous chapters +Let’s put together the knowledge from this chapter and other previous chapters and work on a project in the next chapter! diff --git a/src/doc/book/second-edition/src/ch12-00-an-io-project.md b/src/doc/book/second-edition/src/ch12-00-an-io-project.md index fca0b24194..0bc3092162 100644 --- a/src/doc/book/second-edition/src/ch12-00-an-io-project.md +++ b/src/doc/book/second-edition/src/ch12-00-an-io-project.md @@ -1,63 +1,50 @@ -# An I/O Project Building a Small Grep - - - - - -This chapter is both a recap of the many skills you've learned so far and an -exploration of a few more standard library features. We're going to build a -command-line tool that interacts with file and command line input/output to +# An I/O Project: Building a Command Line Program + +This chapter is both a recap of the many skills you’ve learned so far and an +exploration of a few more standard library features. We’re going to build a +command line tool that interacts with file and command line input/output to practice some of the Rust you now have under your belt. -Rust's speed, safety, 'single binary' output, and cross-platform support make -it a good language for creating command line tools, so for our project we'll +Rust’s speed, safety, *single binary* output, and cross-platform support make +it a good language for creating command line tools, so for our project we’ll make our own version of the classic command line tool `grep`. Grep is an -acronym for "Globally search a Regular Expression and Print." In the simplest -use case, `grep` searches a specified file for a specified string using the -following steps: - -- Take as arguments a filename and a string. -- Read the file. -- Find lines in the file that contain the string argument. -- Print out those lines. - -We'll also show how to use environment variables and print to standard error -instead of standard out; these techniques are commonly used in command line -tools. +acronym for “Globally search a Regular Expression and Print.” In the simplest +use case, `grep` searches a specified file for a specified string. To do so, +`grep` takes a filename and a string as its arguments, then reads the file and +finds lines in that file that contain the string argument. It’ll then print out +those lines. + +Along the way, we’ll show how to make our command line tool use features of the +terminal that many command line tools use. We'll read the value of an +environment variable in order to allow the user to configure the behavior of +our tool. We'll print to the standard error console stream (`stderr`) instead +of standard output (`stdout`) so that, for example, the user can choose to +redirect successful output to a file while still seeing error messages on the +screen. One Rust community member, Andrew Gallant, has already created a fully-featured, very fast version of `grep`, called `ripgrep`. By comparison, -our version of `grep` will be fairly simple, this chapter will give you some of -the background knowledge to help you understand a real-world project like -`ripgrep`. +our version of `grep` will be fairly simple, but this chapter will give you +some of the background knowledge to help you understand a real-world project +like `ripgrep`. -This project will bring together a number of concepts you've learned so far: +This project will bring together a number of concepts you’ve learned so far: -- Organizing code (using what we learned in modules, Chapter 7) -- Using vectors and strings (collections, Chapter 8) -- Handling errors (Chapter 9) -- Using traits and lifetimes where appropriate (Chapter 10) -- Writing tests (Chapter 11) +* Organizing code (using what we learned in modules, Chapter 7) +* Using vectors and strings (collections, Chapter 8) +* Handling errors (Chapter 9) +* Using traits and lifetimes where appropriate (Chapter 10) +* Writing tests (Chapter 11) -We'll also briefly introduce closures, iterators, and trait objects, which +We’ll also briefly introduce closures, iterators, and trait objects, which Chapters 13 and 17 will cover in detail. -Let's create a new project with, as always, `cargo new`. We're calling our -project `greprs` to distinguish from the `grep` tool that you may already have -on your system: +Let’s create a new project with, as always, `cargo new`. We’re calling our +project `minigrep` to distinguish from the `grep` tool that you may already +have on your system: ```text -$ cargo new --bin greprs - Created binary (application) `greprs` project -$ cd greprs +$ cargo new --bin minigrep + Created binary (application) `minigrep` project +$ cd minigrep ``` diff --git a/src/doc/book/second-edition/src/ch12-01-accepting-command-line-arguments.md b/src/doc/book/second-edition/src/ch12-01-accepting-command-line-arguments.md index 15a3a0f634..05fa16bb9e 100644 --- a/src/doc/book/second-edition/src/ch12-01-accepting-command-line-arguments.md +++ b/src/doc/book/second-edition/src/ch12-01-accepting-command-line-arguments.md @@ -1,6 +1,6 @@ ## Accepting Command Line Arguments -Our first task is to make `greprs` able to accept its two command line +Our first task is to make `minigrep` able to accept its two command line arguments: the filename and a string to search for. That is, we want to be able to run our program with `cargo run`, a string to search for, and a path to a file to search in, like so: @@ -9,40 +9,27 @@ file to search in, like so: $ cargo run searchstring example-filename.txt ``` -Right now, the program generated by `cargo new` ignores any arguments we give -it. There are some existing libraries on crates.io that can help us accept -command line arguments, but since we're learning, let's implement this +Right now, the program generated by `cargo new` cannot process arguments we +give it. There are some existing libraries on crates.io that can help us accept +command line arguments, but since you’re learning, let’s implement this ourselves. - - - ### Reading the Argument Values -In order to be able to get the values of command line arguments passed to our -program, we'll need to call a function provided in Rust's standard library: -`std::env::args`. This function returns an *iterator* of the command line -arguments that were given to our program. We haven't discussed iterators yet, -and we'll cover them fully in Chapter 13, but for our purposes now we only need -to know two things about iterators: - -1. Iterators produce a series of values. -2. We can call the `collect` function on an iterator to turn it into a vector - containing all of the elements the iterator produces. +We first need to make sure our program is able to get the values of command +line arguments we pass to it, for which we’ll need a function provided in +Rust’s standard library: `std::env::args`. This function returns an *iterator* +of the command line arguments that were given to our program. We haven’t +discussed iterators yet, and we’ll cover them fully in Chapter 13, but for our +purposes now we only need to know two things about iterators: Iterators produce +a series of values, and we can call the `collect` function on an iterator to +turn it into a collection, such as a vector, containing all of the elements the +iterator produces. -Let's give it a try: use the code in Listing 12-1 to read any command line -arguments passed to our `greprs` program and collect them into a vector. +Let’s give it a try: use the code in Listing 12-1 to allow your `minigrep` +program to read any command line arguments passed it and then collect the +values into a vector. - - Filename: src/main.rs @@ -58,82 +45,59 @@ fn main() { Listing 12-1: Collect the command line arguments into a vector and print them out - - First, we bring the `std::env` module into scope with a `use` statement so that we can use its `args` function. Notice the `std::env::args` function is nested in two levels of modules. As we talked about in Chapter 7, in cases where the -desired function is nested in more than one module, it's conventional to bring +desired function is nested in more than one module, it’s conventional to bring the parent module into scope, rather than the function itself. This lets us -easily use other functions from `std::env`. It's also less ambiguous than +easily use other functions from `std::env`. It’s also less ambiguous than adding `use std::env::args;` then calling the function with just `args`; that -might look like a function that's defined in the current module. - - - - +might easily be mistaken for a function that’s defined in the current module. -> Note: `std::env::args` will panic if any argument contains invalid Unicode. -> If you need to accept arguments containing invalid Unicode, use +> ### The `args` Function and Invalid Unicode +> +> Note that `std::env::args` will panic if any argument contains invalid +> Unicode. If you need to accept arguments containing invalid Unicode, use > `std::env::args_os` instead. That function returns `OsString` values instead -> of `String` values. We've chosen to use `std::env::args` here for simplicity +> of `String` values. We’ve chosen to use `std::env::args` here for simplicity > because `OsString` values differ per-platform and are more complex to work > with than `String` values. - - - - - On the first line of `main`, we call `env::args`, and immediately use `collect` -to turn the iterator into a vector containing all of the iterator's values. The -`collect` function can be used to create many kinds of collections, so we -explicitly annotate the type of `args` to specify that we want a vector of -strings. Though we very rarely need to annotate types in Rust, `collect` is one -function you do often need to annotate because Rust isn't able to infer what -kind of collection you want. - -Finally, we print out the vector with the debug formatter, `:?`. Let's try +to turn the iterator into a vector containing all of the values produced by the +iterator. The `collect` function can be used to create many kinds of +collections, so we explicitly annotate the type of `args` to specify that we +want a vector of strings. Though we very rarely need to annotate types in Rust, +`collect` is one function you do often need to annotate because Rust isn’t able +to infer what kind of collection you want. + +Finally, we print out the vector with the debug formatter, `:?`. Let’s try running our code with no arguments, and then with two arguments: ```text $ cargo run -["target/debug/greprs"] +["target/debug/minigrep"] $ cargo run needle haystack ...snip... -["target/debug/greprs", "needle", "haystack"] +["target/debug/minigrep", "needle", "haystack"] ``` - - - -You may notice that the first value in the vector is "target/debug/greprs", -which is the name of our binary. The reasons for this are out of the scope of -this chapter, but we'll need to remember this as we save the two arguments we -need. +You may notice that the first value in the vector is `"target/debug/minigrep"`, +which is the name of our binary. This matches the behavior of the arguments +list in C, and lets programs use the name by which they were invoked in their +execution. It's convenient to have access to the program name in case we want +to print it in messages or change behavior of the program based on what command +line alias was used to invoke the program, but for the purposes of this chapter +we're going to ignore it and only save the two arguments we need. ### Saving the Argument Values in Variables -Printing out the value of the vector of arguments just illustrated that we're -able to access the values specified as command line arguments from our program. -That's not what we actually want to do, though, we want to save the values of -the two arguments in variables so that we can use the values in our program. -Let's do that as shown in Listing 12-2: - - - +Printing out the value of the vector of arguments has illustrated that the +program is able to access the values specified as command line arguments. +That’s not actually our end goal, though: we want to save the values of the two +arguments in variables so that we can use the values in our program. Let’s do +that as shown in Listing 12-2: Filename: src/main.rs @@ -153,28 +117,27 @@ fn main() { Listing 12-2: Create variables to hold the query argument and filename argument - - -As we saw when we printed out the vector, the program's name takes up the first -value in the vector at `args[0]`, so we're starting at index `1`. The first -argument `greprs` takes is the string we're searching for, so we put a +As we saw when we printed out the vector, the program’s name takes up the first +value in the vector at `args[0]`, so that we’re starting at index `1`. The +first argument `minigrep` takes is the string we’re searching for, so we put a reference to the first argument in the variable `query`. The second argument will be the filename, so we put a reference to the second argument in the variable `filename`. -We're temporarily printing out the values of these variables, again to prove to -ourselves that our code is working as we intend. Let's try running this program +We’re temporarily printing out the values of these variables, again to prove to +ourselves that our code is working as we intend. Let’s try running this program again with the arguments `test` and `sample.txt`: ```text $ cargo run test sample.txt Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs - Running `target/debug/greprs test sample.txt` + Running `target/debug/minigrep test sample.txt` Searching for test In file sample.txt ``` -Great, it's working! We're saving the values of the arguments that we need into -the right variables. Later we'll add some error handling to deal with -situations such as when the user provides no arguments, but for now we'll -ignore that and work on adding file reading capabilities instead. +Great, it’s working! The values of the arguments we need are being saved into +the right variables. Later we’ll add some error handling to deal with certain +potential erroneous situations, such as when the user provides no arguments, +but for now we’ll ignore that and work on adding file reading capabilities +instead. diff --git a/src/doc/book/second-edition/src/ch12-02-reading-a-file.md b/src/doc/book/second-edition/src/ch12-02-reading-a-file.md index a07422c938..1d21ba0990 100644 --- a/src/doc/book/second-edition/src/ch12-02-reading-a-file.md +++ b/src/doc/book/second-edition/src/ch12-02-reading-a-file.md @@ -1,19 +1,20 @@ ## Reading a File -Next, we're going to read the file that we specify in the filename command line -argument. First, we need a sample file to test it with---the best kind of file -to use to make sure that `greprs` is working is one with a small amount of text -over multiple lines with some repeated words. Listing 12-3 has an Emily -Dickinson poem that will work well! Create a file called `poem.txt` at the root -level of your project, and enter the poem "I'm nobody! Who are you?": +Next, we’re going to add functionality to read the file that specified in the +`filename` command line argument. First, we need a sample file to test it +with—the best kind of file to use to make sure that `minigrep` is working is +one with a small amount of text over multiple lines with some repeated words. +Listing 12-3 has an Emily Dickinson poem that will work well! Create a file +called `poem.txt` at the root level of your project, and enter the poem “I’m +nobody! Who are you?”: Filename: poem.txt ```text -I'm nobody! Who are you? +I’m nobody! Who are you? Are you nobody, too? -Then there's a pair of us — don't tell! -They'd banish us, you know. +Then there’s a pair of us — don’t tell! +They’d banish us, you know. How dreary to be somebody! How public, like a frog @@ -21,16 +22,9 @@ To tell your name the livelong day To an admiring bog! ``` -Listing 12-3: The poem "I'm nobody! Who are you?" by +Listing 12-3: The poem “I’m nobody! Who are you?” by Emily Dickinson that will make a good test case - - - - With that in place, edit *src/main.rs* and add code to open the file as shown in Listing 12-4: @@ -42,61 +36,62 @@ use std::fs::File; use std::io::prelude::*; fn main() { - let args: Vec = env::args().collect(); - - let query = &args[1]; - let filename = &args[2]; - - println!("Searching for {}", query); +# let args: Vec = env::args().collect(); +# +# let query = &args[1]; +# let filename = &args[2]; +# +# println!("Searching for {}", query); + // ...snip... println!("In file {}", filename); let mut f = File::open(filename).expect("file not found"); let mut contents = String::new(); - f.read_to_string(&mut contents).expect("something went wrong reading the file"); + f.read_to_string(&mut contents) + .expect("something went wrong reading the file"); println!("With text:\n{}", contents); } ``` -Listing 12-4: Reading the contents of the file specified by the second argument - - +Listing 12-4: Reading the contents of the file specified +by the second argument First, we add some more `use` statements to bring in relevant parts of the standard library: we need `std::fs::File` for dealing with files, and `std::io::prelude::*` contains various traits that are useful when doing I/O, including file I/O. In the same way that Rust has a general prelude that brings certain things into scope automatically, the `std::io` module has its own -prelude of common things you'll need when working with I/O. Unlike the default -prelude, we must explicitly `use` the prelude in `std::io`. +prelude of common things you’ll need when working with I/O. Unlike the default +prelude, we must explicitly `use` the prelude from `std::io`. -In `main`, we've added three things: first, we get a mutable handle to the file +In `main`, we’ve added three things: first, we get a mutable handle to the file by calling the `File::open` function and passing it the value of the `filename` variable. Second, we create a variable called `contents` and set it to a mutable, empty `String`. This will hold the content of the file after we read it in. Third, we call `read_to_string` on our file handle and pass a mutable reference to `contents` as an argument. -After those lines, we've again added temporary `println!` that prints out the -value in `contents` after we've read the file so we can check that our program -is working so far. +After those lines, we’ve again added a temporary `println!` statement that +prints out the value of `contents` after the file is read, so that we can check +that our program is working so far. -Let's try running this code with any string as the first command line argument -(since we haven't implemented the searching part yet) and our *poem.txt* file +Let’s try running this code with any string as the first command line argument +(since we haven’t implemented the searching part yet) and our *poem.txt* file as the second argument: ```text $ cargo run the poem.txt Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs - Running `target/debug/greprs the poem.txt` + Running `target/debug/minigrep the poem.txt` Searching for the In file poem.txt With text: -I'm nobody! Who are you? +I’m nobody! Who are you? Are you nobody, too? -Then there's a pair of us — don't tell! -They'd banish us, you know. +Then there’s a pair of us — don’t tell! +They’d banish us, you know. How dreary to be somebody! How public, like a frog @@ -104,10 +99,11 @@ To tell your name the livelong day To an admiring bog! ``` -Great! Our code read in and printed out the content of the file. We've got a -few flaws though: the `main` function has multiple responsibilities, and we're -not handling errors as well as we could be. While our program is still small, -these flaws aren't a big problem, but as our program grows, it will be harder -to fix them cleanly. It's good practice to begin refactoring early on when -developing a program, as it's much easier to refactor smaller amounts of code, -so we'll do that now. +Great! Our code read in and printed out the content of the file. We’ve got a +few flaws though. The `main` function has multiple responsibilities; generally +functions are clearer and easier to maintain if each function is responsible +for only one idea. The other problem is that we’re not handling errors as well +as we could be. While our program is still small, these flaws aren’t a big +problem, but as our program grows, it will be harder to fix them cleanly. It’s +good practice to begin refactoring early on when developing a program, as it’s +much easier to refactor smaller amounts of code, so we’ll do that now. diff --git a/src/doc/book/second-edition/src/ch12-03-improving-error-handling-and-modularity.md b/src/doc/book/second-edition/src/ch12-03-improving-error-handling-and-modularity.md index cd83f7091a..1d39796974 100644 --- a/src/doc/book/second-edition/src/ch12-03-improving-error-handling-and-modularity.md +++ b/src/doc/book/second-edition/src/ch12-03-improving-error-handling-and-modularity.md @@ -1,78 +1,74 @@ ## Refactoring to Improve Modularity and Error Handling -There are four problems that we'd like to fix to improve our program, and they -have to do with the way the program is structured and how it's handling +There are four problems that we’d like to fix to improve our program, and they +have to do with the way the program is structured and how it’s handling potential errors. First, our `main` function now performs two tasks: it parses arguments and -opens up files. For such a small function, this isn't a huge problem. However, +opens up files. For such a small function, this isn’t a huge problem. However, if we keep growing our program inside of `main`, the number of separate tasks the `main` function handles will grow. As a function gains responsibilities, it gets harder to reason about, harder to test, and harder to change without -breaking one of its parts. It's better to separate out functionality so that +breaking one of its parts. It’s better to separate out functionality so that each function is responsible for one task. This also ties into our second problem: while `query` and `filename` are configuration variables to our program, variables like `f` and `contents` are -used to perform our program's logic. The longer `main` gets, the more variables -we're going to need to bring into scope; the more variables we have in scope, -the harder it is to keep track of the purpose of each. It's better to group the +used to perform our program’s logic. The longer `main` gets, the more variables +we’re going to need to bring into scope; the more variables we have in scope, +the harder it is to keep track of the purpose of each. It’s better to group the configuration variables into one structure to make their purpose clear. -The third problem is that we've used `expect` to print out an error message if -opening the file fails, but the error message only says `file not found`. There -are a number of ways that opening a file can fail besides a missing file: for -example, the file might exist, but we might not have permission to open it. -Right now, if we're in that situation, we'd print the `file not found` error -message that would give the user the wrong advice! +The third problem is that we’ve used `expect` to print out an error message +when opening the file fails, but the error message only says `file not found`. +There are a number of ways that opening a file can fail besides the file being +missing: for example, the file might exist, but we might not have permission to +open it. Right now, if we’re in that situation, we’d print the `file not found` +error message that would give the user the wrong advice! Fourth, we use `expect` repeatedly to deal with different errors, and if the -user runs our programs without specifying enough arguments, they'll get an -"index out of bounds" error from Rust that doesn't clearly explain the problem. +user runs our programs without specifying enough arguments, they’ll get an +“index out of bounds” error from Rust that doesn’t clearly explain the problem. It would be better if all our error handling code was in one place so that future maintainers only have one place to consult in the code if the error handling logic needs to change. Having all the error handling code in one place -will also help us to ensure that we're printing messages that will be +will also help us to ensure that we’re printing messages that will be meaningful to our end users. -Let's address these problems by refactoring our project. +Let’s address these problems by refactoring our project. ### Separation of Concerns for Binary Projects -The organizational problem of having the `main` function responsible for -multiple tasks is common to many binary projects, so the Rust community has -developed a kind of guideline process for splitting up the separate concerns of -a binary program when `main` starts getting large. The process has the -following steps: - -1. Split your program into both a *main.rs* and a *lib.rs* and move your - program's logic into *lib.rs*. -2. While your command line parsing logic is small, it can remain in *main.rs*. -3. When the command line parsing logic starts getting complicated, extract it - from *main.rs* into *lib.rs* as well. -4. The responsibilities that remain in the `main` function after this process - should be: - * Calling the command line parsing logic with the argument values - * Setting up any other configuration - * Calling a `run` function in *lib.rs* - * If `run` returns an error, handling that error +The organizational problem of allocating responsibility for multiple tasks to +the `main` function responsible is common to many binary projects, so the Rust +community has developed a kind of guideline process for splitting up the +separate concerns of a binary program when `main` starts getting large. The +process has the following steps: + +* Split your program into both a *main.rs* and a *lib.rs* and move your +program’s logic into *lib.rs*. +* While your command line parsing logic is small, it can remain in *main.rs*. +* When the command line parsing logic starts getting complicated, extract it +from *main.rs* into *lib.rs* as well. +* The responsibilities that remain in the `main` function after this process +should be limited to: + * Calling the command line parsing logic with the argument values + * Setting up any other configuration + * Calling a `run` function in *lib.rs* + * If `run` returns an error, handling that error This pattern is all about separating concerns: *main.rs* handles running the program, and *lib.rs* handles all of the logic of the task at hand. Because we -can't test the `main` function directly, this structure lets us test all of our -program's logic by moving it into functions in *lib.rs*. The only code that +can’t test the `main` function directly, this structure lets us test all of our +program’s logic by moving it into functions in *lib.rs*. The only code that remains in *main.rs* will be small enough to verify its correctness by reading -it. Let's re-work our program by following this process. +it. Let’s re-work our program by following this process. - - +#### Extracting the Argument Parser -### Extracting the Argument Parser - -First, we'll extract the functionality for parsing arguments. Listing 12-5 +First, we’ll extract the functionality for parsing arguments. Listing 12-5 shows the new start of `main` that calls a new function `parse_config`, which -we're still going to define in *src/main.rs* for the moment: +we’re still going to define in *src/main.rs* for the moment: Filename: src/main.rs @@ -96,55 +92,42 @@ fn parse_config(args: &[String]) -> (&str, &str) { Listing 12-5: Extract a `parse_config` function from `main` - - -We're still collecting the command line arguments into a vector, but instead of -assigning the argument value at index 1 to the variable `query` and the -argument value at index 2 to the variable `filename` within the `main` +We’re still collecting the command line arguments into a vector, but instead of +assigning the argument value at index `1` to the variable `query` and the +argument value at index `2` to the variable `filename` within the `main` function, we pass the whole vector to the `parse_config` function. The -`parse_config` function then holds the logic that knows which argument goes in -which variable, and passes the values back to `main`. We still create the -`query` and `filename` variables in `main`, but `main` no longer has the -responsibility of knowing how the command line arguments and variables +`parse_config` function then holds the logic that determines which argument +goes in which variable, and passes the values back to `main`. We still create +the `query` and `filename` variables in `main`, but `main` no longer has the +responsibility of determining how the command line arguments and variables correspond. -This may seem like overkill for our small program, but we're refactoring in +This may seem like overkill for our small program, but we’re refactoring in small, incremental steps. After making this change, run the program again to -verify that the argument parsing still works. It's good to check your progress +verify that the argument parsing still works. It’s good to check your progress often, as that will help you identify the cause of problems when they occur. #### Grouping Configuration Values We can take another small step to improve this function further. At the moment, -we're returning a tuple, but then we immediately break that tuple up into -individual parts again. This is a sign that perhaps we don't have the right +we’re returning a tuple, but then we immediately break that tuple up into +individual parts again. This is a sign that perhaps we don’t have the right abstraction yet. -Another indicator that there's room for improvement is the `config` part of +Another indicator that there’s room for improvement is the `config` part of `parse_config`, which implies that the two values we return are related and are -both part of one configuration value. We're not currently conveying this +both part of one configuration value. We’re not currently conveying this meaning in the structure of the data other than grouping the two values into a tuple: we could put the two values into one struct and give each of the struct fields a meaningful name. This will make it easier for future maintainers of this code to understand how the different values relate to each other and what their purpose is. - - > Note: some people call this anti-pattern of using primitive values when a > complex type would be more appropriate *primitive obsession*. - - - Listing 12-6 shows the addition of a struct named `Config` defined to have -fields named `query` and `filename`. We've also changed the `parse_config` +fields named `query` and `filename`. We’ve also changed the `parse_config` function to return an instance of the `Config` struct, and updated `main` to use the struct fields rather than having separate variables: @@ -180,17 +163,15 @@ fn parse_config(args: &[String]) -> Config { } ``` -Listing 12-6: Refactoring `parse_config` to return an instance of a `Config` -struct - - +Listing 12-6: Refactoring `parse_config` to return an +instance of a `Config` struct The signature of `parse_config` now indicates that it returns a `Config` value. In the body of `parse_config`, where we used to return string slices that -reference `String` values in `args`, we've now chosen to define `Config` to +reference `String` values in `args`, we’ve now chosen to define `Config` to contain owned `String` values. The `args` variable in `main` is the owner of the argument values and is only letting the `parse_config` function borrow -them, though, which means we'd violate Rust's borrowing rules if `Config` tried +them, though, which means we’d violate Rust’s borrowing rules if `Config` tried to take ownership of the values in `args`. There are a number of different ways we could manage the `String` data, and the @@ -198,59 +179,39 @@ easiest, though somewhat inefficient, route is to call the `clone` method on the values. This will make a full copy of the data for the `Config` instance to own, which does take more time and memory than storing a reference to the string data. However, cloning the data also makes our code very straightforward -since we don't have to manage the lifetimes of the references, so in this +since we don’t have to manage the lifetimes of the references, so in this circumstance giving up a little performance to gain simplicity is a worthwhile trade-off. - - - - -> #### The Tradeoffs of Using `clone` +> ### The Tradeoffs of Using `clone` > -> There's a tendency among many Rustaceans to avoid using `clone` to fix +> There’s a tendency among many Rustaceans to avoid using `clone` to fix > ownership problems because of its runtime cost. In Chapter 13 on iterators, -> you'll learn how to use more efficient methods in this kind of situation, but -> for now, it's okay to copy a few strings to keep making progress since we'll +> you’ll learn how to use more efficient methods in this kind of situation, but +> for now, it’s okay to copy a few strings to keep making progress since we’ll > only make these copies once, and our filename and query string are both very -> small. It's better to have a working program that's a bit inefficient than -> try to hyper-optimize code on your first pass. As you get more experienced -> with Rust, it'll be easier to go straight to the desirable method, but for -> now it's perfectly acceptable to call `clone`. - - +> small. It’s better to have a working program that’s a bit inefficient than try +> to hyper-optimize code on your first pass. As you get more experienced with +> Rust, it’ll be easier to go straight to the desirable method, but for now it’s +> perfectly acceptable to call `clone`. -We've updated `main` so that it places the instance of `Config` that -`parse_config` returns into a variable named `config`, and updated the code -that previously used the separate `query` and `filename` variables so that is -now uses the fields on the `Config` struct instead. +We’ve updated `main` so that it places the instance of `Config` returned by +`parse_config` into a variable named `config`, and updated the code that +previously used the separate `query` and `filename` variables so that it now +uses the fields on the `Config` struct instead. -Our code now more clearly conveys our intent that `query` and `filename` are -related and their purpose is to configure how the program will work. Any code -that uses these values knows to find them in the `config` instance in the -fields named for their purpose. +Our code now more clearly conveys that `query` and `filename` are related and +their purpose is to configure how the program will work. Any code that uses +these values knows to find them in the `config` instance in the fields named +for their purpose. #### Creating a Constructor for `Config` - - - -So far, we've extracted the logic responsible for parsing the command line +So far, we’ve extracted the logic responsible for parsing the command line arguments from `main` into the `parse_config` function, which helped us to see that the `query` and `filename` values were related and that relationship should be conveyed in our code. We then added a `Config` struct to name the -related purpose of `query` and `filename`, and to be able to return the values' +related purpose of `query` and `filename`, and to be able to return the values’ names as struct field names from the `parse_config` function. So now that the purpose of the `parse_config` function is to create a `Config` @@ -258,9 +219,9 @@ instance, we can change `parse_config` from being a plain function into a function named `new` that is associated with the `Config` struct. Making this change will make our code more idiomatic: we can create instances of types in the standard library like `String` by calling `String::new`, and by changing -`parse_config` to be a `new` function associated with `Config`, we'll be able -to create instances of `Config` by calling `Config::new`. Listing 12-7 shows -the changes we'll need to make: +`parse_config` into a `new` function associated with `Config`, we’ll be able to +create instances of `Config` by calling `Config::new`. Listing 12-7 shows the +changes we’ll need to make: Filename: src/main.rs @@ -295,39 +256,37 @@ impl Config { Listing 12-7: Changing `parse_config` into `Config::new` - - -We've updated `main` where we were calling `parse_config` to instead call -`Config::new`. We've changed the name of `parse_config` to `new` and moved it +We’ve updated `main` where we were calling `parse_config` to instead call +`Config::new`. We’ve changed the name of `parse_config` to `new` and moved it within an `impl` block, which makes the `new` function associated with `Config`. Try compiling this again to make sure it works. ### Fixing the Error Handling -Now we'll work on fixing our error handling. Recall that we mentioned -attempting to access the values in the `args` vector at index 1 or index 2 will -cause the program to panic if the vector contains fewer than 3 items. Try +Now we’ll work on fixing our error handling. Recall that we mentioned that +attempting to access the values in the `args` vector at index `1` or index `2` +will cause the program to panic if the vector contains fewer than 3 items. Try running the program without any arguments; it will look like this: ```text $ cargo run Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs - Running `target/debug/greprs` + Running `target/debug/minigrep` thread 'main' panicked at 'index out of bounds: the len is 1 -but the index is 1', /stable-dist-rustc/build/src/libcollections/vec.rs:1307 +but the index is 1', /stable-dist-rustc/build/src/libcollections/vec.rs:1307 note: Run with `RUST_BACKTRACE=1` for a backtrace. ``` -`index out of bounds: the len is 1 but the index is 1` is an error message that -is intended for programmers, and won't really help our end users understand -what happened and what they should do instead. Let's fix that now. +The line that states `index out of bounds: the len is 1 but the index is 1` is +an error message intended for programmers, and won’t really help our end users +understand what happened and what they should do instead. Let’s fix that now. #### Improving the Error Message -In Listing 12-8, we're adding a check in the `new` function to check that the -slice is long enough before accessing index 1 and 2. If the slice isn't long -enough, we panic with a better error message than the `index out of bounds` -message: +In Listing 12-8, we’re adding a check in the `new` function that will check +that the slice is long enough before accessing index `1` and `2`. If the slice +isn’t long enough, the program panics, with a better error message than the +`index out of bounds` message: Filename: src/main.rs @@ -343,51 +302,45 @@ fn new(args: &[String]) -> Config { Listing 12-8: Adding a check for the number of arguments - - -This is similar to the `Guess::new` function we wrote in Listing 9-8, where we -called `panic!` if the `value` argument was out of the range of valid values. -Instead of checking for a range of values, we're checking that the length of -`args` is at least 3, and the rest of the function can operate under the -assumption that this condition has been met. If `args` has fewer than 3 items, -this condition will be true, and we call the `panic!` macro to end the program -immediately. +This is similar to the `Guess::new` function we wrote in Listing 9-8, where +`panic!` was called when the `value` argument was out of the range of valid +values. Instead of checking for a range of values here, we’re checking that the +length of `args` is at least 3, and the rest of the function can operate under +the assumption that this condition has been met. If `args` has fewer than 3 +items, this condition will be true, and we call the `panic!` macro to end the +program immediately. -With these extra few lines of code in `new`, let's try running our program +With these extra few lines of code in `new`, let’s try running our program without any arguments again and see what the error looks like now: ```bash $ cargo run Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs - Running `target/debug/greprs` + Running `target/debug/minigrep` thread 'main' panicked at 'not enough arguments', src/main.rs:29 note: Run with `RUST_BACKTRACE=1` for a backtrace. ``` This output is better, we now have a reasonable error message. However, we also -have a bunch of extra information we don't want to give to our users. So -perhaps using the technique we used in Listing 9-8 isn't the best to use here; +have a bunch of extra information we don’t want to give to our users. So +perhaps using the technique we used in Listing 9-8 isn’t the best to use here; a call to `panic!` is more appropriate for a programming problem rather than a -usage problem anyway, as we discussed in Chapter 9. Instead, we can use the -other technique we learned about in that chapter: returning a `Result` that can +usage problem, as we discussed in Chapter 9. Instead, we can use the other +technique you also learned about in Chapter 9: returning a `Result` that can indicate either success or an error. - - - #### Returning a `Result` from `new` Instead of Calling `panic!` We can choose to instead return a `Result` value that will contain a `Config` instance in the successful case, and will describe the problem in the error -case. When `Config::new` is communicating to `main`, we can use Rust's way of -signaling that there was a problem using the `Result` type. Then we can change -`main` to convert an `Err` variant into a nicer error for our users, without -the surrounding text about `thread 'main'` and `RUST_BACKTRACE` that a call to +case. When `Config::new` is communicating to `main`, we can use the `Result` +type to signal that there was a problem. Then we can change `main` to convert +an `Err` variant into a more practical error for our users, without the +surrounding text about `thread 'main'` and `RUST_BACKTRACE` that a call to `panic!` causes. -Listing 12-9 shows the changes to the return value of `Config::new` and the -body of the function needed to return a `Result`: +Listing 12-9 shows the changes you need to make to the return value of +`Config::new` and the body of the function needed to return a `Result`: Filename: src/main.rs @@ -408,20 +361,14 @@ impl Config { Listing 12-9: Return a `Result` from `Config::new` - - - - - Our `new` function now returns a `Result`, with a `Config` instance in the -success case and a `&'static str` in the error case. Recall from "The Static -Lifetime" section in Chapter 10 that `&'static str` is the type of string +success case and a `&'static str` in the error case. Recall from “The Static +Lifetime” section in Chapter 10 that `&'static str` is the type of string literals, which is our error message type for now. -We've made two changes in the body of the `new` function: instead of calling -`panic!` when the user doesn't pass enough arguments, we now return an `Err` -value, and we've wrapped the `Config` return value in an `Ok`. These changes +We’ve made two changes in the body of the `new` function: instead of calling +`panic!` when the user doesn’t pass enough arguments, we now return an `Err` +value, and we’ve wrapped the `Config` return value in an `Ok`. These changes make the function conform to its new type signature. By having `Config::new` return an `Err` value, it allows the `main` function to @@ -431,11 +378,11 @@ more cleanly in the error case. #### Calling `Config::new` and Handling Errors In order to handle the error case and print a user-friendly message, we need to -update `main` to handle the `Result` that `Config::new` is now returning as -shown in Listing 12-10. We're also going to implement by hand something that -`panic!` handled for us: exiting the command line tool with an error code of 1. -A nonzero exit status is a convention to signal to the process that called our -program that our program ended with an error state. +update `main` to handle the `Result` being returned by `Config::new`, as shown +in Listing 12-10. We’re also going to take the responsibility of exiting the +command line tool with a nonzero error code from `panic!` and implement it by +hand. A nonzero exit status is a convention to signal to the process that +called our program that our program ended with an error state. Filename: src/main.rs @@ -456,73 +403,49 @@ fn main() { Listing 12-10: Exiting with an error code if creating a new `Config` fails - - - - - - -In this listing, we're using a method we haven't covered before: +In this listing, we’re using a method we haven’t covered before: `unwrap_or_else`, which is defined on `Result` by the standard library. Using `unwrap_or_else` allows us to define some custom, non-`panic!` error -handling. If the `Result` is an `Ok` value, this method's behavior is similar +handling. If the `Result` is an `Ok` value, this method’s behavior is similar to `unwrap`: it returns the inner value `Ok` is wrapping. However, if the value is an `Err` value, this method calls the code in the *closure*, which is an -anonymous function we define and pass as an argument to `unwrap_or_else`. We'll +anonymous function we define and pass as an argument to `unwrap_or_else`. We’ll be covering closures in more detail in Chapter 13. What you need to know for now is that `unwrap_or_else` will pass the inner value of the `Err`, which in this case is the static string `not enough arguments` that we added in Listing 12-9, to our closure in the argument `err` that appears between the vertical pipes. The code in the closure can then use the `err` value when it runs. - - - -We've added a new `use` line to import `process` from the standard library. The +We’ve added a new `use` line to import `process` from the standard library. The code in the closure that will get run in the error case is only two lines: we -print out the `err` value, then call `std::process::exit` (we've added a new -`use` line at the top to import `process` from the standard library). -`process::exit` will stop the program immediately and return the number that -was passed as the exit status code. This is similar to the `panic!`-based -handling we used in Listing 12-8, with the exception that we no longer get all -the extra output. Let's try it: +print out the `err` value, then call `process::exit`. The `process::exit` +function will stop the program immediately and return the number that was +passed as the exit status code. This is similar to the `panic!`-based handling +we used in Listing 12-8, with the exception that we no longer get all the extra +output. Let’s try it: ```text $ cargo run - Compiling greprs v0.1.0 (file:///projects/greprs) + Compiling minigrep v0.1.0 (file:///projects/minigrep) Finished dev [unoptimized + debuginfo] target(s) in 0.48 secs - Running `target/debug/greprs` + Running `target/debug/minigrep` Problem parsing arguments: not enough arguments ``` Great! This output is much friendlier for our users. -### Extracting a `run` Function - -Now we're done refactoring our configuration parsing; let's turn to our -program's logic. As we laid out in the process we discussed in the "Separation -of Concerns for Binary Projects" section, we're going to extract a function -named `run` that will hold all of the logic currently in the `main` function -that isn't setting up configuration or handling errors. Once we're done, `main` -will be concise and easy to verify by inspection, and we'll be able to write -tests for all of the other logic. - - - - -Listing 12-11 shows the extracted `run` function. For now, we're making only -the small, incremental improvement of extracting the function and still +### Extracting Logic from `main` + +Now we’re done refactoring our configuration parsing; let’s turn to our +program’s logic. As we laid out in the “Separation of Concerns for Binary +Projects” section, we’re going to extract a function named `run` that will hold +all of the logic currently in the `main` function not involved with setting up +configuration or handling errors. Once we’re done, `main` will be concise and +easy to verify by inspection, and we’ll be able to write tests for all of the +other logic. + +Listing 12-11 shows the extracted `run` function. For now, we’re making only +the small, incremental improvement of extracting the function. We’re still defining the function in *src/main.rs*: Filename: src/main.rs @@ -541,7 +464,8 @@ fn run(config: Config) { let mut f = File::open(config.filename).expect("file not found"); let mut contents = String::new(); - f.read_to_string(&mut contents).expect("something went wrong reading the file"); + f.read_to_string(&mut contents) + .expect("something went wrong reading the file"); println!("With text:\n{}", contents); } @@ -552,21 +476,19 @@ fn run(config: Config) { Listing 12-11: Extracting a `run` function containing the rest of the program logic - - The `run` function now contains all the remaining logic from `main` starting from reading the file. The `run` function takes the `Config` instance as an argument. #### Returning Errors from the `run` Function -With the remaining program logic separated into the `run` function rather than -being in `main`, we can improve the error handling like we did with -`Config::new` in Listing 12-9. Instead of allowing the program to panic by -calling `expect`, the `run` function will return a `Result` when -something goes wrong. This will let us further consolidate the logic around -handling errors in a user-friendly way into `main`. Listing 12-12 shows the -changes to the signature and body of `run`: +With the remaining program logic separated into the `run` function, we can +improve the error handling like we did with `Config::new` in Listing 12-9. +Instead of allowing the program to panic by calling `expect`, the `run` +function will return a `Result` when something goes wrong. This will let +us further consolidate the logic around handling errors in a user-friendly way +into `main`. Listing 12-12 shows the changes you need to make to the signature +and body of `run`: Filename: src/main.rs @@ -590,39 +512,34 @@ fn run(config: Config) -> Result<(), Box> { Listing 12-12: Changing the `run` function to return `Result` - - -We've made three big changes here. First, we're changing the return type of the +We’ve made three big changes here. First, we’re changing the return type of the `run` function to `Result<(), Box>`. This function previously returned the unit type, `()`, and we keep that as the value returned in the `Ok` case. - - - -For our error type, we're using the *trait object* `Box` (and we've +For our error type, we’re using the *trait object* `Box` (and we’ve brought `std::error::Error` into scope with a `use` statement at the top). -We'll be covering trait objects in Chapter 17. For now, just know that +We’ll be covering trait objects in Chapter 17. For now, just know that `Box` means the function will return a type that implements the `Error` -trait, but we don't have to specify what particular type the return value will +trait, but we don’t have to specify what particular type the return value will be. This gives us flexibility to return error values that may be of different types in different error cases. -The second change we're making is removing the calls to `expect` in favor of +The second change we’re making is removing the calls to `expect` in favor of `?`, like we talked about in Chapter 9. Rather than `panic!` on an error, this will return the error value from the current function for the caller to handle. -Thirdly, this function now returns an `Ok` value in the success case. We've -declared the `run` function's success type as `()` in the signature, which +Thirdly, this function now returns an `Ok` value in the success case. We’ve +declared the `run` function’s success type as `()` in the signature, which means we need to wrap the unit type value in the `Ok` value. This `Ok(())` syntax may look a bit strange at first, but using `()` like this is the -idiomatic way to indicate that we're calling `run` for its side effects only; -it doesn't return a value we need. +idiomatic way to indicate that we’re calling `run` for its side effects only; +it doesn’t return a value we need. When you run this, it will compile, but with a warning: ```text -warning: unused result which must be used, #[warn(unused_must_use)] on by default +warning: unused result which must be used, #[warn(unused_must_use)] on by +default --> src/main.rs:39:5 | 39 | run(config); @@ -630,14 +547,14 @@ warning: unused result which must be used, #[warn(unused_must_use)] on by defaul ``` Rust is telling us that our code ignores the `Result` value, which might be -indicating that there was an error. We're not checking to see if there was an +indicating that there was an error. We’re not checking to see if there was an error or not, though, and the compiler is reminding us that we probably meant -to have some error handling code here! Let's rectify that now. +to have some error handling code here! Let’s rectify that now. #### Handling Errors Returned from `run` in `main` -We'll check for errors and handle them nicely using a similar technique to the -way we handled errors with `Config::new` in Listing 12-10, but with a slight +We’ll check for errors and handle them using a similar technique to the way we +handled errors with `Config::new` in Listing 12-10, but with a slight difference: Filename: src/main.rs @@ -657,33 +574,32 @@ fn main() { } ``` - - We use `if let` to check whether `run` returns an `Err` value, rather than -`unwrap_or_else`, and call `process::exit(1)` if it does. `run` doesn't return +`unwrap_or_else`, and call `process::exit(1)` if it does. `run` doesn’t return a value that we want to `unwrap` like `Config::new` returns the `Config` instance. Because `run` returns a `()` in the success case, we only care about -detecting an error, so we don't need `unwrap_or_else` to return the unwrapped +detecting an error, so we don’t need `unwrap_or_else` to return the unwrapped value as it would only be `()`. The bodies of the `if let` and the `unwrap_or_else` functions are the same in both cases though: we print out the error and exit. -### Split Code into a Library Crate +### Splitting Code into a Library Crate -This is looking pretty good so far! Now we're going to split the *src/main.rs* +This is looking pretty good so far! Now we’re going to split the *src/main.rs* file up and put some code into *src/lib.rs* so that we can test it and have a -small `main` function. +*src/main.rs* file with fewer responsibilities. -Let's move the following pieces of code from *src/main.rs* to a new file, -*src/lib.rs*: +Let’s move everything that isn't the `main` function from *src/main.rs* to a +new file, *src/lib.rs*: -- The `run` function definition -- The relevant `use` statements -- The definition of `Config` -- The `Config::new` function definition +* The `run` function definition +* The relevant `use` statements +* The definition of `Config` +* The `Config::new` function definition -The contents of *src/lib.rs* should now look like Listing 12-13: +The contents of *src/lib.rs* should have the signatures shown in Listing 12-13 +(we've omitted the bodies of the functions for brevity): Filename: src/lib.rs @@ -699,92 +615,58 @@ pub struct Config { impl Config { pub fn new(args: &[String]) -> Result { - if args.len() < 3 { - return Err("not enough arguments"); - } - - let query = args[1].clone(); - let filename = args[2].clone(); - - Ok(Config { query, filename }) + // ...snip... } } -pub fn run(config: Config) -> Result<(), Box>{ - let mut f = File::open(config.filename)?; - - let mut contents = String::new(); - f.read_to_string(&mut contents)?; - - println!("With text:\n{}", contents); - - Ok(()) +pub fn run(config: Config) -> Result<(), Box> { + // ...snip... } ``` Listing 12-13: Moving `Config` and `run` into *src/lib.rs* - - -We've made liberal use of `pub` here: on `Config`, its fields and its `new` +We’ve made liberal use of `pub` here: on `Config`, its fields and its `new` method, and on the `run` function. We now have a library crate that has a -public API that we can test. - -#### Calling the Library Crate from the Binary Crate +public API that we can test! Now we need to bring the code we moved to *src/lib.rs* into the scope of the -binary crate in *src/main.rs* by using `extern crate greprs`. Then we'll add a -`use greprs::Config` line to bring the `Config` type into scope, and prefix the -`run` function with our crate name as shown in Listing 12-14: +binary crate in *src/main.rs* by using `extern crate minigrep`. Then we’ll add +a `use minigrep::Config` line to bring the `Config` type into scope, and prefix +the `run` function with our crate name as shown in Listing 12-14: Filename: src/main.rs ```rust,ignore -extern crate greprs; +extern crate minigrep; use std::env; use std::process; -use greprs::Config; +use minigrep::Config; fn main() { - let args: Vec = env::args().collect(); - - let config = Config::new(&args).unwrap_or_else(|err| { - println!("Problem parsing arguments: {}", err); - process::exit(1); - }); - - println!("Searching for {}", config.query); - println!("In file {}", config.filename); - - if let Err(e) = greprs::run(config) { - println!("Application error: {}", e); - - process::exit(1); + // ...snip... + if let Err(e) = minigrep::run(config) { + // ...snip... } } ``` -Listing 12-14: Bringing the `greprs` crate into the scope -of *src/main.rs* - - - -With that, all the functionality should be connected and should work. Give it a -`cargo run` and make sure everything is wired up correctly. +Listing 12-14: Bringing the `minigrep` crate into the +scope of *src/main.rs* - - +To bring the library crate into the binary crate, we use `extern crate` +`minigrep`. Then we’ll add a `use` `minigrep``::Config` line to bring the +`Config` type into scope, and we'll prefix the `run` function with our crate +name. With that, all the functionality should be connected and should work. +Give it a `cargo run` and make sure everything is wired up correctly. -Whew! That was a lot of work, but we've set ourselves up for success in the -future. Now it's much easier to handle errors, and we've made our code more +Whew! That was a lot of work, but we’ve set ourselves up for success in the +future. Now it’s much easier to handle errors, and we’ve made our code more modular. Almost all of our work will be done in *src/lib.rs* from here on out. -Let's take advantage of this newfound modularity by doing something that would +Let’s take advantage of this newfound modularity by doing something that would have been hard with our old code, but is easy with our new code: write some tests! diff --git a/src/doc/book/second-edition/src/ch12-04-testing-the-librarys-functionality.md b/src/doc/book/second-edition/src/ch12-04-testing-the-librarys-functionality.md index 2a41b5306d..81cadc00d1 100644 --- a/src/doc/book/second-edition/src/ch12-04-testing-the-librarys-functionality.md +++ b/src/doc/book/second-edition/src/ch12-04-testing-the-librarys-functionality.md @@ -1,38 +1,38 @@ -## Testing the Library's Functionality +## Testing the Library’s Functionality -Now that we've extracted the logic into *src/lib.rs* and left all the argument -parsing and error handling in *src/main.rs*, it's much easier for us to write +Now that we’ve extracted the logic into *src/lib.rs* and left all the argument +parsing and error handling in *src/main.rs*, it’s much easier for us to write tests for the core functionality of our code. We can call our functions directly with various arguments and check return values without having to call our binary from the command line. -In this section, we're going to follow the Test Driven Development (TDD) +In this section, we’re going to follow the Test Driven Development (TDD) process. This is a software development technique that follows this set of steps: -1. Write a test that fails, and run it to make sure it fails for the reason - you expected. -2. Write or modify just enough code to make the new test pass. -3. Refactor the code you just added or changed, and make sure the tests - continue to pass. -4. Repeat! +* Write a test that fails, and run it to make sure it fails for the reason you +expected. +* Write or modify just enough code to make the new test pass. +* Refactor the code you just added or changed, and make sure the tests continue +to pass. +* Repeat! This is just one of many ways to write software, but TDD can help drive the -design of code. Writing the test before writing the code that makes the test +design of code. Writing the test before you write the code that makes the test pass helps to maintain high test coverage throughout the process. -We're going to test drive the implementation of the part of our `greprs` -program that will actually do the searching for the query string in the file -contents and produce a list of lines that match the query. We're going to add -this functionality in a function called `search`. +We’re going to test drive the implementation of the functionality that will +actually do the searching for the query string in the file contents and produce +a list of lines that match the query. We’re going to add this functionality in +a function called `search`. ### Writing a Failing Test -First, since we don't really need them any more, let's remove the `println!` -statements from both *src/lib.rs* and *src/main.rs*. Then we'll add a `test` -module with a test function, like we did in Chapter 11. The test function -specifies the behavior we'd like the `search` function to have: it will take -a query and the text to search for the query in, and will return only the lines +First, since we don’t really need them any more, let’s remove the `println!` +statements from both *src/lib.rs* and *src/main.rs*. Then we’ll add a `test` +module with a test function like we did in Chapter 11. The test function +specifies the behavior we’d like the `search` function to have: it will take a +query and the text to search for the query in, and will return only the lines from the text that contain the query. Listing 12-15 shows this test: Filename: src/lib.rs @@ -65,39 +65,36 @@ Pick three."; Listing 12-15: Creating a failing test for the `search` function we wish we had -We've chosen to use "duct" as the string we're looking for in this test. The -text we're searching in is three lines, only one of which contains "duct". We -assert that the value returned from the `search` function contains only the one -line we expect. +The string we are searching for is “duct” in this test. The text we’re +searching is three lines, only one of which contains “duct”. We assert that +the value returned from the `search` function contains only the line we expect. -We aren't able to run this test and watch it fail though, since this test -doesn't even compile yet! We're going to add just enough code to get it to -compile: a definition of the `search` function that always returns an empty -vector, as shown in Listing 12-16. Once we have this, the test should compile -and fail because an empty vector doesn't match a vector containing the one -line `"safe, fast, productive."`. +We aren’t able to run this test and watch it fail though, since this test +doesn’t even compile–the search function doesn't exist yet! So now we’ll add +just enough code to get the tests to compile and run: a definition of the +`search` function that always returns an empty vector, as shown in Listing +12-16. Once we have this, the test should compile and fail because an empty +vector doesn’t match a vector containing the line `"safe, fast, productive."`. Filename: src/lib.rs -```rust -fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { - vec![] +``` +pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { + vec![] } ``` Listing 12-16: Defining just enough of the `search` function that our test will compile - - Notice that we need an explicit lifetime `'a` defined in the signature of `search` and used with the `contents` argument and the return value. Remember from Chapter 10 that the lifetime parameters specify which argument lifetime is -connected to the lifetime of the return value. In this case, we're indicating +connected to the lifetime of the return value. In this case, we’re indicating that the returned vector should contain string slices that reference slices of the argument `contents` (rather than the argument `query`). -In other words, we're telling Rust that the data returned by the `search` +In other words, we’re telling Rust that the data returned by the `search` function will live as long as the data passed into the `search` function in the `contents` argument. This is important! The data referenced *by* a slice needs to be valid in order for the reference to be valid; if the compiler assumed we @@ -117,23 +114,23 @@ error[E0106]: missing lifetime specifier signature does not say whether it is borrowed from `query` or `contents` ``` -Rust can't possibly know which of the two arguments we need, so we need to tell +Rust can’t possibly know which of the two arguments we need, so we need to tell it. Because `contents` is the argument that contains all of our text and we want to return the parts of that text that match, we know `contents` is the argument that should be connected to the return value using the lifetime syntax. -Other programming languages don't require you to connect arguments to return +Other programming languages don’t require you to connect arguments to return values in the signature, so this may still feel strange, but will get easier over time. You may want to compare this example with the Lifetime Syntax section in Chapter 10. -Now let's try running our test: +Now let’s try running our test: ```text $ cargo test ...warnings... Finished dev [unoptimized + debuginfo] target(s) in 0.43 secs - Running target/debug/deps/greprs-abcabcabc + Running target/debug/deps/minigrep-abcabcabc running 1 test test test::one_result ... FAILED @@ -154,22 +151,22 @@ test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured error: test failed ``` -Great, our test fails, exactly as we expected. Let's get the test to pass! +Great, our test fails, exactly as we expected. Let’s get the test to pass! -### Writing Code that Gets the Test to Pass +### Writing Code to Pass the Test Currently, our test is failing because we always return an empty vector. To fix that and implement `search`, our program needs to follow these steps: -1. Iterate through each line of the contents. -2. Check if the line contains our query string. - * If it does, add it to the list of values we're returning. - * If it doesn't, do nothing. -3. Return the list of results that match. +* Iterate through each line of the contents. +* Check if the line contains our query string. +* If it does, add it to the list of values we’re returning. +* If it doesn’t, do nothing. +* Return the list of results that match. -Let's take each step at a time, starting with iterating through lines. +Let’s take each step at a time, starting with iterating through lines. -#### Iterating Through Lines with the `lines` method +#### Iterating Through Lines with the `lines` Method Rust has a helpful method to handle line-by-line iteration of strings, conveniently named `lines`, that works as shown in Listing 12-17: @@ -177,7 +174,7 @@ conveniently named `lines`, that works as shown in Listing 12-17: Filename: src/lib.rs ```rust,ignore -fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { +pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { for line in contents.lines() { // do something with line } @@ -187,23 +184,14 @@ fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { Listing 12-17: Iterating through each line in `contents` - - -The `lines` method returns an iterator. We'll be talking about iterators in -depth in Chapter 13, but we've already seen this way of using an iterator in +The `lines` method returns an iterator. We’ll be talking about iterators in +depth in Chapter 13, but we’ve already seen this way of using an iterator in Listing 3-6, where we used a `for` loop with an iterator to run some code on each item in a collection. - - - #### Searching Each Line for the Query -Next, we'll add functionality to check if the current line contains the query +Next, we’ll add functionality to check if the current line contains the query string. Luckily, strings have another helpful method named `contains` that does this for us! Add the `contains` method to the `search` function as shown in Listing 12-18: @@ -211,7 +199,7 @@ Listing 12-18: Filename: src/lib.rs ```rust,ignore -fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { +pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { for line in contents.lines() { if line.contains(query) { // do something with line @@ -223,8 +211,6 @@ fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { Listing 12-18: Adding functionality to see if the line contains the string in `query` - - #### Storing Matching Lines Finally, we need a way to store the lines that contain our query string. For @@ -235,7 +221,7 @@ vector, as shown in Listing 12-19: Filename: src/lib.rs ```rust,ignore -fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { +pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { let mut results = Vec::new(); for line in contents.lines() { @@ -251,10 +237,8 @@ fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { Listing 12-19: Storing the lines that match so that we can return them - - Now the `search` function should be returning only the lines that contain -`query`, and our test should pass. Let's run the tests: +`query`, and our test should pass. Let’s run the tests: ```text $ cargo test @@ -262,39 +246,16 @@ running 1 test test test::one_result ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured - - Running target/debug/greprs-2f55ee8cd1721808 - -running 0 tests - -test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured - - Doc-tests greprs - -running 0 tests - -test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ``` Our test passed, great, it works! Now that our test is passing, we could consider opportunities for refactoring -the implementation of the `search` function while keeping the tests passing in -order to maintain the same functionality while we do so. This code isn't bad, -but it isn't taking advantage of some useful features of iterators. We'll be -coming back to this example in Chapter 13 where we'll explore iterators in -detail and see how to improve it. - - - +the implementation of the `search` function while keeping the code that passes +the tests, in order to maintain the same functionality. The code in the +`search` function isn’t too bad, but it isn’t taking advantage of some useful +features of iterators. We’ll be coming back to this example in Chapter 13 where +we’ll explore iterators in detail and see how to improve it. #### Using the `search` Function in the `run` Function @@ -320,46 +281,44 @@ pub fn run(config: Config) -> Result<(), Box> { } ``` - - -We're again using a `for` loop to get each line returned from `search`, and -the code that we run for each line prints it out. +We’re still using a `for` loop to get each line returned from `search` and +printing out each line. -Now our whole program should be working! Let's try it out, first with a word -that should return exactly one line from the Emily Dickinson poem, "frog": +Now our whole program should be working! Let’s try it out, first with a word +that should return exactly one line from the Emily Dickinson poem, “frog”: ```text $ cargo run frog poem.txt - Compiling greprs v0.1.0 (file:///projects/greprs) + Compiling minigrep v0.1.0 (file:///projects/minigrep) Finished dev [unoptimized + debuginfo] target(s) in 0.38 secs - Running `target/debug/greprs frog poem.txt` + Running `target/debug/minigrep frog poem.txt` How public, like a frog ``` -Cool! Next, how about a word that will match multiple lines, like "the": +Cool! Next, how about a word that will match multiple lines, like “the”: ```text $ cargo run the poem.txt Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs - Running `target/debug/greprs the poem.txt` -Then there's a pair of us — don't tell! + Running `target/debug/minigrep the poem.txt` +Then there’s a pair of us — don’t tell! To tell your name the livelong day ``` -And finally, let's make sure that we don't get any lines when we search for a -word that isn't anywhere in the poem, like "monomorphization": +And finally, let’s make sure that we don’t get any lines when we search for a +word that isn’t anywhere in the poem, like “monomorphization”: ```text $ cargo run monomorphization poem.txt Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs - Running `target/debug/greprs monomorphization poem.txt` + Running `target/debug/minigrep monomorphization poem.txt` ``` -Excellent! We've built our own version of a classic tool, and learned a lot -about how to structure applications. We've also learned a bit about file input -and output, lifetimes, testing, and command line parsing. +Excellent! We’ve built our own mini version of a classic tool, and learned a +lot about how to structure applications. We’ve also learned a bit about file +input and output, lifetimes, testing, and command line parsing. -Feel free to move on to Chapter 13 if you'd like at this point. To round out -this project chapter, though, we're going to briefly demonstrate how to work -with environment variables and printing to standard error, both of which are -useful when writing command line programs. +To round out this project chapter, we’re going to briefly demonstrate how to +work with environment variables and how to print to standard error, both of +which are useful when writing command line programs. Feel free to move on to +Chapter 13 if you’d like at this point. diff --git a/src/doc/book/second-edition/src/ch12-05-working-with-environment-variables.md b/src/doc/book/second-edition/src/ch12-05-working-with-environment-variables.md index 0b9c7e20c7..12e5e3540a 100644 --- a/src/doc/book/second-edition/src/ch12-05-working-with-environment-variables.md +++ b/src/doc/book/second-edition/src/ch12-05-working-with-environment-variables.md @@ -1,30 +1,22 @@ ## Working with Environment Variables -We're going to improve our tool with an extra feature: an option for case -insensitive searching turned on via an environment variable. We could make this -a command line option and require that users enter it each time they want it to -apply, but instead we're going to use an environment variable. This allows our -users to set the environment variable once and have all their searches be case -insensitive in that terminal session. +We’re going to improve our tool with an extra feature: an option for case +insensitive searching that the user can turn on via an environment variable. We +could make this a command line option and require that users enter it each time +they want it to apply, but instead we’re going to use an environment variable. +This allows our users to set the environment variable once and have all their +searches be case insensitive in that terminal session. ### Writing a Failing Test for the Case-Insensitive `search` Function -First, let's add a new function that we will call when the environment variable -is on. +We want to add a new `search_case_insensitive` function that we will call when +the environment variable is on. - - - -We're going to continue following the TDD process that we started doing in the -last section, and the first step is again to write a failing test. We'll add a -new test for the new case insensitive search function, and rename our old test -from `one_result` to `case_sensitive` to be clearer about the differences -between the two tests, as shown in Listing 12-20: +We’re going to continue following the TDD process, so the first step is again +to write a failing test. We’ll add a new test for the new case-insensitive +search function, and rename our old test from `one_result` to `case_sensitive` +to be clearer about the differences between the two tests, as shown in Listing +12-20: Filename: src/lib.rs @@ -65,35 +57,32 @@ Trust me."; } ``` - - Listing 12-20: Adding a new failing test for the case -insensitive function we're about to add +insensitive function we’re about to add -Note that we've edited the old test's `contents` too. We've added a new line -with the text "Duct tape", with a capital D, that shouldn't match the query -"duct" when we're searching for the query in a case sensitive manner. We've -changed this test to ensure that we don't accidentally break the case sensitive -search functionality that we've already implemented; this test should pass now +Note that we’ve edited the old test’s `contents` too. We've added a new line +with the text “Duct tape”, with a capital D, that shouldn’t match the query +“duct” when we’re searching in a case sensitive manner. Changing the old test +in this way helps ensure that we don’t accidentally break the case sensitive +search functionality that we’ve already implemented; this test should pass now and should continue to pass as we work on the case insensitive search. -The new test for the case insensitive search uses "rUsT" with some capital -letters as its query. The expected return value from the -`search_case_insensitive` function we're going to add is that the query "rust" -will match both the line containing "Rust:" with a capital R and also the line -"Trust me." that contains "rust" with a lowercase r. This test will fail to -compile right now since we haven't yet defined the `search_case_insensitive` -function; feel free to add a skeleton implementation that always returns an -empty vector in the same way that we did for the `search` function in Listing -12-16 in order to see the test compile and fail. +The new test for the case *insensitive* search uses “rUsT” as its query. In the +`search_case_insensitive` function we’re going to add, the query “rUsT” should +match both the line containing “Rust:” with a capital R and also the line +“Trust me.” even though both of those have different casing than the query. +This is our failing test, and it will fail to compile because we haven’t yet +defined the `search_case_insensitive` function. Feel free to add a skeleton +implementation that always returns an empty vector in the same way that we did +for the `search` function in Listing 12-16 in order to see the test compile and +fail. ### Implementing the `search_case_insensitive` Function The `search_case_insensitive` function, shown in Listing 12-21, will be almost -the same as the `search` function. The difference is that we'll lowercase the -`query` function and each `line` so that whatever the case of the input -arguments, they will be the same case when we check whether the line contains -the query. +the same as the `search` function. The only difference is that we’ll lowercase +the `query` and each `line` so that whatever the case of the input arguments, +they will be the same case when we check whether the line contains the query. Filename: src/lib.rs @@ -115,64 +104,36 @@ fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { Listing 12-21: Defining the `search_case_insensitive` function to lowercase both the query and the line before comparing them - - - - - First, we lowercase the `query` string, and store it in a shadowed variable with the same name. Calling `to_lowercase` on the query is necessary so that no -matter if the user's query is "rust", "RUST", "Rust", or "rUsT", we'll treat -the query as if it was "rust" and be insensitive to the case. +matter if the user’s query is “rust”, “RUST”, “Rust”, or “rUsT”, we’ll treat +the query as if it was “rust” and be insensitive to the case. Note that `query` is now a `String` rather than a string slice, because calling -`to_lowercase` is creating new data, not referencing existing data. If the -query is "rUsT", that string slice does not contain a lowercase u or t for us -to use, so we have to allocate a new `String` containing "rust". Because -`query` is now a `String`, when we pass `query` as an argument to the -`contains` method, we need to add an ampersand since the signature of -`contains` is defined to take a string slice. +`to_lowercase` creates new data rather than referencing existing data. Say the +query is “rUsT”, as an example: that string slice does not contain a lowercase +“u” or “t” for us to use, so we have to allocate a new `String` containing +“rust”. When we pass `query` as an argument to the `contains` method now, we +need to add an ampersand because the signature of `contains` is defined to take +a string slice. Next, we add a call to `to_lowercase` on each `line` before we check if it -contains `query`. This will turn "Rust:" into "rust:" and "Trust me." into -"trust me." Now that we've converted both `line` and `query` to all lowercase, -we'll find matches no matter what case the text in the file has or the user -entered in the query. +contains `query` to lowercase all characters. Now that we’ve converted both +`line` and `query` to lowercase, we’ll find matches no matter what the case of +the query. -Let's see if this implementation passes the tests: +Let’s see if this implementation passes the tests: ```text - Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs - Running target/debug/deps/greprs-e58e9b12d35dc861 - running 2 tests test test::case_insensitive ... ok test test::case_sensitive ... ok test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured - - Running target/debug/greprs-8a7faa2662b5030a - -running 0 tests - -test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured - - Doc-tests greprs - -running 0 tests - -test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ``` -Great! Now, let's actually call the new `search_case_insensitive` function from -the `run` function. First, we're going to add a configuration option for +Great! Now, let’s actually call the new `search_case_insensitive` function from +the `run` function. First, we’re going to add a configuration option for switching between case sensitive and case insensitive search to the `Config` struct: @@ -186,10 +147,8 @@ pub struct Config { } ``` - - We add the `case_sensitive` field that holds a boolean. Then we need our `run` -function to check the `case_sensitive` field's value and use that to decide +function to check the `case_sensitive` field’s value and use that to decide whether to call the `search` function or the `search_case_insensitive` function as shown in Listing 12-22: @@ -237,14 +196,12 @@ pub fn run(config: Config) -> Result<(), Box>{ Listing 12-22: Calling either `search` or `search_case_insensitive` based on the value in `config.case_sensitive` - - Finally, we need to actually check for the environment variable. The functions for working with environment variables are in the `env` module in the standard -library, so we want to bring that module into scope with a `use std::env;` -line at the top of *src/lib.rs*. Then we're going to use the `var` method -from the `env` module in `Config::new` to check for an environment variable -named `CASE_INSENSITIVE`, as shown in Listing 12-23: +library, so we want to bring that module into scope with a `use std::env;` line +at the top of *src/lib.rs*. Then we’re going to use the `var` method from the +`env` module to check for an environment variable named `CASE_INSENSITIVE`, as +shown in Listing 12-23: Filename: src/lib.rs @@ -269,11 +226,7 @@ impl Config { let case_sensitive = env::var("CASE_INSENSITIVE").is_err(); - Ok(Config { - query: query, - filename: filename, - case_sensitive: case_sensitive, - }) + Ok(Config { query, filename, case_sensitive }) } } ``` @@ -281,51 +234,52 @@ impl Config { Listing 12-23: Checking for an environment variable named `CASE_INSENSITIVE` - - Here, we create a new variable `case_sensitive`. In order to set its value, we -call the `env::var` function and pass it the name of the environment variable -we're looking for, `CASE_INSENSITIVE`. `env::var` returns a `Result` that will -be the `Ok` variant containing the value if the environment variable is set, -and will be the `Err` variant if the environment variable is not set. We're -using the `is_err` method on the `Result` to check to see if it's an error (and -therefore unset), which means we *should* do a case sensitive search. If the -`CASE_INSENSITIVE` environment variable is set to anything, `is_err` will -return false and we will do a case insensitive search. We don't care about the -value that the environment variable is set to, just whether it's set or unset, -so we're checking `is_err` rather than `unwrap`, `expect`, or any of the other -methods we've seen on `Result`. We pass the value in the `case_sensitive` -variable to the `Config` instance so that the `run` function can read that -value and decide whether to call `search` or `search_case_insensitive` as we -implemented in Listing 12-22. - -Let's give it a try! First, we'll run our program without the environment -variable set and with the query "to", which should match any line that contains -the word "to" in all lowercase: +call the `env::var` function and pass it the name of the `CASE_INSENSITIVE` +environment variable. The `env::var` method returns a `Result` that will be the +successful `Ok` variant that contains the value of the environment variable if +the environment variable is set. It will return the `Err` variant if the +environment variable is not set. + +We’re using the `is_err` method on the `Result` to check to see if it’s an +error, and therefore unset, which means it *should* do a case sensitive search. +If the `CASE_INSENSITIVE` environment variable is set to anything, `is_err` +will return false and it will perform a case insensitive search. We don’t care +about the *value* of the environment variable, just whether it’s set or unset, +so we’re checking `is_err` rather than `unwrap`, `expect`, or any of the other +methods we’ve seen on `Result`. + +We pass the value in the `case_sensitive` variable to the `Config` instance so +that the `run` function can read that value and decide whether to call `search` +or `search_case_insensitive` as we implemented in Listing 12-22. + +Let’s give it a try! First, we’ll run our program without the environment +variable set and with the query “to”, which should match any line that contains +the word “to” in all lowercase: ```text $ cargo run to poem.txt Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs - Running `target/debug/greprs to poem.txt` + Running `target/debug/minigrep to poem.txt` Are you nobody, too? How dreary to be somebody! ``` -Looks like that still works! Now, let's run the program with `CASE_INSENSITIVE` -set to 1 but with the same query "to", and we should get lines that contain -"to" that might have capital letters: +Looks like that still works! Now, let’s run the program with `CASE_INSENSITIVE` +set to 1 but with the same query “to”, and we should get lines that contain +“to” that might have uppercase letters: ```text $ CASE_INSENSITIVE=1 cargo run to poem.txt Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs - Running `target/debug/greprs to poem.txt` + Running `target/debug/minigrep to poem.txt` Are you nobody, too? How dreary to be somebody! To tell your name the livelong day To an admiring bog! ``` -Excellent, we also got lines containing "To"! Our `greprs` program can now do +Excellent, we also got lines containing “To”! Our `minigrep` program can now do case insensitive searching, controlled by an environment variable. Now you know how to manage options set using either command line arguments or environment variables! @@ -338,4 +292,4 @@ environment variable, and decide which should take precedence if the program is run with contradictory values. The `std::env` module contains many more useful features for dealing with -environment variables; check out its documentation to see what's available. +environment variables; check out its documentation to see what’s available. diff --git a/src/doc/book/second-edition/src/ch12-06-writing-to-stderr-instead-of-stdout.md b/src/doc/book/second-edition/src/ch12-06-writing-to-stderr-instead-of-stdout.md index dacbb538fe..55075cdcb6 100644 --- a/src/doc/book/second-edition/src/ch12-06-writing-to-stderr-instead-of-stdout.md +++ b/src/doc/book/second-edition/src/ch12-06-writing-to-stderr-instead-of-stdout.md @@ -1,131 +1,99 @@ -## Write to `stderr` Instead of `stdout` - -Right now, we're writing all of our output to the terminal with `println!`. -Most terminals provide two kinds of output: "standard out" for general -information, and "standard error" for error messages. This distinction is the -behavior that's expected of command line programs: it enables users to choose -to direct a program's successful output to a file but still print error -messages to the screen, for example. `println!` is only capable of printing to -standard out, though, so we have to use something else in order to print to -standard error. - -We can verify that, the way we've written `greprs` so far, everything is being -written to standard out, including error messages that should be written to -standard error instead. We'll do that by intentionally causing an error, the -one that happens when we run the program without any arguments. We're going to -redirect standard output to a file, but not standard error. The way command -line programs are expected to work is that, because the output is an error -message, it should be shown on the screen rather than being redirected to the -file. Let's see that our program is not currently meeting this expectation by -using `>` and specifying a filename, *output.txt*, that we want to redirect -standard out to: +## Writing Error Messages to `stderr` Instead of `stdout` + +At the moment we’re writing all of our output to the terminal with the +`println!` function. Most terminals provide two kinds of output: *standard out* +for general information, and *standard error* for error messages. This +distinction enables users to choose whether to direct a the successful output +of a program to a file but still print error messages to the screen. + +The `println!` function is only capable of printing to standard out, though, so +we have to use something else in order to print to standard error. + +### Checking Where Errors are Written to + +First, let’s observe how all content printed by `minigrep` is currently being +written to standard out, including error messages that we want to write to +standard error instead. We’ll do that by redirecting the standard output stream +to a file while we also intentionally cause an error. We won't redirect the +standard error stream, so any content sent to standard error will continue to +display on the screen. Command line programs are expected to send error +messages to the standard error stream so that we can still see error messages +on the screen even if we choose to redirect the standard output stream to a +file. Our program is not currently well-behaved; we're about to see that it +saves the error message output to the file instead! + +The way to demonstrate this behavior is by running the program with `>` and the +filename, *output.txt*, that we want to redirect the standard output stream to. +We're not going to pass any arguments, which should cause an error: ```text $ cargo run > output.txt ``` - - - The `>` syntax tells the shell to write the contents of standard out to -*output.txt* instead of the screen. We didn't see the error message we were +*output.txt* instead of the screen. We didn’t see the error message we were expecting printed on the screen, so that means it must have ended up in the -file. Let's see what *output.txt* contains: +file. Let’s see what *output.txt* contains: ```text Problem parsing arguments: not enough arguments ``` - - - -Yup, there's our error message, which means it's being printed to standard out. -This isn't what's expected from command line programs. It's much more useful -for error messages like this to be printed to standard error, and only have -data printed to standard out from a successful run end up in the file when we -redirect standard out in this way. Let's change how error messages are printed -as shown in Listing 12-23. Because of the refactoring we did earlier in this -chapter, all of the code that prints error messages is in one place, in `main`: - -Filename: src/main.rs +Yup, our error message is being printed to standard out. It’s much more useful +for error messages like this to be printed to standard error, and have only +data from a successful run end up in the file when we redirect standard out in +this way. We’ll change that. -```rust,ignore -extern crate greprs; +### Printing Errors to Standard Error -use std::env; -use std::process; -use std::io::prelude::*; +Let’s change how error messages are printed using the code in Listing 12-24. +Because of the refactoring we did earlier in this chapter, all the code that +prints error messages is in one function, in `main`. The standard library +provides the `eprintln!` macro that prints to the standard error stream, so +let's change the two places we were calling `println!` to print errors so that +these spots use `eprintln!` instead: -use greprs::Config; +Filename: src/main.rs +```rust,ignore fn main() { let args: Vec = env::args().collect(); - let mut stderr = std::io::stderr(); let config = Config::new(&args).unwrap_or_else(|err| { - writeln!( - &mut stderr, - "Problem parsing arguments: {}", - err - ).expect("Could not write to stderr"); + eprintln!("Problem parsing arguments: {}", err); process::exit(1); }); - if let Err(e) = greprs::run(config) { - writeln!( - &mut stderr, - "Application error: {}", - e - ).expect("Could not write to stderr"); + if let Err(e) = minigrep::run(config) { + eprintln!("Application error: {}", e); process::exit(1); } } ``` -Listing 12-23: Writing error messages to `stderr` instead -of `stdout` using `writeln!` - - - -Rust does not have a convenient function like `println!` for writing to -standard error. Instead, we use the `writeln!` macro, which is like `println!` -but takes an extra argument. The first thing we pass to it is what to write to. -We can acquire a handle to standard error through the `std::io::stderr` -function. We give a mutable reference to `stderr` to `writeln!`; we need it to -be mutable so we can write to it! The second and third arguments to `writeln!` -are like the first and second arguments to `println!`: a format string and any -variables we're interpolating. +Listing 12-24: Writing error messages to `stderr` instead +of `stdout` using `eprintln!` -Let's try running the program again in the same way, without any arguments and -redirecting `stdout` with `>`: +After changing `println!` to `eprintln!`, let’s try running the program again +in the same way, without any arguments and redirecting `stdout` with `>`: ```text $ cargo run > output.txt Problem parsing arguments: not enough arguments ``` -Now we see our error on the screen, and `output.txt` contains nothing, which is -the behavior that's expected of command line programs. +Now we see our error on the screen and `output.txt` contains nothing, which is +the behavior expected of command line programs. -If we run the program again with arguments that don't cause an error, but still -redirecting standard out to a file: +If we run the program again with arguments that don’t cause an error, but still +redirect standard out to a file: ```text $ cargo run to poem.txt > output.txt ``` -We won't see any output to our terminal, and `output.txt` will contain our +We won’t see any output to our terminal, and `output.txt` will contain our results: Filename: output.txt @@ -135,18 +103,18 @@ Are you nobody, too? How dreary to be somebody! ``` -This demonstrates that we're now using standard out for successful output and -standard error for error output as appropriate. +This demonstrates that we’re now using `stdout` for successful output and +`stderr` for error output as appropriate. ## Summary -In this chapter, we've recapped on some of the major concepts so far and +In this chapter, we’ve recapped on some of the major concepts so far and covered how to do common I/O operations in a Rust context. By using command -line arguments, files, environment variables, and the `writeln!` macro with -`stderr`, you're now prepared to write command line applications. By using the +line arguments, files, environment variables, and the `eprintln!` macro with +`stderr`, you’re now prepared to write command line applications. By using the concepts from previous chapters, your code will be well-organized, be able to store data effectively in the appropriate data structures, handle errors nicely, and be well tested. -Next, let's explore some functional-language influenced Rust features: closures +Next, let’s explore some functional-language influenced Rust features: closures and iterators. diff --git a/src/doc/book/second-edition/src/ch15-05-interior-mutability.md b/src/doc/book/second-edition/src/ch15-05-interior-mutability.md index 75e3e375d4..a9ebf9f97d 100644 --- a/src/doc/book/second-edition/src/ch15-05-interior-mutability.md +++ b/src/doc/book/second-edition/src/ch15-05-interior-mutability.md @@ -99,16 +99,16 @@ a is 5 a is 6 ``` -In `main`, we've created a new `RefCell` containing the value 5, and stored +In `main`, we've created a new `RefCell` containing the value 5, and stored in the variable `data`, declared without the `mut` keyword. We then call the `demo` function with an immutable reference to `data`: as far as `main` is concerned, `data` is immutable! In the `demo` function, we get an immutable reference to the value inside the -`RefCell` by calling the `borrow` method, and we call +`RefCell` by calling the `borrow` method, and we call `a_fn_that_immutably_borrows` with that immutable reference. More interestingly, we can get a *mutable* reference to the value inside the -`RefCell` with the `borrow_mut` method, and the function +`RefCell` with the `borrow_mut` method, and the function `a_fn_that_mutably_borrows` is allowed to change the value. We can see that the next time we call `a_fn_that_immutably_borrows` that prints out the value, it's 6 instead of 5. @@ -229,8 +229,8 @@ can create lists `b` and `c` that start differently but both refer to `a`, similarly to what we did in Listing 15-12. Once we have the lists in `shared_list`, `b`, and `c` created, then we add 10 -to the 5 in `value` by dereferencing the `Rc` and calling `borrow_mut` on -the `RefCell`. +to the 5 in `value` by dereferencing the `Rc` and calling `borrow_mut` on +the `RefCell`. When we print out `shared_list`, `b`, and `c`, we can see that they all have the modified value of 15: diff --git a/src/doc/book/second-edition/src/ch17-03-oo-design-patterns.md b/src/doc/book/second-edition/src/ch17-03-oo-design-patterns.md index 2e1fc89668..391297acb9 100644 --- a/src/doc/book/second-edition/src/ch17-03-oo-design-patterns.md +++ b/src/doc/book/second-edition/src/ch17-03-oo-design-patterns.md @@ -194,7 +194,7 @@ works as we intend. ### Requesting a Review of the Post Changes its State Next up is requesting a review of a post, which should change its state from -`Draft` to `PendingReview`. We want `post` to have a public method named +`Draft` to `PendingReview`. We want `Post` to have a public method named `request_review` that will take a mutable reference to `self`. Then we're going to call an internal `request_review` method on the state that we're holding, and this second `request_review` method will consume the current state and return a @@ -318,7 +318,7 @@ struct PendingReview {} impl State for PendingReview { # fn request_review(self: Box) -> Box { -# Box::new(PendingReview {}) +# self # } # // ...snip... diff --git a/src/doc/book/second-edition/src/ch19-02-advanced-lifetimes.md b/src/doc/book/second-edition/src/ch19-02-advanced-lifetimes.md index 5ca16d5ec0..14b74b0e68 100644 --- a/src/doc/book/second-edition/src/ch19-02-advanced-lifetimes.md +++ b/src/doc/book/second-edition/src/ch19-02-advanced-lifetimes.md @@ -277,57 +277,56 @@ something you have a reference to. ### Lifetime Bounds In Chapter 10, we discussed how to use trait bounds on generic types. We can -also add lifetime parameters as constraints on generic types. For example, -let's say we wanted to make a wrapper over references. Remember `RefCell` -from Chapter 15? This is how the `borrow` and `borrow_mut` methods work; they -return wrappers over references in order to keep track of the borrowing rules -at runtime. The struct definition, without lifetime parameters for now, would -look like Listing 19-16: +also add lifetime parameters as constraints on generic types, which are called +*lifetime bounds*. For example, consider a type that is a wrapper over +references. Recall the `RefCell` type from Chapter 15: its `borrow` and +`borrow_mut` methods return the types `Ref` and `RefMut`, respectively. These +types are wrappers over references that keep track of the borrowing rules at +runtime. The definition of the `Ref` struct is shown in Listing 19-16, without +lifetime bounds for now: ```rust,ignore -struct Ref(&T); +struct Ref<'a, T>(&'a T); ``` Listing 19-16: Defining a struct to wrap a reference to a -generic type; without lifetime parameters to start +generic type; without lifetime bounds to start -However, using no lifetime bounds at all gives an error because Rust doesn't -know how long the generic type `T` will live: +Without constraining the lifetime `'a` in relation to the generic parameter +`T`, we get an error because Rust doesn't know how long the generic type `T` +will live: ```text error[E0309]: the parameter type `T` may not live long enough - --> :2:19 + --> :1:19 | -2 | struct Ref<'a, T>(&'a T); +1 | struct Ref<'a, T>(&'a T); | ^^^^^^ | = help: consider adding an explicit lifetime bound `T: 'a`... note: ...so that the reference type `&'a T` does not outlive the data it points at - --> :2:19 + --> :1:19 | -2 | struct Ref<'a, T>(&'a T); +1 | struct Ref<'a, T>(&'a T); | ^^^^^^ ``` -This is the same error that we'd get if we filled in `T` with a concrete type, -like `struct Ref(&i32)`; all references in struct definitions need a lifetime -parameter. However, because we have a generic type parameter, we can't add a -lifetime parameter in the same way. Defining `Ref` as `struct Ref<'a>(&'a T)` -will result in an error because Rust can't determine that `T` lives long -enough. Since `T` can be any type, `T` could itself be a reference or it could -be a type that holds one or more references, each of which have their own -lifetimes. +Since `T` can be any type, `T` could itself be a reference or a type that holds +one or more references, each of which could have their own lifetimes. Rust +can't be sure `T` will live as long as `'a`. -Rust helpfully gave us good advice on how to specify the lifetime parameter in +Fortunately, Rust gave us helpful advice on how to specify the lifetime bound in this case: ```text consider adding an explicit lifetime bound `T: 'a` so that the reference type -`&'a T` does not outlive the data it points to. +`&'a T` does not outlive the data it points at. ``` -The code in Listing 19-17 works because `T: 'a` syntax specifies that `T` can -be any type, but if it contains any references, `T` must live as long as `'a`: +Listing 19-17 shows how to apply this advice by specifying the lifetime bound +when we declare the generic type `T`. This code now compiles because the `T: +'a` syntax specifies that `T` can be any type, but if it contains any +references, the references must live at least as long as `'a`: ```rust struct Ref<'a, T: 'a>(&'a T); @@ -336,9 +335,10 @@ struct Ref<'a, T: 'a>(&'a T); Listing 19-17: Adding lifetime bounds on `T` to specify that any references in `T` live at least as long as `'a` -We could choose to solve this in a different way as shown in Listing 19-18 by -bounding `T` on `'static`. This means if `T` contains any references, they must -have the `'static` lifetime: +We could choose to solve this in a different way, shown in the definition of a +`StaticRef` struct in Listing 19-18, by adding the `'static` lifetime bound on +`T`. This means if `T` contains any references, they must have the `'static` +lifetime: ```rust struct StaticRef(&'static T); @@ -348,7 +348,7 @@ struct StaticRef(&'static T); to constrain `T` to types that have only `'static` references or no references -Types with no references count as `T: 'static`. Because `'static` means the +Types without any references count as `T: 'static`. Because `'static` means the reference must live as long as the entire program, a type that contains no references meets the criteria of all references living as long as the entire program (since there are no references). Think of it this way: if the borrow diff --git a/src/doc/book/second-edition/src/ch19-04-advanced-types.md b/src/doc/book/second-edition/src/ch19-04-advanced-types.md index c03042b3d4..d6f76e869b 100644 --- a/src/doc/book/second-edition/src/ch19-04-advanced-types.md +++ b/src/doc/book/second-edition/src/ch19-04-advanced-types.md @@ -163,10 +163,10 @@ another `Result`, which means we can use any methods that work on ### The Never Type, `!`, that Never Returns -Rust has a special type named `!`. In type theory lingo, it's called the -*bottom type*, but we prefer to call it the *never type*. The name describes -what it does: it stands in the place of the return type when a function will -never return. For example: +Rust has a special type named `!`. In type theory lingo, it's called the *empty +type*, because it has no values. We prefer to call it the *never type*. The name +describes what it does: it stands in the place of the return type when a +function will never return. For example: ```rust,ignore fn bar() -> ! { diff --git a/src/doc/book/second-edition/theme/index.hbs b/src/doc/book/second-edition/theme/index.hbs index 7635dcdce1..ea382b0aab 100644 --- a/src/doc/book/second-edition/theme/index.hbs +++ b/src/doc/book/second-edition/theme/index.hbs @@ -159,6 +159,7 @@ {{{livereload}}} + diff --git a/src/doc/book/second-edition/tools/docx-to-md.xsl b/src/doc/book/second-edition/tools/docx-to-md.xsl index 78560957ae..d3f6c0668e 100644 --- a/src/doc/book/second-edition/tools/docx-to-md.xsl +++ b/src/doc/book/second-edition/tools/docx-to-md.xsl @@ -72,6 +72,12 @@ + + * + + + + @@ -115,7 +121,7 @@ - + @@ -125,6 +131,13 @@ + + + > + + + + > diff --git a/src/doc/grammar.md b/src/doc/grammar.md index 12daa24e85..78432b6a96 100644 --- a/src/doc/grammar.md +++ b/src/doc/grammar.md @@ -154,19 +154,19 @@ token : simple_token | ident | literal | symbol | whitespace token ;

-| | | | | | -|----------|----------|----------|----------|---------| -| abstract | alignof | as | become | box | -| break | const | continue | crate | do | -| else | enum | extern | false | final | -| fn | for | if | impl | in | -| let | loop | macro | match | mod | -| move | mut | offsetof | override | priv | -| proc | pub | pure | ref | return | -| Self | self | sizeof | static | struct | -| super | trait | true | type | typeof | -| unsafe | unsized | use | virtual | where | -| while | yield | | | | +| | | | | | +|----------|----------|----------|----------|----------| +| _ | abstract | alignof | as | become | +| box | break | const | continue | crate | +| do | else | enum | extern | false | +| final | fn | for | if | impl | +| in | let | loop | macro | match | +| mod | move | mut | offsetof | override | +| priv | proc | pub | pure | ref | +| return | Self | self | sizeof | static | +| struct | super | trait | true | type | +| typeof | unsafe | unsized | use | virtual | +| where | while | yield | | | Each of these keywords has special meaning in its grammar, and all of them are diff --git a/src/doc/nomicon/src/SUMMARY.md b/src/doc/nomicon/src/SUMMARY.md index 0b3495267d..db72286d41 100644 --- a/src/doc/nomicon/src/SUMMARY.md +++ b/src/doc/nomicon/src/SUMMARY.md @@ -11,6 +11,7 @@ * [Other reprs](other-reprs.md) * [Ownership](ownership.md) * [References](references.md) + * [Aliasing](aliasing.md) * [Lifetimes](lifetimes.md) * [Limits of Lifetimes](lifetime-mismatch.md) * [Lifetime Elision](lifetime-elision.md) diff --git a/src/doc/nomicon/src/aliasing.md b/src/doc/nomicon/src/aliasing.md new file mode 100644 index 0000000000..dc846f1661 --- /dev/null +++ b/src/doc/nomicon/src/aliasing.md @@ -0,0 +1,135 @@ +# Aliasing + +First off, let's get some important caveats out of this way: + +* We will be using the broadest possible definition of aliasing for the sake +of discussion. Rust's definition will probably be more restricted to factor +in mutations and liveness. + +* We will be assuming a single-threaded, interrupt-free, execution. We will also +be ignoring things like memory-mapped hardware. Rust assumes these things +don't happen unless you tell it otherwise. For more details, see the +[Concurrency Chapter](concurrency.html). + +With that said, here's our working definition: variables and pointers *alias* +if they refer to overlapping regions of memory. + + + + +# Why Aliasing Matters + +So why should we care about aliasing? + +Consider this simple function: + +```rust +fn compute(input: &u32, output: &mut u32) { + if *input > 10 { + *output = 1; + } + if *input > 5 { + *output *= 2; + } +} +``` + +We would *like* to be able to optimize it to the following function: + +```rust +fn compute(input: &u32, output: &mut u32) { + let cached_input = *input; // keep *input in a register + if cached_input > 10 { + *output = 2; // x > 10 implies x > 5, so double and exit immediately + } else if cached_input > 5 { + *output *= 2; + } +} +``` + +In Rust, this optimization should be sound. For almost any other language, it +wouldn't be (barring global analysis). This is because the optimization relies +on knowing that aliasing doesn't occur, which most languages are fairly liberal +with. Specifically, we need to worry about function arguments that make `input` +and `output` overlap, such as `compute(&x, &mut x)`. + +With that input, we could get this execution: + +```rust,ignore + // input == output == 0xabad1dea + // *input == *output == 20 +if *input > 10 { // true (*input == 20) + *output = 1; // also overwrites *input, because they are the same +} +if *input > 5 { // false (*input == 1) + *output *= 2; +} + // *input == *output == 1 +``` + +Our optimized function would produce `*output == 2` for this input, so the +correctness of our optimization relies on this input being impossible. + +In Rust we know this input should be impossible because `&mut` isn't allowed to be +aliased. So we can safely reject its possibility and perform this optimization. +In most other languages, this input would be entirely possible, and must be considered. + +This is why alias analysis is important: it lets the compiler perform useful +optimizations! Some examples: + +* keeping values in registers by proving no pointers access the value's memory +* eliminating reads by proving some memory hasn't been written to since last we read it +* eliminating writes by proving some memory is never read before the next write to it +* moving or reordering reads and writes by proving they don't depend on each other + +These optimizations also tend to prove the soundness of bigger optimizations +such as loop vectorization, constant propagation, and dead code elimination. + +In the previous example, we used the fact that `&mut u32` can't be aliased to prove +that writes to `*output` can't possibly affect `*input`. This let us cache `*input` +in a register, eliminating a read. + +By caching this read, we knew that the the write in the `> 10` branch couldn't +affect whether we take the `> 5` branch, allowing us to also eliminate a +read-modify-write (doubling `*output`) when `*input > 10`. + +The key thing to remember about alias analysis is that writes are the primary +hazard for optimizations. That is, the only thing that prevents us +from moving a read to any other part of the program is the possibility of us +re-ordering it with a write to the same location. + +For instance, we have no concern for aliasing in the following modified version +of our function, because we've moved the only write to `*output` to the very +end of our function. This allows us to freely reorder the reads of `*input` that +occur before it: + +```rust +fn compute(input: &u32, output: &mut u32) { + let mut temp = *output; + if *input > 10 { + temp = 1; + } + if *input > 5 { + temp *= 2; + } + *output = temp; +} +``` + +We're still relying on alias analysis to assume that `temp` doesn't alias +`input`, but the proof is much simpler: the value of a local variable can't be +aliased by things that existed before it was declared. This is an assumption +every language freely makes, and so this version of the function could be +optimized the way we want in any language. + +This is why the definition of "alias" that Rust will use likely involves some +notion of liveness and mutation: we don't actually care if aliasing occurs if +there aren't any actual writes to memory happening. + +Of course, a full aliasing model for Rust must also take into consideration things like +function calls (which may mutate things we don't see), raw pointers (which have +no aliasing requirements on their own), and UnsafeCell (which lets the referent +of an `&` be mutated). + + + diff --git a/src/doc/nomicon/src/destructors.md b/src/doc/nomicon/src/destructors.md index 6c7b2c9d09..5b3f546804 100644 --- a/src/doc/nomicon/src/destructors.md +++ b/src/doc/nomicon/src/destructors.md @@ -26,14 +26,11 @@ this is totally fine. For instance, a custom implementation of `Box` might write `Drop` like this: ```rust -#![feature(alloc, heap_api, unique)] +#![feature(unique, allocator_api)] -extern crate alloc; - -use std::ptr::{drop_in_place, Unique}; +use std::heap::{Heap, Alloc, Layout}; use std::mem; - -use alloc::heap; +use std::ptr::{drop_in_place, Unique}; struct Box{ ptr: Unique } @@ -41,9 +38,7 @@ impl Drop for Box { fn drop(&mut self) { unsafe { drop_in_place(self.ptr.as_ptr()); - heap::deallocate(self.ptr.as_ptr() as *mut u8, - mem::size_of::(), - mem::align_of::()); + Heap.dealloc(self.ptr.as_ptr() as *mut u8, Layout::new::()) } } } @@ -57,24 +52,19 @@ use-after-free the `ptr` because when drop exits, it becomes inaccessible. However this wouldn't work: ```rust -#![feature(alloc, heap_api, unique)] - -extern crate alloc; +#![feature(allocator_api, unique)] +use std::heap::{Heap, Alloc, Layout}; use std::ptr::{drop_in_place, Unique}; use std::mem; -use alloc::heap; - struct Box{ ptr: Unique } impl Drop for Box { fn drop(&mut self) { unsafe { drop_in_place(self.ptr.as_ptr()); - heap::deallocate(self.ptr.as_ptr() as *mut u8, - mem::size_of::(), - mem::align_of::()); + Heap.dealloc(self.ptr.as_ptr() as *mut u8, Layout::new::()); } } } @@ -86,9 +76,7 @@ impl Drop for SuperBox { unsafe { // Hyper-optimized: deallocate the box's contents for it // without `drop`ing the contents - heap::deallocate(self.my_box.ptr.as_ptr() as *mut u8, - mem::size_of::(), - mem::align_of::()); + Heap.dealloc(self.my_box.ptr.as_ptr() as *mut u8, Layout::new::()); } } } @@ -135,24 +123,19 @@ 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, unique)] - -extern crate alloc; +#![feature(allocator_api, unique)] +use std::heap::{Alloc, Heap, Layout}; use std::ptr::{drop_in_place, Unique}; use std::mem; -use alloc::heap; - struct Box{ ptr: Unique } impl Drop for Box { fn drop(&mut self) { unsafe { drop_in_place(self.ptr.as_ptr()); - heap::deallocate(self.ptr.as_ptr() as *mut u8, - mem::size_of::(), - mem::align_of::()); + Heap.dealloc(self.ptr.as_ptr() as *mut u8, Layout::new::()); } } } @@ -166,9 +149,7 @@ impl Drop for SuperBox { // without `drop`ing the contents. Need to set the `box` // field as `None` to prevent Rust from trying to Drop it. let my_box = self.my_box.take().unwrap(); - heap::deallocate(my_box.ptr.as_ptr() as *mut u8, - mem::size_of::(), - mem::align_of::()); + Heap.dealloc(my_box.ptr.as_ptr() as *mut u8, Layout::new::()); mem::forget(my_box); } } diff --git a/src/doc/nomicon/src/dropck.md b/src/doc/nomicon/src/dropck.md index 39039694be..f1fef35991 100644 --- a/src/doc/nomicon/src/dropck.md +++ b/src/doc/nomicon/src/dropck.md @@ -80,24 +80,18 @@ fn main() { ``` ```text -:12:28: 12:32 error: `days` does not live long enough -:12 inspector = Inspector(&days); - ^~~~ -:9:11: 15:2 note: reference must be valid for the block at 9:10... -:9 fn main() { -:10 let (inspector, days); -:11 days = Box::new(1); -:12 inspector = Inspector(&days); -:13 // Let's say `days` happens to get dropped first. -:14 // Then when Inspector is dropped, it will try to read free'd memory! - ... -:10:27: 15:2 note: ...but borrowed value is only valid for the block suffix following statement 0 at 10:26 -:10 let (inspector, days); -:11 days = Box::new(1); -:12 inspector = Inspector(&days); -:13 // Let's say `days` happens to get dropped first. -:14 // Then when Inspector is dropped, it will try to read free'd memory! -:15 } +error: `days` does not live long enough + --> :15:1 + | +12 | inspector = Inspector(&days); + | ---- borrow occurs here +... +15 | } + | ^ `days` dropped here while still borrowed + | + = note: values in a scope are dropped in the opposite order they are created + +error: aborting due to previous error ``` Implementing Drop lets the Inspector execute some arbitrary code during its diff --git a/src/doc/nomicon/src/references.md b/src/doc/nomicon/src/references.md index 5d80f1edd9..294fe1c8ab 100644 --- a/src/doc/nomicon/src/references.md +++ b/src/doc/nomicon/src/references.md @@ -1,12 +1,5 @@ # References -This section gives a high-level view of the memory model that *all* Rust -programs must satisfy to be correct. Safe code is statically verified -to obey this model by the borrow checker. Unsafe code may go above -and beyond the borrow checker while still satisfying this model. The borrow -checker may also be extended to allow more programs to compile, as long as -this more fundamental model is satisfied. - There are two kinds of reference: * Shared reference: `&` @@ -17,161 +10,22 @@ Which obey the following rules: * A reference cannot outlive its referent * A mutable reference cannot be aliased -That's it. That's the whole model. Of course, we should probably define -what *aliased* means. To define aliasing, we must define the notion of -*paths* and *liveness*. - - -**NOTE: The model that follows is generally agreed to be dubious and have -issues. It's ok-ish as an intuitive model, but fails to capture the desired -semantics. We leave this here to be able to use notions introduced here in later -sections. This will be significantly changed in the future. TODO: do that.** - - -# Paths - -If all Rust had were values (no pointers), then every value would be uniquely -owned by a variable or composite structure. From this we naturally derive a -*tree* of ownership. The stack itself is the root of the tree, with every -variable as its direct children. Each variable's direct children would be their -fields (if any), and so on. - -From this view, every value in Rust has a unique *path* in the tree of -ownership. Of particular interest are *ancestors* and *descendants*: if `x` owns -`y`, then `x` is an ancestor of `y`, and `y` is a descendant of `x`. Note -that this is an inclusive relationship: `x` is a descendant and ancestor of -itself. - -We can then define references as simply *names* for paths. When you create a -reference, you're declaring that an ownership path exists to this address -of memory. - -Tragically, plenty of data doesn't reside on the stack, and we must also -accommodate this. Globals and thread-locals are simple enough to model as -residing at the bottom of the stack (though we must be careful with mutable -globals). Data on the heap poses a different problem. - -If all Rust had on the heap was data uniquely owned by a pointer on the stack, -then we could just treat such a pointer as a struct that owns the value on the -heap. Box, Vec, String, and HashMap, are examples of types which uniquely -own data on the heap. - -Unfortunately, data on the heap is not *always* uniquely owned. Rc for instance -introduces a notion of *shared* ownership. Shared ownership of a value means -there is no unique path to it. A value with no unique path limits what we can do -with it. - -In general, only shared references can be created to non-unique paths. However -mechanisms which ensure mutual exclusion may establish One True Owner -temporarily, establishing a unique path to that value (and therefore all -its children). If this is done, the value may be mutated. In particular, a -mutable reference can be taken. - -The most common way to establish such a path is through *interior mutability*, -in contrast to the *inherited mutability* that everything in Rust normally uses. -Cell, RefCell, Mutex, and RWLock are all examples of interior mutability types. -These types provide exclusive access through runtime restrictions. - -An interesting case of this effect is Rc itself: if an Rc has refcount 1, -then it is safe to mutate or even move its internals. Note however that the -refcount itself uses interior mutability. - -In order to correctly communicate to the type system that a variable or field of -a struct can have interior mutability, it must be wrapped in an UnsafeCell. This -does not in itself make it safe to perform interior mutability operations on -that value. You still must yourself ensure that mutual exclusion is upheld. - - - +That's it. That's the whole model references follow. -# Liveness +Of course, we should probably define what *aliased* means. -Note: Liveness is not the same thing as a *lifetime*, which will be explained -in detail in the next section of this chapter. +```text +error[E0425]: cannot find value `aliased` in this scope + --> :2:20 + | +2 | println!("{}", aliased); + | ^^^^^^^ not found in this scope -Roughly, a reference is *live* at some point in a program if it can be -dereferenced. Shared references are always live unless they are literally -unreachable (for instance, they reside in freed or leaked memory). Mutable -references can be reachable but *not* live through the process of *reborrowing*. - -A mutable reference can be reborrowed to either a shared or mutable reference to -one of its descendants. A reborrowed reference will only be live again once all -reborrows derived from it expire. For instance, a mutable reference can be -reborrowed to point to a field of its referent: - -```rust -let x = &mut (1, 2); -{ - // reborrow x to a subfield - let y = &mut x.0; - // y is now live, but x isn't - *y = 3; -} -// y goes out of scope, so x is live again -*x = (5, 7); +error: aborting due to previous error ``` -It is also possible to reborrow into *multiple* mutable references, as long as -they are *disjoint*: no reference is an ancestor of another. Rust -explicitly enables this to be done with disjoint struct fields, because -disjointness can be statically proven: - -```rust -let x = &mut (1, 2); -{ - // reborrow x to two disjoint subfields - let y = &mut x.0; - let z = &mut x.1; - - // y and z are now live, but x isn't - *y = 3; - *z = 4; -} -// y and z go out of scope, so x is live again -*x = (5, 7); -``` - -However it's often the case that Rust isn't sufficiently smart to prove that -multiple borrows are disjoint. *This does not mean it is fundamentally illegal -to make such a borrow*, just that Rust isn't as smart as you want. - -To simplify things, we can model variables as a fake type of reference: *owned* -references. Owned references have much the same semantics as mutable references: -they can be re-borrowed in a mutable or shared manner, which makes them no -longer live. Live owned references have the unique property that they can be -moved out of (though mutable references *can* be swapped out of). This power is -only given to *live* owned references because moving its referent would of -course invalidate all outstanding references prematurely. - -As a local lint against inappropriate mutation, only variables that are marked -as `mut` can be borrowed mutably. - -It is interesting to note that Box behaves exactly like an owned reference. It -can be moved out of, and Rust understands it sufficiently to reason about its -paths like a normal variable. - - - - -# Aliasing - -With liveness and paths defined, we can now properly define *aliasing*: - -**A mutable reference is aliased if there exists another live reference to one -of its ancestors or descendants.** - -(If you prefer, you may also say the two live references alias *each other*. -This has no semantic consequences, but is probably a more useful notion when -verifying the soundness of a construct.) - -That's it. Super simple right? Except for the fact that it took us two pages to -define all of the terms in that definition. You know: Super. Simple. - -Actually it's a bit more complicated than that. In addition to references, Rust -has *raw pointers*: `*const T` and `*mut T`. Raw pointers have no inherent -ownership or aliasing semantics. As a result, Rust makes absolutely no effort to -track that they are used correctly, and they are wildly unsafe. +Unfortunately, Rust hasn't actually defined its aliasing model. 🙀 -**It is an open question to what degree raw pointers have alias semantics. -However it is important for these definitions to be sound that the existence of -a raw pointer does not imply some kind of live path.** +While we wait for the Rust devs to specify the semantics of their language, +let's use the next section to discuss what aliasing is in general, and why it +matters. diff --git a/src/doc/nomicon/src/vec-final.md b/src/doc/nomicon/src/vec-final.md index cfea0d67e9..fd6c592c33 100644 --- a/src/doc/nomicon/src/vec-final.md +++ b/src/doc/nomicon/src/vec-final.md @@ -2,16 +2,13 @@ ```rust #![feature(unique)] -#![feature(alloc, heap_api)] - -extern crate alloc; +#![feature(allocator_api)] use std::ptr::{Unique, self}; use std::mem; use std::ops::{Deref, DerefMut}; use std::marker::PhantomData; - -use alloc::heap; +use std::heap::{Alloc, Layout, Heap}; struct RawVec { ptr: Unique, @@ -35,22 +32,22 @@ impl RawVec { // 0, getting to here necessarily means the Vec is overfull. assert!(elem_size != 0, "capacity overflow"); - let align = mem::align_of::(); - let (new_cap, ptr) = if self.cap == 0 { - let ptr = heap::allocate(elem_size, align); + let ptr = Heap.alloc(Layout::array::(1).unwrap()); (1, ptr) } else { let new_cap = 2 * self.cap; - let ptr = heap::reallocate(self.ptr.as_ptr() as *mut _, - self.cap * elem_size, - new_cap * elem_size, - align); + let ptr = Heap.realloc(self.ptr.as_ptr() as *mut _, + Layout::array::(self.cap).unwrap(), + Layout::array::(new_cap).unwrap()); (new_cap, ptr) }; - // If allocate or reallocate fail, we'll get `null` back - if ptr.is_null() { oom() } + // If allocate or reallocate fail, oom + let ptr = match ptr { + Ok(ptr) => ptr, + Err(err) => Heap.oom(err), + }; self.ptr = Unique::new(ptr as *mut _); self.cap = new_cap; @@ -62,20 +59,14 @@ impl Drop for RawVec { fn drop(&mut self) { let elem_size = mem::size_of::(); if self.cap != 0 && elem_size != 0 { - let align = mem::align_of::(); - - let num_bytes = elem_size * self.cap; unsafe { - heap::deallocate(self.ptr.as_ptr() as *mut _, num_bytes, align); + Heap.dealloc(self.ptr.as_ptr() as *mut _, + Layout::array::(self.cap).unwrap()); } } } } - - - - pub struct Vec { buf: RawVec, len: usize, diff --git a/src/doc/reference/src/attributes.md b/src/doc/reference/src/attributes.md index 05c1e10038..18d0961105 100644 --- a/src/doc/reference/src/attributes.md +++ b/src/doc/reference/src/attributes.md @@ -28,7 +28,7 @@ fn test_foo() { } // A conditionally-compiled module -#[cfg(target_os="linux")] +#[cfg(target_os = "linux")] mod bar { /* ... */ } @@ -206,8 +206,10 @@ macro scope. You may use format arguments like `{T}`, `{A}` to correspond to the types at the point of use corresponding to the type parameters of the trait of the same name. `{Self}` will be replaced with the type that is supposed - to implement the trait but doesn't. To use this, the `on_unimplemented` feature gate - must be enabled. + to implement the trait but doesn't. You can also use the trait's name which will + be replaced with the full path for the trait, for example for the trait `Foo` in + module `Bar`, `{Foo}` can be used and will show up as `Bar::Foo`. + To use this, the `on_unimplemented` feature gate must be enabled. - `must_use` - on structs and enums, will warn if a value of this type isn't used or assigned to a variable. You may also include an optional message by using `#[must_use = "message"]` which will be given alongside the warning. diff --git a/src/doc/reference/src/behavior-considered-undefined.md b/src/doc/reference/src/behavior-considered-undefined.md index b617ee3d78..9fb3d74148 100644 --- a/src/doc/reference/src/behavior-considered-undefined.md +++ b/src/doc/reference/src/behavior-considered-undefined.md @@ -10,7 +10,7 @@ the guarantee that these issues are never caused by safe code. (uninitialized) memory * Breaking the [pointer aliasing rules](http://llvm.org/docs/LangRef.html#pointer-aliasing-rules) - with raw pointers (a subset of the rules used by C) + on accesses through raw pointers (a subset of the rules used by C) * `&mut T` and `&T` follow LLVM’s scoped [noalias] model, except if the `&T` contains an `UnsafeCell`. Unsafe code must not violate these aliasing guarantees. diff --git a/src/doc/reference/src/behavior-not-considered-unsafe.md b/src/doc/reference/src/behavior-not-considered-unsafe.md index e16103372f..20f3cad5fc 100644 --- a/src/doc/reference/src/behavior-not-considered-unsafe.md +++ b/src/doc/reference/src/behavior-not-considered-unsafe.md @@ -1,15 +1,39 @@ -## Behavior not considered unsafe - -This is a list of behavior not considered *unsafe* in Rust terms, but that may -be undesired. - -* Deadlocks -* Leaks of memory and other resources -* Exiting without calling destructors -* Integer overflow - - Overflow is considered "unexpected" behavior and is always user-error, - unless the `wrapping` primitives are used. In non-optimized builds, the compiler - will insert debug checks that panic on overflow, but in optimized builds overflow - instead results in wrapped values. See [RFC 560] for the rationale and more details. +## Behavior not considered `unsafe` + +The Rust compiler does not consider the following behaviors _unsafe_, +though a programmer may (should) find them undesirable, unexpected, +or erroneous. + +##### Deadlocks +##### Leaks of memory and other resources +##### Exiting without calling destructors +##### Exposing randomized base addresses through pointer leaks +##### Integer overflow + +If a program contains arithmetic overflow, the programmer has made an +error. In the following discussion, we maintain a distinction between +arithmetic overflow and wrapping arithmetic. The first is erroneous, +while the second is intentional. + +When the programmer has enabled `debug_assert!` assertions (for +example, by enabling a non-optimized build), implementations must +insert dynamic checks that `panic` on overflow. Other kinds of builds +may result in `panics` or silently wrapped values on overflow, at the +implementation's discretion. + +In the case of implicitly-wrapped overflow, implementations must +provide well-defined (even if still considered erroneous) results by +using two's complement overflow conventions. + +The integral types provide inherent methods to allow programmers +explicitly to perform wrapping arithmetic. For example, +`i32::wrapping_add` provides two's complement, wrapping addition. + +The standard library also provides a `Wrapping` newtype which +ensures all standard arithmetic operations for `T` have wrapping +semantics. + +See [RFC 560] for error conditions, rationale, and more details about +integer overflow. [RFC 560]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md diff --git a/src/doc/reference/src/expressions.md b/src/doc/reference/src/expressions.md index 0783b9bf19..96d2d21627 100644 --- a/src/doc/reference/src/expressions.md +++ b/src/doc/reference/src/expressions.md @@ -72,13 +72,13 @@ The following expressions can create mutable lvalues: * [Temporary values](#temporary-lifetimes). * [Fields](#field-expressions), this evaluates the subexpression in a mutable lvalue context. -* [Dereferenes](#the-dereference-operator) of a `*mut T` pointer. +* [Dereferences](#the-dereference-operator) of a `*mut T` pointer. * Dereference of a variable, or field of a variable, with type `&mut T`. Note: this is an exception to the requirement for the next rule. * Dereferences of a type that implements `DerefMut`, this then requires that the value being dereferenced is evaluated is a mutable lvalue context. * [Indexing](#index-expressions) of a type that implements `DerefMut`, this - then evalutes the value being indexed (but not the index) in mutable lvalue + then evaluates the value being indexed (but not the index) in mutable lvalue context. ### Temporary lifetimes @@ -168,7 +168,7 @@ also constant expressions: * [Paths](#path-expressions) to [functions](items.html#functions) and constants. Recursively defining constants is not allowed. * Paths to statics, so long as only their address, not their value, is used. - This includes using their value indirectly through a compilicated expression. + This includes using their value indirectly through a complicated expression. \* * [Tuple expressions](#tuple-expressions). * [Array expressions](#array-expressions). @@ -267,7 +267,9 @@ the field values of a new instance of the struct. A field name can be any [identifier](identifiers.html), and is separated from its value expression by a colon. In the case of a tuple struct the field names are numbers corresponding to the position of the field. The numbers must be written in decimal, -containing no underscores and with no leading zeros or integer suffix. +containing no underscores and with no leading zeros or integer suffix. A value +of a [union](items.html#unions) type can also be created using this syntax, +except that it must specify exactly one field. Struct expressions can't be used directly in the head of a [loop](#loops) or an [`if`](#if-expressions), [`if let`](#if-let-expressions) or @@ -441,8 +443,8 @@ A _field expression_ consists of an expression followed by a single dot and an [identifier](identifiers.html), when not immediately followed by a parenthesized expression-list (the latter is always a [method call expression](#method-call-expressions)). A field expression denotes a field of a -[struct](types.html#struct-types). To call a function stored in a struct -parentheses are needed around the field expression +[struct](types.html#struct-types) or [union](items.html#unions). To call a +function stored in a struct parentheses are needed around the field expression ```rust,ignore mystruct.myfield; @@ -452,9 +454,9 @@ mystruct.method(); // Method expression (mystruct.function_field)() // Call expression containing a field expression ``` -A field access is an [lvalue](expressions.html#lvalues-and-rvalues) referring to the value of -that field. When the subexpression is [mutable](#mutability), the field -expression is also mutable. +A field access is an [lvalue](expressions.html#lvalues-and-rvalues) referring +to the location of that field. When the subexpression is +[mutable](#mutability), the field expression is also mutable. Also, if the type of the expression to the left of the dot is a pointer, it is automatically dereferenced as many times as necessary to make the field access @@ -482,7 +484,7 @@ let d: String = x.f3; // Move out of x.f3 ### Tuple indexing expressions [Tuples](types.html#tuple-types) and [struct tuples](items.html#structs) can be -indexed using the number corresponding to the possition of the field. The index +indexed using the number corresponding to the position of the field. The index must be written as a [decimal literal](tokens.html#integer-literals) with no underscores or suffix. Tuple indexing expressions also differ from field expressions in that they can unambiguously be called as a function. In all diff --git a/src/doc/reference/src/items.md b/src/doc/reference/src/items.md index d5eef800ad..cb97b44072 100644 --- a/src/doc/reference/src/items.md +++ b/src/doc/reference/src/items.md @@ -416,6 +416,7 @@ modifier. extern fn new_i32() -> i32 { 0 } // Declares an extern fn with "stdcall" ABI +# #[cfg(target_arch = "x86_64")] extern "stdcall" fn new_i32_stdcall() -> i32 { 0 } ``` @@ -591,7 +592,7 @@ struct types, except that it must specify exactly one field: ```rust # union MyUnion { f1: u32, f2: f32 } - +# let u = MyUnion { f1: 1 }; ``` @@ -612,7 +613,7 @@ union fields have to be placed in `unsafe` blocks. ```rust # union MyUnion { f1: u32, f2: f32 } # let u = MyUnion { f1: 1 }; - +# unsafe { let f = u.f1; } @@ -624,7 +625,7 @@ so these writes don't have to be placed in `unsafe` blocks ```rust # union MyUnion { f1: u32, f2: f32 } # let mut u = MyUnion { f1: 1 }; - +# u.f1 = 2; ``` @@ -639,7 +640,7 @@ to be placed in `unsafe` blocks as well. ```rust # union MyUnion { f1: u32, f2: f32 } - +# fn f(u: MyUnion) { unsafe { match u { @@ -715,12 +716,14 @@ More detailed specification for unions, including unstable bits, can be found in ## Constant items -A *constant item* is a named _constant value_ which is not associated with a +A *constant item* is a named _[constant value]_ which is not associated with a specific memory location in the program. Constants are essentially inlined wherever they are used, meaning that they are copied directly into the relevant context when used. References to the same constant are not necessarily guaranteed to refer to the same memory address. +[constant value]: expressions.html#constant-expressions + Constant values must not have destructors, and otherwise permit most forms of data. Constants may refer to the address of other constants, in which case the address will have elided lifetimes where applicable, otherwise – in most cases – @@ -863,7 +866,7 @@ implement. This interface consists of associated items, which come in three varieties: - functions -- constants +- [constants](#associated-constants) - types Associated functions whose first parameter is named `self` are called @@ -1077,6 +1080,79 @@ let mycircle = Box::new(mycircle) as Box; let nonsense = mycircle.radius() * mycircle.area(); ``` +#### Associated Constants + + +A trait can define constants like this: + +```rust +trait Foo { + const ID: i32; +} + +impl Foo for i32 { + const ID: i32 = 1; +} + +fn main() { + assert_eq!(1, i32::ID); +} +``` + +Any implementor of `Foo` will have to define `ID`. Without the definition: + +```rust,ignore +trait Foo { + const ID: i32; +} + +impl Foo for i32 { +} +``` + +gives + +```text +error: not all trait items implemented, missing: `ID` [E0046] + impl Foo for i32 { + } +``` + +A default value can be implemented as well: + +```rust +trait Foo { + const ID: i32 = 1; +} + +impl Foo for i32 { +} + +impl Foo for i64 { + const ID: i32 = 5; +} + +fn main() { + assert_eq!(1, i32::ID); + assert_eq!(5, i64::ID); +} +``` + +As you can see, when implementing `Foo`, you can leave it unimplemented, as +with `i32`. It will then use the default value. But, as in `i64`, we can also +add our own definition. + +Associated constants don’t have to be associated with a trait. An `impl` block +for a `struct` or an `enum` works fine too: + +```rust +struct Foo; + +impl Foo { + const FOO: u32 = 3; +} +``` + ### Implementations An _implementation_ is an item that implements a [trait](#traits) for a diff --git a/src/doc/reference/src/linkage.md b/src/doc/reference/src/linkage.md index 3072ff135d..3e004315a6 100644 --- a/src/doc/reference/src/linkage.md +++ b/src/doc/reference/src/linkage.md @@ -132,8 +132,8 @@ The standard library in general strives to support both statically linked and dynamically linked C runtimes for targets as appropriate. For example the `x86_64-pc-windows-msvc` and `x86_64-unknown-linux-musl` targets typically come with both runtimes and the user selects which one they'd like. All targets in -the compiler have a default mode of linking to the C runtime. Typicall targets -linked dynamically by default, but there are exceptions which are static by +the compiler have a default mode of linking to the C runtime. Typically targets +are linked dynamically by default, but there are exceptions which are static by default such as: * `arm-unknown-linux-musleabi` diff --git a/src/doc/reference/src/statements.md b/src/doc/reference/src/statements.md index 0c21bb2989..ced9a850a1 100644 --- a/src/doc/reference/src/statements.md +++ b/src/doc/reference/src/statements.md @@ -37,10 +37,9 @@ declaration until the end of the enclosing block scope. ## Expression statements An _expression statement_ is one that evaluates an -[expression](expressions.html) and ignores its result. The type of an -expression statement `e;` is always `()`, regardless of the type of `e`. As a -rule, an expression statement's purpose is to trigger the effects of evaluating -its expression. An expression that consists of only a [block +[expression](expressions.html) and ignores its result. As a rule, an expression +statement's purpose is to trigger the effects of evaluating its expression. +An expression that consists of only a [block expression](expressions.html#block-expressions) or control flow expression, that doesn't end a block and evaluates to `()` can also be used as an expression statement by omitting the trailing semicolon. diff --git a/src/doc/reference/src/tokens.md b/src/doc/reference/src/tokens.md index de3200fe42..3163a9de6b 100644 --- a/src/doc/reference/src/tokens.md +++ b/src/doc/reference/src/tokens.md @@ -12,7 +12,8 @@ grammar as double-quoted strings. Other tokens have exact rules given. A literal is an expression consisting of a single token, rather than a sequence of tokens, that immediately and directly denotes the value it evaluates to, rather than referring to it by name or some other evaluation rule. A literal is -a form of constant expression, so is evaluated (primarily) at compile time. +a form of [constant expression](expressions.html#constant-expressions), so is +evaluated (primarily) at compile time. ### Examples diff --git a/src/doc/reference/src/undocumented.md b/src/doc/reference/src/undocumented.md index 72a5461277..e7eaf10d30 100644 --- a/src/doc/reference/src/undocumented.md +++ b/src/doc/reference/src/undocumented.md @@ -15,8 +15,6 @@ to shrink! - [Flexible target specification] - Some---but not all---flags are documented in [Conditional compilation] - [Require parentheses for chained comparisons] -- [Integer overflow not `unsafe`] - documented with a reference to the RFC, but - requires further details - [`dllimport`] - one element mentioned but not explained at [FFI attributes] - [define `crt_link`] - [define `unaligned_access`] diff --git a/src/doc/rustdoc/src/SUMMARY.md b/src/doc/rustdoc/src/SUMMARY.md new file mode 100644 index 0000000000..cd6883a719 --- /dev/null +++ b/src/doc/rustdoc/src/SUMMARY.md @@ -0,0 +1,8 @@ +# The Rustdoc Book + +- [What is rustdoc?](what-is-rustdoc.md) +- [Command-line arguments](command-line-arguments.md) +- [In-source directives](in-source-directives.md) +- [Documentation tests](documentation-tests.md) +- [Plugins](plugins.md) +- [Passes](passes.md) \ No newline at end of file diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md new file mode 100644 index 0000000000..36c1b050dd --- /dev/null +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -0,0 +1,348 @@ +# Command-line arguments + +Here's the list of arguments you can pass to `rustdoc`: + +## `-h`/`--help`: help + +Using this flag looks like this: + +```bash +$ rustdoc -h +$ rustdoc --help +``` + +This will show `rustdoc`'s built-in help, which largely consists of +a list of possible command-line flags. + +Some of `rustdoc`'s flags are unstable; this page only shows stable +options, `--help` will show them all. + +## `-V`/`--version`: version information + +Using this flag looks like this: + +```bash +$ rustdoc -V +$ rustdoc --version +``` + +This will show `rustdoc`'s version, which will look something +like this: + +```text +rustdoc 1.17.0 (56124baa9 2017-04-24) +``` + +## `-v`/`--verbose`: more verbose output + +Using this flag looks like this: + +```bash +$ rustdoc -v src/lib.rs +$ rustdoc --verbose src/lib.rs +``` + +This enables "verbose mode", which means that more information will be written +to standard out. What is written depends on the other flags you've passed in. +For example, with `--version`: + +```text +$ rustdoc --verbose --version +rustdoc 1.17.0 (56124baa9 2017-04-24) +binary: rustdoc +commit-hash: hash +commit-date: date +host: host-triple +release: 1.17.0 +LLVM version: 3.9 +``` + +## `-r`/`--input-format`: input format + +This flag is currently ignored; the idea is that `rustdoc` would support various +input formats, and you could specify them via this flag. + +Rustdoc only supports Rust source code and Markdown input formats. If the +file ends in `.md` or `.markdown`, `rustdoc` treats it as a Markdown file. +Otherwise, it assumes that the input file is Rust. + + +## `-w`/`--output-format`: output format + +This flag is currently ignored; the idea is that `rustdoc` would support +various output formats, and you could specify them via this flag. + +Rustdoc only supports HTML output, and so this flag is redundant today. + +## `-o`/`--output`: output path + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs -o target\\doc +$ rustdoc src/lib.rs --output target\\doc +``` + +By default, `rustdoc`'s output appears in a directory named `doc` in +the current working directory. With this flag, it will place all output +into the directory you specify. + + +## `--crate-name`: controlling the name of the crate + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs --crate-name mycrate +``` + +By default, `rustodc` assumes that the name of your crate is the same name +as the `.rs` file. `--crate-name` lets you override this assumption with +whatever name you choose. + +## `-L`/`--library-path`: + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs -L target/debug/deps +$ rustdoc src/lib.rs --library-path target/debug/deps +``` + +If your crate has dependencies, `rustdoc` needs to know where to find them. +Passing `--library-path` gives `rustdoc` a list of places to look for these +dependencies. + +This flag takes any number of directories as its argument, and will use all of +them when searching. + + +## `--cfg`: passing configuration flags + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs --cfg feature="foo" +``` + +This flag accepts the same values as `rustc --cfg`, and uses it to configure +compilation. The example above uses `feature`, but any of the `cfg` values +are acceptable. + +## `--extern`: specify a dependency's location + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs --extern lazy-static=/path/to/lazy-static +``` + +Similar to `--library-path`, `--extern` is about specifying the location +of a dependency. `--library-path` provides directories to search in, `--extern` +instead lets you specify exactly which dependency is located where. + + +## `--plugin-path`: loading plugins + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs --plugin-path=/path/to/plugins +``` + +Similar to `--library-path`, but for plugins. For more, see +the [chapter on plugins](plugins.html). + +See also: `--plugins`. + +## `--passes`: add more rustdoc passes + +Using this flag looks like this: + +```bash +$ rustdoc --passes list +$ rustdoc src/lib.rs --passes strip-priv-imports +``` + +An argument of "list" will print a list of possible "rustdoc passes", and other +arguments will be the name of which passes to run in addition to the defaults. + +For more details on passes, see [the chapter on them](passes.html). + +See also `--no-defaults`. + +## `--plugins`: + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs --plugins foo bar +``` + +For more, see the [chapter on plugins](plugins.html). + +See also: `--plugin-path`. + +## `--no-defaults`: don't run default passes + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs --no-defaults +``` + +By default, `rustdoc` will run several passes over your code. This +removes those defaults, allowing you to use `--passes` to specify +exactly which passes you want. + +For more details on passes, see [the chapter on them](passes.html). + +See also `--passes`. + +## `--test`: run code examples as tests + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs --test +``` + +This flag will run your code examples as tests. For more, see [the chapter +on documentation tests](documentation-tests.html). + +See also `--test-args`. + +## `--test-args`: + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs --test --test-args ignored +``` + +This flag will pass options to the test runner when running documentation tests. +For more, see [the chapter on documentation tests](documentation-tests.html). + +See also `--test`. + +## `--target`: + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs --target x86_64-pc-windows-gnu +``` + +Similar to the `--target` flag for `rustc`, this generates documentation +for a target triple that's different than your host triple. + +All of the usual caveats of cross-compiling code apply. + +## `--markdown-css`: include more CSS files when rendering markdown + +Using this flag looks like this: + +```bash +$ rustdoc README.md --markdown-css foo.css +``` + +When rendering Markdown files, this will create a `` element in the +`` section of the generated HTML. For example, with the invocation above, + +```html + +``` + +will be added. + +When rendering Rust files, this flag is ignored. + +## `--html-in-header`: include more HTML in + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs --html-in-header header.html +$ rustdoc README.md --html-in-header header.html +``` + +This flag takes a list of files, and inserts them into the `` section of +the rendered documentation. + +## `--html-before-content`: include more HTML before the content + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs --html-before-content extra.html +$ rustdoc README.md --html-before-content extra.html +``` + +This flag takes a list of files, and inserts them inside the `` tag but +before the other content `rustodc` would normally produce in the rendered +documentation. + +## `--html-after-content`: include more HTML after the content + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs --html-after-content extra.html +$ rustdoc README.md --html-after-content extra.html +``` + +This flag takes a list of files, and inserts them before the `` tag but +after the other content `rustodc` would normally produce in the rendered +documentation. + + +## `--markdown-playground-url`: control the location of the playground + +Using this flag looks like this: + +```bash +$ rustdoc README.md --markdown-playground-url https://play.rust-lang.org/ +``` + +When rendering a Markdown file, this flag gives the base URL of the Rust +Playround, to use for generating `Run` buttons. + + +## `--markdown-no-toc`: don't generate a table of contents + +Using this flag looks like this: + +```bash +$ rustdoc README.md --markdown-no-toc +``` + +When generating documentation from a Markdown file, by default, `rustdoc` will +generate a table of contents. This flag supresses that, and no TOC will be +generated. + + +## `-e`/`--extend-css`: extend rustdoc's CSS + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs -e extra.css +$ rustdoc src/lib.rs --extend-css extra.css +``` + +With this flag, the contents of the files you pass are included at the bottom +of Rustdoc's `theme.css` file. + +While this flag is stable, the contents of `theme.css` are not, so be careful! +Updates may break your theme extensions. + +## `--sysroot`: override the system root + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs --sysroot /path/to/sysroot +``` + +Similar to `rustc --sysroot`, this lets you change the sysroot `rustdoc` uses +when compiling your code. \ No newline at end of file diff --git a/src/doc/rustdoc/src/documentation-tests.md b/src/doc/rustdoc/src/documentation-tests.md new file mode 100644 index 0000000000..cd7d657e11 --- /dev/null +++ b/src/doc/rustdoc/src/documentation-tests.md @@ -0,0 +1,3 @@ +# Documentation tests + +Coming soon! \ No newline at end of file diff --git a/src/doc/rustdoc/src/in-source-directives.md b/src/doc/rustdoc/src/in-source-directives.md new file mode 100644 index 0000000000..83f677fa7f --- /dev/null +++ b/src/doc/rustdoc/src/in-source-directives.md @@ -0,0 +1,3 @@ +# In-source directives + +Coming soon! \ No newline at end of file diff --git a/src/doc/rustdoc/src/passes.md b/src/doc/rustdoc/src/passes.md new file mode 100644 index 0000000000..12054d04a7 --- /dev/null +++ b/src/doc/rustdoc/src/passes.md @@ -0,0 +1,3 @@ +# Passes + +Coming soon! \ No newline at end of file diff --git a/src/doc/rustdoc/src/plugins.md b/src/doc/rustdoc/src/plugins.md new file mode 100644 index 0000000000..c0d5ed752c --- /dev/null +++ b/src/doc/rustdoc/src/plugins.md @@ -0,0 +1,3 @@ +# Plugins + +Coming soon! \ No newline at end of file diff --git a/src/doc/rustdoc/src/what-is-rustdoc.md b/src/doc/rustdoc/src/what-is-rustdoc.md new file mode 100644 index 0000000000..54472e35b1 --- /dev/null +++ b/src/doc/rustdoc/src/what-is-rustdoc.md @@ -0,0 +1,131 @@ +# What is rustdoc? + +The standard Rust distribution ships with a tool called `rustdoc`. Its job is +to generate documentation for Rust projects. On a fundamental level, Rustdoc +takes as an argument either a crate root or a Markdown file, and produces HTML, +CSS, and JavaScript. + +## Basic usage + +Let's give it a try! Let's create a new project with Cargo: + +```bash +$ cargo new docs +$ cd docs +``` + +In `src/lib.rs`, you'll find that Cargo has generated some sample code. Delete +it and replace it with this: + +```rust +/// foo is a function +fn foo() {} +``` + +Let's run `rustdoc` on our code. To do so, we can call it with the path to +our crate root like this: + +```bash +$ rustdoc src/lib.rs +``` + +This will create a new directory, `doc`, with a website inside! In our case, +the main page is located in `doc/lib/index.html`. If you open that up in +a web browser, you'll see a page with a search bar, and "Crate lib" at the +top, with no contents. There's two problems with this: first, why does it +think that our package is named "lib"? Second, why does it not have any +contents? + +The first problem is due to `rustdoc` trying to be helpful; like `rustc`, +it assumes that our crate's name is the name of the file for the crate +root. To fix this, we can pass in a command-line flag: + +```bash +$ rustdoc src/lib.rs --crate-name docs +``` + +Now, `doc/docs/index.html` will be generated, and the page says "Crate docs." + +For the second issue, it's because our function `foo` is not public; `rustdoc` +defaults to generating documentation for only public functions. If we change +our code... + +```rust +/// foo is a function +pub fn foo() {} +``` + +... and then re-run `rustdoc`: + +```bash +$ rustdoc src/lib.rs --crate-name docs +``` + +We'll have some generated documentation. Open up `doc/docs/index.html` and +check it out! It should show a link to the `foo` function's page, which +is located at `doc/docs/fn.foo.html`. On that page, you'll see the "foo is +a function" we put inside the documentation comment in our crate. + +## Using rustdoc with Cargo + +Cargo also has integration with `rustdoc` to make it easier to generate +docs. Instead of the `rustdoc` command, we could have done this: + +```bash +$ cargo doc +``` + +Internally, this calls out to `rustdoc` like this: + +```bash +$ rustdoc --crate-name docs srclib.rs -o \docs\target\doc -L +dependency=docs\target\debug\deps +``` + +You can see this with `cargo doc --verbose`. + +It generates the correct `--crate-name` for us, as well as pointing to +`src/lib.rs` But what about those other arguments? `-o` controls the +*o*utput of our docs. Instead of a top-level `doc` directory, you'll +notice that Cargo puts generated documentation under `target`. That's +the idiomatic place for generated files in Cargo projects. Also, it +passes `-L`, a flag that helps rustdoc find the dependencies +your code relies on. If our project used dependencies, we'd get +documentation for them as well! + +## Using standalone Markdown files + +`rustdoc` can also generate HTML from standalone Markdown files. Let's +give it a try: create a `README.md` file with these contents: + +```text + # Docs + + This is a project to test out `rustdoc`. + + [Here is a link!](https://www.rust-lang.org) + + ## Subheading + + ```rust + fn foo() -> i32 { + 1 + 1 + } + ``` +``` + +And call `rustdoc` on it: + +```bash +$ rustdoc README.md +``` + +You'll find an HTML file in `docs/doc/README.html` generated from its +Markdown contents. + +Cargo currently does not understand standalone Markdown files, unfortunately. + +## Summary + +This covers the simplest use-cases of `rustdoc`. The rest of this book will +explain all of the options that `rustdoc` has, and how to use them. \ No newline at end of file diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md deleted file mode 100644 index f2b54db02e..0000000000 --- a/src/doc/unstable-book/src/SUMMARY.md +++ /dev/null @@ -1,218 +0,0 @@ -[The Unstable Book](the-unstable-book.md) - -- [Compiler flags](compiler-flags.md) - - [linker_flavor](compiler-flags/linker-flavor.md) - - [remap_path_prefix](compiler-flags/remap-path-prefix.md) -- [Language features](language-features.md) - - [abi_msp430_interrupt](language-features/abi-msp430-interrupt.md) - - [abi_ptx](language-features/abi-ptx.md) - - [abi_sysv64](language-features/abi-sysv64.md) - - [abi_thiscall](language-features/abi-thiscall.md) - - [abi_unadjusted](language-features/abi-unadjusted.md) - - [abi_vectorcall](language-features/abi-vectorcall.md) - - [abi_x86_interrupt](language-features/abi-x86-interrupt.md) - - [advanced_slice_patterns](language-features/advanced-slice-patterns.md) - - [allocator](language-features/allocator.md) - - [allow_internal_unstable](language-features/allow-internal-unstable.md) - - [asm](language-features/asm.md) - - [associated_consts](language-features/associated-consts.md) - - [associated_type_defaults](language-features/associated-type-defaults.md) - - [attr_literals](language-features/attr-literals.md) - - [box_patterns](language-features/box-patterns.md) - - [box_syntax](language-features/box-syntax.md) - - [catch_expr](language-features/catch-expr.md) - - [cfg_target_feature](language-features/cfg-target-feature.md) - - [cfg_target_has_atomic](language-features/cfg-target-has-atomic.md) - - [cfg_target_thread_local](language-features/cfg-target-thread-local.md) - - [cfg_target_vendor](language-features/cfg-target-vendor.md) - - [compiler_builtins](language-features/compiler-builtins.md) - - [concat_idents](language-features/concat-idents.md) - - [conservative_impl_trait](language-features/conservative-impl-trait.md) - - [const_fn](language-features/const-fn.md) - - [const_indexing](language-features/const-indexing.md) - - [custom_attribute](language-features/custom-attribute.md) - - [custom_derive](language-features/custom-derive.md) - - [default_type_parameter_fallback](language-features/default-type-parameter-fallback.md) - - [drop_types_in_const](language-features/drop-types-in-const.md) - - [dropck_eyepatch](language-features/dropck-eyepatch.md) - - [dropck_parametricity](language-features/dropck-parametricity.md) - - [exclusive_range_pattern](language-features/exclusive-range-pattern.md) - - [fundamental](language-features/fundamental.md) - - [generic_param_attrs](language-features/generic-param-attrs.md) - - [global_asm](language-features/global_asm.md) - - [i128_type](language-features/i128-type.md) - - [inclusive_range_syntax](language-features/inclusive-range-syntax.md) - - [intrinsics](language-features/intrinsics.md) - - [lang_items](language-features/lang-items.md) - - [link_args](language-features/link-args.md) - - [link_cfg](language-features/link-cfg.md) - - [link_llvm_intrinsics](language-features/link-llvm-intrinsics.md) - - [linkage](language-features/linkage.md) - - [log_syntax](language-features/log-syntax.md) - - [macro_reexport](language-features/macro-reexport.md) - - [macro_vis_matcher](language-features/macro-vis-matcher.md) - - [main](language-features/main.md) - - [naked_functions](language-features/naked-functions.md) - - [needs_allocator](language-features/needs-allocator.md) - - [needs_panic_runtime](language-features/needs-panic-runtime.md) - - [never_type](language-features/never-type.md) - - [no_core](language-features/no-core.md) - - [no_debug](language-features/no-debug.md) - - [non_ascii_idents](language-features/non-ascii-idents.md) - - [omit_gdb_pretty_printer_section](language-features/omit-gdb-pretty-printer-section.md) - - [on_unimplemented](language-features/on-unimplemented.md) - - [optin_builtin_traits](language-features/optin-builtin-traits.md) - - [overlapping_marker_traits](language-features/overlapping-marker-traits.md) - - [panic_runtime](language-features/panic-runtime.md) - - [placement_in_syntax](language-features/placement-in-syntax.md) - - [platform_intrinsics](language-features/platform-intrinsics.md) - - [plugin](language-features/plugin.md) - - [plugin_registrar](language-features/plugin-registrar.md) - - [prelude_import](language-features/prelude-import.md) - - [proc_macro](language-features/proc-macro.md) - - [quote](language-features/quote.md) - - [repr_align](language-features/repr-align.md) - - [repr_simd](language-features/repr-simd.md) - - [rustc_attrs](language-features/rustc-attrs.md) - - [rustc_diagnostic_macros](language-features/rustc-diagnostic-macros.md) - - [rvalue_static_promotion](language-features/rvalue-static-promotion.md) - - [sanitizer_runtime](language-features/sanitizer-runtime.md) - - [simd](language-features/simd.md) - - [simd_ffi](language-features/simd-ffi.md) - - [slice_patterns](language-features/slice-patterns.md) - - [specialization](language-features/specialization.md) - - [staged_api](language-features/staged-api.md) - - [start](language-features/start.md) - - [static_nobundle](language-features/static-nobundle.md) - - [stmt_expr_attributes](language-features/stmt-expr-attributes.md) - - [struct_field_attributes](language-features/struct-field-attributes.md) - - [structural_match](language-features/structural-match.md) - - [target_feature](language-features/target-feature.md) - - [thread_local](language-features/thread-local.md) - - [trace_macros](language-features/trace-macros.md) - - [type_ascription](language-features/type-ascription.md) - - [unboxed_closures](language-features/unboxed-closures.md) - - [untagged_unions](language-features/untagged-unions.md) - - [unwind_attributes](language-features/unwind-attributes.md) - - [use_extern_macros](language-features/use-extern-macros.md) - - [used](language-features/used.md) -- [Library Features](library-features.md) - - [alloc_jemalloc](library-features/alloc-jemalloc.md) - - [alloc_system](library-features/alloc-system.md) - - [alloc](library-features/alloc.md) - - [as_c_str](library-features/as-c-str.md) - - [ascii_ctype](library-features/ascii-ctype.md) - - [box_heap](library-features/box-heap.md) - - [c_void_variant](library-features/c-void-variant.md) - - [char_escape_debug](library-features/char-escape-debug.md) - - [coerce_unsized](library-features/coerce-unsized.md) - - [collection_placement](library-features/collection-placement.md) - - [collections_range](library-features/collections-range.md) - - [collections](library-features/collections.md) - - [compiler_builtins_lib](library-features/compiler-builtins-lib.md) - - [compiler_fences](library-features/compiler-fences.md) - - [concat_idents_macro](library-features/concat-idents-macro.md) - - [core_char_ext](library-features/core-char-ext.md) - - [core_float](library-features/core-float.md) - - [core_intrinsics](library-features/core-intrinsics.md) - - [core_panic](library-features/core-panic.md) - - [core_private_bignum](library-features/core-private-bignum.md) - - [core_private_diy_float](library-features/core-private-diy-float.md) - - [core_slice_ext](library-features/core-slice-ext.md) - - [core_str_ext](library-features/core-str-ext.md) - - [dec2flt](library-features/dec2flt.md) - - [decode_utf8](library-features/decode-utf8.md) - - [derive_clone_copy](library-features/derive-clone-copy.md) - - [derive_eq](library-features/derive-eq.md) - - [discriminant_value](library-features/discriminant-value.md) - - [error_type_id](library-features/error-type-id.md) - - [exact_size_is_empty](library-features/exact-size-is-empty.md) - - [fd](library-features/fd.md) - - [fd_read](library-features/fd-read.md) - - [fixed_size_array](library-features/fixed-size-array.md) - - [float_bits_conv](library-features/float-bits-conv.md) - - [flt2dec](library-features/flt2dec.md) - - [fmt_flags_align](library-features/fmt-flags-align.md) - - [fmt_internals](library-features/fmt-internals.md) - - [fn_traits](library-features/fn-traits.md) - - [fnbox](library-features/fnbox.md) - - [from_utf8_error_as_bytes](library-features/from_utf8_error_as_bytes.md) - - [fused](library-features/fused.md) - - [future_atomic_orderings](library-features/future-atomic-orderings.md) - - [get_type_id](library-features/get-type-id.md) - - [heap_api](library-features/heap-api.md) - - [hint_core_should_pause](library-features/hint-core-should-pause.md) - - [i128](library-features/i128.md) - - [inclusive_range](library-features/inclusive-range.md) - - [integer_atomics](library-features/integer-atomics.md) - - [into_boxed_c_str](library-features/into-boxed-c-str.md) - - [into_boxed_os_str](library-features/into-boxed-os-str.md) - - [into_boxed_path](library-features/into-boxed-path.md) - - [io_error_internals](library-features/io-error-internals.md) - - [io](library-features/io.md) - - [ip](library-features/ip.md) - - [iter_rfind](library-features/iter-rfind.md) - - [iterator_step_by](library-features/iterator-step-by.md) - - [libstd_io_internals](library-features/libstd-io-internals.md) - - [libstd_sys_internals](library-features/libstd-sys-internals.md) - - [libstd_thread_internals](library-features/libstd-thread-internals.md) - - [linked_list_extras](library-features/linked-list-extras.md) - - [lookup_host](library-features/lookup-host.md) - - [manually_drop](library-features/manually-drop.md) - - [more_io_inner_methods](library-features/more-io-inner-methods.md) - - [mpsc_select](library-features/mpsc-select.md) - - [n16](library-features/n16.md) - - [never_type_impls](library-features/never-type-impls.md) - - [nonzero](library-features/nonzero.md) - - [offset_to](library-features/offset-to.md) - - [once_poison](library-features/once-poison.md) - - [oom](library-features/oom.md) - - [option_entry](library-features/option-entry.md) - - [panic_abort](library-features/panic-abort.md) - - [panic_unwind](library-features/panic-unwind.md) - - [pattern](library-features/pattern.md) - - [placement_in](library-features/placement-in.md) - - [placement_new_protocol](library-features/placement-new-protocol.md) - - [print_internals](library-features/print-internals.md) - - [proc_macro_internals](library-features/proc-macro-internals.md) - - [question_mark_carrier](library-features/question-mark-carrier.md) - - [rand](library-features/rand.md) - - [range_contains](library-features/range-contains.md) - - [raw](library-features/raw.md) - - [rt](library-features/rt.md) - - [rustc_private](library-features/rustc-private.md) - - [sanitizer_runtime_lib](library-features/sanitizer-runtime-lib.md) - - [set_stdio](library-features/set-stdio.md) - - [shared](library-features/shared.md) - - [sip_hash_13](library-features/sip-hash-13.md) - - [slice_concat_ext](library-features/slice-concat-ext.md) - - [slice_get_slice](library-features/slice-get-slice.md) - - [slice_rotate](library-features/slice-rotate.md) - - [slice_rsplit](library-features/slice-rsplit.md) - - [sort_internals](library-features/sort-internals.md) - - [sort_unstable](library-features/sort-unstable.md) - - [splice](library-features/splice.md) - - [step_by](library-features/step-by.md) - - [step_trait](library-features/step-trait.md) - - [str_checked_slicing](library-features/str-checked-slicing.md) - - [str_escape](library-features/str-escape.md) - - [str_internals](library-features/str-internals.md) - - [str_box_extras](library-features/str-box-extras.md) - - [str_mut_extras](library-features/str-mut-extras.md) - - [test](library-features/test.md) - - [thread_local_internals](library-features/thread-local-internals.md) - - [thread_local_state](library-features/thread-local-state.md) - - [toowned_clone_into](library-features/toowned-clone-into.md) - - [trusted_len](library-features/trusted-len.md) - - [try_from](library-features/try-from.md) - - [try_trait](library-features/try-trait.md) - - [unicode](library-features/unicode.md) - - [unique](library-features/unique.md) - - [unsize](library-features/unsize.md) - - [utf8_error_error_len](library-features/utf8-error-error-len.md) - - [vec_resize_default](library-features/vec-resize-default.md) - - [vec_remove_item](library-features/vec-remove-item.md) - - [windows_c](library-features/windows-c.md) - - [windows_handle](library-features/windows-handle.md) - - [windows_net](library-features/windows-net.md) - - [windows_stdio](library-features/windows-stdio.md) diff --git a/src/doc/unstable-book/src/compiler-flags/profile.md b/src/doc/unstable-book/src/compiler-flags/profile.md new file mode 100644 index 0000000000..66d14fd099 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/profile.md @@ -0,0 +1,21 @@ +# `profile` + +The tracking issue for this feature is: [#42524](https://github.com/rust-lang/rust/issues/42524). + +------------------------ + +This feature allows the generation of code coverage reports. + +Set the `-Zprofile` compiler flag in order to enable gcov profiling. + +For example: +```Bash +cargo new testgcov --bin +cd testgcov +export RUSTFLAGS="-Zprofile" +cargo build +cargo run +``` + +Once you've built and run your program, files with the `gcno` (after build) and `gcda` (after execution) extensions will be created. +You can parse them with [llvm-cov gcov](http://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-gcov) or [grcov](https://github.com/marco-c/grcov). diff --git a/src/doc/unstable-book/src/language-features/abi-sysv64.md b/src/doc/unstable-book/src/language-features/abi-sysv64.md deleted file mode 100644 index 27f61d5634..0000000000 --- a/src/doc/unstable-book/src/language-features/abi-sysv64.md +++ /dev/null @@ -1,7 +0,0 @@ -# `abi_sysv64` - -The tracking issue for this feature is: [#36167] - -[#36167]: https://github.com/rust-lang/rust/issues/36167 - ------------------------- diff --git a/src/doc/unstable-book/src/language-features/abi-unadjusted.md b/src/doc/unstable-book/src/language-features/abi-unadjusted.md deleted file mode 100644 index 2e3113abdb..0000000000 --- a/src/doc/unstable-book/src/language-features/abi-unadjusted.md +++ /dev/null @@ -1,6 +0,0 @@ -# `abi_unadjusted` - -The tracking issue for this feature is: none. - ------------------------- - diff --git a/src/doc/unstable-book/src/language-features/abi-vectorcall.md b/src/doc/unstable-book/src/language-features/abi-vectorcall.md deleted file mode 100644 index 3e36b1569f..0000000000 --- a/src/doc/unstable-book/src/language-features/abi-vectorcall.md +++ /dev/null @@ -1,7 +0,0 @@ -# `abi_vectorcall` - -The tracking issue for this feature is: none. - ------------------------- - - diff --git a/src/doc/unstable-book/src/language-features/abi-x86-interrupt.md b/src/doc/unstable-book/src/language-features/abi-x86-interrupt.md deleted file mode 100644 index c89d2ee210..0000000000 --- a/src/doc/unstable-book/src/language-features/abi-x86-interrupt.md +++ /dev/null @@ -1,7 +0,0 @@ -# `abi_x86_interrupt` - -The tracking issue for this feature is: [#40180] - -[#40180]: https://github.com/rust-lang/rust/issues/40180 - ------------------------- diff --git a/src/doc/unstable-book/src/language-features/allocator-internals.md b/src/doc/unstable-book/src/language-features/allocator-internals.md new file mode 100644 index 0000000000..2023d758fe --- /dev/null +++ b/src/doc/unstable-book/src/language-features/allocator-internals.md @@ -0,0 +1,7 @@ +# `allocator_internals` + +This feature does not have a tracking issue, it is an unstable implementation +detail of the `global_allocator` feature not intended for use outside the +compiler. + +------------------------ diff --git a/src/doc/unstable-book/src/language-features/allocator.md b/src/doc/unstable-book/src/language-features/allocator.md deleted file mode 100644 index cfcf8e22d7..0000000000 --- a/src/doc/unstable-book/src/language-features/allocator.md +++ /dev/null @@ -1,119 +0,0 @@ -# `allocator` - -The tracking issue for this feature is: [#27389] - -[#27389]: https://github.com/rust-lang/rust/issues/27389 - ------------------------- - -Sometimes even the choices of jemalloc vs the system allocator aren't enough and -an entirely new custom allocator is required. In this you'll write your own -crate which implements the allocator API (e.g. the same as `alloc_system` or -`alloc_jemalloc`). As an example, let's take a look at a simplified and -annotated version of `alloc_system` - -```rust,no_run -# // Only needed for rustdoc --test down below. -# #![feature(lang_items)] -// The compiler needs to be instructed that this crate is an allocator in order -// to realize that when this is linked in another allocator like jemalloc should -// not be linked in. -#![feature(allocator)] -#![allocator] - -// Allocators are not allowed to depend on the standard library which in turn -// requires an allocator in order to avoid circular dependencies. This crate, -// however, can use all of libcore. -#![no_std] - -// Let's give a unique name to our custom allocator: -#![crate_name = "my_allocator"] -#![crate_type = "rlib"] - -// Our system allocator will use the in-tree libc crate for FFI bindings. Note -// that currently the external (crates.io) libc cannot be used because it links -// to the standard library (e.g. `#![no_std]` isn't stable yet), so that's why -// this specifically requires the in-tree version. -#![feature(libc)] -extern crate libc; - -// Listed below are the five allocation functions currently required by custom -// allocators. Their signatures and symbol names are not currently typechecked -// by the compiler, but this is a future extension and are required to match -// what is found below. -// -// Note that the standard `malloc` and `realloc` functions do not provide a way -// to communicate alignment so this implementation would need to be improved -// with respect to alignment in that aspect. - -#[no_mangle] -pub extern fn __rust_allocate(size: usize, _align: usize) -> *mut u8 { - unsafe { libc::malloc(size as libc::size_t) as *mut u8 } -} - -#[no_mangle] -pub extern fn __rust_allocate_zeroed(size: usize, _align: usize) -> *mut u8 { - unsafe { libc::calloc(size as libc::size_t, 1) as *mut u8 } -} - -#[no_mangle] -pub extern fn __rust_deallocate(ptr: *mut u8, _old_size: usize, _align: usize) { - unsafe { libc::free(ptr as *mut libc::c_void) } -} - -#[no_mangle] -pub extern fn __rust_reallocate(ptr: *mut u8, _old_size: usize, size: usize, - _align: usize) -> *mut u8 { - unsafe { - libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8 - } -} - -#[no_mangle] -pub extern fn __rust_reallocate_inplace(_ptr: *mut u8, old_size: usize, - _size: usize, _align: usize) -> usize { - old_size // This api is not supported by libc. -} - -#[no_mangle] -pub extern fn __rust_usable_size(size: usize, _align: usize) -> usize { - size -} - -# // Only needed to get rustdoc to test this: -# fn main() {} -# #[lang = "panic_fmt"] fn panic_fmt() {} -# #[lang = "eh_personality"] fn eh_personality() {} -# #[lang = "eh_unwind_resume"] extern fn eh_unwind_resume() {} -# #[no_mangle] pub extern fn rust_eh_register_frames () {} -# #[no_mangle] pub extern fn rust_eh_unregister_frames () {} -``` - -After we compile this crate, it can be used as follows: - -```rust,ignore -extern crate my_allocator; - -fn main() { - let a = Box::new(8); // Allocates memory via our custom allocator crate. - println!("{}", a); -} -``` - -## Custom allocator limitations - -There are a few restrictions when working with custom allocators which may cause -compiler errors: - -* Any one artifact may only be linked to at most one allocator. Binaries, - dylibs, and staticlibs must link to exactly one allocator, and if none have - been explicitly chosen the compiler will choose one. On the other hand rlibs - do not need to link to an allocator (but still can). - -* A consumer of an allocator is tagged with `#![needs_allocator]` (e.g. the - `liballoc` crate currently) and an `#[allocator]` crate cannot transitively - depend on a crate which needs an allocator (e.g. circular dependencies are not - allowed). This basically means that allocators must restrict themselves to - libcore currently. - - diff --git a/src/doc/unstable-book/src/language-features/allow-internal-unstable.md b/src/doc/unstable-book/src/language-features/allow-internal-unstable.md deleted file mode 100644 index 74709ad5ae..0000000000 --- a/src/doc/unstable-book/src/language-features/allow-internal-unstable.md +++ /dev/null @@ -1,6 +0,0 @@ -# `allow_internal_unstable` - -The tracking issue for this feature is: None. - ------------------------- - diff --git a/src/doc/unstable-book/src/language-features/asm.md b/src/doc/unstable-book/src/language-features/asm.md index 8deb8f4625..f22095fe5d 100644 --- a/src/doc/unstable-book/src/language-features/asm.md +++ b/src/doc/unstable-book/src/language-features/asm.md @@ -190,4 +190,4 @@ constraints, etc. [llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions If you need more power and don't mind losing some of the niceties of -`asm!`, check out [global_asm](language-features/global_asm.html). +`asm!`, check out [global_asm](language-features/global-asm.html). diff --git a/src/doc/unstable-book/src/language-features/associated-consts.md b/src/doc/unstable-book/src/language-features/associated-consts.md deleted file mode 100644 index d661108e7d..0000000000 --- a/src/doc/unstable-book/src/language-features/associated-consts.md +++ /dev/null @@ -1,85 +0,0 @@ -# `associated_consts` - -The tracking issue for this feature is: [#29646] - -[#29646]: https://github.com/rust-lang/rust/issues/29646 - ------------------------- - -With the `associated_consts` feature, you can define constants like this: - -```rust -#![feature(associated_consts)] - -trait Foo { - const ID: i32; -} - -impl Foo for i32 { - const ID: i32 = 1; -} - -fn main() { - assert_eq!(1, i32::ID); -} -``` - -Any implementor of `Foo` will have to define `ID`. Without the definition: - -```rust,ignore -#![feature(associated_consts)] - -trait Foo { - const ID: i32; -} - -impl Foo for i32 { -} -``` - -gives - -```text -error: not all trait items implemented, missing: `ID` [E0046] - impl Foo for i32 { - } -``` - -A default value can be implemented as well: - -```rust -#![feature(associated_consts)] - -trait Foo { - const ID: i32 = 1; -} - -impl Foo for i32 { -} - -impl Foo for i64 { - const ID: i32 = 5; -} - -fn main() { - assert_eq!(1, i32::ID); - assert_eq!(5, i64::ID); -} -``` - -As you can see, when implementing `Foo`, you can leave it unimplemented, as -with `i32`. It will then use the default value. But, as in `i64`, we can also -add our own definition. - -Associated constants don’t have to be associated with a trait. An `impl` block -for a `struct` or an `enum` works fine too: - -```rust -#![feature(associated_consts)] - -struct Foo; - -impl Foo { - const FOO: u32 = 3; -} -``` diff --git a/src/doc/unstable-book/src/language-features/associated-type-defaults.md b/src/doc/unstable-book/src/language-features/associated-type-defaults.md deleted file mode 100644 index 56cc8a5b30..0000000000 --- a/src/doc/unstable-book/src/language-features/associated-type-defaults.md +++ /dev/null @@ -1,10 +0,0 @@ -# `associated_type_defaults` - -The tracking issue for this feature is: [#29661] - -[#29661]: https://github.com/rust-lang/rust/issues/29661 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/cfg-target-feature.md b/src/doc/unstable-book/src/language-features/cfg-target-feature.md deleted file mode 100644 index ddd88bdc2c..0000000000 --- a/src/doc/unstable-book/src/language-features/cfg-target-feature.md +++ /dev/null @@ -1,10 +0,0 @@ -# `cfg_target_feature` - -The tracking issue for this feature is: [#29717] - -[#29717]: https://github.com/rust-lang/rust/issues/29717 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/cfg-target-has-atomic.md b/src/doc/unstable-book/src/language-features/cfg-target-has-atomic.md deleted file mode 100644 index 7496e42e1c..0000000000 --- a/src/doc/unstable-book/src/language-features/cfg-target-has-atomic.md +++ /dev/null @@ -1,10 +0,0 @@ -# `cfg_target_has_atomic` - -The tracking issue for this feature is: [#32976] - -[#32976]: https://github.com/rust-lang/rust/issues/32976 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/cfg-target-thread-local.md b/src/doc/unstable-book/src/language-features/cfg-target-thread-local.md deleted file mode 100644 index a5adb38db3..0000000000 --- a/src/doc/unstable-book/src/language-features/cfg-target-thread-local.md +++ /dev/null @@ -1,10 +0,0 @@ -# `cfg_target_thread_local` - -The tracking issue for this feature is: [#29594] - -[#29594]: https://github.com/rust-lang/rust/issues/29594 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/cfg-target-vendor.md b/src/doc/unstable-book/src/language-features/cfg-target-vendor.md deleted file mode 100644 index ddd88bdc2c..0000000000 --- a/src/doc/unstable-book/src/language-features/cfg-target-vendor.md +++ /dev/null @@ -1,10 +0,0 @@ -# `cfg_target_feature` - -The tracking issue for this feature is: [#29717] - -[#29717]: https://github.com/rust-lang/rust/issues/29717 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/custom-attribute.md b/src/doc/unstable-book/src/language-features/custom-attribute.md deleted file mode 100644 index 838f09670d..0000000000 --- a/src/doc/unstable-book/src/language-features/custom-attribute.md +++ /dev/null @@ -1,10 +0,0 @@ -# `custom_attribute` - -The tracking issue for this feature is: [#29642] - -[#29642]: https://github.com/rust-lang/rust/issues/29642 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/custom-derive.md b/src/doc/unstable-book/src/language-features/custom-derive.md deleted file mode 100644 index d5fdd2b708..0000000000 --- a/src/doc/unstable-book/src/language-features/custom-derive.md +++ /dev/null @@ -1,10 +0,0 @@ -# `custom_derive` - -The tracking issue for this feature is: [#29644] - -[#29644]: https://github.com/rust-lang/rust/issues/29644 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/decl-macro.md b/src/doc/unstable-book/src/language-features/decl-macro.md deleted file mode 100644 index 4700b252e2..0000000000 --- a/src/doc/unstable-book/src/language-features/decl-macro.md +++ /dev/null @@ -1,10 +0,0 @@ -# `decl_macro` - -The tracking issue for this feature is: [#39412] - -[#39412]: https://github.com/rust-lang/rust/issues/39412 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/default-type-parameter-fallback.md b/src/doc/unstable-book/src/language-features/default-type-parameter-fallback.md deleted file mode 100644 index fd16dbf898..0000000000 --- a/src/doc/unstable-book/src/language-features/default-type-parameter-fallback.md +++ /dev/null @@ -1,10 +0,0 @@ -# `default_type_parameter_fallback` - -The tracking issue for this feature is: [#27336] - -[#27336]: https://github.com/rust-lang/rust/issues/27336 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/drop-types-in-const.md b/src/doc/unstable-book/src/language-features/drop-types-in-const.md deleted file mode 100644 index b3367d0df4..0000000000 --- a/src/doc/unstable-book/src/language-features/drop-types-in-const.md +++ /dev/null @@ -1,10 +0,0 @@ -# `drop_types_in_const` - -The tracking issue for this feature is: [#33156] - -[#33156]: https://github.com/rust-lang/rust/issues/33156 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/dropck-eyepatch.md b/src/doc/unstable-book/src/language-features/dropck-eyepatch.md deleted file mode 100644 index 2f189e9b64..0000000000 --- a/src/doc/unstable-book/src/language-features/dropck-eyepatch.md +++ /dev/null @@ -1,10 +0,0 @@ -# `dropck_eyepatch` - -The tracking issue for this feature is: [#34761] - -[#34761]: https://github.com/rust-lang/rust/issues/34761 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/dropck-parametricity.md b/src/doc/unstable-book/src/language-features/dropck-parametricity.md deleted file mode 100644 index c5ae721954..0000000000 --- a/src/doc/unstable-book/src/language-features/dropck-parametricity.md +++ /dev/null @@ -1,10 +0,0 @@ -# `dropck_parametricity` - -The tracking issue for this feature is: [#28498] - -[#28498]: https://github.com/rust-lang/rust/issues/28498 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md b/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md deleted file mode 100644 index b669ce8313..0000000000 --- a/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md +++ /dev/null @@ -1,10 +0,0 @@ -# `exclusive_range_pattern` - -The tracking issue for this feature is: [#37854] - -[#37854]: https://github.com/rust-lang/rust/issues/37854 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/fundamental.md b/src/doc/unstable-book/src/language-features/fundamental.md deleted file mode 100644 index a068dadf95..0000000000 --- a/src/doc/unstable-book/src/language-features/fundamental.md +++ /dev/null @@ -1,10 +0,0 @@ -# `fundamental` - -The tracking issue for this feature is: [#29635] - -[#29635]: https://github.com/rust-lang/rust/issues/29635 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/generic-param-attrs.md b/src/doc/unstable-book/src/language-features/generic-param-attrs.md deleted file mode 100644 index ba49c850e4..0000000000 --- a/src/doc/unstable-book/src/language-features/generic-param-attrs.md +++ /dev/null @@ -1,10 +0,0 @@ -# `generic_param_attrs` - -The tracking issue for this feature is: [#34761] - -[#34761]: https://github.com/rust-lang/rust/issues/34761 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/global-allocator.md b/src/doc/unstable-book/src/language-features/global-allocator.md new file mode 100644 index 0000000000..b3e6925b66 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/global-allocator.md @@ -0,0 +1,71 @@ +# `global_allocator` + +The tracking issue for this feature is: [#27389] + +[#27389]: https://github.com/rust-lang/rust/issues/27389 + +------------------------ + +Rust programs may need to change the allocator that they're running with from +time to time. This use case is distinct from an allocator-per-collection (e.g. a +`Vec` with a custom allocator) and instead is more related to changing the +global default allocator, e.g. what `Vec` uses by default. + +Currently Rust programs don't have a specified global allocator. The compiler +may link to a version of [jemalloc] on some platforms, but this is not +guaranteed. Libraries, however, like cdylibs and staticlibs are guaranteed +to use the "system allocator" which means something like `malloc` on Unixes and +`HeapAlloc` on Windows. + +[jemalloc]: https://github.com/jemalloc/jemalloc + +The `#[global_allocator]` attribute, however, allows configuring this choice. +You can use this to implement a completely custom global allocator to route all +default allocation requests to a custom object. Defined in [RFC 1974] usage +looks like: + +[RFC 1974]: https://github.com/rust-lang/rfcs/pull/1974 + +```rust +#![feature(global_allocator, allocator_api, heap_api)] + +use std::heap::{Alloc, System, Layout, AllocErr}; + +struct MyAllocator; + +unsafe impl<'a> Alloc for &'a MyAllocator { + unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { + System.alloc(layout) + } + + unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) { + System.dealloc(ptr, layout) + } +} + +#[global_allocator] +static GLOBAL: MyAllocator = MyAllocator; + +fn main() { + // This `Vec` will allocate memory through `GLOBAL` above + let mut v = Vec::new(); + v.push(1); +} +``` + +And that's it! The `#[global_allocator]` attribute is applied to a `static` +which implements the `Alloc` trait in the `std::heap` module. Note, though, +that the implementation is defined for `&MyAllocator`, not just `MyAllocator`. +You may wish, however, to also provide `Alloc for MyAllocator` for other use +cases. + +A crate can only have one instance of `#[global_allocator]` and this instance +may be loaded through a dependency. For example `#[global_allocator]` above +could have been placed in one of the dependencies loaded through `extern crate`. + +Note that `Alloc` itself is an `unsafe` trait, with much documentation on the +trait itself about usage and for implementors. Extra care should be taken when +implementing a global allocator as well as the allocator may be called from many +portions of the standard library, such as the panicking routine. As a result it +is highly recommended to not panic during allocation and work in as many +situations with as few dependencies as possible as well. diff --git a/src/doc/unstable-book/src/language-features/global_asm.md b/src/doc/unstable-book/src/language-features/global-asm.md similarity index 100% rename from src/doc/unstable-book/src/language-features/global_asm.md rename to src/doc/unstable-book/src/language-features/global-asm.md diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md index 375b8bd6b8..a2368ee5f4 100644 --- a/src/doc/unstable-book/src/language-features/lang-items.md +++ b/src/doc/unstable-book/src/language-features/lang-items.md @@ -143,7 +143,8 @@ pub extern fn rust_eh_unwind_resume() { #[no_mangle] pub extern fn rust_begin_panic(_msg: core::fmt::Arguments, _file: &'static str, - _line: u32) -> ! { + _line: u32, + _column: u32) -> ! { unsafe { intrinsics::abort() } } ``` @@ -187,7 +188,8 @@ pub extern fn rust_eh_unwind_resume() { #[no_mangle] pub extern fn rust_begin_panic(_msg: core::fmt::Arguments, _file: &'static str, - _line: u32) -> ! { + _line: u32, + _column: u32) -> ! { unsafe { intrinsics::abort() } } ``` diff --git a/src/doc/unstable-book/src/language-features/link-cfg.md b/src/doc/unstable-book/src/language-features/link-cfg.md deleted file mode 100644 index 7393d0628e..0000000000 --- a/src/doc/unstable-book/src/language-features/link-cfg.md +++ /dev/null @@ -1,10 +0,0 @@ -# `link_cfg` - -The tracking issue for this feature is: [#37406] - -[#37406]: https://github.com/rust-lang/rust/issues/37406 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/link-llvm-intrinsics.md b/src/doc/unstable-book/src/language-features/link-llvm-intrinsics.md deleted file mode 100644 index ba639cb57f..0000000000 --- a/src/doc/unstable-book/src/language-features/link-llvm-intrinsics.md +++ /dev/null @@ -1,10 +0,0 @@ -# `link_llvm_intrinsics` - -The tracking issue for this feature is: [#29602] - -[#29602]: https://github.com/rust-lang/rust/issues/29602 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/linkage.md b/src/doc/unstable-book/src/language-features/linkage.md deleted file mode 100644 index 5773d28a00..0000000000 --- a/src/doc/unstable-book/src/language-features/linkage.md +++ /dev/null @@ -1,10 +0,0 @@ -# `linkage` - -The tracking issue for this feature is: [#29603] - -[#29603]: https://github.com/rust-lang/rust/issues/29603 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/log-syntax.md b/src/doc/unstable-book/src/language-features/log-syntax.md deleted file mode 100644 index b13f5ccfd9..0000000000 --- a/src/doc/unstable-book/src/language-features/log-syntax.md +++ /dev/null @@ -1,10 +0,0 @@ -# `log_syntax` - -The tracking issue for this feature is: [#29598] - -[#29598]: https://github.com/rust-lang/rust/issues/29598 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/macro-reexport.md b/src/doc/unstable-book/src/language-features/macro-reexport.md deleted file mode 100644 index 32ffa3b4c3..0000000000 --- a/src/doc/unstable-book/src/language-features/macro-reexport.md +++ /dev/null @@ -1,10 +0,0 @@ -# `macro_reexport` - -The tracking issue for this feature is: [#29638] - -[#29638]: https://github.com/rust-lang/rust/issues/29638 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/main.md b/src/doc/unstable-book/src/language-features/main.md deleted file mode 100644 index 579aabfff8..0000000000 --- a/src/doc/unstable-book/src/language-features/main.md +++ /dev/null @@ -1,10 +0,0 @@ -# `main` - -The tracking issue for this feature is: [#29634] - -[#29634]: https://github.com/rust-lang/rust/issues/29634 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/naked-functions.md b/src/doc/unstable-book/src/language-features/naked-functions.md deleted file mode 100644 index e56ce4770a..0000000000 --- a/src/doc/unstable-book/src/language-features/naked-functions.md +++ /dev/null @@ -1,10 +0,0 @@ -# `naked_functions` - -The tracking issue for this feature is: [#32408] - -[#32408]: https://github.com/rust-lang/rust/issues/32408 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/needs-allocator.md b/src/doc/unstable-book/src/language-features/needs-allocator.md deleted file mode 100644 index 22aa10b218..0000000000 --- a/src/doc/unstable-book/src/language-features/needs-allocator.md +++ /dev/null @@ -1,10 +0,0 @@ -# `needs_allocator` - -The tracking issue for this feature is: [#27389] - -[#27389]: https://github.com/rust-lang/rust/issues/27389 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/needs-panic-runtime.md b/src/doc/unstable-book/src/language-features/needs-panic-runtime.md deleted file mode 100644 index 627c946c1b..0000000000 --- a/src/doc/unstable-book/src/language-features/needs-panic-runtime.md +++ /dev/null @@ -1,10 +0,0 @@ -# `needs_panic_runtime` - -The tracking issue for this feature is: [#32837] - -[#32837]: https://github.com/rust-lang/rust/issues/32837 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/never-type.md b/src/doc/unstable-book/src/language-features/never-type.md deleted file mode 100644 index 3b3729a4b2..0000000000 --- a/src/doc/unstable-book/src/language-features/never-type.md +++ /dev/null @@ -1,10 +0,0 @@ -# `never_type` - -The tracking issue for this feature is: [#35121] - -[#35121]: https://github.com/rust-lang/rust/issues/35121 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/no-core.md b/src/doc/unstable-book/src/language-features/no-core.md deleted file mode 100644 index 6238753447..0000000000 --- a/src/doc/unstable-book/src/language-features/no-core.md +++ /dev/null @@ -1,10 +0,0 @@ -# `no_core` - -The tracking issue for this feature is: [#29639] - -[#29639]: https://github.com/rust-lang/rust/issues/29639 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/no-debug.md b/src/doc/unstable-book/src/language-features/no-debug.md deleted file mode 100644 index 7536ed9d4e..0000000000 --- a/src/doc/unstable-book/src/language-features/no-debug.md +++ /dev/null @@ -1,10 +0,0 @@ -# `no_debug` - -The tracking issue for this feature is: [#29721] - -[#29721]: https://github.com/rust-lang/rust/issues/29721 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/omit-gdb-pretty-printer-section.md b/src/doc/unstable-book/src/language-features/omit-gdb-pretty-printer-section.md deleted file mode 100644 index d8ac520fcb..0000000000 --- a/src/doc/unstable-book/src/language-features/omit-gdb-pretty-printer-section.md +++ /dev/null @@ -1,6 +0,0 @@ -# `omit_gdb_pretty_printer_section` - -The tracking issue for this feature is: None. - ------------------------- - diff --git a/src/doc/unstable-book/src/language-features/optin-builtin-traits.md b/src/doc/unstable-book/src/language-features/optin-builtin-traits.md deleted file mode 100644 index 0b2d60accd..0000000000 --- a/src/doc/unstable-book/src/language-features/optin-builtin-traits.md +++ /dev/null @@ -1,9 +0,0 @@ -# `optin_builtin_traits` - -The tracking issue for this feature is: [#13231] - -[#13231]: https://github.com/rust-lang/rust/issues/13231 - ------------------------- - - diff --git a/src/doc/unstable-book/src/language-features/overlapping-marker-traits.md b/src/doc/unstable-book/src/language-features/overlapping-marker-traits.md deleted file mode 100644 index a4920839c6..0000000000 --- a/src/doc/unstable-book/src/language-features/overlapping-marker-traits.md +++ /dev/null @@ -1,7 +0,0 @@ -# `overlapping_marker_traits` - -The tracking issue for this feature is: [#29864] - -[#29864]: https://github.com/rust-lang/rust/issues/29864 - ------------------------- diff --git a/src/doc/unstable-book/src/language-features/panic-runtime.md b/src/doc/unstable-book/src/language-features/panic-runtime.md deleted file mode 100644 index 65b067e829..0000000000 --- a/src/doc/unstable-book/src/language-features/panic-runtime.md +++ /dev/null @@ -1,10 +0,0 @@ -# `panic_runtime` - -The tracking issue for this feature is: [#32837] - -[#32837]: https://github.com/rust-lang/rust/issues/32837 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/placement-in-syntax.md b/src/doc/unstable-book/src/language-features/placement-in-syntax.md deleted file mode 100644 index da12559a01..0000000000 --- a/src/doc/unstable-book/src/language-features/placement-in-syntax.md +++ /dev/null @@ -1,10 +0,0 @@ -# `placement_in_syntax` - -The tracking issue for this feature is: [#27779] - -[#27779]: https://github.com/rust-lang/rust/issues/27779 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/platform-intrinsics.md b/src/doc/unstable-book/src/language-features/platform-intrinsics.md deleted file mode 100644 index 377ac8f734..0000000000 --- a/src/doc/unstable-book/src/language-features/platform-intrinsics.md +++ /dev/null @@ -1,10 +0,0 @@ -# `platform_intrinsics` - -The tracking issue for this feature is: [#27731] - -[#27731]: https://github.com/rust-lang/rust/issues/27731 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/prelude-import.md b/src/doc/unstable-book/src/language-features/prelude-import.md deleted file mode 100644 index 75dae5cfb7..0000000000 --- a/src/doc/unstable-book/src/language-features/prelude-import.md +++ /dev/null @@ -1,6 +0,0 @@ -# `prelude_import` - -The tracking issue for this feature is: None. - ------------------------- - diff --git a/src/doc/unstable-book/src/language-features/profiler-runtime.md b/src/doc/unstable-book/src/language-features/profiler-runtime.md new file mode 100644 index 0000000000..aee86f6395 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/profiler-runtime.md @@ -0,0 +1,5 @@ +# `profiler_runtime` + +The tracking issue for this feature is: [#42524](https://github.com/rust-lang/rust/issues/42524). + +------------------------ diff --git a/src/doc/unstable-book/src/language-features/quote.md b/src/doc/unstable-book/src/language-features/quote.md deleted file mode 100644 index b4e078d920..0000000000 --- a/src/doc/unstable-book/src/language-features/quote.md +++ /dev/null @@ -1,10 +0,0 @@ -# `quote` - -The tracking issue for this feature is: [#29601] - -[#29601]: https://github.com/rust-lang/rust/issues/29601 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/repr-align.md b/src/doc/unstable-book/src/language-features/repr-align.md deleted file mode 100644 index deea04f4c5..0000000000 --- a/src/doc/unstable-book/src/language-features/repr-align.md +++ /dev/null @@ -1,11 +0,0 @@ -# `repr_align` - -The tracking issue for this feature is: [#33626] - -[#33626]: https://github.com/rust-lang/rust/issues/33626 - ------------------------- - - - - diff --git a/src/doc/unstable-book/src/language-features/repr-simd.md b/src/doc/unstable-book/src/language-features/repr-simd.md deleted file mode 100644 index c6f051e4ff..0000000000 --- a/src/doc/unstable-book/src/language-features/repr-simd.md +++ /dev/null @@ -1,10 +0,0 @@ -# `repr_simd` - -The tracking issue for this feature is: [#27731] - -[#27731]: https://github.com/rust-lang/rust/issues/27731 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/rustc-attrs.md b/src/doc/unstable-book/src/language-features/rustc-attrs.md deleted file mode 100644 index d1f18cead0..0000000000 --- a/src/doc/unstable-book/src/language-features/rustc-attrs.md +++ /dev/null @@ -1,10 +0,0 @@ -# `rustc_attrs` - -The tracking issue for this feature is: [#29642] - -[#29642]: https://github.com/rust-lang/rust/issues/29642 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/rustc-diagnostic-macros.md b/src/doc/unstable-book/src/language-features/rustc-diagnostic-macros.md deleted file mode 100644 index 0df6ca1208..0000000000 --- a/src/doc/unstable-book/src/language-features/rustc-diagnostic-macros.md +++ /dev/null @@ -1,6 +0,0 @@ -# `rustc_diagnostic_macros` - -The tracking issue for this feature is: None. - ------------------------- - diff --git a/src/doc/unstable-book/src/language-features/sanitizer-runtime.md b/src/doc/unstable-book/src/language-features/sanitizer-runtime.md deleted file mode 100644 index f19504de58..0000000000 --- a/src/doc/unstable-book/src/language-features/sanitizer-runtime.md +++ /dev/null @@ -1,6 +0,0 @@ -# `sanitizer_runtime` - -The tracking issue for this feature is: None. - ------------------------- - diff --git a/src/doc/unstable-book/src/language-features/simd-ffi.md b/src/doc/unstable-book/src/language-features/simd-ffi.md deleted file mode 100644 index d85779c3d3..0000000000 --- a/src/doc/unstable-book/src/language-features/simd-ffi.md +++ /dev/null @@ -1,10 +0,0 @@ -# `simd_ffi` - -The tracking issue for this feature is: [#27731] - -[#27731]: https://github.com/rust-lang/rust/issues/27731 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/simd.md b/src/doc/unstable-book/src/language-features/simd.md deleted file mode 100644 index 13c9722c52..0000000000 --- a/src/doc/unstable-book/src/language-features/simd.md +++ /dev/null @@ -1,10 +0,0 @@ -# `simd` - -The tracking issue for this feature is: [#27731] - -[#27731]: https://github.com/rust-lang/rust/issues/27731 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/specialization.md b/src/doc/unstable-book/src/language-features/specialization.md deleted file mode 100644 index efc380df6e..0000000000 --- a/src/doc/unstable-book/src/language-features/specialization.md +++ /dev/null @@ -1,10 +0,0 @@ -# `specialization` - -The tracking issue for this feature is: [#31844] - -[#31844]: https://github.com/rust-lang/rust/issues/31844 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/staged-api.md b/src/doc/unstable-book/src/language-features/staged-api.md deleted file mode 100644 index 1409e570e8..0000000000 --- a/src/doc/unstable-book/src/language-features/staged-api.md +++ /dev/null @@ -1,6 +0,0 @@ -# `staged_api` - -The tracking issue for this feature is: None. - ------------------------- - diff --git a/src/doc/unstable-book/src/language-features/start.md b/src/doc/unstable-book/src/language-features/start.md deleted file mode 100644 index 1ea6d59c78..0000000000 --- a/src/doc/unstable-book/src/language-features/start.md +++ /dev/null @@ -1,10 +0,0 @@ -# `start` - -The tracking issue for this feature is: [#29633] - -[#29633]: https://github.com/rust-lang/rust/issues/29633 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/static-nobundle.md b/src/doc/unstable-book/src/language-features/static-nobundle.md deleted file mode 100644 index 97b9d71d43..0000000000 --- a/src/doc/unstable-book/src/language-features/static-nobundle.md +++ /dev/null @@ -1,10 +0,0 @@ -# `static_nobundle` - -The tracking issue for this feature is: [#37403] - -[#37403]: https://github.com/rust-lang/rust/issues/37403 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/stmt-expr-attributes.md b/src/doc/unstable-book/src/language-features/stmt-expr-attributes.md deleted file mode 100644 index 71092fcf29..0000000000 --- a/src/doc/unstable-book/src/language-features/stmt-expr-attributes.md +++ /dev/null @@ -1,10 +0,0 @@ -# `stmt_expr_attributes` - -The tracking issue for this feature is: [#15701] - -[#15701]: https://github.com/rust-lang/rust/issues/15701 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/struct-field-attributes.md b/src/doc/unstable-book/src/language-features/struct-field-attributes.md deleted file mode 100644 index 1a94562968..0000000000 --- a/src/doc/unstable-book/src/language-features/struct-field-attributes.md +++ /dev/null @@ -1,10 +0,0 @@ -# `struct_field_attributes` - -The tracking issue for this feature is: [#38814] - -[#38814]: https://github.com/rust-lang/rust/issues/38814 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/structural-match.md b/src/doc/unstable-book/src/language-features/structural-match.md deleted file mode 100644 index b3ca26e647..0000000000 --- a/src/doc/unstable-book/src/language-features/structural-match.md +++ /dev/null @@ -1,10 +0,0 @@ -# `structural_match` - -The tracking issue for this feature is: [#31434] - -[#31434]: https://github.com/rust-lang/rust/issues/31434 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/target-feature.md b/src/doc/unstable-book/src/language-features/target-feature.md deleted file mode 100644 index 85ab1ab39e..0000000000 --- a/src/doc/unstable-book/src/language-features/target-feature.md +++ /dev/null @@ -1,6 +0,0 @@ -# `target_feature` - -The tracking issue for this feature is: None. - ------------------------- - diff --git a/src/doc/unstable-book/src/language-features/thread-local.md b/src/doc/unstable-book/src/language-features/thread-local.md deleted file mode 100644 index 83de2f9cd4..0000000000 --- a/src/doc/unstable-book/src/language-features/thread-local.md +++ /dev/null @@ -1,10 +0,0 @@ -# `thread_local` - -The tracking issue for this feature is: [#29594] - -[#29594]: https://github.com/rust-lang/rust/issues/29594 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/trace-macros.md b/src/doc/unstable-book/src/language-features/trace-macros.md deleted file mode 100644 index 856f1b0a7b..0000000000 --- a/src/doc/unstable-book/src/language-features/trace-macros.md +++ /dev/null @@ -1,10 +0,0 @@ -# `trace_macros` - -The tracking issue for this feature is: [#29598] - -[#29598]: https://github.com/rust-lang/rust/issues/29598 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/type-ascription.md b/src/doc/unstable-book/src/language-features/type-ascription.md deleted file mode 100644 index 3ebd0d87cc..0000000000 --- a/src/doc/unstable-book/src/language-features/type-ascription.md +++ /dev/null @@ -1,10 +0,0 @@ -# `type_ascription` - -The tracking issue for this feature is: [#23416] - -[#23416]: https://github.com/rust-lang/rust/issues/23416 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/unboxed-closures.md b/src/doc/unstable-book/src/language-features/unboxed-closures.md deleted file mode 100644 index 2cbb436ce0..0000000000 --- a/src/doc/unstable-book/src/language-features/unboxed-closures.md +++ /dev/null @@ -1,10 +0,0 @@ -# `unboxed_closures` - -The tracking issue for this feature is: [#29625] - -[#29625]: https://github.com/rust-lang/rust/issues/29625 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md b/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md new file mode 100644 index 0000000000..731d2acbfd --- /dev/null +++ b/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md @@ -0,0 +1,27 @@ +# `unsized_tuple_coercion` + +The tracking issue for this feature is: [#42877] + +[#42877]: https://github.com/rust-lang/rust/issues/42877 + +------------------------ + +This is a part of [RFC0401]. According to the RFC, there should be an implementation like this: + +```rust,ignore +impl<..., T, U: ?Sized> Unsized<(..., U)> for (..., T) where T: Unsized {} +``` + +This implementation is currently gated behind `#[feature(unsized_tuple_coercion)]` to avoid insta-stability. Therefore you can use it like this: + +```rust +#![feature(unsized_tuple_coercion)] + +fn main() { + let x : ([i32; 3], [i32; 3]) = ([1, 2, 3], [4, 5, 6]); + let y : &([i32; 3], [i32]) = &x; + assert_eq!(y.1[0], 4); +} +``` + +[RFC0401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md diff --git a/src/doc/unstable-book/src/language-features/untagged-unions.md b/src/doc/unstable-book/src/language-features/untagged-unions.md deleted file mode 100644 index 6fe4f088ac..0000000000 --- a/src/doc/unstable-book/src/language-features/untagged-unions.md +++ /dev/null @@ -1,10 +0,0 @@ -# `untagged_unions` - -The tracking issue for this feature is: [#32836] - -[#32836]: https://github.com/rust-lang/rust/issues/32836 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/unwind-attributes.md b/src/doc/unstable-book/src/language-features/unwind-attributes.md deleted file mode 100644 index 0167a33b08..0000000000 --- a/src/doc/unstable-book/src/language-features/unwind-attributes.md +++ /dev/null @@ -1,6 +0,0 @@ -# `unwind_attributes` - -The tracking issue for this feature is: None. - ------------------------- - diff --git a/src/doc/unstable-book/src/language-features/use-extern-macros.md b/src/doc/unstable-book/src/language-features/use-extern-macros.md deleted file mode 100644 index bc61491150..0000000000 --- a/src/doc/unstable-book/src/language-features/use-extern-macros.md +++ /dev/null @@ -1,10 +0,0 @@ -# `use_extern_macros` - -The tracking issue for this feature is: [#35896] - -[#35896]: https://github.com/rust-lang/rust/issues/35896 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/library-features/alloc.md b/src/doc/unstable-book/src/library-features/alloc.md deleted file mode 100644 index 47eeb0874f..0000000000 --- a/src/doc/unstable-book/src/library-features/alloc.md +++ /dev/null @@ -1,7 +0,0 @@ -# `alloc` - -The tracking issue for this feature is: [#27783] - -[#27783]: https://github.com/rust-lang/rust/issues/27783 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/allocator-api.md b/src/doc/unstable-book/src/library-features/allocator-api.md new file mode 100644 index 0000000000..e3969ace7e --- /dev/null +++ b/src/doc/unstable-book/src/library-features/allocator-api.md @@ -0,0 +1,15 @@ +# `allocator_api` + +The tracking issue for this feature is [#32838] + +[#32838]: https://github.com/rust-lang/rust/issues/32838 + +------------------------ + +Sometimes you want the memory for one collection to use a different +allocator than the memory for another collection. In this case, +replacing the global allocator is not a workable option. Instead, +you need to pass in an instance of an `Alloc` to each collection +for which you want a custom allocator. + +TBD diff --git a/src/doc/unstable-book/src/library-features/as-c-str.md b/src/doc/unstable-book/src/library-features/as-c-str.md deleted file mode 100644 index ed32eedb34..0000000000 --- a/src/doc/unstable-book/src/library-features/as-c-str.md +++ /dev/null @@ -1,8 +0,0 @@ -# `as_c_str` - -The tracking issue for this feature is: [#40380] - -[#40380]: https://github.com/rust-lang/rust/issues/40380 - ------------------------- - diff --git a/src/doc/unstable-book/src/library-features/ascii-ctype.md b/src/doc/unstable-book/src/library-features/ascii-ctype.md deleted file mode 100644 index e253b4dcd9..0000000000 --- a/src/doc/unstable-book/src/library-features/ascii-ctype.md +++ /dev/null @@ -1,5 +0,0 @@ -# `ascii_ctype` - -The tracking issue for this feature is: [#39658] - -[#39658]: https://github.com/rust-lang/rust/issues/39658 diff --git a/src/doc/unstable-book/src/library-features/box-heap.md b/src/doc/unstable-book/src/library-features/box-heap.md deleted file mode 100644 index 0f3f01ba0e..0000000000 --- a/src/doc/unstable-book/src/library-features/box-heap.md +++ /dev/null @@ -1,7 +0,0 @@ -# `box_heap` - -The tracking issue for this feature is: [#27779] - -[#27779]: https://github.com/rust-lang/rust/issues/27779 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/char-error-internals.md b/src/doc/unstable-book/src/library-features/char-error-internals.md new file mode 100644 index 0000000000..8013b4988e --- /dev/null +++ b/src/doc/unstable-book/src/library-features/char-error-internals.md @@ -0,0 +1,5 @@ +# `char_error_internals` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ diff --git a/src/doc/unstable-book/src/library-features/char-escape-debug.md b/src/doc/unstable-book/src/library-features/char-escape-debug.md deleted file mode 100644 index 21aa486219..0000000000 --- a/src/doc/unstable-book/src/library-features/char-escape-debug.md +++ /dev/null @@ -1,7 +0,0 @@ -# `char_escape_debug` - -The tracking issue for this feature is: [#35068] - -[#35068]: https://github.com/rust-lang/rust/issues/35068 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/coerce-unsized.md b/src/doc/unstable-book/src/library-features/coerce-unsized.md deleted file mode 100644 index 078d3faf42..0000000000 --- a/src/doc/unstable-book/src/library-features/coerce-unsized.md +++ /dev/null @@ -1,7 +0,0 @@ -# `coerce_unsized` - -The tracking issue for this feature is: [#27732] - -[#27732]: https://github.com/rust-lang/rust/issues/27732 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/collection-placement.md b/src/doc/unstable-book/src/library-features/collection-placement.md deleted file mode 100644 index 268ca6ea59..0000000000 --- a/src/doc/unstable-book/src/library-features/collection-placement.md +++ /dev/null @@ -1,7 +0,0 @@ -# `collection_placement` - -The tracking issue for this feature is: [#30172] - -[#30172]: https://github.com/rust-lang/rust/issues/30172 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/collections-range.md b/src/doc/unstable-book/src/library-features/collections-range.md deleted file mode 100644 index ea4f999ba0..0000000000 --- a/src/doc/unstable-book/src/library-features/collections-range.md +++ /dev/null @@ -1,7 +0,0 @@ -# `collections_range` - -The tracking issue for this feature is: [#30877] - -[#30877]: https://github.com/rust-lang/rust/issues/30877 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/compiler-builtins-lib.md b/src/doc/unstable-book/src/library-features/compiler-builtins-lib.md deleted file mode 100644 index 5da8968fd0..0000000000 --- a/src/doc/unstable-book/src/library-features/compiler-builtins-lib.md +++ /dev/null @@ -1,35 +0,0 @@ -# `compiler_builtins_lib` - -The tracking issue for this feature is: None. - ------------------------- - -This feature is required to link to the `compiler_builtins` crate which contains -"compiler intrinsics". Compiler intrinsics are software implementations of basic -operations like multiplication of `u64`s. These intrinsics are only required on -platforms where these operations don't directly map to a hardware instruction. - -You should never need to explicitly link to the `compiler_builtins` crate when -building "std" programs as `compiler_builtins` is already in the dependency -graph of `std`. But you may need it when building `no_std` **binary** crates. If -you get a *linker* error like: - -``` text -$PWD/src/main.rs:11: undefined reference to `__aeabi_lmul' -$PWD/src/main.rs:11: undefined reference to `__aeabi_uldivmod' -``` - -That means that you need to link to this crate. - -When you link to this crate, make sure it only appears once in your crate -dependency graph. Also, it doesn't matter where in the dependency graph, you -place the `compiler_builtins` crate. - - - -``` rust,ignore -#![feature(compiler_builtins_lib)] -#![no_std] - -extern crate compiler_builtins; -``` diff --git a/src/doc/unstable-book/src/library-features/concat-idents-macro.md b/src/doc/unstable-book/src/library-features/concat-idents-macro.md deleted file mode 100644 index ac2fdd4fce..0000000000 --- a/src/doc/unstable-book/src/library-features/concat-idents-macro.md +++ /dev/null @@ -1,7 +0,0 @@ -# `concat_idents_macro` - -The tracking issue for this feature is: [#29599] - -[#29599]: https://github.com/rust-lang/rust/issues/29599 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/core-char-ext.md b/src/doc/unstable-book/src/library-features/core-char-ext.md deleted file mode 100644 index d37d6b5c6d..0000000000 --- a/src/doc/unstable-book/src/library-features/core-char-ext.md +++ /dev/null @@ -1,7 +0,0 @@ -# `core_char_ext` - -The tracking issue for this feature is: [#32110] - -[#32110]: https://github.com/rust-lang/rust/issues/32110 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/core-float.md b/src/doc/unstable-book/src/library-features/core-float.md deleted file mode 100644 index 194b2608dd..0000000000 --- a/src/doc/unstable-book/src/library-features/core-float.md +++ /dev/null @@ -1,7 +0,0 @@ -# `core_float` - -The tracking issue for this feature is: [#32110] - -[#32110]: https://github.com/rust-lang/rust/issues/32110 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/core-slice-ext.md b/src/doc/unstable-book/src/library-features/core-slice-ext.md deleted file mode 100644 index c50d44ac0c..0000000000 --- a/src/doc/unstable-book/src/library-features/core-slice-ext.md +++ /dev/null @@ -1,7 +0,0 @@ -# `core_slice_ext` - -The tracking issue for this feature is: [#32110] - -[#32110]: https://github.com/rust-lang/rust/issues/32110 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/core-str-ext.md b/src/doc/unstable-book/src/library-features/core-str-ext.md deleted file mode 100644 index 08c68f11c6..0000000000 --- a/src/doc/unstable-book/src/library-features/core-str-ext.md +++ /dev/null @@ -1,7 +0,0 @@ -# `core_str_ext` - -The tracking issue for this feature is: [#32110] - -[#32110]: https://github.com/rust-lang/rust/issues/32110 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/decode-utf8.md b/src/doc/unstable-book/src/library-features/decode-utf8.md deleted file mode 100644 index b96854ebcd..0000000000 --- a/src/doc/unstable-book/src/library-features/decode-utf8.md +++ /dev/null @@ -1,7 +0,0 @@ -# `decode_utf8` - -The tracking issue for this feature is: [#27783] - -[#27783]: https://github.com/rust-lang/rust/issues/27783 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/discriminant-value.md b/src/doc/unstable-book/src/library-features/discriminant-value.md deleted file mode 100644 index 2f99f5ecab..0000000000 --- a/src/doc/unstable-book/src/library-features/discriminant-value.md +++ /dev/null @@ -1,7 +0,0 @@ -# `discriminant_value` - -The tracking issue for this feature is: [#24263] - -[#24263]: https://github.com/rust-lang/rust/issues/24263 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/error-type-id.md b/src/doc/unstable-book/src/library-features/error-type-id.md deleted file mode 100644 index be7a3ffd4d..0000000000 --- a/src/doc/unstable-book/src/library-features/error-type-id.md +++ /dev/null @@ -1,7 +0,0 @@ -# `error_type_id` - -The tracking issue for this feature is: [#27745] - -[#27745]: https://github.com/rust-lang/rust/issues/27745 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/exact-size-is-empty.md b/src/doc/unstable-book/src/library-features/exact-size-is-empty.md deleted file mode 100644 index 200ec38725..0000000000 --- a/src/doc/unstable-book/src/library-features/exact-size-is-empty.md +++ /dev/null @@ -1,7 +0,0 @@ -# `exact_size_is_empty` - -The tracking issue for this feature is: [#35428] - -[#35428]: https://github.com/rust-lang/rust/issues/35428 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/fixed-size-array.md b/src/doc/unstable-book/src/library-features/fixed-size-array.md deleted file mode 100644 index 9e24e6a085..0000000000 --- a/src/doc/unstable-book/src/library-features/fixed-size-array.md +++ /dev/null @@ -1,7 +0,0 @@ -# `fixed_size_array` - -The tracking issue for this feature is: [#27778] - -[#27778]: https://github.com/rust-lang/rust/issues/27778 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/float-bits-conv.md b/src/doc/unstable-book/src/library-features/float-bits-conv.md deleted file mode 100644 index f519545ac7..0000000000 --- a/src/doc/unstable-book/src/library-features/float-bits-conv.md +++ /dev/null @@ -1,7 +0,0 @@ -# `float_bits_conv` - -The tracking issue for this feature is: [#40470] - -[#40470]: https://github.com/rust-lang/rust/issues/40470 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/fmt-flags-align.md b/src/doc/unstable-book/src/library-features/fmt-flags-align.md deleted file mode 100644 index 755263bd9a..0000000000 --- a/src/doc/unstable-book/src/library-features/fmt-flags-align.md +++ /dev/null @@ -1,7 +0,0 @@ -# `fmt_flags_align` - -The tracking issue for this feature is: [#27726] - -[#27726]: https://github.com/rust-lang/rust/issues/27726 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/fn-traits.md b/src/doc/unstable-book/src/library-features/fn-traits.md deleted file mode 100644 index 3942cda553..0000000000 --- a/src/doc/unstable-book/src/library-features/fn-traits.md +++ /dev/null @@ -1,7 +0,0 @@ -# `fn_traits` - -The tracking issue for this feature is: [#29625] - -[#29625]: https://github.com/rust-lang/rust/issues/29625 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/fnbox.md b/src/doc/unstable-book/src/library-features/fnbox.md deleted file mode 100644 index a9b74d4f00..0000000000 --- a/src/doc/unstable-book/src/library-features/fnbox.md +++ /dev/null @@ -1,7 +0,0 @@ -# `fnbox` - -The tracking issue for this feature is: [#28796] - -[#28796]: https://github.com/rust-lang/rust/issues/28796 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/from_utf8_error_as_bytes.md b/src/doc/unstable-book/src/library-features/from_utf8_error_as_bytes.md deleted file mode 100644 index 570f779417..0000000000 --- a/src/doc/unstable-book/src/library-features/from_utf8_error_as_bytes.md +++ /dev/null @@ -1,7 +0,0 @@ -# `from_utf8_error_as_bytes` - -The tracking issue for this feature is: [#40895] - -[#40895]: https://github.com/rust-lang/rust/issues/40895 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/fused.md b/src/doc/unstable-book/src/library-features/fused.md deleted file mode 100644 index 460555bf1b..0000000000 --- a/src/doc/unstable-book/src/library-features/fused.md +++ /dev/null @@ -1,7 +0,0 @@ -# `fused` - -The tracking issue for this feature is: [#35602] - -[#35602]: https://github.com/rust-lang/rust/issues/35602 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/get-type-id.md b/src/doc/unstable-book/src/library-features/get-type-id.md deleted file mode 100644 index afdb030c40..0000000000 --- a/src/doc/unstable-book/src/library-features/get-type-id.md +++ /dev/null @@ -1,7 +0,0 @@ -# `get_type_id` - -The tracking issue for this feature is: [#27745] - -[#27745]: https://github.com/rust-lang/rust/issues/27745 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/heap-api.md b/src/doc/unstable-book/src/library-features/heap-api.md deleted file mode 100644 index 01404e49db..0000000000 --- a/src/doc/unstable-book/src/library-features/heap-api.md +++ /dev/null @@ -1,7 +0,0 @@ -# `heap_api` - -The tracking issue for this feature is: [#27700] - -[#27700]: https://github.com/rust-lang/rust/issues/27700 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/i128.md b/src/doc/unstable-book/src/library-features/i128.md deleted file mode 100644 index a1a7ce8e63..0000000000 --- a/src/doc/unstable-book/src/library-features/i128.md +++ /dev/null @@ -1,7 +0,0 @@ -# `i128` - -The tracking issue for this feature is: [#35118] - -[#35118]: https://github.com/rust-lang/rust/issues/35118 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/inclusive-range.md b/src/doc/unstable-book/src/library-features/inclusive-range.md deleted file mode 100644 index 2e88e20478..0000000000 --- a/src/doc/unstable-book/src/library-features/inclusive-range.md +++ /dev/null @@ -1,7 +0,0 @@ -# `inclusive_range` - -The tracking issue for this feature is: [#28237] - -[#28237]: https://github.com/rust-lang/rust/issues/28237 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/integer-atomics.md b/src/doc/unstable-book/src/library-features/integer-atomics.md deleted file mode 100644 index 50db9fd4ca..0000000000 --- a/src/doc/unstable-book/src/library-features/integer-atomics.md +++ /dev/null @@ -1,7 +0,0 @@ -# `integer_atomics` - -The tracking issue for this feature is: [#32976] - -[#32976]: https://github.com/rust-lang/rust/issues/32976 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/into-boxed-c-str.md b/src/doc/unstable-book/src/library-features/into-boxed-c-str.md deleted file mode 100644 index 0d94b4fc56..0000000000 --- a/src/doc/unstable-book/src/library-features/into-boxed-c-str.md +++ /dev/null @@ -1,7 +0,0 @@ -# `into_boxed_c_str` - -The tracking issue for this feature is: [#40380] - -[#40380]: https://github.com/rust-lang/rust/issues/40380 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/into-boxed-os-str.md b/src/doc/unstable-book/src/library-features/into-boxed-os-str.md deleted file mode 100644 index 7636e20b14..0000000000 --- a/src/doc/unstable-book/src/library-features/into-boxed-os-str.md +++ /dev/null @@ -1,7 +0,0 @@ -# `into_boxed_os_str` - -The tracking issue for this feature is: [#into_boxed_os_str] - -[#into_boxed_os_str]: https://github.com/rust-lang/rust/issues/40380 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/into-boxed-path.md b/src/doc/unstable-book/src/library-features/into-boxed-path.md deleted file mode 100644 index 754c6042f0..0000000000 --- a/src/doc/unstable-book/src/library-features/into-boxed-path.md +++ /dev/null @@ -1,7 +0,0 @@ -# `into_boxed_path` - -The tracking issue for this feature is: [#40380] - -[#40380]: https://github.com/rust-lang/rust/issues/40380 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/io.md b/src/doc/unstable-book/src/library-features/io.md deleted file mode 100644 index ed6cae24e3..0000000000 --- a/src/doc/unstable-book/src/library-features/io.md +++ /dev/null @@ -1,7 +0,0 @@ -# `io` - -The tracking issue for this feature is: [#27802] - -[#27802]: https://github.com/rust-lang/rust/issues/27802 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/ip.md b/src/doc/unstable-book/src/library-features/ip.md deleted file mode 100644 index 7e7d52adbd..0000000000 --- a/src/doc/unstable-book/src/library-features/ip.md +++ /dev/null @@ -1,7 +0,0 @@ -# `ip` - -The tracking issue for this feature is: [#27709] - -[#27709]: https://github.com/rust-lang/rust/issues/27709 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/iter-rfind.md b/src/doc/unstable-book/src/library-features/iter-rfind.md deleted file mode 100644 index 4447144903..0000000000 --- a/src/doc/unstable-book/src/library-features/iter-rfind.md +++ /dev/null @@ -1,7 +0,0 @@ -# `iter_rfind` - -The tracking issue for this feature is: [#39480] - -[#39480]: https://github.com/rust-lang/rust/issues/39480 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/iterator-for-each.md b/src/doc/unstable-book/src/library-features/iterator-for-each.md new file mode 100644 index 0000000000..ebeb5f6a1d --- /dev/null +++ b/src/doc/unstable-book/src/library-features/iterator-for-each.md @@ -0,0 +1,17 @@ +# `iterator_for_each` + +The tracking issue for this feature is: [#42986] + +[#42986]: https://github.com/rust-lang/rust/issues/42986 + +------------------------ + +To call a closure on each element of an iterator, you can use `for_each`: + +```rust +#![feature(iterator_for_each)] + +fn main() { + (0..10).for_each(|i| println!("{}", i)); +} +``` diff --git a/src/doc/unstable-book/src/library-features/iterator-step-by.md b/src/doc/unstable-book/src/library-features/iterator-step-by.md deleted file mode 100644 index 8467cb6886..0000000000 --- a/src/doc/unstable-book/src/library-features/iterator-step-by.md +++ /dev/null @@ -1,7 +0,0 @@ -# `iterator_step_by` - -The tracking issue for this feature is: [#27741] - -[#27741]: https://github.com/rust-lang/rust/issues/27741 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/linked-list-extras.md b/src/doc/unstable-book/src/library-features/linked-list-extras.md deleted file mode 100644 index be3b96aea7..0000000000 --- a/src/doc/unstable-book/src/library-features/linked-list-extras.md +++ /dev/null @@ -1,7 +0,0 @@ -# `linked_list_extras` - -The tracking issue for this feature is: [#27794] - -[#27794]: https://github.com/rust-lang/rust/issues/27794 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/lookup-host.md b/src/doc/unstable-book/src/library-features/lookup-host.md deleted file mode 100644 index b60e7a0109..0000000000 --- a/src/doc/unstable-book/src/library-features/lookup-host.md +++ /dev/null @@ -1,7 +0,0 @@ -# `lookup_host` - -The tracking issue for this feature is: [#27705] - -[#27705]: https://github.com/rust-lang/rust/issues/27705 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/more-io-inner-methods.md b/src/doc/unstable-book/src/library-features/more-io-inner-methods.md deleted file mode 100644 index c84f40e7ee..0000000000 --- a/src/doc/unstable-book/src/library-features/more-io-inner-methods.md +++ /dev/null @@ -1,11 +0,0 @@ -# `more_io_inner_methods` - -The tracking issue for this feature is: [#41519] - -[#41519]: https://github.com/rust-lang/rust/issues/41519 - ------------------------- - -This feature enables several internal accessor methods on structures in -`std::io` including `Take::{get_ref, get_mut}` and `Chain::{into_inner, get_ref, -get_mut}`. diff --git a/src/doc/unstable-book/src/library-features/mpsc-select.md b/src/doc/unstable-book/src/library-features/mpsc-select.md deleted file mode 100644 index 1405b6c5cb..0000000000 --- a/src/doc/unstable-book/src/library-features/mpsc-select.md +++ /dev/null @@ -1,5 +0,0 @@ -# `mpsc_select` - -The tracking issue for this feature is: [#27800] - -[#27800]: https://github.com/rust-lang/rust/issues/27800 diff --git a/src/doc/unstable-book/src/library-features/needs-drop.md b/src/doc/unstable-book/src/library-features/needs-drop.md deleted file mode 100644 index 10ae95695a..0000000000 --- a/src/doc/unstable-book/src/library-features/needs-drop.md +++ /dev/null @@ -1,7 +0,0 @@ -# `needs_drop` - -The tracking issue for this feature is: [#41890] - -[#41890]: https://github.com/rust-lang/rust/issues/41890 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/never-type-impls.md b/src/doc/unstable-book/src/library-features/never-type-impls.md deleted file mode 100644 index 4063cd0db0..0000000000 --- a/src/doc/unstable-book/src/library-features/never-type-impls.md +++ /dev/null @@ -1,7 +0,0 @@ -# `never_type_impls` - -The tracking issue for this feature is: [#35121] - -[#35121]: https://github.com/rust-lang/rust/issues/35121 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/nonzero.md b/src/doc/unstable-book/src/library-features/nonzero.md deleted file mode 100644 index f200f8e278..0000000000 --- a/src/doc/unstable-book/src/library-features/nonzero.md +++ /dev/null @@ -1,7 +0,0 @@ -# `nonzero` - -The tracking issue for this feature is: [#27730] - -[#27730]: https://github.com/rust-lang/rust/issues/27730 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/offset-to.md b/src/doc/unstable-book/src/library-features/offset-to.md deleted file mode 100644 index 03d990eb4a..0000000000 --- a/src/doc/unstable-book/src/library-features/offset-to.md +++ /dev/null @@ -1,7 +0,0 @@ -# `offset_to` - -The tracking issue for this feature is: [#41079] - -[#41079]: https://github.com/rust-lang/rust/issues/41079 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/once-poison.md b/src/doc/unstable-book/src/library-features/once-poison.md deleted file mode 100644 index 3c16cafae5..0000000000 --- a/src/doc/unstable-book/src/library-features/once-poison.md +++ /dev/null @@ -1,7 +0,0 @@ -# `once_poison` - -The tracking issue for this feature is: [#33577] - -[#33577]: https://github.com/rust-lang/rust/issues/33577 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/oom.md b/src/doc/unstable-book/src/library-features/oom.md deleted file mode 100644 index 908caeb75c..0000000000 --- a/src/doc/unstable-book/src/library-features/oom.md +++ /dev/null @@ -1,7 +0,0 @@ -# `oom` - -The tracking issue for this feature is: [#27700] - -[#27700]: https://github.com/rust-lang/rust/issues/27700 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/option-entry.md b/src/doc/unstable-book/src/library-features/option-entry.md deleted file mode 100644 index edb4efc09e..0000000000 --- a/src/doc/unstable-book/src/library-features/option-entry.md +++ /dev/null @@ -1,7 +0,0 @@ -# `option_entry` - -The tracking issue for this feature is: [#39288] - -[#39288]: https://github.com/rust-lang/rust/issues/39288 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/panic-abort.md b/src/doc/unstable-book/src/library-features/panic-abort.md deleted file mode 100644 index 07a9576269..0000000000 --- a/src/doc/unstable-book/src/library-features/panic-abort.md +++ /dev/null @@ -1,7 +0,0 @@ -# `panic_abort` - -The tracking issue for this feature is: [#32837] - -[#32837]: https://github.com/rust-lang/rust/issues/32837 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/panic-unwind.md b/src/doc/unstable-book/src/library-features/panic-unwind.md deleted file mode 100644 index 840e492597..0000000000 --- a/src/doc/unstable-book/src/library-features/panic-unwind.md +++ /dev/null @@ -1,7 +0,0 @@ -# `panic_unwind` - -The tracking issue for this feature is: [#32837] - -[#32837]: https://github.com/rust-lang/rust/issues/32837 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/pattern.md b/src/doc/unstable-book/src/library-features/pattern.md deleted file mode 100644 index e76ee6beb6..0000000000 --- a/src/doc/unstable-book/src/library-features/pattern.md +++ /dev/null @@ -1,7 +0,0 @@ -# `pattern` - -The tracking issue for this feature is: [#27721] - -[#27721]: https://github.com/rust-lang/rust/issues/27721 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/placement-in.md b/src/doc/unstable-book/src/library-features/placement-in.md deleted file mode 100644 index 6ff010b7e3..0000000000 --- a/src/doc/unstable-book/src/library-features/placement-in.md +++ /dev/null @@ -1,7 +0,0 @@ -# `placement_in` - -The tracking issue for this feature is: [#27779] - -[#27779]: https://github.com/rust-lang/rust/issues/27779 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/placement-new-protocol.md b/src/doc/unstable-book/src/library-features/placement-new-protocol.md deleted file mode 100644 index d53225f0a3..0000000000 --- a/src/doc/unstable-book/src/library-features/placement-new-protocol.md +++ /dev/null @@ -1,7 +0,0 @@ -# `placement_new_protocol` - -The tracking issue for this feature is: [#27779] - -[#27779]: https://github.com/rust-lang/rust/issues/27779 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/proc-macro-internals.md b/src/doc/unstable-book/src/library-features/proc-macro-internals.md deleted file mode 100644 index ea087c0a4f..0000000000 --- a/src/doc/unstable-book/src/library-features/proc-macro-internals.md +++ /dev/null @@ -1,7 +0,0 @@ -# `proc_macro_internals` - -The tracking issue for this feature is: [#27812] - -[#27812]: https://github.com/rust-lang/rust/issues/27812 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/proc-macro.md b/src/doc/unstable-book/src/library-features/proc-macro.md new file mode 100644 index 0000000000..19e7f663c7 --- /dev/null +++ b/src/doc/unstable-book/src/library-features/proc-macro.md @@ -0,0 +1,7 @@ +# `proc_macro` + +The tracking issue for this feature is: [#38356] + +[#38356]: https://github.com/rust-lang/rust/issues/38356 + +------------------------ diff --git a/src/doc/unstable-book/src/library-features/profiler-runtime-lib.md b/src/doc/unstable-book/src/library-features/profiler-runtime-lib.md new file mode 100644 index 0000000000..a01f1e73ab --- /dev/null +++ b/src/doc/unstable-book/src/library-features/profiler-runtime-lib.md @@ -0,0 +1,5 @@ +# `profiler_runtime_lib` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ diff --git a/src/doc/unstable-book/src/library-features/question-mark-carrier.md b/src/doc/unstable-book/src/library-features/question-mark-carrier.md deleted file mode 100644 index a5e6965fae..0000000000 --- a/src/doc/unstable-book/src/library-features/question-mark-carrier.md +++ /dev/null @@ -1,13 +0,0 @@ -# `question_mark_carrier` - -The tracking issue for this feature is: [#31436] - -[#31436]: https://github.com/rust-lang/rust/issues/31436 - ------------------------- - -This feature has been superseded by [`try_trait`][try_trait]. - -It exists only in stage0 for bootstrapping. - -[try_trait]: library-features/try-trait.html diff --git a/src/doc/unstable-book/src/library-features/range-contains.md b/src/doc/unstable-book/src/library-features/range-contains.md deleted file mode 100644 index ac4581faf2..0000000000 --- a/src/doc/unstable-book/src/library-features/range-contains.md +++ /dev/null @@ -1,7 +0,0 @@ -# `range_contains` - -The tracking issue for this feature is: [#32311] - -[#32311]: https://github.com/rust-lang/rust/issues/32311 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/raw.md b/src/doc/unstable-book/src/library-features/raw.md deleted file mode 100644 index d7caf22813..0000000000 --- a/src/doc/unstable-book/src/library-features/raw.md +++ /dev/null @@ -1,7 +0,0 @@ -# `raw` - -The tracking issue for this feature is: [#27751] - -[#27751]: https://github.com/rust-lang/rust/issues/27751 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/read-initializer.md b/src/doc/unstable-book/src/library-features/read-initializer.md new file mode 100644 index 0000000000..898fe58eee --- /dev/null +++ b/src/doc/unstable-book/src/library-features/read-initializer.md @@ -0,0 +1,7 @@ +# `read_initializer` + +The tracking issue for this feature is: [#42788] + +[#0]: https://github.com/rust-lang/rust/issues/42788 + +------------------------ diff --git a/src/doc/unstable-book/src/library-features/rustc-private.md b/src/doc/unstable-book/src/library-features/rustc-private.md deleted file mode 100644 index 2453475efe..0000000000 --- a/src/doc/unstable-book/src/library-features/rustc-private.md +++ /dev/null @@ -1,7 +0,0 @@ -# `rustc_private` - -The tracking issue for this feature is: [#27812] - -[#27812]: https://github.com/rust-lang/rust/issues/27812 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/shared.md b/src/doc/unstable-book/src/library-features/shared.md deleted file mode 100644 index b79d1212c6..0000000000 --- a/src/doc/unstable-book/src/library-features/shared.md +++ /dev/null @@ -1,7 +0,0 @@ -# `shared` - -The tracking issue for this feature is: [#27730] - -[#27730]: https://github.com/rust-lang/rust/issues/27730 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/sip-hash-13.md b/src/doc/unstable-book/src/library-features/sip-hash-13.md deleted file mode 100644 index 8f69c3ab2d..0000000000 --- a/src/doc/unstable-book/src/library-features/sip-hash-13.md +++ /dev/null @@ -1,7 +0,0 @@ -# `sip_hash_13` - -The tracking issue for this feature is: [#34767] - -[#34767]: https://github.com/rust-lang/rust/issues/34767 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/slice-concat-ext.md b/src/doc/unstable-book/src/library-features/slice-concat-ext.md deleted file mode 100644 index 9ba2de5adc..0000000000 --- a/src/doc/unstable-book/src/library-features/slice-concat-ext.md +++ /dev/null @@ -1,7 +0,0 @@ -# `slice_concat_ext` - -The tracking issue for this feature is: [#27747] - -[#27747]: https://github.com/rust-lang/rust/issues/27747 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/slice-get-slice.md b/src/doc/unstable-book/src/library-features/slice-get-slice.md deleted file mode 100644 index 57e2c148e7..0000000000 --- a/src/doc/unstable-book/src/library-features/slice-get-slice.md +++ /dev/null @@ -1,7 +0,0 @@ -# `slice_get_slice` - -The tracking issue for this feature is: [#35729] - -[#35729]: https://github.com/rust-lang/rust/issues/35729 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/slice-rotate.md b/src/doc/unstable-book/src/library-features/slice-rotate.md deleted file mode 100644 index 77fd598f1e..0000000000 --- a/src/doc/unstable-book/src/library-features/slice-rotate.md +++ /dev/null @@ -1,7 +0,0 @@ -# `slice_rotate` - -The tracking issue for this feature is: [#41891] - -[#41891]: https://github.com/rust-lang/rust/issues/41891 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/sort-unstable.md b/src/doc/unstable-book/src/library-features/sort-unstable.md deleted file mode 100644 index 9effcfc774..0000000000 --- a/src/doc/unstable-book/src/library-features/sort-unstable.md +++ /dev/null @@ -1,40 +0,0 @@ -# `sort_unstable` - -The tracking issue for this feature is: [#40585] - -[#40585]: https://github.com/rust-lang/rust/issues/40585 - ------------------------- - -The default `sort` method on slices is stable. In other words, it guarantees -that the original order of equal elements is preserved after sorting. The -method has several undesirable characteristics: - -1. It allocates a sizable chunk of memory. -2. If you don't need stability, it is not as performant as it could be. - -An alternative is the new `sort_unstable` feature, which includes these -methods for sorting slices: - -1. `sort_unstable` -2. `sort_unstable_by` -3. `sort_unstable_by_key` - -Unstable sorting is generally faster and makes no allocations. The majority -of real-world sorting needs doesn't require stability, so these methods can -very often come in handy. - -Another important difference is that `sort` lives in `libstd` and -`sort_unstable` lives in `libcore`. The reason is that the former makes -allocations and the latter doesn't. - -A simple example: - -```rust -#![feature(sort_unstable)] - -let mut v = [-5, 4, 1, -3, 2]; - -v.sort_unstable(); -assert!(v == [-5, -3, 1, 2, 4]); -``` diff --git a/src/doc/unstable-book/src/library-features/step-by.md b/src/doc/unstable-book/src/library-features/step-by.md deleted file mode 100644 index b649496cdd..0000000000 --- a/src/doc/unstable-book/src/library-features/step-by.md +++ /dev/null @@ -1,7 +0,0 @@ -# `step_by` - -The tracking issue for this feature is: [#27741] - -[#27741]: https://github.com/rust-lang/rust/issues/27741 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/step-trait.md b/src/doc/unstable-book/src/library-features/step-trait.md deleted file mode 100644 index 56050c20c6..0000000000 --- a/src/doc/unstable-book/src/library-features/step-trait.md +++ /dev/null @@ -1,7 +0,0 @@ -# `step_trait` - -The tracking issue for this feature is: [#42168] - -[#42168]: https://github.com/rust-lang/rust/issues/42168 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/str-box-extras.md b/src/doc/unstable-book/src/library-features/str-box-extras.md deleted file mode 100644 index d05dcafa84..0000000000 --- a/src/doc/unstable-book/src/library-features/str-box-extras.md +++ /dev/null @@ -1,9 +0,0 @@ -# `str_box_extras` - -The tracking issue for this feature is: [#str_box_extras] - -[#str_box_extras]: https://github.com/rust-lang/rust/issues/41119 - ------------------------- - - diff --git a/src/doc/unstable-book/src/library-features/str-checked-slicing.md b/src/doc/unstable-book/src/library-features/str-checked-slicing.md deleted file mode 100644 index d390139a6b..0000000000 --- a/src/doc/unstable-book/src/library-features/str-checked-slicing.md +++ /dev/null @@ -1,7 +0,0 @@ -# `str_checked_slicing` - -The tracking issue for this feature is: [#39932] - -[#39932]: https://github.com/rust-lang/rust/issues/39932 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/str-escape.md b/src/doc/unstable-book/src/library-features/str-escape.md deleted file mode 100644 index 61e31c8944..0000000000 --- a/src/doc/unstable-book/src/library-features/str-escape.md +++ /dev/null @@ -1,7 +0,0 @@ -# `str_escape` - -The tracking issue for this feature is: [#27791] - -[#27791]: https://github.com/rust-lang/rust/issues/27791 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/str-mut-extras.md b/src/doc/unstable-book/src/library-features/str-mut-extras.md deleted file mode 100644 index df4f35832c..0000000000 --- a/src/doc/unstable-book/src/library-features/str-mut-extras.md +++ /dev/null @@ -1,8 +0,0 @@ -# `str_mut_extras` - -The tracking issue for this feature is: [#str_mut_extras] - -[#str_mut_extras]: https://github.com/rust-lang/rust/issues/41119 - ------------------------- - diff --git a/src/doc/unstable-book/src/library-features/thread-local-state.md b/src/doc/unstable-book/src/library-features/thread-local-state.md deleted file mode 100644 index 113c1e910d..0000000000 --- a/src/doc/unstable-book/src/library-features/thread-local-state.md +++ /dev/null @@ -1,7 +0,0 @@ -# `thread_local_state` - -The tracking issue for this feature is: [#27716] - -[#27716]: https://github.com/rust-lang/rust/issues/27716 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/toowned-clone-into.md b/src/doc/unstable-book/src/library-features/toowned-clone-into.md deleted file mode 100644 index eccc7e0e4d..0000000000 --- a/src/doc/unstable-book/src/library-features/toowned-clone-into.md +++ /dev/null @@ -1,7 +0,0 @@ -# `toowned_clone_into` - -The tracking issue for this feature is: [#41263] - -[#41263]: https://github.com/rust-lang/rust/issues/41263 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/trusted-len.md b/src/doc/unstable-book/src/library-features/trusted-len.md deleted file mode 100644 index 80213cf1fd..0000000000 --- a/src/doc/unstable-book/src/library-features/trusted-len.md +++ /dev/null @@ -1,7 +0,0 @@ -# `trusted_len` - -The tracking issue for this feature is: [#37572] - -[#37572]: https://github.com/rust-lang/rust/issues/37572 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/try-from.md b/src/doc/unstable-book/src/library-features/try-from.md deleted file mode 100644 index d763caff5a..0000000000 --- a/src/doc/unstable-book/src/library-features/try-from.md +++ /dev/null @@ -1,7 +0,0 @@ -# `try_from` - -The tracking issue for this feature is: [#33417] - -[#33417]: https://github.com/rust-lang/rust/issues/33417 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/unicode.md b/src/doc/unstable-book/src/library-features/unicode.md deleted file mode 100644 index 9fecec2ac3..0000000000 --- a/src/doc/unstable-book/src/library-features/unicode.md +++ /dev/null @@ -1,7 +0,0 @@ -# `unicode` - -The tracking issue for this feature is: [#27783] - -[#27783]: https://github.com/rust-lang/rust/issues/27783 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/unique.md b/src/doc/unstable-book/src/library-features/unique.md deleted file mode 100644 index 99a3490d10..0000000000 --- a/src/doc/unstable-book/src/library-features/unique.md +++ /dev/null @@ -1,7 +0,0 @@ -# `unique` - -The tracking issue for this feature is: [#27730] - -[#27730]: https://github.com/rust-lang/rust/issues/27730 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/unsize.md b/src/doc/unstable-book/src/library-features/unsize.md deleted file mode 100644 index 92807e2858..0000000000 --- a/src/doc/unstable-book/src/library-features/unsize.md +++ /dev/null @@ -1,7 +0,0 @@ -# `unsize` - -The tracking issue for this feature is: [#27732] - -[#27732]: https://github.com/rust-lang/rust/issues/27732 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/utf8-error-error-len.md b/src/doc/unstable-book/src/library-features/utf8-error-error-len.md deleted file mode 100644 index 1c14a5a9fa..0000000000 --- a/src/doc/unstable-book/src/library-features/utf8-error-error-len.md +++ /dev/null @@ -1,7 +0,0 @@ -# `utf8_error_error_len` - -The tracking issue for this feature is: [#40494] - -[#40494]: https://github.com/rust-lang/rust/issues/40494 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/vec-remove-item.md b/src/doc/unstable-book/src/library-features/vec-remove-item.md deleted file mode 100644 index 2b8c9f046e..0000000000 --- a/src/doc/unstable-book/src/library-features/vec-remove-item.md +++ /dev/null @@ -1,7 +0,0 @@ -# `vec_remove_item` - -The tracking issue for this feature is: [#40062] - -[#40062]: https://github.com/rust-lang/rust/issues/40062 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/vec-resize-default.md b/src/doc/unstable-book/src/library-features/vec-resize-default.md deleted file mode 100644 index 5803d3215a..0000000000 --- a/src/doc/unstable-book/src/library-features/vec-resize-default.md +++ /dev/null @@ -1,7 +0,0 @@ -# `vec_resize_default` - -The tracking issue for this feature is: [#41758] - -[#41758]: https://github.com/rust-lang/rust/issues/41758 - ------------------------- diff --git a/src/etc/debugger_pretty_printers_common.py b/src/etc/debugger_pretty_printers_common.py index 5e3ff5246a..4a38d4be08 100644 --- a/src/etc/debugger_pretty_printers_common.py +++ b/src/etc/debugger_pretty_printers_common.py @@ -46,6 +46,7 @@ TYPE_KIND_CSTYLE_ENUM = 14 TYPE_KIND_PTR = 15 TYPE_KIND_FIXED_SIZE_VEC = 16 TYPE_KIND_REGULAR_UNION = 17 +TYPE_KIND_OS_STRING = 18 ENCODED_ENUM_PREFIX = "RUST$ENCODED$ENUM$" ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR" @@ -64,6 +65,9 @@ STD_VEC_FIELD_NAMES = [STD_VEC_FIELD_NAME_BUF, # std::String related constants STD_STRING_FIELD_NAMES = ["vec"] +# std::ffi::OsString related constants +OS_STRING_FIELD_NAMES = ["inner"] + class Type(object): """ @@ -162,6 +166,11 @@ class Type(object): self.__conforms_to_field_layout(STD_STRING_FIELD_NAMES)): return TYPE_KIND_STD_STRING + # OS STRING + if (unqualified_type_name == "OsString" and + self.__conforms_to_field_layout(OS_STRING_FIELD_NAMES)): + return TYPE_KIND_OS_STRING + # ENUM VARIANTS if fields[0].name == ENUM_DISR_FIELD_NAME: if field_count == 1: @@ -345,3 +354,8 @@ def extract_type_name(qualified_type_name): return qualified_type_name else: return qualified_type_name[index + 2:] + +try: + compat_str = unicode # Python 2 +except NameError: + compat_str = str diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py index afac8d6bba..822dc58140 100755 --- a/src/etc/gdb_rust_pretty_printing.py +++ b/src/etc/gdb_rust_pretty_printing.py @@ -78,7 +78,8 @@ class GdbValue(rustpp.Value): def as_integer(self): if self.gdb_val.type.code == gdb.TYPE_CODE_PTR: - return int(str(self.gdb_val), 0) + as_str = rustpp.compat_str(self.gdb_val).split()[0] + return int(as_str, 0) return int(self.gdb_val) def get_wrapped_value(self): @@ -99,8 +100,10 @@ def rust_pretty_printer_lookup_function(gdb_val): val = GdbValue(gdb_val) type_kind = val.type.get_type_kind() - if (type_kind == rustpp.TYPE_KIND_REGULAR_STRUCT or - type_kind == rustpp.TYPE_KIND_EMPTY): + if type_kind == rustpp.TYPE_KIND_EMPTY: + return RustEmptyPrinter(val) + + if type_kind == rustpp.TYPE_KIND_REGULAR_STRUCT: return RustStructPrinter(val, omit_first_field = False, omit_type_name = False, @@ -124,6 +127,9 @@ def rust_pretty_printer_lookup_function(gdb_val): if type_kind == rustpp.TYPE_KIND_STD_STRING: return RustStdStringPrinter(val) + if type_kind == rustpp.TYPE_KIND_OS_STRING: + return RustOsStringPrinter(val) + if type_kind == rustpp.TYPE_KIND_TUPLE: return RustStructPrinter(val, omit_first_field = False, @@ -170,6 +176,14 @@ def rust_pretty_printer_lookup_function(gdb_val): #=------------------------------------------------------------------------------ # Pretty Printer Classes #=------------------------------------------------------------------------------ +class RustEmptyPrinter(object): + def __init__(self, val): + self.__val = val + + def to_string(self): + return self.__val.type.get_unqualified_type_name() + + class RustStructPrinter(object): def __init__(self, val, omit_first_field, omit_type_name, is_tuple_like): self.__val = val @@ -186,10 +200,10 @@ class RustStructPrinter(object): cs = [] wrapped_value = self.__val.get_wrapped_value() - for field in self.__val.type.get_fields(): + for number, field in enumerate(self.__val.type.get_fields()): field_value = wrapped_value[field.name] if self.__is_tuple_like: - cs.append(("", field_value)) + cs.append((str(number), field_value)) else: cs.append((field.name, field_value)) @@ -268,6 +282,21 @@ class RustStdStringPrinter(object): length=length) +class RustOsStringPrinter(object): + def __init__(self, val): + self.__val = val + + def to_string(self): + buf = self.__val.get_child_at_index(0) + vec = buf.get_child_at_index(0) + if vec.type.get_unqualified_type_name() == "Wtf8Buf": + vec = vec.get_child_at_index(0) + + (length, data_ptr, cap) = rustpp.extract_length_ptr_and_cap_from_std_vec( + vec) + return '"%s"' % data_ptr.get_wrapped_value().string(length=length) + + class RustCStyleVariantPrinter(object): def __init__(self, val): assert val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_ENUM diff --git a/src/etc/natvis/libcollections.natvis b/src/etc/natvis/liballoc.natvis similarity index 81% rename from src/etc/natvis/libcollections.natvis rename to src/etc/natvis/liballoc.natvis index e7e93be986..1f6d17748a 100644 --- a/src/etc/natvis/libcollections.natvis +++ b/src/etc/natvis/liballoc.natvis @@ -1,6 +1,6 @@ - + {{ size={len} }} len @@ -11,7 +11,7 @@ - + {{ size={tail <= head ? head - tail : buf.cap - tail + head} }} tail <= head ? head - tail : buf.cap - tail + head @@ -30,18 +30,18 @@ - + {{ size={len} }} len - *(collections::linked_list::Node<$T1> **)&head - *(collections::linked_list::Node<$T1> **)&next + *(alloc::linked_list::Node<$T1> **)&head + *(alloc::linked_list::Node<$T1> **)&next element - + {*(char**)this,[vec.len]} *(char**)this,[vec.len] @@ -53,4 +53,4 @@ - \ No newline at end of file + diff --git a/src/etc/platform-intrinsics/arm.json b/src/etc/platform-intrinsics/arm.json index 39e49e239f..d008320713 100644 --- a/src/etc/platform-intrinsics/arm.json +++ b/src/etc/platform-intrinsics/arm.json @@ -1,7 +1,7 @@ { "platform": "arm_v", "intrinsic_prefix": "", - "llvm_prefix": "llvm.neon.v", + "llvm_prefix": "llvm.arm.neon.v", "number_info": { "signed": { "kind": "s", diff --git a/src/etc/rust-windbg.cmd b/src/etc/rust-windbg.cmd index 4cdd6b9860..b09b37c1db 100644 --- a/src/etc/rust-windbg.cmd +++ b/src/etc/rust-windbg.cmd @@ -15,4 +15,4 @@ for /f "delims=" %%i in ('rustc --print=sysroot') do set rustc_sysroot=%%i set rust_etc=%rustc_sysroot%\lib\rustlib\etc -windbg -c ".nvload %rust_etc%\libcore.natvis;.nvload %rust_etc%\libcollections.natvis;" %* \ No newline at end of file +windbg -c ".nvload %rust_etc%\liballoc.natvis; .nvload %rust_etc%\libcore.natvis;" %* diff --git a/src/grammar/lexer.l b/src/grammar/lexer.l index 77737c9949..91652bfdf2 100644 --- a/src/grammar/lexer.l +++ b/src/grammar/lexer.l @@ -126,7 +126,7 @@ while { return WHILE; } {ident} { return IDENT; } 0x[0-9a-fA-F_]+ { BEGIN(suffix); return LIT_INTEGER; } -0o[0-8_]+ { BEGIN(suffix); return LIT_INTEGER; } +0o[0-7_]+ { BEGIN(suffix); return LIT_INTEGER; } 0b[01_]+ { BEGIN(suffix); return LIT_INTEGER; } [0-9][0-9_]* { BEGIN(suffix); return LIT_INTEGER; } [0-9][0-9_]*\.(\.|[a-zA-Z]) { yyless(yyleng - 2); BEGIN(suffix); return LIT_INTEGER; } diff --git a/src/liballoc/Cargo.toml b/src/liballoc/Cargo.toml index 0889ca9fc8..686e5681d1 100644 --- a/src/liballoc/Cargo.toml +++ b/src/liballoc/Cargo.toml @@ -9,3 +9,12 @@ path = "lib.rs" [dependencies] core = { path = "../libcore" } +std_unicode = { path = "../libstd_unicode" } + +[[test]] +name = "collectionstests" +path = "../liballoc/tests/lib.rs" + +[[bench]] +name = "collectionsbenches" +path = "../liballoc/benches/lib.rs" diff --git a/src/liballoc/allocator.rs b/src/liballoc/allocator.rs new file mode 100644 index 0000000000..7c9c239560 --- /dev/null +++ b/src/liballoc/allocator.rs @@ -0,0 +1,1078 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![unstable(feature = "allocator_api", + reason = "the precise API and guarantees it provides may be tweaked \ + slightly, especially to possibly take into account the \ + types being stored to make room for a future \ + tracing garbage collector", + issue = "32838")] + +use core::cmp; +use core::fmt; +use core::mem; +use core::usize; +use core::ptr::{self, Unique}; + +/// Represents the combination of a starting address and +/// a total capacity of the returned block. +#[derive(Debug)] +pub struct Excess(pub *mut u8, pub usize); + +fn size_align() -> (usize, usize) { + (mem::size_of::(), mem::align_of::()) +} + +/// Layout of a block of memory. +/// +/// An instance of `Layout` describes a particular layout of memory. +/// You build a `Layout` up as an input to give to an allocator. +/// +/// All layouts have an associated non-negative size and a +/// power-of-two alignment. +/// +/// (Note however that layouts are *not* required to have positive +/// size, even though many allocators require that all memory +/// requeusts have positive size. A caller to the `Alloc::alloc` +/// method must either ensure that conditions like this are met, or +/// use specific allocators with looser requirements.) +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Layout { + // size of the requested block of memory, measured in bytes. + size: usize, + + // alignment of the requested block of memory, measured in bytes. + // we ensure that this is always a power-of-two, because API's + // like `posix_memalign` require it and it is a reasonable + // constraint to impose on Layout constructors. + // + // (However, we do not analogously require `align >= sizeof(void*)`, + // even though that is *also* a requirement of `posix_memalign`.) + align: usize, +} + + +// FIXME: audit default implementations for overflow errors, +// (potentially switching to overflowing_add and +// overflowing_mul as necessary). + +impl Layout { + /// Constructs a `Layout` from a given `size` and `align`, + /// or returns `None` if either of the following conditions + /// are not met: + /// + /// * `align` must be a power of two, + /// + /// * `size`, when rounded up to the nearest multiple of `align`, + /// must not overflow (i.e. the rounded value must be less than + /// `usize::MAX`). + #[inline] + pub fn from_size_align(size: usize, align: usize) -> Option { + if !align.is_power_of_two() { + return None; + } + + // (power-of-two implies align != 0.) + + // Rounded up size is: + // size_rounded_up = (size + align - 1) & !(align - 1); + // + // We know from above that align != 0. If adding (align - 1) + // does not overflow, then rounding up will be fine. + // + // Conversely, &-masking with !(align - 1) will subtract off + // only low-order-bits. Thus if overflow occurs with the sum, + // the &-mask cannot subtract enough to undo that overflow. + // + // Above implies that checking for summation overflow is both + // necessary and sufficient. + if size > usize::MAX - (align - 1) { + return None; + } + + unsafe { + Some(Layout::from_size_align_unchecked(size, align)) + } + } + + /// Creates a layout, bypassing all checks. + /// + /// # Unsafety + /// + /// This function is unsafe as it does not verify that `align` is a power of + /// two nor that `size` aligned to `align` fits within the address space. + #[inline] + pub unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Layout { + Layout { size: size, align: align } + } + + /// The minimum size in bytes for a memory block of this layout. + #[inline] + pub fn size(&self) -> usize { self.size } + + /// The minimum byte alignment for a memory block of this layout. + #[inline] + pub fn align(&self) -> usize { self.align } + + /// Constructs a `Layout` suitable for holding a value of type `T`. + pub fn new() -> Self { + let (size, align) = size_align::(); + Layout::from_size_align(size, align).unwrap() + } + + /// Produces layout describing a record that could be used to + /// allocate backing structure for `T` (which could be a trait + /// or other unsized type like a slice). + pub fn for_value(t: &T) -> Self { + let (size, align) = (mem::size_of_val(t), mem::align_of_val(t)); + Layout::from_size_align(size, align).unwrap() + } + + /// Creates a layout describing the record that can hold a value + /// of the same layout as `self`, but that also is aligned to + /// alignment `align` (measured in bytes). + /// + /// If `self` already meets the prescribed alignment, then returns + /// `self`. + /// + /// Note that this method does not add any padding to the overall + /// size, regardless of whether the returned layout has a different + /// alignment. In other words, if `K` has size 16, `K.align_to(32)` + /// will *still* have size 16. + /// + /// # Panics + /// + /// Panics if the combination of `self.size` and the given `align` + /// violates the conditions listed in `from_size_align`. + #[inline] + pub fn align_to(&self, align: usize) -> Self { + Layout::from_size_align(self.size, cmp::max(self.align, align)).unwrap() + } + + /// Returns the amount of padding we must insert after `self` + /// to ensure that the following address will satisfy `align` + /// (measured in bytes). + /// + /// E.g. if `self.size` is 9, then `self.padding_needed_for(4)` + /// returns 3, because that is the minimum number of bytes of + /// padding required to get a 4-aligned address (assuming that the + /// corresponding memory block starts at a 4-aligned address). + /// + /// The return value of this function has no meaning if `align` is + /// not a power-of-two. + /// + /// Note that the utility of the returned value requires `align` + /// to be less than or equal to the alignment of the starting + /// address for the whole allocated block of memory. One way to + /// satisfy this constraint is to ensure `align <= self.align`. + #[inline] + pub fn padding_needed_for(&self, align: usize) -> usize { + let len = self.size(); + + // Rounded up value is: + // len_rounded_up = (len + align - 1) & !(align - 1); + // and then we return the padding difference: `len_rounded_up - len`. + // + // We use modular arithmetic throughout: + // + // 1. align is guaranteed to be > 0, so align - 1 is always + // valid. + // + // 2. `len + align - 1` can overflow by at most `align - 1`, + // so the &-mask wth `!(align - 1)` will ensure that in the + // case of overflow, `len_rounded_up` will itself be 0. + // Thus the returned padding, when added to `len`, yields 0, + // which trivially satisfies the alignment `align`. + // + // (Of course, attempts to allocate blocks of memory whose + // size and padding overflow in the above manner should cause + // the allocator to yield an error anyway.) + + let len_rounded_up = len.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1); + return len_rounded_up.wrapping_sub(len); + } + + /// Creates a layout describing the record for `n` instances of + /// `self`, with a suitable amount of padding between each to + /// ensure that each instance is given its requested size and + /// alignment. On success, returns `(k, offs)` where `k` is the + /// layout of the array and `offs` is the distance between the start + /// of each element in the array. + /// + /// On arithmetic overflow, returns `None`. + #[inline] + pub fn repeat(&self, n: usize) -> Option<(Self, usize)> { + let padded_size = match self.size.checked_add(self.padding_needed_for(self.align)) { + None => return None, + Some(padded_size) => padded_size, + }; + let alloc_size = match padded_size.checked_mul(n) { + None => return None, + Some(alloc_size) => alloc_size, + }; + + // We can assume that `self.align` is a power-of-two. + // Furthermore, `alloc_size` has alreayd been rounded up + // to a multiple of `self.align`; therefore, the call + // to `Layout::from_size_align` below should never panic. + Some((Layout::from_size_align(alloc_size, self.align).unwrap(), padded_size)) + } + + /// Creates a layout describing the record for `self` followed by + /// `next`, including any necessary padding to ensure that `next` + /// will be properly aligned. Note that the result layout will + /// satisfy the alignment properties of both `self` and `next`. + /// + /// Returns `Some((k, offset))`, where `k` is layout of the concatenated + /// record and `offset` is the relative location, in bytes, of the + /// start of the `next` embedded witnin the concatenated record + /// (assuming that the record itself starts at offset 0). + /// + /// On arithmetic overflow, returns `None`. + pub fn extend(&self, next: Self) -> Option<(Self, usize)> { + let new_align = cmp::max(self.align, next.align); + let realigned = match Layout::from_size_align(self.size, new_align) { + None => return None, + Some(l) => l, + }; + + let pad = realigned.padding_needed_for(next.align); + + let offset = match self.size.checked_add(pad) { + None => return None, + Some(offset) => offset, + }; + let new_size = match offset.checked_add(next.size) { + None => return None, + Some(new_size) => new_size, + }; + + let layout = match Layout::from_size_align(new_size, new_align) { + None => return None, + Some(l) => l, + }; + Some((layout, offset)) + } + + /// Creates a layout describing the record for `n` instances of + /// `self`, with no padding between each instance. + /// + /// Note that, unlike `repeat`, `repeat_packed` does not guarantee + /// that the repeated instances of `self` will be properly + /// aligned, even if a given instance of `self` is properly + /// aligned. In other words, if the layout returned by + /// `repeat_packed` is used to allocate an array, it is not + /// guaranteed that all elements in the array will be properly + /// aligned. + /// + /// On arithmetic overflow, returns `None`. + pub fn repeat_packed(&self, n: usize) -> Option { + let size = match self.size().checked_mul(n) { + None => return None, + Some(scaled) => scaled, + }; + + Layout::from_size_align(size, self.align) + } + + /// Creates a layout describing the record for `self` followed by + /// `next` with no additional padding between the two. Since no + /// padding is inserted, the alignment of `next` is irrelevant, + /// and is not incoporated *at all* into the resulting layout. + /// + /// Returns `(k, offset)`, where `k` is layout of the concatenated + /// record and `offset` is the relative location, in bytes, of the + /// start of the `next` embedded witnin the concatenated record + /// (assuming that the record itself starts at offset 0). + /// + /// (The `offset` is always the same as `self.size()`; we use this + /// signature out of convenience in matching the signature of + /// `extend`.) + /// + /// On arithmetic overflow, returns `None`. + pub fn extend_packed(&self, next: Self) -> Option<(Self, usize)> { + let new_size = match self.size().checked_add(next.size()) { + None => return None, + Some(new_size) => new_size, + }; + let layout = match Layout::from_size_align(new_size, self.align) { + None => return None, + Some(l) => l, + }; + Some((layout, self.size())) + } + + /// Creates a layout describing the record for a `[T; n]`. + /// + /// On arithmetic overflow, returns `None`. + pub fn array(n: usize) -> Option { + Layout::new::() + .repeat(n) + .map(|(k, offs)| { + debug_assert!(offs == mem::size_of::()); + k + }) + } +} + +/// The `AllocErr` error specifies whether an allocation failure is +/// specifically due to resource exhaustion or if it is due to +/// something wrong when combining the given input arguments with this +/// allocator. +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum AllocErr { + /// Error due to hitting some resource limit or otherwise running + /// out of memory. This condition strongly implies that *some* + /// series of deallocations would allow a subsequent reissuing of + /// the original allocation request to succeed. + Exhausted { request: Layout }, + + /// Error due to allocator being fundamentally incapable of + /// satisfying the original request. This condition implies that + /// such an allocation request will never succeed on the given + /// allocator, regardless of environment, memory pressure, or + /// other contextual conditions. + /// + /// For example, an allocator that does not support requests for + /// large memory blocks might return this error variant. + Unsupported { details: &'static str }, +} + +impl AllocErr { + pub fn invalid_input(details: &'static str) -> Self { + AllocErr::Unsupported { details: details } + } + pub fn is_memory_exhausted(&self) -> bool { + if let AllocErr::Exhausted { .. } = *self { true } else { false } + } + pub fn is_request_unsupported(&self) -> bool { + if let AllocErr::Unsupported { .. } = *self { true } else { false } + } + pub fn description(&self) -> &str { + match *self { + AllocErr::Exhausted { .. } => "allocator memory exhausted", + AllocErr::Unsupported { .. } => "unsupported allocator request", + } + } +} + +// (we need this for downstream impl of trait Error) +impl fmt::Display for AllocErr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.description()) + } +} + +/// The `CannotReallocInPlace` error is used when `grow_in_place` or +/// `shrink_in_place` were unable to reuse the given memory block for +/// a requested layout. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct CannotReallocInPlace; + +impl CannotReallocInPlace { + pub fn description(&self) -> &str { + "cannot reallocate allocator's memory in place" + } +} + +// (we need this for downstream impl of trait Error) +impl fmt::Display for CannotReallocInPlace { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.description()) + } +} + +/// An implementation of `Alloc` can allocate, reallocate, and +/// deallocate arbitrary blocks of data described via `Layout`. +/// +/// Some of the methods require that a memory block be *currently +/// allocated* via an allocator. This means that: +/// +/// * the starting address for that memory block was previously +/// returned by a previous call to an allocation method (`alloc`, +/// `alloc_zeroed`, `alloc_excess`, `alloc_one`, `alloc_array`) or +/// reallocation method (`realloc`, `realloc_excess`, or +/// `realloc_array`), and +/// +/// * the memory block has not been subsequently deallocated, where +/// blocks are deallocated either by being passed to a deallocation +/// method (`dealloc`, `dealloc_one`, `dealloc_array`) or by being +/// passed to a reallocation method (see above) that returns `Ok`. +/// +/// A note regarding zero-sized types and zero-sized layouts: many +/// methods in the `Alloc` trait state that allocation requests +/// must be non-zero size, or else undefined behavior can result. +/// +/// * However, some higher-level allocation methods (`alloc_one`, +/// `alloc_array`) are well-defined on zero-sized types and can +/// optionally support them: it is left up to the implementor +/// whether to return `Err`, or to return `Ok` with some pointer. +/// +/// * If an `Alloc` implementation chooses to return `Ok` in this +/// case (i.e. the pointer denotes a zero-sized inaccessible block) +/// then that returned pointer must be considered "currently +/// allocated". On such an allocator, *all* methods that take +/// currently-allocated pointers as inputs must accept these +/// zero-sized pointers, *without* causing undefined behavior. +/// +/// * In other words, if a zero-sized pointer can flow out of an +/// allocator, then that allocator must likewise accept that pointer +/// flowing back into its deallocation and reallocation methods. +/// +/// Some of the methods require that a layout *fit* a memory block. +/// What it means for a layout to "fit" a memory block means (or +/// equivalently, for a memory block to "fit" a layout) is that the +/// following two conditions must hold: +/// +/// 1. The block's starting address must be aligned to `layout.align()`. +/// +/// 2. The block's size must fall in the range `[use_min, use_max]`, where: +/// +/// * `use_min` is `self.usable_size(layout).0`, and +/// +/// * `use_max` is the capacity that was (or would have been) +/// returned when (if) the block was allocated via a call to +/// `alloc_excess` or `realloc_excess`. +/// +/// Note that: +/// +/// * the size of the layout most recently used to allocate the block +/// is guaranteed to be in the range `[use_min, use_max]`, and +/// +/// * a lower-bound on `use_max` can be safely approximated by a call to +/// `usable_size`. +/// +/// * if a layout `k` fits a memory block (denoted by `ptr`) +/// currently allocated via an allocator `a`, then it is legal to +/// use that layout to deallocate it, i.e. `a.dealloc(ptr, k);`. +/// +/// # Unsafety +/// +/// The `Alloc` trait is an `unsafe` trait for a number of reasons, and +/// implementors must ensure that they adhere to these contracts: +/// +/// * Pointers returned from allocation functions must point to valid memory and +/// retain their validity until at least the instance of `Alloc` is dropped +/// itself. +/// +/// * Implementations of `Alloc` are not currently memory safe if they unwind. +/// This restriction may be lifted in the future, but currently an panic from +/// any of these functions may lead to memory unsafety. +/// +/// * `Layout` queries and calculations in general must be correct. Callers of +/// this trait are allowed to rely on the contracts defined on each method, +/// and implementors must ensure such contracts remain true. +/// +/// Note that this list may get tweaked over time as clarifications are made in +/// the future. Additionally global allocators may gain unique requirements for +/// how to safely implement one in the future as well. +pub unsafe trait Alloc { + + // (Note: existing allocators have unspecified but well-defined + // behavior in response to a zero size allocation request ; + // e.g. in C, `malloc` of 0 will either return a null pointer or a + // unique pointer, but will not have arbitrary undefined + // behavior. Rust should consider revising the alloc::heap crate + // to reflect this reality.) + + /// Returns a pointer meeting the size and alignment guarantees of + /// `layout`. + /// + /// If this method returns an `Ok(addr)`, then the `addr` returned + /// will be non-null address pointing to a block of storage + /// suitable for holding an instance of `layout`. + /// + /// The returned block of storage may or may not have its contents + /// initialized. (Extension subtraits might restrict this + /// behavior, e.g. to ensure initialization to particular sets of + /// bit patterns.) + /// + /// # Unsafety + /// + /// This function is unsafe because undefined behavior can result + /// if the caller does not ensure that `layout` has non-zero size. + /// + /// (Extension subtraits might provide more specific bounds on + /// behavior, e.g. guarantee a sentinel address or a null pointer + /// in response to a zero-size allocation request.) + /// + /// # Errors + /// + /// Returning `Err` indicates that either memory is exhausted or + /// `layout` does not meet allocator's size or alignment + /// constraints. + /// + /// Implementations are encouraged to return `Err` on memory + /// exhaustion rather than panicking or aborting, but this is not + /// a strict requirement. (Specifically: it is *legal* to + /// implement this trait atop an underlying native allocation + /// library that aborts on memory exhaustion.) + /// + /// Clients wishing to abort computation in response to an + /// allocation error are encouraged to call the allocator's `oom` + /// method, rather than directly invoking `panic!` or similar. + unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr>; + + /// Deallocate the memory referenced by `ptr`. + /// + /// # Unsafety + /// + /// This function is unsafe because undefined behavior can result + /// if the caller does not ensure all of the following: + /// + /// * `ptr` must denote a block of memory currently allocated via + /// this allocator, + /// + /// * `layout` must *fit* that block of memory, + /// + /// * In addition to fitting the block of memory `layout`, the + /// alignment of the `layout` must match the alignment used + /// to allocate that block of memory. + unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout); + + /// Allocator-specific method for signalling an out-of-memory + /// condition. + /// + /// `oom` aborts the thread or process, optionally performing + /// cleanup or logging diagnostic information before panicking or + /// aborting. + /// + /// `oom` is meant to be used by clients unable to cope with an + /// unsatisfied allocation request (signaled by an error such as + /// `AllocErr::Exhausted`), and wish to abandon computation rather + /// than attempt to recover locally. Such clients should pass the + /// signalling error value back into `oom`, where the allocator + /// may incorporate that error value into its diagnostic report + /// before aborting. + /// + /// Implementations of the `oom` method are discouraged from + /// infinitely regressing in nested calls to `oom`. In + /// practice this means implementors should eschew allocating, + /// especially from `self` (directly or indirectly). + /// + /// Implementions of the allocation and reallocation methods + /// (e.g. `alloc`, `alloc_one`, `realloc`) are discouraged from + /// panicking (or aborting) in the event of memory exhaustion; + /// instead they should return an appropriate error from the + /// invoked method, and let the client decide whether to invoke + /// this `oom` method in response. + fn oom(&mut self, _: AllocErr) -> ! { + unsafe { ::core::intrinsics::abort() } + } + + // == ALLOCATOR-SPECIFIC QUANTITIES AND LIMITS == + // usable_size + + /// Returns bounds on the guaranteed usable size of a successful + /// allocation created with the specified `layout`. + /// + /// In particular, if one has a memory block allocated via a given + /// allocator `a` and layout `k` where `a.usable_size(k)` returns + /// `(l, u)`, then one can pass that block to `a.dealloc()` with a + /// layout in the size range [l, u]. + /// + /// (All implementors of `usable_size` must ensure that + /// `l <= k.size() <= u`) + /// + /// Both the lower- and upper-bounds (`l` and `u` respectively) + /// are provided, because an allocator based on size classes could + /// misbehave if one attempts to deallocate a block without + /// providing a correct value for its size (i.e., one within the + /// range `[l, u]`). + /// + /// Clients who wish to make use of excess capacity are encouraged + /// to use the `alloc_excess` and `realloc_excess` instead, as + /// this method is constrained to report conservative values that + /// serve as valid bounds for *all possible* allocation method + /// calls. + /// + /// However, for clients that do not wish to track the capacity + /// returned by `alloc_excess` locally, this method is likely to + /// produce useful results. + #[inline] + fn usable_size(&self, layout: &Layout) -> (usize, usize) { + (layout.size(), layout.size()) + } + + // == METHODS FOR MEMORY REUSE == + // realloc. alloc_excess, realloc_excess + + /// Returns a pointer suitable for holding data described by + /// `new_layout`, meeting its size and alignment guarantees. To + /// accomplish this, this may extend or shrink the allocation + /// referenced by `ptr` to fit `new_layout`. + /// + /// If this returns `Ok`, then ownership of the memory block + /// referenced by `ptr` has been transferred to this + /// allocator. The memory may or may not have been freed, and + /// should be considered unusable (unless of course it was + /// transferred back to the caller again via the return value of + /// this method). + /// + /// If this method returns `Err`, then ownership of the memory + /// block has not been transferred to this allocator, and the + /// contents of the memory block are unaltered. + /// + /// For best results, `new_layout` should not impose a different + /// alignment constraint than `layout`. (In other words, + /// `new_layout.align()` should equal `layout.align()`.) However, + /// behavior is well-defined (though underspecified) when this + /// constraint is violated; further discussion below. + /// + /// # Unsafety + /// + /// This function is unsafe because undefined behavior can result + /// if the caller does not ensure all of the following: + /// + /// * `ptr` must be currently allocated via this allocator, + /// + /// * `layout` must *fit* the `ptr` (see above). (The `new_layout` + /// argument need not fit it.) + /// + /// * `new_layout` must have size greater than zero. + /// + /// * the alignment of `new_layout` is non-zero. + /// + /// (Extension subtraits might provide more specific bounds on + /// behavior, e.g. guarantee a sentinel address or a null pointer + /// in response to a zero-size allocation request.) + /// + /// # Errors + /// + /// Returns `Err` only if `new_layout` does not match the + /// alignment of `layout`, or does not meet the allocator's size + /// and alignment constraints of the allocator, or if reallocation + /// otherwise fails. + /// + /// (Note the previous sentence did not say "if and only if" -- in + /// particular, an implementation of this method *can* return `Ok` + /// if `new_layout.align() != old_layout.align()`; or it can + /// return `Err` in that scenario, depending on whether this + /// allocator can dynamically adjust the alignment constraint for + /// the block.) + /// + /// Implementations are encouraged to return `Err` on memory + /// exhaustion rather than panicking or aborting, but this is not + /// a strict requirement. (Specifically: it is *legal* to + /// implement this trait atop an underlying native allocation + /// library that aborts on memory exhaustion.) + /// + /// Clients wishing to abort computation in response to an + /// reallocation error are encouraged to call the allocator's `oom` + /// method, rather than directly invoking `panic!` or similar. + unsafe fn realloc(&mut self, + ptr: *mut u8, + layout: Layout, + new_layout: Layout) -> Result<*mut u8, AllocErr> { + let new_size = new_layout.size(); + let old_size = layout.size(); + let aligns_match = layout.align == new_layout.align; + + if new_size >= old_size && aligns_match { + if let Ok(()) = self.grow_in_place(ptr, layout.clone(), new_layout.clone()) { + return Ok(ptr); + } + } else if new_size < old_size && aligns_match { + if let Ok(()) = self.shrink_in_place(ptr, layout.clone(), new_layout.clone()) { + return Ok(ptr); + } + } + + // otherwise, fall back on alloc + copy + dealloc. + let result = self.alloc(new_layout); + if let Ok(new_ptr) = result { + ptr::copy_nonoverlapping(ptr as *const u8, new_ptr, cmp::min(old_size, new_size)); + self.dealloc(ptr, layout); + } + result + } + + /// Behaves like `alloc`, but also ensures that the contents + /// are set to zero before being returned. + /// + /// # Unsafety + /// + /// This function is unsafe for the same reasons that `alloc` is. + /// + /// # Errors + /// + /// Returning `Err` indicates that either memory is exhausted or + /// `layout` does not meet allocator's size or alignment + /// constraints, just as in `alloc`. + /// + /// Clients wishing to abort computation in response to an + /// allocation error are encouraged to call the allocator's `oom` + /// method, rather than directly invoking `panic!` or similar. + unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { + let size = layout.size(); + let p = self.alloc(layout); + if let Ok(p) = p { + ptr::write_bytes(p, 0, size); + } + p + } + + /// Behaves like `alloc`, but also returns the whole size of + /// the returned block. For some `layout` inputs, like arrays, this + /// may include extra storage usable for additional data. + /// + /// # Unsafety + /// + /// This function is unsafe for the same reasons that `alloc` is. + /// + /// # Errors + /// + /// Returning `Err` indicates that either memory is exhausted or + /// `layout` does not meet allocator's size or alignment + /// constraints, just as in `alloc`. + /// + /// Clients wishing to abort computation in response to an + /// allocation error are encouraged to call the allocator's `oom` + /// method, rather than directly invoking `panic!` or similar. + unsafe fn alloc_excess(&mut self, layout: Layout) -> Result { + let usable_size = self.usable_size(&layout); + self.alloc(layout).map(|p| Excess(p, usable_size.1)) + } + + /// Behaves like `realloc`, but also returns the whole size of + /// the returned block. For some `layout` inputs, like arrays, this + /// may include extra storage usable for additional data. + /// + /// # Unsafety + /// + /// This function is unsafe for the same reasons that `realloc` is. + /// + /// # Errors + /// + /// Returning `Err` indicates that either memory is exhausted or + /// `layout` does not meet allocator's size or alignment + /// constraints, just as in `realloc`. + /// + /// Clients wishing to abort computation in response to an + /// reallocation error are encouraged to call the allocator's `oom` + /// method, rather than directly invoking `panic!` or similar. + unsafe fn realloc_excess(&mut self, + ptr: *mut u8, + layout: Layout, + new_layout: Layout) -> Result { + let usable_size = self.usable_size(&new_layout); + self.realloc(ptr, layout, new_layout) + .map(|p| Excess(p, usable_size.1)) + } + + /// Attempts to extend the allocation referenced by `ptr` to fit `new_layout`. + /// + /// If this returns `Ok`, then the allocator has asserted that the + /// memory block referenced by `ptr` now fits `new_layout`, and thus can + /// be used to carry data of that layout. (The allocator is allowed to + /// expend effort to accomplish this, such as extending the memory block to + /// include successor blocks, or virtual memory tricks.) + /// + /// Regardless of what this method returns, ownership of the + /// memory block referenced by `ptr` has not been transferred, and + /// the contents of the memory block are unaltered. + /// + /// # Unsafety + /// + /// This function is unsafe because undefined behavior can result + /// if the caller does not ensure all of the following: + /// + /// * `ptr` must be currently allocated via this allocator, + /// + /// * `layout` must *fit* the `ptr` (see above); note the + /// `new_layout` argument need not fit it, + /// + /// * `new_layout.size()` must not be less than `layout.size()`, + /// + /// * `new_layout.align()` must equal `layout.align()`. + /// + /// # Errors + /// + /// Returns `Err(CannotReallocInPlace)` when the allocator is + /// unable to assert that the memory block referenced by `ptr` + /// could fit `layout`. + /// + /// Note that one cannot pass `CannotReallocInPlace` to the `oom` + /// method; clients are expected either to be able to recover from + /// `grow_in_place` failures without aborting, or to fall back on + /// another reallocation method before resorting to an abort. + unsafe fn grow_in_place(&mut self, + ptr: *mut u8, + layout: Layout, + new_layout: Layout) -> Result<(), CannotReallocInPlace> { + let _ = ptr; // this default implementation doesn't care about the actual address. + debug_assert!(new_layout.size >= layout.size); + debug_assert!(new_layout.align == layout.align); + let (_l, u) = self.usable_size(&layout); + // _l <= layout.size() [guaranteed by usable_size()] + // layout.size() <= new_layout.size() [required by this method] + if new_layout.size <= u { + return Ok(()); + } else { + return Err(CannotReallocInPlace); + } + } + + /// Attempts to shrink the allocation referenced by `ptr` to fit `new_layout`. + /// + /// If this returns `Ok`, then the allocator has asserted that the + /// memory block referenced by `ptr` now fits `new_layout`, and + /// thus can only be used to carry data of that smaller + /// layout. (The allocator is allowed to take advantage of this, + /// carving off portions of the block for reuse elsewhere.) The + /// truncated contents of the block within the smaller layout are + /// unaltered, and ownership of block has not been transferred. + /// + /// If this returns `Err`, then the memory block is considered to + /// still represent the original (larger) `layout`. None of the + /// block has been carved off for reuse elsewhere, ownership of + /// the memory block has not been transferred, and the contents of + /// the memory block are unaltered. + /// + /// # Unsafety + /// + /// This function is unsafe because undefined behavior can result + /// if the caller does not ensure all of the following: + /// + /// * `ptr` must be currently allocated via this allocator, + /// + /// * `layout` must *fit* the `ptr` (see above); note the + /// `new_layout` argument need not fit it, + /// + /// * `new_layout.size()` must not be greater than `layout.size()` + /// (and must be greater than zero), + /// + /// * `new_layout.align()` must equal `layout.align()`. + /// + /// # Errors + /// + /// Returns `Err(CannotReallocInPlace)` when the allocator is + /// unable to assert that the memory block referenced by `ptr` + /// could fit `layout`. + /// + /// Note that one cannot pass `CannotReallocInPlace` to the `oom` + /// method; clients are expected either to be able to recover from + /// `shrink_in_place` failures without aborting, or to fall back + /// on another reallocation method before resorting to an abort. + unsafe fn shrink_in_place(&mut self, + ptr: *mut u8, + layout: Layout, + new_layout: Layout) -> Result<(), CannotReallocInPlace> { + let _ = ptr; // this default implementation doesn't care about the actual address. + debug_assert!(new_layout.size <= layout.size); + debug_assert!(new_layout.align == layout.align); + let (l, _u) = self.usable_size(&layout); + // layout.size() <= _u [guaranteed by usable_size()] + // new_layout.size() <= layout.size() [required by this method] + if l <= new_layout.size { + return Ok(()); + } else { + return Err(CannotReallocInPlace); + } + } + + + // == COMMON USAGE PATTERNS == + // alloc_one, dealloc_one, alloc_array, realloc_array. dealloc_array + + /// Allocates a block suitable for holding an instance of `T`. + /// + /// Captures a common usage pattern for allocators. + /// + /// The returned block is suitable for passing to the + /// `alloc`/`realloc` methods of this allocator. + /// + /// Note to implementors: If this returns `Ok(ptr)`, then `ptr` + /// must be considered "currently allocated" and must be + /// acceptable input to methods such as `realloc` or `dealloc`, + /// *even if* `T` is a zero-sized type. In other words, if your + /// `Alloc` implementation overrides this method in a manner + /// that can return a zero-sized `ptr`, then all reallocation and + /// deallocation methods need to be similarly overridden to accept + /// such values as input. + /// + /// # Errors + /// + /// Returning `Err` indicates that either memory is exhausted or + /// `T` does not meet allocator's size or alignment constraints. + /// + /// For zero-sized `T`, may return either of `Ok` or `Err`, but + /// will *not* yield undefined behavior. + /// + /// Clients wishing to abort computation in response to an + /// allocation error are encouraged to call the allocator's `oom` + /// method, rather than directly invoking `panic!` or similar. + fn alloc_one(&mut self) -> Result, AllocErr> + where Self: Sized + { + let k = Layout::new::(); + if k.size() > 0 { + unsafe { self.alloc(k).map(|p| Unique::new(p as *mut T)) } + } else { + Err(AllocErr::invalid_input("zero-sized type invalid for alloc_one")) + } + } + + /// Deallocates a block suitable for holding an instance of `T`. + /// + /// The given block must have been produced by this allocator, + /// and must be suitable for storing a `T` (in terms of alignment + /// as well as minimum and maximum size); otherwise yields + /// undefined behavior. + /// + /// Captures a common usage pattern for allocators. + /// + /// # Unsafety + /// + /// This function is unsafe because undefined behavior can result + /// if the caller does not ensure both: + /// + /// * `ptr` must denote a block of memory currently allocated via this allocator + /// + /// * the layout of `T` must *fit* that block of memory. + unsafe fn dealloc_one(&mut self, ptr: Unique) + where Self: Sized + { + let raw_ptr = ptr.as_ptr() as *mut u8; + let k = Layout::new::(); + if k.size() > 0 { + self.dealloc(raw_ptr, k); + } + } + + /// Allocates a block suitable for holding `n` instances of `T`. + /// + /// Captures a common usage pattern for allocators. + /// + /// The returned block is suitable for passing to the + /// `alloc`/`realloc` methods of this allocator. + /// + /// Note to implementors: If this returns `Ok(ptr)`, then `ptr` + /// must be considered "currently allocated" and must be + /// acceptable input to methods such as `realloc` or `dealloc`, + /// *even if* `T` is a zero-sized type. In other words, if your + /// `Alloc` implementation overrides this method in a manner + /// that can return a zero-sized `ptr`, then all reallocation and + /// deallocation methods need to be similarly overridden to accept + /// such values as input. + /// + /// # Errors + /// + /// Returning `Err` indicates that either memory is exhausted or + /// `[T; n]` does not meet allocator's size or alignment + /// constraints. + /// + /// For zero-sized `T` or `n == 0`, may return either of `Ok` or + /// `Err`, but will *not* yield undefined behavior. + /// + /// Always returns `Err` on arithmetic overflow. + /// + /// Clients wishing to abort computation in response to an + /// allocation error are encouraged to call the allocator's `oom` + /// method, rather than directly invoking `panic!` or similar. + fn alloc_array(&mut self, n: usize) -> Result, AllocErr> + where Self: Sized + { + match Layout::array::(n) { + Some(ref layout) if layout.size() > 0 => { + unsafe { + self.alloc(layout.clone()) + .map(|p| { + Unique::new(p as *mut T) + }) + } + } + _ => Err(AllocErr::invalid_input("invalid layout for alloc_array")), + } + } + + /// Reallocates a block previously suitable for holding `n_old` + /// instances of `T`, returning a block suitable for holding + /// `n_new` instances of `T`. + /// + /// Captures a common usage pattern for allocators. + /// + /// The returned block is suitable for passing to the + /// `alloc`/`realloc` methods of this allocator. + /// + /// # Unsafety + /// + /// This function is unsafe because undefined behavior can result + /// if the caller does not ensure all of the following: + /// + /// * `ptr` must be currently allocated via this allocator, + /// + /// * the layout of `[T; n_old]` must *fit* that block of memory. + /// + /// # Errors + /// + /// Returning `Err` indicates that either memory is exhausted or + /// `[T; n_new]` does not meet allocator's size or alignment + /// constraints. + /// + /// For zero-sized `T` or `n_new == 0`, may return either of `Ok` or + /// `Err`, but will *not* yield undefined behavior. + /// + /// Always returns `Err` on arithmetic overflow. + /// + /// Clients wishing to abort computation in response to an + /// reallocation error are encouraged to call the allocator's `oom` + /// method, rather than directly invoking `panic!` or similar. + unsafe fn realloc_array(&mut self, + ptr: Unique, + n_old: usize, + n_new: usize) -> Result, AllocErr> + where Self: Sized + { + match (Layout::array::(n_old), Layout::array::(n_new), ptr.as_ptr()) { + (Some(ref k_old), Some(ref k_new), ptr) if k_old.size() > 0 && k_new.size() > 0 => { + self.realloc(ptr as *mut u8, k_old.clone(), k_new.clone()) + .map(|p|Unique::new(p as *mut T)) + } + _ => { + Err(AllocErr::invalid_input("invalid layout for realloc_array")) + } + } + } + + /// Deallocates a block suitable for holding `n` instances of `T`. + /// + /// Captures a common usage pattern for allocators. + /// + /// # Unsafety + /// + /// This function is unsafe because undefined behavior can result + /// if the caller does not ensure both: + /// + /// * `ptr` must denote a block of memory currently allocated via this allocator + /// + /// * the layout of `[T; n]` must *fit* that block of memory. + /// + /// # Errors + /// + /// Returning `Err` indicates that either `[T; n]` or the given + /// memory block does not meet allocator's size or alignment + /// constraints. + /// + /// Always returns `Err` on arithmetic overflow. + unsafe fn dealloc_array(&mut self, ptr: Unique, n: usize) -> Result<(), AllocErr> + where Self: Sized + { + let raw_ptr = ptr.as_ptr() as *mut u8; + match Layout::array::(n) { + Some(ref k) if k.size() > 0 => { + Ok(self.dealloc(raw_ptr, k.clone())) + } + _ => { + Err(AllocErr::invalid_input("invalid layout for dealloc_array")) + } + } + } +} diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 5faf4dccca..d9edf50b9c 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -23,7 +23,6 @@ use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst}; use core::borrow; use core::fmt; use core::cmp::Ordering; -use core::mem::{align_of_val, size_of_val}; use core::intrinsics::abort; use core::mem; use core::mem::uninitialized; @@ -34,7 +33,8 @@ use core::marker::Unsize; use core::hash::{Hash, Hasher}; use core::{isize, usize}; use core::convert::From; -use heap::deallocate; + +use heap::{Heap, Alloc, Layout}; /// A soft limit on the amount of references that may be made to an `Arc`. /// @@ -42,7 +42,8 @@ use heap::deallocate; /// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references. const MAX_REFCOUNT: usize = (isize::MAX) as usize; -/// A thread-safe reference-counting pointer. +/// A thread-safe reference-counting pointer. 'Arc' stands for 'Atomically +/// Reference Counted'. /// /// The type `Arc` provides shared ownership of a value of type `T`, /// allocated in the heap. Invoking [`clone`][clone] on `Arc` produces @@ -502,7 +503,7 @@ impl Arc { if self.inner().weak.fetch_sub(1, Release) == 1 { atomic::fence(Acquire); - deallocate(ptr as *mut u8, size_of_val(&*ptr), align_of_val(&*ptr)) + Heap.dealloc(ptr as *mut u8, Layout::for_value(&*ptr)) } } @@ -1006,7 +1007,9 @@ impl Drop for Weak { // ref, which can only happen after the lock is released. if self.inner().weak.fetch_sub(1, Release) == 1 { atomic::fence(Acquire); - unsafe { deallocate(ptr as *mut u8, size_of_val(&*ptr), align_of_val(&*ptr)) } + unsafe { + Heap.dealloc(ptr as *mut u8, Layout::for_value(&*ptr)) + } } } } @@ -1221,11 +1224,12 @@ mod tests { use std::sync::atomic; use std::sync::atomic::Ordering::{Acquire, SeqCst}; use std::thread; - use std::vec::Vec; - use super::{Arc, Weak}; use std::sync::Mutex; use std::convert::From; + use super::{Arc, Weak}; + use vec::Vec; + struct Canary(*mut atomic::AtomicUsize); impl Drop for Canary { diff --git a/src/libcollections/benches/btree/map.rs b/src/liballoc/benches/btree/map.rs similarity index 100% rename from src/libcollections/benches/btree/map.rs rename to src/liballoc/benches/btree/map.rs diff --git a/src/libcollections/benches/btree/mod.rs b/src/liballoc/benches/btree/mod.rs similarity index 100% rename from src/libcollections/benches/btree/mod.rs rename to src/liballoc/benches/btree/mod.rs diff --git a/src/libcollections/benches/lib.rs b/src/liballoc/benches/lib.rs similarity index 96% rename from src/libcollections/benches/lib.rs rename to src/liballoc/benches/lib.rs index 958020d0b0..174628ccd0 100644 --- a/src/libcollections/benches/lib.rs +++ b/src/liballoc/benches/lib.rs @@ -14,9 +14,9 @@ #![feature(rand)] #![feature(repr_simd)] #![feature(slice_rotate)] -#![feature(sort_unstable)] #![feature(test)] +extern crate rand; extern crate test; mod btree; diff --git a/src/libcollections/benches/linked_list.rs b/src/liballoc/benches/linked_list.rs similarity index 100% rename from src/libcollections/benches/linked_list.rs rename to src/liballoc/benches/linked_list.rs diff --git a/src/libcollections/benches/slice.rs b/src/liballoc/benches/slice.rs similarity index 86% rename from src/libcollections/benches/slice.rs rename to src/liballoc/benches/slice.rs index aa5a438b35..d99270e7f3 100644 --- a/src/libcollections/benches/slice.rs +++ b/src/liballoc/benches/slice.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::{mem, ptr}; -use std::__rand::{Rng, thread_rng}; +use std::__rand::{thread_rng}; +use std::mem; +use std::ptr; +use rand::{Rng, SeedableRng, XorShiftRng}; use test::{Bencher, black_box}; #[bench] @@ -191,17 +193,17 @@ fn gen_descending(len: usize) -> Vec { } fn gen_random(len: usize) -> Vec { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); rng.gen_iter::().take(len).collect() } fn gen_random_bytes(len: usize) -> Vec { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); rng.gen_iter::().take(len).collect() } fn gen_mostly_ascending(len: usize) -> Vec { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); let mut v = gen_ascending(len); for _ in (0usize..).take_while(|x| x * x <= len) { let x = rng.gen::() % len; @@ -212,7 +214,7 @@ fn gen_mostly_ascending(len: usize) -> Vec { } fn gen_mostly_descending(len: usize) -> Vec { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); let mut v = gen_descending(len); for _ in (0usize..).take_while(|x| x * x <= len) { let x = rng.gen::() % len; @@ -223,7 +225,7 @@ fn gen_mostly_descending(len: usize) -> Vec { } fn gen_strings(len: usize) -> Vec { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); let mut v = vec![]; for _ in 0..len { let n = rng.gen::() % 20 + 1; @@ -233,7 +235,7 @@ fn gen_strings(len: usize) -> Vec { } fn gen_big_random(len: usize) -> Vec<[u64; 16]> { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); rng.gen_iter().map(|x| [x; 16]).take(len).collect() } @@ -241,18 +243,32 @@ macro_rules! sort { ($f:ident, $name:ident, $gen:expr, $len:expr) => { #[bench] fn $name(b: &mut Bencher) { - b.iter(|| $gen($len).$f()); + let v = $gen($len); + b.iter(|| v.clone().$f()); b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64; } } } +macro_rules! sort_strings { + ($f:ident, $name:ident, $gen:expr, $len:expr) => { + #[bench] + fn $name(b: &mut Bencher) { + let v = $gen($len); + let v = v.iter().map(|s| &**s).collect::>(); + b.iter(|| v.clone().$f()); + b.bytes = $len * mem::size_of::<&str>() as u64; + } + } +} + macro_rules! sort_expensive { ($f:ident, $name:ident, $gen:expr, $len:expr) => { #[bench] fn $name(b: &mut Bencher) { + let v = $gen($len); b.iter(|| { - let mut v = $gen($len); + let mut v = v.clone(); let mut count = 0; v.$f(|a: &u64, b: &u64| { count += 1; @@ -263,7 +279,7 @@ macro_rules! sort_expensive { }); black_box(count); }); - b.bytes = $len as u64 * mem::size_of::() as u64; + b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64; } } } @@ -271,30 +287,30 @@ macro_rules! sort_expensive { sort!(sort, sort_small_ascending, gen_ascending, 10); sort!(sort, sort_small_descending, gen_descending, 10); sort!(sort, sort_small_random, gen_random, 10); -sort!(sort, sort_small_big_random, gen_big_random, 10); +sort!(sort, sort_small_big, gen_big_random, 10); sort!(sort, sort_medium_random, gen_random, 100); sort!(sort, sort_large_ascending, gen_ascending, 10000); sort!(sort, sort_large_descending, gen_descending, 10000); sort!(sort, sort_large_mostly_ascending, gen_mostly_ascending, 10000); sort!(sort, sort_large_mostly_descending, gen_mostly_descending, 10000); sort!(sort, sort_large_random, gen_random, 10000); -sort!(sort, sort_large_big_random, gen_big_random, 10000); -sort!(sort, sort_large_strings, gen_strings, 10000); -sort_expensive!(sort_by, sort_large_random_expensive, gen_random, 10000); +sort!(sort, sort_large_big, gen_big_random, 10000); +sort_strings!(sort, sort_large_strings, gen_strings, 10000); +sort_expensive!(sort_by, sort_large_expensive, gen_random, 10000); sort!(sort_unstable, sort_unstable_small_ascending, gen_ascending, 10); sort!(sort_unstable, sort_unstable_small_descending, gen_descending, 10); sort!(sort_unstable, sort_unstable_small_random, gen_random, 10); -sort!(sort_unstable, sort_unstable_small_big_random, gen_big_random, 10); +sort!(sort_unstable, sort_unstable_small_big, gen_big_random, 10); sort!(sort_unstable, sort_unstable_medium_random, gen_random, 100); sort!(sort_unstable, sort_unstable_large_ascending, gen_ascending, 10000); sort!(sort_unstable, sort_unstable_large_descending, gen_descending, 10000); sort!(sort_unstable, sort_unstable_large_mostly_ascending, gen_mostly_ascending, 10000); sort!(sort_unstable, sort_unstable_large_mostly_descending, gen_mostly_descending, 10000); sort!(sort_unstable, sort_unstable_large_random, gen_random, 10000); -sort!(sort_unstable, sort_unstable_large_big_random, gen_big_random, 10000); -sort!(sort_unstable, sort_unstable_large_strings, gen_strings, 10000); -sort_expensive!(sort_unstable_by, sort_unstable_large_random_expensive, gen_random, 10000); +sort!(sort_unstable, sort_unstable_large_big, gen_big_random, 10000); +sort_strings!(sort_unstable, sort_unstable_large_strings, gen_strings, 10000); +sort_expensive!(sort_unstable_by, sort_unstable_large_expensive, gen_random, 10000); macro_rules! reverse { ($name:ident, $ty:ty, $f:expr) => { diff --git a/src/libcollections/benches/str.rs b/src/liballoc/benches/str.rs similarity index 100% rename from src/libcollections/benches/str.rs rename to src/liballoc/benches/str.rs diff --git a/src/libcollections/benches/string.rs b/src/liballoc/benches/string.rs similarity index 100% rename from src/libcollections/benches/string.rs rename to src/liballoc/benches/string.rs diff --git a/src/libcollections/benches/vec.rs b/src/liballoc/benches/vec.rs similarity index 100% rename from src/libcollections/benches/vec.rs rename to src/liballoc/benches/vec.rs diff --git a/src/libcollections/benches/vec_deque.rs b/src/liballoc/benches/vec_deque.rs similarity index 100% rename from src/libcollections/benches/vec_deque.rs rename to src/liballoc/benches/vec_deque.rs diff --git a/src/libcollections/binary_heap.rs b/src/liballoc/binary_heap.rs similarity index 100% rename from src/libcollections/binary_heap.rs rename to src/liballoc/binary_heap.rs diff --git a/src/libcollections/borrow.rs b/src/liballoc/borrow.rs similarity index 100% rename from src/libcollections/borrow.rs rename to src/liballoc/borrow.rs diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 8a39be8fae..94f5f4042e 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -42,8 +42,10 @@ //! Recursive structures must be boxed, because if the definition of `Cons` //! looked like this: //! -//! ```rust,ignore +//! ```compile_fail,E0072 +//! # enum List { //! Cons(T, List), +//! # } //! ``` //! //! It wouldn't work. This is because the size of a `List` depends on how many @@ -53,7 +55,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -use heap; +use heap::{Heap, Layout, Alloc}; use raw_vec::RawVec; use core::any::Any; @@ -95,6 +97,7 @@ pub const HEAP: ExchangeHeapSingleton = ExchangeHeapSingleton { _force_singleton #[unstable(feature = "box_heap", reason = "may be renamed; uncertain about custom allocator design", issue = "27779")] +#[allow(missing_debug_implementations)] #[derive(Copy, Clone)] pub struct ExchangeHeapSingleton { _force_singleton: (), @@ -129,10 +132,10 @@ pub struct Box(Unique); #[unstable(feature = "placement_in", reason = "placement box design is still being worked out.", issue = "27779")] +#[allow(missing_debug_implementations)] pub struct IntermediateBox { ptr: *mut u8, - size: usize, - align: usize, + layout: Layout, marker: marker::PhantomData<*mut T>, } @@ -152,23 +155,21 @@ unsafe fn finalize(b: IntermediateBox) -> Box { } fn make_place() -> IntermediateBox { - let size = mem::size_of::(); - let align = mem::align_of::(); + let layout = Layout::new::(); - let p = if size == 0 { + let p = if layout.size() == 0 { mem::align_of::() as *mut u8 } else { - let p = unsafe { heap::allocate(size, align) }; - if p.is_null() { - panic!("Box make_place allocation failure."); + unsafe { + Heap.alloc(layout.clone()).unwrap_or_else(|err| { + Heap.oom(err) + }) } - p }; IntermediateBox { ptr: p, - size: size, - align: align, + layout: layout, marker: marker::PhantomData, } } @@ -217,8 +218,10 @@ impl Placer for ExchangeHeapSingleton { issue = "27779")] impl Drop for IntermediateBox { fn drop(&mut self) { - if self.size > 0 { - unsafe { heap::deallocate(self.ptr, self.size, self.align) } + if self.layout.size() > 0 { + unsafe { + Heap.dealloc(self.ptr, self.layout.clone()) + } } } } @@ -723,14 +726,14 @@ impl Clone for Box<[T]> { } } -#[stable(feature = "rust1", since = "1.0.0")] +#[stable(feature = "box_borrow", since = "1.1.0")] impl borrow::Borrow for Box { fn borrow(&self) -> &T { &**self } } -#[stable(feature = "rust1", since = "1.0.0")] +#[stable(feature = "box_borrow", since = "1.1.0")] impl borrow::BorrowMut for Box { fn borrow_mut(&mut self) -> &mut T { &mut **self diff --git a/src/libcollections/btree/map.rs b/src/liballoc/btree/map.rs similarity index 99% rename from src/libcollections/btree/map.rs rename to src/liballoc/btree/map.rs index d73c0254a7..a51c70159d 100644 --- a/src/libcollections/btree/map.rs +++ b/src/liballoc/btree/map.rs @@ -334,9 +334,9 @@ pub struct Keys<'a, K: 'a, V: 'a> { } #[stable(feature = "collection_debug", since = "1.17.0")] -impl<'a, K: 'a + fmt::Debug, V: 'a + fmt::Debug> fmt::Debug for Keys<'a, K, V> { +impl<'a, K: 'a + fmt::Debug, V: 'a> fmt::Debug for Keys<'a, K, V> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_list().entries(self.inner.clone()).finish() + f.debug_list().entries(self.clone()).finish() } } @@ -353,9 +353,9 @@ pub struct Values<'a, K: 'a, V: 'a> { } #[stable(feature = "collection_debug", since = "1.17.0")] -impl<'a, K: 'a + fmt::Debug, V: 'a + fmt::Debug> fmt::Debug for Values<'a, K, V> { +impl<'a, K: 'a, V: 'a + fmt::Debug> fmt::Debug for Values<'a, K, V> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_list().entries(self.inner.clone()).finish() + f.debug_list().entries(self.clone()).finish() } } diff --git a/src/libcollections/btree/mod.rs b/src/liballoc/btree/mod.rs similarity index 100% rename from src/libcollections/btree/mod.rs rename to src/liballoc/btree/mod.rs diff --git a/src/libcollections/btree/node.rs b/src/liballoc/btree/node.rs similarity index 98% rename from src/libcollections/btree/node.rs rename to src/liballoc/btree/node.rs index 52cdd39d8f..0eaff6f219 100644 --- a/src/libcollections/btree/node.rs +++ b/src/liballoc/btree/node.rs @@ -41,7 +41,6 @@ // - A node of length `n` has `n` keys, `n` values, and (in an internal node) `n + 1` edges. // This implies that even an empty internal node has at least one edge. -use alloc::heap; use core::marker::PhantomData; use core::mem; use core::nonzero::NonZero; @@ -49,6 +48,7 @@ use core::ptr::{self, Unique}; use core::slice; use boxed::Box; +use heap::{Heap, Alloc, Layout}; const B: usize = 6; pub const MIN_LEN: usize = B - 1; @@ -254,11 +254,7 @@ impl Root { self.as_mut().as_leaf_mut().parent = ptr::null(); unsafe { - heap::deallocate( - top, - mem::size_of::>(), - mem::align_of::>() - ); + Heap.dealloc(top, Layout::new::>()); } } } @@ -445,7 +441,7 @@ impl NodeRef { > { let ptr = self.as_leaf() as *const LeafNode as *const u8 as *mut u8; let ret = self.ascend().ok(); - heap::deallocate(ptr, mem::size_of::>(), mem::align_of::>()); + Heap.dealloc(ptr, Layout::new::>()); ret } } @@ -466,11 +462,7 @@ impl NodeRef { > { let ptr = self.as_internal() as *const InternalNode as *const u8 as *mut u8; let ret = self.ascend().ok(); - heap::deallocate( - ptr, - mem::size_of::>(), - mem::align_of::>() - ); + Heap.dealloc(ptr, Layout::new::>()); ret } } @@ -1252,16 +1244,14 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: ).correct_parent_link(); } - heap::deallocate( + Heap.dealloc( right_node.node.get() as *mut u8, - mem::size_of::>(), - mem::align_of::>() + Layout::new::>(), ); } else { - heap::deallocate( + Heap.dealloc( right_node.node.get() as *mut u8, - mem::size_of::>(), - mem::align_of::>() + Layout::new::>(), ); } diff --git a/src/libcollections/btree/search.rs b/src/liballoc/btree/search.rs similarity index 100% rename from src/libcollections/btree/search.rs rename to src/liballoc/btree/search.rs diff --git a/src/libcollections/btree/set.rs b/src/liballoc/btree/set.rs similarity index 100% rename from src/libcollections/btree/set.rs rename to src/liballoc/btree/set.rs diff --git a/src/libcollections/fmt.rs b/src/liballoc/fmt.rs similarity index 98% rename from src/libcollections/fmt.rs rename to src/liballoc/fmt.rs index 62a8816462..4847b21c0b 100644 --- a/src/libcollections/fmt.rs +++ b/src/liballoc/fmt.rs @@ -230,7 +230,7 @@ //! There are a number of related macros in the `format!` family. The ones that //! are currently implemented are: //! -//! ```ignore +//! ```ignore (only-for-syntax-highlight) //! format! // described above //! write! // first argument is a &mut io::Write, the destination //! writeln! // same as write but appends a newline @@ -498,12 +498,10 @@ pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; use string; -/// The format function takes a precompiled format string and a list of -/// arguments, to return the resulting formatted string. +/// The `format` function takes an `Arguments` struct and returns the resulting +/// formatted string. /// -/// # Arguments -/// -/// * args - a structure of arguments generated via the `format_args!` macro. +/// The `Arguments` instance can be created with the `format_args!` macro. /// /// # Examples /// diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index 5ff21c8648..feab1feadf 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -8,130 +8,223 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![unstable(feature = "heap_api", +#![unstable(feature = "allocator_api", reason = "the precise API and guarantees it provides may be tweaked \ slightly, especially to possibly take into account the \ types being stored to make room for a future \ tracing garbage collector", - issue = "27700")] + issue = "32838")] -use core::{isize, usize}; use core::intrinsics::{min_align_of_val, size_of_val}; +use core::mem::{self, ManuallyDrop}; +use core::usize; -#[allow(improper_ctypes)] -extern "C" { - #[allocator] - fn __rust_allocate(size: usize, align: usize) -> *mut u8; - fn __rust_allocate_zeroed(size: usize, align: usize) -> *mut u8; - fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize); - fn __rust_reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8; - fn __rust_reallocate_inplace(ptr: *mut u8, - old_size: usize, - size: usize, - align: usize) - -> usize; - fn __rust_usable_size(size: usize, align: usize) -> usize; +pub use allocator::*; +#[doc(hidden)] +pub mod __core { + pub use core::*; } -#[inline(always)] -fn check_size_and_alignment(size: usize, align: usize) { - debug_assert!(size != 0); - debug_assert!(size <= isize::MAX as usize, - "Tried to allocate too much: {} bytes", - size); - debug_assert!(usize::is_power_of_two(align), - "Invalid alignment of allocation: {}", - align); +extern "Rust" { + #[allocator] + #[allocator_nounwind] + fn __rust_alloc(size: usize, align: usize, err: *mut u8) -> *mut u8; + #[cold] + #[allocator_nounwind] + fn __rust_oom(err: *const u8) -> !; + #[allocator_nounwind] + fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize); + #[allocator_nounwind] + fn __rust_usable_size(layout: *const u8, + min: *mut usize, + max: *mut usize); + #[allocator_nounwind] + fn __rust_realloc(ptr: *mut u8, + old_size: usize, + old_align: usize, + new_size: usize, + new_align: usize, + err: *mut u8) -> *mut u8; + #[allocator_nounwind] + fn __rust_alloc_zeroed(size: usize, align: usize, err: *mut u8) -> *mut u8; + #[allocator_nounwind] + fn __rust_alloc_excess(size: usize, + align: usize, + excess: *mut usize, + err: *mut u8) -> *mut u8; + #[allocator_nounwind] + fn __rust_realloc_excess(ptr: *mut u8, + old_size: usize, + old_align: usize, + new_size: usize, + new_align: usize, + excess: *mut usize, + err: *mut u8) -> *mut u8; + #[allocator_nounwind] + fn __rust_grow_in_place(ptr: *mut u8, + old_size: usize, + old_align: usize, + new_size: usize, + new_align: usize) -> u8; + #[allocator_nounwind] + fn __rust_shrink_in_place(ptr: *mut u8, + old_size: usize, + old_align: usize, + new_size: usize, + new_align: usize) -> u8; } -// FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias` +#[derive(Copy, Clone, Default, Debug)] +pub struct Heap; -/// Return a pointer to `size` bytes of memory aligned to `align`. -/// -/// On failure, return a null pointer. -/// -/// Behavior is undefined if the requested size is 0 or the alignment is not a -/// power of 2. The alignment must be no larger than the largest supported page -/// size on the platform. -#[inline] -pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { - check_size_and_alignment(size, align); - __rust_allocate(size, align) -} +unsafe impl Alloc for Heap { + #[inline] + unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { + let mut err = ManuallyDrop::new(mem::uninitialized::()); + let ptr = __rust_alloc(layout.size(), + layout.align(), + &mut *err as *mut AllocErr as *mut u8); + if ptr.is_null() { + Err(ManuallyDrop::into_inner(err)) + } else { + Ok(ptr) + } + } -/// Return a pointer to `size` bytes of memory aligned to `align` and -/// initialized to zeroes. -/// -/// On failure, return a null pointer. -/// -/// Behavior is undefined if the requested size is 0 or the alignment is not a -/// power of 2. The alignment must be no larger than the largest supported page -/// size on the platform. -#[inline] -pub unsafe fn allocate_zeroed(size: usize, align: usize) -> *mut u8 { - check_size_and_alignment(size, align); - __rust_allocate_zeroed(size, align) -} + #[inline] + fn oom(&mut self, err: AllocErr) -> ! { + unsafe { + __rust_oom(&err as *const AllocErr as *const u8) + } + } -/// Resize the allocation referenced by `ptr` to `size` bytes. -/// -/// On failure, return a null pointer and leave the original allocation intact. -/// -/// If the allocation was relocated, the memory at the passed-in pointer is -/// undefined after the call. -/// -/// Behavior is undefined if the requested size is 0 or the alignment is not a -/// power of 2. The alignment must be no larger than the largest supported page -/// size on the platform. -/// -/// The `old_size` and `align` parameters are the parameters that were used to -/// create the allocation referenced by `ptr`. The `old_size` parameter may be -/// any value in range_inclusive(requested_size, usable_size). -#[inline] -pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 { - check_size_and_alignment(size, align); - __rust_reallocate(ptr, old_size, size, align) -} + #[inline] + unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) { + __rust_dealloc(ptr, layout.size(), layout.align()) + } -/// Resize the allocation referenced by `ptr` to `size` bytes. -/// -/// If the operation succeeds, it returns `usable_size(size, align)` and if it -/// fails (or is a no-op) it returns `usable_size(old_size, align)`. -/// -/// Behavior is undefined if the requested size is 0 or the alignment is not a -/// power of 2. The alignment must be no larger than the largest supported page -/// size on the platform. -/// -/// The `old_size` and `align` parameters are the parameters that were used to -/// create the allocation referenced by `ptr`. The `old_size` parameter may be -/// any value in range_inclusive(requested_size, usable_size). -#[inline] -pub unsafe fn reallocate_inplace(ptr: *mut u8, - old_size: usize, - size: usize, - align: usize) - -> usize { - check_size_and_alignment(size, align); - __rust_reallocate_inplace(ptr, old_size, size, align) -} + #[inline] + fn usable_size(&self, layout: &Layout) -> (usize, usize) { + let mut min = 0; + let mut max = 0; + unsafe { + __rust_usable_size(layout as *const Layout as *const u8, + &mut min, + &mut max); + } + (min, max) + } -/// Deallocates the memory referenced by `ptr`. -/// -/// The `ptr` parameter must not be null. -/// -/// The `old_size` and `align` parameters are the parameters that were used to -/// create the allocation referenced by `ptr`. The `old_size` parameter may be -/// any value in range_inclusive(requested_size, usable_size). -#[inline] -pub unsafe fn deallocate(ptr: *mut u8, old_size: usize, align: usize) { - __rust_deallocate(ptr, old_size, align) -} + #[inline] + unsafe fn realloc(&mut self, + ptr: *mut u8, + layout: Layout, + new_layout: Layout) + -> Result<*mut u8, AllocErr> + { + let mut err = ManuallyDrop::new(mem::uninitialized::()); + let ptr = __rust_realloc(ptr, + layout.size(), + layout.align(), + new_layout.size(), + new_layout.align(), + &mut *err as *mut AllocErr as *mut u8); + if ptr.is_null() { + Err(ManuallyDrop::into_inner(err)) + } else { + mem::forget(err); + Ok(ptr) + } + } -/// Returns the usable size of an allocation created with the specified the -/// `size` and `align`. -#[inline] -pub fn usable_size(size: usize, align: usize) -> usize { - unsafe { __rust_usable_size(size, align) } + #[inline] + unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { + let mut err = ManuallyDrop::new(mem::uninitialized::()); + let ptr = __rust_alloc_zeroed(layout.size(), + layout.align(), + &mut *err as *mut AllocErr as *mut u8); + if ptr.is_null() { + Err(ManuallyDrop::into_inner(err)) + } else { + Ok(ptr) + } + } + + #[inline] + unsafe fn alloc_excess(&mut self, layout: Layout) -> Result { + let mut err = ManuallyDrop::new(mem::uninitialized::()); + let mut size = 0; + let ptr = __rust_alloc_excess(layout.size(), + layout.align(), + &mut size, + &mut *err as *mut AllocErr as *mut u8); + if ptr.is_null() { + Err(ManuallyDrop::into_inner(err)) + } else { + Ok(Excess(ptr, size)) + } + } + + #[inline] + unsafe fn realloc_excess(&mut self, + ptr: *mut u8, + layout: Layout, + new_layout: Layout) -> Result { + let mut err = ManuallyDrop::new(mem::uninitialized::()); + let mut size = 0; + let ptr = __rust_realloc_excess(ptr, + layout.size(), + layout.align(), + new_layout.size(), + new_layout.align(), + &mut size, + &mut *err as *mut AllocErr as *mut u8); + if ptr.is_null() { + Err(ManuallyDrop::into_inner(err)) + } else { + Ok(Excess(ptr, size)) + } + } + + #[inline] + unsafe fn grow_in_place(&mut self, + ptr: *mut u8, + layout: Layout, + new_layout: Layout) + -> Result<(), CannotReallocInPlace> + { + debug_assert!(new_layout.size() >= layout.size()); + debug_assert!(new_layout.align() == layout.align()); + let ret = __rust_grow_in_place(ptr, + layout.size(), + layout.align(), + new_layout.size(), + new_layout.align()); + if ret != 0 { + Ok(()) + } else { + Err(CannotReallocInPlace) + } + } + + #[inline] + unsafe fn shrink_in_place(&mut self, + ptr: *mut u8, + layout: Layout, + new_layout: Layout) -> Result<(), CannotReallocInPlace> { + debug_assert!(new_layout.size() <= layout.size()); + debug_assert!(new_layout.align() == layout.align()); + let ret = __rust_shrink_in_place(ptr, + layout.size(), + layout.align(), + new_layout.size(), + new_layout.align()); + if ret != 0 { + Ok(()) + } else { + Err(CannotReallocInPlace) + } + } } /// An arbitrary non-null address to represent zero-size allocations. @@ -151,11 +244,10 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { if size == 0 { align as *mut u8 } else { - let ptr = allocate(size, align); - if ptr.is_null() { - ::oom() - } - ptr + let layout = Layout::from_size_align_unchecked(size, align); + Heap.alloc(layout).unwrap_or_else(|err| { + Heap.oom(err) + }) } } @@ -166,7 +258,8 @@ pub(crate) unsafe fn box_free(ptr: *mut T) { let align = min_align_of_val(&*ptr); // We do not allocate for Box when T is ZST, so deallocation is also not necessary. if size != 0 { - deallocate(ptr as *mut u8, size, align); + let layout = Layout::from_size_align_unchecked(size, align); + Heap.dealloc(ptr as *mut u8, layout); } } @@ -175,38 +268,22 @@ mod tests { extern crate test; use self::test::Bencher; use boxed::Box; - use heap; + use heap::{Heap, Alloc, Layout}; #[test] fn allocate_zeroed() { unsafe { - let size = 1024; - let ptr = heap::allocate_zeroed(size, 1); - if ptr.is_null() { - ::oom() - } + let layout = Layout::from_size_align(1024, 1).unwrap(); + let ptr = Heap.alloc_zeroed(layout.clone()) + .unwrap_or_else(|e| Heap.oom(e)); - let end = ptr.offset(size as isize); + let end = ptr.offset(layout.size() as isize); let mut i = ptr; while i < end { assert_eq!(*i, 0); i = i.offset(1); } - heap::deallocate(ptr, size, 1); - } - } - - #[test] - fn basic_reallocate_inplace_noop() { - unsafe { - let size = 4000; - let ptr = heap::allocate(size, 8); - if ptr.is_null() { - ::oom() - } - let ret = heap::reallocate_inplace(ptr, size, size, 8); - heap::deallocate(ptr, size, 8); - assert_eq!(ret, heap::usable_size(size, 8)); + Heap.dealloc(ptr, layout); } } diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 418a084da6..7a5acb1856 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2014-2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,18 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! # The Rust core allocation library +//! # The Rust core allocation and collections library //! -//! This is the lowest level library through which allocation in Rust can be -//! performed. +//! This library provides smart pointers and collections for managing +//! heap-allocated values. //! //! This library, like libcore, is not intended for general usage, but rather as //! a building block of other libraries. The types and interfaces in this //! library are reexported through the [standard library](../std/index.html), //! and should not be used through this library. //! -//! Currently, there are four major definitions in this library. -//! //! ## Boxed values //! //! The [`Box`](boxed/index.html) type is a smart pointer type. There can @@ -51,6 +49,12 @@ //! paired with synchronization primitives such as mutexes to allow mutation of //! shared resources. //! +//! ## Collections +//! +//! Implementations of the most common general purpose data structures are +//! defined in this library. They are reexported through the +//! [standard collections library](../std/collections/index.html). +//! //! ## Heap interfaces //! //! The [`heap`](heap/index.html) module defines the low-level interface to the @@ -71,8 +75,17 @@ #![no_std] #![needs_allocator] #![deny(warnings)] +#![deny(missing_debug_implementations)] -#![feature(allocator)] +#![cfg_attr(test, allow(deprecated))] // rand +#![cfg_attr(test, feature(placement_in))] +#![cfg_attr(not(test), feature(core_float))] +#![cfg_attr(not(test), feature(exact_size_is_empty))] +#![cfg_attr(not(test), feature(slice_rotate))] +#![cfg_attr(test, feature(rand, test))] +#![cfg_attr(stage0, feature(allocator))] +#![feature(allow_internal_unstable)] +#![feature(box_patterns)] #![feature(box_syntax)] #![feature(cfg_target_has_atomic)] #![feature(coerce_unsized)] @@ -80,18 +93,34 @@ #![feature(core_intrinsics)] #![feature(custom_attribute)] #![feature(dropck_eyepatch)] -#![cfg_attr(not(test), feature(exact_size_is_empty))] +#![feature(exact_size_is_empty)] +#![feature(fmt_internals)] #![feature(fundamental)] +#![feature(fused)] #![feature(generic_param_attrs)] +#![feature(i128_type)] +#![feature(inclusive_range)] #![feature(lang_items)] #![feature(needs_allocator)] +#![feature(nonzero)] +#![feature(offset_to)] #![feature(optin_builtin_traits)] +#![feature(pattern)] #![feature(placement_in_syntax)] +#![feature(placement_new_protocol)] #![feature(shared)] +#![feature(slice_get_slice)] +#![feature(slice_patterns)] +#![feature(slice_rsplit)] +#![feature(specialization)] #![feature(staged_api)] +#![feature(str_internals)] +#![feature(trusted_len)] #![feature(unboxed_closures)] +#![feature(unicode)] #![feature(unique)] #![feature(unsize)] +#![cfg_attr(not(stage0), feature(allocator_internals))] #![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol))] #![cfg_attr(test, feature(test, box_heap))] @@ -101,11 +130,19 @@ #[cfg(test)] #[macro_use] extern crate std; +#[cfg(test)] +extern crate test; + +extern crate std_unicode; // Module with internal macros used by other modules (needs to be included before other modules). #[macro_use] mod macros; +// Allocator trait and helper struct definitions + +pub mod allocator; + // Heaps provided for low-level allocation strategies pub mod heap; @@ -120,7 +157,7 @@ pub mod heap; pub mod boxed; #[cfg(test)] mod boxed { - pub use std::boxed::{Box, HEAP}; + pub use std::boxed::{Box, IntermediateBox, HEAP}; } #[cfg(test)] mod boxed_test; @@ -128,8 +165,108 @@ mod boxed_test; pub mod arc; pub mod rc; pub mod raw_vec; -#[unstable(feature = "str_box_extras", issue = "41119")] + +// collections modules +pub mod binary_heap; +mod btree; +pub mod borrow; +pub mod fmt; +pub mod linked_list; +pub mod range; +pub mod slice; pub mod str; -pub mod oom; +pub mod string; +pub mod vec; +pub mod vec_deque; + +#[stable(feature = "rust1", since = "1.0.0")] +pub mod btree_map { + //! A map based on a B-Tree. + #[stable(feature = "rust1", since = "1.0.0")] + pub use btree::map::*; +} + +#[stable(feature = "rust1", since = "1.0.0")] +pub mod btree_set { + //! A set based on a B-Tree. + #[stable(feature = "rust1", since = "1.0.0")] + pub use btree::set::*; +} + +#[cfg(not(test))] +mod std { + pub use core::ops; // RangeFull +} + +/// An endpoint of a range of keys. +/// +/// # Examples +/// +/// `Bound`s are range endpoints: +/// +/// ``` +/// #![feature(collections_range)] +/// +/// use std::collections::range::RangeArgument; +/// use std::collections::Bound::*; +/// +/// assert_eq!((..100).start(), Unbounded); +/// assert_eq!((1..12).start(), Included(&1)); +/// assert_eq!((1..12).end(), Excluded(&12)); +/// ``` +/// +/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`]. +/// Note that in most cases, it's better to use range syntax (`1..5`) instead. +/// +/// ``` +/// use std::collections::BTreeMap; +/// use std::collections::Bound::{Excluded, Included, Unbounded}; +/// +/// let mut map = BTreeMap::new(); +/// map.insert(3, "a"); +/// map.insert(5, "b"); +/// map.insert(8, "c"); +/// +/// for (key, value) in map.range((Excluded(3), Included(8))) { +/// println!("{}: {}", key, value); +/// } +/// +/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next()); +/// ``` +/// +/// [`BTreeMap::range`]: btree_map/struct.BTreeMap.html#method.range +#[stable(feature = "collections_bound", since = "1.17.0")] +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub enum Bound { + /// An inclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Included(T), + /// An exclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Excluded(T), + /// An infinite endpoint. Indicates that there is no bound in this direction. + #[stable(feature = "collections_bound", since = "1.17.0")] + Unbounded, +} + +/// An intermediate trait for specialization of `Extend`. +#[doc(hidden)] +trait SpecExtend { + /// Extends `self` with the contents of the given iterator. + fn spec_extend(&mut self, iter: I); +} -pub use oom::oom; +#[doc(no_inline)] +pub use binary_heap::BinaryHeap; +#[doc(no_inline)] +pub use btree_map::BTreeMap; +#[doc(no_inline)] +pub use btree_set::BTreeSet; +#[doc(no_inline)] +pub use linked_list::LinkedList; +#[doc(no_inline)] +pub use vec_deque::VecDeque; +#[doc(no_inline)] +pub use string::String; +#[doc(no_inline)] +pub use vec::Vec; diff --git a/src/libcollections/linked_list.rs b/src/liballoc/linked_list.rs similarity index 99% rename from src/libcollections/linked_list.rs rename to src/liballoc/linked_list.rs index ae25808354..e8973b7d28 100644 --- a/src/libcollections/linked_list.rs +++ b/src/liballoc/linked_list.rs @@ -22,7 +22,6 @@ #![stable(feature = "rust1", since = "1.0.0")] -use alloc::boxed::{Box, IntermediateBox}; use core::cmp::Ordering; use core::fmt; use core::hash::{Hasher, Hash}; @@ -32,6 +31,7 @@ use core::mem; use core::ops::{BoxPlace, InPlace, Place, Placer}; use core::ptr::{self, Shared}; +use boxed::{Box, IntermediateBox}; use super::SpecExtend; /// A doubly-linked list with owned nodes. diff --git a/src/liballoc/macros.rs b/src/liballoc/macros.rs index 7da91c87e9..763f04fcd0 100644 --- a/src/liballoc/macros.rs +++ b/src/liballoc/macros.rs @@ -8,6 +8,89 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +/// Creates a `Vec` containing the arguments. +/// +/// `vec!` allows `Vec`s to be defined with the same syntax as array expressions. +/// There are two forms of this macro: +/// +/// - Create a `Vec` containing a given list of elements: +/// +/// ``` +/// let v = vec![1, 2, 3]; +/// assert_eq!(v[0], 1); +/// assert_eq!(v[1], 2); +/// assert_eq!(v[2], 3); +/// ``` +/// +/// - Create a `Vec` from a given element and size: +/// +/// ``` +/// let v = vec![1; 3]; +/// assert_eq!(v, [1, 1, 1]); +/// ``` +/// +/// Note that unlike array expressions this syntax supports all elements +/// which implement `Clone` and the number of elements doesn't have to be +/// a constant. +/// +/// This will use `clone()` to duplicate an expression, so one should be careful +/// using this with types having a nonstandard `Clone` implementation. For +/// example, `vec![Rc::new(1); 5]` will create a vector of five references +/// to the same boxed integer value, not five references pointing to independently +/// boxed integers. +#[cfg(not(test))] +#[macro_export] +#[stable(feature = "rust1", since = "1.0.0")] +#[allow_internal_unstable] +macro_rules! vec { + ($elem:expr; $n:expr) => ( + $crate::vec::from_elem($elem, $n) + ); + ($($x:expr),*) => ( + <[_]>::into_vec(box [$($x),*]) + ); + ($($x:expr,)*) => (vec![$($x),*]) +} + +// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is +// required for this macro definition, is not available. Instead use the +// `slice::into_vec` function which is only available with cfg(test) +// NB see the slice::hack module in slice.rs for more information +#[cfg(test)] +macro_rules! vec { + ($elem:expr; $n:expr) => ( + $crate::vec::from_elem($elem, $n) + ); + ($($x:expr),*) => ( + $crate::slice::into_vec(box [$($x),*]) + ); + ($($x:expr,)*) => (vec![$($x),*]) +} + +/// Use the syntax described in `std::fmt` to create a value of type `String`. +/// See [`std::fmt`][fmt] for more information. +/// +/// [fmt]: ../std/fmt/index.html +/// +/// # Panics +/// +/// `format!` panics if a formatting trait implementation returns an error. +/// This indicates an incorrect implementation +/// since `fmt::Write for String` never returns an error itself. +/// +/// # Examples +/// +/// ``` +/// format!("test"); +/// format!("hello {}", "world!"); +/// format!("x = {}, y = {y}", 10, y = 30); +/// ``` +#[macro_export] +#[stable(feature = "rust1", since = "1.0.0")] +macro_rules! format { + ($($arg:tt)*) => ($crate::fmt::format(format_args!($($arg)*))) +} + // Private macro to get the offset of a struct field in bytes from the address of the struct. macro_rules! offset_of { ($container:path, $field:ident) => {{ diff --git a/src/liballoc/oom.rs b/src/liballoc/oom.rs deleted file mode 100644 index 3640156fec..0000000000 --- a/src/liballoc/oom.rs +++ /dev/null @@ -1,61 +0,0 @@ -// 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. - -#[cfg(target_has_atomic = "ptr")] -pub use self::imp::set_oom_handler; -use core::intrinsics; - -fn default_oom_handler() -> ! { - // The default handler can't do much more since we can't assume the presence - // of libc or any way of printing an error message. - unsafe { intrinsics::abort() } -} - -/// Common out-of-memory routine -#[cold] -#[inline(never)] -#[unstable(feature = "oom", reason = "not a scrutinized interface", - issue = "27700")] -pub fn oom() -> ! { - self::imp::oom() -} - -#[cfg(target_has_atomic = "ptr")] -mod imp { - use core::mem; - use core::sync::atomic::{AtomicPtr, Ordering}; - - static OOM_HANDLER: AtomicPtr<()> = AtomicPtr::new(super::default_oom_handler as *mut ()); - - #[inline(always)] - pub fn oom() -> ! { - let value = OOM_HANDLER.load(Ordering::SeqCst); - let handler: fn() -> ! = unsafe { mem::transmute(value) }; - handler(); - } - - /// Set a custom handler for out-of-memory conditions - /// - /// To avoid recursive OOM failures, it is critical that the OOM handler does - /// not allocate any memory itself. - #[unstable(feature = "oom", reason = "not a scrutinized interface", - issue = "27700")] - pub fn set_oom_handler(handler: fn() -> !) { - OOM_HANDLER.store(handler as *mut (), Ordering::SeqCst); - } -} - -#[cfg(not(target_has_atomic = "ptr"))] -mod imp { - #[inline(always)] - pub fn oom() -> ! { - super::default_oom_handler() - } -} diff --git a/src/libcollections/range.rs b/src/liballoc/range.rs similarity index 92% rename from src/libcollections/range.rs rename to src/liballoc/range.rs index bc8566e8cb..f862da0d61 100644 --- a/src/libcollections/range.rs +++ b/src/liballoc/range.rs @@ -27,14 +27,14 @@ pub trait RangeArgument { /// # Examples /// /// ``` - /// #![feature(collections)] + /// #![feature(alloc)] /// #![feature(collections_range)] /// - /// extern crate collections; + /// extern crate alloc; /// /// # fn main() { - /// use collections::range::RangeArgument; - /// use collections::Bound::*; + /// use alloc::range::RangeArgument; + /// use alloc::Bound::*; /// /// assert_eq!((..10).start(), Unbounded); /// assert_eq!((3..10).start(), Included(&3)); @@ -49,14 +49,14 @@ pub trait RangeArgument { /// # Examples /// /// ``` - /// #![feature(collections)] + /// #![feature(alloc)] /// #![feature(collections_range)] /// - /// extern crate collections; + /// extern crate alloc; /// /// # fn main() { - /// use collections::range::RangeArgument; - /// use collections::Bound::*; + /// use alloc::range::RangeArgument; + /// use alloc::Bound::*; /// /// assert_eq!((3..).end(), Unbounded); /// assert_eq!((3..10).end(), Excluded(&10)); diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 7edf07944e..d1aab4c70b 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::ptr::Unique; +use allocator::{Alloc, Layout}; +use core::ptr::{self, Unique}; use core::mem; use core::slice; -use heap; -use super::oom; +use heap::Heap; use super::boxed::Box; use core::ops::Drop; use core::cmp; @@ -44,17 +44,17 @@ use core::cmp; /// `shrink_to_fit`, and `from_box` will actually set RawVec's private capacity /// field. This allows zero-sized types to not be special-cased by consumers of /// this type. -pub struct RawVec { +#[allow(missing_debug_implementations)] +pub struct RawVec { ptr: Unique, cap: usize, + a: A, } -impl RawVec { - /// Creates the biggest possible RawVec without allocating. If T has positive - /// size, then this makes a RawVec with capacity 0. If T has 0 size, then it - /// it makes a RawVec with capacity `usize::MAX`. Useful for implementing - /// delayed allocation. - pub fn new() -> Self { +impl RawVec { + /// Like `new` but parameterized over the choice of allocator for + /// the returned RawVec. + pub fn new_in(a: A) -> Self { // !0 is usize::MAX. This branch should be stripped at compile time. let cap = if mem::size_of::() == 0 { !0 } else { 0 }; @@ -62,35 +62,25 @@ impl RawVec { RawVec { ptr: Unique::empty(), cap: cap, + a: a, } } - /// Creates a RawVec with exactly the capacity and alignment requirements - /// for a `[T; cap]`. This is equivalent to calling RawVec::new when `cap` is 0 - /// or T is zero-sized. Note that if `T` is zero-sized this means you will *not* - /// get a RawVec with the requested capacity! - /// - /// # Panics - /// - /// * Panics if the requested capacity exceeds `usize::MAX` bytes. - /// * Panics on 32-bit platforms if the requested capacity exceeds - /// `isize::MAX` bytes. - /// - /// # Aborts - /// - /// Aborts on OOM + /// Like `with_capacity` but parameterized over the choice of + /// allocator for the returned RawVec. #[inline] - pub fn with_capacity(cap: usize) -> Self { - RawVec::allocate(cap, false) + pub fn with_capacity_in(cap: usize, a: A) -> Self { + RawVec::allocate_in(cap, false, a) } - /// Like `with_capacity` but guarantees the buffer is zeroed. + /// Like `with_capacity_zeroed` but parameterized over the choice + /// of allocator for the returned RawVec. #[inline] - pub fn with_capacity_zeroed(cap: usize) -> Self { - RawVec::allocate(cap, true) + pub fn with_capacity_zeroed_in(cap: usize, a: A) -> Self { + RawVec::allocate_in(cap, true, a) } - fn allocate(cap: usize, zeroed: bool) -> Self { + fn allocate_in(cap: usize, zeroed: bool, mut a: A) -> Self { unsafe { let elem_size = mem::size_of::(); @@ -102,35 +92,93 @@ impl RawVec { mem::align_of::() as *mut u8 } else { let align = mem::align_of::(); - let ptr = if zeroed { - heap::allocate_zeroed(alloc_size, align) + let result = if zeroed { + a.alloc_zeroed(Layout::from_size_align(alloc_size, align).unwrap()) } else { - heap::allocate(alloc_size, align) + a.alloc(Layout::from_size_align(alloc_size, align).unwrap()) }; - if ptr.is_null() { - oom() + match result { + Ok(ptr) => ptr, + Err(err) => a.oom(err), } - ptr }; RawVec { ptr: Unique::new(ptr as *mut _), cap: cap, + a: a, } } } +} + +impl RawVec { + /// Creates the biggest possible RawVec (on the system heap) + /// without allocating. If T has positive size, then this makes a + /// RawVec with capacity 0. If T has 0 size, then it it makes a + /// RawVec with capacity `usize::MAX`. Useful for implementing + /// delayed allocation. + pub fn new() -> Self { + Self::new_in(Heap) + } + + /// Creates a RawVec (on the system heap) with exactly the + /// capacity and alignment requirements for a `[T; cap]`. This is + /// equivalent to calling RawVec::new when `cap` is 0 or T is + /// zero-sized. Note that if `T` is zero-sized this means you will + /// *not* get a RawVec with the requested capacity! + /// + /// # Panics + /// + /// * Panics if the requested capacity exceeds `usize::MAX` bytes. + /// * Panics on 32-bit platforms if the requested capacity exceeds + /// `isize::MAX` bytes. + /// + /// # Aborts + /// + /// Aborts on OOM + #[inline] + pub fn with_capacity(cap: usize) -> Self { + RawVec::allocate_in(cap, false, Heap) + } - /// Reconstitutes a RawVec from a pointer and capacity. + /// Like `with_capacity` but guarantees the buffer is zeroed. + #[inline] + pub fn with_capacity_zeroed(cap: usize) -> Self { + RawVec::allocate_in(cap, true, Heap) + } +} + +impl RawVec { + /// Reconstitutes a RawVec from a pointer, capacity, and allocator. /// /// # Undefined Behavior /// - /// The ptr must be allocated, and with the given capacity. The + /// The ptr must be allocated (via the given allocator `a`), and with the given capacity. The + /// capacity cannot exceed `isize::MAX` (only a concern on 32-bit systems). + /// If the ptr and capacity come from a RawVec created via `a`, then this is guaranteed. + pub unsafe fn from_raw_parts_in(ptr: *mut T, cap: usize, a: A) -> Self { + RawVec { + ptr: Unique::new(ptr), + cap: cap, + a: a, + } + } +} + +impl RawVec { + /// Reconstitutes a RawVec from a pointer, capacity. + /// + /// # Undefined Behavior + /// + /// The ptr must be allocated (on the system heap), and with the given capacity. The /// capacity cannot exceed `isize::MAX` (only a concern on 32-bit systems). /// If the ptr and capacity come from a RawVec, then this is guaranteed. pub unsafe fn from_raw_parts(ptr: *mut T, cap: usize) -> Self { RawVec { ptr: Unique::new(ptr), cap: cap, + a: Heap, } } @@ -144,7 +192,7 @@ impl RawVec { } } -impl RawVec { +impl RawVec { /// Gets a raw pointer to the start of the allocation. Note that this is /// Unique::empty() if `cap = 0` or T is zero-sized. In the former case, you must /// be careful. @@ -164,6 +212,16 @@ impl RawVec { } } + /// Returns a shared reference to the allocator backing this RawVec. + pub fn alloc(&self) -> &A { + &self.a + } + + /// Returns a mutable reference to the allocator backing this RawVec. + pub fn alloc_mut(&mut self) -> &mut A { + &mut self.a + } + /// Doubles the size of the type's backing allocation. This is common enough /// to want to do that it's easiest to just have a dedicated method. Slightly /// more efficient logic can be provided for this than the general case. @@ -186,7 +244,11 @@ impl RawVec { /// /// # Examples /// - /// ```ignore + /// ``` + /// # #![feature(alloc)] + /// # extern crate alloc; + /// # use std::ptr; + /// # use alloc::raw_vec::RawVec; /// struct MyVec { /// buf: RawVec, /// len: usize, @@ -203,6 +265,10 @@ impl RawVec { /// self.len += 1; /// } /// } + /// # fn main() { + /// # let mut vec = MyVec { buf: RawVec::new(), len: 0 }; + /// # vec.push(1); + /// # } /// ``` #[inline(never)] #[cold] @@ -214,32 +280,28 @@ impl RawVec { // 0, getting to here necessarily means the RawVec is overfull. assert!(elem_size != 0, "capacity overflow"); - let align = mem::align_of::(); - - let (new_cap, ptr) = if self.cap == 0 { + let (new_cap, ptr_res) = if self.cap == 0 { // skip to 4 because tiny Vec's are dumb; but not if that would cause overflow let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 }; - let ptr = heap::allocate(new_cap * elem_size, align); - (new_cap, ptr) + let ptr_res = self.a.alloc_array::(new_cap); + (new_cap, ptr_res) } else { // Since we guarantee that we never allocate more than isize::MAX bytes, // `elem_size * self.cap <= isize::MAX` as a precondition, so this can't overflow let new_cap = 2 * self.cap; let new_alloc_size = new_cap * elem_size; alloc_guard(new_alloc_size); - let ptr = heap::reallocate(self.ptr() as *mut _, - self.cap * elem_size, - new_alloc_size, - align); - (new_cap, ptr) + let ptr_res = self.a.realloc_array(self.ptr, self.cap, new_cap); + (new_cap, ptr_res) }; // If allocate or reallocate fail, we'll get `null` back - if ptr.is_null() { - oom() - } + let uniq = match ptr_res { + Err(err) => self.a.oom(err), + Ok(uniq) => uniq, + }; - self.ptr = Unique::new(ptr as *mut _); + self.ptr = uniq; self.cap = new_cap; } } @@ -261,7 +323,6 @@ impl RawVec { pub fn double_in_place(&mut self) -> bool { unsafe { let elem_size = mem::size_of::(); - let align = mem::align_of::(); // since we set the capacity to usize::MAX when elem_size is // 0, getting to here necessarily means the RawVec is overfull. @@ -273,15 +334,20 @@ impl RawVec { let new_alloc_size = new_cap * elem_size; alloc_guard(new_alloc_size); - let size = heap::reallocate_inplace(self.ptr() as *mut _, - self.cap * elem_size, - new_alloc_size, - align); - if size >= new_alloc_size { - // We can't directly divide `size`. - self.cap = new_cap; + + let ptr = self.ptr() as *mut _; + let old_layout = Layout::new::().repeat(self.cap).unwrap().0; + let new_layout = Layout::new::().repeat(new_cap).unwrap().0; + match self.a.grow_in_place(ptr, old_layout, new_layout) { + Ok(_) => { + // We can't directly divide `size`. + self.cap = new_cap; + true + } + Err(_) => { + false + } } - size >= new_alloc_size } } @@ -308,7 +374,6 @@ impl RawVec { pub fn reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize) { unsafe { let elem_size = mem::size_of::(); - let align = mem::align_of::(); // NOTE: we don't early branch on ZSTs here because we want this // to actually catch "asking for more than usize::MAX" in that case. @@ -326,21 +391,19 @@ impl RawVec { let new_alloc_size = new_cap.checked_mul(elem_size).expect("capacity overflow"); alloc_guard(new_alloc_size); - let ptr = if self.cap == 0 { - heap::allocate(new_alloc_size, align) + let result = if self.cap == 0 { + self.a.alloc_array::(new_cap) } else { - heap::reallocate(self.ptr() as *mut _, - self.cap * elem_size, - new_alloc_size, - align) + self.a.realloc_array(self.ptr, self.cap, new_cap) }; // If allocate or reallocate fail, we'll get `null` back - if ptr.is_null() { - oom() - } + let uniq = match result { + Err(err) => self.a.oom(err), + Ok(uniq) => uniq, + }; - self.ptr = Unique::new(ptr as *mut _); + self.ptr = uniq; self.cap = new_cap; } } @@ -385,13 +448,17 @@ impl RawVec { /// /// # Examples /// - /// ```ignore + /// ``` + /// # #![feature(alloc)] + /// # extern crate alloc; + /// # use std::ptr; + /// # use alloc::raw_vec::RawVec; /// struct MyVec { /// buf: RawVec, /// len: usize, /// } /// - /// impl MyVec { + /// impl MyVec { /// pub fn push_all(&mut self, elems: &[T]) { /// self.buf.reserve(self.len, elems.len()); /// // reserve would have aborted or panicked if the len exceeded @@ -404,12 +471,13 @@ impl RawVec { /// } /// } /// } + /// # fn main() { + /// # let mut vector = MyVec { buf: RawVec::new(), len: 0 }; + /// # vector.push_all(&[1, 3, 5, 7, 9]); + /// # } /// ``` pub fn reserve(&mut self, used_cap: usize, needed_extra_cap: usize) { unsafe { - let elem_size = mem::size_of::(); - let align = mem::align_of::(); - // NOTE: we don't early branch on ZSTs here because we want this // to actually catch "asking for more than usize::MAX" in that case. // If we make it past the first branch then we are guaranteed to @@ -425,21 +493,18 @@ impl RawVec { // FIXME: may crash and burn on over-reserve alloc_guard(new_alloc_size); - let ptr = if self.cap == 0 { - heap::allocate(new_alloc_size, align) + let result = if self.cap == 0 { + self.a.alloc_array::(new_cap) } else { - heap::reallocate(self.ptr() as *mut _, - self.cap * elem_size, - new_alloc_size, - align) + self.a.realloc_array(self.ptr, self.cap, new_cap) }; - // If allocate or reallocate fail, we'll get `null` back - if ptr.is_null() { - oom() - } + let uniq = match result { + Err(err) => self.a.oom(err), + Ok(uniq) => uniq, + }; - self.ptr = Unique::new(ptr as *mut _); + self.ptr = uniq; self.cap = new_cap; } } @@ -463,9 +528,6 @@ impl RawVec { /// `isize::MAX` bytes. pub fn reserve_in_place(&mut self, used_cap: usize, needed_extra_cap: usize) -> bool { unsafe { - let elem_size = mem::size_of::(); - let align = mem::align_of::(); - // NOTE: we don't early branch on ZSTs here because we want this // to actually catch "asking for more than usize::MAX" in that case. // If we make it past the first branch then we are guaranteed to @@ -478,18 +540,26 @@ impl RawVec { return false; } - let (_, new_alloc_size) = self.amortized_new_size(used_cap, needed_extra_cap); + let (new_cap, new_alloc_size) = self.amortized_new_size(used_cap, needed_extra_cap); // FIXME: may crash and burn on over-reserve alloc_guard(new_alloc_size); - let size = heap::reallocate_inplace(self.ptr() as *mut _, - self.cap * elem_size, - new_alloc_size, - align); - if size >= new_alloc_size { - self.cap = new_alloc_size / elem_size; + // Here, `cap < used_cap + needed_extra_cap <= new_cap` + // (regardless of whether `self.cap - used_cap` wrapped). + // Therefore we can safely call grow_in_place. + + let ptr = self.ptr() as *mut _; + let old_layout = Layout::new::().repeat(self.cap).unwrap().0; + let new_layout = Layout::new::().repeat(new_cap).unwrap().0; + match self.a.grow_in_place(ptr, old_layout, new_layout) { + Ok(_) => { + self.cap = new_cap; + true + } + Err(_) => { + false + } } - size >= new_alloc_size } } @@ -505,7 +575,6 @@ impl RawVec { /// Aborts on OOM. pub fn shrink_to_fit(&mut self, amount: usize) { let elem_size = mem::size_of::(); - let align = mem::align_of::(); // Set the `cap` because they might be about to promote to a `Box<[T]>` if elem_size == 0 { @@ -517,24 +586,30 @@ impl RawVec { assert!(self.cap >= amount, "Tried to shrink to a larger capacity"); if amount == 0 { - mem::replace(self, RawVec::new()); + // We want to create a new zero-length vector within the + // same allocator. We use ptr::write to avoid an + // erroneous attempt to drop the contents, and we use + // ptr::read to sidestep condition against destructuring + // types that implement Drop. + + unsafe { + let a = ptr::read(&self.a as *const A); + self.dealloc_buffer(); + ptr::write(self, RawVec::new_in(a)); + } } else if self.cap != amount { unsafe { - // Overflow check is unnecessary as the vector is already at - // least this large. - let ptr = heap::reallocate(self.ptr() as *mut _, - self.cap * elem_size, - amount * elem_size, - align); - if ptr.is_null() { - oom() + match self.a.realloc_array(self.ptr, self.cap, amount) { + Err(err) => self.a.oom(err), + Ok(uniq) => self.ptr = uniq, } - self.ptr = Unique::new(ptr as *mut _); } self.cap = amount; } } +} +impl RawVec { /// Converts the entire buffer into `Box<[T]>`. /// /// While it is not *strictly* Undefined Behavior to call @@ -552,21 +627,25 @@ impl RawVec { } } -unsafe impl<#[may_dangle] T> Drop for RawVec { +impl RawVec { /// Frees the memory owned by the RawVec *without* trying to Drop its contents. - fn drop(&mut self) { + pub unsafe fn dealloc_buffer(&mut self) { let elem_size = mem::size_of::(); if elem_size != 0 && self.cap != 0 { - let align = mem::align_of::(); - - let num_bytes = elem_size * self.cap; - unsafe { - heap::deallocate(self.ptr() as *mut u8, num_bytes, align); - } + let ptr = self.ptr() as *mut u8; + let layout = Layout::new::().repeat(self.cap).unwrap().0; + self.a.dealloc(ptr, layout); } } } +unsafe impl<#[may_dangle] T, A: Alloc> Drop for RawVec { + /// Frees the memory owned by the RawVec *without* trying to Drop its contents. + fn drop(&mut self) { + unsafe { self.dealloc_buffer(); } + } +} + // We need to guarantee the following: @@ -591,6 +670,46 @@ fn alloc_guard(alloc_size: usize) { mod tests { use super::*; + #[test] + fn allocator_param() { + use allocator::{Alloc, AllocErr}; + + // Writing a test of integration between third-party + // allocators and RawVec is a little tricky because the RawVec + // API does not expose fallible allocation methods, so we + // cannot check what happens when allocator is exhausted + // (beyond detecting a panic). + // + // Instead, this just checks that the RawVec methods do at + // least go through the Allocator API when it reserves + // storage. + + // A dumb allocator that consumes a fixed amount of fuel + // before allocation attempts start failing. + struct BoundedAlloc { fuel: usize } + unsafe impl Alloc for BoundedAlloc { + unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { + let size = layout.size(); + if size > self.fuel { + return Err(AllocErr::Unsupported { details: "fuel exhausted" }); + } + match Heap.alloc(layout) { + ok @ Ok(_) => { self.fuel -= size; ok } + err @ Err(_) => err, + } + } + unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) { + Heap.dealloc(ptr, layout) + } + } + + let a = BoundedAlloc { fuel: 500 }; + let mut v: RawVec = RawVec::with_capacity_in(50, a); + assert_eq!(v.a.fuel, 450); + v.reserve(50, 150); // (causes a realloc, thus using 50 + 150 = 200 units of fuel) + assert_eq!(v.a.fuel, 250); + } + #[test] fn reserve_does_not_overallocate() { { @@ -623,4 +742,5 @@ mod tests { } } + } diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 33951b911d..306136b21c 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -10,7 +10,8 @@ #![allow(deprecated)] -//! Single-threaded reference-counting pointers. +//! Single-threaded reference-counting pointers. 'Rc' stands for 'Reference +//! Counted'. //! //! The type [`Rc`][`Rc`] provides shared ownership of a value of type `T`, //! allocated in the heap. Invoking [`clone`][clone] on [`Rc`] produces a new @@ -251,13 +252,13 @@ use core::hash::{Hash, Hasher}; use core::intrinsics::abort; use core::marker; use core::marker::Unsize; -use core::mem::{self, align_of_val, forget, size_of, size_of_val, uninitialized}; +use core::mem::{self, forget, size_of, size_of_val, uninitialized}; use core::ops::Deref; use core::ops::CoerceUnsized; use core::ptr::{self, Shared}; use core::convert::From; -use heap::{allocate, deallocate, box_free}; +use heap::{Heap, Alloc, Layout, box_free}; use raw_vec::RawVec; struct RcBox { @@ -266,12 +267,13 @@ struct RcBox { value: T, } -/// A single-threaded reference-counting pointer. +/// A single-threaded reference-counting pointer. 'Rc' stands for 'Reference +/// Counted'. /// /// See the [module-level documentation](./index.html) for more details. /// /// The inherent methods of `Rc` are all associated functions, which means -/// that you have to call them as e.g. [`Rc::get_mut(&value)`][get_mut] instead of +/// that you have to call them as e.g. [`Rc::get_mut(&mut value)`][get_mut] instead of /// `value.get_mut()`. This avoids conflicts with methods of the inner /// type `T`. /// @@ -426,7 +428,7 @@ impl Rc { #[doc(hidden)] #[unstable(feature = "rustc_private", reason = "for internal use in rustc", - issue = "0")] + issue = "27812")] pub fn __from_str(value: &str) -> Rc { unsafe { // Allocate enough space for `RcBox`. @@ -451,7 +453,7 @@ impl Rc<[T]> { #[doc(hidden)] #[unstable(feature = "rustc_private", reason = "for internal use in rustc", - issue = "0")] + issue = "27812")] pub fn __from_array(value: Box<[T]>) -> Rc<[T]> { unsafe { let ptr: *mut RcBox<[T]> = @@ -459,7 +461,8 @@ impl Rc<[T]> { // FIXME(custom-DST): creating this invalid &[T] is dubiously defined, // we should have a better way of getting the size/align // of a DST from its unsized part. - let ptr = allocate(size_of_val(&*ptr), align_of_val(&*ptr)); + let ptr = Heap.alloc(Layout::for_value(&*ptr)) + .unwrap_or_else(|e| Heap.oom(e)); let ptr: *mut RcBox<[T]> = mem::transmute([ptr as usize, value.len()]); // Initialize the new RcBox. @@ -717,7 +720,7 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc { self.dec_weak(); if self.weak() == 0 { - deallocate(ptr as *mut u8, size_of_val(&*ptr), align_of_val(&*ptr)) + Heap.dealloc(ptr as *mut u8, Layout::for_value(&*ptr)); } } } @@ -1095,7 +1098,7 @@ impl Drop for Weak { // the weak count starts at 1, and will only go to zero if all // the strong pointers have disappeared. if self.weak() == 0 { - deallocate(ptr as *mut u8, size_of_val(&*ptr), align_of_val(&*ptr)) + Heap.dealloc(ptr as *mut u8, Layout::for_value(&*ptr)); } } } diff --git a/src/libcollections/slice.rs b/src/liballoc/slice.rs similarity index 98% rename from src/libcollections/slice.rs rename to src/liballoc/slice.rs index 97d6687c79..f4c2b9d054 100644 --- a/src/libcollections/slice.rs +++ b/src/liballoc/slice.rs @@ -97,7 +97,6 @@ // It's cleaner to just turn off the unused_imports warning than to fix them. #![cfg_attr(test, allow(unused_imports, dead_code))] -use alloc::boxed::Box; use core::cmp::Ordering::{self, Less}; use core::mem::size_of; use core::mem; @@ -105,6 +104,7 @@ use core::ptr; use core::slice as core_slice; use borrow::{Borrow, BorrowMut, ToOwned}; +use boxed::Box; use vec::Vec; #[stable(feature = "rust1", since = "1.0.0")] @@ -141,7 +141,7 @@ pub use self::hack::to_vec; // `core::slice::SliceExt` - we need to supply these functions for the // `test_permutations` test mod hack { - use alloc::boxed::Box; + use boxed::Box; use core::mem; #[cfg(test)] @@ -1144,6 +1144,10 @@ impl [T] { /// /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case. /// + /// When applicable, unstable sorting is preferred because it is generally faster than stable + /// sorting and it doesn't allocate auxiliary memory. + /// See [`sort_unstable`](#method.sort_unstable). + /// /// # Current implementation /// /// The current algorithm is an adaptive, iterative merge sort inspired by @@ -1174,6 +1178,10 @@ impl [T] { /// /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case. /// + /// When applicable, unstable sorting is preferred because it is generally faster than stable + /// sorting and it doesn't allocate auxiliary memory. + /// See [`sort_unstable_by`](#method.sort_unstable_by). + /// /// # Current implementation /// /// The current algorithm is an adaptive, iterative merge sort inspired by @@ -1207,6 +1215,10 @@ impl [T] { /// /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case. /// + /// When applicable, unstable sorting is preferred because it is generally faster than stable + /// sorting and it doesn't allocate auxiliary memory. + /// See [`sort_unstable_by_key`](#method.sort_unstable_by_key). + /// /// # Current implementation /// /// The current algorithm is an adaptive, iterative merge sort inspired by @@ -1251,8 +1263,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(sort_unstable)] - /// /// let mut v = [-5, 4, 1, -3, 2]; /// /// v.sort_unstable(); @@ -1260,8 +1270,7 @@ impl [T] { /// ``` /// /// [pdqsort]: https://github.com/orlp/pdqsort - // FIXME #40585: Mention `sort_unstable` in the documentation for `sort`. - #[unstable(feature = "sort_unstable", issue = "40585")] + #[stable(feature = "sort_unstable", since = "1.20.0")] #[inline] pub fn sort_unstable(&mut self) where T: Ord @@ -1288,8 +1297,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(sort_unstable)] - /// /// let mut v = [5, 4, 1, 3, 2]; /// v.sort_unstable_by(|a, b| a.cmp(b)); /// assert!(v == [1, 2, 3, 4, 5]); @@ -1300,8 +1307,7 @@ impl [T] { /// ``` /// /// [pdqsort]: https://github.com/orlp/pdqsort - // FIXME #40585: Mention `sort_unstable_by` in the documentation for `sort_by`. - #[unstable(feature = "sort_unstable", issue = "40585")] + #[stable(feature = "sort_unstable", since = "1.20.0")] #[inline] pub fn sort_unstable_by(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering @@ -1328,8 +1334,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(sort_unstable)] - /// /// let mut v = [-5i32, 4, 1, -3, 2]; /// /// v.sort_unstable_by_key(|k| k.abs()); @@ -1337,8 +1341,7 @@ impl [T] { /// ``` /// /// [pdqsort]: https://github.com/orlp/pdqsort - // FIXME #40585: Mention `sort_unstable_by_key` in the documentation for `sort_by_key`. - #[unstable(feature = "sort_unstable", issue = "40585")] + #[stable(feature = "sort_unstable", since = "1.20.0")] #[inline] pub fn sort_unstable_by_key(&mut self, f: F) where F: FnMut(&T) -> B, @@ -1794,7 +1797,7 @@ unsafe fn merge(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F) impl Drop for MergeHole { fn drop(&mut self) { - // `T` is not a zero-sized type, so it's okay to divide by it's size. + // `T` is not a zero-sized type, so it's okay to divide by its size. let len = (self.end as usize - self.start as usize) / mem::size_of::(); unsafe { ptr::copy_nonoverlapping(self.start, self.dest, len); } } @@ -1908,7 +1911,7 @@ fn merge_sort(v: &mut [T], mut is_less: F) // if `Some(r)` is returned, that means `runs[r]` and `runs[r + 1]` must be merged next. If the // algorithm should continue building a new run instead, `None` is returned. // - // TimSort is infamous for it's buggy implementations, as described here: + // TimSort is infamous for its buggy implementations, as described here: // http://envisage-project.eu/timsort-specification-and-verification/ // // The gist of the story is: we must enforce the invariants on the top four runs on the stack. diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index c87db16a0f..4df13c509a 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -8,14 +8,1991 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Methods for dealing with boxed strings. +//! Unicode string slices. +//! +//! The `&str` type is one of the two main string types, the other being `String`. +//! Unlike its `String` counterpart, its contents are borrowed. +//! +//! # Basic Usage +//! +//! A basic string declaration of `&str` type: +//! +//! ``` +//! let hello_world = "Hello, World!"; +//! ``` +//! +//! Here we have declared a string literal, also known as a string slice. +//! String literals have a static lifetime, which means the string `hello_world` +//! is guaranteed to be valid for the duration of the entire program. +//! We can explicitly specify `hello_world`'s lifetime as well: +//! +//! ``` +//! let hello_world: &'static str = "Hello, world!"; +//! ``` +//! +//! *[See also the `str` primitive type](../../std/primitive.str.html).* + +#![stable(feature = "rust1", since = "1.0.0")] + +// Many of the usings in this module are only used in the test configuration. +// It's cleaner to just turn off the unused_imports warning than to fix them. +#![allow(unused_imports)] + +use core::fmt; +use core::str as core_str; +use core::str::pattern::Pattern; +use core::str::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher}; use core::mem; +use core::iter::FusedIterator; +use std_unicode::str::{UnicodeStr, Utf16Encoder}; +use vec_deque::VecDeque; +use borrow::{Borrow, ToOwned}; +use string::String; +use std_unicode; +use vec::Vec; +use slice::{SliceConcatExt, SliceIndex}; use boxed::Box; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{FromStr, Utf8Error}; +#[allow(deprecated)] +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{Lines, LinesAny}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{Split, RSplit}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{SplitN, RSplitN}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{SplitTerminator, RSplitTerminator}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{Matches, RMatches}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{MatchIndices, RMatchIndices}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{from_utf8, from_utf8_mut, Chars, CharIndices, Bytes}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{from_utf8_unchecked, from_utf8_unchecked_mut, ParseBoolError}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use std_unicode::str::SplitWhitespace; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::pattern; + + +#[unstable(feature = "slice_concat_ext", + reason = "trait should not have to exist", + issue = "27747")] +impl> SliceConcatExt for [S] { + type Output = String; + + fn concat(&self) -> String { + if self.is_empty() { + return String::new(); + } + + // `len` calculation may overflow but push_str will check boundaries + let len = self.iter().map(|s| s.borrow().len()).sum(); + let mut result = String::with_capacity(len); + + for s in self { + result.push_str(s.borrow()) + } + + result + } + + fn join(&self, sep: &str) -> String { + if self.is_empty() { + return String::new(); + } + + // concat is faster + if sep.is_empty() { + return self.concat(); + } + + // this is wrong without the guarantee that `self` is non-empty + // `len` calculation may overflow but push_str but will check boundaries + let len = sep.len() * (self.len() - 1) + + self.iter().map(|s| s.borrow().len()).sum::(); + let mut result = String::with_capacity(len); + let mut first = true; + + for s in self { + if first { + first = false; + } else { + result.push_str(sep); + } + result.push_str(s.borrow()); + } + result + } + + fn connect(&self, sep: &str) -> String { + self.join(sep) + } +} + +/// An iterator of [`u16`] over the string encoded as UTF-16. +/// +/// [`u16`]: ../../std/primitive.u16.html +/// +/// This struct is created by the [`encode_utf16`] method on [`str`]. +/// See its documentation for more. +/// +/// [`encode_utf16`]: ../../std/primitive.str.html#method.encode_utf16 +/// [`str`]: ../../std/primitive.str.html +#[derive(Clone)] +#[stable(feature = "encode_utf16", since = "1.8.0")] +pub struct EncodeUtf16<'a> { + encoder: Utf16Encoder>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl<'a> fmt::Debug for EncodeUtf16<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("EncodeUtf16 { .. }") + } +} + +#[stable(feature = "encode_utf16", since = "1.8.0")] +impl<'a> Iterator for EncodeUtf16<'a> { + type Item = u16; + + #[inline] + fn next(&mut self) -> Option { + self.encoder.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.encoder.size_hint() + } +} + +#[unstable(feature = "fused", issue = "35602")] +impl<'a> FusedIterator for EncodeUtf16<'a> {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Borrow for String { + #[inline] + fn borrow(&self) -> &str { + &self[..] + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ToOwned for str { + type Owned = String; + fn to_owned(&self) -> String { + unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) } + } + + fn clone_into(&self, target: &mut String) { + let mut b = mem::replace(target, String::new()).into_bytes(); + self.as_bytes().clone_into(&mut b); + *target = unsafe { String::from_utf8_unchecked(b) } + } +} + +/// Methods for string slices. +#[lang = "str"] +#[cfg(not(test))] +impl str { + /// Returns the length of `self`. + /// + /// This length is in bytes, not [`char`]s or graphemes. In other words, + /// it may not be what a human considers the length of the string. + /// + /// [`char`]: primitive.char.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let len = "foo".len(); + /// assert_eq!(3, len); + /// + /// let len = "ƒoo".len(); // fancy f! + /// assert_eq!(4, len); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn len(&self) -> usize { + core_str::StrExt::len(self) + } + + /// Returns `true` if `self` has a length of zero bytes. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = ""; + /// assert!(s.is_empty()); + /// + /// let s = "not empty"; + /// assert!(!s.is_empty()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_empty(&self) -> bool { + core_str::StrExt::is_empty(self) + } + + /// Checks that `index`-th byte lies at the start and/or end of a + /// UTF-8 code point sequence. + /// + /// The start and end of the string (when `index == self.len()`) are + /// considered to be + /// boundaries. + /// + /// Returns `false` if `index` is greater than `self.len()`. + /// + /// # Examples + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// assert!(s.is_char_boundary(0)); + /// // start of `老` + /// assert!(s.is_char_boundary(6)); + /// assert!(s.is_char_boundary(s.len())); + /// + /// // second byte of `ö` + /// assert!(!s.is_char_boundary(2)); + /// + /// // third byte of `老` + /// assert!(!s.is_char_boundary(8)); + /// ``` + #[stable(feature = "is_char_boundary", since = "1.9.0")] + #[inline] + pub fn is_char_boundary(&self, index: usize) -> bool { + core_str::StrExt::is_char_boundary(self, index) + } + + /// Converts a string slice to a byte slice. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let bytes = "bors".as_bytes(); + /// assert_eq!(b"bors", bytes); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline(always)] + pub fn as_bytes(&self) -> &[u8] { + core_str::StrExt::as_bytes(self) + } + + /// Converts a mutable string slice to a mutable byte slice. + #[stable(feature = "str_mut_extras", since = "1.20.0")] + #[inline(always)] + pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] { + core_str::StrExt::as_bytes_mut(self) + } + + /// Converts a string slice to a raw pointer. + /// + /// As string slices are a slice of bytes, the raw pointer points to a + /// [`u8`]. This pointer will be pointing to the first byte of the string + /// slice. + /// + /// [`u8`]: primitive.u8.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "Hello"; + /// let ptr = s.as_ptr(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn as_ptr(&self) -> *const u8 { + core_str::StrExt::as_ptr(self) + } + + /// Returns a subslice of `str`. + /// + /// This is the non-panicking alternative to indexing the `str`. Returns + /// [`None`] whenever equivalent indexing operation would panic. + /// + /// [`None`]: option/enum.Option.html#variant.None + /// + /// # Examples + /// + /// ``` + /// let v = "🗻∈🌏"; + /// assert_eq!(Some("🗻"), v.get(0..4)); + /// assert!(v.get(1..).is_none()); + /// assert!(v.get(..8).is_none()); + /// assert!(v.get(..42).is_none()); + /// ``` + #[stable(feature = "str_checked_slicing", since = "1.20.0")] + #[inline] + pub fn get>(&self, i: I) -> Option<&I::Output> { + core_str::StrExt::get(self, i) + } + + /// Returns a mutable subslice of `str`. + /// + /// This is the non-panicking alternative to indexing the `str`. Returns + /// [`None`] whenever equivalent indexing operation would panic. + /// + /// [`None`]: option/enum.Option.html#variant.None + /// + /// # Examples + /// + /// ``` + /// let mut v = String::from("🗻∈🌏"); + /// assert_eq!(Some("🗻"), v.get_mut(0..4).map(|v| &*v)); + /// assert!(v.get_mut(1..).is_none()); + /// assert!(v.get_mut(..8).is_none()); + /// assert!(v.get_mut(..42).is_none()); + /// ``` + #[stable(feature = "str_checked_slicing", since = "1.20.0")] + #[inline] + pub fn get_mut>(&mut self, i: I) -> Option<&mut I::Output> { + core_str::StrExt::get_mut(self, i) + } + + /// Returns a unchecked subslice of `str`. + /// + /// This is the unchecked alternative to indexing the `str`. + /// + /// # Safety + /// + /// Callers of this function are responsible that these preconditions are + /// satisfied: + /// + /// * The starting index must come before the ending index; + /// * Indexes must be within bounds of the original slice; + /// * Indexes must lie on UTF-8 sequence boundaries. + /// + /// Failing that, the returned string slice may reference invalid memory or + /// violate the invariants communicated by the `str` type. + /// + /// # Examples + /// + /// ``` + /// let v = "🗻∈🌏"; + /// unsafe { + /// assert_eq!("🗻", v.get_unchecked(0..4)); + /// assert_eq!("∈", v.get_unchecked(4..7)); + /// assert_eq!("🌏", v.get_unchecked(7..11)); + /// } + /// ``` + #[stable(feature = "str_checked_slicing", since = "1.20.0")] + #[inline] + pub unsafe fn get_unchecked>(&self, i: I) -> &I::Output { + core_str::StrExt::get_unchecked(self, i) + } + + /// Returns a mutable, unchecked subslice of `str`. + /// + /// This is the unchecked alternative to indexing the `str`. + /// + /// # Safety + /// + /// Callers of this function are responsible that these preconditions are + /// satisfied: + /// + /// * The starting index must come before the ending index; + /// * Indexes must be within bounds of the original slice; + /// * Indexes must lie on UTF-8 sequence boundaries. + /// + /// Failing that, the returned string slice may reference invalid memory or + /// violate the invariants communicated by the `str` type. + /// + /// # Examples + /// + /// ``` + /// let mut v = String::from("🗻∈🌏"); + /// unsafe { + /// assert_eq!("🗻", v.get_unchecked_mut(0..4)); + /// assert_eq!("∈", v.get_unchecked_mut(4..7)); + /// assert_eq!("🌏", v.get_unchecked_mut(7..11)); + /// } + /// ``` + #[stable(feature = "str_checked_slicing", since = "1.20.0")] + #[inline] + pub unsafe fn get_unchecked_mut>(&mut self, i: I) -> &mut I::Output { + core_str::StrExt::get_unchecked_mut(self, i) + } + + /// Creates a string slice from another string slice, bypassing safety + /// checks. + /// + /// This is generally not recommended, use with caution! For a safe + /// alternative see [`str`] and [`Index`]. + /// + /// [`str`]: primitive.str.html + /// [`Index`]: ops/trait.Index.html + /// + /// This new slice goes from `begin` to `end`, including `begin` but + /// excluding `end`. + /// + /// To get a mutable string slice instead, see the + /// [`slice_mut_unchecked`] method. + /// + /// [`slice_mut_unchecked`]: #method.slice_mut_unchecked + /// + /// # Safety + /// + /// Callers of this function are responsible that three preconditions are + /// satisfied: + /// + /// * `begin` must come before `end`. + /// * `begin` and `end` must be byte positions within the string slice. + /// * `begin` and `end` must lie on UTF-8 sequence boundaries. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// unsafe { + /// assert_eq!("Löwe 老虎 Léopard", s.slice_unchecked(0, 21)); + /// } + /// + /// let s = "Hello, world!"; + /// + /// unsafe { + /// assert_eq!("world", s.slice_unchecked(7, 12)); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str { + core_str::StrExt::slice_unchecked(self, begin, end) + } + + /// Creates a string slice from another string slice, bypassing safety + /// checks. + /// This is generally not recommended, use with caution! For a safe + /// alternative see [`str`] and [`IndexMut`]. + /// + /// [`str`]: primitive.str.html + /// [`IndexMut`]: ops/trait.IndexMut.html + /// + /// This new slice goes from `begin` to `end`, including `begin` but + /// excluding `end`. + /// + /// To get an immutable string slice instead, see the + /// [`slice_unchecked`] method. + /// + /// [`slice_unchecked`]: #method.slice_unchecked + /// + /// # Safety + /// + /// Callers of this function are responsible that three preconditions are + /// satisfied: + /// + /// * `begin` must come before `end`. + /// * `begin` and `end` must be byte positions within the string slice. + /// * `begin` and `end` must lie on UTF-8 sequence boundaries. + #[stable(feature = "str_slice_mut", since = "1.5.0")] + #[inline] + pub unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str { + core_str::StrExt::slice_mut_unchecked(self, begin, end) + } + + /// Divide one string slice into two at an index. + /// + /// The argument, `mid`, should be a byte offset from the start of the + /// string. It must also be on the boundary of a UTF-8 code point. + /// + /// The two slices returned go from the start of the string slice to `mid`, + /// and from `mid` to the end of the string slice. + /// + /// To get mutable string slices instead, see the [`split_at_mut`] + /// method. + /// + /// [`split_at_mut`]: #method.split_at_mut + /// + /// # Panics + /// + /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is + /// beyond the last code point of the string slice. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "Per Martin-Löf"; + /// + /// let (first, last) = s.split_at(3); + /// + /// assert_eq!("Per", first); + /// assert_eq!(" Martin-Löf", last); + /// ``` + #[inline] + #[stable(feature = "str_split_at", since = "1.4.0")] + pub fn split_at(&self, mid: usize) -> (&str, &str) { + core_str::StrExt::split_at(self, mid) + } + + /// Divide one mutable string slice into two at an index. + /// + /// The argument, `mid`, should be a byte offset from the start of the + /// string. It must also be on the boundary of a UTF-8 code point. + /// + /// The two slices returned go from the start of the string slice to `mid`, + /// and from `mid` to the end of the string slice. + /// + /// To get immutable string slices instead, see the [`split_at`] method. + /// + /// [`split_at`]: #method.split_at + /// + /// # Panics + /// + /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is + /// beyond the last code point of the string slice. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = "Per Martin-Löf".to_string(); + /// + /// let (first, last) = s.split_at_mut(3); + /// + /// assert_eq!("Per", first); + /// assert_eq!(" Martin-Löf", last); + /// ``` + #[inline] + #[stable(feature = "str_split_at", since = "1.4.0")] + pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) { + core_str::StrExt::split_at_mut(self, mid) + } + + /// Returns an iterator over the [`char`]s of a string slice. + /// + /// As a string slice consists of valid UTF-8, we can iterate through a + /// string slice by [`char`]. This method returns such an iterator. + /// + /// It's important to remember that [`char`] represents a Unicode Scalar + /// Value, and may not match your idea of what a 'character' is. Iteration + /// over grapheme clusters may be what you actually want. + /// + /// [`char`]: primitive.char.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let word = "goodbye"; + /// + /// let count = word.chars().count(); + /// assert_eq!(7, count); + /// + /// let mut chars = word.chars(); + /// + /// assert_eq!(Some('g'), chars.next()); + /// assert_eq!(Some('o'), chars.next()); + /// assert_eq!(Some('o'), chars.next()); + /// assert_eq!(Some('d'), chars.next()); + /// assert_eq!(Some('b'), chars.next()); + /// assert_eq!(Some('y'), chars.next()); + /// assert_eq!(Some('e'), chars.next()); + /// + /// assert_eq!(None, chars.next()); + /// ``` + /// + /// Remember, [`char`]s may not match your human intuition about characters: + /// + /// ``` + /// let y = "y̆"; + /// + /// let mut chars = y.chars(); + /// + /// assert_eq!(Some('y'), chars.next()); // not 'y̆' + /// assert_eq!(Some('\u{0306}'), chars.next()); + /// + /// assert_eq!(None, chars.next()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn chars(&self) -> Chars { + core_str::StrExt::chars(self) + } + /// Returns an iterator over the [`char`]s of a string slice, and their + /// positions. + /// + /// As a string slice consists of valid UTF-8, we can iterate through a + /// string slice by [`char`]. This method returns an iterator of both + /// these [`char`]s, as well as their byte positions. + /// + /// The iterator yields tuples. The position is first, the [`char`] is + /// second. + /// + /// [`char`]: primitive.char.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let word = "goodbye"; + /// + /// let count = word.char_indices().count(); + /// assert_eq!(7, count); + /// + /// let mut char_indices = word.char_indices(); + /// + /// assert_eq!(Some((0, 'g')), char_indices.next()); + /// assert_eq!(Some((1, 'o')), char_indices.next()); + /// assert_eq!(Some((2, 'o')), char_indices.next()); + /// assert_eq!(Some((3, 'd')), char_indices.next()); + /// assert_eq!(Some((4, 'b')), char_indices.next()); + /// assert_eq!(Some((5, 'y')), char_indices.next()); + /// assert_eq!(Some((6, 'e')), char_indices.next()); + /// + /// assert_eq!(None, char_indices.next()); + /// ``` + /// + /// Remember, [`char`]s may not match your human intuition about characters: + /// + /// ``` + /// let y = "y̆"; + /// + /// let mut char_indices = y.char_indices(); + /// + /// assert_eq!(Some((0, 'y')), char_indices.next()); // not (0, 'y̆') + /// assert_eq!(Some((1, '\u{0306}')), char_indices.next()); + /// + /// assert_eq!(None, char_indices.next()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn char_indices(&self) -> CharIndices { + core_str::StrExt::char_indices(self) + } + + /// An iterator over the bytes of a string slice. + /// + /// As a string slice consists of a sequence of bytes, we can iterate + /// through a string slice by byte. This method returns such an iterator. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut bytes = "bors".bytes(); + /// + /// assert_eq!(Some(b'b'), bytes.next()); + /// assert_eq!(Some(b'o'), bytes.next()); + /// assert_eq!(Some(b'r'), bytes.next()); + /// assert_eq!(Some(b's'), bytes.next()); + /// + /// assert_eq!(None, bytes.next()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn bytes(&self) -> Bytes { + core_str::StrExt::bytes(self) + } + + /// Split a string slice by whitespace. + /// + /// The iterator returned will return string slices that are sub-slices of + /// the original string slice, separated by any amount of whitespace. + /// + /// 'Whitespace' is defined according to the terms of the Unicode Derived + /// Core Property `White_Space`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut iter = "A few words".split_whitespace(); + /// + /// assert_eq!(Some("A"), iter.next()); + /// assert_eq!(Some("few"), iter.next()); + /// assert_eq!(Some("words"), iter.next()); + /// + /// assert_eq!(None, iter.next()); + /// ``` + /// + /// All kinds of whitespace are considered: + /// + /// ``` + /// let mut iter = " Mary had\ta\u{2009}little \n\t lamb".split_whitespace(); + /// assert_eq!(Some("Mary"), iter.next()); + /// assert_eq!(Some("had"), iter.next()); + /// assert_eq!(Some("a"), iter.next()); + /// assert_eq!(Some("little"), iter.next()); + /// assert_eq!(Some("lamb"), iter.next()); + /// + /// assert_eq!(None, iter.next()); + /// ``` + #[stable(feature = "split_whitespace", since = "1.1.0")] + #[inline] + pub fn split_whitespace(&self) -> SplitWhitespace { + UnicodeStr::split_whitespace(self) + } + + /// An iterator over the lines of a string, as string slices. + /// + /// Lines are ended with either a newline (`\n`) or a carriage return with + /// a line feed (`\r\n`). + /// + /// The final line ending is optional. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let text = "foo\r\nbar\n\nbaz\n"; + /// let mut lines = text.lines(); + /// + /// assert_eq!(Some("foo"), lines.next()); + /// assert_eq!(Some("bar"), lines.next()); + /// assert_eq!(Some(""), lines.next()); + /// assert_eq!(Some("baz"), lines.next()); + /// + /// assert_eq!(None, lines.next()); + /// ``` + /// + /// The final line ending isn't required: + /// + /// ``` + /// let text = "foo\nbar\n\r\nbaz"; + /// let mut lines = text.lines(); + /// + /// assert_eq!(Some("foo"), lines.next()); + /// assert_eq!(Some("bar"), lines.next()); + /// assert_eq!(Some(""), lines.next()); + /// assert_eq!(Some("baz"), lines.next()); + /// + /// assert_eq!(None, lines.next()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn lines(&self) -> Lines { + core_str::StrExt::lines(self) + } + + /// An iterator over the lines of a string. + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_deprecated(since = "1.4.0", reason = "use lines() instead now")] + #[inline] + #[allow(deprecated)] + pub fn lines_any(&self) -> LinesAny { + core_str::StrExt::lines_any(self) + } + + /// Returns an iterator of `u16` over the string encoded as UTF-16. + #[stable(feature = "encode_utf16", since = "1.8.0")] + pub fn encode_utf16(&self) -> EncodeUtf16 { + EncodeUtf16 { encoder: Utf16Encoder::new(self[..].chars()) } + } + + /// Returns `true` if the given pattern matches a sub-slice of + /// this string slice. + /// + /// Returns `false` if it does not. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let bananas = "bananas"; + /// + /// assert!(bananas.contains("nana")); + /// assert!(!bananas.contains("apples")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { + core_str::StrExt::contains(self, pat) + } + + /// Returns `true` if the given pattern matches a prefix of this + /// string slice. + /// + /// Returns `false` if it does not. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let bananas = "bananas"; + /// + /// assert!(bananas.starts_with("bana")); + /// assert!(!bananas.starts_with("nana")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { + core_str::StrExt::starts_with(self, pat) + } + + /// Returns `true` if the given pattern matches a suffix of this + /// string slice. + /// + /// Returns `false` if it does not. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let bananas = "bananas"; + /// + /// assert!(bananas.ends_with("anas")); + /// assert!(!bananas.ends_with("nana")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::ends_with(self, pat) + } + + /// Returns the byte index of the first character of this string slice that + /// matches the pattern. + /// + /// Returns [`None`] if the pattern doesn't match. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines if + /// a character matches. + /// + /// [`char`]: primitive.char.html + /// [`None`]: option/enum.Option.html#variant.None + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.find('L'), Some(0)); + /// assert_eq!(s.find('é'), Some(14)); + /// assert_eq!(s.find("Léopard"), Some(13)); + /// ``` + /// + /// More complex patterns with closures: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.find(char::is_whitespace), Some(5)); + /// assert_eq!(s.find(char::is_lowercase), Some(1)); + /// ``` + /// + /// Not finding the pattern: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// let x: &[_] = &['1', '2']; + /// + /// assert_eq!(s.find(x), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option { + core_str::StrExt::find(self, pat) + } + + /// Returns the byte index of the last character of this string slice that + /// matches the pattern. + /// + /// Returns [`None`] if the pattern doesn't match. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines if + /// a character matches. + /// + /// [`char`]: primitive.char.html + /// [`None`]: option/enum.Option.html#variant.None + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.rfind('L'), Some(13)); + /// assert_eq!(s.rfind('é'), Some(14)); + /// ``` + /// + /// More complex patterns with closures: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.rfind(char::is_whitespace), Some(12)); + /// assert_eq!(s.rfind(char::is_lowercase), Some(20)); + /// ``` + /// + /// Not finding the pattern: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// let x: &[_] = &['1', '2']; + /// + /// assert_eq!(s.rfind(x), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::rfind(self, pat) + } + + /// An iterator over substrings of this string slice, separated by + /// characters matched by a pattern. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines the + /// split. + /// + /// # Iterator behavior + /// + /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern + /// allows a reverse search and forward/reverse search yields the same + /// elements. This is true for, eg, [`char`] but not for `&str`. + /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// + /// If the pattern allows a reverse search but its results might differ + /// from a forward search, the [`rsplit`] method can be used. + /// + /// [`char`]: primitive.char.html + /// [`rsplit`]: #method.rsplit + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect(); + /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]); + /// + /// let v: Vec<&str> = "".split('X').collect(); + /// assert_eq!(v, [""]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect(); + /// assert_eq!(v, ["lion", "", "tiger", "leopard"]); + /// + /// let v: Vec<&str> = "lion::tiger::leopard".split("::").collect(); + /// assert_eq!(v, ["lion", "tiger", "leopard"]); + /// + /// let v: Vec<&str> = "abc1def2ghi".split(char::is_numeric).collect(); + /// assert_eq!(v, ["abc", "def", "ghi"]); + /// + /// let v: Vec<&str> = "lionXtigerXleopard".split(char::is_uppercase).collect(); + /// assert_eq!(v, ["lion", "tiger", "leopard"]); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// let v: Vec<&str> = "abc1defXghi".split(|c| c == '1' || c == 'X').collect(); + /// assert_eq!(v, ["abc", "def", "ghi"]); + /// ``` + /// + /// If a string contains multiple contiguous separators, you will end up + /// with empty strings in the output: + /// + /// ``` + /// let x = "||||a||b|c".to_string(); + /// let d: Vec<_> = x.split('|').collect(); + /// + /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]); + /// ``` + /// + /// Contiguous separators are separated by the empty string. + /// + /// ``` + /// let x = "(///)".to_string(); + /// let d: Vec<_> = x.split('/').collect(); + /// + /// assert_eq!(d, &["(", "", "", ")"]); + /// ``` + /// + /// Separators at the start or end of a string are neighbored + /// by empty strings. + /// + /// ``` + /// let d: Vec<_> = "010".split("0").collect(); + /// assert_eq!(d, &["", "1", ""]); + /// ``` + /// + /// When the empty string is used as a separator, it separates + /// every character in the string, along with the beginning + /// and end of the string. + /// + /// ``` + /// let f: Vec<_> = "rust".split("").collect(); + /// assert_eq!(f, &["", "r", "u", "s", "t", ""]); + /// ``` + /// + /// Contiguous separators can lead to possibly surprising behavior + /// when whitespace is used as the separator. This code is correct: + /// + /// ``` + /// let x = " a b c".to_string(); + /// let d: Vec<_> = x.split(' ').collect(); + /// + /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]); + /// ``` + /// + /// It does _not_ give you: + /// + /// ```,ignore + /// assert_eq!(d, &["a", "b", "c"]); + /// ``` + /// + /// Use [`split_whitespace`] for this behavior. + /// + /// [`split_whitespace`]: #method.split_whitespace + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> { + core_str::StrExt::split(self, pat) + } + + /// An iterator over substrings of the given string slice, separated by + /// characters matched by a pattern and yielded in reverse order. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines the + /// split. + /// + /// [`char`]: primitive.char.html + /// + /// # Iterator behavior + /// + /// The returned iterator requires that the pattern supports a reverse + /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse + /// search yields the same elements. + /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// + /// For iterating from the front, the [`split`] method can be used. + /// + /// [`split`]: #method.split + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lamb".rsplit(' ').collect(); + /// assert_eq!(v, ["lamb", "little", "a", "had", "Mary"]); + /// + /// let v: Vec<&str> = "".rsplit('X').collect(); + /// assert_eq!(v, [""]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".rsplit('X').collect(); + /// assert_eq!(v, ["leopard", "tiger", "", "lion"]); + /// + /// let v: Vec<&str> = "lion::tiger::leopard".rsplit("::").collect(); + /// assert_eq!(v, ["leopard", "tiger", "lion"]); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// let v: Vec<&str> = "abc1defXghi".rsplit(|c| c == '1' || c == 'X').collect(); + /// assert_eq!(v, ["ghi", "def", "abc"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P> + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::rsplit(self, pat) + } + + /// An iterator over substrings of the given string slice, separated by + /// characters matched by a pattern. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines the + /// split. + /// + /// Equivalent to [`split`], except that the trailing substring + /// is skipped if empty. + /// + /// [`split`]: #method.split + /// + /// This method can be used for string data that is _terminated_, + /// rather than _separated_ by a pattern. + /// + /// # Iterator behavior + /// + /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern + /// allows a reverse search and forward/reverse search yields the same + /// elements. This is true for, eg, [`char`] but not for `&str`. + /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// [`char`]: primitive.char.html + /// + /// If the pattern allows a reverse search but its results might differ + /// from a forward search, the [`rsplit_terminator`] method can be used. + /// + /// [`rsplit_terminator`]: #method.rsplit_terminator + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let v: Vec<&str> = "A.B.".split_terminator('.').collect(); + /// assert_eq!(v, ["A", "B"]); + /// + /// let v: Vec<&str> = "A..B..".split_terminator(".").collect(); + /// assert_eq!(v, ["A", "", "B", ""]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> { + core_str::StrExt::split_terminator(self, pat) + } + + /// An iterator over substrings of `self`, separated by characters + /// matched by a pattern and yielded in reverse order. + /// + /// The pattern can be a simple `&str`, [`char`], or a closure that + /// determines the split. + /// Additional libraries might provide more complex patterns like + /// regular expressions. + /// + /// [`char`]: primitive.char.html + /// + /// Equivalent to [`split`], except that the trailing substring is + /// skipped if empty. + /// + /// [`split`]: #method.split + /// + /// This method can be used for string data that is _terminated_, + /// rather than _separated_ by a pattern. + /// + /// # Iterator behavior + /// + /// The returned iterator requires that the pattern supports a + /// reverse search, and it will be double ended if a forward/reverse + /// search yields the same elements. + /// + /// For iterating from the front, the [`split_terminator`] method can be + /// used. + /// + /// [`split_terminator`]: #method.split_terminator + /// + /// # Examples + /// + /// ``` + /// let v: Vec<&str> = "A.B.".rsplit_terminator('.').collect(); + /// assert_eq!(v, ["B", "A"]); + /// + /// let v: Vec<&str> = "A..B..".rsplit_terminator(".").collect(); + /// assert_eq!(v, ["", "B", "", "A"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rsplit_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplitTerminator<'a, P> + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::rsplit_terminator(self, pat) + } + + /// An iterator over substrings of the given string slice, separated by a + /// pattern, restricted to returning at most `n` items. + /// + /// If `n` substrings are returned, the last substring (the `n`th substring) + /// will contain the remainder of the string. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines the + /// split. + /// + /// [`char`]: primitive.char.html + /// + /// # Iterator behavior + /// + /// The returned iterator will not be double ended, because it is + /// not efficient to support. + /// + /// If the pattern allows a reverse search, the [`rsplitn`] method can be + /// used. + /// + /// [`rsplitn`]: #method.rsplitn + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lambda".splitn(3, ' ').collect(); + /// assert_eq!(v, ["Mary", "had", "a little lambda"]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(3, "X").collect(); + /// assert_eq!(v, ["lion", "", "tigerXleopard"]); + /// + /// let v: Vec<&str> = "abcXdef".splitn(1, 'X').collect(); + /// assert_eq!(v, ["abcXdef"]); + /// + /// let v: Vec<&str> = "".splitn(1, 'X').collect(); + /// assert_eq!(v, [""]); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// let v: Vec<&str> = "abc1defXghi".splitn(2, |c| c == '1' || c == 'X').collect(); + /// assert_eq!(v, ["abc", "defXghi"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn splitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> SplitN<'a, P> { + core_str::StrExt::splitn(self, n, pat) + } + + /// An iterator over substrings of this string slice, separated by a + /// pattern, starting from the end of the string, restricted to returning + /// at most `n` items. + /// + /// If `n` substrings are returned, the last substring (the `n`th substring) + /// will contain the remainder of the string. + /// + /// The pattern can be a `&str`, [`char`], or a closure that + /// determines the split. + /// + /// [`char`]: primitive.char.html + /// + /// # Iterator behavior + /// + /// The returned iterator will not be double ended, because it is not + /// efficient to support. + /// + /// For splitting from the front, the [`splitn`] method can be used. + /// + /// [`splitn`]: #method.splitn + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(3, ' ').collect(); + /// assert_eq!(v, ["lamb", "little", "Mary had a"]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(3, 'X').collect(); + /// assert_eq!(v, ["leopard", "tiger", "lionX"]); + /// + /// let v: Vec<&str> = "lion::tiger::leopard".rsplitn(2, "::").collect(); + /// assert_eq!(v, ["leopard", "lion::tiger"]); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// let v: Vec<&str> = "abc1defXghi".rsplitn(2, |c| c == '1' || c == 'X').collect(); + /// assert_eq!(v, ["ghi", "abc1def"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> RSplitN<'a, P> + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::rsplitn(self, n, pat) + } + + /// An iterator over the disjoint matches of a pattern within the given string + /// slice. + /// + /// The pattern can be a `&str`, [`char`], or a closure that + /// determines if a character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Iterator behavior + /// + /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern + /// allows a reverse search and forward/reverse search yields the same + /// elements. This is true for, eg, [`char`] but not for `&str`. + /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// [`char`]: primitive.char.html + /// + /// If the pattern allows a reverse search but its results might differ + /// from a forward search, the [`rmatches`] method can be used. + /// + /// [`rmatches`]: #method.rmatches + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let v: Vec<&str> = "abcXXXabcYYYabc".matches("abc").collect(); + /// assert_eq!(v, ["abc", "abc", "abc"]); + /// + /// let v: Vec<&str> = "1abc2abc3".matches(char::is_numeric).collect(); + /// assert_eq!(v, ["1", "2", "3"]); + /// ``` + #[stable(feature = "str_matches", since = "1.2.0")] + #[inline] + pub fn matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> Matches<'a, P> { + core_str::StrExt::matches(self, pat) + } + + /// An iterator over the disjoint matches of a pattern within this string slice, + /// yielded in reverse order. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines if + /// a character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Iterator behavior + /// + /// The returned iterator requires that the pattern supports a reverse + /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse + /// search yields the same elements. + /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// + /// For iterating from the front, the [`matches`] method can be used. + /// + /// [`matches`]: #method.matches + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let v: Vec<&str> = "abcXXXabcYYYabc".rmatches("abc").collect(); + /// assert_eq!(v, ["abc", "abc", "abc"]); + /// + /// let v: Vec<&str> = "1abc2abc3".rmatches(char::is_numeric).collect(); + /// assert_eq!(v, ["3", "2", "1"]); + /// ``` + #[stable(feature = "str_matches", since = "1.2.0")] + #[inline] + pub fn rmatches<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatches<'a, P> + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::rmatches(self, pat) + } + + /// An iterator over the disjoint matches of a pattern within this string + /// slice as well as the index that the match starts at. + /// + /// For matches of `pat` within `self` that overlap, only the indices + /// corresponding to the first match are returned. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines + /// if a character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Iterator behavior + /// + /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern + /// allows a reverse search and forward/reverse search yields the same + /// elements. This is true for, eg, [`char`] but not for `&str`. + /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// + /// If the pattern allows a reverse search but its results might differ + /// from a forward search, the [`rmatch_indices`] method can be used. + /// + /// [`rmatch_indices`]: #method.rmatch_indices + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let v: Vec<_> = "abcXXXabcYYYabc".match_indices("abc").collect(); + /// assert_eq!(v, [(0, "abc"), (6, "abc"), (12, "abc")]); + /// + /// let v: Vec<_> = "1abcabc2".match_indices("abc").collect(); + /// assert_eq!(v, [(1, "abc"), (4, "abc")]); + /// + /// let v: Vec<_> = "ababa".match_indices("aba").collect(); + /// assert_eq!(v, [(0, "aba")]); // only the first `aba` + /// ``` + #[stable(feature = "str_match_indices", since = "1.5.0")] + #[inline] + pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> { + core_str::StrExt::match_indices(self, pat) + } + + /// An iterator over the disjoint matches of a pattern within `self`, + /// yielded in reverse order along with the index of the match. + /// + /// For matches of `pat` within `self` that overlap, only the indices + /// corresponding to the last match are returned. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines if a + /// character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Iterator behavior + /// + /// The returned iterator requires that the pattern supports a reverse + /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse + /// search yields the same elements. + /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// + /// For iterating from the front, the [`match_indices`] method can be used. + /// + /// [`match_indices`]: #method.match_indices + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let v: Vec<_> = "abcXXXabcYYYabc".rmatch_indices("abc").collect(); + /// assert_eq!(v, [(12, "abc"), (6, "abc"), (0, "abc")]); + /// + /// let v: Vec<_> = "1abcabc2".rmatch_indices("abc").collect(); + /// assert_eq!(v, [(4, "abc"), (1, "abc")]); + /// + /// let v: Vec<_> = "ababa".rmatch_indices("aba").collect(); + /// assert_eq!(v, [(2, "aba")]); // only the last `aba` + /// ``` + #[stable(feature = "str_match_indices", since = "1.5.0")] + #[inline] + pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P> + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::rmatch_indices(self, pat) + } + + /// Returns a string slice with leading and trailing whitespace removed. + /// + /// 'Whitespace' is defined according to the terms of the Unicode Derived + /// Core Property `White_Space`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// + /// assert_eq!("Hello\tworld", s.trim()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim(&self) -> &str { + UnicodeStr::trim(self) + } + + /// Returns a string slice with leading whitespace removed. + /// + /// 'Whitespace' is defined according to the terms of the Unicode Derived + /// Core Property `White_Space`. + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. 'Left' in this context means the first + /// position of that byte string; for a language like Arabic or Hebrew + /// which are 'right to left' rather than 'left to right', this will be + /// the _right_ side, not the left. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// + /// assert_eq!("Hello\tworld\t", s.trim_left()); + /// ``` + /// + /// Directionality: + /// + /// ``` + /// let s = " English"; + /// assert!(Some('E') == s.trim_left().chars().next()); + /// + /// let s = " עברית"; + /// assert!(Some('ע') == s.trim_left().chars().next()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_left(&self) -> &str { + UnicodeStr::trim_left(self) + } + + /// Returns a string slice with trailing whitespace removed. + /// + /// 'Whitespace' is defined according to the terms of the Unicode Derived + /// Core Property `White_Space`. + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. 'Right' in this context means the last + /// position of that byte string; for a language like Arabic or Hebrew + /// which are 'right to left' rather than 'left to right', this will be + /// the _left_ side, not the right. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// + /// assert_eq!(" Hello\tworld", s.trim_right()); + /// ``` + /// + /// Directionality: + /// + /// ``` + /// let s = "English "; + /// assert!(Some('h') == s.trim_right().chars().rev().next()); + /// + /// let s = "עברית "; + /// assert!(Some('ת') == s.trim_right().chars().rev().next()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_right(&self) -> &str { + UnicodeStr::trim_right(self) + } + + /// Returns a string slice with all prefixes and suffixes that match a + /// pattern repeatedly removed. + /// + /// The pattern can be a [`char`] or a closure that determines if a + /// character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar"); + /// assert_eq!("123foo1bar123".trim_matches(char::is_numeric), "foo1bar"); + /// + /// let x: &[_] = &['1', '2']; + /// assert_eq!("12foo1bar12".trim_matches(x), "foo1bar"); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// assert_eq!("1foo1barXX".trim_matches(|c| c == '1' || c == 'X'), "foo1bar"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str + where P::Searcher: DoubleEndedSearcher<'a> + { + core_str::StrExt::trim_matches(self, pat) + } + + /// Returns a string slice with all prefixes that match a pattern + /// repeatedly removed. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines if + /// a character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. 'Left' in this context means the first + /// position of that byte string; for a language like Arabic or Hebrew + /// which are 'right to left' rather than 'left to right', this will be + /// the _right_ side, not the left. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11"); + /// assert_eq!("123foo1bar123".trim_left_matches(char::is_numeric), "foo1bar123"); + /// + /// let x: &[_] = &['1', '2']; + /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str { + core_str::StrExt::trim_left_matches(self, pat) + } + + /// Returns a string slice with all suffixes that match a pattern + /// repeatedly removed. + /// + /// The pattern can be a `&str`, [`char`], or a closure that + /// determines if a character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. 'Right' in this context means the last + /// position of that byte string; for a language like Arabic or Hebrew + /// which are 'right to left' rather than 'left to right', this will be + /// the _left_ side, not the right. + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar"); + /// assert_eq!("123foo1bar123".trim_right_matches(char::is_numeric), "123foo1bar"); + /// + /// let x: &[_] = &['1', '2']; + /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar"); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// assert_eq!("1fooX".trim_left_matches(|c| c == '1' || c == 'X'), "fooX"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::trim_right_matches(self, pat) + } + + /// Parses this string slice into another type. + /// + /// Because `parse` is so general, it can cause problems with type + /// inference. As such, `parse` is one of the few times you'll see + /// the syntax affectionately known as the 'turbofish': `::<>`. This + /// helps the inference algorithm understand specifically which type + /// you're trying to parse into. + /// + /// `parse` can parse any type that implements the [`FromStr`] trait. + /// + /// [`FromStr`]: str/trait.FromStr.html + /// + /// # Errors + /// + /// Will return [`Err`] if it's not possible to parse this string slice into + /// the desired type. + /// + /// [`Err`]: str/trait.FromStr.html#associatedtype.Err + /// + /// # Example + /// + /// Basic usage + /// + /// ``` + /// let four: u32 = "4".parse().unwrap(); + /// + /// assert_eq!(4, four); + /// ``` + /// + /// Using the 'turbofish' instead of annotating `four`: + /// + /// ``` + /// let four = "4".parse::(); + /// + /// assert_eq!(Ok(4), four); + /// ``` + /// + /// Failing to parse: + /// + /// ``` + /// let nope = "j".parse::(); + /// + /// assert!(nope.is_err()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn parse(&self) -> Result { + core_str::StrExt::parse(self) + } + + /// Converts a `Box` into a `Box<[u8]>` without copying or allocating. + #[stable(feature = "str_box_extras", since = "1.20.0")] + pub fn into_boxed_bytes(self: Box) -> Box<[u8]> { + self.into() + } + + /// Replaces all matches of a pattern with another string. + /// + /// `replace` creates a new [`String`], and copies the data from this string slice into it. + /// While doing so, it attempts to find matches of a pattern. If it finds any, it + /// replaces them with the replacement string slice. + /// + /// [`String`]: string/struct.String.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "this is old"; + /// + /// assert_eq!("this is new", s.replace("old", "new")); + /// ``` + /// + /// When the pattern doesn't match: + /// + /// ``` + /// let s = "this is old"; + /// assert_eq!(s, s.replace("cookie monster", "little lamb")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn replace<'a, P: Pattern<'a>>(&'a self, from: P, to: &str) -> String { + let mut result = String::new(); + let mut last_end = 0; + for (start, part) in self.match_indices(from) { + result.push_str(unsafe { self.slice_unchecked(last_end, start) }); + result.push_str(to); + last_end = start + part.len(); + } + result.push_str(unsafe { self.slice_unchecked(last_end, self.len()) }); + result + } + + /// Replaces first N matches of a pattern with another string. + /// + /// `replacen` creates a new [`String`], and copies the data from this string slice into it. + /// While doing so, it attempts to find matches of a pattern. If it finds any, it + /// replaces them with the replacement string slice at most `count` times. + /// + /// [`String`]: string/struct.String.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// 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)); + /// assert_eq!("foo foo new23 foo", s.replacen(char::is_numeric, "new", 1)); + /// ``` + /// + /// When the pattern doesn't match: + /// + /// ``` + /// let s = "this is old"; + /// assert_eq!(s, s.replacen("cookie monster", "little lamb", 10)); + /// ``` + #[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); + let mut last_end = 0; + for (start, part) in self.match_indices(pat).take(count) { + result.push_str(unsafe { self.slice_unchecked(last_end, start) }); + result.push_str(to); + last_end = start + part.len(); + } + result.push_str(unsafe { self.slice_unchecked(last_end, self.len()) }); + result + } + + /// Returns the lowercase equivalent of this string slice, as a new [`String`]. + /// + /// 'Lowercase' is defined according to the terms of the Unicode Derived Core Property + /// `Lowercase`. + /// + /// Since some characters can expand into multiple characters when changing + /// the case, this function returns a [`String`] instead of modifying the + /// parameter in-place. + /// + /// [`String`]: string/struct.String.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "HELLO"; + /// + /// assert_eq!("hello", s.to_lowercase()); + /// ``` + /// + /// A tricky example, with sigma: + /// + /// ``` + /// let sigma = "Σ"; + /// + /// assert_eq!("σ", sigma.to_lowercase()); + /// + /// // but at the end of a word, it's ς, not σ: + /// let odysseus = "ὈΔΥΣΣΕΎΣ"; + /// + /// assert_eq!("ὀδυσσεύς", odysseus.to_lowercase()); + /// ``` + /// + /// Languages without case are not changed: + /// + /// ``` + /// let new_year = "农历新年"; + /// + /// assert_eq!(new_year, new_year.to_lowercase()); + /// ``` + #[stable(feature = "unicode_case_mapping", since = "1.2.0")] + pub fn to_lowercase(&self) -> String { + let mut s = String::with_capacity(self.len()); + for (i, c) in self[..].char_indices() { + if c == 'Σ' { + // Σ maps to σ, except at the end of a word where it maps to ς. + // This is the only conditional (contextual) but language-independent mapping + // in `SpecialCasing.txt`, + // so hard-code it rather than have a generic "condition" mechanism. + // See https://github.com/rust-lang/rust/issues/26035 + map_uppercase_sigma(self, i, &mut s) + } else { + s.extend(c.to_lowercase()); + } + } + return s; + + fn map_uppercase_sigma(from: &str, i: usize, to: &mut String) { + // See http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992 + // for the definition of `Final_Sigma`. + 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 { "σ" }); + } + + fn case_ignoreable_then_cased>(iter: I) -> bool { + use std_unicode::derived_property::{Cased, Case_Ignorable}; + match iter.skip_while(|&c| Case_Ignorable(c)).next() { + Some(c) => Cased(c), + None => false, + } + } + } + + /// Returns the uppercase equivalent of this string slice, as a new [`String`]. + /// + /// 'Uppercase' is defined according to the terms of the Unicode Derived Core Property + /// `Uppercase`. + /// + /// Since some characters can expand into multiple characters when changing + /// the case, this function returns a [`String`] instead of modifying the + /// parameter in-place. + /// + /// [`String`]: string/struct.String.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "hello"; + /// + /// assert_eq!("HELLO", s.to_uppercase()); + /// ``` + /// + /// Scripts without case are not changed: + /// + /// ``` + /// let new_year = "农历新年"; + /// + /// assert_eq!(new_year, new_year.to_uppercase()); + /// ``` + #[stable(feature = "unicode_case_mapping", since = "1.2.0")] + pub fn to_uppercase(&self) -> String { + let mut s = String::with_capacity(self.len()); + s.extend(self.chars().flat_map(|c| c.to_uppercase())); + return s; + } + + /// Escapes each char in `s` with [`char::escape_debug`]. + /// + /// [`char::escape_debug`]: primitive.char.html#method.escape_debug + #[unstable(feature = "str_escape", + reason = "return type may change to be an iterator", + issue = "27791")] + pub fn escape_debug(&self) -> String { + self.chars().flat_map(|c| c.escape_debug()).collect() + } + + /// Escapes each char in `s` with [`char::escape_default`]. + /// + /// [`char::escape_default`]: primitive.char.html#method.escape_default + #[unstable(feature = "str_escape", + reason = "return type may change to be an iterator", + issue = "27791")] + pub fn escape_default(&self) -> String { + self.chars().flat_map(|c| c.escape_default()).collect() + } + + /// Escapes each char in `s` with [`char::escape_unicode`]. + /// + /// [`char::escape_unicode`]: primitive.char.html#method.escape_unicode + #[unstable(feature = "str_escape", + reason = "return type may change to be an iterator", + issue = "27791")] + pub fn escape_unicode(&self) -> String { + self.chars().flat_map(|c| c.escape_unicode()).collect() + } + + /// Converts a [`Box`] into a [`String`] without copying or allocating. + /// + /// [`String`]: string/struct.String.html + /// [`Box`]: boxed/struct.Box.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let string = String::from("birthday gift"); + /// let boxed_str = string.clone().into_boxed_str(); + /// + /// assert_eq!(boxed_str.into_string(), string); + /// ``` + #[stable(feature = "box_str", since = "1.4.0")] + pub fn into_string(self: Box) -> String { + unsafe { + let slice = mem::transmute::, Box<[u8]>>(self); + String::from_utf8_unchecked(slice.into_vec()) + } + } + + /// Create a [`String`] by repeating a string `n` times. + /// + /// [`String`]: string/struct.String.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!("abc".repeat(4), String::from("abcabcabcabc")); + /// ``` + #[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)); + s + } +} + /// Converts a boxed slice of bytes to a boxed string slice without checking /// that the string contains valid UTF-8. -#[unstable(feature = "str_box_extras", issue = "41119")] +#[stable(feature = "str_box_extras", since = "1.20.0")] pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box { mem::transmute(v) } diff --git a/src/libcollections/string.rs b/src/liballoc/string.rs similarity index 93% rename from src/libcollections/string.rs rename to src/liballoc/string.rs index 55f0e01548..622cc68964 100644 --- a/src/libcollections/string.rs +++ b/src/liballoc/string.rs @@ -56,21 +56,19 @@ #![stable(feature = "rust1", since = "1.0.0")] -use alloc::str as alloc_str; - use core::fmt; use core::hash; use core::iter::{FromIterator, FusedIterator}; use core::ops::{self, Add, AddAssign, Index, IndexMut}; use core::ptr; -use core::str as core_str; use core::str::pattern::Pattern; +use std_unicode::lossy; use std_unicode::char::{decode_utf16, REPLACEMENT_CHARACTER}; use borrow::{Cow, ToOwned}; use range::RangeArgument; use Bound::{Excluded, Included, Unbounded}; -use str::{self, FromStr, Utf8Error, Chars}; +use str::{self, from_boxed_utf8_unchecked, FromStr, Utf8Error, Chars}; use vec::Vec; use boxed::Box; @@ -126,7 +124,7 @@ use boxed::Box; /// similar, but without the UTF-8 constraint. The second implication is that /// you cannot index into a `String`: /// -/// ```ignore +/// ```compile_fail,E0277 /// let s = "hello"; /// /// println!("The first letter of s is {}", s[0]); // ERROR!!! @@ -535,111 +533,34 @@ impl String { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> Cow<'a, str> { - let mut i; - match str::from_utf8(v) { - Ok(s) => return Cow::Borrowed(s), - Err(e) => i = e.valid_up_to(), - } + let mut iter = lossy::Utf8Lossy::from_bytes(v).chunks(); - const TAG_CONT_U8: u8 = 128; - const REPLACEMENT: &'static [u8] = b"\xEF\xBF\xBD"; // U+FFFD in UTF-8 - let total = v.len(); - fn unsafe_get(xs: &[u8], i: usize) -> u8 { - unsafe { *xs.get_unchecked(i) } - } - fn safe_get(xs: &[u8], i: usize, total: usize) -> u8 { - if i >= total { 0 } else { unsafe_get(xs, i) } - } + let (first_valid, first_broken) = if let Some(chunk) = iter.next() { + let lossy::Utf8LossyChunk { valid, broken } = chunk; + if valid.len() == v.len() { + debug_assert!(broken.is_empty()); + return Cow::Borrowed(valid); + } + (valid, broken) + } else { + return Cow::Borrowed(""); + }; - let mut res = String::with_capacity(total); + const REPLACEMENT: &'static str = "\u{FFFD}"; - if i > 0 { - unsafe { res.as_mut_vec().extend_from_slice(&v[..i]) }; + let mut res = String::with_capacity(v.len()); + res.push_str(first_valid); + if !first_broken.is_empty() { + res.push_str(REPLACEMENT); } - // subseqidx is the index of the first byte of the subsequence we're - // looking at. It's used to copy a bunch of contiguous good codepoints - // at once instead of copying them one by one. - let mut subseqidx = i; - - while i < total { - let i_ = i; - let byte = unsafe_get(v, i); - i += 1; - - macro_rules! error { () => ({ - unsafe { - if subseqidx != i_ { - res.as_mut_vec().extend_from_slice(&v[subseqidx..i_]); - } - subseqidx = i; - res.as_mut_vec().extend_from_slice(REPLACEMENT); - } - })} - - if byte < 128 { - // subseqidx handles this - } else { - let w = core_str::utf8_char_width(byte); - - match w { - 2 => { - if safe_get(v, i, total) & 192 != TAG_CONT_U8 { - error!(); - continue; - } - i += 1; - } - 3 => { - match (byte, safe_get(v, i, total)) { - (0xE0, 0xA0...0xBF) => (), - (0xE1...0xEC, 0x80...0xBF) => (), - (0xED, 0x80...0x9F) => (), - (0xEE...0xEF, 0x80...0xBF) => (), - _ => { - error!(); - continue; - } - } - i += 1; - if safe_get(v, i, total) & 192 != TAG_CONT_U8 { - error!(); - continue; - } - i += 1; - } - 4 => { - match (byte, safe_get(v, i, total)) { - (0xF0, 0x90...0xBF) => (), - (0xF1...0xF3, 0x80...0xBF) => (), - (0xF4, 0x80...0x8F) => (), - _ => { - error!(); - continue; - } - } - i += 1; - if safe_get(v, i, total) & 192 != TAG_CONT_U8 { - error!(); - continue; - } - i += 1; - if safe_get(v, i, total) & 192 != TAG_CONT_U8 { - error!(); - continue; - } - i += 1; - } - _ => { - error!(); - continue; - } - } + for lossy::Utf8LossyChunk { valid, broken } in iter { + res.push_str(valid); + if !broken.is_empty() { + res.push_str(REPLACEMENT); } } - if subseqidx < total { - unsafe { res.as_mut_vec().extend_from_slice(&v[subseqidx..total]) }; - } + Cow::Owned(res) } @@ -1464,7 +1385,7 @@ impl String { #[stable(feature = "box_str", since = "1.4.0")] pub fn into_boxed_str(self) -> Box { let slice = self.vec.into_boxed_slice(); - unsafe { alloc_str::from_boxed_utf8_unchecked(slice) } + unsafe { from_boxed_utf8_unchecked(slice) } } } @@ -2087,10 +2008,10 @@ impl From> for String { } } -#[stable(feature = "box_from_str", since = "1.18.0")] -impl Into> for String { - fn into(self) -> Box { - self.into_boxed_str() +#[stable(feature = "box_from_str", since = "1.20.0")] +impl From for Box { + fn from(s: String) -> Box { + s.into_boxed_str() } } diff --git a/src/libcollections/tests/binary_heap.rs b/src/liballoc/tests/binary_heap.rs similarity index 100% rename from src/libcollections/tests/binary_heap.rs rename to src/liballoc/tests/binary_heap.rs diff --git a/src/libcollections/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs similarity index 100% rename from src/libcollections/tests/btree/map.rs rename to src/liballoc/tests/btree/map.rs diff --git a/src/libcollections/tests/btree/mod.rs b/src/liballoc/tests/btree/mod.rs similarity index 100% rename from src/libcollections/tests/btree/mod.rs rename to src/liballoc/tests/btree/mod.rs diff --git a/src/libcollections/tests/btree/set.rs b/src/liballoc/tests/btree/set.rs similarity index 100% rename from src/libcollections/tests/btree/set.rs rename to src/liballoc/tests/btree/set.rs diff --git a/src/libcollections/tests/cow_str.rs b/src/liballoc/tests/cow_str.rs similarity index 100% rename from src/libcollections/tests/cow_str.rs rename to src/liballoc/tests/cow_str.rs diff --git a/src/libcollections/tests/fmt.rs b/src/liballoc/tests/fmt.rs similarity index 100% rename from src/libcollections/tests/fmt.rs rename to src/liballoc/tests/fmt.rs diff --git a/src/libcollections/tests/lib.rs b/src/liballoc/tests/lib.rs similarity index 93% rename from src/libcollections/tests/lib.rs rename to src/liballoc/tests/lib.rs index 5f5217b73c..27b23d1405 100644 --- a/src/libcollections/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -10,11 +10,11 @@ #![deny(warnings)] +#![feature(alloc)] #![feature(attr_literals)] #![feature(box_syntax)] #![feature(inclusive_range_syntax)] #![feature(collection_placement)] -#![feature(collections)] #![feature(const_fn)] #![feature(exact_size_is_empty)] #![feature(iterator_step_by)] @@ -28,9 +28,8 @@ #![feature(test)] #![feature(unboxed_closures)] #![feature(unicode)] -#![feature(utf8_error_error_len)] -extern crate collections; +extern crate alloc; extern crate test; extern crate std_unicode; extern crate core; diff --git a/src/libcollections/tests/linked_list.rs b/src/liballoc/tests/linked_list.rs similarity index 100% rename from src/libcollections/tests/linked_list.rs rename to src/liballoc/tests/linked_list.rs diff --git a/src/libcollections/tests/slice.rs b/src/liballoc/tests/slice.rs similarity index 95% rename from src/libcollections/tests/slice.rs rename to src/liballoc/tests/slice.rs index 7fa65a2144..c53bf15f1b 100644 --- a/src/libcollections/tests/slice.rs +++ b/src/liballoc/tests/slice.rs @@ -396,18 +396,44 @@ fn test_sort() { let mut rng = thread_rng(); for len in (2..25).chain(500..510) { - for _ in 0..100 { - let mut v: Vec<_> = rng.gen_iter::().take(len).collect(); - let mut v1 = v.clone(); - - v.sort(); - assert!(v.windows(2).all(|w| w[0] <= w[1])); - - v1.sort_by(|a, b| a.cmp(b)); - assert!(v1.windows(2).all(|w| w[0] <= w[1])); - - v1.sort_by(|a, b| b.cmp(a)); - assert!(v1.windows(2).all(|w| w[0] >= w[1])); + for &modulus in &[5, 10, 100, 1000] { + for _ in 0..10 { + let orig: Vec<_> = rng.gen_iter::() + .map(|x| x % modulus) + .take(len) + .collect(); + + // Sort in default order. + let mut v = orig.clone(); + v.sort(); + assert!(v.windows(2).all(|w| w[0] <= w[1])); + + // Sort in ascending order. + let mut v = orig.clone(); + v.sort_by(|a, b| a.cmp(b)); + assert!(v.windows(2).all(|w| w[0] <= w[1])); + + // Sort in descending order. + let mut v = orig.clone(); + v.sort_by(|a, b| b.cmp(a)); + assert!(v.windows(2).all(|w| w[0] >= w[1])); + + // Sort with many pre-sorted runs. + let mut v = orig.clone(); + v.sort(); + v.reverse(); + for _ in 0..5 { + let a = rng.gen::() % len; + let b = rng.gen::() % len; + if a < b { + v[a..b].reverse(); + } else { + v.swap(a, b); + } + } + v.sort(); + assert!(v.windows(2).all(|w| w[0] <= w[1])); + } } } diff --git a/src/libcollections/tests/str.rs b/src/liballoc/tests/str.rs similarity index 97% rename from src/libcollections/tests/str.rs rename to src/liballoc/tests/str.rs index c9b7104fec..9d8ca38b20 100644 --- a/src/libcollections/tests/str.rs +++ b/src/liballoc/tests/str.rs @@ -358,6 +358,48 @@ fn test_slice_fail() { &"中华Việt Nam"[0..2]; } +#[test] +#[should_panic] +fn test_str_slice_rangetoinclusive_max_panics() { + &"hello"[...usize::max_value()]; +} + +#[test] +#[should_panic] +fn test_str_slice_rangeinclusive_max_panics() { + &"hello"[1...usize::max_value()]; +} + +#[test] +#[should_panic] +fn test_str_slicemut_rangetoinclusive_max_panics() { + let mut s = "hello".to_owned(); + let s: &mut str = &mut s; + &mut s[...usize::max_value()]; +} + +#[test] +#[should_panic] +fn test_str_slicemut_rangeinclusive_max_panics() { + let mut s = "hello".to_owned(); + let s: &mut str = &mut s; + &mut s[1...usize::max_value()]; +} + +#[test] +fn test_str_get_maxinclusive() { + let mut s = "hello".to_owned(); + { + let s: &str = &s; + assert_eq!(s.get(...usize::max_value()), None); + assert_eq!(s.get(1...usize::max_value()), None); + } + { + let s: &mut str = &mut s; + assert_eq!(s.get(...usize::max_value()), None); + assert_eq!(s.get(1...usize::max_value()), None); + } +} #[test] fn test_is_char_boundary() { diff --git a/src/libcollections/tests/string.rs b/src/liballoc/tests/string.rs similarity index 100% rename from src/libcollections/tests/string.rs rename to src/liballoc/tests/string.rs diff --git a/src/libcollections/tests/vec.rs b/src/liballoc/tests/vec.rs similarity index 98% rename from src/libcollections/tests/vec.rs rename to src/liballoc/tests/vec.rs index fdf453b39c..17f1229c20 100644 --- a/src/libcollections/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -274,6 +274,11 @@ fn test_dedup_by() { vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b)); assert_eq!(vec, ["foo", "bar", "baz", "bar"]); + + let mut vec = vec![("foo", 1), ("foo", 2), ("bar", 3), ("bar", 4), ("bar", 5)]; + vec.dedup_by(|a, b| a.0 == b.0 && { b.1 += a.1; true }); + + assert_eq!(vec, [("foo", 3), ("bar", 12)]); } #[test] diff --git a/src/libcollections/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs similarity index 99% rename from src/libcollections/tests/vec_deque.rs rename to src/liballoc/tests/vec_deque.rs index a992351653..f2935c05d4 100644 --- a/src/libcollections/tests/vec_deque.rs +++ b/src/liballoc/tests/vec_deque.rs @@ -510,8 +510,7 @@ fn test_from_iter() { let u: Vec<_> = deq.iter().cloned().collect(); assert_eq!(u, v); - // FIXME #27741: Remove `.skip(0)` when Range::step_by is fully removed - let seq = (0..).skip(0).step_by(2).take(256); + let seq = (0..).step_by(2).take(256); let deq: VecDeque<_> = seq.collect(); for (i, &x) in deq.iter().enumerate() { assert_eq!(2 * i, x); diff --git a/src/libcollections/vec.rs b/src/liballoc/vec.rs similarity index 99% rename from src/libcollections/vec.rs rename to src/liballoc/vec.rs index 3ef8438bc0..780a51aec3 100644 --- a/src/libcollections/vec.rs +++ b/src/liballoc/vec.rs @@ -9,7 +9,7 @@ // except according to those terms. //! A contiguous growable array type with heap-allocated contents, written -//! `Vec` but pronounced 'vector.' +//! `Vec`. //! //! Vectors have `O(1)` indexing, amortized `O(1)` push (to the end) and //! `O(1)` pop (from the end). @@ -66,10 +66,6 @@ #![stable(feature = "rust1", since = "1.0.0")] -use alloc::boxed::Box; -use alloc::raw_vec::RawVec; -use borrow::ToOwned; -use borrow::Cow; use core::cmp::Ordering; use core::fmt; use core::hash::{self, Hash}; @@ -84,6 +80,10 @@ use core::ptr; use core::ptr::Shared; use core::slice; +use borrow::ToOwned; +use borrow::Cow; +use boxed::Box; +use raw_vec::RawVec; use super::range::RangeArgument; use Bound::{Excluded, Included, Unbounded}; @@ -156,7 +156,7 @@ use Bound::{Excluded, Included, Unbounded}; /// However be careful: if you try to access an index which isn't in the `Vec`, /// your software will panic! You cannot do this: /// -/// ```ignore +/// ```should_panic /// let v = vec![0, 2, 4, 6]; /// println!("{}", v[6]); // it will panic! /// ``` @@ -222,7 +222,7 @@ use Bound::{Excluded, Included, Unbounded}; /// on an empty Vec, it will not allocate memory. Similarly, if you store zero-sized /// types inside a `Vec`, it will not allocate space for them. *Note that in this case /// the `Vec` may not report a [`capacity`] of 0*. `Vec` will allocate if and only -/// if [`mem::size_of::`]` * capacity() > 0`. In general, `Vec`'s allocation +/// if [`mem::size_of::`]`() * capacity() > 0`. In general, `Vec`'s allocation /// details are subtle enough that it is strongly recommended that you only /// free memory allocated by a `Vec` by creating a new `Vec` and dropping it. /// @@ -823,7 +823,8 @@ impl Vec { } } - /// Removes consecutive elements in the vector that resolve to the same key. + /// Removes all but the first of consecutive elements in the vector that resolve to the same + /// key. /// /// If the vector is sorted, this removes all duplicates. /// @@ -842,11 +843,13 @@ impl Vec { self.dedup_by(|a, b| key(a) == key(b)) } - /// Removes consecutive elements in the vector according to a predicate. + /// Removes all but the first of consecutive elements in the vector satisfying a given equality + /// relation. /// /// The `same_bucket` function is passed references to two elements from the vector, and - /// returns `true` if the elements compare equal, or `false` if they do not. Only the first - /// of adjacent equal items is kept. + /// returns `true` if the elements compare equal, or `false` if they do not. The elements are + /// passed in opposite order from their order in the vector, so if `same_bucket(a, b)` returns + /// `true`, `a` is removed. /// /// If the vector is sorted, this removes all duplicates. /// @@ -2124,10 +2127,12 @@ impl From> for Vec { } } -#[stable(feature = "box_from_vec", since = "1.18.0")] -impl Into> for Vec { - fn into(self) -> Box<[T]> { - self.into_boxed_slice() +// note: test pulls in libstd, which causes errors here +#[cfg(not(test))] +#[stable(feature = "box_from_vec", since = "1.20.0")] +impl From> for Box<[T]> { + fn from(v: Vec) -> Box<[T]> { + v.into_boxed_slice() } } diff --git a/src/libcollections/vec_deque.rs b/src/liballoc/vec_deque.rs similarity index 99% rename from src/libcollections/vec_deque.rs rename to src/liballoc/vec_deque.rs index e826c9432b..18175a5d01 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/liballoc/vec_deque.rs @@ -29,7 +29,7 @@ use core::slice; use core::hash::{Hash, Hasher}; use core::cmp; -use alloc::raw_vec::RawVec; +use raw_vec::RawVec; use super::range::RangeArgument; use Bound::{Excluded, Included, Unbounded}; diff --git a/src/liballoc_jemalloc/Cargo.toml b/src/liballoc_jemalloc/Cargo.toml index 49e5baad74..99c0bf2aaa 100644 --- a/src/liballoc_jemalloc/Cargo.toml +++ b/src/liballoc_jemalloc/Cargo.toml @@ -15,6 +15,10 @@ doc = false core = { path = "../libcore" } libc = { path = "../rustc/libc_shim" } +[target.'cfg(not(stage0))'.dependencies] +alloc = { path = "../liballoc" } +alloc_system = { path = "../liballoc_system" } + [build-dependencies] build_helper = { path = "../build_helper" } gcc = "0.3.50" diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs index f3a0eebe69..085f62f4b0 100644 --- a/src/liballoc_jemalloc/build.rs +++ b/src/liballoc_jemalloc/build.rs @@ -137,8 +137,6 @@ fn main() { cmd.arg("--enable-debug"); } - // Turn off broken quarantine (see jemalloc/jemalloc#161) - cmd.arg("--disable-fill"); cmd.arg(format!("--host={}", build_helper::gnu_target(&target))); cmd.arg(format!("--build={}", build_helper::gnu_target(&host))); @@ -154,6 +152,11 @@ fn main() { make.current_dir(&native.out_dir) .arg("build_lib_static"); + // These are intended for mingw32-make which we don't use + if cfg!(windows) { + make.env_remove("MAKEFLAGS").env_remove("MFLAGS"); + } + // mingw make seems... buggy? unclear... if !host.contains("windows") { make.arg("-j") diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs index 288531cb5b..72686ddcc0 100644 --- a/src/liballoc_jemalloc/lib.rs +++ b/src/liballoc_jemalloc/lib.rs @@ -11,23 +11,36 @@ #![crate_name = "alloc_jemalloc"] #![crate_type = "rlib"] #![no_std] -#![allocator] #![unstable(feature = "alloc_jemalloc", reason = "this library is unlikely to be stabilized in its current \ form or name", issue = "27783")] #![deny(warnings)] -#![feature(allocator)] #![feature(libc)] #![feature(staged_api)] - +#![feature(linkage)] +#![cfg_attr(stage0, allocator)] +#![cfg_attr(stage0, feature(allocator))] +#![cfg_attr(not(stage0), feature(global_allocator))] +#![cfg_attr(all(not(stage0), not(dummy_jemalloc)), feature(allocator_api))] +#![cfg_attr(not(stage0), feature(alloc))] +#![cfg_attr(not(stage0), feature(alloc_system))] +#![cfg_attr(dummy_jemalloc, allow(dead_code))] + +#[cfg(not(stage0))] +extern crate alloc; +#[cfg(not(stage0))] +extern crate alloc_system; extern crate libc; -pub use imp::*; +#[cfg(all(not(stage0), not(dummy_jemalloc)))] +pub use contents::*; +#[cfg(all(not(stage0), not(dummy_jemalloc)))] +mod contents { + use core::ptr; -// See comments in build.rs for why we sometimes build a crate that does nothing -#[cfg(not(dummy_jemalloc))] -mod imp { + use alloc::heap::{Alloc, AllocErr, Layout}; + use alloc_system::System; use libc::{c_int, c_void, size_t}; // Note that the symbols here are prefixed by default on macOS and Windows (we @@ -91,96 +104,152 @@ mod imp { } } - #[no_mangle] - pub extern "C" fn __rust_allocate(size: usize, align: usize) -> *mut u8 { - let flags = align_to_flags(align); - unsafe { mallocx(size as size_t, flags) as *mut u8 } - } + // for symbol names src/librustc/middle/allocator.rs + // for signatures src/librustc_allocator/lib.rs - #[no_mangle] - pub extern "C" fn __rust_allocate_zeroed(size: usize, align: usize) -> *mut u8 { - if align <= MIN_ALIGN { - unsafe { calloc(size as size_t, 1) as *mut u8 } - } else { - let flags = align_to_flags(align) | MALLOCX_ZERO; - unsafe { mallocx(size as size_t, flags) as *mut u8 } - } - } + // linkage directives are provided as part of the current compiler allocator + // ABI #[no_mangle] - pub extern "C" fn __rust_reallocate(ptr: *mut u8, - _old_size: usize, - size: usize, - align: usize) - -> *mut u8 { + #[linkage = "external"] + pub unsafe extern fn __rde_alloc(size: usize, + align: usize, + err: *mut u8) -> *mut u8 { let flags = align_to_flags(align); - unsafe { rallocx(ptr as *mut c_void, size as size_t, flags) as *mut u8 } + let ptr = mallocx(size as size_t, flags) as *mut u8; + if ptr.is_null() { + let layout = Layout::from_size_align_unchecked(size, align); + ptr::write(err as *mut AllocErr, + AllocErr::Exhausted { request: layout }); + } + ptr } #[no_mangle] - pub extern "C" fn __rust_reallocate_inplace(ptr: *mut u8, - _old_size: usize, - size: usize, - align: usize) - -> usize { - let flags = align_to_flags(align); - unsafe { xallocx(ptr as *mut c_void, size as size_t, 0, flags) as usize } + #[linkage = "external"] + pub unsafe extern fn __rde_oom(err: *const u8) -> ! { + System.oom((*(err as *const AllocErr)).clone()) } #[no_mangle] - pub extern "C" fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) { + #[linkage = "external"] + pub unsafe extern fn __rde_dealloc(ptr: *mut u8, + size: usize, + align: usize) { let flags = align_to_flags(align); - unsafe { sdallocx(ptr as *mut c_void, old_size as size_t, flags) } + sdallocx(ptr as *mut c_void, size, flags); } #[no_mangle] - pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize { - let flags = align_to_flags(align); - unsafe { nallocx(size as size_t, flags) as usize } - } -} - -#[cfg(dummy_jemalloc)] -mod imp { - fn bogus() -> ! { - panic!("jemalloc is not implemented for this platform"); + #[linkage = "external"] + pub unsafe extern fn __rde_usable_size(layout: *const u8, + min: *mut usize, + max: *mut usize) { + let layout = &*(layout as *const Layout); + let flags = align_to_flags(layout.align()); + let size = nallocx(layout.size(), flags) as usize; + *min = layout.size(); + if size > 0 { + *max = size; + } else { + *max = layout.size(); + } } #[no_mangle] - pub extern "C" fn __rust_allocate(_size: usize, _align: usize) -> *mut u8 { - bogus() + #[linkage = "external"] + pub unsafe extern fn __rde_realloc(ptr: *mut u8, + _old_size: usize, + old_align: usize, + new_size: usize, + new_align: usize, + err: *mut u8) -> *mut u8 { + if new_align != old_align { + ptr::write(err as *mut AllocErr, + AllocErr::Unsupported { details: "can't change alignments" }); + return 0 as *mut u8 + } + + let flags = align_to_flags(new_align); + let ptr = rallocx(ptr as *mut c_void, new_size, flags) as *mut u8; + if ptr.is_null() { + let layout = Layout::from_size_align_unchecked(new_size, new_align); + ptr::write(err as *mut AllocErr, + AllocErr::Exhausted { request: layout }); + } + ptr } #[no_mangle] - pub extern "C" fn __rust_allocate_zeroed(_size: usize, _align: usize) -> *mut u8 { - bogus() + #[linkage = "external"] + pub unsafe extern fn __rde_alloc_zeroed(size: usize, + align: usize, + err: *mut u8) -> *mut u8 { + let ptr = if align <= MIN_ALIGN { + calloc(size as size_t, 1) as *mut u8 + } else { + let flags = align_to_flags(align) | MALLOCX_ZERO; + mallocx(size as size_t, flags) as *mut u8 + }; + if ptr.is_null() { + let layout = Layout::from_size_align_unchecked(size, align); + ptr::write(err as *mut AllocErr, + AllocErr::Exhausted { request: layout }); + } + ptr } #[no_mangle] - pub extern "C" fn __rust_reallocate(_ptr: *mut u8, - _old_size: usize, - _size: usize, - _align: usize) - -> *mut u8 { - bogus() + #[linkage = "external"] + pub unsafe extern fn __rde_alloc_excess(size: usize, + align: usize, + excess: *mut usize, + err: *mut u8) -> *mut u8 { + let p = __rde_alloc(size, align, err); + if !p.is_null() { + *excess = size; + } + return p } #[no_mangle] - pub extern "C" fn __rust_reallocate_inplace(_ptr: *mut u8, - _old_size: usize, - _size: usize, - _align: usize) - -> usize { - bogus() + #[linkage = "external"] + pub unsafe extern fn __rde_realloc_excess(ptr: *mut u8, + old_size: usize, + old_align: usize, + new_size: usize, + new_align: usize, + excess: *mut usize, + err: *mut u8) -> *mut u8 { + let p = __rde_realloc(ptr, old_size, old_align, new_size, new_align, err); + if !p.is_null() { + *excess = new_size; + } + return p } #[no_mangle] - pub extern "C" fn __rust_deallocate(_ptr: *mut u8, _old_size: usize, _align: usize) { - bogus() + #[linkage = "external"] + pub unsafe extern fn __rde_grow_in_place(ptr: *mut u8, + old_size: usize, + old_align: usize, + new_size: usize, + new_align: usize) -> u8 { + __rde_shrink_in_place(ptr, old_size, old_align, new_size, new_align) } #[no_mangle] - pub extern "C" fn __rust_usable_size(_size: usize, _align: usize) -> usize { - bogus() + #[linkage = "external"] + pub unsafe extern fn __rde_shrink_in_place(ptr: *mut u8, + _old_size: usize, + old_align: usize, + new_size: usize, + new_align: usize) -> u8 { + if old_align == new_align { + let flags = align_to_flags(new_align); + (xallocx(ptr as *mut c_void, new_size, 0, flags) == new_size) as u8 + } else { + 0 + } } } diff --git a/src/liballoc_system/Cargo.toml b/src/liballoc_system/Cargo.toml index 8e3c2c0b9c..f20be5fdf5 100644 --- a/src/liballoc_system/Cargo.toml +++ b/src/liballoc_system/Cargo.toml @@ -12,3 +12,6 @@ doc = false [dependencies] core = { path = "../libcore" } libc = { path = "../rustc/libc_shim" } + +[target.'cfg(not(stage0))'.dependencies] +alloc = { path = "../liballoc" } diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index 1f36bc4fbc..afecfc16f2 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -11,13 +11,18 @@ #![crate_name = "alloc_system"] #![crate_type = "rlib"] #![no_std] -#![allocator] #![deny(warnings)] #![unstable(feature = "alloc_system", reason = "this library is unlikely to be stabilized in its current \ form or name", issue = "27783")] -#![feature(allocator)] +#![cfg_attr(stage0, allocator)] +#![cfg_attr(stage0, feature(allocator))] +#![cfg_attr(stage0, feature(core_intrinsics))] +#![cfg_attr(not(stage0), feature(global_allocator))] +#![cfg_attr(not(stage0), feature(allocator_api))] +#![cfg_attr(not(stage0), feature(alloc))] +#![cfg_attr(not(stage0), feature(core_intrinsics))] #![feature(staged_api)] #![cfg_attr(any(unix, target_os = "redox"), feature(libc))] @@ -39,62 +44,201 @@ const MIN_ALIGN: usize = 8; target_arch = "sparc64")))] const MIN_ALIGN: usize = 16; -#[no_mangle] -pub extern "C" fn __rust_allocate(size: usize, align: usize) -> *mut u8 { - unsafe { imp::allocate(size, align) } -} +#[cfg(stage0)] +pub use old::*; +#[cfg(stage0)] +mod old; -#[no_mangle] -pub extern "C" fn __rust_allocate_zeroed(size: usize, align: usize) -> *mut u8 { - unsafe { imp::allocate_zeroed(size, align) } -} +#[cfg(not(stage0))] +pub use new::System; +#[cfg(not(stage0))] +mod new { + pub extern crate alloc; -#[no_mangle] -pub extern "C" fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) { - unsafe { imp::deallocate(ptr, old_size, align) } -} + use self::alloc::heap::{Alloc, AllocErr, Layout, Excess, CannotReallocInPlace}; -#[no_mangle] -pub extern "C" fn __rust_reallocate(ptr: *mut u8, - old_size: usize, - size: usize, - align: usize) - -> *mut u8 { - unsafe { imp::reallocate(ptr, old_size, size, align) } -} + #[unstable(feature = "allocator_api", issue = "32838")] + pub struct System; -#[no_mangle] -pub extern "C" fn __rust_reallocate_inplace(ptr: *mut u8, - old_size: usize, - size: usize, - align: usize) - -> usize { - unsafe { imp::reallocate_inplace(ptr, old_size, size, align) } -} + #[unstable(feature = "allocator_api", issue = "32838")] + unsafe impl Alloc for System { + #[inline] + unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { + (&*self).alloc(layout) + } + + #[inline] + unsafe fn alloc_zeroed(&mut self, layout: Layout) + -> Result<*mut u8, AllocErr> + { + (&*self).alloc_zeroed(layout) + } + + #[inline] + unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) { + (&*self).dealloc(ptr, layout) + } + + #[inline] + unsafe fn realloc(&mut self, + ptr: *mut u8, + old_layout: Layout, + new_layout: Layout) -> Result<*mut u8, AllocErr> { + (&*self).realloc(ptr, old_layout, new_layout) + } -#[no_mangle] -pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize { - imp::usable_size(size, align) + fn oom(&mut self, err: AllocErr) -> ! { + (&*self).oom(err) + } + + #[inline] + fn usable_size(&self, layout: &Layout) -> (usize, usize) { + (&self).usable_size(layout) + } + + #[inline] + unsafe fn alloc_excess(&mut self, layout: Layout) -> Result { + (&*self).alloc_excess(layout) + } + + #[inline] + unsafe fn realloc_excess(&mut self, + ptr: *mut u8, + layout: Layout, + new_layout: Layout) -> Result { + (&*self).realloc_excess(ptr, layout, new_layout) + } + + #[inline] + unsafe fn grow_in_place(&mut self, + ptr: *mut u8, + layout: Layout, + new_layout: Layout) -> Result<(), CannotReallocInPlace> { + (&*self).grow_in_place(ptr, layout, new_layout) + } + + #[inline] + unsafe fn shrink_in_place(&mut self, + ptr: *mut u8, + layout: Layout, + new_layout: Layout) -> Result<(), CannotReallocInPlace> { + (&*self).shrink_in_place(ptr, layout, new_layout) + } + } } -#[cfg(any(unix, target_os = "redox"))] -mod imp { +#[cfg(all(not(stage0), any(unix, target_os = "redox")))] +mod platform { extern crate libc; use core::cmp; use core::ptr; + use MIN_ALIGN; + use new::System; + use new::alloc::heap::{Alloc, AllocErr, Layout}; + + #[unstable(feature = "allocator_api", issue = "32838")] + unsafe impl<'a> Alloc for &'a System { + #[inline] + unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { + let ptr = if layout.align() <= MIN_ALIGN { + libc::malloc(layout.size()) as *mut u8 + } else { + aligned_malloc(&layout) + }; + if !ptr.is_null() { + Ok(ptr) + } else { + Err(AllocErr::Exhausted { request: layout }) + } + } - pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { - if align <= MIN_ALIGN { - libc::malloc(size as libc::size_t) as *mut u8 - } else { - aligned_malloc(size, align) + #[inline] + unsafe fn alloc_zeroed(&mut self, layout: Layout) + -> Result<*mut u8, AllocErr> + { + if layout.align() <= MIN_ALIGN { + let ptr = libc::calloc(layout.size(), 1) as *mut u8; + if !ptr.is_null() { + Ok(ptr) + } else { + Err(AllocErr::Exhausted { request: layout }) + } + } else { + let ret = self.alloc(layout.clone()); + if let Ok(ptr) = ret { + ptr::write_bytes(ptr, 0, layout.size()); + } + ret + } + } + + #[inline] + unsafe fn dealloc(&mut self, ptr: *mut u8, _layout: Layout) { + libc::free(ptr as *mut libc::c_void) + } + + #[inline] + unsafe fn realloc(&mut self, + ptr: *mut u8, + old_layout: Layout, + new_layout: Layout) -> Result<*mut u8, AllocErr> { + if old_layout.align() != new_layout.align() { + return Err(AllocErr::Unsupported { + details: "cannot change alignment on `realloc`", + }) + } + + if new_layout.align() <= MIN_ALIGN { + let ptr = libc::realloc(ptr as *mut libc::c_void, new_layout.size()); + if !ptr.is_null() { + Ok(ptr as *mut u8) + } else { + Err(AllocErr::Exhausted { request: new_layout }) + } + } else { + let res = self.alloc(new_layout.clone()); + if let Ok(new_ptr) = res { + let size = cmp::min(old_layout.size(), new_layout.size()); + ptr::copy_nonoverlapping(ptr, new_ptr, size); + self.dealloc(ptr, old_layout); + } + res + } + } + + fn oom(&mut self, err: AllocErr) -> ! { + use core::fmt::{self, Write}; + + // Print a message to stderr before aborting to assist with + // debugging. It is critical that this code does not allocate any + // memory since we are in an OOM situation. Any errors are ignored + // while printing since there's nothing we can do about them and we + // are about to exit anyways. + drop(writeln!(Stderr, "fatal runtime error: {}", err)); + unsafe { + ::core::intrinsics::abort(); + } + + struct Stderr; + + impl Write for Stderr { + fn write_str(&mut self, s: &str) -> fmt::Result { + unsafe { + libc::write(libc::STDERR_FILENO, + s.as_ptr() as *const libc::c_void, + s.len()); + } + Ok(()) + } + } } } #[cfg(any(target_os = "android", target_os = "redox"))] - unsafe fn aligned_malloc(size: usize, align: usize) -> *mut u8 { + #[inline] + unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { // On android we currently target API level 9 which unfortunately // doesn't have the `posix_memalign` API used below. Instead we use // `memalign`, but this unfortunately has the property on some systems @@ -112,74 +256,41 @@ mod imp { // [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579 // [4]: https://chromium.googlesource.com/chromium/src/base/+/master/ // /memory/aligned_memory.cc - libc::memalign(align as libc::size_t, size as libc::size_t) as *mut u8 + libc::memalign(layout.align(), layout.size()) as *mut u8 } #[cfg(not(any(target_os = "android", target_os = "redox")))] - unsafe fn aligned_malloc(size: usize, align: usize) -> *mut u8 { + #[inline] + unsafe fn aligned_malloc(layout: &Layout) -> *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); + let ret = libc::posix_memalign(&mut out, layout.align(), layout.size()); if ret != 0 { ptr::null_mut() } else { out as *mut u8 } } - - pub unsafe fn allocate_zeroed(size: usize, align: usize) -> *mut u8 { - if align <= MIN_ALIGN { - libc::calloc(size as libc::size_t, 1) as *mut u8 - } else { - let ptr = aligned_malloc(size, align); - if !ptr.is_null() { - ptr::write_bytes(ptr, 0, size); - } - ptr - } - } - - pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 { - if align <= MIN_ALIGN { - libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8 - } else { - let new_ptr = allocate(size, align); - if !new_ptr.is_null() { - ptr::copy(ptr, new_ptr, cmp::min(size, old_size)); - deallocate(ptr, old_size, align); - } - new_ptr - } - } - - pub unsafe fn reallocate_inplace(_ptr: *mut u8, - old_size: usize, - _size: usize, - _align: usize) - -> usize { - old_size - } - - pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, _align: usize) { - libc::free(ptr as *mut libc::c_void) - } - - pub fn usable_size(size: usize, _align: usize) -> usize { - size - } } -#[cfg(windows)] +#[cfg(all(windows, not(stage0)))] #[allow(bad_style)] -mod imp { - use core::cmp::min; - use core::ptr::copy_nonoverlapping; +mod platform { + use core::cmp; + use core::ptr; + use MIN_ALIGN; + use new::System; + use new::alloc::heap::{Alloc, AllocErr, Layout, CannotReallocInPlace}; type LPVOID = *mut u8; type HANDLE = LPVOID; type SIZE_T = usize; type DWORD = u32; type BOOL = i32; + type LPDWORD = *mut DWORD; + type LPOVERLAPPED = *mut u8; + + const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD; extern "system" { fn GetProcessHeap() -> HANDLE; @@ -187,12 +298,18 @@ mod imp { fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID; fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL; fn GetLastError() -> DWORD; + fn WriteFile(hFile: HANDLE, + lpBuffer: LPVOID, + nNumberOfBytesToWrite: DWORD, + lpNumberOfBytesWritten: LPDWORD, + lpOverlapped: LPOVERLAPPED) + -> BOOL; + fn GetStdHandle(which: DWORD) -> HANDLE; } #[repr(C)] struct Header(*mut u8); - const HEAP_ZERO_MEMORY: DWORD = 0x00000008; const HEAP_REALLOC_IN_PLACE_ONLY: DWORD = 0x00000010; @@ -207,71 +324,149 @@ mod imp { } #[inline] - unsafe fn allocate_with_flags(size: usize, align: usize, flags: DWORD) -> *mut u8 { - if align <= MIN_ALIGN { - HeapAlloc(GetProcessHeap(), flags, size as SIZE_T) as *mut u8 + unsafe fn allocate_with_flags(layout: Layout, flags: DWORD) + -> Result<*mut u8, AllocErr> + { + let ptr = if layout.align() <= MIN_ALIGN { + HeapAlloc(GetProcessHeap(), flags, layout.size()) } else { - let ptr = HeapAlloc(GetProcessHeap(), flags, (size + align) as SIZE_T) as *mut u8; + let size = layout.size() + layout.align(); + let ptr = HeapAlloc(GetProcessHeap(), flags, size); if ptr.is_null() { - return ptr; + ptr + } else { + align_ptr(ptr, layout.align()) } - align_ptr(ptr, align) + }; + if ptr.is_null() { + Err(AllocErr::Exhausted { request: layout }) + } else { + Ok(ptr as *mut u8) } } - pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { - allocate_with_flags(size, align, 0) - } + #[unstable(feature = "allocator_api", issue = "32838")] + unsafe impl<'a> Alloc for &'a System { + #[inline] + unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { + allocate_with_flags(layout, 0) + } - pub unsafe fn allocate_zeroed(size: usize, align: usize) -> *mut u8 { - allocate_with_flags(size, align, HEAP_ZERO_MEMORY) - } + #[inline] + unsafe fn alloc_zeroed(&mut self, layout: Layout) + -> Result<*mut u8, AllocErr> + { + allocate_with_flags(layout, HEAP_ZERO_MEMORY) + } - pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 { - if align <= MIN_ALIGN { - HeapReAlloc(GetProcessHeap(), 0, ptr as LPVOID, size as SIZE_T) as *mut u8 - } else { - let new = allocate(size, align); - if !new.is_null() { - copy_nonoverlapping(ptr, new, min(size, old_size)); - deallocate(ptr, old_size, align); + #[inline] + unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) { + if layout.align() <= MIN_ALIGN { + let err = HeapFree(GetProcessHeap(), 0, ptr as LPVOID); + debug_assert!(err != 0, "Failed to free heap memory: {}", + GetLastError()); + } else { + let header = get_header(ptr); + let err = HeapFree(GetProcessHeap(), 0, header.0 as LPVOID); + debug_assert!(err != 0, "Failed to free heap memory: {}", + GetLastError()); } - new } - } - pub unsafe fn reallocate_inplace(ptr: *mut u8, - old_size: usize, - size: usize, - align: usize) - -> usize { - let new = if align <= MIN_ALIGN { - HeapReAlloc(GetProcessHeap(), - HEAP_REALLOC_IN_PLACE_ONLY, - ptr as LPVOID, - size as SIZE_T) as *mut u8 - } else { - let header = get_header(ptr); - HeapReAlloc(GetProcessHeap(), - HEAP_REALLOC_IN_PLACE_ONLY, - header.0 as LPVOID, - size + align as SIZE_T) as *mut u8 - }; - if new.is_null() { old_size } else { size } - } + #[inline] + unsafe fn realloc(&mut self, + ptr: *mut u8, + old_layout: Layout, + new_layout: Layout) -> Result<*mut u8, AllocErr> { + if old_layout.align() != new_layout.align() { + return Err(AllocErr::Unsupported { + details: "cannot change alignment on `realloc`", + }) + } - pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, align: usize) { - if align <= MIN_ALIGN { - let err = HeapFree(GetProcessHeap(), 0, ptr as LPVOID); - debug_assert!(err != 0, "Failed to free heap memory: {}", GetLastError()); - } else { - let header = get_header(ptr); - let err = HeapFree(GetProcessHeap(), 0, header.0 as LPVOID); - debug_assert!(err != 0, "Failed to free heap memory: {}", GetLastError()); + if new_layout.align() <= MIN_ALIGN { + let ptr = HeapReAlloc(GetProcessHeap(), + 0, + ptr as LPVOID, + new_layout.size()); + if !ptr.is_null() { + Ok(ptr as *mut u8) + } else { + Err(AllocErr::Exhausted { request: new_layout }) + } + } else { + let res = self.alloc(new_layout.clone()); + if let Ok(new_ptr) = res { + let size = cmp::min(old_layout.size(), new_layout.size()); + ptr::copy_nonoverlapping(ptr, new_ptr, size); + self.dealloc(ptr, old_layout); + } + res + } } - } - pub fn usable_size(size: usize, _align: usize) -> usize { - size + #[inline] + unsafe fn grow_in_place(&mut self, + ptr: *mut u8, + layout: Layout, + new_layout: Layout) -> Result<(), CannotReallocInPlace> { + self.shrink_in_place(ptr, layout, new_layout) + } + + #[inline] + unsafe fn shrink_in_place(&mut self, + ptr: *mut u8, + old_layout: Layout, + new_layout: Layout) -> Result<(), CannotReallocInPlace> { + if old_layout.align() != new_layout.align() { + return Err(CannotReallocInPlace) + } + + let new = if new_layout.align() <= MIN_ALIGN { + HeapReAlloc(GetProcessHeap(), + HEAP_REALLOC_IN_PLACE_ONLY, + ptr as LPVOID, + new_layout.size()) + } else { + let header = get_header(ptr); + HeapReAlloc(GetProcessHeap(), + HEAP_REALLOC_IN_PLACE_ONLY, + header.0 as LPVOID, + new_layout.size() + new_layout.align()) + }; + if new.is_null() { + Err(CannotReallocInPlace) + } else { + Ok(()) + } + } + + fn oom(&mut self, err: AllocErr) -> ! { + use core::fmt::{self, Write}; + + // Same as with unix we ignore all errors here + drop(writeln!(Stderr, "fatal runtime error: {}", err)); + unsafe { + ::core::intrinsics::abort(); + } + + struct Stderr; + + impl Write for Stderr { + fn write_str(&mut self, s: &str) -> fmt::Result { + unsafe { + // WriteFile silently fails if it is passed an invalid + // handle, so there is no need to check the result of + // GetStdHandle. + WriteFile(GetStdHandle(STD_ERROR_HANDLE), + s.as_ptr() as LPVOID, + s.len() as DWORD, + ptr::null_mut(), + ptr::null_mut()); + } + Ok(()) + } + } + } } } diff --git a/src/liballoc_system/old.rs b/src/liballoc_system/old.rs new file mode 100644 index 0000000000..80aa460759 --- /dev/null +++ b/src/liballoc_system/old.rs @@ -0,0 +1,268 @@ +// 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. + +#[no_mangle] +pub unsafe extern fn __rust_alloc(size: usize, + align: usize, + err: *mut u8) -> *mut u8 { + let p = imp::allocate(size, align); + if p.is_null() { + __rust_oom(err); + } + p +} + +#[no_mangle] +pub unsafe extern fn __rust_oom(_err: *const u8) -> ! { + ::core::intrinsics::abort() +} + +#[no_mangle] +pub unsafe extern fn __rust_dealloc(ptr: *mut u8, + size: usize, + align: usize) { + imp::deallocate(ptr, size, align) +} + +#[no_mangle] +pub unsafe extern fn __rust_usable_size(size: usize, + _align: usize, + min: *mut usize, + max: *mut usize) { + *min = size; + *max = size; +} + +#[no_mangle] +pub unsafe extern fn __rust_realloc(ptr: *mut u8, + old_size: usize, + old_align: usize, + new_size: usize, + new_align: usize, + err: *mut u8) -> *mut u8 { + if new_align != old_align { + __rust_oom(err); + } + let p = imp::reallocate(ptr, old_size, new_size, new_align); + if p.is_null() { + __rust_oom(err); + } + p +} + +#[no_mangle] +pub unsafe extern fn __rust_alloc_zeroed(size: usize, + align: usize, + err: *mut u8) -> *mut u8 { + let p = imp::allocate_zeroed(size, align); + if p.is_null() { + __rust_oom(err); + } + p +} + +#[no_mangle] +pub unsafe extern fn __rust_alloc_excess(_size: usize, + _align: usize, + _excess: *mut usize, + err: *mut u8) -> *mut u8 { + __rust_oom(err); +} + +#[no_mangle] +pub unsafe extern fn __rust_realloc_excess(_ptr: *mut u8, + _old_size: usize, + _old_align: usize, + _new_size: usize, + _new_align: usize, + _excess: *mut usize, + err: *mut u8) -> *mut u8 { + __rust_oom(err); +} + +#[no_mangle] +pub unsafe extern fn __rust_grow_in_place(_ptr: *mut u8, + _old_size: usize, + _old_align: usize, + _new_size: usize, + _new_align: usize) -> u8 { + 0 +} + +#[no_mangle] +pub unsafe extern fn __rust_shrink_in_place(_ptr: *mut u8, + _old_size: usize, + _old_align: usize, + _new_size: usize, + _new_align: usize) -> u8 { + 0 +} + +#[cfg(any(unix, target_os = "redox"))] +mod imp { + extern crate libc; + + use core::cmp; + use core::ptr; + use MIN_ALIGN; + + pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { + if align <= MIN_ALIGN { + libc::malloc(size as libc::size_t) as *mut u8 + } else { + aligned_malloc(size, align) + } + } + + #[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 + // `memalign`, but this unfortunately has the property on some systems + // where the memory returned cannot be deallocated by `free`! + // + // Upon closer inspection, however, this appears to work just fine with + // Android, so for this platform we should be fine to call `memalign` + // (which is present in API level 9). Some helpful references could + // possibly be chromium using memalign [1], attempts at documenting that + // memalign + free is ok [2] [3], or the current source of chromium + // which still uses memalign on android [4]. + // + // [1]: https://codereview.chromium.org/10796020/ + // [2]: https://code.google.com/p/android/issues/detail?id=35391 + // [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579 + // [4]: https://chromium.googlesource.com/chromium/src/base/+/master/ + // /memory/aligned_memory.cc + libc::memalign(align as libc::size_t, size as libc::size_t) as *mut u8 + } + + #[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); + if ret != 0 { + ptr::null_mut() + } else { + out as *mut u8 + } + } + + pub unsafe fn allocate_zeroed(size: usize, align: usize) -> *mut u8 { + if align <= MIN_ALIGN { + libc::calloc(size as libc::size_t, 1) as *mut u8 + } else { + let ptr = aligned_malloc(size, align); + if !ptr.is_null() { + ptr::write_bytes(ptr, 0, size); + } + ptr + } + } + + pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 { + if align <= MIN_ALIGN { + libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8 + } else { + let new_ptr = allocate(size, align); + if !new_ptr.is_null() { + ptr::copy(ptr, new_ptr, cmp::min(size, old_size)); + deallocate(ptr, old_size, align); + } + new_ptr + } + } + + pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, _align: usize) { + libc::free(ptr as *mut libc::c_void) + } +} + +#[cfg(windows)] +#[allow(bad_style)] +mod imp { + use core::cmp::min; + use core::ptr::copy_nonoverlapping; + use MIN_ALIGN; + + type LPVOID = *mut u8; + type HANDLE = LPVOID; + type SIZE_T = usize; + type DWORD = u32; + type BOOL = i32; + + extern "system" { + fn GetProcessHeap() -> HANDLE; + fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID; + fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID; + fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL; + fn GetLastError() -> DWORD; + } + + #[repr(C)] + struct Header(*mut u8); + + + const HEAP_ZERO_MEMORY: DWORD = 0x00000008; + + unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header { + &mut *(ptr as *mut Header).offset(-1) + } + + unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 { + let aligned = ptr.offset((align - (ptr as usize & (align - 1))) as isize); + *get_header(aligned) = Header(ptr); + aligned + } + + #[inline] + unsafe fn allocate_with_flags(size: usize, align: usize, flags: DWORD) -> *mut u8 { + if align <= MIN_ALIGN { + HeapAlloc(GetProcessHeap(), flags, size as SIZE_T) as *mut u8 + } else { + let ptr = HeapAlloc(GetProcessHeap(), flags, (size + align) as SIZE_T) as *mut u8; + if ptr.is_null() { + return ptr; + } + align_ptr(ptr, align) + } + } + + pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { + allocate_with_flags(size, align, 0) + } + + pub unsafe fn allocate_zeroed(size: usize, align: usize) -> *mut u8 { + allocate_with_flags(size, align, HEAP_ZERO_MEMORY) + } + + pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 { + if align <= MIN_ALIGN { + HeapReAlloc(GetProcessHeap(), 0, ptr as LPVOID, size as SIZE_T) as *mut u8 + } else { + let new = allocate(size, align); + if !new.is_null() { + copy_nonoverlapping(ptr, new, min(size, old_size)); + deallocate(ptr, old_size, align); + } + new + } + } + + pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, align: usize) { + if align <= MIN_ALIGN { + let err = HeapFree(GetProcessHeap(), 0, ptr as LPVOID); + debug_assert!(err != 0, "Failed to free heap memory: {}", GetLastError()); + } else { + let header = get_header(ptr); + let err = HeapFree(GetProcessHeap(), 0, header.0 as LPVOID); + debug_assert!(err != 0, "Failed to free heap memory: {}", GetLastError()); + } + } +} diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 4338ac7fd0..8e3b3f2074 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -19,7 +19,6 @@ //! objects of a single type. #![crate_name = "arena"] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] #![crate_type = "rlib"] #![crate_type = "dylib"] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", @@ -33,7 +32,6 @@ #![feature(dropck_eyepatch)] #![feature(generic_param_attrs)] #![feature(needs_drop)] -#![cfg_attr(stage0, feature(staged_api))] #![cfg_attr(test, feature(test))] #![allow(deprecated)] diff --git a/src/libcollections/Cargo.toml b/src/libcollections/Cargo.toml index 7e92404bc0..800e36161d 100644 --- a/src/libcollections/Cargo.toml +++ b/src/libcollections/Cargo.toml @@ -10,12 +10,3 @@ path = "lib.rs" [dependencies] alloc = { path = "../liballoc" } core = { path = "../libcore" } -std_unicode = { path = "../libstd_unicode" } - -[[test]] -name = "collectionstests" -path = "../libcollections/tests/lib.rs" - -[[bench]] -name = "collectionsbenches" -path = "../libcollections/benches/lib.rs" diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 34626326c2..38143593eb 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,185 +8,63 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Collection types. -//! -//! See [`std::collections`](../std/collections/index.html) for a detailed -//! discussion of collections in Rust. - #![crate_name = "collections"] #![crate_type = "rlib"] +#![allow(unused_attributes)] #![unstable(feature = "collections", - reason = "library is unlikely to be stabilized with the current \ - layout and name, use std::collections instead", + reason = "this library is unlikely to be stabilized in its current \ + form or name", issue = "27783")] +#![rustc_deprecated(since = "1.20.0", + reason = "collections moved to `alloc`")] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", - html_playground_url = "https://play.rust-lang.org/", issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] - -#![cfg_attr(test, allow(deprecated))] // rand +#![no_std] #![deny(warnings)] -#![deny(missing_debug_implementations)] #![feature(alloc)] -#![feature(allow_internal_unstable)] -#![feature(box_patterns)] -#![feature(box_syntax)] -#![cfg_attr(not(test), feature(char_escape_debug))] -#![cfg_attr(not(test), feature(core_float))] -#![feature(core_intrinsics)] -#![feature(dropck_eyepatch)] -#![feature(exact_size_is_empty)] -#![feature(fmt_internals)] -#![feature(fused)] -#![feature(generic_param_attrs)] -#![feature(heap_api)] -#![feature(i128_type)] -#![feature(inclusive_range)] -#![feature(lang_items)] -#![feature(manually_drop)] -#![feature(nonzero)] -#![feature(pattern)] -#![feature(placement_in)] -#![feature(placement_in_syntax)] -#![feature(placement_new_protocol)] -#![feature(shared)] -#![feature(slice_get_slice)] -#![feature(slice_patterns)] -#![cfg_attr(not(test), feature(slice_rotate))] -#![feature(slice_rsplit)] -#![cfg_attr(not(test), feature(sort_unstable))] -#![feature(specialization)] +#![feature(collections_range)] +#![feature(macro_reexport)] #![feature(staged_api)] -#![feature(str_internals)] -#![feature(str_box_extras)] -#![feature(str_mut_extras)] -#![feature(trusted_len)] -#![feature(unicode)] -#![feature(unique)] -#![cfg_attr(not(test), feature(str_checked_slicing))] -#![cfg_attr(test, feature(rand, test))] -#![feature(offset_to)] -#![no_std] +//! Collection types +//! +//! See [`std::collections`](../std/collections/index.html) for a detailed +//! discussion of collections in Rust. -extern crate std_unicode; +#[macro_reexport(vec, format)] extern crate alloc; -#[cfg(test)] -#[macro_use] -extern crate std; -#[cfg(test)] -extern crate test; +pub use alloc::Bound; + +pub use alloc::binary_heap; +pub use alloc::borrow; +pub use alloc::fmt; +pub use alloc::linked_list; +pub use alloc::range; +pub use alloc::slice; +pub use alloc::str; +pub use alloc::string; +pub use alloc::vec; +pub use alloc::vec_deque; + +pub use alloc::btree_map; +pub use alloc::btree_set; #[doc(no_inline)] -pub use binary_heap::BinaryHeap; +pub use alloc::binary_heap::BinaryHeap; #[doc(no_inline)] -pub use btree_map::BTreeMap; +pub use alloc::btree_map::BTreeMap; #[doc(no_inline)] -pub use btree_set::BTreeSet; +pub use alloc::btree_set::BTreeSet; #[doc(no_inline)] -pub use linked_list::LinkedList; +pub use alloc::linked_list::LinkedList; #[doc(no_inline)] -pub use vec_deque::VecDeque; +pub use alloc::vec_deque::VecDeque; #[doc(no_inline)] -pub use string::String; +pub use alloc::string::String; #[doc(no_inline)] -pub use vec::Vec; - -// Needed for the vec! macro -pub use alloc::boxed; - -#[macro_use] -mod macros; - -pub mod binary_heap; -mod btree; -pub mod borrow; -pub mod fmt; -pub mod linked_list; -pub mod range; -pub mod slice; -pub mod str; -pub mod string; -pub mod vec; -pub mod vec_deque; - -#[stable(feature = "rust1", since = "1.0.0")] -pub mod btree_map { - //! A map based on a B-Tree. - #[stable(feature = "rust1", since = "1.0.0")] - pub use btree::map::*; -} - -#[stable(feature = "rust1", since = "1.0.0")] -pub mod btree_set { - //! A set based on a B-Tree. - #[stable(feature = "rust1", since = "1.0.0")] - pub use btree::set::*; -} - -#[cfg(not(test))] -mod std { - pub use core::ops; // RangeFull -} - -/// An endpoint of a range of keys. -/// -/// # Examples -/// -/// `Bound`s are range endpoints: -/// -/// ``` -/// #![feature(collections_range)] -/// -/// use std::collections::range::RangeArgument; -/// use std::collections::Bound::*; -/// -/// assert_eq!((..100).start(), Unbounded); -/// assert_eq!((1..12).start(), Included(&1)); -/// assert_eq!((1..12).end(), Excluded(&12)); -/// ``` -/// -/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`]. -/// Note that in most cases, it's better to use range syntax (`1..5`) instead. -/// -/// ``` -/// use std::collections::BTreeMap; -/// use std::collections::Bound::{Excluded, Included, Unbounded}; -/// -/// let mut map = BTreeMap::new(); -/// map.insert(3, "a"); -/// map.insert(5, "b"); -/// map.insert(8, "c"); -/// -/// for (key, value) in map.range((Excluded(3), Included(8))) { -/// println!("{}: {}", key, value); -/// } -/// -/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next()); -/// ``` -/// -/// [`BTreeMap::range`]: btree_map/struct.BTreeMap.html#method.range -#[stable(feature = "collections_bound", since = "1.17.0")] -#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] -pub enum Bound { - /// An inclusive bound. - #[stable(feature = "collections_bound", since = "1.17.0")] - Included(T), - /// An exclusive bound. - #[stable(feature = "collections_bound", since = "1.17.0")] - Excluded(T), - /// An infinite endpoint. Indicates that there is no bound in this direction. - #[stable(feature = "collections_bound", since = "1.17.0")] - Unbounded, -} - -/// An intermediate trait for specialization of `Extend`. -#[doc(hidden)] -trait SpecExtend { - /// Extends `self` with the contents of the given iterator. - fn spec_extend(&mut self, iter: I); -} +pub use alloc::vec::Vec; diff --git a/src/libcollections/macros.rs b/src/libcollections/macros.rs deleted file mode 100644 index 396a917dfd..0000000000 --- a/src/libcollections/macros.rs +++ /dev/null @@ -1,92 +0,0 @@ -// 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. - -/// Creates a `Vec` containing the arguments. -/// -/// `vec!` allows `Vec`s to be defined with the same syntax as array expressions. -/// There are two forms of this macro: -/// -/// - Create a `Vec` containing a given list of elements: -/// -/// ``` -/// let v = vec![1, 2, 3]; -/// assert_eq!(v[0], 1); -/// assert_eq!(v[1], 2); -/// assert_eq!(v[2], 3); -/// ``` -/// -/// - Create a `Vec` from a given element and size: -/// -/// ``` -/// let v = vec![1; 3]; -/// assert_eq!(v, [1, 1, 1]); -/// ``` -/// -/// Note that unlike array expressions this syntax supports all elements -/// which implement `Clone` and the number of elements doesn't have to be -/// a constant. -/// -/// This will use `clone()` to duplicate an expression, so one should be careful -/// using this with types having a nonstandard `Clone` implementation. For -/// example, `vec![Rc::new(1); 5]` will create a vector of five references -/// to the same boxed integer value, not five references pointing to independently -/// boxed integers. -#[cfg(not(test))] -#[macro_export] -#[stable(feature = "rust1", since = "1.0.0")] -#[allow_internal_unstable] -macro_rules! vec { - ($elem:expr; $n:expr) => ( - $crate::vec::from_elem($elem, $n) - ); - ($($x:expr),*) => ( - <[_]>::into_vec(box [$($x),*]) - ); - ($($x:expr,)*) => (vec![$($x),*]) -} - -// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is -// required for this macro definition, is not available. Instead use the -// `slice::into_vec` function which is only available with cfg(test) -// NB see the slice::hack module in slice.rs for more information -#[cfg(test)] -macro_rules! vec { - ($elem:expr; $n:expr) => ( - $crate::vec::from_elem($elem, $n) - ); - ($($x:expr),*) => ( - $crate::slice::into_vec(box [$($x),*]) - ); - ($($x:expr,)*) => (vec![$($x),*]) -} - -/// Use the syntax described in `std::fmt` to create a value of type `String`. -/// See [`std::fmt`][fmt] for more information. -/// -/// [fmt]: ../std/fmt/index.html -/// -/// # Panics -/// -/// `format!` panics if a formatting trait implementation returns an error. -/// This indicates an incorrect implementation -/// since `fmt::Write for String` never returns an error itself. -/// -/// # Examples -/// -/// ``` -/// format!("test"); -/// format!("hello {}", "world!"); -/// format!("x = {}, y = {y}", 10, y = 30); -/// ``` -#[macro_export] -#[stable(feature = "rust1", since = "1.0.0")] -macro_rules! format { - ($($arg:tt)*) => ($crate::fmt::format(format_args!($($arg)*))) -} diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs deleted file mode 100644 index eb32f47819..0000000000 --- a/src/libcollections/str.rs +++ /dev/null @@ -1,1997 +0,0 @@ -// Copyright 2012-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. - -//! Unicode string slices. -//! -//! The `&str` type is one of the two main string types, the other being `String`. -//! Unlike its `String` counterpart, its contents are borrowed. -//! -//! # Basic Usage -//! -//! A basic string declaration of `&str` type: -//! -//! ``` -//! let hello_world = "Hello, World!"; -//! ``` -//! -//! Here we have declared a string literal, also known as a string slice. -//! String literals have a static lifetime, which means the string `hello_world` -//! is guaranteed to be valid for the duration of the entire program. -//! We can explicitly specify `hello_world`'s lifetime as well: -//! -//! ``` -//! let hello_world: &'static str = "Hello, world!"; -//! ``` -//! -//! *[See also the `str` primitive type](../../std/primitive.str.html).* - -#![stable(feature = "rust1", since = "1.0.0")] - -// Many of the usings in this module are only used in the test configuration. -// It's cleaner to just turn off the unused_imports warning than to fix them. -#![allow(unused_imports)] - -use core::fmt; -use core::str as core_str; -use core::str::pattern::Pattern; -use core::str::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher}; -use core::mem; -use core::iter::FusedIterator; -use std_unicode::str::{UnicodeStr, Utf16Encoder}; - -use vec_deque::VecDeque; -use borrow::{Borrow, ToOwned}; -use string::String; -use std_unicode; -use vec::Vec; -use slice::{SliceConcatExt, SliceIndex}; -use boxed::Box; - -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::str::{FromStr, Utf8Error}; -#[allow(deprecated)] -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::str::{Lines, LinesAny}; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::str::{Split, RSplit}; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::str::{SplitN, RSplitN}; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::str::{SplitTerminator, RSplitTerminator}; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::str::{Matches, RMatches}; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::str::{MatchIndices, RMatchIndices}; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::str::{from_utf8, from_utf8_mut, Chars, CharIndices, Bytes}; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::str::{from_utf8_unchecked, from_utf8_unchecked_mut, ParseBoolError}; -#[unstable(feature = "str_box_extras", issue = "41119")] -pub use alloc::str::from_boxed_utf8_unchecked; -#[stable(feature = "rust1", since = "1.0.0")] -pub use std_unicode::str::SplitWhitespace; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::str::pattern; - - -#[unstable(feature = "slice_concat_ext", - reason = "trait should not have to exist", - issue = "27747")] -impl> SliceConcatExt for [S] { - type Output = String; - - fn concat(&self) -> String { - if self.is_empty() { - return String::new(); - } - - // `len` calculation may overflow but push_str will check boundaries - let len = self.iter().map(|s| s.borrow().len()).sum(); - let mut result = String::with_capacity(len); - - for s in self { - result.push_str(s.borrow()) - } - - result - } - - fn join(&self, sep: &str) -> String { - if self.is_empty() { - return String::new(); - } - - // concat is faster - if sep.is_empty() { - return self.concat(); - } - - // this is wrong without the guarantee that `self` is non-empty - // `len` calculation may overflow but push_str but will check boundaries - let len = sep.len() * (self.len() - 1) + - self.iter().map(|s| s.borrow().len()).sum::(); - let mut result = String::with_capacity(len); - let mut first = true; - - for s in self { - if first { - first = false; - } else { - result.push_str(sep); - } - result.push_str(s.borrow()); - } - result - } - - fn connect(&self, sep: &str) -> String { - self.join(sep) - } -} - -/// An iterator of [`u16`] over the string encoded as UTF-16. -/// -/// [`u16`]: ../../std/primitive.u16.html -/// -/// This struct is created by the [`encode_utf16`] method on [`str`]. -/// See its documentation for more. -/// -/// [`encode_utf16`]: ../../std/primitive.str.html#method.encode_utf16 -/// [`str`]: ../../std/primitive.str.html -#[derive(Clone)] -#[stable(feature = "encode_utf16", since = "1.8.0")] -pub struct EncodeUtf16<'a> { - encoder: Utf16Encoder>, -} - -#[stable(feature = "collection_debug", since = "1.17.0")] -impl<'a> fmt::Debug for EncodeUtf16<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad("EncodeUtf16 { .. }") - } -} - -#[stable(feature = "encode_utf16", since = "1.8.0")] -impl<'a> Iterator for EncodeUtf16<'a> { - type Item = u16; - - #[inline] - fn next(&mut self) -> Option { - self.encoder.next() - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.encoder.size_hint() - } -} - -#[unstable(feature = "fused", issue = "35602")] -impl<'a> FusedIterator for EncodeUtf16<'a> {} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Borrow for String { - #[inline] - fn borrow(&self) -> &str { - &self[..] - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ToOwned for str { - type Owned = String; - fn to_owned(&self) -> String { - unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) } - } - - fn clone_into(&self, target: &mut String) { - let mut b = mem::replace(target, String::new()).into_bytes(); - self.as_bytes().clone_into(&mut b); - *target = unsafe { String::from_utf8_unchecked(b) } - } -} - -/// Methods for string slices. -#[lang = "str"] -#[cfg(not(test))] -impl str { - /// Returns the length of `self`. - /// - /// This length is in bytes, not [`char`]s or graphemes. In other words, - /// it may not be what a human considers the length of the string. - /// - /// [`char`]: primitive.char.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let len = "foo".len(); - /// assert_eq!(3, len); - /// - /// let len = "ƒoo".len(); // fancy f! - /// assert_eq!(4, len); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn len(&self) -> usize { - core_str::StrExt::len(self) - } - - /// Returns `true` if `self` has a length of zero bytes. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = ""; - /// assert!(s.is_empty()); - /// - /// let s = "not empty"; - /// assert!(!s.is_empty()); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn is_empty(&self) -> bool { - core_str::StrExt::is_empty(self) - } - - /// Checks that `index`-th byte lies at the start and/or end of a - /// UTF-8 code point sequence. - /// - /// The start and end of the string (when `index == self.len()`) are - /// considered to be - /// boundaries. - /// - /// Returns `false` if `index` is greater than `self.len()`. - /// - /// # Examples - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// assert!(s.is_char_boundary(0)); - /// // start of `老` - /// assert!(s.is_char_boundary(6)); - /// assert!(s.is_char_boundary(s.len())); - /// - /// // second byte of `ö` - /// assert!(!s.is_char_boundary(2)); - /// - /// // third byte of `老` - /// assert!(!s.is_char_boundary(8)); - /// ``` - #[stable(feature = "is_char_boundary", since = "1.9.0")] - #[inline] - pub fn is_char_boundary(&self, index: usize) -> bool { - core_str::StrExt::is_char_boundary(self, index) - } - - /// Converts a string slice to a byte slice. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let bytes = "bors".as_bytes(); - /// assert_eq!(b"bors", bytes); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline(always)] - pub fn as_bytes(&self) -> &[u8] { - core_str::StrExt::as_bytes(self) - } - - /// Converts a mutable string slice to a mutable byte slice. - #[unstable(feature = "str_mut_extras", issue = "41119")] - #[inline(always)] - pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] { - core_str::StrExt::as_bytes_mut(self) - } - - /// Converts a string slice to a raw pointer. - /// - /// As string slices are a slice of bytes, the raw pointer points to a - /// [`u8`]. This pointer will be pointing to the first byte of the string - /// slice. - /// - /// [`u8`]: primitive.u8.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = "Hello"; - /// let ptr = s.as_ptr(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn as_ptr(&self) -> *const u8 { - core_str::StrExt::as_ptr(self) - } - - /// Returns a subslice of `str`. - /// - /// This is the non-panicking alternative to indexing the `str`. Returns - /// [`None`] whenever equivalent indexing operation would panic. - /// - /// [`None`]: option/enum.Option.html#variant.None - /// - /// # Examples - /// - /// ``` - /// # #![feature(str_checked_slicing)] - /// let v = "🗻∈🌏"; - /// assert_eq!(Some("🗻"), v.get(0..4)); - /// assert!(v.get(1..).is_none()); - /// assert!(v.get(..8).is_none()); - /// assert!(v.get(..42).is_none()); - /// ``` - #[unstable(feature = "str_checked_slicing", issue = "39932")] - #[inline] - pub fn get>(&self, i: I) -> Option<&I::Output> { - core_str::StrExt::get(self, i) - } - - /// Returns a mutable subslice of `str`. - /// - /// This is the non-panicking alternative to indexing the `str`. Returns - /// [`None`] whenever equivalent indexing operation would panic. - /// - /// [`None`]: option/enum.Option.html#variant.None - /// - /// # Examples - /// - /// ``` - /// # #![feature(str_checked_slicing)] - /// let mut v = String::from("🗻∈🌏"); - /// assert_eq!(Some("🗻"), v.get_mut(0..4).map(|v| &*v)); - /// assert!(v.get_mut(1..).is_none()); - /// assert!(v.get_mut(..8).is_none()); - /// assert!(v.get_mut(..42).is_none()); - /// ``` - #[unstable(feature = "str_checked_slicing", issue = "39932")] - #[inline] - pub fn get_mut>(&mut self, i: I) -> Option<&mut I::Output> { - core_str::StrExt::get_mut(self, i) - } - - /// Returns a unchecked subslice of `str`. - /// - /// This is the unchecked alternative to indexing the `str`. - /// - /// # Safety - /// - /// Callers of this function are responsible that these preconditions are - /// satisfied: - /// - /// * The starting index must come before the ending index; - /// * Indexes must be within bounds of the original slice; - /// * Indexes must lie on UTF-8 sequence boundaries. - /// - /// Failing that, the returned string slice may reference invalid memory or - /// violate the invariants communicated by the `str` type. - /// - /// # Examples - /// - /// ``` - /// # #![feature(str_checked_slicing)] - /// let v = "🗻∈🌏"; - /// unsafe { - /// assert_eq!("🗻", v.get_unchecked(0..4)); - /// assert_eq!("∈", v.get_unchecked(4..7)); - /// assert_eq!("🌏", v.get_unchecked(7..11)); - /// } - /// ``` - #[unstable(feature = "str_checked_slicing", issue = "39932")] - #[inline] - pub unsafe fn get_unchecked>(&self, i: I) -> &I::Output { - core_str::StrExt::get_unchecked(self, i) - } - - /// Returns a mutable, unchecked subslice of `str`. - /// - /// This is the unchecked alternative to indexing the `str`. - /// - /// # Safety - /// - /// Callers of this function are responsible that these preconditions are - /// satisfied: - /// - /// * The starting index must come before the ending index; - /// * Indexes must be within bounds of the original slice; - /// * Indexes must lie on UTF-8 sequence boundaries. - /// - /// Failing that, the returned string slice may reference invalid memory or - /// violate the invariants communicated by the `str` type. - /// - /// # Examples - /// - /// ``` - /// # #![feature(str_checked_slicing)] - /// let mut v = String::from("🗻∈🌏"); - /// unsafe { - /// assert_eq!("🗻", v.get_unchecked_mut(0..4)); - /// assert_eq!("∈", v.get_unchecked_mut(4..7)); - /// assert_eq!("🌏", v.get_unchecked_mut(7..11)); - /// } - /// ``` - #[unstable(feature = "str_checked_slicing", issue = "39932")] - #[inline] - pub unsafe fn get_unchecked_mut>(&mut self, i: I) -> &mut I::Output { - core_str::StrExt::get_unchecked_mut(self, i) - } - - /// Creates a string slice from another string slice, bypassing safety - /// checks. - /// - /// This is generally not recommended, use with caution! For a safe - /// alternative see [`str`] and [`Index`]. - /// - /// [`str`]: primitive.str.html - /// [`Index`]: ops/trait.Index.html - /// - /// This new slice goes from `begin` to `end`, including `begin` but - /// excluding `end`. - /// - /// To get a mutable string slice instead, see the - /// [`slice_mut_unchecked`] method. - /// - /// [`slice_mut_unchecked`]: #method.slice_mut_unchecked - /// - /// # Safety - /// - /// Callers of this function are responsible that three preconditions are - /// satisfied: - /// - /// * `begin` must come before `end`. - /// * `begin` and `end` must be byte positions within the string slice. - /// * `begin` and `end` must lie on UTF-8 sequence boundaries. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// - /// unsafe { - /// assert_eq!("Löwe 老虎 Léopard", s.slice_unchecked(0, 21)); - /// } - /// - /// let s = "Hello, world!"; - /// - /// unsafe { - /// assert_eq!("world", s.slice_unchecked(7, 12)); - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str { - core_str::StrExt::slice_unchecked(self, begin, end) - } - - /// Creates a string slice from another string slice, bypassing safety - /// checks. - /// This is generally not recommended, use with caution! For a safe - /// alternative see [`str`] and [`IndexMut`]. - /// - /// [`str`]: primitive.str.html - /// [`IndexMut`]: ops/trait.IndexMut.html - /// - /// This new slice goes from `begin` to `end`, including `begin` but - /// excluding `end`. - /// - /// To get an immutable string slice instead, see the - /// [`slice_unchecked`] method. - /// - /// [`slice_unchecked`]: #method.slice_unchecked - /// - /// # Safety - /// - /// Callers of this function are responsible that three preconditions are - /// satisfied: - /// - /// * `begin` must come before `end`. - /// * `begin` and `end` must be byte positions within the string slice. - /// * `begin` and `end` must lie on UTF-8 sequence boundaries. - #[stable(feature = "str_slice_mut", since = "1.5.0")] - #[inline] - pub unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str { - core_str::StrExt::slice_mut_unchecked(self, begin, end) - } - - /// Divide one string slice into two at an index. - /// - /// The argument, `mid`, should be a byte offset from the start of the - /// string. It must also be on the boundary of a UTF-8 code point. - /// - /// The two slices returned go from the start of the string slice to `mid`, - /// and from `mid` to the end of the string slice. - /// - /// To get mutable string slices instead, see the [`split_at_mut`] - /// method. - /// - /// [`split_at_mut`]: #method.split_at_mut - /// - /// # Panics - /// - /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is - /// beyond the last code point of the string slice. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = "Per Martin-Löf"; - /// - /// let (first, last) = s.split_at(3); - /// - /// assert_eq!("Per", first); - /// assert_eq!(" Martin-Löf", last); - /// ``` - #[inline] - #[stable(feature = "str_split_at", since = "1.4.0")] - pub fn split_at(&self, mid: usize) -> (&str, &str) { - core_str::StrExt::split_at(self, mid) - } - - /// Divide one mutable string slice into two at an index. - /// - /// The argument, `mid`, should be a byte offset from the start of the - /// string. It must also be on the boundary of a UTF-8 code point. - /// - /// The two slices returned go from the start of the string slice to `mid`, - /// and from `mid` to the end of the string slice. - /// - /// To get immutable string slices instead, see the [`split_at`] method. - /// - /// [`split_at`]: #method.split_at - /// - /// # Panics - /// - /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is - /// beyond the last code point of the string slice. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let mut s = "Per Martin-Löf".to_string(); - /// - /// let (first, last) = s.split_at_mut(3); - /// - /// assert_eq!("Per", first); - /// assert_eq!(" Martin-Löf", last); - /// ``` - #[inline] - #[stable(feature = "str_split_at", since = "1.4.0")] - pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) { - core_str::StrExt::split_at_mut(self, mid) - } - - /// Returns an iterator over the [`char`]s of a string slice. - /// - /// As a string slice consists of valid UTF-8, we can iterate through a - /// string slice by [`char`]. This method returns such an iterator. - /// - /// It's important to remember that [`char`] represents a Unicode Scalar - /// Value, and may not match your idea of what a 'character' is. Iteration - /// over grapheme clusters may be what you actually want. - /// - /// [`char`]: primitive.char.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let word = "goodbye"; - /// - /// let count = word.chars().count(); - /// assert_eq!(7, count); - /// - /// let mut chars = word.chars(); - /// - /// assert_eq!(Some('g'), chars.next()); - /// assert_eq!(Some('o'), chars.next()); - /// assert_eq!(Some('o'), chars.next()); - /// assert_eq!(Some('d'), chars.next()); - /// assert_eq!(Some('b'), chars.next()); - /// assert_eq!(Some('y'), chars.next()); - /// assert_eq!(Some('e'), chars.next()); - /// - /// assert_eq!(None, chars.next()); - /// ``` - /// - /// Remember, [`char`]s may not match your human intuition about characters: - /// - /// ``` - /// let y = "y̆"; - /// - /// let mut chars = y.chars(); - /// - /// assert_eq!(Some('y'), chars.next()); // not 'y̆' - /// assert_eq!(Some('\u{0306}'), chars.next()); - /// - /// assert_eq!(None, chars.next()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn chars(&self) -> Chars { - core_str::StrExt::chars(self) - } - /// Returns an iterator over the [`char`]s of a string slice, and their - /// positions. - /// - /// As a string slice consists of valid UTF-8, we can iterate through a - /// string slice by [`char`]. This method returns an iterator of both - /// these [`char`]s, as well as their byte positions. - /// - /// The iterator yields tuples. The position is first, the [`char`] is - /// second. - /// - /// [`char`]: primitive.char.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let word = "goodbye"; - /// - /// let count = word.char_indices().count(); - /// assert_eq!(7, count); - /// - /// let mut char_indices = word.char_indices(); - /// - /// assert_eq!(Some((0, 'g')), char_indices.next()); - /// assert_eq!(Some((1, 'o')), char_indices.next()); - /// assert_eq!(Some((2, 'o')), char_indices.next()); - /// assert_eq!(Some((3, 'd')), char_indices.next()); - /// assert_eq!(Some((4, 'b')), char_indices.next()); - /// assert_eq!(Some((5, 'y')), char_indices.next()); - /// assert_eq!(Some((6, 'e')), char_indices.next()); - /// - /// assert_eq!(None, char_indices.next()); - /// ``` - /// - /// Remember, [`char`]s may not match your human intuition about characters: - /// - /// ``` - /// let y = "y̆"; - /// - /// let mut char_indices = y.char_indices(); - /// - /// assert_eq!(Some((0, 'y')), char_indices.next()); // not (0, 'y̆') - /// assert_eq!(Some((1, '\u{0306}')), char_indices.next()); - /// - /// assert_eq!(None, char_indices.next()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn char_indices(&self) -> CharIndices { - core_str::StrExt::char_indices(self) - } - - /// An iterator over the bytes of a string slice. - /// - /// As a string slice consists of a sequence of bytes, we can iterate - /// through a string slice by byte. This method returns such an iterator. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let mut bytes = "bors".bytes(); - /// - /// assert_eq!(Some(b'b'), bytes.next()); - /// assert_eq!(Some(b'o'), bytes.next()); - /// assert_eq!(Some(b'r'), bytes.next()); - /// assert_eq!(Some(b's'), bytes.next()); - /// - /// assert_eq!(None, bytes.next()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn bytes(&self) -> Bytes { - core_str::StrExt::bytes(self) - } - - /// Split a string slice by whitespace. - /// - /// The iterator returned will return string slices that are sub-slices of - /// the original string slice, separated by any amount of whitespace. - /// - /// 'Whitespace' is defined according to the terms of the Unicode Derived - /// Core Property `White_Space`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let mut iter = "A few words".split_whitespace(); - /// - /// assert_eq!(Some("A"), iter.next()); - /// assert_eq!(Some("few"), iter.next()); - /// assert_eq!(Some("words"), iter.next()); - /// - /// assert_eq!(None, iter.next()); - /// ``` - /// - /// All kinds of whitespace are considered: - /// - /// ``` - /// let mut iter = " Mary had\ta\u{2009}little \n\t lamb".split_whitespace(); - /// assert_eq!(Some("Mary"), iter.next()); - /// assert_eq!(Some("had"), iter.next()); - /// assert_eq!(Some("a"), iter.next()); - /// assert_eq!(Some("little"), iter.next()); - /// assert_eq!(Some("lamb"), iter.next()); - /// - /// assert_eq!(None, iter.next()); - /// ``` - #[stable(feature = "split_whitespace", since = "1.1.0")] - #[inline] - pub fn split_whitespace(&self) -> SplitWhitespace { - UnicodeStr::split_whitespace(self) - } - - /// An iterator over the lines of a string, as string slices. - /// - /// Lines are ended with either a newline (`\n`) or a carriage return with - /// a line feed (`\r\n`). - /// - /// The final line ending is optional. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let text = "foo\r\nbar\n\nbaz\n"; - /// let mut lines = text.lines(); - /// - /// assert_eq!(Some("foo"), lines.next()); - /// assert_eq!(Some("bar"), lines.next()); - /// assert_eq!(Some(""), lines.next()); - /// assert_eq!(Some("baz"), lines.next()); - /// - /// assert_eq!(None, lines.next()); - /// ``` - /// - /// The final line ending isn't required: - /// - /// ``` - /// let text = "foo\nbar\n\r\nbaz"; - /// let mut lines = text.lines(); - /// - /// assert_eq!(Some("foo"), lines.next()); - /// assert_eq!(Some("bar"), lines.next()); - /// assert_eq!(Some(""), lines.next()); - /// assert_eq!(Some("baz"), lines.next()); - /// - /// assert_eq!(None, lines.next()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn lines(&self) -> Lines { - core_str::StrExt::lines(self) - } - - /// An iterator over the lines of a string. - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_deprecated(since = "1.4.0", reason = "use lines() instead now")] - #[inline] - #[allow(deprecated)] - pub fn lines_any(&self) -> LinesAny { - core_str::StrExt::lines_any(self) - } - - /// Returns an iterator of `u16` over the string encoded as UTF-16. - #[stable(feature = "encode_utf16", since = "1.8.0")] - pub fn encode_utf16(&self) -> EncodeUtf16 { - EncodeUtf16 { encoder: Utf16Encoder::new(self[..].chars()) } - } - - /// Returns `true` if the given pattern matches a sub-slice of - /// this string slice. - /// - /// Returns `false` if it does not. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let bananas = "bananas"; - /// - /// assert!(bananas.contains("nana")); - /// assert!(!bananas.contains("apples")); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { - core_str::StrExt::contains(self, pat) - } - - /// Returns `true` if the given pattern matches a prefix of this - /// string slice. - /// - /// Returns `false` if it does not. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let bananas = "bananas"; - /// - /// assert!(bananas.starts_with("bana")); - /// assert!(!bananas.starts_with("nana")); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { - core_str::StrExt::starts_with(self, pat) - } - - /// Returns `true` if the given pattern matches a suffix of this - /// string slice. - /// - /// Returns `false` if it does not. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let bananas = "bananas"; - /// - /// assert!(bananas.ends_with("anas")); - /// assert!(!bananas.ends_with("nana")); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::ends_with(self, pat) - } - - /// Returns the byte index of the first character of this string slice that - /// matches the pattern. - /// - /// Returns [`None`] if the pattern doesn't match. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines if - /// a character matches. - /// - /// [`char`]: primitive.char.html - /// [`None`]: option/enum.Option.html#variant.None - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// - /// assert_eq!(s.find('L'), Some(0)); - /// assert_eq!(s.find('é'), Some(14)); - /// assert_eq!(s.find("Léopard"), Some(13)); - /// ``` - /// - /// More complex patterns with closures: - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// - /// assert_eq!(s.find(char::is_whitespace), Some(5)); - /// assert_eq!(s.find(char::is_lowercase), Some(1)); - /// ``` - /// - /// Not finding the pattern: - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// let x: &[_] = &['1', '2']; - /// - /// assert_eq!(s.find(x), None); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option { - core_str::StrExt::find(self, pat) - } - - /// Returns the byte index of the last character of this string slice that - /// matches the pattern. - /// - /// Returns [`None`] if the pattern doesn't match. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines if - /// a character matches. - /// - /// [`char`]: primitive.char.html - /// [`None`]: option/enum.Option.html#variant.None - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// - /// assert_eq!(s.rfind('L'), Some(13)); - /// assert_eq!(s.rfind('é'), Some(14)); - /// ``` - /// - /// More complex patterns with closures: - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// - /// assert_eq!(s.rfind(char::is_whitespace), Some(12)); - /// assert_eq!(s.rfind(char::is_lowercase), Some(20)); - /// ``` - /// - /// Not finding the pattern: - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// let x: &[_] = &['1', '2']; - /// - /// assert_eq!(s.rfind(x), None); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::rfind(self, pat) - } - - /// An iterator over substrings of this string slice, separated by - /// characters matched by a pattern. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines the - /// split. - /// - /// # Iterator behavior - /// - /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern - /// allows a reverse search and forward/reverse search yields the same - /// elements. This is true for, eg, [`char`] but not for `&str`. - /// - /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// - /// If the pattern allows a reverse search but its results might differ - /// from a forward search, the [`rsplit`] method can be used. - /// - /// [`char`]: primitive.char.html - /// [`rsplit`]: #method.rsplit - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect(); - /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]); - /// - /// let v: Vec<&str> = "".split('X').collect(); - /// assert_eq!(v, [""]); - /// - /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect(); - /// assert_eq!(v, ["lion", "", "tiger", "leopard"]); - /// - /// let v: Vec<&str> = "lion::tiger::leopard".split("::").collect(); - /// assert_eq!(v, ["lion", "tiger", "leopard"]); - /// - /// let v: Vec<&str> = "abc1def2ghi".split(char::is_numeric).collect(); - /// assert_eq!(v, ["abc", "def", "ghi"]); - /// - /// let v: Vec<&str> = "lionXtigerXleopard".split(char::is_uppercase).collect(); - /// assert_eq!(v, ["lion", "tiger", "leopard"]); - /// ``` - /// - /// A more complex pattern, using a closure: - /// - /// ``` - /// let v: Vec<&str> = "abc1defXghi".split(|c| c == '1' || c == 'X').collect(); - /// assert_eq!(v, ["abc", "def", "ghi"]); - /// ``` - /// - /// If a string contains multiple contiguous separators, you will end up - /// with empty strings in the output: - /// - /// ``` - /// let x = "||||a||b|c".to_string(); - /// let d: Vec<_> = x.split('|').collect(); - /// - /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]); - /// ``` - /// - /// Contiguous separators are separated by the empty string. - /// - /// ``` - /// let x = "(///)".to_string(); - /// let d: Vec<_> = x.split('/').collect(); - /// - /// assert_eq!(d, &["(", "", "", ")"]); - /// ``` - /// - /// Separators at the start or end of a string are neighbored - /// by empty strings. - /// - /// ``` - /// let d: Vec<_> = "010".split("0").collect(); - /// assert_eq!(d, &["", "1", ""]); - /// ``` - /// - /// When the empty string is used as a separator, it separates - /// every character in the string, along with the beginning - /// and end of the string. - /// - /// ``` - /// let f: Vec<_> = "rust".split("").collect(); - /// assert_eq!(f, &["", "r", "u", "s", "t", ""]); - /// ``` - /// - /// Contiguous separators can lead to possibly surprising behavior - /// when whitespace is used as the separator. This code is correct: - /// - /// ``` - /// let x = " a b c".to_string(); - /// let d: Vec<_> = x.split(' ').collect(); - /// - /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]); - /// ``` - /// - /// It does _not_ give you: - /// - /// ```,ignore - /// assert_eq!(d, &["a", "b", "c"]); - /// ``` - /// - /// Use [`split_whitespace`] for this behavior. - /// - /// [`split_whitespace`]: #method.split_whitespace - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> { - core_str::StrExt::split(self, pat) - } - - /// An iterator over substrings of the given string slice, separated by - /// characters matched by a pattern and yielded in reverse order. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines the - /// split. - /// - /// [`char`]: primitive.char.html - /// - /// # Iterator behavior - /// - /// The returned iterator requires that the pattern supports a reverse - /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse - /// search yields the same elements. - /// - /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// - /// For iterating from the front, the [`split`] method can be used. - /// - /// [`split`]: #method.split - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// let v: Vec<&str> = "Mary had a little lamb".rsplit(' ').collect(); - /// assert_eq!(v, ["lamb", "little", "a", "had", "Mary"]); - /// - /// let v: Vec<&str> = "".rsplit('X').collect(); - /// assert_eq!(v, [""]); - /// - /// let v: Vec<&str> = "lionXXtigerXleopard".rsplit('X').collect(); - /// assert_eq!(v, ["leopard", "tiger", "", "lion"]); - /// - /// let v: Vec<&str> = "lion::tiger::leopard".rsplit("::").collect(); - /// assert_eq!(v, ["leopard", "tiger", "lion"]); - /// ``` - /// - /// A more complex pattern, using a closure: - /// - /// ``` - /// let v: Vec<&str> = "abc1defXghi".rsplit(|c| c == '1' || c == 'X').collect(); - /// assert_eq!(v, ["ghi", "def", "abc"]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P> - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::rsplit(self, pat) - } - - /// An iterator over substrings of the given string slice, separated by - /// characters matched by a pattern. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines the - /// split. - /// - /// Equivalent to [`split`], except that the trailing substring - /// is skipped if empty. - /// - /// [`split`]: #method.split - /// - /// This method can be used for string data that is _terminated_, - /// rather than _separated_ by a pattern. - /// - /// # Iterator behavior - /// - /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern - /// allows a reverse search and forward/reverse search yields the same - /// elements. This is true for, eg, [`char`] but not for `&str`. - /// - /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// [`char`]: primitive.char.html - /// - /// If the pattern allows a reverse search but its results might differ - /// from a forward search, the [`rsplit_terminator`] method can be used. - /// - /// [`rsplit_terminator`]: #method.rsplit_terminator - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let v: Vec<&str> = "A.B.".split_terminator('.').collect(); - /// assert_eq!(v, ["A", "B"]); - /// - /// let v: Vec<&str> = "A..B..".split_terminator(".").collect(); - /// assert_eq!(v, ["A", "", "B", ""]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> { - core_str::StrExt::split_terminator(self, pat) - } - - /// An iterator over substrings of `self`, separated by characters - /// matched by a pattern and yielded in reverse order. - /// - /// The pattern can be a simple `&str`, [`char`], or a closure that - /// determines the split. - /// Additional libraries might provide more complex patterns like - /// regular expressions. - /// - /// [`char`]: primitive.char.html - /// - /// Equivalent to [`split`], except that the trailing substring is - /// skipped if empty. - /// - /// [`split`]: #method.split - /// - /// This method can be used for string data that is _terminated_, - /// rather than _separated_ by a pattern. - /// - /// # Iterator behavior - /// - /// The returned iterator requires that the pattern supports a - /// reverse search, and it will be double ended if a forward/reverse - /// search yields the same elements. - /// - /// For iterating from the front, the [`split_terminator`] method can be - /// used. - /// - /// [`split_terminator`]: #method.split_terminator - /// - /// # Examples - /// - /// ``` - /// let v: Vec<&str> = "A.B.".rsplit_terminator('.').collect(); - /// assert_eq!(v, ["B", "A"]); - /// - /// let v: Vec<&str> = "A..B..".rsplit_terminator(".").collect(); - /// assert_eq!(v, ["", "B", "", "A"]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn rsplit_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplitTerminator<'a, P> - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::rsplit_terminator(self, pat) - } - - /// An iterator over substrings of the given string slice, separated by a - /// pattern, restricted to returning at most `n` items. - /// - /// If `n` substrings are returned, the last substring (the `n`th substring) - /// will contain the remainder of the string. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines the - /// split. - /// - /// [`char`]: primitive.char.html - /// - /// # Iterator behavior - /// - /// The returned iterator will not be double ended, because it is - /// not efficient to support. - /// - /// If the pattern allows a reverse search, the [`rsplitn`] method can be - /// used. - /// - /// [`rsplitn`]: #method.rsplitn - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// let v: Vec<&str> = "Mary had a little lambda".splitn(3, ' ').collect(); - /// assert_eq!(v, ["Mary", "had", "a little lambda"]); - /// - /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(3, "X").collect(); - /// assert_eq!(v, ["lion", "", "tigerXleopard"]); - /// - /// let v: Vec<&str> = "abcXdef".splitn(1, 'X').collect(); - /// assert_eq!(v, ["abcXdef"]); - /// - /// let v: Vec<&str> = "".splitn(1, 'X').collect(); - /// assert_eq!(v, [""]); - /// ``` - /// - /// A more complex pattern, using a closure: - /// - /// ``` - /// let v: Vec<&str> = "abc1defXghi".splitn(2, |c| c == '1' || c == 'X').collect(); - /// assert_eq!(v, ["abc", "defXghi"]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn splitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> SplitN<'a, P> { - core_str::StrExt::splitn(self, n, pat) - } - - /// An iterator over substrings of this string slice, separated by a - /// pattern, starting from the end of the string, restricted to returning - /// at most `n` items. - /// - /// If `n` substrings are returned, the last substring (the `n`th substring) - /// will contain the remainder of the string. - /// - /// The pattern can be a `&str`, [`char`], or a closure that - /// determines the split. - /// - /// [`char`]: primitive.char.html - /// - /// # Iterator behavior - /// - /// The returned iterator will not be double ended, because it is not - /// efficient to support. - /// - /// For splitting from the front, the [`splitn`] method can be used. - /// - /// [`splitn`]: #method.splitn - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(3, ' ').collect(); - /// assert_eq!(v, ["lamb", "little", "Mary had a"]); - /// - /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(3, 'X').collect(); - /// assert_eq!(v, ["leopard", "tiger", "lionX"]); - /// - /// let v: Vec<&str> = "lion::tiger::leopard".rsplitn(2, "::").collect(); - /// assert_eq!(v, ["leopard", "lion::tiger"]); - /// ``` - /// - /// A more complex pattern, using a closure: - /// - /// ``` - /// let v: Vec<&str> = "abc1defXghi".rsplitn(2, |c| c == '1' || c == 'X').collect(); - /// assert_eq!(v, ["ghi", "abc1def"]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> RSplitN<'a, P> - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::rsplitn(self, n, pat) - } - - /// An iterator over the matches of a pattern within the given string - /// slice. - /// - /// The pattern can be a `&str`, [`char`], or a closure that - /// determines if a character matches. - /// - /// [`char`]: primitive.char.html - /// - /// # Iterator behavior - /// - /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern - /// allows a reverse search and forward/reverse search yields the same - /// elements. This is true for, eg, [`char`] but not for `&str`. - /// - /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// [`char`]: primitive.char.html - /// - /// If the pattern allows a reverse search but its results might differ - /// from a forward search, the [`rmatches`] method can be used. - /// - /// [`rmatches`]: #method.rmatches - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let v: Vec<&str> = "abcXXXabcYYYabc".matches("abc").collect(); - /// assert_eq!(v, ["abc", "abc", "abc"]); - /// - /// let v: Vec<&str> = "1abc2abc3".matches(char::is_numeric).collect(); - /// assert_eq!(v, ["1", "2", "3"]); - /// ``` - #[stable(feature = "str_matches", since = "1.2.0")] - #[inline] - pub fn matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> Matches<'a, P> { - core_str::StrExt::matches(self, pat) - } - - /// An iterator over the matches of a pattern within this string slice, - /// yielded in reverse order. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines if - /// a character matches. - /// - /// [`char`]: primitive.char.html - /// - /// # Iterator behavior - /// - /// The returned iterator requires that the pattern supports a reverse - /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse - /// search yields the same elements. - /// - /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// - /// For iterating from the front, the [`matches`] method can be used. - /// - /// [`matches`]: #method.matches - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let v: Vec<&str> = "abcXXXabcYYYabc".rmatches("abc").collect(); - /// assert_eq!(v, ["abc", "abc", "abc"]); - /// - /// let v: Vec<&str> = "1abc2abc3".rmatches(char::is_numeric).collect(); - /// assert_eq!(v, ["3", "2", "1"]); - /// ``` - #[stable(feature = "str_matches", since = "1.2.0")] - #[inline] - pub fn rmatches<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatches<'a, P> - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::rmatches(self, pat) - } - - /// An iterator over the disjoint matches of a pattern within this string - /// slice as well as the index that the match starts at. - /// - /// For matches of `pat` within `self` that overlap, only the indices - /// corresponding to the first match are returned. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines - /// if a character matches. - /// - /// [`char`]: primitive.char.html - /// - /// # Iterator behavior - /// - /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern - /// allows a reverse search and forward/reverse search yields the same - /// elements. This is true for, eg, [`char`] but not for `&str`. - /// - /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// - /// If the pattern allows a reverse search but its results might differ - /// from a forward search, the [`rmatch_indices`] method can be used. - /// - /// [`rmatch_indices`]: #method.rmatch_indices - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let v: Vec<_> = "abcXXXabcYYYabc".match_indices("abc").collect(); - /// assert_eq!(v, [(0, "abc"), (6, "abc"), (12, "abc")]); - /// - /// let v: Vec<_> = "1abcabc2".match_indices("abc").collect(); - /// assert_eq!(v, [(1, "abc"), (4, "abc")]); - /// - /// let v: Vec<_> = "ababa".match_indices("aba").collect(); - /// assert_eq!(v, [(0, "aba")]); // only the first `aba` - /// ``` - #[stable(feature = "str_match_indices", since = "1.5.0")] - #[inline] - pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> { - core_str::StrExt::match_indices(self, pat) - } - - /// An iterator over the disjoint matches of a pattern within `self`, - /// yielded in reverse order along with the index of the match. - /// - /// For matches of `pat` within `self` that overlap, only the indices - /// corresponding to the last match are returned. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines if a - /// character matches. - /// - /// [`char`]: primitive.char.html - /// - /// # Iterator behavior - /// - /// The returned iterator requires that the pattern supports a reverse - /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse - /// search yields the same elements. - /// - /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// - /// For iterating from the front, the [`match_indices`] method can be used. - /// - /// [`match_indices`]: #method.match_indices - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let v: Vec<_> = "abcXXXabcYYYabc".rmatch_indices("abc").collect(); - /// assert_eq!(v, [(12, "abc"), (6, "abc"), (0, "abc")]); - /// - /// let v: Vec<_> = "1abcabc2".rmatch_indices("abc").collect(); - /// assert_eq!(v, [(4, "abc"), (1, "abc")]); - /// - /// let v: Vec<_> = "ababa".rmatch_indices("aba").collect(); - /// assert_eq!(v, [(2, "aba")]); // only the last `aba` - /// ``` - #[stable(feature = "str_match_indices", since = "1.5.0")] - #[inline] - pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P> - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::rmatch_indices(self, pat) - } - - /// Returns a string slice with leading and trailing whitespace removed. - /// - /// 'Whitespace' is defined according to the terms of the Unicode Derived - /// Core Property `White_Space`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = " Hello\tworld\t"; - /// - /// assert_eq!("Hello\tworld", s.trim()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn trim(&self) -> &str { - UnicodeStr::trim(self) - } - - /// Returns a string slice with leading whitespace removed. - /// - /// 'Whitespace' is defined according to the terms of the Unicode Derived - /// Core Property `White_Space`. - /// - /// # Text directionality - /// - /// A string is a sequence of bytes. 'Left' in this context means the first - /// position of that byte string; for a language like Arabic or Hebrew - /// which are 'right to left' rather than 'left to right', this will be - /// the _right_ side, not the left. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = " Hello\tworld\t"; - /// - /// assert_eq!("Hello\tworld\t", s.trim_left()); - /// ``` - /// - /// Directionality: - /// - /// ``` - /// let s = " English"; - /// assert!(Some('E') == s.trim_left().chars().next()); - /// - /// let s = " עברית"; - /// assert!(Some('ע') == s.trim_left().chars().next()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn trim_left(&self) -> &str { - UnicodeStr::trim_left(self) - } - - /// Returns a string slice with trailing whitespace removed. - /// - /// 'Whitespace' is defined according to the terms of the Unicode Derived - /// Core Property `White_Space`. - /// - /// # Text directionality - /// - /// A string is a sequence of bytes. 'Right' in this context means the last - /// position of that byte string; for a language like Arabic or Hebrew - /// which are 'right to left' rather than 'left to right', this will be - /// the _left_ side, not the right. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = " Hello\tworld\t"; - /// - /// assert_eq!(" Hello\tworld", s.trim_right()); - /// ``` - /// - /// Directionality: - /// - /// ``` - /// let s = "English "; - /// assert!(Some('h') == s.trim_right().chars().rev().next()); - /// - /// let s = "עברית "; - /// assert!(Some('ת') == s.trim_right().chars().rev().next()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn trim_right(&self) -> &str { - UnicodeStr::trim_right(self) - } - - /// Returns a string slice with all prefixes and suffixes that match a - /// pattern repeatedly removed. - /// - /// The pattern can be a [`char`] or a closure that determines if a - /// character matches. - /// - /// [`char`]: primitive.char.html - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar"); - /// assert_eq!("123foo1bar123".trim_matches(char::is_numeric), "foo1bar"); - /// - /// let x: &[_] = &['1', '2']; - /// assert_eq!("12foo1bar12".trim_matches(x), "foo1bar"); - /// ``` - /// - /// A more complex pattern, using a closure: - /// - /// ``` - /// assert_eq!("1foo1barXX".trim_matches(|c| c == '1' || c == 'X'), "foo1bar"); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str - where P::Searcher: DoubleEndedSearcher<'a> - { - core_str::StrExt::trim_matches(self, pat) - } - - /// Returns a string slice with all prefixes that match a pattern - /// repeatedly removed. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines if - /// a character matches. - /// - /// [`char`]: primitive.char.html - /// - /// # Text directionality - /// - /// A string is a sequence of bytes. 'Left' in this context means the first - /// position of that byte string; for a language like Arabic or Hebrew - /// which are 'right to left' rather than 'left to right', this will be - /// the _right_ side, not the left. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11"); - /// assert_eq!("123foo1bar123".trim_left_matches(char::is_numeric), "foo1bar123"); - /// - /// let x: &[_] = &['1', '2']; - /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12"); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str { - core_str::StrExt::trim_left_matches(self, pat) - } - - /// Returns a string slice with all suffixes that match a pattern - /// repeatedly removed. - /// - /// The pattern can be a `&str`, [`char`], or a closure that - /// determines if a character matches. - /// - /// [`char`]: primitive.char.html - /// - /// # Text directionality - /// - /// A string is a sequence of bytes. 'Right' in this context means the last - /// position of that byte string; for a language like Arabic or Hebrew - /// which are 'right to left' rather than 'left to right', this will be - /// the _left_ side, not the right. - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar"); - /// assert_eq!("123foo1bar123".trim_right_matches(char::is_numeric), "123foo1bar"); - /// - /// let x: &[_] = &['1', '2']; - /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar"); - /// ``` - /// - /// A more complex pattern, using a closure: - /// - /// ``` - /// assert_eq!("1fooX".trim_left_matches(|c| c == '1' || c == 'X'), "fooX"); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::trim_right_matches(self, pat) - } - - /// Parses this string slice into another type. - /// - /// Because `parse` is so general, it can cause problems with type - /// inference. As such, `parse` is one of the few times you'll see - /// the syntax affectionately known as the 'turbofish': `::<>`. This - /// helps the inference algorithm understand specifically which type - /// you're trying to parse into. - /// - /// `parse` can parse any type that implements the [`FromStr`] trait. - /// - /// [`FromStr`]: str/trait.FromStr.html - /// - /// # Errors - /// - /// Will return [`Err`] if it's not possible to parse this string slice into - /// the desired type. - /// - /// [`Err`]: str/trait.FromStr.html#associatedtype.Err - /// - /// # Example - /// - /// Basic usage - /// - /// ``` - /// let four: u32 = "4".parse().unwrap(); - /// - /// assert_eq!(4, four); - /// ``` - /// - /// Using the 'turbofish' instead of annotating `four`: - /// - /// ``` - /// let four = "4".parse::(); - /// - /// assert_eq!(Ok(4), four); - /// ``` - /// - /// Failing to parse: - /// - /// ``` - /// let nope = "j".parse::(); - /// - /// assert!(nope.is_err()); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn parse(&self) -> Result { - core_str::StrExt::parse(self) - } - - /// Converts a `Box` into a `Box<[u8]>` without copying or allocating. - #[unstable(feature = "str_box_extras", issue = "41119")] - pub fn into_boxed_bytes(self: Box) -> Box<[u8]> { - self.into() - } - - /// Replaces all matches of a pattern with another string. - /// - /// `replace` creates a new [`String`], and copies the data from this string slice into it. - /// While doing so, it attempts to find matches of a pattern. If it finds any, it - /// replaces them with the replacement string slice. - /// - /// [`String`]: string/struct.String.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = "this is old"; - /// - /// assert_eq!("this is new", s.replace("old", "new")); - /// ``` - /// - /// When the pattern doesn't match: - /// - /// ``` - /// let s = "this is old"; - /// assert_eq!(s, s.replace("cookie monster", "little lamb")); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn replace<'a, P: Pattern<'a>>(&'a self, from: P, to: &str) -> String { - let mut result = String::new(); - let mut last_end = 0; - for (start, part) in self.match_indices(from) { - result.push_str(unsafe { self.slice_unchecked(last_end, start) }); - result.push_str(to); - last_end = start + part.len(); - } - result.push_str(unsafe { self.slice_unchecked(last_end, self.len()) }); - result - } - - /// Replaces first N matches of a pattern with another string. - /// - /// `replacen` creates a new [`String`], and copies the data from this string slice into it. - /// While doing so, it attempts to find matches of a pattern. If it finds any, it - /// replaces them with the replacement string slice at most `count` times. - /// - /// [`String`]: string/struct.String.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// 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)); - /// assert_eq!("foo foo new23 foo", s.replacen(char::is_numeric, "new", 1)); - /// ``` - /// - /// When the pattern doesn't match: - /// - /// ``` - /// let s = "this is old"; - /// assert_eq!(s, s.replacen("cookie monster", "little lamb", 10)); - /// ``` - #[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); - let mut last_end = 0; - for (start, part) in self.match_indices(pat).take(count) { - result.push_str(unsafe { self.slice_unchecked(last_end, start) }); - result.push_str(to); - last_end = start + part.len(); - } - result.push_str(unsafe { self.slice_unchecked(last_end, self.len()) }); - result - } - - /// Returns the lowercase equivalent of this string slice, as a new [`String`]. - /// - /// 'Lowercase' is defined according to the terms of the Unicode Derived Core Property - /// `Lowercase`. - /// - /// Since some characters can expand into multiple characters when changing - /// the case, this function returns a [`String`] instead of modifying the - /// parameter in-place. - /// - /// [`String`]: string/struct.String.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = "HELLO"; - /// - /// assert_eq!("hello", s.to_lowercase()); - /// ``` - /// - /// A tricky example, with sigma: - /// - /// ``` - /// let sigma = "Σ"; - /// - /// assert_eq!("σ", sigma.to_lowercase()); - /// - /// // but at the end of a word, it's ς, not σ: - /// let odysseus = "ὈΔΥΣΣΕΎΣ"; - /// - /// assert_eq!("ὀδυσσεύς", odysseus.to_lowercase()); - /// ``` - /// - /// Languages without case are not changed: - /// - /// ``` - /// let new_year = "农历新年"; - /// - /// assert_eq!(new_year, new_year.to_lowercase()); - /// ``` - #[stable(feature = "unicode_case_mapping", since = "1.2.0")] - pub fn to_lowercase(&self) -> String { - let mut s = String::with_capacity(self.len()); - for (i, c) in self[..].char_indices() { - if c == 'Σ' { - // Σ maps to σ, except at the end of a word where it maps to ς. - // This is the only conditional (contextual) but language-independent mapping - // in `SpecialCasing.txt`, - // so hard-code it rather than have a generic "condition" mechanism. - // See https://github.com/rust-lang/rust/issues/26035 - map_uppercase_sigma(self, i, &mut s) - } else { - s.extend(c.to_lowercase()); - } - } - return s; - - fn map_uppercase_sigma(from: &str, i: usize, to: &mut String) { - // See http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992 - // for the definition of `Final_Sigma`. - 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 { "σ" }); - } - - fn case_ignoreable_then_cased>(iter: I) -> bool { - use std_unicode::derived_property::{Cased, Case_Ignorable}; - match iter.skip_while(|&c| Case_Ignorable(c)).next() { - Some(c) => Cased(c), - None => false, - } - } - } - - /// Returns the uppercase equivalent of this string slice, as a new [`String`]. - /// - /// 'Uppercase' is defined according to the terms of the Unicode Derived Core Property - /// `Uppercase`. - /// - /// Since some characters can expand into multiple characters when changing - /// the case, this function returns a [`String`] instead of modifying the - /// parameter in-place. - /// - /// [`String`]: string/struct.String.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = "hello"; - /// - /// assert_eq!("HELLO", s.to_uppercase()); - /// ``` - /// - /// Scripts without case are not changed: - /// - /// ``` - /// let new_year = "农历新年"; - /// - /// assert_eq!(new_year, new_year.to_uppercase()); - /// ``` - #[stable(feature = "unicode_case_mapping", since = "1.2.0")] - pub fn to_uppercase(&self) -> String { - let mut s = String::with_capacity(self.len()); - s.extend(self.chars().flat_map(|c| c.to_uppercase())); - return s; - } - - /// Escapes each char in `s` with [`char::escape_debug`]. - /// - /// [`char::escape_debug`]: primitive.char.html#method.escape_debug - #[unstable(feature = "str_escape", - reason = "return type may change to be an iterator", - issue = "27791")] - pub fn escape_debug(&self) -> String { - self.chars().flat_map(|c| c.escape_debug()).collect() - } - - /// Escapes each char in `s` with [`char::escape_default`]. - /// - /// [`char::escape_default`]: primitive.char.html#method.escape_default - #[unstable(feature = "str_escape", - reason = "return type may change to be an iterator", - issue = "27791")] - pub fn escape_default(&self) -> String { - self.chars().flat_map(|c| c.escape_default()).collect() - } - - /// Escapes each char in `s` with [`char::escape_unicode`]. - /// - /// [`char::escape_unicode`]: primitive.char.html#method.escape_unicode - #[unstable(feature = "str_escape", - reason = "return type may change to be an iterator", - issue = "27791")] - pub fn escape_unicode(&self) -> String { - self.chars().flat_map(|c| c.escape_unicode()).collect() - } - - /// Converts a [`Box`] into a [`String`] without copying or allocating. - /// - /// [`String`]: string/struct.String.html - /// [`Box`]: boxed/struct.Box.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let string = String::from("birthday gift"); - /// let boxed_str = string.clone().into_boxed_str(); - /// - /// assert_eq!(boxed_str.into_string(), string); - /// ``` - #[stable(feature = "box_str", since = "1.4.0")] - pub fn into_string(self: Box) -> String { - unsafe { - let slice = mem::transmute::, Box<[u8]>>(self); - String::from_utf8_unchecked(slice.into_vec()) - } - } - - /// Create a [`String`] by repeating a string `n` times. - /// - /// [`String`]: string/struct.String.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// assert_eq!("abc".repeat(4), String::from("abcabcabcabc")); - /// ``` - #[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)); - s - } -} diff --git a/src/libcompiler_builtins/.travis.yml b/src/libcompiler_builtins/.travis.yml new file mode 100644 index 0000000000..8a9d1faa1d --- /dev/null +++ b/src/libcompiler_builtins/.travis.yml @@ -0,0 +1,58 @@ +dist: trusty +language: rust +rust: nightly +services: docker +sudo: required + +matrix: + include: + - env: TARGET=aarch64-unknown-linux-gnu + - env: TARGET=arm-unknown-linux-gnueabi + - env: TARGET=arm-unknown-linux-gnueabihf + - env: TARGET=armv7-unknown-linux-gnueabihf + - env: TARGET=i586-unknown-linux-gnu + - env: TARGET=i686-apple-darwin + os: osx + - env: TARGET=i686-unknown-linux-gnu + - env: TARGET=mips-unknown-linux-gnu + - env: TARGET=mips64-unknown-linux-gnuabi64 + - env: TARGET=mips64el-unknown-linux-gnuabi64 + - env: TARGET=mipsel-unknown-linux-gnu + - env: TARGET=powerpc-unknown-linux-gnu + - env: TARGET=powerpc64-unknown-linux-gnu + - env: TARGET=powerpc64le-unknown-linux-gnu + - env: TARGET=thumbv6m-linux-eabi + - env: TARGET=thumbv7em-linux-eabi + - env: TARGET=thumbv7em-linux-eabihf + - env: TARGET=thumbv7m-linux-eabi + - env: TARGET=x86_64-apple-darwin + os: osx + - env: TARGET=x86_64-unknown-linux-gnu + +before_install: + - test "$TRAVIS_OS_NAME" = "osx" || docker run --rm --privileged multiarch/qemu-user-static:register + +install: + - case $TARGET in + x86_64-apple-darwin | x86_64-unknown-linux-gnu) ;; + thumbv*eabi*) rustup component add rust-src ;; + *) rustup target add $TARGET;; + esac + +script: + # work around rust-lang/cargo#3340 + - test "$TRAVIS_OS_NAME" = "osx" || + export SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt + - cargo generate-lockfile + - if [[ $TRAVIS_OS_NAME = "linux" ]]; then + sudo apt-get remove -y qemu-user-static && + sudo apt-get install -y qemu-user-static && + sh ci/run-docker.sh $TARGET; + else + sh ci/run.sh $TARGET; + fi + +notifications: + email: + on_success: never + webhooks: https://buildbot.rust-lang.org/homu/travis diff --git a/src/libcompiler_builtins/Cargo.toml b/src/libcompiler_builtins/Cargo.toml index 2c9cee5e7a..070d8f8c7a 100644 --- a/src/libcompiler_builtins/Cargo.toml +++ b/src/libcompiler_builtins/Cargo.toml @@ -1,19 +1,39 @@ [package] -authors = ["The Rust Project Developers"] +authors = ["Jorge Aparicio "] build = "build.rs" name = "compiler_builtins" -version = "0.0.0" +version = "0.1.0" -[lib] -name = "compiler_builtins" -path = "lib.rs" -test = false -bench = false -doc = false +[build-dependencies] +cast = { version = "0.2.2", features = ["x128"], optional = true } +rand = { version = "0.3.15", optional = true } -[dependencies] -core = { path = "../libcore" } +[build-dependencies.gcc] +optional = true +version = "0.3.36" -[build-dependencies] -build_helper = { path = "../build_helper" } -gcc = "0.3.50" +[features] +c = ["gcc"] +compiler-builtins = [] +default = ["compiler-builtins"] +mem = [] +rustbuild = ["compiler-builtins"] +mangled-names = [] + +# generate tests +# +# Note that this is an internal-only feature used in testing, this should not +# be relied on with crates.io! Enabling this may expose you to breaking +# changes. +gen-tests = ["cast", "rand"] + +[target.'cfg(all(target_arch = "arm", not(any(target_env = "gnu", target_env = "musl")), target_os = "linux"))'.dev-dependencies] +test = { git = "https://github.com/japaric/utest" } +utest-cortex-m-qemu = { default-features = false, git = "https://github.com/japaric/utest" } +utest-macros = { git = "https://github.com/japaric/utest" } + +[[example]] +name = "intrinsics" +required-features = ["c", "compiler-builtins"] + +[workspace] diff --git a/src/libcompiler_builtins/LICENSE.TXT b/src/libcompiler_builtins/LICENSE.TXT new file mode 100644 index 0000000000..92bbe113ab --- /dev/null +++ b/src/libcompiler_builtins/LICENSE.TXT @@ -0,0 +1,91 @@ +============================================================================== +compiler-builtins License +============================================================================== + +The compiler-builtins crate is dual licensed under both the University of +Illinois "BSD-Like" license and the MIT license. As a user of this code you may +choose to use it under either license. As a contributor, you agree to allow +your code to be used under both. + +Full text of the relevant licenses is included below. + +============================================================================== + +University of Illinois/NCSA +Open Source License + +Copyright (c) 2009-2016 by the contributors listed in CREDITS.TXT + +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. + +============================================================================== + +Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +============================================================================== +Copyrights and Licenses for Third Party Software Distributed with LLVM: +============================================================================== +The LLVM software contains code written by third parties. Such software will +have its own individual LICENSE.TXT file in the directory in which it appears. +This file will describe the copyrights, license, and restrictions which apply +to that code. + +The disclaimer of warranty in the University of Illinois Open Source License +applies to all code in the LLVM Distribution, and nothing in any of the +other licenses gives permission to use the names of the LLVM Team or the +University of Illinois to endorse or promote products derived from this +Software. + diff --git a/src/libcompiler_builtins/README.md b/src/libcompiler_builtins/README.md new file mode 100644 index 0000000000..a0e2a29ed1 --- /dev/null +++ b/src/libcompiler_builtins/README.md @@ -0,0 +1,397 @@ +# `compiler-builtins` + +[![Build status](https://ci.appveyor.com/api/projects/status/eusnjps5ui3d305p?svg=true)](https://ci.appveyor.com/project/rust-lang-libs/compiler-builtins) +[![Build Status](https://travis-ci.org/rust-lang-nursery/compiler-builtins.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/compiler-builtins) + +> [WIP] Porting `compiler-rt` intrinsics to Rust + +See [rust-lang/rust#35437][0]. + +[0]: https://github.com/rust-lang/rust/issues/35437 + +## When and how to use this crate? + +If you are working with a target that doesn't have binary releases of std +available via rustup (this probably means you are building the core crate +yourself) and need compiler-rt intrinsics (i.e. you are probably getting linker +errors when building an executable: `undefined reference to __aeabi_memcpy`), +you can use this crate to get those intrinsics and solve the linker errors. To +do that, add this crate somewhere in the dependency graph of the crate you are +building: + +``` toml +# Cargo.toml +[dependencies] +compiler_builtins = { git = "https://github.com/rust-lang-nursery/compiler-builtins" } +``` + +``` rust +extern crate compiler_builtins; + +// ... +``` + +If you still get an "undefined reference to $INTRINSIC" error after that change, +that means that we haven't ported `$INTRINSIC` to Rust yet! Please open [an +issue] with the name of the intrinsic and the LLVM triple (e.g. +thumbv7m-none-eabi) of the target you are using. That way we can prioritize +porting that particular intrinsic. + +If you've got a C compiler available for your target then while we implement +this intrinsic you can temporarily enable a fallback to the actual compiler-rt +implementation as well for unimplemented intrinsics: + +```toml +[dependencies.compiler_builtins] +git = "https://github.com/rust-lang-nursery/compiler-builtins" +features = ["c"] +``` + +[an issue]: https://github.com/rust-lang-nursery/compiler-builtins/issues + +## Contributing + +1. Pick one or more intrinsics from the [pending list][#progress]. +2. Fork this repository +3. Port the intrinsic(s) and their corresponding [unit tests][1] from their [C implementation][2] to + Rust. +4. Send a Pull Request (PR) +5. Once the PR passes our extensive [testing infrastructure][3], we'll merge it! +6. Celebrate :tada: + +[1]: https://github.com/rust-lang/compiler-rt/tree/8598065bd965d9713bfafb6c1e766d63a7b17b89/test/builtins/Unit +[2]: https://github.com/rust-lang/compiler-rt/tree/8598065bd965d9713bfafb6c1e766d63a7b17b89/lib/builtins +[3]: https://travis-ci.org/rust-lang-nursery/compiler-builtins + +### Porting Reminders + +1. [Rust][4] and [C][5] have slightly different operator precedence. C evaluates comparisons (`== !=`) before bitwise operations (`& | ^`), while Rust evaluates the other way. +2. C assumes wrapping operations everywhere. Rust panics on overflow when in debug mode. Consider using the [Wrapping][6] type or the explicit [wrapping_*][7] functions where applicable. +3. Note [C implicit casts][8], especially integer promotion. Rust is much more explicit about casting, so be sure that any cast which affects the output is ported to the Rust implementation. +4. Rust has [many functions][9] for integer or floating point manipulation in the standard library. Consider using one of these functions rather than porting a new one. + +[4]: https://doc.rust-lang.org/reference.html#operator-precedence +[5]: http://en.cppreference.com/w/c/language/operator_precedence +[6]: https://doc.rust-lang.org/core/num/struct.Wrapping.html +[7]: https://doc.rust-lang.org/std/primitive.i32.html#method.wrapping_add +[8]: http://en.cppreference.com/w/cpp/language/implicit_conversion +[9]: https://doc.rust-lang.org/std/primitive.i32.html + +## Progress + +- [x] adddf3.c +- [x] addsf3.c +- [ ] arm/adddf3vfp.S +- [ ] arm/addsf3vfp.S +- [ ] arm/aeabi_dcmp.S +- [ ] arm/aeabi_fcmp.S +- [x] arm/aeabi_idivmod.S +- [x] arm/aeabi_ldivmod.S +- [x] arm/aeabi_memcpy.S +- [x] arm/aeabi_memmove.S +- [x] arm/aeabi_memset.S +- [x] arm/aeabi_uidivmod.S +- [x] arm/aeabi_uldivmod.S +- [ ] arm/divdf3vfp.S +- [ ] arm/divmodsi4.S (generic version is done) +- [ ] arm/divsf3vfp.S +- [ ] arm/divsi3.S (generic version is done) +- [ ] arm/eqdf2vfp.S +- [ ] arm/eqsf2vfp.S +- [ ] arm/extendsfdf2vfp.S +- [ ] arm/fixdfsivfp.S +- [ ] arm/fixsfsivfp.S +- [ ] arm/fixunsdfsivfp.S +- [ ] arm/fixunssfsivfp.S +- [ ] arm/floatsidfvfp.S +- [ ] arm/floatsisfvfp.S +- [ ] arm/floatunssidfvfp.S +- [ ] arm/floatunssisfvfp.S +- [ ] arm/gedf2vfp.S +- [ ] arm/gesf2vfp.S +- [ ] arm/gtdf2vfp.S +- [ ] arm/gtsf2vfp.S +- [ ] arm/ledf2vfp.S +- [ ] arm/lesf2vfp.S +- [ ] arm/ltdf2vfp.S +- [ ] arm/ltsf2vfp.S +- [ ] arm/modsi3.S (generic version is done) +- [ ] arm/muldf3vfp.S +- [ ] arm/mulsf3vfp.S +- [ ] arm/nedf2vfp.S +- [ ] arm/negdf2vfp.S +- [ ] arm/negsf2vfp.S +- [ ] arm/nesf2vfp.S +- [ ] arm/softfloat-alias.list +- [ ] arm/subdf3vfp.S +- [ ] arm/subsf3vfp.S +- [ ] arm/truncdfsf2vfp.S +- [ ] arm/udivmodsi4.S (generic version is done) +- [ ] arm/udivsi3.S (generic version is done) +- [ ] arm/umodsi3.S (generic version is done) +- [ ] arm/unorddf2vfp.S +- [ ] arm/unordsf2vfp.S +- [x] ashldi3.c +- [x] ashrdi3.c +- [ ] divdf3.c +- [x] divdi3.c +- [x] divmoddi4.c +- [x] divmodsi4.c +- [ ] divsf3.c +- [x] divsi3.c +- [ ] extendhfsf2.c +- [ ] extendsfdf2.c +- [x] fixdfdi.c +- [x] fixdfsi.c +- [x] fixsfdi.c +- [x] fixsfsi.c +- [x] fixunsdfdi.c +- [x] fixunsdfsi.c +- [x] fixunssfdi.c +- [x] fixunssfsi.c +- [x] floatdidf.c +- [ ] floatdisf.c +- [x] floatsidf.c +- [x] floatsisf.c +- [x] floatundidf.c +- [ ] floatundisf.c +- [x] floatunsidf.c +- [x] floatunsisf.c +- [ ] i386/ashldi3.S +- [ ] i386/ashrdi3.S +- [ ] i386/chkstk.S +- [ ] i386/chkstk2.S +- [ ] i386/divdi3.S +- [ ] i386/lshrdi3.S +- [ ] i386/moddi3.S +- [ ] i386/muldi3.S +- [ ] i386/udivdi3.S +- [ ] i386/umoddi3.S +- [x] lshrdi3.c +- [x] moddi3.c +- [x] modsi3.c +- [ ] muldf3.c +- [x] muldi3.c +- [x] mulodi4.c +- [x] mulosi4.c +- [ ] mulsf3.c +- [x] powidf2.c +- [x] powisf2.c +- [ ] subdf3.c +- [ ] subsf3.c +- [ ] truncdfhf2.c +- [ ] truncdfsf2.c +- [ ] truncsfhf2.c +- [x] udivdi3.c +- [x] udivmoddi4.c +- [x] udivmodsi4.c +- [x] udivsi3.c +- [x] umoddi3.c +- [x] umodsi3.c +- [x] x86_64/chkstk.S +- [x] x86_64/chkstk2.S + +These builtins are needed to support 128-bit integers, which are in the process of being added to Rust. + +- [x] ashlti3.c +- [x] ashrti3.c +- [x] divti3.c +- [x] fixdfti.c +- [x] fixsfti.c +- [x] fixunsdfti.c +- [x] fixunssfti.c +- [x] floattidf.c +- [x] floattisf.c +- [x] floatuntidf.c +- [x] floatuntisf.c +- [x] lshrti3.c +- [x] modti3.c +- [x] muloti4.c +- [x] multi3.c +- [x] udivmodti4.c +- [x] udivti3.c +- [x] umodti3.c + +## Unimplemented functions + +These builtins involve floating-point types ("`f128`", "`f80`" and complex numbers) that are not supported by Rust. + +- ~~addtf3.c~~ +- ~~comparetf2.c~~ +- ~~divdc3.c~~ +- ~~divsc3.c~~ +- ~~divtc3.c~~ +- ~~divtf3.c~~ +- ~~divxc3.c~~ +- ~~extenddftf2.c~~ +- ~~extendsftf2.c~~ +- ~~fixtfdi.c~~ +- ~~fixtfsi.c~~ +- ~~fixtfti.c~~ +- ~~fixunstfdi.c~~ +- ~~fixunstfsi.c~~ +- ~~fixunstfti.c~~ +- ~~fixunsxfdi.c~~ +- ~~fixunsxfsi.c~~ +- ~~fixunsxfti.c~~ +- ~~fixxfdi.c~~ +- ~~fixxfti.c~~ +- ~~floatditf.c~~ +- ~~floatdixf.c~~ +- ~~floatsitf.c~~ +- ~~floattixf.c~~ +- ~~floatunditf.c~~ +- ~~floatundixf.c~~ +- ~~floatunsitf.c~~ +- ~~floatuntixf.c~~ +- ~~i386/floatdixf.S~~ +- ~~i386/floatundixf.S~~ +- ~~muldc3.c~~ +- ~~mulsc3.c~~ +- ~~multc3.c~~ +- ~~multf3.c~~ +- ~~mulxc3.c~~ +- ~~powitf2.c~~ +- ~~powixf2.c~~ +- ~~ppc/divtc3.c~~ +- ~~ppc/fixtfdi.c~~ +- ~~ppc/fixunstfdi.c~~ +- ~~ppc/floatditf.c~~ +- ~~ppc/floatunditf.c~~ +- ~~ppc/gcc_qadd.c~~ +- ~~ppc/gcc_qdiv.c~~ +- ~~ppc/gcc_qmul.c~~ +- ~~ppc/gcc_qsub.c~~ +- ~~ppc/multc3.c~~ +- ~~subtf3.c~~ +- ~~trunctfdf2.c~~ +- ~~trunctfsf2.c~~ +- ~~x86_64/floatdixf.c~~ +- ~~x86_64/floatundixf.S~~ + +These builtins are never called by LLVM. + +- ~~absvdi2.c~~ +- ~~absvsi2.c~~ +- ~~absvti2.c~~ +- ~~addvdi3.c~~ +- ~~addvsi3.c~~ +- ~~addvti3.c~~ +- ~~arm/aeabi_cdcmp.S~~ +- ~~arm/aeabi_cdcmpeq_check_nan.c~~ +- ~~arm/aeabi_cfcmp.S~~ +- ~~arm/aeabi_cfcmpeq_check_nan.c~~ +- ~~arm/aeabi_div0.c~~ +- ~~arm/aeabi_drsub.c~~ +- ~~arm/aeabi_frsub.c~~ +- ~~arm/aeabi_memcmp.S~~ +- ~~arm/bswapdi2.S~~ +- ~~arm/bswapsi2.S~~ +- ~~arm/clzdi2.S~~ +- ~~arm/clzsi2.S~~ +- ~~arm/comparesf2.S~~ +- ~~arm/restore_vfp_d8_d15_regs.S~~ +- ~~arm/save_vfp_d8_d15_regs.S~~ +- ~~arm/switch16.S~~ +- ~~arm/switch32.S~~ +- ~~arm/switch8.S~~ +- ~~arm/switchu8.S~~ +- ~~clzdi2.c~~ +- ~~clzsi2.c~~ +- ~~clzti2.c~~ +- ~~cmpdi2.c~~ +- ~~cmpti2.c~~ +- ~~comparedf2.c~~ +- ~~comparesf2.c~~ +- ~~ctzdi2.c~~ +- ~~ctzsi2.c~~ +- ~~ctzti2.c~~ +- ~~ffsdi2.c~~ - this is [called by gcc][jemalloc-fail] though! +- ~~ffsti2.c~~ +- ~~mulvdi3.c~~ +- ~~mulvsi3.c~~ +- ~~mulvti3.c~~ +- ~~negdf2.c~~ +- ~~negdi2.c~~ +- ~~negsf2.c~~ +- ~~negti2.c~~ +- ~~negvdi2.c~~ +- ~~negvsi2.c~~ +- ~~negvti2.c~~ +- ~~paritydi2.c~~ +- ~~paritysi2.c~~ +- ~~parityti2.c~~ +- ~~popcountdi2.c~~ +- ~~popcountsi2.c~~ +- ~~popcountti2.c~~ +- ~~ppc/restFP.S~~ +- ~~ppc/saveFP.S~~ +- ~~subvdi3.c~~ +- ~~subvsi3.c~~ +- ~~subvti3.c~~ +- ~~ucmpdi2.c~~ +- ~~ucmpti2.c~~ +- ~~udivmodti4.c~~ + +[jemalloc-fail]: https://travis-ci.org/rust-lang/rust/jobs/249772758 + +Rust only exposes atomic types on platforms that support them, and therefore does not need to fall back to software implementations. + +- ~~arm/sync_fetch_and_add_4.S~~ +- ~~arm/sync_fetch_and_add_8.S~~ +- ~~arm/sync_fetch_and_and_4.S~~ +- ~~arm/sync_fetch_and_and_8.S~~ +- ~~arm/sync_fetch_and_max_4.S~~ +- ~~arm/sync_fetch_and_max_8.S~~ +- ~~arm/sync_fetch_and_min_4.S~~ +- ~~arm/sync_fetch_and_min_8.S~~ +- ~~arm/sync_fetch_and_nand_4.S~~ +- ~~arm/sync_fetch_and_nand_8.S~~ +- ~~arm/sync_fetch_and_or_4.S~~ +- ~~arm/sync_fetch_and_or_8.S~~ +- ~~arm/sync_fetch_and_sub_4.S~~ +- ~~arm/sync_fetch_and_sub_8.S~~ +- ~~arm/sync_fetch_and_umax_4.S~~ +- ~~arm/sync_fetch_and_umax_8.S~~ +- ~~arm/sync_fetch_and_umin_4.S~~ +- ~~arm/sync_fetch_and_umin_8.S~~ +- ~~arm/sync_fetch_and_xor_4.S~~ +- ~~arm/sync_fetch_and_xor_8.S~~ +- ~~arm/sync_synchronize.S~~ +- ~~atomic.c~~ +- ~~atomic_flag_clear.c~~ +- ~~atomic_flag_clear_explicit.c~~ +- ~~atomic_flag_test_and_set.c~~ +- ~~atomic_flag_test_and_set_explicit.c~~ +- ~~atomic_signal_fence.c~~ +- ~~atomic_thread_fence.c~~ + +Miscellaneous functionality that is not used by Rust. + +- ~~apple_versioning.c~~ +- ~~clear_cache.c~~ +- ~~emutls.c~~ +- ~~enable_execute_stack.c~~ +- ~~eprintf.c~~ +- ~~gcc_personality_v0.c~~ +- ~~trampoline_setup.c~~ + +Floating-point implementations of builtins that are only called from soft-float code. It would be better to simply use the generic soft-float versions in this case. + +- ~~i386/floatdidf.S~~ +- ~~i386/floatdisf.S~~ +- ~~i386/floatundidf.S~~ +- ~~i386/floatundisf.S~~ +- ~~x86_64/floatundidf.S~~ +- ~~x86_64/floatundisf.S~~ +- ~~x86_64/floatdidf.c~~ +- ~~x86_64/floatdisf.c~~ + +## License + +The compiler-builtins crate is dual licensed under both the University of +Illinois "BSD-Like" license and the MIT license. As a user of this code you may +choose to use it under either license. As a contributor, you agree to allow +your code to be used under both. + +Full text of the relevant licenses is in LICENSE.TXT. diff --git a/src/libcompiler_builtins/appveyor.yml b/src/libcompiler_builtins/appveyor.yml new file mode 100644 index 0000000000..e51ddab740 --- /dev/null +++ b/src/libcompiler_builtins/appveyor.yml @@ -0,0 +1,45 @@ +environment: + # It's... a little unclear why the memcpy symbols clash on linux but not on + # other platforms. Would be great to not differ on this though! + INTRINSICS_FAILS_WITH_MEM_FEATURE: 1 + + matrix: + - TARGET: i686-pc-windows-msvc + - TARGET: x86_64-pc-windows-msvc + + # Ensure MinGW works, but we need to download the 32-bit MinGW compiler from a + # custom location. + # + # Note that the MinGW builds have tons of references to + # `rust_eh_unwind_resume` in the debug LTO builds that aren't optimized out, + # so we skip that test for now. Would be great to not skip it! + - TARGET: i686-pc-windows-gnu + MINGW_URL: https://s3.amazonaws.com/rust-lang-ci + MINGW_ARCHIVE: i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z + MINGW_DIR: mingw32 + DEBUG_LTO_BUILD_DOESNT_WORK: 1 + - TARGET: x86_64-pc-windows-gnu + DEBUG_LTO_BUILD_DOESNT_WORK: 1 + +install: + - git submodule update --init + - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe + - rustup-init.exe --default-host x86_64-pc-windows-msvc --default-toolchain nightly -y + - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin + - if NOT "%TARGET%" == "x86_64-pc-windows-msvc" rustup target add %TARGET% + + # Use the system msys + - set PATH=C:\msys64\mingw64\bin;C:\msys64\usr\bin;%PATH% + + # download a custom compiler otherwise + - if defined MINGW_URL appveyor DownloadFile %MINGW_URL%/%MINGW_ARCHIVE% + - if defined MINGW_URL 7z x -y %MINGW_ARCHIVE% > nul + - if defined MINGW_URL set PATH=C:\Python27;%CD%\%MINGW_DIR%\bin;C:\msys64\usr\bin;%PATH% + + - rustc -Vv + - cargo -V + +build: false + +test_script: + - sh ci/run.sh %TARGET% diff --git a/src/libcompiler_builtins/build.rs b/src/libcompiler_builtins/build.rs index 8fe79057bd..25cc5204d2 100644 --- a/src/libcompiler_builtins/build.rs +++ b/src/libcompiler_builtins/build.rs @@ -1,423 +1,4375 @@ -// 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. - -//! Compiles the `compiler-rt` library, or at least the builtins part of it. -//! -//! Note that while compiler-rt has a build system associated with it, we -//! specifically don't use it here. The compiler-rt build system, written in -//! CMake, is actually *very* difficult to work with in terms of getting it to -//! compile on all the relevant platforms we want it to compile on. In the end -//! it became so much pain to work with local patches, work around the oddities -//! of the build system, etc, that we're just building everything by hand now. -//! -//! In general compiler-rt is just a bunch of intrinsics that are in practice -//! *very* stable. We just need to make sure that all the relevant functions and -//! such are compiled somewhere and placed in an object file somewhere. -//! Eventually, these should all be written in Rust! -//! -//! So below you'll find a listing of every single file in the compiler-rt repo -//! that we're compiling. We just reach in and compile with the `gcc` crate -//! which should have all the relevant flags and such already configured. -//! -//! The risk here is that if we update compiler-rt we may need to compile some -//! new intrinsics, but to be honest we surely don't use all of the intrinsics -//! listed below today so the likelihood of us actually needing a new intrinsic -//! is quite low. The failure case is also just that someone reports a link -//! error (if any) and then we just add it to the list. Overall, that cost is -//! far far less than working with compiler-rt's build system over time. - -extern crate build_helper; -extern crate gcc; - -use std::collections::BTreeMap; +#![feature(i128_type)] + use std::env; -use std::path::Path; -use build_helper::native_lib_boilerplate; - -struct Sources { - // SYMBOL -> PATH TO SOURCE - map: BTreeMap<&'static str, &'static str>, -} - -impl Sources { - fn new() -> Sources { - Sources { map: BTreeMap::new() } - } - - fn extend(&mut self, sources: &[&'static str]) { - // NOTE Some intrinsics have both a generic implementation (e.g. - // `floatdidf.c`) and an arch optimized implementation - // (`x86_64/floatdidf.c`). In those cases, we keep the arch optimized - // implementation and discard the generic implementation. If we don't - // and keep both implementations, the linker will yell at us about - // duplicate symbols! - for &src in sources { - let symbol = Path::new(src).file_stem().unwrap().to_str().unwrap(); - if src.contains("/") { - // Arch-optimized implementation (preferred) - self.map.insert(symbol, src); - } else { - // Generic implementation - if !self.map.contains_key(symbol) { - self.map.insert(symbol, src); - } + +fn main() { + println!("cargo:rerun-if-changed=build.rs"); + + let target = env::var("TARGET").unwrap(); + + // Emscripten's runtime includes all the builtins + if target.contains("emscripten") { + return; + } + + // NOTE we are going to assume that llvm-target, what determines our codegen option, matches the + // target triple. This is usually correct for our built-in targets but can break in presence of + // custom targets, which can have arbitrary names. + let llvm_target = target.split('-').collect::>(); + + // Build test files + #[cfg(feature = "gen-tests")] + tests::generate(); + + // Build missing intrinsics from compiler-rt C source code. If we're + // mangling names though we assume that we're also in test mode so we don't + // build anything and we rely on the upstream implementation of compiler-rt + // functions + if !cfg!(feature = "mangled-names") { + #[cfg(feature = "c")] + c::compile(&llvm_target); + } + + // To compile intrinsics.rs for thumb targets, where there is no libc + if llvm_target[0].starts_with("thumb") { + println!("cargo:rustc-cfg=thumb") + } + + // compiler-rt `cfg`s away some intrinsics for thumbv6m because that target doesn't have full + // THUMBv2 support. We have to cfg our code accordingly. + if llvm_target[0] == "thumbv6m" { + println!("cargo:rustc-cfg=thumbv6m") + } +} + +#[cfg(feature = "gen-tests")] +mod tests { + extern crate cast; + extern crate rand; + + use std::collections::HashSet; + use std::fmt::Write; + use std::fs::File; + use std::hash::Hash; + use std::path::PathBuf; + use std::{env, mem}; + + use self::cast::{f32, f64, u32, u64, u128, i32, i64, i128}; + use self::rand::Rng; + + const NTESTS: usize = 10_000; + + macro_rules! test { + ($($intrinsic:ident,)+) => { + $( + mk_file::<$intrinsic>(); + )+ + } + } + + pub fn generate() { + // TODO move to main + test! { + // float/add.rs + Adddf3, + Addsf3, + + // float/conv.rs + Fixdfdi, + Fixdfsi, + Fixsfdi, + Fixsfsi, + Fixsfti, + Fixdfti, + Fixunsdfdi, + Fixunsdfsi, + Fixunssfdi, + Fixunssfsi, + Fixunssfti, + Fixunsdfti, + Floatdidf, + Floatsidf, + Floatsisf, + Floattisf, + Floattidf, + Floatundidf, + Floatunsidf, + Floatunsisf, + Floatuntisf, + Floatuntidf, + + // float/pow.rs + Powidf2, + Powisf2, + + // float/sub.rs + Subdf3, + Subsf3, + + // int/mul.rs + Muldi3, + Mulodi4, + Mulosi4, + Muloti4, + Multi3, + + // int/sdiv.rs + Divdi3, + Divmoddi4, + Divmodsi4, + Divsi3, + Divti3, + Moddi3, + Modsi3, + Modti3, + + // int/shift.rs + Ashldi3, + Ashlti3, + Ashrdi3, + Ashrti3, + Lshrdi3, + Lshrti3, + + // int/udiv.rs + Udivdi3, + Udivmoddi4, + Udivmodsi4, + Udivmodti4, + Udivsi3, + Udivti3, + Umoddi3, + Umodsi3, + Umodti3, + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Adddf3 { + a: u64, // f64 + b: u64, // f64 + c: u64, // f64 + } + + impl TestCase for Adddf3 { + fn name() -> &'static str { + "adddf3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_f64(rng); + let b = gen_f64(rng); + let c = a + b; + // TODO accept NaNs. We don't do that right now because we can't check + // for NaN-ness on the thumb targets (due to missing intrinsics) + if a.is_nan() || b.is_nan() || c.is_nan() { + return None; + } + + Some( + Adddf3 { + a: to_u64(a), + b: to_u64(b), + c: to_u64(c), + }, + ) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::add::__adddf3; + +fn mk_f64(x: u64) -> f64 { + unsafe { mem::transmute(x) } +} + +fn to_u64(x: f64) -> u64 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u64, u64), u64)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn adddf3() { + for &((a, b), c) in TEST_CASES { + let c_ = __adddf3(mk_f64(a), mk_f64(b)); + assert_eq!(((a, b), c), ((a, b), to_u64(c_))); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Addsf3 { + a: u32, // f32 + b: u32, // f32 + c: u32, // f32 + } + + impl TestCase for Addsf3 { + fn name() -> &'static str { + "addsf3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_f32(rng); + let b = gen_f32(rng); + let c = a + b; + // TODO accept NaNs. We don't do that right now because we can't check + // for NaN-ness on the thumb targets (due to missing intrinsics) + if a.is_nan() || b.is_nan() || c.is_nan() { + return None; + } + + Some( + Addsf3 { + a: to_u32(a), + b: to_u32(b), + c: to_u32(c), + }, + ) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::add::__addsf3; + +fn mk_f32(x: u32) -> f32 { + unsafe { mem::transmute(x) } +} + +fn to_u32(x: f32) -> u32 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u32, u32), u32)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn addsf3() { + for &((a, b), c) in TEST_CASES { + let c_ = __addsf3(mk_f32(a), mk_f32(b)); + assert_eq!(((a, b), c), ((a, b), to_u32(c_))); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Ashldi3 { + a: u64, + b: u32, + c: u64, + } + + impl TestCase for Ashldi3 { + fn name() -> &'static str { + "ashldi3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u64(rng); + let b = (rng.gen::() % 64) as u32; + let c = a << b; + + Some(Ashldi3 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::shift::__ashldi3; + +static TEST_CASES: &[((u64, u32), u64)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn ashldi3() { + for &((a, b), c) in TEST_CASES { + let c_ = __ashldi3(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Ashlti3 { + a: u128, + b: u32, + c: u128, + } + + impl TestCase for Ashlti3 { + fn name() -> &'static str { + "ashlti3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u128(rng); + let b = (rng.gen::() % 128) as u32; + let c = a << b; + + Some(Ashlti3 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::shift::__ashlti3; + +static TEST_CASES: &[((u128, u32), u128)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn ashlti3() { + for &((a, b), c) in TEST_CASES { + let c_ = __ashlti3(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Ashrdi3 { + a: i64, + b: u32, + c: i64, + } + + impl TestCase for Ashrdi3 { + fn name() -> &'static str { + "ashrdi3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_i64(rng); + let b = (rng.gen::() % 64) as u32; + let c = a >> b; + + Some(Ashrdi3 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::shift::__ashrdi3; + +static TEST_CASES: &[((i64, u32), i64)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn ashrdi3() { + for &((a, b), c) in TEST_CASES { + let c_ = __ashrdi3(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Ashrti3 { + a: i128, + b: u32, + c: i128, + } + + impl TestCase for Ashrti3 { + fn name() -> &'static str { + "ashrti3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_i128(rng); + let b = (rng.gen::() % 128) as u32; + let c = a >> b; + + Some(Ashrti3 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::shift::__ashrti3; + +static TEST_CASES: &[((i128, u32), i128)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn ashrti3() { + for &((a, b), c) in TEST_CASES { + let c_ = __ashrti3(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Divmoddi4 { + a: i64, + b: i64, + c: i64, + rem: i64, + } + + impl TestCase for Divmoddi4 { + fn name() -> &'static str { + "divmoddi4" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_i64(rng); + let b = gen_i64(rng); + if b == 0 { + return None; + } + let c = a / b; + let rem = a % b; + + Some(Divmoddi4 { a, b, c, rem }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), ({c}, {rem})),", + a = self.a, + b = self.b, + c = self.c, + rem = self.rem + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::sdiv::__divmoddi4; + +static TEST_CASES: &[((i64, i64), (i64, i64))] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn divmoddi4() { + for &((a, b), (c, rem)) in TEST_CASES { + let mut rem_ = 0; + let c_ = __divmoddi4(a, b, &mut rem_); + assert_eq!(((a, b), (c, rem)), ((a, b), (c_, rem_))); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Divdi3 { + a: i64, + b: i64, + c: i64, + } + + impl TestCase for Divdi3 { + fn name() -> &'static str { + "divdi3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_i64(rng); + let b = gen_i64(rng); + if b == 0 { + return None; + } + let c = a / b; + + Some(Divdi3 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::sdiv::__divdi3; + +static TEST_CASES: &[((i64, i64), i64)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn divdi3() { + for &((a, b), c) in TEST_CASES { + let c_ = __divdi3(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Divmodsi4 { + a: i32, + b: i32, + c: i32, + rem: i32, + } + + impl TestCase for Divmodsi4 { + fn name() -> &'static str { + "divmodsi4" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_i32(rng); + let b = gen_i32(rng); + if b == 0 { + return None; + } + let c = a / b; + let rem = a % b; + + Some(Divmodsi4 { a, b, c, rem }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), ({c}, {rem})),", + a = self.a, + b = self.b, + c = self.c, + rem = self.rem + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::sdiv::__divmodsi4; + +static TEST_CASES: &[((i32, i32), (i32, i32))] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn divmodsi4() { + for &((a, b), (c, rem)) in TEST_CASES { + let mut rem_ = 0; + let c_ = __divmodsi4(a, b, &mut rem_); + assert_eq!(((a, b), (c, rem)), ((a, b), (c_, rem_))); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Divsi3 { + a: i32, + b: i32, + c: i32, + } + + impl TestCase for Divsi3 { + fn name() -> &'static str { + "divsi3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_i32(rng); + let b = gen_i32(rng); + if b == 0 { + return None; + } + let c = a / b; + + Some(Divsi3 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::sdiv::__divsi3; + +static TEST_CASES: &[((i32, i32), i32)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn divsi3() { + for &((a, b), c) in TEST_CASES { + let c_ = __divsi3(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Divti3 { + a: i128, + b: i128, + c: i128, + } + + impl TestCase for Divti3 { + fn name() -> &'static str { + "divti3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_i128(rng); + let b = gen_i128(rng); + if b == 0 { + return None; + } + let c = a / b; + + Some(Divti3 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::sdiv::__divti3; + +static TEST_CASES: &[((i128, i128), i128)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn divti3() { + for &((a, b), c) in TEST_CASES { + let c_ = __divti3(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Fixdfdi { + a: u64, // f64 + b: i64, + } + + impl TestCase for Fixdfdi { + fn name() -> &'static str { + "fixdfdi" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_f64(rng); + i64(a).ok().map(|b| Fixdfdi { a: to_u64(a), b }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::conv::__fixdfdi; + +fn mk_f64(x: u64) -> f64 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u64,), i64)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn fixdfdi() { + for &((a,), b) in TEST_CASES { + let b_ = __fixdfdi(mk_f64(a)); + assert_eq!(((a,), b), ((a,), b_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Fixdfsi { + a: u64, // f64 + b: i32, + } + + impl TestCase for Fixdfsi { + fn name() -> &'static str { + "fixdfsi" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_f64(rng); + i32(a).ok().map(|b| Fixdfsi { a: to_u64(a), b }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::conv::__fixdfsi; + +fn mk_f64(x: u64) -> f64 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u64,), i32)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn fixdfdi() { + for &((a,), b) in TEST_CASES { + let b_ = __fixdfsi(mk_f64(a)); + assert_eq!(((a,), b), ((a,), b_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Fixsfdi { + a: u32, // f32 + b: i64, + } + + impl TestCase for Fixsfdi { + fn name() -> &'static str { + "fixsfdi" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_f32(rng); + i64(a).ok().map(|b| Fixsfdi { a: to_u32(a), b }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::conv::__fixsfdi; + +fn mk_f32(x: u32) -> f32 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u32,), i64)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn fixsfdi() { + for &((a,), b) in TEST_CASES { + let b_ = __fixsfdi(mk_f32(a)); + assert_eq!(((a,), b), ((a,), b_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Fixsfsi { + a: u32, // f32 + b: i32, + } + + impl TestCase for Fixsfsi { + fn name() -> &'static str { + "fixsfsi" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_f32(rng); + i32(a).ok().map(|b| Fixsfsi { a: to_u32(a), b }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::conv::__fixsfsi; + +fn mk_f32(x: u32) -> f32 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u32,), i32)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn fixsfsi() { + for &((a,), b) in TEST_CASES { + let b_ = __fixsfsi(mk_f32(a)); + assert_eq!(((a,), b), ((a,), b_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Fixsfti { + a: u32, // f32 + b: i128, + } + + impl TestCase for Fixsfti { + fn name() -> &'static str { + "fixsfti" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_f32(rng); + i128(a).ok().map(|b| Fixsfti { a: to_u32(a), b }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::conv::__fixsfti; + +fn mk_f32(x: u32) -> f32 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u32,), i128)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn fixsfti() { + for &((a,), b) in TEST_CASES { + let b_ = __fixsfti(mk_f32(a)); + assert_eq!(((a,), b), ((a,), b_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Fixdfti { + a: u64, // f64 + b: i128, + } + + impl TestCase for Fixdfti { + fn name() -> &'static str { + "fixdfti" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_f64(rng); + i128(a).ok().map(|b| Fixdfti { a: to_u64(a), b }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::conv::__fixdfti; + +fn mk_f64(x: u64) -> f64 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u64,), i128)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn fixdfti() { + for &((a,), b) in TEST_CASES { + let b_ = __fixdfti(mk_f64(a)); + assert_eq!(((a,), b), ((a,), b_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Fixunsdfdi { + a: u64, // f64 + b: u64, + } + + impl TestCase for Fixunsdfdi { + fn name() -> &'static str { + "fixunsdfdi" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_f64(rng); + u64(a).ok().map(|b| Fixunsdfdi { a: to_u64(a), b }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::conv::__fixunsdfdi; + +fn mk_f64(x: u64) -> f64 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u64,), u64)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn fixunsdfdi() { + for &((a,), b) in TEST_CASES { + let b_ = __fixunsdfdi(mk_f64(a)); + assert_eq!(((a,), b), ((a,), b_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Fixunsdfsi { + a: u64, // f64 + b: u32, + } + + impl TestCase for Fixunsdfsi { + fn name() -> &'static str { + "fixunsdfsi" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_f64(rng); + u32(a).ok().map(|b| Fixunsdfsi { a: to_u64(a), b }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::conv::__fixunsdfsi; + +fn mk_f64(x: u64) -> f64 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u64,), u32)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn fixunsdfdi() { + for &((a,), b) in TEST_CASES { + let b_ = __fixunsdfsi(mk_f64(a)); + assert_eq!(((a,), b), ((a,), b_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Fixunssfdi { + a: u32, // f32 + b: u64, + } + + impl TestCase for Fixunssfdi { + fn name() -> &'static str { + "fixunssfdi" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_f32(rng); + u64(a).ok().map(|b| Fixunssfdi { a: to_u32(a), b }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::conv::__fixunssfdi; + +fn mk_f32(x: u32) -> f32 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u32,), u64)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn fixunssfdi() { + for &((a,), b) in TEST_CASES { + let b_ = __fixunssfdi(mk_f32(a)); + assert_eq!(((a,), b), ((a,), b_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Fixunssfsi { + a: u32, // f32 + b: u32, + } + + impl TestCase for Fixunssfsi { + fn name() -> &'static str { + "fixunssfsi" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_f32(rng); + u32(a).ok().map(|b| Fixunssfsi { a: to_u32(a), b }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::conv::__fixunssfsi; + +fn mk_f32(x: u32) -> f32 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u32,), u32)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn fixunssfsi() { + for &((a,), b) in TEST_CASES { + let b_ = __fixunssfsi(mk_f32(a)); + assert_eq!(((a,), b), ((a,), b_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Fixunssfti { + a: u32, // f32 + b: u128, + } + + impl TestCase for Fixunssfti { + fn name() -> &'static str { + "fixunssfti" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_f32(rng); + u128(a).ok().map(|b| Fixunssfti { a: to_u32(a), b }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::conv::__fixunssfti; + +fn mk_f32(x: u32) -> f32 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u32,), u128)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn fixunssfti() { + for &((a,), b) in TEST_CASES { + let b_ = __fixunssfti(mk_f32(a)); + assert_eq!(((a,), b), ((a,), b_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Fixunsdfti { + a: u64, // f64 + b: u128, + } + + impl TestCase for Fixunsdfti { + fn name() -> &'static str { + "fixunsdfti" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_f64(rng); + u128(a).ok().map(|b| Fixunsdfti { a: to_u64(a), b }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::conv::__fixunsdfti; + +fn mk_f64(x: u64) -> f64 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u64,), u128)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn fixunsdfti() { + for &((a,), b) in TEST_CASES { + let b_ = __fixunsdfti(mk_f64(a)); + assert_eq!(((a,), b), ((a,), b_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Floatdidf { + a: i64, + b: u64, // f64 + } + + impl TestCase for Floatdidf { + fn name() -> &'static str { + "floatdidf" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_i64(rng); + Some( + Floatdidf { + a, + b: to_u64(f64(a)), + }, + ) + } + + fn to_string(&self, buffer: &mut String) { + writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::conv::__floatdidf; + +fn to_u64(x: f64) -> u64 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((i64,), u64)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn floatdidf() { + for &((a,), b) in TEST_CASES { + let b_ = __floatdidf(a); + assert_eq!(((a,), b), ((a,), to_u64(b_))); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Floatsidf { + a: i32, + b: u64, // f64 + } + + impl TestCase for Floatsidf { + fn name() -> &'static str { + "floatsidf" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_i32(rng); + Some( + Floatsidf { + a, + b: to_u64(f64(a)), + }, + ) + } + + fn to_string(&self, buffer: &mut String) { + writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::conv::__floatsidf; + +fn to_u64(x: f64) -> u64 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((i32,), u64)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn floatsidf() { + for &((a,), b) in TEST_CASES { + let b_ = __floatsidf(a); + assert_eq!(((a,), b), ((a,), to_u64(b_))); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Floatsisf { + a: i32, + b: u32, // f32 + } + + impl TestCase for Floatsisf { + fn name() -> &'static str { + "floatsisf" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_i32(rng); + Some( + Floatsisf { + a, + b: to_u32(f32(a)), + }, + ) + } + + fn to_string(&self, buffer: &mut String) { + writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::conv::__floatsisf; + +fn to_u32(x: f32) -> u32 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((i32,), u32)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn floatsisf() { + for &((a,), b) in TEST_CASES { + let b_ = __floatsisf(a); + assert_eq!(((a,), b), ((a,), to_u32(b_))); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Floattisf { + a: i128, + b: u32, // f32 + } + + impl TestCase for Floattisf { + fn name() -> &'static str { + "floattisf" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_i128(rng); + Some( + Floattisf { + a, + b: to_u32(f32(a)), + }, + ) + } + + fn to_string(&self, buffer: &mut String) { + writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::conv::__floattisf; + +fn to_u32(x: f32) -> u32 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((i128,), u32)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn floattisf() { + for &((a,), b) in TEST_CASES { + let b_ = __floattisf(a); + assert_eq!(((a,), b), ((a,), to_u32(b_))); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Floattidf { + a: i128, + b: u64, // f64 + } + + impl TestCase for Floattidf { + fn name() -> &'static str { + "floattidf" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_i128(rng); + Some( + Floattidf { + a, + b: to_u64(f64(a)), + }, + ) + } + + fn to_string(&self, buffer: &mut String) { + writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::conv::__floattidf; + +fn to_u64(x: f64) -> u64 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((i128,), u64)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn floattidf() { + for &((a,), b) in TEST_CASES { + let b_ = __floattidf(a); + let g_b = to_u64(b_); + let diff = if g_b > b { g_b - b } else { b - g_b }; + assert_eq!(((a,), b, g_b, true), ((a,), b, g_b, diff <= 1)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Floatundidf { + a: u64, + b: u64, // f64 + } + + impl TestCase for Floatundidf { + fn name() -> &'static str { + "floatundidf" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u64(rng); + Some( + Floatundidf { + a, + b: to_u64(f64(a)), + }, + ) + } + + fn to_string(&self, buffer: &mut String) { + writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::conv::__floatundidf; + +fn to_u64(x: f64) -> u64 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u64,), u64)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn floatundidf() { + for &((a,), b) in TEST_CASES { + let b_ = __floatundidf(a); + assert_eq!(((a,), b), ((a,), to_u64(b_))); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Floatunsidf { + a: u32, + b: u64, // f64 + } + + impl TestCase for Floatunsidf { + fn name() -> &'static str { + "floatunsidf" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u32(rng); + Some( + Floatunsidf { + a, + b: to_u64(f64(a)), + }, + ) + } + + fn to_string(&self, buffer: &mut String) { + writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::conv::__floatunsidf; + +fn to_u64(x: f64) -> u64 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u32,), u64)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn floatunsidf() { + for &((a,), b) in TEST_CASES { + let b_ = __floatunsidf(a); + assert_eq!(((a,), b), ((a,), to_u64(b_))); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Floatunsisf { + a: u32, + b: u32, // f32 + } + + impl TestCase for Floatunsisf { + fn name() -> &'static str { + "floatunsisf" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u32(rng); + Some( + Floatunsisf { + a, + b: to_u32(f32(a)), + }, + ) + } + + fn to_string(&self, buffer: &mut String) { + writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::conv::__floatunsisf; + +fn to_u32(x: f32) -> u32 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u32,), u32)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn floatunsisf() { + for &((a,), b) in TEST_CASES { + let b_ = __floatunsisf(a); + assert_eq!(((a,), b), ((a,), to_u32(b_))); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Floatuntisf { + a: u128, + b: u32, // f32 + } + + impl TestCase for Floatuntisf { + fn name() -> &'static str { + "floatuntisf" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u128(rng); + let f_a = f32(a); + f_a.ok().map(|f| { + Floatuntisf { + a, + b: to_u32(f), + } + }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::conv::__floatuntisf; + +fn to_u32(x: f32) -> u32 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u128,), u32)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn floatuntisf() { + for &((a,), b) in TEST_CASES { + let b_ = __floatuntisf(a); + assert_eq!(((a,), b), ((a,), to_u32(b_))); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Floatuntidf { + a: u128, + b: u64, // f64 + } + + impl TestCase for Floatuntidf { + fn name() -> &'static str { + "floatuntidf" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u128(rng); + Some( + Floatuntidf { + a, + b: to_u64(f64(a)), + }, + ) + } + + fn to_string(&self, buffer: &mut String) { + writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::conv::__floatuntidf; + +fn to_u64(x: f64) -> u64 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u128,), u64)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn floatuntidf() { + for &((a,), b) in TEST_CASES { + let b_ = __floatuntidf(a); + let g_b = to_u64(b_); + let diff = if g_b > b { g_b - b } else { b - g_b }; + assert_eq!(((a,), b, g_b, true), ((a,), b, g_b, diff <= 1)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Moddi3 { + a: i64, + b: i64, + c: i64, + } + + impl TestCase for Moddi3 { + fn name() -> &'static str { + "moddi3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_i64(rng); + let b = gen_i64(rng); + if b == 0 { + return None; + } + let c = a % b; + + Some(Moddi3 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::sdiv::__moddi3; + +static TEST_CASES: &[((i64, i64), i64)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn moddi3() { + for &((a, b), c) in TEST_CASES { + let c_ = __moddi3(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Modsi3 { + a: i32, + b: i32, + c: i32, + } + + impl TestCase for Modsi3 { + fn name() -> &'static str { + "modsi3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_i32(rng); + let b = gen_i32(rng); + if b == 0 { + return None; + } + let c = a % b; + + Some(Modsi3 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::sdiv::__modsi3; + +static TEST_CASES: &[((i32, i32), i32)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn modsi3() { + for &((a, b), c) in TEST_CASES { + let c_ = __modsi3(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Modti3 { + a: i128, + b: i128, + c: i128, + } + + impl TestCase for Modti3 { + fn name() -> &'static str { + "modti3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_i128(rng); + let b = gen_i128(rng); + if b == 0 { + return None; + } + let c = a % b; + + Some(Modti3 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::sdiv::__modti3; + +static TEST_CASES: &[((i128, i128), i128)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn modti3() { + for &((a, b), c) in TEST_CASES { + let c_ = __modti3(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + struct Muldi3 { + a: u64, + b: u64, + c: u64, + } + + impl TestCase for Muldi3 { + fn name() -> &'static str { + "muldi3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u64(rng); + let b = gen_u64(rng); + let c = a.wrapping_mul(b); + + Some(Muldi3 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::mul::__muldi3; + +static TEST_CASES: &[((u64, u64), u64)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn muldi3() { + for &((a, b), c) in TEST_CASES { + let c_ = __muldi3(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Mulodi4 { + a: i64, + b: i64, + c: i64, + overflow: u32, + } + + impl TestCase for Mulodi4 { + fn name() -> &'static str { + "mulodi4" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + { + let a = gen_i64(rng); + let b = gen_i64(rng); + let c = a.wrapping_mul(b); + let overflow = if a.checked_mul(b).is_some() { 0 } else { 1 }; + + Some(Mulodi4 { a, b, c, overflow }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), ({c}, {overflow})),", + a = self.a, + b = self.b, + c = self.c, + overflow = self.overflow + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::mul::__mulodi4; + +static TEST_CASES: &[((i64, i64), (i64, i32))] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn mulodi4() { + let mut overflow_ = 2; + for &((a, b), (c, overflow)) in TEST_CASES { + let c_ = __mulodi4(a, b, &mut overflow_); + assert_eq!(((a, b), (c, overflow)), ((a, b), (c_, overflow_))); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Mulosi4 { + a: i32, + b: i32, + c: i32, + overflow: u32, + } + + impl TestCase for Mulosi4 { + fn name() -> &'static str { + "mulosi4" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + { + let a = gen_i32(rng); + let b = gen_i32(rng); + let c = a.wrapping_mul(b); + let overflow = if a.checked_mul(b).is_some() { 0 } else { 1 }; + + Some(Mulosi4 { a, b, c, overflow }) + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::mul::__mulosi4; + +static TEST_CASES: &[((i32, i32), (i32, i32))] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn mulosi4() { + let mut overflow_ = 2; + for &((a, b), (c, overflow)) in TEST_CASES { + let c_ = __mulosi4(a, b, &mut overflow_); + assert_eq!(((a, b), (c, overflow)), ((a, b), (c_, overflow_))); + } +} +" + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), ({c}, {overflow})),", + a = self.a, + b = self.b, + c = self.c, + overflow = self.overflow + ) + .unwrap(); + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Muloti4 { + a: i128, + b: i128, + c: i128, + overflow: u32, + } + + impl TestCase for Muloti4 { + fn name() -> &'static str { + "muloti4" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + { + let a = gen_i128(rng); + let b = gen_i128(rng); + let c = a.wrapping_mul(b); + let overflow = if a.checked_mul(b).is_some() { 0 } else { 1 }; + + Some(Muloti4 { a, b, c, overflow }) + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::mul::__muloti4; + +static TEST_CASES: &[((i128, i128), (i128, i32))] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn muloti4() { + let mut overflow_ = 2; + for &((a, b), (c, overflow)) in TEST_CASES { + let c_ = __muloti4(a, b, &mut overflow_); + assert_eq!(((a, b), (c, overflow)), ((a, b), (c_, overflow_))); + } +} +" + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), ({c}, {overflow})),", + a = self.a, + b = self.b, + c = self.c, + overflow = self.overflow + ) + .unwrap(); + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Multi3 { + a: i128, + b: i128, + c: i128, + } + + impl TestCase for Multi3 { + fn name() -> &'static str { + "multi3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_i128(rng); + let b = gen_i128(rng); + let c = a.wrapping_mul(b); + + Some(Multi3 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::mul::__multi3; + +static TEST_CASES: &[((i128, i128), i128)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn multi3() { + for &((a, b), c) in TEST_CASES { + let c_ = __multi3(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Powidf2 { + a: u64, // f64 + b: i32, + c: u64, // f64 + } + + impl TestCase for Powidf2 { + fn name() -> &'static str { + "powidf2" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_f64(rng); + let b = gen_i32(rng); + let c = a.powi(b); + // TODO accept NaNs. We don't do that right now because we can't check + // for NaN-ness on the thumb targets + if a.is_nan() || c.is_nan() { + return None; + } + + Some( + Powidf2 { + a: to_u64(a), + b, + c: to_u64(c), + }, + ) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::pow::__powidf2; + +fn mk_f64(x: u64) -> f64 { + unsafe { mem::transmute(x) } +} + +fn to_u64(x: f64) -> u64 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u64, i32), u64)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn powidf2() { + for &((a, b), c) in TEST_CASES { + let c_ = __powidf2(mk_f64(a), b); + assert_eq!(((a, b), c), ((a, b), to_u64(c_))); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Powisf2 { + a: u32, // f32 + b: i32, + c: u32, // f32 + } + + impl TestCase for Powisf2 { + fn name() -> &'static str { + "powisf2" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_f32(rng); + let b = gen_i32(rng); + let c = a.powi(b); + // TODO accept NaNs. We don't do that right now because we can't check + // for NaN-ness on the thumb targets + if a.is_nan() || c.is_nan() { + return None; + } + + Some( + Powisf2 { + a: to_u32(a), + b, + c: to_u32(c), + }, + ) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::pow::__powisf2; + +fn mk_f32(x: u32) -> f32 { + unsafe { mem::transmute(x) } +} + +fn to_u32(x: f32) -> u32 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u32, i32), u32)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn powisf2() { + for &((a, b), c) in TEST_CASES { + let c_ = __powisf2(mk_f32(a), b); + assert_eq!(((a, b), c), ((a, b), to_u32(c_))); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Lshrdi3 { + a: u64, + b: u32, + c: u64, + } + + impl TestCase for Lshrdi3 { + fn name() -> &'static str { + "lshrdi3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u64(rng); + let b = (rng.gen::() % 64) as u32; + let c = a >> b; + + Some(Lshrdi3 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::shift::__lshrdi3; + +static TEST_CASES: &[((u64, u32), u64)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn lshrdi3() { + for &((a, b), c) in TEST_CASES { + let c_ = __lshrdi3(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Lshrti3 { + a: u128, + b: u32, + c: u128, + } + + impl TestCase for Lshrti3 { + fn name() -> &'static str { + "lshrti3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u128(rng); + let b = (rng.gen::() % 128) as u32; + let c = a >> b; + + Some(Lshrti3 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::shift::__lshrti3; + +static TEST_CASES: &[((u128, u32), u128)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn lshrti3() { + for &((a, b), c) in TEST_CASES { + let c_ = __lshrti3(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Subdf3 { + a: u64, // f64 + b: u64, // f64 + c: u64, // f64 + } + + impl TestCase for Subdf3 { + fn name() -> &'static str { + "subdf3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_f64(rng); + let b = gen_f64(rng); + let c = a - b; + // TODO accept NaNs. We don't do that right now because we can't check + // for NaN-ness on the thumb targets (due to missing intrinsics) + if a.is_nan() || b.is_nan() || c.is_nan() { + return None; + } + + Some( + Subdf3 { + a: to_u64(a), + b: to_u64(b), + c: to_u64(c), + }, + ) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::sub::__subdf3; + +fn mk_f64(x: u64) -> f64 { + unsafe { mem::transmute(x) } +} + +fn to_u64(x: f64) -> u64 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u64, u64), u64)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn subdf3() { + for &((a, b), c) in TEST_CASES { + let c_ = __subdf3(mk_f64(a), mk_f64(b)); + assert_eq!(((a, b), c), ((a, b), to_u64(c_))); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Subsf3 { + a: u32, // f32 + b: u32, // f32 + c: u32, // f32 + } + + impl TestCase for Subsf3 { + fn name() -> &'static str { + "subsf3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_f32(rng); + let b = gen_f32(rng); + let c = a - b; + // TODO accept NaNs. We don't do that right now because we can't check + // for NaN-ness on the thumb targets (due to missing intrinsics) + if a.is_nan() || b.is_nan() || c.is_nan() { + return None; + } + + Some( + Subsf3 { + a: to_u32(a), + b: to_u32(b), + c: to_u32(c), + }, + ) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + r#" +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +use core::mem; +#[cfg(not(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test)))] +use std::mem; +use compiler_builtins::float::sub::__subsf3; + +fn mk_f32(x: u32) -> f32 { + unsafe { mem::transmute(x) } +} + +fn to_u32(x: f32) -> u32 { + unsafe { mem::transmute(x) } +} + +static TEST_CASES: &[((u32, u32), u32)] = &[ +"# + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn subsf3() { + for &((a, b), c) in TEST_CASES { + let c_ = __subsf3(mk_f32(a), mk_f32(b)); + assert_eq!(((a, b), c), ((a, b), to_u32(c_))); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Udivdi3 { + a: u64, + b: u64, + c: u64, + } + + impl TestCase for Udivdi3 { + fn name() -> &'static str { + "udivdi3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u64(rng); + let b = gen_u64(rng); + if b == 0 { + return None; + } + let c = a / b; + + Some(Udivdi3 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::udiv::__udivdi3; + +static TEST_CASES: &[((u64, u64), u64)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn udivdi3() { + for &((a, b), c) in TEST_CASES { + let c_ = __udivdi3(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Udivmoddi4 { + a: u64, + b: u64, + c: u64, + rem: u64, + } + + impl TestCase for Udivmoddi4 { + fn name() -> &'static str { + "udivmoddi4" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u64(rng); + let b = gen_u64(rng); + if b == 0 { + return None; } + let c = a / b; + let rem = a % b; + + Some(Udivmoddi4 { a, b, c, rem }) } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), ({c}, {rem})),", + a = self.a, + b = self.b, + c = self.c, + rem = self.rem + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::udiv::__udivmoddi4; + +static TEST_CASES: &[((u64, u64), (u64, u64))] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn udivmoddi4() { + for &((a, b), (c, rem)) in TEST_CASES { + let mut rem_ = 0; + let c_ = __udivmoddi4(a, b, Some(&mut rem_)); + assert_eq!(((a, b), (c, rem)), ((a, b), (c_, rem_))); } } +" + } + } -fn main() { - let target = env::var("TARGET").expect("TARGET was not set"); + #[derive(Eq, Hash, PartialEq)] + pub struct Udivmodsi4 { + a: u32, + b: u32, + c: u32, + rem: u32, + } - // Emscripten's runtime includes all the builtins - if target.contains("emscripten") { - return; + impl TestCase for Udivmodsi4 { + fn name() -> &'static str { + "udivmodsi4" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u32(rng); + let b = gen_u32(rng); + if b == 0 { + return None; + } + let c = a / b; + let rem = a % b; + + Some(Udivmodsi4 { a, b, c, rem }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), ({c}, {rem})),", + a = self.a, + b = self.b, + c = self.c, + rem = self.rem + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::udiv::__udivmodsi4; + +static TEST_CASES: &[((u32, u32), (u32, u32))] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn udivmodsi4() { + for &((a, b), (c, rem)) in TEST_CASES { + let mut rem_ = 0; + let c_ = __udivmodsi4(a, b, Some(&mut rem_)); + assert_eq!(((a, b), (c, rem)), ((a, b), (c_, rem_))); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Udivmodti4 { + a: u128, + b: u128, + c: u128, + rem: u128, + } + + impl TestCase for Udivmodti4 { + fn name() -> &'static str { + "udivmodti4" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u128(rng); + let b = gen_u128(rng); + if b == 0 { + return None; + } + let c = a / b; + let rem = a % b; + + Some(Udivmodti4 { a, b, c, rem }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), ({c}, {rem})),", + a = self.a, + b = self.b, + c = self.c, + rem = self.rem + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::udiv::__udivmodti4; + +static TEST_CASES: &[((u128, u128), (u128, u128))] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn udivmodti4() { + for &((a, b), (c, rem)) in TEST_CASES { + let mut rem_ = 0; + let c_ = __udivmodti4(a, b, Some(&mut rem_)); + assert_eq!(((a, b), (c, rem)), ((a, b), (c_, rem_))); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Udivsi3 { + a: u32, + b: u32, + c: u32, + } + + impl TestCase for Udivsi3 { + fn name() -> &'static str { + "udivsi3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u32(rng); + let b = gen_u32(rng); + if b == 0 { + return None; + } + let c = a / b; + + Some(Udivsi3 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::udiv::__udivsi3; + +static TEST_CASES: &[((u32, u32), u32)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn udivsi3() { + for &((a, b), c) in TEST_CASES { + let c_ = __udivsi3(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Udivti3 { + a: u128, + b: u128, + c: u128, + } + + impl TestCase for Udivti3 { + fn name() -> &'static str { + "udivti3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u128(rng); + let b = gen_u128(rng); + if b == 0 { + return None; + } + let c = a / b; + + Some(Udivti3 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::udiv::__udivti3; + +static TEST_CASES: &[((u128, u128), u128)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn udivti3() { + for &((a, b), c) in TEST_CASES { + let c_ = __udivti3(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Umoddi3 { + a: u64, + b: u64, + c: u64, + } + + impl TestCase for Umoddi3 { + fn name() -> &'static str { + "umoddi3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u64(rng); + let b = gen_u64(rng); + if b == 0 { + return None; + } + let c = a % b; + + Some(Umoddi3 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::udiv::__umoddi3; + +static TEST_CASES: &[((u64, u64), u64)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn umoddi3() { + for &((a, b), c) in TEST_CASES { + let c_ = __umoddi3(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Umodsi3 { + a: u32, + b: u32, + c: u32, + } + + impl TestCase for Umodsi3 { + fn name() -> &'static str { + "umodsi3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u32(rng); + let b = gen_u32(rng); + if b == 0 { + return None; + } + let c = a % b; + + Some(Umodsi3 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::udiv::__umodsi3; + +static TEST_CASES: &[((u32, u32), u32)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn umodsi3() { + for &((a, b), c) in TEST_CASES { + let c_ = __umodsi3(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct Umodti3 { + a: u128, + b: u128, + c: u128, + } + + impl TestCase for Umodti3 { + fn name() -> &'static str { + "umodti3" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u128(rng); + let b = gen_u128(rng); + if b == 0 { + return None; + } + let c = a % b; + + Some(Umodti3 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::udiv::__umodti3; + +static TEST_CASES: &[((u128, u128), u128)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn umodti3() { + for &((a, b), c) in TEST_CASES { + let c_ = __umodti3(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + trait TestCase { + /// Name of the intrinsic to test + fn name() -> &'static str; + /// Generates a valid test case + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized; + /// Stringifies a test case + fn to_string(&self, buffer: &mut String); + /// Prologue of the test file + fn prologue() -> &'static str; + /// Epilogue of the test file + fn epilogue() -> &'static str; } - // Can't reuse `sources` list for the freshness check becuse it doesn't contain header files. - let native = match native_lib_boilerplate("compiler-rt", "compiler-rt", "compiler-rt", ".") { - Ok(native) => native, - _ => return, + const PROLOGUE: &'static str = r#" +extern crate compiler_builtins; + +// test runner +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +extern crate utest_cortex_m_qemu; + +// overrides `panic!` +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +#[macro_use] +extern crate utest_macros; + +#[cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test))] +macro_rules! panic { + ($($tt:tt)*) => { + upanic!($($tt)*); }; +} +"#; + + macro_rules! gen_int { + ($name:ident, $ity:ident, $hty:ident) => { + fn $name(rng: &mut R) -> $ity + where + R: Rng, + { + let mut mk = || if rng.gen_weighted_bool(10) { + *rng.choose(&[::std::$hty::MAX, 0, ::std::$hty::MIN]).unwrap() + } else { + rng.gen::<$hty>() + }; + unsafe { mem::transmute([mk(), mk()]) } + } + + } + } + + gen_int!(gen_i32, i32, i16); + gen_int!(gen_i64, i64, i32); + gen_int!(gen_i128, i128, i64); + + macro_rules! gen_float { + ($name:ident, + $fty:ident, + $uty:ident, + $bits:expr, + $significand_bits:expr) => { + pub fn $name(rng: &mut R) -> $fty + where + R: Rng, + { + const BITS: u8 = $bits; + const SIGNIFICAND_BITS: u8 = $significand_bits; + + const SIGNIFICAND_MASK: $uty = (1 << SIGNIFICAND_BITS) - 1; + const SIGN_MASK: $uty = (1 << (BITS - 1)); + const EXPONENT_MASK: $uty = !(SIGN_MASK | SIGNIFICAND_MASK); + + fn mk_f32(sign: bool, exponent: $uty, significand: $uty) -> $fty { + unsafe { + mem::transmute(((sign as $uty) << (BITS - 1)) | + ((exponent & EXPONENT_MASK) << + SIGNIFICAND_BITS) | + (significand & SIGNIFICAND_MASK)) + } + } + + if rng.gen_weighted_bool(10) { + // Special values + *rng.choose(&[-0.0, + 0.0, + ::std::$fty::NAN, + ::std::$fty::INFINITY, + -::std::$fty::INFINITY]) + .unwrap() + } else if rng.gen_weighted_bool(10) { + // NaN patterns + mk_f32(rng.gen(), rng.gen(), 0) + } else if rng.gen() { + // Denormalized + mk_f32(rng.gen(), 0, rng.gen()) + } else { + // Random anything + mk_f32(rng.gen(), rng.gen(), rng.gen()) + } + } + } + } + + gen_float!(gen_f32, f32, u32, 32, 23); + gen_float!(gen_f64, f64, u64, 64, 52); + + pub fn gen_u128(rng: &mut R) -> u128 + where + R: Rng, + { + gen_i128(rng) as u128 + } + + pub fn gen_u32(rng: &mut R) -> u32 + where + R: Rng, + { + gen_i32(rng) as u32 + } + + fn gen_u64(rng: &mut R) -> u64 + where + R: Rng, + { + gen_i64(rng) as u64 + } + + pub fn to_u32(x: f32) -> u32 { + unsafe { mem::transmute(x) } + } + + pub fn to_u64(x: f64) -> u64 { + unsafe { mem::transmute(x) } + } + + fn mk_tests(mut n: usize, rng: &mut R) -> String + where + T: Eq + Hash + TestCase, + R: Rng, + { + let mut buffer = PROLOGUE.to_owned(); + buffer.push_str(T::prologue()); + let mut cases = HashSet::new(); + while n != 0 { + if let Some(case) = T::generate(rng) { + if cases.contains(&case) { + continue; + } + case.to_string(&mut buffer); + n -= 1; + cases.insert(case); + } + } + buffer.push_str(T::epilogue()); + buffer + } + + fn mk_file() + where + T: Eq + Hash + TestCase, + { + use std::io::Write; + + let rng = &mut rand::thread_rng(); + let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + let out_file_name = format!("{}.rs", T::name()); + let out_file = out_dir.join(&out_file_name); + println!("Generating {}", out_file_name); + let contents = mk_tests::(NTESTS, rng); + + File::create(out_file) + .unwrap() + .write_all(contents.as_bytes()) + .unwrap(); + } +} + +#[cfg(feature = "c")] +mod c { + extern crate gcc; + + use std::collections::BTreeMap; + use std::env; + use std::path::Path; + + struct Sources { + // SYMBOL -> PATH TO SOURCE + map: BTreeMap<&'static str, &'static str>, + } + + impl Sources { + fn new() -> Sources { + Sources { map: BTreeMap::new() } + } + + fn extend(&mut self, sources: &[&'static str]) { + // NOTE Some intrinsics have both a generic implementation (e.g. + // `floatdidf.c`) and an arch optimized implementation + // (`x86_64/floatdidf.c`). In those cases, we keep the arch optimized + // implementation and discard the generic implementation. If we don't + // and keep both implementations, the linker will yell at us about + // duplicate symbols! + for &src in sources { + let symbol = Path::new(src).file_stem().unwrap().to_str().unwrap(); + if src.contains("/") { + // Arch-optimized implementation (preferred) + self.map.insert(symbol, src); + } else { + // Generic implementation + if !self.map.contains_key(symbol) { + self.map.insert(symbol, src); + } + } + } + } + + fn remove(&mut self, symbols: &[&str]) { + for symbol in symbols { + self.map.remove(*symbol).unwrap(); + } + } + } - let cfg = &mut gcc::Config::new(); - cfg.out_dir(&native.out_dir); - - if target.contains("msvc") { - // Don't pull in extra libraries on MSVC - cfg.flag("/Zl"); - - // Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP - cfg.define("__func__", Some("__FUNCTION__")); - } else { - // Turn off various features of gcc and such, mostly copying - // compiler-rt's build system already - cfg.flag("-fno-builtin"); - cfg.flag("-fvisibility=hidden"); - // Accepted practice on Solaris is to never omit frame pointer so that - // system observability tools work as expected. In addition, at least - // on Solaris, -fomit-frame-pointer on sparcv9 appears to generate - // references to data outside of the current stack frame. A search of - // the gcc bug database provides a variety of issues surrounding - // -fomit-frame-pointer on non-x86 platforms. - if !target.contains("solaris") && !target.contains("sparc") { + /// Compile intrinsics from the compiler-rt C source code + pub fn compile(llvm_target: &[&str]) { + let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); + let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap(); + let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); + let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").unwrap(); + + let cfg = &mut gcc::Config::new(); + + if target_env == "msvc" { + // Don't pull in extra libraries on MSVC + cfg.flag("/Zl"); + + // Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP + cfg.define("__func__", Some("__FUNCTION__")); + } else { + // Turn off various features of gcc and such, mostly copying + // compiler-rt's build system already + cfg.flag("-fno-builtin"); + cfg.flag("-fvisibility=hidden"); cfg.flag("-fomit-frame-pointer"); + cfg.flag("-ffreestanding"); + cfg.define("VISIBILITY_HIDDEN", None); + } + + // NOTE Most of the ARM intrinsics are written in assembly. Tell gcc which arch we are going + // to target to make sure that the assembly implementations really work for the target. If + // the implementation is not valid for the arch, then gcc will error when compiling it. + if llvm_target[0].starts_with("thumb") { + cfg.flag("-mthumb"); + + if llvm_target.last() == Some(&"eabihf") { + cfg.flag("-mfloat-abi=hard"); + } + } + + if llvm_target[0] == "thumbv6m" { + cfg.flag("-march=armv6-m"); + } + + if llvm_target[0] == "thumbv7m" { + cfg.flag("-march=armv7-m"); + } + + if llvm_target[0] == "thumbv7em" { + cfg.flag("-march=armv7e-m"); + } + + let mut sources = Sources::new(); + sources.extend( + &[ + "absvdi2.c", + "absvsi2.c", + "addvdi3.c", + "addvsi3.c", + "apple_versioning.c", + "clzdi2.c", + "clzsi2.c", + "cmpdi2.c", + "comparedf2.c", + "comparesf2.c", + "ctzdi2.c", + "ctzsi2.c", + "divdc3.c", + "divdf3.c", + "divsc3.c", + "divsf3.c", + "divxc3.c", + "extendsfdf2.c", + "extendhfsf2.c", + "floatdisf.c", + "floatundisf.c", + "int_util.c", + "muldc3.c", + "muldf3.c", + "mulsc3.c", + "mulsf3.c", + "mulvdi3.c", + "mulvsi3.c", + "mulxc3.c", + "negdf2.c", + "negdi2.c", + "negsf2.c", + "negvdi2.c", + "negvsi2.c", + "paritydi2.c", + "paritysi2.c", + "popcountdi2.c", + "popcountsi2.c", + "powixf2.c", + "subvdi3.c", + "subvsi3.c", + "truncdfhf2.c", + "truncdfsf2.c", + "truncsfhf2.c", + "ucmpdi2.c", + ], + ); + + // When compiling in rustbuild (the rust-lang/rust repo) this library + // also needs to satisfy intrinsics that jemalloc or C in general may + // need, so include a few more that aren't typically needed by + // LLVM/Rust. + sources.extend(&[ + "ffsdi2.c", + ]); + + if target_os != "ios" { + sources.extend( + &[ + "absvti2.c", + "addvti3.c", + "clzti2.c", + "cmpti2.c", + "ctzti2.c", + "ffsti2.c", + "mulvti3.c", + "negti2.c", + "negvti2.c", + "parityti2.c", + "popcountti2.c", + "subvti3.c", + "ucmpti2.c", + ], + ); + } + + if target_vendor == "apple" { + sources.extend( + &[ + "atomic_flag_clear.c", + "atomic_flag_clear_explicit.c", + "atomic_flag_test_and_set.c", + "atomic_flag_test_and_set_explicit.c", + "atomic_signal_fence.c", + "atomic_thread_fence.c", + ], + ); + } + + if target_env == "msvc" { + if target_arch == "x86_64" { + sources.extend( + &[ + "x86_64/floatdisf.c", + "x86_64/floatdixf.c", + ], + ); + } + } else { + // None of these seem to be used on x86_64 windows, and they've all + // got the wrong ABI anyway, so we want to avoid them. + if target_os != "windows" { + if target_arch == "x86_64" { + sources.extend( + &[ + "x86_64/floatdisf.c", + "x86_64/floatdixf.c", + "x86_64/floatundidf.S", + "x86_64/floatundisf.S", + "x86_64/floatundixf.S", + ], + ); + } + } + + if target_arch == "x86" { + sources.extend( + &[ + "i386/ashldi3.S", + "i386/ashrdi3.S", + "i386/chkstk.S", + "i386/chkstk2.S", + "i386/divdi3.S", + "i386/floatdidf.S", + "i386/floatdisf.S", + "i386/floatdixf.S", + "i386/floatundidf.S", + "i386/floatundisf.S", + "i386/floatundixf.S", + "i386/lshrdi3.S", + "i386/moddi3.S", + "i386/muldi3.S", + "i386/udivdi3.S", + "i386/umoddi3.S", + ], + ); + } + } + + if target_arch == "arm" && target_os != "ios" { + sources.extend( + &[ + "arm/aeabi_cdcmp.S", + "arm/aeabi_cdcmpeq_check_nan.c", + "arm/aeabi_cfcmp.S", + "arm/aeabi_cfcmpeq_check_nan.c", + "arm/aeabi_dcmp.S", + "arm/aeabi_div0.c", + "arm/aeabi_drsub.c", + "arm/aeabi_fcmp.S", + "arm/aeabi_frsub.c", + "arm/bswapdi2.S", + "arm/bswapsi2.S", + "arm/clzdi2.S", + "arm/clzsi2.S", + "arm/comparesf2.S", + "arm/divmodsi4.S", + "arm/modsi3.S", + "arm/switch16.S", + "arm/switch32.S", + "arm/switch8.S", + "arm/switchu8.S", + "arm/sync_synchronize.S", + "arm/udivmodsi4.S", + "arm/umodsi3.S", + + // Exclude these two files for now even though we haven't + // translated their implementation into Rust yet (#173). + // They appear... buggy? The `udivsi3` implementation was + // the one that seemed buggy, but the `divsi3` file + // references a symbol from `udivsi3` so we compile them + // both with the Rust versions. + // + // Note that if these are added back they should be removed + // from thumbv6m below. + // + // "arm/divsi3.S", + // "arm/udivsi3.S", + ], + ); + } + + if llvm_target[0] == "armv7" { + sources.extend( + &[ + "arm/sync_fetch_and_add_4.S", + "arm/sync_fetch_and_add_8.S", + "arm/sync_fetch_and_and_4.S", + "arm/sync_fetch_and_and_8.S", + "arm/sync_fetch_and_max_4.S", + "arm/sync_fetch_and_max_8.S", + "arm/sync_fetch_and_min_4.S", + "arm/sync_fetch_and_min_8.S", + "arm/sync_fetch_and_nand_4.S", + "arm/sync_fetch_and_nand_8.S", + "arm/sync_fetch_and_or_4.S", + "arm/sync_fetch_and_or_8.S", + "arm/sync_fetch_and_sub_4.S", + "arm/sync_fetch_and_sub_8.S", + "arm/sync_fetch_and_umax_4.S", + "arm/sync_fetch_and_umax_8.S", + "arm/sync_fetch_and_umin_4.S", + "arm/sync_fetch_and_umin_8.S", + "arm/sync_fetch_and_xor_4.S", + "arm/sync_fetch_and_xor_8.S", + ], + ); + } + + if llvm_target.last().unwrap().ends_with("eabihf") { + if !llvm_target[0].starts_with("thumbv7em") { + sources.extend( + &[ + "arm/adddf3vfp.S", + "arm/addsf3vfp.S", + "arm/divdf3vfp.S", + "arm/divsf3vfp.S", + "arm/eqdf2vfp.S", + "arm/eqsf2vfp.S", + "arm/extendsfdf2vfp.S", + "arm/fixdfsivfp.S", + "arm/fixsfsivfp.S", + "arm/fixunsdfsivfp.S", + "arm/fixunssfsivfp.S", + "arm/floatsidfvfp.S", + "arm/floatsisfvfp.S", + "arm/floatunssidfvfp.S", + "arm/floatunssisfvfp.S", + "arm/gedf2vfp.S", + "arm/gesf2vfp.S", + "arm/gtdf2vfp.S", + "arm/gtsf2vfp.S", + "arm/ledf2vfp.S", + "arm/lesf2vfp.S", + "arm/ltdf2vfp.S", + "arm/ltsf2vfp.S", + "arm/muldf3vfp.S", + "arm/mulsf3vfp.S", + "arm/nedf2vfp.S", + "arm/nesf2vfp.S", + "arm/restore_vfp_d8_d15_regs.S", + "arm/save_vfp_d8_d15_regs.S", + "arm/subdf3vfp.S", + "arm/subsf3vfp.S", + ], + ); + } + + sources.extend(&["arm/negdf2vfp.S", "arm/negsf2vfp.S"]); + + } + + if target_arch == "aarch64" { + sources.extend( + &[ + "comparetf2.c", + "extenddftf2.c", + "extendsftf2.c", + "fixtfdi.c", + "fixtfsi.c", + "fixtfti.c", + "fixunstfdi.c", + "fixunstfsi.c", + "fixunstfti.c", + "floatditf.c", + "floatsitf.c", + "floatunditf.c", + "floatunsitf.c", + "multc3.c", + "trunctfdf2.c", + "trunctfsf2.c", + ], + ); + } + + // Remove the assembly implementations that won't compile for the target + if llvm_target[0] == "thumbv6m" { + sources.remove( + &[ + "aeabi_cdcmp", + "aeabi_cfcmp", + "aeabi_dcmp", + "aeabi_fcmp", + "clzdi2", + "clzsi2", + "comparesf2", + "divmodsi4", + "modsi3", + "switch16", + "switch32", + "switch8", + "switchu8", + "udivmodsi4", + "umodsi3", + ], + ); + + // But use some generic implementations where possible + sources.extend(&["clzdi2.c", "clzsi2.c"]) + } + + if llvm_target[0] == "thumbv7m" || llvm_target[0] == "thumbv7em" { + sources.remove(&["aeabi_cdcmp", "aeabi_cfcmp"]); + } + + let root = if env::var_os("CARGO_FEATURE_RUSTBUILD").is_some() { + Path::new("../../libcompiler_builtins") + } else { + Path::new(".") + }; + + let src_dir = root.join("compiler-rt/lib/builtins"); + for src in sources.map.values() { + let src = src_dir.join(src); + cfg.file(&src); + println!("cargo:rerun-if-changed={}", src.display()); } - cfg.flag("-ffreestanding"); - cfg.define("VISIBILITY_HIDDEN", None); - } - - let mut sources = Sources::new(); - sources.extend(&["absvdi2.c", - "absvsi2.c", - "adddf3.c", - "addsf3.c", - "addvdi3.c", - "addvsi3.c", - "apple_versioning.c", - "ashldi3.c", - "ashrdi3.c", - "clzdi2.c", - "clzsi2.c", - "cmpdi2.c", - "comparedf2.c", - "comparesf2.c", - "ctzdi2.c", - "ctzsi2.c", - "divdc3.c", - "divdf3.c", - "divdi3.c", - "divmoddi4.c", - "divmodsi4.c", - "divsc3.c", - "divsf3.c", - "divsi3.c", - "divxc3.c", - "extendsfdf2.c", - "extendhfsf2.c", - "ffsdi2.c", - "fixdfdi.c", - "fixdfsi.c", - "fixsfdi.c", - "fixsfsi.c", - "fixunsdfdi.c", - "fixunsdfsi.c", - "fixunssfdi.c", - "fixunssfsi.c", - "fixunsxfdi.c", - "fixunsxfsi.c", - "fixxfdi.c", - "floatdidf.c", - "floatdisf.c", - "floatdixf.c", - "floatsidf.c", - "floatsisf.c", - "floatundidf.c", - "floatundisf.c", - "floatundixf.c", - "floatunsidf.c", - "floatunsisf.c", - "int_util.c", - "lshrdi3.c", - "moddi3.c", - "modsi3.c", - "muldc3.c", - "muldf3.c", - "muldi3.c", - "mulodi4.c", - "mulosi4.c", - "muloti4.c", - "mulsc3.c", - "mulsf3.c", - "mulvdi3.c", - "mulvsi3.c", - "mulxc3.c", - "negdf2.c", - "negdi2.c", - "negsf2.c", - "negvdi2.c", - "negvsi2.c", - "paritydi2.c", - "paritysi2.c", - "popcountdi2.c", - "popcountsi2.c", - "powidf2.c", - "powisf2.c", - "powixf2.c", - "subdf3.c", - "subsf3.c", - "subvdi3.c", - "subvsi3.c", - "truncdfhf2.c", - "truncdfsf2.c", - "truncsfhf2.c", - "ucmpdi2.c", - "udivdi3.c", - "udivmoddi4.c", - "udivmodsi4.c", - "udivsi3.c", - "umoddi3.c", - "umodsi3.c"]); - - if !target.contains("ios") { - sources.extend(&["absvti2.c", - "addvti3.c", - "ashlti3.c", - "ashrti3.c", - "clzti2.c", - "cmpti2.c", - "ctzti2.c", - "divti3.c", - "ffsti2.c", - "fixdfti.c", - "fixsfti.c", - "fixunsdfti.c", - "fixunssfti.c", - "fixunsxfti.c", - "fixxfti.c", - "floattidf.c", - "floattisf.c", - "floattixf.c", - "floatuntidf.c", - "floatuntisf.c", - "floatuntixf.c", - "lshrti3.c", - "modti3.c", - "multi3.c", - "mulvti3.c", - "negti2.c", - "negvti2.c", - "parityti2.c", - "popcountti2.c", - "subvti3.c", - "ucmpti2.c", - "udivmodti4.c", - "udivti3.c", - "umodti3.c"]); - } - - if target.contains("apple") { - sources.extend(&["atomic_flag_clear.c", - "atomic_flag_clear_explicit.c", - "atomic_flag_test_and_set.c", - "atomic_flag_test_and_set_explicit.c", - "atomic_signal_fence.c", - "atomic_thread_fence.c"]); - } - - if target.contains("msvc") { - if target.contains("x86_64") { - sources.extend(&["x86_64/floatdidf.c", "x86_64/floatdisf.c", "x86_64/floatdixf.c"]); - } - } else { - if !target.contains("freebsd") && !target.contains("netbsd") { - sources.extend(&["gcc_personality_v0.c"]); - } - - if target.contains("x86_64") { - sources.extend(&["x86_64/chkstk.S", - "x86_64/chkstk2.S", - "x86_64/floatdidf.c", - "x86_64/floatdisf.c", - "x86_64/floatdixf.c", - "x86_64/floatundidf.S", - "x86_64/floatundisf.S", - "x86_64/floatundixf.S"]); - } - - if target.contains("i386") || target.contains("i586") || target.contains("i686") { - sources.extend(&["i386/ashldi3.S", - "i386/ashrdi3.S", - "i386/chkstk.S", - "i386/chkstk2.S", - "i386/divdi3.S", - "i386/floatdidf.S", - "i386/floatdisf.S", - "i386/floatdixf.S", - "i386/floatundidf.S", - "i386/floatundisf.S", - "i386/floatundixf.S", - "i386/lshrdi3.S", - "i386/moddi3.S", - "i386/muldi3.S", - "i386/udivdi3.S", - "i386/umoddi3.S"]); - } - } - - if target.contains("arm") && !target.contains("ios") { - // (At least) udivsi3.S is broken for Thumb 1 which our gcc uses by - // default, we don't want Thumb 2 since it isn't supported on some - // devices, so disable thumb entirely. - // Upstream bug: https://bugs.llvm.org/show_bug.cgi?id=32492 - cfg.define("__ARM_ARCH_ISA_THUMB", Some("0")); - - sources.extend(&["arm/aeabi_cdcmp.S", - "arm/aeabi_cdcmpeq_check_nan.c", - "arm/aeabi_cfcmp.S", - "arm/aeabi_cfcmpeq_check_nan.c", - "arm/aeabi_dcmp.S", - "arm/aeabi_div0.c", - "arm/aeabi_drsub.c", - "arm/aeabi_fcmp.S", - "arm/aeabi_frsub.c", - "arm/aeabi_idivmod.S", - "arm/aeabi_ldivmod.S", - "arm/aeabi_memcmp.S", - "arm/aeabi_memcpy.S", - "arm/aeabi_memmove.S", - "arm/aeabi_memset.S", - "arm/aeabi_uidivmod.S", - "arm/aeabi_uldivmod.S", - "arm/bswapdi2.S", - "arm/bswapsi2.S", - "arm/clzdi2.S", - "arm/clzsi2.S", - "arm/comparesf2.S", - "arm/divmodsi4.S", - "arm/divsi3.S", - "arm/modsi3.S", - "arm/switch16.S", - "arm/switch32.S", - "arm/switch8.S", - "arm/switchu8.S", - "arm/sync_synchronize.S", - "arm/udivmodsi4.S", - "arm/udivsi3.S", - "arm/umodsi3.S"]); - } - - if target.contains("armv7") { - sources.extend(&["arm/sync_fetch_and_add_4.S", - "arm/sync_fetch_and_add_8.S", - "arm/sync_fetch_and_and_4.S", - "arm/sync_fetch_and_and_8.S", - "arm/sync_fetch_and_max_4.S", - "arm/sync_fetch_and_max_8.S", - "arm/sync_fetch_and_min_4.S", - "arm/sync_fetch_and_min_8.S", - "arm/sync_fetch_and_nand_4.S", - "arm/sync_fetch_and_nand_8.S", - "arm/sync_fetch_and_or_4.S", - "arm/sync_fetch_and_or_8.S", - "arm/sync_fetch_and_sub_4.S", - "arm/sync_fetch_and_sub_8.S", - "arm/sync_fetch_and_umax_4.S", - "arm/sync_fetch_and_umax_8.S", - "arm/sync_fetch_and_umin_4.S", - "arm/sync_fetch_and_umin_8.S", - "arm/sync_fetch_and_xor_4.S", - "arm/sync_fetch_and_xor_8.S"]); - } - - if target.contains("eabihf") { - sources.extend(&["arm/adddf3vfp.S", - "arm/addsf3vfp.S", - "arm/divdf3vfp.S", - "arm/divsf3vfp.S", - "arm/eqdf2vfp.S", - "arm/eqsf2vfp.S", - "arm/extendsfdf2vfp.S", - "arm/fixdfsivfp.S", - "arm/fixsfsivfp.S", - "arm/fixunsdfsivfp.S", - "arm/fixunssfsivfp.S", - "arm/floatsidfvfp.S", - "arm/floatsisfvfp.S", - "arm/floatunssidfvfp.S", - "arm/floatunssisfvfp.S", - "arm/gedf2vfp.S", - "arm/gesf2vfp.S", - "arm/gtdf2vfp.S", - "arm/gtsf2vfp.S", - "arm/ledf2vfp.S", - "arm/lesf2vfp.S", - "arm/ltdf2vfp.S", - "arm/ltsf2vfp.S", - "arm/muldf3vfp.S", - "arm/mulsf3vfp.S", - "arm/negdf2vfp.S", - "arm/negsf2vfp.S", - "arm/nedf2vfp.S", - "arm/nesf2vfp.S", - "arm/restore_vfp_d8_d15_regs.S", - "arm/save_vfp_d8_d15_regs.S", - "arm/subdf3vfp.S", - "arm/subsf3vfp.S", - "arm/truncdfsf2vfp.S", - "arm/unorddf2vfp.S", - "arm/unordsf2vfp.S"]); - } - - if target.contains("aarch64") { - sources.extend(&["comparetf2.c", - "extenddftf2.c", - "extendsftf2.c", - "fixtfdi.c", - "fixtfsi.c", - "fixtfti.c", - "fixunstfdi.c", - "fixunstfsi.c", - "fixunstfti.c", - "floatditf.c", - "floatsitf.c", - "floatunditf.c", - "floatunsitf.c", - "multc3.c", - "trunctfdf2.c", - "trunctfsf2.c"]); - } - - for src in sources.map.values() { - cfg.file(Path::new("../compiler-rt/lib/builtins").join(src)); - } - - cfg.compile("libcompiler-rt.a"); + + cfg.compile("libcompiler-rt.a"); + } } diff --git a/src/libcompiler_builtins/ci/docker/aarch64-unknown-linux-gnu/Dockerfile b/src/libcompiler_builtins/ci/docker/aarch64-unknown-linux-gnu/Dockerfile new file mode 100644 index 0000000000..fe05867e37 --- /dev/null +++ b/src/libcompiler_builtins/ci/docker/aarch64-unknown-linux-gnu/Dockerfile @@ -0,0 +1,9 @@ +FROM ubuntu:16.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc libc6-dev ca-certificates \ + gcc-aarch64-linux-gnu libc6-dev-arm64-cross \ + qemu-user-static +ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc \ + QEMU_LD_PREFIX=/usr/aarch64-linux-gnu \ + RUST_TEST_THREADS=1 diff --git a/src/libcompiler_builtins/ci/docker/arm-unknown-linux-gnueabi/Dockerfile b/src/libcompiler_builtins/ci/docker/arm-unknown-linux-gnueabi/Dockerfile new file mode 100644 index 0000000000..8a09c20c43 --- /dev/null +++ b/src/libcompiler_builtins/ci/docker/arm-unknown-linux-gnueabi/Dockerfile @@ -0,0 +1,9 @@ +FROM ubuntu:16.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc libc6-dev ca-certificates \ + gcc-arm-linux-gnueabi libc6-dev-armel-cross qemu-user-static +ENV CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABI_LINKER=arm-linux-gnueabi-gcc \ + QEMU_LD_PREFIX=/usr/arm-linux-gnueabi \ + RUST_TEST_THREADS=1 + diff --git a/src/libcompiler_builtins/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile b/src/libcompiler_builtins/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile new file mode 100644 index 0000000000..57d830d1cd --- /dev/null +++ b/src/libcompiler_builtins/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile @@ -0,0 +1,8 @@ +FROM ubuntu:16.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc libc6-dev ca-certificates \ + gcc-arm-linux-gnueabihf libc6-dev-armhf-cross qemu-user-static +ENV CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc \ + QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf \ + RUST_TEST_THREADS=1 diff --git a/src/libcompiler_builtins/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile b/src/libcompiler_builtins/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile new file mode 100644 index 0000000000..a2f3cf177a --- /dev/null +++ b/src/libcompiler_builtins/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile @@ -0,0 +1,8 @@ +FROM ubuntu:16.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc libc6-dev ca-certificates \ + gcc-arm-linux-gnueabihf libc6-dev-armhf-cross qemu-user-static +ENV CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc \ + QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf \ + RUST_TEST_THREADS=1 diff --git a/src/libcompiler_builtins/ci/docker/i586-unknown-linux-gnu/Dockerfile b/src/libcompiler_builtins/ci/docker/i586-unknown-linux-gnu/Dockerfile new file mode 100644 index 0000000000..fb32306090 --- /dev/null +++ b/src/libcompiler_builtins/ci/docker/i586-unknown-linux-gnu/Dockerfile @@ -0,0 +1,4 @@ +FROM ubuntu:16.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc-multilib libc6-dev ca-certificates diff --git a/src/libcompiler_builtins/ci/docker/i686-unknown-linux-gnu/Dockerfile b/src/libcompiler_builtins/ci/docker/i686-unknown-linux-gnu/Dockerfile new file mode 100644 index 0000000000..fb32306090 --- /dev/null +++ b/src/libcompiler_builtins/ci/docker/i686-unknown-linux-gnu/Dockerfile @@ -0,0 +1,4 @@ +FROM ubuntu:16.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc-multilib libc6-dev ca-certificates diff --git a/src/libcompiler_builtins/ci/docker/mips-unknown-linux-gnu/Dockerfile b/src/libcompiler_builtins/ci/docker/mips-unknown-linux-gnu/Dockerfile new file mode 100644 index 0000000000..9d69f1dfea --- /dev/null +++ b/src/libcompiler_builtins/ci/docker/mips-unknown-linux-gnu/Dockerfile @@ -0,0 +1,11 @@ +FROM ubuntu:16.04 + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc libc6-dev ca-certificates \ + gcc-mips-linux-gnu libc6-dev-mips-cross \ + binfmt-support qemu-user-static qemu-system-mips + +ENV CARGO_TARGET_MIPS_UNKNOWN_LINUX_GNU_LINKER=mips-linux-gnu-gcc \ + QEMU_LD_PREFIX=/usr/mips-linux-gnu \ + RUST_TEST_THREADS=1 diff --git a/src/libcompiler_builtins/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile b/src/libcompiler_builtins/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile new file mode 100644 index 0000000000..ef6eeaad59 --- /dev/null +++ b/src/libcompiler_builtins/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile @@ -0,0 +1,14 @@ +FROM ubuntu:16.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + gcc \ + gcc-mips64-linux-gnuabi64 \ + libc6-dev \ + libc6-dev-mips64-cross \ + qemu-user-static \ + qemu-system-mips +ENV CARGO_TARGET_MIPS64_UNKNOWN_LINUX_GNUABI64_LINKER=mips64-linux-gnuabi64-gcc \ + CC_mips64_unknown_linux_gnuabi64=mips64-linux-gnuabi64-gcc \ + QEMU_LD_PREFIX=/usr/mips64-linux-gnuabi64 \ + RUST_TEST_THREADS=1 diff --git a/src/libcompiler_builtins/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile b/src/libcompiler_builtins/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile new file mode 100644 index 0000000000..13f770fcc5 --- /dev/null +++ b/src/libcompiler_builtins/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile @@ -0,0 +1,13 @@ +FROM ubuntu:16.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + gcc \ + gcc-mips64el-linux-gnuabi64 \ + libc6-dev \ + libc6-dev-mips64el-cross \ + qemu-user-static +ENV CARGO_TARGET_MIPS64EL_UNKNOWN_LINUX_GNUABI64_LINKER=mips64el-linux-gnuabi64-gcc \ + CC_mips64el_unknown_linux_gnuabi64=mips64el-linux-gnuabi64-gcc \ + QEMU_LD_PREFIX=/usr/mips64el-linux-gnuabi64 \ + RUST_TEST_THREADS=1 diff --git a/src/libcompiler_builtins/ci/docker/mipsel-unknown-linux-gnu/Dockerfile b/src/libcompiler_builtins/ci/docker/mipsel-unknown-linux-gnu/Dockerfile new file mode 100644 index 0000000000..0afd5e7f50 --- /dev/null +++ b/src/libcompiler_builtins/ci/docker/mipsel-unknown-linux-gnu/Dockerfile @@ -0,0 +1,11 @@ +FROM ubuntu:16.04 + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc libc6-dev ca-certificates \ + gcc-mipsel-linux-gnu libc6-dev-mipsel-cross \ + binfmt-support qemu-user-static + +ENV CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_GNU_LINKER=mipsel-linux-gnu-gcc \ + QEMU_LD_PREFIX=/usr/mipsel-linux-gnu \ + RUST_TEST_THREADS=1 diff --git a/src/libcompiler_builtins/ci/docker/powerpc-unknown-linux-gnu/Dockerfile b/src/libcompiler_builtins/ci/docker/powerpc-unknown-linux-gnu/Dockerfile new file mode 100644 index 0000000000..6e65a04db7 --- /dev/null +++ b/src/libcompiler_builtins/ci/docker/powerpc-unknown-linux-gnu/Dockerfile @@ -0,0 +1,11 @@ +FROM ubuntu:16.04 + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc libc6-dev qemu-user-static ca-certificates \ + gcc-powerpc-linux-gnu libc6-dev-powerpc-cross \ + qemu-system-ppc + +ENV CARGO_TARGET_POWERPC_UNKNOWN_LINUX_GNU_LINKER=powerpc-linux-gnu-gcc \ + QEMU_LD_PREFIX=/usr/powerpc-linux-gnu \ + RUST_TEST_THREADS=1 diff --git a/src/libcompiler_builtins/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile b/src/libcompiler_builtins/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile new file mode 100644 index 0000000000..eb86808f64 --- /dev/null +++ b/src/libcompiler_builtins/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile @@ -0,0 +1,12 @@ +FROM ubuntu:16.04 + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc libc6-dev ca-certificates \ + gcc-powerpc64-linux-gnu libc6-dev-ppc64-cross \ + binfmt-support qemu-user-static qemu-system-ppc + +ENV CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_GNU_LINKER=powerpc64-linux-gnu-gcc \ + CC_powerpc64_unknown_linux_gnu=powerpc64-linux-gnu-gcc \ + QEMU_LD_PREFIX=/usr/powerpc64-linux-gnu \ + RUST_TEST_THREADS=1 diff --git a/src/libcompiler_builtins/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile b/src/libcompiler_builtins/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile new file mode 100644 index 0000000000..adb4106d3e --- /dev/null +++ b/src/libcompiler_builtins/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile @@ -0,0 +1,12 @@ +FROM ubuntu:16.04 + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc libc6-dev qemu-user-static ca-certificates \ + gcc-powerpc64le-linux-gnu libc6-dev-ppc64el-cross \ + qemu-system-ppc + +ENV CARGO_TARGET_POWERPC64LE_UNKNOWN_LINUX_GNU_LINKER=powerpc64le-linux-gnu-gcc \ + QEMU_CPU=POWER8 \ + QEMU_LD_PREFIX=/usr/powerpc64le-linux-gnu \ + RUST_TEST_THREADS=1 diff --git a/src/libcompiler_builtins/ci/docker/thumbv6m-linux-eabi/Dockerfile b/src/libcompiler_builtins/ci/docker/thumbv6m-linux-eabi/Dockerfile new file mode 100644 index 0000000000..d26035618e --- /dev/null +++ b/src/libcompiler_builtins/ci/docker/thumbv6m-linux-eabi/Dockerfile @@ -0,0 +1,9 @@ +FROM ubuntu:16.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + ca-certificates curl gcc gcc-arm-none-eabi libc6-dev libcurl4-openssl-dev libssh2-1 libnewlib-dev qemu-user-static +RUN curl -LSfs https://japaric.github.io/trust/install.sh | \ + sh -s -- --git japaric/xargo --tag v0.3.1 --target x86_64-unknown-linux-gnu --to /usr/bin +ENV AR_thumbv6m_linux_eabi=arm-none-eabi-ar \ + CARGO_TARGET_THUMBV6M_LINUX_EABI_LINKER=arm-none-eabi-gcc \ + CC_thumbv6m_linux_eabi=arm-none-eabi-gcc \ diff --git a/src/libcompiler_builtins/ci/docker/thumbv7em-linux-eabi/Dockerfile b/src/libcompiler_builtins/ci/docker/thumbv7em-linux-eabi/Dockerfile new file mode 100644 index 0000000000..d630352a72 --- /dev/null +++ b/src/libcompiler_builtins/ci/docker/thumbv7em-linux-eabi/Dockerfile @@ -0,0 +1,9 @@ +FROM ubuntu:16.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + ca-certificates curl gcc gcc-arm-none-eabi libc6-dev libcurl4-openssl-dev libssh2-1 libnewlib-dev qemu-user-static +RUN curl -LSfs https://japaric.github.io/trust/install.sh | \ + sh -s -- --git japaric/xargo --tag v0.3.1 --target x86_64-unknown-linux-gnu --to /usr/bin +ENV AR_thumbv7em_linux_eabi=arm-none-eabi-ar \ + CARGO_TARGET_THUMBV7EM_LINUX_EABI_LINKER=arm-none-eabi-gcc \ + CC_thumbv7em_linux_eabi=arm-none-eabi-gcc \ diff --git a/src/libcompiler_builtins/ci/docker/thumbv7em-linux-eabihf/Dockerfile b/src/libcompiler_builtins/ci/docker/thumbv7em-linux-eabihf/Dockerfile new file mode 100644 index 0000000000..6f30729fa9 --- /dev/null +++ b/src/libcompiler_builtins/ci/docker/thumbv7em-linux-eabihf/Dockerfile @@ -0,0 +1,9 @@ +FROM ubuntu:16.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + ca-certificates curl gcc gcc-arm-none-eabi libc6-dev libcurl4-openssl-dev libssh2-1 libnewlib-dev qemu-user-static +RUN curl -LSfs https://japaric.github.io/trust/install.sh | \ + sh -s -- --git japaric/xargo --tag v0.3.1 --target x86_64-unknown-linux-gnu --to /usr/bin +ENV AR_thumbv7em_linux_eabihf=arm-none-eabi-ar \ + CARGO_TARGET_THUMBV7EM_LINUX_EABIHF_LINKER=arm-none-eabi-gcc \ + CC_thumbv7em_linux_eabihf=arm-none-eabi-gcc \ diff --git a/src/libcompiler_builtins/ci/docker/thumbv7m-linux-eabi/Dockerfile b/src/libcompiler_builtins/ci/docker/thumbv7m-linux-eabi/Dockerfile new file mode 100644 index 0000000000..a7dbad6472 --- /dev/null +++ b/src/libcompiler_builtins/ci/docker/thumbv7m-linux-eabi/Dockerfile @@ -0,0 +1,9 @@ +FROM ubuntu:16.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + ca-certificates curl gcc gcc-arm-none-eabi libc6-dev libcurl4-openssl-dev libssh2-1 libnewlib-dev qemu-user-static +RUN curl -LSfs https://japaric.github.io/trust/install.sh | \ + sh -s -- --git japaric/xargo --tag v0.3.1 --target x86_64-unknown-linux-gnu --to /usr/bin +ENV AR_thumbv7m_linux_eabi=arm-none-eabi-ar \ + CARGO_TARGET_THUMBV7M_LINUX_EABI_LINKER=arm-none-eabi-gcc \ + CC_thumbv7m_linux_eabi=arm-none-eabi-gcc \ diff --git a/src/libcompiler_builtins/ci/docker/x86_64-unknown-linux-gnu/Dockerfile b/src/libcompiler_builtins/ci/docker/x86_64-unknown-linux-gnu/Dockerfile new file mode 100644 index 0000000000..efc7b26c60 --- /dev/null +++ b/src/libcompiler_builtins/ci/docker/x86_64-unknown-linux-gnu/Dockerfile @@ -0,0 +1,4 @@ +FROM ubuntu:16.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc libc6-dev ca-certificates diff --git a/src/libcompiler_builtins/ci/run-docker.sh b/src/libcompiler_builtins/ci/run-docker.sh new file mode 100644 index 0000000000..5608cedc46 --- /dev/null +++ b/src/libcompiler_builtins/ci/run-docker.sh @@ -0,0 +1,36 @@ +# Small script to run tests for a target (or all targets) inside all the +# respective docker images. + +set -ex + +run() { + local target=$1 + + echo $target + + # This directory needs to exist before calling docker, otherwise docker will create it but it + # will be owned by root + mkdir -p target + + docker build -t $target ci/docker/$target + docker run \ + --rm \ + --user $(id -u):$(id -g) \ + -e CARGO_HOME=/cargo \ + -e CARGO_TARGET_DIR=/target \ + -v $HOME/.cargo:/cargo \ + -v `pwd`/target:/target \ + -v `pwd`:/checkout:ro \ + -v `rustc --print sysroot`:/rust:ro \ + -w /checkout \ + -it $target \ + sh -c "HOME=/tmp PATH=\$PATH:/rust/bin ci/run.sh $target" +} + +if [ -z "$1" ]; then + for d in `ls ci/docker/`; do + run $d + done +else + run $1 +fi diff --git a/src/libcompiler_builtins/ci/run.sh b/src/libcompiler_builtins/ci/run.sh new file mode 100755 index 0000000000..9a32ee9ea6 --- /dev/null +++ b/src/libcompiler_builtins/ci/run.sh @@ -0,0 +1,132 @@ +set -ex + +case $1 in + thumb*) + cargo=xargo + ;; + *) + cargo=cargo + ;; +esac + +INTRINSICS_FEATURES="c" + +# Some architectures like ARM apparently seem to require the `mem` feature +# enabled to successfully compile the `intrinsics` example, and... we're not +# sure why! +if [ -z "$INTRINSICS_FAILS_WITH_MEM_FEATURE" ]; then + INTRINSICS_FEATURES="$INTRINSICS_FEATURES mem" +fi + +# Test our implementation +case $1 in + thumb*) + for t in $(ls tests); do + t=${t%.rs} + + # TODO(#154) enable these tests when aeabi_*mul are implemented + case $t in + powi*f2) + continue + ;; + esac + + xargo test --test $t --target $1 --features 'mem gen-tests' --no-run + qemu-arm-static target/${1}/debug/$t-* + + xargo test --test $t --target $1 --features 'mem gen-tests' --no-run --release + qemu-arm-static target/${1}/release/$t-* + done + ;; + *) + run="cargo test --no-default-features --target $1" + $run --features 'gen-tests mangled-names' + $run --features 'gen-tests mangled-names' --release + $run --features 'gen-tests mangled-names c' + $run --features 'gen-tests mangled-names c' --release + ;; +esac + +PREFIX=$(echo $1 | sed -e 's/unknown-//')- +case $1 in + armv7-*) + PREFIX=arm-linux-gnueabihf- + ;; + thumb*) + PREFIX=arm-none-eabi- + ;; + *86*-*) + PREFIX= + ;; +esac + +case "$TRAVIS_OS_NAME" in + osx) + # NOTE OSx's nm doesn't accept the `--defined-only` or provide an equivalent. + # Use GNU nm instead + NM=gnm + brew install binutils + ;; + *) + NM=nm + ;; +esac + +if [ -d /target ]; then + path=/target/${1}/debug/deps/libcompiler_builtins-*.rlib +else + path=target/${1}/debug/deps/libcompiler_builtins-*.rlib +fi + +# Look out for duplicated symbols when we include the compiler-rt (C) implementation +for rlib in $(echo $path); do + set +x + stdout=$($PREFIX$NM -g --defined-only $rlib 2>&1) + + # NOTE On i586, It's normal that the get_pc_thunk symbol appears several + # times so ignore it + # + # FIXME(#167) - we shouldn't ignore `__builtin_cl` style symbols here. + set +e + echo "$stdout" | \ + sort | \ + uniq -d | \ + grep -v __x86.get_pc_thunk | \ + grep -v __builtin_cl | \ + grep -v __builtin_ctz | \ + grep 'T __' + + if test $? = 0; then + exit 1 + fi + set -ex +done + +rm -f $path + +# Verify that we haven't drop any intrinsic/symbol +RUSTFLAGS="-C debug-assertions=no" \ + $cargo build --features "$INTRINSICS_FEATURES" --target $1 --example intrinsics -v + +# Verify that there are no undefined symbols to `panic` within our +# implementations +# +# TODO(#79) fix the undefined references problem for debug-assertions+lto +if [ -z "$DEBUG_LTO_BUILD_DOESNT_WORK" ]; then + RUSTFLAGS="-C debug-assertions=no" \ + $cargo rustc --features "$INTRINSICS_FEATURES" --target $1 --example intrinsics -- -C lto +fi +$cargo rustc --features "$INTRINSICS_FEATURES" --target $1 --example intrinsics --release -- -C lto + +# Ensure no references to a panicking function +for rlib in $(echo $path); do + set +ex + $PREFIX$NM -u $rlib 2>&1 | grep panicking + + if test $? = 0; then + exit 1 + fi + set -ex +done + +true diff --git a/src/compiler-rt/.arcconfig b/src/libcompiler_builtins/compiler-rt/.arcconfig similarity index 100% rename from src/compiler-rt/.arcconfig rename to src/libcompiler_builtins/compiler-rt/.arcconfig diff --git a/src/compiler-rt/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/CMakeLists.txt similarity index 100% rename from src/compiler-rt/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/CMakeLists.txt diff --git a/src/compiler-rt/CODE_OWNERS.TXT b/src/libcompiler_builtins/compiler-rt/CODE_OWNERS.TXT similarity index 100% rename from src/compiler-rt/CODE_OWNERS.TXT rename to src/libcompiler_builtins/compiler-rt/CODE_OWNERS.TXT diff --git a/src/compiler-rt/CREDITS.TXT b/src/libcompiler_builtins/compiler-rt/CREDITS.TXT similarity index 100% rename from src/compiler-rt/CREDITS.TXT rename to src/libcompiler_builtins/compiler-rt/CREDITS.TXT diff --git a/src/compiler-rt/LICENSE.TXT b/src/libcompiler_builtins/compiler-rt/LICENSE.TXT similarity index 100% rename from src/compiler-rt/LICENSE.TXT rename to src/libcompiler_builtins/compiler-rt/LICENSE.TXT diff --git a/src/compiler-rt/README.txt b/src/libcompiler_builtins/compiler-rt/README.txt similarity index 100% rename from src/compiler-rt/README.txt rename to src/libcompiler_builtins/compiler-rt/README.txt diff --git a/src/compiler-rt/cmake/Modules/AddCompilerRT.cmake b/src/libcompiler_builtins/compiler-rt/cmake/Modules/AddCompilerRT.cmake similarity index 100% rename from src/compiler-rt/cmake/Modules/AddCompilerRT.cmake rename to src/libcompiler_builtins/compiler-rt/cmake/Modules/AddCompilerRT.cmake diff --git a/src/compiler-rt/cmake/Modules/BuiltinTests.cmake b/src/libcompiler_builtins/compiler-rt/cmake/Modules/BuiltinTests.cmake similarity index 100% rename from src/compiler-rt/cmake/Modules/BuiltinTests.cmake rename to src/libcompiler_builtins/compiler-rt/cmake/Modules/BuiltinTests.cmake diff --git a/src/compiler-rt/cmake/Modules/CompilerRTCompile.cmake b/src/libcompiler_builtins/compiler-rt/cmake/Modules/CompilerRTCompile.cmake similarity index 100% rename from src/compiler-rt/cmake/Modules/CompilerRTCompile.cmake rename to src/libcompiler_builtins/compiler-rt/cmake/Modules/CompilerRTCompile.cmake diff --git a/src/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake b/src/libcompiler_builtins/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake similarity index 100% rename from src/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake rename to src/libcompiler_builtins/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake diff --git a/src/compiler-rt/cmake/Modules/CompilerRTLink.cmake b/src/libcompiler_builtins/compiler-rt/cmake/Modules/CompilerRTLink.cmake similarity index 100% rename from src/compiler-rt/cmake/Modules/CompilerRTLink.cmake rename to src/libcompiler_builtins/compiler-rt/cmake/Modules/CompilerRTLink.cmake diff --git a/src/compiler-rt/cmake/Modules/CompilerRTUtils.cmake b/src/libcompiler_builtins/compiler-rt/cmake/Modules/CompilerRTUtils.cmake similarity index 100% rename from src/compiler-rt/cmake/Modules/CompilerRTUtils.cmake rename to src/libcompiler_builtins/compiler-rt/cmake/Modules/CompilerRTUtils.cmake diff --git a/src/compiler-rt/cmake/Modules/SanitizerUtils.cmake b/src/libcompiler_builtins/compiler-rt/cmake/Modules/SanitizerUtils.cmake similarity index 100% rename from src/compiler-rt/cmake/Modules/SanitizerUtils.cmake rename to src/libcompiler_builtins/compiler-rt/cmake/Modules/SanitizerUtils.cmake diff --git a/src/compiler-rt/cmake/base-config-ix.cmake b/src/libcompiler_builtins/compiler-rt/cmake/base-config-ix.cmake similarity index 100% rename from src/compiler-rt/cmake/base-config-ix.cmake rename to src/libcompiler_builtins/compiler-rt/cmake/base-config-ix.cmake diff --git a/src/compiler-rt/cmake/builtin-config-ix.cmake b/src/libcompiler_builtins/compiler-rt/cmake/builtin-config-ix.cmake similarity index 100% rename from src/compiler-rt/cmake/builtin-config-ix.cmake rename to src/libcompiler_builtins/compiler-rt/cmake/builtin-config-ix.cmake diff --git a/src/compiler-rt/cmake/caches/Apple.cmake b/src/libcompiler_builtins/compiler-rt/cmake/caches/Apple.cmake similarity index 100% rename from src/compiler-rt/cmake/caches/Apple.cmake rename to src/libcompiler_builtins/compiler-rt/cmake/caches/Apple.cmake diff --git a/src/compiler-rt/cmake/config-ix.cmake b/src/libcompiler_builtins/compiler-rt/cmake/config-ix.cmake similarity index 100% rename from src/compiler-rt/cmake/config-ix.cmake rename to src/libcompiler_builtins/compiler-rt/cmake/config-ix.cmake diff --git a/src/compiler-rt/docs/TestingGuide.rst b/src/libcompiler_builtins/compiler-rt/docs/TestingGuide.rst similarity index 100% rename from src/compiler-rt/docs/TestingGuide.rst rename to src/libcompiler_builtins/compiler-rt/docs/TestingGuide.rst diff --git a/src/compiler-rt/include/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/include/CMakeLists.txt similarity index 100% rename from src/compiler-rt/include/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/include/CMakeLists.txt diff --git a/src/compiler-rt/include/sanitizer/allocator_interface.h b/src/libcompiler_builtins/compiler-rt/include/sanitizer/allocator_interface.h similarity index 100% rename from src/compiler-rt/include/sanitizer/allocator_interface.h rename to src/libcompiler_builtins/compiler-rt/include/sanitizer/allocator_interface.h diff --git a/src/compiler-rt/include/sanitizer/asan_interface.h b/src/libcompiler_builtins/compiler-rt/include/sanitizer/asan_interface.h similarity index 100% rename from src/compiler-rt/include/sanitizer/asan_interface.h rename to src/libcompiler_builtins/compiler-rt/include/sanitizer/asan_interface.h diff --git a/src/compiler-rt/include/sanitizer/common_interface_defs.h b/src/libcompiler_builtins/compiler-rt/include/sanitizer/common_interface_defs.h similarity index 100% rename from src/compiler-rt/include/sanitizer/common_interface_defs.h rename to src/libcompiler_builtins/compiler-rt/include/sanitizer/common_interface_defs.h diff --git a/src/compiler-rt/include/sanitizer/coverage_interface.h b/src/libcompiler_builtins/compiler-rt/include/sanitizer/coverage_interface.h similarity index 100% rename from src/compiler-rt/include/sanitizer/coverage_interface.h rename to src/libcompiler_builtins/compiler-rt/include/sanitizer/coverage_interface.h diff --git a/src/compiler-rt/include/sanitizer/dfsan_interface.h b/src/libcompiler_builtins/compiler-rt/include/sanitizer/dfsan_interface.h similarity index 100% rename from src/compiler-rt/include/sanitizer/dfsan_interface.h rename to src/libcompiler_builtins/compiler-rt/include/sanitizer/dfsan_interface.h diff --git a/src/compiler-rt/include/sanitizer/esan_interface.h b/src/libcompiler_builtins/compiler-rt/include/sanitizer/esan_interface.h similarity index 100% rename from src/compiler-rt/include/sanitizer/esan_interface.h rename to src/libcompiler_builtins/compiler-rt/include/sanitizer/esan_interface.h diff --git a/src/compiler-rt/include/sanitizer/linux_syscall_hooks.h b/src/libcompiler_builtins/compiler-rt/include/sanitizer/linux_syscall_hooks.h similarity index 100% rename from src/compiler-rt/include/sanitizer/linux_syscall_hooks.h rename to src/libcompiler_builtins/compiler-rt/include/sanitizer/linux_syscall_hooks.h diff --git a/src/compiler-rt/include/sanitizer/lsan_interface.h b/src/libcompiler_builtins/compiler-rt/include/sanitizer/lsan_interface.h similarity index 100% rename from src/compiler-rt/include/sanitizer/lsan_interface.h rename to src/libcompiler_builtins/compiler-rt/include/sanitizer/lsan_interface.h diff --git a/src/compiler-rt/include/sanitizer/msan_interface.h b/src/libcompiler_builtins/compiler-rt/include/sanitizer/msan_interface.h similarity index 100% rename from src/compiler-rt/include/sanitizer/msan_interface.h rename to src/libcompiler_builtins/compiler-rt/include/sanitizer/msan_interface.h diff --git a/src/compiler-rt/include/sanitizer/tsan_interface_atomic.h b/src/libcompiler_builtins/compiler-rt/include/sanitizer/tsan_interface_atomic.h similarity index 100% rename from src/compiler-rt/include/sanitizer/tsan_interface_atomic.h rename to src/libcompiler_builtins/compiler-rt/include/sanitizer/tsan_interface_atomic.h diff --git a/src/compiler-rt/include/xray/xray_interface.h b/src/libcompiler_builtins/compiler-rt/include/xray/xray_interface.h similarity index 100% rename from src/compiler-rt/include/xray/xray_interface.h rename to src/libcompiler_builtins/compiler-rt/include/xray/xray_interface.h diff --git a/src/compiler-rt/include/xray/xray_records.h b/src/libcompiler_builtins/compiler-rt/include/xray/xray_records.h similarity index 100% rename from src/compiler-rt/include/xray/xray_records.h rename to src/libcompiler_builtins/compiler-rt/include/xray/xray_records.h diff --git a/src/compiler-rt/lib/BlocksRuntime/Block.h b/src/libcompiler_builtins/compiler-rt/lib/BlocksRuntime/Block.h similarity index 100% rename from src/compiler-rt/lib/BlocksRuntime/Block.h rename to src/libcompiler_builtins/compiler-rt/lib/BlocksRuntime/Block.h diff --git a/src/compiler-rt/lib/BlocksRuntime/Block_private.h b/src/libcompiler_builtins/compiler-rt/lib/BlocksRuntime/Block_private.h similarity index 100% rename from src/compiler-rt/lib/BlocksRuntime/Block_private.h rename to src/libcompiler_builtins/compiler-rt/lib/BlocksRuntime/Block_private.h diff --git a/src/compiler-rt/lib/BlocksRuntime/data.c b/src/libcompiler_builtins/compiler-rt/lib/BlocksRuntime/data.c similarity index 100% rename from src/compiler-rt/lib/BlocksRuntime/data.c rename to src/libcompiler_builtins/compiler-rt/lib/BlocksRuntime/data.c diff --git a/src/compiler-rt/lib/BlocksRuntime/runtime.c b/src/libcompiler_builtins/compiler-rt/lib/BlocksRuntime/runtime.c similarity index 100% rename from src/compiler-rt/lib/BlocksRuntime/runtime.c rename to src/libcompiler_builtins/compiler-rt/lib/BlocksRuntime/runtime.c diff --git a/src/compiler-rt/lib/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/CMakeLists.txt diff --git a/src/compiler-rt/lib/asan/.clang-format b/src/libcompiler_builtins/compiler-rt/lib/asan/.clang-format similarity index 100% rename from src/compiler-rt/lib/asan/.clang-format rename to src/libcompiler_builtins/compiler-rt/lib/asan/.clang-format diff --git a/src/compiler-rt/lib/asan/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/asan/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/asan/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/asan/CMakeLists.txt diff --git a/src/compiler-rt/lib/asan/README.txt b/src/libcompiler_builtins/compiler-rt/lib/asan/README.txt similarity index 100% rename from src/compiler-rt/lib/asan/README.txt rename to src/libcompiler_builtins/compiler-rt/lib/asan/README.txt diff --git a/src/compiler-rt/lib/asan/asan.syms.extra b/src/libcompiler_builtins/compiler-rt/lib/asan/asan.syms.extra similarity index 100% rename from src/compiler-rt/lib/asan/asan.syms.extra rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan.syms.extra diff --git a/src/compiler-rt/lib/asan/asan_activation.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_activation.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_activation.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_activation.cc diff --git a/src/compiler-rt/lib/asan/asan_activation.h b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_activation.h similarity index 100% rename from src/compiler-rt/lib/asan/asan_activation.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_activation.h diff --git a/src/compiler-rt/lib/asan/asan_activation_flags.inc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_activation_flags.inc similarity index 100% rename from src/compiler-rt/lib/asan/asan_activation_flags.inc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_activation_flags.inc diff --git a/src/compiler-rt/lib/asan/asan_allocator.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_allocator.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_allocator.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_allocator.cc diff --git a/src/compiler-rt/lib/asan/asan_allocator.h b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_allocator.h similarity index 100% rename from src/compiler-rt/lib/asan/asan_allocator.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_allocator.h diff --git a/src/compiler-rt/lib/asan/asan_blacklist.txt b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_blacklist.txt similarity index 100% rename from src/compiler-rt/lib/asan/asan_blacklist.txt rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_blacklist.txt diff --git a/src/compiler-rt/lib/asan/asan_debugging.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_debugging.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_debugging.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_debugging.cc diff --git a/src/compiler-rt/lib/asan/asan_descriptions.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_descriptions.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_descriptions.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_descriptions.cc diff --git a/src/compiler-rt/lib/asan/asan_descriptions.h b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_descriptions.h similarity index 100% rename from src/compiler-rt/lib/asan/asan_descriptions.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_descriptions.h diff --git a/src/compiler-rt/lib/asan/asan_errors.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_errors.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_errors.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_errors.cc diff --git a/src/compiler-rt/lib/asan/asan_errors.h b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_errors.h similarity index 100% rename from src/compiler-rt/lib/asan/asan_errors.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_errors.h diff --git a/src/compiler-rt/lib/asan/asan_fake_stack.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_fake_stack.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_fake_stack.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_fake_stack.cc diff --git a/src/compiler-rt/lib/asan/asan_fake_stack.h b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_fake_stack.h similarity index 100% rename from src/compiler-rt/lib/asan/asan_fake_stack.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_fake_stack.h diff --git a/src/compiler-rt/lib/asan/asan_flags.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_flags.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_flags.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_flags.cc diff --git a/src/compiler-rt/lib/asan/asan_flags.h b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_flags.h similarity index 100% rename from src/compiler-rt/lib/asan/asan_flags.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_flags.h diff --git a/src/compiler-rt/lib/asan/asan_flags.inc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_flags.inc similarity index 100% rename from src/compiler-rt/lib/asan/asan_flags.inc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_flags.inc diff --git a/src/compiler-rt/lib/asan/asan_globals.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_globals.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_globals.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_globals.cc diff --git a/src/compiler-rt/lib/asan/asan_globals_win.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_globals_win.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_globals_win.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_globals_win.cc diff --git a/src/compiler-rt/lib/asan/asan_globals_win.h b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_globals_win.h similarity index 100% rename from src/compiler-rt/lib/asan/asan_globals_win.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_globals_win.h diff --git a/src/compiler-rt/lib/asan/asan_init_version.h b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_init_version.h similarity index 100% rename from src/compiler-rt/lib/asan/asan_init_version.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_init_version.h diff --git a/src/compiler-rt/lib/asan/asan_interceptors.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_interceptors.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_interceptors.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_interceptors.cc diff --git a/src/compiler-rt/lib/asan/asan_interceptors.h b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_interceptors.h similarity index 100% rename from src/compiler-rt/lib/asan/asan_interceptors.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_interceptors.h diff --git a/src/compiler-rt/lib/asan/asan_interface_internal.h b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_interface_internal.h similarity index 100% rename from src/compiler-rt/lib/asan/asan_interface_internal.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_interface_internal.h diff --git a/src/compiler-rt/lib/asan/asan_internal.h b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_internal.h similarity index 100% rename from src/compiler-rt/lib/asan/asan_internal.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_internal.h diff --git a/src/compiler-rt/lib/asan/asan_linux.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_linux.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_linux.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_linux.cc diff --git a/src/compiler-rt/lib/asan/asan_lock.h b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_lock.h similarity index 100% rename from src/compiler-rt/lib/asan/asan_lock.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_lock.h diff --git a/src/compiler-rt/lib/asan/asan_mac.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_mac.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_mac.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_mac.cc diff --git a/src/compiler-rt/lib/asan/asan_malloc_linux.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_malloc_linux.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_malloc_linux.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_malloc_linux.cc diff --git a/src/compiler-rt/lib/asan/asan_malloc_mac.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_malloc_mac.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_malloc_mac.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_malloc_mac.cc diff --git a/src/compiler-rt/lib/asan/asan_malloc_win.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_malloc_win.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_malloc_win.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_malloc_win.cc diff --git a/src/compiler-rt/lib/asan/asan_mapping.h b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_mapping.h similarity index 100% rename from src/compiler-rt/lib/asan/asan_mapping.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_mapping.h diff --git a/src/compiler-rt/lib/asan/asan_memory_profile.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_memory_profile.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_memory_profile.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_memory_profile.cc diff --git a/src/compiler-rt/lib/asan/asan_new_delete.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_new_delete.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_new_delete.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_new_delete.cc diff --git a/src/compiler-rt/lib/asan/asan_poisoning.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_poisoning.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_poisoning.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_poisoning.cc diff --git a/src/compiler-rt/lib/asan/asan_poisoning.h b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_poisoning.h similarity index 100% rename from src/compiler-rt/lib/asan/asan_poisoning.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_poisoning.h diff --git a/src/compiler-rt/lib/asan/asan_posix.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_posix.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_posix.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_posix.cc diff --git a/src/compiler-rt/lib/asan/asan_preinit.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_preinit.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_preinit.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_preinit.cc diff --git a/src/compiler-rt/lib/asan/asan_report.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_report.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_report.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_report.cc diff --git a/src/compiler-rt/lib/asan/asan_report.h b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_report.h similarity index 100% rename from src/compiler-rt/lib/asan/asan_report.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_report.h diff --git a/src/compiler-rt/lib/asan/asan_rtl.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_rtl.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_rtl.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_rtl.cc diff --git a/src/compiler-rt/lib/asan/asan_scariness_score.h b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_scariness_score.h similarity index 100% rename from src/compiler-rt/lib/asan/asan_scariness_score.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_scariness_score.h diff --git a/src/compiler-rt/lib/asan/asan_stack.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_stack.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_stack.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_stack.cc diff --git a/src/compiler-rt/lib/asan/asan_stack.h b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_stack.h similarity index 100% rename from src/compiler-rt/lib/asan/asan_stack.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_stack.h diff --git a/src/compiler-rt/lib/asan/asan_stats.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_stats.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_stats.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_stats.cc diff --git a/src/compiler-rt/lib/asan/asan_stats.h b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_stats.h similarity index 100% rename from src/compiler-rt/lib/asan/asan_stats.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_stats.h diff --git a/src/compiler-rt/lib/asan/asan_suppressions.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_suppressions.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_suppressions.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_suppressions.cc diff --git a/src/compiler-rt/lib/asan/asan_suppressions.h b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_suppressions.h similarity index 100% rename from src/compiler-rt/lib/asan/asan_suppressions.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_suppressions.h diff --git a/src/compiler-rt/lib/asan/asan_thread.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_thread.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_thread.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_thread.cc diff --git a/src/compiler-rt/lib/asan/asan_thread.h b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_thread.h similarity index 100% rename from src/compiler-rt/lib/asan/asan_thread.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_thread.h diff --git a/src/compiler-rt/lib/asan/asan_win.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_win.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_win.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_win.cc diff --git a/src/compiler-rt/lib/asan/asan_win_dll_thunk.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_win_dll_thunk.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_win_dll_thunk.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_win_dll_thunk.cc diff --git a/src/compiler-rt/lib/asan/asan_win_dynamic_runtime_thunk.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/asan_win_dynamic_runtime_thunk.cc similarity index 100% rename from src/compiler-rt/lib/asan/asan_win_dynamic_runtime_thunk.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/asan_win_dynamic_runtime_thunk.cc diff --git a/src/compiler-rt/lib/asan/scripts/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/asan/scripts/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/asan/scripts/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/asan/scripts/CMakeLists.txt diff --git a/src/compiler-rt/lib/asan/scripts/asan_device_setup b/src/libcompiler_builtins/compiler-rt/lib/asan/scripts/asan_device_setup similarity index 100% rename from src/compiler-rt/lib/asan/scripts/asan_device_setup rename to src/libcompiler_builtins/compiler-rt/lib/asan/scripts/asan_device_setup diff --git a/src/compiler-rt/lib/asan/scripts/asan_symbolize.py b/src/libcompiler_builtins/compiler-rt/lib/asan/scripts/asan_symbolize.py similarity index 100% rename from src/compiler-rt/lib/asan/scripts/asan_symbolize.py rename to src/libcompiler_builtins/compiler-rt/lib/asan/scripts/asan_symbolize.py diff --git a/src/compiler-rt/lib/asan/tests/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/asan/tests/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/asan/tests/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/asan/tests/CMakeLists.txt diff --git a/src/compiler-rt/lib/asan/tests/asan_asm_test.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_asm_test.cc similarity index 100% rename from src/compiler-rt/lib/asan/tests/asan_asm_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_asm_test.cc diff --git a/src/compiler-rt/lib/asan/tests/asan_benchmarks_test.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_benchmarks_test.cc similarity index 100% rename from src/compiler-rt/lib/asan/tests/asan_benchmarks_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_benchmarks_test.cc diff --git a/src/compiler-rt/lib/asan/tests/asan_exceptions_test.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_exceptions_test.cc similarity index 100% rename from src/compiler-rt/lib/asan/tests/asan_exceptions_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_exceptions_test.cc diff --git a/src/compiler-rt/lib/asan/tests/asan_fake_stack_test.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_fake_stack_test.cc similarity index 100% rename from src/compiler-rt/lib/asan/tests/asan_fake_stack_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_fake_stack_test.cc diff --git a/src/compiler-rt/lib/asan/tests/asan_globals_test.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_globals_test.cc similarity index 100% rename from src/compiler-rt/lib/asan/tests/asan_globals_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_globals_test.cc diff --git a/src/compiler-rt/lib/asan/tests/asan_interface_test.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_interface_test.cc similarity index 100% rename from src/compiler-rt/lib/asan/tests/asan_interface_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_interface_test.cc diff --git a/src/compiler-rt/lib/asan/tests/asan_internal_interface_test.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_internal_interface_test.cc similarity index 100% rename from src/compiler-rt/lib/asan/tests/asan_internal_interface_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_internal_interface_test.cc diff --git a/src/compiler-rt/lib/asan/tests/asan_mac_test.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_mac_test.cc similarity index 100% rename from src/compiler-rt/lib/asan/tests/asan_mac_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_mac_test.cc diff --git a/src/compiler-rt/lib/asan/tests/asan_mac_test.h b/src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_mac_test.h similarity index 100% rename from src/compiler-rt/lib/asan/tests/asan_mac_test.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_mac_test.h diff --git a/src/compiler-rt/lib/asan/tests/asan_mac_test_helpers.mm b/src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_mac_test_helpers.mm similarity index 100% rename from src/compiler-rt/lib/asan/tests/asan_mac_test_helpers.mm rename to src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_mac_test_helpers.mm diff --git a/src/compiler-rt/lib/asan/tests/asan_mem_test.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_mem_test.cc similarity index 100% rename from src/compiler-rt/lib/asan/tests/asan_mem_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_mem_test.cc diff --git a/src/compiler-rt/lib/asan/tests/asan_noinst_test.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_noinst_test.cc similarity index 100% rename from src/compiler-rt/lib/asan/tests/asan_noinst_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_noinst_test.cc diff --git a/src/compiler-rt/lib/asan/tests/asan_oob_test.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_oob_test.cc similarity index 100% rename from src/compiler-rt/lib/asan/tests/asan_oob_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_oob_test.cc diff --git a/src/compiler-rt/lib/asan/tests/asan_racy_double_free_test.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_racy_double_free_test.cc similarity index 100% rename from src/compiler-rt/lib/asan/tests/asan_racy_double_free_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_racy_double_free_test.cc diff --git a/src/compiler-rt/lib/asan/tests/asan_str_test.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_str_test.cc similarity index 100% rename from src/compiler-rt/lib/asan/tests/asan_str_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_str_test.cc diff --git a/src/compiler-rt/lib/asan/tests/asan_test.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_test.cc similarity index 100% rename from src/compiler-rt/lib/asan/tests/asan_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_test.cc diff --git a/src/compiler-rt/lib/asan/tests/asan_test.ignore b/src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_test.ignore similarity index 100% rename from src/compiler-rt/lib/asan/tests/asan_test.ignore rename to src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_test.ignore diff --git a/src/compiler-rt/lib/asan/tests/asan_test_config.h b/src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_test_config.h similarity index 100% rename from src/compiler-rt/lib/asan/tests/asan_test_config.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_test_config.h diff --git a/src/compiler-rt/lib/asan/tests/asan_test_main.cc b/src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_test_main.cc similarity index 100% rename from src/compiler-rt/lib/asan/tests/asan_test_main.cc rename to src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_test_main.cc diff --git a/src/compiler-rt/lib/asan/tests/asan_test_utils.h b/src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_test_utils.h similarity index 100% rename from src/compiler-rt/lib/asan/tests/asan_test_utils.h rename to src/libcompiler_builtins/compiler-rt/lib/asan/tests/asan_test_utils.h diff --git a/src/compiler-rt/lib/asan/weak_symbols.txt b/src/libcompiler_builtins/compiler-rt/lib/asan/weak_symbols.txt similarity index 100% rename from src/compiler-rt/lib/asan/weak_symbols.txt rename to src/libcompiler_builtins/compiler-rt/lib/asan/weak_symbols.txt diff --git a/src/compiler-rt/lib/builtins/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/builtins/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/builtins/CMakeLists.txt diff --git a/src/compiler-rt/lib/builtins/Darwin-excludes/10.4.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/10.4.txt similarity index 100% rename from src/compiler-rt/lib/builtins/Darwin-excludes/10.4.txt rename to src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/10.4.txt diff --git a/src/compiler-rt/lib/builtins/Darwin-excludes/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/builtins/Darwin-excludes/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/CMakeLists.txt diff --git a/src/compiler-rt/lib/builtins/Darwin-excludes/README.TXT b/src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/README.TXT similarity index 100% rename from src/compiler-rt/lib/builtins/Darwin-excludes/README.TXT rename to src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/README.TXT diff --git a/src/compiler-rt/lib/builtins/Darwin-excludes/ios-armv7.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/ios-armv7.txt similarity index 100% rename from src/compiler-rt/lib/builtins/Darwin-excludes/ios-armv7.txt rename to src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/ios-armv7.txt diff --git a/src/compiler-rt/lib/builtins/Darwin-excludes/ios-armv7s.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/ios-armv7s.txt similarity index 100% rename from src/compiler-rt/lib/builtins/Darwin-excludes/ios-armv7s.txt rename to src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/ios-armv7s.txt diff --git a/src/compiler-rt/lib/builtins/Darwin-excludes/ios.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/ios.txt similarity index 100% rename from src/compiler-rt/lib/builtins/Darwin-excludes/ios.txt rename to src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/ios.txt diff --git a/src/compiler-rt/lib/builtins/Darwin-excludes/ios6-armv7.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/ios6-armv7.txt similarity index 100% rename from src/compiler-rt/lib/builtins/Darwin-excludes/ios6-armv7.txt rename to src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/ios6-armv7.txt diff --git a/src/compiler-rt/lib/builtins/Darwin-excludes/ios6-armv7s.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/ios6-armv7s.txt similarity index 100% rename from src/compiler-rt/lib/builtins/Darwin-excludes/ios6-armv7s.txt rename to src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/ios6-armv7s.txt diff --git a/src/compiler-rt/lib/builtins/Darwin-excludes/ios7-arm64.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/ios7-arm64.txt similarity index 100% rename from src/compiler-rt/lib/builtins/Darwin-excludes/ios7-arm64.txt rename to src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/ios7-arm64.txt diff --git a/src/compiler-rt/lib/builtins/Darwin-excludes/iossim-i386.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/iossim-i386.txt similarity index 100% rename from src/compiler-rt/lib/builtins/Darwin-excludes/iossim-i386.txt rename to src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/iossim-i386.txt diff --git a/src/compiler-rt/lib/builtins/Darwin-excludes/iossim-x86_64.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/iossim-x86_64.txt similarity index 100% rename from src/compiler-rt/lib/builtins/Darwin-excludes/iossim-x86_64.txt rename to src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/iossim-x86_64.txt diff --git a/src/compiler-rt/lib/builtins/Darwin-excludes/iossim.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/iossim.txt similarity index 100% rename from src/compiler-rt/lib/builtins/Darwin-excludes/iossim.txt rename to src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/iossim.txt diff --git a/src/compiler-rt/lib/builtins/Darwin-excludes/osx-i386.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/osx-i386.txt similarity index 100% rename from src/compiler-rt/lib/builtins/Darwin-excludes/osx-i386.txt rename to src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/osx-i386.txt diff --git a/src/compiler-rt/lib/builtins/Darwin-excludes/osx.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/osx.txt similarity index 100% rename from src/compiler-rt/lib/builtins/Darwin-excludes/osx.txt rename to src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/osx.txt diff --git a/src/compiler-rt/lib/builtins/README.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/README.txt similarity index 100% rename from src/compiler-rt/lib/builtins/README.txt rename to src/libcompiler_builtins/compiler-rt/lib/builtins/README.txt diff --git a/src/compiler-rt/lib/builtins/absvdi2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/absvdi2.c similarity index 100% rename from src/compiler-rt/lib/builtins/absvdi2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/absvdi2.c diff --git a/src/compiler-rt/lib/builtins/absvsi2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/absvsi2.c similarity index 100% rename from src/compiler-rt/lib/builtins/absvsi2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/absvsi2.c diff --git a/src/compiler-rt/lib/builtins/absvti2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/absvti2.c similarity index 100% rename from src/compiler-rt/lib/builtins/absvti2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/absvti2.c diff --git a/src/compiler-rt/lib/builtins/adddf3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/adddf3.c similarity index 100% rename from src/compiler-rt/lib/builtins/adddf3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/adddf3.c diff --git a/src/compiler-rt/lib/builtins/addsf3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/addsf3.c similarity index 100% rename from src/compiler-rt/lib/builtins/addsf3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/addsf3.c diff --git a/src/compiler-rt/lib/builtins/addtf3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/addtf3.c similarity index 100% rename from src/compiler-rt/lib/builtins/addtf3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/addtf3.c diff --git a/src/compiler-rt/lib/builtins/addvdi3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/addvdi3.c similarity index 100% rename from src/compiler-rt/lib/builtins/addvdi3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/addvdi3.c diff --git a/src/compiler-rt/lib/builtins/addvsi3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/addvsi3.c similarity index 100% rename from src/compiler-rt/lib/builtins/addvsi3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/addvsi3.c diff --git a/src/compiler-rt/lib/builtins/addvti3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/addvti3.c similarity index 100% rename from src/compiler-rt/lib/builtins/addvti3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/addvti3.c diff --git a/src/compiler-rt/lib/builtins/apple_versioning.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/apple_versioning.c similarity index 100% rename from src/compiler-rt/lib/builtins/apple_versioning.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/apple_versioning.c diff --git a/src/compiler-rt/lib/builtins/arm/adddf3vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/adddf3vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/adddf3vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/adddf3vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/addsf3vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/addsf3vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/addsf3vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/addsf3vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_cdcmp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_cdcmp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/aeabi_cdcmp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_cdcmp.S diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_cdcmpeq_check_nan.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_cdcmpeq_check_nan.c similarity index 100% rename from src/compiler-rt/lib/builtins/arm/aeabi_cdcmpeq_check_nan.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_cdcmpeq_check_nan.c diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_cfcmp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_cfcmp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/aeabi_cfcmp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_cfcmp.S diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_cfcmpeq_check_nan.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_cfcmpeq_check_nan.c similarity index 100% rename from src/compiler-rt/lib/builtins/arm/aeabi_cfcmpeq_check_nan.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_cfcmpeq_check_nan.c diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_dcmp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_dcmp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/aeabi_dcmp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_dcmp.S diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_div0.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_div0.c similarity index 100% rename from src/compiler-rt/lib/builtins/arm/aeabi_div0.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_div0.c diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_drsub.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_drsub.c similarity index 100% rename from src/compiler-rt/lib/builtins/arm/aeabi_drsub.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_drsub.c diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_fcmp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_fcmp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/aeabi_fcmp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_fcmp.S diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_frsub.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_frsub.c similarity index 100% rename from src/compiler-rt/lib/builtins/arm/aeabi_frsub.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_frsub.c diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_idivmod.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_idivmod.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/aeabi_idivmod.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_idivmod.S diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_ldivmod.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_ldivmod.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/aeabi_ldivmod.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_ldivmod.S diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_memcmp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_memcmp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/aeabi_memcmp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_memcmp.S diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_memcpy.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_memcpy.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/aeabi_memcpy.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_memcpy.S diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_memmove.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_memmove.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/aeabi_memmove.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_memmove.S diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_memset.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_memset.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/aeabi_memset.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_memset.S diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_uidivmod.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_uidivmod.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/aeabi_uidivmod.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_uidivmod.S diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_uldivmod.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_uldivmod.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/aeabi_uldivmod.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/aeabi_uldivmod.S diff --git a/src/compiler-rt/lib/builtins/arm/bswapdi2.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/bswapdi2.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/bswapdi2.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/bswapdi2.S diff --git a/src/compiler-rt/lib/builtins/arm/bswapsi2.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/bswapsi2.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/bswapsi2.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/bswapsi2.S diff --git a/src/compiler-rt/lib/builtins/arm/clzdi2.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/clzdi2.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/clzdi2.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/clzdi2.S diff --git a/src/compiler-rt/lib/builtins/arm/clzsi2.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/clzsi2.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/clzsi2.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/clzsi2.S diff --git a/src/compiler-rt/lib/builtins/arm/comparesf2.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/comparesf2.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/comparesf2.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/comparesf2.S diff --git a/src/compiler-rt/lib/builtins/arm/divdf3vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/divdf3vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/divdf3vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/divdf3vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/divmodsi4.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/divmodsi4.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/divmodsi4.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/divmodsi4.S diff --git a/src/compiler-rt/lib/builtins/arm/divsf3vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/divsf3vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/divsf3vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/divsf3vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/divsi3.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/divsi3.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/divsi3.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/divsi3.S diff --git a/src/compiler-rt/lib/builtins/arm/eqdf2vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/eqdf2vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/eqdf2vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/eqdf2vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/eqsf2vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/eqsf2vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/eqsf2vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/eqsf2vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/extendsfdf2vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/extendsfdf2vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/extendsfdf2vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/extendsfdf2vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/fixdfsivfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/fixdfsivfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/fixdfsivfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/fixdfsivfp.S diff --git a/src/compiler-rt/lib/builtins/arm/fixsfsivfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/fixsfsivfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/fixsfsivfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/fixsfsivfp.S diff --git a/src/compiler-rt/lib/builtins/arm/fixunsdfsivfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/fixunsdfsivfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/fixunsdfsivfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/fixunsdfsivfp.S diff --git a/src/compiler-rt/lib/builtins/arm/fixunssfsivfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/fixunssfsivfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/fixunssfsivfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/fixunssfsivfp.S diff --git a/src/compiler-rt/lib/builtins/arm/floatsidfvfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/floatsidfvfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/floatsidfvfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/floatsidfvfp.S diff --git a/src/compiler-rt/lib/builtins/arm/floatsisfvfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/floatsisfvfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/floatsisfvfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/floatsisfvfp.S diff --git a/src/compiler-rt/lib/builtins/arm/floatunssidfvfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/floatunssidfvfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/floatunssidfvfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/floatunssidfvfp.S diff --git a/src/compiler-rt/lib/builtins/arm/floatunssisfvfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/floatunssisfvfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/floatunssisfvfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/floatunssisfvfp.S diff --git a/src/compiler-rt/lib/builtins/arm/gedf2vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/gedf2vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/gedf2vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/gedf2vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/gesf2vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/gesf2vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/gesf2vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/gesf2vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/gtdf2vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/gtdf2vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/gtdf2vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/gtdf2vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/gtsf2vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/gtsf2vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/gtsf2vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/gtsf2vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/ledf2vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/ledf2vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/ledf2vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/ledf2vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/lesf2vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/lesf2vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/lesf2vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/lesf2vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/ltdf2vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/ltdf2vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/ltdf2vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/ltdf2vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/ltsf2vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/ltsf2vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/ltsf2vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/ltsf2vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/modsi3.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/modsi3.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/modsi3.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/modsi3.S diff --git a/src/compiler-rt/lib/builtins/arm/muldf3vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/muldf3vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/muldf3vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/muldf3vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/mulsf3vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/mulsf3vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/mulsf3vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/mulsf3vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/nedf2vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/nedf2vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/nedf2vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/nedf2vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/negdf2vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/negdf2vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/negdf2vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/negdf2vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/negsf2vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/negsf2vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/negsf2vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/negsf2vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/nesf2vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/nesf2vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/nesf2vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/nesf2vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/restore_vfp_d8_d15_regs.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/restore_vfp_d8_d15_regs.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/restore_vfp_d8_d15_regs.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/restore_vfp_d8_d15_regs.S diff --git a/src/compiler-rt/lib/builtins/arm/save_vfp_d8_d15_regs.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/save_vfp_d8_d15_regs.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/save_vfp_d8_d15_regs.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/save_vfp_d8_d15_regs.S diff --git a/src/compiler-rt/lib/builtins/arm/softfloat-alias.list b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/softfloat-alias.list similarity index 100% rename from src/compiler-rt/lib/builtins/arm/softfloat-alias.list rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/softfloat-alias.list diff --git a/src/compiler-rt/lib/builtins/arm/subdf3vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/subdf3vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/subdf3vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/subdf3vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/subsf3vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/subsf3vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/subsf3vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/subsf3vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/switch16.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/switch16.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/switch16.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/switch16.S diff --git a/src/compiler-rt/lib/builtins/arm/switch32.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/switch32.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/switch32.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/switch32.S diff --git a/src/compiler-rt/lib/builtins/arm/switch8.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/switch8.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/switch8.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/switch8.S diff --git a/src/compiler-rt/lib/builtins/arm/switchu8.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/switchu8.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/switchu8.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/switchu8.S diff --git a/src/compiler-rt/lib/builtins/arm/sync-ops.h b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync-ops.h similarity index 100% rename from src/compiler-rt/lib/builtins/arm/sync-ops.h rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync-ops.h diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_add_4.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_add_4.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/sync_fetch_and_add_4.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_add_4.S diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_add_8.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_add_8.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/sync_fetch_and_add_8.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_add_8.S diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_and_4.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_and_4.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/sync_fetch_and_and_4.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_and_4.S diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_and_8.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_and_8.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/sync_fetch_and_and_8.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_and_8.S diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_max_4.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_max_4.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/sync_fetch_and_max_4.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_max_4.S diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_max_8.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_max_8.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/sync_fetch_and_max_8.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_max_8.S diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_min_4.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_min_4.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/sync_fetch_and_min_4.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_min_4.S diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_min_8.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_min_8.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/sync_fetch_and_min_8.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_min_8.S diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_4.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_4.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_4.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_4.S diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_8.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_8.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_8.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_8.S diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_or_4.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_or_4.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/sync_fetch_and_or_4.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_or_4.S diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_or_8.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_or_8.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/sync_fetch_and_or_8.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_or_8.S diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_4.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_4.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_4.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_4.S diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_8.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_8.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_8.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_8.S diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_4.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_4.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_4.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_4.S diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_8.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_8.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_8.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_8.S diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_4.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_4.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_4.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_4.S diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_8.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_8.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_8.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_8.S diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_4.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_4.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_4.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_4.S diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_8.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_8.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_8.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_8.S diff --git a/src/compiler-rt/lib/builtins/arm/sync_synchronize.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_synchronize.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/sync_synchronize.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/sync_synchronize.S diff --git a/src/compiler-rt/lib/builtins/arm/truncdfsf2vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/truncdfsf2vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/truncdfsf2vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/truncdfsf2vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/udivmodsi4.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/udivmodsi4.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/udivmodsi4.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/udivmodsi4.S diff --git a/src/compiler-rt/lib/builtins/arm/udivsi3.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/udivsi3.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/udivsi3.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/udivsi3.S diff --git a/src/compiler-rt/lib/builtins/arm/umodsi3.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/umodsi3.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/umodsi3.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/umodsi3.S diff --git a/src/compiler-rt/lib/builtins/arm/unorddf2vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/unorddf2vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/unorddf2vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/unorddf2vfp.S diff --git a/src/compiler-rt/lib/builtins/arm/unordsf2vfp.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/unordsf2vfp.S similarity index 100% rename from src/compiler-rt/lib/builtins/arm/unordsf2vfp.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/arm/unordsf2vfp.S diff --git a/src/compiler-rt/lib/builtins/ashldi3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/ashldi3.c similarity index 100% rename from src/compiler-rt/lib/builtins/ashldi3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ashldi3.c diff --git a/src/compiler-rt/lib/builtins/ashlti3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/ashlti3.c similarity index 100% rename from src/compiler-rt/lib/builtins/ashlti3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ashlti3.c diff --git a/src/compiler-rt/lib/builtins/ashrdi3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/ashrdi3.c similarity index 100% rename from src/compiler-rt/lib/builtins/ashrdi3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ashrdi3.c diff --git a/src/compiler-rt/lib/builtins/ashrti3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/ashrti3.c similarity index 100% rename from src/compiler-rt/lib/builtins/ashrti3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ashrti3.c diff --git a/src/compiler-rt/lib/builtins/assembly.h b/src/libcompiler_builtins/compiler-rt/lib/builtins/assembly.h similarity index 100% rename from src/compiler-rt/lib/builtins/assembly.h rename to src/libcompiler_builtins/compiler-rt/lib/builtins/assembly.h diff --git a/src/compiler-rt/lib/builtins/atomic.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/atomic.c similarity index 100% rename from src/compiler-rt/lib/builtins/atomic.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/atomic.c diff --git a/src/compiler-rt/lib/builtins/atomic_flag_clear.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/atomic_flag_clear.c similarity index 100% rename from src/compiler-rt/lib/builtins/atomic_flag_clear.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/atomic_flag_clear.c diff --git a/src/compiler-rt/lib/builtins/atomic_flag_clear_explicit.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/atomic_flag_clear_explicit.c similarity index 100% rename from src/compiler-rt/lib/builtins/atomic_flag_clear_explicit.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/atomic_flag_clear_explicit.c diff --git a/src/compiler-rt/lib/builtins/atomic_flag_test_and_set.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/atomic_flag_test_and_set.c similarity index 100% rename from src/compiler-rt/lib/builtins/atomic_flag_test_and_set.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/atomic_flag_test_and_set.c diff --git a/src/compiler-rt/lib/builtins/atomic_flag_test_and_set_explicit.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/atomic_flag_test_and_set_explicit.c similarity index 100% rename from src/compiler-rt/lib/builtins/atomic_flag_test_and_set_explicit.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/atomic_flag_test_and_set_explicit.c diff --git a/src/compiler-rt/lib/builtins/atomic_signal_fence.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/atomic_signal_fence.c similarity index 100% rename from src/compiler-rt/lib/builtins/atomic_signal_fence.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/atomic_signal_fence.c diff --git a/src/compiler-rt/lib/builtins/atomic_thread_fence.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/atomic_thread_fence.c similarity index 100% rename from src/compiler-rt/lib/builtins/atomic_thread_fence.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/atomic_thread_fence.c diff --git a/src/compiler-rt/lib/builtins/clear_cache.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/clear_cache.c similarity index 100% rename from src/compiler-rt/lib/builtins/clear_cache.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/clear_cache.c diff --git a/src/compiler-rt/lib/builtins/clzdi2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/clzdi2.c similarity index 100% rename from src/compiler-rt/lib/builtins/clzdi2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/clzdi2.c diff --git a/src/compiler-rt/lib/builtins/clzsi2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/clzsi2.c similarity index 100% rename from src/compiler-rt/lib/builtins/clzsi2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/clzsi2.c diff --git a/src/compiler-rt/lib/builtins/clzti2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/clzti2.c similarity index 100% rename from src/compiler-rt/lib/builtins/clzti2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/clzti2.c diff --git a/src/compiler-rt/lib/builtins/cmpdi2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/cmpdi2.c similarity index 100% rename from src/compiler-rt/lib/builtins/cmpdi2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/cmpdi2.c diff --git a/src/compiler-rt/lib/builtins/cmpti2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/cmpti2.c similarity index 100% rename from src/compiler-rt/lib/builtins/cmpti2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/cmpti2.c diff --git a/src/compiler-rt/lib/builtins/comparedf2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/comparedf2.c similarity index 100% rename from src/compiler-rt/lib/builtins/comparedf2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/comparedf2.c diff --git a/src/compiler-rt/lib/builtins/comparesf2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/comparesf2.c similarity index 100% rename from src/compiler-rt/lib/builtins/comparesf2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/comparesf2.c diff --git a/src/compiler-rt/lib/builtins/comparetf2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/comparetf2.c similarity index 100% rename from src/compiler-rt/lib/builtins/comparetf2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/comparetf2.c diff --git a/src/compiler-rt/lib/builtins/cpu_model.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/cpu_model.c similarity index 100% rename from src/compiler-rt/lib/builtins/cpu_model.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/cpu_model.c diff --git a/src/compiler-rt/lib/builtins/ctzdi2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/ctzdi2.c similarity index 100% rename from src/compiler-rt/lib/builtins/ctzdi2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ctzdi2.c diff --git a/src/compiler-rt/lib/builtins/ctzsi2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/ctzsi2.c similarity index 100% rename from src/compiler-rt/lib/builtins/ctzsi2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ctzsi2.c diff --git a/src/compiler-rt/lib/builtins/ctzti2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/ctzti2.c similarity index 100% rename from src/compiler-rt/lib/builtins/ctzti2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ctzti2.c diff --git a/src/compiler-rt/lib/builtins/divdc3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/divdc3.c similarity index 100% rename from src/compiler-rt/lib/builtins/divdc3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/divdc3.c diff --git a/src/compiler-rt/lib/builtins/divdf3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/divdf3.c similarity index 100% rename from src/compiler-rt/lib/builtins/divdf3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/divdf3.c diff --git a/src/compiler-rt/lib/builtins/divdi3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/divdi3.c similarity index 100% rename from src/compiler-rt/lib/builtins/divdi3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/divdi3.c diff --git a/src/compiler-rt/lib/builtins/divmoddi4.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/divmoddi4.c similarity index 100% rename from src/compiler-rt/lib/builtins/divmoddi4.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/divmoddi4.c diff --git a/src/compiler-rt/lib/builtins/divmodsi4.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/divmodsi4.c similarity index 100% rename from src/compiler-rt/lib/builtins/divmodsi4.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/divmodsi4.c diff --git a/src/compiler-rt/lib/builtins/divsc3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/divsc3.c similarity index 100% rename from src/compiler-rt/lib/builtins/divsc3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/divsc3.c diff --git a/src/compiler-rt/lib/builtins/divsf3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/divsf3.c similarity index 100% rename from src/compiler-rt/lib/builtins/divsf3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/divsf3.c diff --git a/src/compiler-rt/lib/builtins/divsi3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/divsi3.c similarity index 100% rename from src/compiler-rt/lib/builtins/divsi3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/divsi3.c diff --git a/src/compiler-rt/lib/builtins/divtc3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/divtc3.c similarity index 100% rename from src/compiler-rt/lib/builtins/divtc3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/divtc3.c diff --git a/src/compiler-rt/lib/builtins/divtf3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/divtf3.c similarity index 100% rename from src/compiler-rt/lib/builtins/divtf3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/divtf3.c diff --git a/src/compiler-rt/lib/builtins/divti3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/divti3.c similarity index 100% rename from src/compiler-rt/lib/builtins/divti3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/divti3.c diff --git a/src/compiler-rt/lib/builtins/divxc3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/divxc3.c similarity index 100% rename from src/compiler-rt/lib/builtins/divxc3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/divxc3.c diff --git a/src/compiler-rt/lib/builtins/emutls.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/emutls.c similarity index 100% rename from src/compiler-rt/lib/builtins/emutls.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/emutls.c diff --git a/src/compiler-rt/lib/builtins/enable_execute_stack.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/enable_execute_stack.c similarity index 100% rename from src/compiler-rt/lib/builtins/enable_execute_stack.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/enable_execute_stack.c diff --git a/src/compiler-rt/lib/builtins/eprintf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/eprintf.c similarity index 100% rename from src/compiler-rt/lib/builtins/eprintf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/eprintf.c diff --git a/src/compiler-rt/lib/builtins/extenddftf2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/extenddftf2.c similarity index 100% rename from src/compiler-rt/lib/builtins/extenddftf2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/extenddftf2.c diff --git a/src/compiler-rt/lib/builtins/extendhfsf2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/extendhfsf2.c similarity index 100% rename from src/compiler-rt/lib/builtins/extendhfsf2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/extendhfsf2.c diff --git a/src/compiler-rt/lib/builtins/extendsfdf2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/extendsfdf2.c similarity index 100% rename from src/compiler-rt/lib/builtins/extendsfdf2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/extendsfdf2.c diff --git a/src/compiler-rt/lib/builtins/extendsftf2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/extendsftf2.c similarity index 100% rename from src/compiler-rt/lib/builtins/extendsftf2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/extendsftf2.c diff --git a/src/compiler-rt/lib/builtins/ffsdi2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/ffsdi2.c similarity index 100% rename from src/compiler-rt/lib/builtins/ffsdi2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ffsdi2.c diff --git a/src/compiler-rt/lib/builtins/ffsti2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/ffsti2.c similarity index 100% rename from src/compiler-rt/lib/builtins/ffsti2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ffsti2.c diff --git a/src/compiler-rt/lib/builtins/fixdfdi.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixdfdi.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixdfdi.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixdfdi.c diff --git a/src/compiler-rt/lib/builtins/fixdfsi.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixdfsi.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixdfsi.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixdfsi.c diff --git a/src/compiler-rt/lib/builtins/fixdfti.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixdfti.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixdfti.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixdfti.c diff --git a/src/compiler-rt/lib/builtins/fixsfdi.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixsfdi.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixsfdi.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixsfdi.c diff --git a/src/compiler-rt/lib/builtins/fixsfsi.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixsfsi.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixsfsi.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixsfsi.c diff --git a/src/compiler-rt/lib/builtins/fixsfti.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixsfti.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixsfti.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixsfti.c diff --git a/src/compiler-rt/lib/builtins/fixtfdi.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixtfdi.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixtfdi.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixtfdi.c diff --git a/src/compiler-rt/lib/builtins/fixtfsi.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixtfsi.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixtfsi.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixtfsi.c diff --git a/src/compiler-rt/lib/builtins/fixtfti.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixtfti.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixtfti.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixtfti.c diff --git a/src/compiler-rt/lib/builtins/fixunsdfdi.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixunsdfdi.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixunsdfdi.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixunsdfdi.c diff --git a/src/compiler-rt/lib/builtins/fixunsdfsi.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixunsdfsi.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixunsdfsi.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixunsdfsi.c diff --git a/src/compiler-rt/lib/builtins/fixunsdfti.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixunsdfti.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixunsdfti.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixunsdfti.c diff --git a/src/compiler-rt/lib/builtins/fixunssfdi.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixunssfdi.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixunssfdi.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixunssfdi.c diff --git a/src/compiler-rt/lib/builtins/fixunssfsi.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixunssfsi.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixunssfsi.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixunssfsi.c diff --git a/src/compiler-rt/lib/builtins/fixunssfti.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixunssfti.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixunssfti.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixunssfti.c diff --git a/src/compiler-rt/lib/builtins/fixunstfdi.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixunstfdi.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixunstfdi.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixunstfdi.c diff --git a/src/compiler-rt/lib/builtins/fixunstfsi.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixunstfsi.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixunstfsi.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixunstfsi.c diff --git a/src/compiler-rt/lib/builtins/fixunstfti.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixunstfti.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixunstfti.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixunstfti.c diff --git a/src/compiler-rt/lib/builtins/fixunsxfdi.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixunsxfdi.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixunsxfdi.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixunsxfdi.c diff --git a/src/compiler-rt/lib/builtins/fixunsxfsi.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixunsxfsi.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixunsxfsi.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixunsxfsi.c diff --git a/src/compiler-rt/lib/builtins/fixunsxfti.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixunsxfti.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixunsxfti.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixunsxfti.c diff --git a/src/compiler-rt/lib/builtins/fixxfdi.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixxfdi.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixxfdi.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixxfdi.c diff --git a/src/compiler-rt/lib/builtins/fixxfti.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/fixxfti.c similarity index 100% rename from src/compiler-rt/lib/builtins/fixxfti.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fixxfti.c diff --git a/src/compiler-rt/lib/builtins/floatdidf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/floatdidf.c similarity index 100% rename from src/compiler-rt/lib/builtins/floatdidf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/floatdidf.c diff --git a/src/compiler-rt/lib/builtins/floatdisf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/floatdisf.c similarity index 100% rename from src/compiler-rt/lib/builtins/floatdisf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/floatdisf.c diff --git a/src/compiler-rt/lib/builtins/floatditf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/floatditf.c similarity index 100% rename from src/compiler-rt/lib/builtins/floatditf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/floatditf.c diff --git a/src/compiler-rt/lib/builtins/floatdixf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/floatdixf.c similarity index 100% rename from src/compiler-rt/lib/builtins/floatdixf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/floatdixf.c diff --git a/src/compiler-rt/lib/builtins/floatsidf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/floatsidf.c similarity index 100% rename from src/compiler-rt/lib/builtins/floatsidf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/floatsidf.c diff --git a/src/compiler-rt/lib/builtins/floatsisf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/floatsisf.c similarity index 100% rename from src/compiler-rt/lib/builtins/floatsisf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/floatsisf.c diff --git a/src/compiler-rt/lib/builtins/floatsitf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/floatsitf.c similarity index 100% rename from src/compiler-rt/lib/builtins/floatsitf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/floatsitf.c diff --git a/src/compiler-rt/lib/builtins/floattidf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/floattidf.c similarity index 100% rename from src/compiler-rt/lib/builtins/floattidf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/floattidf.c diff --git a/src/compiler-rt/lib/builtins/floattisf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/floattisf.c similarity index 100% rename from src/compiler-rt/lib/builtins/floattisf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/floattisf.c diff --git a/src/compiler-rt/lib/builtins/floattitf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/floattitf.c similarity index 100% rename from src/compiler-rt/lib/builtins/floattitf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/floattitf.c diff --git a/src/compiler-rt/lib/builtins/floattixf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/floattixf.c similarity index 100% rename from src/compiler-rt/lib/builtins/floattixf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/floattixf.c diff --git a/src/compiler-rt/lib/builtins/floatundidf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/floatundidf.c similarity index 100% rename from src/compiler-rt/lib/builtins/floatundidf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/floatundidf.c diff --git a/src/compiler-rt/lib/builtins/floatundisf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/floatundisf.c similarity index 100% rename from src/compiler-rt/lib/builtins/floatundisf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/floatundisf.c diff --git a/src/compiler-rt/lib/builtins/floatunditf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/floatunditf.c similarity index 100% rename from src/compiler-rt/lib/builtins/floatunditf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/floatunditf.c diff --git a/src/compiler-rt/lib/builtins/floatundixf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/floatundixf.c similarity index 100% rename from src/compiler-rt/lib/builtins/floatundixf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/floatundixf.c diff --git a/src/compiler-rt/lib/builtins/floatunsidf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/floatunsidf.c similarity index 100% rename from src/compiler-rt/lib/builtins/floatunsidf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/floatunsidf.c diff --git a/src/compiler-rt/lib/builtins/floatunsisf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/floatunsisf.c similarity index 100% rename from src/compiler-rt/lib/builtins/floatunsisf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/floatunsisf.c diff --git a/src/compiler-rt/lib/builtins/floatunsitf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/floatunsitf.c similarity index 100% rename from src/compiler-rt/lib/builtins/floatunsitf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/floatunsitf.c diff --git a/src/compiler-rt/lib/builtins/floatuntidf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/floatuntidf.c similarity index 100% rename from src/compiler-rt/lib/builtins/floatuntidf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/floatuntidf.c diff --git a/src/compiler-rt/lib/builtins/floatuntisf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/floatuntisf.c similarity index 100% rename from src/compiler-rt/lib/builtins/floatuntisf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/floatuntisf.c diff --git a/src/compiler-rt/lib/builtins/floatuntitf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/floatuntitf.c similarity index 100% rename from src/compiler-rt/lib/builtins/floatuntitf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/floatuntitf.c diff --git a/src/compiler-rt/lib/builtins/floatuntixf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/floatuntixf.c similarity index 100% rename from src/compiler-rt/lib/builtins/floatuntixf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/floatuntixf.c diff --git a/src/compiler-rt/lib/builtins/fp_add_impl.inc b/src/libcompiler_builtins/compiler-rt/lib/builtins/fp_add_impl.inc similarity index 100% rename from src/compiler-rt/lib/builtins/fp_add_impl.inc rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fp_add_impl.inc diff --git a/src/compiler-rt/lib/builtins/fp_extend.h b/src/libcompiler_builtins/compiler-rt/lib/builtins/fp_extend.h similarity index 100% rename from src/compiler-rt/lib/builtins/fp_extend.h rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fp_extend.h diff --git a/src/compiler-rt/lib/builtins/fp_extend_impl.inc b/src/libcompiler_builtins/compiler-rt/lib/builtins/fp_extend_impl.inc similarity index 100% rename from src/compiler-rt/lib/builtins/fp_extend_impl.inc rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fp_extend_impl.inc diff --git a/src/compiler-rt/lib/builtins/fp_fixint_impl.inc b/src/libcompiler_builtins/compiler-rt/lib/builtins/fp_fixint_impl.inc similarity index 100% rename from src/compiler-rt/lib/builtins/fp_fixint_impl.inc rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fp_fixint_impl.inc diff --git a/src/compiler-rt/lib/builtins/fp_fixuint_impl.inc b/src/libcompiler_builtins/compiler-rt/lib/builtins/fp_fixuint_impl.inc similarity index 100% rename from src/compiler-rt/lib/builtins/fp_fixuint_impl.inc rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fp_fixuint_impl.inc diff --git a/src/compiler-rt/lib/builtins/fp_lib.h b/src/libcompiler_builtins/compiler-rt/lib/builtins/fp_lib.h similarity index 100% rename from src/compiler-rt/lib/builtins/fp_lib.h rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fp_lib.h diff --git a/src/compiler-rt/lib/builtins/fp_mul_impl.inc b/src/libcompiler_builtins/compiler-rt/lib/builtins/fp_mul_impl.inc similarity index 100% rename from src/compiler-rt/lib/builtins/fp_mul_impl.inc rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fp_mul_impl.inc diff --git a/src/compiler-rt/lib/builtins/fp_trunc.h b/src/libcompiler_builtins/compiler-rt/lib/builtins/fp_trunc.h similarity index 100% rename from src/compiler-rt/lib/builtins/fp_trunc.h rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fp_trunc.h diff --git a/src/compiler-rt/lib/builtins/fp_trunc_impl.inc b/src/libcompiler_builtins/compiler-rt/lib/builtins/fp_trunc_impl.inc similarity index 100% rename from src/compiler-rt/lib/builtins/fp_trunc_impl.inc rename to src/libcompiler_builtins/compiler-rt/lib/builtins/fp_trunc_impl.inc diff --git a/src/compiler-rt/lib/builtins/gcc_personality_v0.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/gcc_personality_v0.c similarity index 100% rename from src/compiler-rt/lib/builtins/gcc_personality_v0.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/gcc_personality_v0.c diff --git a/src/compiler-rt/lib/builtins/i386/ashldi3.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/i386/ashldi3.S similarity index 100% rename from src/compiler-rt/lib/builtins/i386/ashldi3.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/i386/ashldi3.S diff --git a/src/compiler-rt/lib/builtins/i386/ashrdi3.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/i386/ashrdi3.S similarity index 100% rename from src/compiler-rt/lib/builtins/i386/ashrdi3.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/i386/ashrdi3.S diff --git a/src/compiler-rt/lib/builtins/i386/chkstk.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/i386/chkstk.S similarity index 100% rename from src/compiler-rt/lib/builtins/i386/chkstk.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/i386/chkstk.S diff --git a/src/compiler-rt/lib/builtins/i386/chkstk2.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/i386/chkstk2.S similarity index 100% rename from src/compiler-rt/lib/builtins/i386/chkstk2.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/i386/chkstk2.S diff --git a/src/compiler-rt/lib/builtins/i386/divdi3.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/i386/divdi3.S similarity index 100% rename from src/compiler-rt/lib/builtins/i386/divdi3.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/i386/divdi3.S diff --git a/src/compiler-rt/lib/builtins/i386/floatdidf.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/i386/floatdidf.S similarity index 100% rename from src/compiler-rt/lib/builtins/i386/floatdidf.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/i386/floatdidf.S diff --git a/src/compiler-rt/lib/builtins/i386/floatdisf.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/i386/floatdisf.S similarity index 100% rename from src/compiler-rt/lib/builtins/i386/floatdisf.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/i386/floatdisf.S diff --git a/src/compiler-rt/lib/builtins/i386/floatdixf.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/i386/floatdixf.S similarity index 100% rename from src/compiler-rt/lib/builtins/i386/floatdixf.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/i386/floatdixf.S diff --git a/src/compiler-rt/lib/builtins/i386/floatundidf.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/i386/floatundidf.S similarity index 100% rename from src/compiler-rt/lib/builtins/i386/floatundidf.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/i386/floatundidf.S diff --git a/src/compiler-rt/lib/builtins/i386/floatundisf.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/i386/floatundisf.S similarity index 100% rename from src/compiler-rt/lib/builtins/i386/floatundisf.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/i386/floatundisf.S diff --git a/src/compiler-rt/lib/builtins/i386/floatundixf.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/i386/floatundixf.S similarity index 100% rename from src/compiler-rt/lib/builtins/i386/floatundixf.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/i386/floatundixf.S diff --git a/src/compiler-rt/lib/builtins/i386/lshrdi3.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/i386/lshrdi3.S similarity index 100% rename from src/compiler-rt/lib/builtins/i386/lshrdi3.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/i386/lshrdi3.S diff --git a/src/compiler-rt/lib/builtins/i386/moddi3.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/i386/moddi3.S similarity index 100% rename from src/compiler-rt/lib/builtins/i386/moddi3.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/i386/moddi3.S diff --git a/src/compiler-rt/lib/builtins/i386/muldi3.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/i386/muldi3.S similarity index 100% rename from src/compiler-rt/lib/builtins/i386/muldi3.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/i386/muldi3.S diff --git a/src/compiler-rt/lib/builtins/i386/udivdi3.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/i386/udivdi3.S similarity index 100% rename from src/compiler-rt/lib/builtins/i386/udivdi3.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/i386/udivdi3.S diff --git a/src/compiler-rt/lib/builtins/i386/umoddi3.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/i386/umoddi3.S similarity index 100% rename from src/compiler-rt/lib/builtins/i386/umoddi3.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/i386/umoddi3.S diff --git a/src/compiler-rt/lib/builtins/int_endianness.h b/src/libcompiler_builtins/compiler-rt/lib/builtins/int_endianness.h similarity index 100% rename from src/compiler-rt/lib/builtins/int_endianness.h rename to src/libcompiler_builtins/compiler-rt/lib/builtins/int_endianness.h diff --git a/src/compiler-rt/lib/builtins/int_lib.h b/src/libcompiler_builtins/compiler-rt/lib/builtins/int_lib.h similarity index 100% rename from src/compiler-rt/lib/builtins/int_lib.h rename to src/libcompiler_builtins/compiler-rt/lib/builtins/int_lib.h diff --git a/src/compiler-rt/lib/builtins/int_math.h b/src/libcompiler_builtins/compiler-rt/lib/builtins/int_math.h similarity index 100% rename from src/compiler-rt/lib/builtins/int_math.h rename to src/libcompiler_builtins/compiler-rt/lib/builtins/int_math.h diff --git a/src/compiler-rt/lib/builtins/int_types.h b/src/libcompiler_builtins/compiler-rt/lib/builtins/int_types.h similarity index 100% rename from src/compiler-rt/lib/builtins/int_types.h rename to src/libcompiler_builtins/compiler-rt/lib/builtins/int_types.h diff --git a/src/compiler-rt/lib/builtins/int_util.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/int_util.c similarity index 100% rename from src/compiler-rt/lib/builtins/int_util.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/int_util.c diff --git a/src/compiler-rt/lib/builtins/int_util.h b/src/libcompiler_builtins/compiler-rt/lib/builtins/int_util.h similarity index 100% rename from src/compiler-rt/lib/builtins/int_util.h rename to src/libcompiler_builtins/compiler-rt/lib/builtins/int_util.h diff --git a/src/compiler-rt/lib/builtins/lshrdi3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/lshrdi3.c similarity index 100% rename from src/compiler-rt/lib/builtins/lshrdi3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/lshrdi3.c diff --git a/src/compiler-rt/lib/builtins/lshrti3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/lshrti3.c similarity index 100% rename from src/compiler-rt/lib/builtins/lshrti3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/lshrti3.c diff --git a/src/compiler-rt/lib/builtins/macho_embedded/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/macho_embedded/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/builtins/macho_embedded/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/builtins/macho_embedded/CMakeLists.txt diff --git a/src/compiler-rt/lib/builtins/macho_embedded/arm.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/macho_embedded/arm.txt similarity index 100% rename from src/compiler-rt/lib/builtins/macho_embedded/arm.txt rename to src/libcompiler_builtins/compiler-rt/lib/builtins/macho_embedded/arm.txt diff --git a/src/compiler-rt/lib/builtins/macho_embedded/common.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/macho_embedded/common.txt similarity index 100% rename from src/compiler-rt/lib/builtins/macho_embedded/common.txt rename to src/libcompiler_builtins/compiler-rt/lib/builtins/macho_embedded/common.txt diff --git a/src/compiler-rt/lib/builtins/macho_embedded/i386.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/macho_embedded/i386.txt similarity index 100% rename from src/compiler-rt/lib/builtins/macho_embedded/i386.txt rename to src/libcompiler_builtins/compiler-rt/lib/builtins/macho_embedded/i386.txt diff --git a/src/compiler-rt/lib/builtins/macho_embedded/thumb2-64.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/macho_embedded/thumb2-64.txt similarity index 100% rename from src/compiler-rt/lib/builtins/macho_embedded/thumb2-64.txt rename to src/libcompiler_builtins/compiler-rt/lib/builtins/macho_embedded/thumb2-64.txt diff --git a/src/compiler-rt/lib/builtins/macho_embedded/thumb2.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/macho_embedded/thumb2.txt similarity index 100% rename from src/compiler-rt/lib/builtins/macho_embedded/thumb2.txt rename to src/libcompiler_builtins/compiler-rt/lib/builtins/macho_embedded/thumb2.txt diff --git a/src/compiler-rt/lib/builtins/mingw_fixfloat.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/mingw_fixfloat.c similarity index 100% rename from src/compiler-rt/lib/builtins/mingw_fixfloat.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/mingw_fixfloat.c diff --git a/src/compiler-rt/lib/builtins/moddi3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/moddi3.c similarity index 100% rename from src/compiler-rt/lib/builtins/moddi3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/moddi3.c diff --git a/src/compiler-rt/lib/builtins/modsi3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/modsi3.c similarity index 100% rename from src/compiler-rt/lib/builtins/modsi3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/modsi3.c diff --git a/src/compiler-rt/lib/builtins/modti3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/modti3.c similarity index 100% rename from src/compiler-rt/lib/builtins/modti3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/modti3.c diff --git a/src/compiler-rt/lib/builtins/muldc3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/muldc3.c similarity index 100% rename from src/compiler-rt/lib/builtins/muldc3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/muldc3.c diff --git a/src/compiler-rt/lib/builtins/muldf3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/muldf3.c similarity index 100% rename from src/compiler-rt/lib/builtins/muldf3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/muldf3.c diff --git a/src/compiler-rt/lib/builtins/muldi3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/muldi3.c similarity index 100% rename from src/compiler-rt/lib/builtins/muldi3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/muldi3.c diff --git a/src/compiler-rt/lib/builtins/mulodi4.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/mulodi4.c similarity index 100% rename from src/compiler-rt/lib/builtins/mulodi4.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/mulodi4.c diff --git a/src/compiler-rt/lib/builtins/mulosi4.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/mulosi4.c similarity index 100% rename from src/compiler-rt/lib/builtins/mulosi4.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/mulosi4.c diff --git a/src/compiler-rt/lib/builtins/muloti4.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/muloti4.c similarity index 100% rename from src/compiler-rt/lib/builtins/muloti4.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/muloti4.c diff --git a/src/compiler-rt/lib/builtins/mulsc3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/mulsc3.c similarity index 100% rename from src/compiler-rt/lib/builtins/mulsc3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/mulsc3.c diff --git a/src/compiler-rt/lib/builtins/mulsf3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/mulsf3.c similarity index 100% rename from src/compiler-rt/lib/builtins/mulsf3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/mulsf3.c diff --git a/src/compiler-rt/lib/builtins/multc3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/multc3.c similarity index 100% rename from src/compiler-rt/lib/builtins/multc3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/multc3.c diff --git a/src/compiler-rt/lib/builtins/multf3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/multf3.c similarity index 100% rename from src/compiler-rt/lib/builtins/multf3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/multf3.c diff --git a/src/compiler-rt/lib/builtins/multi3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/multi3.c similarity index 100% rename from src/compiler-rt/lib/builtins/multi3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/multi3.c diff --git a/src/compiler-rt/lib/builtins/mulvdi3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/mulvdi3.c similarity index 100% rename from src/compiler-rt/lib/builtins/mulvdi3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/mulvdi3.c diff --git a/src/compiler-rt/lib/builtins/mulvsi3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/mulvsi3.c similarity index 100% rename from src/compiler-rt/lib/builtins/mulvsi3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/mulvsi3.c diff --git a/src/compiler-rt/lib/builtins/mulvti3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/mulvti3.c similarity index 100% rename from src/compiler-rt/lib/builtins/mulvti3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/mulvti3.c diff --git a/src/compiler-rt/lib/builtins/mulxc3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/mulxc3.c similarity index 100% rename from src/compiler-rt/lib/builtins/mulxc3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/mulxc3.c diff --git a/src/compiler-rt/lib/builtins/negdf2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/negdf2.c similarity index 100% rename from src/compiler-rt/lib/builtins/negdf2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/negdf2.c diff --git a/src/compiler-rt/lib/builtins/negdi2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/negdi2.c similarity index 100% rename from src/compiler-rt/lib/builtins/negdi2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/negdi2.c diff --git a/src/compiler-rt/lib/builtins/negsf2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/negsf2.c similarity index 100% rename from src/compiler-rt/lib/builtins/negsf2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/negsf2.c diff --git a/src/compiler-rt/lib/builtins/negti2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/negti2.c similarity index 100% rename from src/compiler-rt/lib/builtins/negti2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/negti2.c diff --git a/src/compiler-rt/lib/builtins/negvdi2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/negvdi2.c similarity index 100% rename from src/compiler-rt/lib/builtins/negvdi2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/negvdi2.c diff --git a/src/compiler-rt/lib/builtins/negvsi2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/negvsi2.c similarity index 100% rename from src/compiler-rt/lib/builtins/negvsi2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/negvsi2.c diff --git a/src/compiler-rt/lib/builtins/negvti2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/negvti2.c similarity index 100% rename from src/compiler-rt/lib/builtins/negvti2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/negvti2.c diff --git a/src/compiler-rt/lib/builtins/paritydi2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/paritydi2.c similarity index 100% rename from src/compiler-rt/lib/builtins/paritydi2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/paritydi2.c diff --git a/src/compiler-rt/lib/builtins/paritysi2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/paritysi2.c similarity index 100% rename from src/compiler-rt/lib/builtins/paritysi2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/paritysi2.c diff --git a/src/compiler-rt/lib/builtins/parityti2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/parityti2.c similarity index 100% rename from src/compiler-rt/lib/builtins/parityti2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/parityti2.c diff --git a/src/compiler-rt/lib/builtins/popcountdi2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/popcountdi2.c similarity index 100% rename from src/compiler-rt/lib/builtins/popcountdi2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/popcountdi2.c diff --git a/src/compiler-rt/lib/builtins/popcountsi2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/popcountsi2.c similarity index 100% rename from src/compiler-rt/lib/builtins/popcountsi2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/popcountsi2.c diff --git a/src/compiler-rt/lib/builtins/popcountti2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/popcountti2.c similarity index 100% rename from src/compiler-rt/lib/builtins/popcountti2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/popcountti2.c diff --git a/src/compiler-rt/lib/builtins/powidf2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/powidf2.c similarity index 100% rename from src/compiler-rt/lib/builtins/powidf2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/powidf2.c diff --git a/src/compiler-rt/lib/builtins/powisf2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/powisf2.c similarity index 100% rename from src/compiler-rt/lib/builtins/powisf2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/powisf2.c diff --git a/src/compiler-rt/lib/builtins/powitf2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/powitf2.c similarity index 100% rename from src/compiler-rt/lib/builtins/powitf2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/powitf2.c diff --git a/src/compiler-rt/lib/builtins/powixf2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/powixf2.c similarity index 100% rename from src/compiler-rt/lib/builtins/powixf2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/powixf2.c diff --git a/src/compiler-rt/lib/builtins/ppc/DD.h b/src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/DD.h similarity index 100% rename from src/compiler-rt/lib/builtins/ppc/DD.h rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/DD.h diff --git a/src/compiler-rt/lib/builtins/ppc/divtc3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/divtc3.c similarity index 100% rename from src/compiler-rt/lib/builtins/ppc/divtc3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/divtc3.c diff --git a/src/compiler-rt/lib/builtins/ppc/fixtfdi.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/fixtfdi.c similarity index 100% rename from src/compiler-rt/lib/builtins/ppc/fixtfdi.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/fixtfdi.c diff --git a/src/compiler-rt/lib/builtins/ppc/fixunstfdi.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/fixunstfdi.c similarity index 100% rename from src/compiler-rt/lib/builtins/ppc/fixunstfdi.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/fixunstfdi.c diff --git a/src/compiler-rt/lib/builtins/ppc/floatditf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/floatditf.c similarity index 100% rename from src/compiler-rt/lib/builtins/ppc/floatditf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/floatditf.c diff --git a/src/compiler-rt/lib/builtins/ppc/floatunditf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/floatunditf.c similarity index 100% rename from src/compiler-rt/lib/builtins/ppc/floatunditf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/floatunditf.c diff --git a/src/compiler-rt/lib/builtins/ppc/gcc_qadd.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/gcc_qadd.c similarity index 100% rename from src/compiler-rt/lib/builtins/ppc/gcc_qadd.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/gcc_qadd.c diff --git a/src/compiler-rt/lib/builtins/ppc/gcc_qdiv.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/gcc_qdiv.c similarity index 100% rename from src/compiler-rt/lib/builtins/ppc/gcc_qdiv.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/gcc_qdiv.c diff --git a/src/compiler-rt/lib/builtins/ppc/gcc_qmul.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/gcc_qmul.c similarity index 100% rename from src/compiler-rt/lib/builtins/ppc/gcc_qmul.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/gcc_qmul.c diff --git a/src/compiler-rt/lib/builtins/ppc/gcc_qsub.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/gcc_qsub.c similarity index 100% rename from src/compiler-rt/lib/builtins/ppc/gcc_qsub.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/gcc_qsub.c diff --git a/src/compiler-rt/lib/builtins/ppc/multc3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/multc3.c similarity index 100% rename from src/compiler-rt/lib/builtins/ppc/multc3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/multc3.c diff --git a/src/compiler-rt/lib/builtins/ppc/restFP.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/restFP.S similarity index 100% rename from src/compiler-rt/lib/builtins/ppc/restFP.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/restFP.S diff --git a/src/compiler-rt/lib/builtins/ppc/saveFP.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/saveFP.S similarity index 100% rename from src/compiler-rt/lib/builtins/ppc/saveFP.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ppc/saveFP.S diff --git a/src/compiler-rt/lib/builtins/subdf3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/subdf3.c similarity index 100% rename from src/compiler-rt/lib/builtins/subdf3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/subdf3.c diff --git a/src/compiler-rt/lib/builtins/subsf3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/subsf3.c similarity index 100% rename from src/compiler-rt/lib/builtins/subsf3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/subsf3.c diff --git a/src/compiler-rt/lib/builtins/subtf3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/subtf3.c similarity index 100% rename from src/compiler-rt/lib/builtins/subtf3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/subtf3.c diff --git a/src/compiler-rt/lib/builtins/subvdi3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/subvdi3.c similarity index 100% rename from src/compiler-rt/lib/builtins/subvdi3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/subvdi3.c diff --git a/src/compiler-rt/lib/builtins/subvsi3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/subvsi3.c similarity index 100% rename from src/compiler-rt/lib/builtins/subvsi3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/subvsi3.c diff --git a/src/compiler-rt/lib/builtins/subvti3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/subvti3.c similarity index 100% rename from src/compiler-rt/lib/builtins/subvti3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/subvti3.c diff --git a/src/compiler-rt/lib/builtins/trampoline_setup.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/trampoline_setup.c similarity index 100% rename from src/compiler-rt/lib/builtins/trampoline_setup.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/trampoline_setup.c diff --git a/src/compiler-rt/lib/builtins/truncdfhf2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/truncdfhf2.c similarity index 100% rename from src/compiler-rt/lib/builtins/truncdfhf2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/truncdfhf2.c diff --git a/src/compiler-rt/lib/builtins/truncdfsf2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/truncdfsf2.c similarity index 100% rename from src/compiler-rt/lib/builtins/truncdfsf2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/truncdfsf2.c diff --git a/src/compiler-rt/lib/builtins/truncsfhf2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/truncsfhf2.c similarity index 100% rename from src/compiler-rt/lib/builtins/truncsfhf2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/truncsfhf2.c diff --git a/src/compiler-rt/lib/builtins/trunctfdf2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/trunctfdf2.c similarity index 100% rename from src/compiler-rt/lib/builtins/trunctfdf2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/trunctfdf2.c diff --git a/src/compiler-rt/lib/builtins/trunctfsf2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/trunctfsf2.c similarity index 100% rename from src/compiler-rt/lib/builtins/trunctfsf2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/trunctfsf2.c diff --git a/src/compiler-rt/lib/builtins/ucmpdi2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/ucmpdi2.c similarity index 100% rename from src/compiler-rt/lib/builtins/ucmpdi2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ucmpdi2.c diff --git a/src/compiler-rt/lib/builtins/ucmpti2.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/ucmpti2.c similarity index 100% rename from src/compiler-rt/lib/builtins/ucmpti2.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/ucmpti2.c diff --git a/src/compiler-rt/lib/builtins/udivdi3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/udivdi3.c similarity index 100% rename from src/compiler-rt/lib/builtins/udivdi3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/udivdi3.c diff --git a/src/compiler-rt/lib/builtins/udivmoddi4.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/udivmoddi4.c similarity index 100% rename from src/compiler-rt/lib/builtins/udivmoddi4.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/udivmoddi4.c diff --git a/src/compiler-rt/lib/builtins/udivmodsi4.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/udivmodsi4.c similarity index 100% rename from src/compiler-rt/lib/builtins/udivmodsi4.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/udivmodsi4.c diff --git a/src/compiler-rt/lib/builtins/udivmodti4.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/udivmodti4.c similarity index 100% rename from src/compiler-rt/lib/builtins/udivmodti4.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/udivmodti4.c diff --git a/src/compiler-rt/lib/builtins/udivsi3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/udivsi3.c similarity index 100% rename from src/compiler-rt/lib/builtins/udivsi3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/udivsi3.c diff --git a/src/compiler-rt/lib/builtins/udivti3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/udivti3.c similarity index 100% rename from src/compiler-rt/lib/builtins/udivti3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/udivti3.c diff --git a/src/compiler-rt/lib/builtins/umoddi3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/umoddi3.c similarity index 100% rename from src/compiler-rt/lib/builtins/umoddi3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/umoddi3.c diff --git a/src/compiler-rt/lib/builtins/umodsi3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/umodsi3.c similarity index 100% rename from src/compiler-rt/lib/builtins/umodsi3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/umodsi3.c diff --git a/src/compiler-rt/lib/builtins/umodti3.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/umodti3.c similarity index 100% rename from src/compiler-rt/lib/builtins/umodti3.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/umodti3.c diff --git a/src/compiler-rt/lib/builtins/unwind-ehabi-helpers.h b/src/libcompiler_builtins/compiler-rt/lib/builtins/unwind-ehabi-helpers.h similarity index 100% rename from src/compiler-rt/lib/builtins/unwind-ehabi-helpers.h rename to src/libcompiler_builtins/compiler-rt/lib/builtins/unwind-ehabi-helpers.h diff --git a/src/compiler-rt/lib/builtins/x86_64/chkstk.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/x86_64/chkstk.S similarity index 100% rename from src/compiler-rt/lib/builtins/x86_64/chkstk.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/x86_64/chkstk.S diff --git a/src/compiler-rt/lib/builtins/x86_64/chkstk2.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/x86_64/chkstk2.S similarity index 100% rename from src/compiler-rt/lib/builtins/x86_64/chkstk2.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/x86_64/chkstk2.S diff --git a/src/compiler-rt/lib/builtins/x86_64/floatdidf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/x86_64/floatdidf.c similarity index 100% rename from src/compiler-rt/lib/builtins/x86_64/floatdidf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/x86_64/floatdidf.c diff --git a/src/compiler-rt/lib/builtins/x86_64/floatdisf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/x86_64/floatdisf.c similarity index 100% rename from src/compiler-rt/lib/builtins/x86_64/floatdisf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/x86_64/floatdisf.c diff --git a/src/compiler-rt/lib/builtins/x86_64/floatdixf.c b/src/libcompiler_builtins/compiler-rt/lib/builtins/x86_64/floatdixf.c similarity index 100% rename from src/compiler-rt/lib/builtins/x86_64/floatdixf.c rename to src/libcompiler_builtins/compiler-rt/lib/builtins/x86_64/floatdixf.c diff --git a/src/compiler-rt/lib/builtins/x86_64/floatundidf.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/x86_64/floatundidf.S similarity index 100% rename from src/compiler-rt/lib/builtins/x86_64/floatundidf.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/x86_64/floatundidf.S diff --git a/src/compiler-rt/lib/builtins/x86_64/floatundisf.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/x86_64/floatundisf.S similarity index 100% rename from src/compiler-rt/lib/builtins/x86_64/floatundisf.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/x86_64/floatundisf.S diff --git a/src/compiler-rt/lib/builtins/x86_64/floatundixf.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/x86_64/floatundixf.S similarity index 100% rename from src/compiler-rt/lib/builtins/x86_64/floatundixf.S rename to src/libcompiler_builtins/compiler-rt/lib/builtins/x86_64/floatundixf.S diff --git a/src/compiler-rt/lib/cfi/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/cfi/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/cfi/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/cfi/CMakeLists.txt diff --git a/src/compiler-rt/lib/cfi/cfi.cc b/src/libcompiler_builtins/compiler-rt/lib/cfi/cfi.cc similarity index 100% rename from src/compiler-rt/lib/cfi/cfi.cc rename to src/libcompiler_builtins/compiler-rt/lib/cfi/cfi.cc diff --git a/src/compiler-rt/lib/cfi/cfi_blacklist.txt b/src/libcompiler_builtins/compiler-rt/lib/cfi/cfi_blacklist.txt similarity index 100% rename from src/compiler-rt/lib/cfi/cfi_blacklist.txt rename to src/libcompiler_builtins/compiler-rt/lib/cfi/cfi_blacklist.txt diff --git a/src/compiler-rt/lib/dfsan/.clang-format b/src/libcompiler_builtins/compiler-rt/lib/dfsan/.clang-format similarity index 100% rename from src/compiler-rt/lib/dfsan/.clang-format rename to src/libcompiler_builtins/compiler-rt/lib/dfsan/.clang-format diff --git a/src/compiler-rt/lib/dfsan/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/dfsan/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/dfsan/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/dfsan/CMakeLists.txt diff --git a/src/compiler-rt/lib/dfsan/dfsan.cc b/src/libcompiler_builtins/compiler-rt/lib/dfsan/dfsan.cc similarity index 100% rename from src/compiler-rt/lib/dfsan/dfsan.cc rename to src/libcompiler_builtins/compiler-rt/lib/dfsan/dfsan.cc diff --git a/src/compiler-rt/lib/dfsan/dfsan.h b/src/libcompiler_builtins/compiler-rt/lib/dfsan/dfsan.h similarity index 100% rename from src/compiler-rt/lib/dfsan/dfsan.h rename to src/libcompiler_builtins/compiler-rt/lib/dfsan/dfsan.h diff --git a/src/compiler-rt/lib/dfsan/dfsan.syms.extra b/src/libcompiler_builtins/compiler-rt/lib/dfsan/dfsan.syms.extra similarity index 100% rename from src/compiler-rt/lib/dfsan/dfsan.syms.extra rename to src/libcompiler_builtins/compiler-rt/lib/dfsan/dfsan.syms.extra diff --git a/src/compiler-rt/lib/dfsan/dfsan_custom.cc b/src/libcompiler_builtins/compiler-rt/lib/dfsan/dfsan_custom.cc similarity index 100% rename from src/compiler-rt/lib/dfsan/dfsan_custom.cc rename to src/libcompiler_builtins/compiler-rt/lib/dfsan/dfsan_custom.cc diff --git a/src/compiler-rt/lib/dfsan/dfsan_flags.inc b/src/libcompiler_builtins/compiler-rt/lib/dfsan/dfsan_flags.inc similarity index 100% rename from src/compiler-rt/lib/dfsan/dfsan_flags.inc rename to src/libcompiler_builtins/compiler-rt/lib/dfsan/dfsan_flags.inc diff --git a/src/compiler-rt/lib/dfsan/dfsan_interceptors.cc b/src/libcompiler_builtins/compiler-rt/lib/dfsan/dfsan_interceptors.cc similarity index 100% rename from src/compiler-rt/lib/dfsan/dfsan_interceptors.cc rename to src/libcompiler_builtins/compiler-rt/lib/dfsan/dfsan_interceptors.cc diff --git a/src/compiler-rt/lib/dfsan/dfsan_platform.h b/src/libcompiler_builtins/compiler-rt/lib/dfsan/dfsan_platform.h similarity index 100% rename from src/compiler-rt/lib/dfsan/dfsan_platform.h rename to src/libcompiler_builtins/compiler-rt/lib/dfsan/dfsan_platform.h diff --git a/src/compiler-rt/lib/dfsan/done_abilist.txt b/src/libcompiler_builtins/compiler-rt/lib/dfsan/done_abilist.txt similarity index 100% rename from src/compiler-rt/lib/dfsan/done_abilist.txt rename to src/libcompiler_builtins/compiler-rt/lib/dfsan/done_abilist.txt diff --git a/src/compiler-rt/lib/dfsan/libc_ubuntu1404_abilist.txt b/src/libcompiler_builtins/compiler-rt/lib/dfsan/libc_ubuntu1404_abilist.txt similarity index 100% rename from src/compiler-rt/lib/dfsan/libc_ubuntu1404_abilist.txt rename to src/libcompiler_builtins/compiler-rt/lib/dfsan/libc_ubuntu1404_abilist.txt diff --git a/src/compiler-rt/lib/dfsan/scripts/build-libc-list.py b/src/libcompiler_builtins/compiler-rt/lib/dfsan/scripts/build-libc-list.py similarity index 100% rename from src/compiler-rt/lib/dfsan/scripts/build-libc-list.py rename to src/libcompiler_builtins/compiler-rt/lib/dfsan/scripts/build-libc-list.py diff --git a/src/compiler-rt/lib/dfsan/scripts/check_custom_wrappers.sh b/src/libcompiler_builtins/compiler-rt/lib/dfsan/scripts/check_custom_wrappers.sh similarity index 100% rename from src/compiler-rt/lib/dfsan/scripts/check_custom_wrappers.sh rename to src/libcompiler_builtins/compiler-rt/lib/dfsan/scripts/check_custom_wrappers.sh diff --git a/src/compiler-rt/lib/esan/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/esan/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/esan/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/esan/CMakeLists.txt diff --git a/src/compiler-rt/lib/esan/cache_frag.cpp b/src/libcompiler_builtins/compiler-rt/lib/esan/cache_frag.cpp similarity index 100% rename from src/compiler-rt/lib/esan/cache_frag.cpp rename to src/libcompiler_builtins/compiler-rt/lib/esan/cache_frag.cpp diff --git a/src/compiler-rt/lib/esan/cache_frag.h b/src/libcompiler_builtins/compiler-rt/lib/esan/cache_frag.h similarity index 100% rename from src/compiler-rt/lib/esan/cache_frag.h rename to src/libcompiler_builtins/compiler-rt/lib/esan/cache_frag.h diff --git a/src/compiler-rt/lib/esan/esan.cpp b/src/libcompiler_builtins/compiler-rt/lib/esan/esan.cpp similarity index 100% rename from src/compiler-rt/lib/esan/esan.cpp rename to src/libcompiler_builtins/compiler-rt/lib/esan/esan.cpp diff --git a/src/compiler-rt/lib/esan/esan.h b/src/libcompiler_builtins/compiler-rt/lib/esan/esan.h similarity index 100% rename from src/compiler-rt/lib/esan/esan.h rename to src/libcompiler_builtins/compiler-rt/lib/esan/esan.h diff --git a/src/compiler-rt/lib/esan/esan.syms.extra b/src/libcompiler_builtins/compiler-rt/lib/esan/esan.syms.extra similarity index 100% rename from src/compiler-rt/lib/esan/esan.syms.extra rename to src/libcompiler_builtins/compiler-rt/lib/esan/esan.syms.extra diff --git a/src/compiler-rt/lib/esan/esan_circular_buffer.h b/src/libcompiler_builtins/compiler-rt/lib/esan/esan_circular_buffer.h similarity index 100% rename from src/compiler-rt/lib/esan/esan_circular_buffer.h rename to src/libcompiler_builtins/compiler-rt/lib/esan/esan_circular_buffer.h diff --git a/src/compiler-rt/lib/esan/esan_flags.cpp b/src/libcompiler_builtins/compiler-rt/lib/esan/esan_flags.cpp similarity index 100% rename from src/compiler-rt/lib/esan/esan_flags.cpp rename to src/libcompiler_builtins/compiler-rt/lib/esan/esan_flags.cpp diff --git a/src/compiler-rt/lib/esan/esan_flags.h b/src/libcompiler_builtins/compiler-rt/lib/esan/esan_flags.h similarity index 100% rename from src/compiler-rt/lib/esan/esan_flags.h rename to src/libcompiler_builtins/compiler-rt/lib/esan/esan_flags.h diff --git a/src/compiler-rt/lib/esan/esan_flags.inc b/src/libcompiler_builtins/compiler-rt/lib/esan/esan_flags.inc similarity index 100% rename from src/compiler-rt/lib/esan/esan_flags.inc rename to src/libcompiler_builtins/compiler-rt/lib/esan/esan_flags.inc diff --git a/src/compiler-rt/lib/esan/esan_hashtable.h b/src/libcompiler_builtins/compiler-rt/lib/esan/esan_hashtable.h similarity index 100% rename from src/compiler-rt/lib/esan/esan_hashtable.h rename to src/libcompiler_builtins/compiler-rt/lib/esan/esan_hashtable.h diff --git a/src/compiler-rt/lib/esan/esan_interceptors.cpp b/src/libcompiler_builtins/compiler-rt/lib/esan/esan_interceptors.cpp similarity index 100% rename from src/compiler-rt/lib/esan/esan_interceptors.cpp rename to src/libcompiler_builtins/compiler-rt/lib/esan/esan_interceptors.cpp diff --git a/src/compiler-rt/lib/esan/esan_interface.cpp b/src/libcompiler_builtins/compiler-rt/lib/esan/esan_interface.cpp similarity index 100% rename from src/compiler-rt/lib/esan/esan_interface.cpp rename to src/libcompiler_builtins/compiler-rt/lib/esan/esan_interface.cpp diff --git a/src/compiler-rt/lib/esan/esan_interface_internal.h b/src/libcompiler_builtins/compiler-rt/lib/esan/esan_interface_internal.h similarity index 100% rename from src/compiler-rt/lib/esan/esan_interface_internal.h rename to src/libcompiler_builtins/compiler-rt/lib/esan/esan_interface_internal.h diff --git a/src/compiler-rt/lib/esan/esan_linux.cpp b/src/libcompiler_builtins/compiler-rt/lib/esan/esan_linux.cpp similarity index 100% rename from src/compiler-rt/lib/esan/esan_linux.cpp rename to src/libcompiler_builtins/compiler-rt/lib/esan/esan_linux.cpp diff --git a/src/compiler-rt/lib/esan/esan_shadow.h b/src/libcompiler_builtins/compiler-rt/lib/esan/esan_shadow.h similarity index 100% rename from src/compiler-rt/lib/esan/esan_shadow.h rename to src/libcompiler_builtins/compiler-rt/lib/esan/esan_shadow.h diff --git a/src/compiler-rt/lib/esan/esan_sideline.h b/src/libcompiler_builtins/compiler-rt/lib/esan/esan_sideline.h similarity index 100% rename from src/compiler-rt/lib/esan/esan_sideline.h rename to src/libcompiler_builtins/compiler-rt/lib/esan/esan_sideline.h diff --git a/src/compiler-rt/lib/esan/esan_sideline_linux.cpp b/src/libcompiler_builtins/compiler-rt/lib/esan/esan_sideline_linux.cpp similarity index 100% rename from src/compiler-rt/lib/esan/esan_sideline_linux.cpp rename to src/libcompiler_builtins/compiler-rt/lib/esan/esan_sideline_linux.cpp diff --git a/src/compiler-rt/lib/esan/working_set.cpp b/src/libcompiler_builtins/compiler-rt/lib/esan/working_set.cpp similarity index 100% rename from src/compiler-rt/lib/esan/working_set.cpp rename to src/libcompiler_builtins/compiler-rt/lib/esan/working_set.cpp diff --git a/src/compiler-rt/lib/esan/working_set.h b/src/libcompiler_builtins/compiler-rt/lib/esan/working_set.h similarity index 100% rename from src/compiler-rt/lib/esan/working_set.h rename to src/libcompiler_builtins/compiler-rt/lib/esan/working_set.h diff --git a/src/compiler-rt/lib/esan/working_set_posix.cpp b/src/libcompiler_builtins/compiler-rt/lib/esan/working_set_posix.cpp similarity index 100% rename from src/compiler-rt/lib/esan/working_set_posix.cpp rename to src/libcompiler_builtins/compiler-rt/lib/esan/working_set_posix.cpp diff --git a/src/compiler-rt/lib/interception/.clang-format b/src/libcompiler_builtins/compiler-rt/lib/interception/.clang-format similarity index 100% rename from src/compiler-rt/lib/interception/.clang-format rename to src/libcompiler_builtins/compiler-rt/lib/interception/.clang-format diff --git a/src/compiler-rt/lib/interception/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/interception/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/interception/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/interception/CMakeLists.txt diff --git a/src/compiler-rt/lib/interception/interception.h b/src/libcompiler_builtins/compiler-rt/lib/interception/interception.h similarity index 100% rename from src/compiler-rt/lib/interception/interception.h rename to src/libcompiler_builtins/compiler-rt/lib/interception/interception.h diff --git a/src/compiler-rt/lib/interception/interception_linux.cc b/src/libcompiler_builtins/compiler-rt/lib/interception/interception_linux.cc similarity index 100% rename from src/compiler-rt/lib/interception/interception_linux.cc rename to src/libcompiler_builtins/compiler-rt/lib/interception/interception_linux.cc diff --git a/src/compiler-rt/lib/interception/interception_linux.h b/src/libcompiler_builtins/compiler-rt/lib/interception/interception_linux.h similarity index 100% rename from src/compiler-rt/lib/interception/interception_linux.h rename to src/libcompiler_builtins/compiler-rt/lib/interception/interception_linux.h diff --git a/src/compiler-rt/lib/interception/interception_mac.cc b/src/libcompiler_builtins/compiler-rt/lib/interception/interception_mac.cc similarity index 100% rename from src/compiler-rt/lib/interception/interception_mac.cc rename to src/libcompiler_builtins/compiler-rt/lib/interception/interception_mac.cc diff --git a/src/compiler-rt/lib/interception/interception_mac.h b/src/libcompiler_builtins/compiler-rt/lib/interception/interception_mac.h similarity index 100% rename from src/compiler-rt/lib/interception/interception_mac.h rename to src/libcompiler_builtins/compiler-rt/lib/interception/interception_mac.h diff --git a/src/compiler-rt/lib/interception/interception_type_test.cc b/src/libcompiler_builtins/compiler-rt/lib/interception/interception_type_test.cc similarity index 100% rename from src/compiler-rt/lib/interception/interception_type_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/interception/interception_type_test.cc diff --git a/src/compiler-rt/lib/interception/interception_win.cc b/src/libcompiler_builtins/compiler-rt/lib/interception/interception_win.cc similarity index 100% rename from src/compiler-rt/lib/interception/interception_win.cc rename to src/libcompiler_builtins/compiler-rt/lib/interception/interception_win.cc diff --git a/src/compiler-rt/lib/interception/interception_win.h b/src/libcompiler_builtins/compiler-rt/lib/interception/interception_win.h similarity index 100% rename from src/compiler-rt/lib/interception/interception_win.h rename to src/libcompiler_builtins/compiler-rt/lib/interception/interception_win.h diff --git a/src/compiler-rt/lib/interception/tests/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/interception/tests/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/interception/tests/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/interception/tests/CMakeLists.txt diff --git a/src/compiler-rt/lib/interception/tests/interception_linux_test.cc b/src/libcompiler_builtins/compiler-rt/lib/interception/tests/interception_linux_test.cc similarity index 100% rename from src/compiler-rt/lib/interception/tests/interception_linux_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/interception/tests/interception_linux_test.cc diff --git a/src/compiler-rt/lib/interception/tests/interception_test_main.cc b/src/libcompiler_builtins/compiler-rt/lib/interception/tests/interception_test_main.cc similarity index 100% rename from src/compiler-rt/lib/interception/tests/interception_test_main.cc rename to src/libcompiler_builtins/compiler-rt/lib/interception/tests/interception_test_main.cc diff --git a/src/compiler-rt/lib/interception/tests/interception_win_test.cc b/src/libcompiler_builtins/compiler-rt/lib/interception/tests/interception_win_test.cc similarity index 100% rename from src/compiler-rt/lib/interception/tests/interception_win_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/interception/tests/interception_win_test.cc diff --git a/src/compiler-rt/lib/lsan/.clang-format b/src/libcompiler_builtins/compiler-rt/lib/lsan/.clang-format similarity index 100% rename from src/compiler-rt/lib/lsan/.clang-format rename to src/libcompiler_builtins/compiler-rt/lib/lsan/.clang-format diff --git a/src/compiler-rt/lib/lsan/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/lsan/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/lsan/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/lsan/CMakeLists.txt diff --git a/src/compiler-rt/lib/lsan/lsan.cc b/src/libcompiler_builtins/compiler-rt/lib/lsan/lsan.cc similarity index 100% rename from src/compiler-rt/lib/lsan/lsan.cc rename to src/libcompiler_builtins/compiler-rt/lib/lsan/lsan.cc diff --git a/src/compiler-rt/lib/lsan/lsan.h b/src/libcompiler_builtins/compiler-rt/lib/lsan/lsan.h similarity index 100% rename from src/compiler-rt/lib/lsan/lsan.h rename to src/libcompiler_builtins/compiler-rt/lib/lsan/lsan.h diff --git a/src/compiler-rt/lib/lsan/lsan_allocator.cc b/src/libcompiler_builtins/compiler-rt/lib/lsan/lsan_allocator.cc similarity index 100% rename from src/compiler-rt/lib/lsan/lsan_allocator.cc rename to src/libcompiler_builtins/compiler-rt/lib/lsan/lsan_allocator.cc diff --git a/src/compiler-rt/lib/lsan/lsan_allocator.h b/src/libcompiler_builtins/compiler-rt/lib/lsan/lsan_allocator.h similarity index 100% rename from src/compiler-rt/lib/lsan/lsan_allocator.h rename to src/libcompiler_builtins/compiler-rt/lib/lsan/lsan_allocator.h diff --git a/src/compiler-rt/lib/lsan/lsan_common.cc b/src/libcompiler_builtins/compiler-rt/lib/lsan/lsan_common.cc similarity index 100% rename from src/compiler-rt/lib/lsan/lsan_common.cc rename to src/libcompiler_builtins/compiler-rt/lib/lsan/lsan_common.cc diff --git a/src/compiler-rt/lib/lsan/lsan_common.h b/src/libcompiler_builtins/compiler-rt/lib/lsan/lsan_common.h similarity index 100% rename from src/compiler-rt/lib/lsan/lsan_common.h rename to src/libcompiler_builtins/compiler-rt/lib/lsan/lsan_common.h diff --git a/src/compiler-rt/lib/lsan/lsan_common_linux.cc b/src/libcompiler_builtins/compiler-rt/lib/lsan/lsan_common_linux.cc similarity index 100% rename from src/compiler-rt/lib/lsan/lsan_common_linux.cc rename to src/libcompiler_builtins/compiler-rt/lib/lsan/lsan_common_linux.cc diff --git a/src/compiler-rt/lib/lsan/lsan_flags.inc b/src/libcompiler_builtins/compiler-rt/lib/lsan/lsan_flags.inc similarity index 100% rename from src/compiler-rt/lib/lsan/lsan_flags.inc rename to src/libcompiler_builtins/compiler-rt/lib/lsan/lsan_flags.inc diff --git a/src/compiler-rt/lib/lsan/lsan_interceptors.cc b/src/libcompiler_builtins/compiler-rt/lib/lsan/lsan_interceptors.cc similarity index 100% rename from src/compiler-rt/lib/lsan/lsan_interceptors.cc rename to src/libcompiler_builtins/compiler-rt/lib/lsan/lsan_interceptors.cc diff --git a/src/compiler-rt/lib/lsan/lsan_preinit.cc b/src/libcompiler_builtins/compiler-rt/lib/lsan/lsan_preinit.cc similarity index 100% rename from src/compiler-rt/lib/lsan/lsan_preinit.cc rename to src/libcompiler_builtins/compiler-rt/lib/lsan/lsan_preinit.cc diff --git a/src/compiler-rt/lib/lsan/lsan_thread.cc b/src/libcompiler_builtins/compiler-rt/lib/lsan/lsan_thread.cc similarity index 100% rename from src/compiler-rt/lib/lsan/lsan_thread.cc rename to src/libcompiler_builtins/compiler-rt/lib/lsan/lsan_thread.cc diff --git a/src/compiler-rt/lib/lsan/lsan_thread.h b/src/libcompiler_builtins/compiler-rt/lib/lsan/lsan_thread.h similarity index 100% rename from src/compiler-rt/lib/lsan/lsan_thread.h rename to src/libcompiler_builtins/compiler-rt/lib/lsan/lsan_thread.h diff --git a/src/compiler-rt/lib/msan/.clang-format b/src/libcompiler_builtins/compiler-rt/lib/msan/.clang-format similarity index 100% rename from src/compiler-rt/lib/msan/.clang-format rename to src/libcompiler_builtins/compiler-rt/lib/msan/.clang-format diff --git a/src/compiler-rt/lib/msan/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/msan/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/msan/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/msan/CMakeLists.txt diff --git a/src/compiler-rt/lib/msan/msan.cc b/src/libcompiler_builtins/compiler-rt/lib/msan/msan.cc similarity index 100% rename from src/compiler-rt/lib/msan/msan.cc rename to src/libcompiler_builtins/compiler-rt/lib/msan/msan.cc diff --git a/src/compiler-rt/lib/msan/msan.h b/src/libcompiler_builtins/compiler-rt/lib/msan/msan.h similarity index 100% rename from src/compiler-rt/lib/msan/msan.h rename to src/libcompiler_builtins/compiler-rt/lib/msan/msan.h diff --git a/src/compiler-rt/lib/msan/msan.syms.extra b/src/libcompiler_builtins/compiler-rt/lib/msan/msan.syms.extra similarity index 100% rename from src/compiler-rt/lib/msan/msan.syms.extra rename to src/libcompiler_builtins/compiler-rt/lib/msan/msan.syms.extra diff --git a/src/compiler-rt/lib/msan/msan_allocator.cc b/src/libcompiler_builtins/compiler-rt/lib/msan/msan_allocator.cc similarity index 100% rename from src/compiler-rt/lib/msan/msan_allocator.cc rename to src/libcompiler_builtins/compiler-rt/lib/msan/msan_allocator.cc diff --git a/src/compiler-rt/lib/msan/msan_allocator.h b/src/libcompiler_builtins/compiler-rt/lib/msan/msan_allocator.h similarity index 100% rename from src/compiler-rt/lib/msan/msan_allocator.h rename to src/libcompiler_builtins/compiler-rt/lib/msan/msan_allocator.h diff --git a/src/compiler-rt/lib/msan/msan_blacklist.txt b/src/libcompiler_builtins/compiler-rt/lib/msan/msan_blacklist.txt similarity index 100% rename from src/compiler-rt/lib/msan/msan_blacklist.txt rename to src/libcompiler_builtins/compiler-rt/lib/msan/msan_blacklist.txt diff --git a/src/compiler-rt/lib/msan/msan_chained_origin_depot.cc b/src/libcompiler_builtins/compiler-rt/lib/msan/msan_chained_origin_depot.cc similarity index 100% rename from src/compiler-rt/lib/msan/msan_chained_origin_depot.cc rename to src/libcompiler_builtins/compiler-rt/lib/msan/msan_chained_origin_depot.cc diff --git a/src/compiler-rt/lib/msan/msan_chained_origin_depot.h b/src/libcompiler_builtins/compiler-rt/lib/msan/msan_chained_origin_depot.h similarity index 100% rename from src/compiler-rt/lib/msan/msan_chained_origin_depot.h rename to src/libcompiler_builtins/compiler-rt/lib/msan/msan_chained_origin_depot.h diff --git a/src/compiler-rt/lib/msan/msan_flags.h b/src/libcompiler_builtins/compiler-rt/lib/msan/msan_flags.h similarity index 100% rename from src/compiler-rt/lib/msan/msan_flags.h rename to src/libcompiler_builtins/compiler-rt/lib/msan/msan_flags.h diff --git a/src/compiler-rt/lib/msan/msan_flags.inc b/src/libcompiler_builtins/compiler-rt/lib/msan/msan_flags.inc similarity index 100% rename from src/compiler-rt/lib/msan/msan_flags.inc rename to src/libcompiler_builtins/compiler-rt/lib/msan/msan_flags.inc diff --git a/src/compiler-rt/lib/msan/msan_interceptors.cc b/src/libcompiler_builtins/compiler-rt/lib/msan/msan_interceptors.cc similarity index 100% rename from src/compiler-rt/lib/msan/msan_interceptors.cc rename to src/libcompiler_builtins/compiler-rt/lib/msan/msan_interceptors.cc diff --git a/src/compiler-rt/lib/msan/msan_interface_internal.h b/src/libcompiler_builtins/compiler-rt/lib/msan/msan_interface_internal.h similarity index 100% rename from src/compiler-rt/lib/msan/msan_interface_internal.h rename to src/libcompiler_builtins/compiler-rt/lib/msan/msan_interface_internal.h diff --git a/src/compiler-rt/lib/msan/msan_linux.cc b/src/libcompiler_builtins/compiler-rt/lib/msan/msan_linux.cc similarity index 100% rename from src/compiler-rt/lib/msan/msan_linux.cc rename to src/libcompiler_builtins/compiler-rt/lib/msan/msan_linux.cc diff --git a/src/compiler-rt/lib/msan/msan_new_delete.cc b/src/libcompiler_builtins/compiler-rt/lib/msan/msan_new_delete.cc similarity index 100% rename from src/compiler-rt/lib/msan/msan_new_delete.cc rename to src/libcompiler_builtins/compiler-rt/lib/msan/msan_new_delete.cc diff --git a/src/compiler-rt/lib/msan/msan_origin.h b/src/libcompiler_builtins/compiler-rt/lib/msan/msan_origin.h similarity index 100% rename from src/compiler-rt/lib/msan/msan_origin.h rename to src/libcompiler_builtins/compiler-rt/lib/msan/msan_origin.h diff --git a/src/compiler-rt/lib/msan/msan_poisoning.cc b/src/libcompiler_builtins/compiler-rt/lib/msan/msan_poisoning.cc similarity index 100% rename from src/compiler-rt/lib/msan/msan_poisoning.cc rename to src/libcompiler_builtins/compiler-rt/lib/msan/msan_poisoning.cc diff --git a/src/compiler-rt/lib/msan/msan_poisoning.h b/src/libcompiler_builtins/compiler-rt/lib/msan/msan_poisoning.h similarity index 100% rename from src/compiler-rt/lib/msan/msan_poisoning.h rename to src/libcompiler_builtins/compiler-rt/lib/msan/msan_poisoning.h diff --git a/src/compiler-rt/lib/msan/msan_report.cc b/src/libcompiler_builtins/compiler-rt/lib/msan/msan_report.cc similarity index 100% rename from src/compiler-rt/lib/msan/msan_report.cc rename to src/libcompiler_builtins/compiler-rt/lib/msan/msan_report.cc diff --git a/src/compiler-rt/lib/msan/msan_thread.cc b/src/libcompiler_builtins/compiler-rt/lib/msan/msan_thread.cc similarity index 100% rename from src/compiler-rt/lib/msan/msan_thread.cc rename to src/libcompiler_builtins/compiler-rt/lib/msan/msan_thread.cc diff --git a/src/compiler-rt/lib/msan/msan_thread.h b/src/libcompiler_builtins/compiler-rt/lib/msan/msan_thread.h similarity index 100% rename from src/compiler-rt/lib/msan/msan_thread.h rename to src/libcompiler_builtins/compiler-rt/lib/msan/msan_thread.h diff --git a/src/compiler-rt/lib/msan/tests/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/msan/tests/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/msan/tests/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/msan/tests/CMakeLists.txt diff --git a/src/compiler-rt/lib/msan/tests/msan_loadable.cc b/src/libcompiler_builtins/compiler-rt/lib/msan/tests/msan_loadable.cc similarity index 100% rename from src/compiler-rt/lib/msan/tests/msan_loadable.cc rename to src/libcompiler_builtins/compiler-rt/lib/msan/tests/msan_loadable.cc diff --git a/src/compiler-rt/lib/msan/tests/msan_test.cc b/src/libcompiler_builtins/compiler-rt/lib/msan/tests/msan_test.cc similarity index 100% rename from src/compiler-rt/lib/msan/tests/msan_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/msan/tests/msan_test.cc diff --git a/src/compiler-rt/lib/msan/tests/msan_test_config.h b/src/libcompiler_builtins/compiler-rt/lib/msan/tests/msan_test_config.h similarity index 100% rename from src/compiler-rt/lib/msan/tests/msan_test_config.h rename to src/libcompiler_builtins/compiler-rt/lib/msan/tests/msan_test_config.h diff --git a/src/compiler-rt/lib/msan/tests/msan_test_main.cc b/src/libcompiler_builtins/compiler-rt/lib/msan/tests/msan_test_main.cc similarity index 100% rename from src/compiler-rt/lib/msan/tests/msan_test_main.cc rename to src/libcompiler_builtins/compiler-rt/lib/msan/tests/msan_test_main.cc diff --git a/src/compiler-rt/lib/profile/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/profile/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/profile/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/profile/CMakeLists.txt diff --git a/src/compiler-rt/lib/profile/GCDAProfiling.c b/src/libcompiler_builtins/compiler-rt/lib/profile/GCDAProfiling.c similarity index 100% rename from src/compiler-rt/lib/profile/GCDAProfiling.c rename to src/libcompiler_builtins/compiler-rt/lib/profile/GCDAProfiling.c diff --git a/src/compiler-rt/lib/profile/InstrProfData.inc b/src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfData.inc similarity index 100% rename from src/compiler-rt/lib/profile/InstrProfData.inc rename to src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfData.inc diff --git a/src/compiler-rt/lib/profile/InstrProfiling.c b/src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfiling.c similarity index 100% rename from src/compiler-rt/lib/profile/InstrProfiling.c rename to src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfiling.c diff --git a/src/compiler-rt/lib/profile/InstrProfiling.h b/src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfiling.h similarity index 100% rename from src/compiler-rt/lib/profile/InstrProfiling.h rename to src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfiling.h diff --git a/src/compiler-rt/lib/profile/InstrProfilingBuffer.c b/src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingBuffer.c similarity index 100% rename from src/compiler-rt/lib/profile/InstrProfilingBuffer.c rename to src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingBuffer.c diff --git a/src/compiler-rt/lib/profile/InstrProfilingFile.c b/src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingFile.c similarity index 100% rename from src/compiler-rt/lib/profile/InstrProfilingFile.c rename to src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingFile.c diff --git a/src/compiler-rt/lib/profile/InstrProfilingInternal.h b/src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingInternal.h similarity index 100% rename from src/compiler-rt/lib/profile/InstrProfilingInternal.h rename to src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingInternal.h diff --git a/src/compiler-rt/lib/profile/InstrProfilingMerge.c b/src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingMerge.c similarity index 100% rename from src/compiler-rt/lib/profile/InstrProfilingMerge.c rename to src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingMerge.c diff --git a/src/compiler-rt/lib/profile/InstrProfilingMergeFile.c b/src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingMergeFile.c similarity index 100% rename from src/compiler-rt/lib/profile/InstrProfilingMergeFile.c rename to src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingMergeFile.c diff --git a/src/compiler-rt/lib/profile/InstrProfilingPlatformDarwin.c b/src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingPlatformDarwin.c similarity index 100% rename from src/compiler-rt/lib/profile/InstrProfilingPlatformDarwin.c rename to src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingPlatformDarwin.c diff --git a/src/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c b/src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c similarity index 100% rename from src/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c rename to src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c diff --git a/src/compiler-rt/lib/profile/InstrProfilingPlatformOther.c b/src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingPlatformOther.c similarity index 100% rename from src/compiler-rt/lib/profile/InstrProfilingPlatformOther.c rename to src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingPlatformOther.c diff --git a/src/compiler-rt/lib/profile/InstrProfilingPort.h b/src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingPort.h similarity index 100% rename from src/compiler-rt/lib/profile/InstrProfilingPort.h rename to src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingPort.h diff --git a/src/compiler-rt/lib/profile/InstrProfilingRuntime.cc b/src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingRuntime.cc similarity index 100% rename from src/compiler-rt/lib/profile/InstrProfilingRuntime.cc rename to src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingRuntime.cc diff --git a/src/compiler-rt/lib/profile/InstrProfilingUtil.c b/src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingUtil.c similarity index 100% rename from src/compiler-rt/lib/profile/InstrProfilingUtil.c rename to src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingUtil.c diff --git a/src/compiler-rt/lib/profile/InstrProfilingUtil.h b/src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingUtil.h similarity index 100% rename from src/compiler-rt/lib/profile/InstrProfilingUtil.h rename to src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingUtil.h diff --git a/src/compiler-rt/lib/profile/InstrProfilingValue.c b/src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingValue.c similarity index 100% rename from src/compiler-rt/lib/profile/InstrProfilingValue.c rename to src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingValue.c diff --git a/src/compiler-rt/lib/profile/InstrProfilingWriter.c b/src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingWriter.c similarity index 100% rename from src/compiler-rt/lib/profile/InstrProfilingWriter.c rename to src/libcompiler_builtins/compiler-rt/lib/profile/InstrProfilingWriter.c diff --git a/src/compiler-rt/lib/profile/WindowsMMap.c b/src/libcompiler_builtins/compiler-rt/lib/profile/WindowsMMap.c similarity index 100% rename from src/compiler-rt/lib/profile/WindowsMMap.c rename to src/libcompiler_builtins/compiler-rt/lib/profile/WindowsMMap.c diff --git a/src/compiler-rt/lib/profile/WindowsMMap.h b/src/libcompiler_builtins/compiler-rt/lib/profile/WindowsMMap.h similarity index 100% rename from src/compiler-rt/lib/profile/WindowsMMap.h rename to src/libcompiler_builtins/compiler-rt/lib/profile/WindowsMMap.h diff --git a/src/compiler-rt/lib/safestack/.clang-format b/src/libcompiler_builtins/compiler-rt/lib/safestack/.clang-format similarity index 100% rename from src/compiler-rt/lib/safestack/.clang-format rename to src/libcompiler_builtins/compiler-rt/lib/safestack/.clang-format diff --git a/src/compiler-rt/lib/safestack/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/safestack/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/safestack/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/safestack/CMakeLists.txt diff --git a/src/compiler-rt/lib/safestack/safestack.cc b/src/libcompiler_builtins/compiler-rt/lib/safestack/safestack.cc similarity index 100% rename from src/compiler-rt/lib/safestack/safestack.cc rename to src/libcompiler_builtins/compiler-rt/lib/safestack/safestack.cc diff --git a/src/compiler-rt/lib/sanitizer_common/.clang-format b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/.clang-format similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/.clang-format rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/.clang-format diff --git a/src/compiler-rt/lib/sanitizer_common/.clang-tidy b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/.clang-tidy similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/.clang-tidy rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/.clang-tidy diff --git a/src/compiler-rt/lib/sanitizer_common/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/CMakeLists.txt diff --git a/src/compiler-rt/lib/sanitizer_common/sancov_flags.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sancov_flags.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sancov_flags.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sancov_flags.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sancov_flags.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sancov_flags.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sancov_flags.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sancov_flags.h diff --git a/src/compiler-rt/lib/sanitizer_common/sancov_flags.inc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sancov_flags.inc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sancov_flags.inc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sancov_flags.inc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_addrhashmap.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_addrhashmap.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_addrhashmap.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_addrhashmap.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_allocator_bytemap.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator_bytemap.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_allocator_bytemap.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator_bytemap.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_allocator_combined.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator_combined.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_allocator_combined.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator_combined.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_allocator_interface.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator_interface.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_allocator_interface.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator_interface.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_allocator_local_cache.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator_local_cache.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_allocator_local_cache.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator_local_cache.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary32.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary32.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary32.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary32.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_allocator_secondary.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator_secondary.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_allocator_secondary.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator_secondary.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_allocator_size_class_map.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator_size_class_map.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_allocator_size_class_map.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator_size_class_map.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_allocator_stats.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator_stats.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_allocator_stats.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_allocator_stats.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_asm.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_asm.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_asm.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_asm.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_atomic.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_atomic.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_atomic.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_atomic.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_other.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_other.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_other.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_other.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_x86.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_x86.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_x86.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_x86.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_atomic_msvc.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_atomic_msvc.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_atomic_msvc.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_atomic_msvc.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_bitvector.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_bitvector.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_bitvector.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_bitvector.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_bvgraph.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_bvgraph.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_bvgraph.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_bvgraph.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_common.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_common.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_common.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_common.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_common.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_common.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_common.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_format.inc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_format.inc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_format.inc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_format.inc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_common_nolibc.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_common_nolibc.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_common_nolibc.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_common_nolibc.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_dbghelp.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_dbghelp.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_dbghelp.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_dbghelp.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector1.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector1.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector1.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector1.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector2.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector2.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector2.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector2.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_flag_parser.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_flag_parser.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_flag_parser.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_flag_parser.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_flag_parser.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_flag_parser.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_flag_parser.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_flag_parser.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_flags.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_flags.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_flags.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_flags.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_flags.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_flags.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_flags.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_flags.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_freebsd.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_freebsd.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_freebsd.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_freebsd.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_interface_internal.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_interface_internal.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_interface_internal.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_interface_internal.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_lfstack.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_lfstack.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_lfstack.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_lfstack.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_libc.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_libc.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_libc.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_libc.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_libc.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_libc.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_libc.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_libc.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_libignore.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_libignore.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_libignore.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_libignore.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_libignore.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_libignore.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_libignore.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_libignore.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_linux.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_linux.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_linux.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_linux.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_linux_mips64.S b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_linux_mips64.S similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_linux_mips64.S rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_linux_mips64.S diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_linux_s390.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_linux_s390.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_linux_s390.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_linux_s390.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_linux_x86_64.S b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_linux_x86_64.S similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_linux_x86_64.S rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_linux_x86_64.S diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_list.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_list.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_list.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_list.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_mac.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_mac.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_mac.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_mac.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_malloc_mac.inc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_malloc_mac.inc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_malloc_mac.inc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_malloc_mac.inc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_mutex.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_mutex.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_mutex.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_mutex.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_persistent_allocator.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_persistent_allocator.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_persistent_allocator.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_persistent_allocator.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_persistent_allocator.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_persistent_allocator.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_persistent_allocator.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_persistent_allocator.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_placement_new.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_placement_new.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_placement_new.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_placement_new.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_platform.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_platform.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_platform.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_platform.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_posix.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_posix.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_posix.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_posix.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_printf.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_printf.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_printf.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_printf.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_common.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_common.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_common.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_common.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_freebsd.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_freebsd.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_freebsd.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_freebsd.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_linux.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_linux.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_linux.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_linux.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_mac.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_mac.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_mac.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_mac.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_quarantine.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_quarantine.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_quarantine.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_quarantine.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_report_decorator.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_report_decorator.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_report_decorator.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_report_decorator.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_stackdepotbase.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_stackdepotbase.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_stackdepotbase.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_stackdepotbase.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_internal.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_internal.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_internal.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_internal.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_syscall_linux_aarch64.inc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_syscall_linux_aarch64.inc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_syscall_linux_aarch64.inc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_syscall_linux_aarch64.inc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_termination.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_termination.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_termination.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_termination.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.h diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cc diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_win.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_win.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/sanitizer_win.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/sanitizer_win.cc diff --git a/src/compiler-rt/lib/sanitizer_common/scripts/check_lint.sh b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/scripts/check_lint.sh similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/scripts/check_lint.sh rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/scripts/check_lint.sh diff --git a/src/compiler-rt/lib/sanitizer_common/scripts/cpplint.py b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/scripts/cpplint.py similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/scripts/cpplint.py rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/scripts/cpplint.py diff --git a/src/compiler-rt/lib/sanitizer_common/scripts/gen_dynamic_list.py b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/scripts/gen_dynamic_list.py similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/scripts/gen_dynamic_list.py rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/scripts/gen_dynamic_list.py diff --git a/src/compiler-rt/lib/sanitizer_common/scripts/litlint.py b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/scripts/litlint.py similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/scripts/litlint.py rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/scripts/litlint.py diff --git a/src/compiler-rt/lib/sanitizer_common/scripts/litlint_test.py b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/scripts/litlint_test.py similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/scripts/litlint_test.py rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/scripts/litlint_test.py diff --git a/src/compiler-rt/lib/sanitizer_common/scripts/sancov.py b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/scripts/sancov.py similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/scripts/sancov.py rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/scripts/sancov.py diff --git a/src/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_symbolize.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_symbolize.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_symbolize.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_symbolize.cc diff --git a/src/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_wrappers.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_wrappers.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_wrappers.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_wrappers.cc diff --git a/src/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh diff --git a/src/compiler-rt/lib/sanitizer_common/symbolizer/scripts/global_symbols.txt b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/symbolizer/scripts/global_symbols.txt similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/symbolizer/scripts/global_symbols.txt rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/symbolizer/scripts/global_symbols.txt diff --git a/src/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt diff --git a/src/compiler-rt/lib/sanitizer_common/tests/malloc_stress_transfer_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/malloc_stress_transfer_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/malloc_stress_transfer_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/malloc_stress_transfer_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_testlib.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_testlib.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_testlib.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_testlib.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_atomic_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_atomic_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_atomic_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_atomic_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_bitvector_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_bitvector_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_bitvector_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_bitvector_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_bvgraph_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_bvgraph_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_bvgraph_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_bvgraph_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_deadlock_detector_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_deadlock_detector_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_deadlock_detector_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_deadlock_detector_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_flags_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_flags_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_flags_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_flags_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_format_interceptor_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_format_interceptor_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_format_interceptor_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_format_interceptor_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_ioctl_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_ioctl_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_ioctl_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_ioctl_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_libc_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_libc_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_libc_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_libc_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_linux_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_linux_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_linux_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_linux_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_list_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_list_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_list_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_list_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_mutex_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_mutex_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_mutex_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_mutex_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_nolibc_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_nolibc_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_nolibc_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_nolibc_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_nolibc_test_main.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_nolibc_test_main.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_nolibc_test_main.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_nolibc_test_main.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_printf_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_printf_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_printf_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_printf_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_procmaps_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_procmaps_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_procmaps_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_procmaps_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_pthread_wrappers.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_pthread_wrappers.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_pthread_wrappers.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_pthread_wrappers.h diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_stackdepot_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_stackdepot_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_stackdepot_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_stackdepot_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_printer_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_printer_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_printer_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_printer_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_stoptheworld_testlib.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_stoptheworld_testlib.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_stoptheworld_testlib.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_stoptheworld_testlib.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_symbolizer_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_symbolizer_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_symbolizer_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_symbolizer_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_test_config.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_test_config.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_test_config.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_test_config.h diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_test_main.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_test_main.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_test_main.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_test_main.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_test_utils.h b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_test_utils.h similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_test_utils.h rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_test_utils.h diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/tests/standalone_malloc_test.cc b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/standalone_malloc_test.cc similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/tests/standalone_malloc_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/tests/standalone_malloc_test.cc diff --git a/src/compiler-rt/lib/sanitizer_common/weak_symbols.txt b/src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/weak_symbols.txt similarity index 100% rename from src/compiler-rt/lib/sanitizer_common/weak_symbols.txt rename to src/libcompiler_builtins/compiler-rt/lib/sanitizer_common/weak_symbols.txt diff --git a/src/compiler-rt/lib/scudo/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/scudo/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/scudo/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/scudo/CMakeLists.txt diff --git a/src/compiler-rt/lib/scudo/scudo_allocator.cpp b/src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_allocator.cpp similarity index 100% rename from src/compiler-rt/lib/scudo/scudo_allocator.cpp rename to src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_allocator.cpp diff --git a/src/compiler-rt/lib/scudo/scudo_allocator.h b/src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_allocator.h similarity index 100% rename from src/compiler-rt/lib/scudo/scudo_allocator.h rename to src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_allocator.h diff --git a/src/compiler-rt/lib/scudo/scudo_allocator_secondary.h b/src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_allocator_secondary.h similarity index 100% rename from src/compiler-rt/lib/scudo/scudo_allocator_secondary.h rename to src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_allocator_secondary.h diff --git a/src/compiler-rt/lib/scudo/scudo_crc32.cpp b/src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_crc32.cpp similarity index 100% rename from src/compiler-rt/lib/scudo/scudo_crc32.cpp rename to src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_crc32.cpp diff --git a/src/compiler-rt/lib/scudo/scudo_crc32.h b/src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_crc32.h similarity index 100% rename from src/compiler-rt/lib/scudo/scudo_crc32.h rename to src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_crc32.h diff --git a/src/compiler-rt/lib/scudo/scudo_flags.cpp b/src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_flags.cpp similarity index 100% rename from src/compiler-rt/lib/scudo/scudo_flags.cpp rename to src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_flags.cpp diff --git a/src/compiler-rt/lib/scudo/scudo_flags.h b/src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_flags.h similarity index 100% rename from src/compiler-rt/lib/scudo/scudo_flags.h rename to src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_flags.h diff --git a/src/compiler-rt/lib/scudo/scudo_flags.inc b/src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_flags.inc similarity index 100% rename from src/compiler-rt/lib/scudo/scudo_flags.inc rename to src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_flags.inc diff --git a/src/compiler-rt/lib/scudo/scudo_interceptors.cpp b/src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_interceptors.cpp similarity index 100% rename from src/compiler-rt/lib/scudo/scudo_interceptors.cpp rename to src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_interceptors.cpp diff --git a/src/compiler-rt/lib/scudo/scudo_new_delete.cpp b/src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_new_delete.cpp similarity index 100% rename from src/compiler-rt/lib/scudo/scudo_new_delete.cpp rename to src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_new_delete.cpp diff --git a/src/compiler-rt/lib/scudo/scudo_termination.cpp b/src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_termination.cpp similarity index 100% rename from src/compiler-rt/lib/scudo/scudo_termination.cpp rename to src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_termination.cpp diff --git a/src/compiler-rt/lib/scudo/scudo_utils.cpp b/src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_utils.cpp similarity index 100% rename from src/compiler-rt/lib/scudo/scudo_utils.cpp rename to src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_utils.cpp diff --git a/src/compiler-rt/lib/scudo/scudo_utils.h b/src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_utils.h similarity index 100% rename from src/compiler-rt/lib/scudo/scudo_utils.h rename to src/libcompiler_builtins/compiler-rt/lib/scudo/scudo_utils.h diff --git a/src/compiler-rt/lib/stats/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/stats/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/stats/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/stats/CMakeLists.txt diff --git a/src/compiler-rt/lib/stats/stats.cc b/src/libcompiler_builtins/compiler-rt/lib/stats/stats.cc similarity index 100% rename from src/compiler-rt/lib/stats/stats.cc rename to src/libcompiler_builtins/compiler-rt/lib/stats/stats.cc diff --git a/src/compiler-rt/lib/stats/stats.h b/src/libcompiler_builtins/compiler-rt/lib/stats/stats.h similarity index 100% rename from src/compiler-rt/lib/stats/stats.h rename to src/libcompiler_builtins/compiler-rt/lib/stats/stats.h diff --git a/src/compiler-rt/lib/stats/stats_client.cc b/src/libcompiler_builtins/compiler-rt/lib/stats/stats_client.cc similarity index 100% rename from src/compiler-rt/lib/stats/stats_client.cc rename to src/libcompiler_builtins/compiler-rt/lib/stats/stats_client.cc diff --git a/src/compiler-rt/lib/tsan/.clang-format b/src/libcompiler_builtins/compiler-rt/lib/tsan/.clang-format similarity index 100% rename from src/compiler-rt/lib/tsan/.clang-format rename to src/libcompiler_builtins/compiler-rt/lib/tsan/.clang-format diff --git a/src/compiler-rt/lib/tsan/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/tsan/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/tsan/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/tsan/CMakeLists.txt diff --git a/src/compiler-rt/lib/tsan/analyze_libtsan.sh b/src/libcompiler_builtins/compiler-rt/lib/tsan/analyze_libtsan.sh similarity index 100% rename from src/compiler-rt/lib/tsan/analyze_libtsan.sh rename to src/libcompiler_builtins/compiler-rt/lib/tsan/analyze_libtsan.sh diff --git a/src/compiler-rt/lib/tsan/benchmarks/mini_bench_local.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/benchmarks/mini_bench_local.cc similarity index 100% rename from src/compiler-rt/lib/tsan/benchmarks/mini_bench_local.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/benchmarks/mini_bench_local.cc diff --git a/src/compiler-rt/lib/tsan/benchmarks/mini_bench_shared.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/benchmarks/mini_bench_shared.cc similarity index 100% rename from src/compiler-rt/lib/tsan/benchmarks/mini_bench_shared.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/benchmarks/mini_bench_shared.cc diff --git a/src/compiler-rt/lib/tsan/benchmarks/start_many_threads.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/benchmarks/start_many_threads.cc similarity index 100% rename from src/compiler-rt/lib/tsan/benchmarks/start_many_threads.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/benchmarks/start_many_threads.cc diff --git a/src/compiler-rt/lib/tsan/benchmarks/vts_many_threads_bench.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/benchmarks/vts_many_threads_bench.cc similarity index 100% rename from src/compiler-rt/lib/tsan/benchmarks/vts_many_threads_bench.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/benchmarks/vts_many_threads_bench.cc diff --git a/src/compiler-rt/lib/tsan/check_analyze.sh b/src/libcompiler_builtins/compiler-rt/lib/tsan/check_analyze.sh similarity index 100% rename from src/compiler-rt/lib/tsan/check_analyze.sh rename to src/libcompiler_builtins/compiler-rt/lib/tsan/check_analyze.sh diff --git a/src/compiler-rt/lib/tsan/check_cmake.sh b/src/libcompiler_builtins/compiler-rt/lib/tsan/check_cmake.sh similarity index 100% rename from src/compiler-rt/lib/tsan/check_cmake.sh rename to src/libcompiler_builtins/compiler-rt/lib/tsan/check_cmake.sh diff --git a/src/compiler-rt/lib/tsan/dd/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/tsan/dd/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/tsan/dd/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/tsan/dd/CMakeLists.txt diff --git a/src/compiler-rt/lib/tsan/dd/dd_interceptors.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/dd/dd_interceptors.cc similarity index 100% rename from src/compiler-rt/lib/tsan/dd/dd_interceptors.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/dd/dd_interceptors.cc diff --git a/src/compiler-rt/lib/tsan/dd/dd_rtl.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/dd/dd_rtl.cc similarity index 100% rename from src/compiler-rt/lib/tsan/dd/dd_rtl.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/dd/dd_rtl.cc diff --git a/src/compiler-rt/lib/tsan/dd/dd_rtl.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/dd/dd_rtl.h similarity index 100% rename from src/compiler-rt/lib/tsan/dd/dd_rtl.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/dd/dd_rtl.h diff --git a/src/compiler-rt/lib/tsan/go/build.bat b/src/libcompiler_builtins/compiler-rt/lib/tsan/go/build.bat similarity index 100% rename from src/compiler-rt/lib/tsan/go/build.bat rename to src/libcompiler_builtins/compiler-rt/lib/tsan/go/build.bat diff --git a/src/compiler-rt/lib/tsan/go/buildgo.sh b/src/libcompiler_builtins/compiler-rt/lib/tsan/go/buildgo.sh similarity index 100% rename from src/compiler-rt/lib/tsan/go/buildgo.sh rename to src/libcompiler_builtins/compiler-rt/lib/tsan/go/buildgo.sh diff --git a/src/compiler-rt/lib/tsan/go/test.c b/src/libcompiler_builtins/compiler-rt/lib/tsan/go/test.c similarity index 100% rename from src/compiler-rt/lib/tsan/go/test.c rename to src/libcompiler_builtins/compiler-rt/lib/tsan/go/test.c diff --git a/src/compiler-rt/lib/tsan/go/tsan_go.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/go/tsan_go.cc similarity index 100% rename from src/compiler-rt/lib/tsan/go/tsan_go.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/go/tsan_go.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan.syms.extra b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan.syms.extra similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan.syms.extra rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan.syms.extra diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_clock.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_clock.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_clock.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_clock.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_clock.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_clock.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_clock.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_clock.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_debugging.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_debugging.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_debugging.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_debugging.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_defs.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_defs.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_defs.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_defs.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_dense_alloc.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_dense_alloc.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_dense_alloc.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_dense_alloc.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_fd.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_fd.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_fd.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_fd.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_fd.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_fd.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_fd.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_fd.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_flags.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_flags.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_flags.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_flags.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_flags.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_flags.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_flags.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_flags.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_flags.inc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_flags.inc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_flags.inc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_flags.inc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_ignoreset.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_ignoreset.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_ignoreset.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_ignoreset.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_ignoreset.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_ignoreset.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_ignoreset.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_ignoreset.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_interceptors.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_interceptors.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_interceptors.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_interface.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_interface.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_interface.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_interface.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_interface.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_interface.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_interface.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_interface.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_interface_ann.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_interface_ann.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_interface_ann.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_interface_ann.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_interface_inl.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_interface_inl.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_interface_inl.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_interface_inl.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_interface_java.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_interface_java.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_interface_java.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_interface_java.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_interface_java.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_interface_java.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_interface_java.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_interface_java.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_libdispatch_mac.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_libdispatch_mac.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_libdispatch_mac.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_libdispatch_mac.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_malloc_mac.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_malloc_mac.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_malloc_mac.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_malloc_mac.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_md5.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_md5.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_md5.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_md5.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_mman.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_mman.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_mman.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_mman.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_mman.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_mman.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_mman.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_mman.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_mutex.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_mutex.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_mutex.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_mutex.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_mutex.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_mutex.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_mutex.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_mutex.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_mutexset.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_mutexset.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_mutexset.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_mutexset.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_mutexset.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_mutexset.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_mutexset.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_mutexset.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_new_delete.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_new_delete.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_new_delete.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_new_delete.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_platform.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_platform.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_platform.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_platform.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_platform_windows.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_platform_windows.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_platform_windows.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_platform_windows.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_ppc_regs.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_ppc_regs.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_ppc_regs.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_ppc_regs.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_preinit.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_preinit.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_preinit.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_preinit.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_report.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_report.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_report.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_report.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_report.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_report.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_report.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_report.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_rtl.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_rtl.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_rtl.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_rtl.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_rtl.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_rtl.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_rtl.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_rtl_aarch64.S b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_rtl_aarch64.S similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_rtl_aarch64.S rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_rtl_aarch64.S diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_rtl_amd64.S b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_rtl_amd64.S similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_rtl_amd64.S rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_rtl_amd64.S diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_rtl_mips64.S b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_rtl_mips64.S similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_rtl_mips64.S rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_rtl_mips64.S diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_rtl_ppc64.S b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_rtl_ppc64.S similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_rtl_ppc64.S rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_rtl_ppc64.S diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_rtl_proc.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_rtl_proc.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_rtl_proc.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_rtl_proc.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_stack_trace.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_stack_trace.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_stack_trace.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_stack_trace.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_stack_trace.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_stack_trace.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_stack_trace.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_stack_trace.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_stat.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_stat.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_stat.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_stat.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_stat.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_stat.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_stat.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_stat.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_suppressions.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_suppressions.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_suppressions.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_suppressions.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_symbolize.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_symbolize.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_symbolize.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_symbolize.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_symbolize.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_symbolize.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_symbolize.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_symbolize.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_sync.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_sync.cc similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_sync.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_sync.cc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_sync.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_sync.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_sync.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_sync.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_trace.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_trace.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_trace.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_trace.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_update_shadow_word_inl.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_update_shadow_word_inl.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_update_shadow_word_inl.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_update_shadow_word_inl.h diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_vector.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_vector.h similarity index 100% rename from src/compiler-rt/lib/tsan/rtl/tsan_vector.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/rtl/tsan_vector.h diff --git a/src/compiler-rt/lib/tsan/tests/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/tsan/tests/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/CMakeLists.txt diff --git a/src/compiler-rt/lib/tsan/tests/rtl/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/rtl/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/tsan/tests/rtl/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/rtl/CMakeLists.txt diff --git a/src/compiler-rt/lib/tsan/tests/rtl/tsan_bench.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/rtl/tsan_bench.cc similarity index 100% rename from src/compiler-rt/lib/tsan/tests/rtl/tsan_bench.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/rtl/tsan_bench.cc diff --git a/src/compiler-rt/lib/tsan/tests/rtl/tsan_mop.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/rtl/tsan_mop.cc similarity index 100% rename from src/compiler-rt/lib/tsan/tests/rtl/tsan_mop.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/rtl/tsan_mop.cc diff --git a/src/compiler-rt/lib/tsan/tests/rtl/tsan_mutex.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/rtl/tsan_mutex.cc similarity index 100% rename from src/compiler-rt/lib/tsan/tests/rtl/tsan_mutex.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/rtl/tsan_mutex.cc diff --git a/src/compiler-rt/lib/tsan/tests/rtl/tsan_posix.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/rtl/tsan_posix.cc similarity index 100% rename from src/compiler-rt/lib/tsan/tests/rtl/tsan_posix.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/rtl/tsan_posix.cc diff --git a/src/compiler-rt/lib/tsan/tests/rtl/tsan_posix_util.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/rtl/tsan_posix_util.h similarity index 100% rename from src/compiler-rt/lib/tsan/tests/rtl/tsan_posix_util.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/rtl/tsan_posix_util.h diff --git a/src/compiler-rt/lib/tsan/tests/rtl/tsan_string.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/rtl/tsan_string.cc similarity index 100% rename from src/compiler-rt/lib/tsan/tests/rtl/tsan_string.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/rtl/tsan_string.cc diff --git a/src/compiler-rt/lib/tsan/tests/rtl/tsan_test.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/rtl/tsan_test.cc similarity index 100% rename from src/compiler-rt/lib/tsan/tests/rtl/tsan_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/rtl/tsan_test.cc diff --git a/src/compiler-rt/lib/tsan/tests/rtl/tsan_test_util.h b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/rtl/tsan_test_util.h similarity index 100% rename from src/compiler-rt/lib/tsan/tests/rtl/tsan_test_util.h rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/rtl/tsan_test_util.h diff --git a/src/compiler-rt/lib/tsan/tests/rtl/tsan_test_util_posix.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/rtl/tsan_test_util_posix.cc similarity index 100% rename from src/compiler-rt/lib/tsan/tests/rtl/tsan_test_util_posix.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/rtl/tsan_test_util_posix.cc diff --git a/src/compiler-rt/lib/tsan/tests/rtl/tsan_thread.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/rtl/tsan_thread.cc similarity index 100% rename from src/compiler-rt/lib/tsan/tests/rtl/tsan_thread.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/rtl/tsan_thread.cc diff --git a/src/compiler-rt/lib/tsan/tests/unit/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/tsan/tests/unit/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/CMakeLists.txt diff --git a/src/compiler-rt/lib/tsan/tests/unit/tsan_clock_test.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/tsan_clock_test.cc similarity index 100% rename from src/compiler-rt/lib/tsan/tests/unit/tsan_clock_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/tsan_clock_test.cc diff --git a/src/compiler-rt/lib/tsan/tests/unit/tsan_dense_alloc_test.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/tsan_dense_alloc_test.cc similarity index 100% rename from src/compiler-rt/lib/tsan/tests/unit/tsan_dense_alloc_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/tsan_dense_alloc_test.cc diff --git a/src/compiler-rt/lib/tsan/tests/unit/tsan_flags_test.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/tsan_flags_test.cc similarity index 100% rename from src/compiler-rt/lib/tsan/tests/unit/tsan_flags_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/tsan_flags_test.cc diff --git a/src/compiler-rt/lib/tsan/tests/unit/tsan_mman_test.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/tsan_mman_test.cc similarity index 100% rename from src/compiler-rt/lib/tsan/tests/unit/tsan_mman_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/tsan_mman_test.cc diff --git a/src/compiler-rt/lib/tsan/tests/unit/tsan_mutex_test.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/tsan_mutex_test.cc similarity index 100% rename from src/compiler-rt/lib/tsan/tests/unit/tsan_mutex_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/tsan_mutex_test.cc diff --git a/src/compiler-rt/lib/tsan/tests/unit/tsan_mutexset_test.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/tsan_mutexset_test.cc similarity index 100% rename from src/compiler-rt/lib/tsan/tests/unit/tsan_mutexset_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/tsan_mutexset_test.cc diff --git a/src/compiler-rt/lib/tsan/tests/unit/tsan_shadow_test.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/tsan_shadow_test.cc similarity index 100% rename from src/compiler-rt/lib/tsan/tests/unit/tsan_shadow_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/tsan_shadow_test.cc diff --git a/src/compiler-rt/lib/tsan/tests/unit/tsan_stack_test.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/tsan_stack_test.cc similarity index 100% rename from src/compiler-rt/lib/tsan/tests/unit/tsan_stack_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/tsan_stack_test.cc diff --git a/src/compiler-rt/lib/tsan/tests/unit/tsan_sync_test.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/tsan_sync_test.cc similarity index 100% rename from src/compiler-rt/lib/tsan/tests/unit/tsan_sync_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/tsan_sync_test.cc diff --git a/src/compiler-rt/lib/tsan/tests/unit/tsan_unit_test_main.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/tsan_unit_test_main.cc similarity index 100% rename from src/compiler-rt/lib/tsan/tests/unit/tsan_unit_test_main.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/tsan_unit_test_main.cc diff --git a/src/compiler-rt/lib/tsan/tests/unit/tsan_vector_test.cc b/src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/tsan_vector_test.cc similarity index 100% rename from src/compiler-rt/lib/tsan/tests/unit/tsan_vector_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/tsan/tests/unit/tsan_vector_test.cc diff --git a/src/compiler-rt/lib/ubsan/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/ubsan/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/ubsan/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/CMakeLists.txt diff --git a/src/compiler-rt/lib/ubsan/ubsan.syms.extra b/src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan.syms.extra similarity index 100% rename from src/compiler-rt/lib/ubsan/ubsan.syms.extra rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan.syms.extra diff --git a/src/compiler-rt/lib/ubsan/ubsan_checks.inc b/src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_checks.inc similarity index 100% rename from src/compiler-rt/lib/ubsan/ubsan_checks.inc rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_checks.inc diff --git a/src/compiler-rt/lib/ubsan/ubsan_diag.cc b/src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_diag.cc similarity index 100% rename from src/compiler-rt/lib/ubsan/ubsan_diag.cc rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_diag.cc diff --git a/src/compiler-rt/lib/ubsan/ubsan_diag.h b/src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_diag.h similarity index 100% rename from src/compiler-rt/lib/ubsan/ubsan_diag.h rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_diag.h diff --git a/src/compiler-rt/lib/ubsan/ubsan_flags.cc b/src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_flags.cc similarity index 100% rename from src/compiler-rt/lib/ubsan/ubsan_flags.cc rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_flags.cc diff --git a/src/compiler-rt/lib/ubsan/ubsan_flags.h b/src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_flags.h similarity index 100% rename from src/compiler-rt/lib/ubsan/ubsan_flags.h rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_flags.h diff --git a/src/compiler-rt/lib/ubsan/ubsan_flags.inc b/src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_flags.inc similarity index 100% rename from src/compiler-rt/lib/ubsan/ubsan_flags.inc rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_flags.inc diff --git a/src/compiler-rt/lib/ubsan/ubsan_handlers.cc b/src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_handlers.cc similarity index 100% rename from src/compiler-rt/lib/ubsan/ubsan_handlers.cc rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_handlers.cc diff --git a/src/compiler-rt/lib/ubsan/ubsan_handlers.h b/src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_handlers.h similarity index 100% rename from src/compiler-rt/lib/ubsan/ubsan_handlers.h rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_handlers.h diff --git a/src/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc b/src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc similarity index 100% rename from src/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc diff --git a/src/compiler-rt/lib/ubsan/ubsan_handlers_cxx.h b/src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_handlers_cxx.h similarity index 100% rename from src/compiler-rt/lib/ubsan/ubsan_handlers_cxx.h rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_handlers_cxx.h diff --git a/src/compiler-rt/lib/ubsan/ubsan_init.cc b/src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_init.cc similarity index 100% rename from src/compiler-rt/lib/ubsan/ubsan_init.cc rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_init.cc diff --git a/src/compiler-rt/lib/ubsan/ubsan_init.h b/src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_init.h similarity index 100% rename from src/compiler-rt/lib/ubsan/ubsan_init.h rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_init.h diff --git a/src/compiler-rt/lib/ubsan/ubsan_init_standalone.cc b/src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_init_standalone.cc similarity index 100% rename from src/compiler-rt/lib/ubsan/ubsan_init_standalone.cc rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_init_standalone.cc diff --git a/src/compiler-rt/lib/ubsan/ubsan_platform.h b/src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_platform.h similarity index 100% rename from src/compiler-rt/lib/ubsan/ubsan_platform.h rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_platform.h diff --git a/src/compiler-rt/lib/ubsan/ubsan_type_hash.cc b/src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_type_hash.cc similarity index 100% rename from src/compiler-rt/lib/ubsan/ubsan_type_hash.cc rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_type_hash.cc diff --git a/src/compiler-rt/lib/ubsan/ubsan_type_hash.h b/src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_type_hash.h similarity index 100% rename from src/compiler-rt/lib/ubsan/ubsan_type_hash.h rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_type_hash.h diff --git a/src/compiler-rt/lib/ubsan/ubsan_type_hash_itanium.cc b/src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_type_hash_itanium.cc similarity index 100% rename from src/compiler-rt/lib/ubsan/ubsan_type_hash_itanium.cc rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_type_hash_itanium.cc diff --git a/src/compiler-rt/lib/ubsan/ubsan_type_hash_win.cc b/src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_type_hash_win.cc similarity index 100% rename from src/compiler-rt/lib/ubsan/ubsan_type_hash_win.cc rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_type_hash_win.cc diff --git a/src/compiler-rt/lib/ubsan/ubsan_value.cc b/src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_value.cc similarity index 100% rename from src/compiler-rt/lib/ubsan/ubsan_value.cc rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_value.cc diff --git a/src/compiler-rt/lib/ubsan/ubsan_value.h b/src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_value.h similarity index 100% rename from src/compiler-rt/lib/ubsan/ubsan_value.h rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/ubsan_value.h diff --git a/src/compiler-rt/lib/ubsan/weak_symbols.txt b/src/libcompiler_builtins/compiler-rt/lib/ubsan/weak_symbols.txt similarity index 100% rename from src/compiler-rt/lib/ubsan/weak_symbols.txt rename to src/libcompiler_builtins/compiler-rt/lib/ubsan/weak_symbols.txt diff --git a/src/compiler-rt/lib/xray/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/xray/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/xray/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/xray/CMakeLists.txt diff --git a/src/compiler-rt/lib/xray/tests/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/xray/tests/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/xray/tests/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/xray/tests/CMakeLists.txt diff --git a/src/compiler-rt/lib/xray/tests/unit/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/xray/tests/unit/CMakeLists.txt similarity index 100% rename from src/compiler-rt/lib/xray/tests/unit/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/lib/xray/tests/unit/CMakeLists.txt diff --git a/src/compiler-rt/lib/xray/tests/unit/buffer_queue_test.cc b/src/libcompiler_builtins/compiler-rt/lib/xray/tests/unit/buffer_queue_test.cc similarity index 100% rename from src/compiler-rt/lib/xray/tests/unit/buffer_queue_test.cc rename to src/libcompiler_builtins/compiler-rt/lib/xray/tests/unit/buffer_queue_test.cc diff --git a/src/compiler-rt/lib/xray/tests/unit/xray_unit_test_main.cc b/src/libcompiler_builtins/compiler-rt/lib/xray/tests/unit/xray_unit_test_main.cc similarity index 100% rename from src/compiler-rt/lib/xray/tests/unit/xray_unit_test_main.cc rename to src/libcompiler_builtins/compiler-rt/lib/xray/tests/unit/xray_unit_test_main.cc diff --git a/src/compiler-rt/lib/xray/xray_AArch64.cc b/src/libcompiler_builtins/compiler-rt/lib/xray/xray_AArch64.cc similarity index 100% rename from src/compiler-rt/lib/xray/xray_AArch64.cc rename to src/libcompiler_builtins/compiler-rt/lib/xray/xray_AArch64.cc diff --git a/src/compiler-rt/lib/xray/xray_arm.cc b/src/libcompiler_builtins/compiler-rt/lib/xray/xray_arm.cc similarity index 100% rename from src/compiler-rt/lib/xray/xray_arm.cc rename to src/libcompiler_builtins/compiler-rt/lib/xray/xray_arm.cc diff --git a/src/compiler-rt/lib/xray/xray_buffer_queue.cc b/src/libcompiler_builtins/compiler-rt/lib/xray/xray_buffer_queue.cc similarity index 100% rename from src/compiler-rt/lib/xray/xray_buffer_queue.cc rename to src/libcompiler_builtins/compiler-rt/lib/xray/xray_buffer_queue.cc diff --git a/src/compiler-rt/lib/xray/xray_buffer_queue.h b/src/libcompiler_builtins/compiler-rt/lib/xray/xray_buffer_queue.h similarity index 100% rename from src/compiler-rt/lib/xray/xray_buffer_queue.h rename to src/libcompiler_builtins/compiler-rt/lib/xray/xray_buffer_queue.h diff --git a/src/compiler-rt/lib/xray/xray_defs.h b/src/libcompiler_builtins/compiler-rt/lib/xray/xray_defs.h similarity index 100% rename from src/compiler-rt/lib/xray/xray_defs.h rename to src/libcompiler_builtins/compiler-rt/lib/xray/xray_defs.h diff --git a/src/compiler-rt/lib/xray/xray_emulate_tsc.h b/src/libcompiler_builtins/compiler-rt/lib/xray/xray_emulate_tsc.h similarity index 100% rename from src/compiler-rt/lib/xray/xray_emulate_tsc.h rename to src/libcompiler_builtins/compiler-rt/lib/xray/xray_emulate_tsc.h diff --git a/src/compiler-rt/lib/xray/xray_flags.cc b/src/libcompiler_builtins/compiler-rt/lib/xray/xray_flags.cc similarity index 100% rename from src/compiler-rt/lib/xray/xray_flags.cc rename to src/libcompiler_builtins/compiler-rt/lib/xray/xray_flags.cc diff --git a/src/compiler-rt/lib/xray/xray_flags.h b/src/libcompiler_builtins/compiler-rt/lib/xray/xray_flags.h similarity index 100% rename from src/compiler-rt/lib/xray/xray_flags.h rename to src/libcompiler_builtins/compiler-rt/lib/xray/xray_flags.h diff --git a/src/compiler-rt/lib/xray/xray_flags.inc b/src/libcompiler_builtins/compiler-rt/lib/xray/xray_flags.inc similarity index 100% rename from src/compiler-rt/lib/xray/xray_flags.inc rename to src/libcompiler_builtins/compiler-rt/lib/xray/xray_flags.inc diff --git a/src/compiler-rt/lib/xray/xray_init.cc b/src/libcompiler_builtins/compiler-rt/lib/xray/xray_init.cc similarity index 100% rename from src/compiler-rt/lib/xray/xray_init.cc rename to src/libcompiler_builtins/compiler-rt/lib/xray/xray_init.cc diff --git a/src/compiler-rt/lib/xray/xray_inmemory_log.cc b/src/libcompiler_builtins/compiler-rt/lib/xray/xray_inmemory_log.cc similarity index 100% rename from src/compiler-rt/lib/xray/xray_inmemory_log.cc rename to src/libcompiler_builtins/compiler-rt/lib/xray/xray_inmemory_log.cc diff --git a/src/compiler-rt/lib/xray/xray_interface.cc b/src/libcompiler_builtins/compiler-rt/lib/xray/xray_interface.cc similarity index 100% rename from src/compiler-rt/lib/xray/xray_interface.cc rename to src/libcompiler_builtins/compiler-rt/lib/xray/xray_interface.cc diff --git a/src/compiler-rt/lib/xray/xray_interface_internal.h b/src/libcompiler_builtins/compiler-rt/lib/xray/xray_interface_internal.h similarity index 100% rename from src/compiler-rt/lib/xray/xray_interface_internal.h rename to src/libcompiler_builtins/compiler-rt/lib/xray/xray_interface_internal.h diff --git a/src/compiler-rt/lib/xray/xray_trampoline_AArch64.S b/src/libcompiler_builtins/compiler-rt/lib/xray/xray_trampoline_AArch64.S similarity index 100% rename from src/compiler-rt/lib/xray/xray_trampoline_AArch64.S rename to src/libcompiler_builtins/compiler-rt/lib/xray/xray_trampoline_AArch64.S diff --git a/src/compiler-rt/lib/xray/xray_trampoline_arm.S b/src/libcompiler_builtins/compiler-rt/lib/xray/xray_trampoline_arm.S similarity index 100% rename from src/compiler-rt/lib/xray/xray_trampoline_arm.S rename to src/libcompiler_builtins/compiler-rt/lib/xray/xray_trampoline_arm.S diff --git a/src/compiler-rt/lib/xray/xray_trampoline_x86_64.S b/src/libcompiler_builtins/compiler-rt/lib/xray/xray_trampoline_x86_64.S similarity index 100% rename from src/compiler-rt/lib/xray/xray_trampoline_x86_64.S rename to src/libcompiler_builtins/compiler-rt/lib/xray/xray_trampoline_x86_64.S diff --git a/src/compiler-rt/lib/xray/xray_x86_64.cc b/src/libcompiler_builtins/compiler-rt/lib/xray/xray_x86_64.cc similarity index 100% rename from src/compiler-rt/lib/xray/xray_x86_64.cc rename to src/libcompiler_builtins/compiler-rt/lib/xray/xray_x86_64.cc diff --git a/src/compiler-rt/lib/xray/xray_x86_64.h b/src/libcompiler_builtins/compiler-rt/lib/xray/xray_x86_64.h similarity index 100% rename from src/compiler-rt/lib/xray/xray_x86_64.h rename to src/libcompiler_builtins/compiler-rt/lib/xray/xray_x86_64.h diff --git a/src/compiler-rt/test/BlocksRuntime/block-static.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/block-static.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/block-static.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/block-static.c diff --git a/src/compiler-rt/test/BlocksRuntime/blockimport.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/blockimport.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/blockimport.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/blockimport.c diff --git a/src/compiler-rt/test/BlocksRuntime/byrefaccess.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/byrefaccess.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/byrefaccess.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/byrefaccess.c diff --git a/src/compiler-rt/test/BlocksRuntime/byrefcopy.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/byrefcopy.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/byrefcopy.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/byrefcopy.c diff --git a/src/compiler-rt/test/BlocksRuntime/byrefcopycopy.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/byrefcopycopy.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/byrefcopycopy.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/byrefcopycopy.c diff --git a/src/compiler-rt/test/BlocksRuntime/byrefcopyinner.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/byrefcopyinner.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/byrefcopyinner.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/byrefcopyinner.c diff --git a/src/compiler-rt/test/BlocksRuntime/byrefcopyint.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/byrefcopyint.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/byrefcopyint.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/byrefcopyint.c diff --git a/src/compiler-rt/test/BlocksRuntime/byrefcopystack.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/byrefcopystack.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/byrefcopystack.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/byrefcopystack.c diff --git a/src/compiler-rt/test/BlocksRuntime/byrefsanity.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/byrefsanity.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/byrefsanity.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/byrefsanity.c diff --git a/src/compiler-rt/test/BlocksRuntime/byrefstruct.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/byrefstruct.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/byrefstruct.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/byrefstruct.c diff --git a/src/compiler-rt/test/BlocksRuntime/c99.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/c99.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/c99.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/c99.c diff --git a/src/compiler-rt/test/BlocksRuntime/cast.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/cast.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/cast.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/cast.c diff --git a/src/compiler-rt/test/BlocksRuntime/constassign.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/constassign.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/constassign.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/constassign.c diff --git a/src/compiler-rt/test/BlocksRuntime/copy-block-literal-rdar6439600.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/copy-block-literal-rdar6439600.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/copy-block-literal-rdar6439600.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/copy-block-literal-rdar6439600.c diff --git a/src/compiler-rt/test/BlocksRuntime/copyconstructor.C b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/copyconstructor.C similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/copyconstructor.C rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/copyconstructor.C diff --git a/src/compiler-rt/test/BlocksRuntime/copynull.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/copynull.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/copynull.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/copynull.c diff --git a/src/compiler-rt/test/BlocksRuntime/dispatch_async.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/dispatch_async.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/dispatch_async.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/dispatch_async.c diff --git a/src/compiler-rt/test/BlocksRuntime/dispatch_call_Block_with_release.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/dispatch_call_Block_with_release.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/dispatch_call_Block_with_release.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/dispatch_call_Block_with_release.c diff --git a/src/compiler-rt/test/BlocksRuntime/fail.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/fail.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/fail.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/fail.c diff --git a/src/compiler-rt/test/BlocksRuntime/flagsisa.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/flagsisa.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/flagsisa.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/flagsisa.c diff --git a/src/compiler-rt/test/BlocksRuntime/globalexpression.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/globalexpression.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/globalexpression.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/globalexpression.c diff --git a/src/compiler-rt/test/BlocksRuntime/goto.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/goto.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/goto.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/goto.c diff --git a/src/compiler-rt/test/BlocksRuntime/hasdescriptor.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/hasdescriptor.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/hasdescriptor.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/hasdescriptor.c diff --git a/src/compiler-rt/test/BlocksRuntime/josh.C b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/josh.C similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/josh.C rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/josh.C diff --git a/src/compiler-rt/test/BlocksRuntime/k-and-r.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/k-and-r.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/k-and-r.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/k-and-r.c diff --git a/src/compiler-rt/test/BlocksRuntime/large-struct.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/large-struct.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/large-struct.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/large-struct.c diff --git a/src/compiler-rt/test/BlocksRuntime/localisglobal.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/localisglobal.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/localisglobal.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/localisglobal.c diff --git a/src/compiler-rt/test/BlocksRuntime/macro.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/macro.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/macro.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/macro.c diff --git a/src/compiler-rt/test/BlocksRuntime/makefile b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/makefile similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/makefile rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/makefile diff --git a/src/compiler-rt/test/BlocksRuntime/modglobal.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/modglobal.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/modglobal.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/modglobal.c diff --git a/src/compiler-rt/test/BlocksRuntime/nestedimport.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/nestedimport.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/nestedimport.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/nestedimport.c diff --git a/src/compiler-rt/test/BlocksRuntime/nullblockisa.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/nullblockisa.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/nullblockisa.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/nullblockisa.c diff --git a/src/compiler-rt/test/BlocksRuntime/objectRRGC.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/objectRRGC.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/objectRRGC.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/objectRRGC.c diff --git a/src/compiler-rt/test/BlocksRuntime/objectassign.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/objectassign.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/objectassign.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/objectassign.c diff --git a/src/compiler-rt/test/BlocksRuntime/orbars.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/orbars.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/orbars.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/orbars.c diff --git a/src/compiler-rt/test/BlocksRuntime/rdar6396238.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/rdar6396238.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/rdar6396238.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/rdar6396238.c diff --git a/src/compiler-rt/test/BlocksRuntime/rdar6405500.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/rdar6405500.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/rdar6405500.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/rdar6405500.c diff --git a/src/compiler-rt/test/BlocksRuntime/rdar6414583.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/rdar6414583.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/rdar6414583.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/rdar6414583.c diff --git a/src/compiler-rt/test/BlocksRuntime/recursive-block.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/recursive-block.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/recursive-block.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/recursive-block.c diff --git a/src/compiler-rt/test/BlocksRuntime/recursive-test.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/recursive-test.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/recursive-test.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/recursive-test.c diff --git a/src/compiler-rt/test/BlocksRuntime/recursiveassign.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/recursiveassign.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/recursiveassign.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/recursiveassign.c diff --git a/src/compiler-rt/test/BlocksRuntime/reference.C b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/reference.C similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/reference.C rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/reference.C diff --git a/src/compiler-rt/test/BlocksRuntime/rettypepromotion.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/rettypepromotion.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/rettypepromotion.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/rettypepromotion.c diff --git a/src/compiler-rt/test/BlocksRuntime/returnfunctionptr.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/returnfunctionptr.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/returnfunctionptr.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/returnfunctionptr.c diff --git a/src/compiler-rt/test/BlocksRuntime/shorthandexpression.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/shorthandexpression.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/shorthandexpression.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/shorthandexpression.c diff --git a/src/compiler-rt/test/BlocksRuntime/sizeof.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/sizeof.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/sizeof.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/sizeof.c diff --git a/src/compiler-rt/test/BlocksRuntime/small-struct.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/small-struct.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/small-struct.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/small-struct.c diff --git a/src/compiler-rt/test/BlocksRuntime/structmember.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/structmember.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/structmember.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/structmember.c diff --git a/src/compiler-rt/test/BlocksRuntime/testfilerunner.h b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/testfilerunner.h similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/testfilerunner.h rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/testfilerunner.h diff --git a/src/compiler-rt/test/BlocksRuntime/testfilerunner.m b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/testfilerunner.m similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/testfilerunner.m rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/testfilerunner.m diff --git a/src/compiler-rt/test/BlocksRuntime/varargs-bad-assign.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/varargs-bad-assign.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/varargs-bad-assign.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/varargs-bad-assign.c diff --git a/src/compiler-rt/test/BlocksRuntime/varargs.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/varargs.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/varargs.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/varargs.c diff --git a/src/compiler-rt/test/BlocksRuntime/variadic.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/variadic.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/variadic.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/variadic.c diff --git a/src/compiler-rt/test/BlocksRuntime/voidarg.c b/src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/voidarg.c similarity index 100% rename from src/compiler-rt/test/BlocksRuntime/voidarg.c rename to src/libcompiler_builtins/compiler-rt/test/BlocksRuntime/voidarg.c diff --git a/src/compiler-rt/test/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/test/CMakeLists.txt similarity index 100% rename from src/compiler-rt/test/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/test/CMakeLists.txt diff --git a/src/compiler-rt/test/asan/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/test/asan/CMakeLists.txt similarity index 100% rename from src/compiler-rt/test/asan/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/test/asan/CMakeLists.txt diff --git a/src/compiler-rt/test/asan/TestCases/Android/coverage-android.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Android/coverage-android.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Android/coverage-android.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Android/coverage-android.cc diff --git a/src/compiler-rt/test/asan/TestCases/Android/lit.local.cfg b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Android/lit.local.cfg similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Android/lit.local.cfg rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Android/lit.local.cfg diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/abort_on_error.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/abort_on_error.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/abort_on_error.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/abort_on_error.cc diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/address-range-limit.mm b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/address-range-limit.mm similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/address-range-limit.mm rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/address-range-limit.mm diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/asan_gen_prefixes.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/asan_gen_prefixes.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/asan_gen_prefixes.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/asan_gen_prefixes.cc diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/atos-symbolizer-dyld-root-path.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/atos-symbolizer-dyld-root-path.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/atos-symbolizer-dyld-root-path.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/atos-symbolizer-dyld-root-path.cc diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/atos-symbolizer.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/atos-symbolizer.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/atos-symbolizer.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/atos-symbolizer.cc diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/crashlog-stacktraces.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/crashlog-stacktraces.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/crashlog-stacktraces.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/crashlog-stacktraces.c diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/cstring_literals_regtest.mm b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/cstring_literals_regtest.mm similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/cstring_literals_regtest.mm rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/cstring_literals_regtest.mm diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/cstring_section.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/cstring_section.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/cstring_section.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/cstring_section.c diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/dead-strip.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/dead-strip.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/dead-strip.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/dead-strip.c diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/dladdr-demangling.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/dladdr-demangling.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/dladdr-demangling.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/dladdr-demangling.cc diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/dump_registers.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/dump_registers.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/dump_registers.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/dump_registers.cc diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/dyld_insert_libraries_reexec.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/dyld_insert_libraries_reexec.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/dyld_insert_libraries_reexec.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/dyld_insert_libraries_reexec.cc diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/dyld_insert_libraries_remove.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/dyld_insert_libraries_remove.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/dyld_insert_libraries_remove.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/dyld_insert_libraries_remove.cc diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/empty-section.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/empty-section.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/empty-section.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/empty-section.cc diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/haswell-symbolication.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/haswell-symbolication.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/haswell-symbolication.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/haswell-symbolication.cc diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/interface_symbols_darwin.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/interface_symbols_darwin.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/interface_symbols_darwin.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/interface_symbols_darwin.c diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/linked-only.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/linked-only.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/linked-only.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/linked-only.cc diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/lit.local.cfg b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/lit.local.cfg similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/lit.local.cfg rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/lit.local.cfg diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/malloc_destroy_zone.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/malloc_destroy_zone.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/malloc_destroy_zone.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/malloc_destroy_zone.cc diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/malloc_set_zone_name-mprotect.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/malloc_set_zone_name-mprotect.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/malloc_set_zone_name-mprotect.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/malloc_set_zone_name-mprotect.cc diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/malloc_size_crash.mm b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/malloc_size_crash.mm similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/malloc_size_crash.mm rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/malloc_size_crash.mm diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/malloc_zone-protected.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/malloc_zone-protected.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/malloc_zone-protected.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/malloc_zone-protected.cc diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/mixing-global-constructors.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/mixing-global-constructors.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/mixing-global-constructors.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/mixing-global-constructors.cc diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/objc-odr.mm b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/objc-odr.mm similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/objc-odr.mm rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/objc-odr.mm diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/odr-lto.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/odr-lto.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/odr-lto.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/odr-lto.cc diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/reexec-insert-libraries-env.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/reexec-insert-libraries-env.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/reexec-insert-libraries-env.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/reexec-insert-libraries-env.cc diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/sandbox-symbolizer.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/sandbox-symbolizer.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/sandbox-symbolizer.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/sandbox-symbolizer.cc diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/segv_read_write.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/segv_read_write.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/segv_read_write.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/segv_read_write.c diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/suppressions-darwin.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/suppressions-darwin.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/suppressions-darwin.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/suppressions-darwin.cc diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/suppressions-sandbox.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/suppressions-sandbox.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/suppressions-sandbox.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/suppressions-sandbox.cc diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/unset-insert-libraries-on-exec.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/unset-insert-libraries-on-exec.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/unset-insert-libraries-on-exec.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/unset-insert-libraries-on-exec.cc diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/uuid.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/uuid.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Darwin/uuid.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Darwin/uuid.cc diff --git a/src/compiler-rt/test/asan/TestCases/Helpers/blacklist-extra.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Helpers/blacklist-extra.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Helpers/blacklist-extra.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Helpers/blacklist-extra.cc diff --git a/src/compiler-rt/test/asan/TestCases/Helpers/echo-env.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Helpers/echo-env.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Helpers/echo-env.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Helpers/echo-env.cc diff --git a/src/compiler-rt/test/asan/TestCases/Helpers/init-order-atexit-extra.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Helpers/init-order-atexit-extra.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Helpers/init-order-atexit-extra.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Helpers/init-order-atexit-extra.cc diff --git a/src/compiler-rt/test/asan/TestCases/Helpers/initialization-blacklist-extra.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Helpers/initialization-blacklist-extra.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Helpers/initialization-blacklist-extra.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Helpers/initialization-blacklist-extra.cc diff --git a/src/compiler-rt/test/asan/TestCases/Helpers/initialization-blacklist-extra2.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Helpers/initialization-blacklist-extra2.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Helpers/initialization-blacklist-extra2.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Helpers/initialization-blacklist-extra2.cc diff --git a/src/compiler-rt/test/asan/TestCases/Helpers/initialization-blacklist.txt b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Helpers/initialization-blacklist.txt similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Helpers/initialization-blacklist.txt rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Helpers/initialization-blacklist.txt diff --git a/src/compiler-rt/test/asan/TestCases/Helpers/initialization-bug-extra.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Helpers/initialization-bug-extra.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Helpers/initialization-bug-extra.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Helpers/initialization-bug-extra.cc diff --git a/src/compiler-rt/test/asan/TestCases/Helpers/initialization-bug-extra2.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Helpers/initialization-bug-extra2.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Helpers/initialization-bug-extra2.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Helpers/initialization-bug-extra2.cc diff --git a/src/compiler-rt/test/asan/TestCases/Helpers/initialization-constexpr-extra.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Helpers/initialization-constexpr-extra.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Helpers/initialization-constexpr-extra.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Helpers/initialization-constexpr-extra.cc diff --git a/src/compiler-rt/test/asan/TestCases/Helpers/initialization-nobug-extra.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Helpers/initialization-nobug-extra.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Helpers/initialization-nobug-extra.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Helpers/initialization-nobug-extra.cc diff --git a/src/compiler-rt/test/asan/TestCases/Helpers/lit.local.cfg b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Helpers/lit.local.cfg similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Helpers/lit.local.cfg rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Helpers/lit.local.cfg diff --git a/src/compiler-rt/test/asan/TestCases/Linux/abort_on_error.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/abort_on_error.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/abort_on_error.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/abort_on_error.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/activation-options.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/activation-options.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/activation-options.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/activation-options.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/asan-asm-stacktrace-test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/asan-asm-stacktrace-test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/asan-asm-stacktrace-test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/asan-asm-stacktrace-test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/asan_default_suppressions.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/asan_default_suppressions.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/asan_default_suppressions.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/asan_default_suppressions.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/asan_dlopen_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/asan_dlopen_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/asan_dlopen_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/asan_dlopen_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/asan_prelink_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/asan_prelink_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/asan_prelink_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/asan_prelink_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/asan_preload_test-1.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/asan_preload_test-1.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/asan_preload_test-1.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/asan_preload_test-1.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/asan_preload_test-2.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/asan_preload_test-2.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/asan_preload_test-2.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/asan_preload_test-2.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/asan_rt_confict_test-1.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/asan_rt_confict_test-1.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/asan_rt_confict_test-1.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/asan_rt_confict_test-1.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/asan_rt_confict_test-2.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/asan_rt_confict_test-2.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/asan_rt_confict_test-2.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/asan_rt_confict_test-2.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/auto_memory_profile_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/auto_memory_profile_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/auto_memory_profile_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/auto_memory_profile_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/calloc-preload.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/calloc-preload.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/calloc-preload.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/calloc-preload.c diff --git a/src/compiler-rt/test/asan/TestCases/Linux/clang_gcc_abi.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/clang_gcc_abi.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/clang_gcc_abi.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/clang_gcc_abi.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/clone_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/clone_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/clone_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/clone_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/coverage-missing.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/coverage-missing.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/coverage-missing.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/coverage-missing.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/cuda_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/cuda_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/cuda_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/cuda_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/function-sections-are-bad.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/function-sections-are-bad.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/function-sections-are-bad.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/function-sections-are-bad.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/globals-gc-sections.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/globals-gc-sections.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/globals-gc-sections.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/globals-gc-sections.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/init-order-dlopen.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/init-order-dlopen.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/init-order-dlopen.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/init-order-dlopen.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/init_fini_sections.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/init_fini_sections.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/init_fini_sections.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/init_fini_sections.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/initialization-bug-any-order.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/initialization-bug-any-order.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/initialization-bug-any-order.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/initialization-bug-any-order.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/interception_malloc_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/interception_malloc_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/interception_malloc_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/interception_malloc_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/interception_readdir_r_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/interception_readdir_r_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/interception_readdir_r_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/interception_readdir_r_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/interception_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/interception_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/interception_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/interception_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.c diff --git a/src/compiler-rt/test/asan/TestCases/Linux/kernel-area.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/kernel-area.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/kernel-area.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/kernel-area.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/leak.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/leak.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/leak.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/leak.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/leak_check_segv.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/leak_check_segv.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/leak_check_segv.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/leak_check_segv.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/lit.local.cfg b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/lit.local.cfg similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/lit.local.cfg rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/lit.local.cfg diff --git a/src/compiler-rt/test/asan/TestCases/Linux/local_alias.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/local_alias.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/local_alias.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/local_alias.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/malloc-in-qsort.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/malloc-in-qsort.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/malloc-in-qsort.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/malloc-in-qsort.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/malloc_delete_mismatch.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/malloc_delete_mismatch.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/malloc_delete_mismatch.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/malloc_delete_mismatch.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/memmem_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/memmem_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/memmem_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/memmem_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/mincore.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/mincore.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/mincore.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/mincore.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/new_delete_mismatch.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/new_delete_mismatch.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/new_delete_mismatch.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/new_delete_mismatch.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/nohugepage_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/nohugepage_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/nohugepage_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/nohugepage_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/odr-violation.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/odr-violation.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/odr-violation.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/odr-violation.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/odr_c_test.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/odr_c_test.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/odr_c_test.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/odr_c_test.c diff --git a/src/compiler-rt/test/asan/TestCases/Linux/overflow-in-qsort.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/overflow-in-qsort.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/overflow-in-qsort.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/overflow-in-qsort.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/preinit_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/preinit_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/preinit_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/preinit_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/print_memory_profile_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/print_memory_profile_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/print_memory_profile_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/print_memory_profile_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/pthread_create_from_constructor.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/pthread_create_from_constructor.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/pthread_create_from_constructor.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/pthread_create_from_constructor.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/pthread_create_version.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/pthread_create_version.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/pthread_create_version.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/pthread_create_version.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/ptrace.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/ptrace.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/ptrace.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/ptrace.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/quarantine_size_mb.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/quarantine_size_mb.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/quarantine_size_mb.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/quarantine_size_mb.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/read_binary_name_regtest.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/read_binary_name_regtest.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/read_binary_name_regtest.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/read_binary_name_regtest.c diff --git a/src/compiler-rt/test/asan/TestCases/Linux/recvfrom.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/recvfrom.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/recvfrom.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/recvfrom.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/release_to_os_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/release_to_os_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/release_to_os_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/release_to_os_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/rlimit_mmap_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/rlimit_mmap_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/rlimit_mmap_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/rlimit_mmap_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/segv_read_write.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/segv_read_write.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/segv_read_write.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/segv_read_write.c diff --git a/src/compiler-rt/test/asan/TestCases/Linux/shmctl.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/shmctl.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/shmctl.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/shmctl.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/signal_during_stop_the_world.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/signal_during_stop_the_world.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/signal_during_stop_the_world.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/signal_during_stop_the_world.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/sized_delete_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/sized_delete_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/sized_delete_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/sized_delete_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/stack-overflow-recovery-mode.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/stack-overflow-recovery-mode.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/stack-overflow-recovery-mode.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/stack-overflow-recovery-mode.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/stack-overflow-sigbus.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/stack-overflow-sigbus.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/stack-overflow-sigbus.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/stack-overflow-sigbus.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/stack-trace-dlclose.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/stack-trace-dlclose.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/stack-trace-dlclose.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/stack-trace-dlclose.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/static_tls.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/static_tls.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/static_tls.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/static_tls.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/stress_dtls.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/stress_dtls.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/stress_dtls.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/stress_dtls.c diff --git a/src/compiler-rt/test/asan/TestCases/Linux/swapcontext_annotation.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/swapcontext_annotation.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/swapcontext_annotation.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/swapcontext_annotation.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/swapcontext_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/swapcontext_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/swapcontext_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/swapcontext_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/syscalls.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/syscalls.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/syscalls.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/syscalls.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/thread_local_quarantine_size_kb.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/thread_local_quarantine_size_kb.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/thread_local_quarantine_size_kb.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/thread_local_quarantine_size_kb.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/uar_signals.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/uar_signals.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/uar_signals.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/uar_signals.cc diff --git a/src/compiler-rt/test/asan/TestCases/Linux/unpoison_tls.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/unpoison_tls.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Linux/unpoison_tls.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Linux/unpoison_tls.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/allow_user_segv.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/allow_user_segv.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/allow_user_segv.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/allow_user_segv.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/asan-symbolize-bad-path.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/asan-symbolize-bad-path.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/asan-symbolize-bad-path.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/asan-symbolize-bad-path.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/asprintf.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/asprintf.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/asprintf.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/asprintf.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/assign_large_valloc_to_global.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/assign_large_valloc_to_global.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/assign_large_valloc_to_global.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/assign_large_valloc_to_global.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/closed-fds.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/closed-fds.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/closed-fds.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/closed-fds.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/coverage-caller-callee.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/coverage-caller-callee.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/coverage-caller-callee.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/coverage-caller-callee.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/coverage-direct-activation.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/coverage-direct-activation.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/coverage-direct-activation.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/coverage-direct-activation.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/coverage-direct-large.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/coverage-direct-large.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/coverage-direct-large.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/coverage-direct-large.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/coverage-direct.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/coverage-direct.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/coverage-direct.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/coverage-direct.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/coverage-fork-direct.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/coverage-fork-direct.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/coverage-fork-direct.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/coverage-fork-direct.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/coverage-fork.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/coverage-fork.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/coverage-fork.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/coverage-fork.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/coverage-maybe-open-file.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/coverage-maybe-open-file.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/coverage-maybe-open-file.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/coverage-maybe-open-file.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/coverage-module-unloaded.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/coverage-module-unloaded.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/coverage-module-unloaded.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/coverage-module-unloaded.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/coverage-sandboxing.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/coverage-sandboxing.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/coverage-sandboxing.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/coverage-sandboxing.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/coverage.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/coverage.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/coverage.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/coverage.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/current_allocated_bytes.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/current_allocated_bytes.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/current_allocated_bytes.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/current_allocated_bytes.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/deep_call_stack.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/deep_call_stack.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/deep_call_stack.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/deep_call_stack.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/deep_thread_stack.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/deep_thread_stack.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/deep_thread_stack.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/deep_thread_stack.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/dlclose-test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/dlclose-test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/dlclose-test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/dlclose-test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/dump_instruction_bytes.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/dump_instruction_bytes.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/dump_instruction_bytes.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/dump_instruction_bytes.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/free_hook_realloc.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/free_hook_realloc.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/free_hook_realloc.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/free_hook_realloc.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/freopen.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/freopen.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/freopen.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/freopen.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/gc-test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/gc-test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/gc-test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/gc-test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/glob.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/glob.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/glob.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/glob.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/glob_test_root/aa b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/glob_test_root/aa similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/glob_test_root/aa rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/glob_test_root/aa diff --git a/src/compiler-rt/test/asan/TestCases/Posix/glob_test_root/ab b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/glob_test_root/ab similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/glob_test_root/ab rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/glob_test_root/ab diff --git a/src/compiler-rt/test/asan/TestCases/Posix/glob_test_root/ba b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/glob_test_root/ba similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/glob_test_root/ba rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/glob_test_root/ba diff --git a/src/compiler-rt/test/asan/TestCases/Posix/global-registration.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/global-registration.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/global-registration.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/global-registration.c diff --git a/src/compiler-rt/test/asan/TestCases/Posix/halt_on_error-signals.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/halt_on_error-signals.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/halt_on_error-signals.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/halt_on_error-signals.c diff --git a/src/compiler-rt/test/asan/TestCases/Posix/halt_on_error-torture.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/halt_on_error-torture.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/halt_on_error-torture.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/halt_on_error-torture.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/handle_abort_on_error.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/handle_abort_on_error.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/handle_abort_on_error.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/handle_abort_on_error.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/init-order-pthread-create.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/init-order-pthread-create.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/init-order-pthread-create.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/init-order-pthread-create.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/interception-in-shared-lib-test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/interception-in-shared-lib-test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/interception-in-shared-lib-test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/interception-in-shared-lib-test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/ioctl.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/ioctl.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/ioctl.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/ioctl.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/large_allocator_unpoisons_on_free.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/large_allocator_unpoisons_on_free.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/large_allocator_unpoisons_on_free.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/large_allocator_unpoisons_on_free.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/lit.local.cfg b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/lit.local.cfg similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/lit.local.cfg rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/lit.local.cfg diff --git a/src/compiler-rt/test/asan/TestCases/Posix/log_path_fork_test.cc.disabled b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/log_path_fork_test.cc.disabled similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/log_path_fork_test.cc.disabled rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/log_path_fork_test.cc.disabled diff --git a/src/compiler-rt/test/asan/TestCases/Posix/mmap_limit_mb.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/mmap_limit_mb.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/mmap_limit_mb.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/mmap_limit_mb.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/new_array_cookie_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/new_array_cookie_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/new_array_cookie_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/new_array_cookie_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/no_asan_gen_globals.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/no_asan_gen_globals.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/no_asan_gen_globals.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/no_asan_gen_globals.c diff --git a/src/compiler-rt/test/asan/TestCases/Posix/print_cmdline.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/print_cmdline.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/print_cmdline.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/print_cmdline.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/readv.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/readv.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/readv.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/readv.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/shared-lib-test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/shared-lib-test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/shared-lib-test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/shared-lib-test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/stack-overflow.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/stack-overflow.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/stack-overflow.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/stack-overflow.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/stack-use-after-return.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/stack-use-after-return.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/stack-use-after-return.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/stack-use-after-return.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/start-deactivated.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/start-deactivated.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/start-deactivated.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/start-deactivated.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/strerror_r_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/strerror_r_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/strerror_r_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/strerror_r_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/tsd_dtor_leak.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/tsd_dtor_leak.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/tsd_dtor_leak.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/tsd_dtor_leak.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/wait.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/wait.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/wait.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/wait.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/wait3.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/wait3.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/wait3.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/wait3.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/wait4.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/wait4.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/wait4.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/wait4.cc diff --git a/src/compiler-rt/test/asan/TestCases/Posix/waitid.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/waitid.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Posix/waitid.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Posix/waitid.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/aligned_mallocs.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/aligned_mallocs.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/aligned_mallocs.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/aligned_mallocs.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/allocators_sanity.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/allocators_sanity.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/allocators_sanity.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/allocators_sanity.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/beginthreadex.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/beginthreadex.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/beginthreadex.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/beginthreadex.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/bind_io_completion_callback.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/bind_io_completion_callback.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/bind_io_completion_callback.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/bind_io_completion_callback.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/bitfield.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/bitfield.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/bitfield.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/bitfield.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/bitfield_uaf.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/bitfield_uaf.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/bitfield_uaf.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/bitfield_uaf.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/calloc_left_oob.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/calloc_left_oob.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/calloc_left_oob.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/calloc_left_oob.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/calloc_right_oob.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/calloc_right_oob.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/calloc_right_oob.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/calloc_right_oob.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/calloc_uaf.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/calloc_uaf.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/calloc_uaf.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/calloc_uaf.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/coverage-basic.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/coverage-basic.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/coverage-basic.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/coverage-basic.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/coverage-dll-stdio.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/coverage-dll-stdio.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/coverage-dll-stdio.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/coverage-dll-stdio.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/crash_read_write.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/crash_read_write.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/crash_read_write.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/crash_read_write.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/crt_initializers.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/crt_initializers.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/crt_initializers.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/crt_initializers.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/delay_dbghelp.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/delay_dbghelp.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/delay_dbghelp.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/delay_dbghelp.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/demangled_names.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/demangled_names.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/demangled_names.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/demangled_names.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_aligned_mallocs.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_aligned_mallocs.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_aligned_mallocs.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_aligned_mallocs.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_allocators_sanity.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_allocators_sanity.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_allocators_sanity.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_allocators_sanity.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_and_lib.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_and_lib.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_and_lib.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_and_lib.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_cerr.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_cerr.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_cerr.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_cerr.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_control_c.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_control_c.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_control_c.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_control_c.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_global_dead_strip.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_global_dead_strip.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_global_dead_strip.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_global_dead_strip.c diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_host.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_host.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_host.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_host.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_intercept_memchr.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_intercept_memchr.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_intercept_memchr.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_intercept_memchr.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_intercept_memcpy.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_intercept_memcpy.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_intercept_memcpy.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_intercept_memcpy.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_intercept_memcpy_indirect.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_intercept_memcpy_indirect.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_intercept_memcpy_indirect.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_intercept_memcpy_indirect.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_intercept_memset.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_intercept_memset.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_intercept_memset.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_intercept_memset.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_intercept_strlen.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_intercept_strlen.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_intercept_strlen.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_intercept_strlen.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_large_function.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_large_function.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_large_function.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_large_function.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_malloc_left_oob.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_malloc_left_oob.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_malloc_left_oob.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_malloc_left_oob.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_malloc_uaf.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_malloc_uaf.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_malloc_uaf.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_malloc_uaf.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_noreturn.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_noreturn.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_noreturn.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_noreturn.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_null_deref.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_null_deref.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_null_deref.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_null_deref.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_operator_array_new_left_oob.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_operator_array_new_left_oob.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_operator_array_new_left_oob.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_operator_array_new_left_oob.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_operator_array_new_with_dtor_left_oob.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_operator_array_new_with_dtor_left_oob.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_operator_array_new_with_dtor_left_oob.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_operator_array_new_with_dtor_left_oob.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_poison_unpoison.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_poison_unpoison.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_poison_unpoison.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_poison_unpoison.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_report_globals_symbolization_at_startup.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_report_globals_symbolization_at_startup.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_report_globals_symbolization_at_startup.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_report_globals_symbolization_at_startup.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_seh.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_seh.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_seh.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_seh.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_stack_use_after_return.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_stack_use_after_return.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_stack_use_after_return.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_stack_use_after_return.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/dll_thread_stack_array_left_oob.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_thread_stack_array_left_oob.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/dll_thread_stack_array_left_oob.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/dll_thread_stack_array_left_oob.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/double_free.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/double_free.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/double_free.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/double_free.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/double_operator_delete.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/double_operator_delete.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/double_operator_delete.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/double_operator_delete.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/free_hook_realloc.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/free_hook_realloc.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/free_hook_realloc.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/free_hook_realloc.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/fuse-lld.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/fuse-lld.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/fuse-lld.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/fuse-lld.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/global_const_string.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/global_const_string.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/global_const_string.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/global_const_string.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/global_const_string_oob.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/global_const_string_oob.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/global_const_string_oob.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/global_const_string_oob.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/global_dead_strip.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/global_dead_strip.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/global_dead_strip.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/global_dead_strip.c diff --git a/src/compiler-rt/test/asan/TestCases/Windows/hello_world.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/hello_world.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/hello_world.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/hello_world.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/intercept_memcpy.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/intercept_memcpy.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/intercept_memcpy.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/intercept_memcpy.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/intercept_strdup.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/intercept_strdup.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/intercept_strdup.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/intercept_strdup.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/intercept_strlen.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/intercept_strlen.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/intercept_strlen.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/intercept_strlen.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/iostream_sbo.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/iostream_sbo.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/iostream_sbo.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/iostream_sbo.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/lit.local.cfg b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/lit.local.cfg similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/lit.local.cfg rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/lit.local.cfg diff --git a/src/compiler-rt/test/asan/TestCases/Windows/longjmp.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/longjmp.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/longjmp.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/longjmp.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/malloc_left_oob.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/malloc_left_oob.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/malloc_left_oob.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/malloc_left_oob.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/malloc_right_oob.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/malloc_right_oob.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/malloc_right_oob.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/malloc_right_oob.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/malloc_uaf.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/malloc_uaf.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/malloc_uaf.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/malloc_uaf.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/null_deref.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/null_deref.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/null_deref.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/null_deref.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/null_deref_multiple_dlls.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/null_deref_multiple_dlls.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/null_deref_multiple_dlls.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/null_deref_multiple_dlls.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/oom.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/oom.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/oom.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/oom.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/operator_array_new_left_oob.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/operator_array_new_left_oob.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/operator_array_new_left_oob.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/operator_array_new_left_oob.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/operator_array_new_right_oob.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/operator_array_new_right_oob.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/operator_array_new_right_oob.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/operator_array_new_right_oob.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/operator_array_new_uaf.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/operator_array_new_uaf.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/operator_array_new_uaf.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/operator_array_new_uaf.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/operator_delete_wrong_argument.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/operator_delete_wrong_argument.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/operator_delete_wrong_argument.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/operator_delete_wrong_argument.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/operator_new_left_oob.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/operator_new_left_oob.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/operator_new_left_oob.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/operator_new_left_oob.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/operator_new_right_oob.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/operator_new_right_oob.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/operator_new_right_oob.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/operator_new_right_oob.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/operator_new_uaf.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/operator_new_uaf.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/operator_new_uaf.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/operator_new_uaf.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/queue_user_work_item.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/queue_user_work_item.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/queue_user_work_item.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/queue_user_work_item.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/queue_user_work_item_report.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/queue_user_work_item_report.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/queue_user_work_item_report.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/queue_user_work_item_report.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/realloc_left_oob.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/realloc_left_oob.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/realloc_left_oob.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/realloc_left_oob.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/realloc_right_oob.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/realloc_right_oob.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/realloc_right_oob.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/realloc_right_oob.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/realloc_uaf.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/realloc_uaf.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/realloc_uaf.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/realloc_uaf.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/report_after_syminitialize.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/report_after_syminitialize.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/report_after_syminitialize.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/report_after_syminitialize.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/report_globals_reload_dll.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/report_globals_reload_dll.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/report_globals_reload_dll.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/report_globals_reload_dll.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/report_globals_vs_freelibrary.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/report_globals_vs_freelibrary.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/report_globals_vs_freelibrary.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/report_globals_vs_freelibrary.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/seh.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/seh.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/seh.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/seh.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/shadow_conflict_32.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/shadow_conflict_32.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/shadow_conflict_32.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/shadow_conflict_32.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/shadow_mapping_failure.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/shadow_mapping_failure.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/shadow_mapping_failure.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/shadow_mapping_failure.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/stack_array_left_oob.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/stack_array_left_oob.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/stack_array_left_oob.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/stack_array_left_oob.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/stack_array_right_oob.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/stack_array_right_oob.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/stack_array_right_oob.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/stack_array_right_oob.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/stack_array_sanity.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/stack_array_sanity.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/stack_array_sanity.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/stack_array_sanity.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/stack_use_after_return.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/stack_use_after_return.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/stack_use_after_return.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/stack_use_after_return.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/symbols_path.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/symbols_path.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/symbols_path.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/symbols_path.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/thread_simple.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/thread_simple.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/thread_simple.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/thread_simple.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/thread_stack_array_left_oob.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/thread_stack_array_left_oob.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/thread_stack_array_left_oob.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/thread_stack_array_left_oob.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/thread_stack_array_right_oob.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/thread_stack_array_right_oob.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/thread_stack_array_right_oob.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/thread_stack_array_right_oob.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/thread_stack_reuse.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/thread_stack_reuse.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/thread_stack_reuse.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/thread_stack_reuse.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/thread_stress.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/thread_stress.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/thread_stress.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/thread_stress.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/thread_suspended.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/thread_suspended.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/thread_suspended.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/thread_suspended.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/tls_init.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/tls_init.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/tls_init.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/tls_init.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/unsymbolized.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/unsymbolized.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/unsymbolized.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/unsymbolized.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/use_after_realloc.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/use_after_realloc.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/use_after_realloc.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/use_after_realloc.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/use_after_return_linkage.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/use_after_return_linkage.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/use_after_return_linkage.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/use_after_return_linkage.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/windows_h.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/windows_h.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/windows_h.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/windows_h.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/wrong_downcast_on_heap.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/wrong_downcast_on_heap.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/wrong_downcast_on_heap.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/wrong_downcast_on_heap.cc diff --git a/src/compiler-rt/test/asan/TestCases/Windows/wrong_downcast_on_stack.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/wrong_downcast_on_stack.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/Windows/wrong_downcast_on_stack.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/Windows/wrong_downcast_on_stack.cc diff --git a/src/compiler-rt/test/asan/TestCases/alloca_big_alignment.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/alloca_big_alignment.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/alloca_big_alignment.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/alloca_big_alignment.cc diff --git a/src/compiler-rt/test/asan/TestCases/alloca_constant_size.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/alloca_constant_size.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/alloca_constant_size.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/alloca_constant_size.cc diff --git a/src/compiler-rt/test/asan/TestCases/alloca_detect_custom_size_.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/alloca_detect_custom_size_.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/alloca_detect_custom_size_.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/alloca_detect_custom_size_.cc diff --git a/src/compiler-rt/test/asan/TestCases/alloca_instruments_all_paddings.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/alloca_instruments_all_paddings.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/alloca_instruments_all_paddings.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/alloca_instruments_all_paddings.cc diff --git a/src/compiler-rt/test/asan/TestCases/alloca_loop_unpoisoning.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/alloca_loop_unpoisoning.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/alloca_loop_unpoisoning.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/alloca_loop_unpoisoning.cc diff --git a/src/compiler-rt/test/asan/TestCases/alloca_overflow_partial.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/alloca_overflow_partial.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/alloca_overflow_partial.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/alloca_overflow_partial.cc diff --git a/src/compiler-rt/test/asan/TestCases/alloca_overflow_right.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/alloca_overflow_right.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/alloca_overflow_right.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/alloca_overflow_right.cc diff --git a/src/compiler-rt/test/asan/TestCases/alloca_safe_access.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/alloca_safe_access.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/alloca_safe_access.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/alloca_safe_access.cc diff --git a/src/compiler-rt/test/asan/TestCases/alloca_underflow_left.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/alloca_underflow_left.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/alloca_underflow_left.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/alloca_underflow_left.cc diff --git a/src/compiler-rt/test/asan/TestCases/alloca_vla_interact.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/alloca_vla_interact.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/alloca_vla_interact.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/alloca_vla_interact.cc diff --git a/src/compiler-rt/test/asan/TestCases/allocator_returns_null.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/allocator_returns_null.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/allocator_returns_null.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/allocator_returns_null.cc diff --git a/src/compiler-rt/test/asan/TestCases/asan_and_llvm_coverage_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/asan_and_llvm_coverage_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/asan_and_llvm_coverage_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/asan_and_llvm_coverage_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/asan_options-help.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/asan_options-help.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/asan_options-help.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/asan_options-help.cc diff --git a/src/compiler-rt/test/asan/TestCases/atexit_stats.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/atexit_stats.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/atexit_stats.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/atexit_stats.cc diff --git a/src/compiler-rt/test/asan/TestCases/atoi_strict.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/atoi_strict.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/atoi_strict.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/atoi_strict.c diff --git a/src/compiler-rt/test/asan/TestCases/atol_strict.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/atol_strict.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/atol_strict.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/atol_strict.c diff --git a/src/compiler-rt/test/asan/TestCases/atoll_strict.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/atoll_strict.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/atoll_strict.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/atoll_strict.c diff --git a/src/compiler-rt/test/asan/TestCases/blacklist.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/blacklist.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/blacklist.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/blacklist.cc diff --git a/src/compiler-rt/test/asan/TestCases/contiguous_container.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/contiguous_container.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/contiguous_container.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/contiguous_container.cc diff --git a/src/compiler-rt/test/asan/TestCases/contiguous_container_crash.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/contiguous_container_crash.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/contiguous_container_crash.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/contiguous_container_crash.cc diff --git a/src/compiler-rt/test/asan/TestCases/coverage-and-lsan.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/coverage-and-lsan.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/coverage-and-lsan.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/coverage-and-lsan.cc diff --git a/src/compiler-rt/test/asan/TestCases/coverage-caller-callee-total-count.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/coverage-caller-callee-total-count.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/coverage-caller-callee-total-count.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/coverage-caller-callee-total-count.cc diff --git a/src/compiler-rt/test/asan/TestCases/coverage-disabled.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/coverage-disabled.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/coverage-disabled.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/coverage-disabled.cc diff --git a/src/compiler-rt/test/asan/TestCases/coverage-levels.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/coverage-levels.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/coverage-levels.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/coverage-levels.cc diff --git a/src/compiler-rt/test/asan/TestCases/coverage-order-pcs.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/coverage-order-pcs.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/coverage-order-pcs.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/coverage-order-pcs.cc diff --git a/src/compiler-rt/test/asan/TestCases/coverage-reset.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/coverage-reset.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/coverage-reset.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/coverage-reset.cc diff --git a/src/compiler-rt/test/asan/TestCases/coverage-trace-pc.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/coverage-trace-pc.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/coverage-trace-pc.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/coverage-trace-pc.cc diff --git a/src/compiler-rt/test/asan/TestCases/coverage-tracing.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/coverage-tracing.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/coverage-tracing.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/coverage-tracing.cc diff --git a/src/compiler-rt/test/asan/TestCases/debug_double_free.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/debug_double_free.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/debug_double_free.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/debug_double_free.cc diff --git a/src/compiler-rt/test/asan/TestCases/debug_locate.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/debug_locate.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/debug_locate.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/debug_locate.cc diff --git a/src/compiler-rt/test/asan/TestCases/debug_mapping.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/debug_mapping.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/debug_mapping.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/debug_mapping.cc diff --git a/src/compiler-rt/test/asan/TestCases/debug_ppc64_mapping.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/debug_ppc64_mapping.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/debug_ppc64_mapping.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/debug_ppc64_mapping.cc diff --git a/src/compiler-rt/test/asan/TestCases/debug_report.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/debug_report.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/debug_report.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/debug_report.cc diff --git a/src/compiler-rt/test/asan/TestCases/debug_stacks.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/debug_stacks.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/debug_stacks.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/debug_stacks.cc diff --git a/src/compiler-rt/test/asan/TestCases/deep_stack_uaf.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/deep_stack_uaf.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/deep_stack_uaf.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/deep_stack_uaf.cc diff --git a/src/compiler-rt/test/asan/TestCases/deep_tail_call.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/deep_tail_call.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/deep_tail_call.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/deep_tail_call.cc diff --git a/src/compiler-rt/test/asan/TestCases/default_blacklist.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/default_blacklist.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/default_blacklist.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/default_blacklist.cc diff --git a/src/compiler-rt/test/asan/TestCases/default_options.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/default_options.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/default_options.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/default_options.cc diff --git a/src/compiler-rt/test/asan/TestCases/describe_address.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/describe_address.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/describe_address.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/describe_address.cc diff --git a/src/compiler-rt/test/asan/TestCases/double-free.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/double-free.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/double-free.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/double-free.cc diff --git a/src/compiler-rt/test/asan/TestCases/exitcode.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/exitcode.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/exitcode.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/exitcode.cc diff --git a/src/compiler-rt/test/asan/TestCases/force_inline_opt0.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/force_inline_opt0.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/force_inline_opt0.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/force_inline_opt0.cc diff --git a/src/compiler-rt/test/asan/TestCases/frexp_interceptor.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/frexp_interceptor.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/frexp_interceptor.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/frexp_interceptor.cc diff --git a/src/compiler-rt/test/asan/TestCases/global-address.cpp b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/global-address.cpp similarity index 100% rename from src/compiler-rt/test/asan/TestCases/global-address.cpp rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/global-address.cpp diff --git a/src/compiler-rt/test/asan/TestCases/global-demangle.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/global-demangle.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/global-demangle.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/global-demangle.cc diff --git a/src/compiler-rt/test/asan/TestCases/global-location.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/global-location.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/global-location.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/global-location.cc diff --git a/src/compiler-rt/test/asan/TestCases/global-overflow.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/global-overflow.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/global-overflow.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/global-overflow.cc diff --git a/src/compiler-rt/test/asan/TestCases/halt_on_error-1.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/halt_on_error-1.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/halt_on_error-1.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/halt_on_error-1.c diff --git a/src/compiler-rt/test/asan/TestCases/heap-overflow-large.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/heap-overflow-large.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/heap-overflow-large.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/heap-overflow-large.cc diff --git a/src/compiler-rt/test/asan/TestCases/heap-overflow.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/heap-overflow.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/heap-overflow.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/heap-overflow.cc diff --git a/src/compiler-rt/test/asan/TestCases/heavy_uar_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/heavy_uar_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/heavy_uar_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/heavy_uar_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/huge_negative_hea_oob.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/huge_negative_hea_oob.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/huge_negative_hea_oob.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/huge_negative_hea_oob.cc diff --git a/src/compiler-rt/test/asan/TestCases/ill.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/ill.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/ill.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/ill.cc diff --git a/src/compiler-rt/test/asan/TestCases/init-order-atexit.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/init-order-atexit.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/init-order-atexit.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/init-order-atexit.cc diff --git a/src/compiler-rt/test/asan/TestCases/initialization-blacklist.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/initialization-blacklist.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/initialization-blacklist.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/initialization-blacklist.cc diff --git a/src/compiler-rt/test/asan/TestCases/initialization-bug.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/initialization-bug.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/initialization-bug.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/initialization-bug.cc diff --git a/src/compiler-rt/test/asan/TestCases/initialization-constexpr.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/initialization-constexpr.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/initialization-constexpr.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/initialization-constexpr.cc diff --git a/src/compiler-rt/test/asan/TestCases/initialization-nobug.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/initialization-nobug.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/initialization-nobug.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/initialization-nobug.cc diff --git a/src/compiler-rt/test/asan/TestCases/inline.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/inline.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/inline.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/inline.cc diff --git a/src/compiler-rt/test/asan/TestCases/interception_failure_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/interception_failure_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/interception_failure_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/interception_failure_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/interface_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/interface_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/interface_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/interface_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/intra-object-overflow.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/intra-object-overflow.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/intra-object-overflow.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/intra-object-overflow.cc diff --git a/src/compiler-rt/test/asan/TestCases/invalid-free.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/invalid-free.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/invalid-free.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/invalid-free.cc diff --git a/src/compiler-rt/test/asan/TestCases/invalid-pointer-pairs.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/invalid-pointer-pairs.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/invalid-pointer-pairs.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/invalid-pointer-pairs.cc diff --git a/src/compiler-rt/test/asan/TestCases/large_func_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/large_func_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/large_func_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/large_func_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/log-path_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/log-path_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/log-path_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/log-path_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/longjmp.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/longjmp.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/longjmp.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/longjmp.cc diff --git a/src/compiler-rt/test/asan/TestCases/lsan_annotations.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/lsan_annotations.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/lsan_annotations.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/lsan_annotations.cc diff --git a/src/compiler-rt/test/asan/TestCases/malloc-no-intercept.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/malloc-no-intercept.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/malloc-no-intercept.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/malloc-no-intercept.c diff --git a/src/compiler-rt/test/asan/TestCases/malloc_context_size.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/malloc_context_size.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/malloc_context_size.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/malloc_context_size.cc diff --git a/src/compiler-rt/test/asan/TestCases/malloc_fill.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/malloc_fill.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/malloc_fill.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/malloc_fill.cc diff --git a/src/compiler-rt/test/asan/TestCases/max_redzone.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/max_redzone.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/max_redzone.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/max_redzone.cc diff --git a/src/compiler-rt/test/asan/TestCases/memcmp_strict_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/memcmp_strict_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/memcmp_strict_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/memcmp_strict_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/memcmp_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/memcmp_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/memcmp_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/memcmp_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/memset_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/memset_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/memset_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/memset_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/null_deref.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/null_deref.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/null_deref.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/null_deref.cc diff --git a/src/compiler-rt/test/asan/TestCases/on_error_callback.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/on_error_callback.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/on_error_callback.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/on_error_callback.cc diff --git a/src/compiler-rt/test/asan/TestCases/partial_right.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/partial_right.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/partial_right.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/partial_right.cc diff --git a/src/compiler-rt/test/asan/TestCases/poison_partial.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/poison_partial.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/poison_partial.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/poison_partial.cc diff --git a/src/compiler-rt/test/asan/TestCases/print_summary.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/print_summary.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/print_summary.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/print_summary.cc diff --git a/src/compiler-rt/test/asan/TestCases/printf-1.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/printf-1.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/printf-1.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/printf-1.c diff --git a/src/compiler-rt/test/asan/TestCases/printf-2.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/printf-2.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/printf-2.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/printf-2.c diff --git a/src/compiler-rt/test/asan/TestCases/printf-3.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/printf-3.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/printf-3.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/printf-3.c diff --git a/src/compiler-rt/test/asan/TestCases/printf-4.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/printf-4.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/printf-4.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/printf-4.c diff --git a/src/compiler-rt/test/asan/TestCases/printf-5.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/printf-5.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/printf-5.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/printf-5.c diff --git a/src/compiler-rt/test/asan/TestCases/printf-m.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/printf-m.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/printf-m.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/printf-m.c diff --git a/src/compiler-rt/test/asan/TestCases/sanity_check_pure_c.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/sanity_check_pure_c.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/sanity_check_pure_c.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/sanity_check_pure_c.c diff --git a/src/compiler-rt/test/asan/TestCases/scariness_score_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/scariness_score_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/scariness_score_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/scariness_score_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/set_shadow_test.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/set_shadow_test.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/set_shadow_test.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/set_shadow_test.c diff --git a/src/compiler-rt/test/asan/TestCases/sleep_before_dying.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/sleep_before_dying.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/sleep_before_dying.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/sleep_before_dying.c diff --git a/src/compiler-rt/test/asan/TestCases/speculative_load.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/speculative_load.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/speculative_load.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/speculative_load.cc diff --git a/src/compiler-rt/test/asan/TestCases/speculative_load2.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/speculative_load2.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/speculative_load2.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/speculative_load2.cc diff --git a/src/compiler-rt/test/asan/TestCases/stack-buffer-overflow-with-position.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/stack-buffer-overflow-with-position.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/stack-buffer-overflow-with-position.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/stack-buffer-overflow-with-position.cc diff --git a/src/compiler-rt/test/asan/TestCases/stack-buffer-overflow.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/stack-buffer-overflow.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/stack-buffer-overflow.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/stack-buffer-overflow.cc diff --git a/src/compiler-rt/test/asan/TestCases/stack-frame-demangle.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/stack-frame-demangle.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/stack-frame-demangle.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/stack-frame-demangle.cc diff --git a/src/compiler-rt/test/asan/TestCases/stack-oob-frames.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/stack-oob-frames.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/stack-oob-frames.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/stack-oob-frames.cc diff --git a/src/compiler-rt/test/asan/TestCases/strcasestr-1.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strcasestr-1.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strcasestr-1.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strcasestr-1.c diff --git a/src/compiler-rt/test/asan/TestCases/strcasestr-2.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strcasestr-2.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strcasestr-2.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strcasestr-2.c diff --git a/src/compiler-rt/test/asan/TestCases/strcasestr_strict.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strcasestr_strict.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strcasestr_strict.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strcasestr_strict.c diff --git a/src/compiler-rt/test/asan/TestCases/strcat_strict.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strcat_strict.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strcat_strict.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strcat_strict.c diff --git a/src/compiler-rt/test/asan/TestCases/strchr_strict.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strchr_strict.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strchr_strict.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strchr_strict.c diff --git a/src/compiler-rt/test/asan/TestCases/strcmp_strict.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strcmp_strict.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strcmp_strict.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strcmp_strict.c diff --git a/src/compiler-rt/test/asan/TestCases/strcspn-1.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strcspn-1.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strcspn-1.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strcspn-1.c diff --git a/src/compiler-rt/test/asan/TestCases/strcspn-2.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strcspn-2.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strcspn-2.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strcspn-2.c diff --git a/src/compiler-rt/test/asan/TestCases/strcspn_strict.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strcspn_strict.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strcspn_strict.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strcspn_strict.c diff --git a/src/compiler-rt/test/asan/TestCases/strdup_oob_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strdup_oob_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strdup_oob_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strdup_oob_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/strip_path_prefix.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strip_path_prefix.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strip_path_prefix.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strip_path_prefix.c diff --git a/src/compiler-rt/test/asan/TestCases/strncasecmp_strict.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strncasecmp_strict.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strncasecmp_strict.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strncasecmp_strict.c diff --git a/src/compiler-rt/test/asan/TestCases/strncat_strict.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strncat_strict.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strncat_strict.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strncat_strict.c diff --git a/src/compiler-rt/test/asan/TestCases/strncmp_strict.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strncmp_strict.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strncmp_strict.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strncmp_strict.c diff --git a/src/compiler-rt/test/asan/TestCases/strncpy-overflow.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strncpy-overflow.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strncpy-overflow.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strncpy-overflow.cc diff --git a/src/compiler-rt/test/asan/TestCases/strpbrk-1.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strpbrk-1.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strpbrk-1.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strpbrk-1.c diff --git a/src/compiler-rt/test/asan/TestCases/strpbrk-2.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strpbrk-2.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strpbrk-2.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strpbrk-2.c diff --git a/src/compiler-rt/test/asan/TestCases/strpbrk_strict.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strpbrk_strict.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strpbrk_strict.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strpbrk_strict.c diff --git a/src/compiler-rt/test/asan/TestCases/strspn-1.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strspn-1.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strspn-1.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strspn-1.c diff --git a/src/compiler-rt/test/asan/TestCases/strspn-2.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strspn-2.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strspn-2.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strspn-2.c diff --git a/src/compiler-rt/test/asan/TestCases/strspn_strict.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strspn_strict.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strspn_strict.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strspn_strict.c diff --git a/src/compiler-rt/test/asan/TestCases/strstr-1.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strstr-1.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strstr-1.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strstr-1.c diff --git a/src/compiler-rt/test/asan/TestCases/strstr-2.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strstr-2.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strstr-2.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strstr-2.c diff --git a/src/compiler-rt/test/asan/TestCases/strstr_strict.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strstr_strict.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strstr_strict.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strstr_strict.c diff --git a/src/compiler-rt/test/asan/TestCases/strtol_strict.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strtol_strict.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strtol_strict.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strtol_strict.c diff --git a/src/compiler-rt/test/asan/TestCases/strtoll_strict.c b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strtoll_strict.c similarity index 100% rename from src/compiler-rt/test/asan/TestCases/strtoll_strict.c rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/strtoll_strict.c diff --git a/src/compiler-rt/test/asan/TestCases/suppressions-exec-relative-location.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/suppressions-exec-relative-location.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/suppressions-exec-relative-location.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/suppressions-exec-relative-location.cc diff --git a/src/compiler-rt/test/asan/TestCases/suppressions-function.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/suppressions-function.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/suppressions-function.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/suppressions-function.cc diff --git a/src/compiler-rt/test/asan/TestCases/suppressions-interceptor.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/suppressions-interceptor.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/suppressions-interceptor.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/suppressions-interceptor.cc diff --git a/src/compiler-rt/test/asan/TestCases/suppressions-library.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/suppressions-library.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/suppressions-library.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/suppressions-library.cc diff --git a/src/compiler-rt/test/asan/TestCases/throw_call_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/throw_call_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/throw_call_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/throw_call_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/throw_catch.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/throw_catch.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/throw_catch.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/throw_catch.cc diff --git a/src/compiler-rt/test/asan/TestCases/throw_invoke_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/throw_invoke_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/throw_invoke_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/throw_invoke_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/time_interceptor.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/time_interceptor.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/time_interceptor.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/time_interceptor.cc diff --git a/src/compiler-rt/test/asan/TestCases/uar_and_exceptions.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/uar_and_exceptions.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/uar_and_exceptions.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/uar_and_exceptions.cc diff --git a/src/compiler-rt/test/asan/TestCases/unaligned_loads_and_stores.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/unaligned_loads_and_stores.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/unaligned_loads_and_stores.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/unaligned_loads_and_stores.cc diff --git a/src/compiler-rt/test/asan/TestCases/use-after-delete.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-delete.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/use-after-delete.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-delete.cc diff --git a/src/compiler-rt/test/asan/TestCases/use-after-free-right.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-free-right.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/use-after-free-right.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-free-right.cc diff --git a/src/compiler-rt/test/asan/TestCases/use-after-free.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-free.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/use-after-free.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-free.cc diff --git a/src/compiler-rt/test/asan/TestCases/use-after-poison.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-poison.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/use-after-poison.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-poison.cc diff --git a/src/compiler-rt/test/asan/TestCases/use-after-scope-capture.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-capture.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/use-after-scope-capture.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-capture.cc diff --git a/src/compiler-rt/test/asan/TestCases/use-after-scope-dtor-order.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-dtor-order.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/use-after-scope-dtor-order.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-dtor-order.cc diff --git a/src/compiler-rt/test/asan/TestCases/use-after-scope-goto.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-goto.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/use-after-scope-goto.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-goto.cc diff --git a/src/compiler-rt/test/asan/TestCases/use-after-scope-if.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-if.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/use-after-scope-if.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-if.cc diff --git a/src/compiler-rt/test/asan/TestCases/use-after-scope-inlined.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-inlined.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/use-after-scope-inlined.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-inlined.cc diff --git a/src/compiler-rt/test/asan/TestCases/use-after-scope-loop-bug.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-loop-bug.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/use-after-scope-loop-bug.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-loop-bug.cc diff --git a/src/compiler-rt/test/asan/TestCases/use-after-scope-loop-removed.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-loop-removed.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/use-after-scope-loop-removed.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-loop-removed.cc diff --git a/src/compiler-rt/test/asan/TestCases/use-after-scope-loop.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-loop.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/use-after-scope-loop.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-loop.cc diff --git a/src/compiler-rt/test/asan/TestCases/use-after-scope-nobug.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-nobug.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/use-after-scope-nobug.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-nobug.cc diff --git a/src/compiler-rt/test/asan/TestCases/use-after-scope-temp.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-temp.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/use-after-scope-temp.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-temp.cc diff --git a/src/compiler-rt/test/asan/TestCases/use-after-scope-temp2.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-temp2.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/use-after-scope-temp2.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-temp2.cc diff --git a/src/compiler-rt/test/asan/TestCases/use-after-scope-types.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-types.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/use-after-scope-types.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope-types.cc diff --git a/src/compiler-rt/test/asan/TestCases/use-after-scope.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/use-after-scope.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/use-after-scope.cc diff --git a/src/compiler-rt/test/asan/TestCases/verbose-log-path_test.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/verbose-log-path_test.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/verbose-log-path_test.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/verbose-log-path_test.cc diff --git a/src/compiler-rt/test/asan/TestCases/vla_chrome_testcase.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/vla_chrome_testcase.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/vla_chrome_testcase.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/vla_chrome_testcase.cc diff --git a/src/compiler-rt/test/asan/TestCases/vla_condition_overflow.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/vla_condition_overflow.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/vla_condition_overflow.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/vla_condition_overflow.cc diff --git a/src/compiler-rt/test/asan/TestCases/vla_loop_overfow.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/vla_loop_overfow.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/vla_loop_overfow.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/vla_loop_overfow.cc diff --git a/src/compiler-rt/test/asan/TestCases/zero_page_pc.cc b/src/libcompiler_builtins/compiler-rt/test/asan/TestCases/zero_page_pc.cc similarity index 100% rename from src/compiler-rt/test/asan/TestCases/zero_page_pc.cc rename to src/libcompiler_builtins/compiler-rt/test/asan/TestCases/zero_page_pc.cc diff --git a/src/compiler-rt/test/asan/Unit/lit.site.cfg.in b/src/libcompiler_builtins/compiler-rt/test/asan/Unit/lit.site.cfg.in similarity index 100% rename from src/compiler-rt/test/asan/Unit/lit.site.cfg.in rename to src/libcompiler_builtins/compiler-rt/test/asan/Unit/lit.site.cfg.in diff --git a/src/compiler-rt/test/asan/android_commands/android_common.py b/src/libcompiler_builtins/compiler-rt/test/asan/android_commands/android_common.py similarity index 100% rename from src/compiler-rt/test/asan/android_commands/android_common.py rename to src/libcompiler_builtins/compiler-rt/test/asan/android_commands/android_common.py diff --git a/src/compiler-rt/test/asan/android_commands/android_compile.py b/src/libcompiler_builtins/compiler-rt/test/asan/android_commands/android_compile.py similarity index 100% rename from src/compiler-rt/test/asan/android_commands/android_compile.py rename to src/libcompiler_builtins/compiler-rt/test/asan/android_commands/android_compile.py diff --git a/src/compiler-rt/test/asan/android_commands/android_run.py b/src/libcompiler_builtins/compiler-rt/test/asan/android_commands/android_run.py similarity index 100% rename from src/compiler-rt/test/asan/android_commands/android_run.py rename to src/libcompiler_builtins/compiler-rt/test/asan/android_commands/android_run.py diff --git a/src/compiler-rt/test/asan/lit.cfg b/src/libcompiler_builtins/compiler-rt/test/asan/lit.cfg similarity index 100% rename from src/compiler-rt/test/asan/lit.cfg rename to src/libcompiler_builtins/compiler-rt/test/asan/lit.cfg diff --git a/src/compiler-rt/test/asan/lit.site.cfg.in b/src/libcompiler_builtins/compiler-rt/test/asan/lit.site.cfg.in similarity index 100% rename from src/compiler-rt/test/asan/lit.site.cfg.in rename to src/libcompiler_builtins/compiler-rt/test/asan/lit.site.cfg.in diff --git a/src/compiler-rt/test/builtins/Unit/absvdi2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/absvdi2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/absvdi2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/absvdi2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/absvsi2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/absvsi2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/absvsi2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/absvsi2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/absvti2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/absvti2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/absvti2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/absvti2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/adddf3vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/adddf3vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/adddf3vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/adddf3vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/addsf3vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/addsf3vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/addsf3vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/addsf3vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/addtf3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/addtf3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/addtf3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/addtf3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/addvdi3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/addvdi3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/addvdi3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/addvdi3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/addvsi3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/addvsi3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/addvsi3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/addvsi3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/addvti3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/addvti3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/addvti3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/addvti3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/arm/aeabi_cdcmpeq_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/arm/aeabi_cdcmpeq_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/arm/aeabi_cdcmpeq_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/arm/aeabi_cdcmpeq_test.c diff --git a/src/compiler-rt/test/builtins/Unit/arm/aeabi_cdcmple_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/arm/aeabi_cdcmple_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/arm/aeabi_cdcmple_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/arm/aeabi_cdcmple_test.c diff --git a/src/compiler-rt/test/builtins/Unit/arm/aeabi_cfcmpeq_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/arm/aeabi_cfcmpeq_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/arm/aeabi_cfcmpeq_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/arm/aeabi_cfcmpeq_test.c diff --git a/src/compiler-rt/test/builtins/Unit/arm/aeabi_cfcmple_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/arm/aeabi_cfcmple_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/arm/aeabi_cfcmple_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/arm/aeabi_cfcmple_test.c diff --git a/src/compiler-rt/test/builtins/Unit/arm/aeabi_drsub_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/arm/aeabi_drsub_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/arm/aeabi_drsub_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/arm/aeabi_drsub_test.c diff --git a/src/compiler-rt/test/builtins/Unit/arm/aeabi_frsub_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/arm/aeabi_frsub_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/arm/aeabi_frsub_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/arm/aeabi_frsub_test.c diff --git a/src/compiler-rt/test/builtins/Unit/arm/call_apsr.S b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/arm/call_apsr.S similarity index 100% rename from src/compiler-rt/test/builtins/Unit/arm/call_apsr.S rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/arm/call_apsr.S diff --git a/src/compiler-rt/test/builtins/Unit/arm/call_apsr.h b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/arm/call_apsr.h similarity index 100% rename from src/compiler-rt/test/builtins/Unit/arm/call_apsr.h rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/arm/call_apsr.h diff --git a/src/compiler-rt/test/builtins/Unit/ashldi3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ashldi3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ashldi3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ashldi3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/ashlti3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ashlti3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ashlti3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ashlti3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/ashrdi3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ashrdi3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ashrdi3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ashrdi3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/ashrti3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ashrti3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ashrti3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ashrti3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/bswapdi2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/bswapdi2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/bswapdi2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/bswapdi2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/bswapsi2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/bswapsi2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/bswapsi2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/bswapsi2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/clear_cache_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/clear_cache_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/clear_cache_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/clear_cache_test.c diff --git a/src/compiler-rt/test/builtins/Unit/clzdi2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/clzdi2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/clzdi2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/clzdi2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/clzsi2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/clzsi2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/clzsi2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/clzsi2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/clzti2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/clzti2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/clzti2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/clzti2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/cmpdi2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/cmpdi2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/cmpdi2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/cmpdi2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/cmpti2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/cmpti2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/cmpti2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/cmpti2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/comparedf2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/comparedf2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/comparedf2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/comparedf2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/comparesf2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/comparesf2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/comparesf2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/comparesf2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/cpu_model_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/cpu_model_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/cpu_model_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/cpu_model_test.c diff --git a/src/compiler-rt/test/builtins/Unit/ctzdi2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ctzdi2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ctzdi2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ctzdi2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/ctzsi2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ctzsi2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ctzsi2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ctzsi2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/ctzti2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ctzti2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ctzti2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ctzti2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/divdc3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/divdc3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/divdc3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/divdc3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/divdf3vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/divdf3vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/divdf3vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/divdf3vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/divdi3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/divdi3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/divdi3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/divdi3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/divmodsi4_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/divmodsi4_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/divmodsi4_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/divmodsi4_test.c diff --git a/src/compiler-rt/test/builtins/Unit/divsc3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/divsc3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/divsc3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/divsc3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/divsf3vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/divsf3vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/divsf3vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/divsf3vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/divsi3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/divsi3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/divsi3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/divsi3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/divtc3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/divtc3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/divtc3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/divtc3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/divtf3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/divtf3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/divtf3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/divtf3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/divti3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/divti3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/divti3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/divti3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/divxc3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/divxc3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/divxc3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/divxc3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/enable_execute_stack_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/enable_execute_stack_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/enable_execute_stack_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/enable_execute_stack_test.c diff --git a/src/compiler-rt/test/builtins/Unit/endianness.h b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/endianness.h similarity index 100% rename from src/compiler-rt/test/builtins/Unit/endianness.h rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/endianness.h diff --git a/src/compiler-rt/test/builtins/Unit/eqdf2vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/eqdf2vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/eqdf2vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/eqdf2vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/eqsf2vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/eqsf2vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/eqsf2vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/eqsf2vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/eqtf2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/eqtf2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/eqtf2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/eqtf2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/extebdsfdf2vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/extebdsfdf2vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/extebdsfdf2vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/extebdsfdf2vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/extenddftf2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/extenddftf2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/extenddftf2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/extenddftf2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/extendhfsf2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/extendhfsf2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/extendhfsf2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/extendhfsf2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/extendsftf2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/extendsftf2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/extendsftf2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/extendsftf2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/ffsdi2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ffsdi2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ffsdi2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ffsdi2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/ffsti2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ffsti2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ffsti2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ffsti2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixdfdi_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixdfdi_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixdfdi_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixdfdi_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixdfsivfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixdfsivfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixdfsivfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixdfsivfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixdfti_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixdfti_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixdfti_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixdfti_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixsfdi_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixsfdi_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixsfdi_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixsfdi_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixsfsivfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixsfsivfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixsfsivfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixsfsivfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixsfti_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixsfti_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixsfti_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixsfti_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixtfdi_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixtfdi_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixtfdi_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixtfdi_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixtfsi_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixtfsi_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixtfsi_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixtfsi_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixtfti_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixtfti_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixtfti_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixtfti_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixunsdfdi_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunsdfdi_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixunsdfdi_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunsdfdi_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixunsdfsi_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunsdfsi_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixunsdfsi_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunsdfsi_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixunsdfsivfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunsdfsivfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixunsdfsivfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunsdfsivfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixunsdfti_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunsdfti_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixunsdfti_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunsdfti_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixunssfdi_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunssfdi_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixunssfdi_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunssfdi_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixunssfsi_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunssfsi_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixunssfsi_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunssfsi_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixunssfsivfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunssfsivfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixunssfsivfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunssfsivfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixunssfti_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunssfti_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixunssfti_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunssfti_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixunstfdi_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunstfdi_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixunstfdi_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunstfdi_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixunstfsi_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunstfsi_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixunstfsi_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunstfsi_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixunstfti_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunstfti_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixunstfti_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunstfti_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixunsxfdi_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunsxfdi_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixunsxfdi_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunsxfdi_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixunsxfsi_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunsxfsi_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixunsxfsi_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunsxfsi_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixunsxfti_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunsxfti_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixunsxfti_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixunsxfti_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixxfdi_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixxfdi_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixxfdi_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixxfdi_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fixxfti_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixxfti_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fixxfti_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fixxfti_test.c diff --git a/src/compiler-rt/test/builtins/Unit/floatdidf_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatdidf_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/floatdidf_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatdidf_test.c diff --git a/src/compiler-rt/test/builtins/Unit/floatdisf_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatdisf_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/floatdisf_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatdisf_test.c diff --git a/src/compiler-rt/test/builtins/Unit/floatditf_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatditf_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/floatditf_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatditf_test.c diff --git a/src/compiler-rt/test/builtins/Unit/floatdixf_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatdixf_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/floatdixf_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatdixf_test.c diff --git a/src/compiler-rt/test/builtins/Unit/floatsidfvfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatsidfvfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/floatsidfvfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatsidfvfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/floatsisfvfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatsisfvfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/floatsisfvfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatsisfvfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/floatsitf_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatsitf_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/floatsitf_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatsitf_test.c diff --git a/src/compiler-rt/test/builtins/Unit/floattidf_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floattidf_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/floattidf_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floattidf_test.c diff --git a/src/compiler-rt/test/builtins/Unit/floattisf_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floattisf_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/floattisf_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floattisf_test.c diff --git a/src/compiler-rt/test/builtins/Unit/floattitf_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floattitf_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/floattitf_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floattitf_test.c diff --git a/src/compiler-rt/test/builtins/Unit/floattixf_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floattixf_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/floattixf_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floattixf_test.c diff --git a/src/compiler-rt/test/builtins/Unit/floatundidf_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatundidf_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/floatundidf_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatundidf_test.c diff --git a/src/compiler-rt/test/builtins/Unit/floatundisf_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatundisf_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/floatundisf_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatundisf_test.c diff --git a/src/compiler-rt/test/builtins/Unit/floatunditf_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatunditf_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/floatunditf_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatunditf_test.c diff --git a/src/compiler-rt/test/builtins/Unit/floatundixf_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatundixf_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/floatundixf_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatundixf_test.c diff --git a/src/compiler-rt/test/builtins/Unit/floatunsitf_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatunsitf_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/floatunsitf_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatunsitf_test.c diff --git a/src/compiler-rt/test/builtins/Unit/floatunssidfvfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatunssidfvfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/floatunssidfvfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatunssidfvfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/floatunssisfvfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatunssisfvfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/floatunssisfvfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatunssisfvfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/floatuntidf_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatuntidf_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/floatuntidf_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatuntidf_test.c diff --git a/src/compiler-rt/test/builtins/Unit/floatuntisf_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatuntisf_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/floatuntisf_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatuntisf_test.c diff --git a/src/compiler-rt/test/builtins/Unit/floatuntitf_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatuntitf_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/floatuntitf_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatuntitf_test.c diff --git a/src/compiler-rt/test/builtins/Unit/floatuntixf_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatuntixf_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/floatuntixf_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/floatuntixf_test.c diff --git a/src/compiler-rt/test/builtins/Unit/fp_test.h b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fp_test.h similarity index 100% rename from src/compiler-rt/test/builtins/Unit/fp_test.h rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/fp_test.h diff --git a/src/compiler-rt/test/builtins/Unit/gcc_personality_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/gcc_personality_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/gcc_personality_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/gcc_personality_test.c diff --git a/src/compiler-rt/test/builtins/Unit/gcc_personality_test_helper.cxx b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/gcc_personality_test_helper.cxx similarity index 100% rename from src/compiler-rt/test/builtins/Unit/gcc_personality_test_helper.cxx rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/gcc_personality_test_helper.cxx diff --git a/src/compiler-rt/test/builtins/Unit/gedf2vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/gedf2vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/gedf2vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/gedf2vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/gesf2vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/gesf2vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/gesf2vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/gesf2vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/getf2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/getf2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/getf2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/getf2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/gtdf2vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/gtdf2vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/gtdf2vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/gtdf2vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/gtsf2vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/gtsf2vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/gtsf2vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/gtsf2vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/gttf2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/gttf2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/gttf2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/gttf2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/ledf2vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ledf2vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ledf2vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ledf2vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/lesf2vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/lesf2vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/lesf2vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/lesf2vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/letf2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/letf2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/letf2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/letf2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/lshrdi3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/lshrdi3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/lshrdi3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/lshrdi3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/lshrti3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/lshrti3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/lshrti3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/lshrti3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/ltdf2vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ltdf2vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ltdf2vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ltdf2vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/ltsf2vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ltsf2vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ltsf2vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ltsf2vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/lttf2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/lttf2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/lttf2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/lttf2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/moddi3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/moddi3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/moddi3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/moddi3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/modsi3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/modsi3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/modsi3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/modsi3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/modti3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/modti3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/modti3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/modti3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/muldc3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/muldc3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/muldc3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/muldc3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/muldf3vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/muldf3vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/muldf3vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/muldf3vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/muldi3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/muldi3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/muldi3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/muldi3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/mulodi4_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/mulodi4_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/mulodi4_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/mulodi4_test.c diff --git a/src/compiler-rt/test/builtins/Unit/mulosi4_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/mulosi4_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/mulosi4_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/mulosi4_test.c diff --git a/src/compiler-rt/test/builtins/Unit/muloti4_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/muloti4_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/muloti4_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/muloti4_test.c diff --git a/src/compiler-rt/test/builtins/Unit/mulsc3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/mulsc3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/mulsc3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/mulsc3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/mulsf3vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/mulsf3vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/mulsf3vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/mulsf3vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/multc3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/multc3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/multc3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/multc3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/multf3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/multf3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/multf3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/multf3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/multi3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/multi3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/multi3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/multi3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/mulvdi3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/mulvdi3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/mulvdi3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/mulvdi3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/mulvsi3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/mulvsi3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/mulvsi3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/mulvsi3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/mulvti3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/mulvti3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/mulvti3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/mulvti3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/mulxc3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/mulxc3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/mulxc3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/mulxc3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/nedf2vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/nedf2vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/nedf2vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/nedf2vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/negdf2vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/negdf2vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/negdf2vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/negdf2vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/negdi2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/negdi2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/negdi2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/negdi2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/negsf2vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/negsf2vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/negsf2vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/negsf2vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/negti2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/negti2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/negti2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/negti2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/negvdi2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/negvdi2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/negvdi2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/negvdi2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/negvsi2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/negvsi2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/negvsi2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/negvsi2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/negvti2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/negvti2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/negvti2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/negvti2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/nesf2vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/nesf2vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/nesf2vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/nesf2vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/netf2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/netf2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/netf2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/netf2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/paritydi2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/paritydi2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/paritydi2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/paritydi2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/paritysi2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/paritysi2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/paritysi2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/paritysi2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/parityti2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/parityti2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/parityti2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/parityti2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/popcountdi2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/popcountdi2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/popcountdi2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/popcountdi2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/popcountsi2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/popcountsi2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/popcountsi2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/popcountsi2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/popcountti2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/popcountti2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/popcountti2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/popcountti2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/powidf2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/powidf2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/powidf2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/powidf2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/powisf2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/powisf2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/powisf2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/powisf2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/powitf2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/powitf2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/powitf2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/powitf2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/powixf2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/powixf2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/powixf2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/powixf2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/ppc/DD.h b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ppc/DD.h similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ppc/DD.h rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ppc/DD.h diff --git a/src/compiler-rt/test/builtins/Unit/ppc/fixtfdi_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ppc/fixtfdi_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ppc/fixtfdi_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ppc/fixtfdi_test.c diff --git a/src/compiler-rt/test/builtins/Unit/ppc/floatditf_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ppc/floatditf_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ppc/floatditf_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ppc/floatditf_test.c diff --git a/src/compiler-rt/test/builtins/Unit/ppc/floatditf_test.h b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ppc/floatditf_test.h similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ppc/floatditf_test.h rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ppc/floatditf_test.h diff --git a/src/compiler-rt/test/builtins/Unit/ppc/floatunditf_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ppc/floatunditf_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ppc/floatunditf_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ppc/floatunditf_test.c diff --git a/src/compiler-rt/test/builtins/Unit/ppc/floatunditf_test.h b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ppc/floatunditf_test.h similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ppc/floatunditf_test.h rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ppc/floatunditf_test.h diff --git a/src/compiler-rt/test/builtins/Unit/ppc/qadd_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ppc/qadd_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ppc/qadd_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ppc/qadd_test.c diff --git a/src/compiler-rt/test/builtins/Unit/ppc/qdiv_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ppc/qdiv_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ppc/qdiv_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ppc/qdiv_test.c diff --git a/src/compiler-rt/test/builtins/Unit/ppc/qmul_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ppc/qmul_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ppc/qmul_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ppc/qmul_test.c diff --git a/src/compiler-rt/test/builtins/Unit/ppc/qsub_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ppc/qsub_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ppc/qsub_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ppc/qsub_test.c diff --git a/src/compiler-rt/test/builtins/Unit/ppc/test b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ppc/test similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ppc/test rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ppc/test diff --git a/src/compiler-rt/test/builtins/Unit/subdf3vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/subdf3vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/subdf3vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/subdf3vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/subsf3vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/subsf3vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/subsf3vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/subsf3vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/subtf3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/subtf3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/subtf3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/subtf3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/subvdi3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/subvdi3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/subvdi3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/subvdi3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/subvsi3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/subvsi3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/subvsi3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/subvsi3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/subvti3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/subvti3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/subvti3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/subvti3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/test b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/test similarity index 100% rename from src/compiler-rt/test/builtins/Unit/test rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/test diff --git a/src/compiler-rt/test/builtins/Unit/trampoline_setup_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/trampoline_setup_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/trampoline_setup_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/trampoline_setup_test.c diff --git a/src/compiler-rt/test/builtins/Unit/truncdfhf2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/truncdfhf2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/truncdfhf2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/truncdfhf2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/truncdfsf2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/truncdfsf2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/truncdfsf2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/truncdfsf2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/truncdfsf2vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/truncdfsf2vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/truncdfsf2vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/truncdfsf2vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/truncsfhf2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/truncsfhf2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/truncsfhf2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/truncsfhf2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/trunctfdf2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/trunctfdf2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/trunctfdf2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/trunctfdf2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/trunctfsf2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/trunctfsf2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/trunctfsf2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/trunctfsf2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/ucmpdi2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ucmpdi2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ucmpdi2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ucmpdi2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/ucmpti2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ucmpti2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/ucmpti2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/ucmpti2_test.c diff --git a/src/compiler-rt/test/builtins/Unit/udivdi3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/udivdi3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/udivdi3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/udivdi3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/udivmoddi4_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/udivmoddi4_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/udivmoddi4_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/udivmoddi4_test.c diff --git a/src/compiler-rt/test/builtins/Unit/udivmodsi4_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/udivmodsi4_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/udivmodsi4_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/udivmodsi4_test.c diff --git a/src/compiler-rt/test/builtins/Unit/udivmodti4_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/udivmodti4_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/udivmodti4_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/udivmodti4_test.c diff --git a/src/compiler-rt/test/builtins/Unit/udivsi3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/udivsi3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/udivsi3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/udivsi3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/udivti3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/udivti3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/udivti3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/udivti3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/umoddi3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/umoddi3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/umoddi3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/umoddi3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/umodsi3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/umodsi3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/umodsi3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/umodsi3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/umodti3_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/umodti3_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/umodti3_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/umodti3_test.c diff --git a/src/compiler-rt/test/builtins/Unit/unorddf2vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/unorddf2vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/unorddf2vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/unorddf2vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/unordsf2vfp_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/unordsf2vfp_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/unordsf2vfp_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/unordsf2vfp_test.c diff --git a/src/compiler-rt/test/builtins/Unit/unordtf2_test.c b/src/libcompiler_builtins/compiler-rt/test/builtins/Unit/unordtf2_test.c similarity index 100% rename from src/compiler-rt/test/builtins/Unit/unordtf2_test.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/Unit/unordtf2_test.c diff --git a/src/compiler-rt/test/builtins/timing/ashldi3.c b/src/libcompiler_builtins/compiler-rt/test/builtins/timing/ashldi3.c similarity index 100% rename from src/compiler-rt/test/builtins/timing/ashldi3.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/timing/ashldi3.c diff --git a/src/compiler-rt/test/builtins/timing/ashrdi3.c b/src/libcompiler_builtins/compiler-rt/test/builtins/timing/ashrdi3.c similarity index 100% rename from src/compiler-rt/test/builtins/timing/ashrdi3.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/timing/ashrdi3.c diff --git a/src/compiler-rt/test/builtins/timing/divdi3.c b/src/libcompiler_builtins/compiler-rt/test/builtins/timing/divdi3.c similarity index 100% rename from src/compiler-rt/test/builtins/timing/divdi3.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/timing/divdi3.c diff --git a/src/compiler-rt/test/builtins/timing/floatdidf.c b/src/libcompiler_builtins/compiler-rt/test/builtins/timing/floatdidf.c similarity index 100% rename from src/compiler-rt/test/builtins/timing/floatdidf.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/timing/floatdidf.c diff --git a/src/compiler-rt/test/builtins/timing/floatdisf.c b/src/libcompiler_builtins/compiler-rt/test/builtins/timing/floatdisf.c similarity index 100% rename from src/compiler-rt/test/builtins/timing/floatdisf.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/timing/floatdisf.c diff --git a/src/compiler-rt/test/builtins/timing/floatdixf.c b/src/libcompiler_builtins/compiler-rt/test/builtins/timing/floatdixf.c similarity index 100% rename from src/compiler-rt/test/builtins/timing/floatdixf.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/timing/floatdixf.c diff --git a/src/compiler-rt/test/builtins/timing/floatundidf.c b/src/libcompiler_builtins/compiler-rt/test/builtins/timing/floatundidf.c similarity index 100% rename from src/compiler-rt/test/builtins/timing/floatundidf.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/timing/floatundidf.c diff --git a/src/compiler-rt/test/builtins/timing/floatundisf.c b/src/libcompiler_builtins/compiler-rt/test/builtins/timing/floatundisf.c similarity index 100% rename from src/compiler-rt/test/builtins/timing/floatundisf.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/timing/floatundisf.c diff --git a/src/compiler-rt/test/builtins/timing/floatundixf.c b/src/libcompiler_builtins/compiler-rt/test/builtins/timing/floatundixf.c similarity index 100% rename from src/compiler-rt/test/builtins/timing/floatundixf.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/timing/floatundixf.c diff --git a/src/compiler-rt/test/builtins/timing/lshrdi3.c b/src/libcompiler_builtins/compiler-rt/test/builtins/timing/lshrdi3.c similarity index 100% rename from src/compiler-rt/test/builtins/timing/lshrdi3.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/timing/lshrdi3.c diff --git a/src/compiler-rt/test/builtins/timing/moddi3.c b/src/libcompiler_builtins/compiler-rt/test/builtins/timing/moddi3.c similarity index 100% rename from src/compiler-rt/test/builtins/timing/moddi3.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/timing/moddi3.c diff --git a/src/compiler-rt/test/builtins/timing/modsi3.c b/src/libcompiler_builtins/compiler-rt/test/builtins/timing/modsi3.c similarity index 100% rename from src/compiler-rt/test/builtins/timing/modsi3.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/timing/modsi3.c diff --git a/src/compiler-rt/test/builtins/timing/muldi3.c b/src/libcompiler_builtins/compiler-rt/test/builtins/timing/muldi3.c similarity index 100% rename from src/compiler-rt/test/builtins/timing/muldi3.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/timing/muldi3.c diff --git a/src/compiler-rt/test/builtins/timing/negdi2.c b/src/libcompiler_builtins/compiler-rt/test/builtins/timing/negdi2.c similarity index 100% rename from src/compiler-rt/test/builtins/timing/negdi2.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/timing/negdi2.c diff --git a/src/compiler-rt/test/builtins/timing/time b/src/libcompiler_builtins/compiler-rt/test/builtins/timing/time similarity index 100% rename from src/compiler-rt/test/builtins/timing/time rename to src/libcompiler_builtins/compiler-rt/test/builtins/timing/time diff --git a/src/compiler-rt/test/builtins/timing/timing.h b/src/libcompiler_builtins/compiler-rt/test/builtins/timing/timing.h similarity index 100% rename from src/compiler-rt/test/builtins/timing/timing.h rename to src/libcompiler_builtins/compiler-rt/test/builtins/timing/timing.h diff --git a/src/compiler-rt/test/builtins/timing/udivdi3.c b/src/libcompiler_builtins/compiler-rt/test/builtins/timing/udivdi3.c similarity index 100% rename from src/compiler-rt/test/builtins/timing/udivdi3.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/timing/udivdi3.c diff --git a/src/compiler-rt/test/builtins/timing/umoddi3.c b/src/libcompiler_builtins/compiler-rt/test/builtins/timing/umoddi3.c similarity index 100% rename from src/compiler-rt/test/builtins/timing/umoddi3.c rename to src/libcompiler_builtins/compiler-rt/test/builtins/timing/umoddi3.c diff --git a/src/compiler-rt/test/cfi/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/test/cfi/CMakeLists.txt similarity index 100% rename from src/compiler-rt/test/cfi/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/test/cfi/CMakeLists.txt diff --git a/src/compiler-rt/test/cfi/README.txt b/src/libcompiler_builtins/compiler-rt/test/cfi/README.txt similarity index 100% rename from src/compiler-rt/test/cfi/README.txt rename to src/libcompiler_builtins/compiler-rt/test/cfi/README.txt diff --git a/src/compiler-rt/test/cfi/anon-namespace.cpp b/src/libcompiler_builtins/compiler-rt/test/cfi/anon-namespace.cpp similarity index 100% rename from src/compiler-rt/test/cfi/anon-namespace.cpp rename to src/libcompiler_builtins/compiler-rt/test/cfi/anon-namespace.cpp diff --git a/src/compiler-rt/test/cfi/bad-cast.cpp b/src/libcompiler_builtins/compiler-rt/test/cfi/bad-cast.cpp similarity index 100% rename from src/compiler-rt/test/cfi/bad-cast.cpp rename to src/libcompiler_builtins/compiler-rt/test/cfi/bad-cast.cpp diff --git a/src/compiler-rt/test/cfi/base-derived-destructor.cpp b/src/libcompiler_builtins/compiler-rt/test/cfi/base-derived-destructor.cpp similarity index 100% rename from src/compiler-rt/test/cfi/base-derived-destructor.cpp rename to src/libcompiler_builtins/compiler-rt/test/cfi/base-derived-destructor.cpp diff --git a/src/compiler-rt/test/cfi/create-derivers.test b/src/libcompiler_builtins/compiler-rt/test/cfi/create-derivers.test similarity index 100% rename from src/compiler-rt/test/cfi/create-derivers.test rename to src/libcompiler_builtins/compiler-rt/test/cfi/create-derivers.test diff --git a/src/compiler-rt/test/cfi/cross-dso/dlopen.cpp b/src/libcompiler_builtins/compiler-rt/test/cfi/cross-dso/dlopen.cpp similarity index 100% rename from src/compiler-rt/test/cfi/cross-dso/dlopen.cpp rename to src/libcompiler_builtins/compiler-rt/test/cfi/cross-dso/dlopen.cpp diff --git a/src/compiler-rt/test/cfi/cross-dso/icall/diag.cpp b/src/libcompiler_builtins/compiler-rt/test/cfi/cross-dso/icall/diag.cpp similarity index 100% rename from src/compiler-rt/test/cfi/cross-dso/icall/diag.cpp rename to src/libcompiler_builtins/compiler-rt/test/cfi/cross-dso/icall/diag.cpp diff --git a/src/compiler-rt/test/cfi/cross-dso/icall/icall-from-dso.cpp b/src/libcompiler_builtins/compiler-rt/test/cfi/cross-dso/icall/icall-from-dso.cpp similarity index 100% rename from src/compiler-rt/test/cfi/cross-dso/icall/icall-from-dso.cpp rename to src/libcompiler_builtins/compiler-rt/test/cfi/cross-dso/icall/icall-from-dso.cpp diff --git a/src/compiler-rt/test/cfi/cross-dso/icall/icall.cpp b/src/libcompiler_builtins/compiler-rt/test/cfi/cross-dso/icall/icall.cpp similarity index 100% rename from src/compiler-rt/test/cfi/cross-dso/icall/icall.cpp rename to src/libcompiler_builtins/compiler-rt/test/cfi/cross-dso/icall/icall.cpp diff --git a/src/compiler-rt/test/cfi/cross-dso/icall/lit.local.cfg b/src/libcompiler_builtins/compiler-rt/test/cfi/cross-dso/icall/lit.local.cfg similarity index 100% rename from src/compiler-rt/test/cfi/cross-dso/icall/lit.local.cfg rename to src/libcompiler_builtins/compiler-rt/test/cfi/cross-dso/icall/lit.local.cfg diff --git a/src/compiler-rt/test/cfi/cross-dso/lit.local.cfg b/src/libcompiler_builtins/compiler-rt/test/cfi/cross-dso/lit.local.cfg similarity index 100% rename from src/compiler-rt/test/cfi/cross-dso/lit.local.cfg rename to src/libcompiler_builtins/compiler-rt/test/cfi/cross-dso/lit.local.cfg diff --git a/src/compiler-rt/test/cfi/cross-dso/shadow_is_read_only.cpp b/src/libcompiler_builtins/compiler-rt/test/cfi/cross-dso/shadow_is_read_only.cpp similarity index 100% rename from src/compiler-rt/test/cfi/cross-dso/shadow_is_read_only.cpp rename to src/libcompiler_builtins/compiler-rt/test/cfi/cross-dso/shadow_is_read_only.cpp diff --git a/src/compiler-rt/test/cfi/cross-dso/simple-fail.cpp b/src/libcompiler_builtins/compiler-rt/test/cfi/cross-dso/simple-fail.cpp similarity index 100% rename from src/compiler-rt/test/cfi/cross-dso/simple-fail.cpp rename to src/libcompiler_builtins/compiler-rt/test/cfi/cross-dso/simple-fail.cpp diff --git a/src/compiler-rt/test/cfi/cross-dso/simple-pass.cpp b/src/libcompiler_builtins/compiler-rt/test/cfi/cross-dso/simple-pass.cpp similarity index 100% rename from src/compiler-rt/test/cfi/cross-dso/simple-pass.cpp rename to src/libcompiler_builtins/compiler-rt/test/cfi/cross-dso/simple-pass.cpp diff --git a/src/compiler-rt/test/cfi/cross-dso/stats.cpp b/src/libcompiler_builtins/compiler-rt/test/cfi/cross-dso/stats.cpp similarity index 100% rename from src/compiler-rt/test/cfi/cross-dso/stats.cpp rename to src/libcompiler_builtins/compiler-rt/test/cfi/cross-dso/stats.cpp diff --git a/src/compiler-rt/test/cfi/cross-dso/target_out_of_bounds.cpp b/src/libcompiler_builtins/compiler-rt/test/cfi/cross-dso/target_out_of_bounds.cpp similarity index 100% rename from src/compiler-rt/test/cfi/cross-dso/target_out_of_bounds.cpp rename to src/libcompiler_builtins/compiler-rt/test/cfi/cross-dso/target_out_of_bounds.cpp diff --git a/src/compiler-rt/test/cfi/icall/bad-signature.c b/src/libcompiler_builtins/compiler-rt/test/cfi/icall/bad-signature.c similarity index 100% rename from src/compiler-rt/test/cfi/icall/bad-signature.c rename to src/libcompiler_builtins/compiler-rt/test/cfi/icall/bad-signature.c diff --git a/src/compiler-rt/test/cfi/icall/external-call.c b/src/libcompiler_builtins/compiler-rt/test/cfi/icall/external-call.c similarity index 100% rename from src/compiler-rt/test/cfi/icall/external-call.c rename to src/libcompiler_builtins/compiler-rt/test/cfi/icall/external-call.c diff --git a/src/compiler-rt/test/cfi/icall/lit.local.cfg b/src/libcompiler_builtins/compiler-rt/test/cfi/icall/lit.local.cfg similarity index 100% rename from src/compiler-rt/test/cfi/icall/lit.local.cfg rename to src/libcompiler_builtins/compiler-rt/test/cfi/icall/lit.local.cfg diff --git a/src/compiler-rt/test/cfi/icall/weak.c b/src/libcompiler_builtins/compiler-rt/test/cfi/icall/weak.c similarity index 100% rename from src/compiler-rt/test/cfi/icall/weak.c rename to src/libcompiler_builtins/compiler-rt/test/cfi/icall/weak.c diff --git a/src/compiler-rt/test/cfi/lit.cfg b/src/libcompiler_builtins/compiler-rt/test/cfi/lit.cfg similarity index 100% rename from src/compiler-rt/test/cfi/lit.cfg rename to src/libcompiler_builtins/compiler-rt/test/cfi/lit.cfg diff --git a/src/compiler-rt/test/cfi/lit.site.cfg.in b/src/libcompiler_builtins/compiler-rt/test/cfi/lit.site.cfg.in similarity index 100% rename from src/compiler-rt/test/cfi/lit.site.cfg.in rename to src/libcompiler_builtins/compiler-rt/test/cfi/lit.site.cfg.in diff --git a/src/compiler-rt/test/cfi/multiple-inheritance.cpp b/src/libcompiler_builtins/compiler-rt/test/cfi/multiple-inheritance.cpp similarity index 100% rename from src/compiler-rt/test/cfi/multiple-inheritance.cpp rename to src/libcompiler_builtins/compiler-rt/test/cfi/multiple-inheritance.cpp diff --git a/src/compiler-rt/test/cfi/nvcall.cpp b/src/libcompiler_builtins/compiler-rt/test/cfi/nvcall.cpp similarity index 100% rename from src/compiler-rt/test/cfi/nvcall.cpp rename to src/libcompiler_builtins/compiler-rt/test/cfi/nvcall.cpp diff --git a/src/compiler-rt/test/cfi/overwrite.cpp b/src/libcompiler_builtins/compiler-rt/test/cfi/overwrite.cpp similarity index 100% rename from src/compiler-rt/test/cfi/overwrite.cpp rename to src/libcompiler_builtins/compiler-rt/test/cfi/overwrite.cpp diff --git a/src/compiler-rt/test/cfi/sibling.cpp b/src/libcompiler_builtins/compiler-rt/test/cfi/sibling.cpp similarity index 100% rename from src/compiler-rt/test/cfi/sibling.cpp rename to src/libcompiler_builtins/compiler-rt/test/cfi/sibling.cpp diff --git a/src/compiler-rt/test/cfi/simple-fail.cpp b/src/libcompiler_builtins/compiler-rt/test/cfi/simple-fail.cpp similarity index 100% rename from src/compiler-rt/test/cfi/simple-fail.cpp rename to src/libcompiler_builtins/compiler-rt/test/cfi/simple-fail.cpp diff --git a/src/compiler-rt/test/cfi/simple-pass.cpp b/src/libcompiler_builtins/compiler-rt/test/cfi/simple-pass.cpp similarity index 100% rename from src/compiler-rt/test/cfi/simple-pass.cpp rename to src/libcompiler_builtins/compiler-rt/test/cfi/simple-pass.cpp diff --git a/src/compiler-rt/test/cfi/stats.cpp b/src/libcompiler_builtins/compiler-rt/test/cfi/stats.cpp similarity index 100% rename from src/compiler-rt/test/cfi/stats.cpp rename to src/libcompiler_builtins/compiler-rt/test/cfi/stats.cpp diff --git a/src/compiler-rt/test/cfi/target_uninstrumented.cpp b/src/libcompiler_builtins/compiler-rt/test/cfi/target_uninstrumented.cpp similarity index 100% rename from src/compiler-rt/test/cfi/target_uninstrumented.cpp rename to src/libcompiler_builtins/compiler-rt/test/cfi/target_uninstrumented.cpp diff --git a/src/compiler-rt/test/cfi/two-vcalls.cpp b/src/libcompiler_builtins/compiler-rt/test/cfi/two-vcalls.cpp similarity index 100% rename from src/compiler-rt/test/cfi/two-vcalls.cpp rename to src/libcompiler_builtins/compiler-rt/test/cfi/two-vcalls.cpp diff --git a/src/compiler-rt/test/cfi/utils.h b/src/libcompiler_builtins/compiler-rt/test/cfi/utils.h similarity index 100% rename from src/compiler-rt/test/cfi/utils.h rename to src/libcompiler_builtins/compiler-rt/test/cfi/utils.h diff --git a/src/compiler-rt/test/cfi/vdtor.cpp b/src/libcompiler_builtins/compiler-rt/test/cfi/vdtor.cpp similarity index 100% rename from src/compiler-rt/test/cfi/vdtor.cpp rename to src/libcompiler_builtins/compiler-rt/test/cfi/vdtor.cpp diff --git a/src/compiler-rt/test/dfsan/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/test/dfsan/CMakeLists.txt similarity index 100% rename from src/compiler-rt/test/dfsan/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/test/dfsan/CMakeLists.txt diff --git a/src/compiler-rt/test/dfsan/Inputs/flags_abilist.txt b/src/libcompiler_builtins/compiler-rt/test/dfsan/Inputs/flags_abilist.txt similarity index 100% rename from src/compiler-rt/test/dfsan/Inputs/flags_abilist.txt rename to src/libcompiler_builtins/compiler-rt/test/dfsan/Inputs/flags_abilist.txt diff --git a/src/compiler-rt/test/dfsan/basic.c b/src/libcompiler_builtins/compiler-rt/test/dfsan/basic.c similarity index 100% rename from src/compiler-rt/test/dfsan/basic.c rename to src/libcompiler_builtins/compiler-rt/test/dfsan/basic.c diff --git a/src/compiler-rt/test/dfsan/custom.cc b/src/libcompiler_builtins/compiler-rt/test/dfsan/custom.cc similarity index 100% rename from src/compiler-rt/test/dfsan/custom.cc rename to src/libcompiler_builtins/compiler-rt/test/dfsan/custom.cc diff --git a/src/compiler-rt/test/dfsan/dump_labels.c b/src/libcompiler_builtins/compiler-rt/test/dfsan/dump_labels.c similarity index 100% rename from src/compiler-rt/test/dfsan/dump_labels.c rename to src/libcompiler_builtins/compiler-rt/test/dfsan/dump_labels.c diff --git a/src/compiler-rt/test/dfsan/flags.c b/src/libcompiler_builtins/compiler-rt/test/dfsan/flags.c similarity index 100% rename from src/compiler-rt/test/dfsan/flags.c rename to src/libcompiler_builtins/compiler-rt/test/dfsan/flags.c diff --git a/src/compiler-rt/test/dfsan/fncall.c b/src/libcompiler_builtins/compiler-rt/test/dfsan/fncall.c similarity index 100% rename from src/compiler-rt/test/dfsan/fncall.c rename to src/libcompiler_builtins/compiler-rt/test/dfsan/fncall.c diff --git a/src/compiler-rt/test/dfsan/label_count.c b/src/libcompiler_builtins/compiler-rt/test/dfsan/label_count.c similarity index 100% rename from src/compiler-rt/test/dfsan/label_count.c rename to src/libcompiler_builtins/compiler-rt/test/dfsan/label_count.c diff --git a/src/compiler-rt/test/dfsan/lit.cfg b/src/libcompiler_builtins/compiler-rt/test/dfsan/lit.cfg similarity index 100% rename from src/compiler-rt/test/dfsan/lit.cfg rename to src/libcompiler_builtins/compiler-rt/test/dfsan/lit.cfg diff --git a/src/compiler-rt/test/dfsan/lit.site.cfg.in b/src/libcompiler_builtins/compiler-rt/test/dfsan/lit.site.cfg.in similarity index 100% rename from src/compiler-rt/test/dfsan/lit.site.cfg.in rename to src/libcompiler_builtins/compiler-rt/test/dfsan/lit.site.cfg.in diff --git a/src/compiler-rt/test/dfsan/propagate.c b/src/libcompiler_builtins/compiler-rt/test/dfsan/propagate.c similarity index 100% rename from src/compiler-rt/test/dfsan/propagate.c rename to src/libcompiler_builtins/compiler-rt/test/dfsan/propagate.c diff --git a/src/compiler-rt/test/dfsan/vararg.c b/src/libcompiler_builtins/compiler-rt/test/dfsan/vararg.c similarity index 100% rename from src/compiler-rt/test/dfsan/vararg.c rename to src/libcompiler_builtins/compiler-rt/test/dfsan/vararg.c diff --git a/src/compiler-rt/test/dfsan/write_callback.c b/src/libcompiler_builtins/compiler-rt/test/dfsan/write_callback.c similarity index 100% rename from src/compiler-rt/test/dfsan/write_callback.c rename to src/libcompiler_builtins/compiler-rt/test/dfsan/write_callback.c diff --git a/src/compiler-rt/test/esan/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/test/esan/CMakeLists.txt similarity index 100% rename from src/compiler-rt/test/esan/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/test/esan/CMakeLists.txt diff --git a/src/compiler-rt/test/esan/TestCases/large-stack-linux.c b/src/libcompiler_builtins/compiler-rt/test/esan/TestCases/large-stack-linux.c similarity index 100% rename from src/compiler-rt/test/esan/TestCases/large-stack-linux.c rename to src/libcompiler_builtins/compiler-rt/test/esan/TestCases/large-stack-linux.c diff --git a/src/compiler-rt/test/esan/TestCases/libc-intercept.c b/src/libcompiler_builtins/compiler-rt/test/esan/TestCases/libc-intercept.c similarity index 100% rename from src/compiler-rt/test/esan/TestCases/libc-intercept.c rename to src/libcompiler_builtins/compiler-rt/test/esan/TestCases/libc-intercept.c diff --git a/src/compiler-rt/test/esan/TestCases/mmap-shadow-conflict.c b/src/libcompiler_builtins/compiler-rt/test/esan/TestCases/mmap-shadow-conflict.c similarity index 100% rename from src/compiler-rt/test/esan/TestCases/mmap-shadow-conflict.c rename to src/libcompiler_builtins/compiler-rt/test/esan/TestCases/mmap-shadow-conflict.c diff --git a/src/compiler-rt/test/esan/TestCases/struct-simple.cpp b/src/libcompiler_builtins/compiler-rt/test/esan/TestCases/struct-simple.cpp similarity index 100% rename from src/compiler-rt/test/esan/TestCases/struct-simple.cpp rename to src/libcompiler_builtins/compiler-rt/test/esan/TestCases/struct-simple.cpp diff --git a/src/compiler-rt/test/esan/TestCases/verbose-simple.c b/src/libcompiler_builtins/compiler-rt/test/esan/TestCases/verbose-simple.c similarity index 100% rename from src/compiler-rt/test/esan/TestCases/verbose-simple.c rename to src/libcompiler_builtins/compiler-rt/test/esan/TestCases/verbose-simple.c diff --git a/src/compiler-rt/test/esan/TestCases/workingset-early-fault.c b/src/libcompiler_builtins/compiler-rt/test/esan/TestCases/workingset-early-fault.c similarity index 100% rename from src/compiler-rt/test/esan/TestCases/workingset-early-fault.c rename to src/libcompiler_builtins/compiler-rt/test/esan/TestCases/workingset-early-fault.c diff --git a/src/compiler-rt/test/esan/TestCases/workingset-memset.cpp b/src/libcompiler_builtins/compiler-rt/test/esan/TestCases/workingset-memset.cpp similarity index 100% rename from src/compiler-rt/test/esan/TestCases/workingset-memset.cpp rename to src/libcompiler_builtins/compiler-rt/test/esan/TestCases/workingset-memset.cpp diff --git a/src/compiler-rt/test/esan/TestCases/workingset-midreport.cpp b/src/libcompiler_builtins/compiler-rt/test/esan/TestCases/workingset-midreport.cpp similarity index 100% rename from src/compiler-rt/test/esan/TestCases/workingset-midreport.cpp rename to src/libcompiler_builtins/compiler-rt/test/esan/TestCases/workingset-midreport.cpp diff --git a/src/compiler-rt/test/esan/TestCases/workingset-samples.cpp b/src/libcompiler_builtins/compiler-rt/test/esan/TestCases/workingset-samples.cpp similarity index 100% rename from src/compiler-rt/test/esan/TestCases/workingset-samples.cpp rename to src/libcompiler_builtins/compiler-rt/test/esan/TestCases/workingset-samples.cpp diff --git a/src/compiler-rt/test/esan/TestCases/workingset-signal-posix.cpp b/src/libcompiler_builtins/compiler-rt/test/esan/TestCases/workingset-signal-posix.cpp similarity index 100% rename from src/compiler-rt/test/esan/TestCases/workingset-signal-posix.cpp rename to src/libcompiler_builtins/compiler-rt/test/esan/TestCases/workingset-signal-posix.cpp diff --git a/src/compiler-rt/test/esan/TestCases/workingset-simple.cpp b/src/libcompiler_builtins/compiler-rt/test/esan/TestCases/workingset-simple.cpp similarity index 100% rename from src/compiler-rt/test/esan/TestCases/workingset-simple.cpp rename to src/libcompiler_builtins/compiler-rt/test/esan/TestCases/workingset-simple.cpp diff --git a/src/compiler-rt/test/esan/Unit/circular_buffer.cpp b/src/libcompiler_builtins/compiler-rt/test/esan/Unit/circular_buffer.cpp similarity index 100% rename from src/compiler-rt/test/esan/Unit/circular_buffer.cpp rename to src/libcompiler_builtins/compiler-rt/test/esan/Unit/circular_buffer.cpp diff --git a/src/compiler-rt/test/esan/Unit/hashtable.cpp b/src/libcompiler_builtins/compiler-rt/test/esan/Unit/hashtable.cpp similarity index 100% rename from src/compiler-rt/test/esan/Unit/hashtable.cpp rename to src/libcompiler_builtins/compiler-rt/test/esan/Unit/hashtable.cpp diff --git a/src/compiler-rt/test/esan/lit.cfg b/src/libcompiler_builtins/compiler-rt/test/esan/lit.cfg similarity index 100% rename from src/compiler-rt/test/esan/lit.cfg rename to src/libcompiler_builtins/compiler-rt/test/esan/lit.cfg diff --git a/src/compiler-rt/test/esan/lit.site.cfg.in b/src/libcompiler_builtins/compiler-rt/test/esan/lit.site.cfg.in similarity index 100% rename from src/compiler-rt/test/esan/lit.site.cfg.in rename to src/libcompiler_builtins/compiler-rt/test/esan/lit.site.cfg.in diff --git a/src/compiler-rt/test/interception/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/test/interception/CMakeLists.txt similarity index 100% rename from src/compiler-rt/test/interception/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/test/interception/CMakeLists.txt diff --git a/src/compiler-rt/test/interception/Unit/lit.site.cfg.in b/src/libcompiler_builtins/compiler-rt/test/interception/Unit/lit.site.cfg.in similarity index 100% rename from src/compiler-rt/test/interception/Unit/lit.site.cfg.in rename to src/libcompiler_builtins/compiler-rt/test/interception/Unit/lit.site.cfg.in diff --git a/src/compiler-rt/test/lit.common.cfg b/src/libcompiler_builtins/compiler-rt/test/lit.common.cfg similarity index 100% rename from src/compiler-rt/test/lit.common.cfg rename to src/libcompiler_builtins/compiler-rt/test/lit.common.cfg diff --git a/src/compiler-rt/test/lit.common.configured.in b/src/libcompiler_builtins/compiler-rt/test/lit.common.configured.in similarity index 100% rename from src/compiler-rt/test/lit.common.configured.in rename to src/libcompiler_builtins/compiler-rt/test/lit.common.configured.in diff --git a/src/compiler-rt/test/lsan/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/test/lsan/CMakeLists.txt similarity index 100% rename from src/compiler-rt/test/lsan/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/test/lsan/CMakeLists.txt diff --git a/src/compiler-rt/test/lsan/TestCases/cleanup_in_tsd_destructor.c b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/cleanup_in_tsd_destructor.c similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/cleanup_in_tsd_destructor.c rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/cleanup_in_tsd_destructor.c diff --git a/src/compiler-rt/test/lsan/TestCases/disabler.c b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/disabler.c similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/disabler.c rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/disabler.c diff --git a/src/compiler-rt/test/lsan/TestCases/disabler.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/disabler.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/disabler.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/disabler.cc diff --git a/src/compiler-rt/test/lsan/TestCases/disabler_in_tsd_destructor.c b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/disabler_in_tsd_destructor.c similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/disabler_in_tsd_destructor.c rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/disabler_in_tsd_destructor.c diff --git a/src/compiler-rt/test/lsan/TestCases/do_leak_check_override.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/do_leak_check_override.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/do_leak_check_override.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/do_leak_check_override.cc diff --git a/src/compiler-rt/test/lsan/TestCases/fork.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/fork.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/fork.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/fork.cc diff --git a/src/compiler-rt/test/lsan/TestCases/fork_threaded.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/fork_threaded.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/fork_threaded.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/fork_threaded.cc diff --git a/src/compiler-rt/test/lsan/TestCases/guard-page.c b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/guard-page.c similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/guard-page.c rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/guard-page.c diff --git a/src/compiler-rt/test/lsan/TestCases/high_allocator_contention.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/high_allocator_contention.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/high_allocator_contention.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/high_allocator_contention.cc diff --git a/src/compiler-rt/test/lsan/TestCases/ignore_object.c b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/ignore_object.c similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/ignore_object.c rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/ignore_object.c diff --git a/src/compiler-rt/test/lsan/TestCases/ignore_object_errors.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/ignore_object_errors.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/ignore_object_errors.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/ignore_object_errors.cc diff --git a/src/compiler-rt/test/lsan/TestCases/large_allocation_leak.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/large_allocation_leak.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/large_allocation_leak.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/large_allocation_leak.cc diff --git a/src/compiler-rt/test/lsan/TestCases/leak_check_at_exit.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/leak_check_at_exit.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/leak_check_at_exit.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/leak_check_at_exit.cc diff --git a/src/compiler-rt/test/lsan/TestCases/leak_check_before_thread_started.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/leak_check_before_thread_started.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/leak_check_before_thread_started.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/leak_check_before_thread_started.cc diff --git a/src/compiler-rt/test/lsan/TestCases/link_turned_off.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/link_turned_off.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/link_turned_off.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/link_turned_off.cc diff --git a/src/compiler-rt/test/lsan/TestCases/new_array_with_dtor_0.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/new_array_with_dtor_0.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/new_array_with_dtor_0.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/new_array_with_dtor_0.cc diff --git a/src/compiler-rt/test/lsan/TestCases/pointer_to_self.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/pointer_to_self.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/pointer_to_self.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/pointer_to_self.cc diff --git a/src/compiler-rt/test/lsan/TestCases/print_suppressions.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/print_suppressions.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/print_suppressions.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/print_suppressions.cc diff --git a/src/compiler-rt/test/lsan/TestCases/recoverable_leak_check.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/recoverable_leak_check.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/recoverable_leak_check.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/recoverable_leak_check.cc diff --git a/src/compiler-rt/test/lsan/TestCases/register_root_region.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/register_root_region.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/register_root_region.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/register_root_region.cc diff --git a/src/compiler-rt/test/lsan/TestCases/sanity_check_pure_c.c b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/sanity_check_pure_c.c similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/sanity_check_pure_c.c rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/sanity_check_pure_c.c diff --git a/src/compiler-rt/test/lsan/TestCases/stale_stack_leak.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/stale_stack_leak.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/stale_stack_leak.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/stale_stack_leak.cc diff --git a/src/compiler-rt/test/lsan/TestCases/strace_test.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/strace_test.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/strace_test.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/strace_test.cc diff --git a/src/compiler-rt/test/lsan/TestCases/suppressions_default.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/suppressions_default.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/suppressions_default.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/suppressions_default.cc diff --git a/src/compiler-rt/test/lsan/TestCases/suppressions_file.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/suppressions_file.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/suppressions_file.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/suppressions_file.cc diff --git a/src/compiler-rt/test/lsan/TestCases/swapcontext.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/swapcontext.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/swapcontext.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/swapcontext.cc diff --git a/src/compiler-rt/test/lsan/TestCases/use_after_return.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_after_return.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/use_after_return.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_after_return.cc diff --git a/src/compiler-rt/test/lsan/TestCases/use_globals_initialized.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_globals_initialized.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/use_globals_initialized.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_globals_initialized.cc diff --git a/src/compiler-rt/test/lsan/TestCases/use_globals_uninitialized.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_globals_uninitialized.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/use_globals_uninitialized.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_globals_uninitialized.cc diff --git a/src/compiler-rt/test/lsan/TestCases/use_poisoned_asan.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_poisoned_asan.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/use_poisoned_asan.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_poisoned_asan.cc diff --git a/src/compiler-rt/test/lsan/TestCases/use_registers.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_registers.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/use_registers.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_registers.cc diff --git a/src/compiler-rt/test/lsan/TestCases/use_stacks.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_stacks.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/use_stacks.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_stacks.cc diff --git a/src/compiler-rt/test/lsan/TestCases/use_stacks_threaded.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_stacks_threaded.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/use_stacks_threaded.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_stacks_threaded.cc diff --git a/src/compiler-rt/test/lsan/TestCases/use_tls_dynamic.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_tls_dynamic.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/use_tls_dynamic.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_tls_dynamic.cc diff --git a/src/compiler-rt/test/lsan/TestCases/use_tls_pthread_specific_dynamic.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_tls_pthread_specific_dynamic.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/use_tls_pthread_specific_dynamic.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_tls_pthread_specific_dynamic.cc diff --git a/src/compiler-rt/test/lsan/TestCases/use_tls_pthread_specific_static.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_tls_pthread_specific_static.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/use_tls_pthread_specific_static.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_tls_pthread_specific_static.cc diff --git a/src/compiler-rt/test/lsan/TestCases/use_tls_static.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_tls_static.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/use_tls_static.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_tls_static.cc diff --git a/src/compiler-rt/test/lsan/TestCases/use_unaligned.cc b/src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_unaligned.cc similarity index 100% rename from src/compiler-rt/test/lsan/TestCases/use_unaligned.cc rename to src/libcompiler_builtins/compiler-rt/test/lsan/TestCases/use_unaligned.cc diff --git a/src/compiler-rt/test/lsan/lit.common.cfg b/src/libcompiler_builtins/compiler-rt/test/lsan/lit.common.cfg similarity index 100% rename from src/compiler-rt/test/lsan/lit.common.cfg rename to src/libcompiler_builtins/compiler-rt/test/lsan/lit.common.cfg diff --git a/src/compiler-rt/test/lsan/lit.site.cfg.in b/src/libcompiler_builtins/compiler-rt/test/lsan/lit.site.cfg.in similarity index 100% rename from src/compiler-rt/test/lsan/lit.site.cfg.in rename to src/libcompiler_builtins/compiler-rt/test/lsan/lit.site.cfg.in diff --git a/src/compiler-rt/test/msan/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/test/msan/CMakeLists.txt similarity index 100% rename from src/compiler-rt/test/msan/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/test/msan/CMakeLists.txt diff --git a/src/compiler-rt/test/msan/Linux/cmsghdr.cc b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/cmsghdr.cc similarity index 100% rename from src/compiler-rt/test/msan/Linux/cmsghdr.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/cmsghdr.cc diff --git a/src/compiler-rt/test/msan/Linux/eventfd.cc b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/eventfd.cc similarity index 100% rename from src/compiler-rt/test/msan/Linux/eventfd.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/eventfd.cc diff --git a/src/compiler-rt/test/msan/Linux/fopencookie.cc b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/fopencookie.cc similarity index 100% rename from src/compiler-rt/test/msan/Linux/fopencookie.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/fopencookie.cc diff --git a/src/compiler-rt/test/msan/Linux/forkpty.cc b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/forkpty.cc similarity index 100% rename from src/compiler-rt/test/msan/Linux/forkpty.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/forkpty.cc diff --git a/src/compiler-rt/test/msan/Linux/getresid.cc b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/getresid.cc similarity index 100% rename from src/compiler-rt/test/msan/Linux/getresid.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/getresid.cc diff --git a/src/compiler-rt/test/msan/Linux/glob.cc b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/glob.cc similarity index 100% rename from src/compiler-rt/test/msan/Linux/glob.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/glob.cc diff --git a/src/compiler-rt/test/msan/Linux/glob_altdirfunc.cc b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/glob_altdirfunc.cc similarity index 100% rename from src/compiler-rt/test/msan/Linux/glob_altdirfunc.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/glob_altdirfunc.cc diff --git a/src/compiler-rt/test/msan/Linux/glob_nomatch.cc b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/glob_nomatch.cc similarity index 100% rename from src/compiler-rt/test/msan/Linux/glob_nomatch.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/glob_nomatch.cc diff --git a/src/compiler-rt/test/msan/Linux/glob_test_root/aa b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/glob_test_root/aa similarity index 100% rename from src/compiler-rt/test/msan/Linux/glob_test_root/aa rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/glob_test_root/aa diff --git a/src/compiler-rt/test/msan/Linux/glob_test_root/ab b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/glob_test_root/ab similarity index 100% rename from src/compiler-rt/test/msan/Linux/glob_test_root/ab rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/glob_test_root/ab diff --git a/src/compiler-rt/test/msan/Linux/glob_test_root/ba b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/glob_test_root/ba similarity index 100% rename from src/compiler-rt/test/msan/Linux/glob_test_root/ba rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/glob_test_root/ba diff --git a/src/compiler-rt/test/msan/Linux/ioctl_sound.cc b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/ioctl_sound.cc similarity index 100% rename from src/compiler-rt/test/msan/Linux/ioctl_sound.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/ioctl_sound.cc diff --git a/src/compiler-rt/test/msan/Linux/lit.local.cfg b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/lit.local.cfg similarity index 100% rename from src/compiler-rt/test/msan/Linux/lit.local.cfg rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/lit.local.cfg diff --git a/src/compiler-rt/test/msan/Linux/mallinfo.cc b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/mallinfo.cc similarity index 100% rename from src/compiler-rt/test/msan/Linux/mallinfo.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/mallinfo.cc diff --git a/src/compiler-rt/test/msan/Linux/mincore.cc b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/mincore.cc similarity index 100% rename from src/compiler-rt/test/msan/Linux/mincore.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/mincore.cc diff --git a/src/compiler-rt/test/msan/Linux/obstack.cc b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/obstack.cc similarity index 100% rename from src/compiler-rt/test/msan/Linux/obstack.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/obstack.cc diff --git a/src/compiler-rt/test/msan/Linux/process_vm_readv.cc b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/process_vm_readv.cc similarity index 100% rename from src/compiler-rt/test/msan/Linux/process_vm_readv.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/process_vm_readv.cc diff --git a/src/compiler-rt/test/msan/Linux/sendmsg.cc b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/sendmsg.cc similarity index 100% rename from src/compiler-rt/test/msan/Linux/sendmsg.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/sendmsg.cc diff --git a/src/compiler-rt/test/msan/Linux/sunrpc.cc b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/sunrpc.cc similarity index 100% rename from src/compiler-rt/test/msan/Linux/sunrpc.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/sunrpc.cc diff --git a/src/compiler-rt/test/msan/Linux/sunrpc_bytes.cc b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/sunrpc_bytes.cc similarity index 100% rename from src/compiler-rt/test/msan/Linux/sunrpc_bytes.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/sunrpc_bytes.cc diff --git a/src/compiler-rt/test/msan/Linux/sunrpc_string.cc b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/sunrpc_string.cc similarity index 100% rename from src/compiler-rt/test/msan/Linux/sunrpc_string.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/sunrpc_string.cc diff --git a/src/compiler-rt/test/msan/Linux/syscalls.cc b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/syscalls.cc similarity index 100% rename from src/compiler-rt/test/msan/Linux/syscalls.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/syscalls.cc diff --git a/src/compiler-rt/test/msan/Linux/syscalls_sigaction.cc b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/syscalls_sigaction.cc similarity index 100% rename from src/compiler-rt/test/msan/Linux/syscalls_sigaction.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/syscalls_sigaction.cc diff --git a/src/compiler-rt/test/msan/Linux/tcgetattr.cc b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/tcgetattr.cc similarity index 100% rename from src/compiler-rt/test/msan/Linux/tcgetattr.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/tcgetattr.cc diff --git a/src/compiler-rt/test/msan/Linux/xattr.cc b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/xattr.cc similarity index 100% rename from src/compiler-rt/test/msan/Linux/xattr.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/xattr.cc diff --git a/src/compiler-rt/test/msan/Linux/xattr_test_root/a b/src/libcompiler_builtins/compiler-rt/test/msan/Linux/xattr_test_root/a similarity index 100% rename from src/compiler-rt/test/msan/Linux/xattr_test_root/a rename to src/libcompiler_builtins/compiler-rt/test/msan/Linux/xattr_test_root/a diff --git a/src/compiler-rt/test/msan/Unit/lit.site.cfg.in b/src/libcompiler_builtins/compiler-rt/test/msan/Unit/lit.site.cfg.in similarity index 100% rename from src/compiler-rt/test/msan/Unit/lit.site.cfg.in rename to src/libcompiler_builtins/compiler-rt/test/msan/Unit/lit.site.cfg.in diff --git a/src/compiler-rt/test/msan/allocator_mapping.cc b/src/libcompiler_builtins/compiler-rt/test/msan/allocator_mapping.cc similarity index 100% rename from src/compiler-rt/test/msan/allocator_mapping.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/allocator_mapping.cc diff --git a/src/compiler-rt/test/msan/allocator_returns_null.cc b/src/libcompiler_builtins/compiler-rt/test/msan/allocator_returns_null.cc similarity index 100% rename from src/compiler-rt/test/msan/allocator_returns_null.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/allocator_returns_null.cc diff --git a/src/compiler-rt/test/msan/backtrace.cc b/src/libcompiler_builtins/compiler-rt/test/msan/backtrace.cc similarity index 100% rename from src/compiler-rt/test/msan/backtrace.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/backtrace.cc diff --git a/src/compiler-rt/test/msan/c-strdup.c b/src/libcompiler_builtins/compiler-rt/test/msan/c-strdup.c similarity index 100% rename from src/compiler-rt/test/msan/c-strdup.c rename to src/libcompiler_builtins/compiler-rt/test/msan/c-strdup.c diff --git a/src/compiler-rt/test/msan/chained_origin.cc b/src/libcompiler_builtins/compiler-rt/test/msan/chained_origin.cc similarity index 100% rename from src/compiler-rt/test/msan/chained_origin.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/chained_origin.cc diff --git a/src/compiler-rt/test/msan/chained_origin_empty_stack.cc b/src/libcompiler_builtins/compiler-rt/test/msan/chained_origin_empty_stack.cc similarity index 100% rename from src/compiler-rt/test/msan/chained_origin_empty_stack.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/chained_origin_empty_stack.cc diff --git a/src/compiler-rt/test/msan/chained_origin_limits.cc b/src/libcompiler_builtins/compiler-rt/test/msan/chained_origin_limits.cc similarity index 100% rename from src/compiler-rt/test/msan/chained_origin_limits.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/chained_origin_limits.cc diff --git a/src/compiler-rt/test/msan/chained_origin_memcpy.cc b/src/libcompiler_builtins/compiler-rt/test/msan/chained_origin_memcpy.cc similarity index 100% rename from src/compiler-rt/test/msan/chained_origin_memcpy.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/chained_origin_memcpy.cc diff --git a/src/compiler-rt/test/msan/chained_origin_with_signals.cc b/src/libcompiler_builtins/compiler-rt/test/msan/chained_origin_with_signals.cc similarity index 100% rename from src/compiler-rt/test/msan/chained_origin_with_signals.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/chained_origin_with_signals.cc diff --git a/src/compiler-rt/test/msan/check_mem_is_initialized.cc b/src/libcompiler_builtins/compiler-rt/test/msan/check_mem_is_initialized.cc similarity index 100% rename from src/compiler-rt/test/msan/check_mem_is_initialized.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/check_mem_is_initialized.cc diff --git a/src/compiler-rt/test/msan/coverage-levels.cc b/src/libcompiler_builtins/compiler-rt/test/msan/coverage-levels.cc similarity index 100% rename from src/compiler-rt/test/msan/coverage-levels.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/coverage-levels.cc diff --git a/src/compiler-rt/test/msan/ctermid.cc b/src/libcompiler_builtins/compiler-rt/test/msan/ctermid.cc similarity index 100% rename from src/compiler-rt/test/msan/ctermid.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/ctermid.cc diff --git a/src/compiler-rt/test/msan/cxa_atexit.cc b/src/libcompiler_builtins/compiler-rt/test/msan/cxa_atexit.cc similarity index 100% rename from src/compiler-rt/test/msan/cxa_atexit.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/cxa_atexit.cc diff --git a/src/compiler-rt/test/msan/death-callback.cc b/src/libcompiler_builtins/compiler-rt/test/msan/death-callback.cc similarity index 100% rename from src/compiler-rt/test/msan/death-callback.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/death-callback.cc diff --git a/src/compiler-rt/test/msan/default_blacklist.cc b/src/libcompiler_builtins/compiler-rt/test/msan/default_blacklist.cc similarity index 100% rename from src/compiler-rt/test/msan/default_blacklist.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/default_blacklist.cc diff --git a/src/compiler-rt/test/msan/dlerror.cc b/src/libcompiler_builtins/compiler-rt/test/msan/dlerror.cc similarity index 100% rename from src/compiler-rt/test/msan/dlerror.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/dlerror.cc diff --git a/src/compiler-rt/test/msan/dlopen_executable.cc b/src/libcompiler_builtins/compiler-rt/test/msan/dlopen_executable.cc similarity index 100% rename from src/compiler-rt/test/msan/dlopen_executable.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/dlopen_executable.cc diff --git a/src/compiler-rt/test/msan/dso-origin.cc b/src/libcompiler_builtins/compiler-rt/test/msan/dso-origin.cc similarity index 100% rename from src/compiler-rt/test/msan/dso-origin.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/dso-origin.cc diff --git a/src/compiler-rt/test/msan/dtls_test.c b/src/libcompiler_builtins/compiler-rt/test/msan/dtls_test.c similarity index 100% rename from src/compiler-rt/test/msan/dtls_test.c rename to src/libcompiler_builtins/compiler-rt/test/msan/dtls_test.c diff --git a/src/compiler-rt/test/msan/dtor-base-access.cc b/src/libcompiler_builtins/compiler-rt/test/msan/dtor-base-access.cc similarity index 100% rename from src/compiler-rt/test/msan/dtor-base-access.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/dtor-base-access.cc diff --git a/src/compiler-rt/test/msan/dtor-bit-fields.cc b/src/libcompiler_builtins/compiler-rt/test/msan/dtor-bit-fields.cc similarity index 100% rename from src/compiler-rt/test/msan/dtor-bit-fields.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/dtor-bit-fields.cc diff --git a/src/compiler-rt/test/msan/dtor-derived-class.cc b/src/libcompiler_builtins/compiler-rt/test/msan/dtor-derived-class.cc similarity index 100% rename from src/compiler-rt/test/msan/dtor-derived-class.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/dtor-derived-class.cc diff --git a/src/compiler-rt/test/msan/dtor-member.cc b/src/libcompiler_builtins/compiler-rt/test/msan/dtor-member.cc similarity index 100% rename from src/compiler-rt/test/msan/dtor-member.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/dtor-member.cc diff --git a/src/compiler-rt/test/msan/dtor-multiple-inheritance-nontrivial-class-members.cc b/src/libcompiler_builtins/compiler-rt/test/msan/dtor-multiple-inheritance-nontrivial-class-members.cc similarity index 100% rename from src/compiler-rt/test/msan/dtor-multiple-inheritance-nontrivial-class-members.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/dtor-multiple-inheritance-nontrivial-class-members.cc diff --git a/src/compiler-rt/test/msan/dtor-multiple-inheritance.cc b/src/libcompiler_builtins/compiler-rt/test/msan/dtor-multiple-inheritance.cc similarity index 100% rename from src/compiler-rt/test/msan/dtor-multiple-inheritance.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/dtor-multiple-inheritance.cc diff --git a/src/compiler-rt/test/msan/dtor-trivial-class-members.cc b/src/libcompiler_builtins/compiler-rt/test/msan/dtor-trivial-class-members.cc similarity index 100% rename from src/compiler-rt/test/msan/dtor-trivial-class-members.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/dtor-trivial-class-members.cc diff --git a/src/compiler-rt/test/msan/dtor-trivial.cpp b/src/libcompiler_builtins/compiler-rt/test/msan/dtor-trivial.cpp similarity index 100% rename from src/compiler-rt/test/msan/dtor-trivial.cpp rename to src/libcompiler_builtins/compiler-rt/test/msan/dtor-trivial.cpp diff --git a/src/compiler-rt/test/msan/dtor-vtable-multiple-inheritance.cc b/src/libcompiler_builtins/compiler-rt/test/msan/dtor-vtable-multiple-inheritance.cc similarity index 100% rename from src/compiler-rt/test/msan/dtor-vtable-multiple-inheritance.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/dtor-vtable-multiple-inheritance.cc diff --git a/src/compiler-rt/test/msan/dtor-vtable.cc b/src/libcompiler_builtins/compiler-rt/test/msan/dtor-vtable.cc similarity index 100% rename from src/compiler-rt/test/msan/dtor-vtable.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/dtor-vtable.cc diff --git a/src/compiler-rt/test/msan/errno.cc b/src/libcompiler_builtins/compiler-rt/test/msan/errno.cc similarity index 100% rename from src/compiler-rt/test/msan/errno.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/errno.cc diff --git a/src/compiler-rt/test/msan/fork.cc b/src/libcompiler_builtins/compiler-rt/test/msan/fork.cc similarity index 100% rename from src/compiler-rt/test/msan/fork.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/fork.cc diff --git a/src/compiler-rt/test/msan/ftime.cc b/src/libcompiler_builtins/compiler-rt/test/msan/ftime.cc similarity index 100% rename from src/compiler-rt/test/msan/ftime.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/ftime.cc diff --git a/src/compiler-rt/test/msan/getaddrinfo-positive.cc b/src/libcompiler_builtins/compiler-rt/test/msan/getaddrinfo-positive.cc similarity index 100% rename from src/compiler-rt/test/msan/getaddrinfo-positive.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/getaddrinfo-positive.cc diff --git a/src/compiler-rt/test/msan/getaddrinfo.cc b/src/libcompiler_builtins/compiler-rt/test/msan/getaddrinfo.cc similarity index 100% rename from src/compiler-rt/test/msan/getaddrinfo.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/getaddrinfo.cc diff --git a/src/compiler-rt/test/msan/getc_unlocked.c b/src/libcompiler_builtins/compiler-rt/test/msan/getc_unlocked.c similarity index 100% rename from src/compiler-rt/test/msan/getc_unlocked.c rename to src/libcompiler_builtins/compiler-rt/test/msan/getc_unlocked.c diff --git a/src/compiler-rt/test/msan/getline.cc b/src/libcompiler_builtins/compiler-rt/test/msan/getline.cc similarity index 100% rename from src/compiler-rt/test/msan/getline.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/getline.cc diff --git a/src/compiler-rt/test/msan/getutent.cc b/src/libcompiler_builtins/compiler-rt/test/msan/getutent.cc similarity index 100% rename from src/compiler-rt/test/msan/getutent.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/getutent.cc diff --git a/src/compiler-rt/test/msan/heap-origin.cc b/src/libcompiler_builtins/compiler-rt/test/msan/heap-origin.cc similarity index 100% rename from src/compiler-rt/test/msan/heap-origin.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/heap-origin.cc diff --git a/src/compiler-rt/test/msan/icmp_slt_allones.cc b/src/libcompiler_builtins/compiler-rt/test/msan/icmp_slt_allones.cc similarity index 100% rename from src/compiler-rt/test/msan/icmp_slt_allones.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/icmp_slt_allones.cc diff --git a/src/compiler-rt/test/msan/iconv.cc b/src/libcompiler_builtins/compiler-rt/test/msan/iconv.cc similarity index 100% rename from src/compiler-rt/test/msan/iconv.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/iconv.cc diff --git a/src/compiler-rt/test/msan/if_indextoname.cc b/src/libcompiler_builtins/compiler-rt/test/msan/if_indextoname.cc similarity index 100% rename from src/compiler-rt/test/msan/if_indextoname.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/if_indextoname.cc diff --git a/src/compiler-rt/test/msan/ifaddrs.cc b/src/libcompiler_builtins/compiler-rt/test/msan/ifaddrs.cc similarity index 100% rename from src/compiler-rt/test/msan/ifaddrs.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/ifaddrs.cc diff --git a/src/compiler-rt/test/msan/initgroups.cc b/src/libcompiler_builtins/compiler-rt/test/msan/initgroups.cc similarity index 100% rename from src/compiler-rt/test/msan/initgroups.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/initgroups.cc diff --git a/src/compiler-rt/test/msan/inline.cc b/src/libcompiler_builtins/compiler-rt/test/msan/inline.cc similarity index 100% rename from src/compiler-rt/test/msan/inline.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/inline.cc diff --git a/src/compiler-rt/test/msan/insertvalue_origin.cc b/src/libcompiler_builtins/compiler-rt/test/msan/insertvalue_origin.cc similarity index 100% rename from src/compiler-rt/test/msan/insertvalue_origin.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/insertvalue_origin.cc diff --git a/src/compiler-rt/test/msan/ioctl.cc b/src/libcompiler_builtins/compiler-rt/test/msan/ioctl.cc similarity index 100% rename from src/compiler-rt/test/msan/ioctl.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/ioctl.cc diff --git a/src/compiler-rt/test/msan/ioctl_custom.cc b/src/libcompiler_builtins/compiler-rt/test/msan/ioctl_custom.cc similarity index 100% rename from src/compiler-rt/test/msan/ioctl_custom.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/ioctl_custom.cc diff --git a/src/compiler-rt/test/msan/lit.cfg b/src/libcompiler_builtins/compiler-rt/test/msan/lit.cfg similarity index 100% rename from src/compiler-rt/test/msan/lit.cfg rename to src/libcompiler_builtins/compiler-rt/test/msan/lit.cfg diff --git a/src/compiler-rt/test/msan/lit.site.cfg.in b/src/libcompiler_builtins/compiler-rt/test/msan/lit.site.cfg.in similarity index 100% rename from src/compiler-rt/test/msan/lit.site.cfg.in rename to src/libcompiler_builtins/compiler-rt/test/msan/lit.site.cfg.in diff --git a/src/compiler-rt/test/msan/memcmp_test.cc b/src/libcompiler_builtins/compiler-rt/test/msan/memcmp_test.cc similarity index 100% rename from src/compiler-rt/test/msan/memcmp_test.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/memcmp_test.cc diff --git a/src/compiler-rt/test/msan/mktime.cc b/src/libcompiler_builtins/compiler-rt/test/msan/mktime.cc similarity index 100% rename from src/compiler-rt/test/msan/mktime.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/mktime.cc diff --git a/src/compiler-rt/test/msan/mmap.cc b/src/libcompiler_builtins/compiler-rt/test/msan/mmap.cc similarity index 100% rename from src/compiler-rt/test/msan/mmap.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/mmap.cc diff --git a/src/compiler-rt/test/msan/mmap_below_shadow.cc b/src/libcompiler_builtins/compiler-rt/test/msan/mmap_below_shadow.cc similarity index 100% rename from src/compiler-rt/test/msan/mmap_below_shadow.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/mmap_below_shadow.cc diff --git a/src/compiler-rt/test/msan/msan_check_mem_is_initialized.cc b/src/libcompiler_builtins/compiler-rt/test/msan/msan_check_mem_is_initialized.cc similarity index 100% rename from src/compiler-rt/test/msan/msan_check_mem_is_initialized.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/msan_check_mem_is_initialized.cc diff --git a/src/compiler-rt/test/msan/msan_copy_shadow.cc b/src/libcompiler_builtins/compiler-rt/test/msan/msan_copy_shadow.cc similarity index 100% rename from src/compiler-rt/test/msan/msan_copy_shadow.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/msan_copy_shadow.cc diff --git a/src/compiler-rt/test/msan/msan_dump_shadow.cc b/src/libcompiler_builtins/compiler-rt/test/msan/msan_dump_shadow.cc similarity index 100% rename from src/compiler-rt/test/msan/msan_dump_shadow.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/msan_dump_shadow.cc diff --git a/src/compiler-rt/test/msan/msan_print_shadow.cc b/src/libcompiler_builtins/compiler-rt/test/msan/msan_print_shadow.cc similarity index 100% rename from src/compiler-rt/test/msan/msan_print_shadow.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/msan_print_shadow.cc diff --git a/src/compiler-rt/test/msan/msan_print_shadow2.cc b/src/libcompiler_builtins/compiler-rt/test/msan/msan_print_shadow2.cc similarity index 100% rename from src/compiler-rt/test/msan/msan_print_shadow2.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/msan_print_shadow2.cc diff --git a/src/compiler-rt/test/msan/msan_print_shadow3.cc b/src/libcompiler_builtins/compiler-rt/test/msan/msan_print_shadow3.cc similarity index 100% rename from src/compiler-rt/test/msan/msan_print_shadow3.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/msan_print_shadow3.cc diff --git a/src/compiler-rt/test/msan/mul_by_const.cc b/src/libcompiler_builtins/compiler-rt/test/msan/mul_by_const.cc similarity index 100% rename from src/compiler-rt/test/msan/mul_by_const.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/mul_by_const.cc diff --git a/src/compiler-rt/test/msan/no_sanitize_memory.cc b/src/libcompiler_builtins/compiler-rt/test/msan/no_sanitize_memory.cc similarity index 100% rename from src/compiler-rt/test/msan/no_sanitize_memory.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/no_sanitize_memory.cc diff --git a/src/compiler-rt/test/msan/no_sanitize_memory_prop.cc b/src/libcompiler_builtins/compiler-rt/test/msan/no_sanitize_memory_prop.cc similarity index 100% rename from src/compiler-rt/test/msan/no_sanitize_memory_prop.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/no_sanitize_memory_prop.cc diff --git a/src/compiler-rt/test/msan/origin-store-long.cc b/src/libcompiler_builtins/compiler-rt/test/msan/origin-store-long.cc similarity index 100% rename from src/compiler-rt/test/msan/origin-store-long.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/origin-store-long.cc diff --git a/src/compiler-rt/test/msan/param_tls_limit.cc b/src/libcompiler_builtins/compiler-rt/test/msan/param_tls_limit.cc similarity index 100% rename from src/compiler-rt/test/msan/param_tls_limit.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/param_tls_limit.cc diff --git a/src/compiler-rt/test/msan/poison_in_free.cc b/src/libcompiler_builtins/compiler-rt/test/msan/poison_in_free.cc similarity index 100% rename from src/compiler-rt/test/msan/poison_in_free.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/poison_in_free.cc diff --git a/src/compiler-rt/test/msan/print_stats.cc b/src/libcompiler_builtins/compiler-rt/test/msan/print_stats.cc similarity index 100% rename from src/compiler-rt/test/msan/print_stats.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/print_stats.cc diff --git a/src/compiler-rt/test/msan/pthread_getattr_np_deadlock.cc b/src/libcompiler_builtins/compiler-rt/test/msan/pthread_getattr_np_deadlock.cc similarity index 100% rename from src/compiler-rt/test/msan/pthread_getattr_np_deadlock.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/pthread_getattr_np_deadlock.cc diff --git a/src/compiler-rt/test/msan/pthread_setcancelstate.cc b/src/libcompiler_builtins/compiler-rt/test/msan/pthread_setcancelstate.cc similarity index 100% rename from src/compiler-rt/test/msan/pthread_setcancelstate.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/pthread_setcancelstate.cc diff --git a/src/compiler-rt/test/msan/rand_r.cc b/src/libcompiler_builtins/compiler-rt/test/msan/rand_r.cc similarity index 100% rename from src/compiler-rt/test/msan/rand_r.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/rand_r.cc diff --git a/src/compiler-rt/test/msan/readdir64.cc b/src/libcompiler_builtins/compiler-rt/test/msan/readdir64.cc similarity index 100% rename from src/compiler-rt/test/msan/readdir64.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/readdir64.cc diff --git a/src/compiler-rt/test/msan/realloc-large-origin.cc b/src/libcompiler_builtins/compiler-rt/test/msan/realloc-large-origin.cc similarity index 100% rename from src/compiler-rt/test/msan/realloc-large-origin.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/realloc-large-origin.cc diff --git a/src/compiler-rt/test/msan/realloc-origin.cc b/src/libcompiler_builtins/compiler-rt/test/msan/realloc-origin.cc similarity index 100% rename from src/compiler-rt/test/msan/realloc-origin.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/realloc-origin.cc diff --git a/src/compiler-rt/test/msan/recover-dso.cc b/src/libcompiler_builtins/compiler-rt/test/msan/recover-dso.cc similarity index 100% rename from src/compiler-rt/test/msan/recover-dso.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/recover-dso.cc diff --git a/src/compiler-rt/test/msan/recover.cc b/src/libcompiler_builtins/compiler-rt/test/msan/recover.cc similarity index 100% rename from src/compiler-rt/test/msan/recover.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/recover.cc diff --git a/src/compiler-rt/test/msan/report-demangling.cc b/src/libcompiler_builtins/compiler-rt/test/msan/report-demangling.cc similarity index 100% rename from src/compiler-rt/test/msan/report-demangling.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/report-demangling.cc diff --git a/src/compiler-rt/test/msan/scandir.cc b/src/libcompiler_builtins/compiler-rt/test/msan/scandir.cc similarity index 100% rename from src/compiler-rt/test/msan/scandir.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/scandir.cc diff --git a/src/compiler-rt/test/msan/scandir_null.cc b/src/libcompiler_builtins/compiler-rt/test/msan/scandir_null.cc similarity index 100% rename from src/compiler-rt/test/msan/scandir_null.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/scandir_null.cc diff --git a/src/compiler-rt/test/msan/scandir_test_root/aaa b/src/libcompiler_builtins/compiler-rt/test/msan/scandir_test_root/aaa similarity index 100% rename from src/compiler-rt/test/msan/scandir_test_root/aaa rename to src/libcompiler_builtins/compiler-rt/test/msan/scandir_test_root/aaa diff --git a/src/compiler-rt/test/msan/scandir_test_root/aab b/src/libcompiler_builtins/compiler-rt/test/msan/scandir_test_root/aab similarity index 100% rename from src/compiler-rt/test/msan/scandir_test_root/aab rename to src/libcompiler_builtins/compiler-rt/test/msan/scandir_test_root/aab diff --git a/src/compiler-rt/test/msan/scandir_test_root/bbb b/src/libcompiler_builtins/compiler-rt/test/msan/scandir_test_root/bbb similarity index 100% rename from src/compiler-rt/test/msan/scandir_test_root/bbb rename to src/libcompiler_builtins/compiler-rt/test/msan/scandir_test_root/bbb diff --git a/src/compiler-rt/test/msan/select.cc b/src/libcompiler_builtins/compiler-rt/test/msan/select.cc similarity index 100% rename from src/compiler-rt/test/msan/select.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/select.cc diff --git a/src/compiler-rt/test/msan/select_float_origin.cc b/src/libcompiler_builtins/compiler-rt/test/msan/select_float_origin.cc similarity index 100% rename from src/compiler-rt/test/msan/select_float_origin.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/select_float_origin.cc diff --git a/src/compiler-rt/test/msan/select_origin.cc b/src/libcompiler_builtins/compiler-rt/test/msan/select_origin.cc similarity index 100% rename from src/compiler-rt/test/msan/select_origin.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/select_origin.cc diff --git a/src/compiler-rt/test/msan/sem_getvalue.cc b/src/libcompiler_builtins/compiler-rt/test/msan/sem_getvalue.cc similarity index 100% rename from src/compiler-rt/test/msan/sem_getvalue.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/sem_getvalue.cc diff --git a/src/compiler-rt/test/msan/setlocale.cc b/src/libcompiler_builtins/compiler-rt/test/msan/setlocale.cc similarity index 100% rename from src/compiler-rt/test/msan/setlocale.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/setlocale.cc diff --git a/src/compiler-rt/test/msan/signal_stress_test.cc b/src/libcompiler_builtins/compiler-rt/test/msan/signal_stress_test.cc similarity index 100% rename from src/compiler-rt/test/msan/signal_stress_test.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/signal_stress_test.cc diff --git a/src/compiler-rt/test/msan/sigwait.cc b/src/libcompiler_builtins/compiler-rt/test/msan/sigwait.cc similarity index 100% rename from src/compiler-rt/test/msan/sigwait.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/sigwait.cc diff --git a/src/compiler-rt/test/msan/sigwaitinfo.cc b/src/libcompiler_builtins/compiler-rt/test/msan/sigwaitinfo.cc similarity index 100% rename from src/compiler-rt/test/msan/sigwaitinfo.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/sigwaitinfo.cc diff --git a/src/compiler-rt/test/msan/stack-origin.cc b/src/libcompiler_builtins/compiler-rt/test/msan/stack-origin.cc similarity index 100% rename from src/compiler-rt/test/msan/stack-origin.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/stack-origin.cc diff --git a/src/compiler-rt/test/msan/stack-origin2.cc b/src/libcompiler_builtins/compiler-rt/test/msan/stack-origin2.cc similarity index 100% rename from src/compiler-rt/test/msan/stack-origin2.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/stack-origin2.cc diff --git a/src/compiler-rt/test/msan/strerror_r-non-gnu.c b/src/libcompiler_builtins/compiler-rt/test/msan/strerror_r-non-gnu.c similarity index 100% rename from src/compiler-rt/test/msan/strerror_r-non-gnu.c rename to src/libcompiler_builtins/compiler-rt/test/msan/strerror_r-non-gnu.c diff --git a/src/compiler-rt/test/msan/strlen_of_shadow.cc b/src/libcompiler_builtins/compiler-rt/test/msan/strlen_of_shadow.cc similarity index 100% rename from src/compiler-rt/test/msan/strlen_of_shadow.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/strlen_of_shadow.cc diff --git a/src/compiler-rt/test/msan/strxfrm.cc b/src/libcompiler_builtins/compiler-rt/test/msan/strxfrm.cc similarity index 100% rename from src/compiler-rt/test/msan/strxfrm.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/strxfrm.cc diff --git a/src/compiler-rt/test/msan/sync_lock_set_and_test.cc b/src/libcompiler_builtins/compiler-rt/test/msan/sync_lock_set_and_test.cc similarity index 100% rename from src/compiler-rt/test/msan/sync_lock_set_and_test.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/sync_lock_set_and_test.cc diff --git a/src/compiler-rt/test/msan/test.h b/src/libcompiler_builtins/compiler-rt/test/msan/test.h similarity index 100% rename from src/compiler-rt/test/msan/test.h rename to src/libcompiler_builtins/compiler-rt/test/msan/test.h diff --git a/src/compiler-rt/test/msan/textdomain.cc b/src/libcompiler_builtins/compiler-rt/test/msan/textdomain.cc similarity index 100% rename from src/compiler-rt/test/msan/textdomain.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/textdomain.cc diff --git a/src/compiler-rt/test/msan/times.cc b/src/libcompiler_builtins/compiler-rt/test/msan/times.cc similarity index 100% rename from src/compiler-rt/test/msan/times.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/times.cc diff --git a/src/compiler-rt/test/msan/tls_reuse.cc b/src/libcompiler_builtins/compiler-rt/test/msan/tls_reuse.cc similarity index 100% rename from src/compiler-rt/test/msan/tls_reuse.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/tls_reuse.cc diff --git a/src/compiler-rt/test/msan/tsearch.cc b/src/libcompiler_builtins/compiler-rt/test/msan/tsearch.cc similarity index 100% rename from src/compiler-rt/test/msan/tsearch.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/tsearch.cc diff --git a/src/compiler-rt/test/msan/tzset.cc b/src/libcompiler_builtins/compiler-rt/test/msan/tzset.cc similarity index 100% rename from src/compiler-rt/test/msan/tzset.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/tzset.cc diff --git a/src/compiler-rt/test/msan/unaligned_read_origin.cc b/src/libcompiler_builtins/compiler-rt/test/msan/unaligned_read_origin.cc similarity index 100% rename from src/compiler-rt/test/msan/unaligned_read_origin.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/unaligned_read_origin.cc diff --git a/src/compiler-rt/test/msan/unpoison_string.cc b/src/libcompiler_builtins/compiler-rt/test/msan/unpoison_string.cc similarity index 100% rename from src/compiler-rt/test/msan/unpoison_string.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/unpoison_string.cc diff --git a/src/compiler-rt/test/msan/use-after-dtor.cc b/src/libcompiler_builtins/compiler-rt/test/msan/use-after-dtor.cc similarity index 100% rename from src/compiler-rt/test/msan/use-after-dtor.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/use-after-dtor.cc diff --git a/src/compiler-rt/test/msan/use-after-free.cc b/src/libcompiler_builtins/compiler-rt/test/msan/use-after-free.cc similarity index 100% rename from src/compiler-rt/test/msan/use-after-free.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/use-after-free.cc diff --git a/src/compiler-rt/test/msan/vector_cvt.cc b/src/libcompiler_builtins/compiler-rt/test/msan/vector_cvt.cc similarity index 100% rename from src/compiler-rt/test/msan/vector_cvt.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/vector_cvt.cc diff --git a/src/compiler-rt/test/msan/vector_select.cc b/src/libcompiler_builtins/compiler-rt/test/msan/vector_select.cc similarity index 100% rename from src/compiler-rt/test/msan/vector_select.cc rename to src/libcompiler_builtins/compiler-rt/test/msan/vector_select.cc diff --git a/src/compiler-rt/test/profile/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/test/profile/CMakeLists.txt similarity index 100% rename from src/compiler-rt/test/profile/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/test/profile/CMakeLists.txt diff --git a/src/compiler-rt/test/profile/Inputs/comdat_rename.h b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/comdat_rename.h similarity index 100% rename from src/compiler-rt/test/profile/Inputs/comdat_rename.h rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/comdat_rename.h diff --git a/src/compiler-rt/test/profile/Inputs/comdat_rename_1.cc b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/comdat_rename_1.cc similarity index 100% rename from src/compiler-rt/test/profile/Inputs/comdat_rename_1.cc rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/comdat_rename_1.cc diff --git a/src/compiler-rt/test/profile/Inputs/comdat_rename_2.cc b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/comdat_rename_2.cc similarity index 100% rename from src/compiler-rt/test/profile/Inputs/comdat_rename_2.cc rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/comdat_rename_2.cc diff --git a/src/compiler-rt/test/profile/Inputs/extern_template.cpp b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/extern_template.cpp similarity index 100% rename from src/compiler-rt/test/profile/Inputs/extern_template.cpp rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/extern_template.cpp diff --git a/src/compiler-rt/test/profile/Inputs/extern_template.h b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/extern_template.h similarity index 100% rename from src/compiler-rt/test/profile/Inputs/extern_template.h rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/extern_template.h diff --git a/src/compiler-rt/test/profile/Inputs/extern_template1.cpp b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/extern_template1.cpp similarity index 100% rename from src/compiler-rt/test/profile/Inputs/extern_template1.cpp rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/extern_template1.cpp diff --git a/src/compiler-rt/test/profile/Inputs/extern_template2.cpp b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/extern_template2.cpp similarity index 100% rename from src/compiler-rt/test/profile/Inputs/extern_template2.cpp rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/extern_template2.cpp diff --git a/src/compiler-rt/test/profile/Inputs/gcc-flag-compatibility.c b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/gcc-flag-compatibility.c similarity index 100% rename from src/compiler-rt/test/profile/Inputs/gcc-flag-compatibility.c rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/gcc-flag-compatibility.c diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-alloc.c b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-alloc.c similarity index 100% rename from src/compiler-rt/test/profile/Inputs/instrprof-alloc.c rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-alloc.c diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-comdat-1.cpp b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-comdat-1.cpp similarity index 100% rename from src/compiler-rt/test/profile/Inputs/instrprof-comdat-1.cpp rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-comdat-1.cpp diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-comdat-2.cpp b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-comdat-2.cpp similarity index 100% rename from src/compiler-rt/test/profile/Inputs/instrprof-comdat-2.cpp rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-comdat-2.cpp diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-comdat.h b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-comdat.h similarity index 100% rename from src/compiler-rt/test/profile/Inputs/instrprof-comdat.h rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-comdat.h diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-dlopen-func.c b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-dlopen-func.c similarity index 100% rename from src/compiler-rt/test/profile/Inputs/instrprof-dlopen-func.c rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-dlopen-func.c diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-dlopen-func2.c b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-dlopen-func2.c similarity index 100% rename from src/compiler-rt/test/profile/Inputs/instrprof-dlopen-func2.c rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-dlopen-func2.c diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-dlopen-main.c b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-dlopen-main.c similarity index 100% rename from src/compiler-rt/test/profile/Inputs/instrprof-dlopen-main.c rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-dlopen-main.c diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-dynamic-a.cpp b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-dynamic-a.cpp similarity index 100% rename from src/compiler-rt/test/profile/Inputs/instrprof-dynamic-a.cpp rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-dynamic-a.cpp diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-dynamic-b.cpp b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-dynamic-b.cpp similarity index 100% rename from src/compiler-rt/test/profile/Inputs/instrprof-dynamic-b.cpp rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-dynamic-b.cpp diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-dynamic-header.h b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-dynamic-header.h similarity index 100% rename from src/compiler-rt/test/profile/Inputs/instrprof-dynamic-header.h rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-dynamic-header.h diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-dynamic-main.cpp b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-dynamic-main.cpp similarity index 100% rename from src/compiler-rt/test/profile/Inputs/instrprof-dynamic-main.cpp rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-dynamic-main.cpp diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-file_ex.c b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-file_ex.c similarity index 100% rename from src/compiler-rt/test/profile/Inputs/instrprof-file_ex.c rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-file_ex.c diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-icall-promo.h b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-icall-promo.h similarity index 100% rename from src/compiler-rt/test/profile/Inputs/instrprof-icall-promo.h rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-icall-promo.h diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-icall-promo_1.cc b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-icall-promo_1.cc similarity index 100% rename from src/compiler-rt/test/profile/Inputs/instrprof-icall-promo_1.cc rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-icall-promo_1.cc diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-icall-promo_2.cc b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-icall-promo_2.cc similarity index 100% rename from src/compiler-rt/test/profile/Inputs/instrprof-icall-promo_2.cc rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-icall-promo_2.cc diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-merge-match-lib.c b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-merge-match-lib.c similarity index 100% rename from src/compiler-rt/test/profile/Inputs/instrprof-merge-match-lib.c rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-merge-match-lib.c diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-merge-match.c b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-merge-match.c similarity index 100% rename from src/compiler-rt/test/profile/Inputs/instrprof-merge-match.c rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-merge-match.c diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-shared-lib.c b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-shared-lib.c similarity index 100% rename from src/compiler-rt/test/profile/Inputs/instrprof-shared-lib.c rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-shared-lib.c diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-shared-main.c b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-shared-main.c similarity index 100% rename from src/compiler-rt/test/profile/Inputs/instrprof-shared-main.c rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-shared-main.c diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-value-prof-evict.c b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-value-prof-evict.c similarity index 100% rename from src/compiler-rt/test/profile/Inputs/instrprof-value-prof-evict.c rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-value-prof-evict.c diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-value-prof-real.c b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-value-prof-real.c similarity index 100% rename from src/compiler-rt/test/profile/Inputs/instrprof-value-prof-real.c rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-value-prof-real.c diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-visibility-helper.cpp b/src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-visibility-helper.cpp similarity index 100% rename from src/compiler-rt/test/profile/Inputs/instrprof-visibility-helper.cpp rename to src/libcompiler_builtins/compiler-rt/test/profile/Inputs/instrprof-visibility-helper.cpp diff --git a/src/compiler-rt/test/profile/Linux/comdat_rename.test b/src/libcompiler_builtins/compiler-rt/test/profile/Linux/comdat_rename.test similarity index 100% rename from src/compiler-rt/test/profile/Linux/comdat_rename.test rename to src/libcompiler_builtins/compiler-rt/test/profile/Linux/comdat_rename.test diff --git a/src/compiler-rt/test/profile/Linux/coverage_ctors.cpp b/src/libcompiler_builtins/compiler-rt/test/profile/Linux/coverage_ctors.cpp similarity index 100% rename from src/compiler-rt/test/profile/Linux/coverage_ctors.cpp rename to src/libcompiler_builtins/compiler-rt/test/profile/Linux/coverage_ctors.cpp diff --git a/src/compiler-rt/test/profile/Linux/coverage_dtor.cpp b/src/libcompiler_builtins/compiler-rt/test/profile/Linux/coverage_dtor.cpp similarity index 100% rename from src/compiler-rt/test/profile/Linux/coverage_dtor.cpp rename to src/libcompiler_builtins/compiler-rt/test/profile/Linux/coverage_dtor.cpp diff --git a/src/compiler-rt/test/profile/Linux/coverage_shared.test b/src/libcompiler_builtins/compiler-rt/test/profile/Linux/coverage_shared.test similarity index 100% rename from src/compiler-rt/test/profile/Linux/coverage_shared.test rename to src/libcompiler_builtins/compiler-rt/test/profile/Linux/coverage_shared.test diff --git a/src/compiler-rt/test/profile/Linux/coverage_test.cpp b/src/libcompiler_builtins/compiler-rt/test/profile/Linux/coverage_test.cpp similarity index 100% rename from src/compiler-rt/test/profile/Linux/coverage_test.cpp rename to src/libcompiler_builtins/compiler-rt/test/profile/Linux/coverage_test.cpp diff --git a/src/compiler-rt/test/profile/Linux/extern_template.test b/src/libcompiler_builtins/compiler-rt/test/profile/Linux/extern_template.test similarity index 100% rename from src/compiler-rt/test/profile/Linux/extern_template.test rename to src/libcompiler_builtins/compiler-rt/test/profile/Linux/extern_template.test diff --git a/src/compiler-rt/test/profile/Linux/instrprof-alloc.test b/src/libcompiler_builtins/compiler-rt/test/profile/Linux/instrprof-alloc.test similarity index 100% rename from src/compiler-rt/test/profile/Linux/instrprof-alloc.test rename to src/libcompiler_builtins/compiler-rt/test/profile/Linux/instrprof-alloc.test diff --git a/src/compiler-rt/test/profile/Linux/instrprof-basic.c b/src/libcompiler_builtins/compiler-rt/test/profile/Linux/instrprof-basic.c similarity index 100% rename from src/compiler-rt/test/profile/Linux/instrprof-basic.c rename to src/libcompiler_builtins/compiler-rt/test/profile/Linux/instrprof-basic.c diff --git a/src/compiler-rt/test/profile/Linux/instrprof-comdat.test b/src/libcompiler_builtins/compiler-rt/test/profile/Linux/instrprof-comdat.test similarity index 100% rename from src/compiler-rt/test/profile/Linux/instrprof-comdat.test rename to src/libcompiler_builtins/compiler-rt/test/profile/Linux/instrprof-comdat.test diff --git a/src/compiler-rt/test/profile/Linux/instrprof-cs.c b/src/libcompiler_builtins/compiler-rt/test/profile/Linux/instrprof-cs.c similarity index 100% rename from src/compiler-rt/test/profile/Linux/instrprof-cs.c rename to src/libcompiler_builtins/compiler-rt/test/profile/Linux/instrprof-cs.c diff --git a/src/compiler-rt/test/profile/Linux/instrprof-dlopen.test b/src/libcompiler_builtins/compiler-rt/test/profile/Linux/instrprof-dlopen.test similarity index 100% rename from src/compiler-rt/test/profile/Linux/instrprof-dlopen.test rename to src/libcompiler_builtins/compiler-rt/test/profile/Linux/instrprof-dlopen.test diff --git a/src/compiler-rt/test/profile/Linux/instrprof-dynamic-one-shared.test b/src/libcompiler_builtins/compiler-rt/test/profile/Linux/instrprof-dynamic-one-shared.test similarity index 100% rename from src/compiler-rt/test/profile/Linux/instrprof-dynamic-one-shared.test rename to src/libcompiler_builtins/compiler-rt/test/profile/Linux/instrprof-dynamic-one-shared.test diff --git a/src/compiler-rt/test/profile/Linux/instrprof-dynamic-two-shared.test b/src/libcompiler_builtins/compiler-rt/test/profile/Linux/instrprof-dynamic-two-shared.test similarity index 100% rename from src/compiler-rt/test/profile/Linux/instrprof-dynamic-two-shared.test rename to src/libcompiler_builtins/compiler-rt/test/profile/Linux/instrprof-dynamic-two-shared.test diff --git a/src/compiler-rt/test/profile/Linux/instrprof-file_ex.test b/src/libcompiler_builtins/compiler-rt/test/profile/Linux/instrprof-file_ex.test similarity index 100% rename from src/compiler-rt/test/profile/Linux/instrprof-file_ex.test rename to src/libcompiler_builtins/compiler-rt/test/profile/Linux/instrprof-file_ex.test diff --git a/src/compiler-rt/test/profile/Linux/instrprof-merge-vp.c b/src/libcompiler_builtins/compiler-rt/test/profile/Linux/instrprof-merge-vp.c similarity index 100% rename from src/compiler-rt/test/profile/Linux/instrprof-merge-vp.c rename to src/libcompiler_builtins/compiler-rt/test/profile/Linux/instrprof-merge-vp.c diff --git a/src/compiler-rt/test/profile/Linux/instrprof-value-prof-warn.test b/src/libcompiler_builtins/compiler-rt/test/profile/Linux/instrprof-value-prof-warn.test similarity index 100% rename from src/compiler-rt/test/profile/Linux/instrprof-value-prof-warn.test rename to src/libcompiler_builtins/compiler-rt/test/profile/Linux/instrprof-value-prof-warn.test diff --git a/src/compiler-rt/test/profile/Linux/lit.local.cfg b/src/libcompiler_builtins/compiler-rt/test/profile/Linux/lit.local.cfg similarity index 100% rename from src/compiler-rt/test/profile/Linux/lit.local.cfg rename to src/libcompiler_builtins/compiler-rt/test/profile/Linux/lit.local.cfg diff --git a/src/compiler-rt/test/profile/gcc-flag-compatibility.test b/src/libcompiler_builtins/compiler-rt/test/profile/gcc-flag-compatibility.test similarity index 100% rename from src/compiler-rt/test/profile/gcc-flag-compatibility.test rename to src/libcompiler_builtins/compiler-rt/test/profile/gcc-flag-compatibility.test diff --git a/src/compiler-rt/test/profile/instrprof-basic.c b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-basic.c similarity index 100% rename from src/compiler-rt/test/profile/instrprof-basic.c rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-basic.c diff --git a/src/compiler-rt/test/profile/instrprof-bufferio.c b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-bufferio.c similarity index 100% rename from src/compiler-rt/test/profile/instrprof-bufferio.c rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-bufferio.c diff --git a/src/compiler-rt/test/profile/instrprof-darwin-dead-strip.c b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-darwin-dead-strip.c similarity index 100% rename from src/compiler-rt/test/profile/instrprof-darwin-dead-strip.c rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-darwin-dead-strip.c diff --git a/src/compiler-rt/test/profile/instrprof-dlopen.test b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-dlopen.test similarity index 100% rename from src/compiler-rt/test/profile/instrprof-dlopen.test rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-dlopen.test diff --git a/src/compiler-rt/test/profile/instrprof-dump.c b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-dump.c similarity index 100% rename from src/compiler-rt/test/profile/instrprof-dump.c rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-dump.c diff --git a/src/compiler-rt/test/profile/instrprof-dynamic-one-shared.test b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-dynamic-one-shared.test similarity index 100% rename from src/compiler-rt/test/profile/instrprof-dynamic-one-shared.test rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-dynamic-one-shared.test diff --git a/src/compiler-rt/test/profile/instrprof-dynamic-two-shared.test b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-dynamic-two-shared.test similarity index 100% rename from src/compiler-rt/test/profile/instrprof-dynamic-two-shared.test rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-dynamic-two-shared.test diff --git a/src/compiler-rt/test/profile/instrprof-error.c b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-error.c similarity index 100% rename from src/compiler-rt/test/profile/instrprof-error.c rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-error.c diff --git a/src/compiler-rt/test/profile/instrprof-hostname.c b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-hostname.c similarity index 100% rename from src/compiler-rt/test/profile/instrprof-hostname.c rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-hostname.c diff --git a/src/compiler-rt/test/profile/instrprof-icall-promo.test b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-icall-promo.test similarity index 100% rename from src/compiler-rt/test/profile/instrprof-icall-promo.test rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-icall-promo.test diff --git a/src/compiler-rt/test/profile/instrprof-merge-match.test b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-merge-match.test similarity index 100% rename from src/compiler-rt/test/profile/instrprof-merge-match.test rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-merge-match.test diff --git a/src/compiler-rt/test/profile/instrprof-merge.c b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-merge.c similarity index 100% rename from src/compiler-rt/test/profile/instrprof-merge.c rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-merge.c diff --git a/src/compiler-rt/test/profile/instrprof-override-filename-then-reset-default.c b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-override-filename-then-reset-default.c similarity index 100% rename from src/compiler-rt/test/profile/instrprof-override-filename-then-reset-default.c rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-override-filename-then-reset-default.c diff --git a/src/compiler-rt/test/profile/instrprof-override-filename-with-env.c b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-override-filename-with-env.c similarity index 100% rename from src/compiler-rt/test/profile/instrprof-override-filename-with-env.c rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-override-filename-with-env.c diff --git a/src/compiler-rt/test/profile/instrprof-override-filename.c b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-override-filename.c similarity index 100% rename from src/compiler-rt/test/profile/instrprof-override-filename.c rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-override-filename.c diff --git a/src/compiler-rt/test/profile/instrprof-path.c b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-path.c similarity index 100% rename from src/compiler-rt/test/profile/instrprof-path.c rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-path.c diff --git a/src/compiler-rt/test/profile/instrprof-reset-counters.c b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-reset-counters.c similarity index 100% rename from src/compiler-rt/test/profile/instrprof-reset-counters.c rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-reset-counters.c diff --git a/src/compiler-rt/test/profile/instrprof-set-filename-shared.test b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-set-filename-shared.test similarity index 100% rename from src/compiler-rt/test/profile/instrprof-set-filename-shared.test rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-set-filename-shared.test diff --git a/src/compiler-rt/test/profile/instrprof-set-filename-then-reset-default.c b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-set-filename-then-reset-default.c similarity index 100% rename from src/compiler-rt/test/profile/instrprof-set-filename-then-reset-default.c rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-set-filename-then-reset-default.c diff --git a/src/compiler-rt/test/profile/instrprof-set-filename.c b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-set-filename.c similarity index 100% rename from src/compiler-rt/test/profile/instrprof-set-filename.c rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-set-filename.c diff --git a/src/compiler-rt/test/profile/instrprof-shared.test b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-shared.test similarity index 100% rename from src/compiler-rt/test/profile/instrprof-shared.test rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-shared.test diff --git a/src/compiler-rt/test/profile/instrprof-value-prof-2.c b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-value-prof-2.c similarity index 100% rename from src/compiler-rt/test/profile/instrprof-value-prof-2.c rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-value-prof-2.c diff --git a/src/compiler-rt/test/profile/instrprof-value-prof-evict.test b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-value-prof-evict.test similarity index 100% rename from src/compiler-rt/test/profile/instrprof-value-prof-evict.test rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-value-prof-evict.test diff --git a/src/compiler-rt/test/profile/instrprof-value-prof-reset.c b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-value-prof-reset.c similarity index 100% rename from src/compiler-rt/test/profile/instrprof-value-prof-reset.c rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-value-prof-reset.c diff --git a/src/compiler-rt/test/profile/instrprof-value-prof-shared.test b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-value-prof-shared.test similarity index 100% rename from src/compiler-rt/test/profile/instrprof-value-prof-shared.test rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-value-prof-shared.test diff --git a/src/compiler-rt/test/profile/instrprof-value-prof.c b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-value-prof.c similarity index 100% rename from src/compiler-rt/test/profile/instrprof-value-prof.c rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-value-prof.c diff --git a/src/compiler-rt/test/profile/instrprof-value-prof.test b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-value-prof.test similarity index 100% rename from src/compiler-rt/test/profile/instrprof-value-prof.test rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-value-prof.test diff --git a/src/compiler-rt/test/profile/instrprof-version-mismatch.c b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-version-mismatch.c similarity index 100% rename from src/compiler-rt/test/profile/instrprof-version-mismatch.c rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-version-mismatch.c diff --git a/src/compiler-rt/test/profile/instrprof-visibility-kinds.inc b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-visibility-kinds.inc similarity index 100% rename from src/compiler-rt/test/profile/instrprof-visibility-kinds.inc rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-visibility-kinds.inc diff --git a/src/compiler-rt/test/profile/instrprof-visibility.cpp b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-visibility.cpp similarity index 100% rename from src/compiler-rt/test/profile/instrprof-visibility.cpp rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-visibility.cpp diff --git a/src/compiler-rt/test/profile/instrprof-without-libc.c b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-without-libc.c similarity index 100% rename from src/compiler-rt/test/profile/instrprof-without-libc.c rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-without-libc.c diff --git a/src/compiler-rt/test/profile/instrprof-write-file-atexit-explicitly.c b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-write-file-atexit-explicitly.c similarity index 100% rename from src/compiler-rt/test/profile/instrprof-write-file-atexit-explicitly.c rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-write-file-atexit-explicitly.c diff --git a/src/compiler-rt/test/profile/instrprof-write-file-only.c b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-write-file-only.c similarity index 100% rename from src/compiler-rt/test/profile/instrprof-write-file-only.c rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-write-file-only.c diff --git a/src/compiler-rt/test/profile/instrprof-write-file.c b/src/libcompiler_builtins/compiler-rt/test/profile/instrprof-write-file.c similarity index 100% rename from src/compiler-rt/test/profile/instrprof-write-file.c rename to src/libcompiler_builtins/compiler-rt/test/profile/instrprof-write-file.c diff --git a/src/compiler-rt/test/profile/lit.cfg b/src/libcompiler_builtins/compiler-rt/test/profile/lit.cfg similarity index 100% rename from src/compiler-rt/test/profile/lit.cfg rename to src/libcompiler_builtins/compiler-rt/test/profile/lit.cfg diff --git a/src/compiler-rt/test/profile/lit.site.cfg.in b/src/libcompiler_builtins/compiler-rt/test/profile/lit.site.cfg.in similarity index 100% rename from src/compiler-rt/test/profile/lit.site.cfg.in rename to src/libcompiler_builtins/compiler-rt/test/profile/lit.site.cfg.in diff --git a/src/compiler-rt/test/safestack/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/test/safestack/CMakeLists.txt similarity index 100% rename from src/compiler-rt/test/safestack/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/test/safestack/CMakeLists.txt diff --git a/src/compiler-rt/test/safestack/buffer-copy-vla.c b/src/libcompiler_builtins/compiler-rt/test/safestack/buffer-copy-vla.c similarity index 100% rename from src/compiler-rt/test/safestack/buffer-copy-vla.c rename to src/libcompiler_builtins/compiler-rt/test/safestack/buffer-copy-vla.c diff --git a/src/compiler-rt/test/safestack/buffer-copy.c b/src/libcompiler_builtins/compiler-rt/test/safestack/buffer-copy.c similarity index 100% rename from src/compiler-rt/test/safestack/buffer-copy.c rename to src/libcompiler_builtins/compiler-rt/test/safestack/buffer-copy.c diff --git a/src/compiler-rt/test/safestack/canary.c b/src/libcompiler_builtins/compiler-rt/test/safestack/canary.c similarity index 100% rename from src/compiler-rt/test/safestack/canary.c rename to src/libcompiler_builtins/compiler-rt/test/safestack/canary.c diff --git a/src/compiler-rt/test/safestack/init.c b/src/libcompiler_builtins/compiler-rt/test/safestack/init.c similarity index 100% rename from src/compiler-rt/test/safestack/init.c rename to src/libcompiler_builtins/compiler-rt/test/safestack/init.c diff --git a/src/compiler-rt/test/safestack/lit.cfg b/src/libcompiler_builtins/compiler-rt/test/safestack/lit.cfg similarity index 100% rename from src/compiler-rt/test/safestack/lit.cfg rename to src/libcompiler_builtins/compiler-rt/test/safestack/lit.cfg diff --git a/src/compiler-rt/test/safestack/lit.site.cfg.in b/src/libcompiler_builtins/compiler-rt/test/safestack/lit.site.cfg.in similarity index 100% rename from src/compiler-rt/test/safestack/lit.site.cfg.in rename to src/libcompiler_builtins/compiler-rt/test/safestack/lit.site.cfg.in diff --git a/src/compiler-rt/test/safestack/lto.c b/src/libcompiler_builtins/compiler-rt/test/safestack/lto.c similarity index 100% rename from src/compiler-rt/test/safestack/lto.c rename to src/libcompiler_builtins/compiler-rt/test/safestack/lto.c diff --git a/src/compiler-rt/test/safestack/overflow.c b/src/libcompiler_builtins/compiler-rt/test/safestack/overflow.c similarity index 100% rename from src/compiler-rt/test/safestack/overflow.c rename to src/libcompiler_builtins/compiler-rt/test/safestack/overflow.c diff --git a/src/compiler-rt/test/safestack/pthread-cleanup.c b/src/libcompiler_builtins/compiler-rt/test/safestack/pthread-cleanup.c similarity index 100% rename from src/compiler-rt/test/safestack/pthread-cleanup.c rename to src/libcompiler_builtins/compiler-rt/test/safestack/pthread-cleanup.c diff --git a/src/compiler-rt/test/safestack/pthread.c b/src/libcompiler_builtins/compiler-rt/test/safestack/pthread.c similarity index 100% rename from src/compiler-rt/test/safestack/pthread.c rename to src/libcompiler_builtins/compiler-rt/test/safestack/pthread.c diff --git a/src/compiler-rt/test/safestack/utils.h b/src/libcompiler_builtins/compiler-rt/test/safestack/utils.h similarity index 100% rename from src/compiler-rt/test/safestack/utils.h rename to src/libcompiler_builtins/compiler-rt/test/safestack/utils.h diff --git a/src/compiler-rt/test/sanitizer_common/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/CMakeLists.txt similarity index 100% rename from src/compiler-rt/test/sanitizer_common/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/CMakeLists.txt diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Darwin/abort_on_error.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Darwin/abort_on_error.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Darwin/abort_on_error.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Darwin/abort_on_error.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Darwin/lit.local.cfg b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Darwin/lit.local.cfg similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Darwin/lit.local.cfg rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Darwin/lit.local.cfg diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/abort_on_error.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/abort_on_error.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Linux/abort_on_error.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/abort_on_error.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/aligned_alloc.c b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/aligned_alloc.c similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Linux/aligned_alloc.c rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/aligned_alloc.c diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/assert.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/assert.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Linux/assert.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/assert.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/clock_gettime.c b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/clock_gettime.c similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Linux/clock_gettime.c rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/clock_gettime.c diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/closedir.c b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/closedir.c similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Linux/closedir.c rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/closedir.c diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/decorate_proc_maps.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/decorate_proc_maps.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Linux/decorate_proc_maps.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/decorate_proc_maps.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/fpe.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/fpe.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Linux/fpe.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/fpe.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/hard_rss_limit_mb_test.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/hard_rss_limit_mb_test.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Linux/hard_rss_limit_mb_test.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/hard_rss_limit_mb_test.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/ill.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/ill.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Linux/ill.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/ill.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/lit.local.cfg b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/lit.local.cfg similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Linux/lit.local.cfg rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/lit.local.cfg diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/mlock_test.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/mlock_test.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Linux/mlock_test.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/mlock_test.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/open_memstream.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/open_memstream.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Linux/open_memstream.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/open_memstream.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/ptrace.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/ptrace.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Linux/ptrace.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/ptrace.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/recv_msg_trunc.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/recv_msg_trunc.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Linux/recv_msg_trunc.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/recv_msg_trunc.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/sched_getparam.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/sched_getparam.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Linux/sched_getparam.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/sched_getparam.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/timerfd.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/timerfd.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Linux/timerfd.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/timerfd.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/weak_hook_test.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/weak_hook_test.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Linux/weak_hook_test.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Linux/weak_hook_test.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Posix/dedup_token_length_test.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Posix/dedup_token_length_test.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Posix/dedup_token_length_test.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Posix/dedup_token_length_test.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Posix/getpass.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Posix/getpass.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Posix/getpass.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Posix/getpass.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Posix/lit.local.cfg b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Posix/lit.local.cfg similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Posix/lit.local.cfg rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Posix/lit.local.cfg diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_death_callback_test.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_death_callback_test.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_death_callback_test.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_death_callback_test.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_fd_test.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_fd_test.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_fd_test.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_fd_test.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/corelimit.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/corelimit.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/corelimit.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/corelimit.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/fopen_nullptr.c b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/fopen_nullptr.c similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/fopen_nullptr.c rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/fopen_nullptr.c diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/malloc_hook.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/malloc_hook.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/malloc_hook.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/malloc_hook.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/options-help.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/options-help.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/options-help.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/options-help.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/options-include.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/options-include.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/options-include.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/options-include.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/options-invalid.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/options-invalid.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/options-invalid.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/options-invalid.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/print-stack-trace.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/print-stack-trace.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/print-stack-trace.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/print-stack-trace.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/pthread_mutexattr_get.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/pthread_mutexattr_get.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/pthread_mutexattr_get.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/pthread_mutexattr_get.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_symbolize.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_symbolize.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_symbolize.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_symbolize.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/strcasestr.c b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/strcasestr.c similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/strcasestr.c rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/strcasestr.c diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/strcspn.c b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/strcspn.c similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/strcspn.c rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/strcspn.c diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/strnlen.c b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/strnlen.c similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/strnlen.c rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/strnlen.c diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/strpbrk.c b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/strpbrk.c similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/strpbrk.c rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/strpbrk.c diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/strspn.c b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/strspn.c similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/strspn.c rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/strspn.c diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/strstr.c b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/strstr.c similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/strstr.c rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/strstr.c diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/symbolize_pc.cc b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/symbolize_pc.cc similarity index 100% rename from src/compiler-rt/test/sanitizer_common/TestCases/symbolize_pc.cc rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/TestCases/symbolize_pc.cc diff --git a/src/compiler-rt/test/sanitizer_common/Unit/lit.site.cfg.in b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/Unit/lit.site.cfg.in similarity index 100% rename from src/compiler-rt/test/sanitizer_common/Unit/lit.site.cfg.in rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/Unit/lit.site.cfg.in diff --git a/src/compiler-rt/test/sanitizer_common/lit.common.cfg b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/lit.common.cfg similarity index 100% rename from src/compiler-rt/test/sanitizer_common/lit.common.cfg rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/lit.common.cfg diff --git a/src/compiler-rt/test/sanitizer_common/lit.site.cfg.in b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/lit.site.cfg.in similarity index 100% rename from src/compiler-rt/test/sanitizer_common/lit.site.cfg.in rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/lit.site.cfg.in diff --git a/src/compiler-rt/test/sanitizer_common/print_address.h b/src/libcompiler_builtins/compiler-rt/test/sanitizer_common/print_address.h similarity index 100% rename from src/compiler-rt/test/sanitizer_common/print_address.h rename to src/libcompiler_builtins/compiler-rt/test/sanitizer_common/print_address.h diff --git a/src/compiler-rt/test/scudo/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/test/scudo/CMakeLists.txt similarity index 100% rename from src/compiler-rt/test/scudo/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/test/scudo/CMakeLists.txt diff --git a/src/compiler-rt/test/scudo/alignment.cpp b/src/libcompiler_builtins/compiler-rt/test/scudo/alignment.cpp similarity index 100% rename from src/compiler-rt/test/scudo/alignment.cpp rename to src/libcompiler_builtins/compiler-rt/test/scudo/alignment.cpp diff --git a/src/compiler-rt/test/scudo/double-free.cpp b/src/libcompiler_builtins/compiler-rt/test/scudo/double-free.cpp similarity index 100% rename from src/compiler-rt/test/scudo/double-free.cpp rename to src/libcompiler_builtins/compiler-rt/test/scudo/double-free.cpp diff --git a/src/compiler-rt/test/scudo/interface.cpp b/src/libcompiler_builtins/compiler-rt/test/scudo/interface.cpp similarity index 100% rename from src/compiler-rt/test/scudo/interface.cpp rename to src/libcompiler_builtins/compiler-rt/test/scudo/interface.cpp diff --git a/src/compiler-rt/test/scudo/lit.cfg b/src/libcompiler_builtins/compiler-rt/test/scudo/lit.cfg similarity index 100% rename from src/compiler-rt/test/scudo/lit.cfg rename to src/libcompiler_builtins/compiler-rt/test/scudo/lit.cfg diff --git a/src/compiler-rt/test/scudo/lit.site.cfg.in b/src/libcompiler_builtins/compiler-rt/test/scudo/lit.site.cfg.in similarity index 100% rename from src/compiler-rt/test/scudo/lit.site.cfg.in rename to src/libcompiler_builtins/compiler-rt/test/scudo/lit.site.cfg.in diff --git a/src/compiler-rt/test/scudo/malloc.cpp b/src/libcompiler_builtins/compiler-rt/test/scudo/malloc.cpp similarity index 100% rename from src/compiler-rt/test/scudo/malloc.cpp rename to src/libcompiler_builtins/compiler-rt/test/scudo/malloc.cpp diff --git a/src/compiler-rt/test/scudo/memalign.cpp b/src/libcompiler_builtins/compiler-rt/test/scudo/memalign.cpp similarity index 100% rename from src/compiler-rt/test/scudo/memalign.cpp rename to src/libcompiler_builtins/compiler-rt/test/scudo/memalign.cpp diff --git a/src/compiler-rt/test/scudo/mismatch.cpp b/src/libcompiler_builtins/compiler-rt/test/scudo/mismatch.cpp similarity index 100% rename from src/compiler-rt/test/scudo/mismatch.cpp rename to src/libcompiler_builtins/compiler-rt/test/scudo/mismatch.cpp diff --git a/src/compiler-rt/test/scudo/options.cpp b/src/libcompiler_builtins/compiler-rt/test/scudo/options.cpp similarity index 100% rename from src/compiler-rt/test/scudo/options.cpp rename to src/libcompiler_builtins/compiler-rt/test/scudo/options.cpp diff --git a/src/compiler-rt/test/scudo/overflow.cpp b/src/libcompiler_builtins/compiler-rt/test/scudo/overflow.cpp similarity index 100% rename from src/compiler-rt/test/scudo/overflow.cpp rename to src/libcompiler_builtins/compiler-rt/test/scudo/overflow.cpp diff --git a/src/compiler-rt/test/scudo/preinit.cpp b/src/libcompiler_builtins/compiler-rt/test/scudo/preinit.cpp similarity index 100% rename from src/compiler-rt/test/scudo/preinit.cpp rename to src/libcompiler_builtins/compiler-rt/test/scudo/preinit.cpp diff --git a/src/compiler-rt/test/scudo/quarantine.cpp b/src/libcompiler_builtins/compiler-rt/test/scudo/quarantine.cpp similarity index 100% rename from src/compiler-rt/test/scudo/quarantine.cpp rename to src/libcompiler_builtins/compiler-rt/test/scudo/quarantine.cpp diff --git a/src/compiler-rt/test/scudo/random_shuffle.cpp b/src/libcompiler_builtins/compiler-rt/test/scudo/random_shuffle.cpp similarity index 100% rename from src/compiler-rt/test/scudo/random_shuffle.cpp rename to src/libcompiler_builtins/compiler-rt/test/scudo/random_shuffle.cpp diff --git a/src/compiler-rt/test/scudo/realloc.cpp b/src/libcompiler_builtins/compiler-rt/test/scudo/realloc.cpp similarity index 100% rename from src/compiler-rt/test/scudo/realloc.cpp rename to src/libcompiler_builtins/compiler-rt/test/scudo/realloc.cpp diff --git a/src/compiler-rt/test/scudo/secondary.cpp b/src/libcompiler_builtins/compiler-rt/test/scudo/secondary.cpp similarity index 100% rename from src/compiler-rt/test/scudo/secondary.cpp rename to src/libcompiler_builtins/compiler-rt/test/scudo/secondary.cpp diff --git a/src/compiler-rt/test/scudo/sized-delete.cpp b/src/libcompiler_builtins/compiler-rt/test/scudo/sized-delete.cpp similarity index 100% rename from src/compiler-rt/test/scudo/sized-delete.cpp rename to src/libcompiler_builtins/compiler-rt/test/scudo/sized-delete.cpp diff --git a/src/compiler-rt/test/scudo/sizes.cpp b/src/libcompiler_builtins/compiler-rt/test/scudo/sizes.cpp similarity index 100% rename from src/compiler-rt/test/scudo/sizes.cpp rename to src/libcompiler_builtins/compiler-rt/test/scudo/sizes.cpp diff --git a/src/compiler-rt/test/tsan/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/test/tsan/CMakeLists.txt similarity index 100% rename from src/compiler-rt/test/tsan/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/test/tsan/CMakeLists.txt diff --git a/src/compiler-rt/test/tsan/Darwin/dispatch_main.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/dispatch_main.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/dispatch_main.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/dispatch_main.mm diff --git a/src/compiler-rt/test/tsan/Darwin/dispatch_once_deadlock.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/dispatch_once_deadlock.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/dispatch_once_deadlock.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/dispatch_once_deadlock.mm diff --git a/src/compiler-rt/test/tsan/Darwin/dlopen.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/dlopen.cc similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/dlopen.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/dlopen.cc diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-after.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-after.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-after.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-after.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-apply-race.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-apply-race.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-apply-race.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-apply-race.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-apply.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-apply.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-apply.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-apply.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-async-norace.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-async-norace.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-async-norace.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-async-norace.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-async-race.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-async-race.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-async-race.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-async-race.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-barrier-race.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-barrier-race.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-barrier-race.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-barrier-race.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-barrier.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-barrier.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-barrier.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-barrier.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-blocks.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-blocks.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-blocks.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-blocks.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-data.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-data.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-data.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-data.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-fd.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-fd.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-fd.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-fd.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-groups-destructor.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-groups-destructor.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-groups-destructor.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-groups-destructor.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-groups-leave.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-groups-leave.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-groups-leave.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-groups-leave.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-groups-norace.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-groups-norace.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-groups-norace.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-groups-norace.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-groups-stress.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-groups-stress.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-groups-stress.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-groups-stress.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-io-barrier-race.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-io-barrier-race.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-io-barrier-race.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-io-barrier-race.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-io-barrier.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-io-barrier.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-io-barrier.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-io-barrier.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-io-cleanup.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-io-cleanup.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-io-cleanup.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-io-cleanup.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-io-race.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-io-race.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-io-race.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-io-race.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-io.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-io.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-io.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-io.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-once.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-once.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-once.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-once.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-semaphore-norace.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-semaphore-norace.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-semaphore-norace.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-semaphore-norace.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-serial-queue-norace.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-serial-queue-norace.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-serial-queue-norace.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-serial-queue-norace.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-source-cancel.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-source-cancel.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-source-cancel.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-source-cancel.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-source-cancel2.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-source-cancel2.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-source-cancel2.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-source-cancel2.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-source-event.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-source-event.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-source-event.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-source-event.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-source-event2.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-source-event2.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-source-event2.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-source-event2.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-source-registration.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-source-registration.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-source-registration.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-source-registration.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-source-registration2.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-source-registration2.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-source-registration2.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-source-registration2.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-source-serial.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-source-serial.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-source-serial.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-source-serial.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-suspend.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-suspend.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-suspend.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-suspend.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-sync-norace.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-sync-norace.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-sync-norace.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-sync-norace.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-sync-race.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-sync-race.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-sync-race.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-sync-race.mm diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-target-queue-norace.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-target-queue-norace.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/gcd-target-queue-norace.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/gcd-target-queue-norace.mm diff --git a/src/compiler-rt/test/tsan/Darwin/ignore-noninstrumented.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/ignore-noninstrumented.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/ignore-noninstrumented.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/ignore-noninstrumented.mm diff --git a/src/compiler-rt/test/tsan/Darwin/ignored-interceptors.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/ignored-interceptors.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/ignored-interceptors.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/ignored-interceptors.mm diff --git a/src/compiler-rt/test/tsan/Darwin/libcxx-call-once.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/libcxx-call-once.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/libcxx-call-once.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/libcxx-call-once.mm diff --git a/src/compiler-rt/test/tsan/Darwin/libcxx-future.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/libcxx-future.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/libcxx-future.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/libcxx-future.mm diff --git a/src/compiler-rt/test/tsan/Darwin/libcxx-shared-ptr-recursive.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/libcxx-shared-ptr-recursive.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/libcxx-shared-ptr-recursive.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/libcxx-shared-ptr-recursive.mm diff --git a/src/compiler-rt/test/tsan/Darwin/libcxx-shared-ptr-stress.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/libcxx-shared-ptr-stress.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/libcxx-shared-ptr-stress.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/libcxx-shared-ptr-stress.mm diff --git a/src/compiler-rt/test/tsan/Darwin/libcxx-shared-ptr.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/libcxx-shared-ptr.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/libcxx-shared-ptr.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/libcxx-shared-ptr.mm diff --git a/src/compiler-rt/test/tsan/Darwin/lit.local.cfg b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/lit.local.cfg similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/lit.local.cfg rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/lit.local.cfg diff --git a/src/compiler-rt/test/tsan/Darwin/malloc-stack-logging.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/malloc-stack-logging.cc similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/malloc-stack-logging.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/malloc-stack-logging.cc diff --git a/src/compiler-rt/test/tsan/Darwin/malloc_size.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/malloc_size.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/malloc_size.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/malloc_size.mm diff --git a/src/compiler-rt/test/tsan/Darwin/norace-objcxx-run-time.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/norace-objcxx-run-time.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/norace-objcxx-run-time.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/norace-objcxx-run-time.mm diff --git a/src/compiler-rt/test/tsan/Darwin/objc-double-property.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/objc-double-property.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/objc-double-property.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/objc-double-property.mm diff --git a/src/compiler-rt/test/tsan/Darwin/objc-race.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/objc-race.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/objc-race.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/objc-race.mm diff --git a/src/compiler-rt/test/tsan/Darwin/objc-simple.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/objc-simple.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/objc-simple.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/objc-simple.mm diff --git a/src/compiler-rt/test/tsan/Darwin/osatomics-add.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/osatomics-add.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/osatomics-add.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/osatomics-add.mm diff --git a/src/compiler-rt/test/tsan/Darwin/osatomics-bitops.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/osatomics-bitops.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/osatomics-bitops.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/osatomics-bitops.mm diff --git a/src/compiler-rt/test/tsan/Darwin/osatomics-list.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/osatomics-list.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/osatomics-list.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/osatomics-list.mm diff --git a/src/compiler-rt/test/tsan/Darwin/osspinlock-norace.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/osspinlock-norace.cc similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/osspinlock-norace.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/osspinlock-norace.cc diff --git a/src/compiler-rt/test/tsan/Darwin/realloc-zero.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/realloc-zero.cc similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/realloc-zero.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/realloc-zero.cc diff --git a/src/compiler-rt/test/tsan/Darwin/symbolizer-atos.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/symbolizer-atos.cc similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/symbolizer-atos.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/symbolizer-atos.cc diff --git a/src/compiler-rt/test/tsan/Darwin/symbolizer-dladdr.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/symbolizer-dladdr.cc similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/symbolizer-dladdr.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/symbolizer-dladdr.cc diff --git a/src/compiler-rt/test/tsan/Darwin/xpc-race.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/xpc-race.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/xpc-race.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/xpc-race.mm diff --git a/src/compiler-rt/test/tsan/Darwin/xpc.mm b/src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/xpc.mm similarity index 100% rename from src/compiler-rt/test/tsan/Darwin/xpc.mm rename to src/libcompiler_builtins/compiler-rt/test/tsan/Darwin/xpc.mm diff --git a/src/compiler-rt/test/tsan/Linux/check_memcpy.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/Linux/check_memcpy.cc similarity index 100% rename from src/compiler-rt/test/tsan/Linux/check_memcpy.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/Linux/check_memcpy.cc diff --git a/src/compiler-rt/test/tsan/Linux/check_preinit.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/Linux/check_preinit.cc similarity index 100% rename from src/compiler-rt/test/tsan/Linux/check_preinit.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/Linux/check_preinit.cc diff --git a/src/compiler-rt/test/tsan/Linux/lit.local.cfg b/src/libcompiler_builtins/compiler-rt/test/tsan/Linux/lit.local.cfg similarity index 100% rename from src/compiler-rt/test/tsan/Linux/lit.local.cfg rename to src/libcompiler_builtins/compiler-rt/test/tsan/Linux/lit.local.cfg diff --git a/src/compiler-rt/test/tsan/Linux/mutex_robust.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/Linux/mutex_robust.cc similarity index 100% rename from src/compiler-rt/test/tsan/Linux/mutex_robust.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/Linux/mutex_robust.cc diff --git a/src/compiler-rt/test/tsan/Linux/mutex_robust2.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/Linux/mutex_robust2.cc similarity index 100% rename from src/compiler-rt/test/tsan/Linux/mutex_robust2.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/Linux/mutex_robust2.cc diff --git a/src/compiler-rt/test/tsan/Linux/user_fopen.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/Linux/user_fopen.cc similarity index 100% rename from src/compiler-rt/test/tsan/Linux/user_fopen.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/Linux/user_fopen.cc diff --git a/src/compiler-rt/test/tsan/Linux/user_malloc.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/Linux/user_malloc.cc similarity index 100% rename from src/compiler-rt/test/tsan/Linux/user_malloc.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/Linux/user_malloc.cc diff --git a/src/compiler-rt/test/tsan/Unit/lit.site.cfg.in b/src/libcompiler_builtins/compiler-rt/test/tsan/Unit/lit.site.cfg.in similarity index 100% rename from src/compiler-rt/test/tsan/Unit/lit.site.cfg.in rename to src/libcompiler_builtins/compiler-rt/test/tsan/Unit/lit.site.cfg.in diff --git a/src/compiler-rt/test/tsan/aligned_vs_unaligned_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/aligned_vs_unaligned_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/aligned_vs_unaligned_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/aligned_vs_unaligned_race.cc diff --git a/src/compiler-rt/test/tsan/allocator_returns_null.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/allocator_returns_null.cc similarity index 100% rename from src/compiler-rt/test/tsan/allocator_returns_null.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/allocator_returns_null.cc diff --git a/src/compiler-rt/test/tsan/annotate_happens_before.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/annotate_happens_before.cc similarity index 100% rename from src/compiler-rt/test/tsan/annotate_happens_before.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/annotate_happens_before.cc diff --git a/src/compiler-rt/test/tsan/atexit.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/atexit.cc similarity index 100% rename from src/compiler-rt/test/tsan/atexit.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/atexit.cc diff --git a/src/compiler-rt/test/tsan/atexit2.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/atexit2.cc similarity index 100% rename from src/compiler-rt/test/tsan/atexit2.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/atexit2.cc diff --git a/src/compiler-rt/test/tsan/atomic_free.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/atomic_free.cc similarity index 100% rename from src/compiler-rt/test/tsan/atomic_free.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/atomic_free.cc diff --git a/src/compiler-rt/test/tsan/atomic_free2.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/atomic_free2.cc similarity index 100% rename from src/compiler-rt/test/tsan/atomic_free2.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/atomic_free2.cc diff --git a/src/compiler-rt/test/tsan/atomic_free3.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/atomic_free3.cc similarity index 100% rename from src/compiler-rt/test/tsan/atomic_free3.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/atomic_free3.cc diff --git a/src/compiler-rt/test/tsan/atomic_norace.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/atomic_norace.cc similarity index 100% rename from src/compiler-rt/test/tsan/atomic_norace.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/atomic_norace.cc diff --git a/src/compiler-rt/test/tsan/atomic_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/atomic_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/atomic_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/atomic_race.cc diff --git a/src/compiler-rt/test/tsan/atomic_stack.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/atomic_stack.cc similarity index 100% rename from src/compiler-rt/test/tsan/atomic_stack.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/atomic_stack.cc diff --git a/src/compiler-rt/test/tsan/atomic_store.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/atomic_store.cc similarity index 100% rename from src/compiler-rt/test/tsan/atomic_store.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/atomic_store.cc diff --git a/src/compiler-rt/test/tsan/barrier.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/barrier.cc similarity index 100% rename from src/compiler-rt/test/tsan/barrier.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/barrier.cc diff --git a/src/compiler-rt/test/tsan/bench.h b/src/libcompiler_builtins/compiler-rt/test/tsan/bench.h similarity index 100% rename from src/compiler-rt/test/tsan/bench.h rename to src/libcompiler_builtins/compiler-rt/test/tsan/bench.h diff --git a/src/compiler-rt/test/tsan/bench_acquire_only.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/bench_acquire_only.cc similarity index 100% rename from src/compiler-rt/test/tsan/bench_acquire_only.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/bench_acquire_only.cc diff --git a/src/compiler-rt/test/tsan/bench_acquire_release.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/bench_acquire_release.cc similarity index 100% rename from src/compiler-rt/test/tsan/bench_acquire_release.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/bench_acquire_release.cc diff --git a/src/compiler-rt/test/tsan/bench_local_mutex.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/bench_local_mutex.cc similarity index 100% rename from src/compiler-rt/test/tsan/bench_local_mutex.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/bench_local_mutex.cc diff --git a/src/compiler-rt/test/tsan/bench_mutex.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/bench_mutex.cc similarity index 100% rename from src/compiler-rt/test/tsan/bench_mutex.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/bench_mutex.cc diff --git a/src/compiler-rt/test/tsan/bench_release_only.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/bench_release_only.cc similarity index 100% rename from src/compiler-rt/test/tsan/bench_release_only.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/bench_release_only.cc diff --git a/src/compiler-rt/test/tsan/bench_rwmutex.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/bench_rwmutex.cc similarity index 100% rename from src/compiler-rt/test/tsan/bench_rwmutex.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/bench_rwmutex.cc diff --git a/src/compiler-rt/test/tsan/bench_shadow_flush.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/bench_shadow_flush.cc similarity index 100% rename from src/compiler-rt/test/tsan/bench_shadow_flush.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/bench_shadow_flush.cc diff --git a/src/compiler-rt/test/tsan/bench_single_writer.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/bench_single_writer.cc similarity index 100% rename from src/compiler-rt/test/tsan/bench_single_writer.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/bench_single_writer.cc diff --git a/src/compiler-rt/test/tsan/bench_ten_mutexes.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/bench_ten_mutexes.cc similarity index 100% rename from src/compiler-rt/test/tsan/bench_ten_mutexes.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/bench_ten_mutexes.cc diff --git a/src/compiler-rt/test/tsan/benign_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/benign_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/benign_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/benign_race.cc diff --git a/src/compiler-rt/test/tsan/blacklist.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/blacklist.cc similarity index 100% rename from src/compiler-rt/test/tsan/blacklist.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/blacklist.cc diff --git a/src/compiler-rt/test/tsan/blacklist2.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/blacklist2.cc similarity index 100% rename from src/compiler-rt/test/tsan/blacklist2.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/blacklist2.cc diff --git a/src/compiler-rt/test/tsan/cond.c b/src/libcompiler_builtins/compiler-rt/test/tsan/cond.c similarity index 100% rename from src/compiler-rt/test/tsan/cond.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/cond.c diff --git a/src/compiler-rt/test/tsan/cond_cancel.c b/src/libcompiler_builtins/compiler-rt/test/tsan/cond_cancel.c similarity index 100% rename from src/compiler-rt/test/tsan/cond_cancel.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/cond_cancel.c diff --git a/src/compiler-rt/test/tsan/cond_destruction.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/cond_destruction.cc similarity index 100% rename from src/compiler-rt/test/tsan/cond_destruction.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/cond_destruction.cc diff --git a/src/compiler-rt/test/tsan/cond_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/cond_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/cond_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/cond_race.cc diff --git a/src/compiler-rt/test/tsan/cond_version.c b/src/libcompiler_builtins/compiler-rt/test/tsan/cond_version.c similarity index 100% rename from src/compiler-rt/test/tsan/cond_version.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/cond_version.c diff --git a/src/compiler-rt/test/tsan/deadlock_detector_stress_test.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/deadlock_detector_stress_test.cc similarity index 100% rename from src/compiler-rt/test/tsan/deadlock_detector_stress_test.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/deadlock_detector_stress_test.cc diff --git a/src/compiler-rt/test/tsan/debug_alloc_stack.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/debug_alloc_stack.cc similarity index 100% rename from src/compiler-rt/test/tsan/debug_alloc_stack.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/debug_alloc_stack.cc diff --git a/src/compiler-rt/test/tsan/debug_locate.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/debug_locate.cc similarity index 100% rename from src/compiler-rt/test/tsan/debug_locate.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/debug_locate.cc diff --git a/src/compiler-rt/test/tsan/debugging.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/debugging.cc similarity index 100% rename from src/compiler-rt/test/tsan/debugging.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/debugging.cc diff --git a/src/compiler-rt/test/tsan/deep_stack1.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/deep_stack1.cc similarity index 100% rename from src/compiler-rt/test/tsan/deep_stack1.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/deep_stack1.cc diff --git a/src/compiler-rt/test/tsan/default_options.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/default_options.cc similarity index 100% rename from src/compiler-rt/test/tsan/default_options.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/default_options.cc diff --git a/src/compiler-rt/test/tsan/deflake.bash b/src/libcompiler_builtins/compiler-rt/test/tsan/deflake.bash similarity index 100% rename from src/compiler-rt/test/tsan/deflake.bash rename to src/libcompiler_builtins/compiler-rt/test/tsan/deflake.bash diff --git a/src/compiler-rt/test/tsan/dl_iterate_phdr.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/dl_iterate_phdr.cc similarity index 100% rename from src/compiler-rt/test/tsan/dl_iterate_phdr.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/dl_iterate_phdr.cc diff --git a/src/compiler-rt/test/tsan/dlclose.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/dlclose.cc similarity index 100% rename from src/compiler-rt/test/tsan/dlclose.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/dlclose.cc diff --git a/src/compiler-rt/test/tsan/dtls.c b/src/libcompiler_builtins/compiler-rt/test/tsan/dtls.c similarity index 100% rename from src/compiler-rt/test/tsan/dtls.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/dtls.c diff --git a/src/compiler-rt/test/tsan/exceptions.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/exceptions.cc similarity index 100% rename from src/compiler-rt/test/tsan/exceptions.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/exceptions.cc diff --git a/src/compiler-rt/test/tsan/fd_close_norace.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/fd_close_norace.cc similarity index 100% rename from src/compiler-rt/test/tsan/fd_close_norace.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/fd_close_norace.cc diff --git a/src/compiler-rt/test/tsan/fd_close_norace2.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/fd_close_norace2.cc similarity index 100% rename from src/compiler-rt/test/tsan/fd_close_norace2.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/fd_close_norace2.cc diff --git a/src/compiler-rt/test/tsan/fd_dup_norace.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/fd_dup_norace.cc similarity index 100% rename from src/compiler-rt/test/tsan/fd_dup_norace.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/fd_dup_norace.cc diff --git a/src/compiler-rt/test/tsan/fd_dup_norace2.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/fd_dup_norace2.cc similarity index 100% rename from src/compiler-rt/test/tsan/fd_dup_norace2.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/fd_dup_norace2.cc diff --git a/src/compiler-rt/test/tsan/fd_dup_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/fd_dup_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/fd_dup_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/fd_dup_race.cc diff --git a/src/compiler-rt/test/tsan/fd_location.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/fd_location.cc similarity index 100% rename from src/compiler-rt/test/tsan/fd_location.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/fd_location.cc diff --git a/src/compiler-rt/test/tsan/fd_pipe_norace.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/fd_pipe_norace.cc similarity index 100% rename from src/compiler-rt/test/tsan/fd_pipe_norace.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/fd_pipe_norace.cc diff --git a/src/compiler-rt/test/tsan/fd_pipe_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/fd_pipe_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/fd_pipe_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/fd_pipe_race.cc diff --git a/src/compiler-rt/test/tsan/fd_socket_connect_norace.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/fd_socket_connect_norace.cc similarity index 100% rename from src/compiler-rt/test/tsan/fd_socket_connect_norace.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/fd_socket_connect_norace.cc diff --git a/src/compiler-rt/test/tsan/fd_socket_norace.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/fd_socket_norace.cc similarity index 100% rename from src/compiler-rt/test/tsan/fd_socket_norace.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/fd_socket_norace.cc diff --git a/src/compiler-rt/test/tsan/fd_socketpair_norace.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/fd_socketpair_norace.cc similarity index 100% rename from src/compiler-rt/test/tsan/fd_socketpair_norace.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/fd_socketpair_norace.cc diff --git a/src/compiler-rt/test/tsan/fd_stdout_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/fd_stdout_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/fd_stdout_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/fd_stdout_race.cc diff --git a/src/compiler-rt/test/tsan/fd_tid_recycled.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/fd_tid_recycled.cc similarity index 100% rename from src/compiler-rt/test/tsan/fd_tid_recycled.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/fd_tid_recycled.cc diff --git a/src/compiler-rt/test/tsan/fork_atexit.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/fork_atexit.cc similarity index 100% rename from src/compiler-rt/test/tsan/fork_atexit.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/fork_atexit.cc diff --git a/src/compiler-rt/test/tsan/fork_deadlock.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/fork_deadlock.cc similarity index 100% rename from src/compiler-rt/test/tsan/fork_deadlock.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/fork_deadlock.cc diff --git a/src/compiler-rt/test/tsan/fork_multithreaded.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/fork_multithreaded.cc similarity index 100% rename from src/compiler-rt/test/tsan/fork_multithreaded.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/fork_multithreaded.cc diff --git a/src/compiler-rt/test/tsan/fork_multithreaded3.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/fork_multithreaded3.cc similarity index 100% rename from src/compiler-rt/test/tsan/fork_multithreaded3.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/fork_multithreaded3.cc diff --git a/src/compiler-rt/test/tsan/free_race.c b/src/libcompiler_builtins/compiler-rt/test/tsan/free_race.c similarity index 100% rename from src/compiler-rt/test/tsan/free_race.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/free_race.c diff --git a/src/compiler-rt/test/tsan/free_race.c.supp b/src/libcompiler_builtins/compiler-rt/test/tsan/free_race.c.supp similarity index 100% rename from src/compiler-rt/test/tsan/free_race.c.supp rename to src/libcompiler_builtins/compiler-rt/test/tsan/free_race.c.supp diff --git a/src/compiler-rt/test/tsan/free_race2.c b/src/libcompiler_builtins/compiler-rt/test/tsan/free_race2.c similarity index 100% rename from src/compiler-rt/test/tsan/free_race2.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/free_race2.c diff --git a/src/compiler-rt/test/tsan/getline_nohang.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/getline_nohang.cc similarity index 100% rename from src/compiler-rt/test/tsan/getline_nohang.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/getline_nohang.cc diff --git a/src/compiler-rt/test/tsan/global_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/global_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/global_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/global_race.cc diff --git a/src/compiler-rt/test/tsan/global_race2.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/global_race2.cc similarity index 100% rename from src/compiler-rt/test/tsan/global_race2.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/global_race2.cc diff --git a/src/compiler-rt/test/tsan/global_race3.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/global_race3.cc similarity index 100% rename from src/compiler-rt/test/tsan/global_race3.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/global_race3.cc diff --git a/src/compiler-rt/test/tsan/halt_on_error.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/halt_on_error.cc similarity index 100% rename from src/compiler-rt/test/tsan/halt_on_error.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/halt_on_error.cc diff --git a/src/compiler-rt/test/tsan/heap_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/heap_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/heap_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/heap_race.cc diff --git a/src/compiler-rt/test/tsan/ignore_free.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/ignore_free.cc similarity index 100% rename from src/compiler-rt/test/tsan/ignore_free.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/ignore_free.cc diff --git a/src/compiler-rt/test/tsan/ignore_lib0.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib0.cc similarity index 100% rename from src/compiler-rt/test/tsan/ignore_lib0.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib0.cc diff --git a/src/compiler-rt/test/tsan/ignore_lib0.cc.supp b/src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib0.cc.supp similarity index 100% rename from src/compiler-rt/test/tsan/ignore_lib0.cc.supp rename to src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib0.cc.supp diff --git a/src/compiler-rt/test/tsan/ignore_lib1.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib1.cc similarity index 100% rename from src/compiler-rt/test/tsan/ignore_lib1.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib1.cc diff --git a/src/compiler-rt/test/tsan/ignore_lib1.cc.supp b/src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib1.cc.supp similarity index 100% rename from src/compiler-rt/test/tsan/ignore_lib1.cc.supp rename to src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib1.cc.supp diff --git a/src/compiler-rt/test/tsan/ignore_lib2.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib2.cc similarity index 100% rename from src/compiler-rt/test/tsan/ignore_lib2.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib2.cc diff --git a/src/compiler-rt/test/tsan/ignore_lib2.cc.supp b/src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib2.cc.supp similarity index 100% rename from src/compiler-rt/test/tsan/ignore_lib2.cc.supp rename to src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib2.cc.supp diff --git a/src/compiler-rt/test/tsan/ignore_lib3.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib3.cc similarity index 100% rename from src/compiler-rt/test/tsan/ignore_lib3.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib3.cc diff --git a/src/compiler-rt/test/tsan/ignore_lib3.cc.supp b/src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib3.cc.supp similarity index 100% rename from src/compiler-rt/test/tsan/ignore_lib3.cc.supp rename to src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib3.cc.supp diff --git a/src/compiler-rt/test/tsan/ignore_lib4.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib4.cc similarity index 100% rename from src/compiler-rt/test/tsan/ignore_lib4.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib4.cc diff --git a/src/compiler-rt/test/tsan/ignore_lib5.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib5.cc similarity index 100% rename from src/compiler-rt/test/tsan/ignore_lib5.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib5.cc diff --git a/src/compiler-rt/test/tsan/ignore_lib5.cc.supp b/src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib5.cc.supp similarity index 100% rename from src/compiler-rt/test/tsan/ignore_lib5.cc.supp rename to src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib5.cc.supp diff --git a/src/compiler-rt/test/tsan/ignore_lib_lib.h b/src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib_lib.h similarity index 100% rename from src/compiler-rt/test/tsan/ignore_lib_lib.h rename to src/libcompiler_builtins/compiler-rt/test/tsan/ignore_lib_lib.h diff --git a/src/compiler-rt/test/tsan/ignore_malloc.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/ignore_malloc.cc similarity index 100% rename from src/compiler-rt/test/tsan/ignore_malloc.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/ignore_malloc.cc diff --git a/src/compiler-rt/test/tsan/ignore_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/ignore_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/ignore_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/ignore_race.cc diff --git a/src/compiler-rt/test/tsan/ignore_sync.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/ignore_sync.cc similarity index 100% rename from src/compiler-rt/test/tsan/ignore_sync.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/ignore_sync.cc diff --git a/src/compiler-rt/test/tsan/ignored-interceptors-mmap.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/ignored-interceptors-mmap.cc similarity index 100% rename from src/compiler-rt/test/tsan/ignored-interceptors-mmap.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/ignored-interceptors-mmap.cc diff --git a/src/compiler-rt/test/tsan/inlined_memcpy_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/inlined_memcpy_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/inlined_memcpy_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/inlined_memcpy_race.cc diff --git a/src/compiler-rt/test/tsan/inlined_memcpy_race2.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/inlined_memcpy_race2.cc similarity index 100% rename from src/compiler-rt/test/tsan/inlined_memcpy_race2.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/inlined_memcpy_race2.cc diff --git a/src/compiler-rt/test/tsan/interface_atomic_test.c b/src/libcompiler_builtins/compiler-rt/test/tsan/interface_atomic_test.c similarity index 100% rename from src/compiler-rt/test/tsan/interface_atomic_test.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/interface_atomic_test.c diff --git a/src/compiler-rt/test/tsan/java.h b/src/libcompiler_builtins/compiler-rt/test/tsan/java.h similarity index 100% rename from src/compiler-rt/test/tsan/java.h rename to src/libcompiler_builtins/compiler-rt/test/tsan/java.h diff --git a/src/compiler-rt/test/tsan/java_alloc.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/java_alloc.cc similarity index 100% rename from src/compiler-rt/test/tsan/java_alloc.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/java_alloc.cc diff --git a/src/compiler-rt/test/tsan/java_finalizer.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/java_finalizer.cc similarity index 100% rename from src/compiler-rt/test/tsan/java_finalizer.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/java_finalizer.cc diff --git a/src/compiler-rt/test/tsan/java_heap_init.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/java_heap_init.cc similarity index 100% rename from src/compiler-rt/test/tsan/java_heap_init.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/java_heap_init.cc diff --git a/src/compiler-rt/test/tsan/java_lock.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/java_lock.cc similarity index 100% rename from src/compiler-rt/test/tsan/java_lock.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/java_lock.cc diff --git a/src/compiler-rt/test/tsan/java_lock_move.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/java_lock_move.cc similarity index 100% rename from src/compiler-rt/test/tsan/java_lock_move.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/java_lock_move.cc diff --git a/src/compiler-rt/test/tsan/java_lock_rec.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/java_lock_rec.cc similarity index 100% rename from src/compiler-rt/test/tsan/java_lock_rec.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/java_lock_rec.cc diff --git a/src/compiler-rt/test/tsan/java_lock_rec_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/java_lock_rec_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/java_lock_rec_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/java_lock_rec_race.cc diff --git a/src/compiler-rt/test/tsan/java_move_overlap.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/java_move_overlap.cc similarity index 100% rename from src/compiler-rt/test/tsan/java_move_overlap.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/java_move_overlap.cc diff --git a/src/compiler-rt/test/tsan/java_move_overlap_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/java_move_overlap_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/java_move_overlap_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/java_move_overlap_race.cc diff --git a/src/compiler-rt/test/tsan/java_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/java_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/java_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/java_race.cc diff --git a/src/compiler-rt/test/tsan/java_race_move.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/java_race_move.cc similarity index 100% rename from src/compiler-rt/test/tsan/java_race_move.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/java_race_move.cc diff --git a/src/compiler-rt/test/tsan/java_race_pc.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/java_race_pc.cc similarity index 100% rename from src/compiler-rt/test/tsan/java_race_pc.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/java_race_pc.cc diff --git a/src/compiler-rt/test/tsan/java_rwlock.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/java_rwlock.cc similarity index 100% rename from src/compiler-rt/test/tsan/java_rwlock.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/java_rwlock.cc diff --git a/src/compiler-rt/test/tsan/java_symbolization.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/java_symbolization.cc similarity index 100% rename from src/compiler-rt/test/tsan/java_symbolization.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/java_symbolization.cc diff --git a/src/compiler-rt/test/tsan/java_volatile.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/java_volatile.cc similarity index 100% rename from src/compiler-rt/test/tsan/java_volatile.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/java_volatile.cc diff --git a/src/compiler-rt/test/tsan/large_malloc_meta.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/large_malloc_meta.cc similarity index 100% rename from src/compiler-rt/test/tsan/large_malloc_meta.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/large_malloc_meta.cc diff --git a/src/compiler-rt/test/tsan/libcxx/lit.local.cfg b/src/libcompiler_builtins/compiler-rt/test/tsan/libcxx/lit.local.cfg similarity index 100% rename from src/compiler-rt/test/tsan/libcxx/lit.local.cfg rename to src/libcompiler_builtins/compiler-rt/test/tsan/libcxx/lit.local.cfg diff --git a/src/compiler-rt/test/tsan/libcxx/std_shared_ptr.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/libcxx/std_shared_ptr.cc similarity index 100% rename from src/compiler-rt/test/tsan/libcxx/std_shared_ptr.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/libcxx/std_shared_ptr.cc diff --git a/src/compiler-rt/test/tsan/lit.cfg b/src/libcompiler_builtins/compiler-rt/test/tsan/lit.cfg similarity index 100% rename from src/compiler-rt/test/tsan/lit.cfg rename to src/libcompiler_builtins/compiler-rt/test/tsan/lit.cfg diff --git a/src/compiler-rt/test/tsan/lit.site.cfg.in b/src/libcompiler_builtins/compiler-rt/test/tsan/lit.site.cfg.in similarity index 100% rename from src/compiler-rt/test/tsan/lit.site.cfg.in rename to src/libcompiler_builtins/compiler-rt/test/tsan/lit.site.cfg.in diff --git a/src/compiler-rt/test/tsan/load_shared_lib.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/load_shared_lib.cc similarity index 100% rename from src/compiler-rt/test/tsan/load_shared_lib.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/load_shared_lib.cc diff --git a/src/compiler-rt/test/tsan/longjmp.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/longjmp.cc similarity index 100% rename from src/compiler-rt/test/tsan/longjmp.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/longjmp.cc diff --git a/src/compiler-rt/test/tsan/longjmp2.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/longjmp2.cc similarity index 100% rename from src/compiler-rt/test/tsan/longjmp2.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/longjmp2.cc diff --git a/src/compiler-rt/test/tsan/longjmp3.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/longjmp3.cc similarity index 100% rename from src/compiler-rt/test/tsan/longjmp3.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/longjmp3.cc diff --git a/src/compiler-rt/test/tsan/longjmp4.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/longjmp4.cc similarity index 100% rename from src/compiler-rt/test/tsan/longjmp4.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/longjmp4.cc diff --git a/src/compiler-rt/test/tsan/lots_of_threads.c b/src/libcompiler_builtins/compiler-rt/test/tsan/lots_of_threads.c similarity index 100% rename from src/compiler-rt/test/tsan/lots_of_threads.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/lots_of_threads.c diff --git a/src/compiler-rt/test/tsan/malloc_overflow.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/malloc_overflow.cc similarity index 100% rename from src/compiler-rt/test/tsan/malloc_overflow.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/malloc_overflow.cc diff --git a/src/compiler-rt/test/tsan/malloc_stack.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/malloc_stack.cc similarity index 100% rename from src/compiler-rt/test/tsan/malloc_stack.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/malloc_stack.cc diff --git a/src/compiler-rt/test/tsan/map32bit.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/map32bit.cc similarity index 100% rename from src/compiler-rt/test/tsan/map32bit.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/map32bit.cc diff --git a/src/compiler-rt/test/tsan/memcmp_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/memcmp_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/memcmp_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/memcmp_race.cc diff --git a/src/compiler-rt/test/tsan/memcpy_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/memcpy_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/memcpy_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/memcpy_race.cc diff --git a/src/compiler-rt/test/tsan/mmap_large.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/mmap_large.cc similarity index 100% rename from src/compiler-rt/test/tsan/mmap_large.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/mmap_large.cc diff --git a/src/compiler-rt/test/tsan/mmap_stress.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/mmap_stress.cc similarity index 100% rename from src/compiler-rt/test/tsan/mmap_stress.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/mmap_stress.cc diff --git a/src/compiler-rt/test/tsan/mop1.c b/src/libcompiler_builtins/compiler-rt/test/tsan/mop1.c similarity index 100% rename from src/compiler-rt/test/tsan/mop1.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/mop1.c diff --git a/src/compiler-rt/test/tsan/mop_with_offset.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/mop_with_offset.cc similarity index 100% rename from src/compiler-rt/test/tsan/mop_with_offset.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/mop_with_offset.cc diff --git a/src/compiler-rt/test/tsan/mop_with_offset2.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/mop_with_offset2.cc similarity index 100% rename from src/compiler-rt/test/tsan/mop_with_offset2.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/mop_with_offset2.cc diff --git a/src/compiler-rt/test/tsan/must_deadlock.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/must_deadlock.cc similarity index 100% rename from src/compiler-rt/test/tsan/must_deadlock.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/must_deadlock.cc diff --git a/src/compiler-rt/test/tsan/mutex_annotations.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/mutex_annotations.cc similarity index 100% rename from src/compiler-rt/test/tsan/mutex_annotations.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/mutex_annotations.cc diff --git a/src/compiler-rt/test/tsan/mutex_bad_read_lock.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/mutex_bad_read_lock.cc similarity index 100% rename from src/compiler-rt/test/tsan/mutex_bad_read_lock.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/mutex_bad_read_lock.cc diff --git a/src/compiler-rt/test/tsan/mutex_bad_read_unlock.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/mutex_bad_read_unlock.cc similarity index 100% rename from src/compiler-rt/test/tsan/mutex_bad_read_unlock.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/mutex_bad_read_unlock.cc diff --git a/src/compiler-rt/test/tsan/mutex_bad_unlock.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/mutex_bad_unlock.cc similarity index 100% rename from src/compiler-rt/test/tsan/mutex_bad_unlock.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/mutex_bad_unlock.cc diff --git a/src/compiler-rt/test/tsan/mutex_cycle2.c b/src/libcompiler_builtins/compiler-rt/test/tsan/mutex_cycle2.c similarity index 100% rename from src/compiler-rt/test/tsan/mutex_cycle2.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/mutex_cycle2.c diff --git a/src/compiler-rt/test/tsan/mutex_cycle_long.c b/src/libcompiler_builtins/compiler-rt/test/tsan/mutex_cycle_long.c similarity index 100% rename from src/compiler-rt/test/tsan/mutex_cycle_long.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/mutex_cycle_long.c diff --git a/src/compiler-rt/test/tsan/mutex_destroy_locked.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/mutex_destroy_locked.cc similarity index 100% rename from src/compiler-rt/test/tsan/mutex_destroy_locked.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/mutex_destroy_locked.cc diff --git a/src/compiler-rt/test/tsan/mutex_double_lock.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/mutex_double_lock.cc similarity index 100% rename from src/compiler-rt/test/tsan/mutex_double_lock.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/mutex_double_lock.cc diff --git a/src/compiler-rt/test/tsan/mutex_lock_destroyed.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/mutex_lock_destroyed.cc similarity index 100% rename from src/compiler-rt/test/tsan/mutex_lock_destroyed.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/mutex_lock_destroyed.cc diff --git a/src/compiler-rt/test/tsan/mutexset1.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/mutexset1.cc similarity index 100% rename from src/compiler-rt/test/tsan/mutexset1.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/mutexset1.cc diff --git a/src/compiler-rt/test/tsan/mutexset2.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/mutexset2.cc similarity index 100% rename from src/compiler-rt/test/tsan/mutexset2.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/mutexset2.cc diff --git a/src/compiler-rt/test/tsan/mutexset3.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/mutexset3.cc similarity index 100% rename from src/compiler-rt/test/tsan/mutexset3.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/mutexset3.cc diff --git a/src/compiler-rt/test/tsan/mutexset4.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/mutexset4.cc similarity index 100% rename from src/compiler-rt/test/tsan/mutexset4.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/mutexset4.cc diff --git a/src/compiler-rt/test/tsan/mutexset5.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/mutexset5.cc similarity index 100% rename from src/compiler-rt/test/tsan/mutexset5.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/mutexset5.cc diff --git a/src/compiler-rt/test/tsan/mutexset6.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/mutexset6.cc similarity index 100% rename from src/compiler-rt/test/tsan/mutexset6.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/mutexset6.cc diff --git a/src/compiler-rt/test/tsan/mutexset7.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/mutexset7.cc similarity index 100% rename from src/compiler-rt/test/tsan/mutexset7.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/mutexset7.cc diff --git a/src/compiler-rt/test/tsan/mutexset8.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/mutexset8.cc similarity index 100% rename from src/compiler-rt/test/tsan/mutexset8.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/mutexset8.cc diff --git a/src/compiler-rt/test/tsan/pie_test.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/pie_test.cc similarity index 100% rename from src/compiler-rt/test/tsan/pie_test.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/pie_test.cc diff --git a/src/compiler-rt/test/tsan/printf-1.c b/src/libcompiler_builtins/compiler-rt/test/tsan/printf-1.c similarity index 100% rename from src/compiler-rt/test/tsan/printf-1.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/printf-1.c diff --git a/src/compiler-rt/test/tsan/pthread_atfork_deadlock.c b/src/libcompiler_builtins/compiler-rt/test/tsan/pthread_atfork_deadlock.c similarity index 100% rename from src/compiler-rt/test/tsan/pthread_atfork_deadlock.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/pthread_atfork_deadlock.c diff --git a/src/compiler-rt/test/tsan/pthread_key.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/pthread_key.cc similarity index 100% rename from src/compiler-rt/test/tsan/pthread_key.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/pthread_key.cc diff --git a/src/compiler-rt/test/tsan/race_on_barrier.c b/src/libcompiler_builtins/compiler-rt/test/tsan/race_on_barrier.c similarity index 100% rename from src/compiler-rt/test/tsan/race_on_barrier.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/race_on_barrier.c diff --git a/src/compiler-rt/test/tsan/race_on_barrier2.c b/src/libcompiler_builtins/compiler-rt/test/tsan/race_on_barrier2.c similarity index 100% rename from src/compiler-rt/test/tsan/race_on_barrier2.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/race_on_barrier2.c diff --git a/src/compiler-rt/test/tsan/race_on_heap.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/race_on_heap.cc similarity index 100% rename from src/compiler-rt/test/tsan/race_on_heap.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/race_on_heap.cc diff --git a/src/compiler-rt/test/tsan/race_on_mutex.c b/src/libcompiler_builtins/compiler-rt/test/tsan/race_on_mutex.c similarity index 100% rename from src/compiler-rt/test/tsan/race_on_mutex.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/race_on_mutex.c diff --git a/src/compiler-rt/test/tsan/race_on_mutex2.c b/src/libcompiler_builtins/compiler-rt/test/tsan/race_on_mutex2.c similarity index 100% rename from src/compiler-rt/test/tsan/race_on_mutex2.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/race_on_mutex2.c diff --git a/src/compiler-rt/test/tsan/race_on_puts.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/race_on_puts.cc similarity index 100% rename from src/compiler-rt/test/tsan/race_on_puts.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/race_on_puts.cc diff --git a/src/compiler-rt/test/tsan/race_on_read.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/race_on_read.cc similarity index 100% rename from src/compiler-rt/test/tsan/race_on_read.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/race_on_read.cc diff --git a/src/compiler-rt/test/tsan/race_on_speculative_load.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/race_on_speculative_load.cc similarity index 100% rename from src/compiler-rt/test/tsan/race_on_speculative_load.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/race_on_speculative_load.cc diff --git a/src/compiler-rt/test/tsan/race_on_write.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/race_on_write.cc similarity index 100% rename from src/compiler-rt/test/tsan/race_on_write.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/race_on_write.cc diff --git a/src/compiler-rt/test/tsan/race_stress.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/race_stress.cc similarity index 100% rename from src/compiler-rt/test/tsan/race_stress.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/race_stress.cc diff --git a/src/compiler-rt/test/tsan/race_top_suppression.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/race_top_suppression.cc similarity index 100% rename from src/compiler-rt/test/tsan/race_top_suppression.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/race_top_suppression.cc diff --git a/src/compiler-rt/test/tsan/race_top_suppression1.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/race_top_suppression1.cc similarity index 100% rename from src/compiler-rt/test/tsan/race_top_suppression1.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/race_top_suppression1.cc diff --git a/src/compiler-rt/test/tsan/race_with_finished_thread.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/race_with_finished_thread.cc similarity index 100% rename from src/compiler-rt/test/tsan/race_with_finished_thread.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/race_with_finished_thread.cc diff --git a/src/compiler-rt/test/tsan/real_deadlock_detector_stress_test.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/real_deadlock_detector_stress_test.cc similarity index 100% rename from src/compiler-rt/test/tsan/real_deadlock_detector_stress_test.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/real_deadlock_detector_stress_test.cc diff --git a/src/compiler-rt/test/tsan/restore_stack.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/restore_stack.cc similarity index 100% rename from src/compiler-rt/test/tsan/restore_stack.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/restore_stack.cc diff --git a/src/compiler-rt/test/tsan/setuid.c b/src/libcompiler_builtins/compiler-rt/test/tsan/setuid.c similarity index 100% rename from src/compiler-rt/test/tsan/setuid.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/setuid.c diff --git a/src/compiler-rt/test/tsan/setuid2.c b/src/libcompiler_builtins/compiler-rt/test/tsan/setuid2.c similarity index 100% rename from src/compiler-rt/test/tsan/setuid2.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/setuid2.c diff --git a/src/compiler-rt/test/tsan/signal_block.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/signal_block.cc similarity index 100% rename from src/compiler-rt/test/tsan/signal_block.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/signal_block.cc diff --git a/src/compiler-rt/test/tsan/signal_cond.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/signal_cond.cc similarity index 100% rename from src/compiler-rt/test/tsan/signal_cond.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/signal_cond.cc diff --git a/src/compiler-rt/test/tsan/signal_errno.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/signal_errno.cc similarity index 100% rename from src/compiler-rt/test/tsan/signal_errno.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/signal_errno.cc diff --git a/src/compiler-rt/test/tsan/signal_longjmp.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/signal_longjmp.cc similarity index 100% rename from src/compiler-rt/test/tsan/signal_longjmp.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/signal_longjmp.cc diff --git a/src/compiler-rt/test/tsan/signal_malloc.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/signal_malloc.cc similarity index 100% rename from src/compiler-rt/test/tsan/signal_malloc.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/signal_malloc.cc diff --git a/src/compiler-rt/test/tsan/signal_recursive.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/signal_recursive.cc similarity index 100% rename from src/compiler-rt/test/tsan/signal_recursive.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/signal_recursive.cc diff --git a/src/compiler-rt/test/tsan/signal_reset.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/signal_reset.cc similarity index 100% rename from src/compiler-rt/test/tsan/signal_reset.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/signal_reset.cc diff --git a/src/compiler-rt/test/tsan/signal_sync.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/signal_sync.cc similarity index 100% rename from src/compiler-rt/test/tsan/signal_sync.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/signal_sync.cc diff --git a/src/compiler-rt/test/tsan/signal_sync2.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/signal_sync2.cc similarity index 100% rename from src/compiler-rt/test/tsan/signal_sync2.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/signal_sync2.cc diff --git a/src/compiler-rt/test/tsan/signal_thread.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/signal_thread.cc similarity index 100% rename from src/compiler-rt/test/tsan/signal_thread.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/signal_thread.cc diff --git a/src/compiler-rt/test/tsan/signal_write.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/signal_write.cc similarity index 100% rename from src/compiler-rt/test/tsan/signal_write.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/signal_write.cc diff --git a/src/compiler-rt/test/tsan/sigsuspend.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/sigsuspend.cc similarity index 100% rename from src/compiler-rt/test/tsan/sigsuspend.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/sigsuspend.cc diff --git a/src/compiler-rt/test/tsan/simple_race.c b/src/libcompiler_builtins/compiler-rt/test/tsan/simple_race.c similarity index 100% rename from src/compiler-rt/test/tsan/simple_race.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/simple_race.c diff --git a/src/compiler-rt/test/tsan/simple_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/simple_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/simple_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/simple_race.cc diff --git a/src/compiler-rt/test/tsan/simple_stack.c b/src/libcompiler_builtins/compiler-rt/test/tsan/simple_stack.c similarity index 100% rename from src/compiler-rt/test/tsan/simple_stack.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/simple_stack.c diff --git a/src/compiler-rt/test/tsan/simple_stack2.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/simple_stack2.cc similarity index 100% rename from src/compiler-rt/test/tsan/simple_stack2.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/simple_stack2.cc diff --git a/src/compiler-rt/test/tsan/sleep_sync.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/sleep_sync.cc similarity index 100% rename from src/compiler-rt/test/tsan/sleep_sync.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/sleep_sync.cc diff --git a/src/compiler-rt/test/tsan/sleep_sync2.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/sleep_sync2.cc similarity index 100% rename from src/compiler-rt/test/tsan/sleep_sync2.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/sleep_sync2.cc diff --git a/src/compiler-rt/test/tsan/stack_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/stack_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/stack_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/stack_race.cc diff --git a/src/compiler-rt/test/tsan/stack_race2.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/stack_race2.cc similarity index 100% rename from src/compiler-rt/test/tsan/stack_race2.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/stack_race2.cc diff --git a/src/compiler-rt/test/tsan/stack_sync_reuse.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/stack_sync_reuse.cc similarity index 100% rename from src/compiler-rt/test/tsan/stack_sync_reuse.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/stack_sync_reuse.cc diff --git a/src/compiler-rt/test/tsan/static_init1.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/static_init1.cc similarity index 100% rename from src/compiler-rt/test/tsan/static_init1.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/static_init1.cc diff --git a/src/compiler-rt/test/tsan/static_init2.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/static_init2.cc similarity index 100% rename from src/compiler-rt/test/tsan/static_init2.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/static_init2.cc diff --git a/src/compiler-rt/test/tsan/static_init3.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/static_init3.cc similarity index 100% rename from src/compiler-rt/test/tsan/static_init3.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/static_init3.cc diff --git a/src/compiler-rt/test/tsan/static_init4.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/static_init4.cc similarity index 100% rename from src/compiler-rt/test/tsan/static_init4.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/static_init4.cc diff --git a/src/compiler-rt/test/tsan/static_init5.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/static_init5.cc similarity index 100% rename from src/compiler-rt/test/tsan/static_init5.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/static_init5.cc diff --git a/src/compiler-rt/test/tsan/static_init6.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/static_init6.cc similarity index 100% rename from src/compiler-rt/test/tsan/static_init6.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/static_init6.cc diff --git a/src/compiler-rt/test/tsan/sunrpc.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/sunrpc.cc similarity index 100% rename from src/compiler-rt/test/tsan/sunrpc.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/sunrpc.cc diff --git a/src/compiler-rt/test/tsan/suppress_same_address.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/suppress_same_address.cc similarity index 100% rename from src/compiler-rt/test/tsan/suppress_same_address.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/suppress_same_address.cc diff --git a/src/compiler-rt/test/tsan/suppress_same_stacks.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/suppress_same_stacks.cc similarity index 100% rename from src/compiler-rt/test/tsan/suppress_same_stacks.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/suppress_same_stacks.cc diff --git a/src/compiler-rt/test/tsan/suppressions_global.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/suppressions_global.cc similarity index 100% rename from src/compiler-rt/test/tsan/suppressions_global.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/suppressions_global.cc diff --git a/src/compiler-rt/test/tsan/suppressions_global.cc.supp b/src/libcompiler_builtins/compiler-rt/test/tsan/suppressions_global.cc.supp similarity index 100% rename from src/compiler-rt/test/tsan/suppressions_global.cc.supp rename to src/libcompiler_builtins/compiler-rt/test/tsan/suppressions_global.cc.supp diff --git a/src/compiler-rt/test/tsan/suppressions_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/suppressions_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/suppressions_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/suppressions_race.cc diff --git a/src/compiler-rt/test/tsan/suppressions_race.cc.supp b/src/libcompiler_builtins/compiler-rt/test/tsan/suppressions_race.cc.supp similarity index 100% rename from src/compiler-rt/test/tsan/suppressions_race.cc.supp rename to src/libcompiler_builtins/compiler-rt/test/tsan/suppressions_race.cc.supp diff --git a/src/compiler-rt/test/tsan/suppressions_race2.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/suppressions_race2.cc similarity index 100% rename from src/compiler-rt/test/tsan/suppressions_race2.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/suppressions_race2.cc diff --git a/src/compiler-rt/test/tsan/suppressions_race2.cc.supp b/src/libcompiler_builtins/compiler-rt/test/tsan/suppressions_race2.cc.supp similarity index 100% rename from src/compiler-rt/test/tsan/suppressions_race2.cc.supp rename to src/libcompiler_builtins/compiler-rt/test/tsan/suppressions_race2.cc.supp diff --git a/src/compiler-rt/test/tsan/test.h b/src/libcompiler_builtins/compiler-rt/test/tsan/test.h similarity index 100% rename from src/compiler-rt/test/tsan/test.h rename to src/libcompiler_builtins/compiler-rt/test/tsan/test.h diff --git a/src/compiler-rt/test/tsan/thread_detach.c b/src/libcompiler_builtins/compiler-rt/test/tsan/thread_detach.c similarity index 100% rename from src/compiler-rt/test/tsan/thread_detach.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/thread_detach.c diff --git a/src/compiler-rt/test/tsan/thread_detach2.c b/src/libcompiler_builtins/compiler-rt/test/tsan/thread_detach2.c similarity index 100% rename from src/compiler-rt/test/tsan/thread_detach2.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/thread_detach2.c diff --git a/src/compiler-rt/test/tsan/thread_end_with_ignore.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/thread_end_with_ignore.cc similarity index 100% rename from src/compiler-rt/test/tsan/thread_end_with_ignore.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/thread_end_with_ignore.cc diff --git a/src/compiler-rt/test/tsan/thread_end_with_ignore2.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/thread_end_with_ignore2.cc similarity index 100% rename from src/compiler-rt/test/tsan/thread_end_with_ignore2.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/thread_end_with_ignore2.cc diff --git a/src/compiler-rt/test/tsan/thread_end_with_ignore3.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/thread_end_with_ignore3.cc similarity index 100% rename from src/compiler-rt/test/tsan/thread_end_with_ignore3.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/thread_end_with_ignore3.cc diff --git a/src/compiler-rt/test/tsan/thread_leak.c b/src/libcompiler_builtins/compiler-rt/test/tsan/thread_leak.c similarity index 100% rename from src/compiler-rt/test/tsan/thread_leak.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/thread_leak.c diff --git a/src/compiler-rt/test/tsan/thread_leak2.c b/src/libcompiler_builtins/compiler-rt/test/tsan/thread_leak2.c similarity index 100% rename from src/compiler-rt/test/tsan/thread_leak2.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/thread_leak2.c diff --git a/src/compiler-rt/test/tsan/thread_leak3.c b/src/libcompiler_builtins/compiler-rt/test/tsan/thread_leak3.c similarity index 100% rename from src/compiler-rt/test/tsan/thread_leak3.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/thread_leak3.c diff --git a/src/compiler-rt/test/tsan/thread_leak4.c b/src/libcompiler_builtins/compiler-rt/test/tsan/thread_leak4.c similarity index 100% rename from src/compiler-rt/test/tsan/thread_leak4.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/thread_leak4.c diff --git a/src/compiler-rt/test/tsan/thread_leak5.c b/src/libcompiler_builtins/compiler-rt/test/tsan/thread_leak5.c similarity index 100% rename from src/compiler-rt/test/tsan/thread_leak5.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/thread_leak5.c diff --git a/src/compiler-rt/test/tsan/thread_name.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/thread_name.cc similarity index 100% rename from src/compiler-rt/test/tsan/thread_name.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/thread_name.cc diff --git a/src/compiler-rt/test/tsan/thread_name2.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/thread_name2.cc similarity index 100% rename from src/compiler-rt/test/tsan/thread_name2.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/thread_name2.cc diff --git a/src/compiler-rt/test/tsan/tiny_race.c b/src/libcompiler_builtins/compiler-rt/test/tsan/tiny_race.c similarity index 100% rename from src/compiler-rt/test/tsan/tiny_race.c rename to src/libcompiler_builtins/compiler-rt/test/tsan/tiny_race.c diff --git a/src/compiler-rt/test/tsan/tls_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/tls_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/tls_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/tls_race.cc diff --git a/src/compiler-rt/test/tsan/tls_race2.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/tls_race2.cc similarity index 100% rename from src/compiler-rt/test/tsan/tls_race2.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/tls_race2.cc diff --git a/src/compiler-rt/test/tsan/tsan-vs-gvn.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/tsan-vs-gvn.cc similarity index 100% rename from src/compiler-rt/test/tsan/tsan-vs-gvn.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/tsan-vs-gvn.cc diff --git a/src/compiler-rt/test/tsan/unaligned_norace.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/unaligned_norace.cc similarity index 100% rename from src/compiler-rt/test/tsan/unaligned_norace.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/unaligned_norace.cc diff --git a/src/compiler-rt/test/tsan/unaligned_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/unaligned_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/unaligned_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/unaligned_race.cc diff --git a/src/compiler-rt/test/tsan/vfork.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/vfork.cc similarity index 100% rename from src/compiler-rt/test/tsan/vfork.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/vfork.cc diff --git a/src/compiler-rt/test/tsan/virtual_inheritance_compile_bug.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/virtual_inheritance_compile_bug.cc similarity index 100% rename from src/compiler-rt/test/tsan/virtual_inheritance_compile_bug.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/virtual_inheritance_compile_bug.cc diff --git a/src/compiler-rt/test/tsan/vptr_benign_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/vptr_benign_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/vptr_benign_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/vptr_benign_race.cc diff --git a/src/compiler-rt/test/tsan/vptr_harmful_race.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/vptr_harmful_race.cc similarity index 100% rename from src/compiler-rt/test/tsan/vptr_harmful_race.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/vptr_harmful_race.cc diff --git a/src/compiler-rt/test/tsan/vptr_harmful_race2.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/vptr_harmful_race2.cc similarity index 100% rename from src/compiler-rt/test/tsan/vptr_harmful_race2.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/vptr_harmful_race2.cc diff --git a/src/compiler-rt/test/tsan/vptr_harmful_race3.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/vptr_harmful_race3.cc similarity index 100% rename from src/compiler-rt/test/tsan/vptr_harmful_race3.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/vptr_harmful_race3.cc diff --git a/src/compiler-rt/test/tsan/vptr_harmful_race4.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/vptr_harmful_race4.cc similarity index 100% rename from src/compiler-rt/test/tsan/vptr_harmful_race4.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/vptr_harmful_race4.cc diff --git a/src/compiler-rt/test/tsan/write_in_reader_lock.cc b/src/libcompiler_builtins/compiler-rt/test/tsan/write_in_reader_lock.cc similarity index 100% rename from src/compiler-rt/test/tsan/write_in_reader_lock.cc rename to src/libcompiler_builtins/compiler-rt/test/tsan/write_in_reader_lock.cc diff --git a/src/compiler-rt/test/ubsan/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/test/ubsan/CMakeLists.txt similarity index 100% rename from src/compiler-rt/test/ubsan/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/test/ubsan/CMakeLists.txt diff --git a/src/compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Integer/add-overflow.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/add-overflow.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Integer/add-overflow.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/add-overflow.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Integer/div-overflow.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/div-overflow.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Integer/div-overflow.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/div-overflow.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Integer/div-zero.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/div-zero.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Integer/div-zero.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/div-zero.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Integer/incdec-overflow.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/incdec-overflow.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Integer/incdec-overflow.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/incdec-overflow.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Integer/mul-overflow.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/mul-overflow.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Integer/mul-overflow.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/mul-overflow.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Integer/negate-overflow.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/negate-overflow.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Integer/negate-overflow.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/negate-overflow.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Integer/no-recover.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/no-recover.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Integer/no-recover.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/no-recover.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Integer/shift.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/shift.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Integer/shift.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/shift.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Integer/sub-overflow.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/sub-overflow.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Integer/sub-overflow.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/sub-overflow.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Integer/summary.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/summary.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Integer/summary.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/summary.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Integer/suppressions.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/suppressions.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Integer/suppressions.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/suppressions.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Integer/uadd-overflow.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/uadd-overflow.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Integer/uadd-overflow.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/uadd-overflow.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Integer/uincdec-overflow.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/uincdec-overflow.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Integer/uincdec-overflow.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/uincdec-overflow.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Integer/umul-overflow.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/umul-overflow.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Integer/umul-overflow.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/umul-overflow.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Integer/usub-overflow.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/usub-overflow.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Integer/usub-overflow.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Integer/usub-overflow.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Misc/Linux/lit.local.cfg b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/Linux/lit.local.cfg similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Misc/Linux/lit.local.cfg rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/Linux/lit.local.cfg diff --git a/src/compiler-rt/test/ubsan/TestCases/Misc/Linux/ubsan_options.cc b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/Linux/ubsan_options.cc similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Misc/Linux/ubsan_options.cc rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/Linux/ubsan_options.cc diff --git a/src/compiler-rt/test/ubsan/TestCases/Misc/bool.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/bool.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Misc/bool.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/bool.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Misc/bounds.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/bounds.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Misc/bounds.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/bounds.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Misc/coverage-levels.cc b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/coverage-levels.cc similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Misc/coverage-levels.cc rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/coverage-levels.cc diff --git a/src/compiler-rt/test/ubsan/TestCases/Misc/deduplication.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/deduplication.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Misc/deduplication.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/deduplication.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Misc/enum.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/enum.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Misc/enum.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/enum.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cc b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cc similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cc rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cc diff --git a/src/compiler-rt/test/ubsan/TestCases/Misc/missing_return.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/missing_return.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Misc/missing_return.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/missing_return.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Misc/nonnull-arg.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/nonnull-arg.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Misc/nonnull-arg.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/nonnull-arg.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Misc/nonnull.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/nonnull.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Misc/nonnull.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/nonnull.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Misc/unreachable.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/unreachable.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Misc/unreachable.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/unreachable.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/Misc/vla.c b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/vla.c similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/Misc/vla.c rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/Misc/vla.c diff --git a/src/compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/TypeCheck/Function/lit.local.cfg b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/TypeCheck/Function/lit.local.cfg similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/TypeCheck/Function/lit.local.cfg rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/TypeCheck/Function/lit.local.cfg diff --git a/src/compiler-rt/test/ubsan/TestCases/TypeCheck/misaligned.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/TypeCheck/misaligned.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/TypeCheck/misaligned.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/TypeCheck/misaligned.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/TypeCheck/null.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/TypeCheck/null.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/TypeCheck/null.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/TypeCheck/null.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-corrupted-vtable-itanium.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-corrupted-vtable-itanium.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-corrupted-vtable-itanium.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-corrupted-vtable-itanium.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-non-unique-typeinfo.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-non-unique-typeinfo.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-non-unique-typeinfo.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-non-unique-typeinfo.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-virtual-base-construction.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-virtual-base-construction.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-virtual-base-construction.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-virtual-base-construction.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp diff --git a/src/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr.cpp b/src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr.cpp similarity index 100% rename from src/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr.cpp rename to src/libcompiler_builtins/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr.cpp diff --git a/src/compiler-rt/test/ubsan/lit.common.cfg b/src/libcompiler_builtins/compiler-rt/test/ubsan/lit.common.cfg similarity index 100% rename from src/compiler-rt/test/ubsan/lit.common.cfg rename to src/libcompiler_builtins/compiler-rt/test/ubsan/lit.common.cfg diff --git a/src/compiler-rt/test/ubsan/lit.site.cfg.in b/src/libcompiler_builtins/compiler-rt/test/ubsan/lit.site.cfg.in similarity index 100% rename from src/compiler-rt/test/ubsan/lit.site.cfg.in rename to src/libcompiler_builtins/compiler-rt/test/ubsan/lit.site.cfg.in diff --git a/src/compiler-rt/test/xray/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/test/xray/CMakeLists.txt similarity index 100% rename from src/compiler-rt/test/xray/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/test/xray/CMakeLists.txt diff --git a/src/compiler-rt/test/xray/TestCases/Linux/argv0-log-file-name.cc b/src/libcompiler_builtins/compiler-rt/test/xray/TestCases/Linux/argv0-log-file-name.cc similarity index 100% rename from src/compiler-rt/test/xray/TestCases/Linux/argv0-log-file-name.cc rename to src/libcompiler_builtins/compiler-rt/test/xray/TestCases/Linux/argv0-log-file-name.cc diff --git a/src/compiler-rt/test/xray/TestCases/Linux/fixedsize-logging.cc b/src/libcompiler_builtins/compiler-rt/test/xray/TestCases/Linux/fixedsize-logging.cc similarity index 100% rename from src/compiler-rt/test/xray/TestCases/Linux/fixedsize-logging.cc rename to src/libcompiler_builtins/compiler-rt/test/xray/TestCases/Linux/fixedsize-logging.cc diff --git a/src/compiler-rt/test/xray/TestCases/Linux/optional-inmemory-log.cc b/src/libcompiler_builtins/compiler-rt/test/xray/TestCases/Linux/optional-inmemory-log.cc similarity index 100% rename from src/compiler-rt/test/xray/TestCases/Linux/optional-inmemory-log.cc rename to src/libcompiler_builtins/compiler-rt/test/xray/TestCases/Linux/optional-inmemory-log.cc diff --git a/src/compiler-rt/test/xray/TestCases/Linux/patching-unpatching.cc b/src/libcompiler_builtins/compiler-rt/test/xray/TestCases/Linux/patching-unpatching.cc similarity index 100% rename from src/compiler-rt/test/xray/TestCases/Linux/patching-unpatching.cc rename to src/libcompiler_builtins/compiler-rt/test/xray/TestCases/Linux/patching-unpatching.cc diff --git a/src/compiler-rt/test/xray/Unit/lit.site.cfg.in b/src/libcompiler_builtins/compiler-rt/test/xray/Unit/lit.site.cfg.in similarity index 100% rename from src/compiler-rt/test/xray/Unit/lit.site.cfg.in rename to src/libcompiler_builtins/compiler-rt/test/xray/Unit/lit.site.cfg.in diff --git a/src/compiler-rt/test/xray/lit.cfg b/src/libcompiler_builtins/compiler-rt/test/xray/lit.cfg similarity index 100% rename from src/compiler-rt/test/xray/lit.cfg rename to src/libcompiler_builtins/compiler-rt/test/xray/lit.cfg diff --git a/src/compiler-rt/test/xray/lit.site.cfg.in b/src/libcompiler_builtins/compiler-rt/test/xray/lit.site.cfg.in similarity index 100% rename from src/compiler-rt/test/xray/lit.site.cfg.in rename to src/libcompiler_builtins/compiler-rt/test/xray/lit.site.cfg.in diff --git a/src/compiler-rt/unittests/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/unittests/CMakeLists.txt similarity index 100% rename from src/compiler-rt/unittests/CMakeLists.txt rename to src/libcompiler_builtins/compiler-rt/unittests/CMakeLists.txt diff --git a/src/compiler-rt/unittests/lit.common.unit.cfg b/src/libcompiler_builtins/compiler-rt/unittests/lit.common.unit.cfg similarity index 100% rename from src/compiler-rt/unittests/lit.common.unit.cfg rename to src/libcompiler_builtins/compiler-rt/unittests/lit.common.unit.cfg diff --git a/src/compiler-rt/unittests/lit.common.unit.configured.in b/src/libcompiler_builtins/compiler-rt/unittests/lit.common.unit.configured.in similarity index 100% rename from src/compiler-rt/unittests/lit.common.unit.configured.in rename to src/libcompiler_builtins/compiler-rt/unittests/lit.common.unit.configured.in diff --git a/src/compiler-rt/www/content.css b/src/libcompiler_builtins/compiler-rt/www/content.css similarity index 100% rename from src/compiler-rt/www/content.css rename to src/libcompiler_builtins/compiler-rt/www/content.css diff --git a/src/compiler-rt/www/index.html b/src/libcompiler_builtins/compiler-rt/www/index.html similarity index 100% rename from src/compiler-rt/www/index.html rename to src/libcompiler_builtins/compiler-rt/www/index.html diff --git a/src/compiler-rt/www/menu.css b/src/libcompiler_builtins/compiler-rt/www/menu.css similarity index 100% rename from src/compiler-rt/www/menu.css rename to src/libcompiler_builtins/compiler-rt/www/menu.css diff --git a/src/compiler-rt/www/menu.html.incl b/src/libcompiler_builtins/compiler-rt/www/menu.html.incl similarity index 100% rename from src/compiler-rt/www/menu.html.incl rename to src/libcompiler_builtins/compiler-rt/www/menu.html.incl diff --git a/src/libcompiler_builtins/examples/intrinsics.rs b/src/libcompiler_builtins/examples/intrinsics.rs new file mode 100644 index 0000000000..3820887895 --- /dev/null +++ b/src/libcompiler_builtins/examples/intrinsics.rs @@ -0,0 +1,467 @@ +// By compiling this file we check that all the intrinsics we care about continue to be provided by +// the `compiler_builtins` crate regardless of the changes we make to it. If we, by mistake, stop +// compiling a C implementation and forget to implement that intrinsic in Rust, this file will fail +// to link due to the missing intrinsic (symbol). + +#![allow(unused_features)] +#![cfg_attr(thumb, no_main)] +#![deny(dead_code)] +#![feature(alloc_system)] +#![feature(asm)] +#![feature(compiler_builtins_lib)] +#![feature(core_float)] +#![feature(lang_items)] +#![feature(start)] +#![feature(i128_type)] +#![feature(global_allocator)] +#![feature(allocator_api)] +#![cfg_attr(windows, feature(panic_unwind))] +#![no_std] + +#[cfg(not(thumb))] +extern crate alloc_system; +extern crate compiler_builtins; +#[cfg(windows)] +extern crate panic_unwind; + +#[cfg(not(thumb))] +#[global_allocator] +static A: alloc_system::System = alloc_system::System; + +// NOTE cfg(not(thumbv6m)) means that the operation is not supported on ARMv6-M at all. Not even +// compiler-rt provides a C/assembly implementation. + +// Every function in this module maps will be lowered to an intrinsic by LLVM, if the platform +// doesn't have native support for the operation used in the function. ARM has a naming convention +// convention for its intrinsics that's different from other architectures; that's why some function +// have an additional comment: the function name is the ARM name for the intrinsic and the comment +// in the non-ARM name for the intrinsic. +mod intrinsics { + use core::num::Float; + + // trunccdfsf2 + pub fn aeabi_d2f(x: f64) -> f32 { + x as f32 + } + + // fixdfsi + pub fn aeabi_d2i(x: f64) -> i32 { + x as i32 + } + + // fixdfdi + #[cfg(not(thumbv6m))] + pub fn aeabi_d2l(x: f64) -> i64 { + x as i64 + } + + #[cfg(thumbv6m)] + pub fn aeabi_d2l(_: f64) -> i64 { + 0 + } + + // fixunsdfsi + pub fn aeabi_d2uiz(x: f64) -> u32 { + x as u32 + } + + // fixunsdfdi + #[cfg(not(thumbv6m))] + pub fn aeabi_d2ulz(x: f64) -> u64 { + x as u64 + } + + #[cfg(thumbv6m)] + pub fn aeabi_d2ulz(_: f64) -> u64 { + 0 + } + + // adddf3 + pub fn aeabi_dadd(a: f64, b: f64) -> f64 { + a + b + } + + // eqdf2 + #[cfg(not(thumbv6m))] + pub fn aeabi_dcmpeq(a: f64, b: f64) -> bool { + a == b + } + + #[cfg(thumbv6m)] + pub fn aeabi_dcmpeq(_: f64, _: f64) -> bool { + true + } + + // gtdf2 + #[cfg(not(thumbv6m))] + pub fn aeabi_dcmpgt(a: f64, b: f64) -> bool { + a > b + } + + #[cfg(thumbv6m)] + pub fn aeabi_dcmpgt(_: f64, _: f64) -> bool { + true + } + + // ltdf2 + #[cfg(not(thumbv6m))] + pub fn aeabi_dcmplt(a: f64, b: f64) -> bool { + a < b + } + + #[cfg(thumbv6m)] + pub fn aeabi_dcmplt(_: f64, _: f64) -> bool { + true + } + + // divdf3 + pub fn aeabi_ddiv(a: f64, b: f64) -> f64 { + a / b + } + + // muldf3 + pub fn aeabi_dmul(a: f64, b: f64) -> f64 { + a * b + } + + // subdf3 + pub fn aeabi_dsub(a: f64, b: f64) -> f64 { + a - b + } + + // extendsfdf2 + pub fn aeabi_f2d(x: f32) -> f64 { + x as f64 + } + + // fixsfsi + pub fn aeabi_f2iz(x: f32) -> i32 { + x as i32 + } + + // fixsfdi + #[cfg(not(thumbv6m))] + pub fn aeabi_f2lz(x: f32) -> i64 { + x as i64 + } + + #[cfg(thumbv6m)] + pub fn aeabi_f2lz(_: f32) -> i64 { + 0 + } + + // fixunssfsi + pub fn aeabi_f2uiz(x: f32) -> u32 { + x as u32 + } + + // fixunssfdi + #[cfg(not(thumbv6m))] + pub fn aeabi_f2ulz(x: f32) -> u64 { + x as u64 + } + + #[cfg(thumbv6m)] + pub fn aeabi_f2ulz(_: f32) -> u64 { + 0 + } + + // addsf3 + pub fn aeabi_fadd(a: f32, b: f32) -> f32 { + a + b + } + + // eqsf2 + #[cfg(not(thumbv6m))] + pub fn aeabi_fcmpeq(a: f32, b: f32) -> bool { + a == b + } + + #[cfg(thumbv6m)] + pub fn aeabi_fcmpeq(_: f32, _: f32) -> bool { + true + } + + // gtsf2 + #[cfg(not(thumbv6m))] + pub fn aeabi_fcmpgt(a: f32, b: f32) -> bool { + a > b + } + + #[cfg(thumbv6m)] + pub fn aeabi_fcmpgt(_: f32, _: f32) -> bool { + true + } + + // ltsf2 + #[cfg(not(thumbv6m))] + pub fn aeabi_fcmplt(a: f32, b: f32) -> bool { + a < b + } + + #[cfg(thumbv6m)] + pub fn aeabi_fcmplt(_: f32, _: f32) -> bool { + true + } + + // divsf3 + pub fn aeabi_fdiv(a: f32, b: f32) -> f32 { + a / b + } + + // mulsf3 + pub fn aeabi_fmul(a: f32, b: f32) -> f32 { + a * b + } + + // subsf3 + pub fn aeabi_fsub(a: f32, b: f32) -> f32 { + a - b + } + + // floatsidf + pub fn aeabi_i2d(x: i32) -> f64 { + x as f64 + } + + // floatsisf + pub fn aeabi_i2f(x: i32) -> f32 { + x as f32 + } + + pub fn aeabi_idiv(a: i32, b: i32) -> i32 { + a.wrapping_div(b) + } + + pub fn aeabi_idivmod(a: i32, b: i32) -> i32 { + a % b + } + + // floatdidf + pub fn aeabi_l2d(x: i64) -> f64 { + x as f64 + } + + // floatdisf + pub fn aeabi_l2f(x: i64) -> f32 { + x as f32 + } + + // divdi3 + pub fn aeabi_ldivmod(a: i64, b: i64) -> i64 { + a / b + } + + // muldi3 + pub fn aeabi_lmul(a: i64, b: i64) -> i64 { + a.wrapping_mul(b) + } + + // floatunsidf + pub fn aeabi_ui2d(x: u32) -> f64 { + x as f64 + } + + // floatunsisf + pub fn aeabi_ui2f(x: u32) -> f32 { + x as f32 + } + + pub fn aeabi_uidiv(a: u32, b: u32) -> u32 { + a / b + } + + pub fn aeabi_uidivmod(a: u32, b: u32) -> u32 { + a % b + } + + // floatundidf + pub fn aeabi_ul2d(x: u64) -> f64 { + x as f64 + } + + // floatundisf + pub fn aeabi_ul2f(x: u64) -> f32 { + x as f32 + } + + // udivdi3 + pub fn aeabi_uldivmod(a: u64, b: u64) -> u64 { + a * b + } + + pub fn moddi3(a: i64, b: i64) -> i64 { + a % b + } + + pub fn mulodi4(a: i64, b: i64) -> i64 { + a * b + } + + pub fn powidf2(a: f64, b: i32) -> f64 { + a.powi(b) + } + + pub fn powisf2(a: f32, b: i32) -> f32 { + a.powi(b) + } + + pub fn umoddi3(a: u64, b: u64) -> u64 { + a % b + } + + pub fn muloti4(a: u128, b: u128) -> Option { + a.checked_mul(b) + } + + pub fn multi3(a: u128, b: u128) -> u128 { + a.wrapping_mul(b) + } + + pub fn ashlti3(a: u128, b: usize) -> u128 { + a >> b + } + + pub fn ashrti3(a: u128, b: usize) -> u128 { + a << b + } + + pub fn lshrti3(a: i128, b: usize) -> i128 { + a >> b + } + + pub fn udivti3(a: u128, b: u128) -> u128 { + a / b + } + + pub fn umodti3(a: u128, b: u128) -> u128 { + a % b + } + + pub fn divti3(a: i128, b: i128) -> i128 { + a / b + } + + pub fn modti3(a: i128, b: i128) -> i128 { + a % b + } +} + +fn run() { + use intrinsics::*; + + // A copy of "test::black_box". Used to prevent LLVM from optimizing away the intrinsics during LTO + fn bb(dummy: T) -> T { + unsafe { asm!("" : : "r"(&dummy)) } + dummy + } + + bb(aeabi_d2f(bb(2.))); + bb(aeabi_d2i(bb(2.))); + bb(aeabi_d2l(bb(2.))); + bb(aeabi_d2uiz(bb(2.))); + bb(aeabi_d2ulz(bb(2.))); + bb(aeabi_dadd(bb(2.), bb(3.))); + bb(aeabi_dcmpeq(bb(2.), bb(3.))); + bb(aeabi_dcmpgt(bb(2.), bb(3.))); + bb(aeabi_dcmplt(bb(2.), bb(3.))); + bb(aeabi_ddiv(bb(2.), bb(3.))); + bb(aeabi_dmul(bb(2.), bb(3.))); + bb(aeabi_dsub(bb(2.), bb(3.))); + bb(aeabi_f2d(bb(2.))); + bb(aeabi_f2iz(bb(2.))); + bb(aeabi_f2lz(bb(2.))); + bb(aeabi_f2uiz(bb(2.))); + bb(aeabi_f2ulz(bb(2.))); + bb(aeabi_fadd(bb(2.), bb(3.))); + bb(aeabi_fcmpeq(bb(2.), bb(3.))); + bb(aeabi_fcmpgt(bb(2.), bb(3.))); + bb(aeabi_fcmplt(bb(2.), bb(3.))); + bb(aeabi_fdiv(bb(2.), bb(3.))); + bb(aeabi_fmul(bb(2.), bb(3.))); + bb(aeabi_fsub(bb(2.), bb(3.))); + bb(aeabi_i2d(bb(2))); + bb(aeabi_i2f(bb(2))); + bb(aeabi_idiv(bb(2), bb(3))); + bb(aeabi_idivmod(bb(2), bb(3))); + bb(aeabi_l2d(bb(2))); + bb(aeabi_l2f(bb(2))); + bb(aeabi_ldivmod(bb(2), bb(3))); + bb(aeabi_lmul(bb(2), bb(3))); + bb(aeabi_ui2d(bb(2))); + bb(aeabi_ui2f(bb(2))); + bb(aeabi_uidiv(bb(2), bb(3))); + bb(aeabi_uidivmod(bb(2), bb(3))); + bb(aeabi_ul2d(bb(2))); + bb(aeabi_ul2f(bb(2))); + bb(aeabi_uldivmod(bb(2), bb(3))); + bb(moddi3(bb(2), bb(3))); + bb(mulodi4(bb(2), bb(3))); + bb(powidf2(bb(2.), bb(3))); + bb(powisf2(bb(2.), bb(3))); + bb(umoddi3(bb(2), bb(3))); + bb(muloti4(bb(2), bb(2))); + bb(multi3(bb(2), bb(2))); + bb(ashlti3(bb(2), bb(2))); + bb(ashrti3(bb(2), bb(2))); + bb(lshrti3(bb(2), bb(2))); + bb(udivti3(bb(2), bb(2))); + bb(umodti3(bb(2), bb(2))); + bb(divti3(bb(2), bb(2))); + bb(modti3(bb(2), bb(2))); + + something_with_a_dtor(&|| assert_eq!(bb(1), 1)); +} + +fn something_with_a_dtor(f: &Fn()) { + struct A<'a>(&'a (Fn() + 'a)); + + impl<'a> Drop for A<'a> { + fn drop(&mut self) { + (self.0)(); + } + } + let _a = A(f); + f(); +} + +#[cfg(not(thumb))] +#[start] +fn main(_: isize, _: *const *const u8) -> isize { + run(); + 0 +} + +#[cfg(thumb)] +#[no_mangle] +pub fn _start() -> ! { + run(); + loop {} +} + +#[cfg(windows)] +#[link(name = "kernel32")] +#[link(name = "msvcrt")] +extern {} + +// ARM targets need these symbols +#[no_mangle] +pub fn __aeabi_unwind_cpp_pr0() {} + +#[no_mangle] +pub fn __aeabi_unwind_cpp_pr1() {} + +#[cfg(not(windows))] +#[allow(non_snake_case)] +#[no_mangle] +pub fn _Unwind_Resume() {} + +#[cfg(not(windows))] +#[lang = "eh_personality"] +#[no_mangle] +pub extern "C" fn eh_personality() {} + +#[lang = "panic_fmt"] +#[no_mangle] +#[allow(private_no_mangle_fns)] +extern "C" fn panic_fmt() {} diff --git a/src/libcompiler_builtins/lib.rs b/src/libcompiler_builtins/lib.rs deleted file mode 100644 index 09b3d63950..0000000000 --- a/src/libcompiler_builtins/lib.rs +++ /dev/null @@ -1,721 +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. - -#![feature(compiler_builtins)] -#![no_std] -#![compiler_builtins] -#![unstable(feature = "compiler_builtins_lib", - reason = "internal implementation detail of rustc right now", - issue = "0")] -#![crate_name = "compiler_builtins"] -#![crate_type = "rlib"] -#![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(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; - - macro_rules! ashl { - ($a:expr, $b:expr, $ty:ty) => {{ - let (a, b) = ($a, $b); - let bits = ::core::mem::size_of::<$ty>().wrapping_mul(8) as $ty; - let half_bits = bits.wrapping_shr(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>().wrapping_mul(8) as $ty; - let half_bits = bits.wrapping_shr(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>().wrapping_mul(8) as $ty; - let half_bits = bits.wrapping_shr(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) - } - - 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(128u32.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 - }) - } - - 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 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 - } - } - 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>().wrapping_mul(4) 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) - }} - } - - #[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; - } - - impl AbsExt for i128 { - fn uabs(self) -> u128 { - self.iabs() as u128 - } - fn iabs(self) -> i128 { - let s = self.wrapping_shr(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>().wrapping_mul(8) as i32 { - 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>().wrapping_mul(8) as i32 { - 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; - - let negn = !0u128; - - 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; - - let negn = !0u128; - - 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::{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 $unadj fn f32_as_u128(a: f32) -> u128 { - float_as_unsigned!(a, f32, u128) - } - - #[export_name="__fixdfti"] - pub extern $unadj fn f64_as_i128(a: f64) -> i128 { - float_as_signed!(a, f64, i128) - } - - #[export_name="__fixsfti"] - pub extern $unadj 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(all(windows, target_pointer_width="64"))] - why_are_abi_strings_checked_by_parser!(u64x2, - |i: u128| u64x2(i.low(), i.high()), - "unadjusted"); - - #[cfg(not(all(windows, target_pointer_width="64")))] - why_are_abi_strings_checked_by_parser!(u128, |i|{ i }, "C"); - pub use self::imp::*; -} diff --git a/src/libcompiler_builtins/src/arm.rs b/src/libcompiler_builtins/src/arm.rs new file mode 100644 index 0000000000..fa86e96914 --- /dev/null +++ b/src/libcompiler_builtins/src/arm.rs @@ -0,0 +1,170 @@ +use core::intrinsics; + +// NOTE This function and the ones below are implemented using assembly because they using a custom +// calling convention which can't be implemented using a normal Rust function +#[naked] +#[cfg_attr(not(feature = "mangled-names"), no_mangle)] +pub unsafe fn __aeabi_uidivmod() { + asm!("push {lr} + sub sp, sp, #4 + mov r2, sp + bl __udivmodsi4 + ldr r1, [sp] + add sp, sp, #4 + pop {pc}"); + intrinsics::unreachable(); +} + +#[naked] +#[cfg_attr(not(feature = "mangled-names"), no_mangle)] +pub unsafe fn __aeabi_uldivmod() { + asm!("push {r4, lr} + sub sp, sp, #16 + add r4, sp, #8 + str r4, [sp] + bl __udivmoddi4 + ldr r2, [sp, #8] + ldr r3, [sp, #12] + add sp, sp, #16 + pop {r4, pc}"); + intrinsics::unreachable(); +} + +#[naked] +#[cfg_attr(not(feature = "mangled-names"), no_mangle)] +pub unsafe fn __aeabi_idivmod() { + asm!("push {r0, r1, r4, lr} + bl __aeabi_idiv + pop {r1, r2} + muls r2, r2, r0 + subs r1, r1, r2 + pop {r4, pc}"); + intrinsics::unreachable(); +} + +#[naked] +#[cfg_attr(not(feature = "mangled-names"), no_mangle)] +pub unsafe fn __aeabi_ldivmod() { + asm!("push {r4, lr} + sub sp, sp, #16 + add r4, sp, #8 + str r4, [sp] + bl __divmoddi4 + ldr r2, [sp, #8] + ldr r3, [sp, #12] + add sp, sp, #16 + pop {r4, pc}"); + intrinsics::unreachable(); +} + +// FIXME: The `*4` and `*8` variants should be defined as aliases. + +#[cfg(not(target_os = "ios"))] +#[cfg_attr(not(feature = "mangled-names"), no_mangle)] +#[cfg_attr(thumb, linkage = "weak")] +pub unsafe extern "aapcs" fn __aeabi_memcpy(dest: *mut u8, src: *const u8, n: usize) { + ::mem::memcpy(dest, src, n); +} + +#[cfg(not(target_os = "ios"))] +#[cfg_attr(not(feature = "mangled-names"), no_mangle)] +#[cfg_attr(thumb, linkage = "weak")] +pub unsafe extern "aapcs" fn __aeabi_memcpy4(dest: *mut u8, src: *const u8, mut n: usize) { + use core::ptr; + + let mut dest = dest as *mut u32; + let mut src = src as *mut u32; + + while n >= 4 { + ptr::write(dest, ptr::read(src)); + dest = dest.offset(1); + src = src.offset(1); + n -= 4; + } + + __aeabi_memcpy(dest as *mut u8, src as *const u8, n); +} + +#[cfg(not(target_os = "ios"))] +#[cfg_attr(not(feature = "mangled-names"), no_mangle)] +#[cfg_attr(thumb, linkage = "weak")] +pub unsafe extern "aapcs" fn __aeabi_memcpy8(dest: *mut u8, src: *const u8, n: usize) { + __aeabi_memcpy4(dest, src, n); +} + +#[cfg(not(target_os = "ios"))] +#[cfg_attr(not(feature = "mangled-names"), no_mangle)] +#[cfg_attr(thumb, linkage = "weak")] +pub unsafe extern "aapcs" fn __aeabi_memmove(dest: *mut u8, src: *const u8, n: usize) { + ::mem::memmove(dest, src, n); +} + +#[cfg(not(target_os = "ios"))] +#[cfg_attr(not(feature = "mangled-names"), no_mangle)] +#[cfg_attr(thumb, linkage = "weak")] +pub unsafe extern "aapcs" fn __aeabi_memmove4(dest: *mut u8, src: *const u8, n: usize) { + __aeabi_memmove(dest, src, n); +} + +#[cfg(not(target_os = "ios"))] +#[cfg_attr(not(feature = "mangled-names"), no_mangle)] +#[cfg_attr(thumb, linkage = "weak")] +pub unsafe extern "aapcs" fn __aeabi_memmove8(dest: *mut u8, src: *const u8, n: usize) { + __aeabi_memmove(dest, src, n); +} + +#[cfg(not(target_os = "ios"))] +#[cfg_attr(not(feature = "mangled-names"), no_mangle)] +#[cfg_attr(thumb, linkage = "weak")] +pub unsafe extern "aapcs" fn __aeabi_memset(dest: *mut u8, n: usize, c: i32) { + // Note the different argument order + ::mem::memset(dest, c, n); +} + +#[cfg(not(target_os = "ios"))] +#[cfg_attr(not(feature = "mangled-names"), no_mangle)] +#[cfg_attr(thumb, linkage = "weak")] +pub unsafe extern "aapcs" fn __aeabi_memset4(dest: *mut u8, mut n: usize, c: i32) { + use core::ptr; + + let mut dest = dest as *mut u32; + + let byte = (c as u32) & 0xff; + let c = (byte << 24) | (byte << 16) | (byte << 8) | byte; + + while n >= 4 { + ptr::write(dest, c); + dest = dest.offset(1); + n -= 4; + } + + __aeabi_memset(dest as *mut u8, n, byte as i32); +} + +#[cfg(not(target_os = "ios"))] +#[cfg_attr(not(feature = "mangled-names"), no_mangle)] +#[cfg_attr(thumb, linkage = "weak")] +pub unsafe extern "aapcs" fn __aeabi_memset8(dest: *mut u8, n: usize, c: i32) { + __aeabi_memset4(dest, n, c); +} + +#[cfg(not(target_os = "ios"))] +#[cfg_attr(not(feature = "mangled-names"), no_mangle)] +#[cfg_attr(thumb, linkage = "weak")] +pub unsafe extern "aapcs" fn __aeabi_memclr(dest: *mut u8, n: usize) { + __aeabi_memset(dest, n, 0); +} + +#[cfg(not(target_os = "ios"))] +#[cfg_attr(not(feature = "mangled-names"), no_mangle)] +#[cfg_attr(thumb, linkage = "weak")] +pub unsafe extern "aapcs" fn __aeabi_memclr4(dest: *mut u8, n: usize) { + __aeabi_memset4(dest, n, 0); +} + +#[cfg(not(target_os = "ios"))] +#[cfg_attr(not(feature = "mangled-names"), no_mangle)] +#[cfg_attr(thumb, linkage = "weak")] +pub unsafe extern "aapcs" fn __aeabi_memclr8(dest: *mut u8, n: usize) { + __aeabi_memset4(dest, n, 0); +} diff --git a/src/libcompiler_builtins/src/float/add.rs b/src/libcompiler_builtins/src/float/add.rs new file mode 100644 index 0000000000..696d886fb6 --- /dev/null +++ b/src/libcompiler_builtins/src/float/add.rs @@ -0,0 +1,194 @@ +use core::mem; +use core::num::Wrapping; + +use float::Float; + +/// Returns `a + b` +macro_rules! add { + ($a:expr, $b:expr, $ty:ty) => ({ + let a = $a; + let b = $b; + let one = Wrapping(1 as <$ty as Float>::Int); + let zero = Wrapping(0 as <$ty as Float>::Int); + + let bits = Wrapping(<$ty>::bits() as <$ty as Float>::Int); + let significand_bits = Wrapping(<$ty>::significand_bits() as <$ty as Float>::Int); + let exponent_bits = bits - significand_bits - one; + let max_exponent = (one << exponent_bits.0 as usize) - one; + + let implicit_bit = one << significand_bits.0 as usize; + let significand_mask = implicit_bit - one; + let sign_bit = one << (significand_bits + exponent_bits).0 as usize; + let abs_mask = sign_bit - one; + let exponent_mask = abs_mask ^ significand_mask; + let inf_rep = exponent_mask; + let quiet_bit = implicit_bit >> 1; + let qnan_rep = exponent_mask | quiet_bit; + + let mut a_rep = Wrapping(a.repr()); + let mut b_rep = Wrapping(b.repr()); + let a_abs = a_rep & abs_mask; + let b_abs = b_rep & abs_mask; + + // Detect if a or b is zero, infinity, or NaN. + if a_abs - one >= inf_rep - one || + b_abs - one >= inf_rep - one { + // NaN + anything = qNaN + if a_abs > inf_rep { + return <$ty as Float>::from_repr((a_abs | quiet_bit).0); + } + // anything + NaN = qNaN + if b_abs > inf_rep { + return <$ty as Float>::from_repr((b_abs | quiet_bit).0); + } + + if a_abs == inf_rep { + // +/-infinity + -/+infinity = qNaN + if (a.repr() ^ b.repr()) == sign_bit.0 { + return <$ty as Float>::from_repr(qnan_rep.0); + } else { + // +/-infinity + anything remaining = +/- infinity + return a; + } + } + + // anything remaining + +/-infinity = +/-infinity + if b_abs == inf_rep { + return b; + } + + // zero + anything = anything + if a_abs.0 == 0 { + // but we need to get the sign right for zero + zero + if b_abs.0 == 0 { + return <$ty as Float>::from_repr(a.repr() & b.repr()); + } else { + return b; + } + } + + // anything + zero = anything + if b_abs.0 == 0 { + return a; + } + } + + // Swap a and b if necessary so that a has the larger absolute value. + if b_abs > a_abs { + mem::swap(&mut a_rep, &mut b_rep); + } + + // Extract the exponent and significand from the (possibly swapped) a and b. + let mut a_exponent = Wrapping((a_rep >> significand_bits.0 as usize & max_exponent).0 as i32); + let mut b_exponent = Wrapping((b_rep >> significand_bits.0 as usize & max_exponent).0 as i32); + let mut a_significand = a_rep & significand_mask; + let mut b_significand = b_rep & significand_mask; + + // normalize any denormals, and adjust the exponent accordingly. + if a_exponent.0 == 0 { + let (exponent, significand) = <$ty>::normalize(a_significand.0); + a_exponent = Wrapping(exponent); + a_significand = Wrapping(significand); + } + if b_exponent.0 == 0 { + let (exponent, significand) = <$ty>::normalize(b_significand.0); + b_exponent = Wrapping(exponent); + b_significand = Wrapping(significand); + } + + // The sign of the result is the sign of the larger operand, a. If they + // have opposite signs, we are performing a subtraction; otherwise addition. + let result_sign = a_rep & sign_bit; + let subtraction = ((a_rep ^ b_rep) & sign_bit) != zero; + + // Shift the significands to give us round, guard and sticky, and or in the + // implicit significand bit. (If we fell through from the denormal path it + // was already set by normalize(), but setting it twice won't hurt + // anything.) + a_significand = (a_significand | implicit_bit) << 3; + b_significand = (b_significand | implicit_bit) << 3; + + // Shift the significand of b by the difference in exponents, with a sticky + // bottom bit to get rounding correct. + let align = Wrapping((a_exponent - b_exponent).0 as <$ty as Float>::Int); + if align.0 != 0 { + if align < bits { + let sticky = ((b_significand << (bits - align).0 as usize).0 != 0) as <$ty as Float>::Int; + b_significand = (b_significand >> align.0 as usize) | Wrapping(sticky); + } else { + b_significand = one; // sticky; b is known to be non-zero. + } + } + if subtraction { + a_significand -= b_significand; + // If a == -b, return +zero. + if a_significand.0 == 0 { + return <$ty as Float>::from_repr(0); + } + + // If partial cancellation occured, we need to left-shift the result + // and adjust the exponent: + if a_significand < implicit_bit << 3 { + let shift = a_significand.0.leading_zeros() as i32 + - (implicit_bit << 3).0.leading_zeros() as i32; + a_significand <<= shift as usize; + a_exponent -= Wrapping(shift); + } + } else /* addition */ { + a_significand += b_significand; + + // If the addition carried up, we need to right-shift the result and + // adjust the exponent: + if (a_significand & implicit_bit << 4).0 != 0 { + let sticky = ((a_significand & one).0 != 0) as <$ty as Float>::Int; + a_significand = a_significand >> 1 | Wrapping(sticky); + a_exponent += Wrapping(1); + } + } + + // If we have overflowed the type, return +/- infinity: + if a_exponent >= Wrapping(max_exponent.0 as i32) { + return <$ty>::from_repr((inf_rep | result_sign).0); + } + + if a_exponent.0 <= 0 { + // Result is denormal before rounding; the exponent is zero and we + // need to shift the significand. + let shift = Wrapping((Wrapping(1) - a_exponent).0 as <$ty as Float>::Int); + let sticky = ((a_significand << (bits - shift).0 as usize).0 != 0) as <$ty as Float>::Int; + a_significand = a_significand >> shift.0 as usize | Wrapping(sticky); + a_exponent = Wrapping(0); + } + + // Low three bits are round, guard, and sticky. + let round_guard_sticky: i32 = (a_significand.0 & 0x7) as i32; + + // Shift the significand into place, and mask off the implicit bit. + let mut result = a_significand >> 3 & significand_mask; + + // Insert the exponent and sign. + result |= Wrapping(a_exponent.0 as <$ty as Float>::Int) << significand_bits.0 as usize; + result |= result_sign; + + // Final rounding. The result may overflow to infinity, but that is the + // correct result in that case. + if round_guard_sticky > 0x4 { result += one; } + if round_guard_sticky == 0x4 { result += result & one; } + + <$ty>::from_repr(result.0) + }) +} + +intrinsics! { + #[aapcs_on_arm] + #[arm_aeabi_alias = __aeabi_fadd] + pub extern "C" fn __addsf3(a: f32, b: f32) -> f32 { + add!(a, b, f32) + } + + #[aapcs_on_arm] + #[arm_aeabi_alias = __aeabi_dadd] + pub extern "C" fn __adddf3(a: f64, b: f64) -> f64 { + add!(a, b, f64) + } +} diff --git a/src/libcompiler_builtins/src/float/conv.rs b/src/libcompiler_builtins/src/float/conv.rs new file mode 100644 index 0000000000..f2fd01d37b --- /dev/null +++ b/src/libcompiler_builtins/src/float/conv.rs @@ -0,0 +1,251 @@ +use float::Float; +use int::Int; + +macro_rules! int_to_float { + ($i:expr, $ity:ty, $fty:ty) => ({ + let i = $i; + if i == 0 { + return 0.0 + } + + let mant_dig = <$fty>::significand_bits() + 1; + let exponent_bias = <$fty>::exponent_bias(); + + let n = <$ity>::bits(); + let (s, a) = i.extract_sign(); + let mut a = a; + + // number of significant digits + let sd = n - a.leading_zeros(); + + // exponent + let mut e = sd - 1; + + if <$ity>::bits() < mant_dig { + return <$fty>::from_parts(s, + (e + exponent_bias) as <$fty as Float>::Int, + (a as <$fty as Float>::Int) << (mant_dig - e - 1)) + } + + a = if sd > mant_dig { + /* start: 0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx + * finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR + * 12345678901234567890123456 + * 1 = msb 1 bit + * P = bit MANT_DIG-1 bits to the right of 1 + * Q = bit MANT_DIG bits to the right of 1 + * R = "or" of all bits to the right of Q + */ + let mant_dig_plus_one = mant_dig + 1; + let mant_dig_plus_two = mant_dig + 2; + a = if sd == mant_dig_plus_one { + a << 1 + } else if sd == mant_dig_plus_two { + a + } else { + (a >> (sd - mant_dig_plus_two)) as <$ity as Int>::UnsignedInt | + ((a & <$ity as Int>::UnsignedInt::max_value()).wrapping_shl((n + mant_dig_plus_two) - sd) != 0) as <$ity as Int>::UnsignedInt + }; + + /* finish: */ + a |= ((a & 4) != 0) as <$ity as Int>::UnsignedInt; /* Or P into R */ + a += 1; /* round - this step may add a significant bit */ + a >>= 2; /* dump Q and R */ + + /* a is now rounded to mant_dig or mant_dig+1 bits */ + if (a & (1 << mant_dig)) != 0 { + a >>= 1; e += 1; + } + a + /* a is now rounded to mant_dig bits */ + } else { + a.wrapping_shl(mant_dig - sd) + /* a is now rounded to mant_dig bits */ + }; + + <$fty>::from_parts(s, + (e + exponent_bias) as <$fty as Float>::Int, + a as <$fty as Float>::Int) + }) +} + +intrinsics! { + #[arm_aeabi_alias = __aeabi_i2f] + pub extern "C" fn __floatsisf(i: i32) -> f32 { + int_to_float!(i, i32, f32) + } + + #[arm_aeabi_alias = __aeabi_i2d] + pub extern "C" fn __floatsidf(i: i32) -> f64 { + int_to_float!(i, i32, f64) + } + + #[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))] + #[arm_aeabi_alias = __aeabi_l2d] + pub extern "C" fn __floatdidf(i: i64) -> f64 { + // On x86_64 LLVM will use native instructions for this conversion, we + // can just do it directly + if cfg!(target_arch = "x86_64") { + i as f64 + } else { + int_to_float!(i, i64, f64) + } + } + + #[unadjusted_on_win64] + pub extern "C" fn __floattisf(i: i128) -> f32 { + int_to_float!(i, i128, f32) + } + + #[unadjusted_on_win64] + pub extern "C" fn __floattidf(i: i128) -> f64 { + int_to_float!(i, i128, f64) + } + + #[arm_aeabi_alias = __aeabi_ui2f] + pub extern "C" fn __floatunsisf(i: u32) -> f32 { + int_to_float!(i, u32, f32) + } + + #[arm_aeabi_alias = __aeabi_ui2d] + pub extern "C" fn __floatunsidf(i: u32) -> f64 { + int_to_float!(i, u32, f64) + } + + #[use_c_shim_if(all(not(target_env = "msvc"), + any(target_arch = "x86", + all(not(windows), target_arch = "x86_64"))))] + #[arm_aeabi_alias = __aeabi_ul2d] + pub extern "C" fn __floatundidf(i: u64) -> f64 { + int_to_float!(i, u64, f64) + } + + #[unadjusted_on_win64] + pub extern "C" fn __floatuntisf(i: u128) -> f32 { + int_to_float!(i, u128, f32) + } + + #[unadjusted_on_win64] + pub extern "C" fn __floatuntidf(i: u128) -> f64 { + int_to_float!(i, u128, f64) + } +} + +#[derive(PartialEq)] +enum Sign { + Positive, + Negative +} + +macro_rules! float_to_int { + ($f:expr, $fty:ty, $ity:ty) => ({ + let f = $f; + let fixint_min = <$ity>::min_value(); + let fixint_max = <$ity>::max_value(); + let fixint_bits = <$ity>::bits() as usize; + let fixint_unsigned = fixint_min == 0; + + let sign_bit = <$fty>::sign_mask(); + let significand_bits = <$fty>::significand_bits() as usize; + let exponent_bias = <$fty>::exponent_bias() as usize; + //let exponent_max = <$fty>::exponent_max() as usize; + + // Break a into sign, exponent, significand + let a_rep = <$fty>::repr(f); + let a_abs = a_rep & !sign_bit; + + // this is used to work around -1 not being available for unsigned + let sign = if (a_rep & sign_bit) == 0 { Sign::Positive } else { Sign::Negative }; + let mut exponent = (a_abs >> significand_bits) as usize; + let significand = (a_abs & <$fty>::significand_mask()) | <$fty>::implicit_bit(); + + // if < 1 or unsigned & negative + if exponent < exponent_bias || + fixint_unsigned && sign == Sign::Negative { + return 0 + } + exponent -= exponent_bias; + + // If the value is infinity, saturate. + // If the value is too large for the integer type, 0. + if exponent >= (if fixint_unsigned {fixint_bits} else {fixint_bits -1}) { + return if sign == Sign::Positive {fixint_max} else {fixint_min} + } + // If 0 <= exponent < significand_bits, right shift to get the result. + // Otherwise, shift left. + // (sign - 1) will never overflow as negative signs are already returned as 0 for unsigned + let r = if exponent < significand_bits { + (significand >> (significand_bits - exponent)) as $ity + } else { + (significand as $ity) << (exponent - significand_bits) + }; + + if sign == Sign::Negative { + (!r).wrapping_add(1) + } else { + r + } + }) +} + +intrinsics! { + #[arm_aeabi_alias = __aeabi_f2iz] + pub extern "C" fn __fixsfsi(f: f32) -> i32 { + float_to_int!(f, f32, i32) + } + + #[arm_aeabi_alias = __aeabi_f2lz] + pub extern "C" fn __fixsfdi(f: f32) -> i64 { + float_to_int!(f, f32, i64) + } + + #[unadjusted_on_win64] + pub extern "C" fn __fixsfti(f: f32) -> i128 { + float_to_int!(f, f32, i128) + } + + #[arm_aeabi_alias = __aeabi_d2iz] + pub extern "C" fn __fixdfsi(f: f64) -> i32 { + float_to_int!(f, f64, i32) + } + + #[arm_aeabi_alias = __aeabi_d2lz] + pub extern "C" fn __fixdfdi(f: f64) -> i64 { + float_to_int!(f, f64, i64) + } + + #[unadjusted_on_win64] + pub extern "C" fn __fixdfti(f: f64) -> i128 { + float_to_int!(f, f64, i128) + } + + #[arm_aeabi_alias = __aeabi_f2uiz] + pub extern "C" fn __fixunssfsi(f: f32) -> u32 { + float_to_int!(f, f32, u32) + } + + #[arm_aeabi_alias = __aeabi_f2ulz] + pub extern "C" fn __fixunssfdi(f: f32) -> u64 { + float_to_int!(f, f32, u64) + } + + #[unadjusted_on_win64] + pub extern "C" fn __fixunssfti(f: f32) -> u128 { + float_to_int!(f, f32, u128) + } + + #[arm_aeabi_alias = __aeabi_d2uiz] + pub extern "C" fn __fixunsdfsi(f: f64) -> u32 { + float_to_int!(f, f64, u32) + } + + #[arm_aeabi_alias = __aeabi_d2ulz] + pub extern "C" fn __fixunsdfdi(f: f64) -> u64 { + float_to_int!(f, f64, u64) + } + + #[unadjusted_on_win64] + pub extern "C" fn __fixunsdfti(f: f64) -> u128 { + float_to_int!(f, f64, u128) + } +} diff --git a/src/libcompiler_builtins/src/float/mod.rs b/src/libcompiler_builtins/src/float/mod.rs new file mode 100644 index 0000000000..46e3e5d958 --- /dev/null +++ b/src/libcompiler_builtins/src/float/mod.rs @@ -0,0 +1,156 @@ +use core::mem; + +pub mod conv; +pub mod add; +pub mod pow; +pub mod sub; + +/// Trait for some basic operations on floats +pub trait Float: Sized + Copy { + /// A uint of the same with as the float + type Int; + + /// Returns the bitwidth of the float type + fn bits() -> u32; + + /// Returns the bitwidth of the significand + fn significand_bits() -> u32; + + /// Returns the bitwidth of the exponent + fn exponent_bits() -> u32 { + Self::bits() - Self::significand_bits() - 1 + } + /// Returns the maximum value of the exponent + fn exponent_max() -> u32 { + (1 << Self::exponent_bits()) - 1 + } + + /// Returns the exponent bias value + fn exponent_bias() -> u32 { + Self::exponent_max() >> 1 + } + + /// Returns a mask for the sign bit + fn sign_mask() -> Self::Int; + + /// Returns a mask for the significand + fn significand_mask() -> Self::Int; + + // Returns the implicit bit of the float format + fn implicit_bit() -> Self::Int; + + /// Returns a mask for the exponent + fn exponent_mask() -> Self::Int; + + /// Returns `self` transmuted to `Self::Int` + fn repr(self) -> Self::Int; + + #[cfg(test)] + /// Checks if two floats have the same bit representation. *Except* for NaNs! NaN can be + /// represented in multiple different ways. This method returns `true` if two NaNs are + /// compared. + fn eq_repr(self, rhs: Self) -> bool; + + /// Returns a `Self::Int` transmuted back to `Self` + fn from_repr(a: Self::Int) -> Self; + + /// Constructs a `Self` from its parts. Inputs are treated as bits and shifted into position. + fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self; + + /// Returns (normalized exponent, normalized significand) + fn normalize(significand: Self::Int) -> (i32, Self::Int); +} + +// FIXME: Some of this can be removed if RFC Issue #1424 is resolved +// https://github.com/rust-lang/rfcs/issues/1424 +impl Float for f32 { + type Int = u32; + fn bits() -> u32 { + 32 + } + fn significand_bits() -> u32 { + 23 + } + fn implicit_bit() -> Self::Int { + 1 << Self::significand_bits() + } + fn sign_mask() -> Self::Int { + 1 << (Self::bits() - 1) + } + fn significand_mask() -> Self::Int { + (1 << Self::significand_bits()) - 1 + } + fn exponent_mask() -> Self::Int { + !(Self::sign_mask() | Self::significand_mask()) + } + fn repr(self) -> Self::Int { + unsafe { mem::transmute(self) } + } + #[cfg(test)] + fn eq_repr(self, rhs: Self) -> bool { + if self.is_nan() && rhs.is_nan() { + true + } else { + self.repr() == rhs.repr() + } + } + fn from_repr(a: Self::Int) -> Self { + unsafe { mem::transmute(a) } + } + fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self { + Self::from_repr(((sign as Self::Int) << (Self::bits() - 1)) | + ((exponent << Self::significand_bits()) & Self::exponent_mask()) | + (significand & Self::significand_mask())) + } + fn normalize(significand: Self::Int) -> (i32, Self::Int) { + let shift = significand.leading_zeros() + .wrapping_sub((1u32 << Self::significand_bits()).leading_zeros()); + (1i32.wrapping_sub(shift as i32), significand << shift as Self::Int) + } +} +impl Float for f64 { + type Int = u64; + fn bits() -> u32 { + 64 + } + fn significand_bits() -> u32 { + 52 + } + // Returns the implicit bit of the float format + fn implicit_bit() -> Self::Int { + 1 << Self::significand_bits() + } + fn sign_mask() -> Self::Int { + 1 << (Self::bits() - 1) + } + fn significand_mask() -> Self::Int { + (1 << Self::significand_bits()) - 1 + } + fn exponent_mask() -> Self::Int { + !(Self::sign_mask() | Self::significand_mask()) + } + fn repr(self) -> Self::Int { + unsafe { mem::transmute(self) } + } + #[cfg(test)] + fn eq_repr(self, rhs: Self) -> bool { + if self.is_nan() && rhs.is_nan() { + true + } else { + self.repr() == rhs.repr() + } + } + fn from_repr(a: Self::Int) -> Self { + unsafe { mem::transmute(a) } + } + fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self { + Self::from_repr(((sign as Self::Int) << (Self::bits() - 1)) | + ((exponent << Self::significand_bits()) & Self::exponent_mask()) | + (significand & Self::significand_mask())) + } + fn normalize(significand: Self::Int) -> (i32, Self::Int) { + let shift = significand.leading_zeros() + .wrapping_sub((1u64 << Self::significand_bits()).leading_zeros()); + (1i32.wrapping_sub(shift as i32), significand << shift as Self::Int) + } +} diff --git a/src/libcompiler_builtins/src/float/pow.rs b/src/libcompiler_builtins/src/float/pow.rs new file mode 100644 index 0000000000..bc15dc0888 --- /dev/null +++ b/src/libcompiler_builtins/src/float/pow.rs @@ -0,0 +1,36 @@ +use int::Int; + +/// Returns `a` raised to the power `b` +macro_rules! pow { + ($a: expr, $b: expr) => ({ + let (mut a, mut b) = ($a, $b); + let recip = b < 0; + let mut r = 1.0; + loop { + if (b & 1) != 0 { + r *= a; + } + b = b.aborting_div(2); + if b == 0 { + break; + } + a *= a; + } + + if recip { + 1.0 / r + } else { + r + } + }) +} + +intrinsics! { + pub extern "C" fn __powisf2(a: f32, b: i32) -> f32 { + pow!(a, b) + } + + pub extern "C" fn __powidf2(a: f64, b: i32) -> f64 { + pow!(a, b) + } +} diff --git a/src/libcompiler_builtins/src/float/sub.rs b/src/libcompiler_builtins/src/float/sub.rs new file mode 100644 index 0000000000..4fa436db61 --- /dev/null +++ b/src/libcompiler_builtins/src/float/sub.rs @@ -0,0 +1,13 @@ +use float::Float; + +intrinsics! { + #[arm_aeabi_alias = __aeabi_fsub] + pub extern "C" fn __subsf3(a: f32, b: f32) -> f32 { + a + f32::from_repr(b.repr() ^ f32::sign_mask()) + } + + #[arm_aeabi_alias = __aeabi_dsub] + pub extern "C" fn __subdf3(a: f64, b: f64) -> f64 { + a + f64::from_repr(b.repr() ^ f64::sign_mask()) + } +} diff --git a/src/libcompiler_builtins/src/int/mod.rs b/src/libcompiler_builtins/src/int/mod.rs new file mode 100644 index 0000000000..0334a4acb8 --- /dev/null +++ b/src/libcompiler_builtins/src/int/mod.rs @@ -0,0 +1,246 @@ +use core::ops; + +macro_rules! hty { + ($ty:ty) => { + <$ty as LargeInt>::HighHalf + } +} + +macro_rules! os_ty { + ($ty:ty) => { + <$ty as Int>::OtherSign + } +} + +pub mod mul; +pub mod sdiv; +pub mod shift; +pub mod udiv; + +/// Trait for some basic operations on integers +pub trait Int: + Copy + + PartialEq + + PartialOrd + + ops::AddAssign + + ops::Add + + ops::Sub + + ops::Div + + ops::Shl + + ops::Shr + + ops::BitOr + + ops::BitXor + + ops::BitAnd + + ops::BitAndAssign + + ops::Not + +{ + /// Type with the same width but other signedness + type OtherSign: Int; + /// Unsigned version of Self + type UnsignedInt: Int; + + /// Returns the bitwidth of the int type + fn bits() -> u32; + + fn zero() -> Self; + fn one() -> Self; + + /// Extracts the sign from self and returns a tuple. + /// + /// # Examples + /// + /// ```rust,ignore + /// let i = -25_i32; + /// let (sign, u) = i.extract_sign(); + /// assert_eq!(sign, true); + /// assert_eq!(u, 25_u32); + /// ``` + fn extract_sign(self) -> (bool, Self::UnsignedInt); + + fn unsigned(self) -> Self::UnsignedInt; + fn from_unsigned(unsigned: Self::UnsignedInt) -> Self; + + // copied from primitive integers, but put in a trait + fn max_value() -> Self; + fn min_value() -> Self; + fn wrapping_add(self, other: Self) -> Self; + fn wrapping_mul(self, other: Self) -> Self; + fn wrapping_sub(self, other: Self) -> Self; + fn aborting_div(self, other: Self) -> Self; + fn aborting_rem(self, other: Self) -> Self; +} + +fn unwrap(t: Option) -> T { + match t { + Some(t) => t, + None => ::abort(), + } +} + +macro_rules! int_impl { + ($ity:ty, $uty:ty, $bits:expr) => { + impl Int for $uty { + type OtherSign = $ity; + type UnsignedInt = $uty; + + fn zero() -> Self { + 0 + } + + fn one() -> Self { + 1 + } + + fn bits() -> u32 { + $bits + } + + fn extract_sign(self) -> (bool, $uty) { + (false, self) + } + + fn unsigned(self) -> $uty { + self + } + + fn from_unsigned(me: $uty) -> Self { + me + } + + fn max_value() -> Self { + ::max_value() + } + + fn min_value() -> Self { + ::min_value() + } + + fn wrapping_add(self, other: Self) -> Self { + ::wrapping_add(self, other) + } + + fn wrapping_mul(self, other: Self) -> Self { + ::wrapping_mul(self, other) + } + + fn wrapping_sub(self, other: Self) -> Self { + ::wrapping_sub(self, other) + } + + fn aborting_div(self, other: Self) -> Self { + unwrap(::checked_div(self, other)) + } + + fn aborting_rem(self, other: Self) -> Self { + unwrap(::checked_rem(self, other)) + } + } + + impl Int for $ity { + type OtherSign = $uty; + type UnsignedInt = $uty; + + fn bits() -> u32 { + $bits + } + + fn zero() -> Self { + 0 + } + + fn one() -> Self { + 1 + } + + fn extract_sign(self) -> (bool, $uty) { + if self < 0 { + (true, (!(self as $uty)).wrapping_add(1)) + } else { + (false, self as $uty) + } + } + + fn unsigned(self) -> $uty { + self as $uty + } + + fn from_unsigned(me: $uty) -> Self { + me as $ity + } + + fn max_value() -> Self { + ::max_value() + } + + fn min_value() -> Self { + ::min_value() + } + + fn wrapping_add(self, other: Self) -> Self { + ::wrapping_add(self, other) + } + + fn wrapping_mul(self, other: Self) -> Self { + ::wrapping_mul(self, other) + } + + fn wrapping_sub(self, other: Self) -> Self { + ::wrapping_sub(self, other) + } + + fn aborting_div(self, other: Self) -> Self { + unwrap(::checked_div(self, other)) + } + + fn aborting_rem(self, other: Self) -> Self { + unwrap(::checked_rem(self, other)) + } + } + } +} + +int_impl!(i32, u32, 32); +int_impl!(i64, u64, 64); +int_impl!(i128, u128, 128); + +/// Trait to convert an integer to/from smaller parts +pub trait LargeInt: Int { + type LowHalf: Int; + type HighHalf: Int; + + fn low(self) -> Self::LowHalf; + fn low_as_high(low: Self::LowHalf) -> Self::HighHalf; + fn high(self) -> Self::HighHalf; + fn high_as_low(low: Self::HighHalf) -> Self::LowHalf; + fn from_parts(low: Self::LowHalf, high: Self::HighHalf) -> Self; +} + +macro_rules! large_int { + ($ty:ty, $tylow:ty, $tyhigh:ty, $halfbits:expr) => { + impl LargeInt for $ty { + type LowHalf = $tylow; + type HighHalf = $tyhigh; + + fn low(self) -> $tylow { + self as $tylow + } + fn low_as_high(low: $tylow) -> $tyhigh { + low as $tyhigh + } + fn high(self) -> $tyhigh { + (self >> $halfbits) as $tyhigh + } + fn high_as_low(high: $tyhigh) -> $tylow { + high as $tylow + } + fn from_parts(low: $tylow, high: $tyhigh) -> $ty { + low as $ty | ((high as $ty) << $halfbits) + } + } + } +} + +large_int!(u64, u32, u32, 32); +large_int!(i64, u32, i32, 32); +large_int!(u128, u64, u64, 64); +large_int!(i128, u64, i64, 64); diff --git a/src/libcompiler_builtins/src/int/mul.rs b/src/libcompiler_builtins/src/int/mul.rs new file mode 100644 index 0000000000..98a8987e1d --- /dev/null +++ b/src/libcompiler_builtins/src/int/mul.rs @@ -0,0 +1,97 @@ +use core::ops; + +use int::LargeInt; +use int::Int; + +trait Mul: LargeInt { + fn mul(self, other: Self) -> Self { + let half_bits = Self::bits() / 4; + let lower_mask = !<::LowHalf>::zero() >> half_bits; + let mut low = (self.low() & lower_mask).wrapping_mul(other.low() & lower_mask); + let mut t = low >> half_bits; + low &= lower_mask; + t += (self.low() >> half_bits).wrapping_mul(other.low() & lower_mask); + low += (t & lower_mask) << half_bits; + let mut high = Self::low_as_high(t >> half_bits); + t = low >> half_bits; + low &= lower_mask; + t += (other.low() >> half_bits).wrapping_mul(self.low() & lower_mask); + low += (t & lower_mask) << half_bits; + high += Self::low_as_high(t >> half_bits); + high += Self::low_as_high((self.low() >> half_bits).wrapping_mul(other.low() >> half_bits)); + high = high.wrapping_add(self.high().wrapping_mul(Self::low_as_high(other.low()))) + .wrapping_add(Self::low_as_high(self.low()).wrapping_mul(other.high())); + Self::from_parts(low, high) + } +} + +impl Mul for u64 {} +impl Mul for i128 {} + +trait Mulo: Int + ops::Neg { + fn mulo(self, other: Self, overflow: &mut i32) -> Self { + *overflow = 0; + let result = self.wrapping_mul(other); + if self == Self::min_value() { + if other != Self::zero() && other != Self::one() { + *overflow = 1; + } + return result; + } + if other == Self::min_value() { + if self != Self::zero() && self != Self::one() { + *overflow = 1; + } + return result; + } + + let sa = self >> (Self::bits() - 1); + let abs_a = (self ^ sa) - sa; + let sb = other >> (Self::bits() - 1); + let abs_b = (other ^ sb) - sb; + let two = Self::one() + Self::one(); + if abs_a < two || abs_b < two { + return result; + } + if sa == sb { + if abs_a > Self::max_value().aborting_div(abs_b) { + *overflow = 1; + } + } else { + if abs_a > Self::min_value().aborting_div(-abs_b) { + *overflow = 1; + } + } + result + } +} + +impl Mulo for i32 {} +impl Mulo for i64 {} +impl Mulo for i128 {} + +intrinsics! { + #[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))] + #[arm_aeabi_alias = __aeabi_lmul] + pub extern "C" fn __muldi3(a: u64, b: u64) -> u64 { + a.mul(b) + } + + #[aapcs_on_arm] + pub extern "C" fn __multi3(a: i128, b: i128) -> i128 { + a.mul(b) + } + + pub extern "C" fn __mulosi4(a: i32, b: i32, oflow: &mut i32) -> i32 { + a.mulo(b, oflow) + } + + pub extern "C" fn __mulodi4(a: i64, b: i64, oflow: &mut i32) -> i64 { + a.mulo(b, oflow) + } + + #[unadjusted_on_win64] + pub extern "C" fn __muloti4(a: i128, b: i128, oflow: &mut i32) -> i128 { + a.mulo(b, oflow) + } +} diff --git a/src/libcompiler_builtins/src/int/sdiv.rs b/src/libcompiler_builtins/src/int/sdiv.rs new file mode 100644 index 0000000000..c949c3394d --- /dev/null +++ b/src/libcompiler_builtins/src/int/sdiv.rs @@ -0,0 +1,99 @@ +use int::Int; + +trait Div: Int { + /// Returns `a / b` + fn div(self, other: Self) -> Self { + let s_a = self >> (Self::bits() - 1); + let s_b = other >> (Self::bits() - 1); + // NOTE it's OK to overflow here because of the `as $uty` cast below + // This whole operation is computing the absolute value of the inputs + // So some overflow will happen when dealing with e.g. `i64::MIN` + // where the absolute value is `(-i64::MIN) as u64` + let a = (self ^ s_a).wrapping_sub(s_a); + let b = (other ^ s_b).wrapping_sub(s_b); + let s = s_a ^ s_b; + + let r = a.unsigned().aborting_div(b.unsigned()); + (Self::from_unsigned(r) ^ s) - s + } +} + +impl Div for i32 {} +impl Div for i64 {} +impl Div for i128 {} + +trait Mod: Int { + /// Returns `a % b` + fn mod_(self, other: Self) -> Self { + let s = other >> (Self::bits() - 1); + // NOTE(wrapping_sub) see comment in the `div` + let b = (other ^ s).wrapping_sub(s); + let s = self >> (Self::bits() - 1); + let a = (self ^ s).wrapping_sub(s); + + let r = a.unsigned().aborting_rem(b.unsigned()); + (Self::from_unsigned(r) ^ s) - s + } +} + +impl Mod for i32 {} +impl Mod for i64 {} +impl Mod for i128 {} + +trait Divmod: Int { + /// Returns `a / b` and sets `*rem = n % d` + fn divmod(self, other: Self, rem: &mut Self, div: F) -> Self + where F: Fn(Self, Self) -> Self, + { + let r = div(self, other); + // NOTE won't overflow because it's using the result from the + // previous division + *rem = self - r.wrapping_mul(other); + r + } +} + +impl Divmod for i32 {} +impl Divmod for i64 {} + +intrinsics! { + #[arm_aeabi_alias = __aeabi_idiv] + pub extern "C" fn __divsi3(a: i32, b: i32) -> i32 { + a.div(b) + } + + #[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))] + pub extern "C" fn __divdi3(a: i64, b: i64) -> i64 { + a.div(b) + } + + #[win64_128bit_abi_hack] + pub extern "C" fn __divti3(a: i128, b: i128) -> i128 { + a.div(b) + } + + #[use_c_shim_if(all(target_arch = "arm", not(target_os = "ios")))] + pub extern "C" fn __modsi3(a: i32, b: i32) -> i32 { + a.mod_(b) + } + + #[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))] + pub extern "C" fn __moddi3(a: i64, b: i64) -> i64 { + a.mod_(b) + } + + #[win64_128bit_abi_hack] + pub extern "C" fn __modti3(a: i128, b: i128) -> i128 { + a.mod_(b) + } + + #[use_c_shim_if(all(target_arch = "arm", not(target_os = "ios")))] + pub extern "C" fn __divmodsi4(a: i32, b: i32, rem: &mut i32) -> i32 { + a.divmod(b, rem, |a, b| __divsi3(a, b)) + } + + #[aapcs_on_arm] + pub extern "C" fn __divmoddi4(a: i64, b: i64, rem: &mut i64) -> i64 { + a.divmod(b, rem, |a, b| __divdi3(a, b)) + } +} diff --git a/src/libcompiler_builtins/src/int/shift.rs b/src/libcompiler_builtins/src/int/shift.rs new file mode 100644 index 0000000000..a9b6c05d3d --- /dev/null +++ b/src/libcompiler_builtins/src/int/shift.rs @@ -0,0 +1,97 @@ +use int::{Int, LargeInt}; + +trait Ashl: Int + LargeInt { + /// Returns `a << b`, requires `b < $ty::bits()` + fn ashl(self, offset: u32) -> Self + where Self: LargeInt::LowHalf>, + { + let half_bits = Self::bits() / 2; + if offset & half_bits != 0 { + Self::from_parts(Int::zero(), self.low() << (offset - half_bits)) + } else if offset == 0 { + self + } else { + Self::from_parts(self.low() << offset, + (self.high() << offset) | + (self.low() >> (half_bits - offset))) + } + } +} + +impl Ashl for u64 {} +impl Ashl for u128 {} + +trait Ashr: Int + LargeInt { + /// Returns arithmetic `a >> b`, requires `b < $ty::bits()` + fn ashr(self, offset: u32) -> Self + where Self: LargeInt::HighHalf as Int>::UnsignedInt>, + { + let half_bits = Self::bits() / 2; + if offset & half_bits != 0 { + Self::from_parts((self.high() >> (offset - half_bits)).unsigned(), + self.high() >> (half_bits - 1)) + } else if offset == 0 { + self + } else { + let high_unsigned = self.high().unsigned(); + Self::from_parts((high_unsigned << (half_bits - offset)) | (self.low() >> offset), + self.high() >> offset) + } + } +} + +impl Ashr for i64 {} +impl Ashr for i128 {} + +trait Lshr: Int + LargeInt { + /// Returns logical `a >> b`, requires `b < $ty::bits()` + fn lshr(self, offset: u32) -> Self + where Self: LargeInt::LowHalf>, + { + let half_bits = Self::bits() / 2; + if offset & half_bits != 0 { + Self::from_parts(self.high() >> (offset - half_bits), Int::zero()) + } else if offset == 0 { + self + } else { + Self::from_parts((self.high() << (half_bits - offset)) | + (self.low() >> offset), + self.high() >> offset) + } + } +} + +impl Lshr for u64 {} +impl Lshr for u128 {} + +intrinsics! { + #[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))] + #[arm_aeabi_alias = __aeabi_llsl] + pub extern "C" fn __ashldi3(a: u64, b: u32) -> u64 { + a.ashl(b) + } + + pub extern "C" fn __ashlti3(a: u128, b: u32) -> u128 { + a.ashl(b) + } + + #[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))] + #[arm_aeabi_alias = __aeabi_lasr] + pub extern "C" fn __ashrdi3(a: i64, b: u32) -> i64 { + a.ashr(b) + } + + pub extern "C" fn __ashrti3(a: i128, b: u32) -> i128 { + a.ashr(b) + } + + #[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))] + #[arm_aeabi_alias = __aeabi_llsr] + pub extern "C" fn __lshrdi3(a: u64, b: u32) -> u64 { + a.lshr(b) + } + + pub extern "C" fn __lshrti3(a: u128, b: u32) -> u128 { + a.lshr(b) + } +} diff --git a/src/libcompiler_builtins/src/int/udiv.rs b/src/libcompiler_builtins/src/int/udiv.rs new file mode 100644 index 0000000000..de276147e3 --- /dev/null +++ b/src/libcompiler_builtins/src/int/udiv.rs @@ -0,0 +1,262 @@ +use int::{Int, LargeInt}; + +macro_rules! udivmod_inner { + ($n:expr, $d:expr, $rem:expr, $ty:ty) => {{ + let (n, d, rem) = ($n, $d, $rem); + // NOTE X is unknown, K != 0 + if n.high() == 0 { + if d.high() == 0 { + // 0 X + // --- + // 0 X + + if let Some(rem) = rem { + *rem = <$ty>::from(n.low().aborting_rem(d.low())); + } + return <$ty>::from(n.low().aborting_div(d.low())) + } else { + // 0 X + // --- + // K X + if let Some(rem) = rem { + *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 + // NOTE This should be unreachable in safe Rust because the program will panic before + // this intrinsic is called + ::abort(); + } + + if n.low() == 0 { + // K 0 + // --- + // K 0 + if let Some(rem) = rem { + *rem = <$ty>::from_parts(0, n.high().aborting_rem(d.high())); + } + return <$ty>::from(n.high().aborting_div(d.high())) + } + + // K K + // --- + // K 0 + + if d.high().is_power_of_two() { + if let Some(rem) = rem { + *rem = <$ty>::from_parts(n.low(), n.high() & (d.high() - 1)); + } + return <$ty>::from(n.high() >> d.high().trailing_zeros()); + } + + sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros()); + + // D > N + if sr > ::bits() - 2 { + if let Some(rem) = rem { + *rem = n; + } + return 0; + } + + sr += 1; + + // 1 <= sr <= ::bits() - 1 + q = n << (<$ty>::bits() - sr); + r = n >> sr; + } else if d.high() == 0 { + // K X + // --- + // 0 K + if d.low().is_power_of_two() { + if let Some(rem) = rem { + *rem = <$ty>::from(n.low() & (d.low() - 1)); + } + + if d.low() == 1 { + return n; + } else { + let sr = d.low().trailing_zeros(); + return n >> sr; + }; + } + + sr = 1 + ::bits() + d.low().leading_zeros() - n.high().leading_zeros(); + + // 2 <= sr <= u64::bits() - 1 + q = n << (<$ty>::bits() - sr); + r = n >> sr; + } else { + // K X + // --- + // K K + sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros()); + + // D > N + if sr > ::bits() - 1 { + if let Some(rem) = rem { + *rem = n; + } + return 0; + } + + sr += 1; + + // 1 <= sr <= ::bits() + q = n << (<$ty>::bits() - sr); + r = n >> 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; + + for _ in 0..sr { + // r:q = ((r:q) << 1) | carry + r = (r << 1) | (q >> (<$ty>::bits() - 1)); + q = (q << 1) | carry as $ty; + + // carry = 0 + // if r >= d { + // r -= d; + // carry = 1; + // } + let s = (d.wrapping_sub(r).wrapping_sub(1)) as os_ty!($ty) >> (<$ty>::bits() - 1); + carry = (s & 1) as hty!($ty); + r -= d & s as $ty; + } + + if let Some(rem) = rem { + *rem = r; + } + (q << 1) | carry as $ty + }} +} + +intrinsics! { + #[arm_aeabi_alias = __aeabi_uidiv] + /// Returns `n / d` + pub extern "C" fn __udivsi3(n: u32, d: u32) -> u32 { + // Special cases + if d == 0 { + // NOTE This should be unreachable in safe Rust because the program will panic before + // this intrinsic is called + ::abort(); + } + + if n == 0 { + return 0; + } + + let mut sr = d.leading_zeros().wrapping_sub(n.leading_zeros()); + + // d > n + if sr > u32::bits() - 1 { + return 0; + } + + // d == 1 + if sr == u32::bits() - 1 { + return n; + } + + sr += 1; + + // 1 <= sr <= u32::bits() - 1 + let mut q = n << (u32::bits() - sr); + let mut r = n >> sr; + + let mut carry = 0; + for _ in 0..sr { + // r:q = ((r:q) << 1) | carry + r = (r << 1) | (q >> (u32::bits() - 1)); + q = (q << 1) | carry; + + // carry = 0; + // if r > d { + // r -= d; + // carry = 1; + // } + + let s = (d.wrapping_sub(r).wrapping_sub(1)) as i32 >> (u32::bits() - 1); + carry = (s & 1) as u32; + r -= d & s as u32; + } + + (q << 1) | carry + } + + #[use_c_shim_if(all(target_arch = "arm", not(target_os = "ios")))] + /// Returns `n % d` + pub extern "C" fn __umodsi3(n: u32, d: u32) -> u32 { + let q = __udivsi3(n, d); + n - q * d + } + + #[use_c_shim_if(all(target_arch = "arm", + not(target_os = "ios"), + not(thumbv6m)))] + /// Returns `n / d` and sets `*rem = n % d` + pub extern "C" fn __udivmodsi4(n: u32, d: u32, rem: Option<&mut u32>) -> u32 { + let q = __udivsi3(n, d); + if let Some(rem) = rem { + *rem = n - (q * d); + } + q + } + + #[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))] + /// Returns `n / d` + pub extern "C" fn __udivdi3(n: u64, d: u64) -> u64 { + __udivmoddi4(n, d, None) + } + + #[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))] + /// Returns `n % d` + pub extern "C" fn __umoddi3(n: u64, d: u64) -> u64 { + let mut rem = 0; + __udivmoddi4(n, d, Some(&mut rem)); + rem + } + + #[win64_128bit_abi_hack] + /// Returns `n / d` + pub extern "C" fn __udivti3(n: u128, d: u128) -> u128 { + __udivmodti4(n, d, None) + } + + #[win64_128bit_abi_hack] + /// Returns `n % d` + pub extern "C" fn __umodti3(n: u128, d: u128) -> u128 { + let mut rem = 0; + __udivmodti4(n, d, Some(&mut rem)); + rem + } + + /// Returns `n / d` and sets `*rem = n % d` + pub extern "C" fn __udivmoddi4(n: u64, d: u64, rem: Option<&mut u64>) -> u64 { + udivmod_inner!(n, d, rem, u64) + } + + #[win64_128bit_abi_hack] + /// Returns `n / d` and sets `*rem = n % d` + pub extern "C" fn __udivmodti4(n: u128, + d: u128, + rem: Option<&mut u128>) -> u128 { + udivmod_inner!(n, d, rem, u128) + } +} diff --git a/src/libcompiler_builtins/src/lib.rs b/src/libcompiler_builtins/src/lib.rs new file mode 100644 index 0000000000..b8cf83e212 --- /dev/null +++ b/src/libcompiler_builtins/src/lib.rs @@ -0,0 +1,57 @@ +#![cfg_attr(not(stage0), deny(warnings))] +#![cfg_attr(not(test), no_std)] +#![cfg_attr(feature = "compiler-builtins", compiler_builtins)] +#![crate_name = "compiler_builtins"] +#![crate_type = "rlib"] +#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", + html_favicon_url = "https://doc.rust-lang.org/favicon.ico", + html_root_url = "https://doc.rust-lang.org/nightly/", + html_playground_url = "https://play.rust-lang.org/", + test(attr(deny(warnings))))] +#![feature(asm)] +#![feature(compiler_builtins)] +#![feature(core_intrinsics)] +#![feature(naked_functions)] +#![feature(staged_api)] +#![feature(i128_type)] +#![feature(repr_simd)] +#![feature(abi_unadjusted)] +#![feature(linkage)] +#![allow(unused_features)] +#![no_builtins] +#![unstable(feature = "compiler_builtins_lib", + reason = "Compiler builtins. Will never become stable.", + issue = "0")] + +// We disable #[no_mangle] for tests so that we can verify the test results +// against the native compiler-rt implementations of the builtins. + +// NOTE cfg(all(feature = "c", ..)) indicate that compiler-rt provides an arch optimized +// implementation of that intrinsic and we'll prefer to use that + +// NOTE(aapcs, aeabi, arm) ARM targets use intrinsics named __aeabi_* instead of the intrinsics +// that follow "x86 naming convention" (e.g. addsf3). Those aeabi intrinsics must adhere to the +// AAPCS calling convention (`extern "aapcs"`) because that's how LLVM will call them. + +#[cfg(test)] +extern crate core; + +fn abort() -> ! { + unsafe { core::intrinsics::abort() } +} + +#[macro_use] +mod macros; + +pub mod int; +pub mod float; + +pub mod mem; + +#[cfg(target_arch = "arm")] +pub mod arm; + +#[cfg(target_arch = "x86_64")] +pub mod x86_64; + +pub mod probestack; diff --git a/src/libcompiler_builtins/src/macros.rs b/src/libcompiler_builtins/src/macros.rs new file mode 100644 index 0000000000..f6d7db7093 --- /dev/null +++ b/src/libcompiler_builtins/src/macros.rs @@ -0,0 +1,282 @@ +//! Macros shared throughout the compiler-builtins implementation + +/// The "main macro" used for defining intrinsics. +/// +/// The compiler-builtins library is super platform-specific with tons of crazy +/// little tweaks for various platforms. As a result it *could* involve a lot of +/// #[cfg] and macro soup, but the intention is that this macro alleviates a lot +/// of that complexity. Ideally this macro has all the weird ABI things +/// platforms need and elsewhere in this library it just looks like normal Rust +/// code. +/// +/// This macro is structured to be invoked with a bunch of functions that looks +/// like: +/// +/// intrinsics! { +/// pub extern "C" fn foo(a: i32) -> u32 { +/// // ... +/// } +/// +/// #[nonstandard_attribute] +/// pub extern "C" fn bar(a: i32) -> u32 { +/// // ... +/// } +/// } +/// +/// Each function is defined in a manner that looks like a normal Rust function. +/// The macro then accepts a few nonstandard attributes that can decorate +/// various functions. Each of the attributes is documented below with what it +/// can do, and each of them slightly tweaks how further expansion happens. +/// +/// A quick overview of attributes supported right now are: +/// +/// * `use_c_shim_if` - takes a #[cfg] directive and falls back to the +/// C-compiled version if `feature = "c"` is specified. +/// * `aapcs_on_arm` - forces the ABI of the function to be `"aapcs"` on ARM and +/// the specified ABI everywhere else. +/// * `unadjusted_on_win64` - like `aapcs_on_arm` this switches to the +/// `"unadjusted"` abi on Win64 and the specified abi elsewhere. +/// * `win64_128bit_abi_hack` - this attribute is used for 128-bit integer +/// intrinsics where the ABI is slightly tweaked on Windows platforms, but +/// it's a normal ABI elsewhere for returning a 128 bit integer. +/// * `arm_aeabi_alias` - handles the "aliasing" of various intrinsics on ARM +/// their otherwise typical names to other prefixed ones. +/// +macro_rules! intrinsics { + () => (); + + // Right now there's a bunch of architecture-optimized intrinsics in the + // stock compiler-rt implementation. Not all of these have been ported over + // to Rust yet so when the `c` feature of this crate is enabled we fall back + // to the architecture-specific versions which should be more optimized. The + // purpose of this macro is to easily allow specifying this. + // + // The argument to `use_c_shim_if` is a `#[cfg]` directive which, when true, + // will cause this crate's exported version of `$name` to just redirect to + // the C implementation. No symbol named `$name` will be in the object file + // for this crate itself. + // + // When the `#[cfg]` directive is false, or when the `c` feature is + // disabled, the provided implementation is used instead. + ( + #[use_c_shim_if($($cfg_clause:tt)*)] + $(#[$($attr:tt)*])* + pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { + $($body:tt)* + } + + $($rest:tt)* + ) => ( + + #[cfg(all(feature = "c", $($cfg_clause)*))] + pub extern $abi fn $name( $($argname: $ty),* ) -> $ret { + extern $abi { + fn $name($($argname: $ty),*) -> $ret; + } + unsafe { + $name($($argname),*) + } + } + + #[cfg(not(all(feature = "c", $($cfg_clause)*)))] + intrinsics! { + $(#[$($attr)*])* + pub extern $abi fn $name( $($argname: $ty),* ) -> $ret { + $($body)* + } + } + + intrinsics!($($rest)*); + ); + + // We recognize the `#[aapcs_on_arm]` attribute here and generate the + // same intrinsic but force it to have the `"aapcs"` calling convention on + // ARM and `"C"` elsewhere. + ( + #[aapcs_on_arm] + $(#[$($attr:tt)*])* + pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { + $($body:tt)* + } + + $($rest:tt)* + ) => ( + #[cfg(target_arch = "arm")] + intrinsics! { + $(#[$($attr)*])* + pub extern "aapcs" fn $name( $($argname: $ty),* ) -> $ret { + $($body)* + } + } + + #[cfg(not(target_arch = "arm"))] + intrinsics! { + $(#[$($attr)*])* + pub extern $abi fn $name( $($argname: $ty),* ) -> $ret { + $($body)* + } + } + + intrinsics!($($rest)*); + ); + + // Like aapcs above we recognize an attribute for the "unadjusted" abi on + // win64 for some methods. + ( + #[unadjusted_on_win64] + $(#[$($attr:tt)*])* + pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { + $($body:tt)* + } + + $($rest:tt)* + ) => ( + #[cfg(all(windows, target_pointer_width = "64"))] + intrinsics! { + $(#[$($attr)*])* + pub extern "unadjusted" fn $name( $($argname: $ty),* ) -> $ret { + $($body)* + } + } + + #[cfg(not(all(windows, target_pointer_width = "64")))] + intrinsics! { + $(#[$($attr)*])* + pub extern $abi fn $name( $($argname: $ty),* ) -> $ret { + $($body)* + } + } + + intrinsics!($($rest)*); + ); + + // Some intrinsics on win64 which return a 128-bit integer have an.. unusual + // calling convention. That's managed here with this "abi hack" which alters + // the generated symbol's ABI. + // + // This will still define a function in this crate with the given name and + // signature, but the actual symbol for the intrinsic may have a slightly + // different ABI on win64. + ( + #[win64_128bit_abi_hack] + $(#[$($attr:tt)*])* + pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { + $($body:tt)* + } + + $($rest:tt)* + ) => ( + #[cfg(all(windows, target_pointer_width = "64"))] + $(#[$($attr)*])* + pub extern $abi fn $name( $($argname: $ty),* ) -> $ret { + $($body)* + } + + #[cfg(all(windows, target_pointer_width = "64"))] + pub mod $name { + + intrinsics! { + pub extern $abi fn $name( $($argname: $ty),* ) + -> ::macros::win64_128bit_abi_hack::U64x2 + { + let e: $ret = super::$name($($argname),*); + ::macros::win64_128bit_abi_hack::U64x2::from(e) + } + } + } + + #[cfg(not(all(windows, target_pointer_width = "64")))] + intrinsics! { + $(#[$($attr)*])* + pub extern $abi fn $name( $($argname: $ty),* ) -> $ret { + $($body)* + } + } + + intrinsics!($($rest)*); + ); + + // A bunch of intrinsics on ARM are aliased in the standard compiler-rt + // build under `__aeabi_*` aliases, and LLVM will call these instead of the + // original function. The aliasing here is used to generate these symbols in + // the object file. + ( + #[arm_aeabi_alias = $alias:ident] + $(#[$($attr:tt)*])* + pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { + $($body:tt)* + } + + $($rest:tt)* + ) => ( + #[cfg(target_arch = "arm")] + pub extern $abi fn $name( $($argname: $ty),* ) -> $ret { + $($body)* + } + + #[cfg(target_arch = "arm")] + pub mod $name { + intrinsics! { + pub extern "aapcs" fn $alias( $($argname: $ty),* ) -> $ret { + super::$name($($argname),*) + } + } + } + + #[cfg(not(target_arch = "arm"))] + intrinsics! { + $(#[$($attr)*])* + pub extern $abi fn $name( $($argname: $ty),* ) -> $ret { + $($body)* + } + } + + intrinsics!($($rest)*); + ); + + // This is the final catch-all rule. At this point we just generate an + // intrinsic with a conditional `#[no_mangle]` directive to avoid + // interfereing with duplicate symbols and whatnot during testing. + // + // After the intrinsic is defined we just continue with the rest of the + // input we were given. + ( + $(#[$($attr:tt)*])* + pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { + $($body:tt)* + } + + $($rest:tt)* + ) => ( + $(#[$($attr)*])* + #[cfg_attr(not(feature = "mangled-names"), no_mangle)] + pub extern $abi fn $name( $($argname: $ty),* ) -> $ret { + $($body)* + } + + intrinsics!($($rest)*); + ); +} + +// Hack for LLVM expectations for ABI on windows. This is used by the +// `#[win64_128bit_abi_hack]` attribute recognized above +#[cfg(all(windows, target_pointer_width="64"))] +pub mod win64_128bit_abi_hack { + #[repr(simd)] + pub struct U64x2(u64, u64); + + impl From for U64x2 { + fn from(i: i128) -> U64x2 { + use int::LargeInt; + let j = i as u128; + U64x2(j.low(), j.high()) + } + } + + impl From for U64x2 { + fn from(i: u128) -> U64x2 { + use int::LargeInt; + U64x2(i.low(), i.high()) + } + } +} diff --git a/src/libcompiler_builtins/src/mem.rs b/src/libcompiler_builtins/src/mem.rs new file mode 100644 index 0000000000..c56391c4d3 --- /dev/null +++ b/src/libcompiler_builtins/src/mem.rs @@ -0,0 +1,66 @@ +#[allow(warnings)] +#[cfg(target_pointer_width = "16")] +type c_int = i16; +#[allow(warnings)] +#[cfg(not(target_pointer_width = "16"))] +type c_int = i32; + +#[cfg_attr(all(feature = "mem", not(feature = "mangled-names")), no_mangle)] +pub unsafe extern "C" fn memcpy(dest: *mut u8, + src: *const u8, + n: usize) + -> *mut u8 { + let mut i = 0; + while i < n { + *dest.offset(i as isize) = *src.offset(i as isize); + i += 1; + } + dest +} + +#[cfg_attr(all(feature = "mem", not(feature = "mangled-names")), no_mangle)] +pub unsafe extern "C" fn memmove(dest: *mut u8, + src: *const u8, + n: usize) + -> *mut u8 { + if src < dest as *const u8 { + // copy from end + let mut i = n; + while i != 0 { + i -= 1; + *dest.offset(i as isize) = *src.offset(i as isize); + } + } else { + // copy from beginning + let mut i = 0; + while i < n { + *dest.offset(i as isize) = *src.offset(i as isize); + i += 1; + } + } + dest +} + +#[cfg_attr(all(feature = "mem", not(feature = "mangled-names")), no_mangle)] +pub unsafe extern "C" fn memset(s: *mut u8, c: c_int, n: usize) -> *mut u8 { + let mut i = 0; + while i < n { + *s.offset(i as isize) = c as u8; + i += 1; + } + s +} + +#[cfg_attr(all(feature = "mem", not(feature = "mangled-names")), no_mangle)] +pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 { + let mut i = 0; + while i < n { + let a = *s1.offset(i as isize); + let b = *s2.offset(i as isize); + if a != b { + return a as i32 - b as i32; + } + i += 1; + } + 0 +} diff --git a/src/libcompiler_builtins/src/probestack.rs b/src/libcompiler_builtins/src/probestack.rs new file mode 100644 index 0000000000..329e272651 --- /dev/null +++ b/src/libcompiler_builtins/src/probestack.rs @@ -0,0 +1,116 @@ +// 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. + +//! This module defines the `__rust_probestack` intrinsic which is used in the +//! implementation of "stack probes" on certain platforms. +//! +//! The purpose of a stack probe is to provide a static guarantee that if a +//! thread has a guard page then a stack overflow is guaranteed to hit that +//! guard page. If a function did not have a stack probe then there's a risk of +//! having a stack frame *larger* than the guard page, so a function call could +//! skip over the guard page entirely and then later hit maybe the heap or +//! another thread, possibly leading to security vulnerabilities such as [The +//! Stack Clash], for example. +//! +//! [The Stack Clash]: https://blog.qualys.com/securitylabs/2017/06/19/the-stack-clash +//! +//! The `__rust_probestack` is called in the prologue of functions whose stack +//! size is larger than the guard page, for example larger than 4096 bytes on +//! x86. This function is then responsible for "touching" all pages relevant to +//! the stack to ensure that that if any of them are the guard page we'll hit +//! them guaranteed. +//! +//! The precise ABI for how this function operates is defined by LLVM. There's +//! no real documentation as to what this is, so you'd basically need to read +//! the LLVM source code for reference. Often though the test cases can be +//! illuminating as to the ABI that's generated, or just looking at the output +//! of `llc`. +//! +//! Note that `#[naked]` is typically used here for the stack probe because the +//! ABI corresponds to no actual ABI. +//! +//! Finally it's worth noting that at the time of this writing LLVM only has +//! support for stack probes on x86 and x86_64. There's no support for stack +//! probes on any other architecture like ARM or PowerPC64. LLVM I'm sure would +//! be more than welcome to accept such a change! + +#![cfg(not(windows))] // Windows already has builtins to do this + +#[naked] +#[cfg_attr(not(feature = "mangled-names"), no_mangle)] +#[cfg(target_arch = "x86_64")] +pub unsafe extern fn __rust_probestack() { + // Our goal here is to touch each page between %rsp+8 and %rsp+8-%rax, + // ensuring that if any pages are unmapped we'll make a page fault. + // + // The ABI here is that the stack frame size is located in `%eax`. Upon + // return we're not supposed to modify `%esp` or `%eax`. + asm!(" + mov %rax,%r11 // duplicate %rax as we're clobbering %r11 + + // Main loop, taken in one page increments. We're decrementing rsp by + // a page each time until there's less than a page remaining. We're + // guaranteed that this function isn't called unless there's more than a + // page needed. + // + // Note that we're also testing against `8(%rsp)` to account for the 8 + // bytes pushed on the stack orginally with our return address. Using + // `8(%rsp)` simulates us testing the stack pointer in the caller's + // context. + 2: + sub $$0x1000,%rsp + test %rsp,8(%rsp) + sub $$0x1000,%r11 + cmp $$0x1000,%r11 + ja 2b + + // Finish up the last remaining stack space requested, getting the last + // bits out of r11 + sub %r11,%rsp + test %rsp,8(%rsp) + + // Restore the stack pointer to what it previously was when entering + // this function. The caller will readjust the stack pointer after we + // return. + add %rax,%rsp + + ret + "); + ::core::intrinsics::unreachable(); +} + +#[naked] +#[cfg_attr(not(feature = "mangled-names"), no_mangle)] +#[cfg(target_arch = "x86")] +pub unsafe extern fn __rust_probestack() { + // This is the same as x86_64 above, only translated for 32-bit sizes. Note + // that on Unix we're expected to restore everything as it was, this + // function basically can't tamper with anything. + // + // The ABI here is the same as x86_64, except everything is 32-bits large. + asm!(" + push %ecx + mov %eax,%ecx + 2: + sub $$0x1000,%esp + test %esp,8(%esp) + sub $$0x1000,%ecx + cmp $$0x1000,%ecx + ja 2b + + sub %ecx,%esp + test %esp,8(%esp) + + add %eax,%esp + pop %ecx + ret + "); + ::core::intrinsics::unreachable(); +} diff --git a/src/libcompiler_builtins/src/x86_64.rs b/src/libcompiler_builtins/src/x86_64.rs new file mode 100644 index 0000000000..64cc06c983 --- /dev/null +++ b/src/libcompiler_builtins/src/x86_64.rs @@ -0,0 +1,69 @@ +#![allow(unused_imports)] + +use core::intrinsics; + +// NOTE These functions are implemented using assembly because they using a custom +// calling convention which can't be implemented using a normal Rust function + +// NOTE These functions are never mangled as they are not tested against compiler-rt +// and mangling ___chkstk would break the `jmp ___chkstk` instruction in __alloca + +#[cfg(windows)] +#[naked] +#[cfg_attr(not(feature = "mangled-names"), no_mangle)] +pub unsafe fn ___chkstk_ms() { + asm!("push %rcx + push %rax + cmp $$0x1000,%rax + lea 24(%rsp),%rcx + jb 1f + 2: + sub $$0x1000,%rcx + test %rcx,(%rcx) + sub $$0x1000,%rax + cmp $$0x1000,%rax + ja 2b + 1: + sub %rax,%rcx + test %rcx,(%rcx) + pop %rax + pop %rcx + ret"); + intrinsics::unreachable(); +} + +#[cfg(windows)] +#[naked] +#[cfg_attr(not(feature = "mangled-names"), no_mangle)] +pub unsafe fn __alloca() { + asm!("mov %rcx,%rax // x64 _alloca is a normal function with parameter in rcx + jmp ___chkstk // Jump to ___chkstk since fallthrough may be unreliable"); + intrinsics::unreachable(); +} + +#[cfg(windows)] +#[naked] +#[cfg_attr(not(feature = "mangled-names"), no_mangle)] +pub unsafe fn ___chkstk() { + asm!("push %rcx + cmp $$0x1000,%rax + lea 16(%rsp),%rcx // rsp before calling this routine -> rcx + jb 1f + 2: + sub $$0x1000,%rcx + test %rcx,(%rcx) + sub $$0x1000,%rax + cmp $$0x1000,%rax + ja 2b + 1: + sub %rax,%rcx + test %rcx,(%rcx) + + lea 8(%rsp),%rax // load pointer to the return address into rax + mov %rcx,%rsp // install the new top of stack pointer into rsp + mov -8(%rax),%rcx // restore rcx + push (%rax) // push return address onto the stack + sub %rsp,%rax // restore the original value in rax + ret"); + intrinsics::unreachable(); +} diff --git a/src/libcompiler_builtins/tests/adddf3.rs b/src/libcompiler_builtins/tests/adddf3.rs new file mode 100644 index 0000000000..3129330afa --- /dev/null +++ b/src/libcompiler_builtins/tests/adddf3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/adddf3.rs")); diff --git a/src/libcompiler_builtins/tests/addsf3.rs b/src/libcompiler_builtins/tests/addsf3.rs new file mode 100644 index 0000000000..b5c9c3dfeb --- /dev/null +++ b/src/libcompiler_builtins/tests/addsf3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/addsf3.rs")); diff --git a/src/libcompiler_builtins/tests/aeabi_memclr.rs b/src/libcompiler_builtins/tests/aeabi_memclr.rs new file mode 100644 index 0000000000..72e944e4c7 --- /dev/null +++ b/src/libcompiler_builtins/tests/aeabi_memclr.rs @@ -0,0 +1,58 @@ +#![cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + feature = "mem"))] +#![feature(compiler_builtins_lib)] +#![no_std] + +extern crate compiler_builtins; + +// test runner +extern crate utest_cortex_m_qemu; + +// overrides `panic!` +#[macro_use] +extern crate utest_macros; + +use core::mem; + +macro_rules! panic { + ($($tt:tt)*) => { + upanic!($($tt)*); + }; +} + +extern "C" { + fn __aeabi_memclr4(dest: *mut u8, n: usize); + fn __aeabi_memset4(dest: *mut u8, n: usize, c: u32); +} + +struct Aligned { + array: [u8; 8], + _alignment: [u32; 0], +} + +impl Aligned { + fn new() -> Self { + Aligned { + array: [0; 8], + _alignment: [], + } + } +} + +#[test] +fn memclr4() { + let mut aligned = Aligned::new();; + assert_eq!(mem::align_of_val(&aligned), 4); + let xs = &mut aligned.array; + + for n in 0..9 { + unsafe { + __aeabi_memset4(xs.as_mut_ptr(), n, 0xff); + __aeabi_memclr4(xs.as_mut_ptr(), n); + } + + assert!(xs[0..n].iter().all(|x| *x == 0)); + } +} diff --git a/src/libcompiler_builtins/tests/aeabi_memcpy.rs b/src/libcompiler_builtins/tests/aeabi_memcpy.rs new file mode 100644 index 0000000000..2ba942c23c --- /dev/null +++ b/src/libcompiler_builtins/tests/aeabi_memcpy.rs @@ -0,0 +1,69 @@ +#![cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + feature = "mem"))] +#![feature(compiler_builtins_lib)] +#![no_std] + +extern crate compiler_builtins; + +// test runner +extern crate utest_cortex_m_qemu; + +// overrides `panic!` +#[macro_use] +extern crate utest_macros; + +macro_rules! panic { + ($($tt:tt)*) => { + upanic!($($tt)*); + }; +} + +extern "C" { + fn __aeabi_memcpy(dest: *mut u8, src: *const u8, n: usize); + fn __aeabi_memcpy4(dest: *mut u8, src: *const u8, n: usize); +} + +struct Aligned { + array: [u8; 8], + _alignment: [u32; 0], +} + +impl Aligned { + fn new(array: [u8; 8]) -> Self { + Aligned { + array: array, + _alignment: [], + } + } +} + +#[test] +fn memcpy() { + let mut dest = [0; 4]; + let src = [0xde, 0xad, 0xbe, 0xef]; + + for n in 0..dest.len() { + dest.copy_from_slice(&[0; 4]); + + unsafe { __aeabi_memcpy(dest.as_mut_ptr(), src.as_ptr(), n) } + + assert_eq!(&dest[0..n], &src[0..n]) + } +} + +#[test] +fn memcpy4() { + let mut aligned = Aligned::new([0; 8]); + let dest = &mut aligned.array; + let src = [0xde, 0xad, 0xbe, 0xef, 0xba, 0xad, 0xf0, 0x0d]; + + for n in 0..dest.len() { + dest.copy_from_slice(&[0; 8]); + + unsafe { __aeabi_memcpy4(dest.as_mut_ptr(), src.as_ptr(), n) } + + assert_eq!(&dest[0..n], &src[0..n]) + } +} diff --git a/src/libcompiler_builtins/tests/aeabi_memset.rs b/src/libcompiler_builtins/tests/aeabi_memset.rs new file mode 100644 index 0000000000..0919f14912 --- /dev/null +++ b/src/libcompiler_builtins/tests/aeabi_memset.rs @@ -0,0 +1,274 @@ +#![cfg(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + feature = "mem"))] +#![feature(compiler_builtins_lib)] +#![no_std] + +extern crate compiler_builtins; + +// test runner +extern crate utest_cortex_m_qemu; + +// overrides `panic!` +#[macro_use] +extern crate utest_macros; + +use core::mem; + +macro_rules! panic { + ($($tt:tt)*) => { + upanic!($($tt)*); + }; +} + +extern "C" { + fn __aeabi_memset4(dest: *mut u8, n: usize, c: u32); +} + +struct Aligned { + array: [u8; 8], + _alignment: [u32; 0], +} + +impl Aligned { + fn new(array: [u8; 8]) -> Self { + Aligned { + array: array, + _alignment: [], + } + } +} + +#[test] +fn zero() { + let mut aligned = Aligned::new([0u8; 8]);; + assert_eq!(mem::align_of_val(&aligned), 4); + let xs = &mut aligned.array; + let c = 0xdeadbeef; + + unsafe { + __aeabi_memset4(xs.as_mut_ptr(), 0, c) + } + + assert_eq!(*xs, [0; 8]); + + let mut aligned = Aligned::new([1u8; 8]);; + assert_eq!(mem::align_of_val(&aligned), 4); + let xs = &mut aligned.array; + let c = 0xdeadbeef; + + unsafe { + __aeabi_memset4(xs.as_mut_ptr(), 0, c) + } + + assert_eq!(*xs, [1; 8]); +} + +#[test] +fn one() { + let mut aligned = Aligned::new([0u8; 8]);; + assert_eq!(mem::align_of_val(&aligned), 4); + let xs = &mut aligned.array; + let n = 1; + let c = 0xdeadbeef; + + unsafe { + __aeabi_memset4(xs.as_mut_ptr(), n, c) + } + + assert_eq!(*xs, [0xef, 0, 0, 0, 0, 0, 0, 0]); + + let mut aligned = Aligned::new([1u8; 8]);; + assert_eq!(mem::align_of_val(&aligned), 4); + let xs = &mut aligned.array; + let c = 0xdeadbeef; + + unsafe { + __aeabi_memset4(xs.as_mut_ptr(), n, c) + } + + assert_eq!(*xs, [0xef, 1, 1, 1, 1, 1, 1, 1]); +} + +#[test] +fn two() { + let mut aligned = Aligned::new([0u8; 8]);; + assert_eq!(mem::align_of_val(&aligned), 4); + let xs = &mut aligned.array; + let n = 2; + let c = 0xdeadbeef; + + unsafe { + __aeabi_memset4(xs.as_mut_ptr(), n, c) + } + + assert_eq!(*xs, [0xef, 0xef, 0, 0, 0, 0, 0, 0]); + + let mut aligned = Aligned::new([1u8; 8]);; + assert_eq!(mem::align_of_val(&aligned), 4); + let xs = &mut aligned.array; + let c = 0xdeadbeef; + + unsafe { + __aeabi_memset4(xs.as_mut_ptr(), n, c) + } + + assert_eq!(*xs, [0xef, 0xef, 1, 1, 1, 1, 1, 1]); +} + +#[test] +fn three() { + let mut aligned = Aligned::new([0u8; 8]);; + assert_eq!(mem::align_of_val(&aligned), 4); + let xs = &mut aligned.array; + let n = 3; + let c = 0xdeadbeef; + + unsafe { + __aeabi_memset4(xs.as_mut_ptr(), n, c) + } + + assert_eq!(*xs, [0xef, 0xef, 0xef, 0, 0, 0, 0, 0]); + + let mut aligned = Aligned::new([1u8; 8]);; + assert_eq!(mem::align_of_val(&aligned), 4); + let xs = &mut aligned.array; + let c = 0xdeadbeef; + + unsafe { + __aeabi_memset4(xs.as_mut_ptr(), n, c) + } + + assert_eq!(*xs, [0xef, 0xef, 0xef, 1, 1, 1, 1, 1]); +} + +#[test] +fn four() { + let mut aligned = Aligned::new([0u8; 8]);; + assert_eq!(mem::align_of_val(&aligned), 4); + let xs = &mut aligned.array; + let n = 4; + let c = 0xdeadbeef; + + unsafe { + __aeabi_memset4(xs.as_mut_ptr(), n, c) + } + + assert_eq!(*xs, [0xef, 0xef, 0xef, 0xef, 0, 0, 0, 0]); + + let mut aligned = Aligned::new([1u8; 8]);; + assert_eq!(mem::align_of_val(&aligned), 4); + let xs = &mut aligned.array; + let c = 0xdeadbeef; + + unsafe { + __aeabi_memset4(xs.as_mut_ptr(), n, c) + } + + assert_eq!(*xs, [0xef, 0xef, 0xef, 0xef, 1, 1, 1, 1]); +} + +#[test] +fn five() { + let mut aligned = Aligned::new([0u8; 8]);; + assert_eq!(mem::align_of_val(&aligned), 4); + let xs = &mut aligned.array; + let n = 5; + let c = 0xdeadbeef; + + unsafe { + __aeabi_memset4(xs.as_mut_ptr(), n, c) + } + + assert_eq!(*xs, [0xef, 0xef, 0xef, 0xef, 0xef, 0, 0, 0]); + + let mut aligned = Aligned::new([1u8; 8]);; + assert_eq!(mem::align_of_val(&aligned), 4); + let xs = &mut aligned.array; + let c = 0xdeadbeef; + + unsafe { + __aeabi_memset4(xs.as_mut_ptr(), n, c) + } + + assert_eq!(*xs, [0xef, 0xef, 0xef, 0xef, 0xef, 1, 1, 1]); +} + +#[test] +fn six() { + let mut aligned = Aligned::new([0u8; 8]);; + assert_eq!(mem::align_of_val(&aligned), 4); + let xs = &mut aligned.array; + let n = 6; + let c = 0xdeadbeef; + + unsafe { + __aeabi_memset4(xs.as_mut_ptr(), n, c) + } + + assert_eq!(*xs, [0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0, 0]); + + let mut aligned = Aligned::new([1u8; 8]);; + assert_eq!(mem::align_of_val(&aligned), 4); + let xs = &mut aligned.array; + let c = 0xdeadbeef; + + unsafe { + __aeabi_memset4(xs.as_mut_ptr(), n, c) + } + + assert_eq!(*xs, [0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 1, 1]); +} + +#[test] +fn seven() { + let mut aligned = Aligned::new([0u8; 8]);; + assert_eq!(mem::align_of_val(&aligned), 4); + let xs = &mut aligned.array; + let n = 7; + let c = 0xdeadbeef; + + unsafe { + __aeabi_memset4(xs.as_mut_ptr(), n, c) + } + + assert_eq!(*xs, [0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0]); + + let mut aligned = Aligned::new([1u8; 8]);; + assert_eq!(mem::align_of_val(&aligned), 4); + let xs = &mut aligned.array; + let c = 0xdeadbeef; + + unsafe { + __aeabi_memset4(xs.as_mut_ptr(), n, c) + } + + assert_eq!(*xs, [0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 1]); +} + +#[test] +fn eight() { + let mut aligned = Aligned::new([0u8; 8]);; + assert_eq!(mem::align_of_val(&aligned), 4); + let xs = &mut aligned.array; + let n = 8; + let c = 0xdeadbeef; + + unsafe { + __aeabi_memset4(xs.as_mut_ptr(), n, c) + } + + assert_eq!(*xs, [0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef]); + + let mut aligned = Aligned::new([1u8; 8]);; + assert_eq!(mem::align_of_val(&aligned), 4); + let xs = &mut aligned.array; + let c = 0xdeadbeef; + + unsafe { + __aeabi_memset4(xs.as_mut_ptr(), n, c) + } + + assert_eq!(*xs, [0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef]); +} diff --git a/src/libcompiler_builtins/tests/ashldi3.rs b/src/libcompiler_builtins/tests/ashldi3.rs new file mode 100644 index 0000000000..1116375d3e --- /dev/null +++ b/src/libcompiler_builtins/tests/ashldi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/ashldi3.rs")); diff --git a/src/libcompiler_builtins/tests/ashlti3.rs b/src/libcompiler_builtins/tests/ashlti3.rs new file mode 100644 index 0000000000..4c799cf882 --- /dev/null +++ b/src/libcompiler_builtins/tests/ashlti3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/ashlti3.rs")); diff --git a/src/libcompiler_builtins/tests/ashrdi3.rs b/src/libcompiler_builtins/tests/ashrdi3.rs new file mode 100644 index 0000000000..a0a2b6cb13 --- /dev/null +++ b/src/libcompiler_builtins/tests/ashrdi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/ashrdi3.rs")); diff --git a/src/libcompiler_builtins/tests/ashrti3.rs b/src/libcompiler_builtins/tests/ashrti3.rs new file mode 100644 index 0000000000..b147051c2d --- /dev/null +++ b/src/libcompiler_builtins/tests/ashrti3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/ashrti3.rs")); diff --git a/src/libcompiler_builtins/tests/divdi3.rs b/src/libcompiler_builtins/tests/divdi3.rs new file mode 100644 index 0000000000..4bdce54156 --- /dev/null +++ b/src/libcompiler_builtins/tests/divdi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/divdi3.rs")); diff --git a/src/libcompiler_builtins/tests/divmoddi4.rs b/src/libcompiler_builtins/tests/divmoddi4.rs new file mode 100644 index 0000000000..9ddd85a829 --- /dev/null +++ b/src/libcompiler_builtins/tests/divmoddi4.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/divmoddi4.rs")); diff --git a/src/libcompiler_builtins/tests/divmodsi4.rs b/src/libcompiler_builtins/tests/divmodsi4.rs new file mode 100644 index 0000000000..6fe80e9756 --- /dev/null +++ b/src/libcompiler_builtins/tests/divmodsi4.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/divmodsi4.rs")); diff --git a/src/libcompiler_builtins/tests/divsi3.rs b/src/libcompiler_builtins/tests/divsi3.rs new file mode 100644 index 0000000000..e6440d782c --- /dev/null +++ b/src/libcompiler_builtins/tests/divsi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/divsi3.rs")); diff --git a/src/libcompiler_builtins/tests/divti3.rs b/src/libcompiler_builtins/tests/divti3.rs new file mode 100644 index 0000000000..7919f8fe39 --- /dev/null +++ b/src/libcompiler_builtins/tests/divti3.rs @@ -0,0 +1,10 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +// FIXME(#137) +#[cfg(not(target_arch = "mips"))] +include!(concat!(env!("OUT_DIR"), "/divti3.rs")); diff --git a/src/libcompiler_builtins/tests/fixdfdi.rs b/src/libcompiler_builtins/tests/fixdfdi.rs new file mode 100644 index 0000000000..b66477502b --- /dev/null +++ b/src/libcompiler_builtins/tests/fixdfdi.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/fixdfdi.rs")); diff --git a/src/libcompiler_builtins/tests/fixdfsi.rs b/src/libcompiler_builtins/tests/fixdfsi.rs new file mode 100644 index 0000000000..2677eec747 --- /dev/null +++ b/src/libcompiler_builtins/tests/fixdfsi.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/fixdfsi.rs")); diff --git a/src/libcompiler_builtins/tests/fixdfti.rs b/src/libcompiler_builtins/tests/fixdfti.rs new file mode 100644 index 0000000000..5bae55e99f --- /dev/null +++ b/src/libcompiler_builtins/tests/fixdfti.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/fixdfti.rs")); diff --git a/src/libcompiler_builtins/tests/fixsfdi.rs b/src/libcompiler_builtins/tests/fixsfdi.rs new file mode 100644 index 0000000000..e38952be59 --- /dev/null +++ b/src/libcompiler_builtins/tests/fixsfdi.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/fixsfdi.rs")); diff --git a/src/libcompiler_builtins/tests/fixsfsi.rs b/src/libcompiler_builtins/tests/fixsfsi.rs new file mode 100644 index 0000000000..242b4c1694 --- /dev/null +++ b/src/libcompiler_builtins/tests/fixsfsi.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/fixsfsi.rs")); diff --git a/src/libcompiler_builtins/tests/fixsfti.rs b/src/libcompiler_builtins/tests/fixsfti.rs new file mode 100644 index 0000000000..653157df26 --- /dev/null +++ b/src/libcompiler_builtins/tests/fixsfti.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/fixsfti.rs")); diff --git a/src/libcompiler_builtins/tests/fixunsdfdi.rs b/src/libcompiler_builtins/tests/fixunsdfdi.rs new file mode 100644 index 0000000000..13b35ba4a1 --- /dev/null +++ b/src/libcompiler_builtins/tests/fixunsdfdi.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/fixunsdfdi.rs")); diff --git a/src/libcompiler_builtins/tests/fixunsdfsi.rs b/src/libcompiler_builtins/tests/fixunsdfsi.rs new file mode 100644 index 0000000000..32faf360c3 --- /dev/null +++ b/src/libcompiler_builtins/tests/fixunsdfsi.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/fixunsdfsi.rs")); diff --git a/src/libcompiler_builtins/tests/fixunsdfti.rs b/src/libcompiler_builtins/tests/fixunsdfti.rs new file mode 100644 index 0000000000..615e7b33b8 --- /dev/null +++ b/src/libcompiler_builtins/tests/fixunsdfti.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/fixunsdfti.rs")); diff --git a/src/libcompiler_builtins/tests/fixunssfdi.rs b/src/libcompiler_builtins/tests/fixunssfdi.rs new file mode 100644 index 0000000000..24e6f6e350 --- /dev/null +++ b/src/libcompiler_builtins/tests/fixunssfdi.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/fixunssfdi.rs")); diff --git a/src/libcompiler_builtins/tests/fixunssfsi.rs b/src/libcompiler_builtins/tests/fixunssfsi.rs new file mode 100644 index 0000000000..da02cd9457 --- /dev/null +++ b/src/libcompiler_builtins/tests/fixunssfsi.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/fixunssfsi.rs")); diff --git a/src/libcompiler_builtins/tests/fixunssfti.rs b/src/libcompiler_builtins/tests/fixunssfti.rs new file mode 100644 index 0000000000..d67f9e794e --- /dev/null +++ b/src/libcompiler_builtins/tests/fixunssfti.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/fixunssfti.rs")); diff --git a/src/libcompiler_builtins/tests/floatdidf.rs b/src/libcompiler_builtins/tests/floatdidf.rs new file mode 100644 index 0000000000..2b3dcb5928 --- /dev/null +++ b/src/libcompiler_builtins/tests/floatdidf.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/floatdidf.rs")); diff --git a/src/libcompiler_builtins/tests/floatsidf.rs b/src/libcompiler_builtins/tests/floatsidf.rs new file mode 100644 index 0000000000..ffee7e2711 --- /dev/null +++ b/src/libcompiler_builtins/tests/floatsidf.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/floatsidf.rs")); diff --git a/src/libcompiler_builtins/tests/floatsisf.rs b/src/libcompiler_builtins/tests/floatsisf.rs new file mode 100644 index 0000000000..c03ab7f9dd --- /dev/null +++ b/src/libcompiler_builtins/tests/floatsisf.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/floatsisf.rs")); diff --git a/src/libcompiler_builtins/tests/floattidf.rs b/src/libcompiler_builtins/tests/floattidf.rs new file mode 100644 index 0000000000..4e4f84ddb0 --- /dev/null +++ b/src/libcompiler_builtins/tests/floattidf.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/floattidf.rs")); diff --git a/src/libcompiler_builtins/tests/floattisf.rs b/src/libcompiler_builtins/tests/floattisf.rs new file mode 100644 index 0000000000..2a0657d3d0 --- /dev/null +++ b/src/libcompiler_builtins/tests/floattisf.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/floattisf.rs")); diff --git a/src/libcompiler_builtins/tests/floatundidf.rs b/src/libcompiler_builtins/tests/floatundidf.rs new file mode 100644 index 0000000000..0b83385124 --- /dev/null +++ b/src/libcompiler_builtins/tests/floatundidf.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/floatundidf.rs")); diff --git a/src/libcompiler_builtins/tests/floatunsidf.rs b/src/libcompiler_builtins/tests/floatunsidf.rs new file mode 100644 index 0000000000..e25a69f5be --- /dev/null +++ b/src/libcompiler_builtins/tests/floatunsidf.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/floatunsidf.rs")); diff --git a/src/libcompiler_builtins/tests/floatunsisf.rs b/src/libcompiler_builtins/tests/floatunsisf.rs new file mode 100644 index 0000000000..c0b9fd8b0b --- /dev/null +++ b/src/libcompiler_builtins/tests/floatunsisf.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/floatunsisf.rs")); diff --git a/src/libcompiler_builtins/tests/floatuntidf.rs b/src/libcompiler_builtins/tests/floatuntidf.rs new file mode 100644 index 0000000000..4ea272e97d --- /dev/null +++ b/src/libcompiler_builtins/tests/floatuntidf.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/floatuntidf.rs")); diff --git a/src/libcompiler_builtins/tests/floatuntisf.rs b/src/libcompiler_builtins/tests/floatuntisf.rs new file mode 100644 index 0000000000..74cd853e49 --- /dev/null +++ b/src/libcompiler_builtins/tests/floatuntisf.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/floatuntisf.rs")); diff --git a/src/libcompiler_builtins/tests/lshrdi3.rs b/src/libcompiler_builtins/tests/lshrdi3.rs new file mode 100644 index 0000000000..b1a2331b19 --- /dev/null +++ b/src/libcompiler_builtins/tests/lshrdi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/lshrdi3.rs")); diff --git a/src/libcompiler_builtins/tests/lshrti3.rs b/src/libcompiler_builtins/tests/lshrti3.rs new file mode 100644 index 0000000000..2ee32ce71f --- /dev/null +++ b/src/libcompiler_builtins/tests/lshrti3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/lshrti3.rs")); diff --git a/src/libcompiler_builtins/tests/moddi3.rs b/src/libcompiler_builtins/tests/moddi3.rs new file mode 100644 index 0000000000..6a58a77ab4 --- /dev/null +++ b/src/libcompiler_builtins/tests/moddi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/moddi3.rs")); diff --git a/src/libcompiler_builtins/tests/modsi3.rs b/src/libcompiler_builtins/tests/modsi3.rs new file mode 100644 index 0000000000..46ad8cd33c --- /dev/null +++ b/src/libcompiler_builtins/tests/modsi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/modsi3.rs")); diff --git a/src/libcompiler_builtins/tests/modti3.rs b/src/libcompiler_builtins/tests/modti3.rs new file mode 100644 index 0000000000..62129cd04d --- /dev/null +++ b/src/libcompiler_builtins/tests/modti3.rs @@ -0,0 +1,10 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +// FIXME(#137) +#[cfg(not(target_arch = "mips"))] +include!(concat!(env!("OUT_DIR"), "/modti3.rs")); diff --git a/src/libcompiler_builtins/tests/muldi3.rs b/src/libcompiler_builtins/tests/muldi3.rs new file mode 100644 index 0000000000..d771e8a6bd --- /dev/null +++ b/src/libcompiler_builtins/tests/muldi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/muldi3.rs")); diff --git a/src/libcompiler_builtins/tests/mulodi4.rs b/src/libcompiler_builtins/tests/mulodi4.rs new file mode 100644 index 0000000000..071a295810 --- /dev/null +++ b/src/libcompiler_builtins/tests/mulodi4.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/mulodi4.rs")); diff --git a/src/libcompiler_builtins/tests/mulosi4.rs b/src/libcompiler_builtins/tests/mulosi4.rs new file mode 100644 index 0000000000..3ec4336d11 --- /dev/null +++ b/src/libcompiler_builtins/tests/mulosi4.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/mulosi4.rs")); diff --git a/src/libcompiler_builtins/tests/muloti4.rs b/src/libcompiler_builtins/tests/muloti4.rs new file mode 100644 index 0000000000..358c57ec52 --- /dev/null +++ b/src/libcompiler_builtins/tests/muloti4.rs @@ -0,0 +1,10 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +// FIXME(#137) +#[cfg(not(target_arch = "mips"))] +include!(concat!(env!("OUT_DIR"), "/muloti4.rs")); diff --git a/src/libcompiler_builtins/tests/multi3.rs b/src/libcompiler_builtins/tests/multi3.rs new file mode 100644 index 0000000000..db52538743 --- /dev/null +++ b/src/libcompiler_builtins/tests/multi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/multi3.rs")); diff --git a/src/libcompiler_builtins/tests/powidf2.rs b/src/libcompiler_builtins/tests/powidf2.rs new file mode 100644 index 0000000000..dde5f03eb9 --- /dev/null +++ b/src/libcompiler_builtins/tests/powidf2.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/powidf2.rs")); diff --git a/src/libcompiler_builtins/tests/powisf2.rs b/src/libcompiler_builtins/tests/powisf2.rs new file mode 100644 index 0000000000..3e0baeb73c --- /dev/null +++ b/src/libcompiler_builtins/tests/powisf2.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/powisf2.rs")); diff --git a/src/libcompiler_builtins/tests/subdf3.rs b/src/libcompiler_builtins/tests/subdf3.rs new file mode 100644 index 0000000000..13f695718e --- /dev/null +++ b/src/libcompiler_builtins/tests/subdf3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/subdf3.rs")); diff --git a/src/libcompiler_builtins/tests/subsf3.rs b/src/libcompiler_builtins/tests/subsf3.rs new file mode 100644 index 0000000000..7be426c453 --- /dev/null +++ b/src/libcompiler_builtins/tests/subsf3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/subsf3.rs")); diff --git a/src/libcompiler_builtins/tests/udivdi3.rs b/src/libcompiler_builtins/tests/udivdi3.rs new file mode 100644 index 0000000000..d87091c7d8 --- /dev/null +++ b/src/libcompiler_builtins/tests/udivdi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/udivdi3.rs")); diff --git a/src/libcompiler_builtins/tests/udivmoddi4.rs b/src/libcompiler_builtins/tests/udivmoddi4.rs new file mode 100644 index 0000000000..a9444c10db --- /dev/null +++ b/src/libcompiler_builtins/tests/udivmoddi4.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/udivmoddi4.rs")); diff --git a/src/libcompiler_builtins/tests/udivmodsi4.rs b/src/libcompiler_builtins/tests/udivmodsi4.rs new file mode 100644 index 0000000000..e93bfe1e55 --- /dev/null +++ b/src/libcompiler_builtins/tests/udivmodsi4.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/udivmodsi4.rs")); diff --git a/src/libcompiler_builtins/tests/udivmodti4.rs b/src/libcompiler_builtins/tests/udivmodti4.rs new file mode 100644 index 0000000000..8185ec0e78 --- /dev/null +++ b/src/libcompiler_builtins/tests/udivmodti4.rs @@ -0,0 +1,10 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +// FIXME(#137) +#[cfg(not(target_arch = "mips"))] +include!(concat!(env!("OUT_DIR"), "/udivmodti4.rs")); diff --git a/src/libcompiler_builtins/tests/udivsi3.rs b/src/libcompiler_builtins/tests/udivsi3.rs new file mode 100644 index 0000000000..d6433e7c31 --- /dev/null +++ b/src/libcompiler_builtins/tests/udivsi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/udivsi3.rs")); diff --git a/src/libcompiler_builtins/tests/udivti3.rs b/src/libcompiler_builtins/tests/udivti3.rs new file mode 100644 index 0000000000..cefddda8f8 --- /dev/null +++ b/src/libcompiler_builtins/tests/udivti3.rs @@ -0,0 +1,10 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +// FIXME(#137) +#[cfg(not(target_arch = "mips"))] +include!(concat!(env!("OUT_DIR"), "/udivti3.rs")); diff --git a/src/libcompiler_builtins/tests/umoddi3.rs b/src/libcompiler_builtins/tests/umoddi3.rs new file mode 100644 index 0000000000..09a114ee6b --- /dev/null +++ b/src/libcompiler_builtins/tests/umoddi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/umoddi3.rs")); diff --git a/src/libcompiler_builtins/tests/umodsi3.rs b/src/libcompiler_builtins/tests/umodsi3.rs new file mode 100644 index 0000000000..aa56e819c2 --- /dev/null +++ b/src/libcompiler_builtins/tests/umodsi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/umodsi3.rs")); diff --git a/src/libcompiler_builtins/tests/umodti3.rs b/src/libcompiler_builtins/tests/umodti3.rs new file mode 100644 index 0000000000..57e651b271 --- /dev/null +++ b/src/libcompiler_builtins/tests/umodti3.rs @@ -0,0 +1,10 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +// FIXME(#137) +#[cfg(not(target_arch = "mips"))] +include!(concat!(env!("OUT_DIR"), "/umodti3.rs")); diff --git a/src/libcompiler_builtins/thumbv6m-linux-eabi.json b/src/libcompiler_builtins/thumbv6m-linux-eabi.json new file mode 100644 index 0000000000..dd0cb61bc0 --- /dev/null +++ b/src/libcompiler_builtins/thumbv6m-linux-eabi.json @@ -0,0 +1,27 @@ +{ + "abi-blacklist": [ + "stdcall", + "fastcall", + "vectorcall", + "win64", + "sysv64" + ], + "arch": "arm", + "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", + "env": "", + "executables": true, + "features": "+strict-align", + "linker": "arm-none-eabi-gcc", + "linker-flavor": "gcc", + "llvm-target": "thumbv6m-none-eabi", + "max-atomic-width": 0, + "os": "linux", + "panic-strategy": "abort", + "pre-link-args": { + "gcc": ["-nostartfiles"] + }, + "relocation-model": "static", + "target-endian": "little", + "target-pointer-width": "32", + "vendor": "" +} diff --git a/src/libcompiler_builtins/thumbv7em-linux-eabi.json b/src/libcompiler_builtins/thumbv7em-linux-eabi.json new file mode 100644 index 0000000000..eef29f5cc7 --- /dev/null +++ b/src/libcompiler_builtins/thumbv7em-linux-eabi.json @@ -0,0 +1,26 @@ +{ + "abi-blacklist": [ + "stdcall", + "fastcall", + "vectorcall", + "win64", + "sysv64" + ], + "arch": "arm", + "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", + "env": "", + "executables": true, + "linker": "arm-none-eabi-gcc", + "linker-flavor": "gcc", + "llvm-target": "thumbv7em-none-eabi", + "max-atomic-width": 32, + "os": "linux", + "panic-strategy": "abort", + "pre-link-args": { + "gcc": ["-nostartfiles"] + }, + "relocation-model": "static", + "target-endian": "little", + "target-pointer-width": "32", + "vendor": "" +} diff --git a/src/libcompiler_builtins/thumbv7em-linux-eabihf.json b/src/libcompiler_builtins/thumbv7em-linux-eabihf.json new file mode 100644 index 0000000000..5d72ec3b47 --- /dev/null +++ b/src/libcompiler_builtins/thumbv7em-linux-eabihf.json @@ -0,0 +1,27 @@ +{ + "abi-blacklist": [ + "stdcall", + "fastcall", + "vectorcall", + "win64", + "sysv64" + ], + "arch": "arm", + "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", + "env": "", + "executables": true, + "features": "+vfp4,+d16,+fp-only-sp", + "linker": "arm-none-eabi-gcc", + "linker-flavor": "gcc", + "llvm-target": "thumbv7em-none-eabihf", + "max-atomic-width": 32, + "os": "linux", + "panic-strategy": "abort", + "pre-link-args": { + "gcc": ["-nostartfiles"] + }, + "relocation-model": "static", + "target-endian": "little", + "target-pointer-width": "32", + "vendor": "" +} diff --git a/src/libcompiler_builtins/thumbv7m-linux-eabi.json b/src/libcompiler_builtins/thumbv7m-linux-eabi.json new file mode 100644 index 0000000000..1e8a7f0086 --- /dev/null +++ b/src/libcompiler_builtins/thumbv7m-linux-eabi.json @@ -0,0 +1,26 @@ +{ + "abi-blacklist": [ + "stdcall", + "fastcall", + "vectorcall", + "win64", + "sysv64" + ], + "arch": "arm", + "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", + "env": "", + "executables": true, + "linker": "arm-none-eabi-gcc", + "linker-flavor": "gcc", + "llvm-target": "thumbv7m-none-eabi", + "max-atomic-width": 32, + "os": "linux", + "panic-strategy": "abort", + "pre-link-args": { + "gcc": ["-nostartfiles"] + }, + "relocation-model": "static", + "target-endian": "little", + "target-pointer-width": "32", + "vendor": "" +} diff --git a/src/libcore/Cargo.toml b/src/libcore/Cargo.toml index 5af63aa970..178df02ccd 100644 --- a/src/libcore/Cargo.toml +++ b/src/libcore/Cargo.toml @@ -9,6 +9,9 @@ path = "lib.rs" test = false bench = false +[dev-dependencies] +rand = { path = "../librand" } + [[test]] name = "coretests" path = "../libcore/tests/lib.rs" diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs index 93d38a5bc8..5b06229c21 100644 --- a/src/libcore/benches/iter.rs +++ b/src/libcore/benches/iter.rs @@ -99,3 +99,50 @@ fn bench_zip_add(b: &mut Bencher) { add_zip(&source, &mut dst) }); } + +/// `Iterator::for_each` implemented as a plain loop. +fn for_each_loop(iter: I, mut f: F) where + I: Iterator, F: FnMut(I::Item) +{ + for item in iter { + f(item); + } +} + +/// `Iterator::for_each` implemented with `fold` for internal iteration. +/// (except when `by_ref()` effectively disables that optimization.) +fn for_each_fold(iter: I, mut f: F) where + I: Iterator, F: FnMut(I::Item) +{ + iter.fold((), move |(), item| f(item)); +} + +#[bench] +fn bench_for_each_chain_loop(b: &mut Bencher) { + b.iter(|| { + let mut acc = 0; + let iter = (0i64..1000000).chain(0..1000000).map(black_box); + for_each_loop(iter, |x| acc += x); + acc + }); +} + +#[bench] +fn bench_for_each_chain_fold(b: &mut Bencher) { + b.iter(|| { + let mut acc = 0; + let iter = (0i64..1000000).chain(0..1000000).map(black_box); + for_each_fold(iter, |x| acc += x); + acc + }); +} + +#[bench] +fn bench_for_each_chain_ref_fold(b: &mut Bencher) { + b.iter(|| { + let mut acc = 0; + let mut iter = (0i64..1000000).chain(0..1000000).map(black_box); + for_each_fold(iter.by_ref(), |x| acc += x); + acc + }); +} diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index 3d223465c8..61558034e6 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -31,7 +31,7 @@ /// `Borrow` is very similar to, but different than, `AsRef`. See /// [the book][book] for more. /// -/// [book]: ../../book/borrow-and-asref.html +/// [book]: ../../book/first-edition/borrow-and-asref.html #[stable(feature = "rust1", since = "1.0.0")] pub trait Borrow { /// Immutably borrows from an owned value. diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index ea480f3894..35744f3f16 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -391,17 +391,17 @@ impl Cell { } } - /// Replaces the contained value. + /// Replaces the contained value, and returns it. /// /// # Examples /// /// ``` /// use std::cell::Cell; /// - /// let c = Cell::new(5); - /// let old = c.replace(10); - /// - /// assert_eq!(5, old); + /// let cell = Cell::new(5); + /// assert_eq!(cell.get(), 5); + /// assert_eq!(cell.replace(10), 5); + /// assert_eq!(cell.get(), 10); /// ``` #[stable(feature = "move_cell", since = "1.17.0")] pub fn replace(&self, val: T) -> T { @@ -942,6 +942,13 @@ impl<'b, T: ?Sized> Ref<'b, T> { #[unstable(feature = "coerce_unsized", issue = "27732")] impl<'b, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for Ref<'b, T> {} +#[stable(feature = "std_guard_impls", since = "1.20.0")] +impl<'a, T: ?Sized + fmt::Display> fmt::Display for Ref<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.value.fmt(f) + } +} + impl<'b, T: ?Sized> RefMut<'b, T> { /// Make a new `RefMut` for a component of the borrowed data, e.g. an enum /// variant. @@ -1034,6 +1041,13 @@ impl<'b, T: ?Sized> DerefMut for RefMut<'b, T> { #[unstable(feature = "coerce_unsized", issue = "27732")] impl<'b, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for RefMut<'b, T> {} +#[stable(feature = "std_guard_impls", since = "1.20.0")] +impl<'a, T: ?Sized + fmt::Display> fmt::Display for RefMut<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.value.fmt(f) + } +} + /// The core primitive for interior mutability in Rust. /// /// `UnsafeCell` is a type that wraps some `T` and indicates unsafe interior operations on the diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 98268e3813..e8b81db070 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -19,7 +19,7 @@ use char_private::is_printable; use convert::TryFrom; use fmt::{self, Write}; use slice; -use str::from_utf8_unchecked_mut; +use str::{from_utf8_unchecked_mut, FromStr}; use iter::FusedIterator; use mem::transmute; @@ -208,6 +208,63 @@ impl From for char { } } + +/// An error which can be returned when parsing a char. +#[stable(feature = "char_from_str", since = "1.20.0")] +#[derive(Clone, Debug)] +pub struct ParseCharError { + kind: CharErrorKind, +} + +impl ParseCharError { + #[unstable(feature = "char_error_internals", + reason = "this method should not be available publicly", + issue = "0")] + #[doc(hidden)] + pub fn __description(&self) -> &str { + match self.kind { + CharErrorKind::EmptyString => { + "cannot parse char from empty string" + }, + CharErrorKind::TooManyChars => "too many characters in string" + } + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +enum CharErrorKind { + EmptyString, + TooManyChars, +} + +#[stable(feature = "char_from_str", since = "1.20.0")] +impl fmt::Display for ParseCharError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.__description().fmt(f) + } +} + + +#[stable(feature = "char_from_str", since = "1.20.0")] +impl FromStr for char { + type Err = ParseCharError; + + #[inline] + fn from_str(s: &str) -> Result { + let mut chars = s.chars(); + match (chars.next(), chars.next()) { + (None, _) => { + Err(ParseCharError { kind: CharErrorKind::EmptyString }) + }, + (Some(c), None) => Ok(c), + _ => { + Err(ParseCharError { kind: CharErrorKind::TooManyChars }) + } + } + } +} + + #[unstable(feature = "try_from", issue = "33417")] impl TryFrom for char { type Error = CharTryFromError; @@ -322,7 +379,7 @@ pub trait CharExt { fn escape_unicode(self) -> EscapeUnicode; #[stable(feature = "core", since = "1.6.0")] fn escape_default(self) -> EscapeDefault; - #[unstable(feature = "char_escape_debug", issue = "35068")] + #[stable(feature = "char_escape_debug", since = "1.20.0")] fn escape_debug(self) -> EscapeDebug; #[stable(feature = "core", since = "1.6.0")] fn len_utf8(self) -> usize; @@ -719,24 +776,24 @@ impl fmt::Display for EscapeDefault { /// /// [`escape_debug`]: ../../std/primitive.char.html#method.escape_debug /// [`char`]: ../../std/primitive.char.html -#[unstable(feature = "char_escape_debug", issue = "35068")] +#[stable(feature = "char_escape_debug", since = "1.20.0")] #[derive(Clone, Debug)] pub struct EscapeDebug(EscapeDefault); -#[unstable(feature = "char_escape_debug", issue = "35068")] +#[stable(feature = "char_escape_debug", since = "1.20.0")] impl Iterator for EscapeDebug { type Item = char; fn next(&mut self) -> Option { self.0.next() } fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } } -#[unstable(feature = "char_escape_debug", issue = "35068")] +#[stable(feature = "char_escape_debug", since = "1.20.0")] impl ExactSizeIterator for EscapeDebug { } #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for EscapeDebug {} -#[unstable(feature = "char_escape_debug", issue = "35068")] +#[stable(feature = "char_escape_debug", since = "1.20.0")] impl fmt::Display for EscapeDebug { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 9c90c0155b..f133bd93c9 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -379,8 +379,9 @@ impl Ord for Reverse { /// /// ## Derivable /// -/// 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. +/// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a +/// lexicographic ordering based on the top-to-bottom declaration order of the struct's members. +/// When `derive`d on enums, variants are ordered by their top-to-bottom declaration order. /// /// ## How can I implement `Ord`? /// @@ -442,6 +443,42 @@ pub trait Ord: Eq + PartialOrd { /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn cmp(&self, other: &Self) -> Ordering; + + /// Compares and returns the maximum of two values. + /// + /// Returns the second argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// #![feature(ord_max_min)] + /// + /// assert_eq!(2, 1.max(2)); + /// assert_eq!(2, 2.max(2)); + /// ``` + #[unstable(feature = "ord_max_min", issue = "25663")] + fn max(self, other: Self) -> Self + where Self: Sized { + if other >= self { other } else { self } + } + + /// Compares and returns the minimum of two values. + /// + /// Returns the first argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// #![feature(ord_max_min)] + /// + /// assert_eq!(1, 1.min(2)); + /// assert_eq!(2, 2.min(2)); + /// ``` + #[unstable(feature = "ord_max_min", issue = "25663")] + fn min(self, other: Self) -> Self + where Self: Sized { + if self <= other { self } else { other } + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -476,8 +513,9 @@ impl PartialOrd for Ordering { /// /// ## Derivable /// -/// 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. +/// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a +/// lexicographic ordering based on the top-to-bottom declaration order of the struct's members. +/// When `derive`d on enums, variants are ordered by their top-to-bottom declaration order. /// /// ## How can I implement `PartialOrd`? /// @@ -677,6 +715,8 @@ pub trait PartialOrd: PartialEq { /// /// Returns the first argument if the comparison determines them to be equal. /// +/// Internally uses an alias to `Ord::min`. +/// /// # Examples /// /// ``` @@ -688,13 +728,15 @@ pub trait PartialOrd: PartialEq { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn min(v1: T, v2: T) -> T { - if v1 <= v2 { v1 } else { v2 } + v1.min(v2) } /// Compares and returns the maximum of two values. /// /// Returns the second argument if the comparison determines them to be equal. /// +/// Internally uses an alias to `Ord::max`. +/// /// # Examples /// /// ``` @@ -706,7 +748,7 @@ pub fn min(v1: T, v2: T) -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn max(v1: T, v2: T) -> T { - if v2 >= v1 { v2 } else { v1 } + v1.max(v2) } // Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 11a360ff90..6f3c3863fa 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -71,7 +71,7 @@ use str::FromStr; /// /// See [the book][book] for a more detailed comparison. /// -/// [book]: ../../book/borrow-and-asref.html +/// [book]: ../../book/first-edition/borrow-and-asref.html /// [`Borrow`]: ../../std/borrow/trait.Borrow.html /// /// **Note: this trait must not fail**. If the conversion can fail, use a @@ -305,7 +305,7 @@ pub trait Into: Sized { /// [`String`]: ../../std/string/struct.String.html /// [`Into`]: trait.Into.html /// [`from`]: trait.From.html#tymethod.from -/// [book]: ../../book/error-handling.html +/// [book]: ../../book/first-edition/error-handling.html #[stable(feature = "rust1", since = "1.0.0")] pub trait From: Sized { /// Performs the conversion. diff --git a/src/libcore/default.rs b/src/libcore/default.rs index 0d7c1672fb..244df1a996 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -126,32 +126,33 @@ pub trait Default: Sized { } macro_rules! default_impl { - ($t:ty, $v:expr) => { + ($t:ty, $v:expr, $doc:expr) => { #[stable(feature = "rust1", since = "1.0.0")] impl Default for $t { #[inline] + #[doc = $doc] fn default() -> $t { $v } } } } -default_impl! { (), () } -default_impl! { bool, false } -default_impl! { char, '\x00' } +default_impl! { (), (), "Returns the default value of `()`" } +default_impl! { bool, false, "Returns the default value of `false`" } +default_impl! { char, '\x00', "Returns the default value of `\\x00`" } -default_impl! { usize, 0 } -default_impl! { u8, 0 } -default_impl! { u16, 0 } -default_impl! { u32, 0 } -default_impl! { u64, 0 } -default_impl! { u128, 0 } +default_impl! { usize, 0, "Returns the default value of `0`" } +default_impl! { u8, 0, "Returns the default value of `0`" } +default_impl! { u16, 0, "Returns the default value of `0`" } +default_impl! { u32, 0, "Returns the default value of `0`" } +default_impl! { u64, 0, "Returns the default value of `0`" } +default_impl! { u128, 0, "Returns the default value of `0`" } -default_impl! { isize, 0 } -default_impl! { i8, 0 } -default_impl! { i16, 0 } -default_impl! { i32, 0 } -default_impl! { i64, 0 } -default_impl! { i128, 0 } +default_impl! { isize, 0, "Returns the default value of `0`" } +default_impl! { i8, 0, "Returns the default value of `0`" } +default_impl! { i16, 0, "Returns the default value of `0`" } +default_impl! { i32, 0, "Returns the default value of `0`" } +default_impl! { i64, 0, "Returns the default value of `0`" } +default_impl! { i128, 0, "Returns the default value of `0`" } -default_impl! { f32, 0.0f32 } -default_impl! { f64, 0.0f64 } +default_impl! { f32, 0.0f32, "Returns the default value of `0.0`" } +default_impl! { f64, 0.0f64, "Returns the default value of `0.0`" } diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs index 102e3c0bd7..322df6e5b4 100644 --- a/src/libcore/fmt/builders.rs +++ b/src/libcore/fmt/builders.rs @@ -49,9 +49,37 @@ impl<'a, 'b: 'a> fmt::Write for PadAdapter<'a, 'b> { } } -/// A struct to help with `fmt::Debug` implementations. +/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations. /// -/// Constructed by the `Formatter::debug_struct` method. +/// This is useful when you wish to output a formatted struct as a part of your +/// [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation. +/// +/// This can be constructed by the +/// [`Formatter::debug_struct`](struct.Formatter.html#method.debug_struct) +/// method. +/// +/// # Example +/// +/// ``` +/// use std::fmt; +/// +/// struct Foo { +/// bar: i32, +/// baz: String, +/// } +/// +/// impl fmt::Debug for Foo { +/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +/// fmt.debug_struct("Foo") +/// .field("bar", &self.bar) +/// .field("baz", &self.baz) +/// .finish() +/// } +/// } +/// +/// // prints "Foo { bar: 10, baz: "Hello World" }" +/// println!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() }); +/// ``` #[must_use] #[allow(missing_debug_implementations)] #[stable(feature = "debug_builders", since = "1.2.0")] @@ -116,9 +144,34 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { } } -/// A struct to help with `fmt::Debug` implementations. +/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations. +/// +/// This is useful when you wish to output a formatted tuple as a part of your +/// [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation. +/// +/// This can be constructed by the +/// [`Formatter::debug_tuple`](struct.Formatter.html#method.debug_tuple) +/// method. /// -/// Constructed by the `Formatter::debug_tuple` method. +/// # Example +/// +/// ``` +/// use std::fmt; +/// +/// struct Foo(i32, String); +/// +/// impl fmt::Debug for Foo { +/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +/// fmt.debug_tuple("Foo") +/// .field(&self.0) +/// .field(&self.1) +/// .finish() +/// } +/// } +/// +/// // prints "Foo(10, "Hello World")" +/// println!("{:?}", Foo(10, "Hello World".to_string())); +/// ``` #[must_use] #[allow(missing_debug_implementations)] #[stable(feature = "debug_builders", since = "1.2.0")] @@ -228,9 +281,31 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> { } } -/// A struct to help with `fmt::Debug` implementations. +/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations. +/// +/// This is useful when you wish to output a formatted set of items as a part +/// of your [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation. +/// +/// This can be constructed by the +/// [`Formatter::debug_set`](struct.Formatter.html#method.debug_set) +/// method. +/// +/// # Example /// -/// Constructed by the `Formatter::debug_set` method. +/// ``` +/// use std::fmt; +/// +/// struct Foo(Vec); +/// +/// impl fmt::Debug for Foo { +/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +/// fmt.debug_set().entries(self.0.iter()).finish() +/// } +/// } +/// +/// // prints "{10, 11}" +/// println!("{:?}", Foo(vec![10, 11])); +/// ``` #[must_use] #[allow(missing_debug_implementations)] #[stable(feature = "debug_builders", since = "1.2.0")] @@ -277,9 +352,31 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { } } -/// A struct to help with `fmt::Debug` implementations. +/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations. +/// +/// This is useful when you wish to output a formatted list of items as a part +/// of your [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation. +/// +/// This can be constructed by the +/// [`Formatter::debug_list`](struct.Formatter.html#method.debug_list) +/// method. +/// +/// # Example +/// +/// ``` +/// use std::fmt; +/// +/// struct Foo(Vec); /// -/// Constructed by the `Formatter::debug_list` method. +/// impl fmt::Debug for Foo { +/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +/// fmt.debug_list().entries(self.0.iter()).finish() +/// } +/// } +/// +/// // prints "[10, 11]" +/// println!("{:?}", Foo(vec![10, 11])); +/// ``` #[must_use] #[allow(missing_debug_implementations)] #[stable(feature = "debug_builders", since = "1.2.0")] @@ -326,9 +423,31 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { } } -/// A struct to help with `fmt::Debug` implementations. +/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations. +/// +/// This is useful when you wish to output a formatted map as a part of your +/// [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation. +/// +/// This can be constructed by the +/// [`Formatter::debug_map`](struct.Formatter.html#method.debug_map) +/// method. +/// +/// # Example +/// +/// ``` +/// use std::fmt; +/// +/// struct Foo(Vec<(String, i32)>); +/// +/// impl fmt::Debug for Foo { +/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +/// fmt.debug_map().entries(self.0.iter().map(|&(ref k, ref v)| (k, v))).finish() +/// } +/// } /// -/// Constructed by the `Formatter::debug_map` method. +/// // prints "{"A": 10, "B": 11}" +/// println!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])); +/// ``` #[must_use] #[allow(missing_debug_implementations)] #[stable(feature = "debug_builders", since = "1.2.0")] diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 8c3d3ce7d8..750e86114c 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -897,14 +897,11 @@ pub trait UpperExp { fn fmt(&self, f: &mut Formatter) -> Result; } -/// The `write` function takes an output stream, a precompiled format string, -/// and a list of arguments. The arguments will be formatted according to the -/// specified format string into the output stream provided. +/// The `write` function takes an output stream, and an `Arguments` struct +/// that can be precompiled with the `format_args!` macro. /// -/// # Arguments -/// -/// * output - the buffer to write output to -/// * args - the precompiled arguments generated by `format_args!` +/// The arguments will be formatted according to the specified format string +/// into the output stream provided. /// /// # Examples /// @@ -1630,13 +1627,13 @@ macro_rules! tuple { () => (); ( $($name:ident,)+ ) => ( #[stable(feature = "rust1", since = "1.0.0")] - impl<$($name:Debug),*> Debug for ($($name,)*) { + impl<$($name:Debug),*> Debug for ($($name,)*) where last_type!($($name,)+): ?Sized { #[allow(non_snake_case, unused_assignments, deprecated)] fn fmt(&self, f: &mut Formatter) -> Result { let mut builder = f.debug_tuple(""); let ($(ref $name,)*) = *self; $( - builder.field($name); + builder.field(&$name); )* builder.finish() @@ -1646,6 +1643,11 @@ macro_rules! tuple { ) } +macro_rules! last_type { + ($a:ident,) => { $a }; + ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; +} + tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index f68361e852..2000ba9146 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -99,7 +99,7 @@ use mem; #[allow(deprecated)] pub use self::sip::SipHasher; -#[unstable(feature = "sip_hash_13", issue = "29754")] +#[unstable(feature = "sip_hash_13", issue = "34767")] #[allow(deprecated)] pub use self::sip::{SipHasher13, SipHasher24}; @@ -559,7 +559,7 @@ mod impls { ( $($name:ident)+) => ( #[stable(feature = "rust1", since = "1.0.0")] - impl<$($name: Hash),*> Hash for ($($name,)*) { + impl<$($name: Hash),*> Hash for ($($name,)*) where last_type!($($name,)+): ?Sized { #[allow(non_snake_case)] fn hash(&self, state: &mut S) { let ($(ref $name,)*) = *self; @@ -569,6 +569,11 @@ mod impls { ); } + macro_rules! last_type { + ($a:ident,) => { $a }; + ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; + } + impl_hash_tuple! {} impl_hash_tuple! { A } impl_hash_tuple! { A B } diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 3566bbdebc..981ab5b6c4 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -572,7 +572,6 @@ extern "rust-intrinsic" { /// /// The `locality` argument must be a constant integer and is a temporal locality specifier /// ranging from (0) - no locality, to (3) - extremely local keep in cache - #[cfg(not(stage0))] pub fn prefetch_read_data(data: *const T, locality: i32); /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction /// if supported; otherwise, it is a noop. @@ -581,7 +580,6 @@ extern "rust-intrinsic" { /// /// The `locality` argument must be a constant integer and is a temporal locality specifier /// ranging from (0) - no locality, to (3) - extremely local keep in cache - #[cfg(not(stage0))] pub fn prefetch_write_data(data: *const T, locality: i32); /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction /// if supported; otherwise, it is a noop. @@ -590,7 +588,6 @@ extern "rust-intrinsic" { /// /// The `locality` argument must be a constant integer and is a temporal locality specifier /// ranging from (0) - no locality, to (3) - extremely local keep in cache - #[cfg(not(stage0))] pub fn prefetch_read_instruction(data: *const T, locality: i32); /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction /// if supported; otherwise, it is a noop. @@ -599,20 +596,9 @@ extern "rust-intrinsic" { /// /// The `locality` argument must be a constant integer and is a temporal locality specifier /// ranging from (0) - no locality, to (3) - extremely local keep in cache - #[cfg(not(stage0))] pub fn prefetch_write_instruction(data: *const T, locality: i32); } -// Empty bootstrap implementations for stage0 compilation -#[cfg(stage0)] -pub fn prefetch_read_data(_data: *const T, _locality: i32) { /* EMPTY */ } -#[cfg(stage0)] -pub fn prefetch_write_data(_data: *const T, _locality: i32) { /* EMPTY */ } -#[cfg(stage0)] -pub fn prefetch_read_instruction(_data: *const T, _locality: i32) { /* EMPTY */ } -#[cfg(stage0)] -pub fn prefetch_write_instruction(_data: *const T, _locality: i32) { /* EMPTY */ } - extern "rust-intrinsic" { pub fn atomic_fence(); @@ -1229,6 +1215,23 @@ extern "rust-intrinsic" { /// ``` pub fn ctlz(x: T) -> T; + /// Like `ctlz`, but extra-unsafe as it returns `undef` when + /// given an `x` with value `0`. + /// + /// # Examples + /// + /// ``` + /// #![feature(core_intrinsics)] + /// + /// use std::intrinsics::ctlz_nonzero; + /// + /// let x = 0b0001_1100_u8; + /// let num_leading = unsafe { ctlz_nonzero(x) }; + /// assert_eq!(num_leading, 3); + /// ``` + #[cfg(not(stage0))] + pub fn ctlz_nonzero(x: T) -> T; + /// Returns the number of trailing unset bits (zeroes) in an integer type `T`. /// /// # Examples @@ -1256,6 +1259,23 @@ extern "rust-intrinsic" { /// ``` pub fn cttz(x: T) -> T; + /// Like `cttz`, but extra-unsafe as it returns `undef` when + /// given an `x` with value `0`. + /// + /// # Examples + /// + /// ``` + /// #![feature(core_intrinsics)] + /// + /// use std::intrinsics::cttz_nonzero; + /// + /// let x = 0b0011_1000_u8; + /// let num_trailing = unsafe { cttz_nonzero(x) }; + /// assert_eq!(num_trailing, 3); + /// ``` + #[cfg(not(stage0))] + pub fn cttz_nonzero(x: T) -> T; + /// Reverses the bytes in an integer type `T`. pub fn bswap(x: T) -> T; diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 85149a0f57..d9887094fe 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -262,7 +262,7 @@ pub trait Iterator { /// Creates an iterator starting at the same point, but stepping by /// the given amount at each iteration. /// - /// Note that it will always return the first element of the range, + /// Note that it will always return the first element of the iterator, /// regardless of the step given. /// /// # Panics @@ -482,6 +482,53 @@ pub trait Iterator { Map{iter: self, f: f} } + /// Calls a closure on each element of an iterator. + /// + /// This is equivalent to using a [`for`] loop on the iterator, although + /// `break` and `continue` are not possible from a closure. It's generally + /// more idiomatic to use a `for` loop, but `for_each` may be more legible + /// when processing items at the end of longer iterator chains. In some + /// cases `for_each` may also be faster than a loop, because it will use + /// internal iteration on adaptors like `Chain`. + /// + /// [`for`]: ../../book/first-edition/loops.html#for + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iterator_for_each)] + /// + /// use std::sync::mpsc::channel; + /// + /// let (tx, rx) = channel(); + /// (0..5).map(|x| x * 2 + 1) + /// .for_each(move |x| tx.send(x).unwrap()); + /// + /// let v: Vec<_> = rx.iter().collect(); + /// assert_eq!(v, vec![1, 3, 5, 7, 9]); + /// ``` + /// + /// For such a small example, a `for` loop may be cleaner, but `for_each` + /// might be preferable to keep a functional style with longer iterators: + /// + /// ``` + /// #![feature(iterator_for_each)] + /// + /// (0..5).flat_map(|x| x * 100 .. x * 110) + /// .enumerate() + /// .filter(|&(i, x)| (i + x) % 3 == 0) + /// .for_each(|(i, x)| println!("{}:{}", i, x)); + /// ``` + #[inline] + #[unstable(feature = "iterator_for_each", issue = "42986")] + fn for_each(self, mut f: F) where + Self: Sized, F: FnMut(Self::Item), + { + self.fold((), move |(), item| f(item)); + } + /// Creates an iterator which uses a closure to determine if an element /// should be yielded. /// diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index c91fd16391..79e6b11bea 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -211,7 +211,7 @@ //! There's one more subtle bit here: the standard library contains an //! interesting implementation of [`IntoIterator`]: //! -//! ```ignore +//! ```ignore (only-for-syntax-highlight) //! impl IntoIterator for I //! ``` //! @@ -314,12 +314,6 @@ pub use self::iterator::Iterator; reason = "likely to be replaced by finer-grained traits", issue = "42168")] pub use self::range::Step; -#[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] -#[rustc_deprecated(since = "1.19.0", - reason = "replaced by `iter::StepBy`")] -#[allow(deprecated)] -pub use self::range::StepBy as DeprecatedStepBy; #[stable(feature = "rust1", since = "1.0.0")] pub use self::sources::{Repeat, repeat}; @@ -365,11 +359,19 @@ impl Iterator for Rev where I: DoubleEndedIterator { #[inline] fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + #[inline] fn find

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool { self.iter.rfind(predicate) } + + #[inline] + fn rposition

(&mut self, predicate: P) -> Option where + P: FnMut(Self::Item) -> bool + { + self.iter.position(predicate) + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 9aea4477fb..32c32e327e 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use convert::TryFrom; use mem; use ops::{self, Add, Sub}; use usize; @@ -21,22 +22,13 @@ use super::{FusedIterator, TrustedLen}; #[unstable(feature = "step_trait", reason = "likely to be replaced by finer-grained traits", issue = "42168")] -pub trait Step: PartialOrd + Sized { - /// Steps `self` if possible. - fn step(&self, by: &Self) -> Option; - +pub trait Step: Clone + PartialOrd + Sized { /// Returns the number of steps between two step objects. The count is /// inclusive of `start` and exclusive of `end`. /// /// Returns `None` if it is not possible to calculate `steps_between` /// without overflow. - fn steps_between(start: &Self, end: &Self, by: &Self) -> Option; - - /// Same as `steps_between`, but with a `by` of 1 - fn steps_between_by_one(start: &Self, end: &Self) -> Option; - - /// Tests whether this step is negative or not (going backwards) - fn is_negative(&self) -> bool; + fn steps_between(start: &Self, end: &Self) -> Option; /// Replaces this step with `1`, returning itself fn replace_one(&mut self) -> Self; @@ -49,6 +41,34 @@ pub trait Step: PartialOrd + Sized { /// Subtracts one to this step, returning the result fn sub_one(&self) -> Self; + + /// Add an usize, returning None on overflow + fn add_usize(&self, n: usize) -> Option; +} + +// These are still macro-generated because the integer literals resolve to different types. +macro_rules! step_identical_methods { + () => { + #[inline] + fn replace_one(&mut self) -> Self { + mem::replace(self, 1) + } + + #[inline] + fn replace_zero(&mut self) -> Self { + mem::replace(self, 0) + } + + #[inline] + fn add_one(&self) -> Self { + Add::add(*self, 1) + } + + #[inline] + fn sub_one(&self) -> Self { + Sub::sub(*self, 1) + } + } } macro_rules! step_impl_unsigned { @@ -57,128 +77,67 @@ macro_rules! step_impl_unsigned { reason = "likely to be replaced by finer-grained traits", issue = "42168")] impl Step for $t { - #[inline] - fn step(&self, by: &$t) -> Option<$t> { - (*self).checked_add(*by) - } #[inline] #[allow(trivial_numeric_casts)] - fn steps_between(start: &$t, end: &$t, by: &$t) -> Option { - if *by == 0 { return None; } + fn steps_between(start: &$t, end: &$t) -> Option { if *start < *end { // Note: We assume $t <= usize here - let diff = (*end - *start) as usize; - let by = *by as usize; - if diff % by > 0 { - Some(diff / by + 1) - } else { - Some(diff / by) - } + Some((*end - *start) as usize) } else { Some(0) } } #[inline] - fn is_negative(&self) -> bool { - false - } - - #[inline] - fn replace_one(&mut self) -> Self { - mem::replace(self, 1) - } - - #[inline] - fn replace_zero(&mut self) -> Self { - mem::replace(self, 0) - } - - #[inline] - fn add_one(&self) -> Self { - Add::add(*self, 1) - } - - #[inline] - fn sub_one(&self) -> Self { - Sub::sub(*self, 1) + fn add_usize(&self, n: usize) -> Option { + match <$t>::try_from(n) { + Ok(n_as_t) => self.checked_add(n_as_t), + Err(_) => None, + } } - #[inline] - fn steps_between_by_one(start: &Self, end: &Self) -> Option { - Self::steps_between(start, end, &1) - } + step_identical_methods!(); } )*) } macro_rules! step_impl_signed { - ($($t:ty)*) => ($( + ($( [$t:ty : $unsigned:ty] )*) => ($( #[unstable(feature = "step_trait", reason = "likely to be replaced by finer-grained traits", issue = "42168")] impl Step for $t { - #[inline] - fn step(&self, by: &$t) -> Option<$t> { - (*self).checked_add(*by) - } #[inline] #[allow(trivial_numeric_casts)] - fn steps_between(start: &$t, end: &$t, by: &$t) -> Option { - if *by == 0 { return None; } - let diff: usize; - let by_u: usize; - if *by > 0 { - if *start >= *end { - return Some(0); - } + fn steps_between(start: &$t, end: &$t) -> Option { + if *start < *end { // Note: We assume $t <= isize here // Use .wrapping_sub and cast to usize to compute the // difference that may not fit inside the range of isize. - diff = (*end as isize).wrapping_sub(*start as isize) as usize; - by_u = *by as usize; + Some((*end as isize).wrapping_sub(*start as isize) as usize) } else { - if *start <= *end { - return Some(0); - } - diff = (*start as isize).wrapping_sub(*end as isize) as usize; - by_u = (*by as isize).wrapping_mul(-1) as usize; - } - if diff % by_u > 0 { - Some(diff / by_u + 1) - } else { - Some(diff / by_u) + Some(0) } } #[inline] - fn is_negative(&self) -> bool { - *self < 0 - } - - #[inline] - fn replace_one(&mut self) -> Self { - mem::replace(self, 1) - } - - #[inline] - fn replace_zero(&mut self) -> Self { - mem::replace(self, 0) - } - - #[inline] - fn add_one(&self) -> Self { - Add::add(*self, 1) - } - - #[inline] - fn sub_one(&self) -> Self { - Sub::sub(*self, 1) + fn add_usize(&self, n: usize) -> Option { + match <$unsigned>::try_from(n) { + Ok(n_as_unsigned) => { + // Wrapping in unsigned space handles cases like + // `-120_i8.add_usize(200) == Some(80_i8)`, + // even though 200_usize is out of range for i8. + let wrapped = (*self as $unsigned).wrapping_add(n_as_unsigned) as $t; + if wrapped >= *self { + Some(wrapped) + } else { + None // Addition overflowed + } + } + Err(_) => None, + } } - #[inline] - fn steps_between_by_one(start: &Self, end: &Self) -> Option { - Self::steps_between(start, end, &1) - } + step_identical_methods!(); } )*) } @@ -190,273 +149,32 @@ macro_rules! step_impl_no_between { issue = "42168")] impl Step for $t { #[inline] - fn step(&self, by: &$t) -> Option<$t> { - (*self).checked_add(*by) - } - #[inline] - fn steps_between(_a: &$t, _b: &$t, _by: &$t) -> Option { + fn steps_between(_start: &Self, _end: &Self) -> Option { None } #[inline] - #[allow(unused_comparisons)] - fn is_negative(&self) -> bool { - *self < 0 + fn add_usize(&self, n: usize) -> Option { + self.checked_add(n as $t) } - #[inline] - fn replace_one(&mut self) -> Self { - mem::replace(self, 1) - } - - #[inline] - fn replace_zero(&mut self) -> Self { - mem::replace(self, 0) - } - - #[inline] - fn add_one(&self) -> Self { - Add::add(*self, 1) - } - - #[inline] - fn sub_one(&self) -> Self { - Sub::sub(*self, 1) - } - - #[inline] - fn steps_between_by_one(start: &Self, end: &Self) -> Option { - Self::steps_between(start, end, &1) - } + step_identical_methods!(); } )*) } step_impl_unsigned!(usize u8 u16 u32); -step_impl_signed!(isize i8 i16 i32); +step_impl_signed!([isize: usize] [i8: u8] [i16: u16] [i32: u32]); #[cfg(target_pointer_width = "64")] step_impl_unsigned!(u64); #[cfg(target_pointer_width = "64")] -step_impl_signed!(i64); +step_impl_signed!([i64: u64]); // If the target pointer width is not 64-bits, we // assume here that it is less than 64-bits. #[cfg(not(target_pointer_width = "64"))] step_impl_no_between!(u64 i64); step_impl_no_between!(u128 i128); -/// An adapter for stepping range iterators by a custom amount. -/// -/// The resulting iterator handles overflow by stopping. The `A` -/// parameter is the type being iterated over, while `R` is the range -/// type (usually one of `std::ops::{Range, RangeFrom, RangeInclusive}`. -#[derive(Clone, Debug)] -#[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] -#[rustc_deprecated(since = "1.19.0", - reason = "replaced by `iter::StepBy`")] -#[allow(deprecated)] -pub struct StepBy { - step_by: A, - range: R, -} - -impl ops::RangeFrom { - /// Creates an iterator starting at the same point, but stepping by - /// the given amount at each iteration. - /// - /// # Examples - /// - /// ``` - /// #![feature(step_by)] - /// fn main() { - /// let result: Vec<_> = (0..).step_by(2).take(5).collect(); - /// assert_eq!(result, vec![0, 2, 4, 6, 8]); - /// } - /// ``` - #[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] - #[rustc_deprecated(since = "1.19.0", - reason = "replaced by `Iterator::step_by`")] - #[allow(deprecated)] - pub fn step_by(self, by: A) -> StepBy { - StepBy { - step_by: by, - range: self - } - } -} - -impl ops::Range { - /// Creates an iterator with the same range, but stepping by the - /// given amount at each iteration. - /// - /// The resulting iterator handles overflow by stopping. - /// - /// # Examples - /// - /// ``` - /// #![feature(step_by)] - /// fn main() { - /// let result: Vec<_> = (0..10).step_by(2).collect(); - /// assert_eq!(result, vec![0, 2, 4, 6, 8]); - /// } - /// ``` - #[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] - #[rustc_deprecated(since = "1.19.0", - reason = "replaced by `Iterator::step_by`")] - #[allow(deprecated)] - pub fn step_by(self, by: A) -> StepBy { - StepBy { - step_by: by, - range: self - } - } -} - -impl ops::RangeInclusive { - /// Creates an iterator with the same range, but stepping by the - /// given amount at each iteration. - /// - /// The resulting iterator handles overflow by stopping. - /// - /// # Examples - /// - /// ``` - /// #![feature(step_by, inclusive_range_syntax)] - /// - /// let result: Vec<_> = (0...10).step_by(2).collect(); - /// assert_eq!(result, vec![0, 2, 4, 6, 8, 10]); - /// ``` - #[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] - #[rustc_deprecated(since = "1.19.0", - reason = "replaced by `Iterator::step_by`")] - #[allow(deprecated)] - pub fn step_by(self, by: A) -> StepBy { - StepBy { - step_by: by, - range: self - } - } -} - -#[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] -#[allow(deprecated)] -impl Iterator for StepBy> where - A: Clone, - for<'a> &'a A: Add<&'a A, Output = A> -{ - type Item = A; - - #[inline] - fn next(&mut self) -> Option { - let mut n = &self.range.start + &self.step_by; - mem::swap(&mut n, &mut self.range.start); - Some(n) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - (usize::MAX, None) // Too bad we can't specify an infinite lower bound - } -} - -#[unstable(feature = "fused", issue = "35602")] -#[allow(deprecated)] -impl FusedIterator for StepBy> - where A: Clone, for<'a> &'a A: Add<&'a A, Output = A> {} - -#[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] -#[allow(deprecated)] -impl Iterator for StepBy> { - type Item = A; - - #[inline] - fn next(&mut self) -> Option { - let rev = self.step_by.is_negative(); - if (rev && self.range.start > self.range.end) || - (!rev && self.range.start < self.range.end) - { - match self.range.start.step(&self.step_by) { - Some(mut n) => { - mem::swap(&mut self.range.start, &mut n); - Some(n) - }, - None => { - let mut n = self.range.end.clone(); - mem::swap(&mut self.range.start, &mut n); - Some(n) - } - } - } else { - None - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - match Step::steps_between(&self.range.start, - &self.range.end, - &self.step_by) { - Some(hint) => (hint, Some(hint)), - None => (0, None) - } - } -} - -#[unstable(feature = "fused", issue = "35602")] -#[allow(deprecated)] -impl FusedIterator for StepBy> {} - -#[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", - issue = "28237")] -#[allow(deprecated)] -impl Iterator for StepBy> { - type Item = A; - - #[inline] - fn next(&mut self) -> Option { - let rev = self.step_by.is_negative(); - - if (rev && self.range.start >= self.range.end) || - (!rev && self.range.start <= self.range.end) - { - match self.range.start.step(&self.step_by) { - Some(n) => { - Some(mem::replace(&mut self.range.start, n)) - }, - None => { - let last = self.range.start.replace_one(); - self.range.end.replace_zero(); - self.step_by.replace_one(); - Some(last) - }, - } - } - else { - None - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - match Step::steps_between(&self.range.start, - &self.range.end, - &self.step_by) { - Some(hint) => (hint.saturating_add(1), hint.checked_add(1)), - None => (0, None) - } - } -} - -#[unstable(feature = "fused", issue = "35602")] -#[allow(deprecated)] -impl FusedIterator for StepBy> {} - macro_rules! range_exact_iter_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] @@ -490,9 +208,7 @@ macro_rules! range_incl_trusted_len_impl { } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for ops::Range where - for<'a> &'a A: Add<&'a A, Output = A> -{ +impl Iterator for ops::Range { type Item = A; #[inline] @@ -508,11 +224,24 @@ impl Iterator for ops::Range where #[inline] fn size_hint(&self) -> (usize, Option) { - match Step::steps_between_by_one(&self.start, &self.end) { + match Step::steps_between(&self.start, &self.end) { Some(hint) => (hint, Some(hint)), None => (0, None) } } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + if let Some(plus_n) = self.start.add_usize(n) { + if plus_n < self.end { + self.start = plus_n.add_one(); + return Some(plus_n) + } + } + + self.start = self.end.clone(); + None + } } // These macros generate `ExactSizeIterator` impls for various range types. @@ -530,10 +259,7 @@ range_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64); range_incl_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64); #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for ops::Range where - for<'a> &'a A: Add<&'a A, Output = A>, - for<'a> &'a A: Sub<&'a A, Output = A> -{ +impl DoubleEndedIterator for ops::Range { #[inline] fn next_back(&mut self) -> Option { if self.start < self.end { @@ -546,13 +272,10 @@ impl DoubleEndedIterator for ops::Range where } #[unstable(feature = "fused", issue = "35602")] -impl FusedIterator for ops::Range - where A: Step, for<'a> &'a A: Add<&'a A, Output = A> {} +impl FusedIterator for ops::Range {} #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for ops::RangeFrom where - for<'a> &'a A: Add<&'a A, Output = A> -{ +impl Iterator for ops::RangeFrom { type Item = A; #[inline] @@ -566,16 +289,20 @@ impl Iterator for ops::RangeFrom where fn size_hint(&self) -> (usize, Option) { (usize::MAX, None) } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + let plus_n = self.start.add_usize(n).expect("overflow in RangeFrom::nth"); + self.start = plus_n.add_one(); + Some(plus_n) + } } #[unstable(feature = "fused", issue = "35602")] -impl FusedIterator for ops::RangeFrom - where A: Step, for<'a> &'a A: Add<&'a A, Output = A> {} +impl FusedIterator for ops::RangeFrom {} #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl Iterator for ops::RangeInclusive where - for<'a> &'a A: Add<&'a A, Output = A> -{ +impl Iterator for ops::RangeInclusive { type Item = A; #[inline] @@ -602,18 +329,39 @@ impl Iterator for ops::RangeInclusive where return (0, Some(0)); } - match Step::steps_between_by_one(&self.start, &self.end) { + match Step::steps_between(&self.start, &self.end) { Some(hint) => (hint.saturating_add(1), hint.checked_add(1)), None => (0, None), } } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + if let Some(plus_n) = self.start.add_usize(n) { + use cmp::Ordering::*; + + match plus_n.partial_cmp(&self.end) { + Some(Less) => { + self.start = plus_n.add_one(); + return Some(plus_n) + } + Some(Equal) => { + self.start.replace_one(); + self.end.replace_zero(); + return Some(plus_n) + } + _ => {} + } + } + + self.start.replace_one(); + self.end.replace_zero(); + None + } } #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl DoubleEndedIterator for ops::RangeInclusive where - for<'a> &'a A: Add<&'a A, Output = A>, - for<'a> &'a A: Sub<&'a A, Output = A> -{ +impl DoubleEndedIterator for ops::RangeInclusive { #[inline] fn next_back(&mut self) -> Option { use cmp::Ordering::*; @@ -634,5 +382,4 @@ impl DoubleEndedIterator for ops::RangeInclusive where } #[unstable(feature = "fused", issue = "35602")] -impl FusedIterator for ops::RangeInclusive - where A: Step, for<'a> &'a A: Add<&'a A, Output = A> {} +impl FusedIterator for ops::RangeInclusive {} diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 015cc150dc..d35aa02668 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -732,7 +732,7 @@ macro_rules! float_sum_product { )*) } -integer_sum_product! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } +integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize } float_sum_product! { f32 f64 } /// An iterator adapter that produces output as long as the underlying @@ -798,6 +798,23 @@ impl Iterator for ResultShunt impl Sum> for Result where T: Sum, { + /// Takes each element in the `Iterator`: if it is an `Err`, no further + /// elements are taken, and the `Err` is returned. Should no `Err` occur, + /// the sum of all elements is returned. + /// + /// # Examples + /// + /// This sums up every integer in a vector, rejecting the sum if a negative + /// element is encountered: + /// + /// ``` + /// let v = vec![1, 2]; + /// let res: Result = v.iter().map(|&x: &i32| + /// if x < 0 { Err("Negative element found") } + /// else { Ok(x) } + /// ).sum(); + /// assert_eq!(res, Ok(3)); + /// ``` fn sum(iter: I) -> Result where I: Iterator>, { @@ -809,6 +826,9 @@ impl Sum> for Result impl Product> for Result where T: Product, { + /// Takes each element in the `Iterator`: if it is an `Err`, no further + /// elements are taken, and the `Err` is returned. Should no `Err` occur, + /// the product of all elements is returned. fn product(iter: I) -> Result where I: Iterator>, { @@ -819,7 +839,7 @@ impl Product> for Result /// An iterator that always continues to yield `None` when exhausted. /// /// Calling next on a fused iterator that has returned `None` once is guaranteed -/// to return [`None`] again. This trait is should be implemented by all iterators +/// to return [`None`] again. This trait should be implemented by all iterators /// that behave this way because it allows for some significant optimizations. /// /// Note: In general, you should not use `FusedIterator` in generic bounds if diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index b6ab1ecaf4..e8e31ffea0 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -36,12 +36,12 @@ //! These functions are often provided by the system libc, but can also be //! provided by the [rlibc crate](https://crates.io/crates/rlibc). //! -//! * `rust_begin_panic` - This function takes three arguments, a -//! `fmt::Arguments`, a `&'static str`, and a `u32`. These three arguments +//! * `rust_begin_panic` - This function takes four arguments, a +//! `fmt::Arguments`, a `&'static str`, and two `u32`'s. These four arguments //! dictate the panic message, the file at which panic was invoked, and the -//! line. It is up to consumers of this core library to define this panic -//! function; it is only required to never return. This requires a `lang` -//! attribute named `panic_fmt`. +//! line and column inside the file. It is up to consumers of this core +//! library to define this panic function; it is only required to never +//! return. This requires a `lang` attribute named `panic_fmt`. //! //! * `rust_eh_personality` - is used by the failure mechanisms of the //! compiler. This is often mapped to GCC's personality function, but crates @@ -70,7 +70,6 @@ #![feature(allow_internal_unstable)] #![feature(asm)] #![feature(associated_type_defaults)] -#![feature(associated_consts)] #![feature(cfg_target_feature)] #![feature(cfg_target_has_atomic)] #![feature(concat_idents)] @@ -94,6 +93,8 @@ #![feature(untagged_unions)] #![feature(unwind_attributes)] +#![cfg_attr(stage0, feature(associated_consts))] + #[prelude_import] #[allow(unused)] use prelude::v1::*; diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index bf4e414d41..684b81a27f 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -8,6 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[macro_export] +// This stability attribute is totally useless. +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(stage0)] +macro_rules! __rust_unstable_column { + () => { + column!() + } +} + /// Entry point of thread panic, for details, see std::macros #[macro_export] #[allow_internal_unstable] @@ -17,16 +27,18 @@ macro_rules! panic { panic!("explicit panic") ); ($msg:expr) => ({ - static _MSG_FILE_LINE: (&'static str, &'static str, u32) = ($msg, file!(), line!()); - $crate::panicking::panic(&_MSG_FILE_LINE) + static _MSG_FILE_LINE_COL: (&'static str, &'static str, u32, u32) = + ($msg, file!(), line!(), __rust_unstable_column!()); + $crate::panicking::panic(&_MSG_FILE_LINE_COL) }); ($fmt:expr, $($arg:tt)*) => ({ // The leading _'s are to avoid dead code warnings if this is // used inside a dead function. Just `#[allow(dead_code)]` is // insufficient, since the user may have // `#[forbid(dead_code)]` and which cannot be overridden. - static _FILE_LINE: (&'static str, u32) = (file!(), line!()); - $crate::panicking::panic_fmt(format_args!($fmt, $($arg)*), &_FILE_LINE) + static _MSG_FILE_LINE_COL: (&'static str, u32, u32) = + (file!(), line!(), __rust_unstable_column!()); + $crate::panicking::panic_fmt(format_args!($fmt, $($arg)*), &_MSG_FILE_LINE_COL) }); } @@ -35,6 +47,8 @@ macro_rules! panic { /// This will invoke the [`panic!`] macro if the provided expression cannot be /// evaluated to `true` at runtime. /// +/// # Uses +/// /// Assertions are always checked in both debug and release builds, and cannot /// be disabled. See [`debug_assert!`] for assertions that are not enabled in /// release builds by default. @@ -45,12 +59,14 @@ 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 +/// # Custom Messages +/// +/// This macro has a second form, where a custom panic message can /// be provided with or without arguments for formatting. /// /// [`panic!`]: macro.panic.html /// [`debug_assert!`]: macro.debug_assert.html -/// [testing]: ../book/testing.html +/// [testing]: ../book/first-edition/testing.html /// /// # Examples /// @@ -85,14 +101,15 @@ macro_rules! assert { ); } -/// Asserts that two expressions are equal to each other. +/// Asserts that two expressions are equal to each other (using [`PartialEq`]). /// /// 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 +/// Like [`assert!`], this macro has a second form, where a custom /// panic message can be provided. /// +/// [`PartialEq`]: cmp/trait.PartialEq.html /// [`assert!`]: macro.assert.html /// /// # Examples @@ -111,8 +128,9 @@ macro_rules! assert_eq { match (&$left, &$right) { (left_val, right_val) => { if !(*left_val == *right_val) { - panic!("assertion failed: `(left == right)` \ - (left: `{:?}`, right: `{:?}`)", left_val, right_val) + panic!(r#"assertion failed: `(left == right)` + left: `{:?}`, + right: `{:?}`"#, left_val, right_val) } } } @@ -121,8 +139,9 @@ macro_rules! assert_eq { match (&($left), &($right)) { (left_val, right_val) => { if !(*left_val == *right_val) { - panic!("assertion failed: `(left == right)` \ - (left: `{:?}`, right: `{:?}`): {}", left_val, right_val, + panic!(r#"assertion failed: `(left == right)` + left: `{:?}`, + right: `{:?}`: {}"#, left_val, right_val, format_args!($($arg)+)) } } @@ -130,14 +149,15 @@ macro_rules! assert_eq { }); } -/// Asserts that two expressions are not equal to each other. +/// Asserts that two expressions are not equal to each other (using [`PartialEq`]). /// /// 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 +/// Like [`assert!`], this macro has a second form, where a custom /// panic message can be provided. /// +/// [`PartialEq`]: cmp/trait.PartialEq.html /// [`assert!`]: macro.assert.html /// /// # Examples @@ -156,8 +176,9 @@ macro_rules! assert_ne { match (&$left, &$right) { (left_val, right_val) => { if *left_val == *right_val { - panic!("assertion failed: `(left != right)` \ - (left: `{:?}`, right: `{:?}`)", left_val, right_val) + panic!(r#"assertion failed: `(left != right)` + left: `{:?}`, + right: `{:?}`"#, left_val, right_val) } } } @@ -166,8 +187,9 @@ macro_rules! assert_ne { match (&($left), &($right)) { (left_val, right_val) => { if *left_val == *right_val { - panic!("assertion failed: `(left != right)` \ - (left: `{:?}`, right: `{:?}`): {}", left_val, right_val, + panic!(r#"assertion failed: `(left != right)` + left: `{:?}`, + right: `{:?}`: {}"#, left_val, right_val, format_args!($($arg)+)) } } @@ -183,6 +205,8 @@ macro_rules! assert_ne { /// Like [`assert!`], this macro also has a second version, where a custom panic /// message can be provided. /// +/// # Uses +/// /// Unlike [`assert!`], `debug_assert!` statements are only enabled in non /// optimized builds by default. An optimized build will omit all /// `debug_assert!` statements unless `-C debug-assertions` is passed to the @@ -448,7 +472,7 @@ macro_rules! writeln { /// /// # Panics /// -/// This will always panic. +/// This will always [panic!](macro.panic.html) /// /// # Examples /// @@ -542,7 +566,8 @@ macro_rules! unreachable { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! unimplemented { - () => (panic!("not yet implemented")) + () => (panic!("not yet implemented")); + ($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)*))); } /// Built-in macros to the compiler itself. @@ -553,6 +578,17 @@ macro_rules! unimplemented { /// /// For more information, see documentation for `std`'s macros. mod builtin { + + /// Unconditionally causes compilation to fail with the given error message when encountered. + /// + /// For more information, see the [RFC]. + /// + /// [RFC]: https://github.com/rust-lang/rfcs/blob/master/text/1695-add-error-macro.md + #[stable(feature = "compile_error_macro", since = "1.20.0")] + #[macro_export] + #[cfg(dox)] + macro_rules! compile_error { ($msg:expr) => ({ /* compiler built-in */ }) } + /// The core macro for formatted string creation & output. /// /// For more information, see the documentation for [`std::format_args!`]. diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 6602fccd58..e8fd729b63 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -85,7 +85,7 @@ impl !Send for *mut T { } /// // be made into an object /// ``` /// -/// [trait object]: ../../book/trait-objects.html +/// [trait object]: ../../book/first-edition/trait-objects.html #[stable(feature = "rust1", since = "1.0.0")] #[lang = "sized"] #[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"] @@ -205,7 +205,7 @@ pub trait Unsize { /// but not `Copy`. /// /// [`Clone`] is a supertrait of `Copy`, so everything which is `Copy` must also implement -/// [`Clone`]. If a type is `Copy` then its [`Clone`] implementation need only return `*self` +/// [`Clone`]. If a type is `Copy` then its [`Clone`] implementation only needs to return `*self` /// (see the example above). /// /// ## When can my type be `Copy`? @@ -434,7 +434,7 @@ macro_rules! impls{ /// example, here is a struct `Slice` that has two pointers of type `*const T`, /// presumably pointing into an array somewhere: /// -/// ```ignore +/// ```compile_fail,E0392 /// struct Slice<'a, T> { /// start: *const T, /// end: *const T, @@ -493,7 +493,7 @@ macro_rules! impls{ /// types. We track the Rust type using a phantom type parameter on /// the struct `ExternalResource` which wraps a handle. /// -/// [FFI]: ../../book/ffi.html +/// [FFI]: ../../book/first-edition/ffi.html /// /// ``` /// # #![allow(dead_code)] diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index d11ad76d65..d891796c1d 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -109,7 +109,7 @@ pub use intrinsics::transmute; /// [`Clone`][clone]. You need the value's destructor to run only once, /// because a double `free` is undefined behavior. /// -/// An example is the definition of [`mem::swap`][swap] in this module: +/// An example is a possible implementation of [`mem::swap`][swap]: /// /// ``` /// use std::mem; @@ -328,11 +328,18 @@ pub fn align_of_val(val: &T) -> usize { /// /// Here's an example of how a collection might make use of needs_drop: /// -/// ```ignore +/// ``` /// #![feature(needs_drop)] /// use std::{mem, ptr}; /// -/// pub struct MyCollection { /* ... */ } +/// pub struct MyCollection { +/// # data: [T; 1], +/// /* ... */ +/// } +/// # impl MyCollection { +/// # fn iter_mut(&mut self) -> &mut [T] { &mut self.data } +/// # fn free_buffer(&mut self) {} +/// # } /// /// impl Drop for MyCollection { /// fn drop(&mut self) { @@ -499,18 +506,7 @@ pub unsafe fn uninitialized() -> T { #[stable(feature = "rust1", since = "1.0.0")] pub fn swap(x: &mut T, y: &mut T) { unsafe { - // Give ourselves some scratch space to work with - let mut t: T = uninitialized(); - - // Perform the swap, `&mut` pointers never alias - ptr::copy_nonoverlapping(&*x, &mut t, 1); - ptr::copy_nonoverlapping(&*y, x, 1); - ptr::copy_nonoverlapping(&t, y, 1); - - // y and t now point to the same thing, but we need to completely - // forget `t` because we do not want to run the destructor for `T` - // on its value, which is still owned somewhere outside this function. - forget(t); + ptr::swap_nonoverlapping(x, y, 1); } } @@ -534,7 +530,7 @@ pub fn swap(x: &mut T, y: &mut T) { /// `replace` allows consumption of a struct field by replacing it with another value. /// Without `replace` you can run into issues like these: /// -/// ```ignore +/// ```compile_fail,E0507 /// struct Buffer { buf: Vec } /// /// impl Buffer { @@ -604,7 +600,7 @@ pub fn replace(dest: &mut T, mut src: T) -> T { /// /// Borrows are based on lexical scope, so this produces an error: /// -/// ```ignore +/// ```compile_fail,E0502 /// let mut v = vec![1, 2, 3]; /// let x = &v[0]; /// @@ -799,7 +795,6 @@ pub fn discriminant(v: &T) -> Discriminant { /// the type: /// /// ```rust -/// # #![feature(manually_drop)] /// use std::mem::ManuallyDrop; /// struct Peach; /// struct Banana; @@ -825,7 +820,7 @@ pub fn discriminant(v: &T) -> Discriminant { /// } /// } /// ``` -#[unstable(feature = "manually_drop", issue = "40673")] +#[stable(feature = "manually_drop", since = "1.20.0")] #[allow(unions_with_drop_fields)] pub union ManuallyDrop{ value: T } @@ -835,11 +830,10 @@ impl ManuallyDrop { /// # Examples /// /// ```rust - /// # #![feature(manually_drop)] /// use std::mem::ManuallyDrop; /// ManuallyDrop::new(Box::new(())); /// ``` - #[unstable(feature = "manually_drop", issue = "40673")] + #[stable(feature = "manually_drop", since = "1.20.0")] #[inline] pub fn new(value: T) -> ManuallyDrop { ManuallyDrop { value: value } @@ -850,12 +844,11 @@ impl ManuallyDrop { /// # Examples /// /// ```rust - /// # #![feature(manually_drop)] /// use std::mem::ManuallyDrop; /// let x = ManuallyDrop::new(Box::new(())); /// let _: Box<()> = ManuallyDrop::into_inner(x); /// ``` - #[unstable(feature = "manually_drop", issue = "40673")] + #[stable(feature = "manually_drop", since = "1.20.0")] #[inline] pub fn into_inner(slot: ManuallyDrop) -> T { unsafe { @@ -870,14 +863,14 @@ impl ManuallyDrop { /// This function runs the destructor of the contained value and thus the wrapped value /// now represents uninitialized data. It is up to the user of this method to ensure the /// uninitialized data is not actually used. - #[unstable(feature = "manually_drop", issue = "40673")] + #[stable(feature = "manually_drop", since = "1.20.0")] #[inline] pub unsafe fn drop(slot: &mut ManuallyDrop) { ptr::drop_in_place(&mut slot.value) } } -#[unstable(feature = "manually_drop", issue = "40673")] +#[stable(feature = "manually_drop", since = "1.20.0")] impl ::ops::Deref for ManuallyDrop { type Target = T; #[inline] @@ -888,7 +881,7 @@ impl ::ops::Deref for ManuallyDrop { } } -#[unstable(feature = "manually_drop", issue = "40673")] +#[stable(feature = "manually_drop", since = "1.20.0")] impl ::ops::DerefMut for ManuallyDrop { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { @@ -898,7 +891,7 @@ impl ::ops::DerefMut for ManuallyDrop { } } -#[unstable(feature = "manually_drop", issue = "40673")] +#[stable(feature = "manually_drop", since = "1.20.0")] impl ::fmt::Debug for ManuallyDrop { fn fmt(&self, fmt: &mut ::fmt::Formatter) -> ::fmt::Result { unsafe { diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 91ca213e96..ebc30dc8b6 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -205,18 +205,25 @@ impl Float for f32 { } } - /// Returns `true` if `self` is positive, including `+0.0` and - /// `Float::infinity()`. + /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with + /// positive sign bit and positive infinity. #[inline] fn is_sign_positive(self) -> bool { - self > 0.0 || (1.0 / self) == INFINITY + !self.is_sign_negative() } - /// Returns `true` if `self` is negative, including `-0.0` and - /// `Float::neg_infinity()`. + /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with + /// negative sign bit and negative infinity. #[inline] fn is_sign_negative(self) -> bool { - self < 0.0 || (1.0 / self) == NEG_INFINITY + // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus + // applies to zeros and NaNs as well. + #[repr(C)] + union F32Bytes { + f: f32, + b: u32 + } + unsafe { F32Bytes { f: self }.b & 0x8000_0000 != 0 } } /// Returns the reciprocal (multiplicative inverse) of the number. @@ -242,4 +249,32 @@ impl Float for f32 { let value: f32 = consts::PI; self * (value / 180.0f32) } + + /// Returns the maximum of the two numbers. + #[inline] + fn max(self, other: f32) -> f32 { + // IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the + // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it + // is either x or y, canonicalized (this means results might differ among implementations). + // When either x or y is a signalingNaN, then the result is according to 6.2. + // + // Since we do not support sNaN in Rust yet, we do not need to handle them. + // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by + // multiplying by 1.0. Should switch to the `canonicalize` when it works. + (if self < other || self.is_nan() { other } else { self }) * 1.0 + } + + /// Returns the minimum of the two numbers. + #[inline] + fn min(self, other: f32) -> f32 { + // IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the + // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it + // is either x or y, canonicalized (this means results might differ among implementations). + // When either x or y is a signalingNaN, then the result is according to 6.2. + // + // Since we do not support sNaN in Rust yet, we do not need to handle them. + // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by + // multiplying by 1.0. Should switch to the `canonicalize` when it works. + (if self < other || other.is_nan() { self } else { other }) * 1.0 + } } diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 7d6d6cef04..1a1fe4d86e 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -205,18 +205,23 @@ impl Float for f64 { } } - /// Returns `true` if `self` is positive, including `+0.0` and - /// `Float::infinity()`. + /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with + /// positive sign bit and positive infinity. #[inline] fn is_sign_positive(self) -> bool { - self > 0.0 || (1.0 / self) == INFINITY + !self.is_sign_negative() } - /// Returns `true` if `self` is negative, including `-0.0` and - /// `Float::neg_infinity()`. + /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with + /// negative sign bit and negative infinity. #[inline] fn is_sign_negative(self) -> bool { - self < 0.0 || (1.0 / self) == NEG_INFINITY + #[repr(C)] + union F64Bytes { + f: f64, + b: u64 + } + unsafe { F64Bytes { f: self }.b & 0x8000_0000_0000_0000 != 0 } } /// Returns the reciprocal (multiplicative inverse) of the number. @@ -242,4 +247,32 @@ impl Float for f64 { let value: f64 = consts::PI; self * (value / 180.0) } + + /// Returns the maximum of the two numbers. + #[inline] + fn max(self, other: f64) -> f64 { + // IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the + // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it + // is either x or y, canonicalized (this means results might differ among implementations). + // When either x or y is a signalingNaN, then the result is according to 6.2. + // + // Since we do not support sNaN in Rust yet, we do not need to handle them. + // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by + // multiplying by 1.0. Should switch to the `canonicalize` when it works. + (if self < other || self.is_nan() { other } else { self }) * 1.0 + } + + /// Returns the minimum of the two numbers. + #[inline] + fn min(self, other: f64) -> f64 { + // IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the + // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it + // is either x or y, canonicalized (this means results might differ among implementations). + // When either x or y is a signalingNaN, then the result is according to 6.2. + // + // Since we do not support sNaN in Rust yet, we do not need to handle them. + // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by + // multiplying by 1.0. Should switch to the `canonicalize` when it works. + (if self < other || other.is_nan() { self } else { other }) * 1.0 + } } diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index be093cca6a..cbd59ed371 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -15,7 +15,6 @@ use convert::TryFrom; use fmt; use intrinsics; -use mem::size_of; use str::FromStr; /// Provides intentionally-wrapped arithmetic on `T`. @@ -1263,6 +1262,7 @@ macro_rules! uint_impl { ($SelfT:ty, $ActualT:ty, $BITS:expr, $ctpop:path, $ctlz:path, + $ctlz_nonzero:path, $cttz:path, $bswap:path, $add_with_overflow:path, @@ -2176,8 +2176,33 @@ macro_rules! uint_impl { (self.wrapping_sub(1)) & self == 0 && !(self == 0) } + // Returns one less than next power of two. + // (For 8u8 next power of two is 8u8 and for 6u8 it is 8u8) + // + // 8u8.one_less_than_next_power_of_two() == 7 + // 6u8.one_less_than_next_power_of_two() == 7 + // + // This method cannot overflow, as in the `next_power_of_two` + // overflow cases it instead ends up returning the maximum value + // of the type, and can return 0 for 0. + #[inline] + fn one_less_than_next_power_of_two(self) -> Self { + if self <= 1 { return 0; } + + // Because `p > 0`, it cannot consist entirely of leading zeros. + // That means the shift is always in-bounds, and some processors + // (such as intel pre-haswell) have more efficient ctlz + // intrinsics when the argument is non-zero. + let p = self - 1; + let z = unsafe { $ctlz_nonzero(p) }; + <$SelfT>::max_value() >> z + } + /// Returns the smallest power of two greater than or equal to `self`. - /// Unspecified behavior on overflow. + /// + /// When return value overflows (i.e. `self > (1 << (N-1))` for type + /// `uN`), it panics in debug mode and return value is wrapped to 0 in + /// release mode (the only situation in which method can return 0). /// /// # Examples /// @@ -2190,9 +2215,7 @@ macro_rules! uint_impl { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn next_power_of_two(self) -> Self { - let bits = size_of::() * 8; - let one: Self = 1; - one << ((bits - self.wrapping_sub(one).leading_zeros() as usize) % bits) + self.one_less_than_next_power_of_two() + 1 } /// Returns the smallest power of two greater than or equal to `n`. If @@ -2210,21 +2233,22 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn checked_next_power_of_two(self) -> Option { - let npot = self.next_power_of_two(); - if npot >= self { - Some(npot) - } else { - None - } + self.one_less_than_next_power_of_two().checked_add(1) } } } +#[cfg(stage0)] +unsafe fn ctlz_nonzero(x: T) -> T { intrinsics::ctlz(x) } +#[cfg(not(stage0))] +unsafe fn ctlz_nonzero(x: T) -> T { intrinsics::ctlz_nonzero(x) } + #[lang = "u8"] impl u8 { uint_impl! { u8, u8, 8, intrinsics::ctpop, intrinsics::ctlz, + ctlz_nonzero, intrinsics::cttz, intrinsics::bswap, intrinsics::add_with_overflow, @@ -2237,6 +2261,7 @@ impl u16 { uint_impl! { u16, u16, 16, intrinsics::ctpop, intrinsics::ctlz, + ctlz_nonzero, intrinsics::cttz, intrinsics::bswap, intrinsics::add_with_overflow, @@ -2249,6 +2274,7 @@ impl u32 { uint_impl! { u32, u32, 32, intrinsics::ctpop, intrinsics::ctlz, + ctlz_nonzero, intrinsics::cttz, intrinsics::bswap, intrinsics::add_with_overflow, @@ -2261,6 +2287,7 @@ impl u64 { uint_impl! { u64, u64, 64, intrinsics::ctpop, intrinsics::ctlz, + ctlz_nonzero, intrinsics::cttz, intrinsics::bswap, intrinsics::add_with_overflow, @@ -2273,6 +2300,7 @@ impl u128 { uint_impl! { u128, u128, 128, intrinsics::ctpop, intrinsics::ctlz, + ctlz_nonzero, intrinsics::cttz, intrinsics::bswap, intrinsics::add_with_overflow, @@ -2286,6 +2314,7 @@ impl usize { uint_impl! { usize, u16, 16, intrinsics::ctpop, intrinsics::ctlz, + ctlz_nonzero, intrinsics::cttz, intrinsics::bswap, intrinsics::add_with_overflow, @@ -2298,6 +2327,7 @@ impl usize { uint_impl! { usize, u32, 32, intrinsics::ctpop, intrinsics::ctlz, + ctlz_nonzero, intrinsics::cttz, intrinsics::bswap, intrinsics::add_with_overflow, @@ -2311,6 +2341,7 @@ impl usize { uint_impl! { usize, u64, 64, intrinsics::ctpop, intrinsics::ctlz, + ctlz_nonzero, intrinsics::cttz, intrinsics::bswap, intrinsics::add_with_overflow, @@ -2428,6 +2459,13 @@ pub trait Float: Sized { /// Convert degrees to radians. #[stable(feature = "deg_rad_conversions", since="1.7.0")] fn to_radians(self) -> Self; + + /// Returns the maximum of the two numbers. + #[stable(feature = "core_float_min_max", since="1.20.0")] + fn max(self, other: Self) -> Self; + /// Returns the minimum of the two numbers. + #[stable(feature = "core_float_min_max", since="1.20.0")] + fn min(self, other: Self) -> Self; } macro_rules! from_str_radix_int_impl { diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs deleted file mode 100644 index a1de8fe76e..0000000000 --- a/src/libcore/ops.rs +++ /dev/null @@ -1,3021 +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. - -//! Overloadable operators. -//! -//! Implementing these traits allows you to overload certain operators. -//! -//! Some of these traits are imported by the prelude, so they are available in -//! every Rust program. Only operators backed by traits can be overloaded. For -//! example, the addition operator (`+`) can be overloaded through the [`Add`] -//! trait, but since the assignment operator (`=`) has no backing trait, there -//! is no way of overloading its semantics. Additionally, this module does not -//! provide any mechanism to create new operators. If traitless overloading or -//! custom operators are required, you should look toward macros or compiler -//! plugins to extend Rust's syntax. -//! -//! Note that the `&&` and `||` operators short-circuit, i.e. they only -//! evaluate their second operand if it contributes to the result. Since this -//! behavior is not enforceable by traits, `&&` and `||` are not supported as -//! overloadable operators. -//! -//! Many of the operators take their operands by value. In non-generic -//! contexts involving built-in types, this is usually not a problem. -//! However, using these operators in generic code, requires some -//! attention if values have to be reused as opposed to letting the operators -//! consume them. One option is to occasionally use [`clone`]. -//! Another option is to rely on the types involved providing additional -//! operator implementations for references. For example, for a user-defined -//! type `T` which is supposed to support addition, it is probably a good -//! idea to have both `T` and `&T` implement the traits [`Add`][`Add`] and -//! [`Add<&T>`][`Add`] so that generic code can be written without unnecessary -//! cloning. -//! -//! # Examples -//! -//! This example creates a `Point` struct that implements [`Add`] and [`Sub`], -//! and then demonstrates adding and subtracting two `Point`s. -//! -//! ```rust -//! use std::ops::{Add, Sub}; -//! -//! #[derive(Debug)] -//! struct Point { -//! x: i32, -//! y: i32, -//! } -//! -//! impl Add for Point { -//! type Output = Point; -//! -//! fn add(self, other: Point) -> Point { -//! Point {x: self.x + other.x, y: self.y + other.y} -//! } -//! } -//! -//! impl Sub for Point { -//! type Output = Point; -//! -//! fn sub(self, other: Point) -> Point { -//! Point {x: self.x - other.x, y: self.y - other.y} -//! } -//! } -//! fn main() { -//! println!("{:?}", Point {x: 1, y: 0} + Point {x: 2, y: 3}); -//! println!("{:?}", Point {x: 1, y: 0} - Point {x: 2, y: 3}); -//! } -//! ``` -//! -//! See the documentation for each trait for an example implementation. -//! -//! The [`Fn`], [`FnMut`], and [`FnOnce`] traits are implemented by types that can be -//! invoked like functions. Note that [`Fn`] takes `&self`, [`FnMut`] takes `&mut -//! self` and [`FnOnce`] takes `self`. These correspond to the three kinds of -//! methods that can be invoked on an instance: call-by-reference, -//! call-by-mutable-reference, and call-by-value. The most common use of these -//! traits is to act as bounds to higher-level functions that take functions or -//! closures as arguments. -//! -//! Taking a [`Fn`] as a parameter: -//! -//! ```rust -//! fn call_with_one(func: F) -> usize -//! where F: Fn(usize) -> usize -//! { -//! func(1) -//! } -//! -//! let double = |x| x * 2; -//! assert_eq!(call_with_one(double), 2); -//! ``` -//! -//! Taking a [`FnMut`] as a parameter: -//! -//! ```rust -//! fn do_twice(mut func: F) -//! where F: FnMut() -//! { -//! func(); -//! func(); -//! } -//! -//! let mut x: usize = 1; -//! { -//! let add_two_to_x = || x += 2; -//! do_twice(add_two_to_x); -//! } -//! -//! assert_eq!(x, 5); -//! ``` -//! -//! Taking a [`FnOnce`] as a parameter: -//! -//! ```rust -//! fn consume_with_relish(func: F) -//! where F: FnOnce() -> String -//! { -//! // `func` consumes its captured variables, so it cannot be run more -//! // than once -//! println!("Consumed: {}", func()); -//! -//! println!("Delicious!"); -//! -//! // Attempting to invoke `func()` again will throw a `use of moved -//! // value` error for `func` -//! } -//! -//! let x = String::from("x"); -//! let consume_and_return_x = move || x; -//! consume_with_relish(consume_and_return_x); -//! -//! // `consume_and_return_x` can no longer be invoked at this point -//! ``` -//! -//! [`Fn`]: trait.Fn.html -//! [`FnMut`]: trait.FnMut.html -//! [`FnOnce`]: trait.FnOnce.html -//! [`Add`]: trait.Add.html -//! [`Sub`]: trait.Sub.html -//! [`clone`]: ../clone/trait.Clone.html#tymethod.clone - -#![stable(feature = "rust1", since = "1.0.0")] - -use fmt; -use marker::Unsize; - -/// The `Drop` trait is used to run some code when a value goes out of scope. -/// This is sometimes called a 'destructor'. -/// -/// When a value goes out of scope, if it implements this trait, it will have -/// its `drop` method called. Then any fields the value contains will also -/// be dropped recursively. -/// -/// Because of the recursive dropping, you do not need to implement this trait -/// unless your type needs its own destructor logic. -/// -/// # Examples -/// -/// A trivial implementation of `Drop`. The `drop` method is called when `_x` -/// goes out of scope, and therefore `main` prints `Dropping!`. -/// -/// ``` -/// struct HasDrop; -/// -/// impl Drop for HasDrop { -/// fn drop(&mut self) { -/// println!("Dropping!"); -/// } -/// } -/// -/// fn main() { -/// let _x = HasDrop; -/// } -/// ``` -/// -/// Showing the recursive nature of `Drop`. When `outer` goes out of scope, the -/// `drop` method will be called first for `Outer`, then for `Inner`. Therefore -/// `main` prints `Dropping Outer!` and then `Dropping Inner!`. -/// -/// ``` -/// struct Inner; -/// struct Outer(Inner); -/// -/// impl Drop for Inner { -/// fn drop(&mut self) { -/// println!("Dropping Inner!"); -/// } -/// } -/// -/// impl Drop for Outer { -/// fn drop(&mut self) { -/// println!("Dropping Outer!"); -/// } -/// } -/// -/// fn main() { -/// let _x = Outer(Inner); -/// } -/// ``` -/// -/// Because variables are dropped in the reverse order they are declared, -/// `main` will print `Declared second!` and then `Declared first!`. -/// -/// ``` -/// struct PrintOnDrop(&'static str); -/// -/// fn main() { -/// let _first = PrintOnDrop("Declared first!"); -/// let _second = PrintOnDrop("Declared second!"); -/// } -/// ``` -#[lang = "drop"] -#[stable(feature = "rust1", since = "1.0.0")] -pub trait Drop { - /// A method called when the value goes out of scope. - /// - /// When this method has been called, `self` has not yet been deallocated. - /// If it were, `self` would be a dangling reference. - /// - /// After this function is over, the memory of `self` will be deallocated. - /// - /// This function cannot be called explicitly. This is compiler error - /// [E0040]. However, the [`std::mem::drop`] function in the prelude can be - /// used to call the argument's `Drop` implementation. - /// - /// [E0040]: ../../error-index.html#E0040 - /// [`std::mem::drop`]: ../../std/mem/fn.drop.html - /// - /// # Panics - /// - /// Given that a `panic!` will call `drop()` as it unwinds, any `panic!` in - /// a `drop()` implementation will likely abort. - #[stable(feature = "rust1", since = "1.0.0")] - fn drop(&mut self); -} - -/// The addition operator `+`. -/// -/// # Examples -/// -/// This example creates a `Point` struct that implements the `Add` trait, and -/// then demonstrates adding two `Point`s. -/// -/// ``` -/// use std::ops::Add; -/// -/// #[derive(Debug)] -/// struct Point { -/// x: i32, -/// y: i32, -/// } -/// -/// impl Add for Point { -/// type Output = Point; -/// -/// fn add(self, other: Point) -> Point { -/// Point { -/// x: self.x + other.x, -/// y: self.y + other.y, -/// } -/// } -/// } -/// -/// impl PartialEq for Point { -/// fn eq(&self, other: &Self) -> bool { -/// self.x == other.x && self.y == other.y -/// } -/// } -/// -/// fn main() { -/// assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 }, -/// Point { x: 3, y: 3 }); -/// } -/// ``` -/// -/// Here is an example of the same `Point` struct implementing the `Add` trait -/// using generics. -/// -/// ``` -/// use std::ops::Add; -/// -/// #[derive(Debug)] -/// struct Point { -/// x: T, -/// y: T, -/// } -/// -/// // Notice that the implementation uses the `Output` associated type -/// impl> Add for Point { -/// type Output = Point; -/// -/// fn add(self, other: Point) -> Point { -/// Point { -/// x: self.x + other.x, -/// y: self.y + other.y, -/// } -/// } -/// } -/// -/// impl PartialEq for Point { -/// fn eq(&self, other: &Self) -> bool { -/// self.x == other.x && self.y == other.y -/// } -/// } -/// -/// fn main() { -/// assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 }, -/// Point { x: 3, y: 3 }); -/// } -/// ``` -/// -/// Note that `RHS = Self` by default, but this is not mandatory. For example, -/// [std::time::SystemTime] implements `Add`, which permits -/// operations of the form `SystemTime = SystemTime + Duration`. -/// -/// [std::time::SystemTime]: ../../std/time/struct.SystemTime.html -#[lang = "add"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} + {RHS}`"] -pub trait Add { - /// The resulting type after applying the `+` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `+` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn add(self, rhs: RHS) -> Self::Output; -} - -macro_rules! add_impl { - ($($t:ty)*) => ($( - #[stable(feature = "rust1", since = "1.0.0")] - impl Add for $t { - type Output = $t; - - #[inline] - #[rustc_inherit_overflow_checks] - fn add(self, other: $t) -> $t { self + other } - } - - forward_ref_binop! { impl Add, add for $t, $t } - )*) -} - -add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } - -/// The subtraction operator `-`. -/// -/// # Examples -/// -/// This example creates a `Point` struct that implements the `Sub` trait, and -/// then demonstrates subtracting two `Point`s. -/// -/// ``` -/// use std::ops::Sub; -/// -/// #[derive(Debug)] -/// struct Point { -/// x: i32, -/// y: i32, -/// } -/// -/// impl Sub for Point { -/// type Output = Point; -/// -/// fn sub(self, other: Point) -> Point { -/// Point { -/// x: self.x - other.x, -/// y: self.y - other.y, -/// } -/// } -/// } -/// -/// impl PartialEq for Point { -/// fn eq(&self, other: &Self) -> bool { -/// self.x == other.x && self.y == other.y -/// } -/// } -/// -/// fn main() { -/// assert_eq!(Point { x: 3, y: 3 } - Point { x: 2, y: 3 }, -/// Point { x: 1, y: 0 }); -/// } -/// ``` -/// -/// Note that `RHS = Self` by default, but this is not mandatory. For example, -/// [std::time::SystemTime] implements `Sub`, which permits -/// operations of the form `SystemTime = SystemTime - Duration`. -/// -/// [std::time::SystemTime]: ../../std/time/struct.SystemTime.html -#[lang = "sub"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} - {RHS}`"] -pub trait Sub { - /// The resulting type after applying the `-` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `-` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn sub(self, rhs: RHS) -> Self::Output; -} - -macro_rules! sub_impl { - ($($t:ty)*) => ($( - #[stable(feature = "rust1", since = "1.0.0")] - impl Sub for $t { - type Output = $t; - - #[inline] - #[rustc_inherit_overflow_checks] - fn sub(self, other: $t) -> $t { self - other } - } - - forward_ref_binop! { impl Sub, sub for $t, $t } - )*) -} - -sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } - -/// The multiplication operator `*`. -/// -/// # Examples -/// -/// Implementing a `Mul`tipliable rational number struct: -/// -/// ``` -/// use std::ops::Mul; -/// -/// // The uniqueness of rational numbers in lowest terms is a consequence of -/// // the fundamental theorem of arithmetic. -/// #[derive(Eq)] -/// #[derive(PartialEq, Debug)] -/// struct Rational { -/// nominator: usize, -/// denominator: usize, -/// } -/// -/// impl Rational { -/// fn new(nominator: usize, denominator: usize) -> Self { -/// if denominator == 0 { -/// panic!("Zero is an invalid denominator!"); -/// } -/// -/// // Reduce to lowest terms by dividing by the greatest common -/// // divisor. -/// let gcd = gcd(nominator, denominator); -/// Rational { -/// nominator: nominator / gcd, -/// denominator: denominator / gcd, -/// } -/// } -/// } -/// -/// impl Mul for Rational { -/// // The multiplication of rational numbers is a closed operation. -/// type Output = Self; -/// -/// fn mul(self, rhs: Self) -> Self { -/// let nominator = self.nominator * rhs.nominator; -/// let denominator = self.denominator * rhs.denominator; -/// Rational::new(nominator, denominator) -/// } -/// } -/// -/// // Euclid's two-thousand-year-old algorithm for finding the greatest common -/// // divisor. -/// fn gcd(x: usize, y: usize) -> usize { -/// let mut x = x; -/// let mut y = y; -/// while y != 0 { -/// let t = y; -/// y = x % y; -/// x = t; -/// } -/// x -/// } -/// -/// assert_eq!(Rational::new(1, 2), Rational::new(2, 4)); -/// assert_eq!(Rational::new(2, 3) * Rational::new(3, 4), -/// Rational::new(1, 2)); -/// ``` -/// -/// Note that `RHS = Self` by default, but this is not mandatory. Here is an -/// implementation which enables multiplication of vectors by scalars, as is -/// done in linear algebra. -/// -/// ``` -/// use std::ops::Mul; -/// -/// struct Scalar {value: usize}; -/// -/// #[derive(Debug)] -/// struct Vector {value: Vec}; -/// -/// impl Mul for Scalar { -/// type Output = Vector; -/// -/// fn mul(self, rhs: Vector) -> Vector { -/// Vector {value: rhs.value.iter().map(|v| self.value * v).collect()} -/// } -/// } -/// -/// impl PartialEq for Vector { -/// fn eq(&self, other: &Self) -> bool { -/// self.value == other.value -/// } -/// } -/// -/// let scalar = Scalar{value: 3}; -/// let vector = Vector{value: vec![2, 4, 6]}; -/// assert_eq!(scalar * vector, Vector{value: vec![6, 12, 18]}); -/// ``` -#[lang = "mul"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} * {RHS}`"] -pub trait Mul { - /// The resulting type after applying the `*` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `*` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn mul(self, rhs: RHS) -> Self::Output; -} - -macro_rules! mul_impl { - ($($t:ty)*) => ($( - #[stable(feature = "rust1", since = "1.0.0")] - impl Mul for $t { - type Output = $t; - - #[inline] - #[rustc_inherit_overflow_checks] - fn mul(self, other: $t) -> $t { self * other } - } - - forward_ref_binop! { impl Mul, mul for $t, $t } - )*) -} - -mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } - -/// The division operator `/`. -/// -/// # Examples -/// -/// Implementing a `Div`idable rational number struct: -/// -/// ``` -/// use std::ops::Div; -/// -/// // The uniqueness of rational numbers in lowest terms is a consequence of -/// // the fundamental theorem of arithmetic. -/// #[derive(Eq)] -/// #[derive(PartialEq, Debug)] -/// struct Rational { -/// nominator: usize, -/// denominator: usize, -/// } -/// -/// impl Rational { -/// fn new(nominator: usize, denominator: usize) -> Self { -/// if denominator == 0 { -/// panic!("Zero is an invalid denominator!"); -/// } -/// -/// // Reduce to lowest terms by dividing by the greatest common -/// // divisor. -/// let gcd = gcd(nominator, denominator); -/// Rational { -/// nominator: nominator / gcd, -/// denominator: denominator / gcd, -/// } -/// } -/// } -/// -/// impl Div for Rational { -/// // The division of rational numbers is a closed operation. -/// type Output = Self; -/// -/// fn div(self, rhs: Self) -> Self { -/// if rhs.nominator == 0 { -/// panic!("Cannot divide by zero-valued `Rational`!"); -/// } -/// -/// let nominator = self.nominator * rhs.denominator; -/// let denominator = self.denominator * rhs.nominator; -/// Rational::new(nominator, denominator) -/// } -/// } -/// -/// // Euclid's two-thousand-year-old algorithm for finding the greatest common -/// // divisor. -/// fn gcd(x: usize, y: usize) -> usize { -/// let mut x = x; -/// let mut y = y; -/// while y != 0 { -/// let t = y; -/// y = x % y; -/// x = t; -/// } -/// x -/// } -/// -/// fn main() { -/// assert_eq!(Rational::new(1, 2), Rational::new(2, 4)); -/// assert_eq!(Rational::new(1, 2) / Rational::new(3, 4), -/// Rational::new(2, 3)); -/// } -/// ``` -/// -/// Note that `RHS = Self` by default, but this is not mandatory. Here is an -/// implementation which enables division of vectors by scalars, as is done in -/// linear algebra. -/// -/// ``` -/// use std::ops::Div; -/// -/// struct Scalar {value: f32}; -/// -/// #[derive(Debug)] -/// struct Vector {value: Vec}; -/// -/// impl Div for Vector { -/// type Output = Vector; -/// -/// fn div(self, rhs: Scalar) -> Vector { -/// Vector {value: self.value.iter().map(|v| v / rhs.value).collect()} -/// } -/// } -/// -/// impl PartialEq for Vector { -/// fn eq(&self, other: &Self) -> bool { -/// self.value == other.value -/// } -/// } -/// -/// let scalar = Scalar{value: 2f32}; -/// let vector = Vector{value: vec![2f32, 4f32, 6f32]}; -/// assert_eq!(vector / scalar, Vector{value: vec![1f32, 2f32, 3f32]}); -/// ``` -#[lang = "div"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} / {RHS}`"] -pub trait Div { - /// The resulting type after applying the `/` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `/` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn div(self, rhs: RHS) -> Self::Output; -} - -macro_rules! div_impl_integer { - ($($t:ty)*) => ($( - /// This operation rounds towards zero, truncating any - /// fractional part of the exact result. - #[stable(feature = "rust1", since = "1.0.0")] - impl Div for $t { - type Output = $t; - - #[inline] - fn div(self, other: $t) -> $t { self / other } - } - - forward_ref_binop! { impl Div, div for $t, $t } - )*) -} - -div_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -macro_rules! div_impl_float { - ($($t:ty)*) => ($( - #[stable(feature = "rust1", since = "1.0.0")] - impl Div for $t { - type Output = $t; - - #[inline] - fn div(self, other: $t) -> $t { self / other } - } - - forward_ref_binop! { impl Div, div for $t, $t } - )*) -} - -div_impl_float! { f32 f64 } - -/// The remainder operator `%`. -/// -/// # Examples -/// -/// This example implements `Rem` on a `SplitSlice` object. After `Rem` is -/// implemented, one can use the `%` operator to find out what the remaining -/// elements of the slice would be after splitting it into equal slices of a -/// given length. -/// -/// ``` -/// use std::ops::Rem; -/// -/// #[derive(PartialEq, Debug)] -/// struct SplitSlice<'a, T: 'a> { -/// slice: &'a [T], -/// } -/// -/// impl<'a, T> Rem for SplitSlice<'a, T> { -/// type Output = SplitSlice<'a, T>; -/// -/// fn rem(self, modulus: usize) -> Self { -/// let len = self.slice.len(); -/// let rem = len % modulus; -/// let start = len - rem; -/// SplitSlice {slice: &self.slice[start..]} -/// } -/// } -/// -/// // If we were to divide &[0, 1, 2, 3, 4, 5, 6, 7] into slices of size 3, -/// // the remainder would be &[6, 7] -/// assert_eq!(SplitSlice { slice: &[0, 1, 2, 3, 4, 5, 6, 7] } % 3, -/// SplitSlice { slice: &[6, 7] }); -/// ``` -#[lang = "rem"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} % {RHS}`"] -pub trait Rem { - /// The resulting type after applying the `%` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output = Self; - - /// The method for the `%` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn rem(self, rhs: RHS) -> Self::Output; -} - -macro_rules! rem_impl_integer { - ($($t:ty)*) => ($( - /// This operation satisfies `n % d == n - (n / d) * d`. The - /// result has the same sign as the left operand. - #[stable(feature = "rust1", since = "1.0.0")] - impl Rem for $t { - type Output = $t; - - #[inline] - fn rem(self, other: $t) -> $t { self % other } - } - - forward_ref_binop! { impl Rem, rem for $t, $t } - )*) -} - -rem_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - - -macro_rules! rem_impl_float { - ($($t:ty)*) => ($( - #[stable(feature = "rust1", since = "1.0.0")] - impl Rem for $t { - type Output = $t; - - #[inline] - fn rem(self, other: $t) -> $t { self % other } - } - - forward_ref_binop! { impl Rem, rem for $t, $t } - )*) -} - -rem_impl_float! { f32 f64 } - -/// The unary negation operator `-`. -/// -/// # Examples -/// -/// An implementation of `Neg` for `Sign`, which allows the use of `-` to -/// negate its value. -/// -/// ``` -/// use std::ops::Neg; -/// -/// #[derive(Debug, PartialEq)] -/// enum Sign { -/// Negative, -/// Zero, -/// Positive, -/// } -/// -/// impl Neg for Sign { -/// type Output = Sign; -/// -/// fn neg(self) -> Sign { -/// match self { -/// Sign::Negative => Sign::Positive, -/// Sign::Zero => Sign::Zero, -/// Sign::Positive => Sign::Negative, -/// } -/// } -/// } -/// -/// // a negative positive is a negative -/// assert_eq!(-Sign::Positive, Sign::Negative); -/// // a double negative is a positive -/// assert_eq!(-Sign::Negative, Sign::Positive); -/// // zero is its own negation -/// assert_eq!(-Sign::Zero, Sign::Zero); -/// ``` -#[lang = "neg"] -#[stable(feature = "rust1", since = "1.0.0")] -pub trait Neg { - /// The resulting type after applying the `-` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the unary `-` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn neg(self) -> Self::Output; -} - - - -macro_rules! neg_impl_core { - ($id:ident => $body:expr, $($t:ty)*) => ($( - #[stable(feature = "rust1", since = "1.0.0")] - impl Neg for $t { - type Output = $t; - - #[inline] - #[rustc_inherit_overflow_checks] - fn neg(self) -> $t { let $id = self; $body } - } - - forward_ref_unop! { impl Neg, neg for $t } - )*) -} - -macro_rules! neg_impl_numeric { - ($($t:ty)*) => { neg_impl_core!{ x => -x, $($t)*} } -} - -#[allow(unused_macros)] -macro_rules! neg_impl_unsigned { - ($($t:ty)*) => { - neg_impl_core!{ x => { - !x.wrapping_add(1) - }, $($t)*} } -} - -// neg_impl_unsigned! { usize u8 u16 u32 u64 } -neg_impl_numeric! { isize i8 i16 i32 i64 i128 f32 f64 } - -/// The unary logical negation operator `!`. -/// -/// # Examples -/// -/// An implementation of `Not` for `Answer`, which enables the use of `!` to -/// invert its value. -/// -/// ``` -/// use std::ops::Not; -/// -/// #[derive(Debug, PartialEq)] -/// enum Answer { -/// Yes, -/// No, -/// } -/// -/// impl Not for Answer { -/// type Output = Answer; -/// -/// fn not(self) -> Answer { -/// match self { -/// Answer::Yes => Answer::No, -/// Answer::No => Answer::Yes -/// } -/// } -/// } -/// -/// assert_eq!(!Answer::Yes, Answer::No); -/// assert_eq!(!Answer::No, Answer::Yes); -/// ``` -#[lang = "not"] -#[stable(feature = "rust1", since = "1.0.0")] -pub trait Not { - /// The resulting type after applying the `!` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the unary `!` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn not(self) -> Self::Output; -} - -macro_rules! not_impl { - ($($t:ty)*) => ($( - #[stable(feature = "rust1", since = "1.0.0")] - impl Not for $t { - type Output = $t; - - #[inline] - fn not(self) -> $t { !self } - } - - forward_ref_unop! { impl Not, not for $t } - )*) -} - -not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -/// The bitwise AND operator `&`. -/// -/// # Examples -/// -/// In this example, the `&` operator is lifted to a trivial `Scalar` type. -/// -/// ``` -/// use std::ops::BitAnd; -/// -/// #[derive(Debug, PartialEq)] -/// struct Scalar(bool); -/// -/// impl BitAnd for Scalar { -/// type Output = Self; -/// -/// // rhs is the "right-hand side" of the expression `a & b` -/// fn bitand(self, rhs: Self) -> Self { -/// Scalar(self.0 & rhs.0) -/// } -/// } -/// -/// fn main() { -/// assert_eq!(Scalar(true) & Scalar(true), Scalar(true)); -/// assert_eq!(Scalar(true) & Scalar(false), Scalar(false)); -/// assert_eq!(Scalar(false) & Scalar(true), Scalar(false)); -/// assert_eq!(Scalar(false) & Scalar(false), Scalar(false)); -/// } -/// ``` -/// -/// In this example, the `BitAnd` trait is implemented for a `BooleanVector` -/// struct. -/// -/// ``` -/// use std::ops::BitAnd; -/// -/// #[derive(Debug, PartialEq)] -/// struct BooleanVector(Vec); -/// -/// impl BitAnd for BooleanVector { -/// type Output = Self; -/// -/// fn bitand(self, BooleanVector(rhs): Self) -> Self { -/// let BooleanVector(lhs) = self; -/// assert_eq!(lhs.len(), rhs.len()); -/// BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x && *y).collect()) -/// } -/// } -/// -/// fn main() { -/// let bv1 = BooleanVector(vec![true, true, false, false]); -/// let bv2 = BooleanVector(vec![true, false, true, false]); -/// let expected = BooleanVector(vec![true, false, false, false]); -/// assert_eq!(bv1 & bv2, expected); -/// } -/// ``` -#[lang = "bitand"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} & {RHS}`"] -pub trait BitAnd { - /// The resulting type after applying the `&` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `&` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn bitand(self, rhs: RHS) -> Self::Output; -} - -macro_rules! bitand_impl { - ($($t:ty)*) => ($( - #[stable(feature = "rust1", since = "1.0.0")] - impl BitAnd for $t { - type Output = $t; - - #[inline] - fn bitand(self, rhs: $t) -> $t { self & rhs } - } - - forward_ref_binop! { impl BitAnd, bitand for $t, $t } - )*) -} - -bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -/// The bitwise OR operator `|`. -/// -/// # Examples -/// -/// In this example, the `|` operator is lifted to a trivial `Scalar` type. -/// -/// ``` -/// use std::ops::BitOr; -/// -/// #[derive(Debug, PartialEq)] -/// struct Scalar(bool); -/// -/// impl BitOr for Scalar { -/// type Output = Self; -/// -/// // rhs is the "right-hand side" of the expression `a | b` -/// fn bitor(self, rhs: Self) -> Self { -/// Scalar(self.0 | rhs.0) -/// } -/// } -/// -/// fn main() { -/// assert_eq!(Scalar(true) | Scalar(true), Scalar(true)); -/// assert_eq!(Scalar(true) | Scalar(false), Scalar(true)); -/// assert_eq!(Scalar(false) | Scalar(true), Scalar(true)); -/// assert_eq!(Scalar(false) | Scalar(false), Scalar(false)); -/// } -/// ``` -/// -/// In this example, the `BitOr` trait is implemented for a `BooleanVector` -/// struct. -/// -/// ``` -/// use std::ops::BitOr; -/// -/// #[derive(Debug, PartialEq)] -/// struct BooleanVector(Vec); -/// -/// impl BitOr for BooleanVector { -/// type Output = Self; -/// -/// fn bitor(self, BooleanVector(rhs): Self) -> Self { -/// let BooleanVector(lhs) = self; -/// assert_eq!(lhs.len(), rhs.len()); -/// BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x || *y).collect()) -/// } -/// } -/// -/// fn main() { -/// let bv1 = BooleanVector(vec![true, true, false, false]); -/// let bv2 = BooleanVector(vec![true, false, true, false]); -/// let expected = BooleanVector(vec![true, true, true, false]); -/// assert_eq!(bv1 | bv2, expected); -/// } -/// ``` -#[lang = "bitor"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} | {RHS}`"] -pub trait BitOr { - /// The resulting type after applying the `|` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `|` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn bitor(self, rhs: RHS) -> Self::Output; -} - -macro_rules! bitor_impl { - ($($t:ty)*) => ($( - #[stable(feature = "rust1", since = "1.0.0")] - impl BitOr for $t { - type Output = $t; - - #[inline] - fn bitor(self, rhs: $t) -> $t { self | rhs } - } - - forward_ref_binop! { impl BitOr, bitor for $t, $t } - )*) -} - -bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -/// The bitwise XOR operator `^`. -/// -/// # Examples -/// -/// In this example, the `^` operator is lifted to a trivial `Scalar` type. -/// -/// ``` -/// use std::ops::BitXor; -/// -/// #[derive(Debug, PartialEq)] -/// struct Scalar(bool); -/// -/// impl BitXor for Scalar { -/// type Output = Self; -/// -/// // rhs is the "right-hand side" of the expression `a ^ b` -/// fn bitxor(self, rhs: Self) -> Self { -/// Scalar(self.0 ^ rhs.0) -/// } -/// } -/// -/// fn main() { -/// assert_eq!(Scalar(true) ^ Scalar(true), Scalar(false)); -/// assert_eq!(Scalar(true) ^ Scalar(false), Scalar(true)); -/// assert_eq!(Scalar(false) ^ Scalar(true), Scalar(true)); -/// assert_eq!(Scalar(false) ^ Scalar(false), Scalar(false)); -/// } -/// ``` -/// -/// In this example, the `BitXor` trait is implemented for a `BooleanVector` -/// struct. -/// -/// ``` -/// use std::ops::BitXor; -/// -/// #[derive(Debug, PartialEq)] -/// struct BooleanVector(Vec); -/// -/// impl BitXor for BooleanVector { -/// type Output = Self; -/// -/// fn bitxor(self, BooleanVector(rhs): Self) -> Self { -/// let BooleanVector(lhs) = self; -/// assert_eq!(lhs.len(), rhs.len()); -/// BooleanVector(lhs.iter() -/// .zip(rhs.iter()) -/// .map(|(x, y)| (*x || *y) && !(*x && *y)) -/// .collect()) -/// } -/// } -/// -/// fn main() { -/// let bv1 = BooleanVector(vec![true, true, false, false]); -/// let bv2 = BooleanVector(vec![true, false, true, false]); -/// let expected = BooleanVector(vec![false, true, true, false]); -/// assert_eq!(bv1 ^ bv2, expected); -/// } -/// ``` -#[lang = "bitxor"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} ^ {RHS}`"] -pub trait BitXor { - /// The resulting type after applying the `^` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `^` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn bitxor(self, rhs: RHS) -> Self::Output; -} - -macro_rules! bitxor_impl { - ($($t:ty)*) => ($( - #[stable(feature = "rust1", since = "1.0.0")] - impl BitXor for $t { - type Output = $t; - - #[inline] - fn bitxor(self, other: $t) -> $t { self ^ other } - } - - forward_ref_binop! { impl BitXor, bitxor for $t, $t } - )*) -} - -bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -/// The left shift operator `<<`. -/// -/// # Examples -/// -/// An implementation of `Shl` that lifts the `<<` operation on integers to a -/// `Scalar` struct. -/// -/// ``` -/// use std::ops::Shl; -/// -/// #[derive(PartialEq, Debug)] -/// struct Scalar(usize); -/// -/// impl Shl for Scalar { -/// type Output = Self; -/// -/// fn shl(self, Scalar(rhs): Self) -> Scalar { -/// let Scalar(lhs) = self; -/// Scalar(lhs << rhs) -/// } -/// } -/// fn main() { -/// assert_eq!(Scalar(4) << Scalar(2), Scalar(16)); -/// } -/// ``` -/// -/// An implementation of `Shl` that spins a vector leftward by a given amount. -/// -/// ``` -/// use std::ops::Shl; -/// -/// #[derive(PartialEq, Debug)] -/// struct SpinVector { -/// vec: Vec, -/// } -/// -/// impl Shl for SpinVector { -/// type Output = Self; -/// -/// fn shl(self, rhs: usize) -> SpinVector { -/// // rotate the vector by `rhs` places -/// let (a, b) = self.vec.split_at(rhs); -/// let mut spun_vector: Vec = vec![]; -/// spun_vector.extend_from_slice(b); -/// spun_vector.extend_from_slice(a); -/// SpinVector { vec: spun_vector } -/// } -/// } -/// -/// fn main() { -/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } << 2, -/// SpinVector { vec: vec![2, 3, 4, 0, 1] }); -/// } -/// ``` -#[lang = "shl"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} << {RHS}`"] -pub trait Shl { - /// The resulting type after applying the `<<` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `<<` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn shl(self, rhs: RHS) -> Self::Output; -} - -macro_rules! shl_impl { - ($t:ty, $f:ty) => ( - #[stable(feature = "rust1", since = "1.0.0")] - impl Shl<$f> for $t { - type Output = $t; - - #[inline] - #[rustc_inherit_overflow_checks] - fn shl(self, other: $f) -> $t { - self << other - } - } - - forward_ref_binop! { impl Shl, shl for $t, $f } - ) -} - -macro_rules! shl_impl_all { - ($($t:ty)*) => ($( - shl_impl! { $t, u8 } - shl_impl! { $t, u16 } - shl_impl! { $t, u32 } - shl_impl! { $t, u64 } - shl_impl! { $t, u128 } - shl_impl! { $t, usize } - - shl_impl! { $t, i8 } - shl_impl! { $t, i16 } - shl_impl! { $t, i32 } - shl_impl! { $t, i64 } - shl_impl! { $t, i128 } - shl_impl! { $t, isize } - )*) -} - -shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 } - -/// The right shift operator `>>`. -/// -/// # Examples -/// -/// An implementation of `Shr` that lifts the `>>` operation on integers to a -/// `Scalar` struct. -/// -/// ``` -/// use std::ops::Shr; -/// -/// #[derive(PartialEq, Debug)] -/// struct Scalar(usize); -/// -/// impl Shr for Scalar { -/// type Output = Self; -/// -/// fn shr(self, Scalar(rhs): Self) -> Scalar { -/// let Scalar(lhs) = self; -/// Scalar(lhs >> rhs) -/// } -/// } -/// fn main() { -/// assert_eq!(Scalar(16) >> Scalar(2), Scalar(4)); -/// } -/// ``` -/// -/// An implementation of `Shr` that spins a vector rightward by a given amount. -/// -/// ``` -/// use std::ops::Shr; -/// -/// #[derive(PartialEq, Debug)] -/// struct SpinVector { -/// vec: Vec, -/// } -/// -/// impl Shr for SpinVector { -/// type Output = Self; -/// -/// fn shr(self, rhs: usize) -> SpinVector { -/// // rotate the vector by `rhs` places -/// let (a, b) = self.vec.split_at(self.vec.len() - rhs); -/// let mut spun_vector: Vec = vec![]; -/// spun_vector.extend_from_slice(b); -/// spun_vector.extend_from_slice(a); -/// SpinVector { vec: spun_vector } -/// } -/// } -/// -/// fn main() { -/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } >> 2, -/// SpinVector { vec: vec![3, 4, 0, 1, 2] }); -/// } -/// ``` -#[lang = "shr"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} >> {RHS}`"] -pub trait Shr { - /// The resulting type after applying the `>>` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `>>` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn shr(self, rhs: RHS) -> Self::Output; -} - -macro_rules! shr_impl { - ($t:ty, $f:ty) => ( - #[stable(feature = "rust1", since = "1.0.0")] - impl Shr<$f> for $t { - type Output = $t; - - #[inline] - #[rustc_inherit_overflow_checks] - fn shr(self, other: $f) -> $t { - self >> other - } - } - - forward_ref_binop! { impl Shr, shr for $t, $f } - ) -} - -macro_rules! shr_impl_all { - ($($t:ty)*) => ($( - shr_impl! { $t, u8 } - shr_impl! { $t, u16 } - shr_impl! { $t, u32 } - shr_impl! { $t, u64 } - shr_impl! { $t, u128 } - shr_impl! { $t, usize } - - shr_impl! { $t, i8 } - shr_impl! { $t, i16 } - shr_impl! { $t, i32 } - shr_impl! { $t, i64 } - shr_impl! { $t, i128 } - shr_impl! { $t, isize } - )*) -} - -shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } - -/// The addition assignment operator `+=`. -/// -/// # Examples -/// -/// This example creates a `Point` struct that implements the `AddAssign` -/// trait, and then demonstrates add-assigning to a mutable `Point`. -/// -/// ``` -/// use std::ops::AddAssign; -/// -/// #[derive(Debug)] -/// struct Point { -/// x: i32, -/// y: i32, -/// } -/// -/// impl AddAssign for Point { -/// fn add_assign(&mut self, other: Point) { -/// *self = Point { -/// x: self.x + other.x, -/// y: self.y + other.y, -/// }; -/// } -/// } -/// -/// impl PartialEq for Point { -/// fn eq(&self, other: &Self) -> bool { -/// self.x == other.x && self.y == other.y -/// } -/// } -/// -/// let mut point = Point { x: 1, y: 0 }; -/// point += Point { x: 2, y: 3 }; -/// assert_eq!(point, Point { x: 3, y: 3 }); -/// ``` -#[lang = "add_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} += {Rhs}`"] -pub trait AddAssign { - /// The method for the `+=` operator - #[stable(feature = "op_assign_traits", since = "1.8.0")] - fn add_assign(&mut self, rhs: Rhs); -} - -macro_rules! add_assign_impl { - ($($t:ty)+) => ($( - #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl AddAssign for $t { - #[inline] - #[rustc_inherit_overflow_checks] - fn add_assign(&mut self, other: $t) { *self += other } - } - )+) -} - -add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } - -/// The subtraction assignment operator `-=`. -/// -/// # Examples -/// -/// This example creates a `Point` struct that implements the `SubAssign` -/// trait, and then demonstrates sub-assigning to a mutable `Point`. -/// -/// ``` -/// use std::ops::SubAssign; -/// -/// #[derive(Debug)] -/// struct Point { -/// x: i32, -/// y: i32, -/// } -/// -/// impl SubAssign for Point { -/// fn sub_assign(&mut self, other: Point) { -/// *self = Point { -/// x: self.x - other.x, -/// y: self.y - other.y, -/// }; -/// } -/// } -/// -/// impl PartialEq for Point { -/// fn eq(&self, other: &Self) -> bool { -/// self.x == other.x && self.y == other.y -/// } -/// } -/// -/// let mut point = Point { x: 3, y: 3 }; -/// point -= Point { x: 2, y: 3 }; -/// assert_eq!(point, Point {x: 1, y: 0}); -/// ``` -#[lang = "sub_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} -= {Rhs}`"] -pub trait SubAssign { - /// The method for the `-=` operator - #[stable(feature = "op_assign_traits", since = "1.8.0")] - fn sub_assign(&mut self, rhs: Rhs); -} - -macro_rules! sub_assign_impl { - ($($t:ty)+) => ($( - #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl SubAssign for $t { - #[inline] - #[rustc_inherit_overflow_checks] - fn sub_assign(&mut self, other: $t) { *self -= other } - } - )+) -} - -sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } - -/// The multiplication assignment operator `*=`. -/// -/// # Examples -/// -/// A trivial implementation of `MulAssign`. When `Foo *= Foo` happens, it ends up -/// calling `mul_assign`, and therefore, `main` prints `Multiplying!`. -/// -/// ``` -/// use std::ops::MulAssign; -/// -/// struct Foo; -/// -/// impl MulAssign for Foo { -/// fn mul_assign(&mut self, _rhs: Foo) { -/// println!("Multiplying!"); -/// } -/// } -/// -/// # #[allow(unused_assignments)] -/// fn main() { -/// let mut foo = Foo; -/// foo *= Foo; -/// } -/// ``` -#[lang = "mul_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} *= {Rhs}`"] -pub trait MulAssign { - /// The method for the `*=` operator - #[stable(feature = "op_assign_traits", since = "1.8.0")] - fn mul_assign(&mut self, rhs: Rhs); -} - -macro_rules! mul_assign_impl { - ($($t:ty)+) => ($( - #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl MulAssign for $t { - #[inline] - #[rustc_inherit_overflow_checks] - fn mul_assign(&mut self, other: $t) { *self *= other } - } - )+) -} - -mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } - -/// The division assignment operator `/=`. -/// -/// # Examples -/// -/// A trivial implementation of `DivAssign`. When `Foo /= Foo` happens, it ends up -/// calling `div_assign`, and therefore, `main` prints `Dividing!`. -/// -/// ``` -/// use std::ops::DivAssign; -/// -/// struct Foo; -/// -/// impl DivAssign for Foo { -/// fn div_assign(&mut self, _rhs: Foo) { -/// println!("Dividing!"); -/// } -/// } -/// -/// # #[allow(unused_assignments)] -/// fn main() { -/// let mut foo = Foo; -/// foo /= Foo; -/// } -/// ``` -#[lang = "div_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} /= {Rhs}`"] -pub trait DivAssign { - /// The method for the `/=` operator - #[stable(feature = "op_assign_traits", since = "1.8.0")] - fn div_assign(&mut self, rhs: Rhs); -} - -macro_rules! div_assign_impl { - ($($t:ty)+) => ($( - #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl DivAssign for $t { - #[inline] - fn div_assign(&mut self, other: $t) { *self /= other } - } - )+) -} - -div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } - -/// The remainder assignment operator `%=`. -/// -/// # Examples -/// -/// A trivial implementation of `RemAssign`. When `Foo %= Foo` happens, it ends up -/// calling `rem_assign`, and therefore, `main` prints `Remainder-ing!`. -/// -/// ``` -/// use std::ops::RemAssign; -/// -/// struct Foo; -/// -/// impl RemAssign for Foo { -/// fn rem_assign(&mut self, _rhs: Foo) { -/// println!("Remainder-ing!"); -/// } -/// } -/// -/// # #[allow(unused_assignments)] -/// fn main() { -/// let mut foo = Foo; -/// foo %= Foo; -/// } -/// ``` -#[lang = "rem_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} %= {Rhs}`"] -pub trait RemAssign { - /// The method for the `%=` operator - #[stable(feature = "op_assign_traits", since = "1.8.0")] - fn rem_assign(&mut self, rhs: Rhs); -} - -macro_rules! rem_assign_impl { - ($($t:ty)+) => ($( - #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl RemAssign for $t { - #[inline] - fn rem_assign(&mut self, other: $t) { *self %= other } - } - )+) -} - -rem_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } - -/// The bitwise AND assignment operator `&=`. -/// -/// # Examples -/// -/// In this example, the `&=` operator is lifted to a trivial `Scalar` type. -/// -/// ``` -/// use std::ops::BitAndAssign; -/// -/// #[derive(Debug, PartialEq)] -/// struct Scalar(bool); -/// -/// impl BitAndAssign for Scalar { -/// // rhs is the "right-hand side" of the expression `a &= b` -/// fn bitand_assign(&mut self, rhs: Self) { -/// *self = Scalar(self.0 & rhs.0) -/// } -/// } -/// -/// fn main() { -/// let mut scalar = Scalar(true); -/// scalar &= Scalar(true); -/// assert_eq!(scalar, Scalar(true)); -/// -/// let mut scalar = Scalar(true); -/// scalar &= Scalar(false); -/// assert_eq!(scalar, Scalar(false)); -/// -/// let mut scalar = Scalar(false); -/// scalar &= Scalar(true); -/// assert_eq!(scalar, Scalar(false)); -/// -/// let mut scalar = Scalar(false); -/// scalar &= Scalar(false); -/// assert_eq!(scalar, Scalar(false)); -/// } -/// ``` -/// -/// In this example, the `BitAndAssign` trait is implemented for a -/// `BooleanVector` struct. -/// -/// ``` -/// use std::ops::BitAndAssign; -/// -/// #[derive(Debug, PartialEq)] -/// struct BooleanVector(Vec); -/// -/// impl BitAndAssign for BooleanVector { -/// // rhs is the "right-hand side" of the expression `a &= b` -/// fn bitand_assign(&mut self, rhs: Self) { -/// assert_eq!(self.0.len(), rhs.0.len()); -/// *self = BooleanVector(self.0 -/// .iter() -/// .zip(rhs.0.iter()) -/// .map(|(x, y)| *x && *y) -/// .collect()); -/// } -/// } -/// -/// fn main() { -/// let mut bv = BooleanVector(vec![true, true, false, false]); -/// bv &= BooleanVector(vec![true, false, true, false]); -/// let expected = BooleanVector(vec![true, false, false, false]); -/// assert_eq!(bv, expected); -/// } -/// ``` -#[lang = "bitand_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} &= {Rhs}`"] -pub trait BitAndAssign { - /// The method for the `&=` operator - #[stable(feature = "op_assign_traits", since = "1.8.0")] - fn bitand_assign(&mut self, rhs: Rhs); -} - -macro_rules! bitand_assign_impl { - ($($t:ty)+) => ($( - #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl BitAndAssign for $t { - #[inline] - fn bitand_assign(&mut self, other: $t) { *self &= other } - } - )+) -} - -bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -/// The bitwise OR assignment operator `|=`. -/// -/// # Examples -/// -/// A trivial implementation of `BitOrAssign`. When `Foo |= Foo` happens, it ends up -/// calling `bitor_assign`, and therefore, `main` prints `Bitwise Or-ing!`. -/// -/// ``` -/// use std::ops::BitOrAssign; -/// -/// struct Foo; -/// -/// impl BitOrAssign for Foo { -/// fn bitor_assign(&mut self, _rhs: Foo) { -/// println!("Bitwise Or-ing!"); -/// } -/// } -/// -/// # #[allow(unused_assignments)] -/// fn main() { -/// let mut foo = Foo; -/// foo |= Foo; -/// } -/// ``` -#[lang = "bitor_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} |= {Rhs}`"] -pub trait BitOrAssign { - /// The method for the `|=` operator - #[stable(feature = "op_assign_traits", since = "1.8.0")] - fn bitor_assign(&mut self, rhs: Rhs); -} - -macro_rules! bitor_assign_impl { - ($($t:ty)+) => ($( - #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl BitOrAssign for $t { - #[inline] - fn bitor_assign(&mut self, other: $t) { *self |= other } - } - )+) -} - -bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -/// The bitwise XOR assignment operator `^=`. -/// -/// # Examples -/// -/// A trivial implementation of `BitXorAssign`. When `Foo ^= Foo` happens, it ends up -/// calling `bitxor_assign`, and therefore, `main` prints `Bitwise Xor-ing!`. -/// -/// ``` -/// use std::ops::BitXorAssign; -/// -/// struct Foo; -/// -/// impl BitXorAssign for Foo { -/// fn bitxor_assign(&mut self, _rhs: Foo) { -/// println!("Bitwise Xor-ing!"); -/// } -/// } -/// -/// # #[allow(unused_assignments)] -/// fn main() { -/// let mut foo = Foo; -/// foo ^= Foo; -/// } -/// ``` -#[lang = "bitxor_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} ^= {Rhs}`"] -pub trait BitXorAssign { - /// The method for the `^=` operator - #[stable(feature = "op_assign_traits", since = "1.8.0")] - fn bitxor_assign(&mut self, rhs: Rhs); -} - -macro_rules! bitxor_assign_impl { - ($($t:ty)+) => ($( - #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl BitXorAssign for $t { - #[inline] - fn bitxor_assign(&mut self, other: $t) { *self ^= other } - } - )+) -} - -bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -/// The left shift assignment operator `<<=`. -/// -/// # Examples -/// -/// A trivial implementation of `ShlAssign`. When `Foo <<= Foo` happens, it ends up -/// calling `shl_assign`, and therefore, `main` prints `Shifting left!`. -/// -/// ``` -/// use std::ops::ShlAssign; -/// -/// struct Foo; -/// -/// impl ShlAssign for Foo { -/// fn shl_assign(&mut self, _rhs: Foo) { -/// println!("Shifting left!"); -/// } -/// } -/// -/// # #[allow(unused_assignments)] -/// fn main() { -/// let mut foo = Foo; -/// foo <<= Foo; -/// } -/// ``` -#[lang = "shl_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} <<= {Rhs}`"] -pub trait ShlAssign { - /// The method for the `<<=` operator - #[stable(feature = "op_assign_traits", since = "1.8.0")] - fn shl_assign(&mut self, rhs: Rhs); -} - -macro_rules! shl_assign_impl { - ($t:ty, $f:ty) => ( - #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl ShlAssign<$f> for $t { - #[inline] - #[rustc_inherit_overflow_checks] - fn shl_assign(&mut self, other: $f) { - *self <<= other - } - } - ) -} - -macro_rules! shl_assign_impl_all { - ($($t:ty)*) => ($( - shl_assign_impl! { $t, u8 } - shl_assign_impl! { $t, u16 } - shl_assign_impl! { $t, u32 } - shl_assign_impl! { $t, u64 } - 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 } - shl_assign_impl! { $t, i128 } - shl_assign_impl! { $t, isize } - )*) -} - -shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } - -/// The right shift assignment operator `>>=`. -/// -/// # Examples -/// -/// A trivial implementation of `ShrAssign`. When `Foo >>= Foo` happens, it ends up -/// calling `shr_assign`, and therefore, `main` prints `Shifting right!`. -/// -/// ``` -/// use std::ops::ShrAssign; -/// -/// struct Foo; -/// -/// impl ShrAssign for Foo { -/// fn shr_assign(&mut self, _rhs: Foo) { -/// println!("Shifting right!"); -/// } -/// } -/// -/// # #[allow(unused_assignments)] -/// fn main() { -/// let mut foo = Foo; -/// foo >>= Foo; -/// } -/// ``` -#[lang = "shr_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} >>= {Rhs}`"] -pub trait ShrAssign { - /// The method for the `>>=` operator - #[stable(feature = "op_assign_traits", since = "1.8.0")] - fn shr_assign(&mut self, rhs: Rhs); -} - -macro_rules! shr_assign_impl { - ($t:ty, $f:ty) => ( - #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl ShrAssign<$f> for $t { - #[inline] - #[rustc_inherit_overflow_checks] - fn shr_assign(&mut self, other: $f) { - *self >>= other - } - } - ) -} - -macro_rules! shr_assign_impl_all { - ($($t:ty)*) => ($( - shr_assign_impl! { $t, u8 } - shr_assign_impl! { $t, u16 } - shr_assign_impl! { $t, u32 } - shr_assign_impl! { $t, u64 } - 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 } - shr_assign_impl! { $t, i128 } - shr_assign_impl! { $t, isize } - )*) -} - -shr_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } - -/// The `Index` trait is used to specify the functionality of indexing operations -/// like `container[index]` when used in an immutable context. -/// -/// `container[index]` is actually syntactic sugar for `*container.index(index)`, -/// but only when used as an immutable value. If a mutable value is requested, -/// [`IndexMut`] is used instead. This allows nice things such as -/// `let value = v[index]` if `value` implements [`Copy`]. -/// -/// [`IndexMut`]: ../../std/ops/trait.IndexMut.html -/// [`Copy`]: ../../std/marker/trait.Copy.html -/// -/// # Examples -/// -/// The following example implements `Index` on a read-only `NucleotideCount` -/// container, enabling individual counts to be retrieved with index syntax. -/// -/// ``` -/// use std::ops::Index; -/// -/// enum Nucleotide { -/// A, -/// C, -/// G, -/// T, -/// } -/// -/// struct NucleotideCount { -/// a: usize, -/// c: usize, -/// g: usize, -/// t: usize, -/// } -/// -/// impl Index for NucleotideCount { -/// type Output = usize; -/// -/// fn index(&self, nucleotide: Nucleotide) -> &usize { -/// match nucleotide { -/// Nucleotide::A => &self.a, -/// Nucleotide::C => &self.c, -/// Nucleotide::G => &self.g, -/// Nucleotide::T => &self.t, -/// } -/// } -/// } -/// -/// let nucleotide_count = NucleotideCount {a: 14, c: 9, g: 10, t: 12}; -/// assert_eq!(nucleotide_count[Nucleotide::A], 14); -/// assert_eq!(nucleotide_count[Nucleotide::C], 9); -/// assert_eq!(nucleotide_count[Nucleotide::G], 10); -/// assert_eq!(nucleotide_count[Nucleotide::T], 12); -/// ``` -#[lang = "index"] -#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"] -#[stable(feature = "rust1", since = "1.0.0")] -pub trait Index { - /// The returned type after indexing - #[stable(feature = "rust1", since = "1.0.0")] - type Output: ?Sized; - - /// The method for the indexing (`container[index]`) operation - #[stable(feature = "rust1", since = "1.0.0")] - fn index(&self, index: Idx) -> &Self::Output; -} - -/// The `IndexMut` trait is used to specify the functionality of indexing -/// operations like `container[index]` when used in a mutable context. -/// -/// `container[index]` is actually syntactic sugar for -/// `*container.index_mut(index)`, but only when used as a mutable value. If -/// an immutable value is requested, the [`Index`] trait is used instead. This -/// allows nice things such as `v[index] = value` if `value` implements [`Copy`]. -/// -/// [`Index`]: ../../std/ops/trait.Index.html -/// [`Copy`]: ../../std/marker/trait.Copy.html -/// -/// # Examples -/// -/// A very simple implementation of a `Balance` struct that has two sides, where -/// each can be indexed mutably and immutably. -/// -/// ``` -/// use std::ops::{Index,IndexMut}; -/// -/// #[derive(Debug)] -/// enum Side { -/// Left, -/// Right, -/// } -/// -/// #[derive(Debug, PartialEq)] -/// enum Weight { -/// Kilogram(f32), -/// Pound(f32), -/// } -/// -/// struct Balance { -/// pub left: Weight, -/// pub right:Weight, -/// } -/// -/// impl Index for Balance { -/// type Output = Weight; -/// -/// fn index<'a>(&'a self, index: Side) -> &'a Weight { -/// println!("Accessing {:?}-side of balance immutably", index); -/// match index { -/// Side::Left => &self.left, -/// Side::Right => &self.right, -/// } -/// } -/// } -/// -/// impl IndexMut for Balance { -/// fn index_mut<'a>(&'a mut self, index: Side) -> &'a mut Weight { -/// println!("Accessing {:?}-side of balance mutably", index); -/// match index { -/// Side::Left => &mut self.left, -/// Side::Right => &mut self.right, -/// } -/// } -/// } -/// -/// fn main() { -/// let mut balance = Balance { -/// right: Weight::Kilogram(2.5), -/// left: Weight::Pound(1.5), -/// }; -/// -/// // In this case balance[Side::Right] is sugar for -/// // *balance.index(Side::Right), since we are only reading -/// // balance[Side::Right], not writing it. -/// assert_eq!(balance[Side::Right],Weight::Kilogram(2.5)); -/// -/// // However in this case balance[Side::Left] is sugar for -/// // *balance.index_mut(Side::Left), since we are writing -/// // balance[Side::Left]. -/// balance[Side::Left] = Weight::Kilogram(3.0); -/// } -/// ``` -#[lang = "index_mut"] -#[rustc_on_unimplemented = "the type `{Self}` cannot be mutably indexed by `{Idx}`"] -#[stable(feature = "rust1", since = "1.0.0")] -pub trait IndexMut: Index { - /// The method for the mutable indexing (`container[index]`) operation - #[stable(feature = "rust1", since = "1.0.0")] - fn index_mut(&mut self, index: Idx) -> &mut Self::Output; -} - -/// An unbounded range. Use `..` (two dots) for its shorthand. -/// -/// Its primary use case is slicing index. It cannot serve as an iterator -/// because it doesn't have a starting point. -/// -/// # Examples -/// -/// The `..` syntax is a `RangeFull`: -/// -/// ``` -/// assert_eq!((..), std::ops::RangeFull); -/// ``` -/// -/// It does not have an `IntoIterator` implementation, so you can't use it in a -/// `for` loop directly. This won't compile: -/// -/// ```ignore -/// for i in .. { -/// // ... -/// } -/// ``` -/// -/// Used as a slicing index, `RangeFull` produces the full array as a slice. -/// -/// ``` -/// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ .. ], [0,1,2,3]); // RangeFull -/// assert_eq!(arr[ ..3], [0,1,2 ]); -/// assert_eq!(arr[1.. ], [ 1,2,3]); -/// assert_eq!(arr[1..3], [ 1,2 ]); -/// ``` -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -#[stable(feature = "rust1", since = "1.0.0")] -pub struct RangeFull; - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for RangeFull { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "..") - } -} - -/// A (half-open) range which is bounded at both ends: { x | start <= x < end }. -/// Use `start..end` (two dots) for its shorthand. -/// -/// See the [`contains`](#method.contains) method for its characterization. -/// -/// # Examples -/// -/// ``` -/// fn main() { -/// assert_eq!((3..5), std::ops::Range{ start: 3, end: 5 }); -/// assert_eq!(3+4+5, (3..6).sum()); -/// -/// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ .. ], [0,1,2,3]); -/// assert_eq!(arr[ ..3], [0,1,2 ]); -/// assert_eq!(arr[1.. ], [ 1,2,3]); -/// assert_eq!(arr[1..3], [ 1,2 ]); // Range -/// } -/// ``` -#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 -#[stable(feature = "rust1", since = "1.0.0")] -pub struct Range { - /// The lower bound of the range (inclusive). - #[stable(feature = "rust1", since = "1.0.0")] - pub start: Idx, - /// The upper bound of the range (exclusive). - #[stable(feature = "rust1", since = "1.0.0")] - pub end: Idx, -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for Range { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{:?}..{:?}", self.start, self.end) - } -} - -#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] -impl> Range { - /// # Examples - /// - /// ``` - /// #![feature(range_contains)] - /// fn main() { - /// assert!( ! (3..5).contains(2)); - /// assert!( (3..5).contains(3)); - /// assert!( (3..5).contains(4)); - /// assert!( ! (3..5).contains(5)); - /// - /// assert!( ! (3..3).contains(3)); - /// assert!( ! (3..2).contains(3)); - /// } - /// ``` - pub fn contains(&self, item: Idx) -> bool { - (self.start <= item) && (item < self.end) - } -} - -/// A range which is only bounded below: { x | start <= x }. -/// Use `start..` for its shorthand. -/// -/// See the [`contains`](#method.contains) method for its characterization. -/// -/// Note: Currently, no overflow checking is done for the iterator -/// implementation; if you use an integer range and the integer overflows, it -/// might panic in debug mode or create an endless loop in release mode. This -/// overflow behavior might change in the future. -/// -/// # Examples -/// -/// ``` -/// fn main() { -/// assert_eq!((2..), std::ops::RangeFrom{ start: 2 }); -/// assert_eq!(2+3+4, (2..).take(3).sum()); -/// -/// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ .. ], [0,1,2,3]); -/// assert_eq!(arr[ ..3], [0,1,2 ]); -/// assert_eq!(arr[1.. ], [ 1,2,3]); // RangeFrom -/// assert_eq!(arr[1..3], [ 1,2 ]); -/// } -/// ``` -#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 -#[stable(feature = "rust1", since = "1.0.0")] -pub struct RangeFrom { - /// The lower bound of the range (inclusive). - #[stable(feature = "rust1", since = "1.0.0")] - pub start: Idx, -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for RangeFrom { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{:?}..", self.start) - } -} - -#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] -impl> RangeFrom { - /// # Examples - /// - /// ``` - /// #![feature(range_contains)] - /// fn main() { - /// assert!( ! (3..).contains(2)); - /// assert!( (3..).contains(3)); - /// assert!( (3..).contains(1_000_000_000)); - /// } - /// ``` - pub fn contains(&self, item: Idx) -> bool { - (self.start <= item) - } -} - -/// A range which is only bounded above: { x | x < end }. -/// Use `..end` (two dots) for its shorthand. -/// -/// See the [`contains`](#method.contains) method for its characterization. -/// -/// It cannot serve as an iterator because it doesn't have a starting point. -/// -/// # Examples -/// -/// The `..{integer}` syntax is a `RangeTo`: -/// -/// ``` -/// assert_eq!((..5), std::ops::RangeTo{ end: 5 }); -/// ``` -/// -/// It does not have an `IntoIterator` implementation, so you can't use it in a -/// `for` loop directly. This won't compile: -/// -/// ```ignore -/// for i in ..5 { -/// // ... -/// } -/// ``` -/// -/// When used as a slicing index, `RangeTo` produces a slice of all array -/// elements before the index indicated by `end`. -/// -/// ``` -/// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ .. ], [0,1,2,3]); -/// assert_eq!(arr[ ..3], [0,1,2 ]); // RangeTo -/// assert_eq!(arr[1.. ], [ 1,2,3]); -/// assert_eq!(arr[1..3], [ 1,2 ]); -/// ``` -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -#[stable(feature = "rust1", since = "1.0.0")] -pub struct RangeTo { - /// The upper bound of the range (exclusive). - #[stable(feature = "rust1", since = "1.0.0")] - pub end: Idx, -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for RangeTo { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "..{:?}", self.end) - } -} - -#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] -impl> RangeTo { - /// # Examples - /// - /// ``` - /// #![feature(range_contains)] - /// fn main() { - /// assert!( (..5).contains(-1_000_000_000)); - /// assert!( (..5).contains(4)); - /// assert!( ! (..5).contains(5)); - /// } - /// ``` - pub fn contains(&self, item: Idx) -> bool { - (item < self.end) - } -} - -/// An inclusive range which is bounded at both ends: { x | start <= x <= end }. -/// Use `start...end` (three dots) for its shorthand. -/// -/// See the [`contains`](#method.contains) method for its characterization. -/// -/// # Examples -/// -/// ``` -/// #![feature(inclusive_range,inclusive_range_syntax)] -/// fn main() { -/// assert_eq!((3...5), std::ops::RangeInclusive{ start: 3, end: 5 }); -/// assert_eq!(3+4+5, (3...5).sum()); -/// -/// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ ...2], [0,1,2 ]); -/// assert_eq!(arr[1...2], [ 1,2 ]); // RangeInclusive -/// } -/// ``` -#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -pub struct RangeInclusive { - /// The lower bound of the range (inclusive). - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", - issue = "28237")] - pub start: Idx, - /// The upper bound of the range (inclusive). - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", - issue = "28237")] - pub end: Idx, -} - -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl fmt::Debug for RangeInclusive { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{:?}...{:?}", self.start, self.end) - } -} - -#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] -impl> RangeInclusive { - /// # Examples - /// - /// ``` - /// #![feature(range_contains,inclusive_range_syntax)] - /// fn main() { - /// assert!( ! (3...5).contains(2)); - /// assert!( (3...5).contains(3)); - /// assert!( (3...5).contains(4)); - /// assert!( (3...5).contains(5)); - /// assert!( ! (3...5).contains(6)); - /// - /// assert!( (3...3).contains(3)); - /// assert!( ! (3...2).contains(3)); - /// } - /// ``` - pub fn contains(&self, item: Idx) -> bool { - self.start <= item && item <= self.end - } -} - -/// An inclusive range which is only bounded above: { x | x <= end }. -/// Use `...end` (three dots) for its shorthand. -/// -/// See the [`contains`](#method.contains) method for its characterization. -/// -/// It cannot serve as an iterator because it doesn't have a starting point. -/// -/// # Examples -/// -/// The `...{integer}` syntax is a `RangeToInclusive`: -/// -/// ``` -/// #![feature(inclusive_range,inclusive_range_syntax)] -/// assert_eq!((...5), std::ops::RangeToInclusive{ end: 5 }); -/// ``` -/// -/// It does not have an `IntoIterator` implementation, so you can't use it in a -/// `for` loop directly. This won't compile: -/// -/// ```ignore -/// for i in ...5 { -/// // ... -/// } -/// ``` -/// -/// When used as a slicing index, `RangeToInclusive` produces a slice of all -/// array elements up to and including the index indicated by `end`. -/// -/// ``` -/// #![feature(inclusive_range_syntax)] -/// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ ...2], [0,1,2 ]); // RangeToInclusive -/// assert_eq!(arr[1...2], [ 1,2 ]); -/// ``` -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -pub struct RangeToInclusive { - /// The upper bound of the range (inclusive) - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", - issue = "28237")] - pub end: Idx, -} - -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl fmt::Debug for RangeToInclusive { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "...{:?}", self.end) - } -} - -#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] -impl> RangeToInclusive { - /// # Examples - /// - /// ``` - /// #![feature(range_contains,inclusive_range_syntax)] - /// fn main() { - /// assert!( (...5).contains(-1_000_000_000)); - /// assert!( (...5).contains(5)); - /// assert!( ! (...5).contains(6)); - /// } - /// ``` - pub fn contains(&self, item: Idx) -> bool { - (item <= self.end) - } -} - -// RangeToInclusive cannot impl From> -// because underflow would be possible with (..0).into() - -/// The `Deref` trait is used to specify the functionality of dereferencing -/// operations, like `*v`. -/// -/// `Deref` also enables ['`Deref` coercions'][coercions]. -/// -/// [coercions]: ../../book/deref-coercions.html -/// -/// # Examples -/// -/// A struct with a single field which is accessible via dereferencing the -/// struct. -/// -/// ``` -/// use std::ops::Deref; -/// -/// struct DerefExample { -/// value: T -/// } -/// -/// impl Deref for DerefExample { -/// type Target = T; -/// -/// fn deref(&self) -> &T { -/// &self.value -/// } -/// } -/// -/// fn main() { -/// let x = DerefExample { value: 'a' }; -/// assert_eq!('a', *x); -/// } -/// ``` -#[lang = "deref"] -#[stable(feature = "rust1", since = "1.0.0")] -pub trait Deref { - /// The resulting type after dereferencing - #[stable(feature = "rust1", since = "1.0.0")] - type Target: ?Sized; - - /// The method called to dereference a value - #[stable(feature = "rust1", since = "1.0.0")] - fn deref(&self) -> &Self::Target; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T: ?Sized> Deref for &'a T { - type Target = T; - - fn deref(&self) -> &T { *self } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T: ?Sized> Deref for &'a mut T { - type Target = T; - - fn deref(&self) -> &T { *self } -} - -/// The `DerefMut` trait is used to specify the functionality of dereferencing -/// mutably like `*v = 1;` -/// -/// `DerefMut` also enables ['`Deref` coercions'][coercions]. -/// -/// [coercions]: ../../book/deref-coercions.html -/// -/// # Examples -/// -/// A struct with a single field which is modifiable via dereferencing the -/// struct. -/// -/// ``` -/// use std::ops::{Deref, DerefMut}; -/// -/// struct DerefMutExample { -/// value: T -/// } -/// -/// impl Deref for DerefMutExample { -/// type Target = T; -/// -/// fn deref(&self) -> &T { -/// &self.value -/// } -/// } -/// -/// impl DerefMut for DerefMutExample { -/// fn deref_mut(&mut self) -> &mut T { -/// &mut self.value -/// } -/// } -/// -/// fn main() { -/// let mut x = DerefMutExample { value: 'a' }; -/// *x = 'b'; -/// assert_eq!('b', *x); -/// } -/// ``` -#[lang = "deref_mut"] -#[stable(feature = "rust1", since = "1.0.0")] -pub trait DerefMut: Deref { - /// The method called to mutably dereference a value - #[stable(feature = "rust1", since = "1.0.0")] - fn deref_mut(&mut self) -> &mut Self::Target; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T: ?Sized> DerefMut for &'a mut T { - fn deref_mut(&mut self) -> &mut T { *self } -} - -/// A version of the call operator that takes an immutable receiver. -/// -/// # Examples -/// -/// Closures automatically implement this trait, which allows them to be -/// invoked. Note, however, that `Fn` takes an immutable reference to any -/// captured variables. To take a mutable capture, implement [`FnMut`], and to -/// consume the capture, implement [`FnOnce`]. -/// -/// [`FnMut`]: trait.FnMut.html -/// [`FnOnce`]: trait.FnOnce.html -/// -/// ``` -/// let square = |x| x * x; -/// assert_eq!(square(5), 25); -/// ``` -/// -/// Closures can also be passed to higher-level functions through a `Fn` -/// parameter (or a `FnMut` or `FnOnce` parameter, which are supertraits of -/// `Fn`). -/// -/// ``` -/// fn call_with_one(func: F) -> usize -/// where F: Fn(usize) -> usize { -/// func(1) -/// } -/// -/// let double = |x| x * 2; -/// assert_eq!(call_with_one(double), 2); -/// ``` -#[lang = "fn"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_paren_sugar] -#[fundamental] // so that regex can rely that `&str: !FnMut` -pub trait Fn : FnMut { - /// This is called when the call operator is used. - #[unstable(feature = "fn_traits", issue = "29625")] - extern "rust-call" fn call(&self, args: Args) -> Self::Output; -} - -/// A version of the call operator that takes a mutable receiver. -/// -/// # Examples -/// -/// Closures that mutably capture variables automatically implement this trait, -/// which allows them to be invoked. -/// -/// ``` -/// let mut x = 5; -/// { -/// let mut square_x = || x *= x; -/// square_x(); -/// } -/// assert_eq!(x, 25); -/// ``` -/// -/// Closures can also be passed to higher-level functions through a `FnMut` -/// parameter (or a `FnOnce` parameter, which is a supertrait of `FnMut`). -/// -/// ``` -/// fn do_twice(mut func: F) -/// where F: FnMut() -/// { -/// func(); -/// func(); -/// } -/// -/// let mut x: usize = 1; -/// { -/// let add_two_to_x = || x += 2; -/// do_twice(add_two_to_x); -/// } -/// -/// assert_eq!(x, 5); -/// ``` -#[lang = "fn_mut"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_paren_sugar] -#[fundamental] // so that regex can rely that `&str: !FnMut` -pub trait FnMut : FnOnce { - /// This is called when the call operator is used. - #[unstable(feature = "fn_traits", issue = "29625")] - extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; -} - -/// A version of the call operator that takes a by-value receiver. -/// -/// # Examples -/// -/// By-value closures automatically implement this trait, which allows them to -/// be invoked. -/// -/// ``` -/// let x = 5; -/// let square_x = move || x * x; -/// assert_eq!(square_x(), 25); -/// ``` -/// -/// By-value Closures can also be passed to higher-level functions through a -/// `FnOnce` parameter. -/// -/// ``` -/// fn consume_with_relish(func: F) -/// where F: FnOnce() -> String -/// { -/// // `func` consumes its captured variables, so it cannot be run more -/// // than once -/// println!("Consumed: {}", func()); -/// -/// println!("Delicious!"); -/// -/// // Attempting to invoke `func()` again will throw a `use of moved -/// // value` error for `func` -/// } -/// -/// let x = String::from("x"); -/// let consume_and_return_x = move || x; -/// consume_with_relish(consume_and_return_x); -/// -/// // `consume_and_return_x` can no longer be invoked at this point -/// ``` -#[lang = "fn_once"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_paren_sugar] -#[fundamental] // so that regex can rely that `&str: !FnMut` -pub trait FnOnce { - /// The returned type after the call operator is used. - #[stable(feature = "fn_once_output", since = "1.12.0")] - type Output; - - /// This is called when the call operator is used. - #[unstable(feature = "fn_traits", issue = "29625")] - extern "rust-call" fn call_once(self, args: Args) -> Self::Output; -} - -mod impls { - #[stable(feature = "rust1", since = "1.0.0")] - impl<'a,A,F:?Sized> Fn for &'a F - where F : Fn - { - extern "rust-call" fn call(&self, args: A) -> F::Output { - (**self).call(args) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl<'a,A,F:?Sized> FnMut for &'a F - where F : Fn - { - extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { - (**self).call(args) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl<'a,A,F:?Sized> FnOnce for &'a F - where F : Fn - { - type Output = F::Output; - - extern "rust-call" fn call_once(self, args: A) -> F::Output { - (*self).call(args) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl<'a,A,F:?Sized> FnMut for &'a mut F - where F : FnMut - { - extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { - (*self).call_mut(args) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl<'a,A,F:?Sized> FnOnce for &'a mut F - where F : FnMut - { - type Output = F::Output; - extern "rust-call" fn call_once(mut self, args: A) -> F::Output { - (*self).call_mut(args) - } - } -} - -/// 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 { - // Empty. -} - -// &mut T -> &mut U -#[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {} -// &mut T -> &U -#[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, 'b: 'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {} -// &mut T -> *mut U -#[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {} -// &mut T -> *const U -#[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {} - -// &T -> &U -#[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, 'b: 'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} -// &T -> *const U -#[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a T {} - -// *mut T -> *mut U -#[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} -// *mut T -> *const U -#[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U: ?Sized> CoerceUnsized<*const U> for *mut T {} - -// *const T -> *const U -#[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} - -/// 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. -/// -/// A `Place` can be thought of as a special representation for a -/// hypothetical `&uninit` reference (which Rust cannot currently -/// express directly). That is, it represents a pointer to -/// uninitialized storage. -/// -/// The client is responsible for two steps: First, initializing the -/// payload (it can access its address via `pointer`). Second, -/// converting the agent to an instance of the owning pointer, via the -/// appropriate `finalize` method (see the `InPlace`. -/// -/// 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")] -pub trait Place { - /// Returns the address where the input value will be written. - /// Note that the data at this address is generally uninitialized, - /// and thus one should use `ptr::write` for initializing it. - fn pointer(&mut self) -> *mut Data; -} - -/// Interface to implementations of `PLACE <- EXPR`. -/// -/// `PLACE <- EXPR` effectively desugars into: -/// -/// ```rust,ignore -/// let p = PLACE; -/// let mut place = Placer::make_place(p); -/// let raw_place = Place::pointer(&mut place); -/// let value = EXPR; -/// unsafe { -/// std::ptr::write(raw_place, value); -/// InPlace::finalize(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). -/// -/// Values for types implementing this trait usually are transient -/// intermediate values (e.g. the return value of `Vec::emplace_back`) -/// or `Copy`, since the `make_place` method takes `self` by value. -#[unstable(feature = "placement_new_protocol", issue = "27779")] -pub trait Placer { - /// `Place` is the intermedate agent guarding the - /// uninitialized state for `Data`. - type Place: InPlace; - - /// Creates a fresh place from `self`. - fn make_place(self) -> Self::Place; -} - -/// 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 `PLACE <- EXPR` - /// - /// 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 - /// case). - type Owner; - - /// Converts self into the final value, shifting - /// deallocation/cleanup responsibilities (if any remain), over to - /// the returned instance of `Owner` and forgetting self. - unsafe fn finalize(self) -> Self::Owner; -} - -/// Core trait for the `box EXPR` form. -/// -/// `box EXPR` effectively desugars into: -/// -/// ```rust,ignore -/// let mut place = BoxPlace::make_place(); -/// let raw_place = Place::pointer(&mut place); -/// let value = EXPR; -/// unsafe { -/// ::std::ptr::write(raw_place, value); -/// Boxed::finalize(place) -/// } -/// ``` -/// -/// The type of `box EXPR` is supplied from its surrounding -/// context; in the above expansion, the result type `T` is used -/// to determine which implementation of `Boxed` to use, and that -/// `` in turn dictates determines which -/// implementation of `BoxPlace` to use, namely: -/// `<::Place as BoxPlace>`. -#[unstable(feature = "placement_new_protocol", issue = "27779")] -pub trait Boxed { - /// The kind of data that is stored in this kind of box. - type Data; /* (`Data` unused b/c cannot yet express below bound.) */ - /// The place that will negotiate the storage of the data. - type Place: BoxPlace; - - /// Converts filled place into final owning value, shifting - /// deallocation/cleanup responsibilities (if any remain), over to - /// returned instance of `Self` and forgetting `filled`. - unsafe fn finalize(filled: Self::Place) -> Self; -} - -/// Specialization of `Place` trait supporting `box EXPR`. -#[unstable(feature = "placement_new_protocol", issue = "27779")] -pub trait BoxPlace : Place { - /// Creates a globally fresh place. - fn make_place() -> Self; -} - -/// This trait has been superseded by the `Try` trait, but must remain -/// here as `?` is still lowered to it in stage0 . -#[cfg(stage0)] -#[unstable(feature = "question_mark_carrier", issue = "31436")] -pub trait Carrier { - /// The type of the value when computation succeeds. - type Success; - /// The type of the value when computation errors out. - type Error; - - /// Create a `Carrier` from a success value. - fn from_success(_: Self::Success) -> Self; - - /// Create a `Carrier` from an error value. - fn from_error(_: Self::Error) -> Self; - - /// Translate this `Carrier` to another implementation of `Carrier` with the - /// same associated types. - fn translate(self) -> T where T: Carrier; -} - -#[cfg(stage0)] -#[unstable(feature = "question_mark_carrier", issue = "31436")] -impl Carrier for Result { - type Success = U; - type Error = V; - - fn from_success(u: U) -> Result { - Ok(u) - } - - fn from_error(e: V) -> Result { - Err(e) - } - - fn translate(self) -> T - where T: Carrier - { - match self { - Ok(u) => T::from_success(u), - Err(e) => T::from_error(e), - } - } -} - -struct _DummyErrorType; - -impl Try for _DummyErrorType { - type Ok = (); - type Error = (); - - fn into_result(self) -> Result { - Ok(()) - } - - fn from_ok(_: ()) -> _DummyErrorType { - _DummyErrorType - } - - fn from_error(_: ()) -> _DummyErrorType { - _DummyErrorType - } -} - -/// A trait for customizing the behaviour of the `?` operator. -/// -/// A type implementing `Try` is one that has a canonical way to view it -/// in terms of a success/failure dichotomy. This trait allows both -/// extracting those success or failure values from an existing instance and -/// creating a new instance from a success or failure value. -#[unstable(feature = "try_trait", issue = "42327")] -pub trait Try { - /// The type of this value when viewed as successful. - #[unstable(feature = "try_trait", issue = "42327")] - type Ok; - /// The type of this value when viewed as failed. - #[unstable(feature = "try_trait", issue = "42327")] - type Error; - - /// Applies the "?" operator. A return of `Ok(t)` means that the - /// execution should continue normally, and the result of `?` is the - /// value `t`. A return of `Err(e)` means that execution should branch - /// to the innermost enclosing `catch`, or return from the function. - /// - /// If an `Err(e)` result is returned, the value `e` will be "wrapped" - /// in the return type of the enclosing scope (which must itself implement - /// `Try`). Specifically, the value `X::from_error(From::from(e))` - /// is returned, where `X` is the return type of the enclosing function. - #[unstable(feature = "try_trait", issue = "42327")] - fn into_result(self) -> Result; - - /// Wrap an error value to construct the composite result. For example, - /// `Result::Err(x)` and `Result::from_error(x)` are equivalent. - #[unstable(feature = "try_trait", issue = "42327")] - fn from_error(v: Self::Error) -> Self; - - /// Wrap an OK value to construct the composite result. For example, - /// `Result::Ok(x)` and `Result::from_ok(x)` are equivalent. - #[unstable(feature = "try_trait", issue = "42327")] - fn from_ok(v: Self::Ok) -> Self; -} diff --git a/src/libcore/ops/arith.rs b/src/libcore/ops/arith.rs new file mode 100644 index 0000000000..c6fb75f6ac --- /dev/null +++ b/src/libcore/ops/arith.rs @@ -0,0 +1,873 @@ +// 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. + +/// The addition operator `+`. +/// +/// # Examples +/// +/// This example creates a `Point` struct that implements the `Add` trait, and +/// then demonstrates adding two `Point`s. +/// +/// ``` +/// use std::ops::Add; +/// +/// #[derive(Debug)] +/// struct Point { +/// x: i32, +/// y: i32, +/// } +/// +/// impl Add for Point { +/// type Output = Point; +/// +/// fn add(self, other: Point) -> Point { +/// Point { +/// x: self.x + other.x, +/// y: self.y + other.y, +/// } +/// } +/// } +/// +/// impl PartialEq for Point { +/// fn eq(&self, other: &Self) -> bool { +/// self.x == other.x && self.y == other.y +/// } +/// } +/// +/// fn main() { +/// assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 }, +/// Point { x: 3, y: 3 }); +/// } +/// ``` +/// +/// Here is an example of the same `Point` struct implementing the `Add` trait +/// using generics. +/// +/// ``` +/// use std::ops::Add; +/// +/// #[derive(Debug)] +/// struct Point { +/// x: T, +/// y: T, +/// } +/// +/// // Notice that the implementation uses the `Output` associated type +/// impl> Add for Point { +/// type Output = Point; +/// +/// fn add(self, other: Point) -> Point { +/// Point { +/// x: self.x + other.x, +/// y: self.y + other.y, +/// } +/// } +/// } +/// +/// impl PartialEq for Point { +/// fn eq(&self, other: &Self) -> bool { +/// self.x == other.x && self.y == other.y +/// } +/// } +/// +/// fn main() { +/// assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 }, +/// Point { x: 3, y: 3 }); +/// } +/// ``` +/// +/// Note that `RHS = Self` by default, but this is not mandatory. For example, +/// [std::time::SystemTime] implements `Add`, which permits +/// operations of the form `SystemTime = SystemTime + Duration`. +/// +/// [std::time::SystemTime]: ../../std/time/struct.SystemTime.html +#[lang = "add"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} + {RHS}`"] +pub trait Add { + /// The resulting type after applying the `+` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `+` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn add(self, rhs: RHS) -> Self::Output; +} + +macro_rules! add_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Add for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn add(self, other: $t) -> $t { self + other } + } + + forward_ref_binop! { impl Add, add for $t, $t } + )*) +} + +add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } + +/// The subtraction operator `-`. +/// +/// # Examples +/// +/// This example creates a `Point` struct that implements the `Sub` trait, and +/// then demonstrates subtracting two `Point`s. +/// +/// ``` +/// use std::ops::Sub; +/// +/// #[derive(Debug)] +/// struct Point { +/// x: i32, +/// y: i32, +/// } +/// +/// impl Sub for Point { +/// type Output = Point; +/// +/// fn sub(self, other: Point) -> Point { +/// Point { +/// x: self.x - other.x, +/// y: self.y - other.y, +/// } +/// } +/// } +/// +/// impl PartialEq for Point { +/// fn eq(&self, other: &Self) -> bool { +/// self.x == other.x && self.y == other.y +/// } +/// } +/// +/// fn main() { +/// assert_eq!(Point { x: 3, y: 3 } - Point { x: 2, y: 3 }, +/// Point { x: 1, y: 0 }); +/// } +/// ``` +/// +/// Note that `RHS = Self` by default, but this is not mandatory. For example, +/// [std::time::SystemTime] implements `Sub`, which permits +/// operations of the form `SystemTime = SystemTime - Duration`. +/// +/// [std::time::SystemTime]: ../../std/time/struct.SystemTime.html +#[lang = "sub"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} - {RHS}`"] +pub trait Sub { + /// The resulting type after applying the `-` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `-` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn sub(self, rhs: RHS) -> Self::Output; +} + +macro_rules! sub_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Sub for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn sub(self, other: $t) -> $t { self - other } + } + + forward_ref_binop! { impl Sub, sub for $t, $t } + )*) +} + +sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } + +/// The multiplication operator `*`. +/// +/// # Examples +/// +/// Implementing a `Mul`tipliable rational number struct: +/// +/// ``` +/// use std::ops::Mul; +/// +/// // The uniqueness of rational numbers in lowest terms is a consequence of +/// // the fundamental theorem of arithmetic. +/// #[derive(Eq)] +/// #[derive(PartialEq, Debug)] +/// struct Rational { +/// nominator: usize, +/// denominator: usize, +/// } +/// +/// impl Rational { +/// fn new(nominator: usize, denominator: usize) -> Self { +/// if denominator == 0 { +/// panic!("Zero is an invalid denominator!"); +/// } +/// +/// // Reduce to lowest terms by dividing by the greatest common +/// // divisor. +/// let gcd = gcd(nominator, denominator); +/// Rational { +/// nominator: nominator / gcd, +/// denominator: denominator / gcd, +/// } +/// } +/// } +/// +/// impl Mul for Rational { +/// // The multiplication of rational numbers is a closed operation. +/// type Output = Self; +/// +/// fn mul(self, rhs: Self) -> Self { +/// let nominator = self.nominator * rhs.nominator; +/// let denominator = self.denominator * rhs.denominator; +/// Rational::new(nominator, denominator) +/// } +/// } +/// +/// // Euclid's two-thousand-year-old algorithm for finding the greatest common +/// // divisor. +/// fn gcd(x: usize, y: usize) -> usize { +/// let mut x = x; +/// let mut y = y; +/// while y != 0 { +/// let t = y; +/// y = x % y; +/// x = t; +/// } +/// x +/// } +/// +/// assert_eq!(Rational::new(1, 2), Rational::new(2, 4)); +/// assert_eq!(Rational::new(2, 3) * Rational::new(3, 4), +/// Rational::new(1, 2)); +/// ``` +/// +/// Note that `RHS = Self` by default, but this is not mandatory. Here is an +/// implementation which enables multiplication of vectors by scalars, as is +/// done in linear algebra. +/// +/// ``` +/// use std::ops::Mul; +/// +/// struct Scalar {value: usize}; +/// +/// #[derive(Debug)] +/// struct Vector {value: Vec}; +/// +/// impl Mul for Scalar { +/// type Output = Vector; +/// +/// fn mul(self, rhs: Vector) -> Vector { +/// Vector {value: rhs.value.iter().map(|v| self.value * v).collect()} +/// } +/// } +/// +/// impl PartialEq for Vector { +/// fn eq(&self, other: &Self) -> bool { +/// self.value == other.value +/// } +/// } +/// +/// let scalar = Scalar{value: 3}; +/// let vector = Vector{value: vec![2, 4, 6]}; +/// assert_eq!(scalar * vector, Vector{value: vec![6, 12, 18]}); +/// ``` +#[lang = "mul"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} * {RHS}`"] +pub trait Mul { + /// The resulting type after applying the `*` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `*` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn mul(self, rhs: RHS) -> Self::Output; +} + +macro_rules! mul_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Mul for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn mul(self, other: $t) -> $t { self * other } + } + + forward_ref_binop! { impl Mul, mul for $t, $t } + )*) +} + +mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } + +/// The division operator `/`. +/// +/// # Examples +/// +/// Implementing a `Div`idable rational number struct: +/// +/// ``` +/// use std::ops::Div; +/// +/// // The uniqueness of rational numbers in lowest terms is a consequence of +/// // the fundamental theorem of arithmetic. +/// #[derive(Eq)] +/// #[derive(PartialEq, Debug)] +/// struct Rational { +/// nominator: usize, +/// denominator: usize, +/// } +/// +/// impl Rational { +/// fn new(nominator: usize, denominator: usize) -> Self { +/// if denominator == 0 { +/// panic!("Zero is an invalid denominator!"); +/// } +/// +/// // Reduce to lowest terms by dividing by the greatest common +/// // divisor. +/// let gcd = gcd(nominator, denominator); +/// Rational { +/// nominator: nominator / gcd, +/// denominator: denominator / gcd, +/// } +/// } +/// } +/// +/// impl Div for Rational { +/// // The division of rational numbers is a closed operation. +/// type Output = Self; +/// +/// fn div(self, rhs: Self) -> Self { +/// if rhs.nominator == 0 { +/// panic!("Cannot divide by zero-valued `Rational`!"); +/// } +/// +/// let nominator = self.nominator * rhs.denominator; +/// let denominator = self.denominator * rhs.nominator; +/// Rational::new(nominator, denominator) +/// } +/// } +/// +/// // Euclid's two-thousand-year-old algorithm for finding the greatest common +/// // divisor. +/// fn gcd(x: usize, y: usize) -> usize { +/// let mut x = x; +/// let mut y = y; +/// while y != 0 { +/// let t = y; +/// y = x % y; +/// x = t; +/// } +/// x +/// } +/// +/// fn main() { +/// assert_eq!(Rational::new(1, 2), Rational::new(2, 4)); +/// assert_eq!(Rational::new(1, 2) / Rational::new(3, 4), +/// Rational::new(2, 3)); +/// } +/// ``` +/// +/// Note that `RHS = Self` by default, but this is not mandatory. Here is an +/// implementation which enables division of vectors by scalars, as is done in +/// linear algebra. +/// +/// ``` +/// use std::ops::Div; +/// +/// struct Scalar {value: f32}; +/// +/// #[derive(Debug)] +/// struct Vector {value: Vec}; +/// +/// impl Div for Vector { +/// type Output = Vector; +/// +/// fn div(self, rhs: Scalar) -> Vector { +/// Vector {value: self.value.iter().map(|v| v / rhs.value).collect()} +/// } +/// } +/// +/// impl PartialEq for Vector { +/// fn eq(&self, other: &Self) -> bool { +/// self.value == other.value +/// } +/// } +/// +/// let scalar = Scalar{value: 2f32}; +/// let vector = Vector{value: vec![2f32, 4f32, 6f32]}; +/// assert_eq!(vector / scalar, Vector{value: vec![1f32, 2f32, 3f32]}); +/// ``` +#[lang = "div"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} / {RHS}`"] +pub trait Div { + /// The resulting type after applying the `/` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `/` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn div(self, rhs: RHS) -> Self::Output; +} + +macro_rules! div_impl_integer { + ($($t:ty)*) => ($( + /// This operation rounds towards zero, truncating any + /// fractional part of the exact result. + #[stable(feature = "rust1", since = "1.0.0")] + impl Div for $t { + type Output = $t; + + #[inline] + fn div(self, other: $t) -> $t { self / other } + } + + forward_ref_binop! { impl Div, div for $t, $t } + )*) +} + +div_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +macro_rules! div_impl_float { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Div for $t { + type Output = $t; + + #[inline] + fn div(self, other: $t) -> $t { self / other } + } + + forward_ref_binop! { impl Div, div for $t, $t } + )*) +} + +div_impl_float! { f32 f64 } + +/// The remainder operator `%`. +/// +/// # Examples +/// +/// This example implements `Rem` on a `SplitSlice` object. After `Rem` is +/// implemented, one can use the `%` operator to find out what the remaining +/// elements of the slice would be after splitting it into equal slices of a +/// given length. +/// +/// ``` +/// use std::ops::Rem; +/// +/// #[derive(PartialEq, Debug)] +/// struct SplitSlice<'a, T: 'a> { +/// slice: &'a [T], +/// } +/// +/// impl<'a, T> Rem for SplitSlice<'a, T> { +/// type Output = SplitSlice<'a, T>; +/// +/// fn rem(self, modulus: usize) -> Self { +/// let len = self.slice.len(); +/// let rem = len % modulus; +/// let start = len - rem; +/// SplitSlice {slice: &self.slice[start..]} +/// } +/// } +/// +/// // If we were to divide &[0, 1, 2, 3, 4, 5, 6, 7] into slices of size 3, +/// // the remainder would be &[6, 7] +/// assert_eq!(SplitSlice { slice: &[0, 1, 2, 3, 4, 5, 6, 7] } % 3, +/// SplitSlice { slice: &[6, 7] }); +/// ``` +#[lang = "rem"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} % {RHS}`"] +pub trait Rem { + /// The resulting type after applying the `%` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output = Self; + + /// The method for the `%` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn rem(self, rhs: RHS) -> Self::Output; +} + +macro_rules! rem_impl_integer { + ($($t:ty)*) => ($( + /// This operation satisfies `n % d == n - (n / d) * d`. The + /// result has the same sign as the left operand. + #[stable(feature = "rust1", since = "1.0.0")] + impl Rem for $t { + type Output = $t; + + #[inline] + fn rem(self, other: $t) -> $t { self % other } + } + + forward_ref_binop! { impl Rem, rem for $t, $t } + )*) +} + +rem_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + + +macro_rules! rem_impl_float { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Rem for $t { + type Output = $t; + + #[inline] + fn rem(self, other: $t) -> $t { self % other } + } + + forward_ref_binop! { impl Rem, rem for $t, $t } + )*) +} + +rem_impl_float! { f32 f64 } + +/// The unary negation operator `-`. +/// +/// # Examples +/// +/// An implementation of `Neg` for `Sign`, which allows the use of `-` to +/// negate its value. +/// +/// ``` +/// use std::ops::Neg; +/// +/// #[derive(Debug, PartialEq)] +/// enum Sign { +/// Negative, +/// Zero, +/// Positive, +/// } +/// +/// impl Neg for Sign { +/// type Output = Sign; +/// +/// fn neg(self) -> Sign { +/// match self { +/// Sign::Negative => Sign::Positive, +/// Sign::Zero => Sign::Zero, +/// Sign::Positive => Sign::Negative, +/// } +/// } +/// } +/// +/// // a negative positive is a negative +/// assert_eq!(-Sign::Positive, Sign::Negative); +/// // a double negative is a positive +/// assert_eq!(-Sign::Negative, Sign::Positive); +/// // zero is its own negation +/// assert_eq!(-Sign::Zero, Sign::Zero); +/// ``` +#[lang = "neg"] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Neg { + /// The resulting type after applying the `-` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the unary `-` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn neg(self) -> Self::Output; +} + + + +macro_rules! neg_impl_core { + ($id:ident => $body:expr, $($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Neg for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn neg(self) -> $t { let $id = self; $body } + } + + forward_ref_unop! { impl Neg, neg for $t } + )*) +} + +macro_rules! neg_impl_numeric { + ($($t:ty)*) => { neg_impl_core!{ x => -x, $($t)*} } +} + +#[allow(unused_macros)] +macro_rules! neg_impl_unsigned { + ($($t:ty)*) => { + neg_impl_core!{ x => { + !x.wrapping_add(1) + }, $($t)*} } +} + +// neg_impl_unsigned! { usize u8 u16 u32 u64 } +neg_impl_numeric! { isize i8 i16 i32 i64 i128 f32 f64 } + +/// The addition assignment operator `+=`. +/// +/// # Examples +/// +/// This example creates a `Point` struct that implements the `AddAssign` +/// trait, and then demonstrates add-assigning to a mutable `Point`. +/// +/// ``` +/// use std::ops::AddAssign; +/// +/// #[derive(Debug)] +/// struct Point { +/// x: i32, +/// y: i32, +/// } +/// +/// impl AddAssign for Point { +/// fn add_assign(&mut self, other: Point) { +/// *self = Point { +/// x: self.x + other.x, +/// y: self.y + other.y, +/// }; +/// } +/// } +/// +/// impl PartialEq for Point { +/// fn eq(&self, other: &Self) -> bool { +/// self.x == other.x && self.y == other.y +/// } +/// } +/// +/// let mut point = Point { x: 1, y: 0 }; +/// point += Point { x: 2, y: 3 }; +/// assert_eq!(point, Point { x: 3, y: 3 }); +/// ``` +#[lang = "add_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} += {Rhs}`"] +pub trait AddAssign { + /// The method for the `+=` operator + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn add_assign(&mut self, rhs: Rhs); +} + +macro_rules! add_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl AddAssign for $t { + #[inline] + #[rustc_inherit_overflow_checks] + fn add_assign(&mut self, other: $t) { *self += other } + } + )+) +} + +add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } + +/// The subtraction assignment operator `-=`. +/// +/// # Examples +/// +/// This example creates a `Point` struct that implements the `SubAssign` +/// trait, and then demonstrates sub-assigning to a mutable `Point`. +/// +/// ``` +/// use std::ops::SubAssign; +/// +/// #[derive(Debug)] +/// struct Point { +/// x: i32, +/// y: i32, +/// } +/// +/// impl SubAssign for Point { +/// fn sub_assign(&mut self, other: Point) { +/// *self = Point { +/// x: self.x - other.x, +/// y: self.y - other.y, +/// }; +/// } +/// } +/// +/// impl PartialEq for Point { +/// fn eq(&self, other: &Self) -> bool { +/// self.x == other.x && self.y == other.y +/// } +/// } +/// +/// let mut point = Point { x: 3, y: 3 }; +/// point -= Point { x: 2, y: 3 }; +/// assert_eq!(point, Point {x: 1, y: 0}); +/// ``` +#[lang = "sub_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} -= {Rhs}`"] +pub trait SubAssign { + /// The method for the `-=` operator + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn sub_assign(&mut self, rhs: Rhs); +} + +macro_rules! sub_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl SubAssign for $t { + #[inline] + #[rustc_inherit_overflow_checks] + fn sub_assign(&mut self, other: $t) { *self -= other } + } + )+) +} + +sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } + +/// The multiplication assignment operator `*=`. +/// +/// # Examples +/// +/// A trivial implementation of `MulAssign`. When `Foo *= Foo` happens, it ends up +/// calling `mul_assign`, and therefore, `main` prints `Multiplying!`. +/// +/// ``` +/// use std::ops::MulAssign; +/// +/// struct Foo; +/// +/// impl MulAssign for Foo { +/// fn mul_assign(&mut self, _rhs: Foo) { +/// println!("Multiplying!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo *= Foo; +/// } +/// ``` +#[lang = "mul_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} *= {Rhs}`"] +pub trait MulAssign { + /// The method for the `*=` operator + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn mul_assign(&mut self, rhs: Rhs); +} + +macro_rules! mul_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl MulAssign for $t { + #[inline] + #[rustc_inherit_overflow_checks] + fn mul_assign(&mut self, other: $t) { *self *= other } + } + )+) +} + +mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } + +/// The division assignment operator `/=`. +/// +/// # Examples +/// +/// A trivial implementation of `DivAssign`. When `Foo /= Foo` happens, it ends up +/// calling `div_assign`, and therefore, `main` prints `Dividing!`. +/// +/// ``` +/// use std::ops::DivAssign; +/// +/// struct Foo; +/// +/// impl DivAssign for Foo { +/// fn div_assign(&mut self, _rhs: Foo) { +/// println!("Dividing!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo /= Foo; +/// } +/// ``` +#[lang = "div_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} /= {Rhs}`"] +pub trait DivAssign { + /// The method for the `/=` operator + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn div_assign(&mut self, rhs: Rhs); +} + +macro_rules! div_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl DivAssign for $t { + #[inline] + fn div_assign(&mut self, other: $t) { *self /= other } + } + )+) +} + +div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } + +/// The remainder assignment operator `%=`. +/// +/// # Examples +/// +/// A trivial implementation of `RemAssign`. When `Foo %= Foo` happens, it ends up +/// calling `rem_assign`, and therefore, `main` prints `Remainder-ing!`. +/// +/// ``` +/// use std::ops::RemAssign; +/// +/// struct Foo; +/// +/// impl RemAssign for Foo { +/// fn rem_assign(&mut self, _rhs: Foo) { +/// println!("Remainder-ing!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo %= Foo; +/// } +/// ``` +#[lang = "rem_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} %= {Rhs}`"] +pub trait RemAssign { + /// The method for the `%=` operator + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn rem_assign(&mut self, rhs: Rhs); +} + +macro_rules! rem_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl RemAssign for $t { + #[inline] + fn rem_assign(&mut self, other: $t) { *self %= other } + } + )+) +} + +rem_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } diff --git a/src/libcore/ops/bit.rs b/src/libcore/ops/bit.rs new file mode 100644 index 0000000000..8743be3557 --- /dev/null +++ b/src/libcore/ops/bit.rs @@ -0,0 +1,839 @@ +// 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. + +/// The unary logical negation operator `!`. +/// +/// # Examples +/// +/// An implementation of `Not` for `Answer`, which enables the use of `!` to +/// invert its value. +/// +/// ``` +/// use std::ops::Not; +/// +/// #[derive(Debug, PartialEq)] +/// enum Answer { +/// Yes, +/// No, +/// } +/// +/// impl Not for Answer { +/// type Output = Answer; +/// +/// fn not(self) -> Answer { +/// match self { +/// Answer::Yes => Answer::No, +/// Answer::No => Answer::Yes +/// } +/// } +/// } +/// +/// assert_eq!(!Answer::Yes, Answer::No); +/// assert_eq!(!Answer::No, Answer::Yes); +/// ``` +#[lang = "not"] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Not { + /// The resulting type after applying the `!` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the unary `!` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn not(self) -> Self::Output; +} + +macro_rules! not_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Not for $t { + type Output = $t; + + #[inline] + fn not(self) -> $t { !self } + } + + forward_ref_unop! { impl Not, not for $t } + )*) +} + +not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The bitwise AND operator `&`. +/// +/// # Examples +/// +/// In this example, the `&` operator is lifted to a trivial `Scalar` type. +/// +/// ``` +/// use std::ops::BitAnd; +/// +/// #[derive(Debug, PartialEq)] +/// struct Scalar(bool); +/// +/// impl BitAnd for Scalar { +/// type Output = Self; +/// +/// // rhs is the "right-hand side" of the expression `a & b` +/// fn bitand(self, rhs: Self) -> Self { +/// Scalar(self.0 & rhs.0) +/// } +/// } +/// +/// fn main() { +/// assert_eq!(Scalar(true) & Scalar(true), Scalar(true)); +/// assert_eq!(Scalar(true) & Scalar(false), Scalar(false)); +/// assert_eq!(Scalar(false) & Scalar(true), Scalar(false)); +/// assert_eq!(Scalar(false) & Scalar(false), Scalar(false)); +/// } +/// ``` +/// +/// In this example, the `BitAnd` trait is implemented for a `BooleanVector` +/// struct. +/// +/// ``` +/// use std::ops::BitAnd; +/// +/// #[derive(Debug, PartialEq)] +/// struct BooleanVector(Vec); +/// +/// impl BitAnd for BooleanVector { +/// type Output = Self; +/// +/// fn bitand(self, BooleanVector(rhs): Self) -> Self { +/// let BooleanVector(lhs) = self; +/// assert_eq!(lhs.len(), rhs.len()); +/// BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x && *y).collect()) +/// } +/// } +/// +/// fn main() { +/// let bv1 = BooleanVector(vec![true, true, false, false]); +/// let bv2 = BooleanVector(vec![true, false, true, false]); +/// let expected = BooleanVector(vec![true, false, false, false]); +/// assert_eq!(bv1 & bv2, expected); +/// } +/// ``` +#[lang = "bitand"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} & {RHS}`"] +pub trait BitAnd { + /// The resulting type after applying the `&` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `&` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn bitand(self, rhs: RHS) -> Self::Output; +} + +macro_rules! bitand_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl BitAnd for $t { + type Output = $t; + + #[inline] + fn bitand(self, rhs: $t) -> $t { self & rhs } + } + + forward_ref_binop! { impl BitAnd, bitand for $t, $t } + )*) +} + +bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The bitwise OR operator `|`. +/// +/// # Examples +/// +/// In this example, the `|` operator is lifted to a trivial `Scalar` type. +/// +/// ``` +/// use std::ops::BitOr; +/// +/// #[derive(Debug, PartialEq)] +/// struct Scalar(bool); +/// +/// impl BitOr for Scalar { +/// type Output = Self; +/// +/// // rhs is the "right-hand side" of the expression `a | b` +/// fn bitor(self, rhs: Self) -> Self { +/// Scalar(self.0 | rhs.0) +/// } +/// } +/// +/// fn main() { +/// assert_eq!(Scalar(true) | Scalar(true), Scalar(true)); +/// assert_eq!(Scalar(true) | Scalar(false), Scalar(true)); +/// assert_eq!(Scalar(false) | Scalar(true), Scalar(true)); +/// assert_eq!(Scalar(false) | Scalar(false), Scalar(false)); +/// } +/// ``` +/// +/// In this example, the `BitOr` trait is implemented for a `BooleanVector` +/// struct. +/// +/// ``` +/// use std::ops::BitOr; +/// +/// #[derive(Debug, PartialEq)] +/// struct BooleanVector(Vec); +/// +/// impl BitOr for BooleanVector { +/// type Output = Self; +/// +/// fn bitor(self, BooleanVector(rhs): Self) -> Self { +/// let BooleanVector(lhs) = self; +/// assert_eq!(lhs.len(), rhs.len()); +/// BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x || *y).collect()) +/// } +/// } +/// +/// fn main() { +/// let bv1 = BooleanVector(vec![true, true, false, false]); +/// let bv2 = BooleanVector(vec![true, false, true, false]); +/// let expected = BooleanVector(vec![true, true, true, false]); +/// assert_eq!(bv1 | bv2, expected); +/// } +/// ``` +#[lang = "bitor"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} | {RHS}`"] +pub trait BitOr { + /// The resulting type after applying the `|` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `|` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn bitor(self, rhs: RHS) -> Self::Output; +} + +macro_rules! bitor_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl BitOr for $t { + type Output = $t; + + #[inline] + fn bitor(self, rhs: $t) -> $t { self | rhs } + } + + forward_ref_binop! { impl BitOr, bitor for $t, $t } + )*) +} + +bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The bitwise XOR operator `^`. +/// +/// # Examples +/// +/// In this example, the `^` operator is lifted to a trivial `Scalar` type. +/// +/// ``` +/// use std::ops::BitXor; +/// +/// #[derive(Debug, PartialEq)] +/// struct Scalar(bool); +/// +/// impl BitXor for Scalar { +/// type Output = Self; +/// +/// // rhs is the "right-hand side" of the expression `a ^ b` +/// fn bitxor(self, rhs: Self) -> Self { +/// Scalar(self.0 ^ rhs.0) +/// } +/// } +/// +/// fn main() { +/// assert_eq!(Scalar(true) ^ Scalar(true), Scalar(false)); +/// assert_eq!(Scalar(true) ^ Scalar(false), Scalar(true)); +/// assert_eq!(Scalar(false) ^ Scalar(true), Scalar(true)); +/// assert_eq!(Scalar(false) ^ Scalar(false), Scalar(false)); +/// } +/// ``` +/// +/// In this example, the `BitXor` trait is implemented for a `BooleanVector` +/// struct. +/// +/// ``` +/// use std::ops::BitXor; +/// +/// #[derive(Debug, PartialEq)] +/// struct BooleanVector(Vec); +/// +/// impl BitXor for BooleanVector { +/// type Output = Self; +/// +/// fn bitxor(self, BooleanVector(rhs): Self) -> Self { +/// let BooleanVector(lhs) = self; +/// assert_eq!(lhs.len(), rhs.len()); +/// BooleanVector(lhs.iter() +/// .zip(rhs.iter()) +/// .map(|(x, y)| (*x || *y) && !(*x && *y)) +/// .collect()) +/// } +/// } +/// +/// fn main() { +/// let bv1 = BooleanVector(vec![true, true, false, false]); +/// let bv2 = BooleanVector(vec![true, false, true, false]); +/// let expected = BooleanVector(vec![false, true, true, false]); +/// assert_eq!(bv1 ^ bv2, expected); +/// } +/// ``` +#[lang = "bitxor"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} ^ {RHS}`"] +pub trait BitXor { + /// The resulting type after applying the `^` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `^` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn bitxor(self, rhs: RHS) -> Self::Output; +} + +macro_rules! bitxor_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl BitXor for $t { + type Output = $t; + + #[inline] + fn bitxor(self, other: $t) -> $t { self ^ other } + } + + forward_ref_binop! { impl BitXor, bitxor for $t, $t } + )*) +} + +bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The left shift operator `<<`. +/// +/// # Examples +/// +/// An implementation of `Shl` that lifts the `<<` operation on integers to a +/// `Scalar` struct. +/// +/// ``` +/// use std::ops::Shl; +/// +/// #[derive(PartialEq, Debug)] +/// struct Scalar(usize); +/// +/// impl Shl for Scalar { +/// type Output = Self; +/// +/// fn shl(self, Scalar(rhs): Self) -> Scalar { +/// let Scalar(lhs) = self; +/// Scalar(lhs << rhs) +/// } +/// } +/// fn main() { +/// assert_eq!(Scalar(4) << Scalar(2), Scalar(16)); +/// } +/// ``` +/// +/// An implementation of `Shl` that spins a vector leftward by a given amount. +/// +/// ``` +/// use std::ops::Shl; +/// +/// #[derive(PartialEq, Debug)] +/// struct SpinVector { +/// vec: Vec, +/// } +/// +/// impl Shl for SpinVector { +/// type Output = Self; +/// +/// fn shl(self, rhs: usize) -> SpinVector { +/// // rotate the vector by `rhs` places +/// let (a, b) = self.vec.split_at(rhs); +/// let mut spun_vector: Vec = vec![]; +/// spun_vector.extend_from_slice(b); +/// spun_vector.extend_from_slice(a); +/// SpinVector { vec: spun_vector } +/// } +/// } +/// +/// fn main() { +/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } << 2, +/// SpinVector { vec: vec![2, 3, 4, 0, 1] }); +/// } +/// ``` +#[lang = "shl"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} << {RHS}`"] +pub trait Shl { + /// The resulting type after applying the `<<` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `<<` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn shl(self, rhs: RHS) -> Self::Output; +} + +macro_rules! shl_impl { + ($t:ty, $f:ty) => ( + #[stable(feature = "rust1", since = "1.0.0")] + impl Shl<$f> for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn shl(self, other: $f) -> $t { + self << other + } + } + + forward_ref_binop! { impl Shl, shl for $t, $f } + ) +} + +macro_rules! shl_impl_all { + ($($t:ty)*) => ($( + shl_impl! { $t, u8 } + shl_impl! { $t, u16 } + shl_impl! { $t, u32 } + shl_impl! { $t, u64 } + shl_impl! { $t, u128 } + shl_impl! { $t, usize } + + shl_impl! { $t, i8 } + shl_impl! { $t, i16 } + shl_impl! { $t, i32 } + shl_impl! { $t, i64 } + shl_impl! { $t, i128 } + shl_impl! { $t, isize } + )*) +} + +shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 } + +/// The right shift operator `>>`. +/// +/// # Examples +/// +/// An implementation of `Shr` that lifts the `>>` operation on integers to a +/// `Scalar` struct. +/// +/// ``` +/// use std::ops::Shr; +/// +/// #[derive(PartialEq, Debug)] +/// struct Scalar(usize); +/// +/// impl Shr for Scalar { +/// type Output = Self; +/// +/// fn shr(self, Scalar(rhs): Self) -> Scalar { +/// let Scalar(lhs) = self; +/// Scalar(lhs >> rhs) +/// } +/// } +/// fn main() { +/// assert_eq!(Scalar(16) >> Scalar(2), Scalar(4)); +/// } +/// ``` +/// +/// An implementation of `Shr` that spins a vector rightward by a given amount. +/// +/// ``` +/// use std::ops::Shr; +/// +/// #[derive(PartialEq, Debug)] +/// struct SpinVector { +/// vec: Vec, +/// } +/// +/// impl Shr for SpinVector { +/// type Output = Self; +/// +/// fn shr(self, rhs: usize) -> SpinVector { +/// // rotate the vector by `rhs` places +/// let (a, b) = self.vec.split_at(self.vec.len() - rhs); +/// let mut spun_vector: Vec = vec![]; +/// spun_vector.extend_from_slice(b); +/// spun_vector.extend_from_slice(a); +/// SpinVector { vec: spun_vector } +/// } +/// } +/// +/// fn main() { +/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } >> 2, +/// SpinVector { vec: vec![3, 4, 0, 1, 2] }); +/// } +/// ``` +#[lang = "shr"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} >> {RHS}`"] +pub trait Shr { + /// The resulting type after applying the `>>` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `>>` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn shr(self, rhs: RHS) -> Self::Output; +} + +macro_rules! shr_impl { + ($t:ty, $f:ty) => ( + #[stable(feature = "rust1", since = "1.0.0")] + impl Shr<$f> for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn shr(self, other: $f) -> $t { + self >> other + } + } + + forward_ref_binop! { impl Shr, shr for $t, $f } + ) +} + +macro_rules! shr_impl_all { + ($($t:ty)*) => ($( + shr_impl! { $t, u8 } + shr_impl! { $t, u16 } + shr_impl! { $t, u32 } + shr_impl! { $t, u64 } + shr_impl! { $t, u128 } + shr_impl! { $t, usize } + + shr_impl! { $t, i8 } + shr_impl! { $t, i16 } + shr_impl! { $t, i32 } + shr_impl! { $t, i64 } + shr_impl! { $t, i128 } + shr_impl! { $t, isize } + )*) +} + +shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } + +/// The bitwise AND assignment operator `&=`. +/// +/// # Examples +/// +/// In this example, the `&=` operator is lifted to a trivial `Scalar` type. +/// +/// ``` +/// use std::ops::BitAndAssign; +/// +/// #[derive(Debug, PartialEq)] +/// struct Scalar(bool); +/// +/// impl BitAndAssign for Scalar { +/// // rhs is the "right-hand side" of the expression `a &= b` +/// fn bitand_assign(&mut self, rhs: Self) { +/// *self = Scalar(self.0 & rhs.0) +/// } +/// } +/// +/// fn main() { +/// let mut scalar = Scalar(true); +/// scalar &= Scalar(true); +/// assert_eq!(scalar, Scalar(true)); +/// +/// let mut scalar = Scalar(true); +/// scalar &= Scalar(false); +/// assert_eq!(scalar, Scalar(false)); +/// +/// let mut scalar = Scalar(false); +/// scalar &= Scalar(true); +/// assert_eq!(scalar, Scalar(false)); +/// +/// let mut scalar = Scalar(false); +/// scalar &= Scalar(false); +/// assert_eq!(scalar, Scalar(false)); +/// } +/// ``` +/// +/// In this example, the `BitAndAssign` trait is implemented for a +/// `BooleanVector` struct. +/// +/// ``` +/// use std::ops::BitAndAssign; +/// +/// #[derive(Debug, PartialEq)] +/// struct BooleanVector(Vec); +/// +/// impl BitAndAssign for BooleanVector { +/// // rhs is the "right-hand side" of the expression `a &= b` +/// fn bitand_assign(&mut self, rhs: Self) { +/// assert_eq!(self.0.len(), rhs.0.len()); +/// *self = BooleanVector(self.0 +/// .iter() +/// .zip(rhs.0.iter()) +/// .map(|(x, y)| *x && *y) +/// .collect()); +/// } +/// } +/// +/// fn main() { +/// let mut bv = BooleanVector(vec![true, true, false, false]); +/// bv &= BooleanVector(vec![true, false, true, false]); +/// let expected = BooleanVector(vec![true, false, false, false]); +/// assert_eq!(bv, expected); +/// } +/// ``` +#[lang = "bitand_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} &= {Rhs}`"] +pub trait BitAndAssign { + /// The method for the `&=` operator + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn bitand_assign(&mut self, rhs: Rhs); +} + +macro_rules! bitand_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl BitAndAssign for $t { + #[inline] + fn bitand_assign(&mut self, other: $t) { *self &= other } + } + )+) +} + +bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The bitwise OR assignment operator `|=`. +/// +/// # Examples +/// +/// A trivial implementation of `BitOrAssign`. When `Foo |= Foo` happens, it ends up +/// calling `bitor_assign`, and therefore, `main` prints `Bitwise Or-ing!`. +/// +/// ``` +/// use std::ops::BitOrAssign; +/// +/// struct Foo; +/// +/// impl BitOrAssign for Foo { +/// fn bitor_assign(&mut self, _rhs: Foo) { +/// println!("Bitwise Or-ing!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo |= Foo; +/// } +/// ``` +#[lang = "bitor_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} |= {Rhs}`"] +pub trait BitOrAssign { + /// The method for the `|=` operator + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn bitor_assign(&mut self, rhs: Rhs); +} + +macro_rules! bitor_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl BitOrAssign for $t { + #[inline] + fn bitor_assign(&mut self, other: $t) { *self |= other } + } + )+) +} + +bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The bitwise XOR assignment operator `^=`. +/// +/// # Examples +/// +/// A trivial implementation of `BitXorAssign`. When `Foo ^= Foo` happens, it ends up +/// calling `bitxor_assign`, and therefore, `main` prints `Bitwise Xor-ing!`. +/// +/// ``` +/// use std::ops::BitXorAssign; +/// +/// struct Foo; +/// +/// impl BitXorAssign for Foo { +/// fn bitxor_assign(&mut self, _rhs: Foo) { +/// println!("Bitwise Xor-ing!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo ^= Foo; +/// } +/// ``` +#[lang = "bitxor_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} ^= {Rhs}`"] +pub trait BitXorAssign { + /// The method for the `^=` operator + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn bitxor_assign(&mut self, rhs: Rhs); +} + +macro_rules! bitxor_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl BitXorAssign for $t { + #[inline] + fn bitxor_assign(&mut self, other: $t) { *self ^= other } + } + )+) +} + +bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The left shift assignment operator `<<=`. +/// +/// # Examples +/// +/// A trivial implementation of `ShlAssign`. When `Foo <<= Foo` happens, it ends up +/// calling `shl_assign`, and therefore, `main` prints `Shifting left!`. +/// +/// ``` +/// use std::ops::ShlAssign; +/// +/// struct Foo; +/// +/// impl ShlAssign for Foo { +/// fn shl_assign(&mut self, _rhs: Foo) { +/// println!("Shifting left!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo <<= Foo; +/// } +/// ``` +#[lang = "shl_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} <<= {Rhs}`"] +pub trait ShlAssign { + /// The method for the `<<=` operator + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn shl_assign(&mut self, rhs: Rhs); +} + +macro_rules! shl_assign_impl { + ($t:ty, $f:ty) => ( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl ShlAssign<$f> for $t { + #[inline] + #[rustc_inherit_overflow_checks] + fn shl_assign(&mut self, other: $f) { + *self <<= other + } + } + ) +} + +macro_rules! shl_assign_impl_all { + ($($t:ty)*) => ($( + shl_assign_impl! { $t, u8 } + shl_assign_impl! { $t, u16 } + shl_assign_impl! { $t, u32 } + shl_assign_impl! { $t, u64 } + 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 } + shl_assign_impl! { $t, i128 } + shl_assign_impl! { $t, isize } + )*) +} + +shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } + +/// The right shift assignment operator `>>=`. +/// +/// # Examples +/// +/// A trivial implementation of `ShrAssign`. When `Foo >>= Foo` happens, it ends up +/// calling `shr_assign`, and therefore, `main` prints `Shifting right!`. +/// +/// ``` +/// use std::ops::ShrAssign; +/// +/// struct Foo; +/// +/// impl ShrAssign for Foo { +/// fn shr_assign(&mut self, _rhs: Foo) { +/// println!("Shifting right!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo >>= Foo; +/// } +/// ``` +#[lang = "shr_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} >>= {Rhs}`"] +pub trait ShrAssign { + /// The method for the `>>=` operator + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn shr_assign(&mut self, rhs: Rhs); +} + +macro_rules! shr_assign_impl { + ($t:ty, $f:ty) => ( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl ShrAssign<$f> for $t { + #[inline] + #[rustc_inherit_overflow_checks] + fn shr_assign(&mut self, other: $f) { + *self >>= other + } + } + ) +} + +macro_rules! shr_assign_impl_all { + ($($t:ty)*) => ($( + shr_assign_impl! { $t, u8 } + shr_assign_impl! { $t, u16 } + shr_assign_impl! { $t, u32 } + shr_assign_impl! { $t, u64 } + 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 } + shr_assign_impl! { $t, i128 } + shr_assign_impl! { $t, isize } + )*) +} + +shr_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } diff --git a/src/libcore/ops/deref.rs b/src/libcore/ops/deref.rs new file mode 100644 index 0000000000..18cf20ac41 --- /dev/null +++ b/src/libcore/ops/deref.rs @@ -0,0 +1,119 @@ +// 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. + +/// The `Deref` trait is used to specify the functionality of dereferencing +/// operations, like `*v`. +/// +/// `Deref` also enables ['`Deref` coercions'][coercions]. +/// +/// [coercions]: ../../book/first-edition/deref-coercions.html +/// +/// # Examples +/// +/// A struct with a single field which is accessible via dereferencing the +/// struct. +/// +/// ``` +/// use std::ops::Deref; +/// +/// struct DerefExample { +/// value: T +/// } +/// +/// impl Deref for DerefExample { +/// type Target = T; +/// +/// fn deref(&self) -> &T { +/// &self.value +/// } +/// } +/// +/// fn main() { +/// let x = DerefExample { value: 'a' }; +/// assert_eq!('a', *x); +/// } +/// ``` +#[lang = "deref"] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Deref { + /// The resulting type after dereferencing + #[stable(feature = "rust1", since = "1.0.0")] + type Target: ?Sized; + + /// The method called to dereference a value + #[stable(feature = "rust1", since = "1.0.0")] + fn deref(&self) -> &Self::Target; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized> Deref for &'a T { + type Target = T; + + fn deref(&self) -> &T { *self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized> Deref for &'a mut T { + type Target = T; + + fn deref(&self) -> &T { *self } +} + +/// The `DerefMut` trait is used to specify the functionality of dereferencing +/// mutably like `*v = 1;` +/// +/// `DerefMut` also enables ['`Deref` coercions'][coercions]. +/// +/// [coercions]: ../../book/first-edition/deref-coercions.html +/// +/// # Examples +/// +/// A struct with a single field which is modifiable via dereferencing the +/// struct. +/// +/// ``` +/// use std::ops::{Deref, DerefMut}; +/// +/// struct DerefMutExample { +/// value: T +/// } +/// +/// impl Deref for DerefMutExample { +/// type Target = T; +/// +/// fn deref(&self) -> &T { +/// &self.value +/// } +/// } +/// +/// impl DerefMut for DerefMutExample { +/// fn deref_mut(&mut self) -> &mut T { +/// &mut self.value +/// } +/// } +/// +/// fn main() { +/// let mut x = DerefMutExample { value: 'a' }; +/// *x = 'b'; +/// assert_eq!('b', *x); +/// } +/// ``` +#[lang = "deref_mut"] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait DerefMut: Deref { + /// The method called to mutably dereference a value + #[stable(feature = "rust1", since = "1.0.0")] + fn deref_mut(&mut self) -> &mut Self::Target; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized> DerefMut for &'a mut T { + fn deref_mut(&mut self) -> &mut T { *self } +} diff --git a/src/libcore/ops/drop.rs b/src/libcore/ops/drop.rs new file mode 100644 index 0000000000..92f3cb256c --- /dev/null +++ b/src/libcore/ops/drop.rs @@ -0,0 +1,99 @@ +// 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. + +/// The `Drop` trait is used to run some code when a value goes out of scope. +/// This is sometimes called a 'destructor'. +/// +/// When a value goes out of scope, if it implements this trait, it will have +/// its `drop` method called. Then any fields the value contains will also +/// be dropped recursively. +/// +/// Because of the recursive dropping, you do not need to implement this trait +/// unless your type needs its own destructor logic. +/// +/// # Examples +/// +/// A trivial implementation of `Drop`. The `drop` method is called when `_x` +/// goes out of scope, and therefore `main` prints `Dropping!`. +/// +/// ``` +/// struct HasDrop; +/// +/// impl Drop for HasDrop { +/// fn drop(&mut self) { +/// println!("Dropping!"); +/// } +/// } +/// +/// fn main() { +/// let _x = HasDrop; +/// } +/// ``` +/// +/// Showing the recursive nature of `Drop`. When `outer` goes out of scope, the +/// `drop` method will be called first for `Outer`, then for `Inner`. Therefore +/// `main` prints `Dropping Outer!` and then `Dropping Inner!`. +/// +/// ``` +/// struct Inner; +/// struct Outer(Inner); +/// +/// impl Drop for Inner { +/// fn drop(&mut self) { +/// println!("Dropping Inner!"); +/// } +/// } +/// +/// impl Drop for Outer { +/// fn drop(&mut self) { +/// println!("Dropping Outer!"); +/// } +/// } +/// +/// fn main() { +/// let _x = Outer(Inner); +/// } +/// ``` +/// +/// Because variables are dropped in the reverse order they are declared, +/// `main` will print `Declared second!` and then `Declared first!`. +/// +/// ``` +/// struct PrintOnDrop(&'static str); +/// +/// fn main() { +/// let _first = PrintOnDrop("Declared first!"); +/// let _second = PrintOnDrop("Declared second!"); +/// } +/// ``` +#[lang = "drop"] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Drop { + /// A method called when the value goes out of scope. + /// + /// When this method has been called, `self` has not yet been deallocated. + /// If it were, `self` would be a dangling reference. + /// + /// After this function is over, the memory of `self` will be deallocated. + /// + /// This function cannot be called explicitly. This is compiler error + /// [E0040]. However, the [`std::mem::drop`] function in the prelude can be + /// used to call the argument's `Drop` implementation. + /// + /// [E0040]: ../../error-index.html#E0040 + /// [`std::mem::drop`]: ../../std/mem/fn.drop.html + /// + /// # Panics + /// + /// Given that a `panic!` will call `drop()` as it unwinds, any `panic!` in + /// a `drop()` implementation will likely abort. + #[stable(feature = "rust1", since = "1.0.0")] + fn drop(&mut self); +} diff --git a/src/libcore/ops/function.rs b/src/libcore/ops/function.rs new file mode 100644 index 0000000000..62bf69336a --- /dev/null +++ b/src/libcore/ops/function.rs @@ -0,0 +1,194 @@ +// 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. + +/// A version of the call operator that takes an immutable receiver. +/// +/// # Examples +/// +/// Closures automatically implement this trait, which allows them to be +/// invoked. Note, however, that `Fn` takes an immutable reference to any +/// captured variables. To take a mutable capture, implement [`FnMut`], and to +/// consume the capture, implement [`FnOnce`]. +/// +/// [`FnMut`]: trait.FnMut.html +/// [`FnOnce`]: trait.FnOnce.html +/// +/// ``` +/// let square = |x| x * x; +/// assert_eq!(square(5), 25); +/// ``` +/// +/// Closures can also be passed to higher-level functions through a `Fn` +/// parameter (or a `FnMut` or `FnOnce` parameter, which are supertraits of +/// `Fn`). +/// +/// ``` +/// fn call_with_one(func: F) -> usize +/// where F: Fn(usize) -> usize { +/// func(1) +/// } +/// +/// let double = |x| x * 2; +/// assert_eq!(call_with_one(double), 2); +/// ``` +#[lang = "fn"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_paren_sugar] +#[fundamental] // so that regex can rely that `&str: !FnMut` +pub trait Fn : FnMut { + /// This is called when the call operator is used. + #[unstable(feature = "fn_traits", issue = "29625")] + extern "rust-call" fn call(&self, args: Args) -> Self::Output; +} + +/// A version of the call operator that takes a mutable receiver. +/// +/// # Examples +/// +/// Closures that mutably capture variables automatically implement this trait, +/// which allows them to be invoked. +/// +/// ``` +/// let mut x = 5; +/// { +/// let mut square_x = || x *= x; +/// square_x(); +/// } +/// assert_eq!(x, 25); +/// ``` +/// +/// Closures can also be passed to higher-level functions through a `FnMut` +/// parameter (or a `FnOnce` parameter, which is a supertrait of `FnMut`). +/// +/// ``` +/// fn do_twice(mut func: F) +/// where F: FnMut() +/// { +/// func(); +/// func(); +/// } +/// +/// let mut x: usize = 1; +/// { +/// let add_two_to_x = || x += 2; +/// do_twice(add_two_to_x); +/// } +/// +/// assert_eq!(x, 5); +/// ``` +#[lang = "fn_mut"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_paren_sugar] +#[fundamental] // so that regex can rely that `&str: !FnMut` +pub trait FnMut : FnOnce { + /// This is called when the call operator is used. + #[unstable(feature = "fn_traits", issue = "29625")] + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; +} + +/// A version of the call operator that takes a by-value receiver. +/// +/// # Examples +/// +/// By-value closures automatically implement this trait, which allows them to +/// be invoked. +/// +/// ``` +/// let x = 5; +/// let square_x = move || x * x; +/// assert_eq!(square_x(), 25); +/// ``` +/// +/// By-value Closures can also be passed to higher-level functions through a +/// `FnOnce` parameter. +/// +/// ``` +/// fn consume_with_relish(func: F) +/// where F: FnOnce() -> String +/// { +/// // `func` consumes its captured variables, so it cannot be run more +/// // than once +/// println!("Consumed: {}", func()); +/// +/// println!("Delicious!"); +/// +/// // Attempting to invoke `func()` again will throw a `use of moved +/// // value` error for `func` +/// } +/// +/// let x = String::from("x"); +/// let consume_and_return_x = move || x; +/// consume_with_relish(consume_and_return_x); +/// +/// // `consume_and_return_x` can no longer be invoked at this point +/// ``` +#[lang = "fn_once"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_paren_sugar] +#[fundamental] // so that regex can rely that `&str: !FnMut` +pub trait FnOnce { + /// The returned type after the call operator is used. + #[stable(feature = "fn_once_output", since = "1.12.0")] + type Output; + + /// This is called when the call operator is used. + #[unstable(feature = "fn_traits", issue = "29625")] + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +mod impls { + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a,A,F:?Sized> Fn for &'a F + where F : Fn + { + extern "rust-call" fn call(&self, args: A) -> F::Output { + (**self).call(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a,A,F:?Sized> FnMut for &'a F + where F : Fn + { + extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { + (**self).call(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a,A,F:?Sized> FnOnce for &'a F + where F : Fn + { + type Output = F::Output; + + extern "rust-call" fn call_once(self, args: A) -> F::Output { + (*self).call(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a,A,F:?Sized> FnMut for &'a mut F + where F : FnMut + { + extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { + (*self).call_mut(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a,A,F:?Sized> FnOnce for &'a mut F + where F : FnMut + { + type Output = F::Output; + extern "rust-call" fn call_once(mut self, args: A) -> F::Output { + (*self).call_mut(args) + } + } +} diff --git a/src/libcore/ops/index.rs b/src/libcore/ops/index.rs new file mode 100644 index 0000000000..b16b956778 --- /dev/null +++ b/src/libcore/ops/index.rs @@ -0,0 +1,158 @@ +// 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. + +/// The `Index` trait is used to specify the functionality of indexing operations +/// like `container[index]` when used in an immutable context. +/// +/// `container[index]` is actually syntactic sugar for `*container.index(index)`, +/// but only when used as an immutable value. If a mutable value is requested, +/// [`IndexMut`] is used instead. This allows nice things such as +/// `let value = v[index]` if `value` implements [`Copy`]. +/// +/// [`IndexMut`]: ../../std/ops/trait.IndexMut.html +/// [`Copy`]: ../../std/marker/trait.Copy.html +/// +/// # Examples +/// +/// The following example implements `Index` on a read-only `NucleotideCount` +/// container, enabling individual counts to be retrieved with index syntax. +/// +/// ``` +/// use std::ops::Index; +/// +/// enum Nucleotide { +/// A, +/// C, +/// G, +/// T, +/// } +/// +/// struct NucleotideCount { +/// a: usize, +/// c: usize, +/// g: usize, +/// t: usize, +/// } +/// +/// impl Index for NucleotideCount { +/// type Output = usize; +/// +/// fn index(&self, nucleotide: Nucleotide) -> &usize { +/// match nucleotide { +/// Nucleotide::A => &self.a, +/// Nucleotide::C => &self.c, +/// Nucleotide::G => &self.g, +/// Nucleotide::T => &self.t, +/// } +/// } +/// } +/// +/// let nucleotide_count = NucleotideCount {a: 14, c: 9, g: 10, t: 12}; +/// assert_eq!(nucleotide_count[Nucleotide::A], 14); +/// assert_eq!(nucleotide_count[Nucleotide::C], 9); +/// assert_eq!(nucleotide_count[Nucleotide::G], 10); +/// assert_eq!(nucleotide_count[Nucleotide::T], 12); +/// ``` +#[lang = "index"] +#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Index { + /// The returned type after indexing + #[stable(feature = "rust1", since = "1.0.0")] + type Output: ?Sized; + + /// The method for the indexing (`container[index]`) operation + #[stable(feature = "rust1", since = "1.0.0")] + fn index(&self, index: Idx) -> &Self::Output; +} + +/// The `IndexMut` trait is used to specify the functionality of indexing +/// operations like `container[index]` when used in a mutable context. +/// +/// `container[index]` is actually syntactic sugar for +/// `*container.index_mut(index)`, but only when used as a mutable value. If +/// an immutable value is requested, the [`Index`] trait is used instead. This +/// allows nice things such as `v[index] = value` if `value` implements [`Copy`]. +/// +/// [`Index`]: ../../std/ops/trait.Index.html +/// [`Copy`]: ../../std/marker/trait.Copy.html +/// +/// # Examples +/// +/// A very simple implementation of a `Balance` struct that has two sides, where +/// each can be indexed mutably and immutably. +/// +/// ``` +/// use std::ops::{Index,IndexMut}; +/// +/// #[derive(Debug)] +/// enum Side { +/// Left, +/// Right, +/// } +/// +/// #[derive(Debug, PartialEq)] +/// enum Weight { +/// Kilogram(f32), +/// Pound(f32), +/// } +/// +/// struct Balance { +/// pub left: Weight, +/// pub right:Weight, +/// } +/// +/// impl Index for Balance { +/// type Output = Weight; +/// +/// fn index<'a>(&'a self, index: Side) -> &'a Weight { +/// println!("Accessing {:?}-side of balance immutably", index); +/// match index { +/// Side::Left => &self.left, +/// Side::Right => &self.right, +/// } +/// } +/// } +/// +/// impl IndexMut for Balance { +/// fn index_mut<'a>(&'a mut self, index: Side) -> &'a mut Weight { +/// println!("Accessing {:?}-side of balance mutably", index); +/// match index { +/// Side::Left => &mut self.left, +/// Side::Right => &mut self.right, +/// } +/// } +/// } +/// +/// fn main() { +/// let mut balance = Balance { +/// right: Weight::Kilogram(2.5), +/// left: Weight::Pound(1.5), +/// }; +/// +/// // In this case balance[Side::Right] is sugar for +/// // *balance.index(Side::Right), since we are only reading +/// // balance[Side::Right], not writing it. +/// assert_eq!(balance[Side::Right],Weight::Kilogram(2.5)); +/// +/// // However in this case balance[Side::Left] is sugar for +/// // *balance.index_mut(Side::Left), since we are writing +/// // balance[Side::Left]. +/// balance[Side::Left] = Weight::Kilogram(3.0); +/// } +/// ``` +#[lang = "index_mut"] +#[rustc_on_unimplemented = "the type `{Self}` cannot be mutably indexed by `{Idx}`"] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait IndexMut: Index { + /// The method for the mutable indexing (`container[index]`) operation + #[stable(feature = "rust1", since = "1.0.0")] + fn index_mut(&mut self, index: Idx) -> &mut Self::Output; +} diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs new file mode 100644 index 0000000000..a78f4fe28a --- /dev/null +++ b/src/libcore/ops/mod.rs @@ -0,0 +1,196 @@ +// 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. + +//! Overloadable operators. +//! +//! Implementing these traits allows you to overload certain operators. +//! +//! Some of these traits are imported by the prelude, so they are available in +//! every Rust program. Only operators backed by traits can be overloaded. For +//! example, the addition operator (`+`) can be overloaded through the [`Add`] +//! trait, but since the assignment operator (`=`) has no backing trait, there +//! is no way of overloading its semantics. Additionally, this module does not +//! provide any mechanism to create new operators. If traitless overloading or +//! custom operators are required, you should look toward macros or compiler +//! plugins to extend Rust's syntax. +//! +//! Note that the `&&` and `||` operators short-circuit, i.e. they only +//! evaluate their second operand if it contributes to the result. Since this +//! behavior is not enforceable by traits, `&&` and `||` are not supported as +//! overloadable operators. +//! +//! Many of the operators take their operands by value. In non-generic +//! contexts involving built-in types, this is usually not a problem. +//! However, using these operators in generic code, requires some +//! attention if values have to be reused as opposed to letting the operators +//! consume them. One option is to occasionally use [`clone`]. +//! Another option is to rely on the types involved providing additional +//! operator implementations for references. For example, for a user-defined +//! type `T` which is supposed to support addition, it is probably a good +//! idea to have both `T` and `&T` implement the traits [`Add`][`Add`] and +//! [`Add<&T>`][`Add`] so that generic code can be written without unnecessary +//! cloning. +//! +//! # Examples +//! +//! This example creates a `Point` struct that implements [`Add`] and [`Sub`], +//! and then demonstrates adding and subtracting two `Point`s. +//! +//! ```rust +//! use std::ops::{Add, Sub}; +//! +//! #[derive(Debug)] +//! struct Point { +//! x: i32, +//! y: i32, +//! } +//! +//! impl Add for Point { +//! type Output = Point; +//! +//! fn add(self, other: Point) -> Point { +//! Point {x: self.x + other.x, y: self.y + other.y} +//! } +//! } +//! +//! impl Sub for Point { +//! type Output = Point; +//! +//! fn sub(self, other: Point) -> Point { +//! Point {x: self.x - other.x, y: self.y - other.y} +//! } +//! } +//! fn main() { +//! println!("{:?}", Point {x: 1, y: 0} + Point {x: 2, y: 3}); +//! println!("{:?}", Point {x: 1, y: 0} - Point {x: 2, y: 3}); +//! } +//! ``` +//! +//! See the documentation for each trait for an example implementation. +//! +//! The [`Fn`], [`FnMut`], and [`FnOnce`] traits are implemented by types that can be +//! invoked like functions. Note that [`Fn`] takes `&self`, [`FnMut`] takes `&mut +//! self` and [`FnOnce`] takes `self`. These correspond to the three kinds of +//! methods that can be invoked on an instance: call-by-reference, +//! call-by-mutable-reference, and call-by-value. The most common use of these +//! traits is to act as bounds to higher-level functions that take functions or +//! closures as arguments. +//! +//! Taking a [`Fn`] as a parameter: +//! +//! ```rust +//! fn call_with_one(func: F) -> usize +//! where F: Fn(usize) -> usize +//! { +//! func(1) +//! } +//! +//! let double = |x| x * 2; +//! assert_eq!(call_with_one(double), 2); +//! ``` +//! +//! Taking a [`FnMut`] as a parameter: +//! +//! ```rust +//! fn do_twice(mut func: F) +//! where F: FnMut() +//! { +//! func(); +//! func(); +//! } +//! +//! let mut x: usize = 1; +//! { +//! let add_two_to_x = || x += 2; +//! do_twice(add_two_to_x); +//! } +//! +//! assert_eq!(x, 5); +//! ``` +//! +//! Taking a [`FnOnce`] as a parameter: +//! +//! ```rust +//! fn consume_with_relish(func: F) +//! where F: FnOnce() -> String +//! { +//! // `func` consumes its captured variables, so it cannot be run more +//! // than once +//! println!("Consumed: {}", func()); +//! +//! println!("Delicious!"); +//! +//! // Attempting to invoke `func()` again will throw a `use of moved +//! // value` error for `func` +//! } +//! +//! let x = String::from("x"); +//! let consume_and_return_x = move || x; +//! consume_with_relish(consume_and_return_x); +//! +//! // `consume_and_return_x` can no longer be invoked at this point +//! ``` +//! +//! [`Fn`]: trait.Fn.html +//! [`FnMut`]: trait.FnMut.html +//! [`FnOnce`]: trait.FnOnce.html +//! [`Add`]: trait.Add.html +//! [`Sub`]: trait.Sub.html +//! [`clone`]: ../clone/trait.Clone.html#tymethod.clone + +#![stable(feature = "rust1", since = "1.0.0")] + +mod arith; +mod bit; +mod deref; +mod drop; +mod function; +mod index; +mod place; +mod range; +mod try; +mod unsize; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::arith::{Add, Sub, Mul, Div, Rem, Neg}; +#[stable(feature = "op_assign_traits", since = "1.8.0")] +pub use self::arith::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::bit::{Not, BitAnd, BitOr, BitXor, Shl, Shr}; +#[stable(feature = "op_assign_traits", since = "1.8.0")] +pub use self::bit::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign}; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::deref::{Deref, DerefMut}; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::drop::Drop; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::function::{Fn, FnMut, FnOnce}; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::index::{Index, IndexMut}; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; + +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +pub use self::range::{RangeInclusive, RangeToInclusive}; + +#[unstable(feature = "try_trait", issue = "42327")] +pub use self::try::Try; + +#[unstable(feature = "placement_new_protocol", issue = "27779")] +pub use self::place::{Place, Placer, InPlace, Boxed, BoxPlace}; + +#[unstable(feature = "coerce_unsized", issue = "27732")] +pub use self::unsize::CoerceUnsized; diff --git a/src/libcore/ops/place.rs b/src/libcore/ops/place.rs new file mode 100644 index 0000000000..19da887cbb --- /dev/null +++ b/src/libcore/ops/place.rs @@ -0,0 +1,140 @@ +// 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. + +/// 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. +/// +/// A `Place` can be thought of as a special representation for a +/// hypothetical `&uninit` reference (which Rust cannot currently +/// express directly). That is, it represents a pointer to +/// uninitialized storage. +/// +/// The client is responsible for two steps: First, initializing the +/// payload (it can access its address via `pointer`). Second, +/// converting the agent to an instance of the owning pointer, via the +/// appropriate `finalize` method (see the `InPlace`. +/// +/// 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")] +pub trait Place { + /// Returns the address where the input value will be written. + /// Note that the data at this address is generally uninitialized, + /// and thus one should use `ptr::write` for initializing it. + fn pointer(&mut self) -> *mut Data; +} + +/// Interface to implementations of `PLACE <- EXPR`. +/// +/// `PLACE <- EXPR` effectively desugars into: +/// +/// ``` +/// # #![feature(placement_new_protocol, box_heap)] +/// # use std::ops::{Placer, Place, InPlace}; +/// # #[allow(non_snake_case)] +/// # fn main() { +/// # let PLACE = std::boxed::HEAP; +/// # let EXPR = 1; +/// let p = PLACE; +/// let mut place = Placer::make_place(p); +/// let raw_place = Place::pointer(&mut place); +/// let value = EXPR; +/// unsafe { +/// std::ptr::write(raw_place, value); +/// InPlace::finalize(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). +/// +/// Values for types implementing this trait usually are transient +/// intermediate values (e.g. the return value of `Vec::emplace_back`) +/// or `Copy`, since the `make_place` method takes `self` by value. +#[unstable(feature = "placement_new_protocol", issue = "27779")] +pub trait Placer { + /// `Place` is the intermedate agent guarding the + /// uninitialized state for `Data`. + type Place: InPlace; + + /// Creates a fresh place from `self`. + fn make_place(self) -> Self::Place; +} + +/// 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 `PLACE <- EXPR` + /// + /// 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 + /// case). + type Owner; + + /// Converts self into the final value, shifting + /// deallocation/cleanup responsibilities (if any remain), over to + /// the returned instance of `Owner` and forgetting self. + unsafe fn finalize(self) -> Self::Owner; +} + +/// Core trait for the `box EXPR` form. +/// +/// `box EXPR` effectively desugars into: +/// +/// ``` +/// # #![feature(placement_new_protocol)] +/// # use std::ops::{BoxPlace, Place, Boxed}; +/// # #[allow(non_snake_case)] +/// # fn main() { +/// # let EXPR = 1; +/// let mut place = BoxPlace::make_place(); +/// let raw_place = Place::pointer(&mut place); +/// let value = EXPR; +/// # let _: Box<_> = +/// unsafe { +/// ::std::ptr::write(raw_place, value); +/// Boxed::finalize(place) +/// } +/// # ; } +/// ``` +/// +/// The type of `box EXPR` is supplied from its surrounding +/// context; in the above expansion, the result type `T` is used +/// to determine which implementation of `Boxed` to use, and that +/// `` in turn dictates determines which +/// implementation of `BoxPlace` to use, namely: +/// `<::Place as BoxPlace>`. +#[unstable(feature = "placement_new_protocol", issue = "27779")] +pub trait Boxed { + /// The kind of data that is stored in this kind of box. + type Data; /* (`Data` unused b/c cannot yet express below bound.) */ + /// The place that will negotiate the storage of the data. + type Place: BoxPlace; + + /// Converts filled place into final owning value, shifting + /// deallocation/cleanup responsibilities (if any remain), over to + /// returned instance of `Self` and forgetting `filled`. + unsafe fn finalize(filled: Self::Place) -> Self; +} + +/// Specialization of `Place` trait supporting `box EXPR`. +#[unstable(feature = "placement_new_protocol", issue = "27779")] +pub trait BoxPlace : Place { + /// Creates a globally fresh place. + fn make_place() -> Self; +} diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs new file mode 100644 index 0000000000..33258b7a87 --- /dev/null +++ b/src/libcore/ops/range.rs @@ -0,0 +1,367 @@ +// 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 fmt; + +/// An unbounded range. Use `..` (two dots) for its shorthand. +/// +/// Its primary use case is slicing index. It cannot serve as an iterator +/// because it doesn't have a starting point. +/// +/// # Examples +/// +/// The `..` syntax is a `RangeFull`: +/// +/// ``` +/// assert_eq!((..), std::ops::RangeFull); +/// ``` +/// +/// It does not have an `IntoIterator` implementation, so you can't use it in a +/// `for` loop directly. This won't compile: +/// +/// ```compile_fail,E0277 +/// for i in .. { +/// // ... +/// } +/// ``` +/// +/// Used as a slicing index, `RangeFull` produces the full array as a slice. +/// +/// ``` +/// let arr = [0, 1, 2, 3]; +/// assert_eq!(arr[ .. ], [0,1,2,3]); // RangeFull +/// assert_eq!(arr[ ..3], [0,1,2 ]); +/// assert_eq!(arr[1.. ], [ 1,2,3]); +/// assert_eq!(arr[1..3], [ 1,2 ]); +/// ``` +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct RangeFull; + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for RangeFull { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "..") + } +} + +/// A (half-open) range which is bounded at both ends: { x | start <= x < end }. +/// Use `start..end` (two dots) for its shorthand. +/// +/// See the [`contains`](#method.contains) method for its characterization. +/// +/// # Examples +/// +/// ``` +/// fn main() { +/// assert_eq!((3..5), std::ops::Range{ start: 3, end: 5 }); +/// assert_eq!(3+4+5, (3..6).sum()); +/// +/// let arr = [0, 1, 2, 3]; +/// assert_eq!(arr[ .. ], [0,1,2,3]); +/// assert_eq!(arr[ ..3], [0,1,2 ]); +/// assert_eq!(arr[1.. ], [ 1,2,3]); +/// assert_eq!(arr[1..3], [ 1,2 ]); // Range +/// } +/// ``` +#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Range { + /// The lower bound of the range (inclusive). + #[stable(feature = "rust1", since = "1.0.0")] + pub start: Idx, + /// The upper bound of the range (exclusive). + #[stable(feature = "rust1", since = "1.0.0")] + pub end: Idx, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Range { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "{:?}..{:?}", self.start, self.end) + } +} + +#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] +impl> Range { + /// # Examples + /// + /// ``` + /// #![feature(range_contains)] + /// fn main() { + /// assert!( ! (3..5).contains(2)); + /// assert!( (3..5).contains(3)); + /// assert!( (3..5).contains(4)); + /// assert!( ! (3..5).contains(5)); + /// + /// assert!( ! (3..3).contains(3)); + /// assert!( ! (3..2).contains(3)); + /// } + /// ``` + pub fn contains(&self, item: Idx) -> bool { + (self.start <= item) && (item < self.end) + } +} + +/// A range which is only bounded below: { x | start <= x }. +/// Use `start..` for its shorthand. +/// +/// See the [`contains`](#method.contains) method for its characterization. +/// +/// Note: Currently, no overflow checking is done for the iterator +/// implementation; if you use an integer range and the integer overflows, it +/// might panic in debug mode or create an endless loop in release mode. This +/// overflow behavior might change in the future. +/// +/// # Examples +/// +/// ``` +/// fn main() { +/// assert_eq!((2..), std::ops::RangeFrom{ start: 2 }); +/// assert_eq!(2+3+4, (2..).take(3).sum()); +/// +/// let arr = [0, 1, 2, 3]; +/// assert_eq!(arr[ .. ], [0,1,2,3]); +/// assert_eq!(arr[ ..3], [0,1,2 ]); +/// assert_eq!(arr[1.. ], [ 1,2,3]); // RangeFrom +/// assert_eq!(arr[1..3], [ 1,2 ]); +/// } +/// ``` +#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[stable(feature = "rust1", since = "1.0.0")] +pub struct RangeFrom { + /// The lower bound of the range (inclusive). + #[stable(feature = "rust1", since = "1.0.0")] + pub start: Idx, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for RangeFrom { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "{:?}..", self.start) + } +} + +#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] +impl> RangeFrom { + /// # Examples + /// + /// ``` + /// #![feature(range_contains)] + /// fn main() { + /// assert!( ! (3..).contains(2)); + /// assert!( (3..).contains(3)); + /// assert!( (3..).contains(1_000_000_000)); + /// } + /// ``` + pub fn contains(&self, item: Idx) -> bool { + (self.start <= item) + } +} + +/// A range which is only bounded above: { x | x < end }. +/// Use `..end` (two dots) for its shorthand. +/// +/// See the [`contains`](#method.contains) method for its characterization. +/// +/// It cannot serve as an iterator because it doesn't have a starting point. +/// +/// # Examples +/// +/// The `..{integer}` syntax is a `RangeTo`: +/// +/// ``` +/// assert_eq!((..5), std::ops::RangeTo{ end: 5 }); +/// ``` +/// +/// It does not have an `IntoIterator` implementation, so you can't use it in a +/// `for` loop directly. This won't compile: +/// +/// ```compile_fail,E0277 +/// for i in ..5 { +/// // ... +/// } +/// ``` +/// +/// When used as a slicing index, `RangeTo` produces a slice of all array +/// elements before the index indicated by `end`. +/// +/// ``` +/// let arr = [0, 1, 2, 3]; +/// assert_eq!(arr[ .. ], [0,1,2,3]); +/// assert_eq!(arr[ ..3], [0,1,2 ]); // RangeTo +/// assert_eq!(arr[1.. ], [ 1,2,3]); +/// assert_eq!(arr[1..3], [ 1,2 ]); +/// ``` +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct RangeTo { + /// The upper bound of the range (exclusive). + #[stable(feature = "rust1", since = "1.0.0")] + pub end: Idx, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for RangeTo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "..{:?}", self.end) + } +} + +#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] +impl> RangeTo { + /// # Examples + /// + /// ``` + /// #![feature(range_contains)] + /// fn main() { + /// assert!( (..5).contains(-1_000_000_000)); + /// assert!( (..5).contains(4)); + /// assert!( ! (..5).contains(5)); + /// } + /// ``` + pub fn contains(&self, item: Idx) -> bool { + (item < self.end) + } +} + +/// An inclusive range which is bounded at both ends: { x | start <= x <= end }. +/// Use `start...end` (three dots) for its shorthand. +/// +/// See the [`contains`](#method.contains) method for its characterization. +/// +/// # Examples +/// +/// ``` +/// #![feature(inclusive_range,inclusive_range_syntax)] +/// fn main() { +/// assert_eq!((3...5), std::ops::RangeInclusive{ start: 3, end: 5 }); +/// assert_eq!(3+4+5, (3...5).sum()); +/// +/// let arr = [0, 1, 2, 3]; +/// assert_eq!(arr[ ...2], [0,1,2 ]); +/// assert_eq!(arr[1...2], [ 1,2 ]); // RangeInclusive +/// } +/// ``` +#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +pub struct RangeInclusive { + /// The lower bound of the range (inclusive). + #[unstable(feature = "inclusive_range", + reason = "recently added, follows RFC", + issue = "28237")] + pub start: Idx, + /// The upper bound of the range (inclusive). + #[unstable(feature = "inclusive_range", + reason = "recently added, follows RFC", + issue = "28237")] + pub end: Idx, +} + +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +impl fmt::Debug for RangeInclusive { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "{:?}...{:?}", self.start, self.end) + } +} + +#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] +impl> RangeInclusive { + /// # Examples + /// + /// ``` + /// #![feature(range_contains,inclusive_range_syntax)] + /// fn main() { + /// assert!( ! (3...5).contains(2)); + /// assert!( (3...5).contains(3)); + /// assert!( (3...5).contains(4)); + /// assert!( (3...5).contains(5)); + /// assert!( ! (3...5).contains(6)); + /// + /// assert!( (3...3).contains(3)); + /// assert!( ! (3...2).contains(3)); + /// } + /// ``` + pub fn contains(&self, item: Idx) -> bool { + self.start <= item && item <= self.end + } +} + +/// An inclusive range which is only bounded above: { x | x <= end }. +/// Use `...end` (three dots) for its shorthand. +/// +/// See the [`contains`](#method.contains) method for its characterization. +/// +/// It cannot serve as an iterator because it doesn't have a starting point. +/// +/// # Examples +/// +/// The `...{integer}` syntax is a `RangeToInclusive`: +/// +/// ``` +/// #![feature(inclusive_range,inclusive_range_syntax)] +/// assert_eq!((...5), std::ops::RangeToInclusive{ end: 5 }); +/// ``` +/// +/// It does not have an `IntoIterator` implementation, so you can't use it in a +/// `for` loop directly. This won't compile: +/// +/// ```compile_fail,E0277 +/// #![feature(inclusive_range_syntax)] +/// for i in ...5 { +/// // ... +/// } +/// ``` +/// +/// When used as a slicing index, `RangeToInclusive` produces a slice of all +/// array elements up to and including the index indicated by `end`. +/// +/// ``` +/// #![feature(inclusive_range_syntax)] +/// let arr = [0, 1, 2, 3]; +/// assert_eq!(arr[ ...2], [0,1,2 ]); // RangeToInclusive +/// assert_eq!(arr[1...2], [ 1,2 ]); +/// ``` +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +pub struct RangeToInclusive { + /// The upper bound of the range (inclusive) + #[unstable(feature = "inclusive_range", + reason = "recently added, follows RFC", + issue = "28237")] + pub end: Idx, +} + +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +impl fmt::Debug for RangeToInclusive { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "...{:?}", self.end) + } +} + +#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] +impl> RangeToInclusive { + /// # Examples + /// + /// ``` + /// #![feature(range_contains,inclusive_range_syntax)] + /// fn main() { + /// assert!( (...5).contains(-1_000_000_000)); + /// assert!( (...5).contains(5)); + /// assert!( ! (...5).contains(6)); + /// } + /// ``` + pub fn contains(&self, item: Idx) -> bool { + (item <= self.end) + } +} + +// RangeToInclusive cannot impl From> +// because underflow would be possible with (..0).into() diff --git a/src/libcore/ops/try.rs b/src/libcore/ops/try.rs new file mode 100644 index 0000000000..9da9879d38 --- /dev/null +++ b/src/libcore/ops/try.rs @@ -0,0 +1,49 @@ +// 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. + +/// A trait for customizing the behaviour of the `?` operator. +/// +/// A type implementing `Try` is one that has a canonical way to view it +/// in terms of a success/failure dichotomy. This trait allows both +/// extracting those success or failure values from an existing instance and +/// creating a new instance from a success or failure value. +#[unstable(feature = "try_trait", issue = "42327")] +#[rustc_on_unimplemented = "the `?` operator can only be used in a function that returns `Result` \ + (or another type that implements `std::ops::Try`)"] +pub trait Try { + /// The type of this value when viewed as successful. + #[unstable(feature = "try_trait", issue = "42327")] + type Ok; + /// The type of this value when viewed as failed. + #[unstable(feature = "try_trait", issue = "42327")] + type Error; + + /// Applies the "?" operator. A return of `Ok(t)` means that the + /// execution should continue normally, and the result of `?` is the + /// value `t`. A return of `Err(e)` means that execution should branch + /// to the innermost enclosing `catch`, or return from the function. + /// + /// If an `Err(e)` result is returned, the value `e` will be "wrapped" + /// in the return type of the enclosing scope (which must itself implement + /// `Try`). Specifically, the value `X::from_error(From::from(e))` + /// is returned, where `X` is the return type of the enclosing function. + #[unstable(feature = "try_trait", issue = "42327")] + fn into_result(self) -> Result; + + /// Wrap an error value to construct the composite result. For example, + /// `Result::Err(x)` and `Result::from_error(x)` are equivalent. + #[unstable(feature = "try_trait", issue = "42327")] + fn from_error(v: Self::Error) -> Self; + + /// Wrap an OK value to construct the composite result. For example, + /// `Result::Ok(x)` and `Result::from_ok(x)` are equivalent. + #[unstable(feature = "try_trait", issue = "42327")] + fn from_ok(v: Self::Ok) -> Self; +} diff --git a/src/libcore/ops/unsize.rs b/src/libcore/ops/unsize.rs new file mode 100644 index 0000000000..1914216e9f --- /dev/null +++ b/src/libcore/ops/unsize.rs @@ -0,0 +1,79 @@ +// 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 marker::Unsize; + +/// Trait that indicates that this is a pointer or a wrapper for one, +/// where unsizing can be performed on the pointee. +/// +/// See the [DST coercion RfC][dst-coerce] and [the nomicon entry on coercion][nomicon-coerce] +/// 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 { + // Empty. +} + +// &mut T -> &mut U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {} +// &mut T -> &U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl<'a, 'b: 'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {} +// &mut T -> *mut U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {} +// &mut T -> *const U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {} + +// &T -> &U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl<'a, 'b: 'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} +// &T -> *const U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a T {} + +// *mut T -> *mut U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} +// *mut T -> *const U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl, U: ?Sized> CoerceUnsized<*const U> for *mut T {} + +// *const T -> *const U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} diff --git a/src/libcore/option.rs b/src/libcore/option.rs index e825acad47..ef41b67941 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -671,8 +671,6 @@ impl Option { /// # Examples /// /// ``` - /// #![feature(option_entry)] - /// /// let mut x = None; /// /// { @@ -685,7 +683,7 @@ impl Option { /// assert_eq!(x, Some(7)); /// ``` #[inline] - #[unstable(feature = "option_entry", issue = "39288")] + #[stable(feature = "option_entry", since = "1.20.0")] pub fn get_or_insert(&mut self, v: T) -> &mut T { match *self { None => *self = Some(v), @@ -706,8 +704,6 @@ impl Option { /// # Examples /// /// ``` - /// #![feature(option_entry)] - /// /// let mut x = None; /// /// { @@ -720,7 +716,7 @@ impl Option { /// assert_eq!(x, Some(7)); /// ``` #[inline] - #[unstable(feature = "option_entry", issue = "39288")] + #[stable(feature = "option_entry", since = "1.20.0")] pub fn get_or_insert_with T>(&mut self, f: F) -> &mut T { match *self { None => *self = Some(f()), diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index 93ddfa72f6..f5a7e78d0f 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -15,8 +15,10 @@ //! useful an upstream crate must define panicking for libcore to use. The current //! interface for panicking is: //! -//! ```ignore -//! fn panic_impl(fmt: fmt::Arguments, &(&'static str, u32)) -> !; +//! ``` +//! # use std::fmt; +//! fn panic_impl(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! +//! # { loop {} } //! ``` //! //! This definition allows for panicking with any general message, but it does not @@ -37,34 +39,55 @@ use fmt; #[cold] #[inline(never)] // this is the slow path, always -#[lang = "panic"] -pub fn panic(expr_file_line: &(&'static str, &'static str, u32)) -> ! { +#[cfg_attr(not(stage0), lang = "panic")] +pub fn panic(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! { // Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially // reduce size overhead. The format_args! macro uses str's Display trait to // write expr, which calls Formatter::pad, which must accommodate string // truncation and padding (even though none is used here). Using // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the // output binary, saving up to a few kilobytes. + let (expr, file, line, col) = *expr_file_line_col; + panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line, col)) +} + +// FIXME: remove when SNAP +#[cold] #[inline(never)] +#[cfg(stage0)] +#[lang = "panic"] +pub fn panic_old(expr_file_line: &(&'static str, &'static str, u32)) -> ! { let (expr, file, line) = *expr_file_line; - panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line)) + let expr_file_line_col = (expr, file, line, 0); + panic(&expr_file_line_col) } #[cold] #[inline(never)] +#[cfg_attr(not(stage0), lang = "panic_bounds_check")] +fn panic_bounds_check(file_line_col: &(&'static str, u32, u32), + index: usize, len: usize) -> ! { + panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}", + len, index), file_line_col) +} + +// FIXME: remove when SNAP +#[cold] #[inline(never)] +#[cfg(stage0)] #[lang = "panic_bounds_check"] -fn panic_bounds_check(file_line: &(&'static str, u32), +fn panic_bounds_check_old(file_line: &(&'static str, u32), index: usize, len: usize) -> ! { + let (file, line) = *file_line; panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}", - len, index), file_line) + len, index), &(file, line, 0)) } #[cold] #[inline(never)] -pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> ! { +pub fn panic_fmt(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! { #[allow(improper_ctypes)] extern { #[lang = "panic_fmt"] #[unwind] - fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: u32) -> !; + fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: u32, col: u32) -> !; } - let (file, line) = *file_line; - unsafe { panic_impl(fmt, file, line) } + let (file, line, col) = *file_line_col; + unsafe { panic_impl(fmt, file, line, col) } } diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index f89f86e18a..4f118f5844 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -117,6 +117,93 @@ pub unsafe fn swap(x: *mut T, y: *mut T) { mem::forget(tmp); } +/// Swaps a sequence of values at two mutable locations of the same type. +/// +/// # Safety +/// +/// The two arguments must each point to the beginning of `count` locations +/// of valid memory, and the two memory ranges must not overlap. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// #![feature(swap_nonoverlapping)] +/// +/// use std::ptr; +/// +/// let mut x = [1, 2, 3, 4]; +/// let mut y = [7, 8, 9]; +/// +/// unsafe { +/// ptr::swap_nonoverlapping(x.as_mut_ptr(), y.as_mut_ptr(), 2); +/// } +/// +/// assert_eq!(x, [7, 8, 3, 4]); +/// assert_eq!(y, [1, 2, 9]); +/// ``` +#[inline] +#[unstable(feature = "swap_nonoverlapping", issue = "42818")] +pub unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { + let x = x as *mut u8; + let y = y as *mut u8; + let len = mem::size_of::() * count; + swap_nonoverlapping_bytes(x, y, len) +} + +#[inline] +unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { + // The approach here is to utilize simd to swap x & y efficiently. Testing reveals + // that swapping either 32 bytes or 64 bytes at a time is most efficient for intel + // Haswell E processors. LLVM is more able to optimize if we give a struct a + // #[repr(simd)], even if we don't actually use this struct directly. + // + // FIXME repr(simd) broken on emscripten and redox + // It's also broken on big-endian powerpc64 and s390x. #42778 + #[cfg_attr(not(any(target_os = "emscripten", target_os = "redox", + target_endian = "big")), + repr(simd))] + struct Block(u64, u64, u64, u64); + struct UnalignedBlock(u64, u64, u64, u64); + + let block_size = mem::size_of::(); + + // Loop through x & y, copying them `Block` at a time + // The optimizer should unroll the loop fully for most types + // N.B. We can't use a for loop as the `range` impl calls `mem::swap` recursively + let mut i = 0; + while i + block_size <= len { + // Create some uninitialized memory as scratch space + // Declaring `t` here avoids aligning the stack when this loop is unused + let mut t: Block = mem::uninitialized(); + let t = &mut t as *mut _ as *mut u8; + let x = x.offset(i as isize); + let y = y.offset(i as isize); + + // Swap a block of bytes of x & y, using t as a temporary buffer + // This should be optimized into efficient SIMD operations where available + copy_nonoverlapping(x, t, block_size); + copy_nonoverlapping(y, x, block_size); + copy_nonoverlapping(t, y, block_size); + i += block_size; + } + + if i < len { + // Swap any remaining bytes + let mut t: UnalignedBlock = mem::uninitialized(); + let rem = len - i; + + let t = &mut t as *mut _ as *mut u8; + let x = x.offset(i as isize); + let y = y.offset(i as isize); + + copy_nonoverlapping(x, t, rem); + copy_nonoverlapping(y, x, rem); + copy_nonoverlapping(t, y, rem); + } +} + /// Replaces the value at `dest` with `src`, returning the old /// value, without dropping either. /// @@ -408,11 +495,11 @@ impl *const T { /// /// Basic usage: /// - /// ```ignore - /// let val: *const u8 = &10u8 as *const u8; + /// ``` + /// let ptr: *const u8 = &10u8 as *const u8; /// /// unsafe { - /// if let Some(val_back) = val.as_ref() { + /// if let Some(val_back) = ptr.as_ref() { /// println!("We got back the value: {}!", val_back); /// } /// } @@ -570,11 +657,11 @@ impl *mut T { /// /// Basic usage: /// - /// ```ignore - /// let val: *mut u8 = &mut 10u8 as *mut u8; + /// ``` + /// let ptr: *mut u8 = &mut 10u8 as *mut u8; /// /// unsafe { - /// if let Some(val_back) = val.as_ref() { + /// if let Some(val_back) = ptr.as_ref() { /// println!("We got back the value: {}!", val_back); /// } /// } diff --git a/src/libcore/result.rs b/src/libcore/result.rs index df7fff0df9..88a93492de 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -1060,12 +1060,9 @@ impl> FromIterator> for Result { /// checking for overflow: /// /// ``` - /// use std::u32; - /// /// let v = vec![1, 2]; - /// let res: Result, &'static str> = v.iter().map(|&x: &u32| - /// if x == u32::MAX { Err("Overflow!") } - /// else { Ok(x + 1) } + /// let res: Result, &'static str> = v.iter().map(|x: &u32| + /// x.checked_add(1).ok_or("Overflow!") /// ).collect(); /// assert!(res == Ok(vec![2, 3])); /// ``` @@ -1126,4 +1123,4 @@ impl ops::Try for Result { fn from_error(v: E) -> Self { Err(v) } -} \ No newline at end of file +} diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index b13e19c030..62c7e7aa1c 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -212,15 +212,15 @@ pub trait SliceExt { #[stable(feature = "copy_from_slice", since = "1.9.0")] fn copy_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Copy; - #[unstable(feature = "sort_unstable", issue = "40585")] + #[stable(feature = "sort_unstable", since = "1.20.0")] fn sort_unstable(&mut self) where Self::Item: Ord; - #[unstable(feature = "sort_unstable", issue = "40585")] + #[stable(feature = "sort_unstable", since = "1.20.0")] fn sort_unstable_by(&mut self, compare: F) where F: FnMut(&Self::Item, &Self::Item) -> Ordering; - #[unstable(feature = "sort_unstable", issue = "40585")] + #[stable(feature = "sort_unstable", since = "1.20.0")] fn sort_unstable_by_key(&mut self, f: F) where F: FnMut(&Self::Item) -> B, B: Ord; @@ -1030,47 +1030,38 @@ impl SliceIndex<[T]> for ops::RangeInclusive { } } -#[cfg(stage0)] // The bootstrap compiler has a different `...` desugar -fn inclusive(start: usize, end: usize) -> ops::RangeInclusive { - ops::RangeInclusive { start, end } -} -#[cfg(not(stage0))] -fn inclusive(start: usize, end: usize) -> ops::RangeInclusive { - start...end -} - #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] impl SliceIndex<[T]> for ops::RangeToInclusive { type Output = [T]; #[inline] fn get(self, slice: &[T]) -> Option<&[T]> { - inclusive(0, self.end).get(slice) + (0...self.end).get(slice) } #[inline] fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { - inclusive(0, self.end).get_mut(slice) + (0...self.end).get_mut(slice) } #[inline] unsafe fn get_unchecked(self, slice: &[T]) -> &[T] { - inclusive(0, self.end).get_unchecked(slice) + (0...self.end).get_unchecked(slice) } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] { - inclusive(0, self.end).get_unchecked_mut(slice) + (0...self.end).get_unchecked_mut(slice) } #[inline] fn index(self, slice: &[T]) -> &[T] { - inclusive(0, self.end).index(slice) + (0...self.end).index(slice) } #[inline] fn index_mut(self, slice: &mut [T]) -> &mut [T] { - inclusive(0, self.end).index_mut(slice) + (0...self.end).index_mut(slice) } } diff --git a/src/libcore/slice/rotate.rs b/src/libcore/slice/rotate.rs index 3b9ae5652c..e4a4e33c17 100644 --- a/src/libcore/slice/rotate.rs +++ b/src/libcore/slice/rotate.rs @@ -76,7 +76,7 @@ pub unsafe fn ptr_rotate(mut left: usize, mid: *mut T, mut right: usize) { break; } - ptr_swap_n( + ptr::swap_nonoverlapping( mid.offset(-(left as isize)), mid.offset((right-delta) as isize), delta); @@ -103,10 +103,3 @@ pub unsafe fn ptr_rotate(mut left: usize, mid: *mut T, mut right: usize) { ptr::copy_nonoverlapping(buf, mid.offset(-(left as isize)), right); } } - -unsafe fn ptr_swap_n(a: *mut T, b: *mut T, n: usize) { - for i in 0..n { - // These are nonoverlapping, so use mem::swap instead of ptr::swap - mem::swap(&mut *a.offset(i as isize), &mut *b.offset(i as isize)); - } -} diff --git a/src/libcore/slice/sort.rs b/src/libcore/slice/sort.rs index 6f9f2915df..518d56095d 100644 --- a/src/libcore/slice/sort.rs +++ b/src/libcore/slice/sort.rs @@ -351,7 +351,7 @@ fn partition_in_blocks(v: &mut [T], pivot: &T, is_less: &mut F) -> usize if start_l < end_l { // The left block remains. - // Move it's remaining out-of-order elements to the far right. + // Move its remaining out-of-order elements to the far right. debug_assert_eq!(width(l, r), block_l); while start_l < end_l { unsafe { @@ -363,7 +363,7 @@ fn partition_in_blocks(v: &mut [T], pivot: &T, is_less: &mut F) -> usize width(v.as_mut_ptr(), r) } else if start_r < end_r { // The right block remains. - // Move it's remaining out-of-order elements to the far left. + // Move its remaining out-of-order elements to the far left. debug_assert_eq!(width(l, r), block_r); while start_r < end_r { unsafe { diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 547a4899c7..cc18222815 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -207,7 +207,7 @@ impl Utf8Error { /// that starts at the index given by `valid_up_to()`. /// Decoding should resume after that sequence /// (after inserting a U+FFFD REPLACEMENT CHARACTER) in case of lossy decoding. - #[unstable(feature = "utf8_error_error_len", reason ="new", issue = "40494")] + #[stable(feature = "utf8_error_error_len", since = "1.20.0")] pub fn error_len(&self) -> Option { self.error_len.map(|len| len as usize) } @@ -301,7 +301,7 @@ pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> { } /// Converts a mutable slice of bytes to a mutable string slice. -#[unstable(feature = "str_mut_extras", issue = "41119")] +#[stable(feature = "str_mut_extras", since = "1.20.0")] pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> { run_utf8_validation(v)?; Ok(unsafe { from_utf8_unchecked_mut(v) }) @@ -381,8 +381,8 @@ pub unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { /// See the immutable version, [`from_utf8_unchecked()`][fromutf8], for more information. /// /// [fromutf8]: fn.from_utf8_unchecked.html -#[inline(always)] -#[unstable(feature = "str_mut_extras", issue = "41119")] +#[inline] +#[stable(feature = "str_mut_extras", since = "1.20.0")] pub unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str { mem::transmute(v) } @@ -710,6 +710,37 @@ impl<'a> Iterator for Bytes<'a> { fn nth(&mut self, n: usize) -> Option { self.0.nth(n) } + + #[inline] + fn all(&mut self, f: F) -> bool where F: FnMut(Self::Item) -> bool { + self.0.all(f) + } + + #[inline] + fn any(&mut self, f: F) -> bool where F: FnMut(Self::Item) -> bool { + self.0.any(f) + } + + #[inline] + fn find

(&mut self, predicate: P) -> Option where + P: FnMut(&Self::Item) -> bool + { + self.0.find(predicate) + } + + #[inline] + fn position

(&mut self, predicate: P) -> Option where + P: FnMut(Self::Item) -> bool + { + self.0.position(predicate) + } + + #[inline] + fn rposition

(&mut self, predicate: P) -> Option where + P: FnMut(Self::Item) -> bool + { + self.0.rposition(predicate) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -718,6 +749,13 @@ impl<'a> DoubleEndedIterator for Bytes<'a> { fn next_back(&mut self) -> Option { self.0.next_back() } + + #[inline] + fn rfind

(&mut self, predicate: P) -> Option where + P: FnMut(&Self::Item) -> bool + { + self.0.rfind(predicate) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1617,12 +1655,7 @@ mod traits { #[inline] fn index(&self, index: ops::RangeTo) -> &str { - // is_char_boundary checks that the index is in [0, .len()] - if self.is_char_boundary(index.end) { - unsafe { self.slice_unchecked(0, index.end) } - } else { - super::slice_error_fail(self, 0, index.end) - } + index.index(self) } } @@ -1636,12 +1669,7 @@ mod traits { impl ops::IndexMut> for str { #[inline] fn index_mut(&mut self, index: ops::RangeTo) -> &mut str { - // is_char_boundary checks that the index is in [0, .len()] - if self.is_char_boundary(index.end) { - unsafe { self.slice_mut_unchecked(0, index.end) } - } else { - super::slice_error_fail(self, 0, index.end) - } + index.index_mut(self) } } @@ -1657,12 +1685,7 @@ mod traits { #[inline] fn index(&self, index: ops::RangeFrom) -> &str { - // is_char_boundary checks that the index is in [0, .len()] - if self.is_char_boundary(index.start) { - unsafe { self.slice_unchecked(index.start, self.len()) } - } else { - super::slice_error_fail(self, index.start, self.len()) - } + index.index(self) } } @@ -1676,13 +1699,7 @@ mod traits { impl ops::IndexMut> for str { #[inline] fn index_mut(&mut self, index: ops::RangeFrom) -> &mut str { - // is_char_boundary checks that the index is in [0, .len()] - if self.is_char_boundary(index.start) { - let len = self.len(); - unsafe { self.slice_mut_unchecked(index.start, len) } - } else { - super::slice_error_fail(self, index.start, self.len()) - } + index.index_mut(self) } } @@ -1724,9 +1741,7 @@ mod traits { #[inline] fn index(&self, index: ops::RangeInclusive) -> &str { - assert!(index.end != usize::max_value(), - "attempted to index str up to maximum usize"); - self.index(index.start .. index.end+1) + index.index(self) } } @@ -1738,9 +1753,7 @@ mod traits { #[inline] fn index(&self, index: ops::RangeToInclusive) -> &str { - assert!(index.end != usize::max_value(), - "attempted to index str up to maximum usize"); - self.index(.. index.end+1) + index.index(self) } } @@ -1750,9 +1763,7 @@ mod traits { impl ops::IndexMut> for str { #[inline] fn index_mut(&mut self, index: ops::RangeInclusive) -> &mut str { - assert!(index.end != usize::max_value(), - "attempted to index str up to maximum usize"); - self.index_mut(index.start .. index.end+1) + index.index_mut(self) } } #[unstable(feature = "inclusive_range", @@ -1761,13 +1772,11 @@ mod traits { impl ops::IndexMut> for str { #[inline] fn index_mut(&mut self, index: ops::RangeToInclusive) -> &mut str { - assert!(index.end != usize::max_value(), - "attempted to index str up to maximum usize"); - self.index_mut(.. index.end+1) + index.index_mut(self) } } - #[unstable(feature = "str_checked_slicing", issue = "39932")] + #[stable(feature = "str_checked_slicing", since = "1.20.0")] impl SliceIndex for ops::RangeFull { type Output = str; #[inline] @@ -1796,7 +1805,7 @@ mod traits { } } - #[unstable(feature = "str_checked_slicing", issue = "39932")] + #[stable(feature = "str_checked_slicing", since = "1.20.0")] impl SliceIndex for ops::Range { type Output = str; #[inline] @@ -1850,7 +1859,7 @@ mod traits { } } - #[unstable(feature = "str_checked_slicing", issue = "39932")] + #[stable(feature = "str_checked_slicing", since = "1.20.0")] impl SliceIndex for ops::RangeTo { type Output = str; #[inline] @@ -1886,6 +1895,7 @@ mod traits { } #[inline] fn index_mut(self, slice: &mut str) -> &mut Self::Output { + // is_char_boundary checks that the index is in [0, .len()] if slice.is_char_boundary(self.end) { unsafe { self.get_unchecked_mut(slice) } } else { @@ -1894,7 +1904,7 @@ mod traits { } } - #[unstable(feature = "str_checked_slicing", issue = "39932")] + #[stable(feature = "str_checked_slicing", since = "1.20.0")] impl SliceIndex for ops::RangeFrom { type Output = str; #[inline] @@ -1932,6 +1942,7 @@ mod traits { } #[inline] fn index_mut(self, slice: &mut str) -> &mut Self::Output { + // is_char_boundary checks that the index is in [0, .len()] if slice.is_char_boundary(self.start) { unsafe { self.get_unchecked_mut(slice) } } else { @@ -1940,16 +1951,24 @@ mod traits { } } - #[unstable(feature = "str_checked_slicing", issue = "39932")] + #[stable(feature = "str_checked_slicing", since = "1.20.0")] impl SliceIndex for ops::RangeInclusive { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { - (self.start..self.end+1).get(slice) + if let Some(end) = self.end.checked_add(1) { + (self.start..end).get(slice) + } else { + None + } } #[inline] fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { - (self.start..self.end+1).get_mut(slice) + if let Some(end) = self.end.checked_add(1) { + (self.start..end).get_mut(slice) + } else { + None + } } #[inline] unsafe fn get_unchecked(self, slice: &str) -> &Self::Output { @@ -1961,22 +1980,26 @@ mod traits { } #[inline] fn index(self, slice: &str) -> &Self::Output { + assert!(self.end != usize::max_value(), + "attempted to index str up to maximum usize"); (self.start..self.end+1).index(slice) } #[inline] fn index_mut(self, slice: &mut str) -> &mut Self::Output { + assert!(self.end != usize::max_value(), + "attempted to index str up to maximum usize"); (self.start..self.end+1).index_mut(slice) } } - #[unstable(feature = "str_checked_slicing", issue = "39932")] + #[stable(feature = "str_checked_slicing", since = "1.20.0")] impl SliceIndex for ops::RangeToInclusive { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { - if slice.is_char_boundary(self.end + 1) { + if self.end < usize::max_value() && slice.is_char_boundary(self.end + 1) { Some(unsafe { self.get_unchecked(slice) }) } else { None @@ -1984,7 +2007,7 @@ mod traits { } #[inline] fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { - if slice.is_char_boundary(self.end + 1) { + if self.end < usize::max_value() && slice.is_char_boundary(self.end + 1) { Some(unsafe { self.get_unchecked_mut(slice) }) } else { None @@ -2002,11 +2025,15 @@ mod traits { } #[inline] fn index(self, slice: &str) -> &Self::Output { + assert!(self.end != usize::max_value(), + "attempted to index str up to maximum usize"); let end = self.end + 1; self.get(slice).unwrap_or_else(|| super::slice_error_fail(slice, 0, end)) } #[inline] fn index_mut(self, slice: &mut str) -> &mut Self::Output { + assert!(self.end != usize::max_value(), + "attempted to index str up to maximum usize"); if slice.is_char_boundary(self.end) { unsafe { self.get_unchecked_mut(slice) } } else { @@ -2026,7 +2053,7 @@ mod traits { issue = "32110")] pub trait StrExt { // NB there are no docs here are they're all located on the StrExt trait in - // libcollections, not here. + // liballoc, not here. #[stable(feature = "core", since = "1.6.0")] fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool; @@ -2067,13 +2094,13 @@ pub trait StrExt { #[rustc_deprecated(since = "1.6.0", reason = "use lines() instead now")] #[allow(deprecated)] fn lines_any(&self) -> LinesAny; - #[unstable(feature = "str_checked_slicing", issue = "39932")] + #[stable(feature = "str_checked_slicing", since = "1.20.0")] fn get>(&self, i: I) -> Option<&I::Output>; - #[unstable(feature = "str_checked_slicing", issue = "39932")] + #[stable(feature = "str_checked_slicing", since = "1.20.0")] fn get_mut>(&mut self, i: I) -> Option<&mut I::Output>; - #[unstable(feature = "str_checked_slicing", issue = "39932")] + #[stable(feature = "str_checked_slicing", since = "1.20.0")] unsafe fn get_unchecked>(&self, i: I) -> &I::Output; - #[unstable(feature = "str_checked_slicing", issue = "39932")] + #[stable(feature = "str_checked_slicing", since = "1.20.0")] unsafe fn get_unchecked_mut>(&mut self, i: I) -> &mut I::Output; #[stable(feature = "core", since = "1.6.0")] unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str; @@ -2096,7 +2123,7 @@ pub trait StrExt { fn is_char_boundary(&self, index: usize) -> bool; #[stable(feature = "core", since = "1.6.0")] fn as_bytes(&self) -> &[u8]; - #[unstable(feature = "str_mut_extras", issue = "0")] + #[stable(feature = "str_mut_extras", since = "1.20.0")] unsafe fn as_bytes_mut(&mut self) -> &mut [u8]; #[stable(feature = "core", since = "1.6.0")] fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option; diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs index 4918e37eb3..5a007285e4 100644 --- a/src/libcore/str/pattern.rs +++ b/src/libcore/str/pattern.rs @@ -618,7 +618,10 @@ impl<'a, 'b> StrSearcher<'a, 'b> { } unsafe impl<'a, 'b> Searcher<'a> for StrSearcher<'a, 'b> { - fn haystack(&self) -> &'a str { self.haystack } + #[inline] + fn haystack(&self) -> &'a str { + self.haystack + } #[inline] fn next(&mut self) -> SearchStep { diff --git a/src/libcore/tests/char.rs b/src/libcore/tests/char.rs index e4012ec91e..7c3b90c815 100644 --- a/src/libcore/tests/char.rs +++ b/src/libcore/tests/char.rs @@ -10,6 +10,7 @@ use std::{char,str}; use std::convert::TryFrom; +use std::str::FromStr; #[test] fn test_convert() { @@ -28,6 +29,16 @@ fn test_convert() { assert!(char::try_from(0xFFFF_FFFF_u32).is_err()); } +#[test] +fn test_from_str() { + assert_eq!(char::from_str("a").unwrap(), 'a'); + assert_eq!(char::try_from("a").unwrap(), 'a'); + assert_eq!(char::from_str("\0").unwrap(), '\0'); + assert_eq!(char::from_str("\u{D7FF}").unwrap(), '\u{d7FF}'); + assert!(char::from_str("").is_err()); + assert!(char::from_str("abc").is_err()); +} + #[test] fn test_is_lowercase() { assert!('a'.is_lowercase()); diff --git a/src/libcore/tests/cmp.rs b/src/libcore/tests/cmp.rs index e3c65ad8b3..8c5179f599 100644 --- a/src/libcore/tests/cmp.rs +++ b/src/libcore/tests/cmp.rs @@ -28,6 +28,16 @@ fn test_mut_int_totalord() { assert_eq!((&mut 12).cmp(&&mut -5), Greater); } +#[test] +fn test_ord_max_min() { + assert_eq!(1.max(2), 2); + assert_eq!(2.max(1), 2); + assert_eq!(1.min(2), 1); + assert_eq!(2.min(1), 1); + assert_eq!(1.max(1), 1); + assert_eq!(1.min(1), 1); +} + #[test] fn test_ordering_reverse() { assert_eq!(Less.reverse(), Greater); diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 4f9951cd15..a1249a5f22 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -12,15 +12,6 @@ use core::iter::*; use core::{i8, i16, isize}; use core::usize; -// FIXME #27741: This is here to simplify calling Iterator::step_by. Remove -// once Range::step_by is completely gone (not just deprecated). -trait IterEx: Sized { - fn iter_step_by(self, n: usize) -> StepBy; -} -impl IterEx for I { - fn iter_step_by(self, n: usize) -> StepBy { self.step_by(n) } -} - #[test] fn test_lt() { let empty: [isize; 0] = []; @@ -76,7 +67,7 @@ fn test_multi_iter() { #[test] fn test_counter_from_iter() { - let it = (0..).iter_step_by(5).take(10); + let it = (0..).step_by(5).take(10); let xs: Vec = FromIterator::from_iter(it); assert_eq!(xs, [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]); } @@ -94,7 +85,7 @@ fn test_iterator_chain() { } assert_eq!(i, expected.len()); - let ys = (30..).iter_step_by(10).take(4); + let ys = (30..).step_by(10).take(4); let it = xs.iter().cloned().chain(ys); let mut i = 0; for x in it { @@ -156,13 +147,13 @@ fn test_iterator_chain_find() { #[test] fn test_iterator_step_by() { // Identity - let mut it = (0..).iter_step_by(1).take(3); + let mut it = (0..).step_by(1).take(3); assert_eq!(it.next(), Some(0)); assert_eq!(it.next(), Some(1)); assert_eq!(it.next(), Some(2)); assert_eq!(it.next(), None); - let mut it = (0..).iter_step_by(3).take(4); + let mut it = (0..).step_by(3).take(4); assert_eq!(it.next(), Some(0)); assert_eq!(it.next(), Some(3)); assert_eq!(it.next(), Some(6)); @@ -173,7 +164,7 @@ fn test_iterator_step_by() { #[test] #[should_panic] fn test_iterator_step_by_zero() { - let mut it = (0..).iter_step_by(0); + let mut it = (0..).step_by(0); it.next(); } @@ -252,7 +243,7 @@ fn test_iterator_step_by_size_hint() { #[test] fn test_filter_map() { - let it = (0..).iter_step_by(1).take(10) + let it = (0..).step_by(1).take(10) .filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None }); assert_eq!(it.collect::>(), [0*0, 2*2, 4*4, 6*6, 8*8]); } @@ -654,7 +645,7 @@ fn test_iterator_scan() { fn test_iterator_flat_map() { let xs = [0, 3, 6]; let ys = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let it = xs.iter().flat_map(|&x| (x..).iter_step_by(1).take(3)); + let it = xs.iter().flat_map(|&x| (x..).step_by(1).take(3)); let mut i = 0; for x in it { assert_eq!(x, ys[i]); @@ -680,13 +671,13 @@ fn test_inspect() { #[test] fn test_cycle() { let cycle_len = 3; - let it = (0..).iter_step_by(1).take(cycle_len).cycle(); + let it = (0..).step_by(1).take(cycle_len).cycle(); assert_eq!(it.size_hint(), (usize::MAX, None)); for (i, x) in it.take(100).enumerate() { assert_eq!(i % cycle_len, x); } - let mut it = (0..).iter_step_by(1).take(0).cycle(); + let mut it = (0..).step_by(1).take(0).cycle(); assert_eq!(it.size_hint(), (0, Some(0))); assert_eq!(it.next(), None); } @@ -765,7 +756,7 @@ fn test_iterator_min() { #[test] fn test_iterator_size_hint() { - let c = (0..).iter_step_by(1); + let c = (0..).step_by(1); let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; let v2 = &[10, 11, 12]; let vi = v.iter(); @@ -1085,13 +1076,82 @@ fn test_range() { (isize::MAX as usize + 2, Some(isize::MAX as usize + 2))); } +#[test] +fn test_range_inclusive_exhaustion() { + let mut r = 10...10; + assert_eq!(r.next(), Some(10)); + assert_eq!(r, 1...0); + + let mut r = 10...10; + assert_eq!(r.next_back(), Some(10)); + assert_eq!(r, 1...0); + + let mut r = 10...12; + assert_eq!(r.nth(2), Some(12)); + assert_eq!(r, 1...0); + + let mut r = 10...12; + assert_eq!(r.nth(5), None); + assert_eq!(r, 1...0); + +} + +#[test] +fn test_range_nth() { + assert_eq!((10..15).nth(0), Some(10)); + assert_eq!((10..15).nth(1), Some(11)); + assert_eq!((10..15).nth(4), Some(14)); + assert_eq!((10..15).nth(5), None); + + let mut r = 10..20; + assert_eq!(r.nth(2), Some(12)); + assert_eq!(r, 13..20); + assert_eq!(r.nth(2), Some(15)); + assert_eq!(r, 16..20); + assert_eq!(r.nth(10), None); + assert_eq!(r, 20..20); +} + +#[test] +fn test_range_from_nth() { + assert_eq!((10..).nth(0), Some(10)); + assert_eq!((10..).nth(1), Some(11)); + assert_eq!((10..).nth(4), Some(14)); + + let mut r = 10..; + assert_eq!(r.nth(2), Some(12)); + assert_eq!(r, 13..); + assert_eq!(r.nth(2), Some(15)); + assert_eq!(r, 16..); + assert_eq!(r.nth(10), Some(26)); + assert_eq!(r, 27..); +} + +#[test] +fn test_range_inclusive_nth() { + assert_eq!((10...15).nth(0), Some(10)); + assert_eq!((10...15).nth(1), Some(11)); + assert_eq!((10...15).nth(5), Some(15)); + assert_eq!((10...15).nth(6), None); + + let mut r = 10_u8...20; + assert_eq!(r.nth(2), Some(12)); + assert_eq!(r, 13...20); + assert_eq!(r.nth(2), Some(15)); + assert_eq!(r, 16...20); + assert_eq!(r.is_empty(), false); + assert_eq!(r.nth(10), None); + assert_eq!(r.is_empty(), true); + assert_eq!(r, 1...0); // We may not want to document/promise this detail +} + #[test] fn test_range_step() { #![allow(deprecated)] assert_eq!((0..20).step_by(5).collect::>(), [0, 5, 10, 15]); - assert_eq!((20..0).step_by(-5).collect::>(), [20, 15, 10, 5]); - assert_eq!((20..0).step_by(-6).collect::>(), [20, 14, 8, 2]); + assert_eq!((1..21).rev().step_by(5).collect::>(), [20, 15, 10, 5]); + assert_eq!((1..21).rev().step_by(6).collect::>(), [20, 14, 8, 2]); assert_eq!((200..255).step_by(50).collect::>(), [200, 250]); assert_eq!((200..-5).step_by(1).collect::>(), []); assert_eq!((200..200).step_by(1).collect::>(), []); @@ -1099,13 +1159,12 @@ fn test_range_step() { assert_eq!((0..20).step_by(1).size_hint(), (20, Some(20))); assert_eq!((0..20).step_by(21).size_hint(), (1, Some(1))); assert_eq!((0..20).step_by(5).size_hint(), (4, Some(4))); - assert_eq!((20..0).step_by(-5).size_hint(), (4, Some(4))); - assert_eq!((20..0).step_by(-6).size_hint(), (4, Some(4))); + assert_eq!((1..21).rev().step_by(5).size_hint(), (4, Some(4))); + assert_eq!((1..21).rev().step_by(6).size_hint(), (4, Some(4))); assert_eq!((20..-5).step_by(1).size_hint(), (0, Some(0))); assert_eq!((20..20).step_by(1).size_hint(), (0, Some(0))); - assert_eq!((0..1).step_by(0).size_hint(), (0, None)); - assert_eq!((i8::MAX..i8::MIN).step_by(i8::MIN).size_hint(), (2, Some(2))); - assert_eq!((i16::MIN..i16::MAX).step_by(i16::MAX).size_hint(), (3, Some(3))); + assert_eq!((i8::MIN..i8::MAX).step_by(-(i8::MIN as i32) as usize).size_hint(), (2, Some(2))); + assert_eq!((i16::MIN..i16::MAX).step_by(i16::MAX as usize).size_hint(), (3, Some(3))); assert_eq!((isize::MIN..isize::MAX).step_by(1).size_hint(), (usize::MAX, Some(usize::MAX))); } diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 505e51fa80..a85c347146 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -11,30 +11,31 @@ #![deny(warnings)] #![feature(box_syntax)] -#![feature(char_escape_debug)] #![feature(const_fn)] +#![feature(core_float)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)] #![feature(dec2flt)] #![feature(decode_utf8)] +#![feature(exact_size_is_empty)] #![feature(fixed_size_array)] #![feature(flt2dec)] #![feature(fmt_internals)] #![feature(iterator_step_by)] #![feature(i128_type)] #![feature(inclusive_range)] +#![feature(inclusive_range_syntax)] #![feature(iter_rfind)] #![feature(libc)] #![feature(nonzero)] +#![feature(ord_max_min)] #![feature(rand)] #![feature(raw)] #![feature(sip_hash_13)] #![feature(slice_patterns)] #![feature(slice_rotate)] #![feature(sort_internals)] -#![feature(sort_unstable)] #![feature(specialization)] -#![feature(step_by)] #![feature(step_trait)] #![feature(test)] #![feature(trusted_len)] diff --git a/src/libcore/tests/num/dec2flt/mod.rs b/src/libcore/tests/num/dec2flt/mod.rs index 5d546c643e..9934e1dab9 100644 --- a/src/libcore/tests/num/dec2flt/mod.rs +++ b/src/libcore/tests/num/dec2flt/mod.rs @@ -33,6 +33,7 @@ macro_rules! test_literal { }) } +#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn ordinary() { test_literal!(1.0); @@ -43,6 +44,7 @@ fn ordinary() { test_literal!(2.2250738585072014e-308); } +#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn special_code_paths() { test_literal!(36893488147419103229.0); // 2^65 - 3, triggers half-to-even with even significand diff --git a/src/libcore/tests/num/dec2flt/rawfp.rs b/src/libcore/tests/num/dec2flt/rawfp.rs index 2b0afc4020..c9cd2bf5a9 100644 --- a/src/libcore/tests/num/dec2flt/rawfp.rs +++ b/src/libcore/tests/num/dec2flt/rawfp.rs @@ -86,6 +86,7 @@ fn rounding_overflow() { assert_eq!(rounded.k, adjusted_k + 1); } +#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn prev_float_monotonic() { let mut x = 1.0; @@ -121,6 +122,7 @@ fn next_float_inf() { assert_eq!(next_float(f64::INFINITY), f64::INFINITY); } +#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn next_prev_identity() { for &x in &SOME_FLOATS { @@ -131,6 +133,7 @@ fn next_prev_identity() { } } +#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn next_float_monotonic() { let mut x = 0.49999999999999; diff --git a/src/libcore/tests/num/flt2dec/strategy/dragon.rs b/src/libcore/tests/num/flt2dec/strategy/dragon.rs index 4edb0f3df6..03772a765c 100644 --- a/src/libcore/tests/num/flt2dec/strategy/dragon.rs +++ b/src/libcore/tests/num/flt2dec/strategy/dragon.rs @@ -24,6 +24,7 @@ fn test_mul_pow10() { } } +#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn shortest_sanity_test() { f64_shortest_sanity_test(format_shortest); diff --git a/src/libcore/tests/num/flt2dec/strategy/grisu.rs b/src/libcore/tests/num/flt2dec/strategy/grisu.rs index 79e66ee669..17fb99bcc9 100644 --- a/src/libcore/tests/num/flt2dec/strategy/grisu.rs +++ b/src/libcore/tests/num/flt2dec/strategy/grisu.rs @@ -38,6 +38,7 @@ fn test_max_pow10_no_more_than() { } +#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn shortest_sanity_test() { f64_shortest_sanity_test(format_shortest); diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs index 51737c9c3b..f233b649a8 100644 --- a/src/libcore/tests/num/mod.rs +++ b/src/libcore/tests/num/mod.rs @@ -169,6 +169,7 @@ test_impl_from! { test_u16f64, u16, f64 } test_impl_from! { test_u32f64, u32, f64 } // Float -> Float +#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn test_f32f64() { use core::f32; @@ -398,3 +399,57 @@ test_impl_try_from_signed_to_unsigned_err! { test_try_i32u16, i32, u16 } test_impl_try_from_signed_to_unsigned_err! { test_try_i64u8, i64, u8 } test_impl_try_from_signed_to_unsigned_err! { test_try_i64u16, i64, u16 } test_impl_try_from_signed_to_unsigned_err! { test_try_i64u32, i64, u32 } + +macro_rules! test_float { + ($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr) => { mod $modname { + use core::num::Float; + // FIXME(nagisa): these tests should test for sign of -0.0 + #[test] + fn min() { + assert_eq!(0.0.min(0.0), 0.0); + assert_eq!((-0.0).min(-0.0), -0.0); + assert_eq!(9.0.min(9.0), 9.0); + assert_eq!((-9.0).min(0.0), -9.0); + assert_eq!(0.0.min(9.0), 0.0); + assert_eq!((-0.0).min(-9.0), -9.0); + assert_eq!($inf.min(9.0), 9.0); + assert_eq!(9.0.min($inf), 9.0); + assert_eq!($inf.min(-9.0), -9.0); + assert_eq!((-9.0).min($inf), -9.0); + assert_eq!($neginf.min(9.0), $neginf); + assert_eq!(9.0.min($neginf), $neginf); + assert_eq!($neginf.min(-9.0), $neginf); + assert_eq!((-9.0).min($neginf), $neginf); + assert_eq!($nan.min(9.0), 9.0); + assert_eq!($nan.min(-9.0), -9.0); + assert_eq!(9.0.min($nan), 9.0); + assert_eq!((-9.0).min($nan), -9.0); + assert!($nan.min($nan).is_nan()); + } + #[test] + fn max() { + assert_eq!(0.0.max(0.0), 0.0); + assert_eq!((-0.0).max(-0.0), -0.0); + assert_eq!(9.0.max(9.0), 9.0); + assert_eq!((-9.0).max(0.0), 0.0); + assert_eq!(0.0.max(9.0), 9.0); + assert_eq!((-0.0).max(-9.0), -0.0); + assert_eq!($inf.max(9.0), $inf); + assert_eq!(9.0.max($inf), $inf); + assert_eq!($inf.max(-9.0), $inf); + assert_eq!((-9.0).max($inf), $inf); + assert_eq!($neginf.max(9.0), 9.0); + assert_eq!(9.0.max($neginf), 9.0); + assert_eq!($neginf.max(-9.0), -9.0); + assert_eq!((-9.0).max($neginf), -9.0); + assert_eq!($nan.max(9.0), 9.0); + assert_eq!($nan.max(-9.0), -9.0); + assert_eq!(9.0.max($nan), 9.0); + assert_eq!((-9.0).max($nan), -9.0); + assert!($nan.max($nan).is_nan()); + } + } } +} + +test_float!(f32, f32, ::core::f32::INFINITY, ::core::f32::NEG_INFINITY, ::core::f32::NAN); +test_float!(f64, f64, ::core::f64::INFINITY, ::core::f64::NEG_INFINITY, ::core::f64::NAN); diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index 55d55079dd..47e9c7c903 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -29,7 +29,7 @@ macro_rules! tuple_impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:PartialEq),+> PartialEq for ($($T,)+) { + impl<$($T:PartialEq),+> PartialEq for ($($T,)+) where last_type!($($T,)+): ?Sized { #[inline] fn eq(&self, other: &($($T,)+)) -> bool { $(self.$idx == other.$idx)&&+ @@ -41,10 +41,11 @@ macro_rules! tuple_impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:Eq),+> Eq for ($($T,)+) {} + impl<$($T:Eq),+> Eq for ($($T,)+) where last_type!($($T,)+): ?Sized {} #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+) { + impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+) + where last_type!($($T,)+): ?Sized { #[inline] fn partial_cmp(&self, other: &($($T,)+)) -> Option { lexical_partial_cmp!($(self.$idx, other.$idx),+) @@ -68,7 +69,7 @@ macro_rules! tuple_impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:Ord),+> Ord for ($($T,)+) { + impl<$($T:Ord),+> Ord for ($($T,)+) where last_type!($($T,)+): ?Sized { #[inline] fn cmp(&self, other: &($($T,)+)) -> Ordering { lexical_cmp!($(self.$idx, other.$idx),+) @@ -118,6 +119,11 @@ macro_rules! lexical_cmp { ($a:expr, $b:expr) => { ($a).cmp(&$b) }; } +macro_rules! last_type { + ($a:ident,) => { $a }; + ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; +} + tuple_impls! { Tuple1 { (0) -> A diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs deleted file mode 100644 index e0bea884f3..0000000000 --- a/src/libflate/lib.rs +++ /dev/null @@ -1,168 +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. - -//! Simple [DEFLATE][def]-based compression. This is a wrapper around the -//! [`miniz`][mz] library, which is a one-file pure-C implementation of zlib. -//! -//! [def]: https://en.wikipedia.org/wiki/DEFLATE -//! [mz]: https://code.google.com/p/miniz/ - -#![crate_name = "flate"] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![crate_type = "rlib"] -#![crate_type = "dylib"] -#![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/", - test(attr(deny(warnings))))] -#![deny(warnings)] - -#![feature(libc)] -#![cfg_attr(stage0, feature(staged_api))] -#![feature(unique)] -#![cfg_attr(test, feature(rand))] - -extern crate libc; - -use libc::{c_int, c_void, size_t}; -use std::fmt; -use std::ops::Deref; -use std::ptr::Unique; -use std::slice; - -#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct Error { - _unused: (), -} - -impl Error { - fn new() -> Error { - Error { _unused: () } - } -} - -impl fmt::Debug for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - "decompression error".fmt(f) - } -} - -pub struct Bytes { - ptr: Unique, - len: usize, -} - -impl Deref for Bytes { - type Target = [u8]; - fn deref(&self) -> &[u8] { - unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len) } - } -} - -impl Drop for Bytes { - fn drop(&mut self) { - unsafe { - libc::free(self.ptr.as_ptr() as *mut _); - } - } -} - -extern "C" { - /// Raw miniz compression function. - fn tdefl_compress_mem_to_heap(psrc_buf: *const c_void, - src_buf_len: size_t, - pout_len: *mut size_t, - flags: c_int) - -> *mut c_void; - - /// Raw miniz decompression function. - fn tinfl_decompress_mem_to_heap(psrc_buf: *const c_void, - src_buf_len: size_t, - pout_len: *mut size_t, - flags: c_int) - -> *mut c_void; -} - -const LZ_FAST: c_int = 0x01; // LZ with 1 probe, "fast" -const TDEFL_GREEDY_PARSING_FLAG: c_int = 0x04000; // fast greedy parsing instead of lazy parsing - -/// Compress a buffer without writing any sort of header on the output. Fast -/// compression is used because it is almost twice as fast as default -/// compression and the compression ratio is only marginally worse. -pub fn deflate_bytes(bytes: &[u8]) -> Bytes { - let flags = LZ_FAST | TDEFL_GREEDY_PARSING_FLAG; - unsafe { - let mut outsz: size_t = 0; - let res = tdefl_compress_mem_to_heap(bytes.as_ptr() as *const _, - bytes.len() as size_t, - &mut outsz, - flags); - assert!(!res.is_null()); - Bytes { - ptr: Unique::new(res as *mut u8), - len: outsz as usize, - } - } -} - -/// Decompress a buffer without parsing any sort of header on the input. -pub fn inflate_bytes(bytes: &[u8]) -> Result { - let flags = 0; - unsafe { - let mut outsz: size_t = 0; - let res = tinfl_decompress_mem_to_heap(bytes.as_ptr() as *const _, - bytes.len() as size_t, - &mut outsz, - flags); - if !res.is_null() { - Ok(Bytes { - ptr: Unique::new(res as *mut u8), - len: outsz as usize, - }) - } else { - Err(Error::new()) - } - } -} - -#[cfg(test)] -mod tests { - #![allow(deprecated)] - use super::{deflate_bytes, inflate_bytes}; - use std::__rand::{Rng, thread_rng}; - - #[test] - fn test_flate_round_trip() { - let mut r = thread_rng(); - let mut words = vec![]; - for _ in 0..20 { - let range = r.gen_range(1, 10); - let v = r.gen_iter::().take(range).collect::>(); - words.push(v); - } - for _ in 0..20 { - let mut input = vec![]; - for _ in 0..2000 { - input.extend_from_slice(r.choose(&words).unwrap()); - } - let cmp = deflate_bytes(&input); - let out = inflate_bytes(&cmp).unwrap(); - assert_eq!(&*input, &*out); - } - } - - #[test] - fn test_zlib_flate() { - let bytes = vec![1, 2, 3, 4, 5]; - let deflated = deflate_bytes(&bytes); - let inflated = inflate_bytes(&deflated).unwrap(); - assert_eq!(&*inflated, &*bytes); - } -} diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 641a42b081..493ce04f67 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -15,7 +15,6 @@ //! generated instead. #![crate_name = "fmt_macros"] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] #![crate_type = "rlib"] #![crate_type = "dylib"] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", @@ -25,9 +24,6 @@ test(attr(deny(warnings))))] #![deny(warnings)] -#![cfg_attr(stage0, feature(staged_api))] -#![feature(unicode)] - pub use self::Piece::*; pub use self::Position::*; pub use self::Alignment::*; diff --git a/src/libgetopts/Cargo.toml b/src/libgetopts/Cargo.toml deleted file mode 100644 index 99e3b89285..0000000000 --- a/src/libgetopts/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -name = "getopts" -version = "0.0.0" - -[lib] -name = "getopts" -path = "lib.rs" -crate-type = ["dylib", "rlib"] diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index c69c68ba59..f41fc5aa29 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -78,9 +78,6 @@ //! ``` #![crate_name = "getopts"] -#![cfg_attr(stage0, unstable(feature = "rustc_private", - reason = "use the crates.io `getopts` library instead", - issue = "27812"))] #![crate_type = "rlib"] #![crate_type = "dylib"] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", @@ -91,7 +88,6 @@ #![deny(missing_docs)] #![deny(warnings)] -#![cfg_attr(stage0, feature(staged_api))] use self::Name::*; use self::HasArg::*; diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index 2c6744e7c9..7412a01e11 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -111,7 +111,7 @@ //! //! Output from first example (in `example1.dot`): //! -//! ```ignore +//! ```dot //! digraph example1 { //! N0[label="N0"]; //! N1[label="N1"]; @@ -284,8 +284,6 @@ //! * [DOT language](http://www.graphviz.org/doc/info/lang.html) #![crate_name = "graphviz"] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(staged_api))] #![crate_type = "rlib"] #![crate_type = "dylib"] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", diff --git a/src/liblibc/.travis.yml b/src/liblibc/.travis.yml index 22d86e033b..b7721b5e60 100644 --- a/src/liblibc/.travis.yml +++ b/src/liblibc/.travis.yml @@ -56,6 +56,10 @@ matrix: - os: linux env: TARGET=i686-linux-android rust: stable + # as of 2017/05/03 x86_64-linux-android are not on stable + - os: linux + env: TARGET=x86_64-linux-android + rust: beta - os: linux env: TARGET=x86_64-unknown-linux-musl rust: stable diff --git a/src/liblibc/Cargo.lock b/src/liblibc/Cargo.lock index 1875b0e358..6fae715e9c 100644 --- a/src/liblibc/Cargo.lock +++ b/src/liblibc/Cargo.lock @@ -2,8 +2,8 @@ name = "libc-test" version = "0.1.0" dependencies = [ - "ctest 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22", + "ctest 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24", ] [[package]] @@ -13,23 +13,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ctest" -version = "0.1.0" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.27.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "gcc" -version = "0.3.35" +version = "0.3.51" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "generate-files" version = "0.1.0" dependencies = [ - "ctest 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ctest 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -43,32 +43,32 @@ dependencies = [ [[package]] name = "libc" -version = "0.1.12" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.22" +version = "0.2.24" [[package]] name = "log" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-serialize" -version = "0.3.19" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syntex_syntax" -version = "0.19.1" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -99,13 +99,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c" -"checksum ctest 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d8e8e44b9fb51a835b9193863b4b873dea29756cf4ba5151c0a6cc0f15fbdeb" -"checksum gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "91ecd03771effb0c968fd6950b37e89476a578aaf1c70297d8e92b6516ec3312" +"checksum ctest 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4714dea251b5a487400bd9f772810cca11e5fe361e1918805c9f1ce35d177e22" +"checksum gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)" = "120d07f202dcc3f72859422563522b66fe6463a4c513df062874daad05f85f0a" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122" -"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" -"checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b" -"checksum syntex_syntax 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8739e1a8b53efe7349917259f8ced15f797c89bf788a86e44f61addc0d1ecf68" +"checksum libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "e7eb6b826bfc1fdea7935d46556250d1799b7fe2d9f7951071f4291710665e3e" +"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" +"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" +"checksum syntex_syntax 0.27.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82b078749c05271b2aebae7230331c903c38128d5a3dec72625d9e3a411a5b69" "checksum term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "f2077e54d38055cf1ca0fd7933a2e00cd3ec8f6fed352b2a377f06dcdaaf3281" "checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" diff --git a/src/liblibc/Cargo.toml b/src/liblibc/Cargo.toml index 2362eec9e1..ecebaed935 100644 --- a/src/liblibc/Cargo.toml +++ b/src/liblibc/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libc" -version = "0.2.22" +version = "0.2.24" authors = ["The Rust Project Developers"] license = "MIT/Apache-2.0" readme = "README.md" diff --git a/src/liblibc/ci/android-sysimage.sh b/src/liblibc/ci/android-sysimage.sh new file mode 100644 index 0000000000..9611dfeb0d --- /dev/null +++ b/src/liblibc/ci/android-sysimage.sh @@ -0,0 +1,52 @@ +# 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 + +URL=https://dl.google.com/android/repository/sys-img/android + +main() { + local arch=$1 + local name=$2 + local dest=/system + local td=$(mktemp -d) + + apt-get install --no-install-recommends e2tools + + pushd $td + curl -O $URL/$name + unzip -q $name + + local system=$(find . -name system.img) + mkdir -p $dest/{bin,lib,lib64} + + # Extract android linker and libraries to /system + # This allows android executables to be run directly (or with qemu) + if [ $arch = "x86_64" -o $arch = "arm64" ]; then + e2cp -p $system:/bin/linker64 $dest/bin/ + e2cp -p $system:/lib64/libdl.so $dest/lib64/ + e2cp -p $system:/lib64/libc.so $dest/lib64/ + e2cp -p $system:/lib64/libm.so $dest/lib64/ + else + e2cp -p $system:/bin/linker $dest/bin/ + e2cp -p $system:/lib/libdl.so $dest/lib/ + e2cp -p $system:/lib/libc.so $dest/lib/ + e2cp -p $system:/lib/libm.so $dest/lib/ + fi + + # clean up + apt-get purge --auto-remove -y e2tools + + popd + + rm -rf $td +} + +main "${@}" diff --git a/src/liblibc/ci/docker/x86_64-linux-android/Dockerfile b/src/liblibc/ci/docker/x86_64-linux-android/Dockerfile index bf4793e060..dfc0c83dae 100644 --- a/src/liblibc/ci/docker/x86_64-linux-android/Dockerfile +++ b/src/liblibc/ci/docker/x86_64-linux-android/Dockerfile @@ -1,32 +1,26 @@ FROM ubuntu:16.04 -RUN dpkg --add-architecture i386 && \ - apt-get update && \ +RUN apt-get update && \ apt-get install -y --no-install-recommends \ - file \ - curl \ ca-certificates \ - python \ - unzip \ - expect \ - openjdk-9-jre \ - libstdc++6:i386 \ - libpulse0 \ + curl \ gcc \ - libc6-dev + libc-dev \ + python \ + unzip WORKDIR /android/ -COPY android* /android/ - ENV ANDROID_ARCH=x86_64 -ENV PATH=$PATH:/android/ndk-$ANDROID_ARCH/bin:/android/sdk/tools:/android/sdk/platform-tools - +COPY android-install-ndk.sh /android/ RUN sh /android/android-install-ndk.sh $ANDROID_ARCH -RUN sh /android/android-install-sdk.sh $ANDROID_ARCH -RUN mv /root/.android /tmp -RUN chmod 777 -R /tmp/.android -RUN chmod 755 /android/sdk/tools/* /android/sdk/tools/qemu/linux-x86_64/* -ENV PATH=$PATH:/rust/bin \ +# We do not run x86_64-linux-android tests on an android emulator. +# See ci/android-sysimage.sh for informations about how tests are run. +COPY android-sysimage.sh /android/ +RUN bash /android/android-sysimage.sh x86_64 x86_64-21_r04.zip + +ENV PATH=$PATH:/rust/bin:/android/ndk-$ANDROID_ARCH/bin \ CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER=x86_64-linux-android-gcc \ + CC_x86_64_linux_android=x86_64-linux-android-gcc \ + CXX_x86_64_linux_android=x86_64-linux-android-g++ \ HOME=/tmp diff --git a/src/liblibc/ci/run.sh b/src/liblibc/ci/run.sh index 4b8825f8df..3ddc7b3954 100755 --- a/src/liblibc/ci/run.sh +++ b/src/liblibc/ci/run.sh @@ -105,7 +105,10 @@ case "$TARGET" in esac case "$TARGET" in - arm-linux-androideabi | aarch64-linux-android | i686-linux-android | x86_64-linux-android) + # Android emulator for x86_64 does not work on travis (missing hardware + # acceleration). Tests are run on case *). See ci/android-sysimage.sh for + # informations about how tests are run. + arm-linux-androideabi | aarch64-linux-android | i686-linux-android) # set SHELL so android can detect a 64bits system, see # http://stackoverflow.com/a/41789144 # https://issues.jenkins-ci.org/browse/JENKINS-26930?focusedCommentId=230791&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-230791 diff --git a/src/liblibc/libc-test/build.rs b/src/liblibc/libc-test/build.rs index 1221c752a0..d573baaf90 100644 --- a/src/liblibc/libc-test/build.rs +++ b/src/liblibc/libc-test/build.rs @@ -14,6 +14,7 @@ fn main() { let android = target.contains("android"); let apple = target.contains("apple"); let musl = target.contains("musl"); + let uclibc = target.contains("uclibc"); let freebsd = target.contains("freebsd"); let dragonfly = target.contains("dragonfly"); let mips = target.contains("mips"); @@ -104,6 +105,7 @@ fn main() { cfg.header("syslog.h"); cfg.header("semaphore.h"); cfg.header("sys/statvfs.h"); + cfg.header("sys/times.h"); } if android { @@ -126,8 +128,10 @@ fn main() { if !musl { cfg.header("sys/sysctl.h"); + } + if !musl && !uclibc { - if !netbsd && !openbsd { + if !netbsd && !openbsd && !uclibc { cfg.header("execinfo.h"); cfg.header("xlocale.h"); } @@ -145,6 +149,7 @@ fn main() { cfg.header("mach/mach_time.h"); cfg.header("malloc/malloc.h"); cfg.header("util.h"); + cfg.header("sys/xattr.h"); if target.starts_with("x86") { cfg.header("crt_externs.h"); } @@ -164,13 +169,21 @@ fn main() { cfg.header("mqueue.h"); cfg.header("ucontext.h"); cfg.header("sys/signalfd.h"); - cfg.header("sys/xattr.h"); + if !uclibc { + // optionally included in uclibc + cfg.header("sys/xattr.h"); + } cfg.header("sys/ipc.h"); + cfg.header("sys/sem.h"); cfg.header("sys/msg.h"); cfg.header("sys/shm.h"); + cfg.header("sys/user.h"); cfg.header("sys/fsuid.h"); cfg.header("pty.h"); cfg.header("shadow.h"); + if x86_64 { + cfg.header("sys/io.h"); + } } if linux || android { @@ -184,7 +197,11 @@ fn main() { cfg.header("sys/sendfile.h"); cfg.header("sys/vfs.h"); cfg.header("sys/syscall.h"); - cfg.header("sys/sysinfo.h"); + cfg.header("sys/personality.h"); + cfg.header("sys/swap.h"); + if !uclibc { + cfg.header("sys/sysinfo.h"); + } cfg.header("sys/reboot.h"); if !musl { cfg.header("linux/netlink.h"); @@ -226,7 +243,9 @@ fn main() { } if linux || freebsd || dragonfly || netbsd || apple { - cfg.header("aio.h"); + if !uclibc { + cfg.header("aio.h"); + } } cfg.type_name(move |ty, is_struct| { @@ -388,6 +407,15 @@ fn main() { "KERN_KDENABLE_BG_TRACE" if apple => true, "KERN_KDDISABLE_BG_TRACE" if apple => true, + // These are either unimplemented or optionally built into uClibc + "LC_CTYPE_MASK" | "LC_NUMERIC_MASK" | "LC_TIME_MASK" | "LC_COLLATE_MASK" | "LC_MONETARY_MASK" | "LC_MESSAGES_MASK" | + "MADV_MERGEABLE" | "MADV_UNMERGEABLE" | "MADV_HWPOISON" | "IPV6_ADD_MEMBERSHIP" | "IPV6_DROP_MEMBERSHIP" | "IPV6_MULTICAST_LOOP" | "IPV6_V6ONLY" | + "MAP_STACK" | "RTLD_DEEPBIND" | "SOL_IPV6" | "SOL_ICMPV6" if uclibc => true, + + // Defined by libattr not libc on linux (hard to test). + // See constant definition for more details. + "ENOATTR" if linux => true, + _ => false, } }); @@ -474,6 +502,17 @@ fn main() { // it's in a header file? "endpwent" if android => true, + + // These are either unimplemented or optionally built into uClibc + // or "sysinfo", where it's defined but the structs in linux/sysinfo.h and sys/sysinfo.h + // clash so it can't be tested + "getxattr" | "lgetxattr" | "fgetxattr" | "setxattr" | "lsetxattr" | "fsetxattr" | + "listxattr" | "llistxattr" | "flistxattr" | "removexattr" | "lremovexattr" | + "fremovexattr" | + "backtrace" | + "sysinfo" | "newlocale" | "duplocale" | "freelocale" | "uselocale" | + "nl_langinfo_l" | "wcslen" | "wcstombs" if uclibc => true, + // Apparently res_init exists on Android, but isn't defined in a header: // https://mail.gnome.org/archives/commits-list/2013-May/msg01329.html "res_init" if android => true, @@ -484,6 +523,9 @@ fn main() { // https://github.com/rust-lang/libc/pull/585#discussion_r114561460 "res_init" if apple => true, + // On Mac we don't use the default `close()`, instead using their $NOCANCEL variants. + "close" if apple => true, + _ => false, } }); diff --git a/src/liblibc/src/dox.rs b/src/liblibc/src/dox.rs index fbec3f2d4e..41aac385f4 100644 --- a/src/liblibc/src/dox.rs +++ b/src/liblibc/src/dox.rs @@ -26,6 +26,9 @@ mod imp { #[lang = "copy"] pub trait Copy {} + #[lang = "freeze"] + pub trait Freeze {} + #[lang = "sync"] pub trait Sync {} impl Sync for T {} diff --git a/src/liblibc/src/unix/bsd/apple/mod.rs b/src/liblibc/src/unix/bsd/apple/mod.rs index 6652bb8c09..148188b107 100644 --- a/src/liblibc/src/unix/bsd/apple/mod.rs +++ b/src/liblibc/src/unix/bsd/apple/mod.rs @@ -1516,6 +1516,13 @@ pub const P_ALL: idtype_t = 0; pub const P_PID: idtype_t = 1; pub const P_PGID: idtype_t = 2; +pub const XATTR_NOFOLLOW: ::c_int = 0x0001; +pub const XATTR_CREATE: ::c_int = 0x0002; +pub const XATTR_REPLACE: ::c_int = 0x0004; +pub const XATTR_NOSECURITY: ::c_int = 0x0008; +pub const XATTR_NODEFAULT: ::c_int = 0x0010; +pub const XATTR_SHOWCOMPRESSION: ::c_int = 0x0020; + f! { pub fn WSTOPSIG(status: ::c_int) -> ::c_int { status >> 8 @@ -1552,6 +1559,8 @@ extern { pub fn lio_listio(mode: ::c_int, aiocb_list: *const *mut aiocb, nitems: ::c_int, sevp: *mut sigevent) -> ::c_int; + pub fn dirfd(dirp: *mut ::DIR) -> ::c_int; + pub fn lutimes(file: *const ::c_char, times: *const ::timeval) -> ::c_int; pub fn getutxent() -> *mut utmpx; @@ -1665,13 +1674,36 @@ extern { pub fn getpriority(which: ::c_int, who: ::id_t) -> ::c_int; pub fn setpriority(which: ::c_int, who: ::id_t, prio: ::c_int) -> ::c_int; + pub fn getxattr(path: *const ::c_char, name: *const ::c_char, + value: *mut ::c_void, size: ::size_t, position: u32, + flags: ::c_int) -> ::ssize_t; + pub fn fgetxattr(filedes: ::c_int, name: *const ::c_char, + value: *mut ::c_void, size: ::size_t, position: u32, + flags: ::c_int) -> ::ssize_t; + pub fn setxattr(path: *const ::c_char, name: *const ::c_char, + value: *const ::c_void, size: ::size_t, position: u32, + flags: ::c_int) -> ::c_int; + pub fn fsetxattr(filedes: ::c_int, name: *const ::c_char, + value: *const ::c_void, size: ::size_t, position: u32, + flags: ::c_int) -> ::c_int; + pub fn listxattr(path: *const ::c_char, list: *mut ::c_char, + size: ::size_t, flags: ::c_int) -> ::ssize_t; + pub fn flistxattr(filedes: ::c_int, list: *mut ::c_char, + size: ::size_t, flags: ::c_int) -> ::ssize_t; + pub fn removexattr(path: *const ::c_char, name: *const ::c_char, + flags: ::c_int) -> ::c_int; + pub fn fremovexattr(filedes: ::c_int, name: *const ::c_char, + flags: ::c_int) -> ::c_int; + pub fn initgroups(user: *const ::c_char, basegroup: ::c_int) -> ::c_int; #[cfg_attr(all(target_os = "macos", target_arch = "x86"), link_name = "waitid$UNIX2003")] pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t, options: ::c_int) -> ::c_int; - + pub fn brk(addr: *const ::c_void) -> *mut ::c_void; + pub fn sbrk(increment: ::c_int) -> *mut ::c_void; + pub fn settimeofday(tv: *const ::timeval, tz: *const ::timezone) -> ::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 5cfa3b1143..4e635ffbfd 100644 --- a/src/liblibc/src/unix/bsd/freebsdlike/mod.rs +++ b/src/liblibc/src/unix/bsd/freebsdlike/mod.rs @@ -876,6 +876,8 @@ pub const SEM_FAILED: *mut sem_t = 0 as *mut sem_t; pub const CRTSCTS: ::tcflag_t = 0x00030000; +pub const AT_FDCWD: ::c_int = -100; + f! { pub fn WIFCONTINUED(status: ::c_int) -> bool { status == 0x13 @@ -916,6 +918,7 @@ 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 dirfd(dirp: *mut ::DIR) -> ::c_int; pub fn getnameinfo(sa: *const ::sockaddr, salen: ::socklen_t, host: *mut ::c_char, @@ -1026,6 +1029,7 @@ extern { nfds: ::nfds_t, timeout: *const ::timespec, sigmask: *const sigset_t) -> ::c_int; + pub fn settimeofday(tv: *const ::timeval, tz: *const ::timezone) -> ::c_int; } cfg_if! { diff --git a/src/liblibc/src/unix/bsd/mod.rs b/src/liblibc/src/unix/bsd/mod.rs index 96b0f22a10..deddca042d 100644 --- a/src/liblibc/src/unix/bsd/mod.rs +++ b/src/liblibc/src/unix/bsd/mod.rs @@ -432,6 +432,8 @@ extern { link_name = "recvmsg$UNIX2003")] pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int) -> ::ssize_t; + + pub fn sync(); } cfg_if! { diff --git a/src/liblibc/src/unix/bsd/netbsdlike/netbsd/mod.rs b/src/liblibc/src/unix/bsd/netbsdlike/netbsd/mod.rs index ffe8d75cb8..a02616792b 100644 --- a/src/liblibc/src/unix/bsd/netbsdlike/netbsd/mod.rs +++ b/src/liblibc/src/unix/bsd/netbsdlike/netbsd/mod.rs @@ -644,6 +644,15 @@ pub const P_PGID: idtype_t = 4; pub const B460800: ::speed_t = 460800; pub const B921600: ::speed_t = 921600; +// dirfd() is a macro on netbsd to access +// the first field of the struct where dirp points to: +// http://cvsweb.netbsd.org/bsdweb.cgi/src/include/dirent.h?rev=1.36 +f! { + pub fn dirfd(dirp: *mut ::DIR) -> ::c_int { + unsafe { *(dirp as *const ::c_int) } + } +} + extern { pub fn aio_read(aiocbp: *mut aiocb) -> ::c_int; pub fn aio_write(aiocbp: *mut aiocb) -> ::c_int; @@ -719,6 +728,8 @@ extern { pub fn newlocale(mask: ::c_int, locale: *const ::c_char, base: ::locale_t) -> ::locale_t; + #[link_name = "__settimeofday50"] + pub fn settimeofday(tv: *const ::timeval, tz: *const ::c_void) -> ::c_int; } mod other; diff --git a/src/liblibc/src/unix/bsd/netbsdlike/openbsdlike/mod.rs b/src/liblibc/src/unix/bsd/netbsdlike/openbsdlike/mod.rs index b0d8128c03..76e458c475 100644 --- a/src/liblibc/src/unix/bsd/netbsdlike/openbsdlike/mod.rs +++ b/src/liblibc/src/unix/bsd/netbsdlike/openbsdlike/mod.rs @@ -457,6 +457,7 @@ pub const KI_MAXLOGNAME: ::c_int = 32; pub const KI_EMULNAMELEN: ::c_int = 8; extern { + pub fn dirfd(dirp: *mut ::DIR) -> ::c_int; pub fn getnameinfo(sa: *const ::sockaddr, salen: ::socklen_t, host: *mut ::c_char, diff --git a/src/liblibc/src/unix/haiku/mod.rs b/src/liblibc/src/unix/haiku/mod.rs index 829c2258bf..e90aa306fd 100644 --- a/src/liblibc/src/unix/haiku/mod.rs +++ b/src/liblibc/src/unix/haiku/mod.rs @@ -749,6 +749,7 @@ extern { pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int; pub fn mprotect(addr: *const ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; + pub fn dirfd(dirp: *mut ::DIR) -> ::c_int; pub fn getnameinfo(sa: *const ::sockaddr, salen: ::socklen_t, host: *mut ::c_char, diff --git a/src/liblibc/src/unix/mod.rs b/src/liblibc/src/unix/mod.rs index a235d6a422..14bf9c5393 100644 --- a/src/liblibc/src/unix/mod.rs +++ b/src/liblibc/src/unix/mod.rs @@ -124,6 +124,20 @@ s! { // Actually a union of an int and a void* pub sival_ptr: *mut ::c_void } + + // + pub struct itimerval { + pub it_interval: ::timeval, + pub it_value: ::timeval, + } + + // + pub struct tms { + pub tms_utime: ::clock_t, + pub tms_stime: ::clock_t, + pub tms_cutime: ::clock_t, + pub tms_cstime: ::clock_t, + } } pub const SIG_DFL: sighandler_t = 0 as sighandler_t; @@ -405,7 +419,9 @@ extern { pub fn lchown(path: *const c_char, uid: uid_t, gid: gid_t) -> ::c_int; #[cfg_attr(all(target_os = "macos", target_arch = "x86"), - link_name = "close$UNIX2003")] + link_name = "close$NOCANCEL$UNIX2003")] + #[cfg_attr(all(target_os = "macos", target_arch = "x86_64"), + link_name = "close$NOCANCEL")] 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; @@ -456,6 +472,7 @@ extern { pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::size_t) -> ::ssize_t; pub fn rmdir(path: *const c_char) -> ::c_int; + pub fn seteuid(uid: uid_t) -> ::c_int; pub fn setgid(gid: gid_t) -> ::c_int; pub fn setpgid(pid: pid_t, pgid: pid_t) -> ::c_int; pub fn setsid() -> pid_t; @@ -566,6 +583,8 @@ extern { #[cfg_attr(target_os = "netbsd", link_name = "__gettimeofday50")] pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int; + #[cfg_attr(target_os = "netbsd", link_name = "__times13")] + pub fn times(buf: *mut ::tms) -> ::clock_t; pub fn pthread_self() -> ::pthread_t; pub fn pthread_create(native: *mut ::pthread_t, @@ -713,8 +732,10 @@ extern { pub fn mktime(tm: *mut tm) -> time_t; #[cfg_attr(target_os = "netbsd", link_name = "__time50")] pub fn time(time: *mut time_t) -> time_t; + #[cfg_attr(target_os = "netbsd", link_name = "__gmtime50")] + pub fn gmtime(time_p: *const time_t) -> *mut tm; #[cfg_attr(target_os = "netbsd", link_name = "__locatime50")] - pub fn localtime(time: *const time_t) -> *mut tm; + pub fn localtime(time_p: *const time_t) -> *mut tm; #[cfg_attr(target_os = "netbsd", link_name = "__mknod50")] pub fn mknod(pathname: *const ::c_char, mode: ::mode_t, @@ -793,6 +814,8 @@ extern { set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; + #[cfg_attr(target_os = "netbsd", link_name = "__sigpending14")] + pub fn sigpending(set: *mut sigset_t) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__timegm50")] pub fn timegm(tm: *mut ::tm) -> time_t; @@ -854,10 +877,13 @@ extern { } cfg_if! { - if #[cfg(any(target_os = "linux", - target_os = "android", - target_os = "emscripten", - target_os = "fuchsia"))] { + if #[cfg(target_env = "uclibc")] { + mod uclibc; + pub use self::uclibc::*; + } else if #[cfg(any(target_os = "linux", + target_os = "android", + target_os = "emscripten", + target_os = "fuchsia"))] { mod notbsd; pub use self::notbsd::*; } else if #[cfg(any(target_os = "macos", diff --git a/src/liblibc/src/unix/notbsd/android/mod.rs b/src/liblibc/src/unix/notbsd/android/mod.rs index 547d8327db..2a7d572dc5 100644 --- a/src/liblibc/src/unix/notbsd/android/mod.rs +++ b/src/liblibc/src/unix/notbsd/android/mod.rs @@ -172,6 +172,7 @@ pub const SA_RESTART: ::c_int = 0x10000000; pub const SA_NOCLDSTOP: ::c_int = 0x00000001; pub const EPOLL_CLOEXEC: ::c_int = 0x80000; +pub const EPOLLONESHOT: ::c_int = 0x40000000; pub const EFD_CLOEXEC: ::c_int = 0x80000; diff --git a/src/liblibc/src/unix/notbsd/linux/mips/mips32.rs b/src/liblibc/src/unix/notbsd/linux/mips/mips32.rs index 042495e70e..59c2486efe 100644 --- a/src/liblibc/src/unix/notbsd/linux/mips/mips32.rs +++ b/src/liblibc/src/unix/notbsd/linux/mips/mips32.rs @@ -10,9 +10,6 @@ pub type ino_t = u32; pub type blkcnt_t = i32; pub type blksize_t = i32; pub type nlink_t = u32; -pub type fsblkcnt_t = ::c_ulong; -pub type fsfilcnt_t = ::c_ulong; -pub type rlim_t = c_ulong; s! { pub struct aiocb { @@ -107,19 +104,6 @@ s! { pub _pad: [::c_int; 29], } - pub struct glob64_t { - pub gl_pathc: ::size_t, - pub gl_pathv: *mut *mut ::c_char, - pub gl_offs: ::size_t, - pub gl_flags: ::c_int, - - __unused1: *mut ::c_void, - __unused2: *mut ::c_void, - __unused3: *mut ::c_void, - __unused4: *mut ::c_void, - __unused5: *mut ::c_void, - } - pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, @@ -238,15 +222,6 @@ s! { pub mem_unit: ::c_uint, pub _f: [::c_char; 8], } - - // FIXME this is actually a union - pub struct sem_t { - #[cfg(target_pointer_width = "32")] - __size: [::c_char; 16], - #[cfg(target_pointer_width = "64")] - __size: [::c_char; 32], - __align: [::c_long; 0], - } } pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; @@ -257,31 +232,3 @@ pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const RLIM_INFINITY: ::rlim_t = 0x7fffffff; pub const SYS_gettid: ::c_long = 4222; // Valid for O32 - -#[link(name = "util")] -extern { - pub fn sysctl(name: *mut ::c_int, - namelen: ::c_int, - oldp: *mut ::c_void, - oldlenp: *mut ::size_t, - newp: *mut ::c_void, - newlen: ::size_t) - -> ::c_int; - pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int; - pub fn backtrace(buf: *mut *mut ::c_void, - sz: ::c_int) -> ::c_int; - pub fn glob64(pattern: *const ::c_char, - flags: ::c_int, - errfunc: ::dox::Option ::c_int>, - pglob: *mut glob64_t) -> ::c_int; - pub fn globfree64(pglob: *mut glob64_t); - pub fn ptrace(request: ::c_uint, ...) -> ::c_long; - pub fn pthread_attr_getaffinity_np(attr: *const ::pthread_attr_t, - cpusetsize: ::size_t, - cpuset: *mut ::cpu_set_t) -> ::c_int; - pub fn pthread_attr_setaffinity_np(attr: *mut ::pthread_attr_t, - cpusetsize: ::size_t, - cpuset: *const ::cpu_set_t) -> ::c_int; -} diff --git a/src/liblibc/src/unix/notbsd/linux/mips/mips64.rs b/src/liblibc/src/unix/notbsd/linux/mips/mips64.rs index 5b0484a39f..1f28ea81f0 100644 --- a/src/liblibc/src/unix/notbsd/linux/mips/mips64.rs +++ b/src/liblibc/src/unix/notbsd/linux/mips/mips64.rs @@ -3,15 +3,13 @@ pub type blksize_t = i64; pub type c_char = i8; pub type c_long = i64; pub type c_ulong = u64; -pub type fsblkcnt_t = ::c_ulong; -pub type fsfilcnt_t = ::c_ulong; pub type ino_t = u64; pub type nlink_t = u64; pub type off_t = i64; -pub type rlim_t = ::c_ulong; pub type suseconds_t = i64; pub type time_t = i64; pub type wchar_t = i32; +pub type clock_t = i64; s! { pub struct aiocb { @@ -186,6 +184,14 @@ s! { pub c_cc: [::cc_t; ::NCCS], } + pub struct flock { + pub l_type: ::c_short, + pub l_whence: ::c_short, + pub l_start: ::off_t, + pub l_len: ::off_t, + pub l_pid: ::pid_t, + } + pub struct sysinfo { pub uptime: ::c_long, pub loads: [::c_ulong; 3], @@ -202,12 +208,6 @@ s! { pub mem_unit: ::c_uint, pub _f: [::c_char; 0], } - - // FIXME this is actually a union - pub struct sem_t { - __size: [::c_char; 32], - __align: [::c_long; 0], - } } pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; @@ -218,8 +218,3 @@ pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const RLIM_INFINITY: ::rlim_t = 0xffff_ffff_ffff_ffff; pub const SYS_gettid: ::c_long = 5178; // Valid for n64 - -#[link(name = "util")] -extern { - pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int; -} diff --git a/src/liblibc/src/unix/notbsd/linux/mips/mod.rs b/src/liblibc/src/unix/notbsd/linux/mips/mod.rs index 7b1c15e2fd..b2ad107cae 100644 --- a/src/liblibc/src/unix/notbsd/linux/mips/mod.rs +++ b/src/liblibc/src/unix/notbsd/linux/mips/mod.rs @@ -1,3 +1,32 @@ +pub type fsblkcnt_t = ::c_ulong; +pub type fsfilcnt_t = ::c_ulong; +pub type rlim_t = c_ulong; +pub type __priority_which_t = ::c_uint; + +s! { + pub struct glob64_t { + pub gl_pathc: ::size_t, + pub gl_pathv: *mut *mut ::c_char, + pub gl_offs: ::size_t, + pub gl_flags: ::c_int, + + __unused1: *mut ::c_void, + __unused2: *mut ::c_void, + __unused3: *mut ::c_void, + __unused4: *mut ::c_void, + __unused5: *mut ::c_void, + } + + // FIXME this is actually a union + pub struct sem_t { + #[cfg(target_pointer_width = "32")] + __size: [::c_char; 16], + #[cfg(target_pointer_width = "64")] + __size: [::c_char; 32], + __align: [::c_long; 0], + } +} + pub const CLONE_NEWCGROUP: ::c_int = 0x02000000; pub const SFD_CLOEXEC: ::c_int = 0x080000; @@ -496,6 +525,44 @@ pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; +#[link(name = "util")] +extern { + pub fn sysctl(name: *mut ::c_int, + namelen: ::c_int, + oldp: *mut ::c_void, + oldlenp: *mut ::size_t, + newp: *mut ::c_void, + newlen: ::size_t) + -> ::c_int; + pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int; + pub fn backtrace(buf: *mut *mut ::c_void, + sz: ::c_int) -> ::c_int; + pub fn glob64(pattern: *const ::c_char, + flags: ::c_int, + errfunc: ::dox::Option ::c_int>, + pglob: *mut glob64_t) -> ::c_int; + pub fn globfree64(pglob: *mut glob64_t); + pub fn ptrace(request: ::c_uint, ...) -> ::c_long; + pub fn pthread_attr_getaffinity_np(attr: *const ::pthread_attr_t, + cpusetsize: ::size_t, + cpuset: *mut ::cpu_set_t) -> ::c_int; + pub fn pthread_attr_setaffinity_np(attr: *mut ::pthread_attr_t, + cpusetsize: ::size_t, + cpuset: *const ::cpu_set_t) -> ::c_int; + pub fn getpriority(which: ::__priority_which_t, who: ::id_t) -> ::c_int; + pub fn setpriority(which: ::__priority_which_t, who: ::id_t, + prio: ::c_int) -> ::c_int; + pub fn pthread_getaffinity_np(thread: ::pthread_t, + cpusetsize: ::size_t, + cpuset: *mut ::cpu_set_t) -> ::c_int; + pub fn pthread_setaffinity_np(thread: ::pthread_t, + cpusetsize: ::size_t, + cpuset: *const ::cpu_set_t) -> ::c_int; + pub fn sched_getcpu() -> ::c_int; +} + cfg_if! { if #[cfg(target_arch = "mips")] { mod mips32; diff --git a/src/liblibc/src/unix/notbsd/linux/mod.rs b/src/liblibc/src/unix/notbsd/linux/mod.rs index 3827207891..7404f2ce43 100644 --- a/src/liblibc/src/unix/notbsd/linux/mod.rs +++ b/src/liblibc/src/unix/notbsd/linux/mod.rs @@ -225,6 +225,12 @@ s! { pub msg_hdr: ::msghdr, pub msg_len: ::c_uint, } + + pub struct sembuf { + pub sem_num: ::c_ushort, + pub sem_op: ::c_short, + pub sem_flg: ::c_short, + } } pub const ABDAY_1: ::nl_item = 0x20000; @@ -378,6 +384,7 @@ pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 78; pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 79; pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 80; pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 81; +pub const _SC_NPROCESSORS_CONF: ::c_int = 83; pub const _SC_NPROCESSORS_ONLN: ::c_int = 84; pub const _SC_ATEXIT_MAX: ::c_int = 87; pub const _SC_XOPEN_VERSION: ::c_int = 89; @@ -697,6 +704,18 @@ 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; +pub const ITIMER_REAL: ::c_int = 0; +pub const ITIMER_VIRTUAL: ::c_int = 1; +pub const ITIMER_PROF: ::c_int = 2; + +pub const XATTR_CREATE: ::c_int = 0x1; +pub const XATTR_REPLACE: ::c_int = 0x2; + +// On Linux, libc doesn't define this constant, libattr does instead. +// We still define it for Linux as it's defined by libc on other platforms, +// and it's mentioned in the man pages for getxattr and setxattr. +pub const ENOATTR: ::c_int = ::ENODATA; + f! { pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.bits.iter_mut() { @@ -788,6 +807,11 @@ extern { cmd: ::c_int, buf: *mut ::shmid_ds) -> ::c_int; pub fn ftok(pathname: *const ::c_char, proj_id: ::c_int) -> ::key_t; + pub fn semget(key: ::key_t, nsems: ::c_int, semflag: ::c_int) -> ::c_int; + pub fn semop(semid: ::c_int, + sops: *mut ::sembuf, nsops: ::size_t) -> ::c_int; + pub fn semctl(semid: ::c_int, + semnum: ::c_int, cmd: ::c_int, ...) -> ::c_int; pub fn msgctl(msqid: ::c_int, cmd: ::c_int, buf: *mut msqid_ds) -> ::c_int; pub fn msgget(key: ::key_t, msgflg: ::c_int) -> ::c_int; pub fn msgrcv(msqid: ::c_int, msgp: *mut ::c_void, msgsz: ::size_t, @@ -903,6 +927,8 @@ extern { serv: *mut ::c_char, sevlen: ::socklen_t, flags: ::c_int) -> ::c_int; + pub fn pthread_setschedprio(native: ::pthread_t, + priority: ::c_int) -> ::c_int; pub fn prlimit(pid: ::pid_t, resource: ::c_int, new_limit: *const ::rlimit, old_limit: *mut ::rlimit) -> ::c_int; pub fn prlimit64(pid: ::pid_t, @@ -986,6 +1012,9 @@ extern { flags: ::c_int) -> ::ssize_t; pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int) -> ::ssize_t; + pub fn getdomainname(name: *mut ::c_char, len: ::size_t) -> ::c_int; + pub fn setdomainname(name: *const ::c_char, len: ::size_t) -> ::c_int; + pub fn vhangup() -> ::c_int; } extern { @@ -993,6 +1022,7 @@ extern { flags: ::c_int) -> ::c_int; pub fn recvmmsg(sockfd: ::c_int, msgvec: *mut mmsghdr, vlen: ::c_uint, flags: ::c_int, timeout: *mut ::timespec) -> ::c_int; + pub fn sync(); } cfg_if! { diff --git a/src/liblibc/src/unix/notbsd/linux/other/b32/x86.rs b/src/liblibc/src/unix/notbsd/linux/other/b32/x86.rs index 263e1406b7..04a3caad12 100644 --- a/src/liblibc/src/unix/notbsd/linux/other/b32/x86.rs +++ b/src/liblibc/src/unix/notbsd/linux/other/b32/x86.rs @@ -20,6 +20,71 @@ s! { pub status: ::c_ulong, } + pub struct user_fpregs_struct { + pub cwd: ::c_long, + pub swd: ::c_long, + pub twd: ::c_long, + pub fip: ::c_long, + pub fcs: ::c_long, + pub foo: ::c_long, + pub fos: ::c_long, + pub st_space: [::c_long; 20], + } + + pub struct user_fpxregs_struct { + pub cwd: ::c_ushort, + pub swd: ::c_ushort, + pub twd: ::c_ushort, + pub fop: ::c_ushort, + pub fip: ::c_long, + pub fcs: ::c_long, + pub foo: ::c_long, + pub fos: ::c_long, + pub mxcsr: ::c_long, + __reserved: ::c_long, + pub st_space: [::c_long; 32], + pub xmm_space: [::c_long; 32], + padding: [::c_long; 56], + } + + pub struct user_regs_struct { + pub ebx: ::c_long, + pub ecx: ::c_long, + pub edx: ::c_long, + pub esi: ::c_long, + pub edi: ::c_long, + pub ebp: ::c_long, + pub eax: ::c_long, + pub xds: ::c_long, + pub xes: ::c_long, + pub xfs: ::c_long, + pub xgs: ::c_long, + pub orig_eax: ::c_long, + pub eip: ::c_long, + pub xcs: ::c_long, + pub eflags: ::c_long, + pub esp: ::c_long, + pub xss: ::c_long, + } + + pub struct user { + pub regs: user_regs_struct, + pub u_fpvalid: ::c_int, + pub i387: user_fpregs_struct, + pub u_tsize: ::c_ulong, + pub u_dsize: ::c_ulong, + pub u_ssize: ::c_ulong, + pub start_code: ::c_ulong, + pub start_stack: ::c_ulong, + pub signal: ::c_long, + __reserved: ::c_int, + pub u_ar0: *mut user_regs_struct, + pub u_fpstate: *mut user_fpregs_struct, + pub magic: ::c_ulong, + pub u_comm: [c_char; 32], + pub u_debugreg: [::c_int; 8], + } + pub struct mcontext_t { pub gregs: [greg_t; 19], pub fpregs: *mut _libc_fpstate, 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 b39ccb3916..e1b65e8e71 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 @@ -78,6 +78,68 @@ s! { __private: [u64; 12], } + pub struct user_fpregs_struct { + pub cwd: ::c_ushort, + pub swd: ::c_ushort, + pub ftw: ::c_ushort, + pub fop: ::c_ushort, + pub rip: ::c_ulonglong, + pub rdp: ::c_ulonglong, + pub mxcsr: ::c_uint, + pub mxcr_mask: ::c_uint, + pub st_space: [::c_uint; 32], + pub xmm_space: [::c_uint; 64], + padding: [::c_uint; 24], + } + + pub struct user_regs_struct { + pub r15: ::c_ulonglong, + pub r14: ::c_ulonglong, + pub r13: ::c_ulonglong, + pub r12: ::c_ulonglong, + pub rbp: ::c_ulonglong, + pub rbx: ::c_ulonglong, + pub r11: ::c_ulonglong, + pub r10: ::c_ulonglong, + pub r9: ::c_ulonglong, + pub r8: ::c_ulonglong, + pub rax: ::c_ulonglong, + pub rcx: ::c_ulonglong, + pub rdx: ::c_ulonglong, + pub rsi: ::c_ulonglong, + pub rdi: ::c_ulonglong, + pub orig_rax: ::c_ulonglong, + pub rip: ::c_ulonglong, + pub cs: ::c_ulonglong, + pub eflags: ::c_ulonglong, + pub rsp: ::c_ulonglong, + pub ss: ::c_ulonglong, + pub fs_base: ::c_ulonglong, + pub gs_base: ::c_ulonglong, + pub ds: ::c_ulonglong, + pub es: ::c_ulonglong, + pub fs: ::c_ulonglong, + pub gs: ::c_ulonglong, + } + + pub struct user { + pub regs: user_regs_struct, + pub u_fpvalid: ::c_int, + pub i387: user_fpregs_struct, + pub u_tsize: ::c_ulonglong, + pub u_dsize: ::c_ulonglong, + pub u_ssize: ::c_ulonglong, + pub start_code: ::c_ulonglong, + pub start_stack: ::c_ulonglong, + pub signal: ::c_longlong, + __reserved: ::c_int, + pub u_ar0: *mut user_regs_struct, + pub u_fpstate: *mut user_fpregs_struct, + pub magic: ::c_ulonglong, + pub u_comm: [::c_char; 32], + pub u_debugreg: [::c_ulonglong; 8], + } + pub struct mcontext_t { pub gregs: [greg_t; 23], pub fpregs: *mut _libc_fpstate, @@ -512,4 +574,7 @@ extern { argc: ::c_int, ...); pub fn swapcontext(uocp: *mut ucontext_t, ucp: *const ucontext_t) -> ::c_int; + pub fn iopl(level: ::c_int) -> ::c_int; + pub fn ioperm(from: ::c_ulong, num: ::c_ulong, + turn_on: ::c_int) -> ::c_int; } diff --git a/src/liblibc/src/unix/notbsd/mod.rs b/src/liblibc/src/unix/notbsd/mod.rs index b20d043d7a..e10d28b304 100644 --- a/src/liblibc/src/unix/notbsd/mod.rs +++ b/src/liblibc/src/unix/notbsd/mod.rs @@ -835,6 +835,9 @@ extern { rqtp: *const ::timespec, rmtp: *mut ::timespec) -> ::c_int; pub fn clock_settime(clk_id: clockid_t, tp: *const ::timespec) -> ::c_int; + pub fn dirfd(dirp: *mut ::DIR) -> ::c_int; + pub fn settimeofday(tv: *const ::timeval, tz: *const ::timezone) -> ::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; @@ -853,6 +856,9 @@ extern { pub fn sched_getscheduler(pid: ::pid_t) -> ::c_int; pub fn sched_get_priority_max(policy: ::c_int) -> ::c_int; pub fn sched_get_priority_min(policy: ::c_int) -> ::c_int; + pub fn sched_setparam(pid: ::pid_t, param: *const sched_param) -> ::c_int; + pub fn sched_getparam(pid: ::pid_t, param: *mut sched_param) -> ::c_int; + pub fn sched_rr_get_interval(pid: ::pid_t, tp: *mut ::timespec) -> ::c_int; pub fn epoll_create(size: ::c_int) -> ::c_int; pub fn epoll_create1(flags: ::c_int) -> ::c_int; pub fn epoll_ctl(epfd: ::c_int, @@ -957,6 +963,12 @@ extern { pshared: ::c_int) -> ::c_int; pub fn pthread_condattr_getpshared(attr: *const pthread_condattr_t, pshared: *mut ::c_int) -> ::c_int; + pub fn pthread_getschedparam(native: ::pthread_t, + policy: *mut ::c_int, + param: *mut ::sched_param) -> ::c_int; + pub fn pthread_setschedparam(native: ::pthread_t, + policy: ::c_int, + param: *const ::sched_param) -> ::c_int; pub fn sched_getaffinity(pid: ::pid_t, cpusetsize: ::size_t, cpuset: *mut cpu_set_t) -> ::c_int; @@ -981,6 +993,22 @@ extern { pub fn clearenv() -> ::c_int; pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t, options: ::c_int) -> ::c_int; + pub fn sigsuspend(mask: *const ::sigset_t) -> ::c_int; + pub fn setreuid(ruid: ::uid_t, euid: ::uid_t) -> ::c_int; + pub fn setregid(rgid: ::gid_t, egid: ::gid_t) -> ::c_int; + pub fn getresuid(ruid: *mut ::uid_t, euid: *mut ::uid_t, + suid: *mut ::uid_t) -> ::c_int; + pub fn getresgid(rgid: *mut ::gid_t, egid: *mut ::gid_t, + sgid: *mut ::gid_t) -> ::c_int; + pub fn personality(persona: ::c_ulong) -> ::c_int; + pub fn swapon(path: *const ::c_char, swapflags: ::c_int) -> ::c_int; + pub fn swapoff(puath: *const ::c_char) -> ::c_int; + pub fn acct(filename: *const ::c_char) -> ::c_int; + pub fn brk(addr: *mut ::c_void) -> ::c_int; + pub fn sbrk(increment: ::intptr_t) -> *mut ::c_void; + pub fn vfork() -> ::pid_t; + pub fn wait4(pid: ::pid_t, status: *mut ::c_int, options: ::c_int, + rusage: *mut ::rusage) -> ::pid_t; } cfg_if! { diff --git a/src/liblibc/src/unix/uclibc/mips/mips32.rs b/src/liblibc/src/unix/uclibc/mips/mips32.rs new file mode 100644 index 0000000000..a81e884e0b --- /dev/null +++ b/src/liblibc/src/unix/uclibc/mips/mips32.rs @@ -0,0 +1,269 @@ +pub type c_char = i8; +pub type c_long = i32; +pub type c_ulong = u32; +pub type clock_t = i32; +pub type time_t = i32; +pub type suseconds_t = i32; +pub type wchar_t = i32; +pub type off_t = i32; +pub type ino_t = u32; +pub type blkcnt_t = i32; +pub type blksize_t = i32; +pub type nlink_t = u32; +pub type fsblkcnt_t = ::c_ulong; +pub type fsfilcnt_t = ::c_ulong; +pub type rlim_t = c_ulong; + +s! { + pub struct stat { + pub st_dev: ::dev_t, + st_pad1: [::c_long; 2], + pub st_ino: ::ino_t, + pub st_mode: ::mode_t, + pub st_nlink: ::nlink_t, + pub st_uid: ::uid_t, + pub st_gid: ::gid_t, + pub st_rdev: ::dev_t, + pub st_pad2: [::c_long; 1], + pub st_size: ::off_t, + st_pad3: ::c_long, + pub st_atime: ::time_t, + pub st_atime_nsec: ::c_long, + pub st_mtime: ::time_t, + pub st_mtime_nsec: ::c_long, + pub st_ctime: ::time_t, + pub st_ctime_nsec: ::c_long, + pub st_blksize: ::blksize_t, + pub st_blocks: ::blkcnt_t, + st_pad5: [::c_long; 14], + } + + pub struct stat64 { + pub st_dev: ::dev_t, + st_pad1: [::c_long; 2], + 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, + st_pad2: [::c_long; 2], + pub st_size: ::off64_t, + pub st_atime: ::time_t, + pub st_atime_nsec: ::c_long, + pub st_mtime: ::time_t, + pub st_mtime_nsec: ::c_long, + pub st_ctime: ::time_t, + pub st_ctime_nsec: ::c_long, + pub st_blksize: ::blksize_t, + st_pad3: ::c_long, + pub st_blocks: ::blkcnt64_t, + st_pad5: [::c_long; 14], + } + + pub struct pthread_attr_t { + __size: [u32; 9] + } + + pub struct sigaction { + pub sa_flags: ::c_uint, + pub sa_sigaction: ::sighandler_t, + pub sa_mask: sigset_t, + _restorer: *mut ::c_void, + } + + pub struct stack_t { + pub ss_sp: *mut ::c_void, + pub ss_size: ::size_t, + pub ss_flags: ::c_int, + } + + pub struct sigset_t { + __val: [::c_ulong; 4], + } + + pub struct siginfo_t { + pub si_signo: ::c_int, + pub si_code: ::c_int, + pub si_errno: ::c_int, + pub _pad: [::c_int; 29], + } + + pub struct glob64_t { + pub gl_pathc: ::size_t, + pub gl_pathv: *mut *mut ::c_char, + pub gl_offs: ::size_t, + pub gl_flags: ::c_int, + + __unused1: *mut ::c_void, + __unused2: *mut ::c_void, + __unused3: *mut ::c_void, + __unused4: *mut ::c_void, + __unused5: *mut ::c_void, + } + + 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: ::c_uint, + pub __seq: ::c_ushort, + __pad1: ::c_ushort, + __unused1: ::c_ulong, + __unused2: ::c_ulong + } + + pub struct shmid_ds { + pub shm_perm: ::ipc_perm, + pub shm_segsz: ::size_t, + pub shm_atime: ::time_t, + pub shm_dtime: ::time_t, + pub shm_ctime: ::time_t, + pub shm_cpid: ::pid_t, + pub shm_lpid: ::pid_t, + pub shm_nattch: ::shmatt_t, + __unused4: ::c_ulong, + __unused5: ::c_ulong + } + + pub struct msqid_ds { + pub msg_perm: ::ipc_perm, + #[cfg(target_endian = "big")] + __glibc_reserved1: ::c_ulong, + pub msg_stime: ::time_t, + #[cfg(target_endian = "little")] + __glibc_reserved1: ::c_ulong, + #[cfg(target_endian = "big")] + __glibc_reserved2: ::c_ulong, + pub msg_rtime: ::time_t, + #[cfg(target_endian = "little")] + __glibc_reserved2: ::c_ulong, + #[cfg(target_endian = "big")] + __glibc_reserved3: ::c_ulong, + pub msg_ctime: ::time_t, + #[cfg(target_endian = "little")] + __glibc_reserved3: ::c_ulong, + __msg_cbytes: ::c_ulong, + pub msg_qnum: ::msgqnum_t, + pub msg_qbytes: ::msglen_t, + pub msg_lspid: ::pid_t, + pub msg_lrpid: ::pid_t, + __glibc_reserved4: ::c_ulong, + __glibc_reserved5: ::c_ulong, + } + + pub struct statfs { + pub f_type: ::c_long, + pub f_bsize: ::c_long, + pub f_frsize: ::c_long, + pub f_blocks: ::fsblkcnt_t, + pub f_bfree: ::fsblkcnt_t, + pub f_files: ::fsblkcnt_t, + pub f_ffree: ::fsblkcnt_t, + pub f_bavail: ::fsblkcnt_t, + pub f_fsid: ::fsid_t, + + pub f_namelen: ::c_long, + f_spare: [::c_long; 6], + } + + pub struct msghdr { + pub msg_name: *mut ::c_void, + pub msg_namelen: ::socklen_t, + pub msg_iov: *mut ::iovec, + pub msg_iovlen: ::c_int, + pub msg_control: *mut ::c_void, + pub msg_controllen: ::size_t, + 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, + pub c_cflag: ::tcflag_t, + pub c_lflag: ::tcflag_t, + pub c_line: ::cc_t, + pub c_cc: [::cc_t; ::NCCS], + } + + pub struct flock { + pub l_type: ::c_short, + pub l_whence: ::c_short, + pub l_start: ::off_t, + pub l_len: ::off_t, + pub l_sysid: ::c_long, + pub l_pid: ::pid_t, + pad: [::c_long; 4], + } + + pub struct sysinfo { + pub uptime: ::c_long, + pub loads: [::c_ulong; 3], + pub totalram: ::c_ulong, + pub freeram: ::c_ulong, + pub sharedram: ::c_ulong, + pub bufferram: ::c_ulong, + pub totalswap: ::c_ulong, + pub freeswap: ::c_ulong, + pub procs: ::c_ushort, + pub pad: ::c_ushort, + pub totalhigh: ::c_ulong, + pub freehigh: ::c_ulong, + pub mem_unit: ::c_uint, + pub _f: [::c_char; 8], + } + + // FIXME this is actually a union + pub struct sem_t { + #[cfg(target_pointer_width = "32")] + __size: [::c_char; 16], + #[cfg(target_pointer_width = "64")] + __size: [::c_char; 32], + __align: [::c_long; 0], + } +} + +pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; +pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 24; +pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32; +pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; + +pub const RLIM_INFINITY: ::rlim_t = 0x7fffffff; + +pub const SYS_gettid: ::c_long = 4222; // Valid for O32 + +#[link(name = "util")] +extern { + pub fn sysctl(name: *mut ::c_int, + namelen: ::c_int, + oldp: *mut ::c_void, + oldlenp: *mut ::size_t, + newp: *mut ::c_void, + newlen: ::size_t) + -> ::c_int; + pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int; + pub fn backtrace(buf: *mut *mut ::c_void, + sz: ::c_int) -> ::c_int; + pub fn glob64(pattern: *const ::c_char, + flags: ::c_int, + errfunc: ::dox::Option ::c_int>, + pglob: *mut glob64_t) -> ::c_int; + pub fn globfree64(pglob: *mut glob64_t); + pub fn ptrace(request: ::c_uint, ...) -> ::c_long; + pub fn pthread_attr_getaffinity_np(attr: *const ::pthread_attr_t, + cpusetsize: ::size_t, + cpuset: *mut ::cpu_set_t) -> ::c_int; + pub fn pthread_attr_setaffinity_np(attr: *mut ::pthread_attr_t, + cpusetsize: ::size_t, + cpuset: *const ::cpu_set_t) -> ::c_int; +} diff --git a/src/liblibc/src/unix/uclibc/mips/mips64.rs b/src/liblibc/src/unix/uclibc/mips/mips64.rs new file mode 100644 index 0000000000..79bac1fa8a --- /dev/null +++ b/src/liblibc/src/unix/uclibc/mips/mips64.rs @@ -0,0 +1,209 @@ +pub type blkcnt_t = i64; +pub type blksize_t = i64; +pub type c_char = i8; +pub type c_long = i64; +pub type c_ulong = u64; +pub type fsblkcnt_t = ::c_ulong; +pub type fsfilcnt_t = ::c_ulong; +pub type ino_t = u64; +pub type nlink_t = u64; +pub type off_t = i64; +pub type rlim_t = ::c_ulong; +pub type suseconds_t = i64; +pub type time_t = i64; +pub type wchar_t = i32; + +s! { + pub struct stat { + pub st_dev: ::c_ulong, + st_pad1: [::c_long; 2], + 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: ::c_ulong, + st_pad2: [::c_ulong; 1], + pub st_size: ::off_t, + st_pad3: ::c_long, + pub st_atime: ::time_t, + pub st_atime_nsec: ::c_long, + pub st_mtime: ::time_t, + pub st_mtime_nsec: ::c_long, + pub st_ctime: ::time_t, + pub st_ctime_nsec: ::c_long, + pub st_blksize: ::blksize_t, + st_pad4: ::c_long, + pub st_blocks: ::blkcnt_t, + st_pad5: [::c_long; 7], + } + + pub struct stat64 { + pub st_dev: ::c_ulong, + st_pad1: [::c_long; 2], + 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: ::c_ulong, + st_pad2: [::c_long; 2], + pub st_size: ::off64_t, + pub st_atime: ::time_t, + pub st_atime_nsec: ::c_long, + pub st_mtime: ::time_t, + pub st_mtime_nsec: ::c_long, + pub st_ctime: ::time_t, + pub st_ctime_nsec: ::c_long, + pub st_blksize: ::blksize_t, + st_pad3: ::c_long, + pub st_blocks: ::blkcnt64_t, + st_pad5: [::c_long; 7], + } + + pub struct pthread_attr_t { + __size: [::c_ulong; 7] + } + + pub struct sigaction { + pub sa_flags: ::c_int, + pub sa_sigaction: ::sighandler_t, + pub sa_mask: sigset_t, + _restorer: *mut ::c_void, + } + + pub struct stack_t { + pub ss_sp: *mut ::c_void, + pub ss_size: ::size_t, + pub ss_flags: ::c_int, + } + + pub struct sigset_t { + __size: [::c_ulong; 16], + } + + pub struct siginfo_t { + pub si_signo: ::c_int, + pub si_code: ::c_int, + pub si_errno: ::c_int, + _pad: ::c_int, + _pad2: [::c_long; 14], + } + + 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: ::c_uint, + pub __seq: ::c_ushort, + __pad1: ::c_ushort, + __unused1: ::c_ulong, + __unused2: ::c_ulong + } + + pub struct shmid_ds { + pub shm_perm: ::ipc_perm, + pub shm_segsz: ::size_t, + pub shm_atime: ::time_t, + pub shm_dtime: ::time_t, + pub shm_ctime: ::time_t, + pub shm_cpid: ::pid_t, + pub shm_lpid: ::pid_t, + pub shm_nattch: ::shmatt_t, + __unused4: ::c_ulong, + __unused5: ::c_ulong + } + + pub struct msqid_ds { + pub msg_perm: ::ipc_perm, + pub msg_stime: ::time_t, + pub msg_rtime: ::time_t, + pub msg_ctime: ::time_t, + __msg_cbytes: ::c_ulong, + pub msg_qnum: ::msgqnum_t, + pub msg_qbytes: ::msglen_t, + pub msg_lspid: ::pid_t, + pub msg_lrpid: ::pid_t, + __glibc_reserved4: ::c_ulong, + __glibc_reserved5: ::c_ulong, + } + + pub struct statfs { + pub f_type: ::c_long, + pub f_bsize: ::c_long, + pub f_frsize: ::c_long, + pub f_blocks: ::fsblkcnt_t, + pub f_bfree: ::fsblkcnt_t, + pub f_files: ::fsblkcnt_t, + pub f_ffree: ::fsblkcnt_t, + pub f_bavail: ::fsblkcnt_t, + pub f_fsid: ::fsid_t, + + pub f_namelen: ::c_long, + f_spare: [::c_long; 6], + } + + pub struct msghdr { + pub msg_name: *mut ::c_void, + pub msg_namelen: ::socklen_t, + pub msg_iov: *mut ::iovec, + pub msg_iovlen: ::size_t, + pub msg_control: *mut ::c_void, + pub msg_controllen: ::size_t, + 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, + pub c_cflag: ::tcflag_t, + pub c_lflag: ::tcflag_t, + pub c_line: ::cc_t, + pub c_cc: [::cc_t; ::NCCS], + } + + pub struct sysinfo { + pub uptime: ::c_long, + pub loads: [::c_ulong; 3], + pub totalram: ::c_ulong, + pub freeram: ::c_ulong, + pub sharedram: ::c_ulong, + pub bufferram: ::c_ulong, + pub totalswap: ::c_ulong, + pub freeswap: ::c_ulong, + pub procs: ::c_ushort, + pub pad: ::c_ushort, + pub totalhigh: ::c_ulong, + pub freehigh: ::c_ulong, + pub mem_unit: ::c_uint, + pub _f: [::c_char; 0], + } + + // FIXME this is actually a union + pub struct sem_t { + __size: [::c_char; 32], + __align: [::c_long; 0], + } +} + +pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; +pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; +pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; +pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; + +pub const RLIM_INFINITY: ::rlim_t = 0xffff_ffff_ffff_ffff; + +pub const SYS_gettid: ::c_long = 5178; // Valid for n64 + +#[link(name = "util")] +extern { + pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int; +} diff --git a/src/liblibc/src/unix/uclibc/mips/mod.rs b/src/liblibc/src/unix/uclibc/mips/mod.rs new file mode 100644 index 0000000000..cc3ddf254d --- /dev/null +++ b/src/liblibc/src/unix/uclibc/mips/mod.rs @@ -0,0 +1,476 @@ +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 = 4096; +pub const TMP_MAX: ::c_uint = 238328; +pub const FOPEN_MAX: ::c_uint = 16; +pub const POSIX_FADV_DONTNEED: ::c_int = 4; +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_DIRECT: ::c_int = 0x8000; +pub const O_DIRECTORY: ::c_int = 0x10000; +pub const O_NOFOLLOW: ::c_int = 0x20000; +pub const ST_RELATIME: ::c_ulong = 4096; +pub const NI_MAXHOST: ::socklen_t = 1025; + +pub const RLIMIT_NOFILE: ::c_int = 5; +pub const RLIMIT_AS: ::c_int = 6; +pub const RLIMIT_RSS: ::c_int = 7; +pub const RLIMIT_NPROC: ::c_int = 8; +pub const RLIMIT_MEMLOCK: ::c_int = 9; +pub const RLIMIT_NLIMITS: ::c_int = 15; + +pub const O_APPEND: ::c_int = 8; +pub const O_CREAT: ::c_int = 256; +pub const O_EXCL: ::c_int = 1024; +pub const O_NOCTTY: ::c_int = 2048; +pub const O_NONBLOCK: ::c_int = 128; +pub const O_SYNC: ::c_int = 0x10; +pub const O_RSYNC: ::c_int = 0x10; +pub const O_DSYNC: ::c_int = 0x10; +pub const O_FSYNC: ::c_int = 0x10; +pub const O_ASYNC: ::c_int = 0x1000; +pub const O_NDELAY: ::c_int = 0x80; + +pub const SOCK_NONBLOCK: ::c_int = 128; + +pub const EDEADLK: ::c_int = 45; +pub const ENAMETOOLONG: ::c_int = 78; +pub const ENOLCK: ::c_int = 46; +pub const ENOSYS: ::c_int = 89; +pub const ENOTEMPTY: ::c_int = 93; +pub const ELOOP: ::c_int = 90; +pub const ENOMSG: ::c_int = 35; +pub const EIDRM: ::c_int = 36; +pub const ECHRNG: ::c_int = 37; +pub const EL2NSYNC: ::c_int = 38; +pub const EL3HLT: ::c_int = 39; +pub const EL3RST: ::c_int = 40; +pub const ELNRNG: ::c_int = 41; +pub const EUNATCH: ::c_int = 42; +pub const ENOCSI: ::c_int = 43; +pub const EL2HLT: ::c_int = 44; +pub const EBADE: ::c_int = 50; +pub const EBADR: ::c_int = 51; +pub const EXFULL: ::c_int = 52; +pub const ENOANO: ::c_int = 53; +pub const EBADRQC: ::c_int = 54; +pub const EBADSLT: ::c_int = 55; +pub const EDEADLOCK: ::c_int = 56; +pub const EMULTIHOP: ::c_int = 74; +pub const EOVERFLOW: ::c_int = 79; +pub const ENOTUNIQ: ::c_int = 80; +pub const EBADFD: ::c_int = 81; +pub const EBADMSG: ::c_int = 77; +pub const EREMCHG: ::c_int = 82; +pub const ELIBACC: ::c_int = 83; +pub const ELIBBAD: ::c_int = 84; +pub const ELIBSCN: ::c_int = 85; +pub const ELIBMAX: ::c_int = 86; +pub const ELIBEXEC: ::c_int = 87; +pub const EILSEQ: ::c_int = 88; +pub const ERESTART: ::c_int = 91; +pub const ESTRPIPE: ::c_int = 92; +pub const EUSERS: ::c_int = 94; +pub const ENOTSOCK: ::c_int = 95; +pub const EDESTADDRREQ: ::c_int = 96; +pub const EMSGSIZE: ::c_int = 97; +pub const EPROTOTYPE: ::c_int = 98; +pub const ENOPROTOOPT: ::c_int = 99; +pub const EPROTONOSUPPORT: ::c_int = 120; +pub const ESOCKTNOSUPPORT: ::c_int = 121; +pub const EOPNOTSUPP: ::c_int = 122; +pub const ENOTSUP: ::c_int = EOPNOTSUPP; +pub const EPFNOSUPPORT: ::c_int = 123; +pub const EAFNOSUPPORT: ::c_int = 124; +pub const EADDRINUSE: ::c_int = 125; +pub const EADDRNOTAVAIL: ::c_int = 126; +pub const ENETDOWN: ::c_int = 127; +pub const ENETUNREACH: ::c_int = 128; +pub const ENETRESET: ::c_int = 129; +pub const ECONNABORTED: ::c_int = 130; +pub const ECONNRESET: ::c_int = 131; +pub const ENOBUFS: ::c_int = 132; +pub const EISCONN: ::c_int = 133; +pub const ENOTCONN: ::c_int = 134; +pub const ESHUTDOWN: ::c_int = 143; +pub const ETOOMANYREFS: ::c_int = 144; +pub const ETIMEDOUT: ::c_int = 145; +pub const ECONNREFUSED: ::c_int = 146; +pub const EHOSTDOWN: ::c_int = 147; +pub const EHOSTUNREACH: ::c_int = 148; +pub const EALREADY: ::c_int = 149; +pub const EINPROGRESS: ::c_int = 150; +pub const ESTALE: ::c_int = 151; +pub const EUCLEAN: ::c_int = 135; +pub const ENOTNAM: ::c_int = 137; +pub const ENAVAIL: ::c_int = 138; +pub const EISNAM: ::c_int = 139; +pub const EREMOTEIO: ::c_int = 140; +pub const EDQUOT: ::c_int = 1133; +pub const ENOMEDIUM: ::c_int = 159; +pub const EMEDIUMTYPE: ::c_int = 160; +pub const ECANCELED: ::c_int = 158; +pub const ENOKEY: ::c_int = 161; +pub const EKEYEXPIRED: ::c_int = 162; +pub const EKEYREVOKED: ::c_int = 163; +pub const EKEYREJECTED: ::c_int = 164; +pub const EOWNERDEAD: ::c_int = 165; +pub const ENOTRECOVERABLE: ::c_int = 166; +pub const ERFKILL: ::c_int = 167; + +pub const MAP_NORESERVE: ::c_int = 0x400; +pub const MAP_ANON: ::c_int = 0x800; +pub const MAP_ANONYMOUS: ::c_int = 0x800; +pub const MAP_GROWSDOWN: ::c_int = 0x1000; +pub const MAP_DENYWRITE: ::c_int = 0x2000; +pub const MAP_EXECUTABLE: ::c_int = 0x4000; +pub const MAP_LOCKED: ::c_int = 0x8000; +pub const MAP_POPULATE: ::c_int = 0x10000; +pub const MAP_NONBLOCK: ::c_int = 0x20000; +pub const MAP_STACK: ::c_int = 0x40000; + +pub const SOCK_STREAM: ::c_int = 2; +pub const SOCK_DGRAM: ::c_int = 1; +pub const SOCK_SEQPACKET: ::c_int = 5; + +pub const SOL_SOCKET: ::c_int = 0xffff; + +pub const SO_REUSEADDR: ::c_int = 0x0004; +pub const SO_KEEPALIVE: ::c_int = 0x0008; +pub const SO_DONTROUTE: ::c_int = 0x0010; +pub const SO_BROADCAST: ::c_int = 0x0020; +pub const SO_LINGER: ::c_int = 0x0080; +pub const SO_OOBINLINE: ::c_int = 0x0100; +pub const SO_REUSEPORT: ::c_int = 0x0200; +pub const SO_TYPE: ::c_int = 0x1008; +pub const SO_STYLE: ::c_int = SO_TYPE; +pub const SO_ERROR: ::c_int = 0x1007; +pub const SO_SNDBUF: ::c_int = 0x1001; +pub const SO_RCVBUF: ::c_int = 0x1002; +pub const SO_SNDLOWAT: ::c_int = 0x1003; +pub const SO_RCVLOWAT: ::c_int = 0x1004; +pub const SO_SNDTIMEO: ::c_int = 0x1005; +pub const SO_RCVTIMEO: ::c_int = 0x1006; +pub const SO_ACCEPTCONN: ::c_int = 0x1009; +pub const SO_PROTOCOL: ::c_int = 0x1028; +pub const SO_DOMAIN: ::c_int = 0x1029; +pub const SO_NO_CHECK: ::c_int = 11; +pub const SO_PRIORITY: ::c_int = 12; +pub const SO_BSDCOMPAT: ::c_int = 14; +pub const SO_PASSCRED: ::c_int = 17; +pub const SO_PEERCRED: ::c_int = 18; +pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22; +pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23; +pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24; +pub const SO_BINDTODEVICE: ::c_int = 25; +pub const SO_ATTACH_FILTER: ::c_int = 26; +pub const SO_DETACH_FILTER: ::c_int = 27; +pub const SO_GET_FILTER: ::c_int = SO_ATTACH_FILTER; +pub const SO_PEERNAME: ::c_int = 28; +pub const SO_TIMESTAMP: ::c_int = 29; +pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP; +pub const SO_PEERSEC: ::c_int = 30; +pub const SO_SNDBUFFORCE: ::c_int = 31; +pub const SO_RCVBUFFORCE: ::c_int = 33; +pub const SO_PASSSEC: ::c_int = 34; +pub const SO_TIMESTAMPNS: ::c_int = 35; +pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS; +pub const SO_MARK: ::c_int = 36; +pub const SO_TIMESTAMPING: ::c_int = 37; +pub const SCM_TIMESTAMPING: ::c_int = SO_TIMESTAMPING; +pub const SO_RXQ_OVFL: ::c_int = 40; +pub const SO_WIFI_STATUS: ::c_int = 41; +pub const SCM_WIFI_STATUS: ::c_int = SO_WIFI_STATUS; +pub const SO_PEEK_OFF: ::c_int = 42; +pub const SO_NOFCS: ::c_int = 43; +pub const SO_LOCK_FILTER: ::c_int = 44; +pub const SO_SELECT_ERR_QUEUE: ::c_int = 45; +pub const SO_BUSY_POLL: ::c_int = 46; +pub const SO_MAX_PACING_RATE: ::c_int = 47; +pub const SO_BPF_EXTENSIONS: ::c_int = 48; + +pub const FIOCLEX: ::c_ulong = 0x6601; +pub const FIONBIO: ::c_ulong = 0x667e; + +pub const SA_ONSTACK: ::c_int = 0x08000000; +pub const SA_SIGINFO: ::c_int = 0x00000008; +pub const SA_NOCLDWAIT: ::c_int = 0x00010000; + +pub const SIGCHLD: ::c_int = 18; +pub const SIGBUS: ::c_int = 10; +pub const SIGTTIN: ::c_int = 26; +pub const SIGTTOU: ::c_int = 27; +pub const SIGXCPU: ::c_int = 30; +pub const SIGXFSZ: ::c_int = 31; +pub const SIGVTALRM: ::c_int = 28; +pub const SIGPROF: ::c_int = 29; +pub const SIGWINCH: ::c_int = 20; +pub const SIGUSR1: ::c_int = 16; +pub const SIGUSR2: ::c_int = 17; +pub const SIGCONT: ::c_int = 25; +pub const SIGSTOP: ::c_int = 23; +pub const SIGTSTP: ::c_int = 24; +pub const SIGURG: ::c_int = 21; +pub const SIGIO: ::c_int = 22; +pub const SIGSYS: ::c_int = 12; +pub const SIGPOLL: ::c_int = 22; +pub const SIGPWR: ::c_int = 19; +pub const SIG_SETMASK: ::c_int = 3; +pub const SIG_BLOCK: ::c_int = 0x1; +pub const SIG_UNBLOCK: ::c_int = 0x2; + +pub const POLLRDNORM: ::c_short = 0x040; +pub const POLLWRNORM: ::c_short = 0x004; +pub const POLLRDBAND: ::c_short = 0x080; +pub const POLLWRBAND: ::c_short = 0x100; + +pub const PTHREAD_STACK_MIN: ::size_t = 16384; + +pub const ADFS_SUPER_MAGIC: ::c_long = 0x0000adf5; +pub const AFFS_SUPER_MAGIC: ::c_long = 0x0000adff; +pub const CODA_SUPER_MAGIC: ::c_long = 0x73757245; +pub const CRAMFS_MAGIC: ::c_long = 0x28cd3d45; +pub const EFS_SUPER_MAGIC: ::c_long = 0x00414a53; +pub const EXT2_SUPER_MAGIC: ::c_long = 0x0000ef53; +pub const EXT3_SUPER_MAGIC: ::c_long = 0x0000ef53; +pub const EXT4_SUPER_MAGIC: ::c_long = 0x0000ef53; +pub const HPFS_SUPER_MAGIC: ::c_long = 0xf995e849; +pub const HUGETLBFS_MAGIC: ::c_long = 0x958458f6; +pub const ISOFS_SUPER_MAGIC: ::c_long = 0x00009660; +pub const JFFS2_SUPER_MAGIC: ::c_long = 0x000072b6; +pub const MINIX_SUPER_MAGIC: ::c_long = 0x0000137f; +pub const MINIX_SUPER_MAGIC2: ::c_long = 0x0000138f; +pub const MINIX2_SUPER_MAGIC: ::c_long = 0x00002468; +pub const MINIX2_SUPER_MAGIC2: ::c_long = 0x00002478; +pub const MSDOS_SUPER_MAGIC: ::c_long = 0x00004d44; +pub const NCP_SUPER_MAGIC: ::c_long = 0x0000564c; +pub const NFS_SUPER_MAGIC: ::c_long = 0x00006969; +pub const OPENPROM_SUPER_MAGIC: ::c_long = 0x00009fa1; +pub const PROC_SUPER_MAGIC: ::c_long = 0x00009fa0; +pub const QNX4_SUPER_MAGIC: ::c_long = 0x0000002f; +pub const REISERFS_SUPER_MAGIC: ::c_long = 0x52654973; +pub const SMB_SUPER_MAGIC: ::c_long = 0x0000517b; +pub const TMPFS_MAGIC: ::c_long = 0x01021994; +pub const USBDEVICE_SUPER_MAGIC: ::c_long = 0x00009fa2; + +pub const VEOF: usize = 16; +pub const VEOL: usize = 17; +pub const VEOL2: usize = 6; +pub const VMIN: usize = 4; +pub const IEXTEN: ::tcflag_t = 0x00000100; +pub const TOSTOP: ::tcflag_t = 0x00008000; +pub const FLUSHO: ::tcflag_t = 0x00002000; +pub const IUTF8: ::tcflag_t = 0x00004000; +pub const TCSANOW: ::c_int = 0x540e; +pub const TCSADRAIN: ::c_int = 0x540f; +pub const TCSAFLUSH: ::c_int = 0x5410; + +pub const CPU_SETSIZE: ::c_int = 0x400; + +pub const PTRACE_TRACEME: ::c_uint = 0; +pub const PTRACE_PEEKTEXT: ::c_uint = 1; +pub const PTRACE_PEEKDATA: ::c_uint = 2; +pub const PTRACE_PEEKUSER: ::c_uint = 3; +pub const PTRACE_POKETEXT: ::c_uint = 4; +pub const PTRACE_POKEDATA: ::c_uint = 5; +pub const PTRACE_POKEUSER: ::c_uint = 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; +pub const PTRACE_GETSIGINFO: ::c_uint = 0x4202; +pub const PTRACE_SETSIGINFO: ::c_uint = 0x4203; +pub const PTRACE_GETFPREGS: ::c_uint = 14; +pub const PTRACE_SETFPREGS: ::c_uint = 15; +pub const PTRACE_GETFPXREGS: ::c_uint = 18; +pub const PTRACE_SETFPXREGS: ::c_uint = 19; +pub const PTRACE_GETREGS: ::c_uint = 12; +pub const PTRACE_SETREGS: ::c_uint = 13; + +pub const EFD_NONBLOCK: ::c_int = 0x80; + +pub const F_GETLK: ::c_int = 14; +pub const F_GETOWN: ::c_int = 23; +pub const F_SETOWN: ::c_int = 24; +pub const F_SETLK: ::c_int = 6; +pub const F_SETLKW: ::c_int = 7; + +pub const SFD_NONBLOCK: ::c_int = 0x80; + +pub const TCGETS: ::c_ulong = 0x540d; +pub const TCSETS: ::c_ulong = 0x540e; +pub const TCSETSW: ::c_ulong = 0x540f; +pub const TCSETSF: ::c_ulong = 0x5410; +pub const TCGETA: ::c_ulong = 0x5401; +pub const TCSETA: ::c_ulong = 0x5402; +pub const TCSETAW: ::c_ulong = 0x5403; +pub const TCSETAF: ::c_ulong = 0x5404; +pub const TCSBRK: ::c_ulong = 0x5405; +pub const TCXONC: ::c_ulong = 0x5406; +pub const TCFLSH: ::c_ulong = 0x5407; +pub const TIOCGSOFTCAR: ::c_ulong = 0x5481; +pub const TIOCSSOFTCAR: ::c_ulong = 0x5482; +pub const TIOCINQ: ::c_ulong = 0x467f; +pub const TIOCLINUX: ::c_ulong = 0x5483; +pub const TIOCGSERIAL: ::c_ulong = 0x5484; +pub const TIOCEXCL: ::c_ulong = 0x740d; +pub const TIOCNXCL: ::c_ulong = 0x740e; +pub const TIOCSCTTY: ::c_ulong = 0x5480; +pub const TIOCGPGRP: ::c_ulong = 0x40047477; +pub const TIOCSPGRP: ::c_ulong = 0x80047476; +pub const TIOCOUTQ: ::c_ulong = 0x7472; +pub const TIOCSTI: ::c_ulong = 0x5472; +pub const TIOCGWINSZ: ::c_ulong = 0x40087468; +pub const TIOCSWINSZ: ::c_ulong = 0x80087467; +pub const TIOCMGET: ::c_ulong = 0x741d; +pub const TIOCMBIS: ::c_ulong = 0x741b; +pub const TIOCMBIC: ::c_ulong = 0x741c; +pub const TIOCMSET: ::c_ulong = 0x741a; +pub const FIONREAD: ::c_ulong = 0x467f; +pub const TIOCCONS: ::c_ulong = 0x80047478; + +pub const RTLD_DEEPBIND: ::c_int = 0x10; +pub const RTLD_GLOBAL: ::c_int = 0x4; +pub const RTLD_NOLOAD: ::c_int = 0x8; + +pub const LINUX_REBOOT_MAGIC1: ::c_int = 0xfee1dead; +pub const LINUX_REBOOT_MAGIC2: ::c_int = 672274793; +pub const LINUX_REBOOT_MAGIC2A: ::c_int = 85072278; +pub const LINUX_REBOOT_MAGIC2B: ::c_int = 369367448; +pub const LINUX_REBOOT_MAGIC2C: ::c_int = 537993216; + +pub const LINUX_REBOOT_CMD_RESTART: ::c_int = 0x01234567; +pub const LINUX_REBOOT_CMD_HALT: ::c_int = 0xCDEF0123; +pub const LINUX_REBOOT_CMD_CAD_ON: ::c_int = 0x89ABCDEF; +pub const LINUX_REBOOT_CMD_CAD_OFF: ::c_int = 0x00000000; +pub const LINUX_REBOOT_CMD_POWER_OFF: ::c_int = 0x4321FEDC; +pub const LINUX_REBOOT_CMD_RESTART2: ::c_int = 0xA1B2C3D4; +pub const LINUX_REBOOT_CMD_SW_SUSPEND: ::c_int = 0xD000FCE2; +pub const LINUX_REBOOT_CMD_KEXEC: ::c_int = 0x45584543; + +pub const MCL_CURRENT: ::c_int = 0x0001; +pub const MCL_FUTURE: ::c_int = 0x0002; + +pub const SIGSTKSZ: ::size_t = 8192; +pub const CBAUD: ::tcflag_t = 0o0010017; +pub const TAB1: ::c_int = 0x00000800; +pub const TAB2: ::c_int = 0x00001000; +pub const TAB3: ::c_int = 0x00001800; +pub const CR1: ::c_int = 0x00000200; +pub const CR2: ::c_int = 0x00000400; +pub const CR3: ::c_int = 0x00000600; +pub const FF1: ::c_int = 0x00008000; +pub const BS1: ::c_int = 0x00002000; +pub const VT1: ::c_int = 0x00004000; +pub const VWERASE: usize = 14; +pub const VREPRINT: usize = 12; +pub const VSUSP: usize = 10; +pub const VSTART: usize = 8; +pub const VSTOP: usize = 9; +pub const VDISCARD: usize = 13; +pub const VTIME: usize = 5; +pub const IXON: ::tcflag_t = 0x00000400; +pub const IXOFF: ::tcflag_t = 0x00001000; +pub const ONLCR: ::tcflag_t = 0x4; +pub const CSIZE: ::tcflag_t = 0x00000030; +pub const CS6: ::tcflag_t = 0x00000010; +pub const CS7: ::tcflag_t = 0x00000020; +pub const CS8: ::tcflag_t = 0x00000030; +pub const CSTOPB: ::tcflag_t = 0x00000040; +pub const CREAD: ::tcflag_t = 0x00000080; +pub const PARENB: ::tcflag_t = 0x00000100; +pub const PARODD: ::tcflag_t = 0x00000200; +pub const HUPCL: ::tcflag_t = 0x00000400; +pub const CLOCAL: ::tcflag_t = 0x00000800; +pub const ECHOKE: ::tcflag_t = 0x00000800; +pub const ECHOE: ::tcflag_t = 0x00000010; +pub const ECHOK: ::tcflag_t = 0x00000020; +pub const ECHONL: ::tcflag_t = 0x00000040; +pub const ECHOPRT: ::tcflag_t = 0x00000400; +pub const ECHOCTL: ::tcflag_t = 0x00000200; +pub const ISIG: ::tcflag_t = 0x00000001; +pub const ICANON: ::tcflag_t = 0x00000002; +pub const PENDIN: ::tcflag_t = 0x00004000; +pub const NOFLSH: ::tcflag_t = 0x00000080; + +pub const B0: ::speed_t = 0o000000; +pub const B50: ::speed_t = 0o000001; +pub const B75: ::speed_t = 0o000002; +pub const B110: ::speed_t = 0o000003; +pub const B134: ::speed_t = 0o000004; +pub const B150: ::speed_t = 0o000005; +pub const B200: ::speed_t = 0o000006; +pub const B300: ::speed_t = 0o000007; +pub const B600: ::speed_t = 0o000010; +pub const B1200: ::speed_t = 0o000011; +pub const B1800: ::speed_t = 0o000012; +pub const B2400: ::speed_t = 0o000013; +pub const B4800: ::speed_t = 0o000014; +pub const B9600: ::speed_t = 0o000015; +pub const B19200: ::speed_t = 0o000016; +pub const B38400: ::speed_t = 0o000017; +pub const EXTA: ::speed_t = B19200; +pub const EXTB: ::speed_t = B38400; +pub const B57600: ::speed_t = 0o010001; +pub const B115200: ::speed_t = 0o010002; +pub const B230400: ::speed_t = 0o010003; +pub const B460800: ::speed_t = 0o010004; +pub const B500000: ::speed_t = 0o010005; +pub const B576000: ::speed_t = 0o010006; +pub const B921600: ::speed_t = 0o010007; +pub const B1000000: ::speed_t = 0o010010; +pub const B1152000: ::speed_t = 0o010011; +pub const B1500000: ::speed_t = 0o010012; +pub const B2000000: ::speed_t = 0o010013; +pub const B2500000: ::speed_t = 0o010014; +pub const B3000000: ::speed_t = 0o010015; +pub const B3500000: ::speed_t = 0o010016; +pub const B4000000: ::speed_t = 0o010017; + +cfg_if! { + if #[cfg(target_arch = "mips")] { + mod mips32; + pub use self::mips32::*; + } else if #[cfg(target_arch = "mips64")] { + mod mips64; + pub use self::mips64::*; + } else { + // Unknown target_arch + } +} diff --git a/src/liblibc/src/unix/uclibc/mod.rs b/src/liblibc/src/unix/uclibc/mod.rs new file mode 100644 index 0000000000..09f7d055f3 --- /dev/null +++ b/src/liblibc/src/unix/uclibc/mod.rs @@ -0,0 +1,1769 @@ +use dox::{mem, Option}; + +pub type sa_family_t = u16; +pub type pthread_key_t = ::c_uint; +pub type speed_t = ::c_uint; +pub type tcflag_t = ::c_uint; +pub type loff_t = ::c_longlong; +pub type clockid_t = ::c_int; +pub type key_t = ::c_int; +pub type id_t = ::c_uint; +pub type useconds_t = u32; +pub type dev_t = u64; +pub type socklen_t = u32; +pub type pthread_t = ::c_ulong; +pub type mode_t = u32; +pub type ino64_t = u64; +pub type off64_t = i64; +pub type blkcnt64_t = i64; +pub type rlim64_t = u64; +pub type shmatt_t = ::c_ulong; +pub type mqd_t = ::c_int; +pub type msgqnum_t = ::c_ulong; +pub type msglen_t = ::c_ulong; +pub type nfds_t = ::c_ulong; +pub type nl_item = ::c_int; +pub type idtype_t = ::c_uint; + +pub enum fpos64_t {} // TODO: fill this out with a struct + +pub enum timezone {} + +s! { + pub struct sockaddr { + pub sa_family: sa_family_t, + pub sa_data: [::c_char; 14], + } + + pub struct sockaddr_in { + pub sin_family: sa_family_t, + pub sin_port: ::in_port_t, + pub sin_addr: ::in_addr, + pub sin_zero: [u8; 8], + } + + pub struct sockaddr_in6 { + pub sin6_family: sa_family_t, + pub sin6_port: ::in_port_t, + pub sin6_flowinfo: u32, + pub sin6_addr: ::in6_addr, + pub sin6_scope_id: u32, + } + + pub struct sockaddr_un { + pub sun_family: sa_family_t, + pub sun_path: [::c_char; 108] + } + + pub struct sockaddr_storage { + pub ss_family: sa_family_t, + __ss_align: ::size_t, + #[cfg(target_pointer_width = "32")] + __ss_pad2: [u8; 128 - 2 * 4], + #[cfg(target_pointer_width = "64")] + __ss_pad2: [u8; 128 - 2 * 8], + } + + pub struct addrinfo { + pub ai_flags: ::c_int, + pub ai_family: ::c_int, + pub ai_socktype: ::c_int, + pub ai_protocol: ::c_int, + pub ai_addrlen: socklen_t, + + pub ai_addr: *mut ::sockaddr, + + pub ai_canonname: *mut c_char, + + pub ai_next: *mut addrinfo, + } + + pub struct sockaddr_nl { + pub nl_family: ::sa_family_t, + nl_pad: ::c_ushort, + pub nl_pid: u32, + pub nl_groups: u32 + } + + pub struct sockaddr_ll { + pub sll_family: ::c_ushort, + pub sll_protocol: ::c_ushort, + pub sll_ifindex: ::c_int, + pub sll_hatype: ::c_ushort, + pub sll_pkttype: ::c_uchar, + pub sll_halen: ::c_uchar, + pub sll_addr: [::c_uchar; 8] + } + + pub struct fd_set { + fds_bits: [::c_ulong; FD_SETSIZE / ULONG_SIZE], + } + + pub struct tm { + pub tm_sec: ::c_int, + pub tm_min: ::c_int, + pub tm_hour: ::c_int, + pub tm_mday: ::c_int, + pub tm_mon: ::c_int, + pub tm_year: ::c_int, + pub tm_wday: ::c_int, + pub tm_yday: ::c_int, + pub tm_isdst: ::c_int, + pub tm_gmtoff: ::c_long, + pub tm_zone: *const ::c_char, + } + + pub struct sched_param { + pub sched_priority: ::c_int, + } + + pub struct Dl_info { + pub dli_fname: *const ::c_char, + pub dli_fbase: *mut ::c_void, + pub dli_sname: *const ::c_char, + pub dli_saddr: *mut ::c_void, + } + + #[cfg_attr(any(all(target_arch = "x86", + target_arch = "x86_64")), + repr(packed))] + pub struct epoll_event { + pub events: ::uint32_t, + pub u64: ::uint64_t, + } + + pub struct utsname { + pub sysname: [::c_char; 65], + pub nodename: [::c_char; 65], + pub release: [::c_char; 65], + pub version: [::c_char; 65], + pub machine: [::c_char; 65], + pub domainname: [::c_char; 65] + } + + pub struct lconv { + pub decimal_point: *mut ::c_char, + pub thousands_sep: *mut ::c_char, + pub grouping: *mut ::c_char, + pub int_curr_symbol: *mut ::c_char, + pub currency_symbol: *mut ::c_char, + pub mon_decimal_point: *mut ::c_char, + pub mon_thousands_sep: *mut ::c_char, + pub mon_grouping: *mut ::c_char, + pub positive_sign: *mut ::c_char, + pub negative_sign: *mut ::c_char, + pub int_frac_digits: ::c_char, + pub frac_digits: ::c_char, + pub p_cs_precedes: ::c_char, + pub p_sep_by_space: ::c_char, + pub n_cs_precedes: ::c_char, + pub n_sep_by_space: ::c_char, + pub p_sign_posn: ::c_char, + pub n_sign_posn: ::c_char, + pub int_p_cs_precedes: ::c_char, + pub int_p_sep_by_space: ::c_char, + pub int_n_cs_precedes: ::c_char, + pub int_n_sep_by_space: ::c_char, + pub int_p_sign_posn: ::c_char, + pub int_n_sign_posn: ::c_char, + } + + pub struct sigevent { + pub sigev_value: ::sigval, + pub sigev_signo: ::c_int, + pub sigev_notify: ::c_int, + // Actually a union. We only expose sigev_notify_thread_id because it's + // the most useful member + pub sigev_notify_thread_id: ::c_int, + #[cfg(target_pointer_width = "64")] + __unused1: [::c_int; 11], + #[cfg(target_pointer_width = "32")] + __unused1: [::c_int; 12] + } + + pub struct dirent { + pub d_ino: ::ino_t, + pub d_off: ::off_t, + pub d_reclen: ::c_ushort, + pub d_type: ::c_uchar, + pub d_name: [::c_char; 256], + } + + pub struct dirent64 { + pub d_ino: ::ino64_t, + pub d_off: ::off64_t, + pub d_reclen: ::c_ushort, + pub d_type: ::c_uchar, + pub d_name: [::c_char; 256], + } + + pub struct rlimit64 { + pub rlim_cur: rlim64_t, + pub rlim_max: rlim64_t, + } + + pub struct glob_t { + pub gl_pathc: ::size_t, + pub gl_pathv: *mut *mut c_char, + pub gl_offs: ::size_t, + pub gl_flags: ::c_int, + + __unused1: *mut ::c_void, + __unused2: *mut ::c_void, + __unused3: *mut ::c_void, + __unused4: *mut ::c_void, + __unused5: *mut ::c_void, + } + + pub struct ifaddrs { + pub ifa_next: *mut ifaddrs, + pub ifa_name: *mut c_char, + pub ifa_flags: ::c_uint, + pub ifa_addr: *mut ::sockaddr, + pub ifa_netmask: *mut ::sockaddr, + pub ifa_ifu: *mut ::sockaddr, // FIXME This should be a union + pub ifa_data: *mut ::c_void + } + + pub struct pthread_mutex_t { + #[cfg(any(target_arch = "mips", target_arch = "arm", + target_arch = "powerpc"))] + __align: [::c_long; 0], + #[cfg(not(any(target_arch = "mips", target_arch = "arm", + target_arch = "powerpc")))] + __align: [::c_longlong; 0], + size: [u8; __SIZEOF_PTHREAD_MUTEX_T], + } + + pub struct pthread_rwlock_t { + #[cfg(any(target_arch = "mips", target_arch = "arm", + target_arch = "powerpc"))] + __align: [::c_long; 0], + #[cfg(not(any(target_arch = "mips", target_arch = "arm", + target_arch = "powerpc")))] + __align: [::c_longlong; 0], + size: [u8; __SIZEOF_PTHREAD_RWLOCK_T], + } + + pub struct pthread_mutexattr_t { + #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64"))] + __align: [::c_int; 0], + #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64")))] + __align: [::c_long; 0], + size: [u8; __SIZEOF_PTHREAD_MUTEXATTR_T], + } + + pub struct pthread_cond_t { + __align: [::c_longlong; 0], + size: [u8; __SIZEOF_PTHREAD_COND_T], + } + + pub struct pthread_condattr_t { + __align: [::c_int; 0], + size: [u8; __SIZEOF_PTHREAD_CONDATTR_T], + } + + pub struct passwd { + pub pw_name: *mut ::c_char, + pub pw_passwd: *mut ::c_char, + pub pw_uid: ::uid_t, + pub pw_gid: ::gid_t, + pub pw_gecos: *mut ::c_char, + pub pw_dir: *mut ::c_char, + pub pw_shell: *mut ::c_char, + } + + pub struct spwd { + pub sp_namp: *mut ::c_char, + pub sp_pwdp: *mut ::c_char, + pub sp_lstchg: ::c_long, + pub sp_min: ::c_long, + pub sp_max: ::c_long, + pub sp_warn: ::c_long, + pub sp_inact: ::c_long, + pub sp_expire: ::c_long, + pub sp_flag: ::c_ulong, + } + + pub struct statvfs { + pub f_bsize: ::c_ulong, + pub f_frsize: ::c_ulong, + pub f_blocks: ::fsblkcnt_t, + pub f_bfree: ::fsblkcnt_t, + pub f_bavail: ::fsblkcnt_t, + pub f_files: ::fsfilcnt_t, + pub f_ffree: ::fsfilcnt_t, + pub f_favail: ::fsfilcnt_t, + #[cfg(target_endian = "little")] + pub f_fsid: ::c_ulong, + #[cfg(target_pointer_width = "32")] + __f_unused: ::c_int, + #[cfg(target_endian = "big")] + pub f_fsid: ::c_ulong, + pub f_flag: ::c_ulong, + pub f_namemax: ::c_ulong, + __f_spare: [::c_int; 6], + } + + pub struct dqblk { + pub dqb_bhardlimit: ::uint32_t, + pub dqb_bsoftlimit: ::uint32_t, + pub dqb_curblocks: ::uint32_t, + pub dqb_ihardlimit: ::uint32_t, + pub dqb_isoftlimit: ::uint32_t, + pub dqb_curinodes: ::uint32_t, + pub dqb_btime: ::time_t, + pub dqb_itime: ::time_t, + } + + pub struct signalfd_siginfo { + pub ssi_signo: ::uint32_t, + pub ssi_errno: ::int32_t, + pub ssi_code: ::int32_t, + pub ssi_pid: ::uint32_t, + pub ssi_uid: ::uint32_t, + pub ssi_fd: ::int32_t, + pub ssi_tid: ::uint32_t, + pub ssi_band: ::uint32_t, + pub ssi_overrun: ::uint32_t, + pub ssi_trapno: ::uint32_t, + pub ssi_status: ::int32_t, + pub ssi_int: ::int32_t, + pub ssi_ptr: ::uint64_t, + pub ssi_utime: ::uint64_t, + pub ssi_stime: ::uint64_t, + pub ssi_addr: ::uint64_t, + _pad: [::uint8_t; 48], + } + + pub struct fsid_t { + __val: [::c_int; 2], + } + + pub struct mq_attr { + pub mq_flags: ::c_long, + pub mq_maxmsg: ::c_long, + pub mq_msgsize: ::c_long, + pub mq_curmsgs: ::c_long, + pad: [::c_long; 4] + } + + pub struct cpu_set_t { + #[cfg(target_pointer_width = "32")] + bits: [u32; 32], + #[cfg(target_pointer_width = "64")] + bits: [u64; 16], + } + + pub struct if_nameindex { + pub if_index: ::c_uint, + pub if_name: *mut ::c_char, + } + + // System V IPC + pub struct msginfo { + pub msgpool: ::c_int, + pub msgmap: ::c_int, + pub msgmax: ::c_int, + pub msgmnb: ::c_int, + pub msgmni: ::c_int, + pub msgssz: ::c_int, + pub msgtql: ::c_int, + pub msgseg: ::c_ushort, + } +} + +// intentionally not public, only used for fd_set +cfg_if! { + if #[cfg(target_pointer_width = "32")] { + const ULONG_SIZE: usize = 32; + } else if #[cfg(target_pointer_width = "64")] { + const ULONG_SIZE: usize = 64; + } else { + // Unknown target_pointer_width + } +} + +pub const EXIT_FAILURE: ::c_int = 1; +pub const EXIT_SUCCESS: ::c_int = 0; +pub const RAND_MAX: ::c_int = 2147483647; +pub const EOF: ::c_int = -1; +pub const SEEK_SET: ::c_int = 0; +pub const SEEK_CUR: ::c_int = 1; +pub const SEEK_END: ::c_int = 2; +pub const _IOFBF: ::c_int = 0; +pub const _IONBF: ::c_int = 2; +pub const _IOLBF: ::c_int = 1; + +pub const F_DUPFD: ::c_int = 0; +pub const F_GETFD: ::c_int = 1; +pub const F_SETFD: ::c_int = 2; +pub const F_GETFL: ::c_int = 3; +pub const F_SETFL: ::c_int = 4; + +// Linux-specific fcntls +pub const F_SETLEASE: ::c_int = 1024; +pub const F_GETLEASE: ::c_int = 1025; +pub const F_NOTIFY: ::c_int = 1026; +pub const F_DUPFD_CLOEXEC: ::c_int = 1030; + +// TODO(#235): Include file sealing fcntls once we have a way to verify them. + +pub const SIGTRAP: ::c_int = 5; + +pub const PTHREAD_CREATE_JOINABLE: ::c_int = 0; +pub const PTHREAD_CREATE_DETACHED: ::c_int = 1; + +pub const CLOCK_REALTIME: clockid_t = 0; +pub const CLOCK_MONOTONIC: clockid_t = 1; +pub const CLOCK_PROCESS_CPUTIME_ID: clockid_t = 2; +pub const CLOCK_THREAD_CPUTIME_ID: clockid_t = 3; +// TODO(#247) Someday our Travis shall have glibc 2.21 (released in Sep +// 2014.) See also musl/mod.rs +// pub const CLOCK_SGI_CYCLE: clockid_t = 10; +// pub const CLOCK_TAI: clockid_t = 11; +pub const TIMER_ABSTIME: ::c_int = 1; + +pub const RLIMIT_CPU: ::c_int = 0; +pub const RLIMIT_FSIZE: ::c_int = 1; +pub const RLIMIT_DATA: ::c_int = 2; +pub const RLIMIT_STACK: ::c_int = 3; +pub const RLIMIT_CORE: ::c_int = 4; +pub const RLIMIT_LOCKS: ::c_int = 10; +pub const RLIMIT_SIGPENDING: ::c_int = 11; +pub const RLIMIT_MSGQUEUE: ::c_int = 12; +pub const RLIMIT_NICE: ::c_int = 13; +pub const RLIMIT_RTPRIO: ::c_int = 14; + +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 SOCK_CLOEXEC: ::c_int = O_CLOEXEC; + +pub const S_IFIFO: ::mode_t = 4096; +pub const S_IFCHR: ::mode_t = 8192; +pub const S_IFBLK: ::mode_t = 24576; +pub const S_IFDIR: ::mode_t = 16384; +pub const S_IFREG: ::mode_t = 32768; +pub const S_IFLNK: ::mode_t = 40960; +pub const S_IFSOCK: ::mode_t = 49152; +pub const S_IFMT: ::mode_t = 61440; +pub const S_IRWXU: ::mode_t = 448; +pub const S_IXUSR: ::mode_t = 64; +pub const S_IWUSR: ::mode_t = 128; +pub const S_IRUSR: ::mode_t = 256; +pub const S_IRWXG: ::mode_t = 56; +pub const S_IXGRP: ::mode_t = 8; +pub const S_IWGRP: ::mode_t = 16; +pub const S_IRGRP: ::mode_t = 32; +pub const S_IRWXO: ::mode_t = 7; +pub const S_IXOTH: ::mode_t = 1; +pub const S_IWOTH: ::mode_t = 2; +pub const S_IROTH: ::mode_t = 4; +pub const F_OK: ::c_int = 0; +pub const R_OK: ::c_int = 4; +pub const W_OK: ::c_int = 2; +pub const X_OK: ::c_int = 1; +pub const STDIN_FILENO: ::c_int = 0; +pub const STDOUT_FILENO: ::c_int = 1; +pub const STDERR_FILENO: ::c_int = 2; +pub const SIGHUP: ::c_int = 1; +pub const SIGINT: ::c_int = 2; +pub const SIGQUIT: ::c_int = 3; +pub const SIGILL: ::c_int = 4; +pub const SIGABRT: ::c_int = 6; +pub const SIGFPE: ::c_int = 8; +pub const SIGKILL: ::c_int = 9; +pub const SIGSEGV: ::c_int = 11; +pub const SIGPIPE: ::c_int = 13; +pub const SIGALRM: ::c_int = 14; +pub const SIGTERM: ::c_int = 15; + +pub const PROT_NONE: ::c_int = 0; +pub const PROT_READ: ::c_int = 1; +pub const PROT_WRITE: ::c_int = 2; +pub const PROT_EXEC: ::c_int = 4; + +pub const LC_CTYPE: ::c_int = 0; +pub const LC_NUMERIC: ::c_int = 1; +pub const LC_MONETARY: ::c_int = 2; +pub const LC_TIME: ::c_int = 3; +pub const LC_COLLATE: ::c_int = 4; +pub const LC_MESSAGES: ::c_int = 5; +pub const LC_ALL: ::c_int = 6; +pub const LC_CTYPE_MASK: ::c_int = (1 << LC_CTYPE); +pub const LC_NUMERIC_MASK: ::c_int = (1 << LC_NUMERIC); +pub const LC_TIME_MASK: ::c_int = (1 << LC_TIME); +pub const LC_COLLATE_MASK: ::c_int = (1 << LC_COLLATE); +pub const LC_MONETARY_MASK: ::c_int = (1 << LC_MONETARY); +pub const LC_MESSAGES_MASK: ::c_int = (1 << LC_MESSAGES); +// LC_ALL_MASK defined per platform + +pub const MAP_FILE: ::c_int = 0x0000; +pub const MAP_SHARED: ::c_int = 0x0001; +pub const MAP_PRIVATE: ::c_int = 0x0002; +pub const MAP_FIXED: ::c_int = 0x0010; + +pub const MAP_FAILED: *mut ::c_void = !0 as *mut ::c_void; + +// MS_ flags for msync(2) +pub const MS_ASYNC: ::c_int = 0x0001; +pub const MS_INVALIDATE: ::c_int = 0x0002; +pub const MS_SYNC: ::c_int = 0x0004; + +// MS_ flags for mount(2) +pub const MS_RDONLY: ::c_ulong = 0x01; +pub const MS_NOSUID: ::c_ulong = 0x02; +pub const MS_NODEV: ::c_ulong = 0x04; +pub const MS_NOEXEC: ::c_ulong = 0x08; +pub const MS_SYNCHRONOUS: ::c_ulong = 0x10; +pub const MS_REMOUNT: ::c_ulong = 0x20; +pub const MS_MANDLOCK: ::c_ulong = 0x40; +pub const MS_NOATIME: ::c_ulong = 0x0400; +pub const MS_NODIRATIME: ::c_ulong = 0x0800; +pub const MS_BIND: ::c_ulong = 0x1000; +pub const MS_NOUSER: ::c_ulong = 0x80000000; +pub const MS_MGC_VAL: ::c_ulong = 0xc0ed0000; +pub const MS_MGC_MSK: ::c_ulong = 0xffff0000; +pub const MS_RMT_MASK: ::c_ulong = 0x800051; + +pub const EPERM: ::c_int = 1; +pub const ENOENT: ::c_int = 2; +pub const ESRCH: ::c_int = 3; +pub const EINTR: ::c_int = 4; +pub const EIO: ::c_int = 5; +pub const ENXIO: ::c_int = 6; +pub const E2BIG: ::c_int = 7; +pub const ENOEXEC: ::c_int = 8; +pub const EBADF: ::c_int = 9; +pub const ECHILD: ::c_int = 10; +pub const EAGAIN: ::c_int = 11; +pub const ENOMEM: ::c_int = 12; +pub const EACCES: ::c_int = 13; +pub const EFAULT: ::c_int = 14; +pub const ENOTBLK: ::c_int = 15; +pub const EBUSY: ::c_int = 16; +pub const EEXIST: ::c_int = 17; +pub const EXDEV: ::c_int = 18; +pub const ENODEV: ::c_int = 19; +pub const ENOTDIR: ::c_int = 20; +pub const EISDIR: ::c_int = 21; +pub const EINVAL: ::c_int = 22; +pub const ENFILE: ::c_int = 23; +pub const EMFILE: ::c_int = 24; +pub const ENOTTY: ::c_int = 25; +pub const ETXTBSY: ::c_int = 26; +pub const EFBIG: ::c_int = 27; +pub const ENOSPC: ::c_int = 28; +pub const ESPIPE: ::c_int = 29; +pub const EROFS: ::c_int = 30; +pub const EMLINK: ::c_int = 31; +pub const EPIPE: ::c_int = 32; +pub const EDOM: ::c_int = 33; +pub const ERANGE: ::c_int = 34; +pub const EWOULDBLOCK: ::c_int = EAGAIN; + +pub const SCM_RIGHTS: ::c_int = 0x01; +pub const SCM_CREDENTIALS: ::c_int = 0x02; + +pub const IPPROTO_RAW: ::c_int = 255; + +pub const PROT_GROWSDOWN: ::c_int = 0x1000000; +pub const PROT_GROWSUP: ::c_int = 0x2000000; + +pub const MAP_TYPE: ::c_int = 0x000f; + +pub const MADV_NORMAL: ::c_int = 0; +pub const MADV_RANDOM: ::c_int = 1; +pub const MADV_SEQUENTIAL: ::c_int = 2; +pub const MADV_WILLNEED: ::c_int = 3; +pub const MADV_DONTNEED: ::c_int = 4; +pub const MADV_REMOVE: ::c_int = 9; +pub const MADV_DONTFORK: ::c_int = 10; +pub const MADV_DOFORK: ::c_int = 11; +pub const MADV_MERGEABLE: ::c_int = 12; +pub const MADV_UNMERGEABLE: ::c_int = 13; +pub const MADV_HWPOISON: ::c_int = 100; + +pub const IFF_UP: ::c_int = 0x1; +pub const IFF_BROADCAST: ::c_int = 0x2; +pub const IFF_DEBUG: ::c_int = 0x4; +pub const IFF_LOOPBACK: ::c_int = 0x8; +pub const IFF_POINTOPOINT: ::c_int = 0x10; +pub const IFF_NOTRAILERS: ::c_int = 0x20; +pub const IFF_RUNNING: ::c_int = 0x40; +pub const IFF_NOARP: ::c_int = 0x80; +pub const IFF_PROMISC: ::c_int = 0x100; +pub const IFF_ALLMULTI: ::c_int = 0x200; +pub const IFF_MASTER: ::c_int = 0x400; +pub const IFF_SLAVE: ::c_int = 0x800; +pub const IFF_MULTICAST: ::c_int = 0x1000; +pub const IFF_PORTSEL: ::c_int = 0x2000; +pub const IFF_AUTOMEDIA: ::c_int = 0x4000; +pub const IFF_DYNAMIC: ::c_int = 0x8000; + +pub const SOL_IP: ::c_int = 0; +pub const SOL_TCP: ::c_int = 6; +pub const SOL_IPV6: ::c_int = 41; +pub const SOL_ICMPV6: ::c_int = 58; +pub const SOL_RAW: ::c_int = 255; +pub const SOL_DECNET: ::c_int = 261; +pub const SOL_X25: ::c_int = 262; +pub const SOL_PACKET: ::c_int = 263; +pub const SOL_ATM: ::c_int = 264; +pub const SOL_AAL: ::c_int = 265; +pub const SOL_IRDA: ::c_int = 266; + +pub const AF_UNSPEC: ::c_int = 0; +pub const AF_UNIX: ::c_int = 1; +pub const AF_LOCAL: ::c_int = 1; +pub const AF_INET: ::c_int = 2; +pub const AF_AX25: ::c_int = 3; +pub const AF_IPX: ::c_int = 4; +pub const AF_APPLETALK: ::c_int = 5; +pub const AF_NETROM: ::c_int = 6; +pub const AF_BRIDGE: ::c_int = 7; +pub const AF_ATMPVC: ::c_int = 8; +pub const AF_X25: ::c_int = 9; +pub const AF_INET6: ::c_int = 10; +pub const AF_ROSE: ::c_int = 11; +pub const AF_DECnet: ::c_int = 12; +pub const AF_NETBEUI: ::c_int = 13; +pub const AF_SECURITY: ::c_int = 14; +pub const AF_KEY: ::c_int = 15; +pub const AF_NETLINK: ::c_int = 16; +pub const AF_ROUTE: ::c_int = AF_NETLINK; +pub const AF_PACKET: ::c_int = 17; +pub const AF_ASH: ::c_int = 18; +pub const AF_ECONET: ::c_int = 19; +pub const AF_ATMSVC: ::c_int = 20; +pub const AF_SNA: ::c_int = 22; +pub const AF_IRDA: ::c_int = 23; +pub const AF_PPPOX: ::c_int = 24; +pub const AF_WANPIPE: ::c_int = 25; +pub const AF_LLC: ::c_int = 26; +pub const AF_CAN: ::c_int = 29; +pub const AF_TIPC: ::c_int = 30; +pub const AF_BLUETOOTH: ::c_int = 31; +pub const AF_IUCV: ::c_int = 32; +pub const AF_RXRPC: ::c_int = 33; +pub const AF_ISDN: ::c_int = 34; +pub const AF_PHONET: ::c_int = 35; +pub const AF_IEEE802154: ::c_int = 36; +pub const AF_CAIF: ::c_int = 37; +pub const AF_ALG: ::c_int = 38; + +pub const PF_UNSPEC: ::c_int = AF_UNSPEC; +pub const PF_UNIX: ::c_int = AF_UNIX; +pub const PF_LOCAL: ::c_int = AF_LOCAL; +pub const PF_INET: ::c_int = AF_INET; +pub const PF_AX25: ::c_int = AF_AX25; +pub const PF_IPX: ::c_int = AF_IPX; +pub const PF_APPLETALK: ::c_int = AF_APPLETALK; +pub const PF_NETROM: ::c_int = AF_NETROM; +pub const PF_BRIDGE: ::c_int = AF_BRIDGE; +pub const PF_ATMPVC: ::c_int = AF_ATMPVC; +pub const PF_X25: ::c_int = AF_X25; +pub const PF_INET6: ::c_int = AF_INET6; +pub const PF_ROSE: ::c_int = AF_ROSE; +pub const PF_DECnet: ::c_int = AF_DECnet; +pub const PF_NETBEUI: ::c_int = AF_NETBEUI; +pub const PF_SECURITY: ::c_int = AF_SECURITY; +pub const PF_KEY: ::c_int = AF_KEY; +pub const PF_NETLINK: ::c_int = AF_NETLINK; +pub const PF_ROUTE: ::c_int = AF_ROUTE; +pub const PF_PACKET: ::c_int = AF_PACKET; +pub const PF_ASH: ::c_int = AF_ASH; +pub const PF_ECONET: ::c_int = AF_ECONET; +pub const PF_ATMSVC: ::c_int = AF_ATMSVC; +pub const PF_SNA: ::c_int = AF_SNA; +pub const PF_IRDA: ::c_int = AF_IRDA; +pub const PF_PPPOX: ::c_int = AF_PPPOX; +pub const PF_WANPIPE: ::c_int = AF_WANPIPE; +pub const PF_LLC: ::c_int = AF_LLC; +pub const PF_CAN: ::c_int = AF_CAN; +pub const PF_TIPC: ::c_int = AF_TIPC; +pub const PF_BLUETOOTH: ::c_int = AF_BLUETOOTH; +pub const PF_IUCV: ::c_int = AF_IUCV; +pub const PF_RXRPC: ::c_int = AF_RXRPC; +pub const PF_ISDN: ::c_int = AF_ISDN; +pub const PF_PHONET: ::c_int = AF_PHONET; +pub const PF_IEEE802154: ::c_int = AF_IEEE802154; +pub const PF_CAIF: ::c_int = AF_CAIF; +pub const PF_ALG: ::c_int = AF_ALG; + +pub const SOMAXCONN: ::c_int = 128; + +pub const MSG_OOB: ::c_int = 1; +pub const MSG_PEEK: ::c_int = 2; +pub const MSG_DONTROUTE: ::c_int = 4; +pub const MSG_CTRUNC: ::c_int = 8; +pub const MSG_TRUNC: ::c_int = 0x20; +pub const MSG_DONTWAIT: ::c_int = 0x40; +pub const MSG_EOR: ::c_int = 0x80; +pub const MSG_WAITALL: ::c_int = 0x100; +pub const MSG_FIN: ::c_int = 0x200; +pub const MSG_SYN: ::c_int = 0x400; +pub const MSG_CONFIRM: ::c_int = 0x800; +pub const MSG_RST: ::c_int = 0x1000; +pub const MSG_ERRQUEUE: ::c_int = 0x2000; +pub const MSG_NOSIGNAL: ::c_int = 0x4000; +pub const MSG_MORE: ::c_int = 0x8000; +pub const MSG_WAITFORONE: ::c_int = 0x10000; +pub const MSG_CMSG_CLOEXEC: ::c_int = 0x40000000; + +pub const SOCK_RAW: ::c_int = 3; +pub const IPPROTO_ICMP: ::c_int = 1; +pub const IPPROTO_ICMPV6: ::c_int = 58; +pub const IPPROTO_TCP: ::c_int = 6; +pub const IPPROTO_IP: ::c_int = 0; +pub const IPPROTO_IPV6: ::c_int = 41; +pub const IP_MULTICAST_TTL: ::c_int = 33; +pub const IP_MULTICAST_LOOP: ::c_int = 34; +pub const IP_TTL: ::c_int = 2; +pub const IP_HDRINCL: ::c_int = 3; +pub const IP_ADD_MEMBERSHIP: ::c_int = 35; +pub const IP_DROP_MEMBERSHIP: ::c_int = 36; + +pub const TCP_NODELAY: ::c_int = 1; +pub const TCP_MAXSEG: ::c_int = 2; +pub const TCP_CORK: ::c_int = 3; +pub const TCP_KEEPIDLE: ::c_int = 4; +pub const TCP_KEEPINTVL: ::c_int = 5; +pub const TCP_KEEPCNT: ::c_int = 6; +pub const TCP_SYNCNT: ::c_int = 7; +pub const TCP_LINGER2: ::c_int = 8; +pub const TCP_DEFER_ACCEPT: ::c_int = 9; +pub const TCP_WINDOW_CLAMP: ::c_int = 10; +pub const TCP_INFO: ::c_int = 11; +pub const TCP_QUICKACK: ::c_int = 12; +pub const TCP_CONGESTION: ::c_int = 13; + +pub const IPV6_MULTICAST_LOOP: ::c_int = 19; +pub const IPV6_V6ONLY: ::c_int = 26; + +pub const SO_DEBUG: ::c_int = 1; + +pub const SHUT_RD: ::c_int = 0; +pub const SHUT_WR: ::c_int = 1; +pub const SHUT_RDWR: ::c_int = 2; + +pub const LOCK_SH: ::c_int = 1; +pub const LOCK_EX: ::c_int = 2; +pub const LOCK_NB: ::c_int = 4; +pub const LOCK_UN: ::c_int = 8; + +pub const SS_ONSTACK: ::c_int = 1; +pub const SS_DISABLE: ::c_int = 2; + +pub const PATH_MAX: ::c_int = 4096; + +pub const FD_SETSIZE: usize = 1024; + +pub const EPOLLIN: ::c_int = 0x1; +pub const EPOLLPRI: ::c_int = 0x2; +pub const EPOLLOUT: ::c_int = 0x4; +pub const EPOLLRDNORM: ::c_int = 0x40; +pub const EPOLLRDBAND: ::c_int = 0x80; +pub const EPOLLWRNORM: ::c_int = 0x100; +pub const EPOLLWRBAND: ::c_int = 0x200; +pub const EPOLLMSG: ::c_int = 0x400; +pub const EPOLLERR: ::c_int = 0x8; +pub const EPOLLHUP: ::c_int = 0x10; +pub const EPOLLET: ::c_int = 0x80000000; + +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 MNT_DETACH: ::c_int = 0x2; +pub const MNT_EXPIRE: ::c_int = 0x4; + +pub const MNT_FORCE: ::c_int = 0x1; + +pub const Q_SYNC: ::c_int = 0x600; +pub const Q_QUOTAON: ::c_int = 0x100; +pub const Q_QUOTAOFF: ::c_int = 0x200; +pub const Q_GETQUOTA: ::c_int = 0x300; +pub const Q_SETQUOTA: ::c_int = 0x400; + +pub const TCIOFF: ::c_int = 2; +pub const TCION: ::c_int = 3; +pub const TCOOFF: ::c_int = 0; +pub const TCOON: ::c_int = 1; +pub const TCIFLUSH: ::c_int = 0; +pub const TCOFLUSH: ::c_int = 1; +pub const TCIOFLUSH: ::c_int = 2; +pub const NL0: ::c_int = 0x00000000; +pub const NL1: ::c_int = 0x00000100; +pub const TAB0: ::c_int = 0x00000000; +pub const CR0: ::c_int = 0x00000000; +pub const FF0: ::c_int = 0x00000000; +pub const BS0: ::c_int = 0x00000000; +pub const VT0: ::c_int = 0x00000000; +pub const VERASE: usize = 2; +pub const VKILL: usize = 3; +pub const VINTR: usize = 0; +pub const VQUIT: usize = 1; +pub const VLNEXT: usize = 15; +pub const IGNBRK: ::tcflag_t = 0x00000001; +pub const BRKINT: ::tcflag_t = 0x00000002; +pub const IGNPAR: ::tcflag_t = 0x00000004; +pub const PARMRK: ::tcflag_t = 0x00000008; +pub const INPCK: ::tcflag_t = 0x00000010; +pub const ISTRIP: ::tcflag_t = 0x00000020; +pub const INLCR: ::tcflag_t = 0x00000040; +pub const IGNCR: ::tcflag_t = 0x00000080; +pub const ICRNL: ::tcflag_t = 0x00000100; +pub const IXANY: ::tcflag_t = 0x00000800; +pub const IMAXBEL: ::tcflag_t = 0x00002000; +pub const OPOST: ::tcflag_t = 0x1; +pub const CS5: ::tcflag_t = 0x00000000; +pub const CRTSCTS: ::tcflag_t = 0x80000000; +pub const ECHO: ::tcflag_t = 0x00000008; + +pub const CLONE_VM: ::c_int = 0x100; +pub const CLONE_FS: ::c_int = 0x200; +pub const CLONE_FILES: ::c_int = 0x400; +pub const CLONE_SIGHAND: ::c_int = 0x800; +pub const CLONE_PTRACE: ::c_int = 0x2000; +pub const CLONE_VFORK: ::c_int = 0x4000; +pub const CLONE_PARENT: ::c_int = 0x8000; +pub const CLONE_THREAD: ::c_int = 0x10000; +pub const CLONE_NEWNS: ::c_int = 0x20000; +pub const CLONE_SYSVSEM: ::c_int = 0x40000; +pub const CLONE_SETTLS: ::c_int = 0x80000; +pub const CLONE_PARENT_SETTID: ::c_int = 0x100000; +pub const CLONE_CHILD_CLEARTID: ::c_int = 0x200000; +pub const CLONE_DETACHED: ::c_int = 0x400000; +pub const CLONE_UNTRACED: ::c_int = 0x800000; +pub const CLONE_CHILD_SETTID: ::c_int = 0x01000000; +pub const CLONE_NEWUTS: ::c_int = 0x04000000; +pub const CLONE_NEWIPC: ::c_int = 0x08000000; +pub const CLONE_NEWUSER: ::c_int = 0x10000000; +pub const CLONE_NEWPID: ::c_int = 0x20000000; +pub const CLONE_NEWNET: ::c_int = 0x40000000; +pub const CLONE_IO: ::c_int = 0x80000000; + +pub const WNOHANG: ::c_int = 0x00000001; +pub const WUNTRACED: ::c_int = 0x00000002; +pub const WSTOPPED: ::c_int = WUNTRACED; +pub const WEXITED: ::c_int = 0x00000004; +pub const WCONTINUED: ::c_int = 0x00000008; +pub const WNOWAIT: ::c_int = 0x01000000; + +pub const __WNOTHREAD: ::c_int = 0x20000000; +pub const __WALL: ::c_int = 0x40000000; +pub const __WCLONE: ::c_int = 0x80000000; + +pub const SPLICE_F_MOVE: ::c_uint = 0x01; +pub const SPLICE_F_NONBLOCK: ::c_uint = 0x02; +pub const SPLICE_F_MORE: ::c_uint = 0x04; +pub const SPLICE_F_GIFT: ::c_uint = 0x08; + +pub const RTLD_LOCAL: ::c_int = 0; + +pub const POSIX_FADV_NORMAL: ::c_int = 0; +pub const POSIX_FADV_RANDOM: ::c_int = 1; +pub const POSIX_FADV_SEQUENTIAL: ::c_int = 2; +pub const POSIX_FADV_WILLNEED: ::c_int = 3; + +pub const AT_FDCWD: ::c_int = -100; +pub const AT_SYMLINK_NOFOLLOW: ::c_int = 0x100; +pub const AT_REMOVEDIR: ::c_int = 0x200; +pub const AT_SYMLINK_FOLLOW: ::c_int = 0x400; + +pub const LOG_CRON: ::c_int = 9 << 3; +pub const LOG_AUTHPRIV: ::c_int = 10 << 3; +pub const LOG_FTP: ::c_int = 11 << 3; +pub const LOG_PERROR: ::c_int = 0x20; + +pub const PIPE_BUF: usize = 4096; + +pub const SI_LOAD_SHIFT: ::c_uint = 16; + +pub const SIGEV_SIGNAL: ::c_int = 0; +pub const SIGEV_NONE: ::c_int = 1; +pub const SIGEV_THREAD: ::c_int = 2; + +pub const P_ALL: idtype_t = 0; +pub const P_PID: idtype_t = 1; +pub const P_PGID: idtype_t = 2; + +pub const UTIME_OMIT: c_long = 1073741822; +pub const UTIME_NOW: c_long = 1073741823; + +pub const L_tmpnam: ::c_uint = 20; +pub const _PC_LINK_MAX: ::c_int = 0; +pub const _PC_MAX_CANON: ::c_int = 1; +pub const _PC_MAX_INPUT: ::c_int = 2; +pub const _PC_NAME_MAX: ::c_int = 3; +pub const _PC_PATH_MAX: ::c_int = 4; +pub const _PC_PIPE_BUF: ::c_int = 5; +pub const _PC_CHOWN_RESTRICTED: ::c_int = 6; +pub const _PC_NO_TRUNC: ::c_int = 7; +pub const _PC_VDISABLE: ::c_int = 8; + +pub const _SC_ARG_MAX: ::c_int = 0; +pub const _SC_CHILD_MAX: ::c_int = 1; +pub const _SC_CLK_TCK: ::c_int = 2; +pub const _SC_NGROUPS_MAX: ::c_int = 3; +pub const _SC_OPEN_MAX: ::c_int = 4; +pub const _SC_STREAM_MAX: ::c_int = 5; +pub const _SC_TZNAME_MAX: ::c_int = 6; +pub const _SC_JOB_CONTROL: ::c_int = 7; +pub const _SC_SAVED_IDS: ::c_int = 8; +pub const _SC_REALTIME_SIGNALS: ::c_int = 9; +pub const _SC_PRIORITY_SCHEDULING: ::c_int = 10; +pub const _SC_TIMERS: ::c_int = 11; +pub const _SC_ASYNCHRONOUS_IO: ::c_int = 12; +pub const _SC_PRIORITIZED_IO: ::c_int = 13; +pub const _SC_SYNCHRONIZED_IO: ::c_int = 14; +pub const _SC_FSYNC: ::c_int = 15; +pub const _SC_MAPPED_FILES: ::c_int = 16; +pub const _SC_MEMLOCK: ::c_int = 17; +pub const _SC_MEMLOCK_RANGE: ::c_int = 18; +pub const _SC_MEMORY_PROTECTION: ::c_int = 19; +pub const _SC_MESSAGE_PASSING: ::c_int = 20; +pub const _SC_SEMAPHORES: ::c_int = 21; +pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 22; +pub const _SC_AIO_LISTIO_MAX: ::c_int = 23; +pub const _SC_AIO_MAX: ::c_int = 24; +pub const _SC_AIO_PRIO_DELTA_MAX: ::c_int = 25; +pub const _SC_DELAYTIMER_MAX: ::c_int = 26; +pub const _SC_MQ_OPEN_MAX: ::c_int = 27; +pub const _SC_MQ_PRIO_MAX: ::c_int = 28; +pub const _SC_VERSION: ::c_int = 29; +pub const _SC_PAGESIZE: ::c_int = 30; +pub const _SC_PAGE_SIZE: ::c_int = _SC_PAGESIZE; +pub const _SC_RTSIG_MAX: ::c_int = 31; +pub const _SC_SEM_NSEMS_MAX: ::c_int = 32; +pub const _SC_SEM_VALUE_MAX: ::c_int = 33; +pub const _SC_SIGQUEUE_MAX: ::c_int = 34; +pub const _SC_TIMER_MAX: ::c_int = 35; +pub const _SC_BC_BASE_MAX: ::c_int = 36; +pub const _SC_BC_DIM_MAX: ::c_int = 37; +pub const _SC_BC_SCALE_MAX: ::c_int = 38; +pub const _SC_BC_STRING_MAX: ::c_int = 39; +pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 40; +pub const _SC_EXPR_NEST_MAX: ::c_int = 42; +pub const _SC_LINE_MAX: ::c_int = 43; +pub const _SC_RE_DUP_MAX: ::c_int = 44; +pub const _SC_2_VERSION: ::c_int = 46; +pub const _SC_2_C_BIND: ::c_int = 47; +pub const _SC_2_C_DEV: ::c_int = 48; +pub const _SC_2_FORT_DEV: ::c_int = 49; +pub const _SC_2_FORT_RUN: ::c_int = 50; +pub const _SC_2_SW_DEV: ::c_int = 51; +pub const _SC_2_LOCALEDEF: ::c_int = 52; +pub const _SC_IOV_MAX: ::c_int = 60; +pub const _SC_THREADS: ::c_int = 67; +pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 68; +pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 69; +pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 70; +pub const _SC_LOGIN_NAME_MAX: ::c_int = 71; +pub const _SC_TTY_NAME_MAX: ::c_int = 72; +pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 73; +pub const _SC_THREAD_KEYS_MAX: ::c_int = 74; +pub const _SC_THREAD_STACK_MIN: ::c_int = 75; +pub const _SC_THREAD_THREADS_MAX: ::c_int = 76; +pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 77; +pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 78; +pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 79; +pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 80; +pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 81; +pub const _SC_NPROCESSORS_ONLN: ::c_int = 84; +pub const _SC_ATEXIT_MAX: ::c_int = 87; +pub const _SC_XOPEN_VERSION: ::c_int = 89; +pub const _SC_XOPEN_XCU_VERSION: ::c_int = 90; +pub const _SC_XOPEN_UNIX: ::c_int = 91; +pub const _SC_XOPEN_CRYPT: ::c_int = 92; +pub const _SC_XOPEN_ENH_I18N: ::c_int = 93; +pub const _SC_XOPEN_SHM: ::c_int = 94; +pub const _SC_2_CHAR_TERM: ::c_int = 95; +pub const _SC_2_UPE: ::c_int = 97; +pub const _SC_XBS5_ILP32_OFF32: ::c_int = 125; +pub const _SC_XBS5_ILP32_OFFBIG: ::c_int = 126; +pub const _SC_XBS5_LPBIG_OFFBIG: ::c_int = 128; +pub const _SC_XOPEN_LEGACY: ::c_int = 129; +pub const _SC_XOPEN_REALTIME: ::c_int = 130; +pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 131; +pub const _SC_HOST_NAME_MAX: ::c_int = 180; + +pub const RLIM_SAVED_MAX: ::rlim_t = RLIM_INFINITY; +pub const RLIM_SAVED_CUR: ::rlim_t = RLIM_INFINITY; + +pub const GLOB_ERR: ::c_int = 1 << 0; +pub const GLOB_MARK: ::c_int = 1 << 1; +pub const GLOB_NOSORT: ::c_int = 1 << 2; +pub const GLOB_DOOFFS: ::c_int = 1 << 3; +pub const GLOB_NOCHECK: ::c_int = 1 << 4; +pub const GLOB_APPEND: ::c_int = 1 << 5; +pub const GLOB_NOESCAPE: ::c_int = 1 << 6; + +pub const GLOB_NOSPACE: ::c_int = 1; +pub const GLOB_ABORTED: ::c_int = 2; +pub const GLOB_NOMATCH: ::c_int = 3; + +pub const POSIX_MADV_NORMAL: ::c_int = 0; +pub const POSIX_MADV_RANDOM: ::c_int = 1; +pub const POSIX_MADV_SEQUENTIAL: ::c_int = 2; +pub const POSIX_MADV_WILLNEED: ::c_int = 3; + +pub const S_IEXEC: mode_t = 64; +pub const S_IWRITE: mode_t = 128; +pub const S_IREAD: mode_t = 256; + +pub const F_LOCK: ::c_int = 1; +pub const F_TEST: ::c_int = 3; +pub const F_TLOCK: ::c_int = 2; +pub const F_ULOCK: ::c_int = 0; + +pub const ST_RDONLY: ::c_ulong = 1; +pub const ST_NOSUID: ::c_ulong = 2; +pub const ST_NODEV: ::c_ulong = 4; +pub const ST_NOEXEC: ::c_ulong = 8; +pub const ST_SYNCHRONOUS: ::c_ulong = 16; +pub const ST_MANDLOCK: ::c_ulong = 64; +pub const ST_WRITE: ::c_ulong = 128; +pub const ST_APPEND: ::c_ulong = 256; +pub const ST_IMMUTABLE: ::c_ulong = 512; +pub const ST_NOATIME: ::c_ulong = 1024; +pub const ST_NODIRATIME: ::c_ulong = 2048; + +pub const RTLD_NEXT: *mut ::c_void = -1i64 as *mut ::c_void; +pub const RTLD_DEFAULT: *mut ::c_void = 0i64 as *mut ::c_void; +pub const RTLD_NODELETE: ::c_int = 0x1000; +pub const RTLD_NOW: ::c_int = 0x2; + +pub const TCP_MD5SIG: ::c_int = 14; + +pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { + __align: [], + size: [0; __SIZEOF_PTHREAD_MUTEX_T], +}; +pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { + __align: [], + size: [0; __SIZEOF_PTHREAD_COND_T], +}; +pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { + __align: [], + size: [0; __SIZEOF_PTHREAD_RWLOCK_T], +}; +pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; +pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1; +pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2; +pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_NORMAL; +pub const __SIZEOF_PTHREAD_COND_T: usize = 48; + +pub const SCHED_OTHER: ::c_int = 0; +pub const SCHED_FIFO: ::c_int = 1; +pub const SCHED_RR: ::c_int = 2; +pub const SCHED_BATCH: ::c_int = 3; +pub const SCHED_IDLE: ::c_int = 5; + +// System V IPC +pub const IPC_PRIVATE: ::key_t = 0; + +pub const IPC_CREAT: ::c_int = 0o1000; +pub const IPC_EXCL: ::c_int = 0o2000; +pub const IPC_NOWAIT: ::c_int = 0o4000; + +pub const IPC_RMID: ::c_int = 0; +pub const IPC_SET: ::c_int = 1; +pub const IPC_STAT: ::c_int = 2; +pub const IPC_INFO: ::c_int = 3; +pub const MSG_STAT: ::c_int = 11; +pub const MSG_INFO: ::c_int = 12; + +pub const MSG_NOERROR: ::c_int = 0o10000; +pub const MSG_EXCEPT: ::c_int = 0o20000; + +pub const SHM_R: ::c_int = 0o400; +pub const SHM_W: ::c_int = 0o200; + +pub const SHM_RDONLY: ::c_int = 0o10000; +pub const SHM_RND: ::c_int = 0o20000; +pub const SHM_REMAP: ::c_int = 0o40000; + +pub const SHM_LOCK: ::c_int = 11; +pub const SHM_UNLOCK: ::c_int = 12; + +pub const SHM_HUGETLB: ::c_int = 0o4000; +pub const SHM_NORESERVE: ::c_int = 0o10000; + +pub const EPOLLRDHUP: ::c_int = 0x2000; +pub const EPOLLONESHOT: ::c_int = 0x40000000; + +pub const QFMT_VFS_OLD: ::c_int = 1; +pub const QFMT_VFS_V0: ::c_int = 2; + +pub const EFD_SEMAPHORE: ::c_int = 0x1; + +pub const LOG_NFACILITIES: ::c_int = 24; + +pub const SEM_FAILED: *mut ::sem_t = 0 as *mut sem_t; + +pub const RB_AUTOBOOT: ::c_int = 0x01234567u32 as i32; +pub const RB_HALT_SYSTEM: ::c_int = 0xcdef0123u32 as i32; +pub const RB_ENABLE_CAD: ::c_int = 0x89abcdefu32 as i32; +pub const RB_DISABLE_CAD: ::c_int = 0x00000000u32 as i32; +pub const RB_POWER_OFF: ::c_int = 0x4321fedcu32 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; + +pub const EAI_SYSTEM: ::c_int = -11; + +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 ABDAY_1: ::nl_item = 0x300; +pub const ABDAY_2: ::nl_item = 0x301; +pub const ABDAY_3: ::nl_item = 0x302; +pub const ABDAY_4: ::nl_item = 0x303; +pub const ABDAY_5: ::nl_item = 0x304; +pub const ABDAY_6: ::nl_item = 0x305; +pub const ABDAY_7: ::nl_item = 0x306; + +pub const DAY_1: ::nl_item = 0x307; +pub const DAY_2: ::nl_item = 0x308; +pub const DAY_3: ::nl_item = 0x309; +pub const DAY_4: ::nl_item = 0x30A; +pub const DAY_5: ::nl_item = 0x30B; +pub const DAY_6: ::nl_item = 0x30C; +pub const DAY_7: ::nl_item = 0x30D; + +pub const ABMON_1: ::nl_item = 0x30E; +pub const ABMON_2: ::nl_item = 0x30F; +pub const ABMON_3: ::nl_item = 0x310; +pub const ABMON_4: ::nl_item = 0x311; +pub const ABMON_5: ::nl_item = 0x312; +pub const ABMON_6: ::nl_item = 0x313; +pub const ABMON_7: ::nl_item = 0x314; +pub const ABMON_8: ::nl_item = 0x315; +pub const ABMON_9: ::nl_item = 0x316; +pub const ABMON_10: ::nl_item = 0x317; +pub const ABMON_11: ::nl_item = 0x318; +pub const ABMON_12: ::nl_item = 0x319; + +pub const MON_1: ::nl_item = 0x31A; +pub const MON_2: ::nl_item = 0x31B; +pub const MON_3: ::nl_item = 0x31C; +pub const MON_4: ::nl_item = 0x31D; +pub const MON_5: ::nl_item = 0x31E; +pub const MON_6: ::nl_item = 0x31F; +pub const MON_7: ::nl_item = 0x320; +pub const MON_8: ::nl_item = 0x321; +pub const MON_9: ::nl_item = 0x322; +pub const MON_10: ::nl_item = 0x323; +pub const MON_11: ::nl_item = 0x324; +pub const MON_12: ::nl_item = 0x325; + +pub const AM_STR: ::nl_item = 0x326; +pub const PM_STR: ::nl_item = 0x327; + +pub const D_T_FMT: ::nl_item = 0x328; +pub const D_FMT: ::nl_item = 0x329; +pub const T_FMT: ::nl_item = 0x32A; +pub const T_FMT_AMPM: ::nl_item = 0x32B; + +pub const ERA: ::nl_item = 0x32C; +pub const ERA_D_FMT: ::nl_item = 0x32E; +pub const ALT_DIGITS: ::nl_item = 0x32F; +pub const ERA_D_T_FMT: ::nl_item = 0x330; +pub const ERA_T_FMT: ::nl_item = 0x331; + +pub const CODESET: ::nl_item = 10; + +pub const CRNCYSTR: ::nl_item = 0x215; + +pub const RADIXCHAR: ::nl_item = 0x100; +pub const THOUSEP: ::nl_item = 0x101; + +pub const NOEXPR: ::nl_item = 0x501; +pub const YESSTR: ::nl_item = 0x502; +pub const NOSTR: ::nl_item = 0x503; + +pub const FILENAME_MAX: ::c_uint = 4095; + +pub const AF_MAX: ::c_int = 39; + +f! { + pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () { + let fd = fd as usize; + let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; + (*set).fds_bits[fd / size] &= !(1 << (fd % size)); + return + } + + pub fn FD_ISSET(fd: ::c_int, set: *mut fd_set) -> bool { + let fd = fd as usize; + let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; + return ((*set).fds_bits[fd / size] & (1 << (fd % size))) != 0 + } + + pub fn FD_SET(fd: ::c_int, set: *mut fd_set) -> () { + let fd = fd as usize; + let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; + (*set).fds_bits[fd / size] |= 1 << (fd % size); + return + } + + pub fn FD_ZERO(set: *mut fd_set) -> () { + for slot in (*set).fds_bits.iter_mut() { + *slot = 0; + } + } + + pub fn WIFSTOPPED(status: ::c_int) -> bool { + (status & 0xff) == 0x7f + } + + pub fn WSTOPSIG(status: ::c_int) -> ::c_int { + (status >> 8) & 0xff + } + + pub fn WIFCONTINUED(status: ::c_int) -> bool { + status == 0xffff + } + + pub fn WIFSIGNALED(status: ::c_int) -> bool { + ((status & 0x7f) + 1) as i8 >= 2 + } + + pub fn WTERMSIG(status: ::c_int) -> ::c_int { + status & 0x7f + } + + pub fn WIFEXITED(status: ::c_int) -> bool { + (status & 0x7f) == 0 + } + + pub fn WEXITSTATUS(status: ::c_int) -> ::c_int { + (status >> 8) & 0xff + } + + pub fn WCOREDUMP(status: ::c_int) -> bool { + (status & 0x80) != 0 + } + + pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { + for slot in cpuset.bits.iter_mut() { + *slot = 0; + } + } + + pub fn CPU_SET(cpu: usize, cpuset: &mut cpu_set_t) -> () { + let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc + let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); + cpuset.bits[idx] |= 1 << offset; + () + } + + pub fn CPU_CLR(cpu: usize, cpuset: &mut cpu_set_t) -> () { + let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc + let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); + cpuset.bits[idx] &= !(1 << offset); + () + } + + pub fn CPU_ISSET(cpu: usize, cpuset: &cpu_set_t) -> bool { + let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]); + let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); + 0 != (cpuset.bits[idx] & (1 << offset)) + } + + pub fn CPU_EQUAL(set1: &cpu_set_t, set2: &cpu_set_t) -> bool { + set1.bits == set2.bits + } +} + +extern { + pub fn getpwnam_r(name: *const ::c_char, + pwd: *mut passwd, + buf: *mut ::c_char, + buflen: ::size_t, + result: *mut *mut passwd) -> ::c_int; + pub fn getpwuid_r(uid: ::uid_t, + pwd: *mut passwd, + buf: *mut ::c_char, + buflen: ::size_t, + result: *mut *mut passwd) -> ::c_int; + pub fn fdatasync(fd: ::c_int) -> ::c_int; + pub fn mincore(addr: *mut ::c_void, len: ::size_t, + vec: *mut ::c_uchar) -> ::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_nanosleep(clk_id: clockid_t, + 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; + 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, + stackaddr: *mut *mut ::c_void, + stacksize: *mut ::size_t) -> ::c_int; + 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; + pub fn sched_getscheduler(pid: ::pid_t) -> ::c_int; + pub fn sched_get_priority_max(policy: ::c_int) -> ::c_int; + pub fn sched_get_priority_min(policy: ::c_int) -> ::c_int; + pub fn epoll_create(size: ::c_int) -> ::c_int; + pub fn epoll_create1(flags: ::c_int) -> ::c_int; + pub fn epoll_ctl(epfd: ::c_int, + op: ::c_int, + fd: ::c_int, + event: *mut epoll_event) -> ::c_int; + pub fn epoll_wait(epfd: ::c_int, + events: *mut epoll_event, + maxevents: ::c_int, + timeout: ::c_int) -> ::c_int; + pub fn pipe2(fds: *mut ::c_int, flags: ::c_int) -> ::c_int; + pub fn mount(src: *const ::c_char, + target: *const ::c_char, + fstype: *const ::c_char, + flags: ::c_ulong, + data: *const ::c_void) -> ::c_int; + pub fn umount(target: *const ::c_char) -> ::c_int; + pub fn umount2(target: *const ::c_char, flags: ::c_int) -> ::c_int; + pub fn clone(cb: extern fn(*mut ::c_void) -> ::c_int, + child_stack: *mut ::c_void, + flags: ::c_int, + arg: *mut ::c_void, ...) -> ::c_int; + pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int; + pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int; + pub fn memrchr(cx: *const ::c_void, + c: ::c_int, + n: ::size_t) -> *mut ::c_void; + pub fn syscall(num: ::c_long, ...) -> ::c_long; + pub fn sendfile(out_fd: ::c_int, + in_fd: ::c_int, + offset: *mut off_t, + count: ::size_t) -> ::ssize_t; + pub fn splice(fd_in: ::c_int, + off_in: *mut ::loff_t, + fd_out: ::c_int, + off_out: *mut ::loff_t, + len: ::size_t, + flags: ::c_uint) -> ::ssize_t; + pub fn tee(fd_in: ::c_int, + fd_out: ::c_int, + len: ::size_t, + flags: ::c_uint) -> ::ssize_t; + pub fn vmsplice(fd: ::c_int, + iov: *const ::iovec, + nr_segs: ::size_t, + flags: ::c_uint) -> ::ssize_t; + + pub fn posix_fadvise(fd: ::c_int, offset: ::off_t, len: ::off_t, + advise: ::c_int) -> ::c_int; + pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int; + pub fn utimensat(dirfd: ::c_int, path: *const ::c_char, + times: *const ::timespec, flag: ::c_int) -> ::c_int; + pub fn duplocale(base: ::locale_t) -> ::locale_t; + pub fn freelocale(loc: ::locale_t); + pub fn newlocale(mask: ::c_int, + locale: *const ::c_char, + base: ::locale_t) -> ::locale_t; + pub fn uselocale(loc: ::locale_t) -> ::locale_t; + pub fn creat64(path: *const c_char, mode: mode_t) -> ::c_int; + pub fn fstat64(fildes: ::c_int, buf: *mut stat64) -> ::c_int; + pub fn ftruncate64(fd: ::c_int, length: off64_t) -> ::c_int; + pub fn getrlimit64(resource: ::c_int, rlim: *mut rlimit64) -> ::c_int; + pub fn lseek64(fd: ::c_int, offset: off64_t, whence: ::c_int) -> off64_t; + pub fn lstat64(path: *const c_char, buf: *mut stat64) -> ::c_int; + pub fn mmap64(addr: *mut ::c_void, + len: ::size_t, + prot: ::c_int, + flags: ::c_int, + fd: ::c_int, + offset: off64_t) + -> *mut ::c_void; + pub fn open64(path: *const c_char, oflag: ::c_int, ...) -> ::c_int; + pub fn openat64(fd: ::c_int, + path: *const c_char, + oflag: ::c_int, ...) -> ::c_int; + pub fn pread64(fd: ::c_int, buf: *mut ::c_void, count: ::size_t, + offset: off64_t) -> ::ssize_t; + pub fn pwrite64(fd: ::c_int, buf: *const ::c_void, count: ::size_t, + offset: off64_t) -> ::ssize_t; + pub fn readdir64(dirp: *mut ::DIR) -> *mut ::dirent64; + pub fn readdir64_r(dirp: *mut ::DIR, entry: *mut ::dirent64, + result: *mut *mut ::dirent64) -> ::c_int; + pub fn setrlimit64(resource: ::c_int, rlim: *const rlimit64) -> ::c_int; + pub fn stat64(path: *const c_char, buf: *mut stat64) -> ::c_int; + pub fn truncate64(path: *const c_char, length: off64_t) -> ::c_int; + pub fn eventfd(init: ::c_uint, flags: ::c_int) -> ::c_int; + + pub fn fdopendir(fd: ::c_int) -> *mut ::DIR; + + pub fn mknodat(dirfd: ::c_int, pathname: *const ::c_char, + mode: ::mode_t, dev: dev_t) -> ::c_int; + pub fn ppoll(fds: *mut ::pollfd, + nfds: nfds_t, + timeout: *const ::timespec, + sigmask: *const sigset_t) -> ::c_int; + pub fn pthread_condattr_getclock(attr: *const pthread_condattr_t, + clock_id: *mut clockid_t) -> ::c_int; + pub fn pthread_condattr_setclock(attr: *mut pthread_condattr_t, + clock_id: clockid_t) -> ::c_int; + pub fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, + pshared: ::c_int) -> ::c_int; + pub fn pthread_condattr_getpshared(attr: *const pthread_condattr_t, + pshared: *mut ::c_int) -> ::c_int; + pub fn sched_getaffinity(pid: ::pid_t, + cpusetsize: ::size_t, + cpuset: *mut cpu_set_t) -> ::c_int; + pub fn sched_setaffinity(pid: ::pid_t, + cpusetsize: ::size_t, + cpuset: *const cpu_set_t) -> ::c_int; + pub fn unshare(flags: ::c_int) -> ::c_int; + pub fn sem_timedwait(sem: *mut sem_t, + abstime: *const ::timespec) -> ::c_int; + pub fn accept4(fd: ::c_int, addr: *mut ::sockaddr, len: *mut ::socklen_t, + flg: ::c_int) -> ::c_int; + pub fn pthread_mutex_timedlock(lock: *mut pthread_mutex_t, + abstime: *const ::timespec) -> ::c_int; + pub fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, + pshared: ::c_int) -> ::c_int; + pub fn pthread_mutexattr_getpshared(attr: *const pthread_mutexattr_t, + pshared: *mut ::c_int) -> ::c_int; + pub fn ptsname_r(fd: ::c_int, + buf: *mut ::c_char, + buflen: ::size_t) -> ::c_int; + pub fn clearenv() -> ::c_int; + pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t, + options: ::c_int) -> ::c_int; + + pub fn lutimes(file: *const ::c_char, times: *const ::timeval) -> ::c_int; + + pub fn setpwent(); + pub fn getpwent() -> *mut passwd; + pub fn setspent(); + pub fn endspent(); + pub fn getspent() -> *mut spwd; + pub fn getspnam(__name: *const ::c_char) -> *mut spwd; + + pub fn shm_open(name: *const c_char, oflag: ::c_int, + mode: mode_t) -> ::c_int; + + // System V IPC + pub fn shmget(key: ::key_t, size: ::size_t, shmflg: ::c_int) -> ::c_int; + pub fn shmat(shmid: ::c_int, + shmaddr: *const ::c_void, + shmflg: ::c_int) -> *mut ::c_void; + pub fn shmdt(shmaddr: *const ::c_void) -> ::c_int; + pub fn shmctl(shmid: ::c_int, + cmd: ::c_int, + buf: *mut ::shmid_ds) -> ::c_int; + pub fn ftok(pathname: *const ::c_char, proj_id: ::c_int) -> ::key_t; + pub fn msgctl(msqid: ::c_int, cmd: ::c_int, buf: *mut msqid_ds) -> ::c_int; + pub fn msgget(key: ::key_t, msgflg: ::c_int) -> ::c_int; + pub fn msgrcv(msqid: ::c_int, msgp: *mut ::c_void, msgsz: ::size_t, + msgtyp: ::c_long, msgflg: ::c_int) -> ::ssize_t; + pub fn msgsnd(msqid: ::c_int, msgp: *const ::c_void, msgsz: ::size_t, + msgflg: ::c_int) -> ::c_int; + + pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) + -> ::c_int; + pub fn __errno_location() -> *mut ::c_int; + + pub fn fopen64(filename: *const c_char, + mode: *const c_char) -> *mut ::FILE; + pub fn freopen64(filename: *const c_char, mode: *const c_char, + file: *mut ::FILE) -> *mut ::FILE; + pub fn tmpfile64() -> *mut ::FILE; + pub fn fgetpos64(stream: *mut ::FILE, ptr: *mut fpos64_t) -> ::c_int; + pub fn fsetpos64(stream: *mut ::FILE, ptr: *const fpos64_t) -> ::c_int; + pub fn fseeko64(stream: *mut ::FILE, + offset: ::off64_t, + whence: ::c_int) -> ::c_int; + pub fn ftello64(stream: *mut ::FILE) -> ::off64_t; + pub fn readahead(fd: ::c_int, offset: ::off64_t, + count: ::size_t) -> ::ssize_t; + pub fn getxattr(path: *const c_char, name: *const c_char, + value: *mut ::c_void, size: ::size_t) -> ::ssize_t; + pub fn lgetxattr(path: *const c_char, name: *const c_char, + value: *mut ::c_void, size: ::size_t) -> ::ssize_t; + pub fn fgetxattr(filedes: ::c_int, name: *const c_char, + value: *mut ::c_void, size: ::size_t) -> ::ssize_t; + pub fn setxattr(path: *const c_char, name: *const c_char, + value: *const ::c_void, size: ::size_t, + flags: ::c_int) -> ::c_int; + pub fn lsetxattr(path: *const c_char, name: *const c_char, + value: *const ::c_void, size: ::size_t, + flags: ::c_int) -> ::c_int; + pub fn fsetxattr(filedes: ::c_int, name: *const c_char, + value: *const ::c_void, size: ::size_t, + flags: ::c_int) -> ::c_int; + pub fn listxattr(path: *const c_char, list: *mut c_char, + size: ::size_t) -> ::ssize_t; + pub fn llistxattr(path: *const c_char, list: *mut c_char, + size: ::size_t) -> ::ssize_t; + pub fn flistxattr(filedes: ::c_int, list: *mut c_char, + size: ::size_t) -> ::ssize_t; + pub fn removexattr(path: *const c_char, name: *const c_char) -> ::c_int; + pub fn lremovexattr(path: *const c_char, name: *const c_char) -> ::c_int; + pub fn fremovexattr(filedes: ::c_int, name: *const c_char) -> ::c_int; + pub fn signalfd(fd: ::c_int, + mask: *const ::sigset_t, + flags: ::c_int) -> ::c_int; + pub fn quotactl(cmd: ::c_int, + special: *const ::c_char, + id: ::c_int, + data: *mut ::c_char) -> ::c_int; + pub fn mq_open(name: *const ::c_char, oflag: ::c_int, ...) -> ::mqd_t; + pub fn mq_close(mqd: ::mqd_t) -> ::c_int; + pub fn mq_unlink(name: *const ::c_char) -> ::c_int; + pub fn mq_receive(mqd: ::mqd_t, + msg_ptr: *mut ::c_char, + msg_len: ::size_t, + msq_prio: *mut ::c_uint) -> ::ssize_t; + pub fn mq_send(mqd: ::mqd_t, + msg_ptr: *const ::c_char, + msg_len: ::size_t, + msq_prio: ::c_uint) -> ::c_int; + pub fn mq_getattr(mqd: ::mqd_t, attr: *mut ::mq_attr) -> ::c_int; + pub fn mq_setattr(mqd: ::mqd_t, + newattr: *const ::mq_attr, + oldattr: *mut ::mq_attr) -> ::c_int; + pub fn epoll_pwait(epfd: ::c_int, + events: *mut ::epoll_event, + maxevents: ::c_int, + timeout: ::c_int, + sigmask: *const ::sigset_t) -> ::c_int; + pub fn sethostname(name: *const ::c_char, len: ::size_t) -> ::c_int; + pub fn sigtimedwait(set: *const sigset_t, + info: *mut siginfo_t, + timeout: *const ::timespec) -> ::c_int; + pub fn sigwaitinfo(set: *const sigset_t, + info: *mut siginfo_t) -> ::c_int; + pub fn nl_langinfo_l(item: ::nl_item, locale: ::locale_t) -> *mut ::c_char; + pub fn prlimit(pid: ::pid_t, resource: ::c_int, new_limit: *const ::rlimit, + old_limit: *mut ::rlimit) -> ::c_int; + pub fn prlimit64(pid: ::pid_t, + resource: ::c_int, + new_limit: *const ::rlimit64, + old_limit: *mut ::rlimit64) -> ::c_int; + pub fn reboot(how_to: ::c_int) -> ::c_int; + pub fn setfsgid(gid: ::gid_t) -> ::c_int; + pub fn setfsuid(uid: ::uid_t) -> ::c_int; + pub fn setresgid(rgid: ::gid_t, egid: ::gid_t, sgid: ::gid_t) -> ::c_int; + pub fn setresuid(ruid: ::uid_t, euid: ::uid_t, suid: ::uid_t) -> ::c_int; + + // Not available now on Android + pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char, + mode: ::mode_t) -> ::c_int; + pub fn if_nameindex() -> *mut if_nameindex; + pub fn if_freenameindex(ptr: *mut if_nameindex); + pub fn sync_file_range(fd: ::c_int, offset: ::off64_t, + 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; + + pub fn glob(pattern: *const c_char, + flags: ::c_int, + errfunc: Option ::c_int>, + pglob: *mut ::glob_t) -> ::c_int; + pub fn globfree(pglob: *mut ::glob_t); + + pub fn shm_unlink(name: *const ::c_char) -> ::c_int; + + pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long); + + pub fn telldir(dirp: *mut ::DIR) -> ::c_long; + pub fn madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) + -> ::c_int; + + pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int; + + pub fn recvfrom(socket: ::c_int, buf: *mut ::c_void, len: ::size_t, + flags: ::c_int, addr: *mut ::sockaddr, + addrlen: *mut ::socklen_t) -> ::ssize_t; + pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char; + + pub fn bind(socket: ::c_int, address: *const ::sockaddr, + address_len: ::socklen_t) -> ::c_int; + + pub fn writev(fd: ::c_int, + iov: *const ::iovec, + iovcnt: ::c_int) -> ::ssize_t; + pub fn readv(fd: ::c_int, + iov: *const ::iovec, + iovcnt: ::c_int) -> ::ssize_t; + + pub fn sendmsg(fd: ::c_int, + msg: *const ::msghdr, + flags: ::c_int) -> ::ssize_t; + pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int) + -> ::ssize_t; +} + +cfg_if! { + if #[cfg(target_arch = "mips")] { + mod mips; + pub use self::mips::*; + } else if #[cfg(target_arch = "x86_64")] { + mod x86_64; + pub use self::x86_64::*; + } else { + pub use unsupported_target; + } +} + diff --git a/src/liblibc/src/unix/uclibc/x86_64/mod.rs b/src/liblibc/src/unix/uclibc/x86_64/mod.rs new file mode 100644 index 0000000000..2722201347 --- /dev/null +++ b/src/liblibc/src/unix/uclibc/x86_64/mod.rs @@ -0,0 +1,312 @@ +//! Definitions for l4re-uclibc on 64bit systems + +pub type blkcnt_t = i64; +pub type blksize_t = i64; +pub type c_char = u8; +pub type c_long = i64; +pub type c_ulong = u64; +pub type fsblkcnt_t = ::c_ulong; +pub type fsfilcnt_t = ::c_ulong; +pub type fsword_t = ::c_long; +pub type ino_t = ::c_ulong; +pub type nlink_t = ::c_uint; +pub type off_t = ::c_long; +pub type rlim_t = c_ulong; +pub type rlim64_t = u64; +pub type suseconds_t = ::c_long; +pub type time_t = ::c_int; +pub type wchar_t = ::c_int; + +// ToDo, used? +//pub type d_ino = ::c_ulong; +pub type nfds_t = ::c_ulong; + +s! { + // ------------------------------------------------------------ + // networking + pub struct in_addr { + pub s_addr: in_addr_t, + } + + pub struct in6_addr { + pub s6_addr: [u8; 16], + __align: [u32; 0], + } + + pub struct sockaddr { + pub sa_family: sa_family_t, + pub sa_data: [::c_char; 14], + } + + pub struct sockaddr_in { + pub sin_family: sa_family_t, + pub sin_port: ::in_port_t, + pub sin_addr: ::in_addr, + pub sin_zero: [u8; 8], + } + + pub struct sockaddr_in6 { + pub sin6_family: sa_family_t, + pub sin6_port: in_port_t, + pub sin6_flowinfo: u32, + pub sin6_addr: ::in6_addr, + pub sin6_scope_id: u32, + } + + // ------------------------------------------------------------ + // definitions below are *unverified* and might **break** the software + pub struct stat { // ToDo + pub st_dev: ::c_ulong, + st_pad1: [::c_long; 2], + 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: u64, + pub st_pad2: [u64; 1], + pub st_size: off_t, + st_pad3: ::c_long, + pub st_atime: ::time_t, + pub st_atime_nsec: ::c_long, + pub st_mtime: ::time_t, + pub st_mtime_nsec: ::c_long, + pub st_ctime: ::time_t, + pub st_ctime_nsec: ::c_long, + pub st_blksize: ::blksize_t, + st_pad4: ::c_long, + pub st_blocks: ::blkcnt_t, + st_pad5: [::c_long; 7], + } + + pub struct statvfs { // ToDo: broken + pub f_bsize: ::c_ulong, + pub f_frsize: ::c_ulong, + pub f_blocks: ::fsblkcnt_t, + pub f_bfree: ::fsblkcnt_t, + pub f_bavail: ::fsblkcnt_t, + pub f_files: ::fsfilcnt_t, + pub f_ffree: ::fsfilcnt_t, + pub f_favail: ::fsfilcnt_t, + #[cfg(target_endian = "little")] + pub f_fsid: ::c_ulong, + #[cfg(target_pointer_width = "32")] + __f_unused: ::c_int, + #[cfg(target_endian = "big")] + pub f_fsid: ::c_ulong, + pub f_flag: ::c_ulong, + pub f_namemax: ::c_ulong, + __f_spare: [::c_int; 6], + } + + pub struct dirent { // Todo + pub d_ino: ino_64_t, + pub d_off: off64_t, + d_reclen: u16, + pub d_type: u8, + pub d_name: [i8; 256], + } + + pub struct dirent64 { // + pub d_ino: ino64_t, + pub d_off: off64_t, + pub d_reclen: u16, + pub d_type: u8, + pub d_name: [i8; 256], + } + + pub struct pthread_attr_t { // ToDo + __size: [u64; 7] + } + + pub struct sigaction { // TODO!! + 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, + } + + pub struct stack_t { // ToDo + pub ss_sp: *mut ::c_void, + pub ss_flags: ::c_int, + pub ss_size: ::size_t + } + + pub struct statfs { // ToDo + pub f_type: fsword_t, + pub f_bsize: fsword_t, + pub f_blocks: ::fsblkcnt_t, + pub f_bfree: ::fsblkcnt_t, + pub f_bavail: ::fsblkcnt_t, + pub f_files: ::fsfilcnt_t, + pub f_ffree: ::fsfilcnt_t, + pub f_fsid: ::fsid_t, + pub f_namelen: fsword_t, + pub f_frsize: fsword_t, + f_spare: [fsword_t; 5], + } + + pub struct msghdr { // ToDo + pub msg_name: *mut ::c_void, + pub msg_namelen: ::socklen_t, + pub msg_iov: *mut ::iovec, + pub msg_iovlen: ::size_t, + pub msg_control: *mut ::c_void, + pub msg_controllen: ::size_t, + pub msg_flags: ::c_int, + } + + pub struct termios { // ToDo + pub c_iflag: ::tcflag_t, + pub c_oflag: ::tcflag_t, + pub c_cflag: ::tcflag_t, + pub c_lflag: ::tcflag_t, + pub c_line: ::cc_t, + pub c_cc: [::cc_t; ::NCCS], + } + + pub struct sem_t { // ToDo + #[cfg(target_pointer_width = "32")] + __size: [::c_char; 16], + #[cfg(target_pointer_width = "64")] + __size: [::c_char; 32], + __align: [::c_long; 0], + } + + pub struct pthread_mutex_t { // ToDo + #[cfg(any(target_arch = "mips", target_arch = "arm", + target_arch = "powerpc"))] + __align: [::c_long; 0], + #[cfg(not(any(target_arch = "mips", target_arch = "arm", + target_arch = "powerpc")))] + __align: [::c_longlong; 0], + size: [u8; __SIZEOF_PTHREAD_MUTEX_T], + } + + pub struct pthread_mutexattr_t { // ToDo + #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64"))] + __align: [::c_int; 0], + #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64")))] + __align: [::c_long; 0], + size: [u8; __SIZEOF_PTHREAD_MUTEXATTR_T], + } + + pub struct pthread_cond_t { // ToDo + __align: [::c_longlong; 0], + size: [u8; __SIZEOF_PTHREAD_COND_T], + } + + pub struct pthread_condattr_t { // ToDo + __align: [::c_int; 0], + size: [u8; __SIZEOF_PTHREAD_CONDATTR_T], + } + + pub struct pthread_rwlock_t { // ToDo + #[cfg(any(target_arch = "mips", target_arch = "arm", + target_arch = "powerpc"))] + __align: [::c_long; 0], + #[cfg(not(any(target_arch = "mips", target_arch = "arm", + target_arch = "powerpc")))] + __align: [::c_longlong; 0], + size: [u8; __SIZEOF_PTHREAD_RWLOCK_T], + } + + pub struct sigset_t { // ToDo + __val: [::c_ulong; 16], + } + + pub struct sysinfo { // ToDo + pub uptime: ::c_long, + pub loads: [::c_ulong; 3], + pub totalram: ::c_ulong, + pub freeram: ::c_ulong, + pub sharedram: ::c_ulong, + pub bufferram: ::c_ulong, + pub totalswap: ::c_ulong, + pub freeswap: ::c_ulong, + pub procs: ::c_ushort, + pub pad: ::c_ushort, + pub totalhigh: ::c_ulong, + pub freehigh: ::c_ulong, + pub mem_unit: ::c_uint, + pub _f: [::c_char; 0], + } + + pub struct glob_t { // ToDo + pub gl_pathc: ::size_t, + pub gl_pathv: *mut *mut c_char, + pub gl_offs: ::size_t, + pub gl_flags: ::c_int, + __unused1: *mut ::c_void, + __unused2: *mut ::c_void, + __unused3: *mut ::c_void, + __unused4: *mut ::c_void, + __unused5: *mut ::c_void, + } + + pub struct stat64 { // ToDo + pub st_dev: ::dev_t, + pub st_ino: ::ino64_t, + pub st_nlink: ::nlink_t, + pub st_mode: ::mode_t, + pub st_uid: ::uid_t, + pub st_gid: ::gid_t, + __pad0: ::c_int, + pub st_rdev: ::dev_t, + pub st_size: ::off_t, + pub st_blksize: ::blksize_t, + pub st_blocks: ::blkcnt64_t, + pub st_atime: ::time_t, + pub st_atime_nsec: ::c_long, + pub st_mtime: ::time_t, + pub st_mtime_nsec: ::c_long, + pub st_ctime: ::time_t, + pub st_ctime_nsec: ::c_long, + __reserved: [::c_long; 3], + } + + pub struct rlimit64 { // ToDo + pub rlim_cur: rlim64_t, + pub rlim_max: rlim64_t, + } + + pub struct cpu_set_t { // ToDo + #[cfg(target_pointer_width = "32")] + bits: [u32; 32], + #[cfg(target_pointer_width = "64")] + bits: [u64; 16], + } + + pub struct timespec { // ToDo + tv_sec: time_t, // seconds + tv_nsec: ::c_ulong, // nanoseconds + } + + pub struct fsid_t { // ToDo + __val: [::c_int; 2], + } +} + +// constants +pub const O_CLOEXEC: ::c_int = 0x80000; +pub const O_DIRECTORY: ::c_int = 0200000; +pub const NCCS: usize = 32; +pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; +pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; +pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; +pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1; +pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2; +pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_NORMAL; +pub const __SIZEOF_PTHREAD_COND_T: usize = 48; +pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; +pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; + +extern { + pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void; +} diff --git a/src/libpanic_unwind/dwarf/eh.rs b/src/libpanic_unwind/dwarf/eh.rs index e7994f4e0e..0c326ce371 100644 --- a/src/libpanic_unwind/dwarf/eh.rs +++ b/src/libpanic_unwind/dwarf/eh.rs @@ -61,9 +61,11 @@ pub enum EHAction { pub const USING_SJLJ_EXCEPTIONS: bool = cfg!(all(target_os = "ios", target_arch = "arm")); -pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext) -> EHAction { +pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext) + -> Result +{ if lsda.is_null() { - return EHAction::None; + return Ok(EHAction::None) } let func_start = context.func_start; @@ -72,7 +74,7 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext) -> EHAction { let start_encoding = reader.read::(); // base address for landing pad offsets let lpad_base = if start_encoding != DW_EH_PE_omit { - read_encoded_pointer(&mut reader, context, start_encoding) + read_encoded_pointer(&mut reader, context, start_encoding)? } else { func_start }; @@ -90,9 +92,9 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext) -> EHAction { if !USING_SJLJ_EXCEPTIONS { while reader.ptr < action_table { - let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding); - let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding); - let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding); + let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding)?; + let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding)?; + let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding)?; let cs_action = reader.read_uleb128(); // Callsite table is sorted by cs_start, so if we've passed the ip, we // may stop searching. @@ -101,23 +103,23 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext) -> EHAction { } if ip < func_start + cs_start + cs_len { if cs_lpad == 0 { - return EHAction::None; + return Ok(EHAction::None) } else { let lpad = lpad_base + cs_lpad; - return interpret_cs_action(cs_action, lpad); + return Ok(interpret_cs_action(cs_action, lpad)) } } } // Ip is not present in the table. This should not happen... but it does: issue #35011. // So rather than returning EHAction::Terminate, we do this. - EHAction::None + Ok(EHAction::None) } else { // SjLj version: // The "IP" is an index into the call-site table, with two exceptions: // -1 means 'no-action', and 0 means 'terminate'. match ip as isize { - -1 => return EHAction::None, - 0 => return EHAction::Terminate, + -1 => return Ok(EHAction::None), + 0 => return Ok(EHAction::Terminate), _ => (), } let mut idx = ip; @@ -129,7 +131,7 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext) -> EHAction { // Can never have null landing pad for sjlj -- that would have // been indicated by a -1 call site index. let lpad = (cs_lpad + 1) as usize; - return interpret_cs_action(cs_action, lpad); + return Ok(interpret_cs_action(cs_action, lpad)) } } } @@ -144,21 +146,26 @@ fn interpret_cs_action(cs_action: u64, lpad: usize) -> EHAction { } #[inline] -fn round_up(unrounded: usize, align: usize) -> usize { - assert!(align.is_power_of_two()); - (unrounded + align - 1) & !(align - 1) +fn round_up(unrounded: usize, align: usize) -> Result { + if align.is_power_of_two() { + Ok((unrounded + align - 1) & !(align - 1)) + } else { + Err(()) + } } unsafe fn read_encoded_pointer(reader: &mut DwarfReader, context: &EHContext, encoding: u8) - -> usize { - assert!(encoding != DW_EH_PE_omit); + -> Result { + if encoding == DW_EH_PE_omit { + return Err(()) + } // DW_EH_PE_aligned implies it's an absolute pointer value if encoding == DW_EH_PE_aligned { - reader.ptr = round_up(reader.ptr as usize, mem::size_of::()) as *const u8; - return reader.read::(); + reader.ptr = round_up(reader.ptr as usize, mem::size_of::())? as *const u8; + return Ok(reader.read::()) } let mut result = match encoding & 0x0F { @@ -171,7 +178,7 @@ unsafe fn read_encoded_pointer(reader: &mut DwarfReader, DW_EH_PE_sdata2 => reader.read::() as usize, DW_EH_PE_sdata4 => reader.read::() as usize, DW_EH_PE_sdata8 => reader.read::() as usize, - _ => panic!(), + _ => return Err(()), }; result += match encoding & 0x70 { @@ -179,17 +186,19 @@ unsafe fn read_encoded_pointer(reader: &mut DwarfReader, // relative to address of the encoded value, despite the name DW_EH_PE_pcrel => reader.ptr as usize, DW_EH_PE_funcrel => { - assert!(context.func_start != 0); + if context.func_start == 0 { + return Err(()) + } context.func_start } DW_EH_PE_textrel => (*context.get_text_start)(), DW_EH_PE_datarel => (*context.get_data_start)(), - _ => panic!(), + _ => return Err(()), }; if encoding & DW_EH_PE_indirect != 0 { result = *(result as *const usize); } - result + Ok(result) } diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs index 84abc6bc4a..aadbeb96b2 100644 --- a/src/libpanic_unwind/gcc.rs +++ b/src/libpanic_unwind/gcc.rs @@ -156,7 +156,10 @@ unsafe extern "C" fn rust_eh_personality(version: c_int, if version != 1 { return uw::_URC_FATAL_PHASE1_ERROR; } - let eh_action = find_eh_action(context); + let eh_action = match find_eh_action(context) { + Ok(action) => action, + Err(_) => return uw::_URC_FATAL_PHASE1_ERROR, + }; if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 { match eh_action { EHAction::None | @@ -219,7 +222,10 @@ unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State, // _Unwind_Context in our libunwind bindings and fetch the required data from there directly, // bypassing DWARF compatibility functions. - let eh_action = find_eh_action(context); + let eh_action = match find_eh_action(context) { + Ok(action) => action, + Err(_) => return uw::_URC_FAILURE, + }; if search_phase { match eh_action { EHAction::None | @@ -260,7 +266,9 @@ unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State, } } -unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) -> EHAction { +unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) + -> Result +{ let lsda = uw::_Unwind_GetLanguageSpecificData(context) as *const u8; let mut ip_before_instr: c_int = 0; let ip = uw::_Unwind_GetIPInfo(context, &mut ip_before_instr); diff --git a/src/libpanic_unwind/seh64_gnu.rs b/src/libpanic_unwind/seh64_gnu.rs index d4906b556b..0a9fa7d9a8 100644 --- a/src/libpanic_unwind/seh64_gnu.rs +++ b/src/libpanic_unwind/seh64_gnu.rs @@ -128,9 +128,10 @@ unsafe fn find_landing_pad(dc: &c::DISPATCHER_CONTEXT) -> Option { get_data_start: &|| unimplemented!(), }; match find_eh_action(dc.HandlerData, &eh_ctx) { - EHAction::None => None, - EHAction::Cleanup(lpad) | - EHAction::Catch(lpad) => Some(lpad), - EHAction::Terminate => intrinsics::abort(), + Err(_) | + Ok(EHAction::None) => None, + Ok(EHAction::Cleanup(lpad)) | + Ok(EHAction::Catch(lpad)) => Some(lpad), + Ok(EHAction::Terminate) => intrinsics::abort(), } } diff --git a/src/libproc_macro/Cargo.toml b/src/libproc_macro/Cargo.toml index 7ce65d0fe4..1b5141773a 100644 --- a/src/libproc_macro/Cargo.toml +++ b/src/libproc_macro/Cargo.toml @@ -9,3 +9,4 @@ crate-type = ["dylib"] [dependencies] syntax = { path = "../libsyntax" } +syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 0ab0550469..3c5d6aceca 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -21,7 +21,7 @@ //! This functionality is intended to be expanded over time as more surface //! area for macro authors is stabilized. //! -//! See [the book](../book/procedural-macros.html) for more. +//! See [the book](../book/first-edition/procedural-macros.html) for more. #![crate_name = "proc_macro"] #![stable(feature = "proc_macro_lib", since = "1.15.0")] @@ -37,18 +37,27 @@ test(no_crate_inject, attr(deny(warnings))), test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))] +#![feature(i128_type)] #![feature(rustc_private)] #![feature(staged_api)] #![feature(lang_items)] +#[macro_use] extern crate syntax; +extern crate syntax_pos; -use std::fmt; +use std::{ascii, fmt, iter}; use std::str::FromStr; +use syntax::ast; use syntax::errors::DiagnosticBuilder; -use syntax::parse; -use syntax::tokenstream::TokenStream as TokenStream_; +use syntax::parse::{self, token, parse_stream_from_source_str}; +use syntax::print::pprust; +use syntax::symbol::Symbol; +use syntax::tokenstream; +use syntax_pos::DUMMY_SP; +use syntax_pos::SyntaxContext; +use syntax_pos::hygiene::Mark; /// The main type provided by this crate, representing an abstract stream of /// tokens. @@ -60,17 +69,516 @@ use syntax::tokenstream::TokenStream as TokenStream_; /// The API of this type is intentionally bare-bones, but it'll be expanded over /// time! #[stable(feature = "proc_macro_lib", since = "1.15.0")] -pub struct TokenStream { - inner: TokenStream_, -} +#[derive(Clone, Debug)] +pub struct TokenStream(tokenstream::TokenStream); /// Error returned from `TokenStream::from_str`. -#[derive(Debug)] #[stable(feature = "proc_macro_lib", since = "1.15.0")] +#[derive(Debug)] pub struct LexError { _inner: (), } +#[stable(feature = "proc_macro_lib", since = "1.15.0")] +impl FromStr for TokenStream { + type Err = LexError; + + fn from_str(src: &str) -> Result { + __internal::with_sess(|(sess, mark)| { + let src = src.to_string(); + let name = "".to_string(); + let expn_info = mark.expn_info().unwrap(); + let call_site = expn_info.call_site; + // notify the expansion info that it is unhygienic + let mark = Mark::fresh(mark); + mark.set_expn_info(expn_info); + let span = syntax_pos::Span { + ctxt: SyntaxContext::empty().apply_mark(mark), + ..call_site + }; + let stream = parse::parse_stream_from_source_str(name, src, sess, Some(span)); + Ok(__internal::token_stream_wrap(stream)) + }) + } +} + +#[stable(feature = "proc_macro_lib", since = "1.15.0")] +impl fmt::Display for TokenStream { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.fmt(f) + } +} + +/// `quote!(..)` accepts arbitrary tokens and expands into a `TokenStream` describing the input. +/// For example, `quote!(a + b)` will produce a expression, that, when evaluated, constructs +/// constructs the `TokenStream` `[Word("a"), Op('+', Alone), Word("b")]`. +/// +/// Unquoting is done with `$`, and works by taking the single next ident as the unquoted term. +/// To quote `$` itself, use `$$`. +#[unstable(feature = "proc_macro", issue = "38356")] +#[macro_export] +macro_rules! quote { () => {} } + +#[unstable(feature = "proc_macro_internals", issue = "27812")] +#[doc(hidden)] +mod quote; + +#[unstable(feature = "proc_macro", issue = "38356")] +impl From for TokenStream { + fn from(tree: TokenTree) -> TokenStream { + TokenStream(tree.to_internal()) + } +} + +#[unstable(feature = "proc_macro", issue = "38356")] +impl From for TokenStream { + fn from(kind: TokenNode) -> TokenStream { + TokenTree::from(kind).into() + } +} + +#[unstable(feature = "proc_macro", issue = "38356")] +impl> iter::FromIterator for TokenStream { + fn from_iter>(streams: I) -> Self { + let mut builder = tokenstream::TokenStreamBuilder::new(); + for stream in streams { + builder.push(stream.into().0); + } + TokenStream(builder.build()) + } +} + +#[unstable(feature = "proc_macro", issue = "38356")] +impl IntoIterator for TokenStream { + type Item = TokenTree; + type IntoIter = TokenTreeIter; + + fn into_iter(self) -> TokenTreeIter { + TokenTreeIter { cursor: self.0.trees(), next: None } + } +} + +impl TokenStream { + /// Returns an empty `TokenStream`. + #[unstable(feature = "proc_macro", issue = "38356")] + pub fn empty() -> TokenStream { + TokenStream(tokenstream::TokenStream::empty()) + } + + /// Checks if this `TokenStream` is empty. + #[unstable(feature = "proc_macro", issue = "38356")] + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + +/// A region of source code, along with macro expansion information. +#[unstable(feature = "proc_macro", issue = "38356")] +#[derive(Copy, Clone, Debug)] +pub struct Span(syntax_pos::Span); + +#[unstable(feature = "proc_macro", issue = "38356")] +impl Default for Span { + fn default() -> Span { + ::__internal::with_sess(|(_, mark)| Span(syntax_pos::Span { + ctxt: SyntaxContext::empty().apply_mark(mark), + ..mark.expn_info().unwrap().call_site + })) + } +} + +/// Quote a `Span` into a `TokenStream`. +/// This is needed to implement a custom quoter. +#[unstable(feature = "proc_macro", issue = "38356")] +pub fn quote_span(span: Span) -> TokenStream { + TokenStream(quote::Quote::quote(&span.0)) +} + +impl Span { + /// The span of the invocation of the current procedural macro. + #[unstable(feature = "proc_macro", issue = "38356")] + pub fn call_site() -> Span { + ::__internal::with_sess(|(_, mark)| Span(mark.expn_info().unwrap().call_site)) + } +} + +/// A single token or a delimited sequence of token trees (e.g. `[1, (), ..]`). +#[unstable(feature = "proc_macro", issue = "38356")] +#[derive(Clone, Debug)] +pub struct TokenTree { + /// The `TokenTree`'s span + pub span: Span, + /// Description of the `TokenTree` + pub kind: TokenNode, +} + +#[unstable(feature = "proc_macro", issue = "38356")] +impl From for TokenTree { + fn from(kind: TokenNode) -> TokenTree { + TokenTree { span: Span::default(), kind: kind } + } +} + +#[unstable(feature = "proc_macro", issue = "38356")] +impl fmt::Display for TokenTree { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + TokenStream::from(self.clone()).fmt(f) + } +} + +/// Description of a `TokenTree` +#[derive(Clone, Debug)] +#[unstable(feature = "proc_macro", issue = "38356")] +pub enum TokenNode { + /// A delimited tokenstream. + Group(Delimiter, TokenStream), + /// A unicode identifier. + Term(Term), + /// A punctuation character (`+`, `,`, `$`, etc.). + Op(char, Spacing), + /// A literal character (`'a'`), string (`"hello"`), or number (`2.3`). + Literal(Literal), +} + +/// Describes how a sequence of token trees is delimited. +#[derive(Copy, Clone, Debug)] +#[unstable(feature = "proc_macro", issue = "38356")] +pub enum Delimiter { + /// `( ... )` + Parenthesis, + /// `[ ... ]` + Brace, + /// `{ ... }` + Bracket, + /// An implicit delimiter, e.g. `$var`, where $var is `...`. + None, +} + +/// An interned string. +#[derive(Copy, Clone, Debug)] +#[unstable(feature = "proc_macro", issue = "38356")] +pub struct Term(Symbol); + +impl Term { + /// Intern a string into a `Term`. + #[unstable(feature = "proc_macro", issue = "38356")] + pub fn intern(string: &str) -> Term { + Term(Symbol::intern(string)) + } + + /// Get a reference to the interned string. + #[unstable(feature = "proc_macro", issue = "38356")] + pub fn as_str(&self) -> &str { + unsafe { &*(&*self.0.as_str() as *const str) } + } +} + +/// Whether an `Op` is either followed immediately by another `Op` or followed by whitespace. +#[derive(Copy, Clone, Debug)] +#[unstable(feature = "proc_macro", issue = "38356")] +pub enum Spacing { + /// e.g. `+` is `Alone` in `+ =`. + Alone, + /// e.g. `+` is `Joint` in `+=`. + Joint, +} + +/// A literal character (`'a'`), string (`"hello"`), or number (`2.3`). +#[derive(Clone, Debug)] +#[unstable(feature = "proc_macro", issue = "38356")] +pub struct Literal(token::Token); + +#[unstable(feature = "proc_macro", issue = "38356")] +impl fmt::Display for Literal { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + TokenTree { kind: TokenNode::Literal(self.clone()), span: Span(DUMMY_SP) }.fmt(f) + } +} + +macro_rules! int_literals { + ($($int_kind:ident),*) => {$( + /// Integer literal. + #[unstable(feature = "proc_macro", issue = "38356")] + pub fn $int_kind(n: $int_kind) -> Literal { + Literal::typed_integer(n as i128, stringify!($int_kind)) + } + )*} +} + +impl Literal { + /// Integer literal + #[unstable(feature = "proc_macro", issue = "38356")] + pub fn integer(n: i128) -> Literal { + Literal(token::Literal(token::Lit::Integer(Symbol::intern(&n.to_string())), None)) + } + + int_literals!(u8, i8, u16, i16, u32, i32, u64, i64, usize, isize); + fn typed_integer(n: i128, kind: &'static str) -> Literal { + Literal(token::Literal(token::Lit::Integer(Symbol::intern(&n.to_string())), + Some(Symbol::intern(kind)))) + } + + /// Floating point literal. + #[unstable(feature = "proc_macro", issue = "38356")] + pub fn float(n: f64) -> Literal { + if !n.is_finite() { + panic!("Invalid float literal {}", n); + } + Literal(token::Literal(token::Lit::Float(Symbol::intern(&n.to_string())), None)) + } + + /// Floating point literal. + #[unstable(feature = "proc_macro", issue = "38356")] + pub fn f32(n: f32) -> Literal { + if !n.is_finite() { + panic!("Invalid f32 literal {}", n); + } + Literal(token::Literal(token::Lit::Float(Symbol::intern(&n.to_string())), + Some(Symbol::intern("f32")))) + } + + /// Floating point literal. + #[unstable(feature = "proc_macro", issue = "38356")] + pub fn f64(n: f64) -> Literal { + if !n.is_finite() { + panic!("Invalid f64 literal {}", n); + } + Literal(token::Literal(token::Lit::Float(Symbol::intern(&n.to_string())), + Some(Symbol::intern("f64")))) + } + + /// String literal. + #[unstable(feature = "proc_macro", issue = "38356")] + pub fn string(string: &str) -> Literal { + let mut escaped = String::new(); + for ch in string.chars() { + escaped.extend(ch.escape_unicode()); + } + Literal(token::Literal(token::Lit::Str_(Symbol::intern(&escaped)), None)) + } + + /// Character literal. + #[unstable(feature = "proc_macro", issue = "38356")] + pub fn character(ch: char) -> Literal { + let mut escaped = String::new(); + escaped.extend(ch.escape_unicode()); + Literal(token::Literal(token::Lit::Char(Symbol::intern(&escaped)), None)) + } + + /// Byte string literal. + #[unstable(feature = "proc_macro", issue = "38356")] + pub fn byte_string(bytes: &[u8]) -> Literal { + let string = bytes.iter().cloned().flat_map(ascii::escape_default) + .map(Into::::into).collect::(); + Literal(token::Literal(token::Lit::ByteStr(Symbol::intern(&string)), None)) + } +} + +/// An iterator over `TokenTree`s. +#[unstable(feature = "proc_macro", issue = "38356")] +pub struct TokenTreeIter { + cursor: tokenstream::Cursor, + next: Option, +} + +#[unstable(feature = "proc_macro", issue = "38356")] +impl Iterator for TokenTreeIter { + type Item = TokenTree; + + fn next(&mut self) -> Option { + loop { + let next = + unwrap_or!(self.next.take().or_else(|| self.cursor.next_as_stream()), return None); + let tree = TokenTree::from_internal(next, &mut self.next); + if tree.span.0 == DUMMY_SP { + if let TokenNode::Group(Delimiter::None, stream) = tree.kind { + self.cursor.insert(stream.0); + continue + } + } + return Some(tree); + } + } +} + +impl Delimiter { + fn from_internal(delim: token::DelimToken) -> Delimiter { + match delim { + token::Paren => Delimiter::Parenthesis, + token::Brace => Delimiter::Brace, + token::Bracket => Delimiter::Bracket, + token::NoDelim => Delimiter::None, + } + } + + fn to_internal(self) -> token::DelimToken { + match self { + Delimiter::Parenthesis => token::Paren, + Delimiter::Brace => token::Brace, + Delimiter::Bracket => token::Bracket, + Delimiter::None => token::NoDelim, + } + } +} + +impl TokenTree { + fn from_internal(stream: tokenstream::TokenStream, next: &mut Option) + -> TokenTree { + use syntax::parse::token::*; + + let (tree, is_joint) = stream.as_tree(); + let (mut span, token) = match tree { + tokenstream::TokenTree::Token(span, token) => (span, token), + tokenstream::TokenTree::Delimited(span, delimed) => { + let delimiter = Delimiter::from_internal(delimed.delim); + return TokenTree { + span: Span(span), + kind: TokenNode::Group(delimiter, TokenStream(delimed.tts.into())), + }; + } + }; + + let op_kind = if is_joint { Spacing::Joint } else { Spacing::Alone }; + macro_rules! op { + ($op:expr) => { TokenNode::Op($op, op_kind) } + } + + macro_rules! joint { + ($first:expr, $rest:expr) => { joint($first, $rest, is_joint, &mut span, next) } + } + + fn joint(first: char, rest: Token, is_joint: bool, span: &mut syntax_pos::Span, + next: &mut Option) + -> TokenNode { + let (first_span, rest_span) = (*span, *span); + *span = first_span; + let tree = tokenstream::TokenTree::Token(rest_span, rest); + *next = Some(if is_joint { tree.joint() } else { tree.into() }); + TokenNode::Op(first, Spacing::Joint) + } + + let kind = match token { + Eq => op!('='), + Lt => op!('<'), + Le => joint!('<', Eq), + EqEq => joint!('=', Eq), + Ne => joint!('!', Eq), + Ge => joint!('>', Eq), + Gt => op!('>'), + AndAnd => joint!('&', BinOp(And)), + OrOr => joint!('|', BinOp(Or)), + Not => op!('!'), + Tilde => op!('~'), + BinOp(Plus) => op!('+'), + BinOp(Minus) => op!('-'), + BinOp(Star) => op!('*'), + BinOp(Slash) => op!('/'), + BinOp(Percent) => op!('%'), + BinOp(Caret) => op!('^'), + BinOp(And) => op!('&'), + BinOp(Or) => op!('|'), + BinOp(Shl) => joint!('<', Lt), + BinOp(Shr) => joint!('>', Gt), + BinOpEq(Plus) => joint!('+', Eq), + BinOpEq(Minus) => joint!('-', Eq), + BinOpEq(Star) => joint!('*', Eq), + BinOpEq(Slash) => joint!('/', Eq), + BinOpEq(Percent) => joint!('%', Eq), + BinOpEq(Caret) => joint!('^', Eq), + BinOpEq(And) => joint!('&', Eq), + BinOpEq(Or) => joint!('|', Eq), + BinOpEq(Shl) => joint!('<', Le), + BinOpEq(Shr) => joint!('>', Ge), + At => op!('@'), + Dot => op!('.'), + DotDot => joint!('.', Dot), + DotDotDot => joint!('.', DotDot), + Comma => op!(','), + Semi => op!(';'), + Colon => op!(':'), + ModSep => joint!(':', Colon), + RArrow => joint!('-', Gt), + LArrow => joint!('<', BinOp(Minus)), + FatArrow => joint!('=', Gt), + Pound => op!('#'), + Dollar => op!('$'), + Question => op!('?'), + Underscore => op!('_'), + + Ident(ident) | Lifetime(ident) => TokenNode::Term(Term(ident.name)), + Literal(..) | DocComment(..) => TokenNode::Literal(self::Literal(token)), + + Interpolated(ref nt) => __internal::with_sess(|(sess, _)| { + TokenNode::Group(Delimiter::None, TokenStream(nt.1.force(|| { + // FIXME(jseyfried): Avoid this pretty-print + reparse hack + let name = "".to_owned(); + let source = pprust::token_to_string(&token); + parse_stream_from_source_str(name, source, sess, Some(span)) + }))) + }), + + OpenDelim(..) | CloseDelim(..) => unreachable!(), + Whitespace | Comment | Shebang(..) | Eof => unreachable!(), + }; + + TokenTree { span: Span(span), kind: kind } + } + + fn to_internal(self) -> tokenstream::TokenStream { + use syntax::parse::token::*; + use syntax::tokenstream::{TokenTree, Delimited}; + + let (op, kind) = match self.kind { + TokenNode::Op(op, kind) => (op, kind), + TokenNode::Group(delimiter, tokens) => { + return TokenTree::Delimited(self.span.0, Delimited { + delim: delimiter.to_internal(), + tts: tokens.0.into(), + }).into(); + }, + TokenNode::Term(symbol) => { + let ident = ast::Ident { name: symbol.0, ctxt: self.span.0.ctxt }; + let token = + if symbol.0.as_str().starts_with("'") { Lifetime(ident) } else { Ident(ident) }; + return TokenTree::Token(self.span.0, token).into(); + } + TokenNode::Literal(token) => return TokenTree::Token(self.span.0, token.0).into(), + }; + + let token = match op { + '=' => Eq, + '<' => Lt, + '>' => Gt, + '!' => Not, + '~' => Tilde, + '+' => BinOp(Plus), + '-' => BinOp(Minus), + '*' => BinOp(Star), + '/' => BinOp(Slash), + '%' => BinOp(Percent), + '^' => BinOp(Caret), + '&' => BinOp(And), + '|' => BinOp(Or), + '@' => At, + '.' => Dot, + ',' => Comma, + ';' => Semi, + ':' => Colon, + '#' => Pound, + '$' => Dollar, + '?' => Question, + '_' => Underscore, + _ => panic!("unsupported character {}", op), + }; + + let tree = TokenTree::Token(self.span.0, token); + match kind { + Spacing::Alone => tree.into(), + Spacing::Joint => tree.joint(), + } + } +} + /// Permanently unstable internal implementation details of this crate. This /// should not be used. /// @@ -83,32 +591,33 @@ pub struct LexError { #[unstable(feature = "proc_macro_internals", issue = "27812")] #[doc(hidden)] pub mod __internal { + pub use quote::{Quoter, __rt}; + use std::cell::Cell; - use std::rc::Rc; use syntax::ast; + use syntax::ext::base::ExtCtxt; + use syntax::ext::hygiene::Mark; use syntax::ptr::P; - use syntax::parse::{self, token, ParseSess}; - use syntax::tokenstream::{TokenTree, TokenStream as TokenStream_}; + use syntax::parse::{self, ParseSess}; + use syntax::parse::token::{self, Token}; + use syntax::tokenstream; + use syntax_pos::DUMMY_SP; use super::{TokenStream, LexError}; pub fn new_token_stream(item: P) -> TokenStream { - TokenStream { - inner: TokenTree::Token(item.span, token::Interpolated(Rc::new(token::NtItem(item)))) - .into() - } + let token = Token::interpolated(token::NtItem(item)); + TokenStream(tokenstream::TokenTree::Token(DUMMY_SP, token).into()) } - pub fn token_stream_wrap(inner: TokenStream_) -> TokenStream { - TokenStream { - inner: inner - } + pub fn token_stream_wrap(inner: tokenstream::TokenStream) -> TokenStream { + TokenStream(inner) } pub fn token_stream_parse_items(stream: TokenStream) -> Result>, LexError> { - with_parse_sess(move |sess| { - let mut parser = parse::stream_to_parser(sess, stream.inner); + with_sess(move |(sess, _)| { + let mut parser = parse::stream_to_parser(sess, stream.0); let mut items = Vec::new(); while let Some(item) = try!(parser.parse_item().map_err(super::parse_to_lex_err)) { @@ -119,8 +628,8 @@ pub mod __internal { }) } - pub fn token_stream_inner(stream: TokenStream) -> TokenStream_ { - stream.inner + pub fn token_stream_inner(stream: TokenStream) -> tokenstream::TokenStream { + stream.0 } pub trait Registry { @@ -140,13 +649,14 @@ pub mod __internal { // Emulate scoped_thread_local!() here essentially thread_local! { - static CURRENT_SESS: Cell<*const ParseSess> = Cell::new(0 as *const _); + static CURRENT_SESS: Cell<(*const ParseSess, Mark)> = + Cell::new((0 as *const _, Mark::root())); } - pub fn set_parse_sess(sess: &ParseSess, f: F) -> R + pub fn set_sess(cx: &ExtCtxt, f: F) -> R where F: FnOnce() -> R { - struct Reset { prev: *const ParseSess } + struct Reset { prev: (*const ParseSess, Mark) } impl Drop for Reset { fn drop(&mut self) { @@ -156,18 +666,18 @@ pub mod __internal { CURRENT_SESS.with(|p| { let _reset = Reset { prev: p.get() }; - p.set(sess); + p.set((cx.parse_sess, cx.current_expansion.mark)); f() }) } - pub fn with_parse_sess(f: F) -> R - where F: FnOnce(&ParseSess) -> R + pub fn with_sess(f: F) -> R + where F: FnOnce((&ParseSess, Mark)) -> R { let p = CURRENT_SESS.with(|p| p.get()); - assert!(!p.is_null(), "proc_macro::__internal::with_parse_sess() called \ - before set_parse_sess()!"); - f(unsafe { &*p }) + assert!(!p.0.is_null(), "proc_macro::__internal::with_sess() called \ + before set_parse_sess()!"); + f(unsafe { (&*p.0, p.1) }) } } @@ -175,24 +685,3 @@ 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; - - fn from_str(src: &str) -> Result { - __internal::with_parse_sess(|sess| { - let src = src.to_string(); - let name = "".to_string(); - let stream = parse::parse_stream_from_source_str(name, src, sess); - Ok(__internal::token_stream_wrap(stream)) - }) - } -} - -#[stable(feature = "proc_macro_lib", since = "1.15.0")] -impl fmt::Display for TokenStream { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.inner.fmt(f) - } -} diff --git a/src/libproc_macro/quote.rs b/src/libproc_macro/quote.rs new file mode 100644 index 0000000000..0db2b86b15 --- /dev/null +++ b/src/libproc_macro/quote.rs @@ -0,0 +1,263 @@ +// 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. + +//! # Quasiquoter +//! This file contains the implementation internals of the quasiquoter provided by `quote!`. + +//! This quasiquoter uses macros 2.0 hygiene to reliably use items from `__rt`, +//! including re-exported API `libsyntax`, to build a `syntax::tokenstream::TokenStream` +//! and wrap it into a `proc_macro::TokenStream`. + +use syntax::ast::Ident; +use syntax::ext::base::{ExtCtxt, ProcMacro}; +use syntax::parse::token::{self, Token, Lit}; +use syntax::symbol::Symbol; +use syntax::tokenstream::{Delimited, TokenTree, TokenStream, TokenStreamBuilder}; +use syntax_pos::{DUMMY_SP, Span}; +use syntax_pos::hygiene::SyntaxContext; + +pub struct Quoter; + +pub mod __rt { + pub use syntax::ast::Ident; + pub use syntax::parse::token; + pub use syntax::symbol::Symbol; + pub use syntax::tokenstream::{TokenStream, TokenStreamBuilder, TokenTree, Delimited}; + pub use super::{ctxt, span}; + + pub fn unquote + Clone>(tokens: &T) -> TokenStream { + T::into(tokens.clone()).0 + } +} + +pub fn ctxt() -> SyntaxContext { + ::__internal::with_sess(|(_, mark)| SyntaxContext::empty().apply_mark(mark)) +} + +pub fn span() -> Span { + ::Span::default().0 +} + +pub trait Quote { + fn quote(&self) -> TokenStream; +} + +macro_rules! quote_tok { + (,) => { Token::Comma }; + (.) => { Token::Dot }; + (:) => { Token::Colon }; + (::) => { Token::ModSep }; + (!) => { Token::Not }; + (<) => { Token::Lt }; + (>) => { Token::Gt }; + (_) => { Token::Underscore }; + (0) => { Token::Literal(token::Lit::Integer(Symbol::intern("0")), None) }; + (&) => { Token::BinOp(token::And) }; + ($i:ident) => { Token::Ident(Ident { name: Symbol::intern(stringify!($i)), ctxt: ctxt() }) }; +} + +macro_rules! quote_tree { + ((unquote $($t:tt)*)) => { TokenStream::from($($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)*)) }; + (rt) => { quote!(::__internal::__rt) }; + ($t:tt) => { TokenStream::from(TokenTree::Token(span(), quote_tok!($t))) }; +} + +fn delimit(delim: token::DelimToken, stream: TokenStream) -> TokenStream { + TokenTree::Delimited(span(), Delimited { delim: delim, tts: stream.into() }).into() +} + +macro_rules! quote { + () => { TokenStream::empty() }; + ($($t:tt)*) => { [ $( quote_tree!($t), )* ].iter().cloned().collect::() }; +} + +impl ProcMacro for Quoter { + fn expand<'cx>(&self, cx: &'cx mut ExtCtxt, _: Span, stream: TokenStream) -> TokenStream { + let mut info = cx.current_expansion.mark.expn_info().unwrap(); + info.callee.allow_internal_unstable = true; + cx.current_expansion.mark.set_expn_info(info); + ::__internal::set_sess(cx, || quote!(::TokenStream { 0: (quote stream) })) + } +} + +impl Quote for Option { + fn quote(&self) -> TokenStream { + match *self { + Some(ref t) => quote!(Some((quote t))), + None => quote!(None), + } + } +} + +impl Quote for TokenStream { + fn quote(&self) -> TokenStream { + let mut builder = TokenStreamBuilder::new(); + builder.push(quote!(rt::TokenStreamBuilder::new())); + + let mut trees = self.trees(); + loop { + let (mut tree, mut is_joint) = match trees.next_as_stream() { + Some(next) => next.as_tree(), + None => return builder.add(quote!(.build())).build(), + }; + if let TokenTree::Token(_, Token::Dollar) = tree { + let (next_tree, next_is_joint) = match trees.next_as_stream() { + Some(next) => next.as_tree(), + None => panic!("unexpected trailing `$` in `quote!`"), + }; + match next_tree { + TokenTree::Token(_, Token::Ident(..)) => { + builder.push(quote!(.add(rt::unquote(&(unquote next_tree))))); + continue + } + TokenTree::Token(_, Token::Dollar) => { + tree = next_tree; + is_joint = next_is_joint; + } + _ => panic!("`$` must be followed by an ident or `$` in `quote!`"), + } + } + + builder.push(match is_joint { + true => quote!(.add((quote tree).joint())), + false => quote!(.add(rt::TokenStream::from((quote tree)))), + }); + } + } +} + +impl Quote for TokenTree { + fn quote(&self) -> TokenStream { + match *self { + TokenTree::Token(span, ref token) => quote! { + rt::TokenTree::Token((quote span), (quote token)) + }, + TokenTree::Delimited(span, ref delimited) => quote! { + rt::TokenTree::Delimited((quote span), (quote delimited)) + }, + } + } +} + +impl Quote for Delimited { + fn quote(&self) -> TokenStream { + quote!(rt::Delimited { delim: (quote self.delim), tts: (quote self.stream()).into() }) + } +} + +impl<'a> Quote for &'a str { + fn quote(&self) -> TokenStream { + TokenTree::Token(span(), Token::Literal(token::Lit::Str_(Symbol::intern(self)), None)) + .into() + } +} + +impl Quote for usize { + fn quote(&self) -> TokenStream { + let integer_symbol = Symbol::intern(&self.to_string()); + TokenTree::Token(DUMMY_SP, Token::Literal(token::Lit::Integer(integer_symbol), None)) + .into() + } +} + +impl Quote for Ident { + fn quote(&self) -> TokenStream { + quote!(rt::Ident { name: (quote self.name), ctxt: rt::ctxt() }) + } +} + +impl Quote for Symbol { + fn quote(&self) -> TokenStream { + quote!(rt::Symbol::intern((quote &*self.as_str()))) + } +} + +impl Quote for Span { + fn quote(&self) -> TokenStream { + quote!(rt::span()) + } +} + +impl Quote for Token { + fn quote(&self) -> TokenStream { + macro_rules! gen_match { + ($($i:ident),*; $($t:tt)*) => { + match *self { + $( Token::$i => quote!(rt::token::$i), )* + $( $t )* + } + } + } + + 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!(rt::token::OpenDelim((quote delim))), + Token::CloseDelim(delim) => quote!(rt::token::CloseDelim((quote delim))), + Token::BinOp(tok) => quote!(rt::token::BinOp((quote tok))), + Token::BinOpEq(tok) => quote!(rt::token::BinOpEq((quote tok))), + Token::Ident(ident) => quote!(rt::token::Ident((quote ident))), + Token::Lifetime(ident) => quote!(rt::token::Lifetime((quote ident))), + Token::Literal(lit, sfx) => quote!(rt::token::Literal((quote lit), (quote sfx))), + _ => panic!("Unhandled case!"), + } + } +} + +impl Quote for token::BinOpToken { + fn quote(&self) -> TokenStream { + macro_rules! gen_match { + ($($i:ident),*) => { + match *self { + $( token::BinOpToken::$i => quote!(rt::token::BinOpToken::$i), )* + } + } + } + + gen_match!(Plus, Minus, Star, Slash, Percent, Caret, And, Or, Shl, Shr) + } +} + +impl Quote for Lit { + fn quote(&self) -> TokenStream { + macro_rules! gen_match { + ($($i:ident),*; $($raw:ident),*) => { + match *self { + $( Lit::$i(lit) => quote!(rt::token::Lit::$i((quote lit))), )* + $( Lit::$raw(lit, n) => { + quote!(::syntax::parse::token::Lit::$raw((quote lit), (quote n))) + })* + } + } + } + + gen_match!(Byte, Char, Float, Str_, Integer, ByteStr; StrRaw, ByteStrRaw) + } +} + +impl Quote for token::DelimToken { + fn quote(&self) -> TokenStream { + macro_rules! gen_match { + ($($i:ident),*) => { + match *self { + $(token::DelimToken::$i => { quote!(rt::token::DelimToken::$i) })* + } + } + } + + gen_match!(Paren, Bracket, Brace, NoDelim) + } +} diff --git a/src/libproc_macro_plugin/lib.rs b/src/libproc_macro_plugin/lib.rs deleted file mode 100644 index 68c5d49591..0000000000 --- a/src/libproc_macro_plugin/lib.rs +++ /dev/null @@ -1,106 +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 `quote!` macro for syntax creation. -//! -//! The `quote!` 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 -//! -//! The quasiquoter creates output that, when run, constructs the tokenstream specified as -//! input. For example, `quote!(5 + 5)` will produce a program, that, when run, will -//! construct the TokenStream `5 | + | 5`. -//! -//! ### Unquoting -//! -//! Unquoting is done with `$`, and works by taking the single next ident as the unquoted term. -//! To quote `$` itself, use `$$`. -//! -//! A simple example is: -//! -//!``` -//!fn double(tmp: TokenStream) -> TokenStream { -//! quote!($tmp * 2) -//!} -//!``` -//! -//! ### Large example: Scheme's `cond` -//! -//! Below is an example implementation of Scheme's `cond`. -//! -//! ``` -//! fn cond(input: TokenStream) -> TokenStream { -//! let mut conds = Vec::new(); -//! let mut input = input.trees().peekable(); -//! while let Some(tree) = input.next() { -//! let mut cond = match tree { -//! TokenTree::Delimited(_, ref delimited) => delimited.stream(), -//! _ => panic!("Invalid input"), -//! }; -//! let mut trees = cond.trees(); -//! let test = trees.next(); -//! let rhs = trees.collect::(); -//! if rhs.is_empty() { -//! panic!("Invalid macro usage in cond: {}", cond); -//! } -//! let is_else = match test { -//! Some(TokenTree::Token(_, Token::Ident(ident))) if ident.name == "else" => true, -//! _ => false, -//! }; -//! conds.push(if is_else || input.peek().is_none() { -//! quote!({ $rhs }) -//! } else { -//! let test = test.unwrap(); -//! quote!(if $test { $rhs } else) -//! }); -//! } -//! -//! conds.into_iter().collect() -//! } -//! ``` -#![crate_name = "proc_macro_plugin"] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![feature(plugin_registrar)] -#![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/")] -#![deny(warnings)] - -#![cfg_attr(stage0, feature(staged_api))] -#![feature(rustc_diagnostic_macros)] -#![cfg_attr(stage0, feature(rustc_private))] - -extern crate rustc_plugin; -extern crate syntax; -extern crate syntax_pos; - -mod quote; -use quote::quote; - -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_syntax_extension(Symbol::intern("quote"), - SyntaxExtension::ProcMacro(Box::new(quote))); -} diff --git a/src/libproc_macro_plugin/quote.rs b/src/libproc_macro_plugin/quote.rs deleted file mode 100644 index 0967556429..0000000000 --- a/src/libproc_macro_plugin/quote.rs +++ /dev/null @@ -1,230 +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. - -//! # Quasiquoter -//! This file contains the implementation internals of the quasiquoter provided by `qquote!`. - -use syntax::ast::Ident; -use syntax::parse::token::{self, Token, Lit}; -use syntax::symbol::Symbol; -use syntax::tokenstream::{self, Delimited, TokenTree, TokenStream}; -use syntax_pos::DUMMY_SP; - -use std::iter; - -pub fn quote<'cx>(stream: TokenStream) -> TokenStream { - stream.quote() -} - -trait Quote { - fn quote(&self) -> TokenStream; -} - -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))) }; -} - -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 delimit(delim: token::DelimToken, stream: TokenStream) -> TokenStream { - TokenTree::Delimited(DUMMY_SP, Delimited { delim: delim, tts: stream.into() }).into() -} - -macro_rules! quote { - () => { TokenStream::empty() }; - ($($t:tt)*) => { [ $( quote_tree!($t), )* ].iter().cloned().collect::() }; -} - -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), - } - } -} - -impl Quote for TokenStream { - fn quote(&self) -> TokenStream { - if self.is_empty() { - return quote!(::syntax::tokenstream::TokenStream::empty()); - } - - struct Quoter(iter::Peekable); - - impl Iterator for Quoter { - type Item = TokenStream; - - fn next(&mut self) -> Option { - let quoted_tree = if let Some(&TokenTree::Token(_, Token::Dollar)) = self.0.peek() { - self.0.next(); - match self.0.next() { - Some(tree @ TokenTree::Token(_, Token::Ident(..))) => Some(tree.into()), - Some(tree @ TokenTree::Token(_, Token::Dollar)) => Some(tree.quote()), - // FIXME(jseyfried): improve these diagnostics - Some(..) => panic!("`$` must be followed by an ident or `$` in `quote!`"), - None => panic!("unexpected trailing `$` in `quote!`"), - } - } else { - self.0.next().as_ref().map(Quote::quote) - }; - - quoted_tree.map(|quoted_tree| { - quote!(::syntax::tokenstream::TokenStream::from((unquote quoted_tree)),) - }) - } - } - - let quoted = Quoter(self.trees().peekable()).collect::(); - quote!([(unquote quoted)].iter().cloned().collect::<::syntax::tokenstream::TokenStream>()) - } -} - -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)) - }, - } - } -} - -impl Quote for Delimited { - fn quote(&self) -> TokenStream { - quote!(::syntax::tokenstream::Delimited { - delim: (quote self.delim), - tts: (quote self.stream()).into(), - }) - } -} - -impl<'a> Quote for &'a str { - fn quote(&self) -> TokenStream { - TokenTree::Token(DUMMY_SP, Token::Literal(token::Lit::Str_(Symbol::intern(self)), None)) - .into() - } -} - -impl Quote for usize { - fn quote(&self) -> TokenStream { - let integer_symbol = Symbol::intern(&self.to_string()); - TokenTree::Token(DUMMY_SP, Token::Literal(token::Lit::Integer(integer_symbol), None)) - .into() - } -} - -impl Quote for Ident { - fn quote(&self) -> TokenStream { - // FIXME(jseyfried) quote hygiene - quote!(::syntax::ast::Ident::from_str((quote &*self.name.as_str()))) - } -} - -impl Quote for Symbol { - fn quote(&self) -> TokenStream { - quote!(::syntax::symbol::Symbol::intern((quote &*self.as_str()))) - } -} - -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 )* - } - } - } - - 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!"), - } - } -} - -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), )* - } - } - } - - gen_match!(Plus, Minus, Star, Slash, Percent, Caret, And, Or, Shl, Shr) - } -} - -impl Quote for Lit { - fn quote(&self) -> TokenStream { - macro_rules! gen_match { - ($($i:ident),*; $($raw:ident),*) => { - match *self { - $( Lit::$i(lit) => quote!(::syntax::parse::token::Lit::$i((quote lit))), )* - $( Lit::$raw(lit, n) => { - quote!(::syntax::parse::token::Lit::$raw((quote lit), (quote n))) - })* - } - } - } - - gen_match!(Byte, Char, Float, Str_, Integer, ByteStr; StrRaw, ByteStrRaw) - } -} - -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) })* - } - } - } - - gen_match!(Paren, Bracket, Brace, NoDelim) - } -} diff --git a/src/libflate/Cargo.toml b/src/libprofiler_builtins/Cargo.toml similarity index 51% rename from src/libflate/Cargo.toml rename to src/libprofiler_builtins/Cargo.toml index e5c611460f..a60db31367 100644 --- a/src/libflate/Cargo.toml +++ b/src/libprofiler_builtins/Cargo.toml @@ -1,14 +1,18 @@ [package] authors = ["The Rust Project Developers"] -name = "flate" -version = "0.0.0" build = "build.rs" +name = "profiler_builtins" +version = "0.0.0" [lib] -name = "flate" +name = "profiler_builtins" path = "lib.rs" -crate-type = ["dylib"] +test = false +bench = false +doc = false + +[dependencies] +core = { path = "../libcore" } [build-dependencies] -build_helper = { path = "../build_helper" } gcc = "0.3.50" diff --git a/src/libprofiler_builtins/build.rs b/src/libprofiler_builtins/build.rs new file mode 100644 index 0000000000..55df14ea21 --- /dev/null +++ b/src/libprofiler_builtins/build.rs @@ -0,0 +1,60 @@ +// 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. + +//! Compiles the profiler part of the `compiler-rt` library. +//! +//! See the build.rs for libcompiler_builtins crate for details. + +extern crate gcc; + +use std::env; +use std::path::Path; + +fn main() { + let target = env::var("TARGET").expect("TARGET was not set"); + let cfg = &mut gcc::Config::new(); + + let mut profile_sources = vec!["GCDAProfiling.c", + "InstrProfiling.c", + "InstrProfilingBuffer.c", + "InstrProfilingFile.c", + "InstrProfilingMerge.c", + "InstrProfilingMergeFile.c", + "InstrProfilingPlatformDarwin.c", + "InstrProfilingPlatformLinux.c", + "InstrProfilingPlatformOther.c", + "InstrProfilingRuntime.cc", + "InstrProfilingUtil.c", + "InstrProfilingValue.c", + "InstrProfilingWriter.c"]; + + if target.contains("msvc") { + // Don't pull in extra libraries on MSVC + cfg.flag("/Zl"); + profile_sources.push("WindowsMMap.c"); + cfg.define("strdup", Some("_strdup")); + cfg.define("open", Some("_open")); + cfg.define("fdopen", Some("_fdopen")); + } else { + // Turn off various features of gcc and such, mostly copying + // compiler-rt's build system already + cfg.flag("-fno-builtin"); + cfg.flag("-fvisibility=hidden"); + cfg.flag("-fomit-frame-pointer"); + cfg.flag("-ffreestanding"); + cfg.define("VISIBILITY_HIDDEN", None); + } + + for src in profile_sources { + cfg.file(Path::new("../libcompiler_builtins/compiler-rt/lib/profile").join(src)); + } + + cfg.compile("libprofiler-rt.a"); +} diff --git a/src/libprofiler_builtins/lib.rs b/src/libprofiler_builtins/lib.rs new file mode 100644 index 0000000000..087cc44418 --- /dev/null +++ b/src/libprofiler_builtins/lib.rs @@ -0,0 +1,20 @@ +// 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. + +#![no_std] +#![cfg_attr(not(stage0), feature(profiler_runtime))] +#![cfg_attr(not(stage0), profiler_runtime)] +#![unstable(feature = "profiler_runtime_lib", + reason = "internal implementation detail of rustc right now", + issue = "0")] +#![crate_name = "profiler_builtins"] +#![crate_type = "rlib"] +#![allow(unused_features)] +#![feature(staged_api)] diff --git a/src/librand/lib.rs b/src/librand/lib.rs index ca05db15ff..5e56b0d8ab 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -31,7 +31,7 @@ issue = "27703")] #![feature(core_intrinsics)] #![feature(staged_api)] -#![feature(step_by)] +#![feature(iterator_step_by)] #![feature(custom_attribute)] #![feature(specialization)] #![allow(unused_attributes)] diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 9d64f51191..89169548bb 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -12,6 +12,7 @@ crate-type = ["dylib"] arena = { path = "../libarena" } fmt_macros = { path = "../libfmt_macros" } graphviz = { path = "../libgraphviz" } +jobserver = "0.1" log = "0.3" owning_ref = "0.3.3" rustc_back = { path = "../librustc_back" } @@ -22,3 +23,32 @@ rustc_errors = { path = "../librustc_errors" } serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } + +# Note that these dependencies are a lie, they're just here to get linkage to +# work. +# +# We're creating a bunch of dylibs for the compiler but we're also compiling a +# bunch of crates.io crates. Everything in the compiler is compiled as an +# rlib/dylib pair but all crates.io crates tend to just be rlibs. This means +# we've got a problem for dependency graphs that look like: +# +# foo - rustc_trans +# / \ +# rustc ---- rustc_driver +# \ / +# foo - rustc_metadata +# +# Here the crate `foo` is linked into the `rustc_trans` and the +# `rustc_metadata` dylibs, meaning we've got duplicate copies! When we then +# go to link `rustc_driver` the compiler notices this and gives us a compiler +# error. +# +# To work around this problem we just add these crates.io dependencies to the +# `rustc` crate which is a shared dependency above. That way the crate `foo` +# shows up in the dylib for the `rustc` crate, deduplicating it and allowing +# crates like `rustc_trans` to use `foo` *through* the `rustc` crate. +# +# tl;dr; this is not needed to get `rustc` to compile, but if you remove it then +# later crate stop compiling. If you can remove this and everything +# compiles, then please feel free to do so! +flate2 = "0.2" diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 85b1858c87..fa6b78045f 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -58,11 +58,11 @@ pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let tables = tcx.typeck_tables_of(owner_def_id); let mut cfg_builder = CFGBuilder { - tcx: tcx, + tcx, owner_def_id, - tables: tables, - graph: graph, - fn_exit: fn_exit, + tables, + graph, + fn_exit, loop_scopes: Vec::new(), breakable_block_scopes: Vec::new(), }; @@ -70,8 +70,8 @@ pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cfg_builder.add_contained_edge(body_exit, fn_exit); let CFGBuilder { graph, .. } = cfg_builder; CFG { - graph: graph, - entry: entry, + graph, + entry, exit: fn_exit, } } diff --git a/src/librustc/dep_graph/README.md b/src/librustc/dep_graph/README.md index 72715cf6bc..c8d0362f17 100644 --- a/src/librustc/dep_graph/README.md +++ b/src/librustc/dep_graph/README.md @@ -16,9 +16,9 @@ The nodes of the graph are defined by the enum `DepNode`. They represent one of three things: 1. HIR nodes (like `Hir(DefId)`) represent the HIR input itself. -2. Data nodes (like `ItemSignature(DefId)`) represent some computed +2. Data nodes (like `TypeOfItem(DefId)`) represent some computed information about a particular item. -3. Procedure notes (like `CoherenceCheckImpl(DefId)`) represent some +3. Procedure nodes (like `CoherenceCheckTrait(DefId)`) represent some procedure that is executing. Usually this procedure is performing some kind of check for errors. You can think of them as computed values where the value being computed is `()` (and the @@ -57,139 +57,10 @@ recompile that item for sure. But we need the dep tracking map to tell us what *else* we have to recompile. Shared state is anything that is used to communicate results from one item to another. -### Identifying the current task +### Identifying the current task, tracking reads/writes, etc -The dep graph always tracks a current task: this is basically the -`DepNode` that the compiler is computing right now. Typically it would -be a procedure node, but it can also be a data node (as noted above, -the two are kind of equivalent). - -You set the current task by calling `dep_graph.in_task(node)`. For example: - -```rust -let _task = tcx.dep_graph.in_task(DepNode::Privacy); -``` - -Now all the code until `_task` goes out of scope will be considered -part of the "privacy task". - -The tasks are maintained in a stack, so it is perfectly fine to nest -one task within another. Because pushing a task is considered to be -computing a value, when you nest a task `N2` inside of a task `N1`, we -automatically add an edge `N2 -> N1` (since `N1` presumably needed the -result of `N2` to complete): - -```rust -let _n1 = tcx.dep_graph.in_task(DepNode::N1); -let _n2 = tcx.dep_graph.in_task(DepNode::N2); -// this will result in an edge N1 -> n2 -``` - -### Ignore tasks - -Although it is rarely needed, you can also push a special "ignore" -task: - -```rust -let _ignore = tc.dep_graph.in_ignore(); -``` - -This will cause all read/write edges to be ignored until it goes out -of scope or until something else is pushed. For example, we could -suppress the edge between nested tasks like so: - -```rust -let _n1 = tcx.dep_graph.in_task(DepNode::N1); -let _ignore = tcx.dep_graph.in_ignore(); -let _n2 = tcx.dep_graph.in_task(DepNode::N2); -// now no edge is added -``` - -### Tracking reads and writes - -We need to identify what shared state is read/written by the current -task as it executes. The most fundamental way of doing that is to invoke -the `read` and `write` methods on `DepGraph`: - -```rust -// Adds an edge from DepNode::Hir(some_def_id) to the current task -tcx.dep_graph.read(DepNode::Hir(some_def_id)) - -// Adds an edge from the current task to DepNode::ItemSignature(some_def_id) -tcx.dep_graph.write(DepNode::ItemSignature(some_def_id)) -``` - -However, you should rarely need to invoke those methods directly. -Instead, the idea is to *encapsulate* shared state into some API that -will invoke `read` and `write` automatically. The most common way to -do this is to use a `DepTrackingMap`, described in the next section, -but any sort of abstraction barrier will do. In general, the strategy -is that getting access to information implicitly adds an appropriate -`read`. So, for example, when you use the -`dep_graph::visit_all_items_in_krate` helper method, it will visit -each item `X`, start a task `Foo(X)` for that item, and automatically -add an edge `Hir(X) -> Foo(X)`. This edge is added because the code is -being given access to the HIR node for `X`, and hence it is expected -to read from it. Similarly, reading from the `tcache` map for item `X` -(which is a `DepTrackingMap`, described below) automatically invokes -`dep_graph.read(ItemSignature(X))`. - -**Note:** adding `Hir` nodes requires a bit of caution due to the -"inlining" that old trans and constant evaluation still use. See the -section on inlining below. - -To make this strategy work, a certain amount of indirection is -required. For example, modules in the HIR do not have direct pointers -to the items that they contain. Rather, they contain node-ids -- one -can then ask the HIR map for the item with a given node-id. This gives -us an opportunity to add an appropriate read edge. - -#### Explicit calls to read and write when starting a new subtask - -One time when you *may* need to call `read` and `write` directly is -when you push a new task onto the stack, either by calling `in_task` -as shown above or indirectly, such as with the `memoize` pattern -described below. In that case, any data that the task has access to -from the surrounding environment must be explicitly "read". For -example, in `librustc_typeck`, the collection code visits all items -and, among other things, starts a subtask producing its signature -(what follows is simplified pseudocode, of course): - -```rust -fn visit_item(item: &hir::Item) { - // Here, current subtask is "Collect(X)", and an edge Hir(X) -> Collect(X) - // has automatically been added by `visit_all_items_in_krate`. - let sig = signature_of_item(item); -} - -fn signature_of_item(item: &hir::Item) { - let def_id = tcx.map.local_def_id(item.id); - let task = tcx.dep_graph.in_task(DepNode::ItemSignature(def_id)); - tcx.dep_graph.read(DepNode::Hir(def_id)); // <-- the interesting line - ... -} -``` - -Here you can see that, in `signature_of_item`, we started a subtask -corresponding to producing the `ItemSignature`. This subtask will read from -`item` -- but it gained access to `item` implicitly. This means that if it just -reads from `item`, there would be missing edges in the graph: - - Hir(X) --+ // added by the explicit call to `read` - | | - | +---> ItemSignature(X) -> Collect(X) - | ^ - | | - +---------------------------------+ // added by `visit_all_items_in_krate` - -In particular, the edge from `Hir(X)` to `ItemSignature(X)` is only -present because we called `read` ourselves when entering the `ItemSignature(X)` -task. - -So, the rule of thumb: when entering a new task yourself, register -reads on any shared state that you inherit. (This actually comes up -fairly infrequently though: the main place you need caution is around -memoization.) +FIXME(#42293). This text needs to be rewritten for the new red-green +system, which doesn't fully exist yet. #### Dependency tracking map @@ -418,7 +289,7 @@ to see something like: Hir(foo) -> Collect(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! diff --git a/src/librustc/dep_graph/debug.rs b/src/librustc/dep_graph/debug.rs index 5b15c5e671..e22552008d 100644 --- a/src/librustc/dep_graph/debug.rs +++ b/src/librustc/dep_graph/debug.rs @@ -12,7 +12,6 @@ use super::dep_node::DepNode; use std::error::Error; -use std::fmt::Debug; /// A dep-node filter goes from a user-defined string to a query over /// nodes. Right now the format is like this: @@ -39,7 +38,7 @@ impl DepNodeFilter { } /// Tests whether `node` meets the filter, returning true if so. - pub fn test(&self, node: &DepNode) -> bool { + pub fn test(&self, node: &DepNode) -> bool { let debug_str = format!("{:?}", node); self.text.split("&") .map(|s| s.trim()) @@ -67,10 +66,10 @@ impl EdgeFilter { } } - pub fn test(&self, - source: &DepNode, - target: &DepNode) - -> bool { + pub fn test(&self, + source: &DepNode, + target: &DepNode) + -> bool { self.source.test(source) && self.target.test(target) } } diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 85a02953a9..c6275e8464 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -8,307 +8,620 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use hir::def_id::CrateNum; -use std::fmt::Debug; -use std::sync::Arc; - -macro_rules! try_opt { - ($e:expr) => ( - match $e { - Some(r) => r, - None => return None, + +//! This module defines the `DepNode` type which the compiler uses to represent +//! nodes in the dependency graph. A `DepNode` consists of a `DepKind` (which +//! specifies the kind of thing it represents, like a piece of HIR, MIR, etc) +//! and a `Fingerprint`, a 128 bit hash value the exact meaning of which +//! depends on the node's `DepKind`. Together, the kind and the fingerprint +//! fully identify a dependency node, even across multiple compilation sessions. +//! In other words, the value of the fingerprint does not depend on anything +//! that is specific to a given compilation session, like an unpredictable +//! interning key (e.g. NodeId, DefId, Symbol) or the numeric value of a +//! pointer. The concept behind this could be compared to how git commit hashes +//! uniquely identify a given commit and has a few advantages: +//! +//! * A `DepNode` can simply be serialized to disk and loaded in another session +//! without the need to do any "rebasing (like we have to do for Spans and +//! NodeIds) or "retracing" like we had to do for `DefId` in earlier +//! implementations of the dependency graph. +//! * A `Fingerprint` is just a bunch of bits, which allows `DepNode` to +//! implement `Copy`, `Sync`, `Send`, `Freeze`, etc. +//! * Since we just have a bit pattern, `DepNode` can be mapped from disk into +//! memory without any post-processing (e.g. "abomination-style" pointer +//! reconstruction). +//! * Because a `DepNode` is self-contained, we can instantiate `DepNodes` that +//! refer to things that do not exist anymore. In previous implementations +//! `DepNode` contained a `DefId`. A `DepNode` referring to something that +//! had been removed between the previous and the current compilation session +//! could not be instantiated because the current compilation session +//! contained no `DefId` for thing that had been removed. +//! +//! `DepNode` definition happens in the `define_dep_nodes!()` macro. This macro +//! defines the `DepKind` enum and a corresponding `DepConstructor` enum. The +//! `DepConstructor` enum links a `DepKind` to the parameters that are needed at +//! runtime in order to construct a valid `DepNode` fingerprint. +//! +//! Because the macro sees what parameters a given `DepKind` requires, it can +//! "infer" some properties for each kind of `DepNode`: +//! +//! * Whether a `DepNode` of a given kind has any parameters at all. Some +//! `DepNode`s, like `Krate`, represent global concepts with only one value. +//! * Whether it is possible, in principle, to reconstruct a query key from a +//! given `DepNode`. Many `DepKind`s only require a single `DefId` parameter, +//! in which case it is possible to map the node's fingerprint back to the +//! `DefId` it was computed from. In other cases, too much information gets +//! lost during fingerprint computation. +//! +//! The `DepConstructor` enum, together with `DepNode::new()` ensures that only +//! valid `DepNode` instances can be constructed. For example, the API does not +//! allow for constructing parameterless `DepNode`s with anything other +//! than a zeroed out fingerprint. More generally speaking, it relieves the +//! user of the `DepNode` API of having to know how to compute the expected +//! fingerprint for a given set of node parameters. + +use hir::def_id::{CrateNum, DefId}; +use hir::map::DefPathHash; + +use ich::Fingerprint; +use ty::{TyCtxt, Instance, InstanceDef}; +use ty::fast_reject::SimplifiedType; +use ty::subst::Substs; +use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; +use ich::StableHashingContext; +use std::fmt; +use std::hash::Hash; + +// erase!() just makes tokens go away. It's used to specify which macro argument +// is repeated (i.e. which sub-expression of the macro we are in) but don't need +// to actually use any of the arguments. +macro_rules! erase { + ($x:tt) => ({}) +} + +macro_rules! anon_attr_to_bool { + (anon) => (true) +} + +macro_rules! define_dep_nodes { + (<$tcx:tt> + $( + [$($anon:ident)*] + $variant:ident $(( $($tuple_arg:tt),* ))* + $({ $($struct_arg_name:ident : $struct_arg_ty:ty),* })* + ,)* + ) => ( + #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, + RustcEncodable, RustcDecodable)] + pub enum DepKind { + $($variant),* + } + + impl DepKind { + #[allow(unreachable_code)] + #[inline] + pub fn can_reconstruct_query_key<$tcx>(&self) -> bool { + match *self { + $( + DepKind :: $variant => { + // tuple args + $({ + return <( $($tuple_arg,)* ) as DepNodeParams> + ::CAN_RECONSTRUCT_QUERY_KEY; + })* + + // struct args + $({ + return <( $($struct_arg_ty,)* ) as DepNodeParams> + ::CAN_RECONSTRUCT_QUERY_KEY; + })* + + true + } + )* + } + } + + #[allow(unreachable_code)] + #[inline] + pub fn is_anon<$tcx>(&self) -> bool { + match *self { + $( + DepKind :: $variant => { + $(return anon_attr_to_bool!($anon);)* + false + } + )* + } + } + + #[allow(unreachable_code)] + #[inline] + pub fn has_params(&self) -> bool { + match *self { + $( + DepKind :: $variant => { + // tuple args + $({ + $(erase!($tuple_arg);)* + return true; + })* + + // struct args + $({ + $(erase!($struct_arg_name);)* + return true; + })* + + false + } + )* + } + } + } + + pub enum DepConstructor<$tcx> { + $( + $variant $(( $($tuple_arg),* ))* + $({ $($struct_arg_name : $struct_arg_ty),* })* + ),* + } + + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, + RustcEncodable, RustcDecodable)] + pub struct DepNode { + pub kind: DepKind, + pub hash: Fingerprint, } - ) + + impl DepNode { + #[allow(unreachable_code, non_snake_case)] + pub fn new<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, + dep: DepConstructor<'gcx>) + -> DepNode + where 'gcx: 'a + 'tcx, + 'tcx: 'a + { + match dep { + $( + DepConstructor :: $variant $(( $($tuple_arg),* ))* + $({ $($struct_arg_name),* })* + => + { + // tuple args + $({ + let tupled_args = ( $($tuple_arg,)* ); + let hash = DepNodeParams::to_fingerprint(&tupled_args, + tcx); + let dep_node = DepNode { + kind: DepKind::$variant, + hash + }; + + if cfg!(debug_assertions) && + !dep_node.kind.can_reconstruct_query_key() && + (tcx.sess.opts.debugging_opts.incremental_info || + tcx.sess.opts.debugging_opts.query_dep_graph) + { + tcx.dep_graph.register_dep_node_debug_str(dep_node, || { + tupled_args.to_debug_str(tcx) + }); + } + + return dep_node; + })* + + // struct args + $({ + let tupled_args = ( $($struct_arg_name,)* ); + let hash = DepNodeParams::to_fingerprint(&tupled_args, + tcx); + let dep_node = DepNode { + kind: DepKind::$variant, + hash + }; + + if cfg!(debug_assertions) && + !dep_node.kind.can_reconstruct_query_key() && + (tcx.sess.opts.debugging_opts.incremental_info || + tcx.sess.opts.debugging_opts.query_dep_graph) + { + tcx.dep_graph.register_dep_node_debug_str(dep_node, || { + tupled_args.to_debug_str(tcx) + }); + } + + return dep_node; + })* + + DepNode { + kind: DepKind::$variant, + hash: Fingerprint::zero(), + } + } + )* + } + } + + /// Construct a DepNode from the given DepKind and DefPathHash. This + /// method will assert that the given DepKind actually requires a + /// single DefId/DefPathHash parameter. + #[inline] + pub fn from_def_path_hash(kind: DepKind, + def_path_hash: DefPathHash) + -> DepNode { + assert!(kind.can_reconstruct_query_key() && kind.has_params()); + DepNode { + kind, + hash: def_path_hash.0, + } + } + + /// Create a new, parameterless DepNode. This method will assert + /// that the DepNode corresponding to the given DepKind actually + /// does not require any parameters. + #[inline] + pub fn new_no_params(kind: DepKind) -> DepNode { + assert!(!kind.has_params()); + DepNode { + kind, + hash: Fingerprint::zero(), + } + } + + /// Extract the DefId corresponding to this DepNode. This will work + /// if two conditions are met: + /// + /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and + /// 2. the item that the DefPath refers to exists in the current tcx. + /// + /// Condition (1) is determined by the DepKind variant of the + /// DepNode. Condition (2) might not be fulfilled if a DepNode + /// refers to something from the previous compilation session that + /// has been removed. + #[inline] + pub fn extract_def_id(&self, tcx: TyCtxt) -> Option { + if self.kind.can_reconstruct_query_key() { + let def_path_hash = DefPathHash(self.hash); + if let Some(ref def_path_map) = tcx.def_path_hash_to_def_id.as_ref() { + def_path_map.get(&def_path_hash).cloned() + } else { + None + } + } else { + None + } + } + + /// Used in testing + pub fn from_label_string(label: &str, + def_path_hash: DefPathHash) + -> Result { + let kind = match label { + $( + stringify!($variant) => DepKind::$variant, + )* + _ => return Err(()), + }; + + if !kind.can_reconstruct_query_key() { + return Err(()); + } + + if kind.has_params() { + Ok(def_path_hash.to_dep_node(kind)) + } else { + Ok(DepNode::new_no_params(kind)) + } + } + } + ); +} + +impl fmt::Debug for DepNode { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self.kind)?; + + if !self.kind.has_params() { + return Ok(()); + } + + write!(f, "(")?; + + ::ty::tls::with_opt(|opt_tcx| { + if let Some(tcx) = opt_tcx { + if let Some(def_id) = self.extract_def_id(tcx) { + write!(f, "{}", tcx.item_path_str(def_id))?; + } else if let Some(ref s) = tcx.dep_graph.dep_node_debug_str(*self) { + write!(f, "{}", s)?; + } else { + write!(f, "{:?}", self.hash)?; + } + } else { + write!(f, "{:?}", self.hash)?; + } + Ok(()) + })?; + + write!(f, ")") + } +} + + +impl DefPathHash { + #[inline] + pub fn to_dep_node(self, kind: DepKind) -> DepNode { + DepNode::from_def_path_hash(kind, self) + } +} + +impl DefId { + #[inline] + pub fn to_dep_node(self, tcx: TyCtxt, kind: DepKind) -> DepNode { + DepNode::from_def_path_hash(kind, tcx.def_path_hash(self)) + } } -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] -pub enum DepNode { - // The `D` type is "how definitions are identified". - // During compilation, it is always `DefId`, but when serializing - // it is mapped to `DefPath`. - - /// 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.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.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 - /// edges yourself for the individual items that you read. - Krate, - - /// Represents the HIR node with the given node-id - Hir(D), - - /// Represents the body of a function or method. The def-id is that of the - /// function/method. - HirBody(D), - - /// Represents the metadata for a given HIR node, typically found - /// in an extern crate. - MetaData(D), - - /// Represents some piece of metadata global to its crate. - GlobalMetaData(D, GlobalMetaDataKind), - - /// Represents some artifact that we save to disk. Note that these - /// do not have a def-id as part of their identifier. - WorkProduct(Arc), +define_dep_nodes!( <'tcx> + // 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.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.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 + // edges yourself for the individual items that you read. + [] Krate, + + // Represents the HIR node with the given node-id + [] Hir(DefId), + + // Represents the body of a function or method. The def-id is that of the + // function/method. + [] HirBody(DefId), + + // Represents the metadata for a given HIR node, typically found + // in an extern crate. + [] MetaData(DefId), + + // Represents some artifact that we save to disk. Note that these + // do not have a def-id as part of their identifier. + [] WorkProduct(WorkProductId), // Represents different phases in the compiler. - RegionMaps(D), - Coherence, - Resolve, - CoherenceCheckTrait(D), - CoherenceCheckImpl(D), - CoherenceOverlapCheck(D), - CoherenceOverlapCheckSpecial(D), - Variance, - PrivacyAccessLevels(CrateNum), + [] RegionMaps(DefId), + [] Coherence, + [] Resolve, + [] CoherenceCheckTrait(DefId), + [] PrivacyAccessLevels(CrateNum), // Represents the MIR for a fn; also used as the task node for // things read/modify that MIR. - MirKrate, - Mir(D), - MirShim(Vec), - - BorrowCheckKrate, - BorrowCheck(D), - RvalueCheck(D), - Reachability, - MirKeys, - LateLintCheck, - TransCrateItem(D), - TransWriteMetadata, - CrateVariances, + [] MirConstQualif(DefId), + [] MirConst(DefId), + [] MirValidated(DefId), + [] MirOptimized(DefId), + [] MirShim { instance_def: InstanceDef<'tcx> }, + + [] BorrowCheckKrate, + [] BorrowCheck(DefId), + [] RvalueCheck(DefId), + [] Reachability, + [] MirKeys, + [] TransWriteMetadata, + [] CrateVariances, // Nodes representing bits of computed IR in the tcx. Each shared // table in the tcx (or elsewhere) maps to one of these - // nodes. Often we map multiple tables to the same node if there - // is no point in distinguishing them (e.g., both the type and - // predicates for an item wind up in `ItemSignature`). - AssociatedItems(D), - ItemSignature(D), - ItemVarianceConstraints(D), - ItemVariances(D), - IsForeignItem(D), - TypeParamPredicates((D, D)), - SizedConstraint(D), - DtorckConstraint(D), - AdtDestructor(D), - AssociatedItemDefIds(D), - InherentImpls(D), - TypeckBodiesKrate, - TypeckTables(D), - UsedTraitImports(D), - ConstEval(D), - SymbolName(D), - SpecializationGraph(D), - ObjectSafety(D), - IsCopy(D), - IsSized(D), - IsFreeze(D), - NeedsDrop(D), - Layout(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 - /// simplified type), but we can't do that until we restructure the - /// HIR to distinguish the *header* of an impl from its body. This - /// is because changes to the header may change the self-type of - /// the impl and hence would require us to be more conservative - /// than changes in the impl body. - TraitImpls(D), - - AllLocalTraitImpls, + // nodes. + [] AssociatedItems(DefId), + [] TypeOfItem(DefId), + [] GenericsOfItem(DefId), + [] PredicatesOfItem(DefId), + [] SuperPredicatesOfItem(DefId), + [] TraitDefOfItem(DefId), + [] AdtDefOfItem(DefId), + [] IsDefaultImpl(DefId), + [] ImplTraitRef(DefId), + [] ImplPolarity(DefId), + [] ClosureKind(DefId), + [] FnSignature(DefId), + [] CoerceUnsizedInfo(DefId), + + [] ItemVarianceConstraints(DefId), + [] ItemVariances(DefId), + [] IsConstFn(DefId), + [] IsForeignItem(DefId), + [] TypeParamPredicates { item_id: DefId, param_id: DefId }, + [] SizedConstraint(DefId), + [] DtorckConstraint(DefId), + [] AdtDestructor(DefId), + [] AssociatedItemDefIds(DefId), + [] InherentImpls(DefId), + [] TypeckBodiesKrate, + [] TypeckTables(DefId), + [] HasTypeckTables(DefId), + [] ConstEval { def_id: DefId, substs: &'tcx Substs<'tcx> }, + [] SymbolName(DefId), + [] InstanceSymbolName { instance: Instance<'tcx> }, + [] SpecializationGraph(DefId), + [] ObjectSafety(DefId), + + [anon] IsCopy(DefId), + [anon] IsSized(DefId), + [anon] IsFreeze(DefId), + [anon] NeedsDrop(DefId), + [anon] Layout(DefId), + + // The set of impls for a given trait. + [] TraitImpls(DefId), + [] RelevantTraitImpls(DefId, SimplifiedType), + + [] AllLocalTraitImpls, // Nodes representing caches. To properly handle a true cache, we // don't use a DepTrackingMap, but rather we push a task node. // Otherwise the write into the map would be incorrectly // attributed to the first task that happened to fill the cache, // which would yield an overly conservative dep-graph. - TraitItems(D), - ReprHints(D), - - /// Trait selection cache is a little funny. Given a trait - /// reference like `Foo: SomeTrait`, there could be - /// arbitrarily many def-ids to map on in there (e.g., `Foo`, - /// `SomeTrait`, `Bar`). We could have a vector of them, but it - /// requires heap-allocation, and trait sel in general can be a - /// surprisingly hot path. So instead we pick two def-ids: the - /// trait def-id, and the first def-id in the input types. If there - /// is no def-id in the input types, then we use the trait def-id - /// again. So for example: - /// - /// - `i32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }` - /// - `u32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }` - /// - `Clone: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }` - /// - `Vec: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Vec }` - /// - `String: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: String }` - /// - `Foo: Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` - /// - `Foo: Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` - /// - `(Foo, Bar): Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` - /// - `i32: Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` - /// - /// You can see that we map many trait refs to the same - /// trait-select node. This is not a problem, it just means - /// imprecision in our dep-graph tracking. The important thing is - /// that for any given trait-ref, we always map to the **same** - /// trait-select node. - TraitSelect { trait_def_id: D, input_def_id: D }, - - /// For proj. cache, we just keep a list of all def-ids, since it is - /// not a hotspot. - ProjectionCache { def_ids: Vec }, - - ParamEnv(D), - DescribeDef(D), - DefSpan(D), - Stability(D), - Deprecation(D), - ItemBodyNestedBodies(D), - ConstIsRvaluePromotableToStatic(D), - ImplParent(D), - TraitOfItem(D), - IsExportedSymbol(D), - IsMirAvailable(D), - ItemAttrs(D), - FnArgNames(D), + [] TraitItems(DefId), + [] ReprHints(DefId), + + // Trait selection cache is a little funny. Given a trait + // reference like `Foo: SomeTrait`, there could be + // arbitrarily many def-ids to map on in there (e.g., `Foo`, + // `SomeTrait`, `Bar`). We could have a vector of them, but it + // requires heap-allocation, and trait sel in general can be a + // surprisingly hot path. So instead we pick two def-ids: the + // trait def-id, and the first def-id in the input types. If there + // is no def-id in the input types, then we use the trait def-id + // again. So for example: + // + // - `i32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }` + // - `u32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }` + // - `Clone: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }` + // - `Vec: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Vec }` + // - `String: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: String }` + // - `Foo: Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` + // - `Foo: Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` + // - `(Foo, Bar): Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` + // - `i32: Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` + // + // You can see that we map many trait refs to the same + // trait-select node. This is not a problem, it just means + // imprecision in our dep-graph tracking. The important thing is + // that for any given trait-ref, we always map to the **same** + // trait-select node. + [] TraitSelect { trait_def_id: DefId, input_def_id: DefId }, + + // For proj. cache, we just keep a list of all def-ids, since it is + // not a hotspot. + [] ProjectionCache { def_ids: DefIdList }, + + [] ParamEnv(DefId), + [] DescribeDef(DefId), + [] DefSpan(DefId), + [] Stability(DefId), + [] Deprecation(DefId), + [] ItemBodyNestedBodies(DefId), + [] ConstIsRvaluePromotableToStatic(DefId), + [] ImplParent(DefId), + [] TraitOfItem(DefId), + [] IsExportedSymbol(DefId), + [] IsMirAvailable(DefId), + [] ItemAttrs(DefId), + [] FnArgNames(DefId), + [] DylibDepFormats(DefId), + [] IsAllocator(DefId), + [] IsPanicRuntime(DefId), + [] ExternCrate(DefId), +); + +trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug { + const CAN_RECONSTRUCT_QUERY_KEY: bool; + + /// This method turns the parameters of a DepNodeConstructor into an opaque + /// Fingerprint to be used in DepNode. + /// Not all DepNodeParams support being turned into a Fingerprint (they + /// don't need to if the corresponding DepNode is anonymous). + fn to_fingerprint(&self, _: TyCtxt<'a, 'gcx, 'tcx>) -> Fingerprint { + panic!("Not implemented. Accidentally called on anonymous node?") + } + + fn to_debug_str(&self, _: TyCtxt<'a, 'gcx, 'tcx>) -> String { + format!("{:?}", self) + } } -impl DepNode { - /// Used in testing - pub fn from_label_string(label: &str, data: D) -> Result, ()> { - macro_rules! check { - ($($name:ident,)*) => { - match label { - $(stringify!($name) => Ok(DepNode::$name(data)),)* - _ => Err(()) - } - } - } +impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a, T> DepNodeParams<'a, 'gcx, 'tcx> for T + where T: HashStable> + fmt::Debug +{ + default const CAN_RECONSTRUCT_QUERY_KEY: bool = false; - if label == "Krate" { - // special case - return Ok(DepNode::Krate); - } + default fn to_fingerprint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Fingerprint { + let mut hcx = StableHashingContext::new(tcx); + let mut hasher = StableHasher::new(); + + self.hash_stable(&mut hcx, &mut hasher); + + hasher.finish() + } + + default fn to_debug_str(&self, _: TyCtxt<'a, 'gcx, 'tcx>) -> String { + format!("{:?}", *self) + } +} + +impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId,) { + const CAN_RECONSTRUCT_QUERY_KEY: bool = true; + + fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint { + tcx.def_path_hash(self.0).0 + } + + fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String { + tcx.item_path_str(self.0) + } +} - check! { - BorrowCheck, - Hir, - HirBody, - TransCrateItem, - AssociatedItems, - ItemSignature, - ItemVariances, - IsForeignItem, - AssociatedItemDefIds, - InherentImpls, - TypeckTables, - UsedTraitImports, - TraitImpls, - ReprHints, +impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId, DefId) { + const CAN_RECONSTRUCT_QUERY_KEY: bool = false; + + // We actually would not need to specialize the implementation of this + // method but it's faster to combine the hashes than to instantiate a full + // hashing context and stable-hashing state. + fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint { + let (def_id_0, def_id_1) = *self; + + let def_path_hash_0 = tcx.def_path_hash(def_id_0); + let def_path_hash_1 = tcx.def_path_hash(def_id_1); + + def_path_hash_0.0.combine(def_path_hash_1.0) + } + + fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String { + let (def_id_0, def_id_1) = *self; + + format!("({}, {})", + tcx.def_path(def_id_0).to_string(tcx), + tcx.def_path(def_id_1).to_string(tcx)) + } +} + + +impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefIdList,) { + const CAN_RECONSTRUCT_QUERY_KEY: bool = false; + + // We actually would not need to specialize the implementation of this + // method but it's faster to combine the hashes than to instantiate a full + // hashing context and stable-hashing state. + fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint { + let mut fingerprint = Fingerprint::zero(); + + for &def_id in self.0.iter() { + let def_path_hash = tcx.def_path_hash(def_id); + fingerprint = fingerprint.combine(def_path_hash.0); } + + fingerprint } - pub fn map_def(&self, mut op: OP) -> Option> - where OP: FnMut(&D) -> Option, E: Clone + Debug - { - use self::DepNode::*; - - match *self { - Krate => Some(Krate), - BorrowCheckKrate => Some(BorrowCheckKrate), - MirKrate => Some(MirKrate), - TypeckBodiesKrate => Some(TypeckBodiesKrate), - Coherence => Some(Coherence), - CrateVariances => Some(CrateVariances), - Resolve => Some(Resolve), - Variance => Some(Variance), - PrivacyAccessLevels(k) => Some(PrivacyAccessLevels(k)), - Reachability => Some(Reachability), - MirKeys => Some(MirKeys), - LateLintCheck => Some(LateLintCheck), - TransWriteMetadata => Some(TransWriteMetadata), - - // work product names do not need to be mapped, because - // they are always absolute. - WorkProduct(ref id) => Some(WorkProduct(id.clone())), - - IsCopy(ref d) => op(d).map(IsCopy), - IsSized(ref d) => op(d).map(IsSized), - IsFreeze(ref d) => op(d).map(IsFreeze), - NeedsDrop(ref d) => op(d).map(NeedsDrop), - Layout(ref d) => op(d).map(Layout), - Hir(ref d) => op(d).map(Hir), - HirBody(ref d) => op(d).map(HirBody), - MetaData(ref d) => op(d).map(MetaData), - CoherenceCheckTrait(ref d) => op(d).map(CoherenceCheckTrait), - CoherenceCheckImpl(ref d) => op(d).map(CoherenceCheckImpl), - CoherenceOverlapCheck(ref d) => op(d).map(CoherenceOverlapCheck), - CoherenceOverlapCheckSpecial(ref d) => op(d).map(CoherenceOverlapCheckSpecial), - Mir(ref d) => op(d).map(Mir), - MirShim(ref def_ids) => { - let def_ids: Option> = def_ids.iter().map(op).collect(); - def_ids.map(MirShim) - } - BorrowCheck(ref d) => op(d).map(BorrowCheck), - RegionMaps(ref d) => op(d).map(RegionMaps), - RvalueCheck(ref d) => op(d).map(RvalueCheck), - TransCrateItem(ref d) => op(d).map(TransCrateItem), - AssociatedItems(ref d) => op(d).map(AssociatedItems), - ItemSignature(ref d) => op(d).map(ItemSignature), - ItemVariances(ref d) => op(d).map(ItemVariances), - ItemVarianceConstraints(ref d) => op(d).map(ItemVarianceConstraints), - IsForeignItem(ref d) => op(d).map(IsForeignItem), - TypeParamPredicates((ref item, ref param)) => { - Some(TypeParamPredicates((try_opt!(op(item)), try_opt!(op(param))))) - } - SizedConstraint(ref d) => op(d).map(SizedConstraint), - DtorckConstraint(ref d) => op(d).map(DtorckConstraint), - AdtDestructor(ref d) => op(d).map(AdtDestructor), - AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds), - InherentImpls(ref d) => op(d).map(InherentImpls), - TypeckTables(ref d) => op(d).map(TypeckTables), - UsedTraitImports(ref d) => op(d).map(UsedTraitImports), - ConstEval(ref d) => op(d).map(ConstEval), - SymbolName(ref d) => op(d).map(SymbolName), - SpecializationGraph(ref d) => op(d).map(SpecializationGraph), - ObjectSafety(ref d) => op(d).map(ObjectSafety), - TraitImpls(ref d) => op(d).map(TraitImpls), - AllLocalTraitImpls => Some(AllLocalTraitImpls), - TraitItems(ref d) => op(d).map(TraitItems), - ReprHints(ref d) => op(d).map(ReprHints), - TraitSelect { ref trait_def_id, ref input_def_id } => { - op(trait_def_id).and_then(|trait_def_id| { - op(input_def_id).and_then(|input_def_id| { - Some(TraitSelect { trait_def_id: trait_def_id, - input_def_id: input_def_id }) - }) - }) - } - ProjectionCache { ref def_ids } => { - let def_ids: Option> = def_ids.iter().map(op).collect(); - def_ids.map(|d| ProjectionCache { def_ids: d }) - } - ParamEnv(ref d) => op(d).map(ParamEnv), - DescribeDef(ref d) => op(d).map(DescribeDef), - DefSpan(ref d) => op(d).map(DefSpan), - Stability(ref d) => op(d).map(Stability), - Deprecation(ref d) => op(d).map(Deprecation), - ItemAttrs(ref d) => op(d).map(ItemAttrs), - FnArgNames(ref d) => op(d).map(FnArgNames), - ImplParent(ref d) => op(d).map(ImplParent), - TraitOfItem(ref d) => op(d).map(TraitOfItem), - IsExportedSymbol(ref d) => op(d).map(IsExportedSymbol), - ItemBodyNestedBodies(ref d) => op(d).map(ItemBodyNestedBodies), - ConstIsRvaluePromotableToStatic(ref d) => op(d).map(ConstIsRvaluePromotableToStatic), - IsMirAvailable(ref d) => op(d).map(IsMirAvailable), - GlobalMetaData(ref d, kind) => op(d).map(|d| GlobalMetaData(d, kind)), + fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String { + use std::fmt::Write; + + let mut s = String::new(); + write!(&mut s, "[").unwrap(); + + for &def_id in self.0.iter() { + write!(&mut s, "{}", tcx.def_path(def_id).to_string(tcx)).unwrap(); } + + write!(&mut s, "]").unwrap(); + + s } } @@ -317,18 +630,38 @@ impl DepNode { /// some independent path or string that persists between runs without /// the need to be mapped or unmapped. (This ensures we can serialize /// them even in the absence of a tcx.) -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] -pub struct WorkProductId(pub String); - -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] -pub enum GlobalMetaDataKind { - Krate, - CrateDeps, - DylibDependencyFormats, - LangItems, - LangItemsMissing, - NativeLibraries, - CodeMap, - Impls, - ExportedSymbols, +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, + RustcEncodable, RustcDecodable)] +pub struct WorkProductId { + hash: Fingerprint +} + +impl WorkProductId { + pub fn from_cgu_name(cgu_name: &str) -> WorkProductId { + let mut hasher = StableHasher::new(); + cgu_name.len().hash(&mut hasher); + cgu_name.hash(&mut hasher); + WorkProductId { + hash: hasher.finish() + } + } + + pub fn from_fingerprint(fingerprint: Fingerprint) -> WorkProductId { + WorkProductId { + hash: fingerprint + } + } + + pub fn to_dep_node(self) -> DepNode { + DepNode { + kind: DepKind::WorkProduct, + hash: self.hash, + } + } } + +impl_stable_hash_for!(struct ::dep_graph::WorkProductId { + hash +}); + +type DefIdList = Vec; diff --git a/src/librustc/dep_graph/dep_tracking_map.rs b/src/librustc/dep_graph/dep_tracking_map.rs index 7a246c814d..ca53fd7a43 100644 --- a/src/librustc/dep_graph/dep_tracking_map.rs +++ b/src/librustc/dep_graph/dep_tracking_map.rs @@ -8,12 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use hir::def_id::DefId; use rustc_data_structures::fx::FxHashMap; use std::cell::RefCell; -use std::ops::Index; use std::hash::Hash; use std::marker::PhantomData; +use ty::TyCtxt; use util::common::MemoizationMap; use super::{DepNode, DepGraph}; @@ -30,32 +29,32 @@ pub struct DepTrackingMap { pub trait DepTrackingMapConfig { type Key: Eq + Hash + Clone; type Value: Clone; - fn to_dep_node(key: &Self::Key) -> DepNode; + fn to_dep_node(tcx: TyCtxt, key: &Self::Key) -> DepNode; } impl DepTrackingMap { pub fn new(graph: DepGraph) -> DepTrackingMap { DepTrackingMap { phantom: PhantomData, - graph: graph, + graph, map: FxHashMap(), } } /// Registers a (synthetic) read from the key `k`. Usually this /// is invoked automatically by `get`. - fn read(&self, k: &M::Key) { - let dep_node = M::to_dep_node(k); + fn read(&self, tcx: TyCtxt, k: &M::Key) { + let dep_node = M::to_dep_node(tcx, k); self.graph.read(dep_node); } - pub fn get(&self, k: &M::Key) -> Option<&M::Value> { - self.read(k); + pub fn get(&self, tcx: TyCtxt, k: &M::Key) -> Option<&M::Value> { + self.read(tcx, k); self.map.get(k) } - pub fn contains_key(&self, k: &M::Key) -> bool { - self.read(k); + pub fn contains_key(&self, tcx: TyCtxt, k: &M::Key) -> bool { + self.read(tcx, k); self.map.contains_key(k) } @@ -99,32 +98,22 @@ impl MemoizationMap for RefCell> { /// The key is the line marked `(*)`: the closure implicitly /// accesses the body of the item `item`, so we register a read /// from `Hir(item_def_id)`. - fn memoize(&self, key: M::Key, op: OP) -> M::Value + fn memoize(&self, tcx: TyCtxt, key: M::Key, op: OP) -> M::Value where OP: FnOnce() -> M::Value { let graph; { let this = self.borrow(); if let Some(result) = this.map.get(&key) { - this.read(&key); + this.read(tcx, &key); return result.clone(); } graph = this.graph.clone(); } - let _task = graph.in_task(M::to_dep_node(&key)); + let _task = graph.in_task(M::to_dep_node(tcx, &key)); let result = op(); self.borrow_mut().map.insert(key, result.clone()); result } } - -impl<'k, M: DepTrackingMapConfig> Index<&'k M::Key> for DepTrackingMap { - type Output = M::Value; - - #[inline] - fn index(&self, k: &'k M::Key) -> &M::Value { - self.get(k).unwrap() - } -} - diff --git a/src/librustc/dep_graph/edges.rs b/src/librustc/dep_graph/edges.rs index 5dbabcc923..277b69262c 100644 --- a/src/librustc/dep_graph/edges.rs +++ b/src/librustc/dep_graph/edges.rs @@ -8,27 +8,35 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use ich::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use std::fmt::Debug; +use rustc_data_structures::stable_hasher::StableHasher; +use std::env; use std::hash::Hash; -use super::{DepGraphQuery, DepNode}; - -pub struct DepGraphEdges { - nodes: Vec>, - indices: FxHashMap, IdIndex>, - edges: FxHashSet<(IdIndex, IdIndex)>, - open_nodes: Vec, +use std::mem; +use super::{DepGraphQuery, DepKind, DepNode}; +use super::debug::EdgeFilter; + +pub struct DepGraphEdges { + nodes: Vec, + indices: FxHashMap, + edges: FxHashSet<(DepNodeIndex, DepNodeIndex)>, + task_stack: Vec, + forbidden_edge: Option, } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -struct IdIndex { +pub struct DepNodeIndex { index: u32 } -impl IdIndex { - fn new(v: usize) -> IdIndex { +impl DepNodeIndex { + + pub const INVALID: DepNodeIndex = DepNodeIndex { index: ::std::u32::MAX }; + + fn new(v: usize) -> DepNodeIndex { assert!((v & 0xFFFF_FFFF) == v); - IdIndex { index: v as u32 } + DepNodeIndex { index: v as u32 } } fn index(self) -> usize { @@ -37,67 +45,136 @@ impl IdIndex { } #[derive(Clone, Debug, PartialEq)] -enum OpenNode { - Node(IdIndex), +enum OpenTask { + Regular { + node: DepNode, + reads: Vec, + read_set: FxHashSet, + }, + Anon { + reads: Vec, + read_set: FxHashSet, + }, Ignore, } -impl DepGraphEdges { - pub fn new() -> DepGraphEdges { +impl DepGraphEdges { + pub fn new() -> DepGraphEdges { + let forbidden_edge = if cfg!(debug_assertions) { + match env::var("RUST_FORBID_DEP_GRAPH_EDGE") { + Ok(s) => { + match EdgeFilter::new(&s) { + Ok(f) => Some(f), + Err(err) => bug!("RUST_FORBID_DEP_GRAPH_EDGE invalid: {}", err), + } + } + Err(_) => None, + } + } else { + None + }; + DepGraphEdges { nodes: vec![], indices: FxHashMap(), edges: FxHashSet(), - open_nodes: Vec::new() + task_stack: Vec::new(), + forbidden_edge, } } - fn id(&self, index: IdIndex) -> DepNode { - self.nodes[index.index()].clone() + fn id(&self, index: DepNodeIndex) -> DepNode { + self.nodes[index.index()] } - /// Creates a node for `id` in the graph. - fn make_node(&mut self, id: DepNode) -> IdIndex { - if let Some(&i) = self.indices.get(&id) { - return i; - } - - let index = IdIndex::new(self.nodes.len()); - self.nodes.push(id.clone()); - self.indices.insert(id, index); - index + pub fn push_ignore(&mut self) { + self.task_stack.push(OpenTask::Ignore); } - /// Top of the stack of open nodes. - fn current_node(&self) -> Option { - self.open_nodes.last().cloned() + pub fn pop_ignore(&mut self) { + let popped_node = self.task_stack.pop().unwrap(); + debug_assert_eq!(popped_node, OpenTask::Ignore); } - pub fn push_ignore(&mut self) { - self.open_nodes.push(OpenNode::Ignore); + pub fn push_task(&mut self, key: DepNode) { + self.task_stack.push(OpenTask::Regular { + node: key, + reads: Vec::new(), + read_set: FxHashSet(), + }); } - pub fn pop_ignore(&mut self) { - let popped_node = self.open_nodes.pop().unwrap(); - assert_eq!(popped_node, OpenNode::Ignore); - } + pub fn pop_task(&mut self, key: DepNode) -> DepNodeIndex { + let popped_node = self.task_stack.pop().unwrap(); + + if let OpenTask::Regular { + node, + read_set: _, + reads + } = popped_node { + debug_assert_eq!(node, key); - pub fn push_task(&mut self, key: DepNode) { - let top_node = self.current_node(); + let target_id = self.get_or_create_node(node); - let new_node = self.make_node(key); - self.open_nodes.push(OpenNode::Node(new_node)); + for read in reads.into_iter() { + let source_id = self.get_or_create_node(read); + self.edges.insert((source_id, target_id)); + } - // if we are in the midst of doing task T, then this new task - // N is a subtask of T, so add an edge N -> T. - if let Some(top_node) = top_node { - self.add_edge_from_open_node(top_node, |t| (new_node, t)); + target_id + } else { + bug!("pop_task() - Expected regular task to be popped") } } - pub fn pop_task(&mut self, key: DepNode) { - let popped_node = self.open_nodes.pop().unwrap(); - assert_eq!(OpenNode::Node(self.indices[&key]), popped_node); + pub fn push_anon_task(&mut self) { + self.task_stack.push(OpenTask::Anon { + reads: Vec::new(), + read_set: FxHashSet(), + }); + } + + pub fn pop_anon_task(&mut self, kind: DepKind) -> DepNodeIndex { + let popped_node = self.task_stack.pop().unwrap(); + + if let OpenTask::Anon { + read_set: _, + reads + } = popped_node { + let mut fingerprint = Fingerprint::zero(); + let mut hasher = StableHasher::new(); + + for read in reads.iter() { + mem::discriminant(&read.kind).hash(&mut hasher); + + // Fingerprint::combine() is faster than sending Fingerprint + // through the StableHasher (at least as long as StableHasher + // is so slow). + fingerprint = fingerprint.combine(read.hash); + } + + fingerprint = fingerprint.combine(hasher.finish()); + + let target_dep_node = DepNode { + kind, + hash: fingerprint, + }; + + if let Some(&index) = self.indices.get(&target_dep_node) { + return index; + } + + let target_id = self.get_or_create_node(target_dep_node); + + for read in reads.into_iter() { + let source_id = self.get_or_create_node(read); + self.edges.insert((source_id, target_id)); + } + + target_id + } else { + bug!("pop_anon_task() - Expected anonymous task to be popped") + } } /// Indicates that the current task `C` reads `v` by adding an @@ -105,64 +182,74 @@ impl DepGraphEdges { /// effect. Note that *reading* from tracked state is harmless if /// you are not in a task; what is bad is *writing* to tracked /// state (and leaking data that you read into a tracked task). - pub fn read(&mut self, v: DepNode) { - if self.current_node().is_some() { - let source = self.make_node(v); - self.add_edge_from_current_node(|current| (source, current)) - } - } - - /// Indicates that the current task `C` writes `v` by adding an - /// edge from `C` to `v`. If there is no current task, panics. If - /// you want to suppress this edge, use `ignore`. - pub fn write(&mut self, v: DepNode) { - let target = self.make_node(v); - self.add_edge_from_current_node(|current| (current, target)) - } - - /// Invoke `add_edge_from_open_node` with the top of the stack, or - /// panic if stack is empty. - fn add_edge_from_current_node(&mut self, - op: OP) - where OP: FnOnce(IdIndex) -> (IdIndex, IdIndex) - { - match self.current_node() { - Some(open_node) => self.add_edge_from_open_node(open_node, op), - None => bug!("no current node, cannot add edge into dependency graph") + pub fn read(&mut self, source: DepNode) { + match self.task_stack.last_mut() { + Some(&mut OpenTask::Regular { + node: target, + ref mut reads, + ref mut read_set, + }) => { + if read_set.insert(source) { + reads.push(source); + + if cfg!(debug_assertions) { + if let Some(ref forbidden_edge) = self.forbidden_edge { + if forbidden_edge.test(&source, &target) { + bug!("forbidden edge {:?} -> {:?} created", source, target) + } + } + } + } + } + Some(&mut OpenTask::Anon { + ref mut reads, + ref mut read_set, + }) => { + if read_set.insert(source) { + reads.push(source); + } + } + Some(&mut OpenTask::Ignore) | None => { + // ignore + } } } - /// Adds an edge to or from the `open_node`, assuming `open_node` - /// is not `Ignore`. The direction of the edge is determined by - /// the closure `op` --- we pass as argument the open node `n`, - /// and the closure returns a (source, target) tuple, which should - /// include `n` in one spot or another. - fn add_edge_from_open_node(&mut self, - open_node: OpenNode, - op: OP) - where OP: FnOnce(IdIndex) -> (IdIndex, IdIndex) - { - let (source, target) = match open_node { - OpenNode::Node(n) => op(n), - OpenNode::Ignore => { return; } - }; - - // ignore trivial self edges, which are not very interesting - if source == target { - return; - } - - if self.edges.insert((source, target)) { - debug!("adding edge from {:?} to {:?}", - self.id(source), - self.id(target)); - } + pub fn read_index(&mut self, source: DepNodeIndex) { + let dep_node = self.nodes[source.index()]; + self.read(dep_node); } - pub fn query(&self) -> DepGraphQuery { + pub fn query(&self) -> DepGraphQuery { let edges: Vec<_> = self.edges.iter() .map(|&(i, j)| (self.id(i), self.id(j))) .collect(); DepGraphQuery::new(&self.nodes, &edges) } + + #[inline] + pub fn add_edge(&mut self, source: DepNode, target: DepNode) { + let source = self.get_or_create_node(source); + let target = self.get_or_create_node(target); + self.edges.insert((source, target)); + } + + pub fn add_node(&mut self, node: DepNode) { + self.get_or_create_node(node); + } + + #[inline] + fn get_or_create_node(&mut self, dep_node: DepNode) -> DepNodeIndex { + let DepGraphEdges { + ref mut indices, + ref mut nodes, + .. + } = *self; + + *indices.entry(dep_node).or_insert_with(|| { + let next_id = nodes.len(); + nodes.push(dep_node); + DepNodeIndex::new(next_id) + }) + } } diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 18eb4e5d0a..4ca59132e0 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -8,66 +8,70 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use hir::def_id::DefId; use rustc_data_structures::fx::FxHashMap; use session::config::OutputType; use std::cell::{Ref, RefCell}; use std::rc::Rc; -use std::sync::Arc; -use super::dep_node::{DepNode, WorkProductId}; +use super::dep_node::{DepNode, DepKind, WorkProductId}; use super::query::DepGraphQuery; use super::raii; use super::safe::DepGraphSafe; -use super::thread::{DepGraphThreadData, DepMessage}; +use super::edges::{DepGraphEdges, DepNodeIndex}; #[derive(Clone)] pub struct DepGraph { - data: Rc + data: Option> } struct DepGraphData { - /// We send messages to the thread to let it build up the dep-graph - /// from the current run. - thread: DepGraphThreadData, + /// The actual graph data. + edges: RefCell, /// When we load, there may be `.o` files, cached mir, or other such /// things available to us. If we find that they are not dirty, we /// load the path to the file storing those work-products here into /// this map. We can later look for and extract that data. - previous_work_products: RefCell, WorkProduct>>, + previous_work_products: RefCell>, /// Work-products that we generate in this run. - work_products: RefCell, WorkProduct>>, + work_products: RefCell>, + + dep_node_debug: RefCell>, } impl DepGraph { pub fn new(enabled: bool) -> DepGraph { DepGraph { - data: Rc::new(DepGraphData { - thread: DepGraphThreadData::new(enabled), - previous_work_products: RefCell::new(FxHashMap()), - work_products: RefCell::new(FxHashMap()), - }) + data: if enabled { + Some(Rc::new(DepGraphData { + previous_work_products: RefCell::new(FxHashMap()), + work_products: RefCell::new(FxHashMap()), + edges: RefCell::new(DepGraphEdges::new()), + dep_node_debug: RefCell::new(FxHashMap()), + })) + } else { + None + } } } /// True if we are actually building the full dep-graph. #[inline] pub fn is_fully_enabled(&self) -> bool { - self.data.thread.is_fully_enabled() + self.data.is_some() } - pub fn query(&self) -> DepGraphQuery { - self.data.thread.query() + pub fn query(&self) -> DepGraphQuery { + self.data.as_ref().unwrap().edges.borrow().query() } pub fn in_ignore<'graph>(&'graph self) -> Option> { - raii::IgnoreTask::new(&self.data.thread) + self.data.as_ref().map(|data| raii::IgnoreTask::new(&data.edges)) } - pub fn in_task<'graph>(&'graph self, key: DepNode) -> Option> { - raii::DepTask::new(&self.data.thread, key) + pub fn in_task<'graph>(&'graph self, key: DepNode) -> Option> { + self.data.as_ref().map(|data| raii::DepTask::new(&data.edges, key)) } pub fn with_ignore(&self, op: OP) -> R @@ -104,55 +108,126 @@ impl DepGraph { /// `arg` parameter. /// /// [README]: README.md - pub fn with_task(&self, key: DepNode, cx: C, arg: A, task: fn(C, A) -> R) -> R - where C: DepGraphSafe, A: DepGraphSafe + pub fn with_task(&self, + key: DepNode, + cx: C, + arg: A, + task: fn(C, A) -> R) + -> (R, DepNodeIndex) + where C: DepGraphSafe { - let _task = self.in_task(key); - task(cx, arg) + if let Some(ref data) = self.data { + data.edges.borrow_mut().push_task(key); + let result = task(cx, arg); + let dep_node_index = data.edges.borrow_mut().pop_task(key); + (result, dep_node_index) + } else { + (task(cx, arg), DepNodeIndex::INVALID) + } } - pub fn read(&self, v: DepNode) { - if self.data.thread.is_enqueue_enabled() { - self.data.thread.enqueue(DepMessage::Read(v)); + /// Execute something within an "anonymous" task, that is, a task the + /// DepNode of which is determined by the list of inputs it read from. + pub fn with_anon_task(&self, dep_kind: DepKind, op: OP) -> (R, DepNodeIndex) + where OP: FnOnce() -> R + { + if let Some(ref data) = self.data { + data.edges.borrow_mut().push_anon_task(); + let result = op(); + let dep_node = data.edges.borrow_mut().pop_anon_task(dep_kind); + (result, dep_node) + } else { + (op(), DepNodeIndex::INVALID) + } + } + + #[inline] + pub fn read(&self, v: DepNode) { + if let Some(ref data) = self.data { + data.edges.borrow_mut().read(v); + } + } + + #[inline] + pub fn read_index(&self, v: DepNodeIndex) { + if let Some(ref data) = self.data { + data.edges.borrow_mut().read_index(v); } } + /// Only to be used during graph loading + #[inline] + pub fn add_edge_directly(&self, source: DepNode, target: DepNode) { + self.data.as_ref().unwrap().edges.borrow_mut().add_edge(source, target); + } + + /// Only to be used during graph loading + pub fn add_node_directly(&self, node: DepNode) { + self.data.as_ref().unwrap().edges.borrow_mut().add_node(node); + } + /// Indicates that a previous work product exists for `v`. This is /// invoked during initial start-up based on what nodes are clean /// (and what files exist in the incr. directory). - pub fn insert_previous_work_product(&self, v: &Arc, data: WorkProduct) { + pub fn insert_previous_work_product(&self, v: &WorkProductId, data: WorkProduct) { debug!("insert_previous_work_product({:?}, {:?})", v, data); - self.data.previous_work_products.borrow_mut() - .insert(v.clone(), data); + self.data + .as_ref() + .unwrap() + .previous_work_products + .borrow_mut() + .insert(v.clone(), data); } /// Indicates that we created the given work-product in this run /// for `v`. This record will be preserved and loaded in the next /// run. - pub fn insert_work_product(&self, v: &Arc, data: WorkProduct) { + pub fn insert_work_product(&self, v: &WorkProductId, data: WorkProduct) { debug!("insert_work_product({:?}, {:?})", v, data); - self.data.work_products.borrow_mut() - .insert(v.clone(), data); + self.data + .as_ref() + .unwrap() + .work_products + .borrow_mut() + .insert(v.clone(), data); } /// Check whether a previous work product exists for `v` and, if /// so, return the path that leads to it. Used to skip doing work. - pub fn previous_work_product(&self, v: &Arc) -> Option { - self.data.previous_work_products.borrow() - .get(v) - .cloned() + pub fn previous_work_product(&self, v: &WorkProductId) -> Option { + self.data + .as_ref() + .and_then(|data| { + data.previous_work_products.borrow().get(v).cloned() + }) } /// Access the map of work-products created during this run. Only /// used during saving of the dep-graph. - pub fn work_products(&self) -> Ref, WorkProduct>> { - self.data.work_products.borrow() + pub fn work_products(&self) -> Ref> { + self.data.as_ref().unwrap().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() + pub fn previous_work_products(&self) -> Ref> { + self.data.as_ref().unwrap().previous_work_products.borrow() + } + + #[inline(always)] + pub fn register_dep_node_debug_str(&self, + dep_node: DepNode, + debug_str_gen: F) + where F: FnOnce() -> String + { + let mut dep_node_debug = self.data.as_ref().unwrap().dep_node_debug.borrow_mut(); + + dep_node_debug.entry(dep_node) + .or_insert_with(debug_str_gen); + } + + pub(super) fn dep_node_debug_str(&self, dep_node: DepNode) -> Option { + self.data.as_ref().and_then(|t| t.dep_node_debug.borrow().get(&dep_node).cloned()) } } @@ -189,6 +264,7 @@ impl DepGraph { /// previous hash. If it matches up, we can reuse the object file. #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub struct WorkProduct { + pub cgu_name: String, /// Extra hash used to decide if work-product is still suitable; /// note that this is *not* a hash of the work-product itself. /// See documentation on `WorkProduct` type for an example. diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs index 822b61df7a..ac0c88ced9 100644 --- a/src/librustc/dep_graph/mod.rs +++ b/src/librustc/dep_graph/mod.rs @@ -16,16 +16,16 @@ mod graph; mod query; mod raii; mod safe; -mod shadow; -mod thread; pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig}; pub use self::dep_node::DepNode; pub use self::dep_node::WorkProductId; -pub use self::dep_node::GlobalMetaDataKind; pub use self::graph::DepGraph; pub use self::graph::WorkProduct; +pub use self::edges::DepNodeIndex; pub use self::query::DepGraphQuery; pub use self::safe::AssertDepGraphSafe; pub use self::safe::DepGraphSafe; pub use self::raii::DepTask; + +pub use self::dep_node::{DepKind, DepConstructor}; diff --git a/src/librustc/dep_graph/query.rs b/src/librustc/dep_graph/query.rs index 4c791f9655..283da1050a 100644 --- a/src/librustc/dep_graph/query.rs +++ b/src/librustc/dep_graph/query.rs @@ -10,20 +10,18 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::graph::{Direction, INCOMING, Graph, NodeIndex, OUTGOING}; -use std::fmt::Debug; -use std::hash::Hash; use super::DepNode; -pub struct DepGraphQuery { - pub graph: Graph, ()>, - pub indices: FxHashMap, NodeIndex>, +pub struct DepGraphQuery { + pub graph: Graph, + pub indices: FxHashMap, } -impl DepGraphQuery { - pub fn new(nodes: &[DepNode], - edges: &[(DepNode, DepNode)]) - -> DepGraphQuery { +impl DepGraphQuery { + pub fn new(nodes: &[DepNode], + edges: &[(DepNode, DepNode)]) + -> DepGraphQuery { let mut graph = Graph::new(); let mut indices = FxHashMap(); for node in nodes { @@ -38,23 +36,23 @@ impl DepGraphQuery { } DepGraphQuery { - graph: graph, - indices: indices + graph, + indices, } } - pub fn contains_node(&self, node: &DepNode) -> bool { + pub fn contains_node(&self, node: &DepNode) -> bool { self.indices.contains_key(&node) } - pub fn nodes(&self) -> Vec<&DepNode> { + pub fn nodes(&self) -> Vec<&DepNode> { self.graph.all_nodes() .iter() .map(|n| &n.data) .collect() } - pub fn edges(&self) -> Vec<(&DepNode,&DepNode)> { + pub fn edges(&self) -> Vec<(&DepNode,&DepNode)> { self.graph.all_edges() .iter() .map(|edge| (edge.source(), edge.target())) @@ -63,7 +61,7 @@ impl DepGraphQuery { .collect() } - fn reachable_nodes(&self, node: &DepNode, direction: Direction) -> Vec<&DepNode> { + fn reachable_nodes(&self, node: &DepNode, direction: Direction) -> Vec<&DepNode> { if let Some(&index) = self.indices.get(node) { self.graph.depth_traverse(index, direction) .map(|s| self.graph.node_data(s)) @@ -75,17 +73,17 @@ impl DepGraphQuery { /// All nodes reachable from `node`. In other words, things that /// will have to be recomputed if `node` changes. - pub fn transitive_successors(&self, node: &DepNode) -> Vec<&DepNode> { + pub fn transitive_successors(&self, node: &DepNode) -> Vec<&DepNode> { self.reachable_nodes(node, OUTGOING) } /// All nodes that can reach `node`. - pub fn transitive_predecessors(&self, node: &DepNode) -> Vec<&DepNode> { + pub fn transitive_predecessors(&self, node: &DepNode) -> Vec<&DepNode> { self.reachable_nodes(node, INCOMING) } /// Just the outgoing edges from `node`. - pub fn immediate_successors(&self, node: &DepNode) -> Vec<&DepNode> { + pub fn immediate_successors(&self, node: &DepNode) -> Vec<&DepNode> { if let Some(&index) = self.indices.get(&node) { self.graph.successor_nodes(index) .map(|s| self.graph.node_data(s)) diff --git a/src/librustc/dep_graph/raii.rs b/src/librustc/dep_graph/raii.rs index e39797599a..ce261ca68e 100644 --- a/src/librustc/dep_graph/raii.rs +++ b/src/librustc/dep_graph/raii.rs @@ -8,55 +8,50 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use hir::def_id::DefId; use super::DepNode; -use super::thread::{DepGraphThreadData, DepMessage}; +use super::edges::DepGraphEdges; + +use std::cell::RefCell; pub struct DepTask<'graph> { - data: &'graph DepGraphThreadData, - key: Option>, + graph: &'graph RefCell, + key: DepNode, } impl<'graph> DepTask<'graph> { - pub fn new(data: &'graph DepGraphThreadData, key: DepNode) - -> Option> { - if data.is_enqueue_enabled() { - data.enqueue(DepMessage::PushTask(key.clone())); - Some(DepTask { data: data, key: Some(key) }) - } else { - None + pub fn new(graph: &'graph RefCell, + key: DepNode) + -> DepTask<'graph> { + graph.borrow_mut().push_task(key); + DepTask { + graph, + key, } } } impl<'graph> Drop for DepTask<'graph> { fn drop(&mut self) { - if self.data.is_enqueue_enabled() { - self.data.enqueue(DepMessage::PopTask(self.key.take().unwrap())); - } + self.graph.borrow_mut().pop_task(self.key); } } pub struct IgnoreTask<'graph> { - data: &'graph DepGraphThreadData + graph: &'graph RefCell, } impl<'graph> IgnoreTask<'graph> { - pub fn new(data: &'graph DepGraphThreadData) -> Option> { - if data.is_enqueue_enabled() { - data.enqueue(DepMessage::PushIgnore); - Some(IgnoreTask { data: data }) - } else { - None + pub fn new(graph: &'graph RefCell) -> IgnoreTask<'graph> { + graph.borrow_mut().push_ignore(); + IgnoreTask { + graph } } } impl<'graph> Drop for IgnoreTask<'graph> { fn drop(&mut self) { - if self.data.is_enqueue_enabled() { - self.data.enqueue(DepMessage::PopIgnore); - } + self.graph.borrow_mut().pop_ignore(); } } diff --git a/src/librustc/dep_graph/shadow.rs b/src/librustc/dep_graph/shadow.rs deleted file mode 100644 index bedb6ff277..0000000000 --- a/src/librustc/dep_graph/shadow.rs +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! The "Shadow Graph" is maintained on the main thread and which -//! tracks each message relating to the dep-graph and applies some -//! sanity checks as they go by. If an error results, it means you get -//! a nice stack-trace telling you precisely what caused the error. -//! -//! NOTE: This is a debugging facility which can potentially have non-trivial -//! runtime impact. Therefore, it is largely compiled out if -//! debug-assertions are not enabled. -//! -//! The basic sanity check, enabled if you have debug assertions -//! enabled, is that there is always a task (or ignore) on the stack -//! when you do read/write, and that the tasks are pushed/popped -//! according to a proper stack discipline. -//! -//! Optionally, if you specify RUST_FORBID_DEP_GRAPH_EDGE, you can -//! specify an edge filter to be applied to each edge as it is -//! created. See `./README.md` for details. - -use hir::def_id::DefId; -use std::cell::RefCell; -use std::env; - -use super::DepNode; -use super::thread::DepMessage; -use super::debug::EdgeFilter; - -pub struct ShadowGraph { - // if you push None onto the stack, that corresponds to an Ignore - stack: RefCell>>>, - forbidden_edge: Option, -} - -const ENABLED: bool = cfg!(debug_assertions); - -impl ShadowGraph { - pub fn new() -> Self { - let forbidden_edge = if !ENABLED { - None - } else { - match env::var("RUST_FORBID_DEP_GRAPH_EDGE") { - Ok(s) => { - match EdgeFilter::new(&s) { - Ok(f) => Some(f), - Err(err) => bug!("RUST_FORBID_DEP_GRAPH_EDGE invalid: {}", err), - } - } - Err(_) => None, - } - }; - - ShadowGraph { - stack: RefCell::new(vec![]), - forbidden_edge: forbidden_edge, - } - } - - #[inline] - pub fn enabled(&self) -> bool { - ENABLED - } - - pub fn enqueue(&self, message: &DepMessage) { - if ENABLED { - if self.stack.try_borrow().is_err() { - // When we apply edge filters, that invokes the Debug trait on - // DefIds, which in turn reads from various bits of state and - // creates reads! Ignore those recursive reads. - return; - } - - let mut stack = self.stack.borrow_mut(); - match *message { - // It is ok to READ shared state outside of a - // task. That can't do any harm (at least, the only - // way it can do harm is by leaking that data into a - // query or task, which would be a problem - // anyway). What would be bad is WRITING to that - // state. - DepMessage::Read(_) => { } - DepMessage::Write(ref n) => self.check_edge(top(&stack), Some(Some(n))), - DepMessage::PushTask(ref n) => stack.push(Some(n.clone())), - DepMessage::PushIgnore => stack.push(None), - DepMessage::PopTask(ref n) => { - match stack.pop() { - Some(Some(m)) => { - if *n != m { - bug!("stack mismatch: found {:?} expected {:?}", m, n) - } - } - Some(None) => bug!("stack mismatch: found Ignore expected {:?}", n), - None => bug!("stack mismatch: found empty stack, expected {:?}", n), - } - } - DepMessage::PopIgnore => { - match stack.pop() { - Some(Some(m)) => bug!("stack mismatch: found {:?} expected ignore", m), - Some(None) => (), - None => bug!("stack mismatch: found empty stack, expected ignore"), - } - } - DepMessage::Query => (), - } - } - } - - fn check_edge(&self, - source: Option>>, - target: Option>>) { - assert!(ENABLED); - match (source, target) { - // cannot happen, one side is always Some(Some(_)) - (None, None) => unreachable!(), - - // nothing on top of the stack - (None, Some(n)) | (Some(n), None) => bug!("write of {:?} but no current task", n), - - // this corresponds to an Ignore being top of the stack - (Some(None), _) | (_, Some(None)) => (), - - // a task is on top of the stack - (Some(Some(source)), Some(Some(target))) => { - if let Some(ref forbidden_edge) = self.forbidden_edge { - if forbidden_edge.test(source, target) { - bug!("forbidden edge {:?} -> {:?} created", source, target) - } - } - } - } - } -} - -// Do a little juggling: we get back a reference to an option at the -// top of the stack, convert it to an optional reference. -fn top<'s>(stack: &'s Vec>>) -> Option>> { - stack.last() - .map(|n: &'s Option>| -> Option<&'s DepNode> { - // (*) - // (*) type annotation just there to clarify what would - // otherwise be some *really* obscure code - n.as_ref() - }) -} diff --git a/src/librustc/dep_graph/thread.rs b/src/librustc/dep_graph/thread.rs deleted file mode 100644 index d3a940c811..0000000000 --- a/src/librustc/dep_graph/thread.rs +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Manages the communication between the compiler's main thread and -//! the thread that constructs the dependency graph. The basic idea is -//! to use double buffering to lower the cost of producing a message. -//! In the compiler thread, we accumulate messages in a vector until -//! the vector is full, or until we want to query the graph, and then -//! we send that vector over to the depgraph thread. At the same time, -//! we receive an empty vector from the depgraph thread that we can use -//! to accumulate more messages. This way we only ever have two vectors -//! allocated (and both have a fairly large capacity). - -use hir::def_id::DefId; -use rustc_data_structures::veccell::VecCell; -use std::sync::mpsc::{self, Sender, Receiver}; -use std::thread; - -use super::DepGraphQuery; -use super::DepNode; -use super::edges::DepGraphEdges; -use super::shadow::ShadowGraph; - -#[derive(Debug)] -pub enum DepMessage { - Read(DepNode), - Write(DepNode), - PushTask(DepNode), - PopTask(DepNode), - PushIgnore, - PopIgnore, - Query, -} - -pub struct DepGraphThreadData { - enabled: bool, - - // The "shadow graph" is a debugging aid. We give it each message - // in real time as it arrives and it checks for various errors - // (for example, a read/write when there is no current task; it - // can also apply user-defined filters; see `shadow` module for - // details). This only occurs if debug-assertions are enabled. - // - // Note that in some cases the same errors will occur when the - // data is processed off the main thread, but that's annoying - // because it lacks precision about the source of the error. - shadow_graph: ShadowGraph, - - // current buffer, where we accumulate messages - messages: VecCell, - - // where to receive new buffer when full - swap_in: Receiver>, - - // where to send buffer when full - swap_out: Sender>, - - // where to receive query results - query_in: Receiver>, -} - -const INITIAL_CAPACITY: usize = 2048; - -impl DepGraphThreadData { - pub fn new(enabled: bool) -> DepGraphThreadData { - let (tx1, rx1) = mpsc::channel(); - let (tx2, rx2) = mpsc::channel(); - let (txq, rxq) = mpsc::channel(); - - if enabled { - thread::spawn(move || main(rx1, tx2, txq)); - } - - DepGraphThreadData { - enabled: enabled, - shadow_graph: ShadowGraph::new(), - messages: VecCell::with_capacity(INITIAL_CAPACITY), - swap_in: rx2, - swap_out: tx1, - query_in: rxq, - } - } - - /// True if we are actually building the full dep-graph. - #[inline] - pub fn is_fully_enabled(&self) -> bool { - self.enabled - } - - /// True if (a) we are actually building the full dep-graph, or (b) we are - /// only enqueuing messages in order to sanity-check them (which happens - /// when debug assertions are enabled). - #[inline] - pub fn is_enqueue_enabled(&self) -> bool { - self.is_fully_enabled() || self.shadow_graph.enabled() - } - - /// Sends the current batch of messages to the thread. Installs a - /// new vector of messages. - fn swap(&self) { - assert!(self.is_fully_enabled(), "should never swap if not fully enabled"); - - // should be a buffer waiting for us (though of course we may - // have to wait for depgraph thread to finish processing the - // old messages) - let new_messages = self.swap_in.recv().unwrap(); - assert!(new_messages.is_empty()); - - // swap in the empty buffer and extract the full one - let old_messages = self.messages.swap(new_messages); - - // send full buffer to depgraph thread to be processed - self.swap_out.send(old_messages).unwrap(); - } - - pub fn query(&self) -> DepGraphQuery { - assert!(self.is_fully_enabled(), "should never query if not fully enabled"); - self.enqueue(DepMessage::Query); - self.swap(); - self.query_in.recv().unwrap() - } - - /// Enqueue a message to be sent when things are next swapped. (If - /// the buffer is full, this may swap.) - #[inline] - pub fn enqueue(&self, message: DepMessage) { - assert!(self.is_enqueue_enabled(), "should never enqueue if not enqueue-enabled"); - self.shadow_graph.enqueue(&message); - if self.is_fully_enabled() { - self.enqueue_enabled(message); - } - } - - // Outline this fn since I expect it may want to be inlined - // separately. - fn enqueue_enabled(&self, message: DepMessage) { - let len = self.messages.push(message); - if len == INITIAL_CAPACITY { - self.swap(); - } - } -} - -/// Definition of the depgraph thread. -pub fn main(swap_in: Receiver>, - swap_out: Sender>, - query_out: Sender>) { - let mut edges = DepGraphEdges::new(); - - // the compiler thread always expects a fresh buffer to be - // waiting, so queue one up - swap_out.send(Vec::with_capacity(INITIAL_CAPACITY)).unwrap(); - - // process the buffers from compiler thread as we receive them - for mut messages in swap_in { - for msg in messages.drain(..) { - match msg { - DepMessage::Read(node) => edges.read(node), - DepMessage::Write(node) => edges.write(node), - DepMessage::PushTask(node) => edges.push_task(node), - DepMessage::PopTask(node) => edges.pop_task(node), - DepMessage::PushIgnore => edges.push_ignore(), - DepMessage::PopIgnore => edges.pop_ignore(), - DepMessage::Query => query_out.send(edges.query()).unwrap(), - } - } - if let Err(_) = swap_out.send(messages) { - // the receiver must have been dropped already - break; - } - } -} diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 2beb40d6b2..cef1be5cee 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -198,7 +198,12 @@ impl Trait for u8 { Now, if we have the following code: -```ignore +```compile_fail,E0038 +# trait Trait { fn foo(&self, on: T); } +# impl Trait for String { fn foo(&self, on: T) {} } +# impl Trait for u8 { fn foo(&self, on: T) {} } +# impl Trait for bool { fn foo(&self, on: T) {} } +# // etc. fn call_foo(thing: Box) { thing.foo(true); // this could be any one of the 8 types above thing.foo(1); @@ -405,7 +410,7 @@ 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 +[book-le]: https://doc.rust-lang.org/nightly/book/first-edition/lifetimes.html#lifetime-elision [iss15872]: https://github.com/rust-lang/rust/issues/15872 "##, @@ -501,7 +506,7 @@ fn main() { } ``` -See also https://doc.rust-lang.org/book/unsafe.html +See also https://doc.rust-lang.org/book/first-edition/unsafe.html "##, // This shouldn't really ever trigger since the repeated value error comes first @@ -565,8 +570,9 @@ fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } // ok! ``` "##, -// isn't thrown anymore E0139: r##" +#### Note: this error code is no longer emitted by the compiler. + There are various restrictions on transmuting between types in Rust; for example types being transmuted must have the same size. To apply all these restrictions, the compiler must know the exact types that may be transmuted. When type @@ -602,22 +608,24 @@ If it's possible, hand-monomorphize the code by writing the function for each possible type substitution. It's possible to use traits to do this cleanly, for example: -```ignore +``` +use std::mem::transmute; + struct Foo(Vec); -trait MyTransmutableType { - fn transmute(Vec) -> Foo; +trait MyTransmutableType: Sized { + fn transmute(_: Vec) -> Foo; } impl MyTransmutableType for u8 { - fn transmute(x: Foo) -> Vec { - transmute(x) + fn transmute(x: Vec) -> Foo { + unsafe { transmute(x) } } } impl MyTransmutableType for String { - fn transmute(x: Foo) -> Vec { - transmute(x) + fn transmute(x: Vec) -> Foo { + unsafe { transmute(x) } } } @@ -635,8 +643,14 @@ is a size mismatch in one of the impls. It is also possible to manually transmute: -```ignore -ptr::read(&v as *const _ as *const SomeType) // `v` transmuted to `SomeType` +``` +# use std::ptr; +# let v = Some("value"); +# type SomeType = &'static [u8]; +unsafe { + ptr::read(&v as *const _ as *const SomeType) // `v` transmuted to `SomeType` +} +# ; ``` Note that this does not move `v` (unlike `transmute`), and may need a @@ -662,11 +676,11 @@ them yourself. You can build a free-standing crate by adding `#![no_std]` to the crate attributes: -```ignore +```ignore (only-for-syntax-highlight) #![no_std] ``` -See also https://doc.rust-lang.org/book/no-stdlib.html +See also https://doc.rust-lang.org/book/first-edition/no-stdlib.html "##, E0261: r##" @@ -764,7 +778,7 @@ foo(3_i8); Here is that same example again, with some explanatory comments: -```ignore +```compile_fail,E0271 trait Trait { type AssociatedType; } fn foo(t: T) where T: Trait { @@ -784,7 +798,7 @@ fn foo(t: T) where T: Trait { } impl Trait for i8 { type AssociatedType = &'static str; } -~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // | | // `i8` does have | // implementation | @@ -816,7 +830,7 @@ The above fails because of an analogous type mismatch, though may be harder to see. Again, here are some explanatory comments for the same example: -```ignore +```compile_fail { let vs = vec![1, 2, 3, 4]; @@ -1416,6 +1430,8 @@ trait SecondTrait : FirstTrait { "##, E0398: r##" +#### Note: this error code is no longer emitted by the compiler. + In Rust 1.3, the default object lifetime bounds are expected to change, as described in [RFC 1156]. You are getting a warning because the compiler thinks it is possible that this change will cause a compilation error in your @@ -1433,14 +1449,16 @@ time, this means that you will want to change the signature of a function that you are calling. For example, if the error is reported on a call like `foo(x)`, and `foo` is defined as follows: -```ignore -fn foo(arg: &Box) { ... } +``` +# trait SomeTrait {} +fn foo(arg: &Box) { /* ... */ } ``` You might change it to: -```ignore -fn foo<'a>(arg: &Box) { ... } +``` +# trait SomeTrait {} +fn foo<'a>(arg: &'a Box) { /* ... */ } ``` This explicitly states that you expect the trait object `SomeTrait` to contain @@ -1631,7 +1649,7 @@ fn takes_u8(_: u8) {} fn main() { unsafe { takes_u8(::std::mem::transmute(0u16)); } - // error: transmute called with differently sized types + // error: transmute called with types of different sizes } ``` @@ -1779,7 +1797,7 @@ fn main() { ``` To understand better how closures work in Rust, read: -https://doc.rust-lang.org/book/closures.html +https://doc.rust-lang.org/book/first-edition/closures.html "##, E0580: r##" @@ -1809,24 +1827,29 @@ specified exit code, use `std::process::exit`. E0591: r##" Per [RFC 401][rfc401], if you have a function declaration `foo`: -```rust,ignore +``` // For the purposes of this explanation, all of these // different kinds of `fn` declarations are equivalent: -fn foo(x: i32) { ... } -extern "C" fn foo(x: i32); -impl i32 { fn foo(x: self) { ... } } +struct S; +fn foo(x: S) { /* ... */ } +# #[cfg(for_demonstration_only)] +extern "C" { fn foo(x: S); } +# #[cfg(for_demonstration_only)] +impl S { fn foo(self) { /* ... */ } } ``` -the type of `foo` is **not** `fn(i32)`, as one might expect. +the type of `foo` is **not** `fn(S)`, as one might expect. Rather, it is a unique, zero-sized marker type written here as `typeof(foo)`. -However, `typeof(foo)` can be _coerced_ to a function pointer `fn(i32)`, +However, `typeof(foo)` can be _coerced_ to a function pointer `fn(S)`, so you rarely notice this: -```rust,ignore -let x: fn(i32) = foo; // OK, coerces +``` +# struct S; +# fn foo(_: S) {} +let x: fn(S) = foo; // OK, coerces ``` -The reason that this matter is that the type `fn(i32)` is not specific to +The reason that this matter is that the type `fn(S)` is not specific to any particular function: it's a function _pointer_. So calling `x()` results in a virtual call, whereas `foo()` is statically dispatched, because the type of `foo` tells us precisely what function is being called. @@ -1837,14 +1860,17 @@ when using **transmute** to convert a fn item into a fn pointer. This is sometimes done as part of an FFI: -```rust,ignore +```compile_fail,E0591 extern "C" fn foo(userdata: Box) { - ... + /* ... */ } +# fn callback(_: extern "C" fn(*mut i32)) {} +# use std::mem::transmute; +# unsafe { let f: extern "C" fn(*mut i32) = transmute(foo); callback(f); - +# } ``` Here, transmute is being used to convert the types of the fn arguments. @@ -1856,8 +1882,15 @@ This pattern should be rewritten. There are a few possible ways to do this: - change the original fn declaration to match the expected signature, and do the cast in the fn body (the prefered option) - cast the fn item fo a fn pointer before calling transmute, as shown here: - - `let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_))` - - `let f: extern "C" fn(*mut i32) = transmute(foo as usize) /* works too */` + + ``` + # extern "C" fn foo(_: Box) {} + # use std::mem::transmute; + # unsafe { + let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_)); + let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too + # } + ``` The same applies to transmutes to `*mut fn()`, which were observedin practice. Note though that use of this type is generally incorrect. @@ -1900,6 +1933,56 @@ If you don't know the basics of Rust, you can go look to the Rust Book to get started: https://doc.rust-lang.org/book/ "##, +E0602: r##" +An unknown lint was used on the command line. + +Erroneous example: + +```sh +rustc -D bogus omse_file.rs +``` + +Maybe you just misspelled the lint name or the lint doesn't exist anymore. +Either way, try to update/remove it in order to fix the error. +"##, + +E0621: r##" +This error code indicates a mismatch between the lifetimes appearing in the +function signature (i.e., the parameter types and the return type) and the +data-flow found in the function body. + +Erroneous code example: + +```compile_fail,E0621 +fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { // error: explicit lifetime + // required in the type of + // `y` + if x > y { x } else { y } +} +``` + +In the code above, the function is returning data borrowed from either `x` or +`y`, but the `'a` annotation indicates that it is returning data only from `x`. +To fix the error, the signature and the body must be made to match. Typically, +this is done by updating the function signature. So, in this case, we change +the type of `y` to `&'a i32`, like so: + +``` +fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { + if x > y { x } else { y } +} +``` + +Now the signature indicates that the function data borrowed from either `x` or +`y`. Alternatively, you could change the body to not return data from `y`: + +``` +fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { + x +} +``` +"##, + } diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index f553c03d09..3034242b59 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -8,6 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! This module implements some validity checks for attributes. +//! In particular it verifies that `#[inline]` and `#[repr]` attributes are +//! attached to items that actually support them and if there are +//! conflicts between multiple such attributes attached to the same +//! item. + use session::Session; use syntax::ast; @@ -40,6 +46,18 @@ struct CheckAttrVisitor<'a> { } impl<'a> CheckAttrVisitor<'a> { + /// Check any attribute. + fn check_attribute(&self, attr: &ast::Attribute, target: Target) { + if let Some(name) = attr.name() { + match &*name.as_str() { + "inline" => self.check_inline(attr, target), + "repr" => self.check_repr(attr, target), + _ => (), + } + } + } + + /// Check if an `#[inline]` is applied to a function. fn check_inline(&self, attr: &ast::Attribute, target: Target) { if target != Target::Fn { struct_span_err!(self.sess, attr.span, E0518, "attribute should be applied to function") @@ -48,6 +66,7 @@ impl<'a> CheckAttrVisitor<'a> { } } + /// Check if an `#[repr]` attr is valid. fn check_repr(&self, attr: &ast::Attribute, target: Target) { let words = match attr.meta_item_list() { Some(words) => words, @@ -135,16 +154,6 @@ impl<'a> CheckAttrVisitor<'a> { "conflicting packed and align representation hints").emit(); } } - - fn check_attribute(&self, attr: &ast::Attribute, target: Target) { - if let Some(name) = attr.name() { - match &*name.as_str() { - "inline" => self.check_inline(attr, target), - "repr" => self.check_repr(attr, target), - _ => (), - } - } - } } impl<'a> Visitor<'a> for CheckAttrVisitor<'a> { diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index feded417ce..c500d770ce 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -17,11 +17,11 @@ use hir; #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum CtorKind { - // Constructor function automatically created by a tuple struct/variant. + /// Constructor function automatically created by a tuple struct/variant. Fn, - // Constructor constant automatically created by a unit struct/variant. + /// Constructor constant automatically created by a unit struct/variant. Const, - // Unusable name in value namespace created by a struct variant. + /// Unusable name in value namespace created by a struct variant. Fictive, } @@ -109,17 +109,21 @@ impl PathResolution { } } -// Definition mapping +/// Definition mapping pub type DefMap = NodeMap; -// This is the replacement export map. It maps a module to all of the exports -// within. + +/// This is the replacement export map. It maps a module to all of the exports +/// within. pub type ExportMap = NodeMap>; #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)] pub struct Export { - pub ident: ast::Ident, // The name of the target. - pub def: Def, // The definition of the target. - pub span: Span, // The span of the target definition. + /// The name of the target. + pub ident: ast::Ident, + /// The definition of the target. + pub def: Def, + /// The span of the target definition. + pub span: Span, } impl CtorKind { @@ -160,6 +164,7 @@ impl Def { } } + /// A human readable kind name pub fn kind_name(&self) -> &'static str { match *self { Def::Fn(..) => "function", diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index 47604b961a..95a27f0659 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -58,6 +58,8 @@ impl CrateNum { pub fn as_u32(&self) -> u32 { self.0 } + + pub fn as_def_id(&self) -> DefId { DefId { krate: *self, index: CRATE_DEF_INDEX } } } impl fmt::Display for CrateNum { @@ -187,6 +189,7 @@ impl fmt::Debug for DefId { impl DefId { + /// Make a local `DefId` with the given index. pub fn local(index: DefIndex) -> DefId { DefId { krate: LOCAL_CRATE, index: index } } diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 836d9775a3..57198d8ca0 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -944,10 +944,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { walk_list!(visitor, visit_expr, arguments); visitor.visit_expr(callee_expression) } - ExprMethodCall(ref name, ref types, ref arguments) => { - visitor.visit_name(name.span, name.node); + ExprMethodCall(ref segment, _, ref arguments) => { + visitor.visit_path_segment(expression.span, segment); walk_list!(visitor, visit_expr, arguments); - walk_list!(visitor, visit_ty, types); } ExprBinary(_, ref left_expression, ref right_expression) => { visitor.visit_expr(left_expression); diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index c3f05928f6..67dc069da4 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -8,37 +8,37 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Lowers the AST to the HIR. -// -// Since the AST and HIR are fairly similar, this is mostly a simple procedure, -// much like a fold. Where lowering involves a bit more work things get more -// interesting and there are some invariants you should know about. These mostly -// concern spans and ids. -// -// Spans are assigned to AST nodes during parsing and then are modified during -// expansion to indicate the origin of a node and the process it went through -// being expanded. Ids are assigned to AST nodes just before lowering. -// -// For the simpler lowering steps, ids and spans should be preserved. Unlike -// expansion we do not preserve the process of lowering in the spans, so spans -// should not be modified here. When creating a new node (as opposed to -// 'folding' an existing one), then you create a new id using `next_id()`. -// -// You must ensure that ids are unique. That means that you should only use the -// id from an AST node in a single HIR node (you can assume that AST node ids -// are unique). Every new node must have a unique id. Avoid cloning HIR nodes. -// If you do, you must then set the new node's id to a fresh one. -// -// Spans are used for error messages and for tools to map semantics back to -// source code. It is therefore not as important with spans as ids to be strict -// about use (you can't break the compiler by screwing up a span). Obviously, a -// HIR node can only have a single span. But multiple nodes can have the same -// span and spans don't need to be kept in order, etc. Where code is preserved -// by lowering, it should have the same span as in the AST. Where HIR nodes are -// new it is probably best to give a span for the whole AST node being lowered. -// All nodes should have real spans, don't use dummy spans. Tools are likely to -// get confused if the spans from leaf AST nodes occur in multiple places -// in the HIR, especially for multiple identifiers. +//! Lowers the AST to the HIR. +//! +//! Since the AST and HIR are fairly similar, this is mostly a simple procedure, +//! much like a fold. Where lowering involves a bit more work things get more +//! interesting and there are some invariants you should know about. These mostly +//! concern spans and ids. +//! +//! Spans are assigned to AST nodes during parsing and then are modified during +//! expansion to indicate the origin of a node and the process it went through +//! being expanded. Ids are assigned to AST nodes just before lowering. +//! +//! For the simpler lowering steps, ids and spans should be preserved. Unlike +//! expansion we do not preserve the process of lowering in the spans, so spans +//! should not be modified here. When creating a new node (as opposed to +//! 'folding' an existing one), then you create a new id using `next_id()`. +//! +//! You must ensure that ids are unique. That means that you should only use the +//! id from an AST node in a single HIR node (you can assume that AST node ids +//! are unique). Every new node must have a unique id. Avoid cloning HIR nodes. +//! If you do, you must then set the new node's id to a fresh one. +//! +//! Spans are used for error messages and for tools to map semantics back to +//! source code. It is therefore not as important with spans as ids to be strict +//! about use (you can't break the compiler by screwing up a span). Obviously, a +//! HIR node can only have a single span. But multiple nodes can have the same +//! span and spans don't need to be kept in order, etc. Where code is preserved +//! by lowering, it should have the same span as in the AST. Where HIR nodes are +//! new it is probably best to give a span for the whole AST node being lowered. +//! All nodes should have real spans, don't use dummy spans. Tools are likely to +//! get confused if the spans from leaf AST nodes occur in multiple places +//! in the HIR, especially for multiple identifiers. use hir; use hir::map::{Definitions, DefKey, REGULAR_SPACE}; @@ -70,8 +70,10 @@ const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF; pub struct LoweringContext<'a> { crate_root: Option<&'static str>, + // Use to assign ids to hir nodes that do not directly correspond to an ast node sess: &'a Session, + // As we walk the AST we must keep track of the current 'parent' def id (in // 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. @@ -102,14 +104,14 @@ pub struct LoweringContext<'a> { } pub trait Resolver { - // Resolve a 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 + /// Obtain the resolution for a node id fn get_resolution(&mut self, id: NodeId) -> Option; - // We must keep the set of definitions up to date as we add nodes that weren't in the AST. - // This should only return `None` during testing. + /// We must keep the set of definitions up to date as we add nodes that weren't in the AST. + /// This should only return `None` during testing. fn definitions(&mut self) -> &mut Definitions; } @@ -124,9 +126,9 @@ pub fn lower_crate(sess: &Session, LoweringContext { crate_root: std_inject::injected_crate_name(krate), - sess: sess, + sess, parent_def: None, - resolver: resolver, + resolver, name_map: FxHashMap(), items: BTreeMap::new(), trait_items: BTreeMap::new(), @@ -249,15 +251,15 @@ impl<'a> LoweringContext<'a> { .init_node_id_to_hir_id_mapping(self.node_id_to_hir_id); hir::Crate { - module: module, - attrs: attrs, + module, + attrs, span: c.span, exported_macros: hir::HirVec::from(self.exported_macros), items: self.items, trait_items: self.trait_items, impl_items: self.impl_items, bodies: self.bodies, - body_ids: body_ids, + body_ids, trait_impls: self.trait_impls, trait_default_impl: self.trait_default_impl, } @@ -366,7 +368,7 @@ impl<'a> LoweringContext<'a> { arguments: decl.map_or(hir_vec![], |decl| { decl.inputs.iter().map(|x| self.lower_arg(x)).collect() }), - value: value + value, }; let id = body.id(); self.bodies.insert(id, body); @@ -807,7 +809,7 @@ impl<'a> LoweringContext<'a> { self.lower_path_segment(p.span, segment, param_mode, 0) }).chain(name.map(|name| { hir::PathSegment { - name: name, + name, parameters: hir::PathParameters::none() } })).collect(), @@ -855,7 +857,7 @@ impl<'a> LoweringContext<'a> { hir::PathSegment { name: self.lower_ident(segment.identifier), - parameters: parameters, + parameters, } } @@ -879,7 +881,7 @@ impl<'a> LoweringContext<'a> { hir::ParenthesizedParameterData { inputs: inputs.iter().map(|ty| self.lower_ty(ty)).collect(), output: output.as_ref().map(|ty| self.lower_ty(ty)), - span: span, + span, } } @@ -968,8 +970,8 @@ impl<'a> LoweringContext<'a> { hir::TyParam { id: self.lower_node_id(tp.id), - name: name, - bounds: bounds, + name, + bounds, default: tp.default.as_ref().map(|x| self.lower_ty(x)), span: tp.span, pure_wrt_drop: tp.attrs.iter().any(|attr| attr.check_name("may_dangle")), @@ -1079,14 +1081,14 @@ impl<'a> LoweringContext<'a> { TraitTyParamBound(_, TraitBoundModifier::Maybe) => None, _ => Some(self.lower_ty_param_bound(bound)) }).collect(), - span: span, + span, }) } WherePredicate::RegionPredicate(WhereRegionPredicate{ ref lifetime, ref bounds, span}) => { hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { - span: span, + span, lifetime: self.lower_lifetime(lifetime), bounds: bounds.iter().map(|bound| self.lower_lifetime(bound)).collect(), }) @@ -1099,7 +1101,7 @@ impl<'a> LoweringContext<'a> { id: self.lower_node_id(id), lhs_ty: self.lower_ty(lhs_ty), rhs_ty: self.lower_ty(rhs_ty), - span: span, + span, }) } } @@ -1131,7 +1133,7 @@ impl<'a> LoweringContext<'a> { qpath => bug!("lower_trait_ref: unexpected QPath `{:?}`", qpath) }; hir::TraitRef { - path: path, + path, ref_id: self.lower_node_id(p.ref_id), } } @@ -1199,10 +1201,10 @@ impl<'a> LoweringContext<'a> { P(hir::Block { id: self.lower_node_id(b.id), stmts: stmts.into(), - expr: expr, + expr, rules: self.lower_block_check_mode(&b.rules), span: b.span, - targeted_by_break: targeted_by_break, + targeted_by_break, }) } @@ -1257,8 +1259,8 @@ impl<'a> LoweringContext<'a> { name: import.rename.unwrap_or(ident).name, attrs: attrs.clone(), node: hir::ItemUse(P(path), hir::UseKind::Single), - vis: vis, - span: span, + vis, + span, }); }); } @@ -1439,7 +1441,7 @@ impl<'a> LoweringContext<'a> { name: self.lower_ident(i.ident), span: i.span, defaultness: self.lower_defaultness(Defaultness::Default, has_default), - kind: kind, + kind, } } @@ -1521,9 +1523,9 @@ impl<'a> LoweringContext<'a> { if let ItemKind::MacroDef(ref def) = i.node { if !def.legacy || i.attrs.iter().any(|attr| attr.path == "macro_export") { self.exported_macros.push(hir::MacroDef { - name: name, - vis: vis, - attrs: attrs, + name, + vis, + attrs, id: i.id, span: i.span, body: def.stream(), @@ -1539,10 +1541,10 @@ impl<'a> LoweringContext<'a> { Some(hir::Item { id: self.lower_node_id(i.id), - name: name, - attrs: attrs, - node: node, - vis: vis, + name, + attrs, + node, + vis, span: i.span, }) } @@ -1648,7 +1650,7 @@ impl<'a> LoweringContext<'a> { Some(def) => { hir::PatKind::Path(hir::QPath::Resolved(None, P(hir::Path { span: pth1.span, - def: def, + def, segments: hir_vec![ hir::PathSegment::from_name(pth1.node.name) ], @@ -1842,10 +1844,10 @@ impl<'a> LoweringContext<'a> { let f = P(self.lower_expr(f)); hir::ExprCall(f, args.iter().map(|x| self.lower_expr(x)).collect()) } - ExprKind::MethodCall(i, ref tps, ref args) => { - let tps = tps.iter().map(|x| self.lower_ty(x)).collect(); + ExprKind::MethodCall(ref seg, ref args) => { + let hir_seg = self.lower_path_segment(e.span, seg, ParamMode::Optional, 0); let args = args.iter().map(|x| self.lower_expr(x)).collect(); - hir::ExprMethodCall(respan(i.span, self.lower_ident(i.node)), tps, args) + hir::ExprMethodCall(hir_seg, seg.span, args) } ExprKind::Binary(binop, ref lhs, ref rhs) => { let binop = self.lower_binop(binop); @@ -1885,9 +1887,9 @@ impl<'a> LoweringContext<'a> { let blk = P(hir::Block { stmts: hir_vec![], expr: Some(els), - id: id, + id, rules: hir::DefaultBlock, - span: span, + span, targeted_by_break: false, }); P(self.expr_block(blk, ThinVec::new())) @@ -2106,7 +2108,7 @@ impl<'a> LoweringContext<'a> { sub_expr, arms.into(), hir::MatchSource::IfLetDesugar { - contains_else_clause: contains_else_clause, + contains_else_clause, }) } @@ -2168,12 +2170,12 @@ impl<'a> LoweringContext<'a> { // let result = match ::std::iter::IntoIterator::into_iter() { // mut iter => { // [opt_ident]: loop { - // let mut _next; + // let mut __next; // match ::std::iter::Iterator::next(&mut iter) { - // ::std::option::Option::Some(val) => _next = val, + // ::std::option::Option::Some(val) => __next = val, // ::std::option::Option::None => break // }; - // let = _next; + // let = __next; // StmtExpr(); // } // } @@ -2186,7 +2188,7 @@ impl<'a> LoweringContext<'a> { let iter = self.str_to_ident("iter"); - let next_ident = self.str_to_ident("_next"); + let next_ident = self.str_to_ident("__next"); let next_pat = self.pat_ident_binding_mode(e.span, next_ident, hir::BindByValue(hir::MutMutable)); @@ -2235,13 +2237,13 @@ impl<'a> LoweringContext<'a> { let next_expr = P(self.expr_ident(e.span, next_ident, next_pat.id)); - // `let mut _next` + // `let mut __next` let next_let = self.stmt_let_pat(e.span, None, next_pat, hir::LocalSource::ForLoopDesugar); - // `let = _next` + // `let = __next` let pat = self.lower_pat(pat); let pat_let = self.stmt_let_pat(e.span, Some(next_expr), @@ -2534,7 +2536,7 @@ impl<'a> LoweringContext<'a> { fn arm(&mut self, pats: hir::HirVec>, expr: P) -> hir::Arm { hir::Arm { attrs: hir_vec![], - pats: pats, + pats, guard: None, body: expr, } @@ -2544,10 +2546,10 @@ impl<'a> LoweringContext<'a> { hir::Field { name: Spanned { node: name, - span: span, + span, }, - span: span, - expr: expr, + span, + expr, is_shorthand: false, } } @@ -2576,8 +2578,8 @@ impl<'a> LoweringContext<'a> { }; let expr_path = hir::ExprPath(hir::QPath::Resolved(None, P(hir::Path { - span: span, - def: def, + span, + def, segments: hir_vec![hir::PathSegment::from_name(id)], }))); @@ -2617,9 +2619,9 @@ impl<'a> LoweringContext<'a> { fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinVec) -> hir::Expr { hir::Expr { id: self.next_id(), - node: node, - span: span, - attrs: attrs, + node, + span, + attrs, } } @@ -2630,7 +2632,7 @@ impl<'a> LoweringContext<'a> { source: hir::LocalSource) -> hir::Stmt { let local = P(hir::Local { - pat: pat, + pat, ty: None, init: ex, id: self.next_id(), @@ -2660,11 +2662,11 @@ impl<'a> LoweringContext<'a> { fn block_all(&mut self, span: Span, stmts: hir::HirVec, expr: Option>) -> hir::Block { hir::Block { - stmts: stmts, - expr: expr, + stmts, + expr, id: self.next_id(), rules: hir::DefaultBlock, - span: span, + span, targeted_by_break: false, } } @@ -2710,22 +2712,22 @@ impl<'a> LoweringContext<'a> { let parent_def = self.parent_def.unwrap(); let def_id = { let defs = self.resolver.definitions(); - let def_path_data = DefPathData::Binding(Ident::with_empty_ctxt(name)); + let def_path_data = DefPathData::Binding(name); let def_index = defs .create_def_with_parent(parent_def, id, def_path_data, REGULAR_SPACE, Mark::root()); DefId::local(def_index) }; P(hir::Pat { - id: id, + id, node: hir::PatKind::Binding(bm, def_id, Spanned { - span: span, + span, node: name, }, None), - span: span, + span, }) } @@ -2737,7 +2739,7 @@ impl<'a> LoweringContext<'a> { P(hir::Pat { id: self.next_id(), node: pat, - span: span, + span, }) } @@ -2746,7 +2748,7 @@ impl<'a> LoweringContext<'a> { /// The path is also resolved according to `is_value`. fn std_path(&mut self, span: Span, components: &[&str], is_value: bool) -> hir::Path { let mut path = hir::Path { - span: span, + span, def: Def::Err, segments: iter::once(keywords::CrateRoot.name()).chain({ self.crate_root.into_iter().chain(components.iter().cloned()).map(Symbol::intern) @@ -2767,9 +2769,9 @@ impl<'a> LoweringContext<'a> { let id = self.next_id(); let block = P(hir::Block { rules: rule, - span: span, - id: id, - stmts: stmts, + span, + id, + stmts, expr: Some(expr), targeted_by_break: false, }); @@ -2808,7 +2810,7 @@ impl<'a> LoweringContext<'a> { fn elided_lifetime(&mut self, span: Span) -> hir::Lifetime { hir::Lifetime { id: self.next_id(), - span: span, + span, name: keywords::Invalid.name() } } diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index ff2f1dc1ba..661798a825 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -130,9 +130,9 @@ impl<'a> ClosureParts<'a> { ClosureParts { decl: d, body: b, - id: id, + id, span: s, - attrs: attrs, + attrs, } } } @@ -149,7 +149,7 @@ impl<'a> FnLikeNode<'a> { }; if fn_like { Some(FnLikeNode { - node: node + node, }) } else { None @@ -224,12 +224,12 @@ impl<'a> FnLikeNode<'a> { id: i.id, name: i.name, decl: &decl, - unsafety: unsafety, + unsafety, body: block, - generics: generics, - abi: abi, + generics, + abi, vis: &i.vis, - constness: constness, + constness, span: i.span, attrs: &i.attrs, }), diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 904f74b878..d3ae3e0e8e 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -28,7 +28,7 @@ pub struct NodeCollector<'hir> { impl<'hir> NodeCollector<'hir> { pub fn root(krate: &'hir Crate) -> NodeCollector<'hir> { let mut collector = NodeCollector { - krate: krate, + krate, map: vec![], parent_node: CRATE_NODE_ID, }; diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index cb25b462b6..d348a5db05 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -15,6 +15,7 @@ use syntax::ast::*; use syntax::ext::hygiene::Mark; use syntax::visit; use syntax::symbol::keywords; +use syntax::symbol::Symbol; use hir::map::{ITEM_LIKE_SPACE, REGULAR_SPACE}; @@ -35,8 +36,8 @@ pub struct MacroInvocationData { impl<'a> DefCollector<'a> { pub fn new(definitions: &'a mut Definitions, expansion: Mark) -> Self { DefCollector { - definitions: definitions, - expansion: expansion, + definitions, + expansion, parent_def: None, visit_macro_invoc: None, } @@ -85,7 +86,7 @@ impl<'a> DefCollector<'a> { if let Some(ref mut visit) = self.visit_macro_invoc { visit(MacroInvocationData { mark: id.placeholder_to_mark(), - const_expr: const_expr, + const_expr, def_index: self.parent_def.unwrap(), }) } @@ -103,14 +104,14 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { DefPathData::Impl, ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) => - DefPathData::TypeNs(i.ident.modern()), + DefPathData::TypeNs(i.ident.name), ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => { return visit::walk_item(self, i); } - ItemKind::Mod(..) => DefPathData::Module(i.ident.modern()), + ItemKind::Mod(..) => DefPathData::Module(i.ident.name), ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => - DefPathData::ValueNs(i.ident.modern()), - ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.modern()), + DefPathData::ValueNs(i.ident.name), + ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name), ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false), ItemKind::GlobalAsm(..) => DefPathData::Misc, ItemKind::Use(ref view_path) => { @@ -138,13 +139,13 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { for v in &enum_definition.variants { let variant_def_index = this.create_def(v.node.data.id(), - DefPathData::EnumVariant(v.node.name.modern()), + DefPathData::EnumVariant(v.node.name.name), REGULAR_SPACE); this.with_parent(variant_def_index, |this| { for (index, field) in v.node.data.fields().iter().enumerate() { - let ident = field.ident.map(Ident::modern) - .unwrap_or_else(|| Ident::from_str(&index.to_string())); - this.create_def(field.id, DefPathData::Field(ident), REGULAR_SPACE); + let name = field.ident.map(|ident| ident.name) + .unwrap_or_else(|| Symbol::intern(&index.to_string())); + this.create_def(field.id, DefPathData::Field(name), REGULAR_SPACE); } if let Some(ref expr) = v.node.disr_expr { @@ -162,9 +163,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { } for (index, field) in struct_def.fields().iter().enumerate() { - let ident = field.ident.map(Ident::modern) - .unwrap_or_else(|| Ident::from_str(&index.to_string())); - this.create_def(field.id, DefPathData::Field(ident), REGULAR_SPACE); + let name = field.ident.map(|ident| ident.name) + .unwrap_or_else(|| Symbol::intern(&index.to_string())); + this.create_def(field.id, DefPathData::Field(name), REGULAR_SPACE); } } _ => {} @@ -175,7 +176,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) { let def = self.create_def(foreign_item.id, - DefPathData::ValueNs(foreign_item.ident.modern()), + DefPathData::ValueNs(foreign_item.ident.name), REGULAR_SPACE); self.with_parent(def, |this| { @@ -186,7 +187,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_generics(&mut self, generics: &'a Generics) { for ty_param in generics.ty_params.iter() { self.create_def(ty_param.id, - DefPathData::TypeParam(ty_param.ident.modern()), + DefPathData::TypeParam(ty_param.ident.name), REGULAR_SPACE); } @@ -196,8 +197,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_trait_item(&mut self, ti: &'a TraitItem) { let def_data = match ti.node { TraitItemKind::Method(..) | TraitItemKind::Const(..) => - DefPathData::ValueNs(ti.ident.modern()), - TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.modern()), + DefPathData::ValueNs(ti.ident.name), + TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name), TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false), }; @@ -214,8 +215,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_impl_item(&mut self, ii: &'a ImplItem) { let def_data = match ii.node { ImplItemKind::Method(..) | ImplItemKind::Const(..) => - DefPathData::ValueNs(ii.ident.modern()), - ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.modern()), + DefPathData::ValueNs(ii.ident.name), + ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name), ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false), }; @@ -236,7 +237,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { PatKind::Mac(..) => return self.visit_macro_invoc(pat.id, false), PatKind::Ident(_, id, _) => { let def = self.create_def(pat.id, - DefPathData::Binding(id.node.modern()), + DefPathData::Binding(id.node.name), REGULAR_SPACE); self.parent_def = Some(def); } @@ -281,7 +282,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_lifetime_def(&mut self, def: &'a LifetimeDef) { self.create_def(def.lifetime.id, - DefPathData::LifetimeDef(def.lifetime.ident.modern()), + DefPathData::LifetimeDef(def.lifetime.ident.name), REGULAR_SPACE); } diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index ced0f351c9..d89e86ee66 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -15,7 +15,8 @@ //! expressions) that are mostly just leftovers. use hir; -use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, DefIndexAddressSpace}; +use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, DefIndexAddressSpace, + CRATE_DEF_INDEX}; use ich::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::IndexVec; @@ -23,8 +24,8 @@ use rustc_data_structures::stable_hasher::StableHasher; use serialize::{Encodable, Decodable, Encoder, Decoder}; use std::fmt::Write; use std::hash::Hash; -use syntax::ast::{self, Ident}; -use syntax::ext::hygiene::{Mark, SyntaxContext}; +use syntax::ast; +use syntax::ext::hygiene::Mark; use syntax::symbol::{Symbol, InternedString}; use ty::TyCtxt; use util::nodemap::NodeMap; @@ -189,9 +190,9 @@ impl Decodable for DefPathTable { } Ok(DefPathTable { - index_to_key: index_to_key, - key_to_index: key_to_index, - def_path_hashes: def_path_hashes, + index_to_key, + key_to_index, + def_path_hashes, }) } } @@ -247,7 +248,39 @@ impl DefKey { // and the special "root_parent" below. 0u8.hash(&mut hasher); parent_hash.hash(&mut hasher); - self.disambiguated_data.hash(&mut hasher); + + let DisambiguatedDefPathData { + ref data, + disambiguator, + } = self.disambiguated_data; + + ::std::mem::discriminant(data).hash(&mut hasher); + match *data { + DefPathData::TypeNs(name) | + DefPathData::ValueNs(name) | + DefPathData::Module(name) | + DefPathData::MacroDef(name) | + DefPathData::TypeParam(name) | + DefPathData::LifetimeDef(name) | + DefPathData::EnumVariant(name) | + DefPathData::Binding(name) | + DefPathData::Field(name) | + DefPathData::GlobalMetaData(name) => { + (*name.as_str()).hash(&mut hasher); + } + + DefPathData::Impl | + DefPathData::CrateRoot | + DefPathData::Misc | + DefPathData::ClosureExpr | + DefPathData::StructCtor | + DefPathData::Initializer | + DefPathData::ImplTrait | + DefPathData::Typeof => {} + }; + + disambiguator.hash(&mut hasher); + DefPathHash(hasher.finish()) } @@ -353,7 +386,7 @@ impl DefPath { } } -#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] +#[derive(Clone, Debug, Eq, PartialEq, 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. @@ -367,35 +400,40 @@ pub enum DefPathData { /// An impl Impl, /// Something in the type NS - TypeNs(Ident), + TypeNs(Symbol), /// Something in the value NS - ValueNs(Ident), + ValueNs(Symbol), /// A module declaration - Module(Ident), + Module(Symbol), /// A macro rule - MacroDef(Ident), + MacroDef(Symbol), /// A closure expression ClosureExpr, // Subportions of items /// A type parameter (generic parameter) - TypeParam(Ident), + TypeParam(Symbol), /// A lifetime definition - LifetimeDef(Ident), + LifetimeDef(Symbol), /// A variant of a enum - EnumVariant(Ident), + EnumVariant(Symbol), /// A struct field - Field(Ident), + Field(Symbol), /// Implicit ctor for a tuple-like struct StructCtor, /// Initializer for a const Initializer, /// Pattern binding - Binding(Ident), + Binding(Symbol), /// An `impl Trait` type node. ImplTrait, /// A `typeof` type node. Typeof, + + /// GlobalMetaData identifies a piece of crate metadata that is global to + /// a whole crate (as opposed to just one item). GlobalMetaData components + /// are only supposed to show up right below the crate root. + GlobalMetaData(Symbol) } #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, @@ -427,8 +465,8 @@ impl Definitions { /// Get the number of definitions. pub fn def_index_counts_lo_hi(&self) -> (usize, usize) { - (self.def_index_to_node[DefIndexAddressSpace::Low.index()].len(), - self.def_index_to_node[DefIndexAddressSpace::High.index()].len()) + (self.table.index_to_key[DefIndexAddressSpace::Low.index()].len(), + self.table.index_to_key[DefIndexAddressSpace::High.index()].len()) } pub fn def_key(&self, index: DefIndex) -> DefKey { @@ -469,7 +507,12 @@ impl Definitions { if def_id.krate == LOCAL_CRATE { let space_index = def_id.index.address_space().index(); let array_index = def_id.index.as_array_index(); - Some(self.def_index_to_node[space_index][array_index]) + let node_id = self.def_index_to_node[space_index][array_index]; + if node_id != ast::DUMMY_NODE_ID { + Some(node_id) + } else { + None + } } else { None } @@ -498,12 +541,16 @@ impl Definitions { // Create the definition. let address_space = super::ITEM_LIKE_SPACE; - let index = self.table.allocate(key, def_path_hash, address_space); + let root_index = self.table.allocate(key, def_path_hash, address_space); + assert_eq!(root_index, CRATE_DEF_INDEX); assert!(self.def_index_to_node[address_space.index()].is_empty()); self.def_index_to_node[address_space.index()].push(ast::CRATE_NODE_ID); - self.node_to_def_index.insert(ast::CRATE_NODE_ID, index); + self.node_to_def_index.insert(ast::CRATE_NODE_ID, root_index); - index + // Allocate some other DefIndices that always must exist. + GlobalMetaDataKind::allocate_def_indices(self); + + root_index } /// Add a definition with a parent definition. @@ -531,7 +578,7 @@ impl Definitions { let mut key = DefKey { parent: Some(parent), disambiguated_data: DisambiguatedDefPathData { - data: data, + data, disambiguator: 0 } }; @@ -550,13 +597,19 @@ impl Definitions { assert_eq!(index.as_array_index(), self.def_index_to_node[address_space.index()].len()); self.def_index_to_node[address_space.index()].push(node_id); + + // Some things for which we allocate DefIndices don't correspond to + // anything in the AST, so they don't have a NodeId. For these cases + // we don't need a mapping from NodeId to DefIndex. + if node_id != ast::DUMMY_NODE_ID { + debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id); + self.node_to_def_index.insert(node_id, index); + } + if expansion.is_modern() { self.expansions.insert(index, expansion); } - debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id); - self.node_to_def_index.insert(node_id, index); - index } @@ -583,18 +636,19 @@ impl Definitions { } impl DefPathData { - pub fn get_opt_ident(&self) -> Option { + pub fn get_opt_name(&self) -> Option { use self::DefPathData::*; match *self { - TypeNs(ident) | - ValueNs(ident) | - Module(ident) | - MacroDef(ident) | - TypeParam(ident) | - LifetimeDef(ident) | - EnumVariant(ident) | - Binding(ident) | - Field(ident) => Some(ident), + TypeNs(name) | + ValueNs(name) | + Module(name) | + MacroDef(name) | + TypeParam(name) | + LifetimeDef(name) | + EnumVariant(name) | + Binding(name) | + Field(name) | + GlobalMetaData(name) => Some(name), Impl | CrateRoot | @@ -607,23 +661,20 @@ impl DefPathData { } } - pub fn get_opt_name(&self) -> Option { - self.get_opt_ident().map(|ident| ident.name) - } - pub fn as_interned_str(&self) -> InternedString { use self::DefPathData::*; let s = match *self { - TypeNs(ident) | - ValueNs(ident) | - Module(ident) | - MacroDef(ident) | - TypeParam(ident) | - LifetimeDef(ident) | - EnumVariant(ident) | - Binding(ident) | - Field(ident) => { - return ident.name.as_str(); + TypeNs(name) | + ValueNs(name) | + Module(name) | + MacroDef(name) | + TypeParam(name) | + LifetimeDef(name) | + EnumVariant(name) | + Binding(name) | + Field(name) | + GlobalMetaData(name) => { + return name.as_str(); } // note that this does not show up in user printouts @@ -646,24 +697,72 @@ impl DefPathData { } } -impl Eq for DefPathData {} -impl PartialEq for DefPathData { - fn eq(&self, other: &DefPathData) -> bool { - ::std::mem::discriminant(self) == ::std::mem::discriminant(other) && - self.get_opt_ident() == other.get_opt_ident() - } -} +// We define the GlobalMetaDataKind enum with this macro because we want to +// make sure that we exhaustively iterate over all variants when registering +// the corresponding DefIndices in the DefTable. +macro_rules! define_global_metadata_kind { + (pub enum GlobalMetaDataKind { + $($variant:ident),* + }) => ( + #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, + RustcEncodable, RustcDecodable)] + pub enum GlobalMetaDataKind { + $($variant),* + } -impl ::std::hash::Hash for DefPathData { - fn hash(&self, hasher: &mut H) { - ::std::mem::discriminant(self).hash(hasher); - if let Some(ident) = self.get_opt_ident() { - if ident.ctxt == SyntaxContext::empty() && ident.name == ident.name.interned() { - ident.name.as_str().hash(hasher) - } else { - // FIXME(jseyfried) implement stable hashing for idents with macros 2.0 hygiene info - ident.hash(hasher) + impl GlobalMetaDataKind { + fn allocate_def_indices(definitions: &mut Definitions) { + $({ + let instance = GlobalMetaDataKind::$variant; + definitions.create_def_with_parent( + CRATE_DEF_INDEX, + ast::DUMMY_NODE_ID, + DefPathData::GlobalMetaData(instance.name()), + DefIndexAddressSpace::High, + Mark::root() + ); + + // Make sure calling def_index does not crash. + instance.def_index(&definitions.table); + })* + } + + pub fn def_index(&self, def_path_table: &DefPathTable) -> DefIndex { + let def_key = DefKey { + parent: Some(CRATE_DEF_INDEX), + disambiguated_data: DisambiguatedDefPathData { + data: DefPathData::GlobalMetaData(self.name()), + disambiguator: 0, + } + }; + + def_path_table.key_to_index[&def_key] + } + + fn name(&self) -> Symbol { + + let string = match *self { + $( + GlobalMetaDataKind::$variant => { + concat!("{{GlobalMetaData::", stringify!($variant), "}}") + } + )* + }; + + Symbol::intern(string) } } - } + ) } + +define_global_metadata_kind!(pub enum GlobalMetaDataKind { + Krate, + CrateDeps, + DylibDependencyFormats, + LangItems, + LangItemsMissing, + NativeLibraries, + CodeMap, + Impls, + ExportedSymbols +}); diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index b3cc0c542e..e6af075a29 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -16,7 +16,7 @@ use rustc_data_structures::fx::FxHashMap; pub fn check_crate<'hir>(hir_map: &hir::map::Map<'hir>) { let mut outer_visitor = OuterVisitor { - hir_map: hir_map, + hir_map, errors: vec![], }; @@ -49,7 +49,7 @@ impl<'a, 'hir: 'a> OuterVisitor<'a, 'hir> { hir_map: &'a hir::map::Map<'hir>) -> HirIdValidator<'a, 'hir> { HirIdValidator { - hir_map: hir_map, + hir_map, owner_def_index: None, hir_ids_seen: FxHashMap(), errors: Vec::new(), diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 176760c255..2044d32ff9 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -15,7 +15,7 @@ pub use self::def_collector::{DefCollector, MacroInvocationData}; pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData, DisambiguatedDefPathData, DefPathHash}; -use dep_graph::{DepGraph, DepNode}; +use dep_graph::{DepGraph, DepNode, DepKind}; use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex, DefIndexAddressSpace}; @@ -228,14 +228,14 @@ pub struct Forest { impl Forest { pub fn new(krate: Crate, dep_graph: &DepGraph) -> Forest { Forest { - krate: krate, + krate, dep_graph: dep_graph.clone(), inlined_bodies: TypedArena::new() } } pub fn krate<'hir>(&'hir self) -> &'hir Crate { - self.dep_graph.read(DepNode::Krate); + self.dep_graph.read(DepNode::new_no_params(DepKind::Krate)); &self.krate } } @@ -280,7 +280,7 @@ impl<'hir> Map<'hir> { self.dep_graph.read(self.dep_node(id)); } - fn dep_node(&self, id0: NodeId) -> DepNode { + fn dep_node(&self, id0: NodeId) -> DepNode { let mut id = id0; let mut last_expr = None; loop { @@ -289,14 +289,16 @@ impl<'hir> Map<'hir> { EntryItem(..) | EntryTraitItem(..) | EntryImplItem(..) => { + let def_index = self.definitions.opt_def_index(id).unwrap(); + let def_path_hash = self.definitions.def_path_hash(def_index); + 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 def_path_hash.to_dep_node(DepKind::HirBody); } } - return DepNode::Hir(self.local_def_id(id)); + return def_path_hash.to_dep_node(DepKind::Hir); } EntryVariant(p, v) => { @@ -305,8 +307,9 @@ impl<'hir> Map<'hir> { 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); + let def_index = self.definitions.opt_def_index(id).unwrap(); + let def_path_hash = self.definitions.def_path_hash(def_index); + return def_path_hash.to_dep_node(DepKind::HirBody); } } } @@ -331,7 +334,8 @@ impl<'hir> Map<'hir> { } RootCrate => { - return DepNode::Hir(DefId::local(CRATE_DEF_INDEX)); + let def_path_hash = self.definitions.def_path_hash(CRATE_DEF_INDEX); + return def_path_hash.to_dep_node(DepKind::Hir); } NotPresent => @@ -339,8 +343,11 @@ impl<'hir> Map<'hir> { // 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)) + return self.definitions.opt_def_index(id) + .map(|def_index| { + let def_path_hash = self.definitions.def_path_hash(def_index); + def_path_hash.to_dep_node(DepKind::Hir) + }) .unwrap_or_else(|| { bug!("Walking parents from `{}` \ led to `NotPresent` at `{}`", @@ -497,7 +504,7 @@ impl<'hir> Map<'hir> { } pub fn trait_impls(&self, trait_did: DefId) -> &'hir [NodeId] { - self.dep_graph.read(DepNode::AllLocalTraitImpls); + self.dep_graph.read(DepNode::new_no_params(DepKind::AllLocalTraitImpls)); // NB: intentionally bypass `self.forest.krate()` so that we // do not trigger a read of the whole krate here @@ -505,7 +512,7 @@ impl<'hir> Map<'hir> { } pub fn trait_default_impl(&self, trait_did: DefId) -> Option { - self.dep_graph.read(DepNode::AllLocalTraitImpls); + self.dep_graph.read(DepNode::new_no_params(DepKind::AllLocalTraitImpls)); // NB: intentionally bypass `self.forest.krate()` so that we // do not trigger a read of the whole krate here @@ -520,8 +527,9 @@ impl<'hir> Map<'hir> { /// invoking `krate.attrs` because it registers a tighter /// dep-graph access. 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)); + let def_path_hash = self.definitions.def_path_hash(CRATE_DEF_INDEX); + + self.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir)); &self.forest.krate.attrs } @@ -586,8 +594,12 @@ impl<'hir> Map<'hir> { /// last good node id we found. Note that reaching the crate root (id == 0), /// 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<'hir>) -> bool + fn walk_parent_nodes(&self, + start_id: NodeId, + found: F, + bail_early: F2) + -> Result + where F: Fn(&Node<'hir>) -> bool, F2: Fn(&Node<'hir>) -> bool { let mut id = start_id; loop { @@ -608,6 +620,8 @@ impl<'hir> Map<'hir> { Some(ref node) => { if found(node) { return Ok(parent_node); + } else if bail_early(node) { + return Err(parent_node); } } None => { @@ -618,6 +632,56 @@ impl<'hir> Map<'hir> { } } + /// Retrieve the NodeId for `id`'s enclosing method, unless there's a + /// `while` or `loop` before reacing it, as block tail returns are not + /// available in them. + /// + /// ``` + /// fn foo(x: usize) -> bool { + /// if x == 1 { + /// true // `get_return_block` gets passed the `id` corresponding + /// } else { // to this, it will return `foo`'s `NodeId`. + /// false + /// } + /// } + /// ``` + /// + /// ``` + /// fn foo(x: usize) -> bool { + /// loop { + /// true // `get_return_block` gets passed the `id` corresponding + /// } // to this, it will return `None`. + /// false + /// } + /// ``` + pub fn get_return_block(&self, id: NodeId) -> Option { + let match_fn = |node: &Node| { + match *node { + NodeItem(_) | + NodeForeignItem(_) | + NodeTraitItem(_) | + NodeImplItem(_) => true, + _ => false, + } + }; + let match_non_returning_block = |node: &Node| { + match *node { + NodeExpr(ref expr) => { + match expr.node { + ExprWhile(..) | ExprLoop(..) => true, + _ => false, + } + } + _ => false, + } + }; + + match self.walk_parent_nodes(id, match_fn, match_non_returning_block) { + Ok(id) => Some(id), + Err(_) => None, + } + } + /// Retrieve the NodeId for `id`'s parent item, or `id` itself if no /// parent item is in this map. The "parent item" is the closest parent node /// in the AST which is recorded by the map and is an item, either an item @@ -629,7 +693,7 @@ impl<'hir> Map<'hir> { NodeTraitItem(_) | NodeImplItem(_) => true, _ => false, - }) { + }, |_| false) { Ok(id) => id, Err(id) => id, } @@ -641,7 +705,7 @@ impl<'hir> Map<'hir> { let id = match self.walk_parent_nodes(id, |node| match *node { NodeItem(&Item { node: Item_::ItemMod(_), .. }) => true, _ => false, - }) { + }, |_| false) { Ok(id) => id, Err(id) => id, }; @@ -660,7 +724,7 @@ impl<'hir> Map<'hir> { NodeImplItem(_) | NodeBlock(_) => true, _ => false, - }) { + }, |_| false) { Ok(id) => Some(id), Err(_) => None, } @@ -754,11 +818,8 @@ impl<'hir> Map<'hir> { } } - 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 get_inlined_body_untracked(&self, def_id: DefId) -> Option<&'hir Body> { + self.inlined_bodies.borrow().get(&def_id).cloned() } pub fn intern_inlined_body(&self, def_id: DefId, body: Body) -> &'hir Body { @@ -996,10 +1057,10 @@ pub fn map_crate<'hir>(forest: &'hir mut Forest, } let map = Map { - forest: forest, + forest, dep_graph: forest.dep_graph.clone(), - map: map, - definitions: definitions, + map, + definitions, inlined_bodies: RefCell::new(DefIdMap()), }; diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 3f2977cc50..fd79ec3b6b 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -218,7 +218,7 @@ impl PathSegment { /// Convert an identifier to the corresponding segment. pub fn from_name(name: Name) -> PathSegment { PathSegment { - name: name, + name, parameters: PathParameters::none() } } @@ -972,19 +972,16 @@ pub enum Expr_ { /// The first field resolves to the function itself (usually an `ExprPath`), /// and the second field is the list of arguments ExprCall(P, HirVec), - /// A method call (`x.foo::(a, b, c, d)`) + /// A method call (`x.foo::<'static, Bar, Baz>(a, b, c, d)`) /// - /// The `Spanned` is the identifier for the method name. - /// The vector of `Ty`s are the ascripted type parameters for the method + /// The `PathSegment`/`Span` represent the method name and its generic arguments /// (within the angle brackets). - /// - /// The first element of the vector of `Expr`s is the expression that - /// evaluates to the object on which the method is being called on (the - /// receiver), and the remaining elements are the rest of the arguments. - /// + /// The first element of the vector of `Expr`s is the expression that evaluates + /// to the object on which the method is being called on (the receiver), + /// and the remaining elements are the rest of the arguments. /// Thus, `x.foo::(a, b, c, d)` is represented as - /// `ExprMethodCall(foo, [Bar, Baz], [x, a, b, c, d])`. - ExprMethodCall(Spanned, HirVec>, HirVec), + /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`. + ExprMethodCall(PathSegment, Span, HirVec), /// A tuple (`(a, b, c ,d)`) ExprTup(HirVec), /// A binary operation (For example: `a + b`, `a * b`) diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index a78d5ce1c1..beaf65b77d 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -15,10 +15,9 @@ use syntax::ast; use syntax::codemap::{CodeMap, Spanned}; 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}; +use syntax::print::pp::{self, Breaks}; use syntax::print::pp::Breaks::{Consistent, Inconsistent}; -use syntax::print::pprust::{self as ast_pp, PrintState}; +use syntax::print::pprust::PrintState; use syntax::ptr::P; use syntax::symbol::keywords; use syntax_pos::{self, BytePos}; @@ -28,6 +27,8 @@ use hir::{PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier, Ra use std::cell::Cell; use std::io::{self, Write, Read}; +use std::iter::Peekable; +use std::vec; pub enum AnnNode<'a> { NodeName(&'a ast::Name), @@ -78,8 +79,8 @@ pub struct State<'a> { pub s: pp::Printer<'a>, cm: Option<&'a CodeMap>, comments: Option>, - literals: Option>, - cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral, + literals: Peekable>, + cur_cmnt: usize, boxes: Vec, ann: &'a (PpAnn + 'a), } @@ -97,12 +98,16 @@ impl<'a> PrintState<'a> for State<'a> { &mut self.comments } - fn cur_cmnt_and_lit(&mut self) -> &mut ast_pp::CurrentCommentAndLiteral { - &mut self.cur_cmnt_and_lit + fn cur_cmnt(&mut self) -> &mut usize { + &mut self.cur_cmnt } - fn literals(&self) -> &Option> { - &self.literals + fn cur_lit(&mut self) -> Option<&comments::Literal> { + self.literals.peek() + } + + fn bump_lit(&mut self) -> Option { + self.literals.next() } } @@ -132,7 +137,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap, s.print_mod(&krate.module, &krate.attrs)?; s.print_remaining_comments()?; - eof(&mut s.s) + s.s.eof() } impl<'a> State<'a> { @@ -170,13 +175,10 @@ impl<'a> State<'a> { s: pp::mk_printer(out, default_columns), cm: Some(cm), comments: comments.clone(), - literals: literals.clone(), - cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral { - cur_cmnt: 0, - cur_lit: 0, - }, + literals: literals.unwrap_or_default().into_iter().peekable(), + cur_cmnt: 0, boxes: Vec::new(), - ann: ann, + ann, } } } @@ -190,16 +192,13 @@ pub fn to_string(ann: &PpAnn, f: F) -> String 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, - }, + literals: vec![].into_iter().peekable(), + cur_cmnt: 0, boxes: Vec::new(), - ann: ann, + ann, }; f(&mut printer).unwrap(); - eof(&mut printer.s).unwrap(); + printer.s.eof().unwrap(); } String::from_utf8(wr).unwrap() } @@ -207,7 +206,7 @@ pub fn to_string(ann: &PpAnn, f: F) -> String pub fn visibility_qualified(vis: &hir::Visibility, w: &str) -> String { to_string(NO_ANN, |s| { s.print_visibility(vis)?; - word(&mut s.s, w) + s.s.word(w) }) } @@ -226,15 +225,15 @@ fn needs_parentheses(expr: &hir::Expr) -> bool { impl<'a> State<'a> { pub fn cbox(&mut self, u: usize) -> io::Result<()> { self.boxes.push(pp::Breaks::Consistent); - pp::cbox(&mut self.s, u) + self.s.cbox(u) } pub fn nbsp(&mut self) -> io::Result<()> { - word(&mut self.s, " ") + self.s.word(" ") } pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> { - word(&mut self.s, w)?; + self.s.word(w)?; self.nbsp() } @@ -251,7 +250,7 @@ impl<'a> State<'a> { } pub fn bopen(&mut self) -> io::Result<()> { - word(&mut self.s, "{")?; + self.s.word("{")?; self.end() // close the head-box } @@ -265,7 +264,7 @@ impl<'a> State<'a> { -> io::Result<()> { self.maybe_print_comment(span.hi)?; self.break_offset_if_not_bol(1, -(indented as isize))?; - word(&mut self.s, "}")?; + self.s.word("}")?; if close_box { self.end()?; // close the outer-box } @@ -283,19 +282,19 @@ impl<'a> State<'a> { } pub fn space_if_not_bol(&mut self) -> io::Result<()> { if !self.is_bol() { - space(&mut self.s)?; + self.s.space()?; } Ok(()) } pub fn break_offset_if_not_bol(&mut self, n: usize, off: isize) -> io::Result<()> { if !self.is_bol() { - break_offset(&mut self.s, n, off) + self.s.break_offset(n, off) } else { if off != 0 && self.s.last_token().is_hardbreak_tok() { // We do something pretty sketchy here: tuck the nonzero // offset-adjustment we were going to deposit along with the // break into the previous hardbreak. - self.s.replace_last_token(pp::hardbreak_tok_offset(off)); + self.s.replace_last_token(pp::Printer::hardbreak_tok_offset(off)); } Ok(()) } @@ -304,11 +303,11 @@ impl<'a> State<'a> { // Synthesizes a comment that was not textually present in the original source // file. pub fn synth_comment(&mut self, text: String) -> io::Result<()> { - word(&mut self.s, "/*")?; - space(&mut self.s)?; - word(&mut self.s, &text[..])?; - space(&mut self.s)?; - word(&mut self.s, "*/") + self.s.word("/*")?; + self.s.space()?; + self.s.word(&text[..])?; + self.s.space()?; + self.s.word("*/") } @@ -329,7 +328,7 @@ impl<'a> State<'a> { op(self, elt)?; i += 1; if i < len { - word(&mut self.s, ",")?; + self.s.word(",")?; self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi))?; self.space_if_not_bol()?; } @@ -373,12 +372,12 @@ impl<'a> State<'a> { self.ibox(0)?; match ty.node { hir::TySlice(ref ty) => { - word(&mut self.s, "[")?; + self.s.word("[")?; self.print_type(&ty)?; - word(&mut self.s, "]")?; + self.s.word("]")?; } hir::TyPtr(ref mt) => { - word(&mut self.s, "*")?; + self.s.word("*")?; match mt.mutbl { hir::MutMutable => self.word_nbsp("mut")?, hir::MutImmutable => self.word_nbsp("const")?, @@ -386,18 +385,18 @@ impl<'a> State<'a> { self.print_type(&mt.ty)?; } hir::TyRptr(ref lifetime, ref mt) => { - word(&mut self.s, "&")?; + self.s.word("&")?; self.print_opt_lifetime(lifetime)?; self.print_mt(mt)?; } hir::TyNever => { - word(&mut self.s, "!")?; + self.s.word("!")?; }, hir::TyTup(ref elts) => { self.popen()?; self.commasep(Inconsistent, &elts[..], |s, ty| s.print_type(&ty))?; if elts.len() == 1 { - word(&mut self.s, ",")?; + self.s.word(",")?; } self.pclose()?; } @@ -436,22 +435,22 @@ impl<'a> State<'a> { self.print_bounds("impl ", &bounds[..])?; } hir::TyArray(ref ty, v) => { - word(&mut self.s, "[")?; + self.s.word("[")?; self.print_type(&ty)?; - word(&mut self.s, "; ")?; + self.s.word("; ")?; self.ann.nested(self, Nested::Body(v))?; - word(&mut self.s, "]")?; + self.s.word("]")?; } hir::TyTypeof(e) => { - word(&mut self.s, "typeof(")?; + self.s.word("typeof(")?; self.ann.nested(self, Nested::Body(e))?; - word(&mut self.s, ")")?; + self.s.word(")")?; } hir::TyInfer => { - word(&mut self.s, "_")?; + self.s.word("_")?; } hir::TyErr => { - word(&mut self.s, "?")?; + self.s.word("?")?; } } self.end() @@ -474,7 +473,7 @@ impl<'a> State<'a> { arg_names, None)?; self.end()?; // end head-ibox - word(&mut self.s, ";")?; + self.s.word(";")?; self.end() // end the outer fn box } hir::ForeignItemStatic(ref t, m) => { @@ -485,7 +484,7 @@ impl<'a> State<'a> { self.print_name(item.name)?; self.word_space(":")?; self.print_type(&t)?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; // end the head-ibox self.end() // end the outer cbox } @@ -498,17 +497,17 @@ impl<'a> State<'a> { default: Option, vis: &hir::Visibility) -> io::Result<()> { - word(&mut self.s, &visibility_qualified(vis, ""))?; + self.s.word(&visibility_qualified(vis, ""))?; self.word_space("const")?; self.print_name(name)?; self.word_space(":")?; self.print_type(ty)?; if let Some(expr) = default { - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.ann.nested(self, Nested::Body(expr))?; } - word(&mut self.s, ";") + self.s.word(";") } fn print_associated_type(&mut self, @@ -522,11 +521,11 @@ impl<'a> State<'a> { self.print_bounds(":", bounds)?; } if let Some(ty) = ty { - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_type(ty)?; } - word(&mut self.s, ";") + self.s.word(";") } /// Pretty-print an item @@ -545,12 +544,12 @@ impl<'a> State<'a> { } else { self.print_name(p)?; } - space(&mut self.s)?; - word(&mut self.s, "as")?; - space(&mut self.s)?; + self.s.space()?; + self.s.word("as")?; + self.s.space()?; } self.print_name(item.name)?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; // end inner head-block self.end()?; // end outer head-block } @@ -561,14 +560,14 @@ impl<'a> State<'a> { match kind { hir::UseKind::Single => { if path.segments.last().unwrap().name != item.name { - space(&mut self.s)?; + self.s.space()?; self.word_space("as")?; self.print_name(item.name)?; } - word(&mut self.s, ";")?; + self.s.word(";")?; } - hir::UseKind::Glob => word(&mut self.s, "::*;")?, - hir::UseKind::ListStem => word(&mut self.s, "::{};")? + hir::UseKind::Glob => self.s.word("::*;")?, + hir::UseKind::ListStem => self.s.word("::{};")? } self.end()?; // end inner head-block self.end()?; // end outer head-block @@ -581,12 +580,12 @@ impl<'a> State<'a> { self.print_name(item.name)?; self.word_space(":")?; self.print_type(&ty)?; - space(&mut self.s)?; + self.s.space()?; self.end()?; // end the head-ibox self.word_space("=")?; self.ann.nested(self, Nested::Body(expr))?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; // end the outer cbox } hir::ItemConst(ref ty, expr) => { @@ -594,12 +593,12 @@ impl<'a> State<'a> { self.print_name(item.name)?; self.word_space(":")?; self.print_type(&ty)?; - space(&mut self.s)?; + self.s.space()?; self.end()?; // end the head-ibox self.word_space("=")?; self.ann.nested(self, Nested::Body(expr))?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; // end the outer cbox } hir::ItemFn(ref decl, unsafety, constness, abi, ref typarams, body) => { @@ -613,7 +612,7 @@ impl<'a> State<'a> { &item.vis, &[], Some(body))?; - word(&mut self.s, " ")?; + self.s.word(" ")?; self.end()?; // need to close a box self.end()?; // need to close a box self.ann.nested(self, Nested::Body(body))?; @@ -635,7 +634,7 @@ impl<'a> State<'a> { } hir::ItemGlobalAsm(ref ga) => { self.head(&visibility_qualified(&item.vis, "global asm"))?; - word(&mut self.s, &ga.asm.as_str())?; + self.s.word(&ga.asm.as_str())?; self.end()? } hir::ItemTy(ref ty, ref params) => { @@ -647,10 +646,10 @@ impl<'a> State<'a> { self.end()?; // end the inner ibox self.print_where_clause(¶ms.where_clause)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_type(&ty)?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; // end the outer ibox } hir::ItemEnum(ref enum_definition, ref params) => { @@ -670,7 +669,7 @@ impl<'a> State<'a> { self.print_unsafety(unsafety)?; self.word_nbsp("impl")?; self.print_trait_ref(trait_ref)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("for")?; self.word_space("..")?; self.bopen()?; @@ -691,12 +690,12 @@ impl<'a> State<'a> { if generics.is_parameterized() { self.print_generics(generics)?; - space(&mut self.s)?; + self.s.space()?; } match polarity { hir::ImplPolarity::Negative => { - word(&mut self.s, "!")?; + self.s.word("!")?; } _ => {} } @@ -704,7 +703,7 @@ impl<'a> State<'a> { match opt_trait { &Some(ref t) => { self.print_trait_ref(t)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("for")?; } &None => {} @@ -713,7 +712,7 @@ impl<'a> State<'a> { self.print_type(&ty)?; self.print_where_clause(&generics.where_clause)?; - space(&mut self.s)?; + self.s.space()?; self.bopen()?; self.print_inner_attributes(&item.attrs)?; for impl_item in impl_items { @@ -731,7 +730,7 @@ impl<'a> State<'a> { let mut real_bounds = Vec::with_capacity(bounds.len()); for b in bounds.iter() { if let TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = *b { - space(&mut self.s)?; + self.s.space()?; self.word_space("for ?")?; self.print_trait_ref(&ptr.trait_ref)?; } else { @@ -740,7 +739,7 @@ impl<'a> State<'a> { } self.print_bounds(":", &real_bounds[..])?; self.print_where_clause(&generics.where_clause)?; - word(&mut self.s, " ")?; + self.s.word(" ")?; self.bopen()?; for trait_item in trait_items { self.ann.nested(self, Nested::TraitItem(trait_item.id))?; @@ -757,7 +756,7 @@ impl<'a> State<'a> { fn print_formal_lifetime_list(&mut self, lifetimes: &[hir::LifetimeDef]) -> io::Result<()> { if !lifetimes.is_empty() { - word(&mut self.s, "for<")?; + self.s.word("for<")?; let mut comma = false; for lifetime_def in lifetimes { if comma { @@ -766,7 +765,7 @@ impl<'a> State<'a> { self.print_lifetime_def(lifetime_def)?; comma = true; } - word(&mut self.s, ">")?; + self.s.word(">")?; } Ok(()) } @@ -787,7 +786,7 @@ impl<'a> State<'a> { self.print_name(name)?; self.print_generics(generics)?; self.print_where_clause(&generics.where_clause)?; - space(&mut self.s)?; + self.s.space()?; self.print_variants(&enum_definition.variants, span) } @@ -802,7 +801,7 @@ impl<'a> State<'a> { self.print_outer_attributes(&v.node.attrs)?; self.ibox(indent_unit)?; self.print_variant(v)?; - word(&mut self.s, ",")?; + self.s.word(",")?; self.end()?; self.maybe_print_trailing_comment(v.span, None)?; } @@ -814,7 +813,7 @@ impl<'a> State<'a> { hir::Public => self.word_nbsp("pub"), hir::Visibility::Crate => self.word_nbsp("pub(crate)"), hir::Visibility::Restricted { ref path, .. } => { - word(&mut self.s, "pub(")?; + self.s.word("pub(")?; self.print_path(path, false)?; self.word_nbsp(")") } @@ -852,7 +851,7 @@ impl<'a> State<'a> { } self.print_where_clause(&generics.where_clause)?; if print_finalizer { - word(&mut self.s, ";")?; + self.s.word(";")?; } self.end()?; self.end() // close the outer-box @@ -870,7 +869,7 @@ impl<'a> State<'a> { self.print_name(field.name)?; self.word_nbsp(":")?; self.print_type(&field.ty)?; - word(&mut self.s, ",")?; + self.s.word(",")?; } self.bclose(span) @@ -882,7 +881,7 @@ impl<'a> State<'a> { let generics = hir::Generics::empty(); self.print_struct(&v.node.data, &generics, v.node.name, v.span, false)?; if let Some(d) = v.node.disr_expr { - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.ann.nested(self, Nested::Body(d))?; } @@ -917,7 +916,7 @@ impl<'a> State<'a> { } 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, ";")?; + self.s.word(";")?; } hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => { self.head("")?; @@ -975,11 +974,11 @@ impl<'a> State<'a> { hir::StmtSemi(ref expr, _) => { self.space_if_not_bol()?; self.print_expr(&expr)?; - word(&mut self.s, ";")?; + self.s.word(";")?; } } if stmt_ends_with_semi(&st.node) { - word(&mut self.s, ";")?; + self.s.word(";")?; } self.maybe_print_trailing_comment(st.span, None) } @@ -1047,9 +1046,9 @@ impl<'a> State<'a> { hir::ExprIf(ref i, ref then, ref e) => { self.cbox(indent_unit - 1)?; self.ibox(0)?; - word(&mut self.s, " else if ")?; + self.s.word(" else if ")?; self.print_expr(&i)?; - space(&mut self.s)?; + self.s.space()?; self.print_expr(&then)?; self.print_else(e.as_ref().map(|e| &**e)) } @@ -1057,7 +1056,7 @@ impl<'a> State<'a> { hir::ExprBlock(ref b) => { self.cbox(indent_unit - 1)?; self.ibox(0)?; - word(&mut self.s, " else ")?; + self.s.word(" else ")?; self.print_block(&b) } // BLEAH, constraints would be great here @@ -1077,7 +1076,7 @@ impl<'a> State<'a> { -> io::Result<()> { self.head("if")?; self.print_expr(test)?; - space(&mut self.s)?; + self.s.space()?; self.print_expr(blk)?; self.print_else(elseopt) } @@ -1090,10 +1089,10 @@ impl<'a> State<'a> { -> io::Result<()> { self.head("if let")?; self.print_pat(pat)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_expr(expr)?; - space(&mut self.s)?; + self.s.space()?; self.print_block(blk)?; self.print_else(elseopt) } @@ -1119,19 +1118,19 @@ impl<'a> State<'a> { fn print_expr_vec(&mut self, exprs: &[hir::Expr]) -> io::Result<()> { self.ibox(indent_unit)?; - word(&mut self.s, "[")?; + self.s.word("[")?; self.commasep_exprs(Inconsistent, exprs)?; - word(&mut self.s, "]")?; + self.s.word("]")?; self.end() } fn print_expr_repeat(&mut self, element: &hir::Expr, count: hir::BodyId) -> io::Result<()> { self.ibox(indent_unit)?; - word(&mut self.s, "[")?; + self.s.word("[")?; self.print_expr(element)?; self.word_space(";")?; self.ann.nested(self, Nested::Body(count))?; - word(&mut self.s, "]")?; + self.s.word("]")?; self.end() } @@ -1141,7 +1140,7 @@ impl<'a> State<'a> { wth: &Option>) -> io::Result<()> { self.print_qpath(qpath, true)?; - word(&mut self.s, "{")?; + self.s.word("{")?; self.commasep_cmnt(Consistent, &fields[..], |s, field| { @@ -1158,18 +1157,18 @@ impl<'a> State<'a> { Some(ref expr) => { self.ibox(indent_unit)?; if !fields.is_empty() { - word(&mut self.s, ",")?; - space(&mut self.s)?; + self.s.word(",")?; + self.s.space()?; } - word(&mut self.s, "..")?; + self.s.word("..")?; self.print_expr(&expr)?; self.end()?; } _ => if !fields.is_empty() { - word(&mut self.s, ",")? + self.s.word(",")? }, } - word(&mut self.s, "}")?; + self.s.word("}")?; Ok(()) } @@ -1177,7 +1176,7 @@ impl<'a> State<'a> { self.popen()?; self.commasep_exprs(Inconsistent, exprs)?; if exprs.len() == 1 { - word(&mut self.s, ",")?; + self.s.word(",")?; } self.pclose() } @@ -1188,18 +1187,17 @@ impl<'a> State<'a> { } fn print_expr_method_call(&mut self, - name: Spanned, - tys: &[P], + segment: &hir::PathSegment, args: &[hir::Expr]) -> io::Result<()> { let base_args = &args[1..]; self.print_expr(&args[0])?; - word(&mut self.s, ".")?; - self.print_name(name.node)?; - if !tys.is_empty() { - word(&mut self.s, "::<")?; - self.commasep(Inconsistent, tys, |s, ty| s.print_type(&ty))?; - word(&mut self.s, ">")?; + self.s.word(".")?; + self.print_name(segment.name)?; + if !segment.parameters.lifetimes().is_empty() || + !segment.parameters.types().is_empty() || + !segment.parameters.bindings().is_empty() { + self.print_path_parameters(&segment.parameters, true)?; } self.print_call_post(base_args) } @@ -1210,13 +1208,13 @@ impl<'a> State<'a> { rhs: &hir::Expr) -> io::Result<()> { self.print_expr(lhs)?; - space(&mut self.s)?; + self.s.space()?; self.word_space(op.node.as_str())?; self.print_expr(rhs) } fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr) -> io::Result<()> { - word(&mut self.s, op.as_str())?; + self.s.word(op.as_str())?; self.print_expr_maybe_paren(expr) } @@ -1224,7 +1222,7 @@ impl<'a> State<'a> { mutability: hir::Mutability, expr: &hir::Expr) -> io::Result<()> { - word(&mut self.s, "&")?; + self.s.word("&")?; self.print_mutability(mutability)?; self.print_expr_maybe_paren(expr) } @@ -1254,8 +1252,8 @@ impl<'a> State<'a> { hir::ExprCall(ref func, ref args) => { self.print_expr_call(&func, args)?; } - hir::ExprMethodCall(name, ref tys, ref args) => { - self.print_expr_method_call(name, &tys[..], args)?; + hir::ExprMethodCall(ref segment, _, ref args) => { + self.print_expr_method_call(segment, args)?; } hir::ExprBinary(op, ref lhs, ref rhs) => { self.print_expr_binary(op, &lhs, &rhs)?; @@ -1271,7 +1269,7 @@ impl<'a> State<'a> { } hir::ExprCast(ref expr, ref ty) => { self.print_expr(&expr)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("as")?; self.print_type(&ty)?; } @@ -1290,7 +1288,7 @@ impl<'a> State<'a> { } self.head("while")?; self.print_expr(&test)?; - space(&mut self.s)?; + self.s.space()?; self.print_block(&blk)?; } hir::ExprLoop(ref blk, opt_sp_name, _) => { @@ -1299,7 +1297,7 @@ impl<'a> State<'a> { self.word_space(":")?; } self.head("loop")?; - space(&mut self.s)?; + self.s.space()?; self.print_block(&blk)?; } hir::ExprMatch(ref expr, ref arms, _) => { @@ -1307,7 +1305,7 @@ impl<'a> State<'a> { self.ibox(4)?; self.word_nbsp("match")?; self.print_expr(&expr)?; - space(&mut self.s)?; + self.s.space()?; self.bopen()?; for arm in arms { self.print_arm(arm)?; @@ -1318,7 +1316,7 @@ impl<'a> State<'a> { self.print_capture_clause(capture_clause)?; self.print_closure_args(&decl, body)?; - space(&mut self.s)?; + self.s.space()?; // this is a bare expression self.ann.nested(self, Nested::Body(body))?; @@ -1338,68 +1336,68 @@ impl<'a> State<'a> { } hir::ExprAssign(ref lhs, ref rhs) => { self.print_expr(&lhs)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_expr(&rhs)?; } hir::ExprAssignOp(op, ref lhs, ref rhs) => { self.print_expr(&lhs)?; - space(&mut self.s)?; - word(&mut self.s, op.node.as_str())?; + self.s.space()?; + self.s.word(op.node.as_str())?; self.word_space("=")?; self.print_expr(&rhs)?; } hir::ExprField(ref expr, name) => { self.print_expr(&expr)?; - word(&mut self.s, ".")?; + self.s.word(".")?; self.print_name(name.node)?; } hir::ExprTupField(ref expr, id) => { self.print_expr(&expr)?; - word(&mut self.s, ".")?; + self.s.word(".")?; self.print_usize(id.node)?; } hir::ExprIndex(ref expr, ref index) => { self.print_expr(&expr)?; - word(&mut self.s, "[")?; + self.s.word("[")?; self.print_expr(&index)?; - word(&mut self.s, "]")?; + self.s.word("]")?; } hir::ExprPath(ref qpath) => { self.print_qpath(qpath, true)? } hir::ExprBreak(label, ref opt_expr) => { - word(&mut self.s, "break")?; - space(&mut self.s)?; + self.s.word("break")?; + self.s.space()?; if let Some(label_ident) = label.ident { self.print_name(label_ident.node.name)?; - space(&mut self.s)?; + self.s.space()?; } if let Some(ref expr) = *opt_expr { self.print_expr(expr)?; - space(&mut self.s)?; + self.s.space()?; } } hir::ExprAgain(label) => { - word(&mut self.s, "continue")?; - space(&mut self.s)?; + self.s.word("continue")?; + self.s.space()?; if let Some(label_ident) = label.ident { self.print_name(label_ident.node.name)?; - space(&mut self.s)? + self.s.space()? } } hir::ExprRet(ref result) => { - word(&mut self.s, "return")?; + self.s.word("return")?; match *result { Some(ref expr) => { - word(&mut self.s, " ")?; + self.s.word(" ")?; self.print_expr(&expr)?; } _ => (), } } hir::ExprInlineAsm(ref a, ref outputs, ref inputs) => { - word(&mut self.s, "asm!")?; + self.s.word("asm!")?; self.popen()?; self.print_string(&a.asm.as_str(), a.asm_str_style)?; self.word_space(":")?; @@ -1421,7 +1419,7 @@ impl<'a> State<'a> { out_idx += 1; Ok(()) })?; - space(&mut self.s)?; + self.s.space()?; self.word_space(":")?; let mut in_idx = 0; @@ -1433,7 +1431,7 @@ impl<'a> State<'a> { in_idx += 1; Ok(()) })?; - space(&mut self.s)?; + self.s.space()?; self.word_space(":")?; self.commasep(Inconsistent, &a.clobbers, |s, co| { @@ -1453,7 +1451,7 @@ impl<'a> State<'a> { } if !options.is_empty() { - space(&mut self.s)?; + self.s.space()?; self.word_space(":")?; self.commasep(Inconsistent, &options, |s, &co| { s.print_string(co, ast::StrStyle::Cooked)?; @@ -1502,17 +1500,17 @@ impl<'a> State<'a> { } pub fn print_usize(&mut self, i: usize) -> io::Result<()> { - word(&mut self.s, &i.to_string()) + self.s.word(&i.to_string()) } pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> { - word(&mut self.s, &name.as_str())?; + self.s.word(&name.as_str())?; self.ann.post(self, NodeName(&name)) } pub fn print_for_decl(&mut self, loc: &hir::Local, coll: &hir::Expr) -> io::Result<()> { self.print_local_decl(loc)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("in")?; self.print_expr(coll) } @@ -1525,9 +1523,10 @@ impl<'a> State<'a> { for (i, segment) in path.segments.iter().enumerate() { if i > 0 { - word(&mut self.s, "::")? + self.s.word("::")? } - if segment.name != keywords::CrateRoot.name() && segment.name != "$crate" { + if segment.name != keywords::CrateRoot.name() && + segment.name != keywords::DollarCrate.name() { self.print_name(segment.name)?; self.print_path_parameters(&segment.parameters, colons_before_params)?; } @@ -1545,32 +1544,33 @@ impl<'a> State<'a> { self.print_path(path, colons_before_params) } hir::QPath::Resolved(Some(ref qself), ref path) => { - word(&mut self.s, "<")?; + self.s.word("<")?; self.print_type(qself)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("as")?; for (i, segment) in path.segments[..path.segments.len() - 1].iter().enumerate() { if i > 0 { - word(&mut self.s, "::")? + self.s.word("::")? } - if segment.name != keywords::CrateRoot.name() && segment.name != "$crate" { + if segment.name != keywords::CrateRoot.name() && + segment.name != keywords::DollarCrate.name() { self.print_name(segment.name)?; self.print_path_parameters(&segment.parameters, colons_before_params)?; } } - word(&mut self.s, ">")?; - word(&mut self.s, "::")?; + self.s.word(">")?; + self.s.word("::")?; let item_segment = path.segments.last().unwrap(); self.print_name(item_segment.name)?; self.print_path_parameters(&item_segment.parameters, colons_before_params) } hir::QPath::TypeRelative(ref qself, ref item_segment) => { - word(&mut self.s, "<")?; + self.s.word("<")?; self.print_type(qself)?; - word(&mut self.s, ">")?; - word(&mut self.s, "::")?; + self.s.word(">")?; + self.s.word("::")?; self.print_name(item_segment.name)?; self.print_path_parameters(&item_segment.parameters, colons_before_params) } @@ -1588,7 +1588,7 @@ impl<'a> State<'a> { let start_or_comma = |this: &mut Self| { if empty.get() { empty.set(false); - word(&mut this.s, start) + this.s.word(start) } else { this.word_space(",") } @@ -1610,26 +1610,26 @@ impl<'a> State<'a> { // "non-exhaustive patterns: `Some::<..>(_)` not covered". if data.infer_types && false { start_or_comma(self)?; - word(&mut self.s, "..")?; + self.s.word("..")?; } for binding in data.bindings.iter() { start_or_comma(self)?; self.print_name(binding.name)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_type(&binding.ty)?; } if !empty.get() { - word(&mut self.s, ">")? + self.s.word(">")? } } hir::ParenthesizedParameters(ref data) => { - word(&mut self.s, "(")?; + self.s.word("(")?; self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(&ty))?; - word(&mut self.s, ")")?; + self.s.word(")")?; if let Some(ref ty) = data.output { self.space_if_not_bol()?; @@ -1648,7 +1648,7 @@ impl<'a> State<'a> { // Pat isn't normalized, but the beauty of it // is that it doesn't matter match pat.node { - PatKind::Wild => word(&mut self.s, "_")?, + PatKind::Wild => self.s.word("_")?, PatKind::Binding(binding_mode, _, ref path1, ref sub) => { match binding_mode { hir::BindByRef(mutbl) => { @@ -1662,7 +1662,7 @@ impl<'a> State<'a> { } self.print_name(path1.node)?; if let Some(ref p) = *sub { - word(&mut self.s, "@")?; + self.s.word("@")?; self.print_pat(&p)?; } } @@ -1674,9 +1674,9 @@ impl<'a> State<'a> { if ddpos != 0 { self.word_space(",")?; } - word(&mut self.s, "..")?; + self.s.word("..")?; if ddpos != elts.len() { - word(&mut self.s, ",")?; + self.s.word(",")?; self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))?; } } else { @@ -1707,10 +1707,10 @@ impl<'a> State<'a> { if !fields.is_empty() { self.word_space(",")?; } - word(&mut self.s, "..")?; + self.s.word("..")?; } - space(&mut self.s)?; - word(&mut self.s, "}")?; + self.s.space()?; + self.s.word("}")?; } PatKind::Tuple(ref elts, ddpos) => { self.popen()?; @@ -1719,42 +1719,42 @@ impl<'a> State<'a> { if ddpos != 0 { self.word_space(",")?; } - word(&mut self.s, "..")?; + self.s.word("..")?; if ddpos != elts.len() { - word(&mut self.s, ",")?; + self.s.word(",")?; self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))?; } } else { self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))?; if elts.len() == 1 { - word(&mut self.s, ",")?; + self.s.word(",")?; } } self.pclose()?; } PatKind::Box(ref inner) => { - word(&mut self.s, "box ")?; + self.s.word("box ")?; self.print_pat(&inner)?; } PatKind::Ref(ref inner, mutbl) => { - word(&mut self.s, "&")?; + self.s.word("&")?; if mutbl == hir::MutMutable { - word(&mut self.s, "mut ")?; + self.s.word("mut ")?; } self.print_pat(&inner)?; } PatKind::Lit(ref e) => self.print_expr(&e)?, PatKind::Range(ref begin, ref end, ref end_kind) => { self.print_expr(&begin)?; - space(&mut self.s)?; + self.s.space()?; match *end_kind { - RangeEnd::Included => word(&mut self.s, "...")?, - RangeEnd::Excluded => word(&mut self.s, "..")?, + RangeEnd::Included => self.s.word("...")?, + RangeEnd::Excluded => self.s.word("..")?, } self.print_expr(&end)?; } PatKind::Slice(ref before, ref slice, ref after) => { - word(&mut self.s, "[")?; + self.s.word("[")?; self.commasep(Inconsistent, &before[..], |s, p| s.print_pat(&p))?; if let Some(ref p) = *slice { if !before.is_empty() { @@ -1763,13 +1763,13 @@ impl<'a> State<'a> { if p.node != PatKind::Wild { self.print_pat(&p)?; } - word(&mut self.s, "..")?; + self.s.word("..")?; if !after.is_empty() { self.word_space(",")?; } } self.commasep(Inconsistent, &after[..], |s, p| s.print_pat(&p))?; - word(&mut self.s, "]")?; + self.s.word("]")?; } } self.ann.post(self, NodePat(pat)) @@ -1779,7 +1779,7 @@ impl<'a> State<'a> { // I have no idea why this check is necessary, but here it // is :( if arm.attrs.is_empty() { - space(&mut self.s)?; + self.s.space()?; } self.cbox(indent_unit)?; self.ibox(0)?; @@ -1789,16 +1789,16 @@ impl<'a> State<'a> { if first { first = false; } else { - space(&mut self.s)?; + self.s.space()?; self.word_space("|")?; } self.print_pat(&p)?; } - space(&mut self.s)?; + self.s.space()?; if let Some(ref e) = arm.guard { self.word_space("if")?; self.print_expr(&e)?; - space(&mut self.s)?; + self.s.space()?; } self.word_space("=>")?; @@ -1809,13 +1809,13 @@ impl<'a> State<'a> { // If it is a user-provided unsafe block, print a comma after it if let hir::UnsafeBlock(hir::UserProvided) = blk.rules { - word(&mut self.s, ",")?; + self.s.word(",")?; } } _ => { self.end()?; // close the ibox for the pattern self.print_expr(&arm.body)?; - word(&mut self.s, ",")?; + self.s.word(",")?; } } self.end() // close enclosing cbox @@ -1847,20 +1847,20 @@ impl<'a> State<'a> { 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)?; + s.s.word(&name.node.as_str())?; + s.s.word(":")?; + s.s.space()?; } 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)?; + s.s.word(":")?; + s.s.space()?; } i += 1; s.print_type(ty)?; s.end() })?; if decl.variadic { - word(&mut self.s, ", ...")?; + self.s.word(", ...")?; } self.pclose()?; @@ -1869,7 +1869,7 @@ impl<'a> State<'a> { } fn print_closure_args(&mut self, decl: &hir::FnDecl, body_id: hir::BodyId) -> io::Result<()> { - word(&mut self.s, "|")?; + self.s.word("|")?; let mut i = 0; self.commasep(Inconsistent, &decl.inputs, |s, ty| { s.ibox(indent_unit)?; @@ -1878,13 +1878,13 @@ impl<'a> State<'a> { i += 1; if ty.node != hir::TyInfer { - word(&mut s.s, ":")?; - space(&mut s.s)?; + s.s.word(":")?; + s.s.space()?; s.print_type(ty)?; } s.end() })?; - word(&mut self.s, "|")?; + self.s.word("|")?; if let hir::DefaultReturn(..) = decl.output { return Ok(()); @@ -1910,7 +1910,7 @@ impl<'a> State<'a> { pub fn print_bounds(&mut self, prefix: &str, bounds: &[hir::TyParamBound]) -> io::Result<()> { if !bounds.is_empty() { - word(&mut self.s, prefix)?; + self.s.word(prefix)?; let mut first = true; for bound in bounds { self.nbsp()?; @@ -1925,7 +1925,7 @@ impl<'a> State<'a> { self.print_poly_trait_ref(tref) } TraitTyParamBound(ref tref, TraitBoundModifier::Maybe) => { - word(&mut self.s, "?")?; + self.s.word("?")?; self.print_poly_trait_ref(tref) } RegionTyParamBound(ref lt) => { @@ -1947,7 +1947,7 @@ impl<'a> State<'a> { self.print_lifetime(&lifetime.lifetime)?; let mut sep = ":"; for v in &lifetime.bounds { - word(&mut self.s, sep)?; + self.s.word(sep)?; self.print_lifetime(v)?; sep = "+"; } @@ -1960,7 +1960,7 @@ impl<'a> State<'a> { return Ok(()); } - word(&mut self.s, "<")?; + self.s.word("<")?; let mut ints = Vec::new(); for i in 0..total { @@ -1978,7 +1978,7 @@ impl<'a> State<'a> { } })?; - word(&mut self.s, ">")?; + self.s.word(">")?; Ok(()) } @@ -1987,7 +1987,7 @@ impl<'a> State<'a> { self.print_bounds(":", ¶m.bounds)?; match param.default { Some(ref default) => { - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_type(&default) } @@ -2000,7 +2000,7 @@ impl<'a> State<'a> { return Ok(()); } - space(&mut self.s)?; + self.s.space()?; self.word_space("where")?; for (i, predicate) in where_clause.predicates.iter().enumerate() { @@ -2021,13 +2021,13 @@ impl<'a> State<'a> { ref bounds, ..}) => { self.print_lifetime(lifetime)?; - word(&mut self.s, ":")?; + self.s.word(":")?; for (i, bound) in bounds.iter().enumerate() { self.print_lifetime(bound)?; if i != 0 { - word(&mut self.s, ":")?; + self.s.word(":")?; } } } @@ -2035,7 +2035,7 @@ impl<'a> State<'a> { ref rhs_ty, ..}) => { self.print_type(lhs_ty)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_type(rhs_ty)?; } @@ -2086,7 +2086,7 @@ impl<'a> State<'a> { -> io::Result<()> { self.ibox(indent_unit)?; if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() { - word(&mut self.s, "for")?; + self.s.word("for")?; self.print_generics(generics)?; } let generics = hir::Generics { @@ -2131,7 +2131,6 @@ impl<'a> State<'a> { if span.hi < (*cmnt).pos && (*cmnt).pos < next && span_line.line == comment_line.line { self.print_comment(cmnt)?; - self.cur_cmnt_and_lit.cur_cmnt += 1; } } Ok(()) @@ -2141,13 +2140,12 @@ impl<'a> State<'a> { // If there aren't any remaining comments, then we need to manually // make sure there is a line break at the end. if self.next_comment().is_none() { - hardbreak(&mut self.s)?; + self.s.hardbreak()?; } loop { match self.next_comment() { Some(ref cmnt) => { self.print_comment(cmnt)?; - self.cur_cmnt_and_lit.cur_cmnt += 1; } _ => break, } @@ -2184,7 +2182,7 @@ impl<'a> State<'a> { abi: Abi, vis: &hir::Visibility) -> io::Result<()> { - word(&mut self.s, &visibility_qualified(vis, ""))?; + self.s.word(&visibility_qualified(vis, ""))?; self.print_unsafety(unsafety)?; match constness { @@ -2197,7 +2195,7 @@ impl<'a> State<'a> { self.word_nbsp(&abi.to_string())?; } - word(&mut self.s, "fn") + self.s.word("fn") } pub fn print_unsafety(&mut self, s: hir::Unsafety) -> io::Result<()> { diff --git a/src/librustc/ich/caching_codemap_view.rs b/src/librustc/ich/caching_codemap_view.rs index 9aecd8ad83..49e18f100c 100644 --- a/src/librustc/ich/caching_codemap_view.rs +++ b/src/librustc/ich/caching_codemap_view.rs @@ -29,8 +29,8 @@ pub struct CachingCodemapView<'tcx> { time_stamp: usize, } -impl<'tcx> CachingCodemapView<'tcx> { - pub fn new<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CachingCodemapView<'tcx> { +impl<'gcx> CachingCodemapView<'gcx> { + pub fn new<'a, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> CachingCodemapView<'gcx> { let codemap = tcx.sess.codemap(); let files = codemap.files(); let first_file = files[0].clone(); @@ -44,7 +44,7 @@ impl<'tcx> CachingCodemapView<'tcx> { }; CachingCodemapView { - codemap: codemap, + codemap, line_cache: [entry.clone(), entry.clone(), entry.clone()], time_stamp: 0, } diff --git a/src/librustc/ich/fingerprint.rs b/src/librustc/ich/fingerprint.rs index 8308c756c0..2391b61253 100644 --- a/src/librustc/ich/fingerprint.rs +++ b/src/librustc/ich/fingerprint.rs @@ -31,9 +31,20 @@ impl Fingerprint { self.0 } + #[inline] + pub fn combine(self, other: Fingerprint) -> Fingerprint { + // See https://stackoverflow.com/a/27952689 on why this function is + // implemented this way. + Fingerprint( + self.0.wrapping_mul(3).wrapping_add(other.0), + self.1.wrapping_mul(3).wrapping_add(other.1) + ) + } + pub fn to_hex(&self) -> String { format!("{:x}{:x}", self.0, self.1) } + } impl ::std::fmt::Display for Fingerprint { diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index a835548894..8ce1b39d93 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -33,9 +33,9 @@ use rustc_data_structures::accumulate_vec::AccumulateVec; /// enough information to transform DefIds and HirIds into stable DefPaths (i.e. /// a reference to the TyCtxt) and it holds a few caches for speeding up various /// things (e.g. each DefId/DefPath is only hashed once). -pub struct StableHashingContext<'a, 'tcx: 'a> { - tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, - codemap: CachingCodemapView<'tcx>, +pub struct StableHashingContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + tcx: ty::TyCtxt<'a, 'gcx, 'tcx>, + codemap: CachingCodemapView<'gcx>, hash_spans: bool, hash_bodies: bool, overflow_checks_enabled: bool, @@ -51,9 +51,9 @@ pub enum NodeIdHashingMode { HashTraitsInScope, } -impl<'a, 'tcx: 'a> StableHashingContext<'a, 'tcx> { +impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> { - pub fn new(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> Self { + pub fn new(tcx: ty::TyCtxt<'a, 'gcx, 'tcx>) -> Self { let hash_spans_initial = tcx.sess.opts.debuginfo != NoDebugInfo; let check_overflow_initial = tcx.sess.overflow_checks(); @@ -65,13 +65,13 @@ impl<'a, 'tcx: 'a> StableHashingContext<'a, 'tcx> { ignored_attr_names.sort(); StableHashingContext { - tcx: tcx, + tcx, codemap: CachingCodemapView::new(tcx), hash_spans: hash_spans_initial, hash_bodies: true, overflow_checks_enabled: check_overflow_initial, node_id_hashing_mode: NodeIdHashingMode::HashDefPath, - ignored_attr_names: ignored_attr_names, + ignored_attr_names, } } @@ -111,7 +111,7 @@ impl<'a, 'tcx: 'a> StableHashingContext<'a, 'tcx> { } #[inline] - pub fn tcx(&self) -> ty::TyCtxt<'a, 'tcx, 'tcx> { + pub fn tcx(&self) -> ty::TyCtxt<'a, 'gcx, 'tcx> { self.tcx } @@ -131,7 +131,7 @@ impl<'a, 'tcx: 'a> StableHashingContext<'a, 'tcx> { } #[inline] - pub fn codemap(&mut self) -> &mut CachingCodemapView<'tcx> { + pub fn codemap(&mut self) -> &mut CachingCodemapView<'gcx> { &mut self.codemap } @@ -195,9 +195,9 @@ impl<'a, 'tcx: 'a> StableHashingContext<'a, 'tcx> { } -impl<'a, 'tcx> HashStable> for ast::NodeId { +impl<'a, 'gcx, 'tcx> HashStable> for ast::NodeId { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { match hcx.node_id_hashing_mode { NodeIdHashingMode::Ignore => { @@ -230,7 +230,7 @@ impl<'a, 'tcx> HashStable> for ast::NodeId { } } -impl<'a, 'tcx> HashStable> for Span { +impl<'a, 'gcx, 'tcx> HashStable> for Span { // Hash a span in a stable way. We can't directly hash the span's BytePos // fields (that would be similar to hashing pointers, since those are just @@ -242,7 +242,7 @@ impl<'a, 'tcx> HashStable> for Span { // Also, hashing filenames is expensive so we avoid doing it twice when the // span starts and ends in the same file, which is almost always the case. fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { use syntax_pos::Pos; @@ -305,15 +305,16 @@ impl<'a, 'tcx> HashStable> for Span { } } -pub fn hash_stable_hashmap<'a, 'tcx, K, V, R, SK, F, W>(hcx: &mut StableHashingContext<'a, 'tcx>, - hasher: &mut StableHasher, - map: &HashMap, - extract_stable_key: F) +pub fn hash_stable_hashmap<'a, 'gcx, 'tcx, K, V, R, SK, F, W>( + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, + hasher: &mut StableHasher, + map: &HashMap, + extract_stable_key: F) where K: Eq + std_hash::Hash, - V: HashStable>, + V: HashStable>, R: std_hash::BuildHasher, - SK: HashStable> + Ord + Clone, - F: Fn(&mut StableHashingContext<'a, 'tcx>, &K) -> SK, + SK: HashStable> + Ord + Clone, + F: Fn(&mut StableHashingContext<'a, 'gcx, 'tcx>, &K) -> SK, W: StableHasherResult, { let mut keys: Vec<_> = map.keys() @@ -327,14 +328,15 @@ pub fn hash_stable_hashmap<'a, 'tcx, K, V, R, SK, F, W>(hcx: &mut StableHashingC } } -pub fn hash_stable_hashset<'a, 'tcx, K, R, SK, F, W>(hcx: &mut StableHashingContext<'a, 'tcx>, - hasher: &mut StableHasher, - set: &HashSet, - extract_stable_key: F) +pub fn hash_stable_hashset<'a, 'tcx, 'gcx, K, R, SK, F, W>( + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, + hasher: &mut StableHasher, + set: &HashSet, + extract_stable_key: F) where K: Eq + std_hash::Hash, R: std_hash::BuildHasher, - SK: HashStable> + Ord + Clone, - F: Fn(&mut StableHashingContext<'a, 'tcx>, &K) -> SK, + SK: HashStable> + Ord + Clone, + F: Fn(&mut StableHashingContext<'a, 'gcx, 'tcx>, &K) -> SK, W: StableHasherResult, { let mut keys: Vec<_> = set.iter() @@ -344,10 +346,11 @@ pub fn hash_stable_hashset<'a, 'tcx, K, R, SK, F, W>(hcx: &mut StableHashingCont keys.hash_stable(hcx, hasher); } -pub fn hash_stable_nodemap<'a, 'tcx, V, W>(hcx: &mut StableHashingContext<'a, 'tcx>, - hasher: &mut StableHasher, - map: &NodeMap) - where V: HashStable>, +pub fn hash_stable_nodemap<'a, 'tcx, 'gcx, V, W>( + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, + hasher: &mut StableHasher, + map: &NodeMap) + where V: HashStable>, W: StableHasherResult, { hash_stable_hashmap(hcx, hasher, map, |hcx, node_id| { @@ -356,14 +359,15 @@ pub fn hash_stable_nodemap<'a, 'tcx, V, W>(hcx: &mut StableHashingContext<'a, 't } -pub fn hash_stable_btreemap<'a, 'tcx, K, V, SK, F, W>(hcx: &mut StableHashingContext<'a, 'tcx>, - hasher: &mut StableHasher, - map: &BTreeMap, - extract_stable_key: F) +pub fn hash_stable_btreemap<'a, 'tcx, 'gcx, K, V, SK, F, W>( + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, + hasher: &mut StableHasher, + map: &BTreeMap, + extract_stable_key: F) where K: Eq + Ord, - V: HashStable>, - SK: HashStable> + Ord + Clone, - F: Fn(&mut StableHashingContext<'a, 'tcx>, &K) -> SK, + V: HashStable>, + SK: HashStable> + Ord + Clone, + F: Fn(&mut StableHashingContext<'a, 'gcx, 'tcx>, &K) -> SK, W: StableHasherResult, { let mut keys: Vec<_> = map.keys() diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index c582cac67e..7805029a67 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -12,7 +12,7 @@ //! types in no particular order. use hir; -use hir::def_id::DefId; +use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX}; use ich::{StableHashingContext, NodeIdHashingMode}; use std::mem; @@ -21,20 +21,20 @@ use syntax::ast; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; -impl<'a, 'tcx> HashStable> for DefId { +impl<'a, 'gcx, 'tcx> HashStable> for DefId { #[inline] fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { hcx.def_path_hash(*self).hash_stable(hcx, hasher); } } -impl<'a, 'tcx> HashStable> for hir::HirId { +impl<'a, 'gcx, 'tcx> HashStable> for hir::HirId { #[inline] fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let hir::HirId { owner, @@ -46,6 +46,19 @@ impl<'a, 'tcx> HashStable> for hir::HirId { } } + +impl<'a, 'gcx, 'tcx> HashStable> for CrateNum { + #[inline] + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, + hasher: &mut StableHasher) { + hcx.def_path_hash(DefId { + krate: *self, + index: CRATE_DEF_INDEX + }).hash_stable(hcx, hasher); + } +} + impl_stable_hash_for!(tuple_struct hir::ItemLocalId { index }); // The following implementations of HashStable for ItemId, TraitItemId, and @@ -55,9 +68,9 @@ impl_stable_hash_for!(tuple_struct hir::ItemLocalId { index }); // want to pick up on a reference changing its target, so we hash the NodeIds // in "DefPath Mode". -impl<'a, 'tcx> HashStable> for hir::ItemId { +impl<'a, 'gcx, 'tcx> HashStable> for hir::ItemId { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let hir::ItemId { id @@ -69,9 +82,9 @@ impl<'a, 'tcx> HashStable> for hir::ItemId { } } -impl<'a, 'tcx> HashStable> for hir::TraitItemId { +impl<'a, 'gcx, 'tcx> HashStable> for hir::TraitItemId { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let hir::TraitItemId { node_id @@ -83,9 +96,9 @@ impl<'a, 'tcx> HashStable> for hir::TraitItemId { } } -impl<'a, 'tcx> HashStable> for hir::ImplItemId { +impl<'a, 'gcx, 'tcx> HashStable> for hir::ImplItemId { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let hir::ImplItemId { node_id @@ -215,9 +228,9 @@ impl_stable_hash_for!(struct hir::TypeBinding { span }); -impl<'a, 'tcx> HashStable> for hir::Ty { +impl<'a, 'gcx, 'tcx> HashStable> for hir::Ty { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let node_id_hashing_mode = match self.node { hir::TySlice(..) | @@ -299,9 +312,9 @@ impl_stable_hash_for!(enum hir::FunctionRetTy { Return(t) }); -impl<'a, 'tcx> HashStable> for hir::TraitRef { +impl<'a, 'gcx, 'tcx> HashStable> for hir::TraitRef { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let hir::TraitRef { ref path, @@ -338,9 +351,9 @@ impl_stable_hash_for!(struct hir::MacroDef { }); -impl<'a, 'tcx> HashStable> for hir::Block { +impl<'a, 'gcx, 'tcx> HashStable> for hir::Block { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let hir::Block { ref stmts, @@ -386,9 +399,9 @@ impl<'a, 'tcx> HashStable> for hir::Block { } } -impl<'a, 'tcx> HashStable> for hir::Pat { +impl<'a, 'gcx, 'tcx> HashStable> for hir::Pat { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let node_id_hashing_mode = match self.node { hir::PatKind::Wild | @@ -529,9 +542,9 @@ impl_stable_hash_for!(enum hir::UnsafeSource { UserProvided }); -impl<'a, 'tcx> HashStable> for hir::Expr { +impl<'a, 'gcx, 'tcx> HashStable> for hir::Expr { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { hcx.while_hashing_hir_bodies(true, |hcx| { let hir::Expr { @@ -613,7 +626,7 @@ impl_stable_hash_for!(enum hir::Expr_ { ExprBox(sub), ExprArray(subs), ExprCall(callee, args), - ExprMethodCall(name, ts, args), + ExprMethodCall(segment, span, args), ExprTup(fields), ExprBinary(op, lhs, rhs), ExprUnary(op, operand), @@ -652,9 +665,9 @@ impl_stable_hash_for!(enum hir::LoopSource { ForLoop }); -impl<'a, 'tcx> HashStable> for hir::MatchSource { +impl<'a, 'gcx, 'tcx> HashStable> for hir::MatchSource { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { use hir::MatchSource; @@ -703,9 +716,9 @@ impl_stable_hash_for!(enum hir::ScopeTarget { Loop(loop_id_result) }); -impl<'a, 'tcx> HashStable> for ast::Ident { +impl<'a, 'gcx, 'tcx> HashStable> for ast::Ident { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let ast::Ident { ref name, @@ -716,9 +729,9 @@ impl<'a, 'tcx> HashStable> for ast::Ident { } } -impl<'a, 'tcx> HashStable> for hir::TraitItem { +impl<'a, 'gcx, 'tcx> HashStable> for hir::TraitItem { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let hir::TraitItem { id, @@ -749,9 +762,9 @@ impl_stable_hash_for!(enum hir::TraitItemKind { Type(bounds, rhs) }); -impl<'a, 'tcx> HashStable> for hir::ImplItem { +impl<'a, 'gcx, 'tcx> HashStable> for hir::ImplItem { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let hir::ImplItem { id, @@ -781,9 +794,9 @@ impl_stable_hash_for!(enum hir::ImplItemKind { Type(t) }); -impl<'a, 'tcx> HashStable> for hir::Visibility { +impl<'a, 'gcx, 'tcx> HashStable> for hir::Visibility { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -802,9 +815,9 @@ impl<'a, 'tcx> HashStable> for hir::Visibility { } } -impl<'a, 'tcx> HashStable> for hir::Defaultness { +impl<'a, 'gcx, 'tcx> HashStable> for hir::Defaultness { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -823,9 +836,9 @@ impl_stable_hash_for!(enum hir::ImplPolarity { Negative }); -impl<'a, 'tcx> HashStable> for hir::Mod { +impl<'a, 'gcx, 'tcx> HashStable> for hir::Mod { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let hir::Mod { inner, @@ -878,29 +891,32 @@ impl_stable_hash_for!(enum hir::VariantData { Unit(id) }); -impl<'a, 'tcx> HashStable> for hir::Item { +impl<'a, 'gcx, 'tcx> HashStable> for hir::Item { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { - let node_id_hashing_mode = match self.node { - hir::ItemExternCrate(..) | + let (node_id_hashing_mode, hash_spans) = match self.node { hir::ItemStatic(..) | hir::ItemConst(..) | - hir::ItemFn(..) | - hir::ItemMod(..) | + hir::ItemFn(..) => { + (NodeIdHashingMode::Ignore, hcx.hash_spans()) + } + hir::ItemUse(..) => { + (NodeIdHashingMode::HashTraitsInScope, false) + } + + hir::ItemExternCrate(..) | hir::ItemForeignMod(..) | hir::ItemGlobalAsm(..) | + hir::ItemMod(..) | + hir::ItemDefaultImpl(..) | + hir::ItemTrait(..) | + hir::ItemImpl(..) | hir::ItemTy(..) | hir::ItemEnum(..) | hir::ItemStruct(..) | - hir::ItemUnion(..) | - hir::ItemTrait(..) | - hir::ItemDefaultImpl(..) | - hir::ItemImpl(..) => { - NodeIdHashingMode::Ignore - } - hir::ItemUse(..) => { - NodeIdHashingMode::HashTraitsInScope + hir::ItemUnion(..) => { + (NodeIdHashingMode::Ignore, false) } }; @@ -914,14 +930,16 @@ impl<'a, 'tcx> HashStable> for hir::Item { } = *self; hcx.hash_hir_item_like(attrs, |hcx| { - hcx.with_node_id_hashing_mode(node_id_hashing_mode, |hcx| { - id.hash_stable(hcx, hasher); + hcx.while_hashing_spans(hash_spans, |hcx| { + hcx.with_node_id_hashing_mode(node_id_hashing_mode, |hcx| { + id.hash_stable(hcx, hasher); + }); + name.hash_stable(hcx, hasher); + attrs.hash_stable(hcx, hasher); + node.hash_stable(hcx, hasher); + vis.hash_stable(hcx, hasher); + span.hash_stable(hcx, hasher); }); - name.hash_stable(hcx, hasher); - attrs.hash_stable(hcx, hasher); - node.hash_stable(hcx, hasher); - vis.hash_stable(hcx, hasher); - span.hash_stable(hcx, hasher); }); } } @@ -961,9 +979,10 @@ impl_stable_hash_for!(struct hir::ImplItemRef { defaultness }); -impl<'a, 'tcx> HashStable> for hir::AssociatedItemKind { +impl<'a, 'gcx, 'tcx> HashStable> +for hir::AssociatedItemKind { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -1008,9 +1027,9 @@ impl_stable_hash_for!(struct hir::Body { value }); -impl<'a, 'tcx> HashStable> for hir::BodyId { +impl<'a, 'gcx, 'tcx> HashStable> for hir::BodyId { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { if hcx.hash_bodies() { hcx.tcx().hir.body(*self).hash_stable(hcx, hasher); @@ -1024,9 +1043,9 @@ impl_stable_hash_for!(struct hir::InlineAsmOutput { is_indirect }); -impl<'a, 'tcx> HashStable> for hir::GlobalAsm { +impl<'a, 'gcx, 'tcx> HashStable> for hir::GlobalAsm { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let hir::GlobalAsm { asm, @@ -1037,9 +1056,9 @@ impl<'a, 'tcx> HashStable> for hir::GlobalAsm { } } -impl<'a, 'tcx> HashStable> for hir::InlineAsm { +impl<'a, 'gcx, 'tcx> HashStable> for hir::InlineAsm { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let hir::InlineAsm { asm, @@ -1114,10 +1133,11 @@ impl_stable_hash_for!(enum hir::Constness { NotConst }); -impl<'a, 'tcx> HashStable> for hir::def_id::DefIndex { +impl<'a, 'gcx, 'tcx> HashStable> +for hir::def_id::DefIndex { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { DefId::local(*self).hash_stable(hcx, hasher); } @@ -1129,9 +1149,10 @@ impl_stable_hash_for!(struct hir::def::Export { span }); -impl<'a, 'tcx> HashStable> for ::middle::lang_items::LangItem { +impl<'a, 'gcx, 'tcx> HashStable> +for ::middle::lang_items::LangItem { fn hash_stable(&self, - _: &mut StableHashingContext<'a, 'tcx>, + _: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { ::std::hash::Hash::hash(self, hasher); } diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index edaeb596fe..cb017b7f88 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -32,10 +32,11 @@ impl_stable_hash_for!(struct mir::LocalDecl<'tcx> { impl_stable_hash_for!(struct mir::UpvarDecl { debug_name, by_ref }); impl_stable_hash_for!(struct mir::BasicBlockData<'tcx> { statements, terminator, is_cleanup }); -impl<'a, 'tcx> HashStable> for mir::Terminator<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> +for mir::Terminator<'tcx> { #[inline] fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let mir::Terminator { ref kind, @@ -72,59 +73,61 @@ impl<'a, 'tcx> HashStable> for mir::Terminator<'t } -impl<'a, 'tcx> HashStable> for mir::Local { +impl<'a, 'gcx, 'tcx> HashStable> for mir::Local { #[inline] fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { use rustc_data_structures::indexed_vec::Idx; self.index().hash_stable(hcx, hasher); } } -impl<'a, 'tcx> HashStable> for mir::BasicBlock { +impl<'a, 'gcx, 'tcx> HashStable> for mir::BasicBlock { #[inline] fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { use rustc_data_structures::indexed_vec::Idx; self.index().hash_stable(hcx, hasher); } } -impl<'a, 'tcx> HashStable> for mir::Field { +impl<'a, 'gcx, 'tcx> HashStable> for mir::Field { #[inline] fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { use rustc_data_structures::indexed_vec::Idx; self.index().hash_stable(hcx, hasher); } } -impl<'a, 'tcx> HashStable> for mir::VisibilityScope { +impl<'a, 'gcx, 'tcx> HashStable> +for mir::VisibilityScope { #[inline] fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { use rustc_data_structures::indexed_vec::Idx; self.index().hash_stable(hcx, hasher); } } -impl<'a, 'tcx> HashStable> for mir::Promoted { +impl<'a, 'gcx, 'tcx> HashStable> for mir::Promoted { #[inline] fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { use rustc_data_structures::indexed_vec::Idx; self.index().hash_stable(hcx, hasher); } } -impl<'a, 'tcx> HashStable> for mir::TerminatorKind<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> +for mir::TerminatorKind<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); @@ -182,9 +185,10 @@ impl<'a, 'tcx> HashStable> for mir::TerminatorKin } } -impl<'a, 'tcx> HashStable> for mir::AssertMessage<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> +for mir::AssertMessage<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); @@ -202,9 +206,10 @@ impl<'a, 'tcx> HashStable> for mir::AssertMessage impl_stable_hash_for!(struct mir::Statement<'tcx> { source_info, kind }); -impl<'a, 'tcx> HashStable> for mir::StatementKind<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> +for mir::StatementKind<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); @@ -221,6 +226,9 @@ impl<'a, 'tcx> HashStable> for mir::StatementKind mir::StatementKind::StorageDead(ref lvalue) => { lvalue.hash_stable(hcx, hasher); } + mir::StatementKind::EndRegion(ref extents) => { + extents.hash_stable(hcx, hasher); + } mir::StatementKind::Nop => {} mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => { asm.hash_stable(hcx, hasher); @@ -231,9 +239,9 @@ impl<'a, 'tcx> HashStable> for mir::StatementKind } } -impl<'a, 'tcx> HashStable> for mir::Lvalue<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> for mir::Lvalue<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -250,12 +258,13 @@ impl<'a, 'tcx> HashStable> for mir::Lvalue<'tcx> } } -impl<'a, 'tcx, B, V> HashStable> for mir::Projection<'tcx, B, V> - where B: HashStable>, - V: HashStable> +impl<'a, 'gcx, 'tcx, B, V> HashStable> +for mir::Projection<'tcx, B, V> + where B: HashStable>, + V: HashStable> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let mir::Projection { ref base, @@ -267,11 +276,12 @@ impl<'a, 'tcx, B, V> HashStable> for mir::Project } } -impl<'a, 'tcx, V> HashStable> for mir::ProjectionElem<'tcx, V> - where V: HashStable> +impl<'a, 'gcx, 'tcx, V> HashStable> +for mir::ProjectionElem<'tcx, V> + where V: HashStable> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -302,9 +312,9 @@ impl<'a, 'tcx, V> HashStable> for mir::Projection impl_stable_hash_for!(struct mir::VisibilityScopeData { span, parent_scope }); -impl<'a, 'tcx> HashStable> for mir::Operand<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> for mir::Operand<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); @@ -319,9 +329,9 @@ impl<'a, 'tcx> HashStable> for mir::Operand<'tcx> } } -impl<'a, 'tcx> HashStable> for mir::Rvalue<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> for mir::Rvalue<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); @@ -379,9 +389,10 @@ impl_stable_hash_for!(enum mir::CastKind { Unsize }); -impl<'a, 'tcx> HashStable> for mir::AggregateKind<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> +for mir::AggregateKind<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -435,9 +446,9 @@ impl_stable_hash_for!(enum mir::NullOp { impl_stable_hash_for!(struct mir::Constant<'tcx> { span, ty, literal }); -impl<'a, 'tcx> HashStable> for mir::Literal<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> for mir::Literal<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index f6ad97445e..b827284271 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -27,20 +27,21 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; use rustc_data_structures::accumulate_vec::AccumulateVec; -impl<'a, 'tcx> HashStable> for ::syntax::symbol::InternedString { +impl<'a, 'gcx, 'tcx> HashStable> +for ::syntax::symbol::InternedString { #[inline] fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let s: &str = &**self; s.hash_stable(hcx, hasher); } } -impl<'a, 'tcx> HashStable> for ast::Name { +impl<'a, 'gcx, 'tcx> HashStable> for ast::Name { #[inline] fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { self.as_str().hash_stable(hcx, hasher); } @@ -82,9 +83,10 @@ impl_stable_hash_for!(enum ::syntax::abi::Abi { impl_stable_hash_for!(struct ::syntax::attr::Deprecation { since, note }); impl_stable_hash_for!(struct ::syntax::attr::Stability { level, feature, rustc_depr }); -impl<'a, 'tcx> HashStable> for ::syntax::attr::StabilityLevel { +impl<'a, 'gcx, 'tcx> HashStable> +for ::syntax::attr::StabilityLevel { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -135,9 +137,9 @@ impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, span, ident }); impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) }); impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner }); -impl<'a, 'tcx> HashStable> for [ast::Attribute] { +impl<'a, 'gcx, 'tcx> HashStable> for [ast::Attribute] { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { // Some attributes are always ignored during hashing. let filtered: AccumulateVec<[&ast::Attribute; 8]> = self @@ -155,9 +157,9 @@ impl<'a, 'tcx> HashStable> for [ast::Attribute] { } } -impl<'a, 'tcx> HashStable> for ast::Attribute { +impl<'a, 'gcx, 'tcx> HashStable> for ast::Attribute { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { // Make sure that these have been filtered out. debug_assert!(self.name().map(|name| !hcx.is_ignored_attr(name)).unwrap_or(true)); @@ -184,9 +186,10 @@ impl<'a, 'tcx> HashStable> for ast::Attribute { } } -impl<'a, 'tcx> HashStable> for tokenstream::TokenTree { +impl<'a, 'gcx, 'tcx> HashStable> +for tokenstream::TokenTree { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -205,9 +208,10 @@ impl<'a, 'tcx> HashStable> for tokenstream::Token } } -impl<'a, 'tcx> HashStable> for tokenstream::TokenStream { +impl<'a, 'gcx, 'tcx> HashStable> +for tokenstream::TokenStream { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { for sub_tt in self.trees() { sub_tt.hash_stable(hcx, hasher); @@ -215,8 +219,8 @@ impl<'a, 'tcx> HashStable> for tokenstream::Token } } -fn hash_token<'a, 'tcx, W: StableHasherResult>(token: &token::Token, - hcx: &mut StableHashingContext<'a, 'tcx>, +fn hash_token<'a, 'gcx, 'tcx, W: StableHasherResult>(token: &token::Token, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher, error_reporting_span: Span) { mem::discriminant(token).hash_stable(hcx, hasher); @@ -279,8 +283,7 @@ fn hash_token<'a, 'tcx, W: StableHasherResult>(token: &token::Token, } token::Token::Ident(ident) | - token::Token::Lifetime(ident) | - token::Token::SubstNt(ident) => ident.name.hash_stable(hcx, hasher), + token::Token::Lifetime(ident) => ident.name.hash_stable(hcx, hasher), token::Token::Interpolated(ref non_terminal) => { // FIXME(mw): This could be implemented properly. It's just a @@ -322,9 +325,9 @@ impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind { NameValue(lit) }); -impl<'a, 'tcx> HashStable> for FileMap { +impl<'a, 'gcx, 'tcx> HashStable> for FileMap { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let FileMap { ref name, @@ -332,6 +335,8 @@ impl<'a, 'tcx> HashStable> for FileMap { crate_of_origin, // Do not hash the source as it is not encoded src: _, + src_hash, + external_src: _, start_pos, end_pos: _, ref lines, @@ -346,6 +351,8 @@ impl<'a, 'tcx> HashStable> for FileMap { index: CRATE_DEF_INDEX, }.hash_stable(hcx, hasher); + src_hash.hash_stable(hcx, hasher); + // We only hash the relative position within this filemap let lines = lines.borrow(); lines.len().hash_stable(hcx, hasher); diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index a362dc31ff..a1dd2caf78 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -19,27 +19,30 @@ use std::mem; use syntax_pos::symbol::InternedString; use ty; -impl<'a, 'tcx, T> HashStable> for &'tcx ty::Slice - where T: HashStable> { +impl<'a, 'gcx, 'tcx, T> HashStable> +for &'tcx ty::Slice + where T: HashStable> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { (&self[..]).hash_stable(hcx, hasher); } } -impl<'a, 'tcx> HashStable> for ty::subst::Kind<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> +for ty::subst::Kind<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { self.as_type().hash_stable(hcx, hasher); self.as_region().hash_stable(hcx, hasher); } } -impl<'a, 'tcx> HashStable> for ty::RegionKind { +impl<'a, 'gcx, 'tcx> HashStable> +for ty::RegionKind { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -72,9 +75,10 @@ impl<'a, 'tcx> HashStable> for ty::RegionKind { } } -impl<'a, 'tcx> HashStable> for ty::adjustment::AutoBorrow<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> +for ty::adjustment::AutoBorrow<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -89,9 +93,10 @@ impl<'a, 'tcx> HashStable> for ty::adjustment::Au } } -impl<'a, 'tcx> HashStable> for ty::adjustment::Adjust<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> +for ty::adjustment::Adjust<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -122,9 +127,10 @@ impl_stable_hash_for!(enum ty::BorrowKind { MutBorrow }); -impl<'a, 'tcx> HashStable> for ty::UpvarCapture<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> +for ty::UpvarCapture<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -143,11 +149,11 @@ impl_stable_hash_for!(struct ty::FnSig<'tcx> { abi }); -impl<'a, 'tcx, T> HashStable> for ty::Binder - where T: HashStable> + ty::fold::TypeFoldable<'tcx> +impl<'a, 'gcx, 'tcx, T> HashStable> for ty::Binder + where T: HashStable> + ty::fold::TypeFoldable<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { hcx.tcx().anonymize_late_bound_regions(self).0.hash_stable(hcx, hasher); } @@ -166,12 +172,13 @@ impl_stable_hash_for!(struct ty::TraitPredicate<'tcx> { trait_ref }); impl_stable_hash_for!(tuple_struct ty::EquatePredicate<'tcx> { t1, t2 }); impl_stable_hash_for!(struct ty::SubtypePredicate<'tcx> { a_is_expected, a, b }); -impl<'a, 'tcx, A, B> HashStable> for ty::OutlivesPredicate - where A: HashStable>, - B: HashStable>, +impl<'a, 'gcx, 'tcx, A, B> HashStable> +for ty::OutlivesPredicate + where A: HashStable>, + B: HashStable>, { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let ty::OutlivesPredicate(ref a, ref b) = *self; a.hash_stable(hcx, hasher); @@ -180,12 +187,12 @@ impl<'a, 'tcx, A, B> HashStable> for ty::Outlives } impl_stable_hash_for!(struct ty::ProjectionPredicate<'tcx> { projection_ty, ty }); -impl_stable_hash_for!(struct ty::ProjectionTy<'tcx> { trait_ref, item_def_id }); +impl_stable_hash_for!(struct ty::ProjectionTy<'tcx> { substs, item_def_id }); -impl<'a, 'tcx> HashStable> for ty::Predicate<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> for ty::Predicate<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -221,9 +228,9 @@ impl<'a, 'tcx> HashStable> for ty::Predicate<'tcx } } -impl<'a, 'tcx> HashStable> for ty::AdtFlags { +impl<'a, 'gcx, 'tcx> HashStable> for ty::AdtFlags { fn hash_stable(&self, - _: &mut StableHashingContext<'a, 'tcx>, + _: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { std_hash::Hash::hash(self, hasher); } @@ -248,10 +255,10 @@ impl_stable_hash_for!(struct ty::FieldDef { vis }); -impl<'a, 'tcx> HashStable> +impl<'a, 'gcx, 'tcx> HashStable> for ::middle::const_val::ConstVal<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { use middle::const_val::ConstVal; @@ -324,9 +331,9 @@ impl_stable_hash_for!(enum ty::adjustment::CustomCoerceUnsized { Struct(index) }); -impl<'a, 'tcx> HashStable> for ty::Generics { +impl<'a, 'gcx, 'tcx> HashStable> for ty::Generics { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let ty::Generics { parent, @@ -350,9 +357,10 @@ impl<'a, 'tcx> HashStable> for ty::Generics { } } -impl<'a, 'tcx> HashStable> for ty::RegionParameterDef { +impl<'a, 'gcx, 'tcx> HashStable> +for ty::RegionParameterDef { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let ty::RegionParameterDef { name, @@ -379,12 +387,12 @@ impl_stable_hash_for!(struct ty::TypeParameterDef { }); -impl<'a, 'tcx, T> HashStable> +impl<'a, 'gcx, 'tcx, T> HashStable> for ::middle::resolve_lifetime::Set1 - where T: HashStable> + where T: HashStable> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { use middle::resolve_lifetime::Set1; @@ -427,10 +435,11 @@ impl_stable_hash_for!(enum ty::cast::CastKind { FnPtrAddrCast }); -impl<'a, 'tcx> HashStable> for ::middle::region::CodeExtent +impl<'a, 'gcx, 'tcx> HashStable> +for ::middle::region::CodeExtent { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { use middle::region::CodeExtent; @@ -472,10 +481,11 @@ impl_stable_hash_for!(enum ty::BoundRegion { BrEnv }); -impl<'a, 'tcx> HashStable> for ty::TypeVariants<'tcx> +impl<'a, 'gcx, 'tcx> HashStable> +for ty::TypeVariants<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { use ty::TypeVariants::*; @@ -514,10 +524,9 @@ impl<'a, 'tcx> HashStable> for ty::TypeVariants<' region.hash_stable(hcx, hasher); pointee_ty.hash_stable(hcx, hasher); } - TyFnDef(def_id, substs, ref sig) => { + TyFnDef(def_id, substs) => { def_id.hash_stable(hcx, hasher); substs.hash_stable(hcx, hasher); - sig.hash_stable(hcx, hasher); } TyFnPtr(ref sig) => { sig.hash_stable(hcx, hasher); @@ -563,10 +572,11 @@ impl_stable_hash_for!(struct ty::TypeAndMut<'tcx> { mutbl }); -impl<'a, 'tcx> HashStable> for ty::ExistentialPredicate<'tcx> +impl<'a, 'gcx, 'tcx> HashStable> +for ty::ExistentialPredicate<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -589,15 +599,16 @@ impl_stable_hash_for!(struct ty::ExistentialTraitRef<'tcx> { }); impl_stable_hash_for!(struct ty::ExistentialProjection<'tcx> { - trait_ref, - item_name, + item_def_id, + substs, ty }); -impl<'a, 'tcx> HashStable> for ty::TypeckTables<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> +for ty::TypeckTables<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let ty::TypeckTables { ref type_dependent_defs, @@ -650,3 +661,60 @@ impl<'a, 'tcx> HashStable> for ty::TypeckTables<' }) } } + +impl_stable_hash_for!(enum ty::fast_reject::SimplifiedType { + BoolSimplifiedType, + CharSimplifiedType, + IntSimplifiedType(int_ty), + UintSimplifiedType(int_ty), + FloatSimplifiedType(float_ty), + AdtSimplifiedType(def_id), + StrSimplifiedType, + ArraySimplifiedType, + PtrSimplifiedType, + NeverSimplifiedType, + TupleSimplifiedType(size), + TraitSimplifiedType(def_id), + ClosureSimplifiedType(def_id), + AnonSimplifiedType(def_id), + FunctionSimplifiedType(params), + ParameterSimplifiedType +}); + +impl_stable_hash_for!(struct ty::Instance<'tcx> { + def, + substs +}); + +impl<'a, 'gcx, 'tcx> HashStable> for ty::InstanceDef<'tcx> { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, + hasher: &mut StableHasher) { + mem::discriminant(self).hash_stable(hcx, hasher); + + match *self { + ty::InstanceDef::Item(def_id) => { + def_id.hash_stable(hcx, hasher); + } + ty::InstanceDef::Intrinsic(def_id) => { + def_id.hash_stable(hcx, hasher); + } + ty::InstanceDef::FnPtrShim(def_id, ty) => { + def_id.hash_stable(hcx, hasher); + ty.hash_stable(hcx, hasher); + } + ty::InstanceDef::Virtual(def_id, n) => { + def_id.hash_stable(hcx, hasher); + n.hash_stable(hcx, hasher); + } + ty::InstanceDef::ClosureOnceShim { call_once } => { + call_once.hash_stable(hcx, hasher); + } + ty::InstanceDef::DropGlue(def_id, t) => { + def_id.hash_stable(hcx, hasher); + t.hash_stable(hcx, hasher); + } + } + } +} + diff --git a/src/librustc/infer/README.md b/src/librustc/infer/README.md index 68e64b8b7b..b4075f6973 100644 --- a/src/librustc/infer/README.md +++ b/src/librustc/infer/README.md @@ -236,4 +236,4 @@ yet, that's what we're trying to find! In our code, we opt to unify We make use of a trait-like implementation strategy to consolidate duplicated code between subtypes, GLB, and LUB computations. See the -section on "Type Combining" below for details. +section on "Type Combining" in combine.rs for more details. diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index 14920b8b66..40e933b26a 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -268,7 +268,7 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> { infcx: self.infcx, span: self.trace.cause.span, for_vid_sub_root: self.infcx.type_variables.borrow_mut().sub_root_var(for_vid), - ambient_variance: ambient_variance, + ambient_variance, needs_wf: false, }; diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 0515e1cc30..95722a93be 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -75,6 +75,9 @@ use errors::{DiagnosticBuilder, DiagnosticStyledString}; mod note; +mod need_type_info; +mod named_anon_conflict; + impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn note_and_explain_region(self, err: &mut DiagnosticBuilder, @@ -254,8 +257,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - pub fn report_region_errors(&self, - errors: &Vec>) { + + pub fn report_region_errors(&self, errors: &Vec>) { debug!("report_region_errors(): {} errors to start", errors.len()); // try to pre-process the errors, which will group some of them @@ -266,21 +269,29 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { for error in errors { debug!("report_region_errors: error = {:?}", error); - match error.clone() { - ConcreteFailure(origin, sub, sup) => { - self.report_concrete_failure(origin, sub, sup).emit(); - } - - GenericBoundFailure(kind, param_ty, sub) => { - self.report_generic_bound_failure(kind, param_ty, sub); - } - SubSupConflict(var_origin, - sub_origin, sub_r, - sup_origin, sup_r) => { - self.report_sub_sup_conflict(var_origin, - sub_origin, sub_r, - sup_origin, sup_r); + if !self.try_report_named_anon_conflict(&error) { + match error.clone() { + // These errors could indicate all manner of different + // problems with many different solutions. Rather + // than generate a "one size fits all" error, what we + // attempt to do is go through a number of specific + // scenarios and try to find the best way to present + // the error. If all of these fails, we fall back to a rather + // general bit of code that displays the error information + ConcreteFailure(origin, sub, sup) => { + self.report_concrete_failure(origin, sub, sup).emit(); + } + GenericBoundFailure(kind, param_ty, sub) => { + self.report_generic_bound_failure(kind, param_ty, sub); + } + SubSupConflict(var_origin, + sub_origin, sub_r, + sup_origin, sup_r) => { + self.report_sub_sup_conflict(var_origin, + sub_origin, sub_r, + sup_origin, sup_r); + } } } } @@ -336,9 +347,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate { let exp_path = self.tcx.item_path_str(did1); let found_path = self.tcx.item_path_str(did2); + let exp_abs_path = self.tcx.absolute_item_path_str(did1); + let found_abs_path = self.tcx.absolute_item_path_str(did2); // We compare strings because DefPath can be different // for imported and non-imported crates - if exp_path == found_path { + if exp_path == found_path + || exp_abs_path == found_abs_path { let crate_name = self.tcx.sess.cstore.crate_name(did1.krate); err.span_note(sp, &format!("Perhaps two different versions \ of crate `{}` are being used?", diff --git a/src/librustc/infer/error_reporting/named_anon_conflict.rs b/src/librustc/infer/error_reporting/named_anon_conflict.rs new file mode 100644 index 0000000000..48f39ac5b3 --- /dev/null +++ b/src/librustc/infer/error_reporting/named_anon_conflict.rs @@ -0,0 +1,192 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Error Reporting for Anonymous Region Lifetime Errors. +use hir; +use infer::InferCtxt; +use ty::{self, Region}; +use infer::region_inference::RegionResolutionError::*; +use infer::region_inference::RegionResolutionError; +use hir::map as hir_map; +use hir::def_id::DefId; + +impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { + // This method walks the Type of the function body arguments using + // `fold_regions()` function and returns the + // &hir::Arg of the function argument corresponding to the anonymous + // region and the Ty corresponding to the named region. + // Currently only the case where the function declaration consists of + // one named region and one anonymous region is handled. + // Consider the example `fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32` + // Here, we would return the hir::Arg for y, we return the type &'a + // i32, which is the type of y but with the anonymous region replaced + // with 'a, the corresponding bound region and is_first which is true if + // the hir::Arg is the first argument in the function declaration. + fn find_arg_with_anonymous_region + (&self, + anon_region: Region<'tcx>, + named_region: Region<'tcx>) + -> Option<(&hir::Arg, ty::Ty<'tcx>, ty::BoundRegion, bool)> { + + match *anon_region { + ty::ReFree(ref free_region) => { + let id = free_region.scope; + let node_id = self.tcx.hir.as_local_node_id(id).unwrap(); + let body_id = self.tcx.hir.maybe_body_owned_by(node_id).unwrap(); + let body = self.tcx.hir.body(body_id); + if let Some(tables) = self.in_progress_tables { + body.arguments + .iter() + .enumerate() + .filter_map(|(index, arg)| { + let ty = tables.borrow().node_id_to_type(arg.id); + let mut found_anon_region = false; + let new_arg_ty = self.tcx + .fold_regions(&ty, &mut false, |r, _| if *r == *anon_region { + found_anon_region = true; + named_region + } else { + r + }); + if found_anon_region { + let is_first = index == 0; + Some((arg, new_arg_ty, free_region.bound_region, is_first)) + } else { + None + } + }) + .next() + } else { + None + } + } + _ => None, + } + } + + // This method generates the error message for the case when + // the function arguments consist of a named region and an anonymous + // region and corresponds to `ConcreteFailure(..)` + pub fn try_report_named_anon_conflict(&self, error: &RegionResolutionError<'tcx>) -> bool { + let (span, sub, sup) = match *error { + ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup), + _ => return false, // inapplicable + }; + + // Determine whether the sub and sup consist of one named region ('a) + // and one anonymous (elided) region. If so, find the parameter arg + // where the anonymous region appears (there must always be one; we + // only introduced anonymous regions in parameters) as well as a + // version new_ty of its type where the anonymous region is replaced + // with the named one. + let (named, (arg, new_ty, br, is_first), scope_def_id) = + if sub.is_named_region() && self.is_suitable_anonymous_region(sup).is_some() { + (sub, + self.find_arg_with_anonymous_region(sup, sub).unwrap(), + self.is_suitable_anonymous_region(sup).unwrap()) + } else if sup.is_named_region() && self.is_suitable_anonymous_region(sub).is_some() { + (sup, + self.find_arg_with_anonymous_region(sub, sup).unwrap(), + self.is_suitable_anonymous_region(sub).unwrap()) + } else { + return false; // inapplicable + }; + + // Here, we check for the case where the anonymous region + // is in the return type. + // FIXME(#42703) - Need to handle certain cases here. + let ret_ty = self.tcx.type_of(scope_def_id); + match ret_ty.sty { + ty::TyFnDef(_, _) => { + let sig = ret_ty.fn_sig(self.tcx); + let late_bound_regions = self.tcx + .collect_referenced_late_bound_regions(&sig.output()); + if late_bound_regions.iter().any(|r| *r == br) { + return false; + } + } + _ => {} + } + + // Here we check for the case where anonymous region + // corresponds to self and if yes, we display E0312. + // FIXME(#42700) - Need to format self properly to + // enable E0621 for it. + if is_first && + self.tcx + .opt_associated_item(scope_def_id) + .map(|i| i.method_has_self_argument) + .unwrap_or(false) { + return false; + } + + let (error_var, span_label_var) = if let Some(simple_name) = arg.pat.simple_name() { + (format!("the type of `{}`", simple_name), format!("the type of `{}`", simple_name)) + } else { + ("parameter type".to_owned(), "type".to_owned()) + }; + + struct_span_err!(self.tcx.sess, + span, + E0621, + "explicit lifetime required in {}", + error_var) + .span_label(arg.pat.span, + format!("consider changing {} to `{}`", span_label_var, new_ty)) + .span_label(span, format!("lifetime `{}` required", named)) + .emit(); + + return true; + } + + // This method returns whether the given Region is Anonymous + // and returns the DefId corresponding to the region. + pub fn is_suitable_anonymous_region(&self, region: Region<'tcx>) -> Option { + match *region { + ty::ReFree(ref free_region) => { + match free_region.bound_region { + ty::BrAnon(..) => { + let anonymous_region_binding_scope = free_region.scope; + let node_id = self.tcx + .hir + .as_local_node_id(anonymous_region_binding_scope) + .unwrap(); + match self.tcx.hir.find(node_id) { + Some(hir_map::NodeItem(..)) | + Some(hir_map::NodeTraitItem(..)) => { + // proceed ahead // + } + Some(hir_map::NodeImplItem(..)) => { + let container_id = self.tcx + .associated_item(anonymous_region_binding_scope) + .container + .id(); + if self.tcx.impl_trait_ref(container_id).is_some() { + // For now, we do not try to target impls of traits. This is + // because this message is going to suggest that the user + // change the fn signature, but they may not be free to do so, + // since the signature must match the trait. + // + // FIXME(#42706) -- in some cases, we could do better here. + return None; + } + } + _ => return None, // inapplicable + // we target only top-level functions + } + return Some(anonymous_region_binding_scope); + } + _ => None, + } + } + _ => None, + } + } +} diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs new file mode 100644 index 0000000000..a684881c09 --- /dev/null +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -0,0 +1,151 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use hir::{self, Local, Pat, Body}; +use hir::intravisit::{self, Visitor, NestedVisitorMap}; +use infer::InferCtxt; +use infer::type_variable::TypeVariableOrigin; +use ty::{self, Ty, TyInfer, TyVar}; + +use syntax::ast::NodeId; +use syntax_pos::Span; + +struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + target_ty: &'a Ty<'tcx>, + hir_map: &'a hir::map::Map<'gcx>, + found_local_pattern: Option<&'gcx Pat>, + found_arg_pattern: Option<&'gcx Pat>, +} + +impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { + fn node_matches_type(&mut self, node_id: NodeId) -> bool { + let ty_opt = self.infcx.in_progress_tables.and_then(|tables| { + tables.borrow().node_id_to_type_opt(node_id) + }); + match ty_opt { + Some(ty) => { + let ty = self.infcx.resolve_type_vars_if_possible(&ty); + ty.walk().any(|inner_ty| { + inner_ty == *self.target_ty || match (&inner_ty.sty, &self.target_ty.sty) { + (&TyInfer(TyVar(a_vid)), &TyInfer(TyVar(b_vid))) => { + self.infcx + .type_variables + .borrow_mut() + .sub_unified(a_vid, b_vid) + } + _ => false, + } + }) + } + None => false, + } + } +} + +impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { + NestedVisitorMap::OnlyBodies(&self.hir_map) + } + + fn visit_local(&mut self, local: &'gcx Local) { + if self.found_local_pattern.is_none() && self.node_matches_type(local.id) { + self.found_local_pattern = Some(&*local.pat); + } + intravisit::walk_local(self, local); + } + + fn visit_body(&mut self, body: &'gcx Body) { + for argument in &body.arguments { + if self.found_arg_pattern.is_none() && self.node_matches_type(argument.id) { + self.found_arg_pattern = Some(&*argument.pat); + } + } + intravisit::walk_body(self, body); + } +} + + +impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { + fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String { + if let ty::TyInfer(ty::TyVar(ty_vid)) = (*ty).sty { + let ty_vars = self.type_variables.borrow(); + if let TypeVariableOrigin::TypeParameterDefinition(_, name) = + *ty_vars.var_origin(ty_vid) { + name.to_string() + } else { + ty.to_string() + } + } else { + ty.to_string() + } + } + + pub fn need_type_info(&self, body_id: Option, span: Span, ty: Ty<'tcx>) { + let ty = self.resolve_type_vars_if_possible(&ty); + let name = self.extract_type_name(&ty); + + let mut err_span = span; + let mut labels = vec![(span, format!("cannot infer type for `{}`", name))]; + + let mut local_visitor = FindLocalByTypeVisitor { + infcx: &self, + target_ty: &ty, + hir_map: &self.tcx.hir, + found_local_pattern: None, + found_arg_pattern: None, + }; + + if let Some(body_id) = body_id { + let expr = self.tcx.hir.expect_expr(body_id.node_id); + local_visitor.visit_expr(expr); + } + + if let Some(pattern) = local_visitor.found_arg_pattern { + err_span = pattern.span; + // We don't want to show the default label for closures. + // + // So, before clearing, the output would look something like this: + // ``` + // let x = |_| { }; + // - ^^^^ cannot infer type for `[_; 0]` + // | + // consider giving this closure parameter a type + // ``` + // + // After clearing, it looks something like this: + // ``` + // let x = |_| { }; + // ^ consider giving this closure parameter a type + // ``` + labels.clear(); + labels.push((pattern.span, format!("consider giving this closure parameter a type"))); + } + + if let Some(pattern) = local_visitor.found_local_pattern { + if let Some(simple_name) = pattern.simple_name() { + labels.push((pattern.span, format!("consider giving `{}` a type", simple_name))); + } else { + labels.push((pattern.span, format!("consider giving the pattern a type"))); + } + } + + let mut err = struct_span_err!(self.tcx.sess, + err_span, + E0282, + "type annotations needed"); + + for (target_span, label_message) in labels { + err.span_label(target_span, label_message); + } + + err.emit(); + } +} diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index a0ef1f65f5..41858088f7 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -48,7 +48,7 @@ impl<'a, 'gcx, 'tcx> TypeFreshener<'a, 'gcx, 'tcx> { pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> TypeFreshener<'a, 'gcx, 'tcx> { TypeFreshener { - infcx: infcx, + infcx, freshen_count: 0, freshen_map: FxHashMap(), } diff --git a/src/librustc/infer/fudge.rs b/src/librustc/infer/fudge.rs index a8bc33f772..9cad6ce6f9 100644 --- a/src/librustc/infer/fudge.rs +++ b/src/librustc/infer/fudge.rs @@ -102,7 +102,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { infcx: self, type_variables: &type_variables, region_vars: ®ion_vars, - origin: origin + origin, }; Ok(value.fold_with(&mut fudger)) diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index dbbcc6cfbe..541a997834 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -218,7 +218,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { Ok(HrMatchResult { value: a_value, - unconstrained_regions: unconstrained_regions, + unconstrained_regions, }) }); } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index f5869b8a20..7154ce9e38 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -19,11 +19,8 @@ pub use self::freshen::TypeFreshener; pub use self::region_inference::{GenericKind, VerifyBound}; use hir::def_id::DefId; -use hir; use middle::free_region::{FreeRegionMap, RegionRelations}; use middle::region::RegionMaps; -use middle::mem_categorization as mc; -use middle::mem_categorization::McResult; use middle::lang_items; use mir::tcx::LvalueTy; use ty::subst::{Kind, Subst, Substs}; @@ -34,13 +31,12 @@ use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use ty::relate::RelateResult; use traits::{self, ObligationCause, PredicateObligations, Reveal}; use rustc_data_structures::unify::{self, UnificationTable}; -use std::cell::{Cell, RefCell, Ref, RefMut}; +use std::cell::{Cell, RefCell, Ref}; 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}; +use util::nodemap::FxHashMap; use arena::DroplessArena; use self::combine::CombineFields; @@ -76,71 +72,14 @@ pub type Bound = Option; pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result" pub type FixupResult = Result; // "fixup result" -/// 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> { - 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) -> 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::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::TypeckTables<'tcx>> { - match self { - InferTables::Interned(_) => { - bug!("InferTables: infcx.tables.borrow_mut() outside of type-checking"); - } - InferTables::InProgress(tables) => tables.borrow_mut(), - InferTables::Missing => { - bug!("InferTables: infcx.tables.borrow_mut() with no tables") - } - } - } -} - pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'gcx, 'tcx>, - pub tables: InferTables<'a, 'gcx, 'tcx>, + /// During type-checking/inference of a body, `in_progress_tables` + /// contains a reference to the tables being built up, which are + /// used for reading closure kinds/signatures as they are inferred, + /// and for error reporting logic to read arbitrary node types. + pub in_progress_tables: Option<&'a RefCell>>, // Cache for projections. This cache is snapshotted along with the // infcx. @@ -171,7 +110,7 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { // the set of predicates on which errors have been reported, to // avoid reporting the same error twice. - pub reported_trait_errors: RefCell>>, + pub reported_trait_errors: RefCell>>>, // When an error occurs, we want to avoid reporting "derived" // errors that are due to this original failure. Normally, we @@ -335,7 +274,7 @@ pub enum LateBoundRegionConversionTime { HigherRankedType, /// when projecting an associated type - AssocTypeProjection(ast::Name), + AssocTypeProjection(ast::Name), // FIXME(tschottdorf): should contain DefId, not Name } /// Reasons to create a region inference variable @@ -396,91 +335,34 @@ 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>); -} - -impl<'a, 'tcx> InferEnv<'a, 'tcx> for () { - fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>) - -> (Option<&'a ty::TypeckTables<'tcx>>, - Option>) { - (None, None) - } -} - -impl<'a, 'tcx> InferEnv<'a, 'tcx> for &'a ty::TypeckTables<'tcx> { - fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>) - -> (Option<&'a ty::TypeckTables<'tcx>>, - Option>) { - (Some(self), None) - } -} - -impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::TypeckTables<'tcx> { - fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>) - -> (Option<&'a ty::TypeckTables<'tcx>>, - Option>) { - (None, Some(self)) - } -} - -impl<'a, 'tcx> InferEnv<'a, 'tcx> for hir::BodyId { - fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> (Option<&'a ty::TypeckTables<'tcx>>, - Option>) { - let def_id = tcx.hir.body_owner_def_id(self); - (Some(tcx.typeck_tables_of(def_id)), None) - } -} - -/// Helper type of a temporary returned by tcx.infer_ctxt(...). +/// 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>, arena: DroplessArena, fresh_tables: Option>>, - tables: Option<&'a ty::TypeckTables<'gcx>>, } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { - pub fn infer_ctxt>(self, env: E) -> InferCtxtBuilder<'a, 'gcx, 'tcx> { - let (tables, fresh_tables) = env.to_parts(self); + pub fn infer_ctxt(self) -> InferCtxtBuilder<'a, 'gcx, 'tcx> { InferCtxtBuilder { global_tcx: self, arena: DroplessArena::new(), - fresh_tables: fresh_tables.map(RefCell::new), - tables: tables, - } - } + fresh_tables: None, - /// 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, body: hir::BodyId) - -> InferCtxt<'a, 'gcx, 'gcx> { - let (tables, _) = body.to_parts(self); - InferCtxt { - tcx: self, - 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), - selection_cache: traits::SelectionCache::new(), - evaluation_cache: traits::EvaluationCache::new(), - projection_cache: RefCell::new(traits::ProjectionCache::new()), - reported_trait_errors: RefCell::new(FxHashSet()), - tainted_by_errors_flag: Cell::new(false), - err_count_on_creation: self.sess.err_count(), - in_snapshot: Cell::new(false), } } } impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { + /// Used only by `rustc_typeck` during body type-checking/inference, + /// will initialize `in_progress_tables` with fresh `TypeckTables`. + pub fn with_fresh_in_progress_tables(mut self) -> Self { + self.fresh_tables = Some(RefCell::new(ty::TypeckTables::empty())); + self + } + pub fn enter(&'tcx mut self, f: F) -> R where F: for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R { @@ -488,14 +370,11 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { global_tcx, ref arena, ref fresh_tables, - tables, } = *self; - let tables = tables.map(InferTables::Interned).unwrap_or_else(|| { - fresh_tables.as_ref().map_or(InferTables::Missing, InferTables::InProgress) - }); + let in_progress_tables = fresh_tables.as_ref(); global_tcx.enter_local(arena, |tcx| f(InferCtxt { - tcx: tcx, - tables: tables, + tcx, + in_progress_tables, projection_cache: RefCell::new(traits::ProjectionCache::new()), type_variables: RefCell::new(type_variable::TypeVariableTable::new()), int_unification_table: RefCell::new(UnificationTable::new()), @@ -503,7 +382,7 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { region_vars: RegionVarBindings::new(tcx), selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), - reported_trait_errors: RefCell::new(FxHashSet()), + reported_trait_errors: RefCell::new(FxHashMap()), tainted_by_errors_flag: Cell::new(false), err_count_on_creation: tcx.sess.err_count(), in_snapshot: Cell::new(false), @@ -580,9 +459,9 @@ impl<'gcx> TransNormalize<'gcx> for LvalueTy<'gcx> { LvalueTy::Ty { ty } => LvalueTy::Ty { ty: ty.trans_normalize(infcx, param_env) }, LvalueTy::Downcast { adt_def, substs, variant_index } => { LvalueTy::Downcast { - adt_def: adt_def, + adt_def, substs: substs.trans_normalize(infcx, param_env), - variant_index: variant_index + variant_index, } } } @@ -618,7 +497,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { return value; } - self.infer_ctxt(()).enter(|infcx| { + self.infer_ctxt().enter(|infcx| { value.trans_normalize(&infcx, param_env) }) } @@ -640,7 +519,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { return value; } - self.infer_ctxt(()).enter(|infcx| { + self.infer_ctxt().enter(|infcx| { value.trans_normalize(&infcx, env.reveal_all()) }) } @@ -796,7 +675,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { -> CombineFields<'a, 'gcx, 'tcx> { CombineFields { infcx: self, - trace: trace, + trace, cause: None, param_env, obligations: PredicateObligations::new(), @@ -844,10 +723,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { was_in_snapshot: in_snapshot, // Borrow tables "in progress" (i.e. during typeck) // to ban writes from within a snapshot to them. - _in_progress_tables: match self.tables { - InferTables::InProgress(ref tables) => tables.try_borrow().ok(), - _ => None - } + _in_progress_tables: self.in_progress_tables.map(|tables| { + tables.borrow() + }) } } @@ -1190,28 +1068,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.tainted_by_errors_flag.set(true) } - pub fn node_type(&self, id: ast::NodeId) -> Ty<'tcx> { - match self.tables.borrow().node_types.get(&id) { - Some(&t) => t, - // FIXME - None if self.is_tainted_by_errors() => - self.tcx.types.err, - None => { - bug!("no type for node {}: {} in fcx", - id, self.tcx.hir.node_to_string(id)); - } - } - } - - pub fn expr_ty(&self, ex: &hir::Expr) -> Ty<'tcx> { - match self.tables.borrow().node_types.get(&ex.id) { - Some(&t) => t, - None => { - bug!("no type for expr in fcx"); - } - } - } - pub fn resolve_regions_and_report_errors(&self, region_context: DefId, region_map: &RegionMaps, @@ -1221,6 +1077,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { region_map, free_regions); let errors = self.region_vars.resolve_regions(®ion_rels); + if !self.is_tainted_by_errors() { // As a heuristic, just skip reporting region errors // altogether if other errors have been reported while @@ -1310,21 +1167,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { value.fold_with(&mut r) } - /// Resolves all type variables in `t` and then, if any were left - /// unresolved, substitutes an error type. This is used after the - /// main checking when doing a second pass before writeback. The - /// justification is that writeback will produce an error for - /// these unconstrained type variables. - fn resolve_type_vars_or_error(&self, t: &Ty<'tcx>) -> mc::McResult> { - let ty = self.resolve_type_vars_if_possible(t); - if ty.references_error() || ty.is_ty_var() { - debug!("resolve_type_vars_or_error: error from {:?}", ty); - Err(()) - } else { - Ok(ty) - } - } - pub fn fully_resolve>(&self, value: &T) -> FixupResult { /*! * Attempts to resolve all type/region variables in @@ -1350,28 +1192,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // types using one of these methods, and should not call span_err directly for such // errors. - pub fn type_error_message(&self, - sp: Span, - mk_msg: M, - actual_ty: Ty<'tcx>) - where M: FnOnce(String) -> String, - { - self.type_error_struct(sp, mk_msg, actual_ty).emit(); - } - - // FIXME: this results in errors without an error code. Deprecate? - pub fn type_error_struct(&self, - sp: Span, - mk_msg: M, - actual_ty: Ty<'tcx>) - -> DiagnosticBuilder<'tcx> - where M: FnOnce(String) -> String, - { - self.type_error_struct_with_diag(sp, |actual_ty| { - self.tcx.sess.struct_span_err(sp, &mk_msg(actual_ty)) - }, actual_ty) - } - pub fn type_error_struct_with_diag(&self, sp: Span, mk_diag: M, @@ -1416,7 +1236,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.report_and_explain_type_error( trace, &TypeError::TyParamDefaultMismatch(ExpectedFound { - expected: expected, + expected, found: actual })) .emit(); @@ -1457,14 +1277,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { match_b: ty::TraitRef<'tcx>) -> InferResult<'tcx, HrMatchResult>> { + let match_pair = match_a.map_bound(|p| (p.projection_ty.trait_ref(self.tcx), p.ty)); let span = cause.span; - let match_trait_ref = match_a.skip_binder().projection_ty.trait_ref; let trace = TypeTrace { - cause: cause, - values: TraitRefs(ExpectedFound::new(true, match_trait_ref, match_b)) + cause, + values: TraitRefs(ExpectedFound::new(true, match_pair.skip_binder().0, match_b)) }; - let match_pair = match_a.map_bound(|p| (p.projection_ty.trait_ref, p.ty)); let mut combine = self.combine_fields(trace, param_env); let result = combine.higher_ranked_match(span, &match_pair, &match_b, true)?; Ok(InferOk { value: result, obligations: combine.obligations }) @@ -1484,30 +1303,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.region_vars.verify_generic_bound(origin, kind, a, bound); } - pub fn node_ty(&self, id: ast::NodeId) -> McResult> { - let ty = self.node_type(id); - self.resolve_type_vars_or_error(&ty) - } - - pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult> { - let ty = self.tables.borrow().expr_ty_adjusted(expr); - self.resolve_type_vars_or_error(&ty) - } - pub fn type_moves_by_default(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>, span: Span) -> bool { let ty = self.resolve_type_vars_if_possible(&ty); - if let Some((param_env, ty)) = self.tcx.lift_to_global(&(param_env, ty)) { - // 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::InProgress(_) => ty.has_closure_types(), - _ => false - }; - if !local_closures { + // Even if the type may have no inference variables, during + // type-checking closure types are in local tables only. + if !self.in_progress_tables.is_some() || !ty.has_closure_types() { + if let Some((param_env, ty)) = self.tcx.lift_to_global(&(param_env, ty)) { return ty.moves_by_default(self.tcx.global_tcx(), param_env, span); } } @@ -1521,15 +1326,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { !traits::type_known_to_meet_bound(self, param_env, ty, copy_def_id, span) } - pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option> { - self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned() - } - pub fn closure_kind(&self, def_id: DefId) -> Option { - if let InferTables::InProgress(tables) = self.tables { + if let Some(tables) = self.in_progress_tables { if let Some(id) = self.tcx.hir.as_local_node_id(def_id) { return tables.borrow() .closure_kinds @@ -1546,8 +1347,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { Some(self.tcx.closure_kind(def_id)) } - pub fn closure_type(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> { - if let InferTables::InProgress(tables) = self.tables { + /// Obtain the signature of a function or closure. + /// For closures, unlike `tcx.fn_sig(def_id)`, this method will + /// work during the type-checking of the enclosing function and + /// return the closure signature in its partially inferred state. + pub fn fn_sig(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> { + if let Some(tables) = self.in_progress_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; @@ -1555,7 +1360,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } - self.tcx.closure_type(def_id) + self.tcx.fn_sig(def_id) } } @@ -1638,10 +1443,10 @@ impl<'tcx> SubregionOrigin<'tcx> { lint_id } => SubregionOrigin::CompareImplMethodObligation { span: cause.span, - item_name: item_name, - impl_item_def_id: impl_item_def_id, - trait_item_def_id: trait_item_def_id, - lint_id: lint_id, + item_name, + impl_item_def_id, + trait_item_def_id, + lint_id, }, _ => default(), diff --git a/src/librustc/infer/region_inference/graphviz.rs b/src/librustc/infer/region_inference/graphviz.rs index cce253c1a1..81a8984e75 100644 --- a/src/librustc/infer/region_inference/graphviz.rs +++ b/src/librustc/infer/region_inference/graphviz.rs @@ -133,7 +133,6 @@ enum Node { Region(ty::RegionKind), } -// type Edge = Constraint; #[derive(Clone, PartialEq, Eq, Debug, Copy)] enum Edge<'tcx> { Constraint(Constraint<'tcx>), diff --git a/src/librustc/infer/region_inference/mod.rs b/src/librustc/infer/region_inference/mod.rs index c1adba5d84..57f2f748b2 100644 --- a/src/librustc/infer/region_inference/mod.rs +++ b/src/librustc/infer/region_inference/mod.rs @@ -35,31 +35,31 @@ use std::u32; mod graphviz; -// A constraint that influences the inference process. +/// A constraint that influences the inference process. #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] pub enum Constraint<'tcx> { - // One region variable is subregion of another + /// One region variable is subregion of another ConstrainVarSubVar(RegionVid, RegionVid), - // Concrete region is subregion of region variable + /// Concrete region is subregion of region variable ConstrainRegSubVar(Region<'tcx>, RegionVid), - // Region variable is subregion of concrete region. This does not - // directly affect inference, but instead is checked after - // inference is complete. + /// Region variable is subregion of concrete region. This does not + /// directly affect inference, but instead is checked after + /// inference is complete. ConstrainVarSubReg(RegionVid, Region<'tcx>), - // A constraint where neither side is a variable. This does not - // directly affect inference, but instead is checked after - // inference is complete. + /// A constraint where neither side is a variable. This does not + /// directly affect inference, but instead is checked after + /// inference is complete. ConstrainRegSubReg(Region<'tcx>, Region<'tcx>), } -// VerifyGenericBound(T, _, R, RS): The parameter type `T` (or -// associated type) must outlive the region `R`. `T` is known to -// outlive `RS`. Therefore verify that `R <= RS[i]` for some -// `i`. Inference variables may be involved (but this verification -// step doesn't influence inference). +/// VerifyGenericBound(T, _, R, RS): The parameter type `T` (or +/// associated type) must outlive the region `R`. `T` is known to +/// outlive `RS`. Therefore verify that `R <= RS[i]` for some +/// `i`. Inference variables may be involved (but this verification +/// step doesn't influence inference). #[derive(Debug)] pub struct Verify<'tcx> { kind: GenericKind<'tcx>, @@ -74,29 +74,29 @@ pub enum GenericKind<'tcx> { Projection(ty::ProjectionTy<'tcx>), } -// When we introduce a verification step, we wish to test that a -// particular region (let's call it `'min`) meets some bound. -// The bound is described the by the following grammar: +/// When we introduce a verification step, we wish to test that a +/// particular region (let's call it `'min`) meets some bound. +/// The bound is described the by the following grammar: #[derive(Debug)] pub enum VerifyBound<'tcx> { - // B = exists {R} --> some 'r in {R} must outlive 'min - // - // Put another way, the subject value is known to outlive all - // regions in {R}, so if any of those outlives 'min, then the - // bound is met. + /// B = exists {R} --> some 'r in {R} must outlive 'min + /// + /// Put another way, the subject value is known to outlive all + /// regions in {R}, so if any of those outlives 'min, then the + /// bound is met. AnyRegion(Vec>), - // B = forall {R} --> all 'r in {R} must outlive 'min - // - // Put another way, the subject value is known to outlive some - // region in {R}, so if all of those outlives 'min, then the bound - // is met. + /// B = forall {R} --> all 'r in {R} must outlive 'min + /// + /// Put another way, the subject value is known to outlive some + /// region in {R}, so if all of those outlives 'min, then the bound + /// is met. AllRegions(Vec>), - // B = exists {B} --> 'min must meet some bound b in {B} + /// B = exists {B} --> 'min must meet some bound b in {B} AnyBound(Vec>), - // B = forall {B} --> 'min must meet all bounds b in {B} + /// B = forall {B} --> 'min must meet all bounds b in {B} AllBounds(Vec>), } @@ -183,35 +183,35 @@ pub struct RegionVarBindings<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, var_origins: RefCell>, - // Constraints of the form `A <= B` introduced by the region - // checker. Here at least one of `A` and `B` must be a region - // variable. + /// Constraints of the form `A <= B` introduced by the region + /// checker. Here at least one of `A` and `B` must be a region + /// variable. constraints: RefCell, SubregionOrigin<'tcx>>>, - // A "verify" is something that we need to verify after inference is - // done, but which does not directly affect inference in any way. - // - // An example is a `A <= B` where neither `A` nor `B` are - // inference variables. + /// A "verify" is something that we need to verify after inference is + /// done, but which does not directly affect inference in any way. + /// + /// An example is a `A <= B` where neither `A` nor `B` are + /// inference variables. verifys: RefCell>>, - // A "given" is a relationship that is known to hold. In particular, - // we often know from closure fn signatures that a particular free - // region must be a subregion of a region variable: - // - // foo.iter().filter(<'a> |x: &'a &'b T| ...) - // - // In situations like this, `'b` is in fact a region variable - // introduced by the call to `iter()`, and `'a` is a bound region - // on the closure (as indicated by the `<'a>` prefix). If we are - // naive, we wind up inferring that `'b` must be `'static`, - // because we require that it be greater than `'a` and we do not - // know what `'a` is precisely. - // - // This hashmap is used to avoid that naive scenario. Basically we - // record the fact that `'a <= 'b` is implied by the fn signature, - // and then ignore the constraint when solving equations. This is - // a bit of a hack but seems to work. + /// A "given" is a relationship that is known to hold. In particular, + /// we often know from closure fn signatures that a particular free + /// region must be a subregion of a region variable: + /// + /// foo.iter().filter(<'a> |x: &'a &'b T| ...) + /// + /// In situations like this, `'b` is in fact a region variable + /// introduced by the call to `iter()`, and `'a` is a bound region + /// on the closure (as indicated by the `<'a>` prefix). If we are + /// naive, we wind up inferring that `'b` must be `'static`, + /// because we require that it be greater than `'a` and we do not + /// know what `'a` is precisely. + /// + /// This hashmap is used to avoid that naive scenario. Basically we + /// record the fact that `'a <= 'b` is implied by the fn signature, + /// and then ignore the constraint when solving equations. This is + /// a bit of a hack but seems to work. givens: RefCell, ty::RegionVid)>>, lubs: RefCell>, @@ -219,20 +219,21 @@ pub struct RegionVarBindings<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { skolemization_count: Cell, bound_count: Cell, - // The undo log records actions that might later be undone. - // - // Note: when the undo_log is empty, we are not actively - // snapshotting. When the `start_snapshot()` method is called, we - // push an OpenSnapshot entry onto the list to indicate that we - // are now actively snapshotting. The reason for this is that - // otherwise we end up adding entries for things like the lower - // bound on a variable and so forth, which can never be rolled - // back. + /// The undo log records actions that might later be undone. + /// + /// Note: when the undo_log is empty, we are not actively + /// snapshotting. When the `start_snapshot()` method is called, we + /// push an OpenSnapshot entry onto the list to indicate that we + /// are now actively snapshotting. The reason for this is that + /// otherwise we end up adding entries for things like the lower + /// bound on a variable and so forth, which can never be rolled + /// back. undo_log: RefCell>>, + unification_table: RefCell>, - // This contains the results of inference. It begins as an empty - // option and only acquires a value after inference is complete. + /// This contains the results of inference. It begins as an empty + /// option and only acquires a value after inference is complete. values: RefCell>>>, } @@ -353,7 +354,7 @@ impl<'a, 'gcx, 'tcx> TaintSet<'tcx> { impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> { pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> RegionVarBindings<'a, 'gcx, 'tcx> { RegionVarBindings { - tcx: tcx, + tcx, var_origins: RefCell::new(Vec::new()), values: RefCell::new(None), constraints: RefCell::new(FxHashMap()), @@ -377,7 +378,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> { debug!("RegionVarBindings: start_snapshot({})", length); self.undo_log.borrow_mut().push(OpenSnapshot); RegionSnapshot { - length: length, + length, region_snapshot: self.unification_table.borrow_mut().snapshot(), skolemization_count: self.skolemization_count.get(), } @@ -732,10 +733,10 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> { sub: Region<'tcx>, bound: VerifyBound<'tcx>) { self.add_verify(Verify { - kind: kind, - origin: origin, + kind, + origin, region: sub, - bound: bound + bound, }); } @@ -1458,7 +1459,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> { ConstrainRegSubVar(region, _) | ConstrainVarSubReg(_, region) => { state.result.push(RegionAndOrigin { - region: region, + region, origin: this.constraints.borrow().get(&edge.data).unwrap().clone(), }); } @@ -1549,8 +1550,7 @@ impl<'a, 'gcx, 'tcx> GenericKind<'tcx> { pub fn to_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { match *self { GenericKind::Param(ref p) => p.to_ty(tcx), - GenericKind::Projection(ref p) => tcx.mk_projection( - p.trait_ref.clone(), p.item_name(tcx)), + GenericKind::Projection(ref p) => tcx.mk_projection(p.item_def_id, p.substs), } } } diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index 4ae2a80264..cc91a637b8 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -181,8 +181,8 @@ impl<'tcx> TypeVariableTable<'tcx> { self.sub_relations.new_key(()); let index = self.values.push(TypeVariableData { value: Bounded { default: default }, - origin: origin, - diverging: diverging + origin, + diverging, }); let v = ty::TyVid { index: index as u32 }; debug!("new_var: diverging={:?} index={:?}", diverging, v); @@ -369,7 +369,7 @@ impl<'tcx> sv::SnapshotVecDelegate for Delegate<'tcx> { fn reverse(values: &mut Vec>, action: Instantiate<'tcx>) { let Instantiate { vid, default } = action; values[vid.index as usize].value = Bounded { - default: default + default, }; } } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 2216103636..e0317e5e7f 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -22,7 +22,6 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![deny(warnings)] -#![feature(associated_consts)] #![feature(box_patterns)] #![feature(box_syntax)] #![feature(conservative_impl_trait)] @@ -39,13 +38,10 @@ #![feature(specialization)] #![feature(unboxed_closures)] #![feature(discriminant_value)] -#![feature(sort_unstable)] #![feature(trace_macros)] +#![feature(test)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] -#![cfg_attr(stage0, feature(loop_break_value))] +#![cfg_attr(stage0, feature(associated_consts))] #![recursion_limit="256"] @@ -65,9 +61,15 @@ extern crate rustc_errors as errors; #[macro_use] extern crate syntax; extern crate syntax_pos; #[macro_use] #[no_link] extern crate rustc_bitflags; +extern crate jobserver; extern crate serialize as rustc_serialize; // used by deriving +// Note that librustc doesn't actually depend on these crates, see the note in +// `Cargo.toml` for this crate about why these are here. +extern crate flate2; +extern crate test; + #[macro_use] mod macros; @@ -83,6 +85,7 @@ pub mod infer; pub mod lint; pub mod middle { + pub mod allocator; pub mod expr_use_visitor; pub mod const_val; pub mod cstore; diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 736c3b289e..2d088c4f6d 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -130,6 +130,12 @@ declare_lint! { "detect private items in public interfaces not caught by the old implementation" } +declare_lint! { + pub PUB_USE_OF_PRIVATE_EXTERN_CRATE, + Deny, + "detect public reexports of private extern crates" +} + declare_lint! { pub INVALID_TYPE_PARAM_DEFAULT, Deny, @@ -144,14 +150,14 @@ declare_lint! { declare_lint! { pub RESOLVE_TRAIT_ON_DEFAULTED_UNIT, - Warn, + Deny, "attempt to resolve a trait on an expression whose type cannot be inferred but which \ currently defaults to ()" } declare_lint! { pub SAFE_EXTERN_STATICS, - Warn, + Deny, "safe access to extern statics was erroneously allowed" } @@ -169,14 +175,14 @@ declare_lint! { declare_lint! { pub LEGACY_DIRECTORY_OWNERSHIP, - Warn, + Deny, "non-inline, non-`#[path]` modules (e.g. `mod foo;`) were erroneously allowed in some files \ not named `mod.rs`" } declare_lint! { pub LEGACY_IMPORTS, - Warn, + Deny, "detects names that resolve to ambiguous glob imports with RFC 1560" } @@ -188,13 +194,13 @@ declare_lint! { declare_lint! { pub MISSING_FRAGMENT_SPECIFIER, - Warn, + Deny, "detects missing fragment specifiers in unused `macro_rules!` patterns" } declare_lint! { pub PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, - Warn, + Deny, "detects parenthesized generic parameters in type and module names" } @@ -230,6 +236,7 @@ impl LintPass for HardwiredLints { TRIVIAL_CASTS, TRIVIAL_NUMERIC_CASTS, PRIVATE_IN_PUBLIC, + PUB_USE_OF_PRIVATE_EXTERN_CRATE, INVALID_TYPE_PARAM_DEFAULT, CONST_ERR, RENAMED_AND_REMOVED_LINTS, diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 4c25a455f2..d67bca1df3 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -25,8 +25,8 @@ //! for all lint attributes. use self::TargetLint::*; -use dep_graph::DepNode; use middle::privacy::AccessLevels; +use traits::Reveal; use ty::{self, TyCtxt}; use session::{config, early_error, Session}; use lint::{Level, LevelSource, Lint, LintId, LintPass, LintSource}; @@ -140,8 +140,8 @@ impl<'a, S: Into> IntoEarlyLint for (S, &'a str) { let mut diagnostic = Diagnostic::new(errors::Level::Warning, msg); diagnostic.set_span(span); EarlyLint { - id: id, - diagnostic: diagnostic, + id, + diagnostic, } } } @@ -149,7 +149,7 @@ impl<'a, S: Into> IntoEarlyLint for (S, &'a str) { impl IntoEarlyLint for Diagnostic { fn into_early_lint(self, id: LintId) -> EarlyLint { EarlyLint { - id: id, + id, diagnostic: self, } } @@ -291,16 +291,13 @@ impl LintStore { self.by_name.insert(name.into(), Removed(reason.into())); } - #[allow(unused_variables)] - fn find_lint(&self, lint_name: &str, sess: &Session, span: Option) - -> Result - { + fn find_lint(&self, lint_name: &str) -> Result { match self.by_name.get(lint_name) { Some(&Id(lint_id)) => Ok(lint_id), Some(&Renamed(_, lint_id)) => { Ok(lint_id) }, - Some(&Removed(ref reason)) => { + Some(&Removed(_)) => { Err(FindLintError::Removed) }, None => Err(FindLintError::NotFound) @@ -313,7 +310,7 @@ impl LintStore { &lint_name[..], level); let lint_flag_val = Symbol::intern(&lint_name); - match self.find_lint(&lint_name[..], sess, None) { + match self.find_lint(&lint_name[..]) { Ok(lint_id) => self.levels.set(lint_id, (level, CommandLine(lint_flag_val))), Err(FindLintError::Removed) => { } Err(_) => { @@ -411,8 +408,8 @@ pub struct LateContext<'a, 'tcx: 'a> { /// Side-tables for the body we are in. pub tables: &'a ty::TypeckTables<'tcx>, - /// The crate being checked. - pub krate: &'a hir::Crate, + /// Parameter environment for the item we are in. + pub param_env: ty::ParamEnv<'tcx>, /// Items accessible from the crate being checked. pub access_levels: &'a AccessLevels, @@ -513,7 +510,6 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session, } let name = lint.name_lower(); - let mut def = None; // Except for possible note details, forbid behaves like deny. let effective_level = if level == Forbid { Deny } else { level }; @@ -528,7 +524,8 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session, match source { Default => { - err.note(&format!("#[{}({})] on by default", level.as_str(), name)); + sess.diag_note_once(&mut err, lint, + &format!("#[{}({})] on by default", level.as_str(), name)); }, CommandLine(lint_flag_val) => { let flag = match level { @@ -537,20 +534,24 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session, }; let hyphen_case_lint_name = name.replace("_", "-"); if lint_flag_val.as_str() == name { - err.note(&format!("requested on the command line with `{} {}`", - flag, hyphen_case_lint_name)); + sess.diag_note_once(&mut err, lint, + &format!("requested on the command line with `{} {}`", + flag, hyphen_case_lint_name)); } else { let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-"); - err.note(&format!("`{} {}` implied by `{} {}`", - flag, hyphen_case_lint_name, flag, hyphen_case_flag_val)); + sess.diag_note_once(&mut err, lint, + &format!("`{} {}` implied by `{} {}`", + flag, hyphen_case_lint_name, flag, + hyphen_case_flag_val)); } }, Node(lint_attr_name, src) => { - def = Some(src); + sess.diag_span_note_once(&mut err, lint, src, "lint level defined here"); if lint_attr_name.as_str() != name { let level_str = level.as_str(); - err.note(&format!("#[{}({})] implied by #[{}({})]", - level_str, name, level_str, lint_attr_name)); + sess.diag_note_once(&mut err, lint, + &format!("#[{}({})] implied by #[{}({})]", + level_str, name, level_str, lint_attr_name)); } } } @@ -566,10 +567,6 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session, err.note(&citation); } - if let Some(span) = def { - sess.diag_span_note_once(&mut err, lint, span, "lint level defined here"); - } - err } @@ -724,21 +721,22 @@ pub trait LintContext<'tcx>: Sized { let mut pushed = 0; for result in gather_attrs(attrs) { - let v = match result { + let (is_group, lint_level_spans) = match result { Err(span) => { span_err!(self.sess(), span, E0452, "malformed lint attribute"); continue; } Ok((lint_name, level, span)) => { - match self.lints().find_lint(&lint_name.as_str(), &self.sess(), Some(span)) { - Ok(lint_id) => vec![(lint_id, level, span)], + match self.lints().find_lint(&lint_name.as_str()) { + Ok(lint_id) => (false, vec![(lint_id, level, span)]), Err(FindLintError::NotFound) => { match self.lints().lint_groups.get(&*lint_name.as_str()) { - Some(&(ref v, _)) => v.iter() + Some(&(ref v, _)) => (true, + v.iter() .map(|lint_id: &LintId| (*lint_id, level, span)) - .collect(), + .collect()), None => { // The lint or lint group doesn't exist. // This is an error, but it was handled @@ -746,22 +744,26 @@ pub trait LintContext<'tcx>: Sized { continue; } } - }, - Err(FindLintError::Removed) => { continue; } + } + Err(FindLintError::Removed) => continue, } } }; let lint_attr_name = result.expect("lint attribute should be well-formed").0; - for (lint_id, level, span) in v { + for (lint_id, level, span) in lint_level_spans { let (now, now_source) = self.lint_sess().get_source(lint_id); if now == Forbid && level != Forbid { - let lint_name = lint_id.to_string(); + let forbidden_lint_name = match now_source { + LintSource::Default => lint_id.to_string(), + LintSource::Node(name, _) => name.to_string(), + LintSource::CommandLine(name) => name.to_string(), + }; let mut diag_builder = struct_span_err!(self.sess(), span, E0453, "{}({}) overruled by outer forbid({})", - level.as_str(), lint_name, - lint_name); + level.as_str(), lint_attr_name, + forbidden_lint_name); diag_builder.span_label(span, "overruled by previous forbid"); match now_source { LintSource::Default => &mut diag_builder, @@ -772,7 +774,10 @@ pub trait LintContext<'tcx>: Sized { LintSource::CommandLine(_) => { diag_builder.note("`forbid` lint level was set on command line") } - }.emit() + }.emit(); + if is_group { // don't set a separate error for every lint in the group + break; + } } else if now != level { let cx = self.lint_sess_mut(); cx.stack.push((lint_id, (now, now_source))); @@ -800,8 +805,8 @@ impl<'a> EarlyContext<'a> { fn new(sess: &'a Session, krate: &'a ast::Crate) -> EarlyContext<'a> { EarlyContext { - sess: sess, - krate: krate, + sess, + krate, lint_sess: LintSession::new(&sess.lint_store), } } @@ -869,6 +874,17 @@ impl<'a> LintContext<'a> for EarlyContext<'a> { } } +impl<'a, 'tcx> LateContext<'a, 'tcx> { + fn with_param_env(&mut self, id: ast::NodeId, f: F) + where F: FnOnce(&mut Self), + { + let old_param_env = self.param_env; + self.param_env = self.tcx.param_env(self.tcx.hir.local_def_id(id)); + f(self); + self.param_env = old_param_env; + } +} + impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { /// Because lints are scoped lexically, we want to walk nested /// items in the context of the outer item, so enable @@ -902,17 +918,21 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { fn visit_item(&mut self, it: &'tcx hir::Item) { self.with_lint_attrs(&it.attrs, |cx| { - run_lints!(cx, check_item, late_passes, it); - hir_visit::walk_item(cx, it); - run_lints!(cx, check_item_post, late_passes, it); + cx.with_param_env(it.id, |cx| { + run_lints!(cx, check_item, late_passes, it); + hir_visit::walk_item(cx, it); + run_lints!(cx, check_item_post, late_passes, it); + }); }) } fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem) { self.with_lint_attrs(&it.attrs, |cx| { - run_lints!(cx, check_foreign_item, late_passes, it); - hir_visit::walk_foreign_item(cx, it); - run_lints!(cx, check_foreign_item_post, late_passes, it); + cx.with_param_env(it.id, |cx| { + run_lints!(cx, check_foreign_item, late_passes, it); + hir_visit::walk_foreign_item(cx, it); + run_lints!(cx, check_foreign_item_post, late_passes, it); + }); }) } @@ -1026,17 +1046,21 @@ 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); - hir_visit::walk_trait_item(cx, trait_item); - run_lints!(cx, check_trait_item_post, late_passes, trait_item); + cx.with_param_env(trait_item.id, |cx| { + run_lints!(cx, check_trait_item, late_passes, trait_item); + hir_visit::walk_trait_item(cx, trait_item); + run_lints!(cx, check_trait_item_post, late_passes, trait_item); + }); }); } 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); - hir_visit::walk_impl_item(cx, impl_item); - run_lints!(cx, check_impl_item_post, late_passes, impl_item); + cx.with_param_env(impl_item.id, |cx| { + run_lints!(cx, check_impl_item, late_passes, impl_item); + hir_visit::walk_impl_item(cx, impl_item); + run_lints!(cx, check_impl_item_post, late_passes, impl_item); + }); }); } @@ -1298,7 +1322,7 @@ fn check_lint_name_cmdline(sess: &Session, lint_cx: &LintStore, Some(sess.struct_warn(msg)) }, CheckLintNameResult::NoLint => { - Some(sess.struct_err(&format!("unknown lint: `{}`", lint_name))) + Some(struct_err!(sess, E0602, "unknown lint: `{}`", lint_name)) } }; @@ -1321,17 +1345,15 @@ fn check_lint_name_cmdline(sess: &Session, lint_cx: &LintStore, /// /// Consumes the `lint_store` field of the `Session`. pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let _task = tcx.dep_graph.in_task(DepNode::LateLintCheck); - let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); let krate = tcx.hir.krate(); let mut cx = LateContext { - tcx: tcx, + tcx, tables: &ty::TypeckTables::empty(), - krate: krate, - access_levels: access_levels, + param_env: ty::ParamEnv::empty(Reveal::UserFacing), + access_levels, lint_sess: LintSession::new(&tcx.sess.lint_store), }; @@ -1403,7 +1425,7 @@ impl Decodable for LintId { fn decode(d: &mut D) -> Result { let s = d.read_str()?; ty::tls::with(|tcx| { - match tcx.sess.lint_store.borrow().find_lint(&s, tcx.sess, None) { + match tcx.sess.lint_store.borrow().find_lint(&s) { Ok(id) => Ok(id), Err(_) => panic!("invalid lint-id `{}`", s), } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index e81d097737..f9222ac940 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -294,7 +294,7 @@ impl LintId { /// Get the `LintId` for a `Lint`. pub fn of(lint: &'static Lint) -> LintId { LintId { - lint: lint, + lint, } } diff --git a/src/librustc/macros.rs b/src/librustc/macros.rs index c18e585f79..f814f941b0 100644 --- a/src/librustc/macros.rs +++ b/src/librustc/macros.rs @@ -73,10 +73,10 @@ macro_rules! __impl_stable_hash_field { #[macro_export] macro_rules! impl_stable_hash_for { (enum $enum_name:path { $( $variant:ident $( ( $($arg:ident),* ) )* ),* }) => { - impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'tcx>> for $enum_name { + impl<'a, 'gcx, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'gcx, 'tcx>> for $enum_name { #[inline] fn hash_stable(&self, - __ctx: &mut $crate::ich::StableHashingContext<'a, 'tcx>, + __ctx: &mut $crate::ich::StableHashingContext<'a, 'gcx, 'tcx>, __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { use $enum_name::*; ::std::mem::discriminant(self).hash_stable(__ctx, __hasher); @@ -92,10 +92,10 @@ macro_rules! impl_stable_hash_for { } }; (struct $struct_name:path { $($field:ident),* }) => { - impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'tcx>> for $struct_name { + impl<'a, 'gcx, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'gcx, 'tcx>> for $struct_name { #[inline] fn hash_stable(&self, - __ctx: &mut $crate::ich::StableHashingContext<'a, 'tcx>, + __ctx: &mut $crate::ich::StableHashingContext<'a, 'gcx, 'tcx>, __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { let $struct_name { $(ref $field),* @@ -106,10 +106,10 @@ macro_rules! impl_stable_hash_for { } }; (tuple_struct $struct_name:path { $($field:ident),* }) => { - impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'tcx>> for $struct_name { + impl<'a, 'gcx, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'gcx, 'tcx>> for $struct_name { #[inline] fn hash_stable(&self, - __ctx: &mut $crate::ich::StableHashingContext<'a, 'tcx>, + __ctx: &mut $crate::ich::StableHashingContext<'a, 'gcx, 'tcx>, __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { let $struct_name ( $(ref $field),* @@ -125,11 +125,11 @@ macro_rules! impl_stable_hash_for { macro_rules! impl_stable_hash_for_spanned { ($T:path) => ( - impl<'a, 'tcx> HashStable> for ::syntax::codemap::Spanned<$T> + impl<'a, 'gcx, 'tcx> HashStable> for ::syntax::codemap::Spanned<$T> { #[inline] fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { self.node.hash_stable(hcx, hasher); self.span.hash_stable(hcx, hasher); diff --git a/src/librustc/middle/allocator.rs b/src/librustc/middle/allocator.rs new file mode 100644 index 0000000000..79a9ef0e8b --- /dev/null +++ b/src/librustc/middle/allocator.rs @@ -0,0 +1,26 @@ +// 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. + +#[derive(Clone, Copy)] +pub enum AllocatorKind { + Global, + DefaultLib, + DefaultExe, +} + +impl AllocatorKind { + pub fn fn_name(&self, base: &str) -> String { + match *self { + AllocatorKind::Global => format!("__rg_{}", base), + AllocatorKind::DefaultLib => format!("__rdl_{}", base), + AllocatorKind::DefaultExe => format!("__rde_{}", base), + } + } +} diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 71b066c668..960d616cd4 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -23,7 +23,6 @@ // probably get a better home if someone can find one. use hir::def; -use dep_graph::DepNode; use hir::def_id::{CrateNum, DefId, DefIndex}; use hir::map as hir_map; use hir::map::definitions::{Definitions, DefKey, DisambiguatedDefPathData, @@ -190,15 +189,14 @@ pub struct EncodedMetadataHash { /// upstream crate. #[derive(Debug, RustcEncodable, RustcDecodable, Clone)] pub struct EncodedMetadataHashes { - pub entry_hashes: Vec, - pub global_hashes: Vec<(DepNode<()>, ich::Fingerprint)>, + // Stable content hashes for things in crate metadata, indexed by DefIndex. + pub hashes: Vec, } impl EncodedMetadataHashes { pub fn new() -> EncodedMetadataHashes { EncodedMetadataHashes { - entry_hashes: Vec::new(), - global_hashes: Vec::new(), + hashes: Vec::new(), } } } @@ -232,7 +230,7 @@ pub trait CrateStore { // item info fn visibility(&self, def: DefId) -> ty::Visibility; - fn visible_parent_map<'a>(&'a self) -> ::std::cell::Ref<'a, DefIdMap>; + fn visible_parent_map<'a>(&'a self, sess: &Session) -> ::std::cell::Ref<'a, DefIdMap>; fn item_generics_cloned(&self, def: DefId) -> ty::Generics; // trait info @@ -245,23 +243,18 @@ pub trait CrateStore { fn associated_item_cloned(&self, def: DefId) -> ty::AssociatedItem; // flags - fn is_const_fn(&self, did: DefId) -> bool; fn is_dllimport_foreign_item(&self, def: DefId) -> bool; fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool; // crate metadata - fn dylib_dependency_formats(&self, cnum: CrateNum) - -> Vec<(CrateNum, LinkagePreference)>; fn dep_kind(&self, cnum: CrateNum) -> DepKind; fn export_macros(&self, cnum: CrateNum); fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>; fn missing_lang_items(&self, cnum: CrateNum) -> Vec; - fn is_allocator(&self, cnum: CrateNum) -> bool; - fn is_panic_runtime(&self, cnum: CrateNum) -> bool; fn is_compiler_builtins(&self, cnum: CrateNum) -> bool; fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool; + fn is_profiler_runtime(&self, cnum: CrateNum) -> bool; fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy; - fn extern_crate(&self, cnum: CrateNum) -> Option; /// The name of the crate as it is referred to in source code of the current /// crate. fn crate_name(&self, cnum: CrateNum) -> Symbol; @@ -285,7 +278,7 @@ pub trait CrateStore { fn def_path_hash(&self, def: DefId) -> hir_map::DefPathHash; fn def_path_table(&self, cnum: CrateNum) -> Rc; fn struct_field_names(&self, def: DefId) -> Vec; - fn item_children(&self, did: DefId) -> Vec; + fn item_children(&self, did: DefId, sess: &Session) -> Vec; fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro; // misc. metadata @@ -347,7 +340,9 @@ impl CrateStore for DummyCrateStore { { bug!("crate_data_as_rc_any") } // item info fn visibility(&self, def: DefId) -> ty::Visibility { bug!("visibility") } - fn visible_parent_map<'a>(&'a self) -> ::std::cell::Ref<'a, DefIdMap> { + fn visible_parent_map<'a>(&'a self, session: &Session) + -> ::std::cell::Ref<'a, DefIdMap> + { bug!("visible_parent_map") } fn item_generics_cloned(&self, def: DefId) -> ty::Generics @@ -364,28 +359,22 @@ impl CrateStore for DummyCrateStore { { bug!("associated_item_cloned") } // flags - fn is_const_fn(&self, did: DefId) -> bool { bug!("is_const_fn") } fn is_dllimport_foreign_item(&self, id: DefId) -> bool { false } fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool { false } // crate metadata - fn dylib_dependency_formats(&self, cnum: CrateNum) - -> Vec<(CrateNum, LinkagePreference)> - { bug!("dylib_dependency_formats") } fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)> { bug!("lang_items") } fn missing_lang_items(&self, cnum: CrateNum) -> Vec { bug!("missing_lang_items") } fn dep_kind(&self, cnum: CrateNum) -> DepKind { bug!("is_explicitly_linked") } fn export_macros(&self, cnum: CrateNum) { bug!("export_macros") } - fn is_allocator(&self, cnum: CrateNum) -> bool { bug!("is_allocator") } - fn is_panic_runtime(&self, cnum: CrateNum) -> bool { bug!("is_panic_runtime") } fn is_compiler_builtins(&self, cnum: CrateNum) -> bool { bug!("is_compiler_builtins") } + fn is_profiler_runtime(&self, cnum: CrateNum) -> bool { bug!("is_profiler_runtime") } fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool { bug!("is_sanitizer_runtime") } fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy { bug!("panic_strategy") } - fn extern_crate(&self, cnum: CrateNum) -> Option { bug!("extern_crate") } fn crate_name(&self, cnum: CrateNum) -> Symbol { bug!("crate_name") } fn original_crate_name(&self, cnum: CrateNum) -> Symbol { bug!("original_crate_name") @@ -421,7 +410,9 @@ impl CrateStore for DummyCrateStore { bug!("def_path_table") } fn struct_field_names(&self, def: DefId) -> Vec { bug!("struct_field_names") } - fn item_children(&self, did: DefId) -> Vec { bug!("item_children") } + fn item_children(&self, did: DefId, sess: &Session) -> Vec { + bug!("item_children") + } fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro { bug!("load_macro") } // misc. metadata diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index 7d62103e38..f6be709009 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -21,7 +21,6 @@ use std::io; use std::mem; use std::usize; use syntax::ast; -use syntax::print::pp; use syntax::print::pprust::PrintState; use util::nodemap::NodeMap; use hir; @@ -157,7 +156,7 @@ impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O ps.synth_comment( format!("id {}: {}{}{}{}", id, entry_str, gens_str, action_kills_str, scope_kills_str))?; - pp::space(&mut ps.s)?; + ps.s.space()?; } Ok(()) } @@ -260,16 +259,16 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { let nodeid_to_index = build_nodeid_to_index(body, cfg); DataFlowContext { - tcx: tcx, - analysis_name: analysis_name, - words_per_id: words_per_id, - nodeid_to_index: nodeid_to_index, - bits_per_id: bits_per_id, - oper: oper, - gens: gens, + tcx, + analysis_name, + words_per_id, + nodeid_to_index, + bits_per_id, + oper, + gens, action_kills: kills1, scope_kills: kills2, - on_entry: on_entry + on_entry, } } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 6077b7863e..2238e464cb 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -287,6 +287,11 @@ fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool { return true; } + // Don't lint about global allocators + if attr::contains_name(attrs, "global_allocator") { + return true; + } + let dead_code = lint::builtin::DEAD_CODE.name_lower(); for attr in lint::gather_attrs(attrs) { match attr { @@ -378,8 +383,8 @@ fn create_and_seed_worklist<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Seed implemented trait items let mut life_seeder = LifeSeeder { - worklist: worklist, - krate: krate, + worklist, + krate, }; krate.visit_all_item_likes(&mut life_seeder); @@ -392,8 +397,8 @@ fn find_live<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, -> Box> { let worklist = create_and_seed_worklist(tcx, access_levels, krate); let mut symbol_visitor = MarkSymbolVisitor { - worklist: worklist, - tcx: tcx, + worklist, + tcx, tables: &ty::TypeckTables::empty(), live_symbols: box FxHashSet(), struct_has_extern_repr: false, diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index e60d0533c9..837ab4fd4a 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -65,6 +65,7 @@ use hir::def_id::CrateNum; use session; use session::config; +use ty::TyCtxt; use middle::cstore::DepKind; use middle::cstore::LinkagePreference::{self, RequireStatic, RequireDynamic}; use util::nodemap::FxHashMap; @@ -91,18 +92,22 @@ pub enum Linkage { Dynamic, } -pub fn calculate(sess: &session::Session) { +pub fn calculate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { + let sess = &tcx.sess; let mut fmts = sess.dependency_formats.borrow_mut(); for &ty in sess.crate_types.borrow().iter() { - let linkage = calculate_type(sess, ty); - verify_ok(sess, &linkage); + let linkage = calculate_type(tcx, ty); + verify_ok(tcx, &linkage); fmts.insert(ty, linkage); } sess.abort_if_errors(); } -fn calculate_type(sess: &session::Session, - ty: config::CrateType) -> DependencyList { +fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + ty: config::CrateType) -> DependencyList { + + let sess = &tcx.sess; + if !sess.opts.output_types.should_trans() { return Vec::new(); } @@ -111,7 +116,7 @@ fn calculate_type(sess: &session::Session, // If the global prefer_dynamic switch is turned off, first attempt // static linkage (this can fail). config::CrateTypeExecutable if !sess.opts.cg.prefer_dynamic => { - if let Some(v) = attempt_static(sess) { + if let Some(v) = attempt_static(tcx) { return v; } } @@ -124,7 +129,7 @@ fn calculate_type(sess: &session::Session, // to be found, we generate some nice pretty errors. config::CrateTypeStaticlib | config::CrateTypeCdylib => { - if let Some(v) = attempt_static(sess) { + if let Some(v) = attempt_static(tcx) { return v; } for cnum in sess.cstore.crates() { @@ -141,7 +146,7 @@ fn calculate_type(sess: &session::Session, // to try to eagerly statically link all dependencies. This is normally // done for end-product dylibs, not intermediate products. config::CrateTypeDylib if !sess.opts.cg.prefer_dynamic => { - if let Some(v) = attempt_static(sess) { + if let Some(v) = attempt_static(tcx) { return v; } } @@ -167,8 +172,8 @@ fn calculate_type(sess: &session::Session, if src.dylib.is_some() { info!("adding dylib: {}", name); add_library(sess, cnum, RequireDynamic, &mut formats); - let deps = sess.cstore.dylib_dependency_formats(cnum); - for &(depnum, style) in &deps { + let deps = tcx.dylib_dependency_formats(cnum.as_def_id()); + for &(depnum, style) in deps.iter() { info!("adding {:?}: {}", style, sess.cstore.crate_name(depnum)); add_library(sess, depnum, style, &mut formats); @@ -209,10 +214,9 @@ fn calculate_type(sess: &session::Session, // // Things like allocators and panic runtimes may not have been activated // quite yet, so do so here. - activate_injected_dep(sess.injected_allocator.get(), &mut ret, - &|cnum| sess.cstore.is_allocator(cnum)); activate_injected_dep(sess.injected_panic_runtime.get(), &mut ret, - &|cnum| sess.cstore.is_panic_runtime(cnum)); + &|cnum| tcx.is_panic_runtime(cnum.as_def_id())); + activate_injected_allocator(sess, &mut ret); // When dylib B links to dylib A, then when using B we must also link to A. // It could be the case, however, that the rlib for A is present (hence we @@ -269,7 +273,8 @@ fn add_library(sess: &session::Session, } } -fn attempt_static(sess: &session::Session) -> Option { +fn attempt_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option { + let sess = &tcx.sess; let crates = sess.cstore.used_crates(RequireStatic); if !crates.iter().by_ref().all(|&(_, ref p)| p.is_some()) { return None @@ -289,10 +294,9 @@ fn attempt_static(sess: &session::Session) -> Option { // Our allocator/panic runtime may not have been linked above if it wasn't // explicitly linked, which is the case for any injected dependency. Handle // that here and activate them. - activate_injected_dep(sess.injected_allocator.get(), &mut ret, - &|cnum| sess.cstore.is_allocator(cnum)); activate_injected_dep(sess.injected_panic_runtime.get(), &mut ret, - &|cnum| sess.cstore.is_panic_runtime(cnum)); + &|cnum| tcx.is_panic_runtime(cnum.as_def_id())); + activate_injected_allocator(sess, &mut ret); Some(ret) } @@ -325,31 +329,33 @@ fn activate_injected_dep(injected: Option, } } +fn activate_injected_allocator(sess: &session::Session, + list: &mut DependencyList) { + let cnum = match sess.injected_allocator.get() { + Some(cnum) => cnum, + None => return, + }; + let idx = cnum.as_usize() - 1; + if list[idx] == Linkage::NotLinked { + list[idx] = Linkage::Static; + } +} + // After the linkage for a crate has been determined we need to verify that // there's only going to be one allocator in the output. -fn verify_ok(sess: &session::Session, list: &[Linkage]) { +fn verify_ok<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, list: &[Linkage]) { + let sess = &tcx.sess; if list.len() == 0 { return } - let mut allocator = None; let mut panic_runtime = None; for (i, linkage) in list.iter().enumerate() { if let Linkage::NotLinked = *linkage { continue } let cnum = CrateNum::new(i + 1); - if sess.cstore.is_allocator(cnum) { - if let Some(prev) = allocator { - let prev_name = sess.cstore.crate_name(prev); - let cur_name = sess.cstore.crate_name(cnum); - sess.err(&format!("cannot link together two \ - allocators: {} and {}", - prev_name, cur_name)); - } - allocator = Some(cnum); - } - if sess.cstore.is_panic_runtime(cnum) { + if tcx.is_panic_runtime(cnum.as_def_id()) { if let Some((prev, _)) = panic_runtime { let prev_name = sess.cstore.crate_name(prev); let cur_name = sess.cstore.crate_name(cnum); @@ -390,7 +396,8 @@ fn verify_ok(sess: &session::Session, list: &[Linkage]) { } let cnum = CrateNum::new(i + 1); let found_strategy = sess.cstore.panic_strategy(cnum); - if desired_strategy == found_strategy { + let is_compiler_builtins = sess.cstore.is_compiler_builtins(cnum); + if is_compiler_builtins || desired_strategy == found_strategy { continue } diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 74e1225f39..abd5cbcb89 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -12,7 +12,7 @@ //! `unsafe`. use self::RootUnsafeContext::*; -use ty::{self, Ty, TyCtxt}; +use ty::{self, TyCtxt}; use lint; use syntax::ast; @@ -40,14 +40,6 @@ enum RootUnsafeContext { UnsafeBlock(ast::NodeId), } -fn type_is_unsafe_function(ty: Ty) -> bool { - match ty.sty { - ty::TyFnDef(.., f) | - ty::TyFnPtr(f) => f.unsafety() == hir::Unsafety::Unsafe, - _ => false, - } -} - struct EffectCheckVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &'a ty::TypeckTables<'tcx>, @@ -174,10 +166,11 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { match expr.node { hir::ExprMethodCall(..) => { let def_id = self.tables.type_dependent_defs[&expr.id].def_id(); - let base_type = self.tcx.type_of(def_id); - debug!("effect: method call case, base type is {:?}", - base_type); - if type_is_unsafe_function(base_type) { + let sig = self.tcx.fn_sig(def_id); + debug!("effect: method call case, signature is {:?}", + sig); + + if sig.0.unsafety == hir::Unsafety::Unsafe { self.require_unsafe(expr.span, "invocation of unsafe method") } @@ -186,8 +179,13 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { 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) { - self.require_unsafe(expr.span, "call to unsafe function") + match base_type.sty { + ty::TyFnDef(..) | ty::TyFnPtr(_) => { + if base_type.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe { + self.require_unsafe(expr.span, "call to unsafe function") + } + } + _ => {} } } hir::ExprUnary(hir::UnDeref, ref base) => { @@ -263,7 +261,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut visitor = EffectCheckVisitor { - tcx: tcx, + tcx, tables: &ty::TypeckTables::empty(), body_id: hir::BodyId { node_id: ast::CRATE_NODE_ID }, unsafe_context: UnsafeContext::new(SafeContext), diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index b26cccf5f1..31e054ec1c 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -71,7 +71,7 @@ pub fn find_entry_point(session: &Session, hir_map: &hir_map::Map) { } let mut ctxt = EntryContext { - session: session, + session, map: hir_map, main_fn: None, attr_main_fn: None, diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 0b2652c748..259bd4f099 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -235,17 +235,14 @@ impl OverloadedCallType { /////////////////////////////////////////////////////////////////////////// // The ExprUseVisitor type // -// This is the code that actually walks the tree. Like -// mem_categorization, it requires a TYPER, which is a type that -// supplies types from the tree. After type checking is complete, you -// can just use the tcx as the typer. +// This is the code that actually walks the tree. pub struct ExprUseVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { mc: mc::MemCategorizationContext<'a, 'gcx, 'tcx>, delegate: &'a mut Delegate<'tcx>, param_env: ty::ParamEnv<'tcx>, } -// If the TYPER results in an error, it's because the type check +// If the MC results in an error, it's because the type check // failed (or will fail, when the error is uncovered and reported // during writeback). In this case, we just ignore this part of the // code. @@ -264,29 +261,32 @@ macro_rules! return_if_err { ) } -impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { +impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> { pub fn new(delegate: &'a mut (Delegate<'tcx>+'a), + tcx: TyCtxt<'a, 'tcx, 'tcx>, + param_env: ty::ParamEnv<'tcx>, region_maps: &'a RegionMaps, - infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - param_env: ty::ParamEnv<'tcx>) + tables: &'a ty::TypeckTables<'tcx>) -> Self { - ExprUseVisitor::with_options(delegate, - infcx, - param_env, - region_maps, - mc::MemCategorizationOptions::default()) + ExprUseVisitor { + mc: mc::MemCategorizationContext::new(tcx, region_maps, tables), + delegate, + param_env, + } } +} - pub fn with_options(delegate: &'a mut (Delegate<'tcx>+'a), - infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - region_maps: &'a RegionMaps, - options: mc::MemCategorizationOptions) - -> Self +impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { + pub fn with_infer(delegate: &'a mut (Delegate<'tcx>+'a), + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + region_maps: &'a RegionMaps, + tables: &'a ty::TypeckTables<'tcx>) + -> Self { ExprUseVisitor { - mc: mc::MemCategorizationContext::with_options(infcx, region_maps, options), + mc: mc::MemCategorizationContext::with_infer(infcx, region_maps, tables), delegate, param_env, } @@ -296,7 +296,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { debug!("consume_body(body={:?})", body); for arg in &body.arguments { - let arg_ty = return_if_err!(self.mc.infcx.node_ty(arg.pat.id)); + let arg_ty = return_if_err!(self.mc.node_ty(arg.pat.id)); let fn_body_scope_r = self.tcx().node_scope_region(body.value.id); let arg_cmt = self.mc.cat_rvalue( @@ -312,7 +312,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { - self.mc.infcx.tcx + self.mc.tcx } fn delegate_consume(&mut self, @@ -322,7 +322,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { debug!("delegate_consume(consume_id={}, cmt={:?})", consume_id, cmt); - let mode = copy_or_move(self.mc.infcx, self.param_env, &cmt, DirectRefMove); + let mode = copy_or_move(&self.mc, self.param_env, &cmt, DirectRefMove); self.delegate.consume(consume_id, consume_span, cmt, mode); } @@ -441,7 +441,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { hir::ExprAddrOf(m, ref base) => { // &base // make sure that the thing we are pointing out stays valid // for the lifetime `scope_r` of the resulting ptr: - let expr_ty = return_if_err!(self.mc.infcx.node_ty(expr.id)); + let expr_ty = return_if_err!(self.mc.expr_ty(expr)); if let ty::TyRef(r, _) = expr_ty.sty { let bk = ty::BorrowKind::from_mutbl(m); self.borrow_expr(&base, r, bk, AddrOf); @@ -505,7 +505,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } hir::ExprAssignOp(_, ref lhs, ref rhs) => { - if self.mc.infcx.tables.borrow().is_method_call(expr) { + if self.mc.tables.is_method_call(expr) { self.consume_expr(lhs); } else { self.mutate_expr(expr, &lhs, MutateMode::WriteAndRead); @@ -528,7 +528,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } fn walk_callee(&mut self, call: &hir::Expr, callee: &hir::Expr) { - let callee_ty = return_if_err!(self.mc.infcx.expr_ty_adjusted(callee)); + let callee_ty = return_if_err!(self.mc.expr_ty_adjusted(callee)); debug!("walk_callee: callee={:?} callee_ty={:?}", callee, callee_ty); match callee_ty.sty { @@ -537,7 +537,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } ty::TyError => { } _ => { - let def_id = self.mc.infcx.tables.borrow().type_dependent_defs[&call.id].def_id(); + let def_id = self.mc.tables.type_dependent_defs[&call.id].def_id(); match OverloadedCallType::from_method_id(self.tcx(), def_id) { FnMutOverloadedCall => { let call_scope_r = self.tcx().node_scope_region(call.id); @@ -678,8 +678,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // consumed or borrowed as part of the automatic adjustment // process. fn walk_adjustment(&mut self, expr: &hir::Expr) { - //NOTE(@jroesch): mixed RefCell borrow causes crash - let adjustments = self.mc.infcx.tables.borrow().expr_adjustments(expr).to_vec(); + let adjustments = self.mc.tables.expr_adjustments(expr); let mut cmt = return_if_err!(self.mc.cat_expr_unadjusted(expr)); for adjustment in adjustments { debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment); @@ -796,12 +795,12 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { mode: &mut TrackMatchMode) { debug!("determine_pat_move_mode cmt_discr={:?} pat={:?}", cmt_discr, pat); - return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |_mc, cmt_pat, pat| { + return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |cmt_pat, pat| { match pat.node { PatKind::Binding(hir::BindByRef(..), ..) => mode.lub(BorrowingMatch), PatKind::Binding(hir::BindByValue(..), ..) => { - match copy_or_move(self.mc.infcx, self.param_env, &cmt_pat, PatBindingMove) { + match copy_or_move(&self.mc, self.param_env, &cmt_pat, PatBindingMove) { Copy => mode.lub(CopyingMatch), Move(..) => mode.lub(MovingMatch), } @@ -817,15 +816,13 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: MatchMode) { debug!("walk_pat cmt_discr={:?} pat={:?}", cmt_discr, pat); - let tcx = self.tcx(); - let infcx = self.mc.infcx; let ExprUseVisitor { ref mc, ref mut delegate, param_env } = *self; - return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| { + return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |cmt_pat, pat| { if let PatKind::Binding(bmode, def_id, ..) = pat.node { debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}", cmt_pat, pat, match_mode); // pat_ty: the type of the binding being produced. - let pat_ty = return_if_err!(infcx.node_ty(pat.id)); + let pat_ty = return_if_err!(mc.node_ty(pat.id)); // Each match binding is effectively an assignment to the // binding being produced. @@ -843,7 +840,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } } hir::BindByValue(..) => { - let mode = copy_or_move(infcx, param_env, &cmt_pat, PatBindingMove); + let mode = copy_or_move(mc, param_env, &cmt_pat, PatBindingMove); debug!("walk_pat binding consuming pat"); delegate.consume_pat(pat, cmt_pat, mode); } @@ -855,24 +852,18 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // the interior nodes (enum variants and structs), as opposed // to the above loop's visit of than the bindings that form // the leaves of the pattern tree structure. - return_if_err!(mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| { + return_if_err!(mc.cat_pattern(cmt_discr, pat, |cmt_pat, pat| { let qpath = match pat.node { PatKind::Path(ref qpath) | PatKind::TupleStruct(ref qpath, ..) | PatKind::Struct(ref qpath, ..) => qpath, _ => return }; - let def = infcx.tables.borrow().qpath_def(qpath, pat.id); + let def = mc.tables.qpath_def(qpath, pat.id); match def { Def::Variant(variant_did) | Def::VariantCtor(variant_did, ..) => { - let enum_did = tcx.parent_def_id(variant_did).unwrap(); - let downcast_cmt = if tcx.adt_def(enum_did).is_univariant() { - cmt_pat - } else { - let cmt_pat_ty = cmt_pat.ty; - mc.cat_downcast(pat, cmt_pat, cmt_pat_ty, variant_did) - }; + let downcast_cmt = mc.cat_downcast_if_needed(pat, cmt_pat, variant_did); debug!("variant downcast_cmt={:?} pat={:?}", downcast_cmt, pat); delegate.matched_pat(pat, downcast_cmt, match_mode); @@ -896,13 +887,13 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { 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(); + let upvar_capture = self.mc.tables.upvar_capture(upvar_id); let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id, fn_decl_span, freevar.def)); match upvar_capture { ty::UpvarCapture::ByValue => { - let mode = copy_or_move(self.mc.infcx, + let mode = copy_or_move(&self.mc, self.param_env, &cmt_var, CaptureMove); @@ -929,18 +920,18 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // Create the cmt for the variable being borrowed, from the // caller's perspective 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)?; + let var_ty = self.mc.node_ty(var_id)?; self.mc.cat_def(closure_id, closure_span, var_ty, upvar_def) } } -fn copy_or_move<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, +fn copy_or_move<'a, 'gcx, 'tcx>(mc: &mc::MemCategorizationContext<'a, 'gcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, cmt: &mc::cmt<'tcx>, move_reason: MoveReason) -> ConsumeMode { - if infcx.type_moves_by_default(param_env, cmt.ty, cmt.span) { + if mc.type_moves_by_default(param_env, cmt.ty, cmt.span) { Move(move_reason) } else { Copy diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index 57815b7f0b..d29622b4a8 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -20,7 +20,7 @@ use hir; pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut visitor = ItemVisitor { - tcx: tcx + tcx, }; tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor()); } @@ -66,11 +66,8 @@ fn unpack_option_like<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl<'a, 'tcx> ExprVisitor<'a, 'tcx> { fn def_id_is_transmute(&self, def_id: DefId) -> bool { - let intrinsic = match self.tcx.type_of(def_id).sty { - ty::TyFnDef(.., bfty) => bfty.abi() == RustIntrinsic, - _ => return false - }; - intrinsic && self.tcx.item_name(def_id) == "transmute" + self.tcx.fn_sig(def_id).abi() == RustIntrinsic && + self.tcx.item_name(def_id) == "transmute" } fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>) { @@ -86,17 +83,16 @@ impl<'a, 'tcx> ExprVisitor<'a, 'tcx> { // Special-case transmutting from `typeof(function)` and // `Option` to present a clearer error. let from = unpack_option_like(self.tcx.global_tcx(), from); - match (&from.sty, sk_to) { - (&ty::TyFnDef(..), SizeSkeleton::Known(size_to)) - if size_to == Pointer.size(self.tcx) => { + if let (&ty::TyFnDef(..), SizeSkeleton::Known(size_to)) = (&from.sty, sk_to) { + if size_to == Pointer.size(self.tcx) { struct_span_err!(self.tcx.sess, span, E0591, - "`{}` is zero-sized and can't be transmuted to `{}`", - from, to) - .span_note(span, "cast with `as` to a pointer instead") + "can't transmute zero-sized type") + .note(&format!("source type: {}", from)) + .note(&format!("target type: {}", to)) + .help("cast with `as` to a pointer instead") .emit(); return; } - _ => {} } } @@ -111,7 +107,7 @@ impl<'a, 'tcx> ExprVisitor<'a, 'tcx> { } Err(LayoutError::Unknown(bad)) => { if bad == ty { - format!("size can vary") + format!("this type's size can vary") } else { format!("size can vary because of {}", bad) } @@ -121,14 +117,9 @@ impl<'a, 'tcx> ExprVisitor<'a, 'tcx> { }; struct_span_err!(self.tcx.sess, span, E0512, - "transmute called with differently sized types: \ - {} ({}) to {} ({})", - from, skeleton_string(from, sk_from), - to, skeleton_string(to, sk_to)) - .span_label(span, - format!("transmuting between {} and {}", - skeleton_string(from, sk_from), - skeleton_string(to, sk_to))) + "transmute called with types of different sizes") + .note(&format!("source type: {} ({})", from, skeleton_string(from, sk_from))) + .note(&format!("target type: {} ({})", to, skeleton_string(to, sk_to))) .emit(); } } @@ -159,22 +150,14 @@ impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> { } else { Def::Err }; - match def { - Def::Fn(did) if self.def_id_is_transmute(did) => { + if let Def::Fn(did) = def { + if self.def_id_is_transmute(did) { let typ = self.tables.node_id_to_type(expr.id); - let typ = self.tcx.lift_to_global(&typ).unwrap(); - match typ.sty { - ty::TyFnDef(.., sig) if sig.abi() == RustIntrinsic => { - let from = sig.inputs().skip_binder()[0]; - let to = *sig.output().skip_binder(); - self.check_transmute(expr.span, from, to); - } - _ => { - span_bug!(expr.span, "transmute wasn't a bare fn?!"); - } - } + let sig = typ.fn_sig(self.tcx); + let from = sig.inputs().skip_binder()[0]; + let to = *sig.output().skip_binder(); + self.check_transmute(expr.span, from, to); } - _ => {} } intravisit::walk_expr(self, expr); diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 3b506d748e..01ed79096b 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -156,10 +156,10 @@ impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> { $( item_refs.insert($name, $variant as usize); )* LanguageItemCollector { - session: session, - hir_map: hir_map, + session, + hir_map, items: LanguageItems::new(), - item_refs: item_refs, + item_refs, } } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index c6a42be613..551a550442 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -269,7 +269,7 @@ struct IrMaps<'a, 'tcx: 'a> { impl<'a, 'tcx> IrMaps<'a, 'tcx> { fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> IrMaps<'a, 'tcx> { IrMaps { - tcx: tcx, + tcx, num_live_nodes: 0, num_vars: 0, live_node_map: NodeMap(), @@ -385,7 +385,7 @@ fn visit_local<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, local: &'tcx hir::Local) { ir.add_live_node_for_node(p_id, VarDefNode(sp)); ir.add_variable(Local(LocalInfo { id: p_id, - name: name + name, })); }); intravisit::walk_local(ir, local); @@ -400,7 +400,7 @@ fn visit_arm<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, arm: &'tcx hir::Arm) { ir.add_live_node_for_node(p_id, VarDefNode(sp)); ir.add_variable(Local(LocalInfo { id: p_id, - name: name + name, })); }) } @@ -534,8 +534,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { let num_vars = ir.num_vars; Liveness { - ir: ir, - tables: tables, + ir, + tables, s: specials, successors: vec![invalid_node(); num_live_nodes], users: vec![invalid_users(); num_live_nodes * num_vars], diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index c114aa1d7a..557d4b24f3 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -76,6 +76,7 @@ use infer::InferCtxt; use hir::def::{Def, CtorKind}; use ty::adjustment; use ty::{self, Ty, TyCtxt}; +use ty::fold::TypeFoldable; use hir::{MutImmutable, MutMutable, PatKind}; use hir::pat_util::EnumerateAndAdjustIterator; @@ -281,20 +282,10 @@ impl ast_node for hir::Pat { #[derive(Clone)] pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + pub tcx: TyCtxt<'a, 'gcx, 'tcx>, pub region_maps: &'a RegionMaps, - options: MemCategorizationOptions, -} - -#[derive(Copy, Clone, Default)] -pub struct MemCategorizationOptions { - // If true, then when analyzing a closure upvar, if the closure - // has a missing kind, we treat it like a Fn closure. When false, - // we ICE if the closure has a missing kind. Should be false - // except during closure kind inference. It is used by the - // mem-categorization code to be able to have stricter assertions - // (which are always true except during upvar inference). - pub during_closure_kind_inference: bool, + pub tables: &'a ty::TypeckTables<'tcx>, + infcx: Option<&'a InferCtxt<'a, 'gcx, 'tcx>>, } pub type McResult = Result; @@ -395,51 +386,90 @@ impl MutabilityCategory { } } -impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { - /// Context should be the `DefId` we use to fetch region-maps. - pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - region_maps: &'a RegionMaps) - -> MemCategorizationContext<'a, 'gcx, 'tcx> { - MemCategorizationContext::with_options(infcx, - region_maps, - MemCategorizationOptions::default()) +impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx, 'tcx> { + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, + region_maps: &'a RegionMaps, + tables: &'a ty::TypeckTables<'tcx>) + -> MemCategorizationContext<'a, 'tcx, 'tcx> { + MemCategorizationContext { tcx, region_maps, tables, infcx: None } } +} - pub fn with_options(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - region_maps: &'a RegionMaps, - options: MemCategorizationOptions) - -> MemCategorizationContext<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { + pub fn with_infer(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + region_maps: &'a RegionMaps, + tables: &'a ty::TypeckTables<'tcx>) + -> MemCategorizationContext<'a, 'gcx, 'tcx> { MemCategorizationContext { - infcx: infcx, - region_maps: region_maps, - options: options, + tcx: infcx.tcx, + region_maps, + tables, + infcx: Some(infcx), } } - fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { - self.infcx.tcx + pub fn type_moves_by_default(&self, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + span: Span) + -> bool { + self.infcx.map(|infcx| infcx.type_moves_by_default(param_env, ty, span)) + .or_else(|| { + self.tcx.lift_to_global(&(param_env, ty)).map(|(param_env, ty)| { + ty.moves_by_default(self.tcx.global_tcx(), param_env, span) + }) + }) + .unwrap_or(true) + } + + fn resolve_type_vars_if_possible(&self, value: &T) -> T + where T: TypeFoldable<'tcx> + { + self.infcx.map(|infcx| infcx.resolve_type_vars_if_possible(value)) + .unwrap_or_else(|| value.clone()) + } + + fn is_tainted_by_errors(&self) -> bool { + self.infcx.map_or(false, |infcx| infcx.is_tainted_by_errors()) } - fn expr_ty(&self, expr: &hir::Expr) -> McResult> { - match self.infcx.node_ty(expr.id) { - Ok(t) => Ok(t), - Err(()) => { - debug!("expr_ty({:?}) yielded Err", expr); - Err(()) + fn resolve_type_vars_or_error(&self, + id: ast::NodeId, + ty: Option>) + -> McResult> { + match ty { + Some(ty) => { + let ty = self.resolve_type_vars_if_possible(&ty); + if ty.references_error() || ty.is_ty_var() { + debug!("resolve_type_vars_or_error: error from {:?}", ty); + Err(()) + } else { + Ok(ty) + } + } + // FIXME + None if self.is_tainted_by_errors() => Err(()), + None => { + bug!("no type for node {}: {} in mem_categorization", + id, self.tcx.hir.node_to_string(id)); } } } - fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult> { - self.infcx.expr_ty_adjusted(expr) + pub fn node_ty(&self, id: ast::NodeId) -> McResult> { + self.resolve_type_vars_or_error(id, self.tables.node_id_to_type_opt(id)) } - fn node_ty(&self, id: ast::NodeId) -> McResult> { - self.infcx.node_ty(id) + pub fn expr_ty(&self, expr: &hir::Expr) -> McResult> { + self.resolve_type_vars_or_error(expr.id, self.tables.expr_ty_opt(expr)) + } + + pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult> { + self.resolve_type_vars_or_error(expr.id, self.tables.expr_ty_adjusted_opt(expr)) } fn pat_ty(&self, pat: &hir::Pat) -> McResult> { - let base_ty = self.infcx.node_ty(pat.id)?; + let base_ty = self.node_ty(pat.id)?; // FIXME (Issue #18207): This code detects whether we are // looking at a `ref x`, and if so, figures out what the type // *being borrowed* is. But ideally we would put in a more @@ -479,7 +509,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } } - helper(self, expr, self.infcx.tables.borrow().expr_adjustments(expr)) + helper(self, expr, self.tables.expr_adjustments(expr)) } pub fn cat_expr_adjusted(&self, expr: &hir::Expr, @@ -496,12 +526,12 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { where F: FnOnce() -> McResult> { debug!("cat_expr_adjusted_with({:?}): {:?}", adjustment, expr); - let target = self.infcx.resolve_type_vars_if_possible(&adjustment.target); + let target = self.resolve_type_vars_if_possible(&adjustment.target); match adjustment.kind { adjustment::Adjust::Deref(overloaded) => { // Equivalent to *expr or something similar. let base = if let Some(deref) = overloaded { - let ref_ty = self.tcx().mk_ref(deref.region, ty::TypeAndMut { + let ref_ty = self.tcx.mk_ref(deref.region, ty::TypeAndMut { ty: target, mutbl: deref.mutbl, }); @@ -531,7 +561,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { let expr_ty = self.expr_ty(expr)?; match expr.node { hir::ExprUnary(hir::UnDeref, ref e_base) => { - if self.infcx.tables.borrow().is_method_call(expr) { + if self.tables.is_method_call(expr) { self.cat_overloaded_lvalue(expr, e_base, false) } else { let base_cmt = self.cat_expr(&e_base)?; @@ -554,7 +584,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } hir::ExprIndex(ref base, _) => { - if self.infcx.tables.borrow().is_method_call(expr) { + if self.tables.is_method_call(expr) { // If this is an index implemented by a method call, then it // will include an implicit deref of the result. // The call to index() returns a `&T` value, which @@ -568,7 +598,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } hir::ExprPath(ref qpath) => { - let def = self.infcx.tables.borrow().qpath_def(qpath, expr.id); + let def = self.tables.qpath_def(qpath, expr.id); self.cat_def(expr.id, expr.span, expr_ty, def) } @@ -619,49 +649,17 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } Def::Upvar(def_id, _, fn_node_id) => { - 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, _) => { - match self.infcx.closure_kind(closure_id) { - Some(kind) => { - self.cat_upvar(id, span, var_id, fn_node_id, kind) - } - None => { - if !self.options.during_closure_kind_inference { - span_bug!( - span, - "No closure kind for {:?}", - closure_id); - } - - // during closure kind inference, we - // don't know the closure kind yet, but - // it's ok because we detect that we are - // accessing an upvar and handle that - // case specially anyhow. Use Fn - // arbitrarily. - self.cat_upvar(id, span, var_id, fn_node_id, ty::ClosureKind::Fn) - } - } - } - _ => { - span_bug!( - span, - "Upvar of non-closure {} - {:?}", - fn_node_id, - ty); - } - } + let var_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); + self.cat_upvar(id, span, var_id, fn_node_id) } Def::Local(def_id) => { - let vid = self.tcx().hir.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, + id, + span, cat: Categorization::Local(vid), - mutbl: MutabilityCategory::from_local(self.tcx(), vid), + mutbl: MutabilityCategory::from_local(self.tcx, vid), ty: expr_ty, note: NoteNone })) @@ -677,8 +675,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { id: ast::NodeId, span: Span, var_id: ast::NodeId, - fn_node_id: ast::NodeId, - kind: ty::ClosureKind) + fn_node_id: ast::NodeId) -> McResult> { // An upvar can have up to 3 components. We translate first to a @@ -704,19 +701,24 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // FnMut | copied -> &'env mut | upvar -> &'env mut -> &'up bk // FnOnce | copied | upvar -> &'up bk - let upvar_id = ty::UpvarId { var_id: var_id, + let kind = match self.tables.closure_kinds.get(&fn_node_id) { + Some(&(kind, _)) => kind, + None => span_bug!(span, "missing closure kind") + }; + + let upvar_id = ty::UpvarId { var_id, closure_expr_id: fn_node_id }; let var_ty = self.node_ty(var_id)?; // Mutability of original variable itself - let var_mutbl = MutabilityCategory::from_local(self.tcx(), var_id); + let var_mutbl = MutabilityCategory::from_local(self.tcx, var_id); // Construct the upvar. This represents access to the field // from the environment (perhaps we should eventually desugar // this field further, but it will do for now). let cmt_result = cmt_ { - id: id, - span: span, + id, + span, cat: Categorization::Upvar(Upvar {id: upvar_id, kind: kind}), mutbl: var_mutbl, ty: var_ty, @@ -741,9 +743,9 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // If this is a by-ref capture, then the upvar we loaded is // actually a reference, so we have to add an implicit deref // for that. - let upvar_id = ty::UpvarId { var_id: var_id, + let upvar_id = ty::UpvarId { var_id, closure_expr_id: fn_node_id }; - let upvar_capture = self.infcx.upvar_capture(upvar_id).unwrap(); + let upvar_capture = self.tables.upvar_capture(upvar_id); let cmt_result = match upvar_capture { ty::UpvarCapture::ByValue => { cmt_result @@ -751,8 +753,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { ty::UpvarCapture::ByRef(upvar_borrow) => { let ptr = BorrowedPtr(upvar_borrow.kind, upvar_borrow.region); cmt_ { - id: id, - span: span, + id, + span, cat: Categorization::Deref(Rc::new(cmt_result), ptr), mutbl: MutabilityCategory::from_borrow_kind(upvar_borrow.kind), ty: var_ty, @@ -776,11 +778,11 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { -> cmt_<'tcx> { // Region of environment pointer - let env_region = self.tcx().mk_region(ty::ReFree(ty::FreeRegion { + let env_region = self.tcx.mk_region(ty::ReFree(ty::FreeRegion { // The environment of a closure is guaranteed to // outlive any bindings introduced in the body of the // closure itself. - scope: self.tcx().hir.local_def_id(upvar_id.closure_expr_id), + scope: self.tcx.hir.local_def_id(upvar_id.closure_expr_id), bound_region: ty::BrEnv })); @@ -797,7 +799,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // one. let cmt_result = cmt_ { mutbl: McImmutable, - ty: self.tcx().types.err, + ty: self.tcx.types.err, ..cmt_result }; @@ -811,8 +813,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } let ret = cmt_ { - id: id, - span: span, + id, + span, cat: Categorization::Deref(Rc::new(cmt_result), env_ptr), mutbl: deref_mutbl, ty: var_ty, @@ -829,7 +831,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { pub fn temporary_scope(&self, id: ast::NodeId) -> ty::Region<'tcx> { let scope = self.region_maps.temporary_scope(id); - self.tcx().mk_region(match scope { + self.tcx.mk_region(match scope { Some(scope) => ty::ReScope(scope), None => ty::ReStatic }) @@ -840,20 +842,20 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { span: Span, expr_ty: Ty<'tcx>) -> cmt<'tcx> { - let promotable = self.tcx().rvalue_promotable_to_static.borrow().get(&id).cloned() + let promotable = self.tcx.rvalue_promotable_to_static.borrow().get(&id).cloned() .unwrap_or(false); // When the corresponding feature isn't toggled, only promote `[T; 0]`. let promotable = match expr_ty.sty { ty::TyArray(_, 0) => true, - _ => promotable && self.tcx().sess.features.borrow().rvalue_static_promotion, + _ => promotable && self.tcx.sess.features.borrow().rvalue_static_promotion, }; // 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 promotable { - self.tcx().types.re_static + self.tcx.types.re_static } else { self.temporary_scope(id) }; @@ -934,7 +936,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { span_bug!(expr.span, "cat_overloaded_lvalue: base is not a reference") } }; - let ref_ty = self.tcx().mk_ref(region, ty::TypeAndMut { + let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut { ty: lvalue_ty, mutbl, }); @@ -1030,33 +1032,40 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { ret } - pub fn cat_downcast(&self, - node: &N, - base_cmt: cmt<'tcx>, - downcast_ty: Ty<'tcx>, - variant_did: DefId) - -> cmt<'tcx> { - let ret = Rc::new(cmt_ { - id: node.id(), - span: node.span(), - mutbl: base_cmt.mutbl.inherit(), - cat: Categorization::Downcast(base_cmt, variant_did), - ty: downcast_ty, - note: NoteNone - }); - debug!("cat_downcast ret={:?}", ret); - ret + pub fn cat_downcast_if_needed(&self, + node: &N, + base_cmt: cmt<'tcx>, + variant_did: DefId) + -> cmt<'tcx> { + // univariant enums do not need downcasts + let base_did = self.tcx.parent_def_id(variant_did).unwrap(); + if !self.tcx.adt_def(base_did).is_univariant() { + let base_ty = base_cmt.ty; + let ret = Rc::new(cmt_ { + id: node.id(), + span: node.span(), + mutbl: base_cmt.mutbl.inherit(), + cat: Categorization::Downcast(base_cmt, variant_did), + ty: base_ty, + note: NoteNone + }); + debug!("cat_downcast ret={:?}", ret); + ret + } else { + debug!("cat_downcast univariant={:?}", base_cmt); + base_cmt + } } pub fn cat_pattern(&self, cmt: cmt<'tcx>, pat: &hir::Pat, mut op: F) -> McResult<()> - where F: FnMut(&MemCategorizationContext<'a, 'gcx, 'tcx>, cmt<'tcx>, &hir::Pat), + where F: FnMut(cmt<'tcx>, &hir::Pat), { self.cat_pattern_(cmt, pat, &mut op) } // FIXME(#19596) This is a workaround, but there should be a better way to do this fn cat_pattern_(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McResult<()> - where F : FnMut(&MemCategorizationContext<'a, 'gcx, 'tcx>, cmt<'tcx>, &hir::Pat) + where F : FnMut(cmt<'tcx>, &hir::Pat) { // Here, `cmt` is the categorization for the value being // matched and pat is the pattern it is being matched against. @@ -1105,47 +1114,25 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { debug!("cat_pattern: {:?} cmt={:?}", pat, cmt); - op(self, cmt.clone(), pat); - - // Note: This goes up here (rather than within the PatKind::TupleStruct arm - // alone) because PatKind::Struct can also refer to variants. - let cmt = match pat.node { - PatKind::Path(hir::QPath::Resolved(_, ref path)) | - PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) | - PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => { - match path.def { - Def::Err => { - debug!("access to unresolvable pattern {:?}", pat); - return Err(()) - } - Def::Variant(variant_did) | - Def::VariantCtor(variant_did, ..) => { - // univariant enums do not need downcasts - let enum_did = self.tcx().parent_def_id(variant_did).unwrap(); - if !self.tcx().adt_def(enum_did).is_univariant() { - self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did) - } else { - cmt - } - } - _ => cmt - } - } - _ => cmt - }; + op(cmt.clone(), pat); match pat.node { PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => { - let def = self.infcx.tables.borrow().qpath_def(qpath, pat.id); - let expected_len = match def { + let def = self.tables.qpath_def(qpath, pat.id); + let (cmt, expected_len) = match def { + Def::Err => { + debug!("access to unresolvable pattern {:?}", pat); + return Err(()) + } Def::VariantCtor(def_id, CtorKind::Fn) => { - let enum_def = self.tcx().parent_def_id(def_id).unwrap(); - self.tcx().adt_def(enum_def).variant_with_id(def_id).fields.len() + let enum_def = self.tcx.parent_def_id(def_id).unwrap(); + (self.cat_downcast_if_needed(pat, cmt, def_id), + self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len()) } Def::StructCtor(_, CtorKind::Fn) => { match self.pat_ty(&pat)?.sty { ty::TyAdt(adt_def, _) => { - adt_def.struct_variant().fields.len() + (cmt, adt_def.struct_variant().fields.len()) } ref ty => { span_bug!(pat.span, "tuple struct pattern unexpected type {:?}", ty); @@ -1166,8 +1153,21 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } } - PatKind::Struct(_, ref field_pats, _) => { + PatKind::Struct(ref qpath, ref field_pats, _) => { // {f1: p1, ..., fN: pN} + let def = self.tables.qpath_def(qpath, pat.id); + let cmt = match def { + Def::Err => { + debug!("access to unresolvable pattern {:?}", pat); + return Err(()) + }, + Def::Variant(variant_did) | + Def::VariantCtor(variant_did, ..) => { + self.cat_downcast_if_needed(pat, cmt, variant_did) + }, + _ => cmt + }; + for fp in field_pats { let field_ty = self.pat_ty(&fp.node.pat)?; // see (*2) let cmt_field = self.cat_field(pat, cmt.clone(), fp.node.name, field_ty); diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index c2f69147e3..df828c8d8e 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -374,11 +374,11 @@ fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> *ty == config::CrateTypeProcMacro }); let mut reachable_context = ReachableContext { - tcx: tcx, + tcx, tables: &ty::TypeckTables::empty(), reachable_symbols: NodeSet(), worklist: Vec::new(), - any_library: any_library, + any_library, }; // Step 1: Seed the worklist with all nodes which were found to be public as @@ -398,8 +398,8 @@ fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> } { let mut collect_private_impl_items = CollectPrivateImplItemsVisitor { - tcx: tcx, - access_levels: access_levels, + tcx, + access_levels, worklist: &mut reachable_context.worklist, }; tcx.hir.krate().visit_all_item_likes(&mut collect_private_impl_items); diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 1a07423bcb..c4f785757c 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -28,6 +28,7 @@ use syntax::attr; use syntax::ptr::P; use syntax_pos::Span; use errors::DiagnosticBuilder; +use util::common::ErrorReported; use util::nodemap::{NodeMap, NodeSet, FxHashSet, FxHashMap, DefIdMap}; use rustc_back::slice; @@ -255,7 +256,7 @@ const ROOT_SCOPE: ScopeRef<'static> = &Scope::Root; pub fn krate(sess: &Session, hir_map: &Map) - -> Result { + -> Result { let krate = hir_map.krate(); let mut map = NamedRegionMap { defs: NodeMap(), @@ -265,8 +266,8 @@ pub fn krate(sess: &Session, }; sess.track_errors(|| { let mut visitor = LifetimeContext { - sess: sess, - hir_map: hir_map, + sess, + hir_map, map: &mut map, scope: ROOT_SCOPE, trait_ref_hack: false, @@ -340,7 +341,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { Region::early(&mut index, def) }).collect(); let scope = Scope::Binder { - lifetimes: lifetimes, + lifetimes, s: ROOT_SCOPE }; self.with(scope, |old_scope, this| { @@ -776,13 +777,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let xcrate_object_lifetime_defaults = replace(&mut self.xcrate_object_lifetime_defaults, DefIdMap()); let mut this = LifetimeContext { - sess: sess, - hir_map: hir_map, + sess, + hir_map, map: *map, scope: &wrap_scope, trait_ref_hack: self.trait_ref_hack, - labels_in_fn: labels_in_fn, - xcrate_object_lifetime_defaults: xcrate_object_lifetime_defaults, + labels_in_fn, + xcrate_object_lifetime_defaults, }; debug!("entering scope {:?}", this.scope); f(self.scope, &mut this); @@ -848,7 +849,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { }).collect(); let scope = Scope::Binder { - lifetimes: lifetimes, + lifetimes, s: self.scope }; self.with(scope, move |old_scope, this| { @@ -1205,7 +1206,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { }; let scope = Scope::Elision { - elide: elide, + elide, s: self.scope }; self.with(scope, |_, this| this.visit_ty(output)); @@ -1363,7 +1364,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { m.push_str(&(if n == 1 { help_name } else { - format!("one of {}'s {} elided {}lifetimes", help_name, n, + format!("one of {}'s {} {}lifetimes", help_name, n, if have_bound_regions { "free " } else { "" } ) })[..]); @@ -1619,7 +1620,7 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap, map.issue_32330.insert( lifetime.lifetime.id, ty::Issue32330 { - fn_def_id: fn_def_id, + fn_def_id, region_name: name, }); continue; diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index e27990c29c..668a8693d3 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -70,14 +70,14 @@ impl DeprecationEntry { fn local(attr: Deprecation, id: DefId) -> DeprecationEntry { assert!(id.is_local()); DeprecationEntry { - attr: attr, + attr, origin: Some(id.index), } } fn external(attr: Deprecation) -> DeprecationEntry { DeprecationEntry { - attr: attr, + attr, origin: None, } } @@ -384,7 +384,7 @@ impl<'a, 'tcx> Index<'tcx> { let krate = tcx.hir.krate(); let mut annotator = Annotator { - tcx: tcx, + tcx, index: self, parent_stab: None, parent_depr: None, @@ -424,7 +424,7 @@ impl<'a, 'tcx> Index<'tcx> { let mut staged_api = FxHashMap(); staged_api.insert(LOCAL_CRATE, is_staged_api); Index { - staged_api: staged_api, + staged_api, stab_map: DefIdMap(), depr_map: DefIdMap(), active_features: FxHashSet(), @@ -717,8 +717,8 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { if tcx.stability.borrow().staged_api[&LOCAL_CRATE] { let krate = tcx.hir.krate(); let mut missing = MissingStabilityAnnotations { - tcx: tcx, - access_levels: access_levels, + tcx, + access_levels, }; missing.check_missing_stability(ast::CRATE_NODE_ID, krate.span); intravisit::walk_crate(&mut missing, krate); @@ -728,6 +728,7 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let ref declared_lib_features = sess.features.borrow().declared_lib_features; let mut remaining_lib_features: FxHashMap = declared_lib_features.clone().into_iter().collect(); + remaining_lib_features.remove(&Symbol::intern("proc_macro")); fn format_stable_since_msg(version: &str) -> String { format!("this feature has been stable since {}. Attribute no longer needed", version) diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 799686ceca..73c702fedb 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -35,9 +35,9 @@ impl serialize::Decodable for Cache { } } -impl<'a, 'tcx> HashStable> for Cache { +impl<'a, 'gcx, 'tcx> HashStable> for Cache { fn hash_stable(&self, - _: &mut StableHashingContext<'a, 'tcx>, + _: &mut StableHashingContext<'a, 'gcx, 'tcx>, _: &mut StableHasher) { // do nothing } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 80c4291719..d176ae761e 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -12,6 +12,7 @@ use graphviz::IntoCow; use middle::const_val::ConstVal; +use middle::region::CodeExtent; use rustc_const_math::{ConstUsize, ConstInt, ConstMathErr}; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc_data_structures::control_flow_graph::dominators::{Dominators, dominators}; @@ -65,6 +66,25 @@ macro_rules! newtype_index { ) } +/// Types for locals +type LocalDecls<'tcx> = IndexVec>; + +pub trait HasLocalDecls<'tcx> { + fn local_decls(&self) -> &LocalDecls<'tcx>; +} + +impl<'tcx> HasLocalDecls<'tcx> for LocalDecls<'tcx> { + fn local_decls(&self) -> &LocalDecls<'tcx> { + self + } +} + +impl<'tcx> HasLocalDecls<'tcx> for Mir<'tcx> { + fn local_decls(&self) -> &LocalDecls<'tcx> { + &self.local_decls + } +} + /// Lowered representation of a single function. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Mir<'tcx> { @@ -89,7 +109,7 @@ pub struct Mir<'tcx> { /// The first local is the return value pointer, followed by `arg_count` /// locals for the function arguments, followed by any user-declared /// variables and temporaries. - pub local_decls: IndexVec>, + pub local_decls: LocalDecls<'tcx>, /// Number of arguments this function takes. /// @@ -135,15 +155,15 @@ impl<'tcx> Mir<'tcx> { assert_eq!(local_decls[RETURN_POINTER].ty, return_ty); Mir { - basic_blocks: basic_blocks, - visibility_scopes: visibility_scopes, - promoted: promoted, - return_ty: return_ty, - local_decls: local_decls, - arg_count: arg_count, - upvar_decls: upvar_decls, + basic_blocks, + visibility_scopes, + promoted, + return_ty, + local_decls, + arg_count, + upvar_decls, spread_arg: None, - span: span, + span, cache: cache::Cache::new() } } @@ -394,10 +414,10 @@ impl<'tcx> LocalDecl<'tcx> { pub fn new_temp(ty: Ty<'tcx>, span: Span) -> Self { LocalDecl { mutability: Mutability::Mut, - ty: ty, + ty, name: None, source_info: SourceInfo { - span: span, + span, scope: ARGUMENT_VISIBILITY_SCOPE }, is_user_variable: false @@ -413,7 +433,7 @@ impl<'tcx> LocalDecl<'tcx> { mutability: Mutability::Mut, ty: return_ty, source_info: SourceInfo { - span: span, + span, scope: ARGUMENT_VISIBILITY_SCOPE }, name: None, // FIXME maybe we do want some name here? @@ -628,7 +648,7 @@ impl<'tcx> BasicBlockData<'tcx> { pub fn new(terminator: Option>) -> BasicBlockData<'tcx> { BasicBlockData { statements: vec![], - terminator: terminator, + terminator, is_cleanup: false, } } @@ -804,6 +824,10 @@ pub enum StatementKind<'tcx> { inputs: Vec> }, + /// Mark one terminating point of an extent (i.e. static region). + /// (The starting point(s) arise implicitly from borrows.) + EndRegion(CodeExtent), + /// No-op. Useful for deleting instructions without affecting statement indices. Nop, } @@ -813,6 +837,8 @@ impl<'tcx> Debug for Statement<'tcx> { use self::StatementKind::*; match self.kind { Assign(ref lv, ref rv) => write!(fmt, "{:?} = {:?}", lv, rv), + // (reuse lifetime rendering policy from ppaux.) + EndRegion(ref ce) => write!(fmt, "EndRegion({})", ty::ReScope(*ce)), StorageLive(ref lv) => write!(fmt, "StorageLive({:?})", lv), StorageDead(ref lv) => write!(fmt, "StorageDead({:?})", lv), SetDiscriminant{lvalue: ref lv, variant_index: index} => { @@ -934,7 +960,7 @@ impl<'tcx> Lvalue<'tcx> { pub fn elem(self, elem: LvalueElem<'tcx>) -> Lvalue<'tcx> { Lvalue::Projection(Box::new(LvalueProjection { base: self, - elem: elem, + elem, })) } } @@ -1016,7 +1042,7 @@ impl<'tcx> Operand<'tcx> { span: Span, ) -> Self { Operand::Constant(box Constant { - span: span, + span, ty: tcx.type_of(def_id).subst(tcx, substs), literal: Literal::Value { value: ConstVal::Function(def_id, substs) }, }) @@ -1176,12 +1202,22 @@ impl<'tcx> Debug for Rvalue<'tcx> { UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a), Discriminant(ref lval) => write!(fmt, "discriminant({:?})", lval), NullaryOp(ref op, ref t) => write!(fmt, "{:?}({:?})", op, t), - Ref(_, borrow_kind, ref lv) => { + Ref(region, borrow_kind, ref lv) => { let kind_str = match borrow_kind { BorrowKind::Shared => "", BorrowKind::Mut | BorrowKind::Unique => "mut ", }; - write!(fmt, "&{}{:?}", kind_str, lv) + + // When identifying regions, add trailing space if + // necessary. + let region = if ppaux::identify_regions() { + let mut region = format!("{}", region); + if region.len() > 0 { region.push(' '); } + region + } else { + "".to_owned() + }; + write!(fmt, "&{}{}{:?}", region, kind_str, lv) } Aggregate(ref kind, ref lvs) => { @@ -1224,7 +1260,11 @@ impl<'tcx> Debug for Rvalue<'tcx> { AggregateKind::Closure(def_id, _) => ty::tls::with(|tcx| { if let Some(node_id) = tcx.hir.as_local_node_id(def_id) { - let name = format!("[closure@{:?}]", tcx.hir.span(node_id)); + let name = if tcx.sess.opts.debugging_opts.span_free_formats { + format!("[closure@{:?}]", node_id) + } else { + format!("[closure@{:?}]", tcx.hir.span(node_id)) + }; let mut struct_fmt = fmt.debug_struct(&name); tcx.with_freevars(node_id, |freevars| { @@ -1449,7 +1489,7 @@ impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> { Assign(ref lval, ref rval) => Assign(lval.fold_with(folder), rval.fold_with(folder)), SetDiscriminant { ref lvalue, variant_index } => SetDiscriminant { lvalue: lvalue.fold_with(folder), - variant_index: variant_index + variant_index, }, StorageLive(ref lval) => StorageLive(lval.fold_with(folder)), StorageDead(ref lval) => StorageDead(lval.fold_with(folder)), @@ -1458,11 +1498,18 @@ impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> { outputs: outputs.fold_with(folder), inputs: inputs.fold_with(folder) }, + + // Note for future: If we want to expose the extents + // during the fold, we need to either generalize EndRegion + // to carry `[ty::Region]`, or extend the `TypeFolder` + // trait with a `fn fold_extent`. + EndRegion(ref extent) => EndRegion(extent.clone()), + Nop => Nop, }; Statement { source_info: self.source_info, - kind: kind + kind, } } @@ -1476,6 +1523,13 @@ impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> { StorageDead(ref lvalue) => lvalue.visit_with(visitor), InlineAsm { ref outputs, ref inputs, .. } => outputs.visit_with(visitor) || inputs.visit_with(visitor), + + // Note for future: If we want to expose the extents + // during the visit, we need to either generalize EndRegion + // to carry `[ty::Region]`, or extend the `TypeVisitor` + // trait with a `fn visit_extent`. + EndRegion(ref _extent) => false, + Nop => false, } } @@ -1495,14 +1549,14 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { }, Drop { ref location, target, unwind } => Drop { location: location.fold_with(folder), - target: target, - unwind: unwind + target, + unwind, }, DropAndReplace { ref location, ref value, target, unwind } => DropAndReplace { location: location.fold_with(folder), value: value.fold_with(folder), - target: target, - unwind: unwind + target, + unwind, }, Call { ref func, ref args, ref destination, cleanup } => { let dest = destination.as_ref().map(|&(ref loc, dest)| { @@ -1513,7 +1567,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { func: func.fold_with(folder), args: args.fold_with(folder), destination: dest, - cleanup: cleanup + cleanup, } }, Assert { ref cond, expected, ref msg, target, cleanup } => { @@ -1527,10 +1581,10 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { }; Assert { cond: cond.fold_with(folder), - expected: expected, - msg: msg, - target: target, - cleanup: cleanup + expected, + msg, + target, + cleanup, } }, Resume => Resume, @@ -1539,7 +1593,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { }; Terminator { source_info: self.source_info, - kind: kind + kind, } } @@ -1681,8 +1735,8 @@ impl<'tcx, B, V> TypeFoldable<'tcx> for Projection<'tcx, B, V> }; Projection { - base: base, - elem: elem + base, + elem, } } @@ -1715,7 +1769,7 @@ impl<'tcx> TypeFoldable<'tcx> for Literal<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { match *self { Literal::Item { def_id, substs } => Literal::Item { - def_id: def_id, + def_id, substs: substs.fold_with(folder) }, _ => self.clone() diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 6078778a61..1af80771fb 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -58,7 +58,7 @@ impl<'a, 'gcx, 'tcx> LvalueTy<'tcx> { }) .ty; LvalueTy::Ty { - ty: ty, + ty, } } ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => @@ -85,8 +85,8 @@ impl<'a, 'gcx, 'tcx> LvalueTy<'tcx> { assert!(adt_def.is_enum()); assert!(index < adt_def.variants.len()); assert_eq!(adt_def, adt_def1); - LvalueTy::Downcast { adt_def: adt_def, - substs: substs, + LvalueTy::Downcast { adt_def, + substs, variant_index: index } } _ => { @@ -104,9 +104,9 @@ impl<'tcx> TypeFoldable<'tcx> for LvalueTy<'tcx> { LvalueTy::Ty { ty } => LvalueTy::Ty { ty: ty.fold_with(folder) }, LvalueTy::Downcast { adt_def, substs, variant_index } => { LvalueTy::Downcast { - adt_def: adt_def, + adt_def, substs: substs.fold_with(folder), - variant_index: variant_index + variant_index, } } } @@ -121,31 +121,34 @@ impl<'tcx> TypeFoldable<'tcx> for LvalueTy<'tcx> { } impl<'tcx> Lvalue<'tcx> { - pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> LvalueTy<'tcx> { + pub fn ty<'a, 'gcx, D>(&self, local_decls: &D, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> LvalueTy<'tcx> + where D: HasLocalDecls<'tcx> + { match *self { Lvalue::Local(index) => - LvalueTy::Ty { ty: mir.local_decls[index].ty }, + LvalueTy::Ty { ty: local_decls.local_decls()[index].ty }, Lvalue::Static(ref data) => LvalueTy::Ty { ty: data.ty }, Lvalue::Projection(ref proj) => - proj.base.ty(mir, tcx).projection_ty(tcx, &proj.elem), + proj.base.ty(local_decls, tcx).projection_ty(tcx, &proj.elem), } } } impl<'tcx> Rvalue<'tcx> { - pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> + pub fn ty<'a, 'gcx, D>(&self, local_decls: &D, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> + where D: HasLocalDecls<'tcx> { match *self { - Rvalue::Use(ref operand) => operand.ty(mir, tcx), + Rvalue::Use(ref operand) => operand.ty(local_decls, tcx), Rvalue::Repeat(ref operand, ref count) => { - let op_ty = operand.ty(mir, tcx); + let op_ty = operand.ty(local_decls, tcx); let count = count.as_u64(tcx.sess.target.uint_type); assert_eq!(count as usize as u64, count); tcx.mk_array(op_ty, count as usize) } Rvalue::Ref(reg, bk, ref lv) => { - let lv_ty = lv.ty(mir, tcx).to_ty(tcx); + let lv_ty = lv.ty(local_decls, tcx).to_ty(tcx); tcx.mk_ref(reg, ty::TypeAndMut { ty: lv_ty, @@ -156,22 +159,22 @@ impl<'tcx> Rvalue<'tcx> { Rvalue::Len(..) => tcx.types.usize, Rvalue::Cast(.., ty) => ty, Rvalue::BinaryOp(op, ref lhs, ref rhs) => { - let lhs_ty = lhs.ty(mir, tcx); - let rhs_ty = rhs.ty(mir, tcx); + let lhs_ty = lhs.ty(local_decls, tcx); + let rhs_ty = rhs.ty(local_decls, tcx); op.ty(tcx, lhs_ty, rhs_ty) } Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) => { - let lhs_ty = lhs.ty(mir, tcx); - let rhs_ty = rhs.ty(mir, tcx); + let lhs_ty = lhs.ty(local_decls, tcx); + let rhs_ty = rhs.ty(local_decls, tcx); let ty = op.ty(tcx, lhs_ty, rhs_ty); tcx.intern_tup(&[ty, tcx.types.bool], false) } Rvalue::UnaryOp(UnOp::Not, ref operand) | Rvalue::UnaryOp(UnOp::Neg, ref operand) => { - operand.ty(mir, tcx) + operand.ty(local_decls, tcx) } Rvalue::Discriminant(ref lval) => { - let ty = lval.ty(mir, tcx).to_ty(tcx); + let ty = lval.ty(local_decls, tcx).to_ty(tcx); if let ty::TyAdt(adt_def, _) = ty.sty { adt_def.repr.discr_type().to_ty(tcx) } else { @@ -189,7 +192,7 @@ impl<'tcx> Rvalue<'tcx> { } AggregateKind::Tuple => { tcx.mk_tup( - ops.iter().map(|op| op.ty(mir, tcx)), + ops.iter().map(|op| op.ty(local_decls, tcx)), false ) } @@ -206,9 +209,11 @@ impl<'tcx> Rvalue<'tcx> { } impl<'tcx> Operand<'tcx> { - pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { + pub fn ty<'a, 'gcx, D>(&self, local_decls: &D, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> + where D: HasLocalDecls<'tcx> + { match self { - &Operand::Consume(ref l) => l.ty(mir, tcx).to_ty(tcx), + &Operand::Consume(ref l) => l.ty(local_decls, tcx).to_ty(tcx), &Operand::Constant(ref c) => c.ty, } } diff --git a/src/librustc/mir/traversal.rs b/src/librustc/mir/traversal.rs index 6057e7ec7e..5aab46b3ce 100644 --- a/src/librustc/mir/traversal.rs +++ b/src/librustc/mir/traversal.rs @@ -44,9 +44,9 @@ impl<'a, 'tcx> Preorder<'a, 'tcx> { let worklist = vec![root]; Preorder { - mir: mir, + mir, visited: BitVector::new(mir.basic_blocks().len()), - worklist: worklist + worklist, } } } @@ -106,7 +106,7 @@ pub struct Postorder<'a, 'tcx: 'a> { impl<'a, 'tcx> Postorder<'a, 'tcx> { pub fn new(mir: &'a Mir<'tcx>, root: BasicBlock) -> Postorder<'a, 'tcx> { let mut po = Postorder { - mir: mir, + mir, visited: BitVector::new(mir.basic_blocks().len()), visit_stack: Vec::new() }; @@ -251,8 +251,8 @@ impl<'a, 'tcx> ReversePostorder<'a, 'tcx> { let len = blocks.len(); ReversePostorder { - mir: mir, - blocks: blocks, + mir, + blocks, idx: len } } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 780ce736bf..ac1c0306f7 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -325,6 +325,7 @@ macro_rules! make_mir_visitor { ref $($mutability)* rvalue) => { self.visit_assign(block, lvalue, rvalue, location); } + StatementKind::EndRegion(_) => {} StatementKind::SetDiscriminant{ ref $($mutability)* lvalue, .. } => { self.visit_lvalue(lvalue, LvalueContext::Store, location); } diff --git a/src/librustc/session/code_stats.rs b/src/librustc/session/code_stats.rs index 215539de67..118b84113a 100644 --- a/src/librustc/session/code_stats.rs +++ b/src/librustc/session/code_stats.rs @@ -82,12 +82,12 @@ impl CodeStats { opt_discr_size: Option, variants: Vec) { let info = TypeSizeInfo { - kind: kind, + kind, type_description: type_desc.to_string(), align: align.abi(), overall_size: overall_size.bytes(), opt_discr_size: opt_discr_size.map(|s| s.bytes()), - variants: variants, + variants, }; self.type_sizes.insert(info); } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 589489b49b..4b41572c1a 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -489,6 +489,12 @@ impl Options { self.debugging_opts.query_dep_graph } + #[inline(always)] + pub fn enable_dep_node_debug_strs(&self) -> bool { + cfg!(debug_assertions) && + (self.debugging_opts.query_dep_graph || self.debugging_opts.incremental_info) + } + pub fn single_codegen_unit(&self) -> bool { self.incremental.is_none() || self.cg.codegen_units == 1 @@ -893,6 +899,10 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, DB_OPTIONS, db_type_desc, dbsetters, verbose: bool = (false, parse_bool, [UNTRACKED], "in general, enable more debug printouts"), + span_free_formats: bool = (false, parse_bool, [UNTRACKED], + "when debug-printing compiler state, do not include spans"), // o/w tests have closure@path + identify_regions: bool = (false, parse_bool, [UNTRACKED], + "make unnamed regions display as '# (where # is some non-ident unique id)"), time_passes: bool = (false, parse_bool, [UNTRACKED], "measure time of each rustc pass"), count_llvm_insns: bool = (false, parse_bool, @@ -935,8 +945,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, save_analysis: bool = (false, parse_bool, [UNTRACKED], "write syntax and type analysis (in JSON format) information, in \ addition to normal output"), - save_analysis_csv: bool = (false, parse_bool, [UNTRACKED], - "write syntax and type analysis (in CSV format) information, in addition to normal output"), save_analysis_api: bool = (false, parse_bool, [UNTRACKED], "write syntax and type analysis information for opaque libraries (in JSON format), \ in addition to normal output"), @@ -1033,6 +1041,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "a single extra argument to prepend the linker invocation (can be used several times)"), pre_link_args: Option> = (None, parse_opt_list, [UNTRACKED], "extra arguments to prepend to the linker invocation (space separated)"), + profile: bool = (false, parse_bool, [TRACKED], + "insert profiling code"), } pub fn default_lib_output() -> CrateType { @@ -1118,9 +1128,9 @@ pub fn build_target_config(opts: &Options, sp: &Handler) -> Config { }; Config { - target: target, - int_type: int_type, - uint_type: uint_type, + target, + int_type, + uint_type, } } @@ -1131,9 +1141,9 @@ pub enum OptionStability { Unstable, } -#[derive(Clone, PartialEq, Eq)] pub struct RustcOptGroup { - pub opt_group: getopts::OptGroup, + pub apply: Box &mut getopts::Options>, + pub name: &'static str, pub stability: OptionStability, } @@ -1142,12 +1152,24 @@ impl RustcOptGroup { self.stability == OptionStability::Stable } - pub fn stable(g: getopts::OptGroup) -> RustcOptGroup { - RustcOptGroup { opt_group: g, stability: OptionStability::Stable } + pub fn stable(name: &'static str, f: F) -> RustcOptGroup + where F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static, + { + RustcOptGroup { + name, + apply: Box::new(f), + stability: OptionStability::Stable, + } } - pub fn unstable(g: getopts::OptGroup) -> RustcOptGroup { - RustcOptGroup { opt_group: g, stability: OptionStability::Unstable } + pub fn unstable(name: &'static str, f: F) -> RustcOptGroup + where F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static, + { + RustcOptGroup { + name, + apply: Box::new(f), + stability: OptionStability::Unstable, + } } } @@ -1166,41 +1188,58 @@ mod opt { use super::RustcOptGroup; pub type R = RustcOptGroup; - pub type S<'a> = &'a str; + pub type S = &'static str; + + fn stable(name: S, f: F) -> R + where F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static + { + RustcOptGroup::stable(name, f) + } + + fn unstable(name: S, f: F) -> R + where F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static + { + RustcOptGroup::unstable(name, f) + } - fn stable(g: getopts::OptGroup) -> R { RustcOptGroup::stable(g) } - fn unstable(g: getopts::OptGroup) -> R { RustcOptGroup::unstable(g) } + fn longer(a: S, b: S) -> S { + if a.len() > b.len() { + a + } else { + b + } + } pub fn opt_s(a: S, b: S, c: S, d: S) -> R { - stable(getopts::optopt(a, b, c, d)) + stable(longer(a, b), move |opts| opts.optopt(a, b, c, d)) } pub fn multi_s(a: S, b: S, c: S, d: S) -> R { - stable(getopts::optmulti(a, b, c, d)) + stable(longer(a, b), move |opts| opts.optmulti(a, b, c, d)) } pub fn flag_s(a: S, b: S, c: S) -> R { - stable(getopts::optflag(a, b, c)) + stable(longer(a, b), move |opts| opts.optflag(a, b, c)) } pub fn flagopt_s(a: S, b: S, c: S, d: S) -> R { - stable(getopts::optflagopt(a, b, c, d)) + stable(longer(a, b), move |opts| opts.optflagopt(a, b, c, d)) } pub fn flagmulti_s(a: S, b: S, c: S) -> R { - stable(getopts::optflagmulti(a, b, c)) + stable(longer(a, b), move |opts| opts.optflagmulti(a, b, c)) } pub fn opt(a: S, b: S, c: S, d: S) -> R { - unstable(getopts::optopt(a, b, c, d)) + unstable(longer(a, b), move |opts| opts.optopt(a, b, c, d)) } pub fn multi(a: S, b: S, c: S, d: S) -> R { - unstable(getopts::optmulti(a, b, c, d)) + unstable(longer(a, b), move |opts| opts.optmulti(a, b, c, d)) } pub fn flag(a: S, b: S, c: S) -> R { - unstable(getopts::optflag(a, b, c)) + unstable(longer(a, b), move |opts| opts.optflag(a, b, c)) } pub fn flagopt(a: S, b: S, c: S, d: S) -> R { - unstable(getopts::optflagopt(a, b, c, d)) + unstable(longer(a, b), move |opts| opts.optflagopt(a, b, c, d)) } pub fn flagmulti(a: S, b: S, c: S) -> R { - unstable(getopts::optflagmulti(a, b, c)) + unstable(longer(a, b), move |opts| opts.optflagmulti(a, b, c)) } } @@ -1208,13 +1247,6 @@ mod opt { /// including metadata for each option, such as whether the option is /// part of the stable long-term interface for rustc. pub fn rustc_short_optgroups() -> Vec { - let mut print_opts = vec!["crate-name", "file-names", "sysroot", "cfg", - "target-list", "target-cpus", "target-features", - "relocation-models", "code-models"]; - if nightly_options::is_nightly_build() { - print_opts.push("target-spec-json"); - } - vec![ opt::flag_s("h", "help", "Display this message"), opt::multi_s("", "cfg", "Configure the compilation environment", "SPEC"), @@ -1234,8 +1266,10 @@ pub fn rustc_short_optgroups() -> Vec { the compiler to emit", "[asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]"), opt::multi_s("", "print", "Comma separated list of compiler information to \ - print on stdout", &format!("[{}]", - &print_opts.join("|"))), + print on stdout", + "[crate-name|file-names|sysroot|cfg|target-list|\ + target-cpus|target-features|relocation-models|\ + code-models|target-spec-json]"), opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"), opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"), opt::opt_s("o", "", "Write output to ", "FILENAME"), @@ -1263,7 +1297,7 @@ pub fn rustc_short_optgroups() -> Vec { /// long-term interface for rustc. pub fn rustc_optgroups() -> Vec { let mut opts = rustc_short_optgroups(); - opts.extend_from_slice(&[ + opts.extend(vec![ opt::multi_s("", "extern", "Specify where an external rust library is located", "NAME=PATH"), opt::opt_s("", "sysroot", "Override the system root", "PATH"), @@ -1599,28 +1633,28 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) let incremental = debugging_opts.incremental.as_ref().map(|m| PathBuf::from(m)); (Options { - crate_types: crate_types, + crate_types, optimize: opt_level, - debuginfo: debuginfo, - lint_opts: lint_opts, - lint_cap: lint_cap, - describe_lints: describe_lints, + debuginfo, + lint_opts, + lint_cap, + describe_lints, output_types: OutputTypes(output_types), - search_paths: search_paths, + search_paths, maybe_sysroot: sysroot_opt, target_triple: target, - test: test, - incremental: incremental, - debugging_opts: debugging_opts, - prints: prints, - cg: cg, - error_format: error_format, + test, + incremental, + debugging_opts, + prints, + cg, + error_format, externs: Externs(externs), - crate_name: crate_name, + crate_name, alt_std_name: None, - libs: libs, + libs, unstable_features: UnstableFeatures::from_environment(), - debug_assertions: debug_assertions, + debug_assertions, actually_rustdoc: false, }, cfg) @@ -1676,19 +1710,14 @@ pub mod nightly_options { if opt.stability == OptionStability::Stable { continue } - let opt_name = if opt.opt_group.long_name.is_empty() { - &opt.opt_group.short_name - } else { - &opt.opt_group.long_name - }; - if !matches.opt_present(opt_name) { + if !matches.opt_present(opt.name) { continue } - if opt_name != "Z" && !has_z_unstable_option { + if opt.name != "Z" && !has_z_unstable_option { early_error(ErrorOutputType::default(), &format!("the `-Z unstable-options` flag must also be passed to enable \ the flag `{}`", - opt_name)); + opt.name)); } if really_allows_unstable_options { continue @@ -1696,7 +1725,7 @@ pub mod nightly_options { match opt.stability { OptionStability::Unstable => { let msg = format!("the option `{}` is only accepted on the \ - nightly compiler", opt_name); + nightly compiler", opt.name); early_error(ErrorOutputType::default(), &msg); } OptionStability::Stable => {} @@ -1865,7 +1894,7 @@ mod dep_tracking { mod tests { use dep_graph::DepGraph; use errors; - use getopts::{getopts, OptGroup}; + use getopts; use lint; use middle::cstore::{self, DummyCrateStore}; use session::config::{build_configuration, build_session_options_and_crate_config}; @@ -1878,10 +1907,12 @@ mod tests { use rustc_back::PanicStrategy; use syntax::symbol::Symbol; - fn optgroups() -> Vec { - super::rustc_optgroups().into_iter() - .map(|a| a.opt_group) - .collect() + fn optgroups() -> getopts::Options { + let mut opts = getopts::Options::new(); + for group in super::rustc_optgroups() { + (group.apply)(&mut opts); + } + return opts } fn mk_map(entries: Vec<(K, V)>) -> BTreeMap { @@ -1897,7 +1928,7 @@ mod tests { fn test_switch_implies_cfg_test() { let dep_graph = DepGraph::new(false); let matches = - &match getopts(&["--test".to_string()], &optgroups()) { + &match optgroups().parse(&["--test".to_string()]) { Ok(m) => m, Err(f) => panic!("test_switch_implies_cfg_test: {}", f) }; @@ -1914,8 +1945,7 @@ mod tests { fn test_switch_implies_cfg_test_unless_cfg_test() { let dep_graph = DepGraph::new(false); let matches = - &match getopts(&["--test".to_string(), "--cfg=test".to_string()], - &optgroups()) { + &match optgroups().parse(&["--test".to_string(), "--cfg=test".to_string()]) { Ok(m) => m, Err(f) => { panic!("test_switch_implies_cfg_test_unless_cfg_test: {}", f) @@ -1935,9 +1965,9 @@ mod tests { fn test_can_print_warnings() { let dep_graph = DepGraph::new(false); { - let matches = getopts(&[ + let matches = optgroups().parse(&[ "-Awarnings".to_string() - ], &optgroups()).unwrap(); + ]).unwrap(); let registry = errors::registry::Registry::new(&[]); let (sessopts, _) = build_session_options_and_crate_config(&matches); let sess = build_session(sessopts, &dep_graph, None, registry, @@ -1946,10 +1976,10 @@ mod tests { } { - let matches = getopts(&[ + let matches = optgroups().parse(&[ "-Awarnings".to_string(), "-Dwarnings".to_string() - ], &optgroups()).unwrap(); + ]).unwrap(); let registry = errors::registry::Registry::new(&[]); let (sessopts, _) = build_session_options_and_crate_config(&matches); let sess = build_session(sessopts, &dep_graph, None, registry, @@ -1958,9 +1988,9 @@ mod tests { } { - let matches = getopts(&[ + let matches = optgroups().parse(&[ "-Adead_code".to_string() - ], &optgroups()).unwrap(); + ]).unwrap(); let registry = errors::registry::Registry::new(&[]); let (sessopts, _) = build_session_options_and_crate_config(&matches); let sess = build_session(sessopts, &dep_graph, None, registry, @@ -2469,8 +2499,6 @@ mod tests { assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.save_analysis = true; assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.save_analysis_csv = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.save_analysis_api = true; assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.print_move_fragments = true; diff --git a/src/librustc/session/filesearch.rs b/src/librustc/session/filesearch.rs index 47b988a21b..1004b28260 100644 --- a/src/librustc/session/filesearch.rs +++ b/src/librustc/session/filesearch.rs @@ -104,10 +104,10 @@ impl<'a> FileSearch<'a> { kind: PathKind) -> FileSearch<'a> { debug!("using sysroot = {}, triple = {}", sysroot.display(), triple); FileSearch { - sysroot: sysroot, - search_paths: search_paths, - triple: triple, - kind: kind, + sysroot, + search_paths, + triple, + kind, } } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 827fa72f03..fe6b24f3e1 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -16,12 +16,13 @@ use hir::def_id::{CrateNum, DefIndex}; use lint; use middle::cstore::CrateStore; +use middle::allocator::AllocatorKind; use middle::dependency_format; use session::search_paths::PathKind; use session::config::DebugInfoLevel; use ty::tls; use util::nodemap::{FxHashMap, FxHashSet}; -use util::common::duration_to_secs_str; +use util::common::{duration_to_secs_str, ErrorReported}; use syntax::ast::NodeId; use errors::{self, DiagnosticBuilder}; @@ -38,14 +39,16 @@ use syntax_pos::{Span, MultiSpan}; use rustc_back::{LinkerFlavor, PanicStrategy}; use rustc_back::target::Target; use rustc_data_structures::flock; +use jobserver::Client; -use std::path::{Path, PathBuf}; use std::cell::{self, Cell, RefCell}; use std::collections::HashMap; use std::env; +use std::fmt; use std::io::Write; +use std::path::{Path, PathBuf}; use std::rc::Rc; -use std::fmt; +use std::sync::{Once, ONCE_INIT}; use std::time::Duration; mod code_stats; @@ -77,10 +80,10 @@ pub struct Session { pub working_dir: (String, bool), pub lint_store: RefCell, pub lints: RefCell, - /// Set of (LintId, span, message) tuples tracking lint (sub)diagnostics - /// that have been set once, but should not be set again, in order to avoid - /// redundantly verbose output (Issue #24690). - pub one_time_diagnostics: RefCell>, + /// Set of (LintId, Option, message) tuples tracking lint + /// (sub)diagnostics that have been set once, but should not be set again, + /// in order to avoid redundantly verbose output (Issue #24690). + pub one_time_diagnostics: RefCell, String)>>, pub plugin_llvm_passes: RefCell>, pub plugin_attributes: RefCell>, pub crate_types: RefCell>, @@ -104,6 +107,7 @@ pub struct Session { /// dependency if it didn't already find one, and this tracks what was /// injected. pub injected_allocator: Cell>, + pub allocator_kind: Cell>, pub injected_panic_runtime: Cell>, /// Map from imported macro spans (which consist of @@ -134,6 +138,13 @@ pub struct Session { pub print_fuel_crate: Option, /// Always set to zero and incremented so that we can print fuel expended by a crate. pub print_fuel: Cell, + + /// Loaded up early on in the initialization of this `Session` to avoid + /// false positives about a job server in our environment. + pub jobserver_from_env: Option, + + /// Metadata about the allocators for the current crate being compiled + pub has_global_allocator: Cell, } pub struct PerfStats { @@ -151,6 +162,13 @@ pub struct PerfStats { pub decode_def_path_tables_time: Cell, } +/// Enum to support dispatch of one-time diagnostics (in Session.diag_once) +enum DiagnosticBuilderMethod { + Note, + SpanNote, + // add more variants as needed to support one-time diagnostics +} + impl Session { pub fn local_crate_disambiguator(&self) -> Symbol { *self.crate_disambiguator.borrow() @@ -242,7 +260,10 @@ impl Session { pub fn abort_if_errors(&self) { self.diagnostic().abort_if_errors(); } - pub fn track_errors(&self, f: F) -> Result + pub fn compile_status(&self) -> Result<(), CompileIncomplete> { + compile_result_from_err_count(self.err_count()) + } + pub fn track_errors(&self, f: F) -> Result where F: FnOnce() -> T { let old_count = self.err_count(); @@ -251,7 +272,7 @@ impl Session { if errors == 0 { Ok(result) } else { - Err(errors) + Err(ErrorReported) } } pub fn span_warn>(&self, sp: S, msg: &str) { @@ -323,34 +344,53 @@ impl Session { &self.parse_sess.span_diagnostic } - /// Analogous to calling `.span_note` on the given DiagnosticBuilder, but - /// deduplicates on lint ID, span, and message for this `Session` if we're - /// not outputting in JSON mode. - // - // FIXME: if the need arises for one-time diagnostics other than - // `span_note`, we almost certainly want to generalize this - // "check/insert-into the one-time diagnostics map, then set message if - // it's not already there" code to accomodate all of them - pub fn diag_span_note_once<'a, 'b>(&'a self, - diag_builder: &'b mut DiagnosticBuilder<'a>, - lint: &'static lint::Lint, span: Span, message: &str) { + /// Analogous to calling methods on the given `DiagnosticBuilder`, but + /// deduplicates on lint ID, span (if any), and message for this `Session` + /// if we're not outputting in JSON mode. + fn diag_once<'a, 'b>(&'a self, + diag_builder: &'b mut DiagnosticBuilder<'a>, + method: DiagnosticBuilderMethod, + lint: &'static lint::Lint, message: &str, span: Option) { + let mut do_method = || { + match method { + DiagnosticBuilderMethod::Note => { + diag_builder.note(message); + }, + DiagnosticBuilderMethod::SpanNote => { + diag_builder.span_note(span.expect("span_note expects a span"), message); + } + } + }; + match self.opts.error_format { // when outputting JSON for tool consumption, the tool might want // the duplicates config::ErrorOutputType::Json => { - diag_builder.span_note(span, &message); + do_method() }, _ => { let lint_id = lint::LintId::of(lint); let id_span_message = (lint_id, span, message.to_owned()); let fresh = self.one_time_diagnostics.borrow_mut().insert(id_span_message); if fresh { - diag_builder.span_note(span, &message); + do_method() } } } } + pub fn diag_span_note_once<'a, 'b>(&'a self, + diag_builder: &'b mut DiagnosticBuilder<'a>, + lint: &'static lint::Lint, span: Span, message: &str) { + self.diag_once(diag_builder, DiagnosticBuilderMethod::SpanNote, lint, message, Some(span)); + } + + pub fn diag_note_once<'a, 'b>(&'a self, + diag_builder: &'b mut DiagnosticBuilder<'a>, + lint: &'static lint::Lint, message: &str) { + self.diag_once(diag_builder, DiagnosticBuilderMethod::Note, lint, message, None); + } + pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap { self.parse_sess.codemap() } @@ -445,7 +485,7 @@ impl Session { *incr_comp_session = IncrCompSession::Active { session_directory: session_dir, - lock_file: lock_file, + lock_file, }; } @@ -475,7 +515,7 @@ impl Session { // Note: This will also drop the lock file, thus unlocking the directory *incr_comp_session = IncrCompSession::InvalidBecauseOfErrors { - session_directory: session_directory + session_directory, }; } @@ -655,18 +695,18 @@ pub fn build_session_(sopts: config::Options, let sess = Session { dep_graph: dep_graph.clone(), target: target_cfg, - host: host, + host, opts: sopts, - cstore: cstore, + cstore, parse_sess: p_s, // For a library crate, this is always none entry_fn: RefCell::new(None), entry_type: Cell::new(None), plugin_registrar_fn: Cell::new(None), derive_registrar_fn: Cell::new(None), - default_sysroot: default_sysroot, - local_crate_source_file: local_crate_source_file, - working_dir: working_dir, + default_sysroot, + local_crate_source_file, + working_dir, lint_store: RefCell::new(lint::LintStore::new()), lints: RefCell::new(lint::LintTable::new()), one_time_diagnostics: RefCell::new(FxHashSet()), @@ -680,6 +720,7 @@ pub fn build_session_(sopts: config::Options, type_length_limit: Cell::new(1048576), next_node_id: Cell::new(NodeId::new(1)), injected_allocator: Cell::new(None), + allocator_kind: Cell::new(None), injected_panic_runtime: Cell::new(None), imported_macro_spans: RefCell::new(HashMap::new()), incr_comp_session: RefCell::new(IncrCompSession::NotInitialized), @@ -692,11 +733,29 @@ pub fn build_session_(sopts: config::Options, decode_def_path_tables_time: Cell::new(Duration::from_secs(0)), }, code_stats: RefCell::new(CodeStats::new()), - optimization_fuel_crate: optimization_fuel_crate, - optimization_fuel_limit: optimization_fuel_limit, - print_fuel_crate: print_fuel_crate, - print_fuel: print_fuel, + optimization_fuel_crate, + optimization_fuel_limit, + print_fuel_crate, + print_fuel, out_of_fuel: Cell::new(false), + // Note that this is unsafe because it may misinterpret file descriptors + // on Unix as jobserver file descriptors. We hopefully execute this near + // the beginning of the process though to ensure we don't get false + // positives, or in other words we try to execute this before we open + // any file descriptors ourselves. + // + // Also note that we stick this in a global because there could be + // multiple `Session` instances in this process, and the jobserver is + // per-process. + jobserver_from_env: unsafe { + static mut GLOBAL_JOBSERVER: *mut Option = 0 as *mut _; + static INIT: Once = ONCE_INIT; + INIT.call_once(|| { + GLOBAL_JOBSERVER = Box::into_raw(Box::new(Client::from_env())); + }); + (*GLOBAL_JOBSERVER).clone() + }, + has_global_allocator: Cell::new(false), }; sess @@ -752,15 +811,23 @@ pub fn early_warn(output: config::ErrorOutputType, msg: &str) { handler.emit(&MultiSpan::new(), msg, errors::Level::Warning); } -// Err(0) means compilation was stopped, but no errors were found. -// This would be better as a dedicated enum, but using try! is so convenient. -pub type CompileResult = Result<(), usize>; +#[derive(Copy, Clone, Debug)] +pub enum CompileIncomplete { + Stopped, + Errored(ErrorReported) +} +impl From for CompileIncomplete { + fn from(err: ErrorReported) -> CompileIncomplete { + CompileIncomplete::Errored(err) + } +} +pub type CompileResult = Result<(), CompileIncomplete>; pub fn compile_result_from_err_count(err_count: usize) -> CompileResult { if err_count == 0 { Ok(()) } else { - Err(err_count) + Err(CompileIncomplete::Errored(ErrorReported)) } } diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 54fe3a42b6..34df447a11 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -47,7 +47,7 @@ fn with_fresh_ty_vars<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, ' let impl_substs = selcx.infcx().fresh_substs_for_item(DUMMY_SP, impl_def_id); let header = ty::ImplHeader { - impl_def_id: impl_def_id, + impl_def_id, self_ty: tcx.type_of(impl_def_id), trait_ref: tcx.impl_trait_ref(impl_def_id), predicates: tcx.predicates_of(impl_def_id).predicates @@ -102,7 +102,7 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, .chain(&b_impl_header.predicates) .map(|p| infcx.resolve_type_vars_if_possible(p)) .map(|p| Obligation { cause: ObligationCause::dummy(), - param_env: param_env, + param_env, recursion_depth: 0, predicate: p }) .chain(obligations) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 049d5e488c..65c0a9f8ff 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -18,6 +18,7 @@ use super::{ OutputTypeParameterMismatch, TraitNotObjectSafe, PredicateObligation, + Reveal, SelectionContext, SelectionError, ObjectSafetyViolation, @@ -25,16 +26,14 @@ use super::{ use errors::DiagnosticBuilder; use fmt_macros::{Parser, Piece, Position}; -use hir::{self, intravisit, Local, Pat, Body}; -use hir::intravisit::{Visitor, NestedVisitorMap}; -use hir::map::NodeExpr; +use hir; use hir::def_id::DefId; use infer::{self, InferCtxt}; use infer::type_variable::TypeVariableOrigin; use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL; use std::fmt; -use syntax::ast::{self, NodeId}; -use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable, TyInfer, TyVar}; +use syntax::ast; +use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; use ty::error::{ExpectedFound, TypeError}; use ty::fast_reject; use ty::fold::TypeFolder; @@ -44,93 +43,115 @@ use util::nodemap::{FxHashMap, FxHashSet}; use syntax_pos::{DUMMY_SP, Span}; +impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { + pub fn report_fulfillment_errors(&self, + errors: &Vec>, + body_id: Option) { + #[derive(Debug)] + struct ErrorDescriptor<'tcx> { + predicate: ty::Predicate<'tcx>, + index: Option, // None if this is an old error + } -#[derive(Debug, PartialEq, Eq, Hash)] -pub struct TraitErrorKey<'tcx> { - span: Span, - predicate: ty::Predicate<'tcx> -} + let mut error_map : FxHashMap<_, _> = + self.reported_trait_errors.borrow().iter().map(|(&span, predicates)| { + (span, predicates.iter().map(|predicate| ErrorDescriptor { + predicate: predicate.clone(), + index: None + }).collect()) + }).collect(); + + for (index, error) in errors.iter().enumerate() { + error_map.entry(error.obligation.cause.span).or_insert(Vec::new()).push( + ErrorDescriptor { + predicate: error.obligation.predicate.clone(), + index: Some(index) + }); -impl<'a, 'gcx, 'tcx> TraitErrorKey<'tcx> { - fn from_error(infcx: &InferCtxt<'a, 'gcx, 'tcx>, - e: &FulfillmentError<'tcx>) -> Self { - let predicate = - infcx.resolve_type_vars_if_possible(&e.obligation.predicate); - TraitErrorKey { - span: e.obligation.cause.span, - predicate: infcx.tcx.erase_regions(&predicate) + self.reported_trait_errors.borrow_mut() + .entry(error.obligation.cause.span).or_insert(Vec::new()) + .push(error.obligation.predicate.clone()); } - } -} -struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { - infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - target_ty: &'a Ty<'tcx>, - hir_map: &'a hir::map::Map<'gcx>, - found_local_pattern: Option<&'gcx Pat>, - found_arg_pattern: Option<&'gcx Pat>, -} + // We do this in 2 passes because we want to display errors in order, tho + // maybe it *is* better to sort errors by span or something. + let mut is_suppressed: Vec = errors.iter().map(|_| false).collect(); + for (_, error_set) in error_map.iter() { + // We want to suppress "duplicate" errors with the same span. + for error in error_set { + if let Some(index) = error.index { + // Suppress errors that are either: + // 1) strictly implied by another error. + // 2) implied by an error with a smaller index. + for error2 in error_set { + if error2.index.map_or(false, |index2| is_suppressed[index2]) { + // Avoid errors being suppressed by already-suppressed + // errors, to prevent all errors from being suppressed + // at once. + continue + } -impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { - fn node_matches_type(&mut self, node_id: &'gcx NodeId) -> bool { - match self.infcx.tables.borrow().node_types.get(node_id) { - Some(&ty) => { - let ty = self.infcx.resolve_type_vars_if_possible(&ty); - ty.walk().any(|inner_ty| { - inner_ty == *self.target_ty || match (&inner_ty.sty, &self.target_ty.sty) { - (&TyInfer(TyVar(a_vid)), &TyInfer(TyVar(b_vid))) => { - self.infcx - .type_variables - .borrow_mut() - .sub_unified(a_vid, b_vid) + if self.error_implies(&error2.predicate, &error.predicate) && + !(error2.index >= error.index && + self.error_implies(&error.predicate, &error2.predicate)) + { + info!("skipping {:?} (implied by {:?})", error, error2); + is_suppressed[index] = true; + break } - _ => false, } - }) + } } - _ => false, } - } -} -impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { - NestedVisitorMap::OnlyBodies(&self.hir_map) + for (error, suppressed) in errors.iter().zip(is_suppressed) { + if !suppressed { + self.report_fulfillment_error(error, body_id); + } + } } - fn visit_local(&mut self, local: &'gcx Local) { - if self.found_local_pattern.is_none() && self.node_matches_type(&local.id) { - self.found_local_pattern = Some(&*local.pat); + // returns if `cond` not occuring implies that `error` does not occur - i.e. that + // `error` occuring implies that `cond` occurs. + fn error_implies(&self, + cond: &ty::Predicate<'tcx>, + error: &ty::Predicate<'tcx>) + -> bool + { + if cond == error { + return true } - intravisit::walk_local(self, local); - } - fn visit_body(&mut self, body: &'gcx Body) { - for argument in &body.arguments { - if self.found_arg_pattern.is_none() && self.node_matches_type(&argument.id) { - self.found_arg_pattern = Some(&*argument.pat); + let (cond, error) = match (cond, error) { + (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error)) + => (cond, error), + _ => { + // FIXME: make this work in other cases too. + return false } - } - intravisit::walk_body(self, body); - } -} + }; -impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - pub fn report_fulfillment_errors(&self, errors: &Vec>) { - for error in errors { - self.report_fulfillment_error(error); + for implication in super::elaborate_predicates(self.tcx, vec![cond.clone()]) { + if let ty::Predicate::Trait(implication) = implication { + let error = error.to_poly_trait_ref(); + let implication = implication.to_poly_trait_ref(); + // FIXME: I'm just not taking associated types at all here. + // Eventually I'll need to implement param-env-aware + // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic. + let param_env = ty::ParamEnv::empty(Reveal::UserFacing); + if let Ok(_) = self.can_sub(param_env, error, implication) { + debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication); + return true + } + } } + + false } - fn report_fulfillment_error(&self, - error: &FulfillmentError<'tcx>) { - let error_key = TraitErrorKey::from_error(self, error); - debug!("report_fulfillment_errors({:?}) - key={:?}", - error, error_key); - if !self.reported_trait_errors.borrow_mut().insert(error_key) { - debug!("report_fulfillment_errors: skipping duplicate"); - return; - } + fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>, + body_id: Option) { + debug!("report_fulfillment_errors({:?})", error); match error.code { FulfillmentErrorCode::CodeSelectionError(ref e) => { self.report_selection_error(&error.obligation, e); @@ -139,7 +160,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.report_projection_error(&error.obligation, e); } FulfillmentErrorCode::CodeAmbiguity => { - self.maybe_report_ambiguity(&error.obligation); + self.maybe_report_ambiguity(&error.obligation, body_id); } FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => { self.report_mismatched_types(&error.obligation.cause, @@ -257,8 +278,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let mut self_match_impls = vec![]; let mut fuzzy_match_impls = vec![]; - self.tcx.trait_def(trait_ref.def_id) - .for_each_relevant_impl(self.tcx, trait_self_ty, |def_id| { + self.tcx.for_each_relevant_impl( + trait_ref.def_id, trait_self_ty, |def_id| { let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id); let impl_trait_ref = tcx .impl_trait_ref(def_id) @@ -309,6 +330,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .filter(|a| a.check_name("rustc_on_unimplemented")) .next() { + let name = self.tcx.item_name(def_id).as_str(); let err_sp = item.span.substitute_dummy(span); let trait_str = self.tcx.item_path_str(trait_ref.def_id); if let Some(istring) = item.value_str() { @@ -326,6 +348,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { Piece::NextArgument(a) => match a.position { Position::ArgumentNamed(s) => match generic_map.get(s) { Some(val) => Some(val), + None if s == name => { + Some(&trait_str) + } None => { span_err!(self.tcx.sess, err_sp, E0272, "the #[rustc_on_unimplemented] attribute on trait \ @@ -371,10 +396,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { trait_ref.skip_binder().self_ty(), true); let mut impl_candidates = Vec::new(); - let trait_def = self.tcx.trait_def(trait_ref.def_id()); match simp { - Some(simp) => trait_def.for_each_impl(self.tcx, |def_id| { + Some(simp) => self.tcx.for_each_impl(trait_ref.def_id(), |def_id| { let imp = self.tcx.impl_trait_ref(def_id).unwrap(); let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), @@ -386,7 +410,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } impl_candidates.push(imp); }), - None => trait_def.for_each_impl(self.tcx, |def_id| { + None => self.tcx.for_each_impl(trait_ref.def_id(), |def_id| { impl_candidates.push( self.tcx.impl_trait_ref(def_id).unwrap()); }) @@ -640,16 +664,36 @@ 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.hir.span_if_local(closure_def_id).unwrap(); + let node_id = self.tcx.hir.as_local_node_id(closure_def_id).unwrap(); let mut err = struct_span_err!( self.tcx.sess, closure_span, E0525, "expected a closure that implements the `{}` trait, \ but this closure only implements `{}`", kind, found_kind); - err.span_note( + + err.span_label( obligation.cause.span, - &format!("the requirement to implement \ - `{}` derives from here", kind)); + format!("the requirement to implement `{}` derives from here", kind)); + + // Additional context information explaining why the closure only implements + // a particular trait. + if let Some(tables) = self.in_progress_tables { + match tables.borrow().closure_kinds.get(&node_id) { + Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) => { + err.span_note(span, &format!( + "closure is `FnOnce` because it moves the \ + variable `{}` out of its environment", name)); + }, + Some(&(ty::ClosureKind::FnMut, Some((span, name)))) => { + err.span_note(span, &format!( + "closure is `FnMut` because it mutates the \ + variable `{}` here", name)); + }, + _ => {} + } + } + err.emit(); return; } @@ -830,14 +874,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) { + fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>, + body_id: Option) { // Unable to successfully determine, probably means // insufficient type information, but could mean // ambiguous impls. The latter *ought* to be a // coherence violation, so we don't report it here. let predicate = self.resolve_type_vars_if_possible(&obligation.predicate); - let body_id = hir::BodyId { node_id: obligation.cause.body_id }; let span = obligation.cause.span; debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})", @@ -914,7 +958,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder(); // both must be type variables, or the other would've been instantiated assert!(a.is_ty_var() && b.is_ty_var()); - self.need_type_info(hir::BodyId { node_id: obligation.cause.body_id }, + self.need_type_info(body_id, obligation.cause.span, a); } @@ -985,83 +1029,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { }) } - fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String { - if let ty::TyInfer(ty::TyVar(ty_vid)) = (*ty).sty { - let ty_vars = self.type_variables.borrow(); - if let TypeVariableOrigin::TypeParameterDefinition(_, name) = - *ty_vars.var_origin(ty_vid) { - name.to_string() - } else { - ty.to_string() - } - } else { - ty.to_string() - } - } - - pub fn need_type_info(&self, body_id: hir::BodyId, span: Span, ty: Ty<'tcx>) { - let ty = self.resolve_type_vars_if_possible(&ty); - let name = self.extract_type_name(&ty); - - let mut err_span = span; - let mut labels = vec![(span, format!("cannot infer type for `{}`", name))]; - - let mut local_visitor = FindLocalByTypeVisitor { - infcx: &self, - target_ty: &ty, - hir_map: &self.tcx.hir, - found_local_pattern: None, - found_arg_pattern: None, - }; - - // #40294: cause.body_id can also be a fn declaration. - // Currently, if it's anything other than NodeExpr, we just ignore it - match self.tcx.hir.find(body_id.node_id) { - Some(NodeExpr(expr)) => local_visitor.visit_expr(expr), - _ => () - } - - if let Some(pattern) = local_visitor.found_arg_pattern { - err_span = pattern.span; - // We don't want to show the default label for closures. - // - // So, before clearing, the output would look something like this: - // ``` - // let x = |_| { }; - // - ^^^^ cannot infer type for `[_; 0]` - // | - // consider giving this closure parameter a type - // ``` - // - // After clearing, it looks something like this: - // ``` - // let x = |_| { }; - // ^ consider giving this closure parameter a type - // ``` - labels.clear(); - labels.push((pattern.span, format!("consider giving this closure parameter a type"))); - } - - if let Some(pattern) = local_visitor.found_local_pattern { - if let Some(simple_name) = pattern.simple_name() { - labels.push((pattern.span, format!("consider giving `{}` a type", simple_name))); - } else { - labels.push((pattern.span, format!("consider giving the pattern a type"))); - } - } - - let mut err = struct_span_err!(self.tcx.sess, - err_span, - E0282, - "type annotations needed"); - - for (target_span, label_message) in labels { - err.span_label(target_span, label_message); - } - - err.emit(); - } - fn note_obligation_cause(&self, err: &mut DiagnosticBuilder, obligation: &Obligation<'tcx, T>) @@ -1096,7 +1063,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err.note("slice and array elements must have `Sized` type"); } ObligationCauseCode::TupleElem => { - err.note("tuple elements must have `Sized` type"); + err.note("only the last element of a tuple may have a dynamically sized type"); } ObligationCauseCode::ProjectionWf(data) => { err.note(&format!("required so that the projection `{}` is well-formed", @@ -1126,13 +1093,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ObligationCauseCode::VariableType(_) => { err.note("all local variables must have a statically known size"); } - ObligationCauseCode::ReturnType => { + ObligationCauseCode::SizedReturnType => { err.note("the return type of a function must have a \ statically known size"); } ObligationCauseCode::AssignmentLhsSized => { err.note("the left-hand-side of an assignment must have a statically known size"); } + ObligationCauseCode::TupleInitializerSized => { + err.note("tuples must have a statically known size to be initialized"); + } ObligationCauseCode::StructInitializerSized => { err.note("structs must have a statically known size to be initialized"); } @@ -1171,6 +1141,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { but not on the corresponding trait method", predicate)); } + ObligationCauseCode::ReturnType(_) | + ObligationCauseCode::BlockTailExpression(_) => (), } } @@ -1182,4 +1154,3 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { suggested_limit)); } } - diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index c2fe045343..fab8991837 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -152,11 +152,11 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> { cause: ObligationCause<'tcx>) { let trait_ref = ty::TraitRef { - def_id: def_id, + def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]), }; self.register_predicate_obligation(infcx, Obligation { - cause: cause, + cause, recursion_depth: 0, param_env, predicate: trait_ref.to_predicate() @@ -183,13 +183,15 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> { assert!(!infcx.is_in_snapshot()); - if infcx.tcx.fulfilled_predicates.borrow().check_duplicate(&obligation.predicate) { + let tcx = infcx.tcx; + + if tcx.fulfilled_predicates.borrow().check_duplicate(tcx, &obligation.predicate) { debug!("register_predicate_obligation: duplicate"); return } self.predicates.register_obligation(PendingPredicateObligation { - obligation: obligation, + obligation, stalled_on: vec![] }); } @@ -257,7 +259,7 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> { // Process pending obligations. let outcome = self.predicates.process_obligations(&mut FulfillProcessor { - selcx: selcx, + selcx, region_obligations: &mut self.region_obligations, }); debug!("select: outcome={:?}", outcome); @@ -373,7 +375,8 @@ fn process_predicate<'a, 'gcx, 'tcx>( match obligation.predicate { ty::Predicate::Trait(ref data) => { - if selcx.tcx().fulfilled_predicates.borrow().check_duplicate_trait(data) { + let tcx = selcx.tcx(); + if tcx.fulfilled_predicates.borrow().check_duplicate_trait(tcx, data) { return Ok(Some(vec![])); } @@ -477,8 +480,9 @@ fn process_predicate<'a, 'gcx, 'tcx>( let project_obligation = obligation.with(data.clone()); match project::poly_project_and_unify_type(selcx, &project_obligation) { Ok(None) => { + let tcx = selcx.tcx(); pending_obligation.stalled_on = - trait_ref_type_vars(selcx, data.to_poly_trait_ref()); + trait_ref_type_vars(selcx, data.to_poly_trait_ref(tcx)); Ok(None) } Ok(v) => Ok(v), @@ -603,26 +607,26 @@ impl<'a, 'gcx, 'tcx> GlobalFulfilledPredicates<'gcx> { pub fn new(dep_graph: DepGraph) -> GlobalFulfilledPredicates<'gcx> { GlobalFulfilledPredicates { set: FxHashSet(), - dep_graph: dep_graph, + dep_graph, } } - pub fn check_duplicate(&self, key: &ty::Predicate<'tcx>) -> bool { + pub fn check_duplicate(&self, tcx: TyCtxt, key: &ty::Predicate<'tcx>) -> bool { if let ty::Predicate::Trait(ref data) = *key { - self.check_duplicate_trait(data) + self.check_duplicate_trait(tcx, data) } else { false } } - pub fn check_duplicate_trait(&self, data: &ty::PolyTraitPredicate<'tcx>) -> bool { + pub fn check_duplicate_trait(&self, tcx: TyCtxt, data: &ty::PolyTraitPredicate<'tcx>) -> bool { // For the global predicate registry, when we find a match, it // may have been computed by some other task, so we want to // add a read from the node corresponding to the predicate // processing to make sure we get the transitive dependencies. if self.set.contains(data) { debug_assert!(data.is_global()); - self.dep_graph.read(data.dep_node()); + self.dep_graph.read(data.dep_node(tcx)); debug!("check_duplicate: global predicate `{:?}` already proved elsewhere", data); true diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index c51974e6e6..6b243ffa5f 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -28,7 +28,6 @@ use std::rc::Rc; use syntax::ast; use syntax_pos::{Span, DUMMY_SP}; -pub use self::error_reporting::TraitErrorKey; pub use self::coherence::orphan_check; pub use self::coherence::overlapping_impls; pub use self::coherence::OrphanCheckErr; @@ -119,27 +118,34 @@ pub enum ObligationCauseCode<'tcx> { /// Obligation incurred due to an object cast. ObjectCastObligation(/* Object type */ Ty<'tcx>), - /// Various cases where expressions must be sized/copy/etc: - AssignmentLhsSized, // L = X implies that L is Sized - StructInitializerSized, // S { ... } must be Sized - VariableType(ast::NodeId), // Type of each variable must be Sized - ReturnType, // Return type must be Sized - RepeatVec, // [T,..n] --> T must be Copy - - // Types of fields (other than the last) in a struct must be sized. + // Various cases where expressions must be sized/copy/etc: + /// L = X implies that L is Sized + AssignmentLhsSized, + /// (x1, .., xn) must be Sized + TupleInitializerSized, + /// S { ... } must be Sized + StructInitializerSized, + /// Type of each variable must be Sized + VariableType(ast::NodeId), + /// Return type must be Sized + SizedReturnType, + /// [T,..n] --> T must be Copy + RepeatVec, + + /// Types of fields (other than the last) in a struct must be sized. FieldSized, - // Constant expressions must be sized. + /// Constant expressions must be sized. ConstSized, - // static items must have `Sync` type + /// static items must have `Sync` type SharedStatic, BuiltinDerivedObligation(DerivedObligationCause<'tcx>), ImplDerivedObligation(DerivedObligationCause<'tcx>), - // error derived when matching traits/impls; see ObligationCause for more details + /// error derived when matching traits/impls; see ObligationCause for more details CompareImplMethodObligation { item_name: ast::Name, impl_item_def_id: DefId, @@ -147,37 +153,43 @@ pub enum ObligationCauseCode<'tcx> { lint_id: Option, }, - // Checking that this expression can be assigned where it needs to be + /// Checking that this expression can be assigned where it needs to be // FIXME(eddyb) #11161 is the original Expr required? ExprAssignable, - // Computing common supertype in the arms of a match expression + /// Computing common supertype in the arms of a match expression MatchExpressionArm { arm_span: Span, source: hir::MatchSource }, - // Computing common supertype in an if expression + /// Computing common supertype in an if expression IfExpression, - // Computing common supertype of an if expression with no else counter-part + /// Computing common supertype of an if expression with no else counter-part IfExpressionWithNoElse, - // `where a == b` + /// `where a == b` EquatePredicate, - // `main` has wrong type + /// `main` has wrong type MainFunctionType, - // `start` has wrong type + /// `start` has wrong type StartFunctionType, - // intrinsic has wrong type + /// intrinsic has wrong type IntrinsicType, - // method receiver + /// method receiver MethodReceiver, - // `return` with no expression + /// `return` with no expression ReturnNoExpression, + + /// `return` with an expression + ReturnType(ast::NodeId), + + /// Block implicit return + BlockTailExpression(ast::NodeId), } #[derive(Clone, Debug, PartialEq, Eq)] @@ -384,7 +396,7 @@ pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx infcx.tcx.item_path_str(def_id)); let trait_ref = ty::TraitRef { - def_id: def_id, + def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]), }; let obligation = Obligation { @@ -484,7 +496,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let elaborated_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates), unnormalized_env.reveal); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let predicates = match fully_normalize( &infcx, cause, @@ -499,7 +511,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ) { Ok(predicates) => predicates, Err(errors) => { - infcx.report_fulfillment_errors(&errors); + infcx.report_fulfillment_errors(&errors, None); // An unnormalized env is better than nothing. return elaborated_env; } @@ -598,7 +610,7 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("normalize_and_test_predicates(predicates={:?})", predicates); - tcx.infer_ctxt(()).enter(|infcx| { + let result = tcx.infer_ctxt().enter(|infcx| { let param_env = ty::ParamEnv::empty(Reveal::All); let mut selcx = SelectionContext::new(&infcx); let mut fulfill_cx = FulfillmentContext::new(); @@ -614,7 +626,10 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } fulfill_cx.select_all_or_error(&infcx).is_ok() - }) + }); + debug!("normalize_and_test_predicates(predicates={:?}) = {:?}", + predicates, result); + result } /// Given a trait `trait_ref`, iterates the vtable entries diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 0e3a53129d..9c04c013c4 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -260,7 +260,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // The `Self` type is erased, so it should not appear in list of // arguments or return type apart from the receiver. - let ref sig = self.type_of(method.def_id).fn_sig(); + let ref sig = self.fn_sig(method.def_id); for input_ty in &sig.skip_binder().inputs()[1..] { if self.contains_illegal_self_type_reference(trait_def_id, input_ty) { return Some(MethodViolationCode::ReferencesSelf); @@ -354,7 +354,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // direct equality here because all of these types // are part of the formal parameter listing, and // hence there should be no inference variables. - let projection_trait_ref = ty::Binder(data.trait_ref.clone()); + let projection_trait_ref = ty::Binder(data.trait_ref(self)); let is_supertrait_of_current_trait = supertraits.as_ref().unwrap().contains(&projection_trait_ref); diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 787452121d..b528485274 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -245,11 +245,11 @@ impl<'a, 'b, 'gcx, 'tcx> AssociatedTypeNormalizer<'a, 'b, 'gcx, 'tcx> { -> AssociatedTypeNormalizer<'a, 'b, 'gcx, 'tcx> { AssociatedTypeNormalizer { - selcx: selcx, - param_env: param_env, - cause: cause, + selcx, + param_env, + cause, obligations: vec![], - depth: depth, + depth, } } @@ -365,13 +365,11 @@ pub fn normalize_projection_type<'a, 'b, 'gcx, 'tcx>( // information is available. let tcx = selcx.infcx().tcx; - let def_id = tcx.associated_items(projection_ty.trait_ref.def_id).find(|i| - i.name == projection_ty.item_name(tcx) && i.kind == ty::AssociatedKind::Type - ).map(|i| i.def_id).unwrap(); + let def_id = projection_ty.item_def_id; let ty_var = selcx.infcx().next_ty_var( TypeVariableOrigin::NormalizeProjectionType(tcx.def_span(def_id))); let projection = ty::Binder(ty::ProjectionPredicate { - projection_ty: projection_ty, + projection_ty, ty: ty_var }); let obligation = Obligation::with_depth( @@ -447,8 +445,8 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>( // normalization. In that case, I think we will want this code: // // ``` - // let ty = selcx.tcx().mk_projection(projection_ty.trait_ref, - // projection_ty.item_name(tcx); + // let ty = selcx.tcx().mk_projection(projection_ty.item_def_id, + // projection_ty.substs; // return Some(NormalizedTy { value: v, obligations: vec![] }); // ``` @@ -514,12 +512,12 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>( obligations.extend(normalizer.obligations); Normalized { value: normalized_ty, - obligations: obligations, + obligations, } } else { Normalized { value: projected_ty, - obligations: obligations, + obligations, } }; infcx.projection_cache.borrow_mut() @@ -585,15 +583,13 @@ fn normalize_to_error<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, 'gcx, 'tc depth: usize) -> NormalizedTy<'tcx> { - let trait_ref = projection_ty.trait_ref.to_poly_trait_ref(); - let trait_obligation = Obligation { cause: cause, + let trait_ref = projection_ty.trait_ref(selcx.tcx()).to_poly_trait_ref(); + let trait_obligation = Obligation { cause, recursion_depth: depth, param_env, predicate: trait_ref.to_predicate() }; let tcx = selcx.infcx().tcx; - let def_id = tcx.associated_items(projection_ty.trait_ref.def_id).find(|i| - i.name == projection_ty.item_name(tcx) && i.kind == ty::AssociatedKind::Type - ).map(|i| i.def_id).unwrap(); + let def_id = projection_ty.item_def_id; let new_value = selcx.infcx().next_ty_var( TypeVariableOrigin::NormalizeProjectionType(tcx.def_span(def_id))); Normalized { @@ -654,7 +650,7 @@ fn project_type<'cx, 'gcx, 'tcx>( selcx.infcx().report_overflow_error(&obligation, true); } - let obligation_trait_ref = &obligation.predicate.trait_ref; + let obligation_trait_ref = &obligation.predicate.trait_ref(selcx.tcx()); debug!("project: obligation_trait_ref={:?}", obligation_trait_ref); @@ -743,12 +739,10 @@ fn project_type<'cx, 'gcx, 'tcx>( &obligation_trait_ref, candidate))) } - None => { - Ok(ProjectedTy::NoProgress( - selcx.tcx().mk_projection( - obligation.predicate.trait_ref.clone(), - obligation.predicate.item_name(selcx.tcx())))) - } + None => Ok(ProjectedTy::NoProgress( + selcx.tcx().mk_projection( + obligation.predicate.item_def_id, + obligation.predicate.substs))) } } @@ -788,10 +782,11 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>( { debug!("assemble_candidates_from_trait_def(..)"); + let tcx = selcx.tcx(); // Check whether the self-type is itself a projection. let (def_id, substs) = match obligation_trait_ref.self_ty().sty { ty::TyProjection(ref data) => { - (data.trait_ref.def_id, data.trait_ref.substs) + (data.trait_ref(tcx).def_id, data.substs) } ty::TyAnon(def_id, substs) => (def_id, substs), ty::TyInfer(ty::TyVar(_)) => { @@ -804,9 +799,9 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>( }; // If so, extract what we know from the trait and try to come up with a good answer. - let trait_predicates = selcx.tcx().predicates_of(def_id); - let bounds = trait_predicates.instantiate(selcx.tcx(), substs); - let bounds = elaborate_predicates(selcx.tcx(), bounds.predicates); + let trait_predicates = tcx.predicates_of(def_id); + let bounds = trait_predicates.instantiate(tcx, substs); + let bounds = elaborate_predicates(tcx, bounds.predicates); assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref, @@ -832,12 +827,12 @@ fn assemble_candidates_from_predicates<'cx, 'gcx, 'tcx, I>( predicate); match predicate { ty::Predicate::Projection(ref data) => { - let tcx = selcx.tcx(); - let same_name = data.item_name(tcx) == obligation.predicate.item_name(tcx); + let same_def_id = + data.0.projection_ty.item_def_id == obligation.predicate.item_def_id; - let is_match = same_name && infcx.probe(|_| { + let is_match = same_def_id && infcx.probe(|_| { let data_poly_trait_ref = - data.to_poly_trait_ref(); + data.to_poly_trait_ref(infcx.tcx); let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); infcx.at(&obligation.cause, obligation.param_env) @@ -850,8 +845,8 @@ fn assemble_candidates_from_predicates<'cx, 'gcx, 'tcx, I>( }); debug!("assemble_candidates_from_predicates: candidate={:?} \ - is_match={} same_name={}", - data, is_match, same_name); + is_match={} same_def_id={}", + data, is_match, same_def_id); if is_match { candidate_set.vec.push(ctor(data.clone())); @@ -916,9 +911,10 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>( // In either case, we handle this by not adding a // candidate for an impl if it contains a `default` // type. + let item_name = selcx.tcx().associated_item(obligation.predicate.item_def_id).name; let node_item = assoc_ty_def(selcx, impl_data.impl_def_id, - obligation.predicate.item_name(selcx.tcx())); + item_name); let is_default = if node_item.node.is_from_trait() { // If true, the impl inherited a `type Foo = Bar` @@ -1091,10 +1087,9 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>( // select only those projections that are actually projecting an // item with the correct name - let tcx = selcx.tcx(); let env_predicates = env_predicates.filter_map(|p| match p { ty::Predicate::Projection(data) => - if data.item_name(tcx) == obligation.predicate.item_name(tcx) { + if data.0.projection_ty.item_def_id == obligation.predicate.item_def_id { Some(data) } else { None @@ -1104,7 +1099,7 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>( // select those with a relevant trait-ref let mut env_predicates = env_predicates.filter(|data| { - let data_poly_trait_ref = data.to_poly_trait_ref(); + let data_poly_trait_ref = data.to_poly_trait_ref(selcx.tcx()); let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); selcx.infcx().probe(|_| { selcx.infcx().at(&obligation.cause, obligation.param_env) @@ -1137,9 +1132,19 @@ fn confirm_fn_pointer_candidate<'cx, 'gcx, 'tcx>( -> Progress<'tcx> { let fn_type = selcx.infcx().shallow_resolve(fn_pointer_vtable.fn_ty); - let sig = fn_type.fn_sig(); + let sig = fn_type.fn_sig(selcx.tcx()); + let Normalized { + value: sig, + obligations + } = normalize_with_depth(selcx, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth+1, + &sig); + confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes) .with_addl_obligations(fn_pointer_vtable.nested) + .with_addl_obligations(obligations) } fn confirm_closure_candidate<'cx, 'gcx, 'tcx>( @@ -1149,7 +1154,7 @@ fn confirm_closure_candidate<'cx, 'gcx, 'tcx>( -> Progress<'tcx> { let closure_typer = selcx.closure_typer(); - let closure_type = closure_typer.closure_type(vtable.closure_def_id) + let closure_type = closure_typer.fn_sig(vtable.closure_def_id) .subst(selcx.tcx(), vtable.substs.substs); let Normalized { value: closure_type, @@ -1192,7 +1197,7 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>( // Note: we unwrap the binder here but re-create it below (1) let ty::Binder((trait_ref, ret_type)) = tcx.closure_trait_ref_and_return_type(fn_once_def_id, - obligation.predicate.trait_ref.self_ty(), + obligation.predicate.self_ty(), fn_sig, flag); @@ -1217,12 +1222,12 @@ fn confirm_param_env_candidate<'cx, 'gcx, 'tcx>( let infcx = selcx.infcx(); let cause = obligation.cause.clone(); let param_env = obligation.param_env; - let trait_ref = obligation.predicate.trait_ref; + let trait_ref = obligation.predicate.trait_ref(infcx.tcx); match infcx.match_poly_projection_predicate(cause, param_env, poly_projection, trait_ref) { Ok(InferOk { value: ty_match, obligations }) => { Progress { ty: ty_match.value, - obligations: obligations, + obligations, cacheable: ty_match.unconstrained_regions.is_empty(), } } @@ -1248,7 +1253,8 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>( let tcx = selcx.tcx(); let param_env = obligation.param_env; - let assoc_ty = assoc_ty_def(selcx, impl_def_id, obligation.predicate.item_name(tcx)); + let assoc_ty = assoc_ty_def(selcx, impl_def_id, + tcx.associated_item(obligation.predicate.item_def_id).name); let ty = if !assoc_ty.item.defaultness.has_value() { // This means that the impl is missing a definition for the @@ -1257,7 +1263,7 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>( // just return TyError. debug!("confirm_impl_candidate: no associated type {:?} for {:?}", assoc_ty.item.name, - obligation.predicate.trait_ref); + obligation.predicate); tcx.types.err } else { tcx.type_of(assoc_ty.item.def_id) @@ -1296,7 +1302,7 @@ fn assoc_ty_def<'cx, 'gcx, 'tcx>( if item.kind == ty::AssociatedKind::Type && item.name == assoc_ty_name { return specialization_graph::NodeItem { node: specialization_graph::Node::Impl(impl_def_id), - item: item, + item, }; } } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 998201ad8d..f046cad82f 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -212,7 +212,7 @@ impl<'a, 'tcx> ty::Lift<'tcx> for SelectionCandidate<'a> { Some(match *self { BuiltinCandidate { has_nested } => { BuiltinCandidate { - has_nested: has_nested + has_nested, } } ImplCandidate(def_id) => ImplCandidate(def_id), @@ -290,7 +290,7 @@ pub struct EvaluationCache<'tcx> { impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { pub fn new(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>) -> SelectionContext<'cx, 'gcx, 'tcx> { SelectionContext { - infcx: infcx, + infcx, freshener: infcx.freshener(), intercrate: false, inferred_obligations: SnapshotVec::new(), @@ -299,7 +299,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>) -> SelectionContext<'cx, 'gcx, 'tcx> { SelectionContext { - infcx: infcx, + infcx, freshener: infcx.freshener(), intercrate: true, inferred_obligations: SnapshotVec::new(), @@ -381,7 +381,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { assert!(!obligation.predicate.has_escaping_regions()); let tcx = self.tcx(); - let dep_node = obligation.predicate.dep_node(); + let dep_node = obligation.predicate.dep_node(tcx); let _task = tcx.dep_graph.in_task(dep_node); let stack = self.push_stack(TraitObligationStackList::empty(), obligation); @@ -514,11 +514,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { debug!("evaluate_predicate_recursively({:?})", obligation); + let tcx = self.tcx(); + // Check the cache from the tcx of predicates that we know // have been proven elsewhere. This cache only contains // predicates that are global in scope and hence unaffected by // the current environment. - if self.tcx().fulfilled_predicates.borrow().check_duplicate(&obligation.predicate) { + if tcx.fulfilled_predicates.borrow().check_duplicate(tcx, &obligation.predicate) { return EvaluatedToOk; } @@ -1210,7 +1212,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { skol_map); let (def_id, substs) = match skol_trait_predicate.trait_ref.self_ty().sty { - ty::TyProjection(ref data) => (data.trait_ref.def_id, data.trait_ref.substs), + ty::TyProjection(ref data) => + (data.trait_ref(self.tcx()).def_id, data.substs), ty::TyAnon(def_id, substs) => (def_id, substs), _ => { span_bug!( @@ -1402,19 +1405,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } // provide an impl, but only for suitable `fn` pointers - ty::TyFnDef(.., ty::Binder(ty::FnSig { - unsafety: hir::Unsafety::Normal, - abi: Abi::Rust, - variadic: false, - .. - })) | - ty::TyFnPtr(ty::Binder(ty::FnSig { - unsafety: hir::Unsafety::Normal, - abi: Abi::Rust, - variadic: false, - .. - })) => { - candidates.vec.push(FnPointerCandidate); + ty::TyFnDef(..) | ty::TyFnPtr(_) => { + if let ty::Binder(ty::FnSig { + unsafety: hir::Unsafety::Normal, + abi: Abi::Rust, + variadic: false, + .. + }) = self_ty.fn_sig(self.tcx()) { + candidates.vec.push(FnPointerCandidate); + } } _ => { } @@ -1431,10 +1430,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { { debug!("assemble_candidates_from_impls(obligation={:?})", obligation); - let def = self.tcx().trait_def(obligation.predicate.def_id()); - - def.for_each_relevant_impl( - self.tcx(), + self.tcx().for_each_relevant_impl( + obligation.predicate.def_id(), obligation.predicate.0.trait_ref.self_ty(), |impl_def_id| { self.probe(|this, snapshot| { /* [1] */ @@ -1653,6 +1650,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { def_id_a == def_id_b } + // (.., T) -> (.., U). + (&ty::TyTuple(tys_a, _), &ty::TyTuple(tys_b, _)) => { + tys_a.len() == tys_b.len() + } + _ => false }; @@ -2202,7 +2204,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { debug!("vtable_default_impl: obligations={:?}", obligations); VtableDefaultImplData { - trait_def_id: trait_def_id, + trait_def_id, nested: obligations } } @@ -2270,7 +2272,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // e.g. `impl> Foo<::T> for V` impl_obligations.append(&mut substs.obligations); - VtableImplData { impl_def_id: impl_def_id, + VtableImplData { impl_def_id, substs: substs.value, nested: impl_obligations } } @@ -2333,7 +2335,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { VtableObjectData { upcast_trait_ref: upcast_trait_ref.unwrap(), - vtable_base: vtable_base, + vtable_base, nested: vec![] } } @@ -2346,7 +2348,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // ok to skip binder; it is reintroduced below let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); - let sig = self_ty.fn_sig(); + let sig = self_ty.fn_sig(self.tcx()); let trait_ref = self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(), self_ty, @@ -2354,11 +2356,18 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { util::TupleArgumentsFlag::Yes) .map_bound(|(trait_ref, _)| trait_ref); + let Normalized { value: trait_ref, obligations } = + project::normalize_with_depth(self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &trait_ref); + self.confirm_poly_trait_refs(obligation.cause.clone(), obligation.param_env, obligation.predicate.to_poly_trait_ref(), trait_ref)?; - Ok(VtableFnPointerData { fn_ty: self_ty, nested: vec![] }) + Ok(VtableFnPointerData { fn_ty: self_ty, nested: obligations }) } fn confirm_closure_candidate(&mut self, @@ -2395,7 +2404,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::Predicate::ClosureKind(closure_def_id, kind))); Ok(VtableClosureData { - closure_def_id: closure_def_id, + closure_def_id, substs: substs.clone(), nested: obligations }) @@ -2586,8 +2595,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let inner_source = field.subst(tcx, substs_a); let inner_target = field.subst(tcx, substs_b); - // Check that the source structure with the target's - // type parameters is a subtype of the target. + // Check that the source struct with the target's + // unsized parameters is equal to the target. let params = substs_a.iter().enumerate().map(|(i, &k)| { if ty_params.contains(i) { Kind::from(substs_b.type_at(i)) @@ -2612,6 +2621,37 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &[inner_target])); } + // (.., T) -> (.., U). + (&ty::TyTuple(tys_a, _), &ty::TyTuple(tys_b, _)) => { + assert_eq!(tys_a.len(), tys_b.len()); + + // The last field of the tuple has to exist. + let (a_last, a_mid) = if let Some(x) = tys_a.split_last() { + x + } else { + return Err(Unimplemented); + }; + let b_last = tys_b.last().unwrap(); + + // Check that the source tuple with the target's + // last element is equal to the target. + let new_tuple = tcx.mk_tup(a_mid.iter().chain(Some(b_last)), false); + let InferOk { obligations, .. } = + self.infcx.at(&obligation.cause, obligation.param_env) + .eq(target, new_tuple) + .map_err(|_| Unimplemented)?; + self.inferred_obligations.extend(obligations); + + // Construct the nested T: Unsize predicate. + nested.push(tcx.predicate_for_trait_def( + obligation.param_env, + obligation.cause.clone(), + obligation.predicate.def_id(), + obligation.recursion_depth + 1, + a_last, + &[b_last])); + } + _ => bug!() }; @@ -2785,8 +2825,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation.predicate.to_poly_trait_ref().fold_with(&mut self.freshener); TraitObligationStack { - obligation: obligation, - fresh_trait_ref: fresh_trait_ref, + obligation, + fresh_trait_ref, previous: previous_stack, } } @@ -2797,7 +2837,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { substs: ty::ClosureSubsts<'tcx>) -> ty::PolyTraitRef<'tcx> { - let closure_type = self.infcx.closure_type(closure_def_id) + let closure_type = self.infcx.fn_sig(closure_def_id) .subst(self.tcx(), substs.substs); let ty::Binder((trait_ref, _)) = self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(), @@ -2870,7 +2910,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { predicate.obligations.into_iter().chain( Some(Obligation { cause: cause.clone(), - recursion_depth: recursion_depth, + recursion_depth, param_env, predicate: predicate.value })) diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 689f06a359..36b2027a3d 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -125,7 +125,7 @@ pub fn find_associated_item<'a, 'tcx>( let ancestors = trait_def.ancestors(tcx, impl_data.impl_def_id); match ancestors.defs(tcx, item.name, item.kind).next() { Some(node_item) => { - let substs = tcx.infer_ctxt(()).enter(|infcx| { + let substs = tcx.infer_ctxt().enter(|infcx| { let param_env = ty::ParamEnv::empty(Reveal::All); let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs); let substs = translate_substs(&infcx, param_env, impl_data.impl_def_id, @@ -188,7 +188,7 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap(); // Create a infcx, taking the predicates of impl1 as assumptions: - let result = tcx.infer_ctxt(()).enter(|infcx| { + let result = tcx.infer_ctxt().enter(|infcx| { // Normalize the trait reference. The WF rules ought to ensure // that this always succeeds. let impl1_trait_ref = @@ -300,7 +300,8 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx -> Rc { let mut sg = specialization_graph::Graph::new(); - let mut trait_impls: Vec = tcx.trait_impls_of(trait_id).iter().collect(); + let mut trait_impls = Vec::new(); + tcx.for_each_impl(trait_id, |impl_did| trait_impls.push(impl_did)); // The coherence checking implementation seems to rely on impls being // iterated over (roughly) in definition order, so we are sorting by diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index 702c5035a1..f80caeec46 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -109,7 +109,7 @@ impl<'a, 'gcx, 'tcx> Children { let possible_sibling = *slot; let tcx = tcx.global_tcx(); - let (le, ge) = tcx.infer_ctxt(()).enter(|infcx| { + let (le, ge) = tcx.infer_ctxt().enter(|infcx| { let overlap = traits::overlapping_impls(&infcx, possible_sibling, impl_def_id); diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 4abb0cb549..f1c176561e 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -189,9 +189,11 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { tcx.lift(&ty).map(super::ObjectCastObligation) } super::AssignmentLhsSized => Some(super::AssignmentLhsSized), + super::TupleInitializerSized => Some(super::TupleInitializerSized), super::StructInitializerSized => Some(super::StructInitializerSized), super::VariableType(id) => Some(super::VariableType(id)), - super::ReturnType => Some(super::ReturnType), + super::ReturnType(id) => Some(super::ReturnType(id)), + super::SizedReturnType => Some(super::SizedReturnType), super::RepeatVec => Some(super::RepeatVec), super::FieldSized => Some(super::FieldSized), super::ConstSized => Some(super::ConstSized), @@ -207,40 +209,25 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { trait_item_def_id, lint_id } => { Some(super::CompareImplMethodObligation { - item_name: item_name, - impl_item_def_id: impl_item_def_id, - trait_item_def_id: trait_item_def_id, - lint_id: lint_id, + item_name, + impl_item_def_id, + trait_item_def_id, + lint_id, }) } - super::ExprAssignable => { - Some(super::ExprAssignable) - } + super::ExprAssignable => Some(super::ExprAssignable), super::MatchExpressionArm { arm_span, source } => { - Some(super::MatchExpressionArm { arm_span: arm_span, + Some(super::MatchExpressionArm { arm_span, source: source }) } - super::IfExpression => { - Some(super::IfExpression) - } - super::IfExpressionWithNoElse => { - Some(super::IfExpressionWithNoElse) - } - super::EquatePredicate => { - Some(super::EquatePredicate) - } - super::MainFunctionType => { - Some(super::MainFunctionType) - } - super::StartFunctionType => { - Some(super::StartFunctionType) - } - super::IntrinsicType => { - Some(super::IntrinsicType) - } - super::MethodReceiver => { - Some(super::MethodReceiver) - } + super::IfExpression => Some(super::IfExpression), + super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse), + super::EquatePredicate => Some(super::EquatePredicate), + super::MainFunctionType => Some(super::MainFunctionType), + super::StartFunctionType => Some(super::StartFunctionType), + super::IntrinsicType => Some(super::IntrinsicType), + super::MethodReceiver => Some(super::MethodReceiver), + super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)), } } } @@ -266,7 +253,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCause<'a> { traits::ObligationCause { span: self.span, body_id: self.body_id, - code: code, + code, } }) } @@ -284,9 +271,9 @@ impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> { }) => { tcx.lift(&substs).map(|substs| { traits::VtableImpl(traits::VtableImplData { - impl_def_id: impl_def_id, - substs: substs, - nested: nested + impl_def_id, + substs, + nested, }) }) } @@ -298,17 +285,17 @@ impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> { }) => { tcx.lift(&substs).map(|substs| { traits::VtableClosure(traits::VtableClosureData { - closure_def_id: closure_def_id, - substs: substs, - nested: nested + closure_def_id, + substs, + nested, }) }) } traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested }) => { tcx.lift(&fn_ty).map(|fn_ty| { traits::VtableFnPointer(traits::VtableFnPointerData { - fn_ty: fn_ty, - nested: nested, + fn_ty, + nested, }) }) } @@ -322,8 +309,8 @@ impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> { tcx.lift(&upcast_trait_ref).map(|trait_ref| { traits::VtableObject(traits::VtableObjectData { upcast_trait_ref: trait_ref, - vtable_base: vtable_base, - nested: nested + vtable_base, + nested, }) }) } @@ -490,14 +477,17 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> { super::TupleElem | super::ItemObligation(_) | super::AssignmentLhsSized | + super::TupleInitializerSized | super::StructInitializerSized | super::VariableType(_) | - super::ReturnType | + super::ReturnType(_) | + super::SizedReturnType | super::ReturnNoExpression | super::RepeatVec | super::FieldSized | super::ConstSized | super::SharedStatic | + super::BlockTailExpression(_) | super::CompareImplMethodObligation { .. } => self.clone(), super::ProjectionWf(proj) => super::ProjectionWf(proj.fold_with(folder)), @@ -535,14 +525,17 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> { super::TupleElem | super::ItemObligation(_) | super::AssignmentLhsSized | + super::TupleInitializerSized | super::StructInitializerSized | super::VariableType(_) | - super::ReturnType | + super::ReturnType(_) | + super::SizedReturnType | super::ReturnNoExpression | super::RepeatVec | super::FieldSized | super::ConstSized | super::SharedStatic | + super::BlockTailExpression(_) | super::CompareImplMethodObligation { .. } => false, super::ProjectionWf(proj) => proj.visit_with(visitor), diff --git a/src/librustc/traits/trans/mod.rs b/src/librustc/traits/trans/mod.rs index 7ad2ef90f0..9c6047b28b 100644 --- a/src/librustc/traits/trans/mod.rs +++ b/src/librustc/traits/trans/mod.rs @@ -13,7 +13,8 @@ // seems likely that they should eventually be merged into more // general routines. -use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig}; +use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig, + DepConstructor}; use hir::def_id::DefId; use infer::TransNormalize; use std::cell::RefCell; @@ -40,13 +41,13 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { // Remove any references to regions; this helps improve caching. let trait_ref = self.erase_regions(&trait_ref); - self.trans_trait_caches.trait_cache.memoize(trait_ref, || { + self.trans_trait_caches.trait_cache.memoize(self, trait_ref, || { debug!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})", trait_ref, trait_ref.def_id()); // Do the initial selection for the obligation. This yields the // shallow result we are looking for -- that is, what specific impl. - self.infer_ctxt(()).enter(|infcx| { + self.infer_ctxt().enter(|infcx| { let mut selcx = SelectionContext::new(&infcx); let param_env = ty::ParamEnv::empty(Reveal::All); @@ -138,7 +139,7 @@ impl<'a, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'gcx> { if !ty.has_projection_types() { ty } else { - self.tcx.trans_trait_caches.project_cache.memoize(ty, || { + self.tcx.trans_trait_caches.project_cache.memoize(self.tcx, ty, || { debug!("AssociatedTypeNormalizer: ty={:?}", ty); self.tcx.normalize_associated_type(&ty) }) @@ -170,8 +171,8 @@ pub struct TraitSelectionCache<'tcx> { impl<'tcx> DepTrackingMapConfig for TraitSelectionCache<'tcx> { type Key = ty::PolyTraitRef<'tcx>; type Value = Vtable<'tcx, ()>; - fn to_dep_node(key: &ty::PolyTraitRef<'tcx>) -> DepNode { - key.to_poly_trait_predicate().dep_node() + fn to_dep_node(tcx: TyCtxt, key: &ty::PolyTraitRef<'tcx>) -> DepNode { + key.to_poly_trait_predicate().dep_node(tcx) } } @@ -184,7 +185,7 @@ pub struct ProjectionCache<'gcx> { impl<'gcx> DepTrackingMapConfig for ProjectionCache<'gcx> { type Key = Ty<'gcx>; type Value = Ty<'gcx>; - fn to_dep_node(key: &Self::Key) -> DepNode { + fn to_dep_node(tcx: TyCtxt, key: &Self::Key) -> DepNode { // Ideally, we'd just put `key` into the dep-node, but we // can't put full types in there. So just collect up all the // def-ids of structs/enums as well as any traits that we @@ -202,13 +203,13 @@ impl<'gcx> DepTrackingMapConfig for ProjectionCache<'gcx> { let def_ids: Vec = key.walk() .filter_map(|t| match t.sty { - ty::TyAdt(adt_def, _) => Some(adt_def.did), - ty::TyProjection(ref proj) => Some(proj.trait_ref.def_id), - _ => None, + ty::TyAdt(adt_def, _) => Some(adt_def.did), + ty::TyProjection(ref proj) => Some(proj.item_def_id), + _ => None, }) .collect(); - DepNode::ProjectionCache { def_ids: def_ids } + DepNode::new(tcx, DepConstructor::ProjectionCache { def_ids: def_ids }) } } diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index c385927811..dae0c89690 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -288,7 +288,7 @@ pub fn supertrait_def_ids<'cx, 'gcx, 'tcx>(tcx: TyCtxt<'cx, 'gcx, 'tcx>, -> SupertraitDefIds<'cx, 'gcx, 'tcx> { SupertraitDefIds { - tcx: tcx, + tcx, stack: vec![trait_def_id], visited: Some(trait_def_id).into_iter().collect(), } @@ -399,8 +399,8 @@ pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>, generic_bounds.predicates.iter().map(|predicate| { Obligation { cause: cause.clone(), - recursion_depth: recursion_depth, - param_env: param_env, + recursion_depth, + param_env, predicate: predicate.clone() } }).collect() } @@ -413,9 +413,9 @@ pub fn predicate_for_trait_ref<'tcx>( -> PredicateObligation<'tcx> { Obligation { - cause: cause, - param_env: param_env, - recursion_depth: recursion_depth, + cause, + param_env, + recursion_depth, predicate: trait_ref.to_predicate(), } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 2bbb71610a..48d6bdf95b 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -28,7 +28,7 @@ use mir::transform::Passes; use ty::subst::{Kind, Substs}; use ty::ReprOptions; use traits; -use ty::{self, TraitRef, Ty, TypeAndMut}; +use ty::{self, Ty, TypeAndMut}; use ty::{TyS, TypeVariants, Slice}; use ty::{AdtKind, AdtDef, ClosureSubsts, Region}; use hir::FreevarMap; @@ -107,7 +107,7 @@ pub struct CtxtInterners<'tcx> { impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { fn new(arena: &'tcx DroplessArena) -> CtxtInterners<'tcx> { CtxtInterners { - arena: arena, + arena, type_: RefCell::new(FxHashSet()), type_list: RefCell::new(FxHashSet()), substs: RefCell::new(FxHashSet()), @@ -376,8 +376,8 @@ impl<'tcx> TypeckTables<'tcx> { } } - pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option> { - Some(self.upvar_capture_map.get(&upvar_id).unwrap().clone()) + pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> ty::UpvarCapture<'tcx> { + self.upvar_capture_map[&upvar_id] } } @@ -732,12 +732,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { global_interners: interners, dep_graph: dep_graph.clone(), types: common_types, - named_region_map: named_region_map, + named_region_map, trait_map: resolutions.trait_map, export_map: resolutions.export_map, fulfilled_predicates: RefCell::new(fulfilled_predicates), - hir: hir, - def_path_hash_to_def_id: def_path_hash_to_def_id, + hir, + def_path_hash_to_def_id, maps: maps::Maps::new(providers), mir_passes, freevars: RefCell::new(resolutions.freevars), @@ -745,7 +745,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { rcache: RefCell::new(FxHashMap()), normalized_cache: RefCell::new(FxHashMap()), inhabitedness_cache: RefCell::new(FxHashMap()), - lang_items: lang_items, + lang_items, used_unsafe: RefCell::new(NodeSet()), used_mut_nodes: RefCell::new(NodeSet()), stability: RefCell::new(stability), @@ -753,7 +753,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { evaluation_cache: traits::EvaluationCache::new(), rvalue_promotable_to_static: RefCell::new(NodeMap()), crate_name: Symbol::intern(crate_name), - data_layout: data_layout, + data_layout, layout_interner: RefCell::new(FxHashSet()), layout_depth: Cell::new(0), derive_macros: RefCell::new(NodeMap()), @@ -964,8 +964,8 @@ pub mod tls { let prev = tls.get(); tls.set(Some((gcx_ptr, interners_ptr))); let ret = f(TyCtxt { - gcx: gcx, - interners: interners + gcx, + interners, }); tls.set(prev); ret @@ -980,8 +980,8 @@ pub mod tls { let gcx = unsafe { &*(gcx as *const GlobalCtxt) }; let interners = unsafe { &*(interners as *const CtxtInterners) }; f(TyCtxt { - gcx: gcx, - interners: interners + gcx, + interners, }) }) } @@ -1378,9 +1378,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn mk_fn_def(self, def_id: DefId, - substs: &'tcx Substs<'tcx>, - fty: PolyFnSig<'tcx>) -> Ty<'tcx> { - self.mk_ty(TyFnDef(def_id, substs, fty)) + substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { + self.mk_ty(TyFnDef(def_id, substs)) } pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> { @@ -1396,12 +1395,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn mk_projection(self, - trait_ref: TraitRef<'tcx>, - item_name: Name) + item_def_id: DefId, + substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { - // take a copy of substs so that we own the vectors inside - let inner = ProjectionTy::from_ref_and_name(self, trait_ref, item_name); - self.mk_ty(TyProjection(inner)) + self.mk_ty(TyProjection(ProjectionTy { + item_def_id: item_def_id, + substs: substs, + })) } pub fn mk_closure(self, @@ -1409,7 +1409,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { self.mk_closure_from_closure_substs(closure_id, ClosureSubsts { - substs: substs + substs, }) } diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index d6804976e8..3442cf0ef6 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -14,7 +14,7 @@ use ty::{self, BoundRegion, DefIdTree, Region, Ty, TyCtxt}; use std::fmt; use syntax::abi; -use syntax::ast::{self, Name}; +use syntax::ast; use errors::DiagnosticBuilder; use syntax_pos::Span; @@ -47,7 +47,7 @@ pub enum TypeError<'tcx> { Traits(ExpectedFound), VariadicMismatch(ExpectedFound), CyclicTy, - ProjectionNameMismatched(ExpectedFound), + ProjectionMismatched(ExpectedFound), ProjectionBoundsLength(ExpectedFound), TyParamDefaultMismatch(ExpectedFound>), ExistentialMismatch(ExpectedFound<&'tcx ty::Slice>>), @@ -154,11 +154,11 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { if values.expected { "variadic" } else { "non-variadic" }, if values.found { "variadic" } else { "non-variadic" }) } - ProjectionNameMismatched(ref values) => { + ProjectionMismatched(ref values) => ty::tls::with(|tcx| { write!(f, "expected {}, found {}", - values.expected, - values.found) - } + tcx.item_path_str(values.expected), + tcx.item_path_str(values.found)) + }), ProjectionBoundsLength(ref values) => { write!(f, "expected {} associated type bindings, found {}", values.expected, diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 3d2cc4c598..68f85ba7d3 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -68,6 +68,7 @@ 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::TyFnDef(def_id, _) | ty::TyClosure(def_id, _) => { Some(ClosureSimplifiedType(def_id)) } @@ -75,7 +76,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ty::TyTuple(ref tys, _) => { Some(TupleSimplifiedType(tys.len())) } - ty::TyFnDef(.., ref f) | ty::TyFnPtr(ref f) => { + ty::TyFnPtr(ref f) => { Some(FunctionSimplifiedType(f.skip_binder().inputs().len())) } ty::TyProjection(_) | ty::TyParam(_) => { diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 46afa6ee7d..ce2bb23660 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -155,9 +155,8 @@ impl FlagComputation { self.add_tys(&ts[..]); } - &ty::TyFnDef(_, substs, f) => { + &ty::TyFnDef(_, substs) => { self.add_substs(substs); - self.add_fn_sig(f); } &ty::TyFnPtr(f) => { @@ -194,12 +193,12 @@ impl FlagComputation { } fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection) { - self.add_substs(projection.trait_ref.substs); + self.add_substs(projection.substs); self.add_ty(projection.ty); } fn add_projection_ty(&mut self, projection_ty: &ty::ProjectionTy) { - self.add_substs(projection_ty.trait_ref.substs); + self.add_substs(projection_ty.substs); } fn add_substs(&mut self, substs: &Substs) { diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index bb13031a2b..a1cd92c760 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -150,10 +150,6 @@ pub trait TypeVisitor<'tcx> : Sized { t.super_visit_with(self) } - fn visit_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool { - trait_ref.super_visit_with(self) - } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { r.super_visit_with(self) } @@ -238,10 +234,10 @@ impl<'a, 'gcx, 'tcx> RegionFolder<'a, 'gcx, 'tcx> { where F : FnMut(ty::Region<'tcx>, u32) -> ty::Region<'tcx> { RegionFolder { - tcx: tcx, - skipped_regions: skipped_regions, + tcx, + skipped_regions, current_depth: 1, - fld_r: fld_r, + fld_r, } } } @@ -393,9 +389,9 @@ impl<'a, 'gcx, 'tcx> RegionReplacer<'a, 'gcx, 'tcx> { where F : FnMut(ty::BoundRegion) -> ty::Region<'tcx> { RegionReplacer { - tcx: tcx, + tcx, current_depth: 1, - fld_r: fld_r, + fld_r, map: FxHashMap() } } @@ -621,7 +617,7 @@ impl LateBoundRegionsCollector { LateBoundRegionsCollector { current_depth: 1, regions: FxHashSet(), - just_constrained: just_constrained, + just_constrained, } } } diff --git a/src/librustc/ty/inhabitedness/def_id_forest.rs b/src/librustc/ty/inhabitedness/def_id_forest.rs index 6801e82fe7..231600f95a 100644 --- a/src/librustc/ty/inhabitedness/def_id_forest.rs +++ b/src/librustc/ty/inhabitedness/def_id_forest.rs @@ -52,7 +52,7 @@ impl<'a, 'gcx, 'tcx> DefIdForest { let mut root_ids = SmallVec::new(); root_ids.push(id); DefIdForest { - root_ids: root_ids, + root_ids, } } diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 7dca28df9d..32063a2dda 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use dep_graph::DepNode; use hir::def_id::DefId; use ty::{self, Ty, TypeFoldable, Substs}; use util::ppaux; @@ -59,26 +58,6 @@ impl<'tcx> InstanceDef<'tcx> { pub fn attrs<'a>(&self, tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> ty::Attributes<'tcx> { tcx.get_attrs(self.def_id()) } - - pub(crate) fn dep_node(&self) -> DepNode { - // HACK: def-id binning, project-style; someone replace this with - // real on-demand. - let ty = match self { - &InstanceDef::FnPtrShim(_, ty) => Some(ty), - &InstanceDef::DropGlue(_, ty) => ty, - _ => None - }.into_iter(); - - DepNode::MirShim( - Some(self.def_id()).into_iter().chain( - ty.flat_map(|t| t.walk()).flat_map(|t| match t.sty { - ty::TyAdt(adt_def, _) => Some(adt_def.did), - ty::TyProjection(ref proj) => Some(proj.trait_ref.def_id), - _ => None, - }) - ).collect() - ) - } } impl<'tcx> fmt::Display for Instance<'tcx> { diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 78536b53ba..73b577e2e8 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -100,7 +100,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // // Returns `None` for the local crate. if cnum != LOCAL_CRATE { - let opt_extern_crate = self.sess.cstore.extern_crate(cnum); + let opt_extern_crate = self.extern_crate(cnum.as_def_id()); let opt_extern_crate = opt_extern_crate.and_then(|extern_crate| { if extern_crate.direct { Some(extern_crate.def_id) @@ -129,15 +129,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn try_push_visible_item_path(self, buffer: &mut T, external_def_id: DefId) -> bool where T: ItemPathBuffer { - let visible_parent_map = self.sess.cstore.visible_parent_map(); + let visible_parent_map = self.sess.cstore.visible_parent_map(self.sess); let (mut cur_def, mut cur_path) = (external_def_id, Vec::::new()); loop { // If `cur_def` is a direct or injected extern crate, push the path to the crate // followed by the path to the item within the crate and return. if cur_def.index == CRATE_DEF_INDEX { - match self.sess.cstore.extern_crate(cur_def.krate) { - Some(extern_crate) if extern_crate.direct => { + match *self.extern_crate(cur_def) { + Some(ref extern_crate) if extern_crate.direct => { self.push_item_path(buffer, extern_crate.def_id); cur_path.iter().rev().map(|segment| buffer.push(&segment.as_str())).count(); return true; @@ -197,7 +197,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { data @ DefPathData::ClosureExpr | data @ DefPathData::Binding(..) | data @ DefPathData::ImplTrait | - data @ DefPathData::Typeof => { + data @ DefPathData::Typeof | + data @ DefPathData::GlobalMetaData(..) => { let parent_def_id = self.parent_def_id(def_id).unwrap(); self.push_item_path(buffer, parent_def_id); buffer.push(&data.as_interned_str()); @@ -347,7 +348,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option { .filter_map(|ty| characteristic_def_id_of_type(ty)) .next(), - ty::TyFnDef(def_id, ..) | + ty::TyFnDef(def_id, _) | ty::TyClosure(def_id, _) => Some(def_id), ty::TyBool | @@ -396,7 +397,7 @@ struct LocalPathBuffer { impl LocalPathBuffer { fn new(root_mode: RootMode) -> LocalPathBuffer { LocalPathBuffer { - root_mode: root_mode, + root_mode, str: String::new(), } } diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 12af56d5c3..4b8b39c1f5 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -285,11 +285,13 @@ impl Size { } /// Alignment of a type in bytes, both ABI-mandated and preferred. -/// Since alignments are always powers of 2, we can pack both in one byte, -/// giving each a nibble (4 bits) for a maximum alignment of 215 = 32768. +/// Each field is a power of two, giving the alignment a maximum +/// value of 2^(2^8 - 1), which is limited by LLVM to a i32, with +/// a maximum capacity of 2^31 - 1 or 2147483647. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct Align { - raw: u8 + abi: u8, + pref: u8, } impl Align { @@ -298,7 +300,7 @@ impl Align { } pub fn from_bytes(abi: u64, pref: u64) -> Result { - let pack = |align: u64| { + let log2 = |align: u64| { // Treat an alignment of 0 bytes like 1-byte alignment. if align == 0 { return Ok(0); @@ -312,7 +314,7 @@ impl Align { } if bytes != 1 { Err(format!("`{}` is not a power of 2", align)) - } else if pow > 0x0f { + } else if pow > 30 { Err(format!("`{}` is too large", align)) } else { Ok(pow) @@ -320,31 +322,30 @@ impl Align { }; Ok(Align { - raw: pack(abi)? | (pack(pref)? << 4) + abi: log2(abi)?, + pref: log2(pref)?, }) } pub fn abi(self) -> u64 { - 1 << (self.raw & 0xf) + 1 << self.abi } pub fn pref(self) -> u64 { - 1 << (self.raw >> 4) + 1 << self.pref } pub fn min(self, other: Align) -> Align { - let abi = cmp::min(self.raw & 0x0f, other.raw & 0x0f); - let pref = cmp::min(self.raw & 0xf0, other.raw & 0xf0); Align { - raw: abi | pref + abi: cmp::min(self.abi, other.abi), + pref: cmp::min(self.pref, other.pref), } } pub fn max(self, other: Align) -> Align { - let abi = cmp::max(self.raw & 0x0f, other.raw & 0x0f); - let pref = cmp::max(self.raw & 0xf0, other.raw & 0xf0); Align { - raw: abi | pref + abi: cmp::max(self.abi, other.abi), + pref: cmp::max(self.pref, other.pref), } } } @@ -609,7 +610,7 @@ impl<'a, 'tcx> Struct { }; let mut ret = Struct { - align: align, + align, primitive_align: align, packed: repr.packed(), sized: true, @@ -910,10 +911,10 @@ impl<'a, 'tcx> Union { fn new(dl: &TargetDataLayout, packed: bool) -> Union { let align = if packed { dl.i8_align } else { dl.aggregate_align }; Union { - align: align, + align, primitive_align: align, min_size: Size::from_bytes(0), - packed: packed, + packed, } } @@ -1169,8 +1170,8 @@ impl<'a, 'tcx> Layout { sized: true, align: element.align(dl), primitive_align: element.primitive_align(dl), - element_size: element_size, - count: count + element_size, + count, } } ty::TySlice(element) => { @@ -1220,12 +1221,16 @@ impl<'a, 'tcx> Layout { } ty::TyTuple(tys, _) => { - // FIXME(camlorn): if we ever allow unsized tuples, this needs to be checked. - // See the univariant case below to learn how. + let kind = if tys.len() == 0 { + StructKind::AlwaysSizedUnivariant + } else { + StructKind::MaybeUnsizedUnivariant + }; + let st = Struct::new(dl, &tys.iter().map(|ty| ty.layout(tcx, param_env)) .collect::, _>>()?, - &ReprOptions::default(), StructKind::AlwaysSizedUnivariant, ty)?; + &ReprOptions::default(), kind, ty)?; Univariant { variant: st, non_zero: false } } @@ -1276,9 +1281,9 @@ impl<'a, 'tcx> Layout { // grok. let (discr, signed) = Integer::repr_discr(tcx, ty, &def.repr, min, max); return success(CEnum { - discr: discr, - signed: signed, - non_zero: non_zero, + discr, + signed, + non_zero, // FIXME: should be u128? min: min as u64, max: max as u64 @@ -1360,7 +1365,7 @@ impl<'a, 'tcx> Layout { }; return success(RawNullablePointer { nndiscr: discr as u64, - value: value, + value, }); } @@ -1487,10 +1492,10 @@ impl<'a, 'tcx> Layout { General { discr: ity, - variants: variants, - size: size, - align: align, - primitive_align: primitive_align + variants, + size, + align, + primitive_align, } } @@ -1953,7 +1958,7 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> { ty::TyParam(_) | ty::TyProjection(_) => { assert!(tail.has_param_types() || tail.has_self_ty()); Ok(SizeSkeleton::Pointer { - non_zero: non_zero, + non_zero, tail: tcx.erase_regions(&tail) }) } @@ -2012,7 +2017,7 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> { return Ok(SizeSkeleton::Pointer { non_zero: non_zero || Some(def.did) == tcx.lang_items.non_zero(), - tail: tail + tail, }); } else { return Err(err); @@ -2026,7 +2031,7 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> { (None, Some(SizeSkeleton::Pointer { non_zero: true, tail })) => { Ok(SizeSkeleton::Pointer { non_zero: false, - tail: tail + tail, }) } _ => Err(err) @@ -2111,7 +2116,7 @@ impl<'a, 'tcx> LayoutTyper<'tcx> for LayoutCx<'a, 'tcx> { let ty = self.normalize_projections(ty); Ok(TyLayout { - ty: ty, + ty, layout: ty.layout(self.tcx, self.param_env)?, variant_index: None }) diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index b5adcc8ed7..e803010383 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -8,11 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use dep_graph::{DepNode, DepTrackingMapConfig}; +use dep_graph::{DepConstructor, DepNode, DepNodeIndex}; use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; use hir::def::Def; use hir; use middle::const_val; +use middle::cstore::{ExternCrate, LinkagePreference}; use middle::privacy::AccessLevels; use middle::region::RegionMaps; use mir; @@ -185,7 +186,7 @@ impl<'tcx> Value<'tcx> for ty::SymbolName { struct QueryMap { phantom: PhantomData, - map: FxHashMap, + map: FxHashMap, } impl QueryMap { @@ -245,7 +246,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if let Some((i, _)) = stack.iter().enumerate().rev() .find(|&(_, &(_, ref q))| *q == query) { return Err(CycleError { - span: span, + span, cycle: RefMut::map(stack, |stack| &mut stack[i..]) }); } @@ -260,11 +261,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } -trait QueryDescription: DepTrackingMapConfig { +pub trait QueryConfig { + type Key: Eq + Hash + Clone; + type Value; +} + +trait QueryDescription: QueryConfig { fn describe(tcx: TyCtxt, key: Self::Key) -> String; } -impl> QueryDescription for M { +impl> QueryDescription for M { default fn describe(tcx: TyCtxt, def_id: DefId) -> String { format!("processing `{}`", tcx.item_path_str(def_id)) } @@ -464,15 +470,39 @@ impl<'tcx> QueryDescription for queries::trait_impls_of<'tcx> { } } -impl<'tcx> QueryDescription for queries::relevant_trait_impls_for<'tcx> { - fn describe(tcx: TyCtxt, (def_id, ty): (DefId, SimplifiedType)) -> String { - format!("relevant impls for: `({}, {:?})`", tcx.item_path_str(def_id), ty) +impl<'tcx> QueryDescription for queries::is_object_safe<'tcx> { + fn describe(tcx: TyCtxt, def_id: DefId) -> String { + format!("determine object safety of trait `{}`", tcx.item_path_str(def_id)) } } -impl<'tcx> QueryDescription for queries::is_object_safe<'tcx> { +impl<'tcx> QueryDescription for queries::is_const_fn<'tcx> { fn describe(tcx: TyCtxt, def_id: DefId) -> String { - format!("determine object safety of trait `{}`", tcx.item_path_str(def_id)) + format!("checking if item is const fn: `{}`", tcx.item_path_str(def_id)) + } +} + +impl<'tcx> QueryDescription for queries::dylib_dependency_formats<'tcx> { + fn describe(_: TyCtxt, _: DefId) -> String { + "dylib dependency formats of crate".to_string() + } +} + +impl<'tcx> QueryDescription for queries::is_allocator<'tcx> { + fn describe(_: TyCtxt, _: DefId) -> String { + "checking if the crate is_allocator".to_string() + } +} + +impl<'tcx> QueryDescription for queries::is_panic_runtime<'tcx> { + fn describe(_: TyCtxt, _: DefId) -> String { + "checking if the crate is_panic_runtime".to_string() + } +} + +impl<'tcx> QueryDescription for queries::extern_crate<'tcx> { + fn describe(_: TyCtxt, _: DefId) -> String { + "getting crate's ExternCrateData".to_string() } } @@ -519,18 +549,19 @@ macro_rules! define_maps { })* } - $(impl<$tcx> DepTrackingMapConfig for queries::$name<$tcx> { + $(impl<$tcx> QueryConfig for queries::$name<$tcx> { type Key = $K; type Value = $V; + } + impl<'a, $tcx, 'lcx> queries::$name<$tcx> { #[allow(unused)] - fn to_dep_node(key: &$K) -> DepNode { - use dep_graph::DepNode::*; + fn to_dep_node(tcx: TyCtxt<'a, $tcx, 'lcx>, key: &$K) -> DepNode { + use dep_graph::DepConstructor::*; - $node(*key) + DepNode::new(tcx, $node(*key)) } - } - impl<'a, $tcx, 'lcx> queries::$name<$tcx> { + fn try_get_with(tcx: TyCtxt<'a, $tcx, 'lcx>, mut span: Span, key: $K, @@ -543,7 +574,8 @@ macro_rules! define_maps { key, span); - if let Some(result) = tcx.maps.$name.borrow().map.get(&key) { + if let Some(&(ref result, dep_node_index)) = tcx.maps.$name.borrow().map.get(&key) { + tcx.dep_graph.read_index(dep_node_index); return Ok(f(result)); } @@ -554,26 +586,46 @@ macro_rules! define_maps { span = key.default_span(tcx) } - let _task = tcx.dep_graph.in_task(Self::to_dep_node(&key)); - - let result = tcx.cycle_check(span, Query::$name(key), || { - let provider = tcx.maps.providers[key.map_crate()].$name; - provider(tcx.global_tcx(), key) + let (result, dep_node_index) = tcx.cycle_check(span, Query::$name(key), || { + let dep_node = Self::to_dep_node(tcx, &key); + + if dep_node.kind.is_anon() { + tcx.dep_graph.with_anon_task(dep_node.kind, || { + let provider = tcx.maps.providers[key.map_crate()].$name; + provider(tcx.global_tcx(), key) + }) + } else { + fn run_provider<'a, 'tcx, 'lcx>(tcx: TyCtxt<'a, 'tcx, 'lcx>, + key: $K) + -> $V { + let provider = tcx.maps.providers[key.map_crate()].$name; + provider(tcx.global_tcx(), key) + } + + tcx.dep_graph.with_task(dep_node, tcx, key, run_provider) + } })?; - Ok(f(tcx.maps.$name.borrow_mut().map.entry(key).or_insert(result))) + tcx.dep_graph.read_index(dep_node_index); + + Ok(f(&tcx.maps + .$name + .borrow_mut() + .map + .entry(key) + .or_insert((result, dep_node_index)) + .0)) } pub fn try_get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K) -> Result<$V, CycleError<'a, $tcx>> { - // We register the `read` here, but not in `force`, since - // `force` does not give access to the value produced (and thus - // we actually don't read it). - tcx.dep_graph.read(Self::to_dep_node(&key)); Self::try_get_with(tcx, span, key, Clone::clone) } pub fn force(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K) { + // Ignore dependencies, since we not reading the computed value + let _task = tcx.dep_graph.in_ignore(); + match Self::try_get_with(tcx, span, key, |_| ()) { Ok(()) => {} Err(e) => tcx.report_cycle(e) @@ -765,12 +817,12 @@ macro_rules! define_provider_struct { // the driver creates (using several `rustc_*` crates). define_maps! { <'tcx> /// Records the type of every item. - [] type_of: ItemSignature(DefId) -> Ty<'tcx>, + [] type_of: TypeOfItem(DefId) -> Ty<'tcx>, /// Maps from the def-id of an item (trait/struct/enum/fn) to its /// associated generics and predicates. - [] generics_of: ItemSignature(DefId) -> &'tcx ty::Generics, - [] predicates_of: ItemSignature(DefId) -> ty::GenericPredicates<'tcx>, + [] generics_of: GenericsOfItem(DefId) -> &'tcx ty::Generics, + [] predicates_of: PredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>, /// Maps from the def-id of a trait to the list of /// super-predicates. This is a subset of the full list of @@ -778,24 +830,27 @@ define_maps! { <'tcx> /// evaluate them even during type conversion, often before the /// full predicates are available (note that supertraits have /// additional acyclicity requirements). - [] super_predicates_of: ItemSignature(DefId) -> ty::GenericPredicates<'tcx>, + [] super_predicates_of: SuperPredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>, /// To avoid cycles within the predicates of a single item we compute /// per-type-parameter predicates for resolving `T::AssocTy`. - [] type_param_predicates: TypeParamPredicates((DefId, DefId)) + [] type_param_predicates: type_param_predicates((DefId, DefId)) -> ty::GenericPredicates<'tcx>, - [] trait_def: ItemSignature(DefId) -> &'tcx ty::TraitDef, - [] adt_def: ItemSignature(DefId) -> &'tcx ty::AdtDef, + [] trait_def: TraitDefOfItem(DefId) -> &'tcx ty::TraitDef, + [] adt_def: AdtDefOfItem(DefId) -> &'tcx ty::AdtDef, [] adt_destructor: AdtDestructor(DefId) -> Option, [] adt_sized_constraint: SizedConstraint(DefId) -> &'tcx [Ty<'tcx>], [] adt_dtorck_constraint: DtorckConstraint(DefId) -> ty::DtorckConstraint<'tcx>, + /// True if this is a const fn + [] is_const_fn: IsConstFn(DefId) -> bool, + /// True if this is a foreign item (i.e., linked via `extern { ... }`). [] is_foreign_item: IsForeignItem(DefId) -> bool, /// True if this is a default impl (aka impl Foo for ..) - [] is_default_impl: ItemSignature(DefId) -> bool, + [] is_default_impl: IsDefaultImpl(DefId) -> bool, /// Get a map with the variance of every item; use `item_variance` /// instead. @@ -811,8 +866,8 @@ define_maps! { <'tcx> /// Maps from a trait item to the trait item "descriptor" [] associated_item: AssociatedItems(DefId) -> ty::AssociatedItem, - [] impl_trait_ref: ItemSignature(DefId) -> Option>, - [] impl_polarity: ItemSignature(DefId) -> hir::ImplPolarity, + [] impl_trait_ref: ImplTraitRef(DefId) -> Option>, + [] impl_polarity: ImplPolarity(DefId) -> hir::ImplPolarity, /// Maps a DefId of a type to a list of its inherent impls. /// Contains implementations of methods that are inherent to a type. @@ -827,37 +882,36 @@ define_maps! { <'tcx> /// Maps DefId's that have an associated Mir to the result /// of the MIR qualify_consts pass. The actual meaning of /// the value isn't known except to the pass itself. - [] mir_const_qualif: Mir(DefId) -> u8, + [] mir_const_qualif: MirConstQualif(DefId) -> u8, /// Fetch the MIR for a given def-id up till the point where it is /// ready for const evaluation. /// /// See the README for the `mir` module for details. - [] mir_const: Mir(DefId) -> &'tcx Steal>, + [] mir_const: MirConst(DefId) -> &'tcx Steal>, - [] mir_validated: Mir(DefId) -> &'tcx Steal>, + [] mir_validated: MirValidated(DefId) -> &'tcx Steal>, /// MIR after our optimization passes have run. This is MIR that is ready /// for trans. This is also the only query that can fetch non-local MIR, at present. - [] optimized_mir: Mir(DefId) -> &'tcx mir::Mir<'tcx>, + [] optimized_mir: MirOptimized(DefId) -> &'tcx mir::Mir<'tcx>, - /// Records the type of each closure. The def ID is the ID of the + /// Type of each closure. The def ID is the ID of the /// expression defining the closure. - [] closure_kind: ItemSignature(DefId) -> ty::ClosureKind, + [] closure_kind: ClosureKind(DefId) -> ty::ClosureKind, - /// Records the type of each closure. The def ID is the ID of the - /// expression defining the closure. - [] closure_type: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>, + /// The signature of functions and closures. + [] fn_sig: FnSignature(DefId) -> ty::PolyFnSig<'tcx>, /// Caches CoerceUnsized kinds for impls on custom types. - [] coerce_unsized_info: ItemSignature(DefId) + [] coerce_unsized_info: CoerceUnsizedInfo(DefId) -> ty::adjustment::CoerceUnsizedInfo, [] typeck_item_bodies: typeck_item_bodies_dep_node(CrateNum) -> CompileResult, [] typeck_tables_of: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>, - [] has_typeck_tables: TypeckTables(DefId) -> bool, + [] has_typeck_tables: HasTypeckTables(DefId) -> bool, [] coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (), @@ -906,10 +960,7 @@ define_maps! { <'tcx> [] const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool, [] is_mir_available: IsMirAvailable(DefId) -> bool, - [] trait_impls_of: TraitImpls(DefId) -> ty::trait_def::TraitImpls, - // Note that TraitDef::for_each_relevant_impl() will do type simplication for you. - [] relevant_trait_impls_for: relevant_trait_impls_for((DefId, SimplifiedType)) - -> ty::trait_def::TraitImpls, + [] trait_impls_of: TraitImpls(DefId) -> Rc, [] specialization_graph_of: SpecializationGraph(DefId) -> Rc, [] is_object_safe: ObjectSafety(DefId) -> bool, @@ -929,76 +980,88 @@ define_maps! { <'tcx> [] needs_drop_raw: needs_drop_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool, [] layout_raw: layout_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> Result<&'tcx Layout, LayoutError<'tcx>>, + + [] dylib_dependency_formats: DylibDepFormats(DefId) + -> Rc>, + + [] is_allocator: IsAllocator(DefId) -> bool, + [] is_panic_runtime: IsPanicRuntime(DefId) -> bool, + + [] extern_crate: ExternCrate(DefId) -> Rc>, } -fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode { - DepNode::CoherenceCheckTrait(def_id) +fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> { + DepConstructor::TypeParamPredicates { + item_id, + param_id + } } -fn crate_inherent_impls_dep_node(_: CrateNum) -> DepNode { - DepNode::Coherence +fn coherent_trait_dep_node<'tcx>((_, def_id): (CrateNum, DefId)) -> DepConstructor<'tcx> { + DepConstructor::CoherenceCheckTrait(def_id) } -fn reachability_dep_node(_: CrateNum) -> DepNode { - DepNode::Reachability +fn crate_inherent_impls_dep_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { + DepConstructor::Coherence } -fn mir_shim_dep_node(instance: ty::InstanceDef) -> DepNode { - instance.dep_node() +fn reachability_dep_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { + DepConstructor::Reachability } -fn symbol_name_dep_node(instance: ty::Instance) -> DepNode { - // symbol_name uses the substs only to traverse them to find the - // hash, and that does not create any new dep-nodes. - DepNode::SymbolName(instance.def.def_id()) +fn mir_shim_dep_node<'tcx>(instance_def: ty::InstanceDef<'tcx>) -> DepConstructor<'tcx> { + DepConstructor::MirShim { + instance_def + } } -fn typeck_item_bodies_dep_node(_: CrateNum) -> DepNode { - DepNode::TypeckBodiesKrate +fn symbol_name_dep_node<'tcx>(instance: ty::Instance<'tcx>) -> DepConstructor<'tcx> { + DepConstructor::InstanceSymbolName { instance } } -fn const_eval_dep_node((def_id, _): (DefId, &Substs)) -> DepNode { - DepNode::ConstEval(def_id) +fn typeck_item_bodies_dep_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { + DepConstructor::TypeckBodiesKrate } -fn mir_keys(_: CrateNum) -> DepNode { - DepNode::MirKeys +fn const_eval_dep_node<'tcx>((def_id, substs): (DefId, &'tcx Substs<'tcx>)) + -> DepConstructor<'tcx> { + DepConstructor::ConstEval { def_id, substs } } -fn crate_variances(_: CrateNum) -> DepNode { - DepNode::CrateVariances +fn mir_keys<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { + DepConstructor::MirKeys } -fn relevant_trait_impls_for((def_id, _): (DefId, SimplifiedType)) -> DepNode { - DepNode::TraitImpls(def_id) +fn crate_variances<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { + DepConstructor::CrateVariances } -fn is_copy_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode { +fn is_copy_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<'tcx> { let def_id = ty::item_path::characteristic_def_id_of_type(key.value) .unwrap_or(DefId::local(CRATE_DEF_INDEX)); - DepNode::IsCopy(def_id) + DepConstructor::IsCopy(def_id) } -fn is_sized_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode { +fn is_sized_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<'tcx> { let def_id = ty::item_path::characteristic_def_id_of_type(key.value) .unwrap_or(DefId::local(CRATE_DEF_INDEX)); - DepNode::IsSized(def_id) + DepConstructor::IsSized(def_id) } -fn is_freeze_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode { +fn is_freeze_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<'tcx> { let def_id = ty::item_path::characteristic_def_id_of_type(key.value) .unwrap_or(DefId::local(CRATE_DEF_INDEX)); - DepNode::IsFreeze(def_id) + DepConstructor::IsFreeze(def_id) } -fn needs_drop_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode { +fn needs_drop_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<'tcx> { let def_id = ty::item_path::characteristic_def_id_of_type(key.value) .unwrap_or(DefId::local(CRATE_DEF_INDEX)); - DepNode::NeedsDrop(def_id) + DepConstructor::NeedsDrop(def_id) } -fn layout_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode { +fn layout_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<'tcx> { let def_id = ty::item_path::characteristic_def_id_of_type(key.value) .unwrap_or(DefId::local(CRATE_DEF_INDEX)); - DepNode::Layout(def_id) + DepConstructor::Layout(def_id) } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 653021119a..8bd05f5d70 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -15,7 +15,7 @@ pub use self::IntVarValue::*; pub use self::LvaluePreference::*; pub use self::fold::TypeFoldable; -use dep_graph::DepNode; +use dep_graph::{DepNode, DepConstructor}; use hir::{map as hir_map, FreevarMap, TraitMap}; use hir::def::{Def, CtorKind, ExportMap}; use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; @@ -206,7 +206,7 @@ impl AssociatedItem { // late-bound regions, and we don't want method signatures to show up // `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound // regions just fine, showing `fn(&MyType)`. - format!("{}", tcx.type_of(self.def_id).fn_sig().skip_binder()) + format!("{}", tcx.fn_sig(self.def_id).skip_binder()) } ty::AssociatedKind::Type => format!("type {};", self.name.to_string()), ty::AssociatedKind::Const => { @@ -465,9 +465,39 @@ impl<'tcx> Hash for TyS<'tcx> { } } -impl<'a, 'tcx> HashStable> for ty::TyS<'tcx> { +impl<'tcx> TyS<'tcx> { + pub fn is_primitive_ty(&self) -> bool { + match self.sty { + TypeVariants::TyBool | + TypeVariants::TyChar | + TypeVariants::TyInt(_) | + TypeVariants::TyUint(_) | + TypeVariants::TyFloat(_) | + TypeVariants::TyInfer(InferTy::IntVar(_)) | + TypeVariants::TyInfer(InferTy::FloatVar(_)) | + TypeVariants::TyInfer(InferTy::FreshIntTy(_)) | + TypeVariants::TyInfer(InferTy::FreshFloatTy(_)) => true, + TypeVariants::TyRef(_, x) => x.ty.is_primitive_ty(), + _ => false, + } + } + + pub fn is_suggestable(&self) -> bool { + match self.sty { + TypeVariants::TyAnon(..) | + TypeVariants::TyFnDef(..) | + TypeVariants::TyFnPtr(..) | + TypeVariants::TyDynamic(..) | + TypeVariants::TyClosure(..) | + TypeVariants::TyProjection(..) => false, + _ => true, + } + } +} + +impl<'a, 'gcx, 'tcx> HashStable> for ty::TyS<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let ty::TyS { ref sty, @@ -918,7 +948,7 @@ impl<'tcx> TraitPredicate<'tcx> { } /// Creates the dep-node for selecting/evaluating this trait reference. - fn dep_node(&self) -> DepNode { + fn dep_node(&self, tcx: TyCtxt) -> DepNode { // Extact the trait-def and first def-id from inputs. See the // docs for `DepNode::TraitSelect` for more information. let trait_def_id = self.def_id(); @@ -926,15 +956,17 @@ impl<'tcx> TraitPredicate<'tcx> { self.input_types() .flat_map(|t| t.walk()) .filter_map(|t| match t.sty { - ty::TyAdt(adt_def, _) => Some(adt_def.did), + ty::TyAdt(adt_def, ..) => Some(adt_def.did), + ty::TyClosure(def_id, ..) => Some(def_id), + ty::TyFnDef(def_id, ..) => Some(def_id), _ => None }) .next() .unwrap_or(trait_def_id); - DepNode::TraitSelect { - trait_def_id: trait_def_id, - input_def_id: input_def_id - } + DepNode::new(tcx, DepConstructor::TraitSelect { + trait_def_id, + input_def_id, + }) } pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator> + 'a { @@ -952,9 +984,9 @@ impl<'tcx> PolyTraitPredicate<'tcx> { self.0.def_id() } - pub fn dep_node(&self) -> DepNode { + pub fn dep_node(&self, tcx: TyCtxt) -> DepNode { // ok to skip binder since depnode does not care about regions - self.0.dep_node() + self.0.dep_node(tcx) } } @@ -998,8 +1030,13 @@ pub struct ProjectionPredicate<'tcx> { pub type PolyProjectionPredicate<'tcx> = Binder>; impl<'tcx> PolyProjectionPredicate<'tcx> { - pub fn item_name(&self, tcx: TyCtxt) -> Name { - self.0.projection_ty.item_name(tcx) // safe to skip the binder to access a name + pub fn to_poly_trait_ref(&self, tcx: TyCtxt) -> PolyTraitRef<'tcx> { + // Note: unlike with TraitRef::to_poly_trait_ref(), + // self.0.trait_ref is permitted to have escaping regions. + // This is because here `self` has a `Binder` and so does our + // return value, so we are preserving the number of binding + // levels. + ty::Binder(self.0.projection_ty.trait_ref(tcx)) } } @@ -1020,17 +1057,6 @@ impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { } } -impl<'tcx> ToPolyTraitRef<'tcx> for PolyProjectionPredicate<'tcx> { - fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { - // Note: unlike with TraitRef::to_poly_trait_ref(), - // self.0.trait_ref is permitted to have escaping regions. - // This is because here `self` has a `Binder` and so does our - // return value, so we are preserving the number of binding - // levels. - ty::Binder(self.0.projection_ty.trait_ref) - } -} - pub trait ToPredicate<'tcx> { fn to_predicate(&self) -> Predicate<'tcx>; } @@ -1100,8 +1126,7 @@ impl<'tcx> Predicate<'tcx> { vec![] } ty::Predicate::Projection(ref data) => { - let trait_inputs = data.0.projection_ty.trait_ref.input_types(); - trait_inputs.chain(Some(data.0.ty)).collect() + data.0.projection_ty.substs.types().chain(Some(data.0.ty)).collect() } ty::Predicate::WellFormed(data) => { vec![data] @@ -1212,12 +1237,12 @@ impl<'tcx> ParamEnv<'tcx> { if value.has_param_types() || value.has_self_ty() { ParamEnvAnd { param_env: self, - value: value, + value, } } else { ParamEnvAnd { param_env: ParamEnv::empty(self.reveal), - value: value, + value, } } } @@ -1318,9 +1343,9 @@ impl<'tcx> serialize::UseSpecializedEncodable for &'tcx AdtDef { impl<'tcx> serialize::UseSpecializedDecodable for &'tcx AdtDef {} -impl<'a, 'tcx> HashStable> for AdtDef { +impl<'a, 'gcx, 'tcx> HashStable> for AdtDef { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let ty::AdtDef { did, @@ -1366,7 +1391,7 @@ impl_stable_hash_for!(struct ReprFlags { #[derive(Copy, Clone, Eq, PartialEq, RustcEncodable, RustcDecodable, Default)] pub struct ReprOptions { pub int: Option, - pub align: u16, + pub align: u32, pub flags: ReprFlags, } @@ -1455,10 +1480,10 @@ impl<'a, 'gcx, 'tcx> AdtDef { AdtKind::Struct => {} } AdtDef { - did: did, - variants: variants, - flags: flags, - repr: repr, + did, + variants, + flags, + repr, } } @@ -2081,11 +2106,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { AssociatedItem { name: trait_item_ref.name, - kind: kind, + kind, // Visibility of trait items is inherited from their traits. vis: Visibility::from_hir(parent_vis, trait_item_ref.id.node_id, self), defaultness: trait_item_ref.defaultness, - def_id: def_id, + def_id, container: TraitContainer(parent_def_id), method_has_self_argument: has_self } @@ -2106,11 +2131,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ty::AssociatedItem { name: impl_item_ref.name, - kind: kind, + kind, // Visibility of trait impl items doesn't matter. vis: ty::Visibility::from_hir(&impl_item_ref.vis, impl_item_ref.id.node_id, self), defaultness: impl_item_ref.defaultness, - def_id: def_id, + def_id, container: ImplContainer(parent_def_id), method_has_self_argument: has_self } @@ -2505,7 +2530,6 @@ pub fn provide(providers: &mut ty::maps::Providers) { param_env, trait_of_item, trait_impls_of: trait_def::trait_impls_of_provider, - relevant_trait_impls_for: trait_def::relevant_trait_impls_provider, ..*providers }; } @@ -2515,7 +2539,6 @@ pub fn provide_extern(providers: &mut ty::maps::Providers) { adt_sized_constraint, adt_dtorck_constraint, trait_impls_of: trait_def::trait_impls_of_provider, - relevant_trait_impls_for: trait_def::relevant_trait_impls_provider, param_env, ..*providers }; diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index d4f06a902e..0d9ef8196c 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -182,8 +182,8 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { Ok(ty::FnSig { inputs_and_output: relation.tcx().intern_type_list(&inputs_and_output), variadic: a.variadic, - unsafety: unsafety, - abi: abi + unsafety, + abi, }) } } @@ -225,13 +225,15 @@ impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> { -> RelateResult<'tcx, ty::ProjectionTy<'tcx>> where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a { - let tcx = relation.tcx(); - if a.item_name(tcx) != b.item_name(tcx) { - Err(TypeError::ProjectionNameMismatched( - expected_found(relation, &a.item_name(tcx), &b.item_name(tcx)))) + if a.item_def_id != b.item_def_id { + Err(TypeError::ProjectionMismatched( + expected_found(relation, &a.item_def_id, &b.item_def_id))) } else { - let trait_ref = relation.relate(&a.trait_ref, &b.trait_ref)?; - Ok(ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, a.item_name(tcx))) + let substs = relation.relate(&a.substs, &b.substs)?; + Ok(ty::ProjectionTy { + item_def_id: a.item_def_id, + substs: &substs, + }) } } } @@ -243,16 +245,16 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> { -> RelateResult<'tcx, ty::ExistentialProjection<'tcx>> where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a { - if a.item_name != b.item_name { - Err(TypeError::ProjectionNameMismatched( - expected_found(relation, &a.item_name, &b.item_name))) + if a.item_def_id != b.item_def_id { + Err(TypeError::ProjectionMismatched( + expected_found(relation, &a.item_def_id, &b.item_def_id))) } else { - let trait_ref = relation.relate(&a.trait_ref, &b.trait_ref)?; let ty = relation.relate(&a.ty, &b.ty)?; + let substs = relation.relate(&a.substs, &b.substs)?; Ok(ty::ExistentialProjection { - trait_ref: trait_ref, - item_name: a.item_name, - ty: ty + item_def_id: a.item_def_id, + substs: substs, + ty, }) } } @@ -291,7 +293,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> { if a.def_id != b.def_id { Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id))) } else { - let substs = relation.relate_item_substs(a.def_id, a.substs, b.substs)?; + let substs = relate_substs(relation, None, a.substs, b.substs)?; Ok(ty::TraitRef { def_id: a.def_id, substs: substs }) } } @@ -308,7 +310,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { if a.def_id != b.def_id { Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id))) } else { - let substs = relation.relate_item_substs(a.def_id, a.substs, b.substs)?; + let substs = relate_substs(relation, None, a.substs, b.substs)?; Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs: substs }) } } @@ -440,13 +442,11 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, } } - (&ty::TyFnDef(a_def_id, a_substs, a_fty), - &ty::TyFnDef(b_def_id, b_substs, b_fty)) + (&ty::TyFnDef(a_def_id, a_substs), &ty::TyFnDef(b_def_id, b_substs)) if a_def_id == b_def_id => { - let substs = relate_substs(relation, None, a_substs, b_substs)?; - let fty = relation.relate(&a_fty, &b_fty)?; - Ok(tcx.mk_fn_def(a_def_id, substs, fty)) + let substs = relation.relate_item_substs(a_def_id, a_substs, b_substs)?; + Ok(tcx.mk_fn_def(a_def_id, substs)) } (&ty::TyFnPtr(a_fty), &ty::TyFnPtr(b_fty)) => @@ -458,7 +458,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, (&ty::TyProjection(ref a_data), &ty::TyProjection(ref b_data)) => { let projection_ty = relation.relate(a_data, b_data)?; - Ok(tcx.mk_projection(projection_ty.trait_ref, projection_ty.item_name(tcx))) + Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs)) } (&ty::TyAnon(a_def_id, a_substs), &ty::TyAnon(b_def_id, b_substs)) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 1e26892439..b81bd595e2 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -78,7 +78,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::TraitRef<'a> { fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { tcx.lift(&self.substs).map(|substs| ty::TraitRef { def_id: self.def_id, - substs: substs + substs, }) } } @@ -88,7 +88,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialTraitRef<'a> { fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { tcx.lift(&self.substs).map(|substs| ty::ExistentialTraitRef { def_id: self.def_id, - substs: substs + substs, }) } } @@ -98,7 +98,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::TraitPredicate<'a> { fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option> { tcx.lift(&self.trait_ref).map(|trait_ref| ty::TraitPredicate { - trait_ref: trait_ref + trait_ref, }) } } @@ -117,8 +117,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::SubtypePredicate<'a> { -> Option> { tcx.lift(&(self.a, self.b)).map(|(a, b)| ty::SubtypePredicate { a_is_expected: self.a_is_expected, - a: a, - b: b, + a, + b, }) } } @@ -134,8 +134,11 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionTy<'a> { type Lifted = ty::ProjectionTy<'tcx>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option> { - tcx.lift(&self.trait_ref).map(|trait_ref| { - ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, self.item_name(tcx)) + tcx.lift(&self.substs).map(|substs| { + ty::ProjectionTy { + item_def_id: self.item_def_id, + substs: substs, + } }) } } @@ -146,8 +149,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionPredicate<'a> { -> Option> { tcx.lift(&(self.projection_ty, self.ty)).map(|(projection_ty, ty)| { ty::ProjectionPredicate { - projection_ty: projection_ty, - ty: ty + projection_ty, + ty, } }) } @@ -156,11 +159,11 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionPredicate<'a> { impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialProjection<'a> { type Lifted = ty::ExistentialProjection<'tcx>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { - tcx.lift(&(self.trait_ref, self.ty)).map(|(trait_ref, ty)| { + tcx.lift(&self.substs).map(|substs| { ty::ExistentialProjection { - trait_ref: trait_ref, - item_name: self.item_name, - ty: ty + substs, + ty: tcx.lift(&self.ty).expect("type must lift when substs do"), + item_def_id: self.item_def_id, } }) } @@ -300,8 +303,8 @@ impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::error::ExpectedFound { tcx.lift(&self.expected).and_then(|expected| { tcx.lift(&self.found).map(|found| { ty::error::ExpectedFound { - expected: expected, - found: found + expected, + found, } }) }) @@ -313,7 +316,7 @@ impl<'a, 'tcx> Lift<'tcx> for type_variable::Default<'a> { fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { tcx.lift(&self.ty).map(|ty| { type_variable::Default { - ty: ty, + ty, origin_span: self.origin_span, def_id: self.def_id } @@ -356,7 +359,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { Traits(x) => Traits(x), VariadicMismatch(x) => VariadicMismatch(x), CyclicTy => CyclicTy, - ProjectionNameMismatched(x) => ProjectionNameMismatched(x), + ProjectionMismatched(x) => ProjectionMismatched(x), ProjectionBoundsLength(x) => ProjectionBoundsLength(x), Sorts(ref x) => return tcx.lift(x).map(Sorts), @@ -531,10 +534,8 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::TyDynamic(ref trait_ty, ref region) => ty::TyDynamic(trait_ty.fold_with(folder), region.fold_with(folder)), ty::TyTuple(ts, defaulted) => ty::TyTuple(ts.fold_with(folder), defaulted), - ty::TyFnDef(def_id, substs, f) => { - ty::TyFnDef(def_id, - substs.fold_with(folder), - f.fold_with(folder)) + ty::TyFnDef(def_id, substs) => { + ty::TyFnDef(def_id, substs.fold_with(folder)) } ty::TyFnPtr(f) => ty::TyFnPtr(f.fold_with(folder)), ty::TyRef(ref r, tm) => { @@ -568,9 +569,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::TyDynamic(ref trait_ty, ref reg) => trait_ty.visit_with(visitor) || reg.visit_with(visitor), ty::TyTuple(ts, _) => ts.visit_with(visitor), - ty::TyFnDef(_, substs, ref f) => { - substs.visit_with(visitor) || f.visit_with(visitor) - } + ty::TyFnDef(_, substs) => substs.visit_with(visitor), ty::TyFnPtr(ref f) => f.visit_with(visitor), ty::TyRef(r, ref tm) => r.visit_with(visitor) || tm.visit_with(visitor), ty::TyClosure(_did, ref substs) => substs.visit_with(visitor), @@ -625,10 +624,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TraitRef<'tcx> { fn super_visit_with>(&self, visitor: &mut V) -> bool { self.substs.visit_with(visitor) } - - fn visit_with>(&self, visitor: &mut V) -> bool { - visitor.visit_trait_ref(*self) - } } impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialTraitRef<'tcx> { @@ -851,27 +846,27 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionPredicate<'tcx> { impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialProjection<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { ty::ExistentialProjection { - trait_ref: self.trait_ref.fold_with(folder), - item_name: self.item_name, ty: self.ty.fold_with(folder), + substs: self.substs.fold_with(folder), + item_def_id: self.item_def_id, } } fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.trait_ref.visit_with(visitor) || self.ty.visit_with(visitor) + self.substs.visit_with(visitor) || self.ty.visit_with(visitor) } } impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionTy<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { ty::ProjectionTy { - trait_ref: self.trait_ref.fold_with(folder), + substs: self.substs.fold_with(folder), item_def_id: self.item_def_id, } } fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.trait_ref.visit_with(visitor) + self.substs.visit_with(visitor) } } @@ -964,6 +959,20 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::error::ExpectedFoun } } +impl<'tcx> TypeFoldable<'tcx> for type_variable::Default<'tcx> { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + type_variable::Default { + ty: self.ty.fold_with(folder), + origin_span: self.origin_span, + def_id: self.def_id + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + self.ty.visit_with(visitor) + } +} + impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { self.iter().map(|x| x.fold_with(folder)).collect() @@ -973,3 +982,79 @@ impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec self.iter().any(|t| t.visit_with(visitor)) } } + +impl<'tcx> TypeFoldable<'tcx> for ty::error::TypeError<'tcx> { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + use ty::error::TypeError::*; + + match *self { + Mismatch => Mismatch, + UnsafetyMismatch(x) => UnsafetyMismatch(x.fold_with(folder)), + AbiMismatch(x) => AbiMismatch(x.fold_with(folder)), + Mutability => Mutability, + TupleSize(x) => TupleSize(x), + FixedArraySize(x) => FixedArraySize(x), + ArgCount => ArgCount, + RegionsDoesNotOutlive(a, b) => { + RegionsDoesNotOutlive(a.fold_with(folder), b.fold_with(folder)) + }, + RegionsNotSame(a, b) => { + RegionsNotSame(a.fold_with(folder), b.fold_with(folder)) + }, + RegionsNoOverlap(a, b) => { + RegionsNoOverlap(a.fold_with(folder), b.fold_with(folder)) + }, + RegionsInsufficientlyPolymorphic(a, b, ref c) => { + let c = c.clone(); + RegionsInsufficientlyPolymorphic(a, b.fold_with(folder), c) + }, + RegionsOverlyPolymorphic(a, b, ref c) => { + let c = c.clone(); + RegionsOverlyPolymorphic(a, b.fold_with(folder), c) + }, + IntMismatch(x) => IntMismatch(x), + FloatMismatch(x) => FloatMismatch(x), + Traits(x) => Traits(x), + VariadicMismatch(x) => VariadicMismatch(x), + CyclicTy => CyclicTy, + ProjectionMismatched(x) => ProjectionMismatched(x), + ProjectionBoundsLength(x) => ProjectionBoundsLength(x), + Sorts(x) => Sorts(x.fold_with(folder)), + TyParamDefaultMismatch(ref x) => TyParamDefaultMismatch(x.fold_with(folder)), + ExistentialMismatch(x) => ExistentialMismatch(x.fold_with(folder)), + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + use ty::error::TypeError::*; + + match *self { + UnsafetyMismatch(x) => x.visit_with(visitor), + AbiMismatch(x) => x.visit_with(visitor), + RegionsDoesNotOutlive(a, b) | + RegionsNotSame(a, b) | + RegionsNoOverlap(a, b) => { + a.visit_with(visitor) || b.visit_with(visitor) + }, + RegionsInsufficientlyPolymorphic(_, b, _) | + RegionsOverlyPolymorphic(_, b, _) => { + b.visit_with(visitor) + }, + Sorts(x) => x.visit_with(visitor), + TyParamDefaultMismatch(ref x) => x.visit_with(visitor), + ExistentialMismatch(x) => x.visit_with(visitor), + Mismatch | + Mutability | + TupleSize(_) | + FixedArraySize(_) | + ArgCount | + IntMismatch(_) | + FloatMismatch(_) | + Traits(_) | + VariadicMismatch(_) | + CyclicTy | + ProjectionMismatched(_) | + ProjectionBoundsLength(_) => false, + } + } +} diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 6923a6d21d..5f89714b33 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -11,10 +11,9 @@ //! This module contains TypeVariants and its major components use hir::def_id::DefId; -use hir::map::DefPathHash; use middle::region; -use ty::subst::Substs; +use ty::subst::{Substs, Subst}; use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable}; use ty::{Slice, TyS}; use ty::subst::Kind; @@ -24,7 +23,7 @@ use std::iter; use std::cmp::Ordering; use syntax::abi; use syntax::ast::{self, Name}; -use syntax::symbol::{keywords, InternedString}; +use syntax::symbol::keywords; use util::nodemap::FxHashMap; use serialize; @@ -138,7 +137,7 @@ pub enum TypeVariants<'tcx> { /// The anonymous type of a function declaration/definition. Each /// function has a unique type. - TyFnDef(DefId, &'tcx Substs<'tcx>, PolyFnSig<'tcx>), + TyFnDef(DefId, &'tcx Substs<'tcx>), /// A pointer to a function. Written as `fn() -> i32`. TyFnPtr(PolyFnSig<'tcx>), @@ -291,7 +290,8 @@ impl<'a, 'gcx, 'tcx> ExistentialPredicate<'tcx> { use self::ExistentialPredicate::*; match (*self, *other) { (Trait(_), Trait(_)) => Ordering::Equal, - (Projection(ref a), Projection(ref b)) => a.sort_key(tcx).cmp(&b.sort_key(tcx)), + (Projection(ref a), Projection(ref b)) => + tcx.def_path_hash(a.item_def_id).cmp(&tcx.def_path_hash(b.item_def_id)), (AutoTrait(ref a), AutoTrait(ref b)) => tcx.trait_def(*a).def_path_hash.cmp(&tcx.trait_def(*b).def_path_hash), (Trait(_), _) => Ordering::Less, @@ -551,8 +551,8 @@ impl fmt::Debug for TypeFlags { /// form this would be written `>::N`. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct ProjectionTy<'tcx> { - /// The trait reference `T as Trait<..>`. - pub trait_ref: ty::TraitRef<'tcx>, + /// The parameters of the associated item. + pub substs: &'tcx Substs<'tcx>, /// The DefId of the TraitItem for the associated type N. /// @@ -568,16 +568,28 @@ impl<'a, 'tcx> ProjectionTy<'tcx> { tcx: TyCtxt, trait_ref: ty::TraitRef<'tcx>, item_name: Name ) -> ProjectionTy<'tcx> { let item_def_id = tcx.associated_items(trait_ref.def_id).find( - |item| item.name == item_name).unwrap().def_id; + |item| item.name == item_name && item.kind == ty::AssociatedKind::Type + ).unwrap().def_id; ProjectionTy { - trait_ref: trait_ref, - item_def_id: item_def_id, + substs: trait_ref.substs, + item_def_id, } } - pub fn item_name(self, tcx: TyCtxt) -> Name { - tcx.associated_item(self.item_def_id).name + /// Extracts the underlying trait reference from this projection. + /// For example, if this is a projection of `::Item`, + /// then this function would return a `T: Iterator` trait reference. + pub fn trait_ref(&self, tcx: TyCtxt) -> ty::TraitRef<'tcx> { + let def_id = tcx.associated_item(self.item_def_id).container.id(); + ty::TraitRef { + def_id: def_id, + substs: self.substs, + } + } + + pub fn self_ty(&self) -> Ty<'tcx> { + self.substs.type_at(0) } } @@ -861,29 +873,24 @@ pub enum InferTy { /// A `ProjectionPredicate` for an `ExistentialTraitRef`. #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct ExistentialProjection<'tcx> { - pub trait_ref: ExistentialTraitRef<'tcx>, - pub item_name: Name, + pub item_def_id: DefId, + pub substs: &'tcx Substs<'tcx>, pub ty: Ty<'tcx>, } pub type PolyExistentialProjection<'tcx> = Binder>; impl<'a, 'tcx, 'gcx> ExistentialProjection<'tcx> { - pub fn item_name(&self) -> Name { - self.item_name // safe to skip the binder to access a name - } - - pub fn sort_key(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> (DefPathHash, InternedString) { - // We want something here that is stable across crate boundaries. - // The DefId isn't but the `deterministic_hash` of the corresponding - // DefPath is. - let trait_def = tcx.trait_def(self.trait_ref.def_id); - let def_path_hash = trait_def.def_path_hash; - - // An `ast::Name` is also not stable (it's just an index into an - // interning table), so map to the corresponding `InternedString`. - let item_name = self.item_name.as_str(); - (def_path_hash, item_name) + /// Extracts the underlying existential trait reference from this projection. + /// For example, if this is a projection of `exists T. ::Item == X`, + /// then this function would return a `exists T. T: Iterator` existential trait + /// reference. + pub fn trait_ref(&self, tcx: TyCtxt) -> ty::ExistentialTraitRef<'tcx> { + let def_id = tcx.associated_item(self.item_def_id).container.id(); + ty::ExistentialTraitRef{ + def_id: def_id, + substs: self.substs, + } } pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, @@ -894,24 +901,17 @@ impl<'a, 'tcx, 'gcx> ExistentialProjection<'tcx> { assert!(!self_ty.has_escaping_regions()); ty::ProjectionPredicate { - projection_ty: ty::ProjectionTy::from_ref_and_name( - tcx, - self.trait_ref.with_self_ty(tcx, self_ty), - self.item_name), + projection_ty: ty::ProjectionTy { + item_def_id: self.item_def_id, + substs: tcx.mk_substs( + iter::once(Kind::from(self_ty)).chain(self.substs.iter().cloned())), + }, ty: self.ty, } } } impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> { - pub fn item_name(&self) -> Name { - self.skip_binder().item_name() - } - - pub fn sort_key(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> (DefPathHash, InternedString) { - self.skip_binder().sort_key(tcx) - } - pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>) -> ty::PolyProjectionPredicate<'tcx> { self.map_bound(|p| p.with_self_ty(tcx, self_ty)) @@ -990,6 +990,19 @@ impl RegionKind { flags } + + // This method returns whether the given Region is Named + pub fn is_named_region(&self) -> bool { + match *self { + ty::ReFree(ref free_region) => { + match free_region.bound_region { + ty::BrNamed(..) => true, + _ => false, + } + } + _ => false, + } + } } /// Type utilities @@ -1329,9 +1342,12 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } - pub fn fn_sig(&self) -> PolyFnSig<'tcx> { + pub fn fn_sig(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> PolyFnSig<'tcx> { match self.sty { - TyFnDef(.., f) | TyFnPtr(f) => f, + TyFnDef(def_id, substs) => { + tcx.fn_sig(def_id).subst(tcx, substs) + } + TyFnPtr(f) => f, _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self) } } @@ -1381,7 +1397,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { substs.substs.regions().collect() } TyProjection(ref data) => { - data.trait_ref.substs.regions().collect() + data.substs.regions().collect() } TyFnDef(..) | TyFnPtr(_) | diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index d0d6132339..f6112d4887 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -352,9 +352,9 @@ impl<'tcx, T:TypeFoldable<'tcx>> Subst<'tcx> for T { span: Option) -> T { - let mut folder = SubstFolder { tcx: tcx, - substs: substs, - span: span, + let mut folder = SubstFolder { tcx, + substs, + span, root_ty: None, ty_stack_depth: 0, region_binders_passed: 0 }; diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs index ef6bce8a3d..9990472c6b 100644 --- a/src/librustc/ty/trait_def.rs +++ b/src/librustc/ty/trait_def.rs @@ -8,14 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use hir; use hir::def_id::DefId; use hir::map::DefPathHash; use traits::specialization_graph; use ty::fast_reject; use ty::fold::TypeFoldable; use ty::{Ty, TyCtxt}; + +use rustc_data_structures::fx::FxHashMap; + use std::rc::Rc; -use hir; /// A trait's definition with type information. pub struct TraitDef { @@ -36,60 +39,12 @@ pub struct TraitDef { pub def_path_hash: DefPathHash, } -// We don't store the list of impls in a flat list because each cached list of -// `relevant_impls_for` we would then duplicate all blanket impls. By keeping -// blanket and non-blanket impls separate, we can share the list of blanket -// impls. -#[derive(Clone)] pub struct TraitImpls { - blanket_impls: Rc>, - non_blanket_impls: Rc>, + blanket_impls: Vec, + /// Impls indexed by their simplified self-type, for fast lookup. + non_blanket_impls: FxHashMap>, } -impl TraitImpls { - pub fn iter(&self) -> TraitImplsIter { - TraitImplsIter { - blanket_impls: self.blanket_impls.clone(), - non_blanket_impls: self.non_blanket_impls.clone(), - index: 0 - } - } -} - -#[derive(Clone)] -pub struct TraitImplsIter { - blanket_impls: Rc>, - non_blanket_impls: Rc>, - index: usize, -} - -impl Iterator for TraitImplsIter { - type Item = DefId; - - fn next(&mut self) -> Option { - if self.index < self.blanket_impls.len() { - let bi_index = self.index; - self.index += 1; - Some(self.blanket_impls[bi_index]) - } else { - let nbi_index = self.index - self.blanket_impls.len(); - if nbi_index < self.non_blanket_impls.len() { - self.index += 1; - Some(self.non_blanket_impls[nbi_index]) - } else { - None - } - } - } - - fn size_hint(&self) -> (usize, Option) { - let items_left = (self.blanket_impls.len() + self.non_blanket_impls.len()) - self.index; - (items_left, Some(items_left)) - } -} - -impl ExactSizeIterator for TraitImplsIter {} - impl<'a, 'gcx, 'tcx> TraitDef { pub fn new(def_id: DefId, unsafety: hir::Unsafety, @@ -111,20 +66,36 @@ impl<'a, 'gcx, 'tcx> TraitDef { -> specialization_graph::Ancestors { specialization_graph::ancestors(tcx, self.def_id, of_impl) } +} - pub fn for_each_impl(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, mut f: F) { - for impl_def_id in tcx.trait_impls_of(self.def_id).iter() { +impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { + pub fn for_each_impl(self, def_id: DefId, mut f: F) { + let impls = self.trait_impls_of(def_id); + + for &impl_def_id in impls.blanket_impls.iter() { f(impl_def_id); } + + for v in impls.non_blanket_impls.values() { + for &impl_def_id in v { + f(impl_def_id); + } + } } /// Iterate over every impl that could possibly match the /// self-type `self_ty`. - pub fn for_each_relevant_impl(&self, - tcx: TyCtxt<'a, 'gcx, 'tcx>, + pub fn for_each_relevant_impl(self, + def_id: DefId, self_ty: Ty<'tcx>, mut f: F) { + let impls = self.trait_impls_of(def_id); + + for &impl_def_id in impls.blanket_impls.iter() { + f(impl_def_id); + } + // simplify_type(.., false) basically replaces type parameters and // projections with infer-variables. This is, of course, done on // the impl trait-ref when it is instantiated, but not on the @@ -137,15 +108,31 @@ impl<'a, 'gcx, 'tcx> TraitDef { // replace `S` with anything - this impl of course can't be // selected, and as there are hundreds of similar impls, // considering them would significantly harm performance. - let relevant_impls = if let Some(simplified_self_ty) = - fast_reject::simplify_type(tcx, self_ty, true) { - tcx.relevant_trait_impls_for((self.def_id, simplified_self_ty)) - } else { - tcx.trait_impls_of(self.def_id) - }; - for impl_def_id in relevant_impls.iter() { - f(impl_def_id); + // This depends on the set of all impls for the trait. That is + // unfortunate. When we get red-green recompilation, we would like + // to have a way of knowing whether the set of relevant impls + // changed. The most naive + // way would be to compute the Vec of relevant impls and see whether + // it differs between compilations. That shouldn't be too slow by + // itself - we do quite a bit of work for each relevant impl anyway. + // + // If we want to be faster, we could have separate queries for + // blanket and non-blanket impls, and compare them separately. + // + // I think we'll cross that bridge when we get to it. + if let Some(simp) = fast_reject::simplify_type(self, self_ty, true) { + if let Some(impls) = impls.non_blanket_impls.get(&simp) { + for &impl_def_id in impls { + f(impl_def_id); + } + } + } else { + for v in impls.non_blanket_impls.values() { + for &impl_def_id in v { + f(impl_def_id); + } + } } } } @@ -153,7 +140,7 @@ impl<'a, 'gcx, 'tcx> TraitDef { // Query provider for `trait_impls_of`. pub(super) fn trait_impls_of_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_id: DefId) - -> TraitImpls { + -> Rc { let remote_impls = if trait_id.is_local() { // Traits defined in the current crate can't have impls in upstream // crates, so we don't bother querying the cstore. @@ -163,7 +150,7 @@ pub(super) fn trait_impls_of_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; let mut blanket_impls = Vec::new(); - let mut non_blanket_impls = Vec::new(); + let mut non_blanket_impls = FxHashMap(); let local_impls = tcx.hir .trait_impls(trait_id) @@ -176,47 +163,20 @@ pub(super) fn trait_impls_of_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, continue } - if fast_reject::simplify_type(tcx, impl_self_ty, false).is_some() { - non_blanket_impls.push(impl_def_id); + if let Some(simplified_self_ty) = + fast_reject::simplify_type(tcx, impl_self_ty, false) + { + non_blanket_impls + .entry(simplified_self_ty) + .or_insert(vec![]) + .push(impl_def_id); } else { blanket_impls.push(impl_def_id); } } - TraitImpls { - blanket_impls: Rc::new(blanket_impls), - non_blanket_impls: Rc::new(non_blanket_impls), - } -} - -// Query provider for `relevant_trait_impls_for`. -pub(super) fn relevant_trait_impls_provider<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - (trait_id, self_ty): (DefId, fast_reject::SimplifiedType)) - -> TraitImpls -{ - let all_trait_impls = tcx.trait_impls_of(trait_id); - - let relevant: Vec = all_trait_impls - .non_blanket_impls - .iter() - .cloned() - .filter(|&impl_def_id| { - let impl_self_ty = tcx.type_of(impl_def_id); - let impl_simple_self_ty = fast_reject::simplify_type(tcx, - impl_self_ty, - false).unwrap(); - impl_simple_self_ty == self_ty - }) - .collect(); - - if all_trait_impls.non_blanket_impls.len() == relevant.len() { - // If we didn't filter anything out, re-use the existing vec. - all_trait_impls - } else { - TraitImpls { - blanket_impls: all_trait_impls.blanket_impls.clone(), - non_blanket_impls: Rc::new(relevant), - } - } + Rc::new(TraitImpls { + blanket_impls: blanket_impls, + non_blanket_impls: non_blanket_impls, + }) } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index ec4ca54d6f..d1c7383154 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -25,6 +25,7 @@ use middle::lang_items; use rustc_const_math::{ConstInt, ConstIsize, ConstUsize}; use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult, HashStable}; +use rustc_data_structures::fx::FxHashMap; use std::cmp; use std::hash::Hash; use std::intrinsics; @@ -175,7 +176,7 @@ impl<'tcx> ty::ParamEnv<'tcx> { self_type: Ty<'tcx>, span: Span) -> Result<(), CopyImplementationError<'tcx>> { // FIXME: (@jroesch) float this code up - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let (adt, substs) = match self_type.sty { ty::TyAdt(adt, substs) => (adt, substs), _ => return Err(CopyImplementationError::NotAnAdt), @@ -316,15 +317,26 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { target: Ty<'tcx>) -> (Ty<'tcx>, Ty<'tcx>) { let (mut a, mut b) = (source, target); - while let (&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs)) = (&a.sty, &b.sty) { - if a_def != b_def || !a_def.is_struct() { - break; - } - match a_def.struct_variant().fields.last() { - Some(f) => { - a = f.ty(self, a_substs); - b = f.ty(self, b_substs); - } + loop { + match (&a.sty, &b.sty) { + (&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs)) + if a_def == b_def && a_def.is_struct() => { + if let Some(f) = a_def.struct_variant().fields.last() { + a = f.ty(self, a_substs); + b = f.ty(self, b_substs); + } else { + break; + } + }, + (&TyTuple(a_tys, _), &TyTuple(b_tys, _)) + if a_tys.len() == b_tys.len() => { + if let Some(a_last) = a_tys.last() { + a = a_last; + b = b_tys.last().unwrap(); + } else { + break; + } + }, _ => break, } } @@ -410,7 +422,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let mut dtor_did = None; let ty = self.type_of(adt_did); - self.trait_def(drop_trait).for_each_relevant_impl(self, ty, |impl_did| { + self.for_each_relevant_impl(drop_trait, ty, |impl_did| { if let Some(item) = self.associated_items(impl_did).next() { if let Ok(()) = validate(self, impl_did) { dtor_did = Some(item.def_id); @@ -678,7 +690,7 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W> TyRef(_, m) => self.hash(m.mutbl), TyClosure(def_id, _) | TyAnon(def_id, _) | - TyFnDef(def_id, ..) => self.def_id(def_id), + TyFnDef(def_id, _) => self.def_id(def_id), TyAdt(d, _) => self.def_id(d.did), TyFnPtr(f) => { self.hash(f.unsafety()); @@ -835,27 +847,33 @@ impl<'a, 'tcx> ty::TyS<'tcx> { }) } - fn are_inner_types_recursive<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, - seen: &mut Vec>, ty: Ty<'tcx>) - -> Representability { + fn are_inner_types_recursive<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, + seen: &mut Vec>, + representable_cache: &mut FxHashMap, Representability>, + ty: Ty<'tcx>) + -> Representability + { match ty.sty { TyTuple(ref ts, _) => { // Find non representable fold_repr(ts.iter().map(|ty| { - is_type_structurally_recursive(tcx, sp, seen, ty) + is_type_structurally_recursive(tcx, sp, seen, representable_cache, ty) })) } // Fixed-length vectors. // FIXME(#11924) Behavior undecided for zero-length vectors. TyArray(ty, _) => { - is_type_structurally_recursive(tcx, sp, seen, ty) + is_type_structurally_recursive(tcx, sp, seen, representable_cache, ty) } TyAdt(def, substs) => { // Find non representable fields with their spans fold_repr(def.all_fields().map(|field| { let ty = field.ty(tcx, substs); let span = tcx.hir.span_if_local(field.did).unwrap_or(sp); - match is_type_structurally_recursive(tcx, span, seen, ty) { + match is_type_structurally_recursive(tcx, span, seen, + representable_cache, ty) + { Representability::SelfRecursive(_) => { Representability::SelfRecursive(vec![span]) } @@ -896,12 +914,34 @@ impl<'a, 'tcx> ty::TyS<'tcx> { // Does the type `ty` directly (without indirection through a pointer) // contain any types on stack `seen`? - fn is_type_structurally_recursive<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - sp: Span, - seen: &mut Vec>, - ty: Ty<'tcx>) -> Representability { + fn is_type_structurally_recursive<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + sp: Span, + seen: &mut Vec>, + representable_cache: &mut FxHashMap, Representability>, + ty: Ty<'tcx>) -> Representability + { debug!("is_type_structurally_recursive: {:?} {:?}", ty, sp); + if let Some(representability) = representable_cache.get(ty) { + debug!("is_type_structurally_recursive: {:?} {:?} - (cached) {:?}", + ty, sp, representability); + return representability.clone(); + } + + let representability = is_type_structurally_recursive_inner( + tcx, sp, seen, representable_cache, ty); + + representable_cache.insert(ty, representability.clone()); + representability + } + fn is_type_structurally_recursive_inner<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + sp: Span, + seen: &mut Vec>, + representable_cache: &mut FxHashMap, Representability>, + ty: Ty<'tcx>) -> Representability + { match ty.sty { TyAdt(def, _) => { { @@ -948,13 +988,13 @@ impl<'a, 'tcx> ty::TyS<'tcx> { // For structs and enums, track all previously seen types by pushing them // onto the 'seen' stack. seen.push(ty); - let out = are_inner_types_recursive(tcx, sp, seen, ty); + let out = are_inner_types_recursive(tcx, sp, seen, representable_cache, ty); seen.pop(); out } _ => { // No need to push in other cases. - are_inner_types_recursive(tcx, sp, seen, ty) + are_inner_types_recursive(tcx, sp, seen, representable_cache, ty) } } } @@ -965,7 +1005,9 @@ impl<'a, 'tcx> ty::TyS<'tcx> { // contains a different, structurally recursive type, maintain a stack // of seen types and check recursion for each of them (issues #3008, #3779). let mut seen: Vec = Vec::new(); - let r = is_type_structurally_recursive(tcx, sp, &mut seen, self); + let mut representable_cache = FxHashMap(); + let r = is_type_structurally_recursive( + tcx, sp, &mut seen, &mut representable_cache, self); debug!("is_type_representable: {:?} is {:?}", self, r); r } @@ -977,7 +1019,7 @@ fn is_copy_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { let (param_env, ty) = query.into_parts(); let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem); - tcx.infer_ctxt(()) + tcx.infer_ctxt() .enter(|infcx| traits::type_known_to_meet_bound(&infcx, param_env, ty, @@ -991,7 +1033,7 @@ fn is_sized_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { let (param_env, ty) = query.into_parts(); let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem); - tcx.infer_ctxt(()) + tcx.infer_ctxt() .enter(|infcx| traits::type_known_to_meet_bound(&infcx, param_env, ty, @@ -1005,7 +1047,7 @@ fn is_freeze_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { let (param_env, ty) = query.into_parts(); let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem); - tcx.infer_ctxt(()) + tcx.infer_ctxt() .enter(|infcx| traits::type_known_to_meet_bound(&infcx, param_env, ty, diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index d7954953ab..a7f0bafe9b 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -90,14 +90,14 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { stack.push(mt.ty); } ty::TyProjection(ref data) => { - stack.extend(data.trait_ref.substs.types().rev()); + stack.extend(data.substs.types().rev()); } ty::TyDynamic(ref obj, ..) => { stack.extend(obj.iter().rev().flat_map(|predicate| { let (substs, opt_ty) = match *predicate.skip_binder() { ty::ExistentialPredicate::Trait(tr) => (tr.substs, None), ty::ExistentialPredicate::Projection(p) => - (p.trait_ref.substs, Some(p.ty)), + (p.substs, Some(p.ty)), ty::ExistentialPredicate::AutoTrait(_) => // Empty iterator (ty::Substs::empty(), None), @@ -115,9 +115,8 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { ty::TyTuple(ts, _) => { stack.extend(ts.iter().cloned().rev()); } - ty::TyFnDef(_, substs, ft) => { + ty::TyFnDef(_, substs) => { stack.extend(substs.types().rev()); - push_sig_subtypes(stack, ft); } ty::TyFnPtr(ft) => { push_sig_subtypes(stack, ft); diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 2eb0acac4f..c24c583ad1 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -31,10 +31,10 @@ pub fn obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, span: Span) -> Option>> { - let mut wf = WfPredicates { infcx: infcx, - param_env: param_env, - body_id: body_id, - span: span, + let mut wf = WfPredicates { infcx, + param_env, + body_id, + span, out: vec![] }; if wf.compute(ty) { debug!("wf::obligations({:?}, body_id={:?}) = {:?}", ty, body_id, wf.out); @@ -155,11 +155,11 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { // A projection is well-formed if (a) the trait ref itself is // WF and (b) the trait-ref holds. (It may also be // normalizable and be WF that way.) - - self.compute_trait_ref(&data.trait_ref); + let trait_ref = data.trait_ref(self.infcx.tcx); + self.compute_trait_ref(&trait_ref); if !data.has_escaping_regions() { - let predicate = data.trait_ref.to_predicate(); + let predicate = trait_ref.to_predicate(); let cause = self.cause(traits::ProjectionWf(data)); self.out.push(traits::Obligation::new(cause, self.param_env, predicate)); } diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 17564671a1..40ee3cd28f 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -19,6 +19,8 @@ use std::iter::repeat; use std::path::Path; use std::time::{Duration, Instant}; +use ty::TyCtxt; + // The name of the associated type for `Fn` return types pub const FN_OUTPUT_NAME: &'static str = "Output"; @@ -209,7 +211,7 @@ pub trait MemoizationMap { /// needed in the `op` to ensure that the correct edges are /// added into the dep graph. See the `DepTrackingMap` impl for /// more details! - fn memoize(&self, key: Self::Key, op: OP) -> Self::Value + fn memoize(&self, tcx: TyCtxt, key: Self::Key, op: OP) -> Self::Value where OP: FnOnce() -> Self::Value; } @@ -219,7 +221,7 @@ impl MemoizationMap for RefCell> type Key = K; type Value = V; - fn memoize(&self, key: K, op: OP) -> V + fn memoize(&self, _tcx: TyCtxt, key: K, op: OP) -> V where OP: FnOnce() -> V { let result = self.borrow().get(&key).cloned(); diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 15fbeb5108..d9c99ccd50 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use hir::BodyId; use hir::def_id::DefId; use hir::map::definitions::DefPathData; +use middle::region::{CodeExtent, BlockRemainder}; use ty::subst::{self, Subst}; use ty::{BrAnon, BrEnv, BrFresh, BrNamed}; use ty::{TyBool, TyChar, TyAdt}; @@ -32,6 +34,10 @@ pub fn verbose() -> bool { ty::tls::with(|tcx| tcx.sess.verbose()) } +pub fn identify_regions() -> bool { + ty::tls::with(|tcx| tcx.sess.opts.debugging_opts.identify_regions) +} + fn fn_sig(f: &mut fmt::Formatter, inputs: &[Ty], variadic: bool, @@ -218,7 +224,7 @@ pub fn parameterized(f: &mut fmt::Formatter, start_or_continue(f, "<", ", ")?; ty::tls::with(|tcx| write!(f, "{}={}", - projection.projection_ty.item_name(tcx), + tcx.associated_item(projection.projection_ty.item_def_id).name, projection.ty) )?; } @@ -519,6 +525,23 @@ impl fmt::Display for ty::RegionKind { ty::ReSkolemized(_, br) => { write!(f, "{}", br) } + ty::ReScope(code_extent) if identify_regions() => { + match code_extent { + CodeExtent::Misc(node_id) => + write!(f, "'{}mce", node_id.as_u32()), + CodeExtent::CallSiteScope(BodyId { node_id }) => + write!(f, "'{}cce", node_id.as_u32()), + CodeExtent::ParameterScope(BodyId { node_id }) => + write!(f, "'{}pce", node_id.as_u32()), + CodeExtent::DestructionScope(node_id) => + write!(f, "'{}dce", node_id.as_u32()), + CodeExtent::Remainder(BlockRemainder { block, first_statement_index }) => + write!(f, "'{}_{}rce", block, first_statement_index), + } + } + ty::ReVar(region_vid) if identify_regions() => { + write!(f, "'{}rv", region_vid.index) + } ty::ReScope(_) | ty::ReVar(_) | ty::ReErased => Ok(()), @@ -730,8 +753,14 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { } write!(f, ")") } - TyFnDef(def_id, substs, ref bare_fn) => { - write!(f, "{} {{", bare_fn.0)?; + TyFnDef(def_id, substs) => { + ty::tls::with(|tcx| { + let mut sig = tcx.fn_sig(def_id); + if let Some(substs) = tcx.lift(&substs) { + sig = sig.subst(tcx, substs); + } + write!(f, "{} {{", sig.0) + })?; parameterized(f, substs, def_id, &[])?; write!(f, "}}") } @@ -789,7 +818,11 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { write!(f, "[closure")?; if let Some(node_id) = tcx.hir.as_local_node_id(did) { - write!(f, "@{:?}", tcx.hir.span(node_id))?; + if tcx.sess.opts.debugging_opts.span_free_formats { + write!(f, "@{:?}", node_id)?; + } else { + 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) { @@ -925,9 +958,14 @@ impl<'tcx> fmt::Display for ty::ProjectionPredicate<'tcx> { impl<'tcx> fmt::Display for ty::ProjectionTy<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let item_name = ty::tls::with(|tcx| self.item_name(tcx)); + // FIXME(tschottdorf): use something like + // parameterized(f, self.substs, self.item_def_id, &[]) + // (which currently ICEs). + let (trait_ref, item_name) = ty::tls::with(|tcx| + (self.trait_ref(tcx), tcx.associated_item(self.item_def_id).name) + ); write!(f, "{:?}::{}", - self.trait_ref, + trait_ref, item_name) } } diff --git a/src/libproc_macro_plugin/Cargo.toml b/src/librustc_allocator/Cargo.toml similarity index 64% rename from src/libproc_macro_plugin/Cargo.toml rename to src/librustc_allocator/Cargo.toml index 146a66cdf0..e3d1d8e32c 100644 --- a/src/libproc_macro_plugin/Cargo.toml +++ b/src/librustc_allocator/Cargo.toml @@ -1,13 +1,15 @@ [package] authors = ["The Rust Project Developers"] -name = "proc_macro_plugin" +name = "rustc_allocator" version = "0.0.0" [lib] path = "lib.rs" crate-type = ["dylib"] +test = false [dependencies] -rustc_plugin = { path = "../librustc_plugin" } +rustc = { path = "../librustc" } +rustc_errors = { path = "../librustc_errors" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs new file mode 100644 index 0000000000..e942b7264c --- /dev/null +++ b/src/librustc_allocator/expand.rs @@ -0,0 +1,498 @@ +// 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 rustc::middle::allocator::AllocatorKind; +use rustc_errors; +use syntax::abi::Abi; +use syntax::ast::{Crate, Attribute, LitKind, StrStyle, ExprKind}; +use syntax::ast::{Unsafety, Constness, Generics, Mutability, Ty, Mac, Arg}; +use syntax::ast::{self, Ident, Item, ItemKind, TyKind, Visibility, Expr}; +use syntax::attr; +use syntax::codemap::dummy_spanned; +use syntax::codemap::{ExpnInfo, NameAndSpan, MacroAttribute}; +use syntax::ext::base::ExtCtxt; +use syntax::ext::base::Resolver; +use syntax::ext::build::AstBuilder; +use syntax::ext::expand::ExpansionConfig; +use syntax::ext::hygiene::{Mark, SyntaxContext}; +use syntax::fold::{self, Folder}; +use syntax::parse::ParseSess; +use syntax::ptr::P; +use syntax::symbol::Symbol; +use syntax::util::small_vector::SmallVector; +use syntax_pos::{Span, DUMMY_SP}; + +use {AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS}; + +pub fn modify(sess: &ParseSess, + resolver: &mut Resolver, + krate: Crate, + handler: &rustc_errors::Handler) -> ast::Crate { + ExpandAllocatorDirectives { + handler: handler, + sess: sess, + resolver: resolver, + found: false, + }.fold_crate(krate) +} + +struct ExpandAllocatorDirectives<'a> { + found: bool, + handler: &'a rustc_errors::Handler, + sess: &'a ParseSess, + resolver: &'a mut Resolver, +} + +impl<'a> Folder for ExpandAllocatorDirectives<'a> { + fn fold_item(&mut self, item: P) -> SmallVector> { + let name = if attr::contains_name(&item.attrs, "global_allocator") { + "global_allocator" + } else { + return fold::noop_fold_item(item, self) + }; + match item.node { + ItemKind::Static(..) => {} + _ => { + self.handler.span_err(item.span, "allocators must be statics"); + return SmallVector::one(item) + } + } + + if self.found { + self.handler.span_err(item.span, "cannot define more than one \ + #[global_allocator]"); + return SmallVector::one(item) + } + self.found = true; + + let mark = Mark::fresh(Mark::root()); + mark.set_expn_info(ExpnInfo { + call_site: DUMMY_SP, + callee: NameAndSpan { + format: MacroAttribute(Symbol::intern(name)), + span: None, + allow_internal_unstable: true, + } + }); + let span = Span { + ctxt: SyntaxContext::empty().apply_mark(mark), + ..item.span + }; + let ecfg = ExpansionConfig::default(name.to_string()); + let mut f = AllocFnFactory { + span: span, + kind: AllocatorKind::Global, + global: item.ident, + alloc: Ident::from_str("alloc"), + cx: ExtCtxt::new(self.sess, ecfg, self.resolver), + }; + let super_path = f.cx.path(f.span, vec![ + Ident::from_str("super"), + f.global, + ]); + let mut items = vec![ + f.cx.item_extern_crate(f.span, f.alloc), + f.cx.item_use_simple(f.span, Visibility::Inherited, super_path), + ]; + for method in ALLOCATOR_METHODS { + items.push(f.allocator_fn(method)); + } + let name = f.kind.fn_name("allocator_abi"); + let allocator_abi = Ident::with_empty_ctxt(Symbol::gensym(&name)); + let module = f.cx.item_mod(span, span, allocator_abi, Vec::new(), items); + let module = f.cx.monotonic_expander().fold_item(module).pop().unwrap(); + + let mut ret = SmallVector::new(); + ret.push(item); + ret.push(module); + return ret + } + + fn fold_mac(&mut self, mac: Mac) -> Mac { + fold::noop_fold_mac(mac, self) + } +} + +struct AllocFnFactory<'a> { + span: Span, + kind: AllocatorKind, + global: Ident, + alloc: Ident, + cx: ExtCtxt<'a>, +} + +impl<'a> AllocFnFactory<'a> { + fn allocator_fn(&self, method: &AllocatorMethod) -> P { + let mut abi_args = Vec::new(); + let mut i = 0; + let ref mut mk = || { + let name = Ident::from_str(&format!("arg{}", i)); + i += 1; + name + }; + let args = method.inputs.iter().map(|ty| { + self.arg_ty(ty, &mut abi_args, mk) + }).collect(); + let result = self.call_allocator(method.name, args); + let (output_ty, output_expr) = + self.ret_ty(&method.output, &mut abi_args, mk, result); + let kind = ItemKind::Fn(self.cx.fn_decl(abi_args, output_ty), + Unsafety::Unsafe, + dummy_spanned(Constness::NotConst), + Abi::Rust, + Generics::default(), + self.cx.block_expr(output_expr)); + self.cx.item(self.span, + Ident::from_str(&self.kind.fn_name(method.name)), + self.attrs(), + kind) + } + + fn call_allocator(&self, method: &str, mut args: Vec>) -> P { + let method = self.cx.path(self.span, vec![ + self.alloc, + Ident::from_str("heap"), + Ident::from_str("Alloc"), + Ident::from_str(method), + ]); + let method = self.cx.expr_path(method); + let allocator = self.cx.path_ident(self.span, self.global); + let allocator = self.cx.expr_path(allocator); + let allocator = self.cx.expr_addr_of(self.span, allocator); + let allocator = self.cx.expr_mut_addr_of(self.span, allocator); + args.insert(0, allocator); + + self.cx.expr_call(self.span, method, args) + } + + fn attrs(&self) -> Vec { + let key = Symbol::intern("linkage"); + let value = LitKind::Str(Symbol::intern("external"), StrStyle::Cooked); + let linkage = self.cx.meta_name_value(self.span, key, value); + + let no_mangle = Symbol::intern("no_mangle"); + let no_mangle = self.cx.meta_word(self.span, no_mangle); + vec![ + self.cx.attribute(self.span, linkage), + self.cx.attribute(self.span, no_mangle), + ] + } + + fn arg_ty(&self, + ty: &AllocatorTy, + args: &mut Vec, + mut ident: &mut FnMut() -> Ident) -> P { + match *ty { + AllocatorTy::Layout => { + let usize = self.cx.path_ident(self.span, Ident::from_str("usize")); + let ty_usize = self.cx.ty_path(usize); + let size = ident(); + let align = ident(); + args.push(self.cx.arg(self.span, size, ty_usize.clone())); + args.push(self.cx.arg(self.span, align, ty_usize)); + + let layout_new = self.cx.path(self.span, vec![ + self.alloc, + Ident::from_str("heap"), + Ident::from_str("Layout"), + Ident::from_str("from_size_align_unchecked"), + ]); + let layout_new = self.cx.expr_path(layout_new); + let size = self.cx.expr_ident(self.span, size); + let align = self.cx.expr_ident(self.span, align); + let layout = self.cx.expr_call(self.span, + layout_new, + vec![size, align]); + layout + } + + AllocatorTy::LayoutRef => { + let ident = ident(); + args.push(self.cx.arg(self.span, ident, self.ptr_u8())); + + // Convert our `arg: *const u8` via: + // + // &*(arg as *const Layout) + let expr = self.cx.expr_ident(self.span, ident); + let expr = self.cx.expr_cast(self.span, expr, self.layout_ptr()); + let expr = self.cx.expr_deref(self.span, expr); + self.cx.expr_addr_of(self.span, expr) + } + + AllocatorTy::AllocErr => { + // We're creating: + // + // (*(arg as *const AllocErr)).clone() + let ident = ident(); + args.push(self.cx.arg(self.span, ident, self.ptr_u8())); + let expr = self.cx.expr_ident(self.span, ident); + let expr = self.cx.expr_cast(self.span, expr, self.alloc_err_ptr()); + let expr = self.cx.expr_deref(self.span, expr); + self.cx.expr_method_call( + self.span, + expr, + Ident::from_str("clone"), + Vec::new() + ) + } + + AllocatorTy::Ptr => { + let ident = ident(); + args.push(self.cx.arg(self.span, ident, self.ptr_u8())); + self.cx.expr_ident(self.span, ident) + } + + AllocatorTy::ResultPtr | + AllocatorTy::ResultExcess | + AllocatorTy::ResultUnit | + AllocatorTy::Bang | + AllocatorTy::UsizePair | + AllocatorTy::Unit => { + panic!("can't convert AllocatorTy to an argument") + } + } + } + + fn ret_ty(&self, + ty: &AllocatorTy, + args: &mut Vec, + mut ident: &mut FnMut() -> Ident, + expr: P) -> (P, P) + { + match *ty { + AllocatorTy::UsizePair => { + // We're creating: + // + // let arg = #expr; + // *min = arg.0; + // *max = arg.1; + + let min = ident(); + let max = ident(); + + args.push(self.cx.arg(self.span, min, self.ptr_usize())); + args.push(self.cx.arg(self.span, max, self.ptr_usize())); + + let ident = ident(); + let stmt = self.cx.stmt_let(self.span, false, ident, expr); + let min = self.cx.expr_ident(self.span, min); + let max = self.cx.expr_ident(self.span, max); + let layout = self.cx.expr_ident(self.span, ident); + let assign_min = self.cx.expr(self.span, ExprKind::Assign( + self.cx.expr_deref(self.span, min), + self.cx.expr_tup_field_access(self.span, layout.clone(), 0), + )); + let assign_min = self.cx.stmt_semi(assign_min); + let assign_max = self.cx.expr(self.span, ExprKind::Assign( + self.cx.expr_deref(self.span, max), + self.cx.expr_tup_field_access(self.span, layout.clone(), 1), + )); + let assign_max = self.cx.stmt_semi(assign_max); + + let stmts = vec![stmt, assign_min, assign_max]; + let block = self.cx.block(self.span, stmts); + let ty_unit = self.cx.ty(self.span, TyKind::Tup(Vec::new())); + (ty_unit, self.cx.expr_block(block)) + } + + AllocatorTy::ResultExcess => { + // We're creating: + // + // match #expr { + // Ok(ptr) => { + // *excess = ptr.1; + // ptr.0 + // } + // Err(e) => { + // ptr::write(err_ptr, e); + // 0 as *mut u8 + // } + // } + + let excess_ptr = ident(); + args.push(self.cx.arg(self.span, excess_ptr, self.ptr_usize())); + let excess_ptr = self.cx.expr_ident(self.span, excess_ptr); + + let err_ptr = ident(); + args.push(self.cx.arg(self.span, err_ptr, self.ptr_u8())); + let err_ptr = self.cx.expr_ident(self.span, err_ptr); + let err_ptr = self.cx.expr_cast(self.span, + err_ptr, + self.alloc_err_ptr()); + + let name = ident(); + let ok_expr = { + let ptr = self.cx.expr_ident(self.span, name); + let write = self.cx.expr(self.span, ExprKind::Assign( + self.cx.expr_deref(self.span, excess_ptr), + self.cx.expr_tup_field_access(self.span, ptr.clone(), 1), + )); + let write = self.cx.stmt_semi(write); + let ret = self.cx.expr_tup_field_access(self.span, + ptr.clone(), + 0); + let ret = self.cx.stmt_expr(ret); + let block = self.cx.block(self.span, vec![write, ret]); + self.cx.expr_block(block) + }; + let pat = self.cx.pat_ident(self.span, name); + let ok = self.cx.path_ident(self.span, Ident::from_str("Ok")); + let ok = self.cx.pat_tuple_struct(self.span, ok, vec![pat]); + let ok = self.cx.arm(self.span, vec![ok], ok_expr); + + let name = ident(); + let err_expr = { + let err = self.cx.expr_ident(self.span, name); + let write = self.cx.path(self.span, vec![ + self.alloc, + Ident::from_str("heap"), + Ident::from_str("__core"), + Ident::from_str("ptr"), + Ident::from_str("write"), + ]); + let write = self.cx.expr_path(write); + let write = self.cx.expr_call(self.span, write, + vec![err_ptr, err]); + let write = self.cx.stmt_semi(write); + let null = self.cx.expr_usize(self.span, 0); + let null = self.cx.expr_cast(self.span, null, self.ptr_u8()); + let null = self.cx.stmt_expr(null); + let block = self.cx.block(self.span, vec![write, null]); + self.cx.expr_block(block) + }; + let pat = self.cx.pat_ident(self.span, name); + let err = self.cx.path_ident(self.span, Ident::from_str("Err")); + let err = self.cx.pat_tuple_struct(self.span, err, vec![pat]); + let err = self.cx.arm(self.span, vec![err], err_expr); + + let expr = self.cx.expr_match(self.span, expr, vec![ok, err]); + (self.ptr_u8(), expr) + } + + AllocatorTy::ResultPtr => { + // We're creating: + // + // match #expr { + // Ok(ptr) => ptr, + // Err(e) => { + // ptr::write(err_ptr, e); + // 0 as *mut u8 + // } + // } + + let err_ptr = ident(); + args.push(self.cx.arg(self.span, err_ptr, self.ptr_u8())); + let err_ptr = self.cx.expr_ident(self.span, err_ptr); + let err_ptr = self.cx.expr_cast(self.span, + err_ptr, + self.alloc_err_ptr()); + + let name = ident(); + let ok_expr = self.cx.expr_ident(self.span, name); + let pat = self.cx.pat_ident(self.span, name); + let ok = self.cx.path_ident(self.span, Ident::from_str("Ok")); + let ok = self.cx.pat_tuple_struct(self.span, ok, vec![pat]); + let ok = self.cx.arm(self.span, vec![ok], ok_expr); + + let name = ident(); + let err_expr = { + let err = self.cx.expr_ident(self.span, name); + let write = self.cx.path(self.span, vec![ + self.alloc, + Ident::from_str("heap"), + Ident::from_str("__core"), + Ident::from_str("ptr"), + Ident::from_str("write"), + ]); + let write = self.cx.expr_path(write); + let write = self.cx.expr_call(self.span, write, + vec![err_ptr, err]); + let write = self.cx.stmt_semi(write); + let null = self.cx.expr_usize(self.span, 0); + let null = self.cx.expr_cast(self.span, null, self.ptr_u8()); + let null = self.cx.stmt_expr(null); + let block = self.cx.block(self.span, vec![write, null]); + self.cx.expr_block(block) + }; + let pat = self.cx.pat_ident(self.span, name); + let err = self.cx.path_ident(self.span, Ident::from_str("Err")); + let err = self.cx.pat_tuple_struct(self.span, err, vec![pat]); + let err = self.cx.arm(self.span, vec![err], err_expr); + + let expr = self.cx.expr_match(self.span, expr, vec![ok, err]); + (self.ptr_u8(), expr) + } + + AllocatorTy::ResultUnit => { + // We're creating: + // + // #expr.is_ok() as u8 + + let cast = self.cx.expr_method_call( + self.span, + expr, + Ident::from_str("is_ok"), + Vec::new() + ); + let u8 = self.cx.path_ident(self.span, Ident::from_str("u8")); + let u8 = self.cx.ty_path(u8); + let cast = self.cx.expr_cast(self.span, cast, u8.clone()); + (u8, cast) + } + + AllocatorTy::Bang => { + (self.cx.ty(self.span, TyKind::Never), expr) + } + + AllocatorTy::Unit => { + (self.cx.ty(self.span, TyKind::Tup(Vec::new())), expr) + } + + AllocatorTy::AllocErr | + AllocatorTy::Layout | + AllocatorTy::LayoutRef | + AllocatorTy::Ptr => { + panic!("can't convert AllocatorTy to an output") + } + } + } + + fn ptr_u8(&self) -> P { + let u8 = self.cx.path_ident(self.span, Ident::from_str("u8")); + let ty_u8 = self.cx.ty_path(u8); + self.cx.ty_ptr(self.span, ty_u8, Mutability::Mutable) + } + + fn ptr_usize(&self) -> P { + let usize = self.cx.path_ident(self.span, Ident::from_str("usize")); + let ty_usize = self.cx.ty_path(usize); + self.cx.ty_ptr(self.span, ty_usize, Mutability::Mutable) + } + + fn layout_ptr(&self) -> P { + let layout = self.cx.path(self.span, vec![ + self.alloc, + Ident::from_str("heap"), + Ident::from_str("Layout"), + ]); + let layout = self.cx.ty_path(layout); + self.cx.ty_ptr(self.span, layout, Mutability::Mutable) + } + + fn alloc_err_ptr(&self) -> P { + let err = self.cx.path(self.span, vec![ + self.alloc, + Ident::from_str("heap"), + Ident::from_str("AllocErr"), + ]); + let err = self.cx.ty_path(err); + self.cx.ty_ptr(self.span, err, Mutability::Mutable) + } +} diff --git a/src/librustc_allocator/lib.rs b/src/librustc_allocator/lib.rs new file mode 100644 index 0000000000..d0ea40d1e3 --- /dev/null +++ b/src/librustc_allocator/lib.rs @@ -0,0 +1,101 @@ +// 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. + +#![feature(rustc_private)] + +extern crate rustc; +extern crate rustc_errors; +extern crate syntax; +extern crate syntax_pos; + +pub mod expand; + +pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[ + AllocatorMethod { + name: "alloc", + inputs: &[AllocatorTy::Layout], + output: AllocatorTy::ResultPtr, + is_unsafe: true, + }, + AllocatorMethod { + name: "oom", + inputs: &[AllocatorTy::AllocErr], + output: AllocatorTy::Bang, + is_unsafe: false, + }, + AllocatorMethod { + name: "dealloc", + inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout], + output: AllocatorTy::Unit, + is_unsafe: true, + }, + AllocatorMethod { + name: "usable_size", + inputs: &[AllocatorTy::LayoutRef], + output: AllocatorTy::UsizePair, + is_unsafe: false, + }, + AllocatorMethod { + name: "realloc", + inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout], + output: AllocatorTy::ResultPtr, + is_unsafe: true, + }, + AllocatorMethod { + name: "alloc_zeroed", + inputs: &[AllocatorTy::Layout], + output: AllocatorTy::ResultPtr, + is_unsafe: true, + }, + AllocatorMethod { + name: "alloc_excess", + inputs: &[AllocatorTy::Layout], + output: AllocatorTy::ResultExcess, + is_unsafe: true, + }, + AllocatorMethod { + name: "realloc_excess", + inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout], + output: AllocatorTy::ResultExcess, + is_unsafe: true, + }, + AllocatorMethod { + name: "grow_in_place", + inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout], + output: AllocatorTy::ResultUnit, + is_unsafe: true, + }, + AllocatorMethod { + name: "shrink_in_place", + inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout], + output: AllocatorTy::ResultUnit, + is_unsafe: true, + }, +]; + +pub struct AllocatorMethod { + pub name: &'static str, + pub inputs: &'static [AllocatorTy], + pub output: AllocatorTy, + pub is_unsafe: bool, +} + +pub enum AllocatorTy { + AllocErr, + Bang, + Layout, + LayoutRef, + Ptr, + ResultExcess, + ResultPtr, + ResultUnit, + Unit, + UsizePair, +} diff --git a/src/librustc_asan/Cargo.toml b/src/librustc_asan/Cargo.toml index 0fda2805fe..8f8ef1cc4a 100644 --- a/src/librustc_asan/Cargo.toml +++ b/src/librustc_asan/Cargo.toml @@ -14,5 +14,6 @@ build_helper = { path = "../build_helper" } cmake = "0.1.18" [dependencies] +alloc = { path = "../liballoc" } alloc_system = { path = "../liballoc_system" } core = { path = "../libcore" } diff --git a/src/librustc_asan/build.rs b/src/librustc_asan/build.rs index 3a80baa048..cb7721affe 100644 --- a/src/librustc_asan/build.rs +++ b/src/librustc_asan/build.rs @@ -32,4 +32,5 @@ fn main() { .build_target("asan") .build(); } + println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); } diff --git a/src/librustc_asan/lib.rs b/src/librustc_asan/lib.rs index 54941362e8..e987b1f335 100644 --- a/src/librustc_asan/lib.rs +++ b/src/librustc_asan/lib.rs @@ -11,6 +11,8 @@ #![sanitizer_runtime] #![feature(sanitizer_runtime)] #![feature(alloc_system)] +#![cfg_attr(not(stage0), feature(allocator_api))] +#![cfg_attr(not(stage0), feature(global_allocator))] #![feature(staged_api)] #![no_std] #![unstable(feature = "sanitizer_runtime_lib", @@ -18,3 +20,10 @@ issue = "0")] extern crate alloc_system; + +#[cfg(not(stage0))] +use alloc_system::System; + +#[cfg(not(stage0))] +#[global_allocator] +static ALLOC: System = System; diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index 69eabfe2ac..c776f28ecd 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -35,10 +35,6 @@ #![feature(rand)] #![cfg_attr(test, feature(rand))] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] - extern crate syntax; extern crate libc; extern crate serialize; diff --git a/src/librustc_back/target/aarch64_unknown_freebsd.rs b/src/librustc_back/target/aarch64_unknown_freebsd.rs index c5cfff0be0..c5427a13e4 100644 --- a/src/librustc_back/target/aarch64_unknown_freebsd.rs +++ b/src/librustc_back/target/aarch64_unknown_freebsd.rs @@ -16,7 +16,7 @@ pub fn target() -> TargetResult { base.max_atomic_width = Some(128); // see #36994 - base.exe_allocation_crate = "alloc_system".to_string(); + base.exe_allocation_crate = None; Ok(Target { llvm_target: "aarch64-unknown-freebsd".to_string(), diff --git a/src/librustc_back/target/aarch64_unknown_linux_gnu.rs b/src/librustc_back/target/aarch64_unknown_linux_gnu.rs index 043bd881c7..7c2c45a284 100644 --- a/src/librustc_back/target/aarch64_unknown_linux_gnu.rs +++ b/src/librustc_back/target/aarch64_unknown_linux_gnu.rs @@ -16,7 +16,7 @@ pub fn target() -> TargetResult { base.max_atomic_width = Some(128); // see #36994 - base.exe_allocation_crate = "alloc_system".to_string(); + base.exe_allocation_crate = None; Ok(Target { llvm_target: "aarch64-unknown-linux-gnu".to_string(), diff --git a/src/librustc_back/target/bitrig_base.rs b/src/librustc_back/target/bitrig_base.rs index 62418e68d4..5c4e01886a 100644 --- a/src/librustc_back/target/bitrig_base.rs +++ b/src/librustc_back/target/bitrig_base.rs @@ -19,7 +19,6 @@ pub fn opts() -> TargetOptions { linker_is_gnu: true, has_rpath: true, position_independent_executables: true, - exe_allocation_crate: "alloc_system".to_string(), .. Default::default() } diff --git a/src/librustc_back/target/fuchsia_base.rs b/src/librustc_back/target/fuchsia_base.rs index c6207cdc4d..63ccd21c22 100644 --- a/src/librustc_back/target/fuchsia_base.rs +++ b/src/librustc_back/target/fuchsia_base.rs @@ -37,7 +37,6 @@ pub fn opts() -> TargetOptions { has_rpath: true, pre_link_args: args, position_independent_executables: true, - exe_allocation_crate: "alloc_system".to_string(), has_elf_tls: true, .. Default::default() } diff --git a/src/librustc_back/target/i386_apple_ios.rs b/src/librustc_back/target/i386_apple_ios.rs index a6383179f3..0e4e690002 100644 --- a/src/librustc_back/target/i386_apple_ios.rs +++ b/src/librustc_back/target/i386_apple_ios.rs @@ -26,6 +26,7 @@ pub fn target() -> TargetResult { linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { max_atomic_width: Some(64), + stack_probes: true, .. base } }) diff --git a/src/librustc_back/target/i686_apple_darwin.rs b/src/librustc_back/target/i686_apple_darwin.rs index 6b14972e9f..8c931f1841 100644 --- a/src/librustc_back/target/i686_apple_darwin.rs +++ b/src/librustc_back/target/i686_apple_darwin.rs @@ -16,6 +16,7 @@ pub fn target() -> TargetResult { base.cpu = "yonah".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".to_string()]); + base.stack_probes = true; Ok(Target { llvm_target: "i686-apple-darwin".to_string(), diff --git a/src/librustc_back/target/i686_linux_android.rs b/src/librustc_back/target/i686_linux_android.rs index a5390cbfb7..565fbe37bf 100644 --- a/src/librustc_back/target/i686_linux_android.rs +++ b/src/librustc_back/target/i686_linux_android.rs @@ -22,6 +22,7 @@ pub fn target() -> TargetResult { // http://developer.android.com/ndk/guides/abis.html#x86 base.cpu = "pentiumpro".to_string(); base.features = "+mmx,+sse,+sse2,+sse3,+ssse3".to_string(); + base.stack_probes = true; Ok(Target { llvm_target: "i686-linux-android".to_string(), diff --git a/src/librustc_back/target/i686_unknown_dragonfly.rs b/src/librustc_back/target/i686_unknown_dragonfly.rs index 052bc23c11..9eda49a370 100644 --- a/src/librustc_back/target/i686_unknown_dragonfly.rs +++ b/src/librustc_back/target/i686_unknown_dragonfly.rs @@ -16,6 +16,7 @@ pub fn target() -> TargetResult { base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); + base.stack_probes = true; Ok(Target { llvm_target: "i686-unknown-dragonfly".to_string(), diff --git a/src/librustc_back/target/i686_unknown_freebsd.rs b/src/librustc_back/target/i686_unknown_freebsd.rs index d77a9cca26..041f3070c9 100644 --- a/src/librustc_back/target/i686_unknown_freebsd.rs +++ b/src/librustc_back/target/i686_unknown_freebsd.rs @@ -16,6 +16,7 @@ pub fn target() -> TargetResult { base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); + base.stack_probes = true; Ok(Target { llvm_target: "i686-unknown-freebsd".to_string(), diff --git a/src/librustc_back/target/i686_unknown_haiku.rs b/src/librustc_back/target/i686_unknown_haiku.rs index b0e67bd90d..f21c2f8c77 100644 --- a/src/librustc_back/target/i686_unknown_haiku.rs +++ b/src/librustc_back/target/i686_unknown_haiku.rs @@ -16,6 +16,7 @@ pub fn target() -> TargetResult { base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".to_string()]); + base.stack_probes = true; Ok(Target { llvm_target: "i686-unknown-haiku".to_string(), diff --git a/src/librustc_back/target/i686_unknown_linux_gnu.rs b/src/librustc_back/target/i686_unknown_linux_gnu.rs index 3c5c106762..f7b916816b 100644 --- a/src/librustc_back/target/i686_unknown_linux_gnu.rs +++ b/src/librustc_back/target/i686_unknown_linux_gnu.rs @@ -16,6 +16,7 @@ pub fn target() -> TargetResult { base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); + base.stack_probes = true; Ok(Target { llvm_target: "i686-unknown-linux-gnu".to_string(), diff --git a/src/librustc_back/target/i686_unknown_linux_musl.rs b/src/librustc_back/target/i686_unknown_linux_musl.rs index 3ed8c94d0b..00567d70fd 100644 --- a/src/librustc_back/target/i686_unknown_linux_musl.rs +++ b/src/librustc_back/target/i686_unknown_linux_musl.rs @@ -17,6 +17,7 @@ pub fn target() -> TargetResult { base.max_atomic_width = Some(64); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,-melf_i386".to_string()); + base.stack_probes = true; // The unwinder used by i686-unknown-linux-musl, the LLVM libunwind // implementation, apparently relies on frame pointers existing... somehow. diff --git a/src/librustc_back/target/i686_unknown_netbsd.rs b/src/librustc_back/target/i686_unknown_netbsd.rs index fc92e5aee6..7a9de52956 100644 --- a/src/librustc_back/target/i686_unknown_netbsd.rs +++ b/src/librustc_back/target/i686_unknown_netbsd.rs @@ -16,6 +16,7 @@ pub fn target() -> TargetResult { base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); + base.stack_probes = true; Ok(Target { llvm_target: "i686-unknown-netbsdelf".to_string(), diff --git a/src/librustc_back/target/i686_unknown_openbsd.rs b/src/librustc_back/target/i686_unknown_openbsd.rs index 7ef68bd6d9..b19bdbe049 100644 --- a/src/librustc_back/target/i686_unknown_openbsd.rs +++ b/src/librustc_back/target/i686_unknown_openbsd.rs @@ -16,6 +16,7 @@ pub fn target() -> TargetResult { base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); + base.stack_probes = true; Ok(Target { llvm_target: "i686-unknown-openbsd".to_string(), diff --git a/src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs b/src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs index 038a70ed6b..2d77902046 100644 --- a/src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs +++ b/src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs @@ -29,7 +29,7 @@ pub fn target() -> TargetResult { max_atomic_width: Some(64), // see #36994 - exe_allocation_crate: "alloc_system".to_string(), + exe_allocation_crate: None, ..super::linux_base::opts() }, diff --git a/src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs b/src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs index aed4c4fbb0..c26780b9e6 100644 --- a/src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs +++ b/src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs @@ -29,7 +29,7 @@ pub fn target() -> TargetResult { max_atomic_width: Some(64), // see #36994 - exe_allocation_crate: "alloc_system".to_string(), + exe_allocation_crate: None, ..super::linux_base::opts() }, diff --git a/src/librustc_back/target/mips_unknown_linux_gnu.rs b/src/librustc_back/target/mips_unknown_linux_gnu.rs index 9ef61f9cad..24649851d7 100644 --- a/src/librustc_back/target/mips_unknown_linux_gnu.rs +++ b/src/librustc_back/target/mips_unknown_linux_gnu.rs @@ -28,7 +28,7 @@ pub fn target() -> TargetResult { max_atomic_width: Some(32), // see #36994 - exe_allocation_crate: "alloc_system".to_string(), + exe_allocation_crate: None, ..super::linux_base::opts() }, diff --git a/src/librustc_back/target/mips_unknown_linux_musl.rs b/src/librustc_back/target/mips_unknown_linux_musl.rs index f54790bab9..6303722945 100644 --- a/src/librustc_back/target/mips_unknown_linux_musl.rs +++ b/src/librustc_back/target/mips_unknown_linux_musl.rs @@ -28,7 +28,7 @@ pub fn target() -> TargetResult { max_atomic_width: Some(32), // see #36994 - exe_allocation_crate: "alloc_system".to_string(), + exe_allocation_crate: None, ..super::linux_base::opts() } diff --git a/src/librustc_back/target/mips_unknown_linux_uclibc.rs b/src/librustc_back/target/mips_unknown_linux_uclibc.rs index 59c07efe0f..1a7a56a977 100644 --- a/src/librustc_back/target/mips_unknown_linux_uclibc.rs +++ b/src/librustc_back/target/mips_unknown_linux_uclibc.rs @@ -28,7 +28,7 @@ pub fn target() -> TargetResult { max_atomic_width: Some(32), // see #36994 - exe_allocation_crate: "alloc_system".to_string(), + exe_allocation_crate: None, ..super::linux_base::opts() }, diff --git a/src/librustc_back/target/mipsel_unknown_linux_gnu.rs b/src/librustc_back/target/mipsel_unknown_linux_gnu.rs index ec19cc1a53..cbf8339993 100644 --- a/src/librustc_back/target/mipsel_unknown_linux_gnu.rs +++ b/src/librustc_back/target/mipsel_unknown_linux_gnu.rs @@ -29,7 +29,7 @@ pub fn target() -> TargetResult { max_atomic_width: Some(32), // see #36994 - exe_allocation_crate: "alloc_system".to_string(), + exe_allocation_crate: None, ..super::linux_base::opts() }, diff --git a/src/librustc_back/target/mipsel_unknown_linux_musl.rs b/src/librustc_back/target/mipsel_unknown_linux_musl.rs index 00085d18e6..b367bce75a 100644 --- a/src/librustc_back/target/mipsel_unknown_linux_musl.rs +++ b/src/librustc_back/target/mipsel_unknown_linux_musl.rs @@ -28,7 +28,7 @@ pub fn target() -> TargetResult { max_atomic_width: Some(32), // see #36994 - exe_allocation_crate: "alloc_system".to_string(), + exe_allocation_crate: None, ..super::linux_base::opts() } diff --git a/src/librustc_back/target/mipsel_unknown_linux_uclibc.rs b/src/librustc_back/target/mipsel_unknown_linux_uclibc.rs index b3ca2edec1..686dfbe987 100644 --- a/src/librustc_back/target/mipsel_unknown_linux_uclibc.rs +++ b/src/librustc_back/target/mipsel_unknown_linux_uclibc.rs @@ -29,7 +29,7 @@ pub fn target() -> TargetResult { max_atomic_width: Some(32), // see #36994 - exe_allocation_crate: "alloc_system".to_string(), + exe_allocation_crate: None, ..super::linux_base::opts() }, diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index e60fdc386c..edbbcf6f0b 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -214,11 +214,14 @@ supported_targets! { ("le32-unknown-nacl", le32_unknown_nacl), ("asmjs-unknown-emscripten", asmjs_unknown_emscripten), ("wasm32-unknown-emscripten", wasm32_unknown_emscripten), + ("wasm32-experimental-emscripten", wasm32_experimental_emscripten), ("thumbv6m-none-eabi", thumbv6m_none_eabi), ("thumbv7m-none-eabi", thumbv7m_none_eabi), ("thumbv7em-none-eabi", thumbv7em_none_eabi), ("thumbv7em-none-eabihf", thumbv7em_none_eabihf), + + ("msp430-none-elf", msp430_none_elf), } /// Everything `rustc` knows about how to compile for a specific target. @@ -281,6 +284,9 @@ pub struct TargetOptions { /// user-defined libraries. pub post_link_args: LinkArgs, + /// Environment variables to be set before invoking the linker. + pub link_env: Vec<(String, String)>, + /// Extra arguments to pass to the external assembler (when used) pub asm_args: Vec, @@ -374,9 +380,8 @@ pub struct TargetOptions { /// `eh_unwind_resume` lang item. pub custom_unwind_resume: bool, - /// Default crate for allocation symbols to link against - pub lib_allocation_crate: String, - pub exe_allocation_crate: String, + /// If necessary, a different crate to link exe allocators by default + pub exe_allocation_crate: Option, /// Flag indicating whether ELF TLS (e.g. #[thread_local]) is available for /// this target. @@ -406,6 +411,9 @@ pub struct TargetOptions { /// Whether or not the CRT is statically linked by default. pub crt_static_default: bool, + + /// Whether or not stack probes (__rust_probestack) are enabled + pub stack_probes: bool, } impl Default for TargetOptions { @@ -450,10 +458,10 @@ impl Default for TargetOptions { pre_link_objects_dll: Vec::new(), post_link_objects: Vec::new(), late_link_args: LinkArgs::new(), + link_env: Vec::new(), archive_format: "gnu".to_string(), custom_unwind_resume: false, - lib_allocation_crate: "alloc_system".to_string(), - exe_allocation_crate: "alloc_system".to_string(), + exe_allocation_crate: None, allow_asm: true, has_elf_tls: false, obj_is_bitcode: false, @@ -463,6 +471,7 @@ impl Default for TargetOptions { panic_strategy: PanicStrategy::Unwind, abi_blacklist: vec![], crt_static_default: false, + stack_probes: false, } } } @@ -619,6 +628,21 @@ impl Target { base.options.$key_name = args; } } ); + ($key_name:ident, env) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(a) = obj.find(&name[..]).and_then(|o| o.as_array()) { + for o in a { + if let Some(s) = o.as_string() { + let p = s.split('=').collect::>(); + if p.len() == 2 { + let k = p[0].to_string(); + let v = p[1].to_string(); + base.options.$key_name.push((k, v)); + } + } + } + } + } ); } key!(is_builtin, bool); @@ -630,6 +654,7 @@ impl Target { key!(late_link_args, link_args); key!(post_link_objects, list); key!(post_link_args, link_args); + key!(link_env, env); key!(asm_args, list); key!(cpu); key!(features); @@ -661,8 +686,7 @@ impl Target { key!(archive_format); key!(allow_asm, bool); key!(custom_unwind_resume, bool); - key!(lib_allocation_crate); - key!(exe_allocation_crate); + key!(exe_allocation_crate, optional); key!(has_elf_tls, bool); key!(obj_is_bitcode, bool); key!(no_integrated_as, bool); @@ -670,6 +694,7 @@ impl Target { key!(min_atomic_width, Option); try!(key!(panic_strategy, PanicStrategy)); key!(crt_static_default, bool); + key!(stack_probes, bool); if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) { for name in array.iter().filter_map(|abi| abi.as_string()) { @@ -784,6 +809,17 @@ impl ToJson for Target { d.insert(name.to_string(), obj.to_json()); } } ); + (env - $attr:ident) => ( { + let name = (stringify!($attr)).replace("_", "-"); + if default.$attr != self.options.$attr { + let obj = self.options.$attr + .iter() + .map(|&(ref k, ref v)| k.clone() + "=" + &v) + .collect::>(); + d.insert(name.to_string(), obj.to_json()); + } + } ); + } target_val!(llvm_target); @@ -805,6 +841,7 @@ impl ToJson for Target { target_option_val!(link_args - late_link_args); target_option_val!(post_link_objects); target_option_val!(link_args - post_link_args); + target_option_val!(env - link_env); target_option_val!(asm_args); target_option_val!(cpu); target_option_val!(features); @@ -836,7 +873,6 @@ impl ToJson for Target { target_option_val!(archive_format); target_option_val!(allow_asm); target_option_val!(custom_unwind_resume); - target_option_val!(lib_allocation_crate); target_option_val!(exe_allocation_crate); target_option_val!(has_elf_tls); target_option_val!(obj_is_bitcode); @@ -845,6 +881,7 @@ impl ToJson for Target { target_option_val!(max_atomic_width); target_option_val!(panic_strategy); target_option_val!(crt_static_default); + target_option_val!(stack_probes); if default.abi_blacklist != self.options.abi_blacklist { d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter() @@ -856,10 +893,10 @@ impl ToJson for Target { } } -fn maybe_jemalloc() -> String { +fn maybe_jemalloc() -> Option { if cfg!(feature = "jemalloc") { - "alloc_jemalloc".to_string() + Some("alloc_jemalloc".to_string()) } else { - "alloc_system".to_string() + None } } diff --git a/src/librustc_back/target/msp430_none_elf.rs b/src/librustc_back/target/msp430_none_elf.rs new file mode 100644 index 0000000000..588a8bde79 --- /dev/null +++ b/src/librustc_back/target/msp430_none_elf.rs @@ -0,0 +1,53 @@ +// 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 {LinkerFlavor, PanicStrategy}; +use target::{Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + Ok(Target { + llvm_target: "msp430-none-elf".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "16".to_string(), + data_layout: "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16".to_string(), + arch: "msp430".to_string(), + target_os: "none".to_string(), + target_env: "".to_string(), + target_vendor: "".to_string(), + linker_flavor: LinkerFlavor::Gcc, + + options: TargetOptions { + executables: true, + + // The LLVM backend currently can't generate object files. To + // workaround this LLVM generates assembly files which then we feed + // to gcc to get object files. For this reason we have a hard + // dependency on this specific gcc. + asm_args: vec!["-mcpu=msp430".to_string()], + linker: "msp430-elf-gcc".to_string(), + no_integrated_as: true, + + // There are no atomic instructions available in the MSP430 + // instruction set + max_atomic_width: Some(0), + + // Because these devices have very little resources having an + // unwinder is too onerous so we default to "abort" because the + // "unwind" strategy is very rare. + panic_strategy: PanicStrategy::Abort, + + // Similarly, one almost always never wants to use relocatable + // code because of the extra costs it involves. + relocation_model: "static".to_string(), + + .. Default::default( ) + } + }) +} diff --git a/src/librustc_back/target/openbsd_base.rs b/src/librustc_back/target/openbsd_base.rs index 2df9b8e03f..051028d5c4 100644 --- a/src/librustc_back/target/openbsd_base.rs +++ b/src/librustc_back/target/openbsd_base.rs @@ -34,7 +34,6 @@ pub fn opts() -> TargetOptions { is_like_openbsd: true, pre_link_args: args, position_independent_executables: true, - exe_allocation_crate: "alloc_system".to_string(), .. Default::default() } } diff --git a/src/librustc_back/target/powerpc64_unknown_linux_gnu.rs b/src/librustc_back/target/powerpc64_unknown_linux_gnu.rs index 55a5bfd1e6..718a79a685 100644 --- a/src/librustc_back/target/powerpc64_unknown_linux_gnu.rs +++ b/src/librustc_back/target/powerpc64_unknown_linux_gnu.rs @@ -18,7 +18,7 @@ pub fn target() -> TargetResult { base.max_atomic_width = Some(64); // see #36994 - base.exe_allocation_crate = "alloc_system".to_string(); + base.exe_allocation_crate = None; Ok(Target { llvm_target: "powerpc64-unknown-linux-gnu".to_string(), diff --git a/src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs b/src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs index c22bc3b041..5b50b96837 100644 --- a/src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs +++ b/src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs @@ -18,7 +18,7 @@ pub fn target() -> TargetResult { base.max_atomic_width = Some(64); // see #36994 - base.exe_allocation_crate = "alloc_system".to_string(); + base.exe_allocation_crate = None; Ok(Target { llvm_target: "powerpc64le-unknown-linux-gnu".to_string(), diff --git a/src/librustc_back/target/powerpc_unknown_linux_gnu.rs b/src/librustc_back/target/powerpc_unknown_linux_gnu.rs index 677d198b1a..8d4ad5f0b4 100644 --- a/src/librustc_back/target/powerpc_unknown_linux_gnu.rs +++ b/src/librustc_back/target/powerpc_unknown_linux_gnu.rs @@ -17,7 +17,7 @@ pub fn target() -> TargetResult { base.max_atomic_width = Some(32); // see #36994 - base.exe_allocation_crate = "alloc_system".to_string(); + base.exe_allocation_crate = None; Ok(Target { llvm_target: "powerpc-unknown-linux-gnu".to_string(), diff --git a/src/librustc_back/target/redox_base.rs b/src/librustc_back/target/redox_base.rs index f26a86d4bd..2eae0a1240 100644 --- a/src/librustc_back/target/redox_base.rs +++ b/src/librustc_back/target/redox_base.rs @@ -36,8 +36,6 @@ pub fn opts() -> TargetOptions { 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 cc8eb7c4e8..78a6bb7933 100644 --- a/src/librustc_back/target/s390x_unknown_linux_gnu.rs +++ b/src/librustc_back/target/s390x_unknown_linux_gnu.rs @@ -21,7 +21,7 @@ pub fn target() -> TargetResult { base.features = "-vector".to_string(); base.max_atomic_width = Some(64); // see #36994 - base.exe_allocation_crate = "alloc_system".to_string(); + base.exe_allocation_crate = None; Ok(Target { llvm_target: "s390x-unknown-linux-gnu".to_string(), diff --git a/src/librustc_back/target/sparc64_unknown_linux_gnu.rs b/src/librustc_back/target/sparc64_unknown_linux_gnu.rs index 1bd51ac625..7f710ad402 100644 --- a/src/librustc_back/target/sparc64_unknown_linux_gnu.rs +++ b/src/librustc_back/target/sparc64_unknown_linux_gnu.rs @@ -15,7 +15,7 @@ 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(); + base.exe_allocation_crate = None; Ok(Target { llvm_target: "sparc64-unknown-linux-gnu".to_string(), diff --git a/src/librustc_back/target/wasm32_experimental_emscripten.rs b/src/librustc_back/target/wasm32_experimental_emscripten.rs new file mode 100644 index 0000000000..053fab5425 --- /dev/null +++ b/src/librustc_back/target/wasm32_experimental_emscripten.rs @@ -0,0 +1,54 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use LinkerFlavor; +use super::{LinkArgs, Target, TargetOptions}; +use super::emscripten_base::{cmd}; + +pub fn target() -> Result { + let mut post_link_args = LinkArgs::new(); + post_link_args.insert(LinkerFlavor::Em, + vec!["-s".to_string(), + "WASM=1".to_string(), + "-s".to_string(), + "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()]); + + let opts = TargetOptions { + linker: cmd("emcc"), + ar: cmd("emar"), + + dynamic_linking: false, + executables: true, + // Today emcc emits two files - a .js file to bootstrap and + // possibly interpret the wasm, and a .wasm file + exe_suffix: ".js".to_string(), + linker_is_gnu: true, + link_env: vec![("EMCC_WASM_BACKEND".to_string(), "1".to_string())], + allow_asm: false, + obj_is_bitcode: true, + is_like_emscripten: true, + max_atomic_width: Some(32), + post_link_args: post_link_args, + target_family: Some("unix".to_string()), + .. Default::default() + }; + Ok(Target { + llvm_target: "wasm32-unknown-unknown".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_os: "emscripten".to_string(), + target_env: "".to_string(), + target_vendor: "unknown".to_string(), + data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(), + arch: "wasm32".to_string(), + linker_flavor: LinkerFlavor::Em, + options: opts, + }) +} diff --git a/src/librustc_back/target/windows_msvc_base.rs b/src/librustc_back/target/windows_msvc_base.rs index 421f59aea9..c07321e418 100644 --- a/src/librustc_back/target/windows_msvc_base.rs +++ b/src/librustc_back/target/windows_msvc_base.rs @@ -63,7 +63,6 @@ pub fn opts() -> TargetOptions { is_like_windows: true, is_like_msvc: true, pre_link_args: args, - exe_allocation_crate: "alloc_system".to_string(), .. Default::default() } diff --git a/src/librustc_back/target/x86_64_apple_darwin.rs b/src/librustc_back/target/x86_64_apple_darwin.rs index 8fd1b80430..8ac7667900 100644 --- a/src/librustc_back/target/x86_64_apple_darwin.rs +++ b/src/librustc_back/target/x86_64_apple_darwin.rs @@ -17,6 +17,7 @@ pub fn target() -> TargetResult { base.max_atomic_width = Some(128); // core2 support cmpxchg16b base.eliminate_frame_pointer = false; base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]); + base.stack_probes = true; Ok(Target { llvm_target: "x86_64-apple-darwin".to_string(), diff --git a/src/librustc_back/target/x86_64_apple_ios.rs b/src/librustc_back/target/x86_64_apple_ios.rs index bbd81fd86f..61a71da216 100644 --- a/src/librustc_back/target/x86_64_apple_ios.rs +++ b/src/librustc_back/target/x86_64_apple_ios.rs @@ -26,6 +26,7 @@ pub fn target() -> TargetResult { linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { max_atomic_width: Some(64), + stack_probes: true, .. base } }) diff --git a/src/librustc_back/target/x86_64_linux_android.rs b/src/librustc_back/target/x86_64_linux_android.rs index 75cf3e1243..158e2b1360 100644 --- a/src/librustc_back/target/x86_64_linux_android.rs +++ b/src/librustc_back/target/x86_64_linux_android.rs @@ -18,6 +18,7 @@ pub fn target() -> TargetResult { base.features = "+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.stack_probes = true; Ok(Target { llvm_target: "x86_64-linux-android".to_string(), diff --git a/src/librustc_back/target/x86_64_pc_windows_msvc.rs b/src/librustc_back/target/x86_64_pc_windows_msvc.rs index b07031c4bf..7eb673d8b3 100644 --- a/src/librustc_back/target/x86_64_pc_windows_msvc.rs +++ b/src/librustc_back/target/x86_64_pc_windows_msvc.rs @@ -15,6 +15,7 @@ pub fn target() -> TargetResult { let mut base = super::windows_msvc_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); + base.has_elf_tls = true; Ok(Target { llvm_target: "x86_64-pc-windows-msvc".to_string(), diff --git a/src/librustc_back/target/x86_64_rumprun_netbsd.rs b/src/librustc_back/target/x86_64_rumprun_netbsd.rs index eea4389cfd..c7e5edde63 100644 --- a/src/librustc_back/target/x86_64_rumprun_netbsd.rs +++ b/src/librustc_back/target/x86_64_rumprun_netbsd.rs @@ -24,7 +24,8 @@ pub fn target() -> TargetResult { base.position_independent_executables = false; base.disable_redzone = true; base.no_default_libraries = false; - base.exe_allocation_crate = "alloc_system".to_string(); + base.exe_allocation_crate = None; + base.stack_probes = true; Ok(Target { llvm_target: "x86_64-rumprun-netbsd".to_string(), diff --git a/src/librustc_back/target/x86_64_sun_solaris.rs b/src/librustc_back/target/x86_64_sun_solaris.rs index fe8691f369..38a38ed68b 100644 --- a/src/librustc_back/target/x86_64_sun_solaris.rs +++ b/src/librustc_back/target/x86_64_sun_solaris.rs @@ -16,6 +16,7 @@ pub fn target() -> TargetResult { base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); + base.stack_probes = true; Ok(Target { llvm_target: "x86_64-pc-solaris".to_string(), diff --git a/src/librustc_back/target/x86_64_unknown_bitrig.rs b/src/librustc_back/target/x86_64_unknown_bitrig.rs index 5f87fe177a..cf4b019dce 100644 --- a/src/librustc_back/target/x86_64_unknown_bitrig.rs +++ b/src/librustc_back/target/x86_64_unknown_bitrig.rs @@ -16,6 +16,7 @@ pub fn target() -> TargetResult { base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]); + base.stack_probes = true; Ok(Target { llvm_target: "x86_64-unknown-bitrig".to_string(), diff --git a/src/librustc_back/target/x86_64_unknown_dragonfly.rs b/src/librustc_back/target/x86_64_unknown_dragonfly.rs index 96f608409f..8885d89c6f 100644 --- a/src/librustc_back/target/x86_64_unknown_dragonfly.rs +++ b/src/librustc_back/target/x86_64_unknown_dragonfly.rs @@ -16,6 +16,7 @@ pub fn target() -> TargetResult { base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.stack_probes = true; Ok(Target { llvm_target: "x86_64-unknown-dragonfly".to_string(), diff --git a/src/librustc_back/target/x86_64_unknown_freebsd.rs b/src/librustc_back/target/x86_64_unknown_freebsd.rs index 500629a168..95870f2be5 100644 --- a/src/librustc_back/target/x86_64_unknown_freebsd.rs +++ b/src/librustc_back/target/x86_64_unknown_freebsd.rs @@ -16,6 +16,7 @@ pub fn target() -> TargetResult { base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.stack_probes = true; Ok(Target { llvm_target: "x86_64-unknown-freebsd".to_string(), diff --git a/src/librustc_back/target/x86_64_unknown_fuchsia.rs b/src/librustc_back/target/x86_64_unknown_fuchsia.rs index 6e37896d41..1aebb88559 100644 --- a/src/librustc_back/target/x86_64_unknown_fuchsia.rs +++ b/src/librustc_back/target/x86_64_unknown_fuchsia.rs @@ -16,6 +16,7 @@ pub fn target() -> TargetResult { base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.stack_probes = true; Ok(Target { llvm_target: "x86_64-unknown-fuchsia".to_string(), diff --git a/src/librustc_back/target/x86_64_unknown_haiku.rs b/src/librustc_back/target/x86_64_unknown_haiku.rs index 7fab9128b2..3794a516ec 100644 --- a/src/librustc_back/target/x86_64_unknown_haiku.rs +++ b/src/librustc_back/target/x86_64_unknown_haiku.rs @@ -16,6 +16,7 @@ pub fn target() -> TargetResult { base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]); + base.stack_probes = true; Ok(Target { llvm_target: "x86_64-unknown-haiku".to_string(), diff --git a/src/librustc_back/target/x86_64_unknown_linux_gnu.rs b/src/librustc_back/target/x86_64_unknown_linux_gnu.rs index f73055ceba..d2135f8a0b 100644 --- a/src/librustc_back/target/x86_64_unknown_linux_gnu.rs +++ b/src/librustc_back/target/x86_64_unknown_linux_gnu.rs @@ -16,6 +16,7 @@ pub fn target() -> TargetResult { base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.stack_probes = true; Ok(Target { llvm_target: "x86_64-unknown-linux-gnu".to_string(), diff --git a/src/librustc_back/target/x86_64_unknown_linux_musl.rs b/src/librustc_back/target/x86_64_unknown_linux_musl.rs index 38b9c0bace..7d542b4d3c 100644 --- a/src/librustc_back/target/x86_64_unknown_linux_musl.rs +++ b/src/librustc_back/target/x86_64_unknown_linux_musl.rs @@ -16,6 +16,7 @@ pub fn target() -> TargetResult { base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.stack_probes = true; Ok(Target { llvm_target: "x86_64-unknown-linux-musl".to_string(), diff --git a/src/librustc_back/target/x86_64_unknown_netbsd.rs b/src/librustc_back/target/x86_64_unknown_netbsd.rs index 6fe2e3fc08..5d49fcbd64 100644 --- a/src/librustc_back/target/x86_64_unknown_netbsd.rs +++ b/src/librustc_back/target/x86_64_unknown_netbsd.rs @@ -16,6 +16,7 @@ pub fn target() -> TargetResult { base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.stack_probes = true; Ok(Target { llvm_target: "x86_64-unknown-netbsd".to_string(), diff --git a/src/librustc_back/target/x86_64_unknown_openbsd.rs b/src/librustc_back/target/x86_64_unknown_openbsd.rs index b292b5fc1e..aa289fb577 100644 --- a/src/librustc_back/target/x86_64_unknown_openbsd.rs +++ b/src/librustc_back/target/x86_64_unknown_openbsd.rs @@ -16,6 +16,7 @@ pub fn target() -> TargetResult { base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.stack_probes = true; Ok(Target { llvm_target: "x86_64-unknown-openbsd".to_string(), diff --git a/src/librustc_back/target/x86_64_unknown_redox.rs b/src/librustc_back/target/x86_64_unknown_redox.rs index a693e76099..8d2a7afeea 100644 --- a/src/librustc_back/target/x86_64_unknown_redox.rs +++ b/src/librustc_back/target/x86_64_unknown_redox.rs @@ -16,6 +16,7 @@ pub fn target() -> TargetResult { base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.stack_probes = true; Ok(Target { llvm_target: "x86_64-unknown-redox".to_string(), diff --git a/src/librustc_bitflags/lib.rs b/src/librustc_bitflags/lib.rs index 23558d8288..83660714af 100644 --- a/src/librustc_bitflags/lib.rs +++ b/src/librustc_bitflags/lib.rs @@ -10,12 +10,11 @@ #![crate_name = "rustc_bitflags"] -#![feature(associated_consts)] #![crate_type = "rlib"] #![no_std] #![deny(warnings)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(staged_api))] + +#![cfg_attr(stage0, feature(associated_consts))] //! A typesafe bitmask flag generator. @@ -33,7 +32,6 @@ extern crate std; /// /// ```{.rust} /// #![feature(rustc_private)] -/// #![feature(associated_consts)] /// #[macro_use] extern crate rustc_bitflags; /// /// bitflags! { diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index 122a37ee32..b84cd212c4 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -192,7 +192,6 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, debug!("check_loans(body id={})", body.value.id); let def_id = bccx.tcx.hir.body_owner_def_id(body.id()); - let infcx = bccx.tcx.borrowck_fake_infer_ctxt(body.id()); let param_env = bccx.tcx.param_env(def_id); let mut clcx = CheckLoanCtxt { bccx: bccx, @@ -201,7 +200,8 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, all_loans: all_loans, param_env, }; - euv::ExprUseVisitor::new(&mut clcx, &bccx.region_maps, &infcx, param_env).consume_body(body); + euv::ExprUseVisitor::new(&mut clcx, bccx.tcx, param_env, &bccx.region_maps, bccx.tables) + .consume_body(body); } #[derive(PartialEq)] @@ -755,15 +755,20 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { /// /// For example: /// - /// ```ignore + /// ``` /// let a: i32; /// a = 10; // ok, even though a is uninitialized + /// ``` /// + /// ``` /// struct Point { x: u32, y: u32 } - /// let p: Point; + /// let mut p: Point; /// p.x = 22; // ok, even though `p` is uninitialized + /// ``` /// - /// let p: Box; + /// ```compile_fail,E0381 + /// # struct Point { x: u32, y: u32 } + /// let mut p: Box; /// (*p).x = 22; // not ok, p is uninitialized, can't deref /// ``` fn check_if_assigned_path_is_moved(&self, diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 85a09969ac..7dcb6ce76a 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -18,7 +18,6 @@ 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; @@ -40,11 +39,9 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, body: hir::BodyId) -> (Vec>, move_data::MoveData<'tcx>) { let def_id = bccx.tcx.hir.body_owner_def_id(body); - let infcx = bccx.tcx.borrowck_fake_infer_ctxt(body); let param_env = bccx.tcx.param_env(def_id); let mut glcx = GatherLoanCtxt { bccx: bccx, - infcx: &infcx, all_loans: Vec::new(), item_ub: region::CodeExtent::Misc(body.node_id), move_data: MoveData::new(), @@ -52,7 +49,8 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, }; let body = glcx.bccx.tcx.hir.body(body); - euv::ExprUseVisitor::new(&mut glcx, &bccx.region_maps, &infcx, param_env).consume_body(body); + euv::ExprUseVisitor::new(&mut glcx, bccx.tcx, param_env, &bccx.region_maps, bccx.tables) + .consume_body(body); glcx.report_potential_errors(); let GatherLoanCtxt { all_loans, move_data, .. } = glcx; @@ -61,7 +59,6 @@ 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>, @@ -158,7 +155,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { } fn decl_without_init(&mut self, id: ast::NodeId, _span: Span) { - let ty = self.infcx.tables.borrow().node_id_to_type(id); + let ty = self.bccx.tables.node_id_to_type(id); gather_moves::gather_decl(self.bccx, &self.move_data, id, ty); } } diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index c72bdd0401..1bfc5805bc 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -18,8 +18,6 @@ pub use self::bckerr_code::*; pub use self::AliasableViolationKind::*; pub use self::MovedValueUseKind::*; -pub use self::mir::elaborate_drops::ElaborateDrops; - use self::InteriorKind::*; use rustc::hir::map as hir_map; @@ -55,8 +53,6 @@ pub mod gather_loans; pub mod move_data; -mod mir; - #[derive(Clone, Copy)] pub struct LoanDataFlowOperator; @@ -100,26 +96,21 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) { } let body_id = tcx.hir.body_owned_by(owner_id); - let attributes = tcx.get_attrs(owner_def_id); let tables = tcx.typeck_tables_of(owner_def_id); let region_maps = tcx.region_maps(owner_def_id); let mut bccx = &mut BorrowckCtxt { tcx, tables, region_maps, owner_def_id }; let body = bccx.tcx.hir.body(body_id); - if bccx.tcx.has_attr(owner_def_id, "rustc_mir_borrowck") { - mir::borrowck_mir(bccx, owner_id, &attributes); - } else { - // Eventually, borrowck will always read the MIR, but at the - // moment we do not. So, for now, we always force MIR to be - // constructed for a given fn, since this may result in errors - // being reported and we want that to happen. - // - // Note that `mir_validated` is a "stealable" result; the - // thief, `optimized_mir()`, forces borrowck, so we know that - // is not yet stolen. - tcx.mir_validated(owner_def_id).borrow(); - } + // Eventually, borrowck will always read the MIR, but at the + // moment we do not. So, for now, we always force MIR to be + // constructed for a given fn, since this may result in errors + // being reported and we want that to happen. + // + // Note that `mir_validated` is a "stealable" result; the + // thief, `optimized_mir()`, forces borrowck, so we know that + // is not yet stolen. + tcx.mir_validated(owner_def_id).borrow(); let cfg = cfg::CFG::new(bccx.tcx, &body); let AnalysisData { all_loans, @@ -1000,7 +991,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { .span_suggestion(err.span, &format!("to force the closure to take ownership of {} \ (and any other referenced variables), \ - use the `move` keyword, as shown:", + use the `move` keyword", cmt_path_or_string), suggestion) .emit(); diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs index 2a38dcfd26..38dcc73123 100644 --- a/src/librustc_borrowck/diagnostics.rs +++ b/src/librustc_borrowck/diagnostics.rs @@ -144,7 +144,7 @@ that at most one writer or multiple readers can access the data at any one time. If you wish to learn more about ownership in Rust, start with the chapter in the Book: -https://doc.rust-lang.org/book/ownership.html +https://doc.rust-lang.org/book/first-edition/ownership.html "##, E0383: r##" @@ -153,10 +153,13 @@ structure that is currently uninitialized. For example, this can happen when a drop has taken place: -```ignore +```compile_fail,E0383 struct Foo { a: u32, } +impl Drop for Foo { + fn drop(&mut self) { /* ... */ } +} let mut x = Foo { a: 1 }; drop(x); // `x` is now uninitialized @@ -169,6 +172,9 @@ This error can be fixed by fully reinitializing the structure in question: struct Foo { a: u32, } +impl Drop for Foo { + fn drop(&mut self) { /* ... */ } +} let mut x = Foo { a: 1 }; drop(x); @@ -366,8 +372,8 @@ let mut a = &mut i; Please note that in rust, you can either have many immutable references, or one mutable reference. Take a look at -https://doc.rust-lang.org/stable/book/references-and-borrowing.html for more -information. Example: +https://doc.rust-lang.org/book/first-edition/references-and-borrowing.html +for more information. Example: ``` @@ -533,7 +539,7 @@ fn foo(a: &mut i32) { ``` For more information on the rust ownership system, take a look at -https://doc.rust-lang.org/stable/book/references-and-borrowing.html. +https://doc.rust-lang.org/book/first-edition/references-and-borrowing.html. "##, E0503: r##" @@ -589,7 +595,7 @@ fn main() { ``` You can find more information about borrowing in the rust-book: -http://doc.rust-lang.org/stable/book/references-and-borrowing.html +http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html "##, E0504: r##" @@ -773,7 +779,7 @@ fn main() { ``` You can find more information about borrowing in the rust-book: -http://doc.rust-lang.org/stable/book/references-and-borrowing.html +http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html "##, E0506: r##" @@ -944,10 +950,9 @@ fn main() { } ``` -Moving out of a member of a mutably borrowed struct is fine if you put something -back. `mem::replace` can be used for that: +Moving a member out of a mutably borrowed struct will also cause E0507 error: -```ignore +```compile_fail,E0507 struct TheDarkKnight; impl TheDarkKnight { @@ -959,20 +964,33 @@ struct Batcave { } fn main() { - use std::mem; - let mut cave = Batcave { knight: TheDarkKnight }; let borrowed = &mut cave; borrowed.knight.nothing_is_true(); // E0507 - mem::replace(&mut borrowed.knight, TheDarkKnight).nothing_is_true(); // ok! } ``` +It is fine only if you put something back. `mem::replace` can be used for that: + +``` +# struct TheDarkKnight; +# impl TheDarkKnight { fn nothing_is_true(self) {} } +# struct Batcave { knight: TheDarkKnight } +use std::mem; + +let mut cave = Batcave { + knight: TheDarkKnight +}; +let borrowed = &mut cave; + +mem::replace(&mut borrowed.knight, TheDarkKnight).nothing_is_true(); // ok! +``` + You can find more information about borrowing in the rust-book: -http://doc.rust-lang.org/stable/book/references-and-borrowing.html +http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html "##, E0508: r##" diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs index 6173268089..723df56441 100644 --- a/src/librustc_borrowck/lib.rs +++ b/src/librustc_borrowck/lib.rs @@ -20,12 +20,8 @@ #![feature(quote)] #![feature(rustc_diagnostic_macros)] -#![feature(associated_consts)] -#![feature(nonzero)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] +#![cfg_attr(stage0, feature(associated_consts))] #[macro_use] extern crate log; #[macro_use] extern crate syntax; @@ -43,7 +39,7 @@ extern crate core; // for NonZero pub use borrowck::check_crate; pub use borrowck::build_borrowck_dataflow_data_for_fn; -pub use borrowck::{AnalysisData, BorrowckCtxt, ElaborateDrops}; +pub use borrowck::{AnalysisData, BorrowckCtxt}; // NB: This module needs to be declared first so diagnostics are // registered before they are used. diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs index c1dc5f5f7a..bae44c0047 100644 --- a/src/librustc_const_eval/_match.rs +++ b/src/librustc_const_eval/_match.rs @@ -774,21 +774,26 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>, }, 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() + if adt.is_box() { + // Use T as the sub pattern type of Box. + vec![substs[0].as_type().unwrap()] + } else { + 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![], } @@ -830,7 +835,7 @@ fn slice_pat_covered_by_constructor(_tcx: TyCtxt, _span: Span, Ok(true) } -fn range_covered_by_constructor(tcx: TyCtxt, span: Span, +fn constructor_covered_by_range(tcx: TyCtxt, span: Span, ctor: &Constructor, from: &ConstVal, to: &ConstVal, end: RangeEnd) @@ -840,14 +845,14 @@ fn range_covered_by_constructor(tcx: TyCtxt, span: Span, match *ctor { ConstantValue(ref value) => { let to = cmp_to(value)?; - let end = (to != Ordering::Greater) || - (end == RangeEnd::Excluded && to == Ordering::Equal); + let end = (to == Ordering::Less) || + (end == RangeEnd::Included && 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); + let end = (to == Ordering::Less) || + (end == RangeEnd::Included && to == Ordering::Equal); Ok(cmp_from(from)? && end) }, ConstantRange(ref from, ref to, RangeEnd::Excluded) => { @@ -928,7 +933,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( "unexpected const-val {:?} with ctor {:?}", value, constructor) }, _ => { - match range_covered_by_constructor( + match constructor_covered_by_range( cx.tcx, pat.span, constructor, value, value, RangeEnd::Included ) { Ok(true) => Some(vec![]), @@ -940,7 +945,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( } PatternKind::Range { ref lo, ref hi, ref end } => { - match range_covered_by_constructor( + match constructor_covered_by_range( cx.tcx, pat.span, constructor, lo, hi, end.clone() ) { Ok(true) => Some(vec![]), diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 7c3076fda4..fcdabf89e3 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -493,19 +493,18 @@ 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(cx.tables).enter(|infcx| { - let mut checker = MutationChecker { - cx: cx, - }; - ExprUseVisitor::new(&mut checker, cx.region_maps, &infcx, cx.param_env).walk_expr(guard); - }); + let mut checker = MutationChecker { + cx: cx, + }; + ExprUseVisitor::new(&mut checker, cx.tcx, cx.param_env, cx.region_maps, cx.tables) + .walk_expr(guard); } -struct MutationChecker<'a, 'gcx: 'a> { - cx: &'a MatchVisitor<'a, 'gcx>, +struct MutationChecker<'a, 'tcx: 'a> { + cx: &'a MatchVisitor<'a, 'tcx>, } -impl<'a, 'gcx, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'gcx> { +impl<'a, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'tcx> { fn matched_pat(&mut self, _: &Pat, _: cmt, _: euv::MatchMode) {} fn consume(&mut self, _: ast::NodeId, _: Span, _: cmt, _: ConsumeMode) {} fn consume_pat(&mut self, _: &Pat, _: cmt, _: ConsumeMode) {} diff --git a/src/librustc_const_eval/diagnostics.rs b/src/librustc_const_eval/diagnostics.rs index 4fc7ef8035..56d08184a0 100644 --- a/src/librustc_const_eval/diagnostics.rs +++ b/src/librustc_const_eval/diagnostics.rs @@ -436,17 +436,19 @@ that happens. Qualified names are good practice, and most code works well with them. But if you prefer them unqualified, you can import the variants into scope: -```ignore +``` use Method::*; enum Method { GET, POST } +# fn main() {} ``` If you want others to be able to import variants from your module directly, use `pub use`: -```ignore +``` pub use Method::*; -enum Method { GET, POST } +pub enum Method { GET, POST } +# fn main() {} ``` "##, diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 3d07ffc2bc..4ce985568c 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -351,7 +351,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, signal!(e, TypeckError) } } else { - if tcx.sess.cstore.is_const_fn(def_id) { + if tcx.is_const_fn(def_id) { tcx.sess.cstore.item_body(tcx, def_id) } else { signal!(e, TypeckError) @@ -483,7 +483,7 @@ fn resolve_trait_associated_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("resolve_trait_associated_const: trait_ref={:?}", trait_ref); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let param_env = ty::ParamEnv::empty(Reveal::UserFacing); let mut selcx = traits::SelectionContext::new(&infcx); let obligation = traits::Obligation::new(traits::ObligationCause::dummy(), diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_eval/lib.rs index 8142829e81..5a61f35ed1 100644 --- a/src/librustc_const_eval/lib.rs +++ b/src/librustc_const_eval/lib.rs @@ -29,10 +29,6 @@ #![feature(const_fn)] #![feature(i128_type)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] - extern crate arena; #[macro_use] extern crate syntax; #[macro_use] extern crate log; diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index d175920e8a..0a966b0c17 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -12,7 +12,7 @@ use eval; use rustc::middle::const_val::{ConstEvalErr, ConstVal}; use rustc::mir::{Field, BorrowKind, Mutability}; -use rustc::ty::{self, TyCtxt, AdtDef, Ty, TypeVariants, Region}; +use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region}; use rustc::ty::subst::{Substs, Kind}; use rustc::hir::{self, PatKind, RangeEnd}; use rustc::hir::def::{Def, CtorKind}; @@ -549,8 +549,8 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { let adt_def = self.tcx.adt_def(enum_id); if adt_def.variants.len() > 1 { let substs = match ty.sty { - TypeVariants::TyAdt(_, substs) => substs, - TypeVariants::TyFnDef(_, substs, _) => substs, + ty::TyAdt(_, substs) | + ty::TyFnDef(_, substs) => substs, _ => bug!("inappropriate type for def: {:?}", ty.sty), }; PatternKind::Variant { diff --git a/src/librustc_const_math/lib.rs b/src/librustc_const_math/lib.rs index 528170781e..0dce0e1fb0 100644 --- a/src/librustc_const_math/lib.rs +++ b/src/librustc_const_math/lib.rs @@ -26,10 +26,6 @@ #![feature(i128)] #![feature(i128_type)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] - extern crate syntax; extern crate serialize as rustc_serialize; // used by deriving diff --git a/src/librustc_data_structures/fnv.rs b/src/librustc_data_structures/fnv.rs index ae90c2fac8..5bd57236e7 100644 --- a/src/librustc_data_structures/fnv.rs +++ b/src/librustc_data_structures/fnv.rs @@ -26,7 +26,7 @@ pub fn FnvHashSet() -> FnvHashSet { } /// A speedy hash algorithm for node ids and def ids. The hashmap in -/// libcollections by default uses SipHash which isn't quite as speedy as we +/// liballoc by default uses SipHash which isn't quite as speedy as we /// want. In the compiler we're not really worried about DOS attempts, so we /// just default to a non-cryptographic hash. /// diff --git a/src/librustc_data_structures/fx.rs b/src/librustc_data_structures/fx.rs index 1fb7673521..00dfc1617a 100644 --- a/src/librustc_data_structures/fx.rs +++ b/src/librustc_data_structures/fx.rs @@ -26,7 +26,7 @@ pub fn FxHashSet() -> FxHashSet { HashSet::default() } -/// A speedy hash algorithm for use within rustc. The hashmap in libcollections +/// A speedy hash algorithm for use within rustc. The hashmap in liballoc /// by default uses SipHash which isn't quite as speedy as we want. In the /// compiler we're not really worried about DOS attempts, so we use a fast /// non-cryptographic hash. diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 83cd5cef00..eb766e71bf 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -29,18 +29,14 @@ #![feature(nonzero)] #![feature(unboxed_closures)] #![feature(fn_traits)] -#![feature(associated_consts)] #![feature(unsize)] #![feature(i128_type)] #![feature(conservative_impl_trait)] #![feature(discriminant_value)] #![feature(specialization)] -#![feature(manually_drop)] -#![feature(struct_field_attributes)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] +#![cfg_attr(stage0, feature(associated_consts))] +#![cfg_attr(stage0, feature(struct_field_attributes))] #![cfg_attr(unix, feature(libc))] #![cfg_attr(test, feature(test))] diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index 635b95d861..5e291ea3c1 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -78,6 +78,17 @@ impl StableHasherResult for [u8; 20] { } } +impl StableHasherResult for u128 { + fn finish(mut hasher: StableHasher) -> Self { + let hash_bytes: &[u8] = hasher.finalize(); + assert!(hash_bytes.len() >= mem::size_of::()); + + unsafe { + ::std::ptr::read_unaligned(hash_bytes.as_ptr() as *const u128) + } + } +} + impl StableHasherResult for u64 { fn finish(mut hasher: StableHasher) -> Self { hasher.state.finalize(); @@ -244,6 +255,14 @@ impl HashStable for f64 { } } +impl, CTX> HashStable for (T1,) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { + self.0.hash_stable(ctx, hasher); + } +} + impl, T2: HashStable, CTX> HashStable for (T1, T2) { fn hash_stable(&self, ctx: &mut CTX, @@ -273,6 +292,24 @@ impl, CTX> HashStable for Vec { } } +impl, CTX> HashStable for ::std::rc::Rc { + #[inline] + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { + (**self).hash_stable(ctx, hasher); + } +} + +impl, CTX> HashStable for ::std::sync::Arc { + #[inline] + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { + (**self).hash_stable(ctx, hasher); + } +} + impl HashStable for str { #[inline] fn hash_stable(&self, diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 2e949f48c1..f1bdf0b2c3 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -13,8 +13,8 @@ arena = { path = "../libarena" } graphviz = { path = "../libgraphviz" } log = { version = "0.3", features = ["release_max_level_info"] } env_logger = { version = "0.4", default-features = false } -proc_macro_plugin = { path = "../libproc_macro_plugin" } rustc = { path = "../librustc" } +rustc_allocator = { path = "../librustc_allocator" } rustc_back = { path = "../librustc_back" } rustc_borrowck = { path = "../librustc_borrowck" } rustc_const_eval = { path = "../librustc_const_eval" } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index bca82ff9a4..daa5917cf3 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -13,7 +13,8 @@ use rustc::hir::lowering::lower_crate; use rustc::ich::Fingerprint; use rustc_data_structures::stable_hasher::StableHasher; use rustc_mir as mir; -use rustc::session::{Session, CompileResult, compile_result_from_err_count}; +use rustc::session::{Session, CompileResult}; +use rustc::session::CompileIncomplete; use rustc::session::config::{self, Input, OutputFilenames, OutputType, OutputTypes}; use rustc::session::search_paths::PathKind; @@ -23,9 +24,10 @@ use rustc::middle::privacy::AccessLevels; use rustc::mir::transform::{MIR_CONST, MIR_VALIDATED, MIR_OPTIMIZED, Passes}; use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas}; use rustc::traits; -use rustc::util::common::time; +use rustc::util::common::{ErrorReported, time}; use rustc::util::nodemap::NodeSet; use rustc::util::fs::rename_or_copy_remove; +use rustc_allocator as allocator; use rustc_borrowck as borrowck; use rustc_incremental::{self, IncrementalHashesMap}; use rustc_resolve::{MakeGlobMap, Resolver}; @@ -78,7 +80,9 @@ pub fn compile_input(sess: &Session, } if control.$point.stop == Compilation::Stop { - return compile_result_from_err_count($tsess.err_count()); + // FIXME: shouldn't this return Err(CompileIncomplete::Stopped) + // if there are no errors? + return $tsess.compile_status(); } }} } @@ -91,7 +95,7 @@ pub fn compile_input(sess: &Session, Ok(krate) => krate, Err(mut parse_error) => { parse_error.emit(); - return Err(1); + return Err(CompileIncomplete::Errored(ErrorReported)); } }; @@ -194,7 +198,7 @@ pub fn compile_input(sess: &Session, (control.after_analysis.callback)(&mut state); if control.after_analysis.stop == Compilation::Stop { - return result.and_then(|_| Err(0usize)); + return result.and_then(|_| Err(CompileIncomplete::Stopped)); } } @@ -204,7 +208,8 @@ pub fn compile_input(sess: &Session, println!("Pre-trans"); tcx.print_debug_stats(); } - let trans = phase_4_translate_to_llvm(tcx, analysis, &incremental_hashes_map); + let trans = phase_4_translate_to_llvm(tcx, analysis, &incremental_hashes_map, + &outputs); if log_enabled!(::log::LogLevel::Info) { println!("Post-trans"); @@ -563,7 +568,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, addl_plugins: Option>, make_glob_map: MakeGlobMap, after_expand: F) - -> Result + -> Result where F: FnOnce(&ast::Crate) -> CompileResult, { let time_passes = sess.time_passes(); @@ -635,7 +640,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, // Lint plugins are registered; now we can process command line flags. if sess.opts.describe_lints { super::describe_lints(&sess.lint_store.borrow(), true); - return Err(0); + return Err(CompileIncomplete::Stopped); } sess.track_errors(|| sess.lint_store.borrow_mut().process_command_line(sess))?; @@ -746,6 +751,13 @@ pub fn phase_2_configure_and_expand(sess: &Session, }); } + krate = time(time_passes, "creating allocators", || { + allocator::expand::modify(&sess.parse_sess, + &mut resolver, + krate, + sess.diagnostic()) + }); + after_expand(&krate)?; if sess.opts.debugging_opts.input_stats { @@ -838,7 +850,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, arenas: &'tcx GlobalArenas<'tcx>, name: &str, f: F) - -> Result + -> Result where F: for<'a> FnOnce(TyCtxt<'a, 'tcx, 'tcx>, ty::CrateAnalysis, IncrementalHashesMap, @@ -899,6 +911,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, reachable::provide(&mut local_providers); rustc_const_eval::provide(&mut local_providers); middle::region::provide(&mut local_providers); + cstore::provide_local(&mut local_providers); let mut extern_providers = ty::maps::Providers::default(); cstore::provide(&mut extern_providers); @@ -912,9 +925,13 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, let mut passes = Passes::new(); passes.push_hook(mir::transform::dump_mir::DumpMir); + // Remove all `EndRegion` statements that are not involved in borrows. + passes.push_pass(MIR_CONST, mir::transform::clean_end_regions::CleanEndRegions); + // What we need to do constant evaluation. passes.push_pass(MIR_CONST, mir::transform::simplify::SimplifyCfg::new("initial")); passes.push_pass(MIR_CONST, mir::transform::type_check::TypeckMir); + passes.push_pass(MIR_CONST, mir::transform::rustc_peek::SanityCheck); // What we need to run borrowck etc. passes.push_pass(MIR_VALIDATED, mir::transform::qualify_consts::QualifyAndPromoteConstants); @@ -929,7 +946,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, // From here on out, regions are gone. passes.push_pass(MIR_OPTIMIZED, mir::transform::erase_regions::EraseRegions); passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::AddCallGuards); - passes.push_pass(MIR_OPTIMIZED, borrowck::ElaborateDrops); + passes.push_pass(MIR_OPTIMIZED, mir::transform::elaborate_drops::ElaborateDrops); passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads); passes.push_pass(MIR_OPTIMIZED, mir::transform::simplify::SimplifyCfg::new("elaborate-drops")); @@ -1013,7 +1030,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, // lint warnings and so on -- kindck used to do this abort, but // kindck is gone now). -nmatsakis if sess.err_count() > 0 { - return Ok(f(tcx, analysis, incremental_hashes_map, Err(sess.err_count()))); + return Ok(f(tcx, analysis, incremental_hashes_map, sess.compile_status())); } analysis.reachable = @@ -1029,12 +1046,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, time(time_passes, "lint checking", || lint::check_crate(tcx)); - // The above three passes generate errors w/o aborting - if sess.err_count() > 0 { - return Ok(f(tcx, analysis, incremental_hashes_map, Err(sess.err_count()))); - } - - Ok(f(tcx, analysis, incremental_hashes_map, Ok(()))) + return Ok(f(tcx, analysis, incremental_hashes_map, tcx.sess.compile_status())); }) } @@ -1042,18 +1054,19 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, /// be discarded. pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, analysis: ty::CrateAnalysis, - incremental_hashes_map: &IncrementalHashesMap) + incremental_hashes_map: &IncrementalHashesMap, + output_filenames: &OutputFilenames) -> trans::CrateTranslation { let time_passes = tcx.sess.time_passes(); time(time_passes, "resolving dependency formats", - || dependency_format::calculate(&tcx.sess)); + || dependency_format::calculate(tcx)); let translation = time(time_passes, "translation", - move || trans::trans_crate(tcx, analysis, &incremental_hashes_map)); + move || trans::trans_crate(tcx, analysis, &incremental_hashes_map, output_filenames)); time(time_passes, "assert dep graph", @@ -1109,11 +1122,7 @@ pub fn phase_5_run_llvm_passes(sess: &Session, "serialize work products", move || rustc_incremental::save_work_products(sess)); - if sess.err_count() > 0 { - Err(sess.err_count()) - } else { - Ok(()) - } + sess.compile_status() } /// Run the linker on any artifacts that resulted from the LLVM run. diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index c5f89e861f..1f9f6aad90 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -28,17 +28,13 @@ #![feature(rustc_diagnostic_macros)] #![feature(set_stdio)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] -#![cfg_attr(stage0, feature(loop_break_value))] - extern crate arena; extern crate getopts; extern crate graphviz; extern crate env_logger; extern crate libc; extern crate rustc; +extern crate rustc_allocator; extern crate rustc_back; extern crate rustc_borrowck; extern crate rustc_const_eval; @@ -72,6 +68,7 @@ use rustc_trans::back::link; use rustc_trans::back::write::{RELOC_MODEL_ARGS, CODE_GEN_MODEL_ARGS}; use rustc::dep_graph::DepGraph; use rustc::session::{self, config, Session, build_session, CompileResult}; +use rustc::session::CompileIncomplete; use rustc::session::config::{Input, PrintRequest, OutputType, ErrorOutputType}; use rustc::session::config::nightly_options; use rustc::session::{early_error, early_warn}; @@ -79,7 +76,7 @@ use rustc::lint::Lint; use rustc::lint; use rustc_metadata::locator; use rustc_metadata::cstore::CStore; -use rustc::util::common::time; +use rustc::util::common::{time, ErrorReported}; use serialize::json::ToJson; @@ -88,10 +85,11 @@ use std::cmp::max; use std::cmp::Ordering::Equal; use std::default::Default; use std::env; +use std::ffi::OsString; use std::io::{self, Read, Write}; use std::iter::repeat; use std::path::PathBuf; -use std::process; +use std::process::{self, Command, Stdio}; use std::rc::Rc; use std::str; use std::sync::{Arc, Mutex}; @@ -114,18 +112,14 @@ mod derive_registrar; const BUG_REPORT_URL: &'static str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.\ md#bug-reports"; -#[inline] -fn abort_msg(err_count: usize) -> String { - match err_count { - 0 => "aborting with no errors (maybe a bug?)".to_owned(), - _ => "aborting due to previous error(s)".to_owned(), - } -} - -pub fn abort_on_err(result: Result, sess: &Session) -> T { +pub fn abort_on_err(result: Result, sess: &Session) -> T { match result { - Err(err_count) => { - sess.fatal(&abort_msg(err_count)); + Err(CompileIncomplete::Errored(ErrorReported)) => { + sess.abort_if_errors(); + panic!("error reported but abort_if_errors didn't abort???"); + } + Err(CompileIncomplete::Stopped) => { + sess.fatal("compilation terminated"); } Ok(x) => x, } @@ -136,19 +130,20 @@ pub fn run(run_compiler: F) -> isize { monitor(move || { let (result, session) = run_compiler(); - if let Err(err_count) = result { - if err_count > 0 { - match session { - Some(sess) => sess.fatal(&abort_msg(err_count)), - None => { - let emitter = - errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, None); - let handler = errors::Handler::with_emitter(true, false, Box::new(emitter)); - handler.emit(&MultiSpan::new(), - &abort_msg(err_count), - errors::Level::Fatal); - exit_on_err(); - } + if let Err(CompileIncomplete::Errored(_)) = result { + match session { + Some(sess) => { + sess.abort_if_errors(); + panic!("error reported but abort_if_errors didn't abort???"); + } + None => { + let emitter = + errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, None); + let handler = errors::Handler::with_emitter(true, false, Box::new(emitter)); + handler.emit(&MultiSpan::new(), + "aborting due to previous error(s)", + errors::Level::Fatal); + exit_on_err(); } } } @@ -350,6 +345,31 @@ pub trait CompilerCalls<'a> { #[derive(Copy, Clone)] pub struct RustcDefaultCalls; +// FIXME remove these and use winapi 0.3 instead +// Duplicates: bootstrap/compile.rs, librustc_errors/emitter.rs +#[cfg(unix)] +fn stdout_isatty() -> bool { + unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 } +} + +#[cfg(windows)] +fn stdout_isatty() -> bool { + type DWORD = u32; + type BOOL = i32; + type HANDLE = *mut u8; + type LPDWORD = *mut u32; + const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD; + extern "system" { + fn GetStdHandle(which: DWORD) -> HANDLE; + fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL; + } + unsafe { + let handle = GetStdHandle(STD_OUTPUT_HANDLE); + let mut out = 0; + GetConsoleMode(handle, &mut out) != 0 + } +} + fn handle_explain(code: &str, descriptions: &errors::registry::Registry, output: ErrorOutputType) { @@ -360,14 +380,30 @@ fn handle_explain(code: &str, }; match descriptions.find_description(&normalised) { Some(ref description) => { + let mut is_in_code_block = false; + let mut text = String::new(); + // Slice off the leading newline and print. - print!("{}", &(&description[1..]).split("\n").map(|x| { - format!("{}\n", if x.starts_with("```") { - "```" + for line in description[1..].lines() { + let indent_level = line.find(|c: char| !c.is_whitespace()) + .unwrap_or_else(|| line.len()); + let dedented_line = &line[indent_level..]; + if dedented_line.starts_with("```") { + is_in_code_block = !is_in_code_block; + text.push_str(&line[..(indent_level+3)]); + } else if is_in_code_block && dedented_line.starts_with("# ") { + continue; } else { - x - }) - }).collect::()); + text.push_str(line); + } + text.push('\n'); + } + + if stdout_isatty() { + show_content_with_pager(&text); + } else { + print!("{}", text); + } } None => { early_error(output, &format!("no extended information for {}", code)); @@ -375,6 +411,39 @@ fn handle_explain(code: &str, } } +fn show_content_with_pager(content: &String) { + let pager_name = env::var_os("PAGER").unwrap_or_else(|| if cfg!(windows) { + OsString::from("more.com") + } else { + OsString::from("less") + }); + + let mut fallback_to_println = false; + + match Command::new(pager_name).stdin(Stdio::piped()).spawn() { + Ok(mut pager) => { + if let Some(mut pipe) = pager.stdin.as_mut() { + if pipe.write_all(content.as_bytes()).is_err() { + fallback_to_println = true; + } + } + + if pager.wait().is_err() { + fallback_to_println = true; + } + } + Err(_) => { + fallback_to_println = true; + } + } + + // If pager fails for whatever reason, we should still print the content + // to standard output + if fallback_to_println { + print!("{}", content); + } +} + impl<'a> CompilerCalls<'a> for RustcDefaultCalls { fn early_callback(&mut self, matches: &getopts::Matches, @@ -534,15 +603,12 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { fn save_analysis(sess: &Session) -> bool { sess.opts.debugging_opts.save_analysis || - sess.opts.debugging_opts.save_analysis_csv || sess.opts.debugging_opts.save_analysis_api } fn save_analysis_format(sess: &Session) -> save::Format { if sess.opts.debugging_opts.save_analysis { save::Format::Json - } else if sess.opts.debugging_opts.save_analysis_csv { - save::Format::Csv } else if sess.opts.debugging_opts.save_analysis_api { save::Format::JsonApi } else { @@ -733,10 +799,10 @@ fn usage(verbose: bool, include_unstable_options: bool) { } else { config::rustc_short_optgroups() }; - let groups: Vec<_> = groups.into_iter() - .filter(|x| include_unstable_options || x.is_stable()) - .map(|x| x.opt_group) - .collect(); + let mut options = getopts::Options::new(); + for option in groups.iter().filter(|x| include_unstable_options || x.is_stable()) { + (option.apply)(&mut options); + } let message = format!("Usage: rustc [OPTIONS] INPUT"); let extra_help = if verbose { "" @@ -749,7 +815,7 @@ fn usage(verbose: bool, include_unstable_options: bool) { Print 'lint' options and default settings -Z help Print internal \ options for debugging rustc{}\n", - getopts::usage(&message, &groups), + options.usage(&message), extra_help); } @@ -963,11 +1029,11 @@ pub fn handle_options(args: &[String]) -> Option { // Parse with *all* options defined in the compiler, we don't worry about // option stability here we just want to parse as much as possible. - let all_groups: Vec = config::rustc_optgroups() - .into_iter() - .map(|x| x.opt_group) - .collect(); - let matches = match getopts::getopts(&args, &all_groups) { + let mut options = getopts::Options::new(); + for option in config::rustc_optgroups() { + (option.apply)(&mut options); + } + let matches = match options.parse(args) { Ok(m) => m, Err(f) => early_error(ErrorOutputType::default(), &f.to_string()), }; @@ -1101,7 +1167,10 @@ pub fn monitor(f: F) { } let xs = ["the compiler unexpectedly panicked. this is a bug.".to_string(), - format!("we would appreciate a bug report: {}", BUG_REPORT_URL)]; + format!("we would appreciate a bug report: {}", BUG_REPORT_URL), + format!("rustc {} running on {}", + option_env!("CFG_VERSION").unwrap_or("unknown_version"), + config::host_triple())]; for note in &xs { handler.emit(&MultiSpan::new(), ¬e, diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index d40a2ab0b5..269363fdd2 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -30,7 +30,7 @@ use rustc_mir::util::{write_mir_pretty, write_mir_graphviz}; use syntax::ast::{self, BlockCheckMode}; use syntax::fold::{self, Folder}; -use syntax::print::{pp, pprust}; +use syntax::print::{pprust}; use syntax::print::pprust::PrintState; use syntax::ptr::P; use syntax::util::small_vector::SmallVector; @@ -163,13 +163,12 @@ pub fn parse_pretty(sess: &Session, impl PpSourceMode { /// Constructs a `PrinterSupport` object and passes it to `f`. - fn call_with_pp_support<'tcx, A, B, F>(&self, + fn call_with_pp_support<'tcx, A, F>(&self, sess: &'tcx Session, hir_map: Option<&hir_map::Map<'tcx>>, - payload: B, f: F) -> A - where F: FnOnce(&PrinterSupport, B) -> A + where F: FnOnce(&PrinterSupport) -> A { match *self { PpmNormal | PpmEveryBodyLoops | PpmExpanded => { @@ -177,7 +176,7 @@ impl PpSourceMode { sess: sess, hir_map: hir_map.map(|m| m.clone()), }; - f(&annotation, payload) + f(&annotation) } PpmIdentified | PpmExpandedIdentified => { @@ -185,18 +184,18 @@ impl PpSourceMode { sess: sess, hir_map: hir_map.map(|m| m.clone()), }; - f(&annotation, payload) + f(&annotation) } PpmExpandedHygiene => { let annotation = HygieneAnnotation { sess: sess, }; - f(&annotation, payload) + f(&annotation) } _ => panic!("Should use call_with_pp_support_hir"), } } - fn call_with_pp_support_hir<'tcx, A, B, F>(&self, + fn call_with_pp_support_hir<'tcx, A, F>(&self, sess: &'tcx Session, hir_map: &hir_map::Map<'tcx>, analysis: &ty::CrateAnalysis, @@ -204,10 +203,9 @@ impl PpSourceMode { arena: &'tcx DroplessArena, arenas: &'tcx GlobalArenas<'tcx>, id: &str, - payload: B, f: F) -> A - where F: FnOnce(&HirPrinterSupport, B, &hir::Crate) -> A + where F: FnOnce(&HirPrinterSupport, &hir::Crate) -> A { match *self { PpmNormal => { @@ -215,7 +213,7 @@ impl PpSourceMode { sess: sess, hir_map: Some(hir_map.clone()), }; - f(&annotation, payload, hir_map.forest.krate()) + f(&annotation, hir_map.forest.krate()) } PpmIdentified => { @@ -223,7 +221,7 @@ impl PpSourceMode { sess: sess, hir_map: Some(hir_map.clone()), }; - f(&annotation, payload, hir_map.forest.krate()) + f(&annotation, hir_map.forest.krate()) } PpmTyped => { abort_on_err(driver::phase_3_run_analysis_passes(sess, @@ -240,7 +238,7 @@ impl PpSourceMode { tables: Cell::new(&empty_tables) }; let _ignore = tcx.dep_graph.in_ignore(); - f(&annotation, payload, hir_map.forest.krate()) + f(&annotation, hir_map.forest.krate()) }), sess) } @@ -357,24 +355,24 @@ impl<'hir> pprust::PpAnn for IdentifiedAnnotation<'hir> { pprust::NodeName(_) => Ok(()), pprust::NodeItem(item) => { - pp::space(&mut s.s)?; + s.s.space()?; s.synth_comment(item.id.to_string()) } pprust::NodeSubItem(id) => { - pp::space(&mut s.s)?; + s.s.space()?; s.synth_comment(id.to_string()) } pprust::NodeBlock(blk) => { - pp::space(&mut s.s)?; + s.s.space()?; s.synth_comment(format!("block {}", blk.id)) } pprust::NodeExpr(expr) => { - pp::space(&mut s.s)?; + s.s.space()?; s.synth_comment(expr.id.to_string())?; s.pclose() } pprust::NodePat(pat) => { - pp::space(&mut s.s)?; + s.s.space()?; s.synth_comment(format!("pat {}", pat.id)) } } @@ -414,24 +412,24 @@ impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> { match node { pprust_hir::NodeName(_) => Ok(()), pprust_hir::NodeItem(item) => { - pp::space(&mut s.s)?; + s.s.space()?; s.synth_comment(item.id.to_string()) } pprust_hir::NodeSubItem(id) => { - pp::space(&mut s.s)?; + s.s.space()?; s.synth_comment(id.to_string()) } pprust_hir::NodeBlock(blk) => { - pp::space(&mut s.s)?; + s.s.space()?; s.synth_comment(format!("block {}", blk.id)) } pprust_hir::NodeExpr(expr) => { - pp::space(&mut s.s)?; + s.s.space()?; s.synth_comment(expr.id.to_string())?; s.pclose() } pprust_hir::NodePat(pat) => { - pp::space(&mut s.s)?; + s.s.space()?; s.synth_comment(format!("pat {}", pat.id)) } } @@ -456,13 +454,13 @@ 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 }) => { - pp::space(&mut s.s)?; + s.s.space()?; // FIXME #16420: this doesn't display the connections // between syntax contexts s.synth_comment(format!("{}{:?}", name.as_u32(), ctxt)) } pprust::NodeName(&name) => { - pp::space(&mut s.s)?; + s.s.space()?; s.synth_comment(name.as_u32().to_string()) } _ => Ok(()), @@ -514,10 +512,10 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { fn post(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> { match node { pprust_hir::NodeExpr(expr) => { - pp::space(&mut s.s)?; - pp::word(&mut s.s, "as")?; - pp::space(&mut s.s)?; - pp::word(&mut s.s, &self.tables.get().expr_ty(expr).to_string())?; + s.s.space()?; + s.s.word("as")?; + s.s.space()?; + s.s.word(&self.tables.get().expr_ty(expr).to_string())?; s.pclose() } _ => Ok(()), @@ -825,7 +823,7 @@ pub fn print_after_parsing(sess: &Session, if let PpmSource(s) = ppm { // Silently ignores an identified node. let out: &mut Write = &mut out; - s.call_with_pp_support(sess, None, box out, |annotation, out| { + s.call_with_pp_support(sess, None, move |annotation| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); pprust::print_crate(sess.codemap(), @@ -833,7 +831,7 @@ pub fn print_after_parsing(sess: &Session, krate, src_name.to_string(), &mut rdr, - out, + box out, annotation.pp_ann(), false) }) @@ -883,7 +881,7 @@ 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(hir_map), box out, |annotation, out| { + s.call_with_pp_support(sess, Some(hir_map), move |annotation| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); pprust::print_crate(sess.codemap(), @@ -891,7 +889,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, krate, src_name.to_string(), &mut rdr, - out, + box out, annotation.pp_ann(), true) }) @@ -906,8 +904,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, arena, arenas, crate_name, - box out, - |annotation, out, krate| { + move |annotation, krate| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); pprust_hir::print_crate(sess.codemap(), @@ -915,7 +912,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, krate, src_name.to_string(), &mut rdr, - out, + box out, annotation.pp_ann(), true) }) @@ -930,8 +927,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, arena, arenas, crate_name, - (out, uii), - |annotation, (out, uii), _| { + move |annotation, _| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); let hir_map = annotation.hir_map().expect("--unpretty missing HIR map"); @@ -945,13 +941,13 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, 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)?; + pp_state.s.space()?; let path = annotation.node_path(node_id) .expect("--unpretty missing node paths"); pp_state.synth_comment(path)?; - pp::hardbreak(&mut pp_state.s)?; + pp_state.s.hardbreak()?; } - pp::eof(&mut pp_state.s) + pp_state.s.eof() }) } _ => unreachable!(), diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 2b74d0a812..62e20a90f8 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -154,7 +154,7 @@ fn test_env(source_string: &str, index, "test_crate", |tcx| { - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let mut region_maps = RegionMaps::new(); body(Env { infcx: &infcx, diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 7a64cdeee6..ee07b6e909 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -211,6 +211,18 @@ impl Diagnostic { /// Prints out a message with a suggested edit of the code. /// + /// In case of short messages and a simple suggestion, + /// rustc displays it as a label like + /// + /// "try adding parentheses: `(tup.0).1`" + /// + /// The message + /// * should not end in any punctuation (a `:` is added automatically) + /// * should not be a question + /// * should not contain any parts like "the following", "as shown" + /// * may look like "to do xyz, use" or "to do xyz, use abc" + /// * may contain a name of a function, variable or type, but not whole expressions + /// /// See `diagnostic::CodeSuggestion` for more information. pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self { self.suggestions.push(CodeSuggestion { @@ -248,6 +260,10 @@ impl Diagnostic { self.message.iter().map(|i| i.0.to_owned()).collect::() } + pub fn set_message(&mut self, message: &str) { + self.message = vec![(message.to_owned(), Style::NoStyle)]; + } + 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 f820ea4c5e..3e8bd093f4 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -17,6 +17,7 @@ use RenderSpan::*; use snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, StyledString, Style}; use styled_buffer::StyledBuffer; +use std::borrow::Cow; use std::io::prelude::*; use std::io; use std::rc::Rc; @@ -46,7 +47,12 @@ impl Emitter for EmitterWriter { // don't display multiline suggestions as labels sugg.substitution_parts[0].substitutions[0].find('\n').is_none() { let substitution = &sugg.substitution_parts[0].substitutions[0]; - let msg = format!("help: {} `{}`", sugg.msg, substitution); + let msg = if substitution.len() == 0 { + // This substitution is only removal, don't show it + format!("help: {}", sugg.msg) + } else { + format!("help: {}: `{}`", sugg.msg, substitution) + }; primary_span.push_span_label(sugg.substitution_spans().next().unwrap(), msg); } else { // if there are multiple suggestions, print them all in full @@ -131,7 +137,7 @@ impl EmitterWriter { } } - fn preprocess_annotations(&self, msp: &MultiSpan) -> Vec { + fn preprocess_annotations(&mut self, msp: &MultiSpan) -> Vec { fn add_annotation_to_file(file_vec: &mut Vec, file: Rc, line_index: usize, @@ -175,6 +181,7 @@ impl EmitterWriter { if span_label.span == DUMMY_SP { continue; } + let lo = cm.lookup_char_pos(span_label.span.lo); let mut hi = cm.lookup_char_pos(span_label.span.hi); @@ -445,8 +452,11 @@ impl EmitterWriter { && next.has_label()) // multiline start/end, move it to a new line || (annotation.has_label() // so as not to overlap the orizontal lines. && next.takes_space()) - || (annotation.takes_space() - && next.takes_space()) + || (annotation.takes_space() && next.takes_space()) + || (overlaps(next, annotation, l) + && next.end_col <= annotation.end_col + && next.has_label() + && p == 0) // Avoid #42595. { // This annotation needs a new line in the output. p += 1; @@ -887,10 +897,10 @@ impl EmitterWriter { let mut annotated_files = self.preprocess_annotations(msp); // Make sure our primary file comes first - let primary_lo = if let (Some(ref cm), Some(ref primary_span)) = + let (primary_lo, cm) = if let (Some(cm), Some(ref primary_span)) = (self.cm.as_ref(), msp.primary_span().as_ref()) { if primary_span != &&DUMMY_SP { - cm.lookup_char_pos(primary_span.lo) + (cm.lookup_char_pos(primary_span.lo), cm) } else { emit_to_destination(&buffer.render(), level, &mut self.dst)?; return Ok(()); @@ -908,7 +918,7 @@ impl EmitterWriter { // Print out the annotate source lines that correspond with the error for annotated_file in annotated_files { // we can't annotate anything if the source is unavailable. - if annotated_file.file.src.is_none() { + if !cm.ensure_filemap_source_present(annotated_file.file.clone()) { continue; } @@ -1009,7 +1019,7 @@ impl EmitterWriter { } else if line_idx_delta == 2 { let unannotated_line = annotated_file.file .get_line(annotated_file.lines[line_idx].line_index) - .unwrap_or(""); + .unwrap_or_else(|| Cow::from("")); let last_buffer_line_num = buffer.num_lines(); @@ -1050,44 +1060,72 @@ impl EmitterWriter { -> io::Result<()> { use std::borrow::Borrow; - let primary_span = suggestion.substitution_spans().next().unwrap(); + let primary_sub = &suggestion.substitution_parts[0]; if let Some(ref cm) = self.cm { let mut buffer = StyledBuffer::new(); - let lines = cm.span_to_lines(primary_span).unwrap(); + let lines = cm.span_to_lines(primary_sub.span).unwrap(); assert!(!lines.lines.is_empty()); buffer.append(0, &level.to_string(), Style::Level(level.clone())); buffer.append(0, ": ", Style::HeaderMsg); self.msg_to_buffer(&mut buffer, - &[(suggestion.msg.to_owned(), Style::NoStyle)], - max_line_num_len, - "suggestion", - Some(Style::HeaderMsg)); + &[(suggestion.msg.to_owned(), Style::NoStyle)], + max_line_num_len, + "suggestion", + Some(Style::HeaderMsg)); let suggestions = suggestion.splice_lines(cm.borrow()); - let mut row_num = 1; - for complete in suggestions.iter().take(MAX_SUGGESTIONS) { - - // print the suggestion without any line numbers, but leave - // space for them. This helps with lining up with previous - // snippets from the actual error being reported. + let span_start_pos = cm.lookup_char_pos(primary_sub.span.lo); + let line_start = span_start_pos.line; + draw_col_separator_no_space(&mut buffer, 1, max_line_num_len + 1); + let mut row_num = 2; + for (&(ref complete, show_underline), ref sub) in suggestions + .iter().zip(primary_sub.substitutions.iter()).take(MAX_SUGGESTIONS) + { + let mut line_pos = 0; + // Only show underline if there's a single suggestion and it is a single line let mut lines = complete.lines(); for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) { + // Print the span column to avoid confusion + buffer.puts(row_num, + 0, + &((line_start + line_pos).to_string()), + Style::LineNumber); + // print the suggestion draw_col_separator(&mut buffer, row_num, max_line_num_len + 1); buffer.append(row_num, line, Style::NoStyle); + line_pos += 1; row_num += 1; + // Only show an underline in the suggestions if the suggestion is not the + // entirety of the code being shown and the displayed code is not multiline. + if show_underline { + draw_col_separator(&mut buffer, row_num, max_line_num_len + 1); + let sub_len = sub.trim_right().len(); + let underline_start = span_start_pos.col.0; + let underline_end = span_start_pos.col.0 + sub_len; + for p in underline_start..underline_end { + buffer.putc(row_num, + max_line_num_len + 3 + p, + '^', + Style::UnderlinePrimary); + } + row_num += 1; + } } // if we elided some lines, add an ellipsis if let Some(_) = lines.next() { - buffer.append(row_num, "...", Style::NoStyle); + buffer.puts(row_num, max_line_num_len - 1, "...", Style::LineNumber); + } else if !show_underline { + draw_col_separator_no_space(&mut buffer, row_num, max_line_num_len + 1); + row_num += 1; } } if suggestions.len() > MAX_SUGGESTIONS { let msg = format!("and {} other candidates", suggestions.len() - MAX_SUGGESTIONS); - buffer.append(row_num, &msg, Style::NoStyle); + buffer.puts(row_num, 0, &msg, Style::NoStyle); } emit_to_destination(&buffer.render(), level, &mut self.dst)?; } @@ -1335,7 +1373,7 @@ impl Destination { fn apply_style(&mut self, lvl: Level, style: Style) -> io::Result<()> { match style { - Style::FileNameStyle | Style::LineAndColumn => {} + Style::LineAndColumn => {} Style::LineNumber => { self.start_attr(term::Attr::Bold)?; if cfg!(windows) { @@ -1344,16 +1382,8 @@ impl Destination { self.start_attr(term::Attr::ForegroundColor(term::color::BRIGHT_BLUE))?; } } - Style::ErrorCode => { - self.start_attr(term::Attr::Bold)?; - self.start_attr(term::Attr::ForegroundColor(term::color::BRIGHT_MAGENTA))?; - } Style::Quotation => {} - Style::OldSchoolNote => { - self.start_attr(term::Attr::Bold)?; - self.start_attr(term::Attr::ForegroundColor(term::color::BRIGHT_GREEN))?; - } - Style::OldSchoolNoteText | Style::HeaderMsg => { + Style::HeaderMsg => { self.start_attr(term::Attr::Bold)?; if cfg!(windows) { self.start_attr(term::Attr::ForegroundColor(term::color::BRIGHT_WHITE))?; diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 8d5e9e776e..c4beb5ebc4 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -22,10 +22,6 @@ #![feature(libc)] #![feature(conservative_impl_trait)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] - extern crate term; extern crate libc; extern crate serialize as rustc_serialize; @@ -37,6 +33,7 @@ use self::Level::*; use emitter::{Emitter, EmitterWriter}; +use std::borrow::Cow; use std::cell::{RefCell, Cell}; use std::{error, fmt}; use std::rc::Rc; @@ -44,12 +41,12 @@ use std::rc::Rc; pub mod diagnostic; pub mod diagnostic_builder; pub mod emitter; -pub mod snippet; +mod snippet; pub mod registry; -pub mod styled_buffer; +mod styled_buffer; mod lock; -use syntax_pos::{BytePos, Loc, FileLinesResult, FileName, MultiSpan, Span, NO_EXPANSION}; +use syntax_pos::{BytePos, Loc, FileLinesResult, FileMap, FileName, MultiSpan, Span, NO_EXPANSION}; #[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub enum RenderSpan { @@ -103,6 +100,7 @@ pub trait CodeMapper { fn span_to_filename(&self, sp: Span) -> FileName; fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option; fn call_span_if_macro(&self, sp: Span) -> Span; + fn ensure_filemap_source_present(&self, file_map: Rc) -> bool; } impl CodeSuggestion { @@ -116,12 +114,12 @@ impl CodeSuggestion { self.substitution_parts.iter().map(|sub| sub.span) } - /// Returns the assembled code suggestions. - pub fn splice_lines(&self, cm: &CodeMapper) -> Vec { + /// Returns the assembled code suggestions and wether they should be shown with an underline. + pub fn splice_lines(&self, cm: &CodeMapper) -> Vec<(String, bool)> { use syntax_pos::{CharPos, Loc, Pos}; fn push_trailing(buf: &mut String, - line_opt: Option<&str>, + line_opt: Option<&Cow>, lo: &Loc, hi_opt: Option<&Loc>) { let (lo, hi_opt) = (lo.col.to_usize(), hi_opt.map(|hi| hi.col.to_usize())); @@ -140,7 +138,7 @@ impl CodeSuggestion { } if self.substitution_parts.is_empty() { - return vec![String::new()]; + return vec![(String::new(), false)]; } let mut primary_spans: Vec<_> = self.substitution_parts @@ -177,19 +175,30 @@ impl CodeSuggestion { prev_hi.col = CharPos::from_usize(0); let mut prev_line = fm.get_line(lines.lines[0].line_index); - let mut bufs = vec![String::new(); self.substitutions()]; + let mut bufs = vec![(String::new(), false); self.substitutions()]; for (sp, substitutes) in primary_spans { let cur_lo = cm.lookup_char_pos(sp.lo); - for (buf, substitute) in bufs.iter_mut().zip(substitutes) { + for (&mut (ref mut buf, ref mut underline), substitute) in bufs.iter_mut() + .zip(substitutes) { if prev_hi.line == cur_lo.line { - push_trailing(buf, prev_line, &prev_hi, Some(&cur_lo)); + push_trailing(buf, prev_line.as_ref(), &prev_hi, Some(&cur_lo)); + + // Only show an underline in the suggestions if the suggestion is not the + // entirety of the code being shown and the displayed code is not multiline. + if prev_line.as_ref().unwrap().trim().len() > 0 + && !substitute.ends_with('\n') + && substitute.lines().count() == 1 + { + *underline = true; + } } else { - push_trailing(buf, prev_line, &prev_hi, None); + *underline = false; + push_trailing(buf, prev_line.as_ref(), &prev_hi, None); // push lines between the previous and current span (if any) for idx in prev_hi.line..(cur_lo.line - 1) { if let Some(line) = fm.get_line(idx) { - buf.push_str(line); + buf.push_str(line.as_ref()); buf.push('\n'); } } @@ -202,10 +211,10 @@ impl CodeSuggestion { prev_hi = cm.lookup_char_pos(sp.hi); prev_line = fm.get_line(prev_hi.line - 1); } - for buf in &mut bufs { + for &mut (ref mut buf, _) in &mut bufs { // if the replacement already ends with a newline, don't print the next line if !buf.ends_with('\n') { - push_trailing(buf, prev_line, &prev_hi, None); + push_trailing(buf, prev_line.as_ref(), &prev_hi, None); } // remove trailing newline buf.pop(); @@ -508,7 +517,10 @@ impl Handler { return; } - _ => s = "aborting due to previous error(s)".to_string(), + 1 => s = "aborting due to previous error".to_string(), + _ => { + s = format!("aborting due to {} previous errors", self.err_count.get()); + } } panic!(self.fatal(&s)); diff --git a/src/librustc_errors/snippet.rs b/src/librustc_errors/snippet.rs index 7401ead220..3c5a6c031e 100644 --- a/src/librustc_errors/snippet.rs +++ b/src/librustc_errors/snippet.rs @@ -206,7 +206,6 @@ pub struct StyledString { #[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub enum Style { HeaderMsg, - FileNameStyle, LineAndColumn, LineNumber, Quotation, @@ -214,10 +213,7 @@ pub enum Style { UnderlineSecondary, LabelPrimary, LabelSecondary, - OldSchoolNoteText, - OldSchoolNote, NoStyle, - ErrorCode, Level(Level), Highlight, } diff --git a/src/librustc_errors/styled_buffer.rs b/src/librustc_errors/styled_buffer.rs index dfc7c64de0..f1f2e6c55e 100644 --- a/src/librustc_errors/styled_buffer.rs +++ b/src/librustc_errors/styled_buffer.rs @@ -111,12 +111,6 @@ impl StyledBuffer { } } - pub fn set_style(&mut self, line: usize, col: usize, style: Style) { - if self.styles.len() > line && self.styles[line].len() > col { - self.styles[line][col] = style; - } - } - pub fn prepend(&mut self, line: usize, string: &str, style: Style) { self.ensure_lines(line); let string_len = string.len(); diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index 39fe2188f6..04192c35ef 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -44,7 +44,7 @@ //! ``` use graphviz as dot; -use rustc::dep_graph::{DepGraphQuery, DepNode}; +use rustc::dep_graph::{DepGraphQuery, DepNode, DepKind}; use rustc::dep_graph::debug::{DepNodeFilter, EdgeFilter}; use rustc::hir::def_id::DefId; use rustc::ty::TyCtxt; @@ -95,8 +95,8 @@ pub fn assert_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { check_paths(tcx, &if_this_changed, &then_this_would_need); } -type Sources = Vec<(Span, DefId, DepNode)>; -type Targets = Vec<(Span, ast::Name, ast::NodeId, DepNode)>; +type Sources = Vec<(Span, DefId, DepNode)>; +type Targets = Vec<(Span, ast::Name, ast::NodeId, DepNode)>; struct IfThisChanged<'a, 'tcx:'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -121,13 +121,14 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> { fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) { let def_id = self.tcx.hir.local_def_id(node_id); + let def_path_hash = self.tcx.def_path_hash(def_id); for attr in attrs { if attr.check_name(ATTR_IF_THIS_CHANGED) { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { - None => DepNode::Hir(def_id), + None => def_path_hash.to_dep_node(DepKind::Hir), Some(n) => { - match DepNode::from_label_string(&n.as_str(), def_id) { + match DepNode::from_label_string(&n.as_str(), def_path_hash) { Ok(n) => n, Err(()) => { self.tcx.sess.span_fatal( @@ -142,7 +143,7 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { Some(n) => { - match DepNode::from_label_string(&n.as_str(), def_id) { + match DepNode::from_label_string(&n.as_str(), def_path_hash) { Ok(n) => n, Err(()) => { self.tcx.sess.span_fatal( @@ -263,34 +264,34 @@ fn dump_graph(tcx: TyCtxt) { } } -pub struct GraphvizDepGraph<'q>(FxHashSet<&'q DepNode>, - Vec<(&'q DepNode, &'q DepNode)>); +pub struct GraphvizDepGraph<'q>(FxHashSet<&'q DepNode>, + Vec<(&'q DepNode, &'q DepNode)>); impl<'a, 'tcx, 'q> dot::GraphWalk<'a> for GraphvizDepGraph<'q> { - type Node = &'q DepNode; - type Edge = (&'q DepNode, &'q DepNode); - fn nodes(&self) -> dot::Nodes<&'q DepNode> { + type Node = &'q DepNode; + type Edge = (&'q DepNode, &'q DepNode); + fn nodes(&self) -> dot::Nodes<&'q DepNode> { let nodes: Vec<_> = self.0.iter().cloned().collect(); nodes.into_cow() } - fn edges(&self) -> dot::Edges<(&'q DepNode, &'q DepNode)> { + fn edges(&self) -> dot::Edges<(&'q DepNode, &'q DepNode)> { self.1[..].into_cow() } - fn source(&self, edge: &(&'q DepNode, &'q DepNode)) -> &'q DepNode { + fn source(&self, edge: &(&'q DepNode, &'q DepNode)) -> &'q DepNode { edge.0 } - fn target(&self, edge: &(&'q DepNode, &'q DepNode)) -> &'q DepNode { + fn target(&self, edge: &(&'q DepNode, &'q DepNode)) -> &'q DepNode { edge.1 } } impl<'a, 'tcx, 'q> dot::Labeller<'a> for GraphvizDepGraph<'q> { - type Node = &'q DepNode; - type Edge = (&'q DepNode, &'q DepNode); + type Node = &'q DepNode; + type Edge = (&'q DepNode, &'q DepNode); fn graph_id(&self) -> dot::Id { dot::Id::new("DependencyGraph").unwrap() } - fn node_id(&self, n: &&'q DepNode) -> dot::Id { + fn node_id(&self, n: &&'q DepNode) -> dot::Id { let s: String = format!("{:?}", n).chars() .map(|c| if c == '_' || c.is_alphanumeric() { c } else { '_' }) @@ -298,7 +299,7 @@ impl<'a, 'tcx, 'q> dot::Labeller<'a> for GraphvizDepGraph<'q> { debug!("n={:?} s={:?}", n, s); dot::Id::new(s).unwrap() } - fn node_label(&self, n: &&'q DepNode) -> dot::LabelText { + fn node_label(&self, n: &&'q DepNode) -> dot::LabelText { dot::LabelText::label(format!("{:?}", n)) } } @@ -306,8 +307,8 @@ impl<'a, 'tcx, 'q> dot::Labeller<'a> for GraphvizDepGraph<'q> { // Given an optional filter like `"x,y,z"`, returns either `None` (no // filter) or the set of nodes whose labels contain all of those // substrings. -fn node_set<'q>(query: &'q DepGraphQuery, filter: &DepNodeFilter) - -> Option>> +fn node_set<'q>(query: &'q DepGraphQuery, filter: &DepNodeFilter) + -> Option> { debug!("node_set(filter={:?})", filter); @@ -318,10 +319,10 @@ fn node_set<'q>(query: &'q DepGraphQuery, filter: &DepNodeFilter) Some(query.nodes().into_iter().filter(|n| filter.test(n)).collect()) } -fn filter_nodes<'q>(query: &'q DepGraphQuery, - sources: &Option>>, - targets: &Option>>) - -> FxHashSet<&'q DepNode> +fn filter_nodes<'q>(query: &'q DepGraphQuery, + sources: &Option>, + targets: &Option>) + -> FxHashSet<&'q DepNode> { if let &Some(ref sources) = sources { if let &Some(ref targets) = targets { @@ -336,10 +337,10 @@ fn filter_nodes<'q>(query: &'q DepGraphQuery, } } -fn walk_nodes<'q>(query: &'q DepGraphQuery, - starts: &FxHashSet<&'q DepNode>, +fn walk_nodes<'q>(query: &'q DepGraphQuery, + starts: &FxHashSet<&'q DepNode>, direction: Direction) - -> FxHashSet<&'q DepNode> + -> FxHashSet<&'q DepNode> { let mut set = FxHashSet(); for &start in starts { @@ -360,10 +361,10 @@ fn walk_nodes<'q>(query: &'q DepGraphQuery, set } -fn walk_between<'q>(query: &'q DepGraphQuery, - sources: &FxHashSet<&'q DepNode>, - targets: &FxHashSet<&'q DepNode>) - -> FxHashSet<&'q DepNode> +fn walk_between<'q>(query: &'q DepGraphQuery, + sources: &FxHashSet<&'q DepNode>, + targets: &FxHashSet<&'q DepNode>) + -> FxHashSet<&'q DepNode> { // This is a bit tricky. We want to include a node only if it is: // (a) reachable from a source and (b) will reach a target. And we @@ -391,7 +392,7 @@ fn walk_between<'q>(query: &'q DepGraphQuery, }) .collect(); - fn recurse(query: &DepGraphQuery, + fn recurse(query: &DepGraphQuery, node_states: &mut [State], node: NodeIndex) -> bool @@ -428,9 +429,9 @@ fn walk_between<'q>(query: &'q DepGraphQuery, } } -fn filter_edges<'q>(query: &'q DepGraphQuery, - nodes: &FxHashSet<&'q DepNode>) - -> Vec<(&'q DepNode, &'q DepNode)> +fn filter_edges<'q>(query: &'q DepGraphQuery, + nodes: &FxHashSet<&'q DepNode>) + -> Vec<(&'q DepNode, &'q DepNode)> { query.edges() .into_iter() diff --git a/src/librustc_incremental/calculate_svh/mod.rs b/src/librustc_incremental/calculate_svh/mod.rs index be4d610a89..f30a0f553b 100644 --- a/src/librustc_incremental/calculate_svh/mod.rs +++ b/src/librustc_incremental/calculate_svh/mod.rs @@ -29,7 +29,7 @@ use std::cell::RefCell; use std::hash::Hash; -use rustc::dep_graph::DepNode; +use rustc::dep_graph::{DepNode, DepKind}; use rustc::hir; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use rustc::hir::map::DefPathHash; @@ -44,7 +44,7 @@ use rustc_data_structures::accumulate_vec::AccumulateVec; pub type IchHasher = StableHasher; pub struct IncrementalHashesMap { - hashes: FxHashMap, Fingerprint>, + hashes: FxHashMap, // These are the metadata hashes for the current crate as they were stored // during the last compilation session. They are only loaded if @@ -62,16 +62,16 @@ impl IncrementalHashesMap { } } - pub fn get(&self, k: &DepNode) -> Option<&Fingerprint> { + pub fn get(&self, k: &DepNode) -> Option<&Fingerprint> { self.hashes.get(k) } - pub fn insert(&mut self, k: DepNode, v: Fingerprint) -> Option { - self.hashes.insert(k, v) + pub fn insert(&mut self, k: DepNode, v: Fingerprint) { + assert!(self.hashes.insert(k, v).is_none()); } pub fn iter<'a>(&'a self) - -> ::std::collections::hash_map::Iter<'a, DepNode, Fingerprint> { + -> ::std::collections::hash_map::Iter<'a, DepNode, Fingerprint> { self.hashes.iter() } @@ -80,10 +80,10 @@ impl IncrementalHashesMap { } } -impl<'a> ::std::ops::Index<&'a DepNode> for IncrementalHashesMap { +impl<'a> ::std::ops::Index<&'a DepNode> for IncrementalHashesMap { type Output = Fingerprint; - fn index(&self, index: &'a DepNode) -> &Fingerprint { + fn index(&self, index: &'a DepNode) -> &Fingerprint { match self.hashes.get(index) { Some(fingerprint) => fingerprint, None => { @@ -94,16 +94,16 @@ impl<'a> ::std::ops::Index<&'a DepNode> for IncrementalHashesMap { } struct ComputeItemHashesVisitor<'a, 'tcx: 'a> { - hcx: StableHashingContext<'a, 'tcx>, + hcx: StableHashingContext<'a, 'tcx, 'tcx>, hashes: IncrementalHashesMap, } impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> { fn compute_and_store_ich_for_item_like(&mut self, - dep_node: DepNode, + dep_node: DepNode, hash_bodies: bool, item_like: T) - where T: HashStable> + where T: HashStable> { if !hash_bodies && !self.hcx.tcx().sess.opts.build_dep_graph() { // If we just need the hashes in order to compute the SVH, we don't @@ -143,36 +143,29 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> { // add each item (in some deterministic order) to the overall // crate hash. { - let hcx = &mut self.hcx; let mut item_hashes: Vec<_> = self.hashes.iter() - .filter_map(|(item_dep_node, &item_hash)| { + .filter_map(|(&item_dep_node, &item_hash)| { // This `match` determines what kinds of nodes // go into the SVH: - match *item_dep_node { - DepNode::Hir(_) | - DepNode::HirBody(_) => { + match item_dep_node.kind { + DepKind::Hir | + DepKind::HirBody => { // We want to incoporate these into the // SVH. } - DepNode::AllLocalTraitImpls => { + DepKind::AllLocalTraitImpls => { // These are already covered by hashing // the HIR. return None } ref other => { - bug!("Found unexpected DepNode during \ + bug!("Found unexpected DepKind during \ SVH computation: {:?}", other) } } - // Convert from a DepNode to a - // DepNode where the u64 is the hash of - // the def-id's def-path: - let item_dep_node = - item_dep_node.map_def(|&did| Some(hcx.def_path_hash(did))) - .unwrap(); Some((item_dep_node, item_hash)) }) .collect(); @@ -183,7 +176,7 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> { krate.attrs.hash_stable(&mut self.hcx, &mut crate_state); let crate_hash = crate_state.finish(); - self.hashes.insert(DepNode::Krate, crate_hash); + self.hashes.insert(DepNode::new_no_params(DepKind::Krate), crate_hash); debug!("calculate_crate_hash: crate_hash={:?}", crate_hash); } @@ -206,11 +199,11 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> { body_ids: _, } = *krate; - let def_id = DefId::local(CRATE_DEF_INDEX); - self.compute_and_store_ich_for_item_like(DepNode::Hir(def_id), + let def_path_hash = self.hcx.tcx().hir.definitions().def_path_hash(CRATE_DEF_INDEX); + self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::Hir), false, (module, (span, attrs))); - self.compute_and_store_ich_for_item_like(DepNode::HirBody(def_id), + self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::HirBody), true, (module, (span, attrs))); } @@ -255,27 +248,43 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> { let mut hasher = StableHasher::new(); impls.hash_stable(&mut self.hcx, &mut hasher); - self.hashes.insert(DepNode::AllLocalTraitImpls, hasher.finish()); + self.hashes.insert(DepNode::new_no_params(DepKind::AllLocalTraitImpls), + hasher.finish()); } } impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for ComputeItemHashesVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item) { let def_id = self.hcx.tcx().hir.local_def_id(item.id); - self.compute_and_store_ich_for_item_like(DepNode::Hir(def_id), false, item); - self.compute_and_store_ich_for_item_like(DepNode::HirBody(def_id), true, item); + let def_path_hash = self.hcx.tcx().def_path_hash(def_id); + self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::Hir), + false, + item); + self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::HirBody), + true, + item); } fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) { let def_id = self.hcx.tcx().hir.local_def_id(item.id); - self.compute_and_store_ich_for_item_like(DepNode::Hir(def_id), false, item); - self.compute_and_store_ich_for_item_like(DepNode::HirBody(def_id), true, item); + let def_path_hash = self.hcx.tcx().def_path_hash(def_id); + self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::Hir), + false, + item); + self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::HirBody), + true, + item); } fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) { let def_id = self.hcx.tcx().hir.local_def_id(item.id); - self.compute_and_store_ich_for_item_like(DepNode::Hir(def_id), false, item); - self.compute_and_store_ich_for_item_like(DepNode::HirBody(def_id), true, item); + let def_path_hash = self.hcx.tcx().def_path_hash(def_id); + self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::Hir), + false, + item); + self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::HirBody), + true, + item); } } @@ -297,8 +306,13 @@ pub fn compute_incremental_hashes_map<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) for macro_def in krate.exported_macros.iter() { let def_id = tcx.hir.local_def_id(macro_def.id); - visitor.compute_and_store_ich_for_item_like(DepNode::Hir(def_id), false, macro_def); - visitor.compute_and_store_ich_for_item_like(DepNode::HirBody(def_id), true, macro_def); + let def_path_hash = tcx.def_path_hash(def_id); + visitor.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::Hir), + false, + macro_def); + visitor.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::HirBody), + true, + macro_def); } visitor.compute_and_store_ich_for_trait_impls(krate); diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs index 70f967d50b..ac3149b90b 100644 --- a/src/librustc_incremental/lib.rs +++ b/src/librustc_incremental/lib.rs @@ -20,11 +20,6 @@ #![feature(rand)] #![feature(conservative_impl_trait)] -#![feature(sort_unstable)] - -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] extern crate graphviz; #[macro_use] extern crate rustc; diff --git a/src/librustc_incremental/persist/data.rs b/src/librustc_incremental/persist/data.rs index 682a7051a1..06acfb5d77 100644 --- a/src/librustc_incremental/persist/data.rs +++ b/src/librustc_incremental/persist/data.rs @@ -15,7 +15,6 @@ use rustc::hir::def_id::DefIndex; use rustc::hir::map::DefPathHash; use rustc::ich::Fingerprint; use rustc::middle::cstore::EncodedMetadataHash; -use std::sync::Arc; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; @@ -23,11 +22,11 @@ use rustc_data_structures::indexed_vec::{IndexVec, Idx}; #[derive(Debug, RustcEncodable, RustcDecodable)] pub struct SerializedDepGraph { /// The set of all DepNodes in the graph - pub nodes: IndexVec>, + pub nodes: IndexVec, /// For each DepNode, stores the list of edges originating from that /// DepNode. Encoded as a [start, end) pair indexing into edge_list_data, /// which holds the actual DepNodeIndices of the target nodes. - pub edge_list_indices: Vec<(u32, u32)>, + pub edge_list_indices: IndexVec, /// A flattened list of all edge targets in the graph. Edge sources are /// implicit in edge_list_indices. pub edge_list_data: Vec, @@ -35,7 +34,7 @@ pub struct SerializedDepGraph { /// These are output nodes that have no incoming edges. We track /// these separately so that when we reload all edges, we don't /// lose track of these nodes. - pub bootstrap_outputs: Vec>, + pub bootstrap_outputs: Vec, /// These are hashes of two things: /// - the HIR nodes in this crate @@ -56,7 +55,14 @@ pub struct SerializedDepGraph { /// will be different when we next compile) related to each node, /// but rather the `DefPathIndex`. This can then be retraced /// to find the current def-id. - pub hashes: Vec, + pub hashes: Vec<(DepNodeIndex, Fingerprint)>, +} + +impl SerializedDepGraph { + pub fn edge_targets_from(&self, source: DepNodeIndex) -> &[DepNodeIndex] { + let targets = self.edge_list_indices[source]; + &self.edge_list_data[targets.0 as usize .. targets.1 as usize] + } } /// The index of a DepNode in the SerializedDepGraph::nodes array. @@ -85,20 +91,10 @@ impl Idx for DepNodeIndex { } } -#[derive(Debug, RustcEncodable, RustcDecodable)] -pub struct SerializedHash { - /// def-id of thing being hashed - pub dep_node: DepNode, - - /// the hash as of previous compilation, computed by code in - /// `hash` module - pub hash: Fingerprint, -} - #[derive(Debug, RustcEncodable, RustcDecodable)] pub struct SerializedWorkProduct { /// node that produced the work-product - pub id: Arc, + pub id: WorkProductId, /// work-product data itself pub work_product: WorkProduct, @@ -127,10 +123,6 @@ pub struct SerializedMetadataHashes { /// (matching the one found in this structure). pub entry_hashes: Vec, - /// This map contains fingerprints that are not specific to some DefId but - /// describe something global to the whole crate. - pub global_hashes: Vec<(DepNode<()>, Fingerprint)>, - /// For each DefIndex (as it occurs in SerializedMetadataHash), this /// map stores the DefPathIndex (as it occurs in DefIdDirectory), so /// that we can find the new DefId for a SerializedMetadataHash in a diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index 3a428bd7b8..3f3dc10365 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -40,8 +40,9 @@ //! previous revision to compare things to. //! +use super::data::DepNodeIndex; use super::load::DirtyNodes; -use rustc::dep_graph::{DepGraphQuery, DepNode}; +use rustc::dep_graph::{DepGraphQuery, DepNode, DepKind}; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -50,6 +51,7 @@ use rustc::ich::{Fingerprint, ATTR_DIRTY, ATTR_CLEAN, ATTR_DIRTY_METADATA, ATTR_CLEAN_METADATA}; use syntax::ast::{self, Attribute, NestedMetaItem}; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; +use rustc_data_structures::indexed_vec::IndexVec; use syntax_pos::Span; use rustc::ty::TyCtxt; @@ -57,6 +59,7 @@ const LABEL: &'static str = "label"; const CFG: &'static str = "cfg"; pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + nodes: &IndexVec, dirty_inputs: &DirtyNodes) { // can't add `#[rustc_dirty]` etc without opting in to this feature if !tcx.sess.features.borrow().rustc_attrs { @@ -64,13 +67,15 @@ pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } let _ignore = tcx.dep_graph.in_ignore(); - let def_path_hash_to_def_id = tcx.def_path_hash_to_def_id.as_ref().unwrap(); - let dirty_inputs: FxHashSet> = + let dirty_inputs: FxHashSet = dirty_inputs.keys() - .filter_map(|dep_node| { - dep_node.map_def(|def_path_hash| { - def_path_hash_to_def_id.get(def_path_hash).cloned() - }) + .filter_map(|dep_node_index| { + let dep_node = nodes[*dep_node_index]; + if dep_node.extract_def_id(tcx).is_some() { + Some(dep_node) + } else { + None + } }) .collect(); @@ -100,18 +105,19 @@ pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub struct DirtyCleanVisitor<'a, 'tcx:'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, - query: &'a DepGraphQuery, - dirty_inputs: FxHashSet>, + query: &'a DepGraphQuery, + dirty_inputs: FxHashSet, checked_attrs: FxHashSet, } impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { - fn dep_node(&self, attr: &Attribute, def_id: DefId) -> DepNode { + fn dep_node(&self, attr: &Attribute, def_id: DefId) -> DepNode { + let def_path_hash = self.tcx.def_path_hash(def_id); for item in attr.meta_item_list().unwrap_or_else(Vec::new) { if item.check_name(LABEL) { let value = expect_associated_value(self.tcx, &item); - match DepNode::from_label_string(&value.as_str(), def_id) { - Ok(def_id) => return def_id, + match DepNode::from_label_string(&value.as_str(), def_path_hash) { + Ok(dep_node) => return dep_node, Err(()) => { self.tcx.sess.span_fatal( item.span, @@ -124,24 +130,30 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { self.tcx.sess.span_fatal(attr.span, "no `label` found"); } - fn dep_node_str(&self, dep_node: &DepNode) -> DepNode { - dep_node.map_def(|&def_id| Some(self.tcx.item_path_str(def_id))).unwrap() + fn dep_node_str(&self, dep_node: &DepNode) -> String { + if let Some(def_id) = dep_node.extract_def_id(self.tcx) { + format!("{:?}({})", + dep_node.kind, + self.tcx.item_path_str(def_id)) + } else { + format!("{:?}({:?})", dep_node.kind, dep_node.hash) + } } - fn assert_dirty(&self, item_span: Span, dep_node: DepNode) { + fn assert_dirty(&self, item_span: Span, dep_node: DepNode) { debug!("assert_dirty({:?})", dep_node); - match dep_node { - DepNode::Krate | - DepNode::Hir(_) | - DepNode::HirBody(_) => { + match dep_node.kind { + DepKind::Krate | + DepKind::Hir | + DepKind::HirBody => { // HIR nodes are inputs, so if we are asserting that the HIR node is // dirty, we check the dirty input set. if !self.dirty_inputs.contains(&dep_node) { let dep_node_str = self.dep_node_str(&dep_node); self.tcx.sess.span_err( item_span, - &format!("`{:?}` not found in dirty set, but should be dirty", + &format!("`{}` not found in dirty set, but should be dirty", dep_node_str)); } } @@ -152,25 +164,25 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { let dep_node_str = self.dep_node_str(&dep_node); self.tcx.sess.span_err( item_span, - &format!("`{:?}` found in dep graph, but should be dirty", dep_node_str)); + &format!("`{}` found in dep graph, but should be dirty", dep_node_str)); } } } } - fn assert_clean(&self, item_span: Span, dep_node: DepNode) { + fn assert_clean(&self, item_span: Span, dep_node: DepNode) { debug!("assert_clean({:?})", dep_node); - match dep_node { - DepNode::Krate | - DepNode::Hir(_) | - DepNode::HirBody(_) => { + match dep_node.kind { + DepKind::Krate | + DepKind::Hir | + DepKind::HirBody => { // For HIR nodes, check the inputs. if self.dirty_inputs.contains(&dep_node) { let dep_node_str = self.dep_node_str(&dep_node); self.tcx.sess.span_err( item_span, - &format!("`{:?}` found in dirty-node set, but should be clean", + &format!("`{}` found in dirty-node set, but should be clean", dep_node_str)); } } @@ -180,7 +192,7 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { let dep_node_str = self.dep_node_str(&dep_node); self.tcx.sess.span_err( item_span, - &format!("`{:?}` not found in dep graph, but should be clean", + &format!("`{}` not found in dep graph, but should be clean", dep_node_str)); } } diff --git a/src/librustc_incremental/persist/file_format.rs b/src/librustc_incremental/persist/file_format.rs index 5c20f65274..13b019af2e 100644 --- a/src/librustc_incremental/persist/file_format.rs +++ b/src/librustc_incremental/persist/file_format.rs @@ -117,9 +117,9 @@ fn report_format_mismatch(sess: &Session, file: &Path, message: &str) { debug!("read_file: {}", message); if sess.opts.debugging_opts.incremental_info { - println!("incremental: ignoring cache artifact `{}`: {}", - file.file_name().unwrap().to_string_lossy(), - message); + eprintln!("incremental: ignoring cache artifact `{}`: {}", + file.file_name().unwrap().to_string_lossy(), + message); } } diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs index 2a4a01cd4a..28d33d9528 100644 --- a/src/librustc_incremental/persist/fs.rs +++ b/src/librustc_incremental/persist/fs.rs @@ -435,8 +435,8 @@ fn copy_files(target_dir: &Path, } if print_stats_on_success { - println!("incremental: session directory: {} files hard-linked", files_linked); - println!("incremental: session directory: {} files copied", files_copied); + eprintln!("incremental: session directory: {} files hard-linked", files_linked); + eprintln!("incremental: session directory: {} files copied", files_copied); } Ok(files_linked > 0 || files_copied == 0) diff --git a/src/librustc_incremental/persist/hash.rs b/src/librustc_incremental/persist/hash.rs index 6ab280be47..0e8ffb9ee3 100644 --- a/src/librustc_incremental/persist/hash.rs +++ b/src/librustc_incremental/persist/hash.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::dep_graph::DepNode; -use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX}; +use rustc::dep_graph::{DepNode, DepKind}; +use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::hir::svh::Svh; use rustc::ich::Fingerprint; use rustc::ty::TyCtxt; @@ -29,9 +29,8 @@ use std::fmt::Debug; pub struct HashContext<'a, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'tcx, 'tcx>, incremental_hashes_map: &'a IncrementalHashesMap, - item_metadata_hashes: FxHashMap, + metadata_hashes: FxHashMap, crate_hashes: FxHashMap, - global_metadata_hashes: FxHashMap, Fingerprint>, } impl<'a, 'tcx> HashContext<'a, 'tcx> { @@ -41,38 +40,34 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { HashContext { tcx: tcx, incremental_hashes_map: incremental_hashes_map, - item_metadata_hashes: FxHashMap(), + metadata_hashes: FxHashMap(), crate_hashes: FxHashMap(), - global_metadata_hashes: FxHashMap(), } } - pub fn is_hashable(dep_node: &DepNode) -> bool { - match *dep_node { - DepNode::Krate | - DepNode::Hir(_) | - DepNode::HirBody(_) => + pub fn is_hashable(tcx: TyCtxt, dep_node: &DepNode) -> bool { + match dep_node.kind { + DepKind::Krate | + DepKind::Hir | + DepKind::HirBody => true, - DepNode::MetaData(def_id) | - DepNode::GlobalMetaData(def_id, _) => !def_id.is_local(), + DepKind::MetaData => { + let def_id = dep_node.extract_def_id(tcx).unwrap(); + !def_id.is_local() + } _ => false, } } - pub fn hash(&mut self, dep_node: &DepNode) -> Option { - match *dep_node { - DepNode::Krate => { + pub fn hash(&mut self, dep_node: &DepNode) -> Option { + match dep_node.kind { + DepKind::Krate => { Some(self.incremental_hashes_map[dep_node]) } // HIR nodes (which always come from our crate) are an input: - DepNode::Hir(def_id) | - DepNode::HirBody(def_id) => { - assert!(def_id.is_local(), - "cannot hash HIR for non-local def-id {:?} => {:?}", - def_id, - self.tcx.item_path_str(def_id)); - + DepKind::Hir | + DepKind::HirBody => { Some(self.incremental_hashes_map[dep_node]) } @@ -80,16 +75,15 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { // MetaData nodes from *our* crates are an *output*; we // don't hash them, but we do compute a hash for them and // save it for others to use. - DepNode::MetaData(def_id) if !def_id.is_local() => { - Some(self.metadata_hash(def_id, - def_id.krate, - |this| &mut this.item_metadata_hashes)) - } - - DepNode::GlobalMetaData(def_id, kind) => { - Some(self.metadata_hash(DepNode::GlobalMetaData(def_id, kind), + DepKind::MetaData => { + let def_id = dep_node.extract_def_id(self.tcx).unwrap(); + if !def_id.is_local() { + Some(self.metadata_hash(def_id, def_id.krate, - |this| &mut this.global_metadata_hashes)) + |this| &mut this.metadata_hashes)) + } else { + None + } } _ => { @@ -217,27 +211,11 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { let def_id = DefId { krate: cnum, index: serialized_hash.def_index }; // record the hash for this dep-node - let old = self.item_metadata_hashes.insert(def_id, serialized_hash.hash); + let old = self.metadata_hashes.insert(def_id, serialized_hash.hash); debug!("load_from_data: def_id={:?} hash={}", def_id, serialized_hash.hash); assert!(old.is_none(), "already have hash for {:?}", def_id); } - for (dep_node, fingerprint) in serialized_hashes.global_hashes { - // Here we need to remap the CrateNum in the DepNode. - let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX }; - let dep_node = match dep_node { - DepNode::GlobalMetaData(_, kind) => DepNode::GlobalMetaData(def_id, kind), - other => { - bug!("unexpected DepNode variant: {:?}", other) - } - }; - - // record the hash for this dep-node - debug!("load_from_data: def_node={:?} hash={}", dep_node, fingerprint); - let old = self.global_metadata_hashes.insert(dep_node.clone(), fingerprint); - assert!(old.is_none(), "already have hash for {:?}", dep_node); - } - Ok(()) } } diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index b30a1f4d32..2c43896ec7 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -10,19 +10,17 @@ //! Code to save/load the dep-graph from files. -use rustc::dep_graph::{DepNode, WorkProductId}; +use rustc::dep_graph::{DepNode, WorkProductId, DepKind}; use rustc::hir::def_id::DefId; -use rustc::hir::map::DefPathHash; use rustc::hir::svh::Svh; use rustc::ich::Fingerprint; use rustc::session::Session; use rustc::ty::TyCtxt; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_serialize::Decodable as RustcDecodable; use rustc_serialize::opaque::Decoder; -use std::default::Default; use std::path::{Path}; -use std::sync::Arc; use IncrementalHashesMap; use super::data::*; @@ -34,7 +32,7 @@ use super::work_product; // The key is a dirty node. The value is **some** base-input that we // can blame it on. -pub type DirtyNodes = FxHashMap, DepNode>; +pub type DirtyNodes = FxHashMap; /// If we are in incremental mode, and a previous dep-graph exists, /// then load up those nodes/edges that are still valid into the @@ -119,14 +117,20 @@ fn load_data(sess: &Session, path: &Path) -> Option> { None } -/// Try to convert a DepNode from the old dep-graph into a DepNode in the -/// current graph by mapping the DefPathHash to a valid DefId. This will fail -/// if the DefPathHash refers to something that has been removed (because -/// there is no DefId for that thing anymore). -fn retrace(tcx: TyCtxt, dep_node: &DepNode) -> Option> { - dep_node.map_def(|def_path_hash| { - tcx.def_path_hash_to_def_id.as_ref().unwrap().get(def_path_hash).cloned() - }) +/// Check if a DepNode from the previous dep-graph refers to something that +/// still exists in the current compilation session. Only works for DepNode +/// variants that represent inputs (HIR and imported Metadata). +fn does_still_exist(tcx: TyCtxt, dep_node: &DepNode) -> bool { + match dep_node.kind { + DepKind::Hir | + DepKind::HirBody | + DepKind::MetaData => { + dep_node.extract_def_id(tcx).is_some() + } + _ => { + bug!("unexpected Input DepNode: {:?}", dep_node) + } + } } /// Decode the dep graph and load the edges/nodes that are still clean @@ -147,8 +151,8 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if prev_commandline_args_hash != tcx.sess.opts.dep_tracking_hash() { if tcx.sess.opts.debugging_opts.incremental_info { - println!("incremental: completely ignoring cache because of \ - differing commandline arguments"); + eprintln!("incremental: completely ignoring cache because of \ + differing commandline arguments"); } // We can't reuse the cache, purge it. debug!("decode_dep_graph: differing commandline arg hashes"); @@ -162,86 +166,52 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let serialized_dep_graph = SerializedDepGraph::decode(&mut dep_graph_decoder)?; - let edge_map: FxHashMap, Vec>> = { - let capacity = serialized_dep_graph.edge_list_data.len(); - let mut edge_map = FxHashMap::with_capacity_and_hasher(capacity, Default::default()); - - for (node_index, source) in serialized_dep_graph.nodes.iter().enumerate() { - let (start, end) = serialized_dep_graph.edge_list_indices[node_index]; - let targets = - (&serialized_dep_graph.edge_list_data[start as usize .. end as usize]) - .into_iter() - .map(|&node_index| serialized_dep_graph.nodes[node_index].clone()) - .collect(); - - edge_map.insert(source.clone(), targets); - } - - edge_map - }; - // Compute the set of nodes from the old graph where some input - // has changed or been removed. These are "raw" source nodes, - // which means that they still use the original `DefPathIndex` - // values from the encoding, rather than having been retraced to a - // `DefId`. The reason for this is that this way we can include - // nodes that have been removed (which no longer have a `DefId` in - // the current compilation). + // has changed or been removed. let dirty_raw_nodes = initial_dirty_nodes(tcx, incremental_hashes_map, + &serialized_dep_graph.nodes, &serialized_dep_graph.hashes); - let dirty_raw_nodes = transitive_dirty_nodes(&edge_map, dirty_raw_nodes); + let dirty_raw_nodes = transitive_dirty_nodes(&serialized_dep_graph, + dirty_raw_nodes); // Recreate the edges in the graph that are still clean. let mut clean_work_products = FxHashSet(); let mut dirty_work_products = FxHashSet(); // incomplete; just used to suppress debug output - let mut extra_edges = vec![]; - for (source, targets) in &edge_map { - for target in targets { - process_edges(tcx, source, target, &edge_map, &dirty_raw_nodes, - &mut clean_work_products, &mut dirty_work_products, &mut extra_edges); + for (source, targets) in serialized_dep_graph.edge_list_indices.iter_enumerated() { + let target_begin = targets.0 as usize; + let target_end = targets.1 as usize; + + for &target in &serialized_dep_graph.edge_list_data[target_begin .. target_end] { + process_edge(tcx, + source, + target, + &serialized_dep_graph.nodes, + &dirty_raw_nodes, + &mut clean_work_products, + &mut dirty_work_products, + &work_products); } } - // Recreate bootstrap outputs, which are outputs that have no incoming edges (and hence cannot - // be dirty). + // Recreate bootstrap outputs, which are outputs that have no incoming edges + // (and hence cannot be dirty). for bootstrap_output in &serialized_dep_graph.bootstrap_outputs { - if let Some(n) = retrace(tcx, bootstrap_output) { - if let DepNode::WorkProduct(ref wp) = n { - clean_work_products.insert(wp.clone()); - } - - tcx.dep_graph.with_task(n, (), (), create_node); - - fn create_node((): (), (): ()) { - // just create the node with no inputs - } + if let DepKind::WorkProduct = bootstrap_output.kind { + let wp_id = WorkProductId::from_fingerprint(bootstrap_output.hash); + clean_work_products.insert(wp_id); } - } - // Subtle. Sometimes we have intermediate nodes that we can't recreate in the new graph. - // This is pretty unusual but it arises in a scenario like this: - // - // Hir(X) -> Foo(Y) -> Bar - // - // Note that the `Hir(Y)` is not an input to `Foo(Y)` -- this - // almost never happens, but can happen in some obscure - // scenarios. In that case, if `Y` is removed, then we can't - // recreate `Foo(Y)` (the def-id `Y` no longer exists); what we do - // then is to push the edge `Hir(X) -> Bar` onto `extra_edges` - // (along with any other targets of `Foo(Y)`). We will then add - // the edge from `Hir(X)` to `Bar` (or, if `Bar` itself cannot be - // recreated, to the targets of `Bar`). - while let Some((source, target)) = extra_edges.pop() { - process_edges(tcx, source, target, &edge_map, &dirty_raw_nodes, - &mut clean_work_products, &mut dirty_work_products, &mut extra_edges); + tcx.dep_graph.add_node_directly(*bootstrap_output); } // Add in work-products that are still clean, and delete those that are // dirty. reconcile_work_products(tcx, work_products, &clean_work_products); - dirty_clean::check_dirty_clean_annotations(tcx, &dirty_raw_nodes); + dirty_clean::check_dirty_clean_annotations(tcx, + &serialized_dep_graph.nodes, + &dirty_raw_nodes); load_prev_metadata_hashes(tcx, &mut *incremental_hashes_map.prev_metadata_hashes.borrow_mut()); @@ -252,70 +222,65 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, /// a bit vector where the index is the DefPathIndex. fn initial_dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, incremental_hashes_map: &IncrementalHashesMap, - serialized_hashes: &[SerializedHash]) + nodes: &IndexVec, + serialized_hashes: &[(DepNodeIndex, Fingerprint)]) -> DirtyNodes { let mut hcx = HashContext::new(tcx, incremental_hashes_map); let mut dirty_nodes = FxHashMap(); - let print_removed_message = |dep_node: &DepNode<_>| { - if tcx.sess.opts.debugging_opts.incremental_dump_hash { - println!("node {:?} is dirty as it was removed", dep_node); - } + for &(dep_node_index, prev_hash) in serialized_hashes { + let dep_node = nodes[dep_node_index]; + if does_still_exist(tcx, &dep_node) { + let current_hash = hcx.hash(&dep_node).unwrap_or_else(|| { + bug!("Cannot find current ICH for input that still exists?") + }); - debug!("initial_dirty_nodes: {:?} is dirty as it was removed", dep_node); - }; - - for hash in serialized_hashes { - if let Some(dep_node) = retrace(tcx, &hash.dep_node) { - if let Some(current_hash) = hcx.hash(&dep_node) { - if current_hash == hash.hash { - debug!("initial_dirty_nodes: {:?} is clean (hash={:?})", - dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(), + if current_hash == prev_hash { + debug!("initial_dirty_nodes: {:?} is clean (hash={:?})", + dep_node, current_hash); - continue; - } - - if tcx.sess.opts.debugging_opts.incremental_dump_hash { - println!("node {:?} is dirty as hash is {:?} was {:?}", - dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(), - current_hash, - hash.hash); - } + continue; + } - debug!("initial_dirty_nodes: {:?} is dirty as hash is {:?}, was {:?}", - dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(), - current_hash, - hash.hash); - } else { - print_removed_message(&hash.dep_node); + if tcx.sess.opts.debugging_opts.incremental_dump_hash { + println!("node {:?} is dirty as hash is {:?}, was {:?}", + dep_node, + current_hash, + prev_hash); } + + debug!("initial_dirty_nodes: {:?} is dirty as hash is {:?}, was {:?}", + dep_node, + current_hash, + prev_hash); } else { - print_removed_message(&hash.dep_node); - } + if tcx.sess.opts.debugging_opts.incremental_dump_hash { + println!("node {:?} is dirty as it was removed", dep_node); + } - dirty_nodes.insert(hash.dep_node.clone(), hash.dep_node.clone()); + debug!("initial_dirty_nodes: {:?} is dirty as it was removed", dep_node); + } + dirty_nodes.insert(dep_node_index, dep_node_index); } dirty_nodes } -fn transitive_dirty_nodes(edge_map: &FxHashMap, Vec>>, +fn transitive_dirty_nodes(serialized_dep_graph: &SerializedDepGraph, mut dirty_nodes: DirtyNodes) -> DirtyNodes { - let mut stack: Vec<(DepNode, DepNode)> = vec![]; - stack.extend(dirty_nodes.iter().map(|(s, b)| (s.clone(), b.clone()))); + let mut stack: Vec<(DepNodeIndex, DepNodeIndex)> = vec![]; + stack.extend(dirty_nodes.iter().map(|(&s, &b)| (s, b))); while let Some((source, blame)) = stack.pop() { // we know the source is dirty (because of the node `blame`)... - assert!(dirty_nodes.contains_key(&source)); + debug_assert!(dirty_nodes.contains_key(&source)); // ...so we dirty all the targets (with the same blame) - if let Some(targets) = edge_map.get(&source) { - for target in targets { - if !dirty_nodes.contains_key(target) { - dirty_nodes.insert(target.clone(), blame.clone()); - stack.push((target.clone(), blame.clone())); - } + for &target in serialized_dep_graph.edge_targets_from(source) { + if !dirty_nodes.contains_key(&target) { + dirty_nodes.insert(target, blame); + stack.push((target, blame)); } } } @@ -327,7 +292,7 @@ fn transitive_dirty_nodes(edge_map: &FxHashMap, Vec(tcx: TyCtxt<'a, 'tcx, 'tcx>, work_products: Vec, - clean_work_products: &FxHashSet>) { + clean_work_products: &FxHashSet) { debug!("reconcile_work_products({:?})", work_products); for swp in work_products { if !clean_work_products.contains(&swp.id) { @@ -341,8 +306,8 @@ fn reconcile_work_products<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, all_files_exist = false; if tcx.sess.opts.debugging_opts.incremental_info { - println!("incremental: could not find file for up-to-date work product: {}", - path.display()); + eprintln!("incremental: could not find file for \ + up-to-date work product: {}", path.display()); } } } @@ -367,6 +332,7 @@ fn delete_dirty_work_product(tcx: TyCtxt, fn load_prev_metadata_hashes(tcx: TyCtxt, output: &mut FxHashMap) { if !tcx.sess.opts.debugging_opts.query_dep_graph { + // Previous metadata hashes are only needed for testing. return } @@ -418,71 +384,76 @@ fn load_prev_metadata_hashes(tcx: TyCtxt, serialized_hashes.index_map.len()); } -fn process_edges<'a, 'tcx, 'edges>( +fn process_edge<'a, 'tcx, 'edges>( tcx: TyCtxt<'a, 'tcx, 'tcx>, - source: &'edges DepNode, - target: &'edges DepNode, - edges: &'edges FxHashMap, Vec>>, + source: DepNodeIndex, + target: DepNodeIndex, + nodes: &IndexVec, dirty_raw_nodes: &DirtyNodes, - clean_work_products: &mut FxHashSet>, - dirty_work_products: &mut FxHashSet>, - extra_edges: &mut Vec<(&'edges DepNode, &'edges DepNode)>) + clean_work_products: &mut FxHashSet, + dirty_work_products: &mut FxHashSet, + work_products: &[SerializedWorkProduct]) { // If the target is dirty, skip the edge. If this is an edge // that targets a work-product, we can print the blame // information now. - if let Some(blame) = dirty_raw_nodes.get(target) { - if let DepNode::WorkProduct(ref wp) = *target { + if let Some(&blame) = dirty_raw_nodes.get(&target) { + let target = nodes[target]; + if let DepKind::WorkProduct = target.kind { if tcx.sess.opts.debugging_opts.incremental_info { - if dirty_work_products.insert(wp.clone()) { + let wp_id = WorkProductId::from_fingerprint(target.hash); + + if dirty_work_products.insert(wp_id) { // Try to reconstruct the human-readable version of the // DepNode. This cannot be done for things that where // removed. - let readable_blame = if let Some(dep_node) = retrace(tcx, blame) { - dep_node.map_def(|&def_id| Some(tcx.def_path(def_id).to_string(tcx))) - .unwrap() + let blame = nodes[blame]; + let blame_str = if let Some(def_id) = blame.extract_def_id(tcx) { + format!("{:?}({})", + blame.kind, + tcx.def_path(def_id).to_string(tcx)) } else { - blame.map_def(|def_path_hash| Some(format!("{:?}", def_path_hash))) - .unwrap() + format!("{:?}", blame) }; - println!("incremental: module {:?} is dirty because {:?} \ - changed or was removed", - wp, - readable_blame); + let wp = work_products.iter().find(|swp| swp.id == wp_id).unwrap(); + + eprintln!("incremental: module {:?} is dirty because \ + {:?} changed or was removed", + wp.work_product.cgu_name, + blame_str); } } } return; } - // If the source is dirty, the target will be dirty. - assert!(!dirty_raw_nodes.contains_key(source)); - - // Retrace the source -> target edges to def-ids and then create - // an edge in the graph. Retracing may yield none if some of the - // data happens to have been removed. - if let Some(source_node) = retrace(tcx, source) { - if let Some(target_node) = retrace(tcx, target) { - let _task = tcx.dep_graph.in_task(target_node); - tcx.dep_graph.read(source_node); - if let DepNode::WorkProduct(ref wp) = *target { - clean_work_products.insert(wp.clone()); - } - } else { - // As discussed in `decode_dep_graph` above, sometimes the - // target cannot be recreated again, in which case we add - // edges to go from `source` to the targets of `target`. - extra_edges.extend( - edges[target].iter().map(|t| (source, t))); + // At this point we have asserted that the target is clean -- otherwise, we + // would have hit the return above. We can do some further consistency + // checks based on this fact: + + // We should never have an edge where the target is clean but the source + // was dirty. Otherwise something was wrong with the dirtying pass above: + debug_assert!(!dirty_raw_nodes.contains_key(&source)); + + // We also never should encounter an edge going from a removed input to a + // clean target because removing the input would have dirtied the input + // node and transitively dirtied the target. + debug_assert!(match nodes[source].kind { + DepKind::Hir | DepKind::HirBody | DepKind::MetaData => { + does_still_exist(tcx, &nodes[source]) + } + _ => true, + }); + + if !dirty_raw_nodes.contains_key(&target) { + let target = nodes[target]; + let source = nodes[source]; + tcx.dep_graph.add_edge_directly(source, target); + + if let DepKind::WorkProduct = target.kind { + let wp_id = WorkProductId::from_fingerprint(target.hash); + clean_work_products.insert(wp_id); } - } else { - // It's also possible that the source can't be created! But we - // can ignore such cases, because (a) if `source` is a HIR - // node, it would be considered dirty; and (b) in other cases, - // there must be some input to this node that is clean, and so - // we'll re-create the edges over in the case where target is - // undefined. } } - diff --git a/src/librustc_incremental/persist/preds/mod.rs b/src/librustc_incremental/persist/preds/mod.rs index e769641a4c..f7b6b7376d 100644 --- a/src/librustc_incremental/persist/preds/mod.rs +++ b/src/librustc_incremental/persist/preds/mod.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::dep_graph::{DepGraphQuery, DepNode}; -use rustc::hir::def_id::DefId; +use rustc::dep_graph::{DepGraphQuery, DepNode, DepKind}; use rustc::ich::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::graph::{Graph, NodeIndex}; @@ -26,7 +25,7 @@ pub struct Predecessors<'query> { // nodes) and all of the "work-products" we may care about // later. Other nodes may be retained if it keeps the overall size // of the graph down. - pub reduced_graph: Graph<&'query DepNode, ()>, + pub reduced_graph: Graph<&'query DepNode, ()>, // These are output nodes that have no incoming edges. We have to // track these specially because, when we load the data back up @@ -34,32 +33,31 @@ pub struct Predecessors<'query> { // to recreate the nodes where all incoming edges are clean; but // since we ordinarily just serialize edges, we wind up just // forgetting that bootstrap outputs even exist in that case.) - pub bootstrap_outputs: Vec<&'query DepNode>, + pub bootstrap_outputs: Vec<&'query DepNode>, // For the inputs (hir/foreign-metadata), we include hashes. - pub hashes: FxHashMap<&'query DepNode, Fingerprint>, + pub hashes: FxHashMap<&'query DepNode, Fingerprint>, } impl<'q> Predecessors<'q> { - pub fn new(query: &'q DepGraphQuery, hcx: &mut HashContext) -> Self { + pub fn new(query: &'q DepGraphQuery, hcx: &mut HashContext) -> Self { let tcx = hcx.tcx; // Find the set of "start nodes". These are nodes that we will // possibly query later. - let is_output = |node: &DepNode| -> bool { - match *node { - DepNode::WorkProduct(_) => true, - DepNode::MetaData(ref def_id) => { + let is_output = |node: &DepNode| -> bool { + match node.kind { + DepKind::WorkProduct => true, + DepKind::MetaData => { // We do *not* create dep-nodes for the current crate's // metadata anymore, just for metadata that we import/read // from other crates. - debug_assert!(!def_id.is_local()); + debug_assert!(!node.extract_def_id(tcx).unwrap().is_local()); false } // if -Z query-dep-graph is passed, save more extended data // to enable better unit testing - DepNode::TypeckTables(_) | - DepNode::TransCrateItem(_) => tcx.sess.opts.debugging_opts.query_dep_graph, + DepKind::TypeckTables => tcx.sess.opts.debugging_opts.query_dep_graph, _ => false, } @@ -67,7 +65,9 @@ impl<'q> Predecessors<'q> { // Reduce the graph to the most important nodes. let compress::Reduction { graph, input_nodes } = - compress::reduce_graph(&query.graph, HashContext::is_hashable, |n| is_output(n)); + compress::reduce_graph(&query.graph, + |n| HashContext::is_hashable(tcx, n), + |n| is_output(n)); let mut hashes = FxHashMap(); for input_index in input_nodes { @@ -81,8 +81,8 @@ impl<'q> Predecessors<'q> { // Not all inputs might have been reachable from an output node, // but we still want their hash for our unit tests. let hir_nodes = query.graph.all_nodes().iter().filter_map(|node| { - match node.data { - DepNode::Hir(_) => Some(&node.data), + match node.data.kind { + DepKind::Hir => Some(&node.data), _ => None, } }); @@ -93,7 +93,7 @@ impl<'q> Predecessors<'q> { } } - let bootstrap_outputs: Vec<&'q DepNode> = + let bootstrap_outputs: Vec<&'q DepNode> = (0 .. graph.len_nodes()) .map(NodeIndex) .filter(|&n| graph.incoming_edges(n).next().is_none()) diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index 6d717d6f40..1bdd4f851f 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -11,7 +11,6 @@ use rustc::dep_graph::DepNode; use rustc::hir::def_id::DefId; use rustc::hir::svh::Svh; -use rustc::hir::map::DefPathHash; use rustc::ich::Fingerprint; use rustc::middle::cstore::EncodedMetadataHashes; use rustc::session::Session; @@ -48,8 +47,8 @@ pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let query = tcx.dep_graph.query(); if tcx.sess.opts.debugging_opts.incremental_info { - println!("incremental: {} nodes in dep-graph", query.graph.len_nodes()); - println!("incremental: {} edges in dep-graph", query.graph.len_edges()); + eprintln!("incremental: {} nodes in dep-graph", query.graph.len_nodes()); + eprintln!("incremental: {} edges in dep-graph", query.graph.len_edges()); } let mut hcx = HashContext::new(tcx, incremental_hashes_map); @@ -174,19 +173,15 @@ pub fn encode_dep_graph(tcx: TyCtxt, // First encode the commandline arguments hash tcx.sess.opts.dep_tracking_hash().encode(encoder)?; - let to_hash_based_node = |dep_node: &DepNode| { - dep_node.map_def(|&def_id| Some(tcx.def_path_hash(def_id))).unwrap() - }; - // NB: We rely on this Vec being indexable by reduced_graph's NodeIndex. - let nodes: IndexVec> = preds + let mut nodes: IndexVec = preds .reduced_graph .all_nodes() .iter() - .map(|node| to_hash_based_node(node.data)) + .map(|node| node.data.clone()) .collect(); - let mut edge_list_indices = Vec::with_capacity(nodes.len()); + let mut edge_list_indices = IndexVec::with_capacity(nodes.len()); let mut edge_list_data = Vec::with_capacity(preds.reduced_graph.len_edges()); for node_index in 0 .. nodes.len() { @@ -201,43 +196,71 @@ pub fn encode_dep_graph(tcx: TyCtxt, edge_list_indices.push((start, end)); } - // Let's make we had no overflow there. + // Let's make sure we had no overflow there. assert!(edge_list_data.len() <= ::std::u32::MAX as usize); // Check that we have a consistent number of edges. assert_eq!(edge_list_data.len(), preds.reduced_graph.len_edges()); - let bootstrap_outputs = preds - .bootstrap_outputs - .iter() - .map(|n| to_hash_based_node(n)) - .collect(); + let bootstrap_outputs = preds.bootstrap_outputs + .iter() + .map(|dep_node| (**dep_node).clone()) + .collect(); + + // Next, build the map of content hashes. To this end, we need to transform + // the (DepNode -> Fingerprint) map that we have into a + // (DepNodeIndex -> Fingerprint) map. This may necessitate adding nodes back + // to the dep-graph that have been filtered out during reduction. + let content_hashes = { + // We have to build a (DepNode -> DepNodeIndex) map. We over-allocate a + // little because we expect some more nodes to be added. + let capacity = (nodes.len() * 120) / 100; + let mut node_to_index = FxHashMap::with_capacity_and_hasher(capacity, + Default::default()); + // Add the nodes we already have in the graph. + node_to_index.extend(nodes.iter_enumerated() + .map(|(index, &node)| (node, index))); + + let mut content_hashes = Vec::with_capacity(preds.hashes.len()); + + for (&&dep_node, &hash) in preds.hashes.iter() { + let dep_node_index = *node_to_index + .entry(dep_node) + .or_insert_with(|| { + // There is no DepNodeIndex for this DepNode yet. This + // happens when the DepNode got filtered out during graph + // reduction. Since we have a content hash for the DepNode, + // we add it back to the graph. + let next_index = nodes.len(); + nodes.push(dep_node); + + debug_assert_eq!(next_index, edge_list_indices.len()); + // Push an empty list of edges + edge_list_indices.push((0,0)); + + DepNodeIndex::new(next_index) + }); + + content_hashes.push((dep_node_index, hash)); + } - let hashes = preds - .hashes - .iter() - .map(|(&dep_node, &hash)| { - SerializedHash { - dep_node: to_hash_based_node(dep_node), - hash: hash, - } - }) - .collect(); + content_hashes + }; let graph = SerializedDepGraph { nodes, edge_list_indices, edge_list_data, bootstrap_outputs, - hashes, + hashes: content_hashes, }; // Encode the graph data. graph.encode(encoder)?; if tcx.sess.opts.debugging_opts.incremental_info { - println!("incremental: {} nodes in reduced dep-graph", graph.nodes.len()); - println!("incremental: {} edges in serialized dep-graph", graph.edge_list_data.len()); - println!("incremental: {} hashes in serialized dep-graph", graph.hashes.len()); + eprintln!("incremental: {} nodes in reduced dep-graph", graph.nodes.len()); + eprintln!("incremental: {} edges in serialized dep-graph", graph.edge_list_data.len()); + eprintln!("incremental: {} hashes in serialized dep-graph", graph.hashes.len()); } if tcx.sess.opts.debugging_opts.incremental_dump_hash { @@ -255,9 +278,11 @@ pub fn encode_metadata_hashes(tcx: TyCtxt, current_metadata_hashes: &mut FxHashMap, encoder: &mut Encoder) -> io::Result<()> { + assert_eq!(metadata_hashes.hashes.len(), + metadata_hashes.hashes.iter().map(|x| (x.def_index, ())).collect::>().len()); + let mut serialized_hashes = SerializedMetadataHashes { - entry_hashes: metadata_hashes.entry_hashes.to_vec(), - global_hashes: metadata_hashes.global_hashes.to_vec(), + entry_hashes: metadata_hashes.hashes.to_vec(), index_map: FxHashMap() }; diff --git a/src/librustc_incremental/persist/work_product.rs b/src/librustc_incremental/persist/work_product.rs index 0e9f906154..8f99ce91a6 100644 --- a/src/librustc_incremental/persist/work_product.rs +++ b/src/librustc_incremental/persist/work_product.rs @@ -16,7 +16,6 @@ use rustc::session::Session; use rustc::session::config::OutputType; use rustc::util::fs::link_or_copy; use std::path::PathBuf; -use std::sync::Arc; use std::fs as std_fs; pub fn save_trans_partition(sess: &Session, @@ -30,7 +29,7 @@ pub fn save_trans_partition(sess: &Session, if sess.opts.incremental.is_none() { return; } - let work_product_id = Arc::new(WorkProductId(cgu_name.to_string())); + let work_product_id = WorkProductId::from_cgu_name(cgu_name); let saved_files: Option> = files.iter() @@ -56,6 +55,7 @@ pub fn save_trans_partition(sess: &Session, }; let work_product = WorkProduct { + cgu_name: cgu_name.to_string(), input_hash: partition_hash, saved_files: saved_files, }; diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 3a4729e645..6726a6fa1f 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -32,7 +32,7 @@ use rustc::hir::def::Def; use rustc::hir::def_id::DefId; use rustc::cfg; use rustc::ty::subst::Substs; -use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::{self, Ty}; use rustc::traits::{self, Reveal}; use rustc::hir::map as hir_map; use util::nodemap::NodeSet; @@ -542,9 +542,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations { }; if self.impling_types.is_none() { - let debug_def = cx.tcx.trait_def(debug); let mut impls = NodeSet(); - debug_def.for_each_impl(cx.tcx, |d| { + cx.tcx.for_each_impl(debug, |d| { if let Some(ty_def) = cx.tcx.type_of(d).ty_to_def_id() { if let Some(node_id) = cx.tcx.hir.as_local_node_id(ty_def) { impls.insert(node_id); @@ -684,13 +683,9 @@ fn fl_lit_check_expr(cx: &EarlyContext, expr: &ast::Expr) { // These may occur in patterns // and can maybe contain float literals ExprKind::Unary(_, ref f) => fl_lit_check_expr(cx, f), - // These may occur in patterns - // and can't contain float literals - ExprKind::Path(..) => (), - // If something unhandled is encountered, we need to expand the - // search or ignore more ExprKinds. - _ => span_bug!(expr.span, "Unhandled expression {:?} in float lit pattern lint", - expr.node), + // Other kinds of exprs can't occur in patterns so we don't have to check them + // (ast_validation will emit an error if they occur) + _ => (), } } @@ -893,7 +888,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { for adjustment in cx.tables.expr_adjustments(expr) { if let Adjust::Deref(Some(deref)) = adjustment.kind { let (def_id, substs) = deref.method_call(cx.tcx, source); - if method_call_refers_to_method(cx.tcx, method, def_id, substs, id) { + if method_call_refers_to_method(cx, method, def_id, substs, id) { return true; } } @@ -904,7 +899,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { if cx.tables.is_method_call(expr) { let def_id = cx.tables.type_dependent_defs[&id].def_id(); let substs = cx.tables.node_substs(id); - if method_call_refers_to_method(cx.tcx, method, def_id, substs, id) { + if method_call_refers_to_method(cx, method, def_id, substs, id) { return true; } } @@ -920,8 +915,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { match def { Def::Method(def_id) => { let substs = cx.tables.node_substs(callee.id); - method_call_refers_to_method( - cx.tcx, method, def_id, substs, id) + method_call_refers_to_method(cx, method, def_id, substs, id) } _ => false, } @@ -932,12 +926,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { // Check if the method call to the method with the ID `callee_id` // and instantiated with `callee_substs` refers to method `method`. - fn method_call_refers_to_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + fn method_call_refers_to_method<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, method: &ty::AssociatedItem, callee_id: DefId, callee_substs: &Substs<'tcx>, expr_id: ast::NodeId) -> bool { + let tcx = cx.tcx; let callee_item = tcx.associated_item(callee_id); match callee_item.container { @@ -951,13 +946,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { let trait_ref = ty::TraitRef::from_method(tcx, trait_def_id, callee_substs); let trait_ref = ty::Binder(trait_ref); let span = tcx.hir.span(expr_id); - let param_env = tcx.param_env(method.def_id); let obligation = traits::Obligation::new(traits::ObligationCause::misc(span, expr_id), - param_env, + cx.param_env, trait_ref.to_poly_trait_predicate()); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let mut selcx = traits::SelectionContext::new(&infcx); match selcx.select(&obligation) { // The method comes from a `T: Trait` bound. @@ -1076,7 +1070,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { hir::ItemFn(.., ref generics, _) => { - if attr::contains_name(&it.attrs, "no_mangle") { + if attr::contains_name(&it.attrs, "no_mangle") && + !attr::contains_name(&it.attrs, "linkage") { if !cx.access_levels.is_reachable(it.id) { let msg = format!("function {} is marked #[no_mangle], but not exported", it.name); @@ -1155,24 +1150,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { if !def_id_is_transmute(cx, did) { return None; } - let typ = cx.tables.node_id_to_type(expr.id); - match typ.sty { - ty::TyFnDef(.., bare_fn) if bare_fn.abi() == RustIntrinsic => { - let from = bare_fn.inputs().skip_binder()[0]; - let to = *bare_fn.output().skip_binder(); - return Some((&from.sty, &to.sty)); - } - _ => (), - } + let sig = cx.tables.node_id_to_type(expr.id).fn_sig(cx.tcx); + let from = sig.inputs().skip_binder()[0]; + let to = *sig.output().skip_binder(); + return Some((&from.sty, &to.sty)); } None } fn def_id_is_transmute(cx: &LateContext, def_id: DefId) -> bool { - match cx.tcx.type_of(def_id).sty { - ty::TyFnDef(.., bfty) if bfty.abi() == RustIntrinsic => (), - _ => return false, - } + cx.tcx.fn_sig(def_id).abi() == RustIntrinsic && cx.tcx.item_name(def_id) == "transmute" } } @@ -1224,11 +1211,9 @@ impl LintPass for UnionsWithDropFields { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields { fn check_item(&mut self, ctx: &LateContext, item: &hir::Item) { if let hir::ItemUnion(ref vdata, _) = item.node { - let item_def_id = ctx.tcx.hir.local_def_id(item.id); - let param_env = ctx.tcx.param_env(item_def_id); for field in vdata.fields() { let field_ty = ctx.tcx.type_of(ctx.tcx.hir.local_def_id(field.id)); - if field_ty.needs_drop(ctx.tcx, param_env) { + if field_ty.needs_drop(ctx.tcx, ctx.param_env) { ctx.span_lint(UNIONS_WITH_DROP_FIELDS, field.span, "union contains a field with possibly non-trivial drop code, \ diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 9870842a28..a03f12c3df 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -35,10 +35,6 @@ #![feature(rustc_diagnostic_macros)] #![feature(slice_patterns)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] - #[macro_use] extern crate syntax; #[macro_use] @@ -188,6 +184,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { id: LintId::of(PRIVATE_IN_PUBLIC), reference: "issue #34537 ", }, + FutureIncompatibleInfo { + id: LintId::of(PUB_USE_OF_PRIVATE_EXTERN_CRATE), + reference: "issue #34537 ", + }, FutureIncompatibleInfo { id: LintId::of(PATTERNS_IN_FNS_WITHOUT_BODY), reference: "issue #35203 ", diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 3019165bfb..ac3977bd21 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -659,7 +659,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { fn check_foreign_fn(&mut self, id: ast::NodeId, decl: &hir::FnDecl) { let def_id = self.cx.tcx.hir.local_def_id(id); - let sig = self.cx.tcx.type_of(def_id).fn_sig(); + let sig = self.cx.tcx.fn_sig(def_id); let sig = self.cx.tcx.erase_late_bound_regions(&sig); for (input_ty, input_hir) in sig.inputs().iter().zip(&decl.inputs) { @@ -725,7 +725,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences { // sizes only make sense for non-generic types let item_def_id = cx.tcx.hir.local_def_id(it.id); let t = cx.tcx.type_of(item_def_id); - let param_env = cx.tcx.param_env(item_def_id).reveal_all(); + let param_env = cx.param_env.reveal_all(); let ty = cx.tcx.erase_regions(&t); let layout = ty.layout(cx.tcx, param_env).unwrap_or_else(|e| { bug!("failed to get layout for `{}`: {}", t, e) diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 0c82679c30..473c0f3ffd 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use rustc::hir::def_id::DefId; use rustc::ty; use rustc::ty::adjustment; use util::nodemap::FxHashMap; @@ -144,20 +145,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { ty::TyTuple(ref tys, _) if tys.is_empty() => return, ty::TyNever => return, ty::TyBool => return, - ty::TyAdt(def, _) => { - let attrs = cx.tcx.get_attrs(def.did); - check_must_use(cx, &attrs, s.span) - } + ty::TyAdt(def, _) => check_must_use(cx, def.did, s.span), _ => false, }; if !warned { cx.span_lint(UNUSED_RESULTS, s.span, "unused result"); } - fn check_must_use(cx: &LateContext, attrs: &[ast::Attribute], sp: Span) -> bool { - for attr in attrs { + fn check_must_use(cx: &LateContext, def_id: DefId, sp: Span) -> bool { + for attr in cx.tcx.get_attrs(def_id).iter() { if attr.check_name("must_use") { - let mut msg = "unused result which must be used".to_string(); + let mut msg = format!("unused `{}` which must be used", + cx.tcx.item_path_str(def_id)); // check for #[must_use="..."] if let Some(s) = attr.value_str() { msg.push_str(": "); diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index ba56885795..3f0f536960 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -60,6 +60,7 @@ fn main() { }); println!("cargo:rerun-if-changed={}", llvm_config.display()); + println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); // Test whether we're cross-compiling LLVM. This is a pretty rare case // currently where we're producing an LLVM for a different platform than @@ -88,7 +89,7 @@ fn main() { let mut optional_components = vec!["x86", "arm", "aarch64", "mips", "powerpc", "pnacl", - "systemz", "jsbackend", "msp430", "sparc", "nvptx"]; + "systemz", "jsbackend", "webassembly", "msp430", "sparc", "nvptx"]; let mut version_cmd = Command::new(&llvm_config); version_cmd.arg("--version"); diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index d7b575d90a..9f0ee95b5a 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -591,7 +591,9 @@ extern "C" { pub fn LLVMIsUndef(Val: ValueRef) -> Bool; // Operations on metadata + pub fn LLVMMDStringInContext(C: ContextRef, Str: *const c_char, SLen: c_uint) -> ValueRef; pub fn LLVMMDNodeInContext(C: ContextRef, Vals: *const ValueRef, Count: c_uint) -> ValueRef; + pub fn LLVMAddNamedMetadataOperand(M: ModuleRef, Name: *const c_char, Val: ValueRef); // Operations on scalar constants pub fn LLVMConstInt(IntTy: TypeRef, N: c_ulonglong, SignExtend: Bool) -> ValueRef; @@ -696,6 +698,7 @@ extern "C" { pub fn LLVMIsGlobalConstant(GlobalVar: ValueRef) -> Bool; pub fn LLVMSetGlobalConstant(GlobalVar: ValueRef, IsConstant: Bool); pub fn LLVMRustGetNamedValue(M: ModuleRef, Name: *const c_char) -> ValueRef; + pub fn LLVMSetTailCall(CallInst: ValueRef, IsTailCall: Bool); // Operations on functions pub fn LLVMAddFunction(M: ModuleRef, Name: *const c_char, FunctionTy: TypeRef) -> ValueRef; @@ -1332,6 +1335,8 @@ extern "C" { pub fn LLVMRustAddModuleFlag(M: ModuleRef, name: *const c_char, value: u32); + pub fn LLVMRustMetadataAsValue(C: ContextRef, MD: MetadataRef) -> ValueRef; + pub fn LLVMRustDIBuilderCreate(M: ModuleRef) -> DIBuilderRef; pub fn LLVMRustDIBuilderDispose(Builder: DIBuilderRef); @@ -1593,7 +1598,13 @@ extern "C" { Output: *const c_char, FileType: FileType) -> LLVMRustResult; - pub fn LLVMRustPrintModule(PM: PassManagerRef, M: ModuleRef, Output: *const c_char); + pub fn LLVMRustPrintModule(PM: PassManagerRef, + M: ModuleRef, + Output: *const c_char, + Demangle: extern fn(*const c_char, + size_t, + *mut c_char, + size_t) -> size_t); pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char); pub fn LLVMRustPrintPasses(); pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *const c_char); diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 790d493f19..947e433fdb 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -21,16 +21,13 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![deny(warnings)] -#![feature(associated_consts)] #![feature(box_syntax)] #![feature(concat_idents)] #![feature(libc)] #![feature(link_args)] #![feature(static_nobundle)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] +#![cfg_attr(stage0, feature(associated_consts))] extern crate libc; #[macro_use] @@ -389,6 +386,11 @@ pub fn initialize_available_targets() { LLVMInitializeHexagonTargetMC, LLVMInitializeHexagonAsmPrinter, LLVMInitializeHexagonAsmParser); + init_target!(llvm_component = "webassembly", + LLVMInitializeWebAssemblyTargetInfo, + LLVMInitializeWebAssemblyTarget, + LLVMInitializeWebAssemblyTargetMC, + LLVMInitializeWebAssemblyAsmPrinter); } pub fn last_error() -> Option { diff --git a/src/librustc_lsan/Cargo.toml b/src/librustc_lsan/Cargo.toml index 786883d213..087c316211 100644 --- a/src/librustc_lsan/Cargo.toml +++ b/src/librustc_lsan/Cargo.toml @@ -14,5 +14,6 @@ build_helper = { path = "../build_helper" } cmake = "0.1.18" [dependencies] +alloc = { path = "../liballoc" } alloc_system = { path = "../liballoc_system" } core = { path = "../libcore" } diff --git a/src/librustc_lsan/build.rs b/src/librustc_lsan/build.rs index da53571a24..3d2ae480de 100644 --- a/src/librustc_lsan/build.rs +++ b/src/librustc_lsan/build.rs @@ -32,4 +32,5 @@ fn main() { .build_target("lsan") .build(); } + println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); } diff --git a/src/librustc_lsan/lib.rs b/src/librustc_lsan/lib.rs index 54941362e8..e987b1f335 100644 --- a/src/librustc_lsan/lib.rs +++ b/src/librustc_lsan/lib.rs @@ -11,6 +11,8 @@ #![sanitizer_runtime] #![feature(sanitizer_runtime)] #![feature(alloc_system)] +#![cfg_attr(not(stage0), feature(allocator_api))] +#![cfg_attr(not(stage0), feature(global_allocator))] #![feature(staged_api)] #![no_std] #![unstable(feature = "sanitizer_runtime_lib", @@ -18,3 +20,10 @@ issue = "0")] extern crate alloc_system; + +#[cfg(not(stage0))] +use alloc_system::System; + +#[cfg(not(stage0))] +#[global_allocator] +static ALLOC: System = System; diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml index f47788ee03..67b459ea18 100644 --- a/src/librustc_metadata/Cargo.toml +++ b/src/librustc_metadata/Cargo.toml @@ -9,7 +9,7 @@ path = "lib.rs" crate-type = ["dylib"] [dependencies] -flate = { path = "../libflate" } +flate2 = "0.2" log = "0.3" owning_ref = "0.3.3" proc_macro = { path = "../libproc_macro" } diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 51f152991f..d15843b4f3 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -14,9 +14,9 @@ use cstore::{self, CStore, CrateSource, MetadataBlob}; use locator::{self, CratePaths}; use schema::{CrateRoot, Tracked}; -use rustc::dep_graph::{DepNode, GlobalMetaDataKind}; -use rustc::hir::def_id::{DefId, CrateNum, DefIndex, CRATE_DEF_INDEX}; +use rustc::hir::def_id::{CrateNum, DefIndex}; use rustc::hir::svh::Svh; +use rustc::middle::allocator::AllocatorKind; use rustc::middle::cstore::DepKind; use rustc::session::Session; use rustc::session::config::{Sanitizer, self}; @@ -41,6 +41,7 @@ use syntax::attr; use syntax::ext::base::SyntaxExtension; use syntax::feature_gate::{self, GateIssue}; use syntax::symbol::Symbol; +use syntax::visit; use syntax_pos::{Span, DUMMY_SP}; use log; @@ -516,14 +517,11 @@ impl<'a> CrateLoader<'a> { return cstore::CrateNumMap::new(); } - let dep_node = DepNode::GlobalMetaData(DefId { krate, index: CRATE_DEF_INDEX }, - GlobalMetaDataKind::CrateDeps); - // The map from crate numbers in the crate we're resolving to local crate numbers. // We map 0 and all other holes in the map to our parent crate. The "additional" // self-dependencies should be harmless. ::std::iter::once(krate).chain(crate_root.crate_deps - .get(&self.sess.dep_graph, dep_node) + .get_untracked() .decode(metadata) .map(|dep| { debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash); @@ -858,21 +856,48 @@ impl<'a> CrateLoader<'a> { return } - if !self.sess.crate_types.borrow().iter().all(|ct| { - match *ct { - // Link the runtime - config::CrateTypeExecutable => true, - // This crate will be compiled with the required - // instrumentation pass - config::CrateTypeRlib => false, - _ => { - self.sess.err(&format!("Only executables and rlibs can be \ - compiled with `-Z sanitizer`")); - false + // firstyear 2017 - during testing I was unable to access an OSX machine + // to make this work on different crate types. As a result, today I have + // only been able to test and support linux as a target. + if self.sess.target.target.llvm_target == "x86_64-unknown-linux-gnu" { + if !self.sess.crate_types.borrow().iter().all(|ct| { + match *ct { + // Link the runtime + config::CrateTypeStaticlib | + config::CrateTypeExecutable => true, + // This crate will be compiled with the required + // instrumentation pass + config::CrateTypeRlib | + config::CrateTypeDylib | + config::CrateTypeCdylib => + false, + _ => { + self.sess.err(&format!("Only executables, staticlibs, \ + cdylibs, dylibs and rlibs can be compiled with \ + `-Z sanitizer`")); + false + } } + }) { + return + } + } else { + if !self.sess.crate_types.borrow().iter().all(|ct| { + match *ct { + // Link the runtime + config::CrateTypeExecutable => true, + // This crate will be compiled with the required + // instrumentation pass + config::CrateTypeRlib => false, + _ => { + self.sess.err(&format!("Only executables and rlibs can be \ + compiled with `-Z sanitizer`")); + false + } + } + }) { + return } - }) { - return } let mut uses_std = false; @@ -892,7 +917,7 @@ impl<'a> CrateLoader<'a> { info!("loading sanitizer: {}", name); let symbol = Symbol::intern(name); - let dep_kind = DepKind::Implicit; + let dep_kind = DepKind::Explicit; let (_, data) = self.resolve_crate(&None, symbol, symbol, None, DUMMY_SP, PathKind::Crate, dep_kind); @@ -902,38 +927,52 @@ impl<'a> CrateLoader<'a> { self.sess.err(&format!("the crate `{}` is not a sanitizer runtime", name)); } + } else { + self.sess.err(&format!("Must link std to be compiled with `-Z sanitizer`")); } } } - fn inject_allocator_crate(&mut self) { - // Make sure that we actually need an allocator, if none of our - // dependencies need one then we definitely don't! - // - // Also, if one of our dependencies has an explicit allocator, then we - // also bail out as we don't need to implicitly inject one. - let mut needs_allocator = false; - let mut found_required_allocator = false; + fn inject_profiler_runtime(&mut self) { + if self.sess.opts.debugging_opts.profile { + info!("loading profiler"); + + let symbol = Symbol::intern("profiler_builtins"); + let dep_kind = DepKind::Implicit; + let (_, data) = + self.resolve_crate(&None, symbol, symbol, None, DUMMY_SP, + PathKind::Crate, dep_kind); + + // Sanity check the loaded crate to ensure it is indeed a profiler runtime + if !data.is_profiler_runtime(&self.sess.dep_graph) { + self.sess.err(&format!("the crate `profiler_builtins` is not \ + a profiler runtime")); + } + } + } + + fn inject_allocator_crate(&mut self, krate: &ast::Crate) { + let has_global_allocator = has_global_allocator(krate); + if has_global_allocator { + self.sess.has_global_allocator.set(true); + } + + // Check to see if we actually need an allocator. This desire comes + // about through the `#![needs_allocator]` attribute and is typically + // written down in liballoc. + let mut needs_allocator = attr::contains_name(&krate.attrs, + "needs_allocator"); let dep_graph = &self.sess.dep_graph; - self.cstore.iter_crate_data(|cnum, data| { + self.cstore.iter_crate_data(|_, data| { needs_allocator = needs_allocator || data.needs_allocator(dep_graph); - if data.is_allocator(dep_graph) { - info!("{} required by rlib and is an allocator", data.name()); - self.inject_dependency_if(cnum, "an allocator", - &|data| data.needs_allocator(dep_graph)); - found_required_allocator = found_required_allocator || - data.dep_kind.get() == DepKind::Explicit; - } }); - if !needs_allocator || found_required_allocator { return } + if !needs_allocator { + return + } - // At this point we've determined that we need an allocator and no - // previous allocator has been activated. We look through our outputs of - // crate types to see what kind of allocator types we may need. - // - // The main special output type here is that rlibs do **not** need an - // allocator linked in (they're just object files), only final products - // (exes, dylibs, staticlibs) need allocators. + // At this point we've determined that we need an allocator. Let's see + // if our compilation session actually needs an allocator based on what + // we're emitting. let mut need_lib_alloc = false; let mut need_exe_alloc = false; for ct in self.sess.crate_types.borrow().iter() { @@ -946,44 +985,132 @@ impl<'a> CrateLoader<'a> { config::CrateTypeRlib => {} } } - if !need_lib_alloc && !need_exe_alloc { return } + if !need_lib_alloc && !need_exe_alloc { + return + } - // The default allocator crate comes from the custom target spec, and we - // choose between the standard library allocator or exe allocator. This - // distinction exists because the default allocator for binaries (where - // the world is Rust) is different than library (where the world is - // likely *not* Rust). + // Ok, we need an allocator. Not only that but we're actually going to + // create an artifact that needs one linked in. Let's go find the one + // that we're going to link in. // - // If a library is being produced, but we're also flagged with `-C - // prefer-dynamic`, then we interpret this as a *Rust* dynamic library - // is being produced so we use the exe allocator instead. - // - // What this boils down to is: - // - // * Binaries use jemalloc - // * Staticlibs and Rust dylibs use system malloc - // * Rust dylibs used as dependencies to rust use jemalloc - let name = if need_lib_alloc && !self.sess.opts.cg.prefer_dynamic { - Symbol::intern(&self.sess.target.target.options.lib_allocation_crate) + // First up we check for global allocators. Look at the crate graph here + // and see what's a global allocator, including if we ourselves are a + // global allocator. + let dep_graph = &self.sess.dep_graph; + let mut global_allocator = if has_global_allocator { + Some(None) } else { - Symbol::intern(&self.sess.target.target.options.exe_allocation_crate) + None }; - let dep_kind = DepKind::Implicit; - let (cnum, data) = - self.resolve_crate(&None, name, name, None, DUMMY_SP, PathKind::Crate, dep_kind); + self.cstore.iter_crate_data(|_, data| { + if !data.has_global_allocator(dep_graph) { + return + } + match global_allocator { + Some(Some(other_crate)) => { + self.sess.err(&format!("the #[global_allocator] in {} \ + conflicts with this global \ + allocator in: {}", + other_crate, + data.name())); + } + Some(None) => { + self.sess.err(&format!("the #[global_allocator] in this \ + crate conflicts with global \ + allocator in: {}", data.name())); + } + None => global_allocator = Some(Some(data.name())), + } + }); + if global_allocator.is_some() { + self.sess.allocator_kind.set(Some(AllocatorKind::Global)); + return + } - // Sanity check the crate we loaded to ensure that it is indeed an - // allocator. - if !data.is_allocator(dep_graph) { - self.sess.err(&format!("the allocator crate `{}` is not tagged \ - with #![allocator]", data.name())); + // Ok we haven't found a global allocator but we still need an + // allocator. At this point we'll either fall back to the "library + // allocator" or the "exe allocator" depending on a few variables. Let's + // figure out which one. + // + // Note that here we favor linking to the "library allocator" as much as + // possible. If we're not creating rustc's version of libstd + // (need_lib_alloc and prefer_dynamic) then we select `None`, and if the + // exe allocation crate doesn't exist for this target then we also + // select `None`. + let exe_allocation_crate = + if need_lib_alloc && !self.sess.opts.cg.prefer_dynamic { + None + } else { + self.sess.target.target.options.exe_allocation_crate.as_ref() + }; + + match exe_allocation_crate { + // We've determined that we're injecting an "exe allocator" which + // means that we're going to load up a whole new crate. An example + // of this is that we're producing a normal binary on Linux which + // means we need to load the `alloc_jemalloc` crate to link as an + // allocator. + Some(krate) => { + self.sess.allocator_kind.set(Some(AllocatorKind::DefaultExe)); + let name = Symbol::intern(krate); + let dep_kind = DepKind::Implicit; + let (cnum, _data) = + self.resolve_crate(&None, + name, + name, + None, + DUMMY_SP, + PathKind::Crate, dep_kind); + self.sess.injected_allocator.set(Some(cnum)); + // self.cstore.iter_crate_data(|_, data| { + // if !data.needs_allocator(dep_graph) { + // return + // } + // data.cnum_map.borrow_mut().push(cnum); + // }); + } + + // We're not actually going to inject an allocator, we're going to + // require that something in our crate graph is the default lib + // allocator. This is typically libstd, so this'll rarely be an + // error. + None => { + self.sess.allocator_kind.set(Some(AllocatorKind::DefaultLib)); + let mut found_lib_allocator = + attr::contains_name(&krate.attrs, "default_lib_allocator"); + self.cstore.iter_crate_data(|_, data| { + if !found_lib_allocator { + if data.has_default_lib_allocator(dep_graph) { + found_lib_allocator = true; + } + } + }); + if found_lib_allocator { + return + } + self.sess.err("no #[default_lib_allocator] found but one is \ + required; is libstd not linked?"); + } } - self.sess.injected_allocator.set(Some(cnum)); - self.inject_dependency_if(cnum, "an allocator", - &|data| data.needs_allocator(dep_graph)); + fn has_global_allocator(krate: &ast::Crate) -> bool { + struct Finder(bool); + let mut f = Finder(false); + visit::walk_crate(&mut f, krate); + return f.0; + + impl<'ast> visit::Visitor<'ast> for Finder { + fn visit_item(&mut self, i: &'ast ast::Item) { + if attr::contains_name(&i.attrs, "global_allocator") { + self.0 = true; + } + visit::walk_item(self, i) + } + } + } } + fn inject_dependency_if(&self, krate: CrateNum, what: &str, @@ -1108,7 +1235,8 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { // inject the sanitizer runtime before the allocator runtime because all // sanitizers force the use of the `alloc_system` allocator self.inject_sanitizer_runtime(); - self.inject_allocator_crate(); + self.inject_profiler_runtime(); + self.inject_allocator_crate(krate); self.inject_panic_runtime(krate); if log_enabled!(log::LogLevel::Info) { diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 5066b927c1..fb43f91c46 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -13,9 +13,9 @@ use schema::{self, Tracked}; -use rustc::dep_graph::{DepGraph, DepNode, GlobalMetaDataKind}; +use rustc::dep_graph::DepGraph; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefIndex, DefId}; -use rustc::hir::map::definitions::DefPathTable; +use rustc::hir::map::definitions::{DefPathTable, GlobalMetaDataKind}; use rustc::hir::svh::Svh; use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader}; use rustc_back::PanicStrategy; @@ -34,7 +34,7 @@ pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePrefere pub use rustc::middle::cstore::NativeLibraryKind::*; pub use rustc::middle::cstore::{CrateSource, LinkMeta, LibSource}; -pub use cstore_impl::provide; +pub use cstore_impl::{provide, provide_local}; // A map from external crate numbers (as decoded from some crate file) to // local crate numbers (as generated during this session). Each external @@ -255,6 +255,13 @@ impl CStore { pub fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option { self.extern_mod_crate_map.borrow().get(&emod_id).cloned() } + + pub fn read_dep_node(&self, def_id: DefId) { + use rustc::middle::cstore::CrateStore; + let def_path_hash = self.def_path_hash(def_id); + let dep_node = def_path_hash.to_dep_node(::rustc::dep_graph::DepKind::MetaData); + self.dep_graph.read(dep_node); + } } impl CrateMetadata { @@ -268,16 +275,27 @@ impl CrateMetadata { self.root.disambiguator } - pub fn is_allocator(&self, dep_graph: &DepGraph) -> bool { - let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph); - attr::contains_name(&attrs, "allocator") - } - pub fn needs_allocator(&self, dep_graph: &DepGraph) -> bool { let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph); attr::contains_name(&attrs, "needs_allocator") } + pub fn has_global_allocator(&self, dep_graph: &DepGraph) -> bool { + let dep_node = self.metadata_dep_node(GlobalMetaDataKind::Krate); + self.root + .has_global_allocator + .get(dep_graph, dep_node) + .clone() + } + + pub fn has_default_lib_allocator(&self, dep_graph: &DepGraph) -> bool { + let dep_node = self.metadata_dep_node(GlobalMetaDataKind::Krate); + self.root + .has_default_lib_allocator + .get(dep_graph, dep_node) + .clone() + } + pub fn is_panic_runtime(&self, dep_graph: &DepGraph) -> bool { let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph); attr::contains_name(&attrs, "panic_runtime") @@ -298,18 +316,18 @@ impl CrateMetadata { attr::contains_name(&attrs, "sanitizer_runtime") } + pub fn is_profiler_runtime(&self, dep_graph: &DepGraph) -> bool { + let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph); + attr::contains_name(&attrs, "profiler_runtime") + } + pub fn is_no_builtins(&self, dep_graph: &DepGraph) -> bool { let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph); attr::contains_name(&attrs, "no_builtins") } pub fn panic_strategy(&self, dep_graph: &DepGraph) -> PanicStrategy { - let def_id = DefId { - krate: self.cnum, - index: CRATE_DEF_INDEX, - }; - let dep_node = DepNode::GlobalMetaData(def_id, GlobalMetaDataKind::Krate); - + let dep_node = self.metadata_dep_node(GlobalMetaDataKind::Krate); self.root .panic_strategy .get(dep_graph, dep_node) diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index dcc55846b5..4bdfdd51f6 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -12,9 +12,9 @@ use cstore; use encoder; use schema; -use rustc::dep_graph::DepTrackingMapConfig; +use rustc::ty::maps::QueryConfig; use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind, - ExternCrate, NativeLibrary, MetadataLoader, LinkMeta, + NativeLibrary, MetadataLoader, LinkMeta, LinkagePreference, LoadedMacro, EncodedMetadata}; use rustc::hir::def; use rustc::middle::lang_items; @@ -22,10 +22,9 @@ use rustc::session::Session; use rustc::ty::{self, TyCtxt}; use rustc::ty::maps::Providers; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; - -use rustc::dep_graph::{DepNode, GlobalMetaDataKind}; use rustc::hir::map::{DefKey, DefPath, DisambiguatedDefPathData, DefPathHash}; -use rustc::hir::map::definitions::DefPathTable; +use rustc::hir::map::blocks::FnLikeNode; +use rustc::hir::map::definitions::{DefPathTable, GlobalMetaDataKind}; use rustc::util::nodemap::{NodeSet, DefIdMap}; use rustc_back::PanicStrategy; @@ -34,6 +33,7 @@ use std::rc::Rc; use syntax::ast; use syntax::attr; +use syntax::ext::base::SyntaxExtension; use syntax::parse::filemap_to_stream; use syntax::symbol::Symbol; use syntax_pos::{Span, NO_EXPANSION}; @@ -41,14 +41,17 @@ use rustc::hir::svh::Svh; use rustc::hir; macro_rules! provide { - (<$lt:tt> $tcx:ident, $def_id:ident, $cdata:ident $($name:ident => $compute:block)*) => { + (<$lt:tt> $tcx:ident, $def_id:ident, $cdata:ident, $($name:ident => $compute:block)*) => { pub fn provide<$lt>(providers: &mut Providers<$lt>) { $(fn $name<'a, $lt:$lt>($tcx: TyCtxt<'a, $lt, $lt>, $def_id: DefId) -> as - DepTrackingMapConfig>::Value { + QueryConfig>::Value { assert!(!$def_id.is_local()); - $tcx.dep_graph.read(DepNode::MetaData($def_id)); + let def_path_hash = $tcx.def_path_hash($def_id); + let dep_node = def_path_hash.to_dep_node(::rustc::dep_graph::DepKind::MetaData); + + $tcx.dep_graph.read(dep_node); let $cdata = $tcx.sess.cstore.crate_data_as_rc_any($def_id.krate); let $cdata = $cdata.downcast_ref::() @@ -64,7 +67,7 @@ macro_rules! provide { } } -provide! { <'tcx> tcx, def_id, cdata +provide! { <'tcx> tcx, def_id, cdata, type_of => { cdata.get_type(def_id.index, tcx) } generics_of => { tcx.alloc_generics(cdata.get_generics(def_id.index)) } predicates_of => { cdata.get_predicates(def_id.index, tcx) } @@ -80,7 +83,8 @@ provide! { <'tcx> tcx, def_id, cdata variances_of => { Rc::new(cdata.get_item_variances(def_id.index)) } associated_item_def_ids => { let mut result = vec![]; - cdata.each_child_of_item(def_id.index, |child| result.push(child.def.def_id())); + cdata.each_child_of_item(def_id.index, + |child| result.push(child.def.def_id()), tcx.sess); Rc::new(result) } associated_item => { cdata.get_associated_item(def_id.index) } @@ -103,8 +107,9 @@ provide! { <'tcx> tcx, def_id, cdata mir_const_qualif => { cdata.mir_const_qualif(def_id.index) } typeck_tables_of => { cdata.item_body_tables(def_id.index, tcx) } closure_kind => { cdata.closure_kind(def_id.index) } - closure_type => { cdata.closure_ty(def_id.index, tcx) } + fn_sig => { cdata.fn_sig(def_id.index, tcx) } inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) } + is_const_fn => { cdata.is_const_fn(def_id.index) } is_foreign_item => { cdata.is_foreign_item(def_id.index) } is_default_impl => { cdata.is_default_impl(def_id.index) } describe_def => { cdata.get_def(def_id.index) } @@ -128,6 +133,28 @@ provide! { <'tcx> tcx, def_id, cdata cdata.const_is_rvalue_promotable_to_static(def_id.index) } is_mir_available => { cdata.is_item_mir_available(def_id.index) } + + dylib_dependency_formats => { Rc::new(cdata.get_dylib_dependency_formats(&tcx.dep_graph)) } + is_panic_runtime => { cdata.is_panic_runtime(&tcx.dep_graph) } + extern_crate => { Rc::new(cdata.extern_crate.get()) } +} + +pub fn provide_local<'tcx>(providers: &mut Providers<'tcx>) { + fn is_const_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool { + let node_id = tcx.hir.as_local_node_id(def_id) + .expect("Non-local call to local provider is_const_fn"); + + if let Some(fn_like) = FnLikeNode::from_node(tcx.hir.get(node_id)) { + fn_like.constness() == hir::Constness::Const + } else { + false + } + } + + *providers = Providers { + is_const_fn, + ..*providers + }; } impl CrateStore for cstore::CStore { @@ -140,12 +167,12 @@ impl CrateStore for cstore::CStore { } fn visibility(&self, def: DefId) -> ty::Visibility { - self.dep_graph.read(DepNode::MetaData(def)); + self.read_dep_node(def); self.get_crate_data(def.krate).get_visibility(def.index) } fn item_generics_cloned(&self, def: DefId) -> ty::Generics { - self.dep_graph.read(DepNode::MetaData(def)); + self.read_dep_node(def); self.get_crate_data(def.krate).get_generics(def.index) } @@ -161,22 +188,16 @@ impl CrateStore for cstore::CStore { fn impl_defaultness(&self, def: DefId) -> hir::Defaultness { - self.dep_graph.read(DepNode::MetaData(def)); + self.read_dep_node(def); self.get_crate_data(def.krate).get_impl_defaultness(def.index) } fn associated_item_cloned(&self, def: DefId) -> ty::AssociatedItem { - self.dep_graph.read(DepNode::MetaData(def)); + self.read_dep_node(def); self.get_crate_data(def.krate).get_associated_item(def.index) } - fn is_const_fn(&self, did: DefId) -> bool - { - self.dep_graph.read(DepNode::MetaData(did)); - self.get_crate_data(did.krate).is_const_fn(did.index) - } - fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool { self.do_is_statically_included_foreign_item(def_id) @@ -191,12 +212,6 @@ impl CrateStore for cstore::CStore { } } - fn dylib_dependency_formats(&self, cnum: CrateNum) - -> Vec<(CrateNum, LinkagePreference)> - { - self.get_crate_data(cnum).get_dylib_dependency_formats(&self.dep_graph) - } - fn dep_kind(&self, cnum: CrateNum) -> DepKind { let data = self.get_crate_data(cnum); @@ -226,16 +241,6 @@ impl CrateStore for cstore::CStore { self.get_crate_data(cnum).get_missing_lang_items(&self.dep_graph) } - fn is_allocator(&self, cnum: CrateNum) -> bool - { - self.get_crate_data(cnum).is_allocator(&self.dep_graph) - } - - fn is_panic_runtime(&self, cnum: CrateNum) -> bool - { - self.get_crate_data(cnum).is_panic_runtime(&self.dep_graph) - } - fn is_compiler_builtins(&self, cnum: CrateNum) -> bool { self.get_crate_data(cnum).is_compiler_builtins(&self.dep_graph) } @@ -244,6 +249,10 @@ impl CrateStore for cstore::CStore { self.get_crate_data(cnum).is_sanitizer_runtime(&self.dep_graph) } + fn is_profiler_runtime(&self, cnum: CrateNum) -> bool { + self.get_crate_data(cnum).is_profiler_runtime(&self.dep_graph) + } + fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy { self.get_crate_data(cnum).panic_strategy(&self.dep_graph) } @@ -258,11 +267,6 @@ impl CrateStore for cstore::CStore { self.get_crate_data(cnum).name() } - fn extern_crate(&self, cnum: CrateNum) -> Option - { - self.get_crate_data(cnum).extern_crate.get() - } - fn crate_hash(&self, cnum: CrateNum) -> Svh { self.get_crate_hash(cnum) @@ -344,16 +348,16 @@ impl CrateStore for cstore::CStore { fn struct_field_names(&self, def: DefId) -> Vec { - self.dep_graph.read(DepNode::MetaData(def)); + self.read_dep_node(def); self.get_crate_data(def.krate).get_struct_field_names(def.index) } - fn item_children(&self, def_id: DefId) -> Vec + fn item_children(&self, def_id: DefId, sess: &Session) -> Vec { - self.dep_graph.read(DepNode::MetaData(def_id)); + self.read_dep_node(def_id); let mut result = vec![]; self.get_crate_data(def_id.krate) - .each_child_of_item(def_id.index, |child| result.push(child)); + .each_child_of_item(def_id.index, |child| result.push(child), sess); result } @@ -361,6 +365,10 @@ impl CrateStore for cstore::CStore { let data = self.get_crate_data(id.krate); if let Some(ref proc_macros) = data.proc_macros { return LoadedMacro::ProcMacro(proc_macros[id.index.as_usize() - 1].1.clone()); + } else if data.name == "proc_macro" && + self.get_crate_data(id.krate).item_name(id.index) == "quote" { + let ext = SyntaxExtension::ProcMacro(Box::new(::proc_macro::__internal::Quoter)); + return LoadedMacro::ProcMacro(Rc::new(ext)); } let (name, def) = data.get_macro(id.index); @@ -368,7 +376,7 @@ impl CrateStore for cstore::CStore { let filemap = sess.parse_sess.codemap().new_filemap(source_name, def.body); let local_span = Span { lo: filemap.start_pos, hi: filemap.end_pos, ctxt: NO_EXPANSION }; - let body = filemap_to_stream(&sess.parse_sess, filemap); + let body = filemap_to_stream(&sess.parse_sess, filemap, None); // Mark the attrs as used let attrs = data.get_item_attrs(id.index, &self.dep_graph); @@ -398,11 +406,12 @@ impl CrateStore for cstore::CStore { tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx hir::Body { - if let Some(cached) = tcx.hir.get_inlined_body(def_id) { + self.read_dep_node(def_id); + + if let Some(cached) = tcx.hir.get_inlined_body_untracked(def_id) { return cached; } - self.dep_graph.read(DepNode::MetaData(def_id)); debug!("item_body({:?}): inlining item", def_id); self.get_crate_data(def_id.krate).item_body(tcx, def_id.index) @@ -456,7 +465,7 @@ impl CrateStore for cstore::CStore { /// Returns a map from a sufficiently visible external item (i.e. an external item that is /// visible from at least one local module) to a sufficiently visible parent (considering /// modules that re-export the external item to be parents). - fn visible_parent_map<'a>(&'a self) -> ::std::cell::Ref<'a, DefIdMap> { + fn visible_parent_map<'a>(&'a self, sess: &Session) -> ::std::cell::Ref<'a, DefIdMap> { { let visible_parent_map = self.visible_parent_map.borrow(); if !visible_parent_map.is_empty() { @@ -506,7 +515,7 @@ impl CrateStore for cstore::CStore { index: CRATE_DEF_INDEX }); while let Some(def) = bfs_queue.pop_front() { - for child in self.item_children(def) { + for child in self.item_children(def, sess) { add_child(bfs_queue, child, def); } } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 91470f238e..ad3a9dd9fe 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -13,8 +13,9 @@ use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary}; use schema::*; -use rustc::dep_graph::{DepGraph, DepNode, GlobalMetaDataKind}; +use rustc::dep_graph::{DepGraph, DepNode, DepKind}; use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash}; +use rustc::hir::map::definitions::GlobalMetaDataKind; use rustc::hir; use rustc::middle::cstore::LinkagePreference; @@ -471,7 +472,7 @@ impl<'a, 'tcx> CrateMetadata { } } - fn item_name(&self, item_index: DefIndex) -> ast::Name { + pub fn item_name(&self, item_index: DefIndex) -> ast::Name { self.def_key(item_index) .disambiguated_data .data @@ -653,7 +654,7 @@ impl<'a, 'tcx> CrateMetadata { } /// Iterates over each child of the given item. - pub fn each_child_of_item(&self, id: DefIndex, mut callback: F) + pub fn each_child_of_item(&self, id: DefIndex, mut callback: F, sess: &Session) where F: FnMut(def::Export) { if let Some(ref proc_macros) = self.proc_macros { @@ -676,19 +677,19 @@ impl<'a, 'tcx> CrateMetadata { // Find the item. let item = match self.maybe_entry(id) { None => return, - Some(item) => item.decode(self), + Some(item) => item.decode((self, sess)), }; // Iterate over all children. let macros_only = self.dep_kind.get().macros_only(); - for child_index in item.children.decode(self) { + for child_index in item.children.decode((self, sess)) { if macros_only { continue } // Get the item. if let Some(child) = self.maybe_entry(child_index) { - let child = child.decode(self); + let child = child.decode((self, sess)); match child.kind { EntryKind::MacroDef(..) => {} _ if macros_only => continue, @@ -699,12 +700,12 @@ impl<'a, 'tcx> CrateMetadata { match child.kind { // FIXME(eddyb) Don't encode these in children. EntryKind::ForeignMod => { - for child_index in child.children.decode(self) { + for child_index in child.children.decode((self, sess)) { if let Some(def) = self.get_def(child_index) { callback(def::Export { def: def, ident: Ident::with_empty_ctxt(self.item_name(child_index)), - span: self.entry(child_index).span.decode(self), + span: self.entry(child_index).span.decode((self, sess)), }); } } @@ -717,7 +718,7 @@ impl<'a, 'tcx> CrateMetadata { } let def_key = self.def_key(child_index); - let span = child.span.decode(self); + let span = child.span.decode((self, sess)); if let (Some(def), Some(name)) = (self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) { let ident = Ident::with_empty_ctxt(name); @@ -746,7 +747,7 @@ impl<'a, 'tcx> CrateMetadata { } if let EntryKind::Mod(data) = item.kind { - for exp in data.decode(self).reexports.decode(self) { + for exp in data.decode((self, sess)).reexports.decode((self, sess)) { match exp.def { Def::Macro(..) => {} _ if macros_only => continue, @@ -764,7 +765,7 @@ impl<'a, 'tcx> CrateMetadata { assert!(!self.is_proc_macro(id)); let ast = self.entry(id).ast.unwrap(); let def_id = self.local_def_id(id); - let body = ast.decode(self).body.decode(self); + let body = ast.decode((self, tcx)).body.decode((self, tcx)); tcx.hir.intern_inlined_body(def_id, body) } @@ -875,7 +876,8 @@ impl<'a, 'tcx> CrateMetadata { return Rc::new([]); } - dep_graph.read(DepNode::MetaData(self.local_def_id(node_id))); + let dep_node = self.def_path_hash(node_id).to_dep_node(DepKind::MetaData); + dep_graph.read(dep_node); if let Some(&Some(ref val)) = self.attribute_cache.borrow()[node_as].get(node_index) { @@ -993,12 +995,8 @@ impl<'a, 'tcx> CrateMetadata { pub fn get_dylib_dependency_formats(&self, dep_graph: &DepGraph) -> Vec<(CrateNum, LinkagePreference)> { - let def_id = DefId { - krate: self.cnum, - index: CRATE_DEF_INDEX, - }; - let dep_node = DepNode::GlobalMetaData(def_id, - GlobalMetaDataKind::DylibDependencyFormats); + let dep_node = + self.metadata_dep_node(GlobalMetaDataKind::DylibDependencyFormats); self.root .dylib_dependency_formats .get(dep_graph, dep_node) @@ -1086,14 +1084,20 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn closure_ty(&self, - closure_id: DefIndex, - tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> ty::PolyFnSig<'tcx> { - match self.entry(closure_id).kind { - EntryKind::Closure(data) => data.decode(self).ty.decode((self, tcx)), + pub fn fn_sig(&self, + id: DefIndex, + tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> ty::PolyFnSig<'tcx> { + let sig = match self.entry(id).kind { + EntryKind::Fn(data) | + EntryKind::ForeignFn(data) => data.decode(self).sig, + EntryKind::Method(data) => data.decode(self).fn_data.sig, + EntryKind::Variant(data) | + EntryKind::Struct(data, _) => data.decode(self).ctor_sig.unwrap(), + EntryKind::Closure(data) => data.decode(self).sig, _ => bug!(), - } + }; + sig.decode((self, tcx)) } #[inline] @@ -1151,6 +1155,7 @@ impl<'a, 'tcx> CrateMetadata { // containing the information we need. let syntax_pos::FileMap { name, name_was_remapped, + src_hash, start_pos, end_pos, lines, @@ -1176,6 +1181,7 @@ impl<'a, 'tcx> CrateMetadata { let local_version = local_codemap.new_imported_filemap(name, name_was_remapped, self.cnum.as_u32(), + src_hash, source_length, lines, multibyte_chars); @@ -1197,12 +1203,9 @@ impl<'a, 'tcx> CrateMetadata { self.codemap_import_info.borrow() } - pub fn metadata_dep_node(&self, kind: GlobalMetaDataKind) -> DepNode { - let def_id = DefId { - krate: self.cnum, - index: CRATE_DEF_INDEX, - }; - - DepNode::GlobalMetaData(def_id, kind) + pub fn metadata_dep_node(&self, kind: GlobalMetaDataKind) -> DepNode { + let def_index = kind.def_index(&self.def_path_table); + let def_path_hash = self.def_path_table.def_path_hash(def_index); + def_path_hash.to_dep_node(DepKind::MetaData) } } diff --git a/src/librustc_metadata/diagnostics.rs b/src/librustc_metadata/diagnostics.rs index fbdc4695cf..1fa1a896dd 100644 --- a/src/librustc_metadata/diagnostics.rs +++ b/src/librustc_metadata/diagnostics.rs @@ -21,7 +21,7 @@ A link name was given with an empty name. Erroneous code example: The rust compiler cannot link to an external library if you don't give it its name. Example: -```ignore +```no_run #[link(name = "some_lib")] extern {} // ok! ``` "##, @@ -32,7 +32,7 @@ as frameworks are specific to that operating system. Erroneous code example: -```ignore +```ignore (should-compile_fail-but-cannot-doctest-conditionally-without-macos) #[link(name = "FooCoreServices", kind = "framework")] extern {} // OS used to compile is Linux for example ``` @@ -44,7 +44,8 @@ To solve this error you can use conditional compilation: extern {} ``` -See more: https://doc.rust-lang.org/book/conditional-compilation.html +See more: +https://doc.rust-lang.org/book/first-edition/conditional-compilation.html "##, E0458: r##" @@ -74,7 +75,7 @@ A link was used without a name parameter. Erroneous code example: Please add the name parameter to allow the rust compiler to find the library you want. Example: -```ignore +```no_run #[link(kind = "dylib", name = "some_lib")] extern {} // ok! ``` "##, diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index a02a82dfe6..5d73abc3ee 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -14,10 +14,11 @@ use isolated_encoder::IsolatedEncoder; use schema::*; use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary, - EncodedMetadata, EncodedMetadataHashes}; + EncodedMetadata, EncodedMetadataHashes, + EncodedMetadataHash}; +use rustc::hir::def::CtorKind; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE}; -use rustc::hir::map::definitions::DefPathTable; -use rustc::dep_graph::{DepNode, GlobalMetaDataKind}; +use rustc::hir::map::definitions::{DefPathTable, GlobalMetaDataKind}; use rustc::ich::Fingerprint; use rustc::middle::dependency_format::Linkage; use rustc::middle::lang_items; @@ -244,7 +245,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Encodes something that corresponds to a single DepNode::GlobalMetaData // and registers the Fingerprint in the `metadata_hashes` map. pub fn tracked<'x, DATA, R>(&'x mut self, - dep_node: DepNode<()>, + def_index: DefIndex, op: fn(&mut IsolatedEncoder<'x, 'a, 'tcx>, DATA) -> R, data: DATA) -> Tracked { @@ -253,7 +254,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let (fingerprint, this) = entry_builder.finish(); if let Some(fingerprint) = fingerprint { - this.metadata_hashes.global_hashes.push((dep_node, fingerprint)); + this.metadata_hashes.hashes.push(EncodedMetadataHash { + def_index, + hash: fingerprint, + }) } Tracked::new(ret) @@ -322,12 +326,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_crate_root(&mut self) -> Lazy { let mut i = self.position(); + let tcx = self.tcx; + let global_metadata_def_index = move |kind: GlobalMetaDataKind| { + kind.def_index(tcx.hir.definitions().def_path_table()) + }; + let crate_deps = self.tracked( - DepNode::GlobalMetaData((), GlobalMetaDataKind::CrateDeps), + global_metadata_def_index(GlobalMetaDataKind::CrateDeps), IsolatedEncoder::encode_crate_deps, ()); let dylib_dependency_formats = self.tracked( - DepNode::GlobalMetaData((), GlobalMetaDataKind::DylibDependencyFormats), + global_metadata_def_index(GlobalMetaDataKind::DylibDependencyFormats), IsolatedEncoder::encode_dylib_dependency_formats, ()); let dep_bytes = self.position() - i; @@ -335,12 +344,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Encode the language items. i = self.position(); let lang_items = self.tracked( - DepNode::GlobalMetaData((), GlobalMetaDataKind::LangItems), + global_metadata_def_index(GlobalMetaDataKind::LangItems), IsolatedEncoder::encode_lang_items, ()); let lang_items_missing = self.tracked( - DepNode::GlobalMetaData((), GlobalMetaDataKind::LangItemsMissing), + global_metadata_def_index(GlobalMetaDataKind::LangItemsMissing), IsolatedEncoder::encode_lang_items_missing, ()); let lang_item_bytes = self.position() - i; @@ -348,7 +357,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Encode the native libraries used i = self.position(); let native_libraries = self.tracked( - DepNode::GlobalMetaData((), GlobalMetaDataKind::NativeLibraries), + global_metadata_def_index(GlobalMetaDataKind::NativeLibraries), IsolatedEncoder::encode_native_libraries, ()); let native_lib_bytes = self.position() - i; @@ -366,7 +375,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Encode the def IDs of impls, for coherence checking. i = self.position(); let impls = self.tracked( - DepNode::GlobalMetaData((), GlobalMetaDataKind::Impls), + global_metadata_def_index(GlobalMetaDataKind::Impls), IsolatedEncoder::encode_impls, ()); let impl_bytes = self.position() - i; @@ -374,7 +383,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Encode exported symbols info. i = self.position(); let exported_symbols = self.tracked( - DepNode::GlobalMetaData((), GlobalMetaDataKind::ExportedSymbols), + global_metadata_def_index(GlobalMetaDataKind::ExportedSymbols), IsolatedEncoder::encode_exported_symbols, self.exported_symbols); let exported_symbols_bytes = self.position() - i; @@ -391,12 +400,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let tcx = self.tcx; let link_meta = self.link_meta; let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateTypeProcMacro); + let has_default_lib_allocator = + attr::contains_name(tcx.hir.krate_attrs(), "default_lib_allocator"); + let has_global_allocator = tcx.sess.has_global_allocator.get(); let root = self.lazy(&CrateRoot { name: tcx.crate_name(LOCAL_CRATE), triple: tcx.sess.opts.target_triple.clone(), hash: link_meta.crate_hash, disambiguator: tcx.sess.local_crate_disambiguator(), panic_strategy: Tracked::new(tcx.sess.panic_strategy()), + has_global_allocator: Tracked::new(has_global_allocator), + has_default_lib_allocator: Tracked::new(has_default_lib_allocator), plugin_registrar_fn: tcx.sess .plugin_registrar_fn .get() @@ -422,10 +436,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let total_bytes = self.position(); - self.metadata_hashes.global_hashes.push(( - DepNode::GlobalMetaData((), GlobalMetaDataKind::Krate), - Fingerprint::from_smaller_hash(link_meta.crate_hash.as_u64()) - )); + self.metadata_hashes.hashes.push(EncodedMetadataHash { + def_index: global_metadata_def_index(GlobalMetaDataKind::Krate), + hash: Fingerprint::from_smaller_hash(link_meta.crate_hash.as_u64()) + }); if self.tcx.sess.meta_stats() { let mut zero_bytes = 0; @@ -491,6 +505,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, struct_ctor: None, + ctor_sig: if variant.ctor_kind == CtorKind::Fn { + Some(self.lazy(&tcx.fn_sig(def_id))) + } else { + None + } }; let enum_id = tcx.hir.as_local_node_id(enum_did).unwrap(); @@ -510,7 +529,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ty: Some(self.encode_item_type(def_id)), inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + variances: if variant.ctor_kind == CtorKind::Fn { + self.encode_variances_of(def_id) + } else { + LazySeq::empty() + }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -609,6 +632,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, struct_ctor: Some(def_id.index), + ctor_sig: if variant.ctor_kind == CtorKind::Fn { + Some(self.lazy(&tcx.fn_sig(def_id))) + } else { + None + } }; let struct_id = tcx.hir.as_local_node_id(adt_def_id).unwrap(); @@ -633,7 +661,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ty: Some(self.encode_item_type(def_id)), inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + variances: if variant.ctor_kind == CtorKind::Fn { + self.encode_variances_of(def_id) + } else { + LazySeq::empty() + }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -687,7 +719,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { }; FnData { constness: hir::Constness::NotConst, - arg_names: arg_names + arg_names: arg_names, + sig: self.lazy(&tcx.fn_sig(def_id)), } } else { bug!() @@ -724,7 +757,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } }, inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + variances: if trait_item.kind == ty::AssociatedKind::Method { + self.encode_variances_of(def_id) + } else { + LazySeq::empty() + }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -739,6 +776,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> { debug!("IsolatedEncoder::encode_info_for_impl_item({:?})", def_id); + let tcx = self.tcx; + let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); let ast_item = self.tcx.hir.expect_impl_item(node_id); let impl_item = self.tcx.associated_item(def_id); @@ -760,6 +799,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { FnData { constness: sig.constness, arg_names: self.encode_fn_arg_names_for_body(body), + sig: self.lazy(&tcx.fn_sig(def_id)), } } else { bug!() @@ -798,7 +838,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ty: Some(self.encode_item_type(def_id)), inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + variances: if impl_item.kind == ty::AssociatedKind::Method { + self.encode_variances_of(def_id) + } else { + LazySeq::empty() + }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -873,6 +917,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let data = FnData { constness: constness, arg_names: self.encode_fn_arg_names_for_body(body), + sig: self.lazy(&tcx.fn_sig(def_id)), }; EntryKind::Fn(self.lazy(&data)) @@ -902,6 +947,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, struct_ctor: struct_ctor, + ctor_sig: None, }), repr_options) } hir::ItemUnion(..) => { @@ -912,6 +958,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, struct_ctor: None, + ctor_sig: None, }), repr_options) } hir::ItemDefaultImpl(..) => { @@ -1029,7 +1076,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { hir::ItemEnum(..) | hir::ItemStruct(..) | hir::ItemUnion(..) | - hir::ItemTrait(..) => self.encode_variances_of(def_id), + hir::ItemFn(..) => self.encode_variances_of(def_id), _ => LazySeq::empty(), }, generics: match item.node { @@ -1087,6 +1134,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { /// Serialize the text of exported macros fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) -> Entry<'tcx> { use syntax::print::pprust; + let def_id = self.tcx.hir.local_def_id(macro_def.id); Entry { kind: EntryKind::MacroDef(self.lazy(&MacroDef { body: pprust::tts_to_string(¯o_def.body.trees().collect::>()), @@ -1094,11 +1142,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { })), visibility: self.lazy(&ty::Visibility::Public), span: self.lazy(¯o_def.span), - attributes: self.encode_attributes(¯o_def.attrs), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + children: LazySeq::empty(), - stability: None, - deprecation: None, ty: None, inherent_impls: LazySeq::empty(), variances: LazySeq::empty(), @@ -1167,7 +1215,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let data = ClosureData { kind: tcx.closure_kind(def_id), - ty: self.lazy(&tcx.closure_type(def_id)), + sig: self.lazy(&tcx.fn_sig(def_id)), }; Entry { @@ -1355,6 +1403,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let data = FnData { constness: hir::Constness::NotConst, arg_names: self.encode_fn_arg_names(names), + sig: self.lazy(&tcx.fn_sig(def_id)), }; EntryKind::ForeignFn(self.lazy(&data)) } @@ -1373,7 +1422,10 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ty: Some(self.encode_item_type(def_id)), inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + variances: match nitem.node { + hir::ForeignItemFn(..) => self.encode_variances_of(def_id), + _ => LazySeq::empty(), + }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs index 478202aeba..2db9c6a4ff 100644 --- a/src/librustc_metadata/index_builder.rs +++ b/src/librustc_metadata/index_builder.rs @@ -135,7 +135,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { let (fingerprint, ecx) = entry_builder.finish(); if let Some(hash) = fingerprint { - ecx.metadata_hashes.entry_hashes.push(EncodedMetadataHash { + ecx.metadata_hashes.hashes.push(EncodedMetadataHash { def_index: id.index, hash: hash, }); diff --git a/src/librustc_metadata/isolated_encoder.rs b/src/librustc_metadata/isolated_encoder.rs index ed1680fbfa..c411648935 100644 --- a/src/librustc_metadata/isolated_encoder.rs +++ b/src/librustc_metadata/isolated_encoder.rs @@ -23,7 +23,7 @@ use rustc_serialize::Encodable; pub struct IsolatedEncoder<'a, 'b: 'a, 'tcx: 'b> { pub tcx: TyCtxt<'b, 'tcx, 'tcx>, ecx: &'a mut EncodeContext<'b, 'tcx>, - hcx: Option<(StableHashingContext<'b, 'tcx>, StableHasher)>, + hcx: Option<(StableHashingContext<'b, 'tcx, 'tcx>, StableHasher)>, } impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { @@ -61,7 +61,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } pub fn lazy(&mut self, value: &T) -> Lazy - where T: Encodable + HashStable> + where T: Encodable + HashStable> { if let Some((ref mut hcx, ref mut hasher)) = self.hcx { value.hash_stable(hcx, hasher); @@ -72,7 +72,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { pub fn lazy_seq(&mut self, iter: I) -> LazySeq where I: IntoIterator, - T: Encodable + HashStable> + T: Encodable + HashStable> { if let Some((ref mut hcx, ref mut hasher)) = self.hcx { let iter = iter.into_iter(); @@ -111,7 +111,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { pub fn lazy_seq_ref<'x, I, T>(&mut self, iter: I) -> LazySeq where I: IntoIterator, - T: 'x + Encodable + HashStable> + T: 'x + Encodable + HashStable> { if let Some((ref mut hcx, ref mut hasher)) = self.hcx { let iter = iter.into_iter(); @@ -149,7 +149,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } pub fn lazy_seq_from_slice(&mut self, slice: &[T]) -> LazySeq - where T: Encodable + HashStable> + where T: Encodable + HashStable> { if let Some((ref mut hcx, ref mut hasher)) = self.hcx { slice.hash_stable(hcx, hasher); @@ -159,7 +159,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } pub fn lazy_seq_ref_from_slice(&mut self, slice: &[&T]) -> LazySeq - where T: Encodable + HashStable> + where T: Encodable + HashStable> { if let Some((ref mut hcx, ref mut hasher)) = self.hcx { slice.hash_stable(hcx, hasher); diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 56c150fd4c..99b718ea07 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -27,16 +27,12 @@ #![feature(discriminant_value)] #![feature(rustc_private)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(staged_api))] -#![feature(sort_unstable)] - #[macro_use] extern crate log; #[macro_use] extern crate syntax; extern crate syntax_pos; -extern crate flate; +extern crate flate2; extern crate serialize as rustc_serialize; // used by deriving extern crate owning_ref; extern crate rustc_errors as errors; diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 34b07af9f0..9bcf590eb8 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -150,7 +150,7 @@ //! the compiler. For example, if crate A wanted to use Bv1 and Bv2, then it //! would look something like: //! -//! ```ignore +//! ```compile_fail,E0463 //! extern crate b1; //! extern crate b2; //! @@ -242,7 +242,7 @@ use std::io::{self, Read}; use std::path::{Path, PathBuf}; use std::time::Instant; -use flate; +use flate2::read::DeflateDecoder; use owning_ref::{ErasedBoxRef, OwningRef}; pub struct CrateMismatch { @@ -861,8 +861,9 @@ fn get_metadata_section_imp(target: &Target, // Header is okay -> inflate the actual metadata let compressed_bytes = &buf[header_len..]; debug!("inflating {} bytes of compressed metadata", compressed_bytes.len()); - match flate::inflate_bytes(compressed_bytes) { - Ok(inflated) => { + let mut inflated = Vec::new(); + match DeflateDecoder::new(compressed_bytes).read_to_end(&mut inflated) { + Ok(_) => { let buf = unsafe { OwningRef::new_assert_stable_address(inflated) }; buf.map_owner_box().erase_owner() } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 2ffe7cc02a..0b670121ba 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -203,7 +203,7 @@ impl Tracked { } } - pub fn get(&self, dep_graph: &DepGraph, dep_node: DepNode) -> &T { + pub fn get(&self, dep_graph: &DepGraph, dep_node: DepNode) -> &T { dep_graph.read(dep_node); &self.state } @@ -221,11 +221,11 @@ impl Tracked { } } -impl<'a, 'tcx, T> HashStable> for Tracked - where T: HashStable> +impl<'a, 'gcx, 'tcx, T> HashStable> for Tracked + where T: HashStable> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let Tracked { ref state @@ -243,6 +243,8 @@ pub struct CrateRoot { pub hash: hir::svh::Svh, pub disambiguator: Symbol, pub panic_strategy: Tracked, + pub has_global_allocator: Tracked, + pub has_default_lib_allocator: Tracked, pub plugin_registrar_fn: Option, pub macro_derive_registrar: Option, @@ -277,9 +279,9 @@ pub struct TraitImpls { pub impls: LazySeq, } -impl<'a, 'tcx> HashStable> for TraitImpls { +impl<'a, 'gcx, 'tcx> HashStable> for TraitImpls { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let TraitImpls { trait_id: (krate, def_index), @@ -343,25 +345,25 @@ pub enum EntryKind<'tcx> { Type, Enum(ReprOptions), Field, - Variant(Lazy), - Struct(Lazy, ReprOptions), - Union(Lazy, ReprOptions), - Fn(Lazy), - ForeignFn(Lazy), + Variant(Lazy>), + Struct(Lazy>, ReprOptions), + Union(Lazy>, ReprOptions), + Fn(Lazy>), + ForeignFn(Lazy>), Mod(Lazy), MacroDef(Lazy), Closure(Lazy>), Trait(Lazy>), Impl(Lazy>), DefaultImpl(Lazy>), - Method(Lazy), + Method(Lazy>), AssociatedType(AssociatedContainer), AssociatedConst(AssociatedContainer, u8), } -impl<'a, 'tcx> HashStable> for EntryKind<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> for EntryKind<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -439,27 +441,33 @@ pub struct MacroDef { impl_stable_hash_for!(struct MacroDef { body, legacy }); #[derive(RustcEncodable, RustcDecodable)] -pub struct FnData { +pub struct FnData<'tcx> { pub constness: hir::Constness, pub arg_names: LazySeq, + pub sig: Lazy>, } -impl_stable_hash_for!(struct FnData { constness, arg_names }); +impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig }); #[derive(RustcEncodable, RustcDecodable)] -pub struct VariantData { +pub struct VariantData<'tcx> { pub ctor_kind: CtorKind, pub discr: ty::VariantDiscr, /// If this is a struct's only variant, this /// is the index of the "struct ctor" item. pub struct_ctor: Option, + + /// If this is a tuple struct or variant + /// ctor, this is its "function" signature. + pub ctor_sig: Option>>, } -impl_stable_hash_for!(struct VariantData { +impl_stable_hash_for!(struct VariantData<'tcx> { ctor_kind, discr, - struct_ctor + struct_ctor, + ctor_sig }); #[derive(RustcEncodable, RustcDecodable)] @@ -543,16 +551,16 @@ impl AssociatedContainer { } #[derive(RustcEncodable, RustcDecodable)] -pub struct MethodData { - pub fn_data: FnData, +pub struct MethodData<'tcx> { + pub fn_data: FnData<'tcx>, pub container: AssociatedContainer, pub has_self: bool, } -impl_stable_hash_for!(struct MethodData { fn_data, container, has_self }); +impl_stable_hash_for!(struct MethodData<'tcx> { fn_data, container, has_self }); #[derive(RustcEncodable, RustcDecodable)] pub struct ClosureData<'tcx> { pub kind: ty::ClosureKind, - pub ty: Lazy>, + pub sig: Lazy>, } -impl_stable_hash_for!(struct ClosureData<'tcx> { kind, ty }); +impl_stable_hash_for!(struct ClosureData<'tcx> { kind, sig }); diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index d81de954db..865174aa27 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -21,21 +21,24 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ast_block: &'tcx hir::Block, source_info: SourceInfo) -> BlockAnd<()> { - let Block { extent, span, stmts, expr, targeted_by_break } = self.hir.mirror(ast_block); - self.in_scope(extent, block, move |this| { - if targeted_by_break { - // This is a `break`-able block (currently only `catch { ... }`) - let exit_block = this.cfg.start_new_block(); - let block_exit = this.in_breakable_scope(None, exit_block, - destination.clone(), |this| { + let Block { extent, opt_destruction_extent, span, stmts, expr, targeted_by_break } = + self.hir.mirror(ast_block); + self.in_opt_scope(opt_destruction_extent.map(|de|(de, source_info)), block, move |this| { + this.in_scope((extent, source_info), block, move |this| { + if targeted_by_break { + // This is a `break`-able block (currently only `catch { ... }`) + let exit_block = this.cfg.start_new_block(); + let block_exit = this.in_breakable_scope( + None, exit_block, destination.clone(), |this| { + this.ast_block_stmts(destination, block, span, stmts, expr) + }); + this.cfg.terminate(unpack!(block_exit), source_info, + TerminatorKind::Goto { target: exit_block }); + exit_block.unit() + } else { this.ast_block_stmts(destination, block, span, stmts, expr) - }); - this.cfg.terminate(unpack!(block_exit), source_info, - TerminatorKind::Goto { target: exit_block }); - exit_block.unit() - } else { - this.ast_block_stmts(destination, block, span, stmts, expr) - } + } + }) }) } @@ -66,14 +69,18 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // First we build all the statements in the block. let mut let_extent_stack = Vec::with_capacity(8); let outer_visibility_scope = this.visibility_scope; + let source_info = this.source_info(span); for stmt in stmts { - let Stmt { span: _, kind } = this.hir.mirror(stmt); + let Stmt { span, kind, opt_destruction_extent } = this.hir.mirror(stmt); match kind { StmtKind::Expr { scope, expr } => { - unpack!(block = this.in_scope(scope, block, |this| { - let expr = this.hir.mirror(expr); - this.stmt_expr(block, expr) - })); + unpack!(block = this.in_opt_scope( + opt_destruction_extent.map(|de|(de, source_info)), block, |this| { + this.in_scope((scope, source_info), block, |this| { + let expr = this.hir.mirror(expr); + this.stmt_expr(block, expr) + }) + })); } StmtKind::Let { remainder_scope, init_scope, pattern, initializer } => { let tcx = this.hir.tcx(); @@ -89,10 +96,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Evaluate the initializer, if present. if let Some(init) = initializer { - unpack!(block = this.in_scope(init_scope, block, move |this| { - // FIXME #30046 ^~~~ - this.expr_into_pattern(block, pattern, init) - })); + unpack!(block = this.in_opt_scope( + opt_destruction_extent.map(|de|(de, source_info)), block, move |this| { + this.in_scope((init_scope, source_info), block, move |this| { + // FIXME #30046 ^~~~ + this.expr_into_pattern(block, pattern, init) + }) + })); } else { this.visit_bindings(&pattern, &mut |this, _, _, node, span, _| { this.storage_live_binding(block, node, span); @@ -112,13 +122,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { if let Some(expr) = expr { unpack!(block = this.into(destination, block, expr)); } else { - let source_info = this.source_info(span); this.cfg.push_assign_unit(block, source_info, destination); } // Finally, we pop all the let scopes before exiting out from the scope of block // itself. for extent in let_extent_stack.into_iter().rev() { - unpack!(block = this.pop_scope(extent, block)); + unpack!(block = this.pop_scope((extent, source_info), block)); } // Restore the original visibility scope. this.visibility_scope = outer_visibility_scope; diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs index 40a78933aa..c20f8bde78 100644 --- a/src/librustc_mir/build/cfg.rs +++ b/src/librustc_mir/build/cfg.rs @@ -14,6 +14,7 @@ //! Routines for manipulating the control-flow graph. use build::CFG; +use rustc::middle::region::CodeExtent; use rustc::mir::*; impl<'tcx> CFG<'tcx> { @@ -43,6 +44,16 @@ impl<'tcx> CFG<'tcx> { self.block_data_mut(block).statements.push(statement); } + pub fn push_end_region(&mut self, + block: BasicBlock, + source_info: SourceInfo, + extent: CodeExtent) { + self.push(block, Statement { + source_info: source_info, + kind: StatementKind::EndRegion(extent), + }); + } + pub fn push_assign(&mut self, block: BasicBlock, source_info: SourceInfo, diff --git a/src/librustc_mir/build/expr/as_lvalue.rs b/src/librustc_mir/build/expr/as_lvalue.rs index df2841a668..04c2321546 100644 --- a/src/librustc_mir/build/expr/as_lvalue.rs +++ b/src/librustc_mir/build/expr/as_lvalue.rs @@ -40,7 +40,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let source_info = this.source_info(expr_span); match expr.kind { ExprKind::Scope { extent, value } => { - this.in_scope(extent, block, |this| this.as_lvalue(block, value)) + this.in_scope((extent, source_info), block, |this| this.as_lvalue(block, value)) } ExprKind::Field { lhs, name } => { let lvalue = unpack!(block = this.as_lvalue(block, lhs)); diff --git a/src/librustc_mir/build/expr/as_operand.rs b/src/librustc_mir/build/expr/as_operand.rs index 5178963179..4679e0bb0a 100644 --- a/src/librustc_mir/build/expr/as_operand.rs +++ b/src/librustc_mir/build/expr/as_operand.rs @@ -56,6 +56,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let this = self; if let ExprKind::Scope { extent, value } = expr.kind { + let source_info = this.source_info(expr.span); + let extent = (extent, source_info); return this.in_scope(extent, block, |this| { this.as_operand(block, scope, value) }); diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 2884b60fdd..2512291f1a 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -59,6 +59,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { match expr.kind { ExprKind::Scope { extent, value } => { + let extent = (extent, source_info); this.in_scope(extent, block, |this| this.as_rvalue(block, scope, value)) } ExprKind::Repeat { value, count } => { @@ -99,7 +100,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // to start, malloc some memory of suitable type (thus far, uninitialized): let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty); this.cfg.push_assign(block, source_info, &result, box_); - this.in_scope(value_extents, block, |this| { + this.in_scope((value_extents, source_info), block, |this| { // schedule a shallow free of that memory, lest we unwind: this.schedule_box_free(expr_span, value_extents, &result, value.ty); // initialize the box contents: diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index 17d74571ce..9be306d284 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -39,16 +39,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { block, temp_lifetime, expr); let this = self; + let expr_span = expr.span; + let source_info = this.source_info(expr_span); if let ExprKind::Scope { extent, value } = expr.kind { - return this.in_scope(extent, block, |this| { + return this.in_scope((extent, source_info), block, |this| { this.as_temp(block, temp_lifetime, value) }); } let expr_ty = expr.ty.clone(); - let expr_span = expr.span; let temp = this.temp(expr_ty.clone(), expr_span); - let source_info = this.source_info(expr_span); if !expr_ty.is_never() && temp_lifetime.is_some() { this.cfg.push(block, Statement { diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index d456bc3ded..326c1df69e 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -39,6 +39,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { match expr.kind { ExprKind::Scope { extent, value } => { + let extent = (extent, source_info); this.in_scope(extent, block, |this| this.into(destination, block, value)) } ExprKind::Block { body: ast_block } => { @@ -204,11 +205,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // FIXME(canndrew): This is_never should probably be an is_uninhabited let diverges = expr.ty.is_never(); let intrinsic = match ty.sty { - ty::TyFnDef(def_id, _, ref f) if - f.abi() == Abi::RustIntrinsic || - f.abi() == Abi::PlatformIntrinsic => - { - Some(this.hir.tcx().item_name(def_id).as_str()) + ty::TyFnDef(def_id, _) => { + let f = ty.fn_sig(this.hir.tcx()); + if f.abi() == Abi::RustIntrinsic || + f.abi() == Abi::PlatformIntrinsic { + Some(this.hir.tcx().item_name(def_id).as_str()) + } else { + None + } } _ => None }; @@ -233,7 +237,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { .collect(); let success = this.cfg.start_new_block(); - let cleanup = this.diverge_cleanup(); + let cleanup = this.diverge_cleanup(expr_span); this.cfg.terminate(block, source_info, TerminatorKind::Call { func: fun, args: args, diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs index 3c7ab37365..3120ac2190 100644 --- a/src/librustc_mir/build/expr/stmt.rs +++ b/src/librustc_mir/build/expr/stmt.rs @@ -24,7 +24,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { match expr.kind { ExprKind::Scope { extent, value } => { let value = this.hir.mirror(value); - this.in_scope(extent, block, |this| this.stmt_expr(block, value)) + this.in_scope((extent, source_info), block, |this| this.stmt_expr(block, value)) } ExprKind::Assign { lhs, rhs } => { let lhs = this.hir.mirror(lhs); @@ -81,7 +81,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { *this.find_breakable_scope(expr_span, label); let continue_block = continue_block.expect( "Attempted to continue in non-continuable breakable block"); - this.exit_scope(expr_span, extent, block, continue_block); + this.exit_scope(expr_span, (extent, source_info), block, continue_block); this.cfg.start_new_block().unit() } ExprKind::Break { label, value } => { @@ -99,7 +99,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } else { this.cfg.push_assign_unit(block, source_info, &destination) } - this.exit_scope(expr_span, extent, block, break_block); + this.exit_scope(expr_span, (extent, source_info), block, break_block); this.cfg.start_new_block().unit() } ExprKind::Return { value } => { @@ -116,7 +116,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }; let extent = this.extent_of_return_scope(); let return_block = this.return_block(); - this.exit_scope(expr_span, extent, block, return_block); + this.exit_scope(expr_span, (extent, source_info), block, return_block); this.cfg.start_new_block().unit() } ExprKind::InlineAsm { asm, outputs, inputs } => { diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 2505e2f821..54f285480a 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -471,7 +471,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// But there may also be candidates that the test just doesn't /// apply to. The classical example involves wildcards: /// - /// ```rust,ignore + /// ``` + /// # let (x, y, z) = (true, true, true); /// match (x, y, z) { /// (true, _, true) => true, // (0) /// (_, true, _) => true, // (1) diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 28386fa598..f4d43e041a 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -306,7 +306,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let bool_ty = self.hir.bool_ty(); let eq_result = self.temp(bool_ty, test.span); let eq_block = self.cfg.start_new_block(); - let cleanup = self.diverge_cleanup(); + let cleanup = self.diverge_cleanup(test.span); self.cfg.terminate(block, source_info, TerminatorKind::Call { func: Operand::Constant(box Constant { span: test.span, diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 08a5cb37e5..eb1414d42e 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -83,7 +83,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t }; let src = MirSource::from_node(tcx, id); - tcx.infer_ctxt(body_id).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let cx = Cx::new(&infcx, src); let mut mir = if cx.tables().tainted_by_errors { build::construct_error(cx, body_id) @@ -171,7 +171,7 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { let span = tcx.hir.span(ctor_id); if let hir::VariantData::Tuple(ref fields, ctor_id) = *v { - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let (mut mir, src) = shim::build_adt_ctor(&infcx, ctor_id, fields, span); @@ -339,8 +339,9 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let call_site_extent = CodeExtent::CallSiteScope(body.id()); let arg_extent = CodeExtent::ParameterScope(body.id()); let mut block = START_BLOCK; - unpack!(block = builder.in_scope(call_site_extent, block, |builder| { - unpack!(block = builder.in_scope(arg_extent, block, |builder| { + let source_info = builder.source_info(span); + unpack!(block = builder.in_scope((call_site_extent, source_info), block, |builder| { + unpack!(block = builder.in_scope((arg_extent, source_info), block, |builder| { builder.args_and_body(block, &arguments, arg_extent, &body.value) })); // Attribute epilogue to function's closing brace @@ -365,13 +366,14 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| { freevars.iter().map(|fv| { let var_id = tcx.hir.as_local_node_id(fv.def.def_id()).unwrap(); - let by_ref = hir.tables().upvar_capture(ty::UpvarId { + let capture = hir.tables().upvar_capture(ty::UpvarId { var_id: var_id, closure_expr_id: fn_id - }).map_or(false, |capture| match capture { + }); + let by_ref = match capture { ty::UpvarCapture::ByValue => false, ty::UpvarCapture::ByRef(..) => true - }); + }; let mut decl = UpvarDecl { debug_name: keywords::Invalid.name(), by_ref: by_ref diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index a99e7b4be5..2244ffde3c 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -47,11 +47,12 @@ set of scheduled drops up front, and so whenever we exit from the scope we only drop the values scheduled thus far. For example, consider the scope S corresponding to this loop: -```rust,ignore +``` +# let cond = true; loop { - let x = ...; + let x = ..; if cond { break; } - let y = ...; + let y = ..; } ``` @@ -94,10 +95,11 @@ use rustc::ty::subst::{Kind, Subst}; use rustc::ty::{Ty, TyCtxt}; use rustc::mir::*; use rustc::mir::transform::MirSource; -use syntax_pos::Span; +use syntax_pos::{Span}; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::fx::FxHashMap; +#[derive(Debug)] pub struct Scope<'tcx> { /// The visibility scope this scope was created in. visibility_scope: VisibilityScope, @@ -114,7 +116,7 @@ pub struct Scope<'tcx> { /// * pollutting the cleanup MIR with StorageDead creates /// landing pads even though there's no actual destructors /// * freeing up stack space has no effect during unwinding - needs_cleanup: bool, + pub(super) needs_cleanup: bool, /// set of lvalues to drop when exiting this scope. This starts /// out empty but grows as variables are declared during the @@ -141,6 +143,7 @@ pub struct Scope<'tcx> { cached_exits: FxHashMap<(BasicBlock, CodeExtent), BasicBlock>, } +#[derive(Debug)] struct DropData<'tcx> { /// span where drop obligation was incurred (typically where lvalue was declared) span: Span, @@ -152,6 +155,7 @@ struct DropData<'tcx> { kind: DropKind } +#[derive(Debug)] enum DropKind { Value { /// The cached block for the cleanups-on-diverge path. This block @@ -163,6 +167,7 @@ enum DropKind { Storage } +#[derive(Debug)] struct FreeData<'tcx> { /// span where free obligation was incurred span: Span, @@ -269,17 +274,34 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { res } + pub fn in_opt_scope(&mut self, + opt_extent: Option<(CodeExtent, SourceInfo)>, + mut block: BasicBlock, + f: F) + -> BlockAnd + where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) -> BlockAnd + { + debug!("in_opt_scope(opt_extent={:?}, block={:?})", opt_extent, block); + if let Some(extent) = opt_extent { self.push_scope(extent.0); } + let rv = unpack!(block = f(self)); + if let Some(extent) = opt_extent { + unpack!(block = self.pop_scope(extent, block)); + } + debug!("in_scope: exiting opt_extent={:?} block={:?}", opt_extent, block); + block.and(rv) + } + /// Convenience wrapper that pushes a scope and then executes `f` /// to build its contents, popping the scope afterwards. pub fn in_scope(&mut self, - extent: CodeExtent, + extent: (CodeExtent, SourceInfo), mut block: BasicBlock, f: F) -> BlockAnd where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) -> BlockAnd { debug!("in_scope(extent={:?}, block={:?})", extent, block); - self.push_scope(extent); + self.push_scope(extent.0); let rv = unpack!(block = f(self)); unpack!(block = self.pop_scope(extent, block)); debug!("in_scope: exiting extent={:?} block={:?}", extent, block); @@ -307,20 +329,22 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// drops onto the end of `block` that are needed. This must /// match 1-to-1 with `push_scope`. pub fn pop_scope(&mut self, - extent: CodeExtent, + extent: (CodeExtent, SourceInfo), mut block: BasicBlock) -> BlockAnd<()> { debug!("pop_scope({:?}, {:?})", extent, block); // We need to have `cached_block`s available for all the drops, so we call diverge_cleanup // to make sure all the `cached_block`s are filled in. - self.diverge_cleanup(); + self.diverge_cleanup(extent.1.span); let scope = self.scopes.pop().unwrap(); - assert_eq!(scope.extent, extent); + assert_eq!(scope.extent, extent.0); unpack!(block = build_scope_drops(&mut self.cfg, &scope, &self.scopes, block, self.arg_count)); + + self.cfg.push_end_region(block, extent.1, scope.extent); block.unit() } @@ -331,11 +355,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// module comment for details. pub fn exit_scope(&mut self, span: Span, - extent: CodeExtent, + extent: (CodeExtent, SourceInfo), mut block: BasicBlock, target: BasicBlock) { debug!("exit_scope(extent={:?}, block={:?}, target={:?})", extent, block, target); - let scope_count = 1 + self.scopes.iter().rev().position(|scope| scope.extent == extent) + let scope_count = 1 + self.scopes.iter().rev().position(|scope| scope.extent == extent.0) .unwrap_or_else(||{ span_bug!(span, "extent {:?} does not enclose", extent) }); @@ -346,7 +370,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let mut rest = &mut self.scopes[(len - scope_count)..]; while let Some((scope, rest_)) = {rest}.split_last_mut() { rest = rest_; - block = if let Some(&e) = scope.cached_exits.get(&(target, extent)) { + block = if let Some(&e) = scope.cached_exits.get(&(target, extent.0)) { self.cfg.terminate(block, scope.source_info(span), TerminatorKind::Goto { target: e }); return; @@ -354,7 +378,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let b = self.cfg.start_new_block(); self.cfg.terminate(block, scope.source_info(span), TerminatorKind::Goto { target: b }); - scope.cached_exits.insert((target, extent), b); + scope.cached_exits.insert((target, extent.0), b); b }; unpack!(block = build_scope_drops(&mut self.cfg, @@ -362,6 +386,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { rest, block, self.arg_count)); + + // End all regions for scopes out of which we are breaking. + self.cfg.push_end_region(block, extent.1, scope.extent); + if let Some(ref free_data) = scope.free { let next = self.cfg.start_new_block(); let free = build_free(self.hir.tcx(), &tmp, free_data, next); @@ -590,7 +618,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// This path terminates in Resume. Returns the start of the path. /// See module comment for more details. None indicates there’s no /// cleanup to do at this point. - pub fn diverge_cleanup(&mut self) -> Option { + pub fn diverge_cleanup(&mut self, span: Span) -> Option { if !self.scopes.iter().any(|scope| scope.needs_cleanup) { return None; } @@ -623,8 +651,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { resumeblk }; - for scope in scopes.iter_mut().filter(|s| s.needs_cleanup) { - target = build_diverge_scope(hir.tcx(), cfg, &unit_temp, scope, target); + for scope in scopes.iter_mut() { + target = build_diverge_scope(hir.tcx(), cfg, &unit_temp, span, scope, target); } Some(target) } @@ -640,7 +668,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } let source_info = self.source_info(span); let next_target = self.cfg.start_new_block(); - let diverge_target = self.diverge_cleanup(); + let diverge_target = self.diverge_cleanup(span); self.cfg.terminate(block, source_info, TerminatorKind::Drop { location: location, @@ -658,7 +686,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { value: Operand<'tcx>) -> BlockAnd<()> { let source_info = self.source_info(span); let next_target = self.cfg.start_new_block(); - let diverge_target = self.diverge_cleanup(); + let diverge_target = self.diverge_cleanup(span); self.cfg.terminate(block, source_info, TerminatorKind::DropAndReplace { location: location, @@ -681,7 +709,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let source_info = self.source_info(span); let success_block = self.cfg.start_new_block(); - let cleanup = self.diverge_cleanup(); + let cleanup = self.diverge_cleanup(span); self.cfg.terminate(block, source_info, TerminatorKind::Assert { @@ -750,6 +778,7 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>, fn build_diverge_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, cfg: &mut CFG<'tcx>, unit_temp: &Lvalue<'tcx>, + span: Span, scope: &mut Scope<'tcx>, mut target: BasicBlock) -> BasicBlock @@ -757,9 +786,9 @@ fn build_diverge_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, // Build up the drops in **reverse** order. The end result will // look like: // - // [drops[n]] -...-> [drops[0]] -> [Free] -> [target] - // | | - // +------------------------------------+ + // [EndRegion Block] -> [drops[n]] -...-> [drops[0]] -> [Free] -> [target] + // | | + // +---------------------------------------------------------+ // code for scope // // The code in this function reads from right to left. At each @@ -789,9 +818,16 @@ fn build_diverge_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, // Next, build up the drops. Here we iterate the vector in // *forward* order, so that we generate drops[0] first (right to // left in diagram above). - for drop_data in &mut scope.drops { + for (j, drop_data) in scope.drops.iter_mut().enumerate() { + debug!("build_diverge_scope drop_data[{}]: {:?}", j, drop_data); // Only full value drops are emitted in the diverging path, // not StorageDead. + // + // Note: This may not actually be what we desire (are we + // "freeing" stack storage as we unwind, or merely observing a + // frozen stack)? In particular, the intent may have been to + // match the behavior of clang, but on inspection eddyb says + // this is not what clang does. let cached_block = match drop_data.kind { DropKind::Value { ref mut cached_block } => cached_block, DropKind::Storage => continue @@ -811,6 +847,15 @@ fn build_diverge_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, }; } + // Finally, push the EndRegion block, used by mir-borrowck. (Block + // becomes trivial goto after pass that removes all EndRegions.) + { + let block = cfg.start_new_cleanup_block(); + cfg.push_end_region(block, source_info(span), scope.extent); + cfg.terminate(block, source_info(span), TerminatorKind::Goto { target: target }); + target = block + } + target } diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_mir/dataflow/drop_flag_effects.rs similarity index 67% rename from src/librustc_borrowck/borrowck/mir/mod.rs rename to src/librustc_mir/dataflow/drop_flag_effects.rs index 2b39d2a256..daafbecc5d 100644 --- a/src/librustc_borrowck/borrowck/mir/mod.rs +++ b/src/librustc_mir/dataflow/drop_flag_effects.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2016 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. // @@ -8,33 +8,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use borrowck::BorrowckCtxt; - use syntax::ast::{self, MetaItem}; use syntax_pos::DUMMY_SP; -use rustc::mir::{self, BasicBlock, BasicBlockData, Mir, Statement, Terminator, Location}; + +use rustc::mir::{self, Mir, BasicBlock, Location}; use rustc::session::Session; use rustc::ty::{self, TyCtxt}; -use rustc_mir::util::elaborate_drops::DropFlagState; -use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf}; - -mod abs_domain; -pub mod elaborate_drops; -mod dataflow; -mod gather_moves; -// mod graphviz; - -use self::dataflow::{BitDenotation}; -use self::dataflow::{DataflowOperator}; -use self::dataflow::{Dataflow, DataflowAnalysis, DataflowResults}; -use self::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; -use self::dataflow::{DefinitelyInitializedLvals}; -use self::gather_moves::{HasMoveData, MoveData, MovePathIndex, LookupResult}; +use util::elaborate_drops::DropFlagState; +use rustc_data_structures::indexed_set::{IdxSet}; use std::fmt; -fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option { +use super::{Dataflow, DataflowBuilder, DataflowAnalysis}; +use super::{BitDenotation, DataflowOperator, DataflowResults}; +use super::indexes::MovePathIndex; +use super::move_paths::{MoveData, LookupResult}; + +pub(crate) fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option { for attr in attrs { if attr.check_name("rustc_mir") { let items = attr.meta_item_list(); @@ -50,69 +41,11 @@ fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option } pub struct MoveDataParamEnv<'tcx> { - move_data: MoveData<'tcx>, - param_env: ty::ParamEnv<'tcx>, + pub(crate) move_data: MoveData<'tcx>, + pub(crate) param_env: ty::ParamEnv<'tcx>, } -pub fn borrowck_mir(bcx: &mut BorrowckCtxt, - id: ast::NodeId, - attributes: &[ast::Attribute]) { - let tcx = bcx.tcx; - let def_id = tcx.hir.local_def_id(id); - debug!("borrowck_mir({:?}) UNIMPLEMENTED", def_id); - - // It is safe for us to borrow `mir_validated()`: `optimized_mir` - // steals it, but it forces the `borrowck` query. - let mir = &tcx.mir_validated(def_id).borrow(); - - let param_env = tcx.param_env(def_id); - let move_data = MoveData::gather_moves(mir, tcx, param_env); - let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; - let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); - let flow_inits = - do_dataflow(tcx, mir, id, attributes, &dead_unwinds, - MaybeInitializedLvals::new(tcx, mir, &mdpe), - |bd, i| &bd.move_data().move_paths[i]); - let flow_uninits = - do_dataflow(tcx, mir, id, attributes, &dead_unwinds, - MaybeUninitializedLvals::new(tcx, mir, &mdpe), - |bd, i| &bd.move_data().move_paths[i]); - let flow_def_inits = - do_dataflow(tcx, mir, id, attributes, &dead_unwinds, - 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, &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, &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, &flow_def_inits); - } - - if has_rustc_mir_with(attributes, "stop_after_dataflow").is_some() { - bcx.tcx.sess.fatal("stop_after_dataflow ended compilation"); - } - - let mut mbcx = MirBorrowckCtxt { - bcx: bcx, - mir: mir, - node_id: id, - move_data: &mdpe.move_data, - flow_inits: flow_inits, - flow_uninits: flow_uninits, - }; - - for bb in mir.basic_blocks().indices() { - mbcx.process_basic_block(bb); - } - - debug!("borrowck_mir done"); -} - -fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>, +pub(crate) fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, node_id: ast::NodeId, attributes: &[ast::Attribute], @@ -142,7 +75,7 @@ fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let print_postflow_to = name_found(tcx.sess, attributes, "borrowck_graphviz_postflow"); - let mut mbcx = MirBorrowckCtxtPreDataflow { + let mut mbcx = DataflowBuilder { node_id: node_id, print_preflow_to: print_preflow_to, print_postflow_to: print_postflow_to, @@ -153,46 +86,7 @@ fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mbcx.flow_state.results() } - -pub struct MirBorrowckCtxtPreDataflow<'a, 'tcx: 'a, BD> where BD: BitDenotation -{ - node_id: ast::NodeId, - flow_state: DataflowAnalysis<'a, 'tcx, BD>, - print_preflow_to: Option, - print_postflow_to: Option, -} - -#[allow(dead_code)] -pub struct MirBorrowckCtxt<'b, 'a: 'b, 'tcx: 'a> { - bcx: &'b mut BorrowckCtxt<'a, 'tcx>, - mir: &'b Mir<'tcx>, - node_id: ast::NodeId, - move_data: &'b MoveData<'tcx>, - flow_inits: DataflowResults>, - flow_uninits: DataflowResults> -} - -impl<'b, 'a: 'b, 'tcx: 'a> MirBorrowckCtxt<'b, 'a, 'tcx> { - fn process_basic_block(&mut self, bb: BasicBlock) { - let BasicBlockData { ref statements, ref terminator, is_cleanup: _ } = - self.mir[bb]; - for stmt in statements { - self.process_statement(bb, stmt); - } - - self.process_terminator(bb, terminator); - } - - fn process_statement(&mut self, bb: BasicBlock, stmt: &Statement<'tcx>) { - debug!("MirBorrowckCtxt::process_statement({:?}, {:?}", bb, stmt); - } - - fn process_terminator(&mut self, bb: BasicBlock, term: &Option>) { - debug!("MirBorrowckCtxt::process_terminator({:?}, {:?})", bb, term); - } -} - -fn move_path_children_matching<'tcx, F>(move_data: &MoveData<'tcx>, +pub fn move_path_children_matching<'tcx, F>(move_data: &MoveData<'tcx>, path: MovePathIndex, mut cond: F) -> Option @@ -253,7 +147,7 @@ fn lvalue_contents_drop_state_cannot_differ<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx } } -fn on_lookup_result_bits<'a, 'tcx, F>( +pub(crate) fn on_lookup_result_bits<'a, 'tcx, F>( tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, move_data: &MoveData<'tcx>, @@ -271,7 +165,7 @@ fn on_lookup_result_bits<'a, 'tcx, F>( } } -fn on_all_children_bits<'a, 'tcx, F>( +pub(crate) fn on_all_children_bits<'a, 'tcx, F>( tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, move_data: &MoveData<'tcx>, @@ -312,7 +206,7 @@ fn on_all_children_bits<'a, 'tcx, F>( on_all_children_bits(tcx, mir, move_data, move_path_index, &mut each_child); } -fn on_all_drop_children_bits<'a, 'tcx, F>( +pub(crate) fn on_all_drop_children_bits<'a, 'tcx, F>( tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, ctxt: &MoveDataParamEnv<'tcx>, @@ -333,7 +227,7 @@ fn on_all_drop_children_bits<'a, 'tcx, F>( }) } -fn drop_flag_effects_for_function_entry<'a, 'tcx, F>( +pub(crate) fn drop_flag_effects_for_function_entry<'a, 'tcx, F>( tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, ctxt: &MoveDataParamEnv<'tcx>, @@ -350,7 +244,7 @@ fn drop_flag_effects_for_function_entry<'a, 'tcx, F>( } } -fn drop_flag_effects_for_location<'a, 'tcx, F>( +pub(crate) fn drop_flag_effects_for_location<'a, 'tcx, F>( tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, ctxt: &MoveDataParamEnv<'tcx>, @@ -394,6 +288,7 @@ fn drop_flag_effects_for_location<'a, 'tcx, F>( mir::StatementKind::StorageLive(_) | mir::StatementKind::StorageDead(_) | mir::StatementKind::InlineAsm { .. } | + mir::StatementKind::EndRegion(_) | mir::StatementKind::Nop => {} }, None => { diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs similarity index 97% rename from src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs rename to src/librustc_mir/dataflow/graphviz.rs index 7f95f07f48..e6d77aa268 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs +++ b/src/librustc_mir/dataflow/graphviz.rs @@ -15,7 +15,6 @@ use rustc::mir::{BasicBlock, Mir}; use rustc_data_structures::bitslice::bits_to_string; use rustc_data_structures::indexed_set::{IdxSet}; use rustc_data_structures::indexed_vec::Idx; -use rustc_mir::util as mir_util; use dot; use dot::IntoCow; @@ -28,8 +27,10 @@ use std::marker::PhantomData; use std::mem; use std::path::Path; -use super::super::MirBorrowckCtxtPreDataflow; +use util; + use super::{BitDenotation, DataflowState}; +use super::DataflowBuilder; impl DataflowState { fn each_bit(&self, words: &IdxSet, mut f: F) @@ -86,7 +87,7 @@ pub trait MirWithFlowState<'tcx> { fn flow_state(&self) -> &DataflowState; } -impl<'a, 'tcx: 'a, BD> MirWithFlowState<'tcx> for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD> +impl<'a, 'tcx: 'a, BD> MirWithFlowState<'tcx> for DataflowBuilder<'a, 'tcx, BD> where 'tcx: 'a, BD: BitDenotation { type BD = BD; @@ -103,8 +104,8 @@ struct Graph<'a, 'tcx, MWF:'a, P> where render_idx: P, } -pub fn print_borrowck_graph_to<'a, 'tcx, BD, P>( - mbcx: &MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>, +pub(crate) fn print_borrowck_graph_to<'a, 'tcx, BD, P>( + mbcx: &DataflowBuilder<'a, 'tcx, BD>, path: &Path, render_idx: P) -> io::Result<()> @@ -220,7 +221,7 @@ impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P> } Ok(()) } - mir_util::write_graphviz_node_label( + util::write_graphviz_node_label( *n, self.mbcx.mir(), &mut v, 4, |w| { let flow = self.mbcx.flow_state(); diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs b/src/librustc_mir/dataflow/impls/mod.rs similarity index 96% rename from src/librustc_borrowck/borrowck/mir/dataflow/impls.rs rename to src/librustc_mir/dataflow/impls/mod.rs index da8aa231cc..97c996dea6 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -8,25 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Dataflow analyses are built upon some interpretation of the +//! bitvectors attached to each basic block, represented via a +//! zero-sized structure. + use rustc::ty::TyCtxt; use rustc::mir::{self, Mir, Location}; use rustc_data_structures::bitslice::BitSlice; // adds set_bit/get_bit to &[usize] bitvector rep. use rustc_data_structures::bitslice::{BitwiseOperator}; use rustc_data_structures::indexed_set::{IdxSet}; use rustc_data_structures::indexed_vec::Idx; -use rustc_mir::util::elaborate_drops::DropFlagState; -use super::super::gather_moves::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex}; -use super::super::MoveDataParamEnv; -use super::super::drop_flag_effects_for_function_entry; -use super::super::drop_flag_effects_for_location; -use super::super::on_lookup_result_bits; +use super::MoveDataParamEnv; +use util::elaborate_drops::DropFlagState; +use super::move_paths::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex}; use super::{BitDenotation, BlockSets, DataflowOperator}; -// Dataflow analyses are built upon some interpretation of the -// bitvectors attached to each basic block, represented via a -// zero-sized structure. +use super::drop_flag_effects_for_function_entry; +use super::drop_flag_effects_for_location; +use super::on_lookup_result_bits; /// `MaybeInitializedLvals` tracks all l-values that might be /// initialized upon reaching a particular point in the control flow @@ -219,6 +220,16 @@ pub struct MovingOutStatements<'a, 'tcx: 'a> { mdpe: &'a MoveDataParamEnv<'tcx>, } +impl<'a, 'tcx: 'a> MovingOutStatements<'a, 'tcx> { + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &'a Mir<'tcx>, + mdpe: &'a MoveDataParamEnv<'tcx>) + -> Self + { + MovingOutStatements { tcx: tcx, mir: mir, mdpe: mdpe } + } +} + impl<'a, 'tcx> HasMoveData<'tcx> for MovingOutStatements<'a, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } } @@ -474,6 +485,7 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> { mir::StatementKind::StorageLive(_) | mir::StatementKind::StorageDead(_) | mir::StatementKind::InlineAsm { .. } | + mir::StatementKind::EndRegion(_) | mir::StatementKind::Nop => {} } } diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs similarity index 95% rename from src/librustc_borrowck/borrowck/mir/dataflow/mod.rs rename to src/librustc_mir/dataflow/mod.rs index f0f082a256..d7ad9f9c09 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use syntax::ast; + use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf}; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::bitslice::{bitwise, BitwiseOperator}; -use rustc::ty::TyCtxt; +use rustc::ty::{TyCtxt}; use rustc::mir::{self, Mir}; use std::fmt::Debug; @@ -21,21 +23,31 @@ use std::mem; use std::path::PathBuf; use std::usize; -use super::MirBorrowckCtxtPreDataflow; - -pub use self::sanity_check::sanity_check_via_rustc_peek; pub use self::impls::{MaybeInitializedLvals, MaybeUninitializedLvals}; pub use self::impls::{DefinitelyInitializedLvals, MovingOutStatements}; +pub(crate) use self::drop_flag_effects::*; + +mod drop_flag_effects; mod graphviz; -mod sanity_check; mod impls; +pub mod move_paths; + +pub(crate) use self::move_paths::indexes; + +pub(crate) struct DataflowBuilder<'a, 'tcx: 'a, BD> where BD: BitDenotation +{ + node_id: ast::NodeId, + flow_state: DataflowAnalysis<'a, 'tcx, BD>, + print_preflow_to: Option, + print_postflow_to: Option, +} pub trait Dataflow { fn dataflow

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

(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug { @@ -135,7 +147,7 @@ fn dataflow_path(context: &str, prepost: &str, path: &str) -> PathBuf { path } -impl<'a, 'tcx: 'a, BD> MirBorrowckCtxtPreDataflow<'a, 'tcx, BD> +impl<'a, 'tcx: 'a, BD> DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation { fn pre_dataflow_instrumentation

(&self, p: P) -> io::Result<()> @@ -195,7 +207,7 @@ impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O> pub fn mir(&self) -> &'a Mir<'tcx> { self.mir } } -pub struct DataflowResults(DataflowState) where O: BitDenotation; +pub struct DataflowResults(pub(crate) DataflowState) where O: BitDenotation; impl DataflowResults { pub fn sets(&self) -> &AllSets { @@ -213,7 +225,7 @@ pub struct DataflowState pub sets: AllSets, /// operator used to initialize, combine, and interpret bits. - operator: O, + pub(crate) operator: O, } #[derive(Debug)] @@ -240,9 +252,9 @@ pub struct AllSets { } pub struct BlockSets<'a, E: Idx> { - on_entry: &'a mut IdxSet, - gen_set: &'a mut IdxSet, - kill_set: &'a mut IdxSet, + pub(crate) on_entry: &'a mut IdxSet, + pub(crate) gen_set: &'a mut IdxSet, + pub(crate) kill_set: &'a mut IdxSet, } impl<'a, E:Idx> BlockSets<'a, E> { diff --git a/src/librustc_borrowck/borrowck/mir/abs_domain.rs b/src/librustc_mir/dataflow/move_paths/abs_domain.rs similarity index 100% rename from src/librustc_borrowck/borrowck/mir/abs_domain.rs rename to src/librustc_mir/dataflow/move_paths/abs_domain.rs diff --git a/src/librustc_borrowck/borrowck/mir/gather_moves.rs b/src/librustc_mir/dataflow/move_paths/mod.rs similarity index 98% rename from src/librustc_borrowck/borrowck/mir/gather_moves.rs rename to src/librustc_mir/dataflow/move_paths/mod.rs index b03d2a775d..d7ed0938e8 100644 --- a/src/librustc_borrowck/borrowck/mir/gather_moves.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -21,14 +21,16 @@ use std::fmt; use std::mem; use std::ops::{Index, IndexMut}; -use super::abs_domain::{AbstractElem, Lift}; +use self::abs_domain::{AbstractElem, Lift}; + +mod abs_domain; // This submodule holds some newtype'd Index wrappers that are using // NonZero to ensure that Option occupies only a single word. // They are in a submodule to impose privacy restrictions; namely, to // ensure that other code does not accidentally access `index.0` // (which is likely to yield a subtle off-by-one error). -mod indexes { +pub(crate) mod indexes { use std::fmt; use core::nonzero::NonZero; use rustc_data_structures::indexed_vec::Idx; @@ -65,7 +67,7 @@ mod indexes { pub use self::indexes::MovePathIndex; pub use self::indexes::MoveOutIndex; -impl self::indexes::MoveOutIndex { +impl MoveOutIndex { pub fn move_path_index(&self, move_data: &MoveData) -> MovePathIndex { move_data.moves[*self].path } @@ -128,7 +130,7 @@ pub trait HasMoveData<'tcx> { pub struct LocationMap { /// Location-indexed (BasicBlock for outer index, index within BB /// for inner index) map. - map: IndexVec>, + pub(crate) map: IndexVec>, } impl Index for LocationMap { @@ -188,7 +190,7 @@ pub struct MovePathLookup<'tcx> { projections: FxHashMap<(MovePathIndex, AbstractElem<'tcx>), MovePathIndex> } -struct MoveDataBuilder<'a, 'tcx: 'a> { +pub(super) struct MoveDataBuilder<'a, 'tcx: 'a> { mir: &'a Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -413,6 +415,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { "SetDiscriminant should not exist during borrowck"); } StatementKind::InlineAsm { .. } | + StatementKind::EndRegion(_) | StatementKind::Nop => {} } } diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs index bb07081fe4..6f3db0b388 100644 --- a/src/librustc_mir/diagnostics.rs +++ b/src/librustc_mir/diagnostics.rs @@ -309,8 +309,8 @@ use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT}; const A: AtomicUsize = ATOMIC_USIZE_INIT; static B: &'static AtomicUsize = &A; -// error: cannot borrow a constant which contains interior mutability, create a -// static instead +// error: cannot borrow a constant which may contain interior mutability, +// create a static instead ``` A `const` represents a constant value that should never change. If one takes @@ -338,8 +338,8 @@ use std::cell::Cell; const A: Cell = Cell::new(1); const B: &'static Cell = &A; -// error: cannot borrow a constant which contains interior mutability, create -// a static instead +// error: cannot borrow a constant which may contain interior mutability, +// create a static instead // or: struct C { a: Cell } diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index 47c50b78f3..fad070ca8d 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -22,9 +22,14 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block { // We have to eagerly translate the "spine" of the statements // in order to get the lexical scoping correctly. let stmts = mirror_stmts(cx, self.id, &*self.stmts); + let opt_def_id = cx.tcx.hir.opt_local_def_id(self.id); + let opt_destruction_extent = opt_def_id.and_then(|def_id| { + cx.tcx.region_maps(def_id).opt_destruction_extent(self.id) + }); Block { targeted_by_break: self.targeted_by_break, extent: CodeExtent::Misc(self.id), + opt_destruction_extent: opt_destruction_extent, span: self.span, stmts: stmts, expr: self.expr.to_ref(), @@ -37,7 +42,11 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, stmts: &'tcx [hir::Stmt]) -> Vec> { let mut result = vec![]; + let opt_def_id = cx.tcx.hir.opt_local_def_id(block_id); for (index, stmt) in stmts.iter().enumerate() { + let opt_dxn_ext = opt_def_id.and_then(|def_id| { + cx.tcx.region_maps(def_id).opt_destruction_extent(stmt.node.id()) + }); match stmt.node { hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) => { @@ -47,6 +56,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, scope: CodeExtent::Misc(id), expr: expr.to_ref(), }, + opt_destruction_extent: opt_dxn_ext, }))) } hir::StmtDecl(ref decl, id) => { @@ -69,6 +79,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, pattern: pattern, initializer: local.init.to_ref(), }, + opt_destruction_extent: opt_dxn_ext, }))); } } diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 8cfeecdafb..0010f312ef 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -19,7 +19,6 @@ use rustc::middle::const_val::ConstVal; use rustc::ty::{self, AdtKind, VariantDef, Ty}; use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow}; use rustc::ty::cast::CastKind as TyCastKind; -use rustc::ty::subst::Subst; use rustc::hir; impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { @@ -586,7 +585,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }); Expr { temp_lifetime: temp_lifetime, - ty: cx.tcx.type_of(def_id).subst(cx.tcx, substs), + ty: cx.tcx().mk_fn_def(def_id, substs), span: expr.span, kind: ExprKind::Literal { literal: Literal::Value { @@ -758,13 +757,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, var_id: id_var, closure_expr_id: closure_expr_id, }; - let upvar_capture = match cx.tables().upvar_capture(upvar_id) { - Some(c) => c, - None => { - span_bug!(expr.span, "no upvar_capture for {:?}", upvar_id); - } - }; - match upvar_capture { + match cx.tables().upvar_capture(upvar_id) { ty::UpvarCapture::ByValue => field_kind, ty::UpvarCapture::ByRef(borrow) => { ExprKind::Deref { @@ -878,7 +871,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, var_id: id_var, closure_expr_id: closure_expr.id, }; - let upvar_capture = cx.tables().upvar_capture(upvar_id).unwrap(); + let upvar_capture = cx.tables().upvar_capture(upvar_id); let temp_lifetime = cx.region_maps.temporary_scope(closure_expr.id); let var_ty = cx.tables().node_id_to_type(id_var); let captured_var = Expr { diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 5b7b52a72b..2bb6b39966 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -37,6 +37,7 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, pub param_env: ty::ParamEnv<'tcx>, pub region_maps: Rc, + pub tables: &'a ty::TypeckTables<'gcx>, /// This is `Constness::Const` if we are compiling a `static`, /// `const`, or the body of a `const fn`. @@ -67,6 +68,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { let param_env = tcx.param_env(src_def_id); let region_maps = tcx.region_maps(src_def_id); + let tables = tcx.typeck_tables_of(src_def_id); let attrs = tcx.hir.attrs(src_id); @@ -82,7 +84,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { // Constants and const fn's always need overflow checks. check_overflow |= constness == hir::Constness::Const; - Cx { tcx, infcx, param_env, region_maps, constness, src, check_overflow } + Cx { tcx, infcx, param_env, region_maps, tables, constness, src, check_overflow } } } @@ -184,7 +186,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { } pub fn tables(&self) -> &'a ty::TypeckTables<'gcx> { - self.infcx.tables.expect_interned() + self.tables } pub fn check_overflow(&self) -> bool { diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 044096699b..bb11cce748 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -33,6 +33,7 @@ pub use rustc_const_eval::pattern::{BindingMode, Pattern, PatternKind, FieldPatt pub struct Block<'tcx> { pub targeted_by_break: bool, pub extent: CodeExtent, + pub opt_destruction_extent: Option, pub span: Span, pub stmts: Vec>, pub expr: Option>, @@ -47,6 +48,7 @@ pub enum StmtRef<'tcx> { pub struct Stmt<'tcx> { pub span: Span, pub kind: StmtKind<'tcx>, + pub opt_destruction_extent: Option, } #[derive(Clone, Debug)] diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 014705bf32..bb17677733 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -19,17 +19,15 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![crate_type = "dylib"] #![deny(warnings)] -#![feature(associated_consts)] #![feature(box_patterns)] #![feature(box_syntax)] #![feature(i128_type)] #![feature(rustc_diagnostic_macros)] #![feature(placement_in_syntax)] #![feature(collection_placement)] +#![feature(nonzero)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] +#![cfg_attr(stage0, feature(associated_consts))] #[macro_use] extern crate log; extern crate graphviz as dot; @@ -44,10 +42,12 @@ extern crate syntax; extern crate syntax_pos; extern crate rustc_const_math; extern crate rustc_const_eval; +extern crate core; // for NonZero pub mod diagnostics; mod build; +pub mod dataflow; mod hair; mod shim; pub mod transform; diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 54779cbe30..11ad5d1509 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -58,7 +58,7 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, // types in the MIR. They will be substituted again with // the param-substs, but because they are concrete, this // will not do any harm. - let sig = tcx.erase_late_bound_regions(&ty.fn_sig()); + let sig = tcx.erase_late_bound_regions(&ty.fn_sig(tcx)); let arg_tys = sig.inputs(); build_call_shim( @@ -153,8 +153,8 @@ fn build_drop_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, } else { Substs::identity_for_item(tcx, def_id) }; - let fn_ty = tcx.type_of(def_id).subst(tcx, substs); - let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig()); + let sig = tcx.fn_sig(def_id).subst(tcx, substs); + let sig = tcx.erase_late_bound_regions(&sig); let span = tcx.def_span(def_id); let source_info = SourceInfo { span, scope: ARGUMENT_VISIBILITY_SCOPE }; @@ -276,8 +276,8 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, call_kind={:?}, untuple_args={:?})", def_id, rcvr_adjustment, call_kind, untuple_args); - let fn_ty = tcx.type_of(def_id); - let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig()); + let sig = tcx.fn_sig(def_id); + let sig = tcx.erase_late_bound_regions(&sig); let span = tcx.def_span(def_id); debug!("build_call_shim: sig={:?}", sig); @@ -409,11 +409,8 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, { let tcx = infcx.tcx; let def_id = tcx.hir.local_def_id(ctor_id); - let sig = match tcx.type_of(def_id).sty { - ty::TyFnDef(_, _, fty) => tcx.no_late_bound_regions(&fty) - .expect("LBR in ADT constructor signature"), - _ => bug!("unexpected type for ctor {:?}", def_id) - }; + let sig = tcx.no_late_bound_regions(&tcx.fn_sig(def_id)) + .expect("LBR in ADT constructor signature"); let sig = tcx.erase_regions(&sig); let (adt_def, substs) = match sig.output().sty { diff --git a/src/librustc_mir/transform/clean_end_regions.rs b/src/librustc_mir/transform/clean_end_regions.rs new file mode 100644 index 0000000000..36125f9454 --- /dev/null +++ b/src/librustc_mir/transform/clean_end_regions.rs @@ -0,0 +1,84 @@ +// 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. + +//! This module provides one pass, `CleanEndRegions`, that reduces the +//! set of `EndRegion` statements in the MIR. +//! +//! The "pass" is actually implemented as two traversals (aka visits) +//! of the input MIR. The first traversal, `GatherBorrowedRegions`, +//! finds all of the regions in the MIR that are involved in a borrow. +//! +//! The second traversal, `DeleteTrivialEndRegions`, walks over the +//! MIR and removes any `EndRegion` that is applied to a region that +//! was not seen in the previous pass. + +use rustc_data_structures::fx::FxHashSet; + +use rustc::middle::region::CodeExtent; +use rustc::mir::transform::{MirPass, MirSource}; +use rustc::mir::{BasicBlock, Location, Mir, Rvalue, Statement, StatementKind}; +use rustc::mir::visit::{MutVisitor, Visitor}; +use rustc::ty::{RegionKind, TyCtxt}; + +pub struct CleanEndRegions; + +struct GatherBorrowedRegions { + seen_regions: FxHashSet, +} + +struct DeleteTrivialEndRegions<'a> { + seen_regions: &'a FxHashSet, +} + +impl MirPass for CleanEndRegions { + fn run_pass<'a, 'tcx>(&self, + _tcx: TyCtxt<'a, 'tcx, 'tcx>, + _source: MirSource, + mir: &mut Mir<'tcx>) { + let mut gather = GatherBorrowedRegions { seen_regions: FxHashSet() }; + gather.visit_mir(mir); + + let mut delete = DeleteTrivialEndRegions { seen_regions: &mut gather.seen_regions }; + delete.visit_mir(mir); + } +} + +impl<'tcx> Visitor<'tcx> for GatherBorrowedRegions { + fn visit_rvalue(&mut self, + rvalue: &Rvalue<'tcx>, + location: Location) { + if let Rvalue::Ref(r, _, _) = *rvalue { + if let RegionKind::ReScope(ce) = *r { + self.seen_regions.insert(ce); + } + } + self.super_rvalue(rvalue, location); + } +} + +impl<'a, 'tcx> MutVisitor<'tcx> for DeleteTrivialEndRegions<'a> { + fn visit_statement(&mut self, + block: BasicBlock, + statement: &mut Statement<'tcx>, + location: Location) { + let mut delete_it = false; + + if let StatementKind::EndRegion(ref extent) = statement.kind { + if !self.seen_regions.contains(extent) { + delete_it = true; + } + } + + if delete_it { + statement.kind = StatementKind::Nop; + } + self.super_statement(block, statement, location); + } +} diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs index 08a4961c6c..dec0717e9e 100644 --- a/src/librustc_mir/transform/copy_prop.rs +++ b/src/librustc_mir/transform/copy_prop.rs @@ -34,7 +34,6 @@ use rustc::mir::transform::{MirPass, MirSource}; use rustc::mir::visit::MutVisitor; use rustc::ty::TyCtxt; use util::def_use::DefUseAnalysis; -use transform::qualify_consts; pub struct CopyPropagation; @@ -55,7 +54,7 @@ impl MirPass for CopyPropagation { return } MirSource::Fn(function_node_id) => { - if qualify_consts::is_const_fn(tcx, tcx.hir.local_def_id(function_node_id)) { + if tcx.is_const_fn(tcx.hir.local_def_id(function_node_id)) { // Don't run on const functions, as, again, trans might not be able to evaluate // the optimized IR. return diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs similarity index 93% rename from src/librustc_borrowck/borrowck/mir/elaborate_drops.rs rename to src/librustc_mir/transform/elaborate_drops.rs index b03d34819f..b158cb43ce 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -8,12 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::gather_moves::{HasMoveData, MoveData, MovePathIndex, LookupResult}; -use super::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; -use super::dataflow::{DataflowResults}; -use super::{on_all_children_bits, on_all_drop_children_bits}; -use super::{drop_flag_effects_for_location, on_lookup_result_bits}; -use super::MoveDataParamEnv; +use dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex, LookupResult}; +use dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; +use dataflow::{DataflowResults}; +use dataflow::{on_all_children_bits, on_all_drop_children_bits}; +use dataflow::{drop_flag_effects_for_location, on_lookup_result_bits}; +use dataflow::MoveDataParamEnv; +use dataflow; use rustc::ty::{self, TyCtxt}; use rustc::mir::*; use rustc::mir::transform::{MirPass, MirSource}; @@ -21,9 +22,9 @@ use rustc::middle::const_val::ConstVal; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_data_structures::indexed_vec::Idx; -use rustc_mir::util::patch::MirPatch; -use rustc_mir::util::elaborate_drops::{DropFlagState, Unwind, elaborate_drop}; -use rustc_mir::util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode}; +use util::patch::MirPatch; +use util::elaborate_drops::{DropFlagState, Unwind, elaborate_drop}; +use util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode}; use syntax::ast; use syntax_pos::Span; @@ -54,13 +55,13 @@ impl MirPass for ElaborateDrops { }; let dead_unwinds = find_dead_unwinds(tcx, mir, id, &env); let flow_inits = - super::do_dataflow(tcx, mir, id, &[], &dead_unwinds, - MaybeInitializedLvals::new(tcx, mir, &env), - |bd, p| &bd.move_data().move_paths[p]); + dataflow::do_dataflow(tcx, mir, id, &[], &dead_unwinds, + MaybeInitializedLvals::new(tcx, mir, &env), + |bd, p| &bd.move_data().move_paths[p]); let flow_uninits = - super::do_dataflow(tcx, mir, id, &[], &dead_unwinds, - MaybeUninitializedLvals::new(tcx, mir, &env), - |bd, p| &bd.move_data().move_paths[p]); + dataflow::do_dataflow(tcx, mir, id, &[], &dead_unwinds, + MaybeUninitializedLvals::new(tcx, mir, &env), + |bd, p| &bd.move_data().move_paths[p]); ElaborateDropsCtxt { tcx: tcx, @@ -91,7 +92,7 @@ fn find_dead_unwinds<'a, 'tcx>( // reach cleanup blocks, which can't have unwind edges themselves. let mut dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); let flow_inits = - super::do_dataflow(tcx, mir, id, &[], &dead_unwinds, + dataflow::do_dataflow(tcx, mir, id, &[], &dead_unwinds, MaybeInitializedLvals::new(tcx, mir, &env), |bd, p| &bd.move_data().move_paths[p]); for (bb, bb_data) in mir.basic_blocks().iter_enumerated() { @@ -242,7 +243,7 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> { } fn field_subpath(&self, path: Self::Path, field: Field) -> Option { - super::move_path_children_matching(self.ctxt.move_data(), path, |p| { + dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| { match p { &Projection { elem: ProjectionElem::Field(idx, _), .. @@ -253,7 +254,7 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> { } fn deref_subpath(&self, path: Self::Path) -> Option { - super::move_path_children_matching(self.ctxt.move_data(), path, |p| { + dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| { match p { &Projection { elem: ProjectionElem::Deref, .. } => true, _ => false @@ -262,7 +263,7 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> { } fn downcast_subpath(&self, path: Self::Path, variant: usize) -> Option { - super::move_path_children_matching(self.ctxt.move_data(), path, |p| { + dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| { match p { &Projection { elem: ProjectionElem::Downcast(_, idx), .. @@ -560,7 +561,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { fn drop_flags_for_args(&mut self) { let loc = Location { block: START_BLOCK, statement_index: 0 }; - super::drop_flag_effects_for_function_entry( + dataflow::drop_flag_effects_for_function_entry( self.tcx, self.mir, self.env, |path, ds| { self.set_drop_flag(loc, path, ds); } @@ -594,13 +595,18 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { assert!(self.patch.is_patched(bb)); allow_initializations = false; } + TerminatorKind::Resume => { + // It is possible for `Resume` to be patched + // (in particular it can be patched to be replaced with + // a Goto; see `MirPatch::new`). + } _ => { assert!(!self.patch.is_patched(bb)); } } } let loc = Location { block: bb, statement_index: i }; - super::drop_flag_effects_for_location( + dataflow::drop_flag_effects_for_location( self.tcx, self.mir, self.env, loc, |path, ds| { if ds == DropFlagState::Absent || allow_initializations { self.set_drop_flag(loc, path, ds) diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index fa88eca6ec..eb283df869 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -65,6 +65,16 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> { substs: &mut ClosureSubsts<'tcx>) { *substs = self.tcx.erase_regions(substs); } + + fn visit_statement(&mut self, + block: BasicBlock, + statement: &mut Statement<'tcx>, + location: Location) { + if let StatementKind::EndRegion(_) = statement.kind { + statement.kind = StatementKind::Nop; + } + self.super_statement(block, statement, location); + } } pub struct EraseRegions; diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 0ac35a5fdd..d3fee8045e 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -87,7 +87,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { let terminator = bb_data.terminator(); if let TerminatorKind::Call { func: Operand::Constant(ref f), .. } = terminator.kind { - if let ty::TyFnDef(callee_def_id, substs, _) = f.ty.sty { + if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty { callsites.push_back(CallSite { callee: callee_def_id, substs: substs, @@ -131,7 +131,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { let terminator = bb_data.terminator(); if let TerminatorKind::Call { func: Operand::Constant(ref f), .. } = terminator.kind { - if let ty::TyFnDef(callee_def_id, substs, _) = f.ty.sty { + if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty { // Don't inline the same function multiple times. if callsite.callee != callee_def_id { callsites.push_back(CallSite { @@ -250,7 +250,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { work_list.push(target); // If the location doesn't actually need dropping, treat it like // a regular goto. - let ty = location.ty(&callee_mir, tcx).subst(tcx, callsite.substs); + let ty = location.ty(callee_mir, tcx).subst(tcx, callsite.substs); let ty = ty.to_ty(tcx); if ty.needs_drop(tcx, param_env) { cost += CALL_PENALTY; @@ -270,8 +270,9 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { } TerminatorKind::Call {func: Operand::Constant(ref f), .. } => { - if let ty::TyFnDef(.., f) = f.ty.sty { + if let ty::TyFnDef(def_id, _) = f.ty.sty { // Don't give intrinsics the extra penalty for calls + let f = tcx.fn_sig(def_id); if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic { cost += INSTR_COST; } else { diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index fcea5d4c86..1530ea8e0d 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -24,11 +24,14 @@ use syntax::ast; use syntax_pos::{DUMMY_SP, Span}; use transform; +pub mod clean_end_regions; pub mod simplify_branches; pub mod simplify; pub mod erase_regions; pub mod no_landing_pads; pub mod type_check; +pub mod rustc_peek; +pub mod elaborate_drops; pub mod add_call_guards; pub mod promote_consts; pub mod qualify_consts; diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index ef88e813a5..502c64a209 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -19,7 +19,6 @@ use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc::hir; use rustc::hir::map as hir_map; use rustc::hir::def_id::DefId; -use rustc::hir::map::blocks::FnLikeNode; use rustc::traits::{self, Reveal}; use rustc::ty::{self, TyCtxt, Ty, TypeFoldable}; use rustc::ty::cast::CastTy; @@ -109,18 +108,6 @@ impl fmt::Display for Mode { } } -pub fn is_const_fn(tcx: TyCtxt, def_id: DefId) -> bool { - if let Some(node_id) = tcx.hir.as_local_node_id(def_id) { - if let Some(fn_like) = FnLikeNode::from_node(tcx.hir.get(node_id)) { - fn_like.constness() == hir::Constness::Const - } else { - false - } - } else { - tcx.sess.cstore.is_const_fn(def_id) - } -} - struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { mode: Mode, span: Span, @@ -257,8 +244,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { let mut span = None; self.tcx - .trait_def(drop_trait_id) - .for_each_relevant_impl(self.tcx, self.mir.return_ty, |impl_did| { + .for_each_relevant_impl(drop_trait_id, self.mir.return_ty, |impl_did| { self.tcx.hir .as_local_node_id(impl_did) .and_then(|impl_node_id| self.tcx.hir.find(impl_node_id)) @@ -663,7 +649,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { self.add(Qualif::NOT_CONST); if self.mode != Mode::Fn { span_err!(self.tcx.sess, self.span, E0492, - "cannot borrow a constant which contains \ + "cannot borrow a constant which may contain \ interior mutability, create a static instead"); } } @@ -763,10 +749,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { let fn_ty = func.ty(self.mir, self.tcx); let (is_shuffle, is_const_fn) = match fn_ty.sty { - ty::TyFnDef(def_id, _, f) => { - (f.abi() == Abi::PlatformIntrinsic && + ty::TyFnDef(def_id, _) => { + (self.tcx.fn_sig(def_id).abi() == Abi::PlatformIntrinsic && self.tcx.item_name(def_id).as_str().starts_with("simd_shuffle"), - is_const_fn(self.tcx, def_id)) + self.tcx.is_const_fn(def_id)) } _ => (false, false) }; @@ -907,6 +893,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::InlineAsm {..} | + StatementKind::EndRegion(_) | StatementKind::Nop => {} } }); @@ -957,7 +944,7 @@ impl MirPass for QualifyAndPromoteConstants { let def_id = tcx.hir.local_def_id(id); let mode = match src { MirSource::Fn(_) => { - if is_const_fn(tcx, def_id) { + if tcx.is_const_fn(def_id) { Mode::ConstFn } else { Mode::Fn @@ -998,7 +985,7 @@ impl MirPass for QualifyAndPromoteConstants { // Statics must be Sync. if mode == Mode::Static { let ty = mir.return_ty; - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let param_env = ty::ParamEnv::empty(Reveal::UserFacing); let cause = traits::ObligationCause::new(mir.span, id, traits::SharedStatic); let mut fulfillment_cx = traits::FulfillmentContext::new(); @@ -1008,7 +995,7 @@ impl MirPass for QualifyAndPromoteConstants { tcx.require_lang_item(lang_items::SyncTraitLangItem), cause); if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(&err); + infcx.report_fulfillment_errors(&err, None); } }); } diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs b/src/librustc_mir/transform/rustc_peek.rs similarity index 69% rename from src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs rename to src/librustc_mir/transform/rustc_peek.rs index 44e3b38ea3..5918de0c68 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -14,12 +14,67 @@ use syntax_pos::Span; use rustc::ty::{self, TyCtxt}; use rustc::mir::{self, Mir}; +use rustc::mir::transform::{MirPass, MirSource}; +use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_data_structures::indexed_vec::Idx; -use super::super::gather_moves::{MovePathIndex, LookupResult}; -use super::BitDenotation; -use super::DataflowResults; -use super::super::gather_moves::HasMoveData; +use dataflow::do_dataflow; +use dataflow::MoveDataParamEnv; +use dataflow::BitDenotation; +use dataflow::DataflowResults; +use dataflow::{DefinitelyInitializedLvals, MaybeInitializedLvals, MaybeUninitializedLvals}; +use dataflow::move_paths::{MovePathIndex, LookupResult}; +use dataflow::move_paths::{HasMoveData, MoveData}; +use dataflow; + +use dataflow::has_rustc_mir_with; + +pub struct SanityCheck; + +impl MirPass for SanityCheck { + fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, + src: MirSource, mir: &mut Mir<'tcx>) { + let id = src.item_id(); + let def_id = tcx.hir.local_def_id(id); + if !tcx.has_attr(def_id, "rustc_mir_borrowck") { + debug!("skipping rustc_peek::SanityCheck on {}", tcx.item_path_str(def_id)); + return; + } else { + debug!("running rustc_peek::SanityCheck on {}", tcx.item_path_str(def_id)); + } + + let attributes = tcx.get_attrs(def_id); + let param_env = tcx.param_env(def_id); + let move_data = MoveData::gather_moves(mir, tcx, param_env); + let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; + let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); + let flow_inits = + do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, + MaybeInitializedLvals::new(tcx, mir, &mdpe), + |bd, i| &bd.move_data().move_paths[i]); + let flow_uninits = + do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, + MaybeUninitializedLvals::new(tcx, mir, &mdpe), + |bd, i| &bd.move_data().move_paths[i]); + let flow_def_inits = + do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, + 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() { + sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_inits); + } + if has_rustc_mir_with(&attributes, "rustc_peek_maybe_uninit").is_some() { + sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_uninits); + } + if has_rustc_mir_with(&attributes, "rustc_peek_definite_init").is_some() { + sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_def_inits); + } + if has_rustc_mir_with(&attributes, "stop_after_dataflow").is_some() { + tcx.sess.fatal("stop_after_dataflow ended compilation"); + } + } +} /// This function scans `mir` for all calls to the intrinsic /// `rustc_peek` that have the expression form `rustc_peek(&expr)`. @@ -92,7 +147,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // of the argument at time immediate preceding Call to // `rustc_peek`). - let mut sets = super::BlockSets { on_entry: &mut entry, + let mut sets = dataflow::BlockSets { on_entry: &mut entry, gen_set: &mut gen, kill_set: &mut kill }; @@ -105,6 +160,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir::StatementKind::StorageLive(_) | mir::StatementKind::StorageDead(_) | mir::StatementKind::InlineAsm { .. } | + mir::StatementKind::EndRegion(_) | mir::StatementKind::Nop => continue, mir::StatementKind::SetDiscriminant{ .. } => span_bug!(stmt.source_info.span, @@ -160,18 +216,13 @@ fn is_rustc_peek<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, terminator: &'a Option>) -> Option<(&'a [mir::Operand<'tcx>], Span)> { if let Some(mir::Terminator { ref kind, source_info, .. }) = *terminator { - if let mir::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind - { - if let mir::Operand::Constant(ref func) = *oper - { - if let ty::TyFnDef(def_id, _, sig) = func.ty.sty - { - let abi = sig.abi(); + if let mir::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind { + if let mir::Operand::Constant(ref func) = *oper { + if let ty::TyFnDef(def_id, _) = func.ty.sty { + let abi = tcx.fn_sig(def_id).abi(); let name = tcx.item_name(def_id); - if abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic { - if name == "rustc_peek" { - return Some((args, source_info.span)); - } + if abi == Abi::RustIntrinsic && name == "rustc_peek" { + return Some((args, source_info.span)); } } } diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index da8e3b5a42..7e6fccf301 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -413,6 +413,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } StatementKind::InlineAsm { .. } | + StatementKind::EndRegion(_) | StatementKind::Nop => {} } } @@ -461,7 +462,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { let func_ty = func.ty(mir, tcx); debug!("check_terminator: call, func_ty={:?}", func_ty); let sig = match func_ty.sty { - ty::TyFnDef(.., sig) | ty::TyFnPtr(sig) => sig, + ty::TyFnDef(..) | ty::TyFnPtr(_) => func_ty.fn_sig(tcx), _ => { span_mirbug!(self, term, "call to non-function {:?}", func_ty); return; @@ -759,7 +760,7 @@ impl MirPass for TypeckMir { return; } let param_env = tcx.param_env(def_id); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let mut checker = TypeChecker::new(&infcx, item_id, param_env); { let mut verifier = TypeVerifier::new(&mut checker, mir); diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs index 7898d93c22..ac121131eb 100644 --- a/src/librustc_mir/util/patch.rs +++ b/src/librustc_mir/util/patch.rs @@ -46,6 +46,7 @@ impl<'tcx> MirPatch<'tcx> { for (bb, block) in mir.basic_blocks().iter_enumerated() { if let TerminatorKind::Resume = block.terminator().kind { if block.statements.len() > 0 { + assert!(resume_stmt_block.is_none()); resume_stmt_block = Some(bb); } else { resume_block = Some(bb); diff --git a/src/librustc_msan/Cargo.toml b/src/librustc_msan/Cargo.toml index b3b70bc0a2..8d7279b29e 100644 --- a/src/librustc_msan/Cargo.toml +++ b/src/librustc_msan/Cargo.toml @@ -14,5 +14,6 @@ build_helper = { path = "../build_helper" } cmake = "0.1.18" [dependencies] +alloc = { path = "../liballoc" } alloc_system = { path = "../liballoc_system" } core = { path = "../libcore" } diff --git a/src/librustc_msan/build.rs b/src/librustc_msan/build.rs index dcadbe8696..7e2a82dd0a 100644 --- a/src/librustc_msan/build.rs +++ b/src/librustc_msan/build.rs @@ -32,4 +32,5 @@ fn main() { .build_target("msan") .build(); } + println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); } diff --git a/src/librustc_msan/lib.rs b/src/librustc_msan/lib.rs index 54941362e8..e987b1f335 100644 --- a/src/librustc_msan/lib.rs +++ b/src/librustc_msan/lib.rs @@ -11,6 +11,8 @@ #![sanitizer_runtime] #![feature(sanitizer_runtime)] #![feature(alloc_system)] +#![cfg_attr(not(stage0), feature(allocator_api))] +#![cfg_attr(not(stage0), feature(global_allocator))] #![feature(staged_api)] #![no_std] #![unstable(feature = "sanitizer_runtime_lib", @@ -18,3 +20,10 @@ issue = "0")] extern crate alloc_system; + +#[cfg(not(stage0))] +use alloc_system::System; + +#[cfg(not(stage0))] +#[global_allocator] +static ALLOC: System = System; diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 7c443a4ac7..66736507ab 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -93,6 +93,32 @@ impl<'a> AstValidator<'a> { } } } + + /// matches '-' lit | lit (cf. parser::Parser::parse_pat_literal_maybe_minus), + /// or path for ranges. + /// + /// FIXME: do we want to allow expr -> pattern conversion to create path expressions? + /// That means making this work: + /// + /// ```rust,ignore (FIXME) + /// struct S; + /// macro_rules! m { + /// ($a:expr) => { + /// let $a = S; + /// } + /// } + /// m!(S); + /// ``` + fn check_expr_within_pat(&self, expr: &Expr, allow_paths: bool) { + match expr.node { + ExprKind::Lit(..) => {} + ExprKind::Path(..) if allow_paths => {} + ExprKind::Unary(UnOp::Neg, ref inner) + if match inner.node { ExprKind::Lit(_) => true, _ => false } => {} + _ => self.err_handler().span_err(expr.span, "arbitrary expressions aren't allowed \ + in patterns") + } + } } impl<'a> Visitor<'a> for AstValidator<'a> { @@ -114,6 +140,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ExprKind::Continue(Some(ident)) => { self.check_label(ident.node, ident.span); } + ExprKind::MethodCall(ref segment, ..) => { + if let Some(ref params) = segment.parameters { + match **params { + PathParameters::AngleBracketed(ref param_data) => { + if !param_data.bindings.is_empty() { + let binding_span = param_data.bindings[0].span; + self.err_handler().span_err(binding_span, + "type bindings cannot be used in method calls"); + } + } + PathParameters::Parenthesized(..) => { + self.err_handler().span_err(expr.span, + "parenthesized parameters cannot be used on method calls"); + } + } + } + } _ => {} } @@ -308,6 +351,21 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } visit::walk_generics(self, g) } + + fn visit_pat(&mut self, pat: &'a Pat) { + match pat.node { + PatKind::Lit(ref expr) => { + self.check_expr_within_pat(expr, false); + } + PatKind::Range(ref start, ref end, _) => { + self.check_expr_within_pat(start, true); + self.check_expr_within_pat(end, true); + } + _ => {} + } + + visit::walk_pat(self, pat) + } } pub fn check_crate(session: &Session, krate: &Crate) { diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 65a9334bba..bec4c08390 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -51,7 +51,6 @@ use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use std::collections::hash_map::Entry; use std::cmp::Ordering; -use std::mem; struct CheckCrateVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -102,7 +101,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { fn_like.constness() == hir::Constness::Const }) } else { - self.tcx.sess.cstore.is_const_fn(def_id) + self.tcx.is_const_fn(def_id) }; } } @@ -138,13 +137,14 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { self.check_const_eval(&body.value); } - let outer_penv = self.tcx.infer_ctxt(body_id).enter(|infcx| { - let param_env = self.tcx.param_env(item_def_id); - let outer_penv = mem::replace(&mut self.param_env, param_env); - let region_maps = &self.tcx.region_maps(item_def_id); - euv::ExprUseVisitor::new(self, region_maps, &infcx, param_env).consume_body(body); - outer_penv - }); + let outer_penv = self.param_env; + self.param_env = self.tcx.param_env(item_def_id); + + let tcx = self.tcx; + let param_env = self.param_env; + let region_maps = self.tcx.region_maps(item_def_id); + euv::ExprUseVisitor::new(self, tcx, param_env, ®ion_maps, self.tables) + .consume_body(body); self.visit_body(body); diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs index 036a52d5a3..464dd72e56 100644 --- a/src/librustc_passes/diagnostics.rs +++ b/src/librustc_passes/diagnostics.rs @@ -154,7 +154,7 @@ E0449: r##" A visibility qualifier was used when it was unnecessary. Erroneous code examples: -```compile_fail +```compile_fail,E0449 struct Bar; trait Foo { @@ -171,7 +171,7 @@ pub impl Foo for Bar { // error: unnecessary visibility qualifier To fix this error, please remove the visibility qualifier when it is not required. Example: -```ignore +``` struct Bar; trait Foo { @@ -184,8 +184,8 @@ impl Bar {} // Trait methods share the visibility of the trait, so `pub` is // unnecessary in either case -pub impl Foo for Bar { - pub fn foo() {} +impl Foo for Bar { + fn foo() {} } ``` "##, diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 97f0022b8d..3949152e84 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -24,10 +24,6 @@ #![feature(rustc_diagnostic_macros)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] - #[macro_use] extern crate rustc; extern crate rustc_const_eval; diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs index e29da3a649..4dd38cc515 100644 --- a/src/librustc_passes/mir_stats.rs +++ b/src/librustc_passes/mir_stats.rs @@ -125,6 +125,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { self.record("Statement", statement); self.record(match statement.kind { StatementKind::Assign(..) => "StatementKind::Assign", + StatementKind::EndRegion(..) => "StatementKind::EndRegion", StatementKind::SetDiscriminant { .. } => "StatementKind::SetDiscriminant", StatementKind::StorageLive(..) => "StatementKind::StorageLive", StatementKind::StorageDead(..) => "StatementKind::StorageDead", diff --git a/src/librustc_passes/static_recursion.rs b/src/librustc_passes/static_recursion.rs index 8d455adc23..0dbb2d1d4d 100644 --- a/src/librustc_passes/static_recursion.rs +++ b/src/librustc_passes/static_recursion.rs @@ -12,8 +12,9 @@ // recursively. use rustc::hir::map as hir_map; -use rustc::session::{CompileResult, Session}; +use rustc::session::Session; use rustc::hir::def::{Def, CtorKind}; +use rustc::util::common::ErrorReported; use rustc::util::nodemap::{NodeMap, NodeSet}; use syntax::ast; @@ -86,7 +87,9 @@ impl<'a, 'hir: 'a> Visitor<'hir> for CheckCrateVisitor<'a, 'hir> { } } -pub fn check_crate<'hir>(sess: &Session, hir_map: &hir_map::Map<'hir>) -> CompileResult { +pub fn check_crate<'hir>(sess: &Session, hir_map: &hir_map::Map<'hir>) + -> Result<(), ErrorReported> +{ let mut visitor = CheckCrateVisitor { sess: sess, hir_map: hir_map, diff --git a/src/librustc_platform_intrinsics/arm.rs b/src/librustc_platform_intrinsics/arm.rs index 834528aaaa..59ac5ccc53 100644 --- a/src/librustc_platform_intrinsics/arm.rs +++ b/src/librustc_platform_intrinsics/arm.rs @@ -25,232 +25,232 @@ pub fn find(name: &str) -> Option { "hadd_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vhadds.v8i8") + definition: Named("llvm.arm.neon.vhadds.v8i8") }, "hadd_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vhaddu.v8i8") + definition: Named("llvm.arm.neon.vhaddu.v8i8") }, "hadd_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vhadds.v4i16") + definition: Named("llvm.arm.neon.vhadds.v4i16") }, "hadd_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vhaddu.v4i16") + definition: Named("llvm.arm.neon.vhaddu.v4i16") }, "hadd_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vhadds.v2i32") + definition: Named("llvm.arm.neon.vhadds.v2i32") }, "hadd_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vhaddu.v2i32") + definition: Named("llvm.arm.neon.vhaddu.v2i32") }, "haddq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vhadds.v16i8") + definition: Named("llvm.arm.neon.vhadds.v16i8") }, "haddq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vhaddu.v16i8") + definition: Named("llvm.arm.neon.vhaddu.v16i8") }, "haddq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vhadds.v8i16") + definition: Named("llvm.arm.neon.vhadds.v8i16") }, "haddq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vhaddu.v8i16") + definition: Named("llvm.arm.neon.vhaddu.v8i16") }, "haddq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vhadds.v4i32") + definition: Named("llvm.arm.neon.vhadds.v4i32") }, "haddq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vhaddu.v4i32") + definition: Named("llvm.arm.neon.vhaddu.v4i32") }, "rhadd_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vrhadds.v8i8") + definition: Named("llvm.arm.neon.vrhadds.v8i8") }, "rhadd_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vrhaddu.v8i8") + definition: Named("llvm.arm.neon.vrhaddu.v8i8") }, "rhadd_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vrhadds.v4i16") + definition: Named("llvm.arm.neon.vrhadds.v4i16") }, "rhadd_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vrhaddu.v4i16") + definition: Named("llvm.arm.neon.vrhaddu.v4i16") }, "rhadd_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vrhadds.v2i32") + definition: Named("llvm.arm.neon.vrhadds.v2i32") }, "rhadd_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vrhaddu.v2i32") + definition: Named("llvm.arm.neon.vrhaddu.v2i32") }, "rhaddq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vrhadds.v16i8") + definition: Named("llvm.arm.neon.vrhadds.v16i8") }, "rhaddq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vrhaddu.v16i8") + definition: Named("llvm.arm.neon.vrhaddu.v16i8") }, "rhaddq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vrhadds.v8i16") + definition: Named("llvm.arm.neon.vrhadds.v8i16") }, "rhaddq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vrhaddu.v8i16") + definition: Named("llvm.arm.neon.vrhaddu.v8i16") }, "rhaddq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vrhadds.v4i32") + definition: Named("llvm.arm.neon.vrhadds.v4i32") }, "rhaddq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vrhaddu.v4i32") + definition: Named("llvm.arm.neon.vrhaddu.v4i32") }, "qadd_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vqadds.v8i8") + definition: Named("llvm.arm.neon.vqadds.v8i8") }, "qadd_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vqaddu.v8i8") + definition: Named("llvm.arm.neon.vqaddu.v8i8") }, "qadd_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vqadds.v4i16") + definition: Named("llvm.arm.neon.vqadds.v4i16") }, "qadd_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vqaddu.v4i16") + definition: Named("llvm.arm.neon.vqaddu.v4i16") }, "qadd_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vqadds.v2i32") + definition: Named("llvm.arm.neon.vqadds.v2i32") }, "qadd_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vqaddu.v2i32") + definition: Named("llvm.arm.neon.vqaddu.v2i32") }, "qadd_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x1, &::I64x1]; &INPUTS }, output: &::I64x1, - definition: Named("llvm.neon.vqadds.v1i64") + definition: Named("llvm.arm.neon.vqadds.v1i64") }, "qadd_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x1, &::U64x1]; &INPUTS }, output: &::U64x1, - definition: Named("llvm.neon.vqaddu.v1i64") + definition: Named("llvm.arm.neon.vqaddu.v1i64") }, "qaddq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vqadds.v16i8") + definition: Named("llvm.arm.neon.vqadds.v16i8") }, "qaddq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vqaddu.v16i8") + definition: Named("llvm.arm.neon.vqaddu.v16i8") }, "qaddq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vqadds.v8i16") + definition: Named("llvm.arm.neon.vqadds.v8i16") }, "qaddq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vqaddu.v8i16") + definition: Named("llvm.arm.neon.vqaddu.v8i16") }, "qaddq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vqadds.v4i32") + definition: Named("llvm.arm.neon.vqadds.v4i32") }, "qaddq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vqaddu.v4i32") + definition: Named("llvm.arm.neon.vqaddu.v4i32") }, "qaddq_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::I64x2]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vqadds.v2i64") + definition: Named("llvm.arm.neon.vqadds.v2i64") }, "qaddq_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::U64x2]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vqaddu.v2i64") + definition: Named("llvm.arm.neon.vqaddu.v2i64") }, "raddhn_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vraddhn.v8i8") + definition: Named("llvm.arm.neon.vraddhn.v8i8") }, "raddhn_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vraddhn.v8i8") + definition: Named("llvm.arm.neon.vraddhn.v8i8") }, "raddhn_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vraddhn.v4i16") + definition: Named("llvm.arm.neon.vraddhn.v4i16") }, "raddhn_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vraddhn.v4i16") + definition: Named("llvm.arm.neon.vraddhn.v4i16") }, "raddhn_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::I64x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vraddhn.v2i32") + definition: Named("llvm.arm.neon.vraddhn.v2i32") }, "raddhn_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::U64x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vraddhn.v2i32") + definition: Named("llvm.arm.neon.vraddhn.v2i32") }, "fma_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x2, &::F32x2]; &INPUTS }, @@ -265,1122 +265,1122 @@ pub fn find(name: &str) -> Option { "qdmulh_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vsqdmulh.v4i16") + definition: Named("llvm.arm.neon.vsqdmulh.v4i16") }, "qdmulh_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vsqdmulh.v2i32") + definition: Named("llvm.arm.neon.vsqdmulh.v2i32") }, "qdmulhq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vsqdmulh.v8i16") + definition: Named("llvm.arm.neon.vsqdmulh.v8i16") }, "qdmulhq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vsqdmulh.v4i32") + definition: Named("llvm.arm.neon.vsqdmulh.v4i32") }, "qrdmulh_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vsqrdmulh.v4i16") + definition: Named("llvm.arm.neon.vsqrdmulh.v4i16") }, "qrdmulh_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vsqrdmulh.v2i32") + definition: Named("llvm.arm.neon.vsqrdmulh.v2i32") }, "qrdmulhq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vsqrdmulh.v8i16") + definition: Named("llvm.arm.neon.vsqrdmulh.v8i16") }, "qrdmulhq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vsqrdmulh.v4i32") + definition: Named("llvm.arm.neon.vsqrdmulh.v4i32") }, "mull_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vmulls.v8i16") + definition: Named("llvm.arm.neon.vmulls.v8i16") }, "mull_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vmullu.v8i16") + definition: Named("llvm.arm.neon.vmullu.v8i16") }, "mull_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vmulls.v4i32") + definition: Named("llvm.arm.neon.vmulls.v4i32") }, "mull_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vmullu.v4i32") + definition: Named("llvm.arm.neon.vmullu.v4i32") }, "mull_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vmulls.v2i64") + definition: Named("llvm.arm.neon.vmulls.v2i64") }, "mull_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vmullu.v2i64") + definition: Named("llvm.arm.neon.vmullu.v2i64") }, "qdmullq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vsqdmull.v8i16") + definition: Named("llvm.arm.neon.vsqdmull.v8i16") }, "qdmullq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vsqdmull.v4i32") + definition: Named("llvm.arm.neon.vsqdmull.v4i32") }, "hsub_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vhsubs.v8i8") + definition: Named("llvm.arm.neon.vhsubs.v8i8") }, "hsub_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vhsubu.v8i8") + definition: Named("llvm.arm.neon.vhsubu.v8i8") }, "hsub_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vhsubs.v4i16") + definition: Named("llvm.arm.neon.vhsubs.v4i16") }, "hsub_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vhsubu.v4i16") + definition: Named("llvm.arm.neon.vhsubu.v4i16") }, "hsub_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vhsubs.v2i32") + definition: Named("llvm.arm.neon.vhsubs.v2i32") }, "hsub_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vhsubu.v2i32") + definition: Named("llvm.arm.neon.vhsubu.v2i32") }, "hsubq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vhsubs.v16i8") + definition: Named("llvm.arm.neon.vhsubs.v16i8") }, "hsubq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vhsubu.v16i8") + definition: Named("llvm.arm.neon.vhsubu.v16i8") }, "hsubq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vhsubs.v8i16") + definition: Named("llvm.arm.neon.vhsubs.v8i16") }, "hsubq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vhsubu.v8i16") + definition: Named("llvm.arm.neon.vhsubu.v8i16") }, "hsubq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vhsubs.v4i32") + definition: Named("llvm.arm.neon.vhsubs.v4i32") }, "hsubq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vhsubu.v4i32") + definition: Named("llvm.arm.neon.vhsubu.v4i32") }, "qsub_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vqsubs.v8i8") + definition: Named("llvm.arm.neon.vqsubs.v8i8") }, "qsub_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vqsubu.v8i8") + definition: Named("llvm.arm.neon.vqsubu.v8i8") }, "qsub_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vqsubs.v4i16") + definition: Named("llvm.arm.neon.vqsubs.v4i16") }, "qsub_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vqsubu.v4i16") + definition: Named("llvm.arm.neon.vqsubu.v4i16") }, "qsub_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vqsubs.v2i32") + definition: Named("llvm.arm.neon.vqsubs.v2i32") }, "qsub_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vqsubu.v2i32") + definition: Named("llvm.arm.neon.vqsubu.v2i32") }, "qsub_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x1, &::I64x1]; &INPUTS }, output: &::I64x1, - definition: Named("llvm.neon.vqsubs.v1i64") + definition: Named("llvm.arm.neon.vqsubs.v1i64") }, "qsub_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x1, &::U64x1]; &INPUTS }, output: &::U64x1, - definition: Named("llvm.neon.vqsubu.v1i64") + definition: Named("llvm.arm.neon.vqsubu.v1i64") }, "qsubq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vqsubs.v16i8") + definition: Named("llvm.arm.neon.vqsubs.v16i8") }, "qsubq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vqsubu.v16i8") + definition: Named("llvm.arm.neon.vqsubu.v16i8") }, "qsubq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vqsubs.v8i16") + definition: Named("llvm.arm.neon.vqsubs.v8i16") }, "qsubq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vqsubu.v8i16") + definition: Named("llvm.arm.neon.vqsubu.v8i16") }, "qsubq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vqsubs.v4i32") + definition: Named("llvm.arm.neon.vqsubs.v4i32") }, "qsubq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vqsubu.v4i32") + definition: Named("llvm.arm.neon.vqsubu.v4i32") }, "qsubq_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::I64x2]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vqsubs.v2i64") + definition: Named("llvm.arm.neon.vqsubs.v2i64") }, "qsubq_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::U64x2]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vqsubu.v2i64") + definition: Named("llvm.arm.neon.vqsubu.v2i64") }, "rsubhn_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vrsubhn.v8i8") + definition: Named("llvm.arm.neon.vrsubhn.v8i8") }, "rsubhn_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vrsubhn.v8i8") + definition: Named("llvm.arm.neon.vrsubhn.v8i8") }, "rsubhn_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vrsubhn.v4i16") + definition: Named("llvm.arm.neon.vrsubhn.v4i16") }, "rsubhn_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vrsubhn.v4i16") + definition: Named("llvm.arm.neon.vrsubhn.v4i16") }, "rsubhn_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::I64x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vrsubhn.v2i32") + definition: Named("llvm.arm.neon.vrsubhn.v2i32") }, "rsubhn_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::U64x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vrsubhn.v2i32") + definition: Named("llvm.arm.neon.vrsubhn.v2i32") }, "abd_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vabds.v8i8") + definition: Named("llvm.arm.neon.vabds.v8i8") }, "abd_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vabdu.v8i8") + definition: Named("llvm.arm.neon.vabdu.v8i8") }, "abd_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vabds.v4i16") + definition: Named("llvm.arm.neon.vabds.v4i16") }, "abd_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vabdu.v4i16") + definition: Named("llvm.arm.neon.vabdu.v4i16") }, "abd_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vabds.v2i32") + definition: Named("llvm.arm.neon.vabds.v2i32") }, "abd_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vabdu.v2i32") + definition: Named("llvm.arm.neon.vabdu.v2i32") }, "abd_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x2, &::F32x2]; &INPUTS }, output: &::F32x2, - definition: Named("llvm.neon.vabdf.v2f32") + definition: Named("llvm.arm.neon.vabdf.v2f32") }, "abdq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vabds.v16i8") + definition: Named("llvm.arm.neon.vabds.v16i8") }, "abdq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vabdu.v16i8") + definition: Named("llvm.arm.neon.vabdu.v16i8") }, "abdq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vabds.v8i16") + definition: Named("llvm.arm.neon.vabds.v8i16") }, "abdq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vabdu.v8i16") + definition: Named("llvm.arm.neon.vabdu.v8i16") }, "abdq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vabds.v4i32") + definition: Named("llvm.arm.neon.vabds.v4i32") }, "abdq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vabdu.v4i32") + definition: Named("llvm.arm.neon.vabdu.v4i32") }, "abdq_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x4, &::F32x4]; &INPUTS }, output: &::F32x4, - definition: Named("llvm.neon.vabdf.v4f32") + definition: Named("llvm.arm.neon.vabdf.v4f32") }, "max_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vmaxs.v8i8") + definition: Named("llvm.arm.neon.vmaxs.v8i8") }, "max_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vmaxu.v8i8") + definition: Named("llvm.arm.neon.vmaxu.v8i8") }, "max_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vmaxs.v4i16") + definition: Named("llvm.arm.neon.vmaxs.v4i16") }, "max_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vmaxu.v4i16") + definition: Named("llvm.arm.neon.vmaxu.v4i16") }, "max_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vmaxs.v2i32") + definition: Named("llvm.arm.neon.vmaxs.v2i32") }, "max_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vmaxu.v2i32") + definition: Named("llvm.arm.neon.vmaxu.v2i32") }, "max_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x2, &::F32x2]; &INPUTS }, output: &::F32x2, - definition: Named("llvm.neon.vmaxf.v2f32") + definition: Named("llvm.arm.neon.vmaxf.v2f32") }, "maxq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vmaxs.v16i8") + definition: Named("llvm.arm.neon.vmaxs.v16i8") }, "maxq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vmaxu.v16i8") + definition: Named("llvm.arm.neon.vmaxu.v16i8") }, "maxq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vmaxs.v8i16") + definition: Named("llvm.arm.neon.vmaxs.v8i16") }, "maxq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vmaxu.v8i16") + definition: Named("llvm.arm.neon.vmaxu.v8i16") }, "maxq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vmaxs.v4i32") + definition: Named("llvm.arm.neon.vmaxs.v4i32") }, "maxq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vmaxu.v4i32") + definition: Named("llvm.arm.neon.vmaxu.v4i32") }, "maxq_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x4, &::F32x4]; &INPUTS }, output: &::F32x4, - definition: Named("llvm.neon.vmaxf.v4f32") + definition: Named("llvm.arm.neon.vmaxf.v4f32") }, "min_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vmins.v8i8") + definition: Named("llvm.arm.neon.vmins.v8i8") }, "min_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vminu.v8i8") + definition: Named("llvm.arm.neon.vminu.v8i8") }, "min_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vmins.v4i16") + definition: Named("llvm.arm.neon.vmins.v4i16") }, "min_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vminu.v4i16") + definition: Named("llvm.arm.neon.vminu.v4i16") }, "min_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vmins.v2i32") + definition: Named("llvm.arm.neon.vmins.v2i32") }, "min_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vminu.v2i32") + definition: Named("llvm.arm.neon.vminu.v2i32") }, "min_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x2, &::F32x2]; &INPUTS }, output: &::F32x2, - definition: Named("llvm.neon.vminf.v2f32") + definition: Named("llvm.arm.neon.vminf.v2f32") }, "minq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vmins.v16i8") + definition: Named("llvm.arm.neon.vmins.v16i8") }, "minq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vminu.v16i8") + definition: Named("llvm.arm.neon.vminu.v16i8") }, "minq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vmins.v8i16") + definition: Named("llvm.arm.neon.vmins.v8i16") }, "minq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vminu.v8i16") + definition: Named("llvm.arm.neon.vminu.v8i16") }, "minq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vmins.v4i32") + definition: Named("llvm.arm.neon.vmins.v4i32") }, "minq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vminu.v4i32") + definition: Named("llvm.arm.neon.vminu.v4i32") }, "minq_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x4, &::F32x4]; &INPUTS }, output: &::F32x4, - definition: Named("llvm.neon.vminf.v4f32") + definition: Named("llvm.arm.neon.vminf.v4f32") }, "shl_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vshls.v8i8") + definition: Named("llvm.arm.neon.vshls.v8i8") }, "shl_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::I8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vshlu.v8i8") + definition: Named("llvm.arm.neon.vshlu.v8i8") }, "shl_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vshls.v4i16") + definition: Named("llvm.arm.neon.vshls.v4i16") }, "shl_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::I16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vshlu.v4i16") + definition: Named("llvm.arm.neon.vshlu.v4i16") }, "shl_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vshls.v2i32") + definition: Named("llvm.arm.neon.vshls.v2i32") }, "shl_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::I32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vshlu.v2i32") + definition: Named("llvm.arm.neon.vshlu.v2i32") }, "shl_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x1, &::I64x1]; &INPUTS }, output: &::I64x1, - definition: Named("llvm.neon.vshls.v1i64") + definition: Named("llvm.arm.neon.vshls.v1i64") }, "shl_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x1, &::I64x1]; &INPUTS }, output: &::U64x1, - definition: Named("llvm.neon.vshlu.v1i64") + definition: Named("llvm.arm.neon.vshlu.v1i64") }, "shlq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vshls.v16i8") + definition: Named("llvm.arm.neon.vshls.v16i8") }, "shlq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::I8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vshlu.v16i8") + definition: Named("llvm.arm.neon.vshlu.v16i8") }, "shlq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vshls.v8i16") + definition: Named("llvm.arm.neon.vshls.v8i16") }, "shlq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::I16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vshlu.v8i16") + definition: Named("llvm.arm.neon.vshlu.v8i16") }, "shlq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vshls.v4i32") + definition: Named("llvm.arm.neon.vshls.v4i32") }, "shlq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::I32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vshlu.v4i32") + definition: Named("llvm.arm.neon.vshlu.v4i32") }, "shlq_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::I64x2]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vshls.v2i64") + definition: Named("llvm.arm.neon.vshls.v2i64") }, "shlq_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::I64x2]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vshlu.v2i64") + definition: Named("llvm.arm.neon.vshlu.v2i64") }, "qshl_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vqshls.v8i8") + definition: Named("llvm.arm.neon.vqshls.v8i8") }, "qshl_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::I8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vqshlu.v8i8") + definition: Named("llvm.arm.neon.vqshlu.v8i8") }, "qshl_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vqshls.v4i16") + definition: Named("llvm.arm.neon.vqshls.v4i16") }, "qshl_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::I16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vqshlu.v4i16") + definition: Named("llvm.arm.neon.vqshlu.v4i16") }, "qshl_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vqshls.v2i32") + definition: Named("llvm.arm.neon.vqshls.v2i32") }, "qshl_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::I32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vqshlu.v2i32") + definition: Named("llvm.arm.neon.vqshlu.v2i32") }, "qshl_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x1, &::I64x1]; &INPUTS }, output: &::I64x1, - definition: Named("llvm.neon.vqshls.v1i64") + definition: Named("llvm.arm.neon.vqshls.v1i64") }, "qshl_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x1, &::I64x1]; &INPUTS }, output: &::U64x1, - definition: Named("llvm.neon.vqshlu.v1i64") + definition: Named("llvm.arm.neon.vqshlu.v1i64") }, "qshlq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vqshls.v16i8") + definition: Named("llvm.arm.neon.vqshls.v16i8") }, "qshlq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::I8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vqshlu.v16i8") + definition: Named("llvm.arm.neon.vqshlu.v16i8") }, "qshlq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vqshls.v8i16") + definition: Named("llvm.arm.neon.vqshls.v8i16") }, "qshlq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::I16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vqshlu.v8i16") + definition: Named("llvm.arm.neon.vqshlu.v8i16") }, "qshlq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vqshls.v4i32") + definition: Named("llvm.arm.neon.vqshls.v4i32") }, "qshlq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::I32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vqshlu.v4i32") + definition: Named("llvm.arm.neon.vqshlu.v4i32") }, "qshlq_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::I64x2]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vqshls.v2i64") + definition: Named("llvm.arm.neon.vqshls.v2i64") }, "qshlq_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::I64x2]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vqshlu.v2i64") + definition: Named("llvm.arm.neon.vqshlu.v2i64") }, "rshl_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vrshls.v8i8") + definition: Named("llvm.arm.neon.vrshls.v8i8") }, "rshl_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::I8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vrshlu.v8i8") + definition: Named("llvm.arm.neon.vrshlu.v8i8") }, "rshl_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vrshls.v4i16") + definition: Named("llvm.arm.neon.vrshls.v4i16") }, "rshl_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::I16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vrshlu.v4i16") + definition: Named("llvm.arm.neon.vrshlu.v4i16") }, "rshl_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vrshls.v2i32") + definition: Named("llvm.arm.neon.vrshls.v2i32") }, "rshl_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::I32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vrshlu.v2i32") + definition: Named("llvm.arm.neon.vrshlu.v2i32") }, "rshl_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x1, &::I64x1]; &INPUTS }, output: &::I64x1, - definition: Named("llvm.neon.vrshls.v1i64") + definition: Named("llvm.arm.neon.vrshls.v1i64") }, "rshl_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x1, &::I64x1]; &INPUTS }, output: &::U64x1, - definition: Named("llvm.neon.vrshlu.v1i64") + definition: Named("llvm.arm.neon.vrshlu.v1i64") }, "rshlq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vrshls.v16i8") + definition: Named("llvm.arm.neon.vrshls.v16i8") }, "rshlq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::I8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vrshlu.v16i8") + definition: Named("llvm.arm.neon.vrshlu.v16i8") }, "rshlq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vrshls.v8i16") + definition: Named("llvm.arm.neon.vrshls.v8i16") }, "rshlq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::I16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vrshlu.v8i16") + definition: Named("llvm.arm.neon.vrshlu.v8i16") }, "rshlq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vrshls.v4i32") + definition: Named("llvm.arm.neon.vrshls.v4i32") }, "rshlq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::I32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vrshlu.v4i32") + definition: Named("llvm.arm.neon.vrshlu.v4i32") }, "rshlq_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::I64x2]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vrshls.v2i64") + definition: Named("llvm.arm.neon.vrshls.v2i64") }, "rshlq_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::I64x2]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vrshlu.v2i64") + definition: Named("llvm.arm.neon.vrshlu.v2i64") }, "qrshl_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vqrshls.v8i8") + definition: Named("llvm.arm.neon.vqrshls.v8i8") }, "qrshl_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::I8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vqrshlu.v8i8") + definition: Named("llvm.arm.neon.vqrshlu.v8i8") }, "qrshl_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vqrshls.v4i16") + definition: Named("llvm.arm.neon.vqrshls.v4i16") }, "qrshl_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::I16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vqrshlu.v4i16") + definition: Named("llvm.arm.neon.vqrshlu.v4i16") }, "qrshl_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vqrshls.v2i32") + definition: Named("llvm.arm.neon.vqrshls.v2i32") }, "qrshl_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::I32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vqrshlu.v2i32") + definition: Named("llvm.arm.neon.vqrshlu.v2i32") }, "qrshl_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x1, &::I64x1]; &INPUTS }, output: &::I64x1, - definition: Named("llvm.neon.vqrshls.v1i64") + definition: Named("llvm.arm.neon.vqrshls.v1i64") }, "qrshl_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x1, &::I64x1]; &INPUTS }, output: &::U64x1, - definition: Named("llvm.neon.vqrshlu.v1i64") + definition: Named("llvm.arm.neon.vqrshlu.v1i64") }, "qrshlq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vqrshls.v16i8") + definition: Named("llvm.arm.neon.vqrshls.v16i8") }, "qrshlq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::I8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vqrshlu.v16i8") + definition: Named("llvm.arm.neon.vqrshlu.v16i8") }, "qrshlq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vqrshls.v8i16") + definition: Named("llvm.arm.neon.vqrshls.v8i16") }, "qrshlq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::I16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vqrshlu.v8i16") + definition: Named("llvm.arm.neon.vqrshlu.v8i16") }, "qrshlq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vqrshls.v4i32") + definition: Named("llvm.arm.neon.vqrshls.v4i32") }, "qrshlq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::I32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vqrshlu.v4i32") + definition: Named("llvm.arm.neon.vqrshlu.v4i32") }, "qrshlq_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::I64x2]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vqrshls.v2i64") + definition: Named("llvm.arm.neon.vqrshls.v2i64") }, "qrshlq_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::I64x2]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vqrshlu.v2i64") + definition: Named("llvm.arm.neon.vqrshlu.v2i64") }, "qshrun_n_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::U32]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vsqshrun.v8i8") + definition: Named("llvm.arm.neon.vsqshrun.v8i8") }, "qshrun_n_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::U32]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vsqshrun.v4i16") + definition: Named("llvm.arm.neon.vsqshrun.v4i16") }, "qshrun_n_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::U32]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vsqshrun.v2i32") + definition: Named("llvm.arm.neon.vsqshrun.v2i32") }, "qrshrun_n_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::U32]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vsqrshrun.v8i8") + definition: Named("llvm.arm.neon.vsqrshrun.v8i8") }, "qrshrun_n_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::U32]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vsqrshrun.v4i16") + definition: Named("llvm.arm.neon.vsqrshrun.v4i16") }, "qrshrun_n_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::U32]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vsqrshrun.v2i32") + definition: Named("llvm.arm.neon.vsqrshrun.v2i32") }, "qshrn_n_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::U32]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vqshrns.v8i8") + definition: Named("llvm.arm.neon.vqshrns.v8i8") }, "qshrn_n_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U32]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vqshrnu.v8i8") + definition: Named("llvm.arm.neon.vqshrnu.v8i8") }, "qshrn_n_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::U32]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vqshrns.v4i16") + definition: Named("llvm.arm.neon.vqshrns.v4i16") }, "qshrn_n_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vqshrnu.v4i16") + definition: Named("llvm.arm.neon.vqshrnu.v4i16") }, "qshrn_n_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::U32]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vqshrns.v2i32") + definition: Named("llvm.arm.neon.vqshrns.v2i32") }, "qshrn_n_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::U32]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vqshrnu.v2i32") + definition: Named("llvm.arm.neon.vqshrnu.v2i32") }, "rshrn_n_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::U32]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vrshrn.v8i8") + definition: Named("llvm.arm.neon.vrshrn.v8i8") }, "rshrn_n_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U32]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vrshrn.v8i8") + definition: Named("llvm.arm.neon.vrshrn.v8i8") }, "rshrn_n_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::U32]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vrshrn.v4i16") + definition: Named("llvm.arm.neon.vrshrn.v4i16") }, "rshrn_n_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vrshrn.v4i16") + definition: Named("llvm.arm.neon.vrshrn.v4i16") }, "rshrn_n_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::U32]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vrshrn.v2i32") + definition: Named("llvm.arm.neon.vrshrn.v2i32") }, "rshrn_n_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::U32]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vrshrn.v2i32") + definition: Named("llvm.arm.neon.vrshrn.v2i32") }, "qrshrn_n_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::U32]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vqrshrns.v8i8") + definition: Named("llvm.arm.neon.vqrshrns.v8i8") }, "qrshrn_n_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U32]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vqrshrnu.v8i8") + definition: Named("llvm.arm.neon.vqrshrnu.v8i8") }, "qrshrn_n_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::U32]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vqrshrns.v4i16") + definition: Named("llvm.arm.neon.vqrshrns.v4i16") }, "qrshrn_n_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vqrshrnu.v4i16") + definition: Named("llvm.arm.neon.vqrshrnu.v4i16") }, "qrshrn_n_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::U32]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vqrshrns.v2i32") + definition: Named("llvm.arm.neon.vqrshrns.v2i32") }, "qrshrn_n_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::U32]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vqrshrnu.v2i32") + definition: Named("llvm.arm.neon.vqrshrnu.v2i32") }, "sri_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vvsri.v8i8") + definition: Named("llvm.arm.neon.vvsri.v8i8") }, "sri_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vvsri.v8i8") + definition: Named("llvm.arm.neon.vvsri.v8i8") }, "sri_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vvsri.v4i16") + definition: Named("llvm.arm.neon.vvsri.v4i16") }, "sri_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vvsri.v4i16") + definition: Named("llvm.arm.neon.vvsri.v4i16") }, "sri_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vvsri.v2i32") + definition: Named("llvm.arm.neon.vvsri.v2i32") }, "sri_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vvsri.v2i32") + definition: Named("llvm.arm.neon.vvsri.v2i32") }, "sri_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x1, &::I64x1]; &INPUTS }, output: &::I64x1, - definition: Named("llvm.neon.vvsri.v1i64") + definition: Named("llvm.arm.neon.vvsri.v1i64") }, "sri_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x1, &::U64x1]; &INPUTS }, output: &::U64x1, - definition: Named("llvm.neon.vvsri.v1i64") + definition: Named("llvm.arm.neon.vvsri.v1i64") }, "sriq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vvsri.v16i8") + definition: Named("llvm.arm.neon.vvsri.v16i8") }, "sriq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vvsri.v16i8") + definition: Named("llvm.arm.neon.vvsri.v16i8") }, "sriq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vvsri.v8i16") + definition: Named("llvm.arm.neon.vvsri.v8i16") }, "sriq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vvsri.v8i16") + definition: Named("llvm.arm.neon.vvsri.v8i16") }, "sriq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vvsri.v4i32") + definition: Named("llvm.arm.neon.vvsri.v4i32") }, "sriq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vvsri.v4i32") + definition: Named("llvm.arm.neon.vvsri.v4i32") }, "sriq_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::I64x2]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vvsri.v2i64") + definition: Named("llvm.arm.neon.vvsri.v2i64") }, "sriq_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::U64x2]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vvsri.v2i64") + definition: Named("llvm.arm.neon.vvsri.v2i64") }, "sli_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vvsli.v8i8") + definition: Named("llvm.arm.neon.vvsli.v8i8") }, "sli_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vvsli.v8i8") + definition: Named("llvm.arm.neon.vvsli.v8i8") }, "sli_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vvsli.v4i16") + definition: Named("llvm.arm.neon.vvsli.v4i16") }, "sli_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vvsli.v4i16") + definition: Named("llvm.arm.neon.vvsli.v4i16") }, "sli_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vvsli.v2i32") + definition: Named("llvm.arm.neon.vvsli.v2i32") }, "sli_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vvsli.v2i32") + definition: Named("llvm.arm.neon.vvsli.v2i32") }, "sli_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x1, &::I64x1]; &INPUTS }, output: &::I64x1, - definition: Named("llvm.neon.vvsli.v1i64") + definition: Named("llvm.arm.neon.vvsli.v1i64") }, "sli_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x1, &::U64x1]; &INPUTS }, output: &::U64x1, - definition: Named("llvm.neon.vvsli.v1i64") + definition: Named("llvm.arm.neon.vvsli.v1i64") }, "sliq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vvsli.v16i8") + definition: Named("llvm.arm.neon.vvsli.v16i8") }, "sliq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vvsli.v16i8") + definition: Named("llvm.arm.neon.vvsli.v16i8") }, "sliq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vvsli.v8i16") + definition: Named("llvm.arm.neon.vvsli.v8i16") }, "sliq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vvsli.v8i16") + definition: Named("llvm.arm.neon.vvsli.v8i16") }, "sliq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vvsli.v4i32") + definition: Named("llvm.arm.neon.vvsli.v4i32") }, "sliq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vvsli.v4i32") + definition: Named("llvm.arm.neon.vvsli.v4i32") }, "sliq_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::I64x2]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vvsli.v2i64") + definition: Named("llvm.arm.neon.vvsli.v2i64") }, "sliq_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::U64x2]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vvsli.v2i64") + definition: Named("llvm.arm.neon.vvsli.v2i64") }, "vqmovn_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I16x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vqxtns.v8i8") + definition: Named("llvm.arm.neon.vqxtns.v8i8") }, "vqmovn_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U16x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vqxtnu.v8i8") + definition: Named("llvm.arm.neon.vqxtnu.v8i8") }, "vqmovn_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I32x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vqxtns.v4i16") + definition: Named("llvm.arm.neon.vqxtns.v4i16") }, "vqmovn_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U32x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vqxtnu.v4i16") + definition: Named("llvm.arm.neon.vqxtnu.v4i16") }, "vqmovn_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I64x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vqxtns.v2i32") + definition: Named("llvm.arm.neon.vqxtns.v2i32") }, "vqmovn_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U64x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vqxtnu.v2i32") + definition: Named("llvm.arm.neon.vqxtnu.v2i32") }, "abs_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vabs.v8i8") + definition: Named("llvm.arm.neon.vabs.v8i8") }, "abs_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vabs.v4i16") + definition: Named("llvm.arm.neon.vabs.v4i16") }, "abs_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vabs.v2i32") + definition: Named("llvm.arm.neon.vabs.v2i32") }, "absq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vabs.v16i8") + definition: Named("llvm.arm.neon.vabs.v16i8") }, "absq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vabs.v8i16") + definition: Named("llvm.arm.neon.vabs.v8i16") }, "absq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vabs.v4i32") + definition: Named("llvm.arm.neon.vabs.v4i32") }, "abs_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::F32x2]; &INPUTS }, @@ -1395,62 +1395,62 @@ pub fn find(name: &str) -> Option { "qabs_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vsqabs.v8i8") + definition: Named("llvm.arm.neon.vsqabs.v8i8") }, "qabs_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vsqabs.v4i16") + definition: Named("llvm.arm.neon.vsqabs.v4i16") }, "qabs_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vsqabs.v2i32") + definition: Named("llvm.arm.neon.vsqabs.v2i32") }, "qabsq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vsqabs.v16i8") + definition: Named("llvm.arm.neon.vsqabs.v16i8") }, "qabsq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vsqabs.v8i16") + definition: Named("llvm.arm.neon.vsqabs.v8i16") }, "qabsq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vsqabs.v4i32") + definition: Named("llvm.arm.neon.vsqabs.v4i32") }, "qneg_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vsqneg.v8i8") + definition: Named("llvm.arm.neon.vsqneg.v8i8") }, "qneg_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vsqneg.v4i16") + definition: Named("llvm.arm.neon.vsqneg.v4i16") }, "qneg_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vsqneg.v2i32") + definition: Named("llvm.arm.neon.vsqneg.v2i32") }, "qnegq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vsqneg.v16i8") + definition: Named("llvm.arm.neon.vsqneg.v16i8") }, "qnegq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vsqneg.v8i16") + definition: Named("llvm.arm.neon.vsqneg.v8i16") }, "qnegq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vsqneg.v4i32") + definition: Named("llvm.arm.neon.vsqneg.v4i32") }, "clz_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x8]; &INPUTS }, @@ -1515,62 +1515,62 @@ pub fn find(name: &str) -> Option { "cls_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vcls.v8i8") + definition: Named("llvm.arm.neon.vcls.v8i8") }, "cls_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vcls.v8i8") + definition: Named("llvm.arm.neon.vcls.v8i8") }, "cls_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vcls.v4i16") + definition: Named("llvm.arm.neon.vcls.v4i16") }, "cls_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vcls.v4i16") + definition: Named("llvm.arm.neon.vcls.v4i16") }, "cls_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vcls.v2i32") + definition: Named("llvm.arm.neon.vcls.v2i32") }, "cls_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vcls.v2i32") + definition: Named("llvm.arm.neon.vcls.v2i32") }, "clsq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vcls.v16i8") + definition: Named("llvm.arm.neon.vcls.v16i8") }, "clsq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vcls.v16i8") + definition: Named("llvm.arm.neon.vcls.v16i8") }, "clsq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vcls.v8i16") + definition: Named("llvm.arm.neon.vcls.v8i16") }, "clsq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vcls.v8i16") + definition: Named("llvm.arm.neon.vcls.v8i16") }, "clsq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vcls.v4i32") + definition: Named("llvm.arm.neon.vcls.v4i32") }, "clsq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vcls.v4i32") + definition: Named("llvm.arm.neon.vcls.v4i32") }, "cnt_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x8]; &INPUTS }, @@ -1595,32 +1595,32 @@ pub fn find(name: &str) -> Option { "recpe_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vrecpe.v2i32") + definition: Named("llvm.arm.neon.vrecpe.v2i32") }, "recpe_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::F32x2]; &INPUTS }, output: &::F32x2, - definition: Named("llvm.neon.vrecpe.v2f32") + definition: Named("llvm.arm.neon.vrecpe.v2f32") }, "recpeq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vrecpe.v4i32") + definition: Named("llvm.arm.neon.vrecpe.v4i32") }, "recpeq_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::F32x4]; &INPUTS }, output: &::F32x4, - definition: Named("llvm.neon.vrecpe.v4f32") + definition: Named("llvm.arm.neon.vrecpe.v4f32") }, "recps_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x2, &::F32x2]; &INPUTS }, output: &::F32x2, - definition: Named("llvm.neon.vfrecps.v2f32") + definition: Named("llvm.arm.neon.vfrecps.v2f32") }, "recpsq_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x4, &::F32x4]; &INPUTS }, output: &::F32x4, - definition: Named("llvm.neon.vfrecps.v4f32") + definition: Named("llvm.arm.neon.vfrecps.v4f32") }, "sqrt_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::F32x2]; &INPUTS }, @@ -1635,452 +1635,452 @@ pub fn find(name: &str) -> Option { "rsqrte_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vrsqrte.v2i32") + definition: Named("llvm.arm.neon.vrsqrte.v2i32") }, "rsqrte_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::F32x2]; &INPUTS }, output: &::F32x2, - definition: Named("llvm.neon.vrsqrte.v2f32") + definition: Named("llvm.arm.neon.vrsqrte.v2f32") }, "rsqrteq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vrsqrte.v4i32") + definition: Named("llvm.arm.neon.vrsqrte.v4i32") }, "rsqrteq_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::F32x4]; &INPUTS }, output: &::F32x4, - definition: Named("llvm.neon.vrsqrte.v4f32") + definition: Named("llvm.arm.neon.vrsqrte.v4f32") }, "rsqrts_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x2, &::F32x2]; &INPUTS }, output: &::F32x2, - definition: Named("llvm.neon.vrsqrts.v2f32") + definition: Named("llvm.arm.neon.vrsqrts.v2f32") }, "rsqrtsq_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x4, &::F32x4]; &INPUTS }, output: &::F32x4, - definition: Named("llvm.neon.vrsqrts.v4f32") + definition: Named("llvm.arm.neon.vrsqrts.v4f32") }, "bsl_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vbsl.v8i8") + definition: Named("llvm.arm.neon.vbsl.v8i8") }, "bsl_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vbsl.v8i8") + definition: Named("llvm.arm.neon.vbsl.v8i8") }, "bsl_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vbsl.v4i16") + definition: Named("llvm.arm.neon.vbsl.v4i16") }, "bsl_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vbsl.v4i16") + definition: Named("llvm.arm.neon.vbsl.v4i16") }, "bsl_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vbsl.v2i32") + definition: Named("llvm.arm.neon.vbsl.v2i32") }, "bsl_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vbsl.v2i32") + definition: Named("llvm.arm.neon.vbsl.v2i32") }, "bsl_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x1, &::I64x1]; &INPUTS }, output: &::I64x1, - definition: Named("llvm.neon.vbsl.v1i64") + definition: Named("llvm.arm.neon.vbsl.v1i64") }, "bsl_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x1, &::U64x1]; &INPUTS }, output: &::U64x1, - definition: Named("llvm.neon.vbsl.v1i64") + definition: Named("llvm.arm.neon.vbsl.v1i64") }, "bslq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vbsl.v16i8") + definition: Named("llvm.arm.neon.vbsl.v16i8") }, "bslq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vbsl.v16i8") + definition: Named("llvm.arm.neon.vbsl.v16i8") }, "bslq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vbsl.v8i16") + definition: Named("llvm.arm.neon.vbsl.v8i16") }, "bslq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vbsl.v8i16") + definition: Named("llvm.arm.neon.vbsl.v8i16") }, "bslq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vbsl.v4i32") + definition: Named("llvm.arm.neon.vbsl.v4i32") }, "bslq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vbsl.v4i32") + definition: Named("llvm.arm.neon.vbsl.v4i32") }, "bslq_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::I64x2]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vbsl.v2i64") + definition: Named("llvm.arm.neon.vbsl.v2i64") }, "bslq_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::U64x2]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vbsl.v2i64") + definition: Named("llvm.arm.neon.vbsl.v2i64") }, "padd_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vpadd.v8i8") + definition: Named("llvm.arm.neon.vpadd.v8i8") }, "padd_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vpadd.v8i8") + definition: Named("llvm.arm.neon.vpadd.v8i8") }, "padd_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vpadd.v4i16") + definition: Named("llvm.arm.neon.vpadd.v4i16") }, "padd_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vpadd.v4i16") + definition: Named("llvm.arm.neon.vpadd.v4i16") }, "padd_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vpadd.v2i32") + definition: Named("llvm.arm.neon.vpadd.v2i32") }, "padd_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vpadd.v2i32") + definition: Named("llvm.arm.neon.vpadd.v2i32") }, "padd_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x2, &::F32x2]; &INPUTS }, output: &::F32x2, - definition: Named("llvm.neon.vpadd.v2f32") + definition: Named("llvm.arm.neon.vpadd.v2f32") }, "paddl_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x8]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vpaddls.v4i16.v8i8") + definition: Named("llvm.arm.neon.vpaddls.v4i16.v8i8") }, "paddl_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U8x8]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vpaddlu.v4i16.v8i8") + definition: Named("llvm.arm.neon.vpaddlu.v4i16.v8i8") }, "paddl_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I16x4]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vpaddls.v2i32.v4i16") + definition: Named("llvm.arm.neon.vpaddls.v2i32.v4i16") }, "paddl_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U16x4]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vpaddlu.v2i32.v4i16") + definition: Named("llvm.arm.neon.vpaddlu.v2i32.v4i16") }, "paddl_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I32x2]; &INPUTS }, output: &::I64x1, - definition: Named("llvm.neon.vpaddls.v1i64.v2i32") + definition: Named("llvm.arm.neon.vpaddls.v1i64.v2i32") }, "paddl_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U32x2]; &INPUTS }, output: &::U64x1, - definition: Named("llvm.neon.vpaddlu.v1i64.v2i32") + definition: Named("llvm.arm.neon.vpaddlu.v1i64.v2i32") }, "paddlq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x16]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vpaddls.v8i16.v16i8") + definition: Named("llvm.arm.neon.vpaddls.v8i16.v16i8") }, "paddlq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U8x16]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vpaddlu.v8i16.v16i8") + definition: Named("llvm.arm.neon.vpaddlu.v8i16.v16i8") }, "paddlq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I16x8]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vpaddls.v4i32.v8i16") + definition: Named("llvm.arm.neon.vpaddls.v4i32.v8i16") }, "paddlq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U16x8]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vpaddlu.v4i32.v8i16") + definition: Named("llvm.arm.neon.vpaddlu.v4i32.v8i16") }, "paddlq_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I32x4]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vpaddls.v2i64.v4i32") + definition: Named("llvm.arm.neon.vpaddls.v2i64.v4i32") }, "paddlq_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U32x4]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vpaddlu.v2i64.v4i32") + definition: Named("llvm.arm.neon.vpaddlu.v2i64.v4i32") }, "padal_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I8x8]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vpadals.v4i16.v4i16") + definition: Named("llvm.arm.neon.vpadals.v4i16.v4i16") }, "padal_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U8x8]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vpadalu.v4i16.v4i16") + definition: Named("llvm.arm.neon.vpadalu.v4i16.v4i16") }, "padal_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I16x4]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vpadals.v2i32.v2i32") + definition: Named("llvm.arm.neon.vpadals.v2i32.v2i32") }, "padal_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U16x4]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vpadalu.v2i32.v2i32") + definition: Named("llvm.arm.neon.vpadalu.v2i32.v2i32") }, "padal_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x1, &::I32x2]; &INPUTS }, output: &::I64x1, - definition: Named("llvm.neon.vpadals.v1i64.v1i64") + definition: Named("llvm.arm.neon.vpadals.v1i64.v1i64") }, "padal_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x1, &::U32x2]; &INPUTS }, output: &::U64x1, - definition: Named("llvm.neon.vpadalu.v1i64.v1i64") + definition: Named("llvm.arm.neon.vpadalu.v1i64.v1i64") }, "padalq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I8x16]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vpadals.v8i16.v8i16") + definition: Named("llvm.arm.neon.vpadals.v8i16.v8i16") }, "padalq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U8x16]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vpadalu.v8i16.v8i16") + definition: Named("llvm.arm.neon.vpadalu.v8i16.v8i16") }, "padalq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I16x8]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vpadals.v4i32.v4i32") + definition: Named("llvm.arm.neon.vpadals.v4i32.v4i32") }, "padalq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U16x8]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vpadalu.v4i32.v4i32") + definition: Named("llvm.arm.neon.vpadalu.v4i32.v4i32") }, "padalq_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::I32x4]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vpadals.v2i64.v2i64") + definition: Named("llvm.arm.neon.vpadals.v2i64.v2i64") }, "padalq_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::U32x4]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vpadalu.v2i64.v2i64") + definition: Named("llvm.arm.neon.vpadalu.v2i64.v2i64") }, "pmax_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vpmaxs.v8i8") + definition: Named("llvm.arm.neon.vpmaxs.v8i8") }, "pmax_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vpmaxu.v8i8") + definition: Named("llvm.arm.neon.vpmaxu.v8i8") }, "pmax_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vpmaxs.v4i16") + definition: Named("llvm.arm.neon.vpmaxs.v4i16") }, "pmax_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vpmaxu.v4i16") + definition: Named("llvm.arm.neon.vpmaxu.v4i16") }, "pmax_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vpmaxs.v2i32") + definition: Named("llvm.arm.neon.vpmaxs.v2i32") }, "pmax_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vpmaxu.v2i32") + definition: Named("llvm.arm.neon.vpmaxu.v2i32") }, "pmax_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x2, &::F32x2]; &INPUTS }, output: &::F32x2, - definition: Named("llvm.neon.vpmaxf.v2f32") + definition: Named("llvm.arm.neon.vpmaxf.v2f32") }, "pmin_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vpmins.v8i8") + definition: Named("llvm.arm.neon.vpmins.v8i8") }, "pmin_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vpminu.v8i8") + definition: Named("llvm.arm.neon.vpminu.v8i8") }, "pmin_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vpmins.v4i16") + definition: Named("llvm.arm.neon.vpmins.v4i16") }, "pmin_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vpminu.v4i16") + definition: Named("llvm.arm.neon.vpminu.v4i16") }, "pmin_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vpmins.v2i32") + definition: Named("llvm.arm.neon.vpmins.v2i32") }, "pmin_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vpminu.v2i32") + definition: Named("llvm.arm.neon.vpminu.v2i32") }, "pmin_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x2, &::F32x2]; &INPUTS }, output: &::F32x2, - definition: Named("llvm.neon.vpminf.v2f32") + definition: Named("llvm.arm.neon.vpminf.v2f32") }, "pminq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vpmins.v16i8") + definition: Named("llvm.arm.neon.vpmins.v16i8") }, "pminq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vpminu.v16i8") + definition: Named("llvm.arm.neon.vpminu.v16i8") }, "pminq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vpmins.v8i16") + definition: Named("llvm.arm.neon.vpmins.v8i16") }, "pminq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vpminu.v8i16") + definition: Named("llvm.arm.neon.vpminu.v8i16") }, "pminq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vpmins.v4i32") + definition: Named("llvm.arm.neon.vpmins.v4i32") }, "pminq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vpminu.v4i32") + definition: Named("llvm.arm.neon.vpminu.v4i32") }, "pminq_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x4, &::F32x4]; &INPUTS }, output: &::F32x4, - definition: Named("llvm.neon.vpminf.v4f32") + definition: Named("llvm.arm.neon.vpminf.v4f32") }, "tbl1_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::U8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vtbl1") + definition: Named("llvm.arm.neon.vtbl1") }, "tbl1_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vtbl1") + definition: Named("llvm.arm.neon.vtbl1") }, "tbx1_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 3] = [&::I8x8, &::I8x8, &::U8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vtbx1") + definition: Named("llvm.arm.neon.vtbx1") }, "tbx1_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 3] = [&::U8x8, &::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vtbx1") + definition: Named("llvm.arm.neon.vtbx1") }, "tbl2_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [{ static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vtbl2") + definition: Named("llvm.arm.neon.vtbl2") }, "tbl2_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [{ static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vtbl2") + definition: Named("llvm.arm.neon.vtbl2") }, "tbx2_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [{ static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vtbx2") + definition: Named("llvm.arm.neon.vtbx2") }, "tbx2_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [{ static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vtbx2") + definition: Named("llvm.arm.neon.vtbx2") }, "tbl3_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [{ static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 3] = [&::I8x8, &::I8x8, &::I8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vtbl3") + definition: Named("llvm.arm.neon.vtbl3") }, "tbl3_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [{ static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 3] = [&::U8x8, &::U8x8, &::U8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vtbl3") + definition: Named("llvm.arm.neon.vtbl3") }, "tbx3_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 3] = [&::I8x8, { static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 3] = [&::I8x8, &::I8x8, &::I8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vtbx3") + definition: Named("llvm.arm.neon.vtbx3") }, "tbx3_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 3] = [&::U8x8, { static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 3] = [&::U8x8, &::U8x8, &::U8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vtbx3") + definition: Named("llvm.arm.neon.vtbx3") }, "tbl4_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [{ static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 4] = [&::I8x8, &::I8x8, &::I8x8, &::I8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vtbl4") + definition: Named("llvm.arm.neon.vtbl4") }, "tbl4_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [{ static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 4] = [&::U8x8, &::U8x8, &::U8x8, &::U8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vtbl4") + definition: Named("llvm.arm.neon.vtbl4") }, "tbx4_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 3] = [&::I8x8, { static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 4] = [&::I8x8, &::I8x8, &::I8x8, &::I8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vtbx4") + definition: Named("llvm.arm.neon.vtbx4") }, "tbx4_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 3] = [&::U8x8, { static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 4] = [&::U8x8, &::U8x8, &::U8x8, &::U8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vtbx4") + definition: Named("llvm.arm.neon.vtbx4") }, _ => return None, }) diff --git a/src/librustc_platform_intrinsics/lib.rs b/src/librustc_platform_intrinsics/lib.rs index 21dd360c9b..347708a4f9 100644 --- a/src/librustc_platform_intrinsics/lib.rs +++ b/src/librustc_platform_intrinsics/lib.rs @@ -9,10 +9,8 @@ // except according to those terms. #![crate_name = "rustc_platform_intrinsics"] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] #![crate_type = "dylib"] #![crate_type = "rlib"] -#![cfg_attr(stage0, feature(staged_api))] #![deny(warnings)] #![allow(bad_style)] diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs index 16ab593e47..1de31c5d79 100644 --- a/src/librustc_plugin/lib.rs +++ b/src/librustc_plugin/lib.rs @@ -20,21 +20,31 @@ //! To define a plugin, build a dylib crate with a //! `#[plugin_registrar]` function: //! -//! ```rust,ignore +//! ```no_run //! #![crate_name = "myplugin"] //! #![crate_type = "dylib"] //! #![feature(plugin_registrar)] +//! #![feature(rustc_private)] //! -//! extern crate rustc; +//! extern crate rustc_plugin; +//! extern crate syntax; +//! extern crate syntax_pos; //! //! use rustc_plugin::Registry; +//! use syntax::ext::base::{ExtCtxt, MacResult}; +//! use syntax_pos::Span; +//! use syntax::tokenstream::TokenTree; //! //! #[plugin_registrar] //! pub fn plugin_registrar(reg: &mut Registry) { //! reg.register_macro("mymacro", expand_mymacro); //! } //! -//! fn expand_mymacro(...) { // details elided +//! fn expand_mymacro(cx: &mut ExtCtxt, span: Span, tt: &[TokenTree]) -> Box { +//! unimplemented!() +//! } +//! +//! # fn main() {} //! ``` //! //! WARNING: We currently don't check that the registrar function @@ -47,8 +57,8 @@ //! #![plugin(myplugin)] //! ``` //! -//! See the [Plugins Chapter](../../book/compiler-plugins.html) of the book -//! for more examples. +//! See the [`plugin` feature](../../unstable-book/language-features/plugin.html) of +//! the Unstable Book for more examples. #![crate_name = "rustc_plugin"] #![crate_type = "dylib"] @@ -60,10 +70,6 @@ #![feature(rustc_diagnostic_macros)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] - #[macro_use] extern crate syntax; extern crate rustc; diff --git a/src/librustc_privacy/diagnostics.rs b/src/librustc_privacy/diagnostics.rs index 49f2ccb7c5..f8559954db 100644 --- a/src/librustc_privacy/diagnostics.rs +++ b/src/librustc_privacy/diagnostics.rs @@ -32,7 +32,7 @@ To solve this error, please ensure that the trait is also public. The trait can be made inaccessible if necessary by placing it into a private inner module, but it still has to be marked with `pub`. Example: -```ignore +``` pub trait Foo { // we set the Foo trait public fn dummy(&self) { } } @@ -75,9 +75,11 @@ mod Foo { "##, E0447: r##" +#### Note: this error code is no longer emitted by the compiler. + The `pub` keyword was used inside a function. Erroneous code example: -```ignore +``` fn foo() { pub struct Bar; // error: visibility has no effect inside functions } @@ -100,7 +102,7 @@ pub enum Foo { Since the enum is already public, adding `pub` on one its elements is unnecessary. Example: -```compile_fail, +```compile_fail enum Foo { pub Bar, // not ok! } @@ -108,7 +110,7 @@ enum Foo { This is the correct syntax: -```ignore +``` pub enum Foo { Bar, // ok! } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 153da91db6..64af24d92e 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -18,17 +18,13 @@ #![feature(rustc_diagnostic_macros)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] - -extern crate rustc; +#[macro_use] extern crate rustc; #[macro_use] extern crate syntax; extern crate syntax_pos; use rustc::hir::{self, PatKind}; use rustc::hir::def::Def; -use rustc::hir::def_id::{LOCAL_CRATE, CrateNum, DefId}; +use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::itemlikevisit::DeepVisitor; use rustc::lint; @@ -93,7 +89,7 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { ty::TyAdt(adt, _) => adt.did, ty::TyDynamic(ref obj, ..) if obj.principal().is_some() => obj.principal().unwrap().def_id(), - ty::TyProjection(ref proj) => proj.trait_ref.def_id, + ty::TyProjection(ref proj) => proj.trait_ref(self.tcx).def_id, _ => return Some(AccessLevel::Public) }; if let Some(node_id) = self.tcx.hir.as_local_node_id(ty_def_id) { @@ -399,19 +395,50 @@ impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { } fn predicates(&mut self) -> &mut Self { - self.ev.tcx.predicates_of(self.item_def_id).visit_with(self); + let predicates = self.ev.tcx.predicates_of(self.item_def_id); + for predicate in &predicates.predicates { + predicate.visit_with(self); + match predicate { + &ty::Predicate::Trait(poly_predicate) => { + self.check_trait_ref(poly_predicate.skip_binder().trait_ref); + }, + &ty::Predicate::Projection(poly_predicate) => { + let tcx = self.ev.tcx; + self.check_trait_ref( + poly_predicate.skip_binder().projection_ty.trait_ref(tcx) + ); + }, + _ => (), + }; + } self } fn ty(&mut self) -> &mut Self { - self.ev.tcx.type_of(self.item_def_id).visit_with(self); + let ty = self.ev.tcx.type_of(self.item_def_id); + ty.visit_with(self); + if let ty::TyFnDef(def_id, _) = ty.sty { + if def_id == self.item_def_id { + self.ev.tcx.fn_sig(def_id).visit_with(self); + } + } self } fn impl_trait_ref(&mut self) -> &mut Self { - self.ev.tcx.impl_trait_ref(self.item_def_id).visit_with(self); + if let Some(impl_trait_ref) = self.ev.tcx.impl_trait_ref(self.item_def_id) { + self.check_trait_ref(impl_trait_ref); + impl_trait_ref.super_visit_with(self); + } self } + + fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) { + if let Some(node_id) = self.ev.tcx.hir.as_local_node_id(trait_ref.def_id) { + let item = self.ev.tcx.hir.expect_item(node_id); + self.ev.update(item.id, Some(AccessLevel::Reachable)); + } + } } impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { @@ -419,7 +446,7 @@ impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b let ty_def_id = match ty.sty { ty::TyAdt(adt, _) => Some(adt.did), ty::TyDynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()), - ty::TyProjection(ref proj) => Some(proj.trait_ref.def_id), + ty::TyProjection(ref proj) => Some(proj.item_def_id), ty::TyFnDef(def_id, ..) | ty::TyAnon(def_id, _) => Some(def_id), _ => None @@ -433,15 +460,6 @@ impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b ty.super_visit_with(self) } - - fn visit_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool { - if let Some(node_id) = self.ev.tcx.hir.as_local_node_id(trait_ref.def_id) { - let item = self.ev.tcx.hir.expect_item(node_id); - self.ev.update(item.id, Some(AccessLevel::Reachable)); - } - - trait_ref.super_visit_with(self) - } } ////////////////////////////////////////////////////////////////////////////////////// @@ -535,6 +553,370 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { } } +//////////////////////////////////////////////////////////////////////////////////////////// +/// Type privacy visitor, checks types for privacy and reports violations. +/// Both explicitly written types and inferred types of expressions and patters are checked. +/// Checks are performed on "semantic" types regardless of names and their hygiene. +//////////////////////////////////////////////////////////////////////////////////////////// + +struct TypePrivacyVisitor<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: &'a ty::TypeckTables<'tcx>, + current_item: DefId, + span: Span, +} + +impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { + fn def_id_visibility(&self, did: DefId) -> ty::Visibility { + match self.tcx.hir.as_local_node_id(did) { + Some(node_id) => { + let vis = match self.tcx.hir.get(node_id) { + hir::map::NodeItem(item) => &item.vis, + hir::map::NodeForeignItem(foreign_item) => &foreign_item.vis, + hir::map::NodeImplItem(impl_item) => &impl_item.vis, + hir::map::NodeTraitItem(..) | + hir::map::NodeVariant(..) => { + return self.def_id_visibility(self.tcx.hir.get_parent_did(node_id)); + } + hir::map::NodeStructCtor(vdata) => { + let struct_node_id = self.tcx.hir.get_parent(node_id); + let struct_vis = match self.tcx.hir.get(struct_node_id) { + hir::map::NodeItem(item) => &item.vis, + node => bug!("unexpected node kind: {:?}", node), + }; + let mut ctor_vis + = ty::Visibility::from_hir(struct_vis, struct_node_id, self.tcx); + for field in vdata.fields() { + let field_vis = ty::Visibility::from_hir(&field.vis, node_id, self.tcx); + if ctor_vis.is_at_least(field_vis, self.tcx) { + ctor_vis = field_vis; + } + } + return ctor_vis; + } + node => bug!("unexpected node kind: {:?}", node) + }; + ty::Visibility::from_hir(vis, node_id, self.tcx) + } + None => self.tcx.sess.cstore.visibility(did), + } + } + + fn item_is_accessible(&self, did: DefId) -> bool { + self.def_id_visibility(did).is_accessible_from(self.current_item, self.tcx) + } + + // Take node ID of an expression or pattern and check its type for privacy. + fn check_expr_pat_type(&mut self, id: ast::NodeId, span: Span) -> bool { + self.span = span; + if let Some(ty) = self.tables.node_id_to_type_opt(id) { + if ty.visit_with(self) { + return true; + } + } + if self.tables.node_substs(id).visit_with(self) { + return true; + } + if let Some(adjustments) = self.tables.adjustments.get(&id) { + for adjustment in adjustments { + if adjustment.target.visit_with(self) { + return true; + } + } + } + false + } + + fn check_item(&mut self, item_id: ast::NodeId) -> &mut Self { + self.current_item = self.tcx.hir.local_def_id(item_id); + self.span = self.tcx.hir.span(item_id); + self + } + + // Convenience methods for checking item interfaces + fn ty(&mut self) -> &mut Self { + self.tcx.type_of(self.current_item).visit_with(self); + self + } + + fn generics(&mut self) -> &mut Self { + for def in &self.tcx.generics_of(self.current_item).types { + if def.has_default { + self.tcx.type_of(def.def_id).visit_with(self); + } + } + self + } + + fn predicates(&mut self) -> &mut Self { + let predicates = self.tcx.predicates_of(self.current_item); + for predicate in &predicates.predicates { + predicate.visit_with(self); + match predicate { + &ty::Predicate::Trait(poly_predicate) => { + self.check_trait_ref(poly_predicate.skip_binder().trait_ref); + }, + &ty::Predicate::Projection(poly_predicate) => { + let tcx = self.tcx; + self.check_trait_ref( + poly_predicate.skip_binder().projection_ty.trait_ref(tcx) + ); + }, + _ => (), + }; + } + self + } + + fn impl_trait_ref(&mut self) -> &mut Self { + if let Some(impl_trait_ref) = self.tcx.impl_trait_ref(self.current_item) { + self.check_trait_ref(impl_trait_ref); + } + self.tcx.predicates_of(self.current_item).visit_with(self); + self + } + + fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool { + if !self.item_is_accessible(trait_ref.def_id) { + let msg = format!("trait `{}` is private", trait_ref); + self.tcx.sess.span_err(self.span, &msg); + return true; + } + + trait_ref.super_visit_with(self) + } +} + +impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { + /// We want to visit items in the context of their containing + /// module and so forth, so supply a crate for doing a deep walk. + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::All(&self.tcx.hir) + } + + fn visit_nested_body(&mut self, body: hir::BodyId) { + let orig_tables = replace(&mut self.tables, self.tcx.body_tables(body)); + let body = self.tcx.hir.body(body); + self.visit_body(body); + self.tables = orig_tables; + } + + // Check types of expressions + fn visit_expr(&mut self, expr: &'tcx hir::Expr) { + if self.check_expr_pat_type(expr.id, expr.span) { + // Do not check nested expressions if the error already happened. + return; + } + match expr.node { + hir::ExprAssign(.., ref rhs) | hir::ExprMatch(ref rhs, ..) => { + // Do not report duplicate errors for `x = y` and `match x { ... }`. + if self.check_expr_pat_type(rhs.id, rhs.span) { + return; + } + } + hir::ExprMethodCall(_, span, _) => { + // Method calls have to be checked specially. + let def_id = self.tables.type_dependent_defs[&expr.id].def_id(); + self.span = span; + if self.tcx.type_of(def_id).visit_with(self) { + return; + } + } + _ => {} + } + + intravisit::walk_expr(self, expr); + } + + fn visit_qpath(&mut self, qpath: &'tcx hir::QPath, id: ast::NodeId, span: Span) { + // Inherent associated constants don't have self type in substs, + // we have to check it additionally. + if let hir::QPath::TypeRelative(..) = *qpath { + if let Some(def) = self.tables.type_dependent_defs.get(&id).cloned() { + if let Some(assoc_item) = self.tcx.opt_associated_item(def.def_id()) { + if let ty::ImplContainer(impl_def_id) = assoc_item.container { + if self.tcx.type_of(impl_def_id).visit_with(self) { + return; + } + } + } + } + } + + intravisit::walk_qpath(self, qpath, id, span); + } + + // Check types of patterns + fn visit_pat(&mut self, pattern: &'tcx hir::Pat) { + if self.check_expr_pat_type(pattern.id, pattern.span) { + // Do not check nested patterns if the error already happened. + return; + } + + intravisit::walk_pat(self, pattern); + } + + fn visit_local(&mut self, local: &'tcx hir::Local) { + if let Some(ref init) = local.init { + if self.check_expr_pat_type(init.id, init.span) { + // Do not report duplicate errors for `let x = y`. + return; + } + } + + intravisit::walk_local(self, local); + } + + // Check types in item interfaces + fn visit_item(&mut self, item: &'tcx hir::Item) { + let orig_current_item = self.current_item; + + match item.node { + hir::ItemExternCrate(..) | hir::ItemMod(..) | + hir::ItemUse(..) | hir::ItemGlobalAsm(..) => {} + hir::ItemConst(..) | hir::ItemStatic(..) | + hir::ItemTy(..) | hir::ItemFn(..) => { + self.check_item(item.id).generics().predicates().ty(); + } + hir::ItemTrait(.., ref trait_item_refs) => { + self.check_item(item.id).generics().predicates(); + for trait_item_ref in trait_item_refs { + let mut check = self.check_item(trait_item_ref.id.node_id); + check.generics().predicates(); + if trait_item_ref.kind != hir::AssociatedItemKind::Type || + trait_item_ref.defaultness.has_value() { + check.ty(); + } + } + } + hir::ItemEnum(ref def, _) => { + self.check_item(item.id).generics().predicates(); + for variant in &def.variants { + for field in variant.node.data.fields() { + self.check_item(field.id).ty(); + } + } + } + hir::ItemForeignMod(ref foreign_mod) => { + for foreign_item in &foreign_mod.items { + self.check_item(foreign_item.id).generics().predicates().ty(); + } + } + hir::ItemStruct(ref struct_def, _) | + hir::ItemUnion(ref struct_def, _) => { + self.check_item(item.id).generics().predicates(); + for field in struct_def.fields() { + self.check_item(field.id).ty(); + } + } + hir::ItemDefaultImpl(..) => { + self.check_item(item.id).impl_trait_ref(); + } + hir::ItemImpl(.., ref trait_ref, _, ref impl_item_refs) => { + { + let mut check = self.check_item(item.id); + check.ty().generics().predicates(); + if trait_ref.is_some() { + check.impl_trait_ref(); + } + } + for impl_item_ref in impl_item_refs { + let impl_item = self.tcx.hir.impl_item(impl_item_ref.id); + self.check_item(impl_item.id).generics().predicates().ty(); + } + } + } + + self.current_item = self.tcx.hir.local_def_id(item.id); + intravisit::walk_item(self, item); + self.current_item = orig_current_item; + } +} + +impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { + match ty.sty { + ty::TyAdt(&ty::AdtDef { did: def_id, .. }, ..) | ty::TyFnDef(def_id, ..) => { + if !self.item_is_accessible(def_id) { + let msg = format!("type `{}` is private", ty); + self.tcx.sess.span_err(self.span, &msg); + return true; + } + if let ty::TyFnDef(..) = ty.sty { + if self.tcx.fn_sig(def_id).visit_with(self) { + return true; + } + } + // Inherent static methods don't have self type in substs, + // we have to check it additionally. + if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) { + if let ty::ImplContainer(impl_def_id) = assoc_item.container { + if self.tcx.type_of(impl_def_id).visit_with(self) { + return true; + } + } + } + } + ty::TyDynamic(ref predicates, ..) => { + let is_private = predicates.skip_binder().iter().any(|predicate| { + let def_id = match *predicate { + ty::ExistentialPredicate::Trait(trait_ref) => trait_ref.def_id, + ty::ExistentialPredicate::Projection(proj) => + proj.trait_ref(self.tcx).def_id, + ty::ExistentialPredicate::AutoTrait(def_id) => def_id, + }; + !self.item_is_accessible(def_id) + }); + if is_private { + let msg = format!("type `{}` is private", ty); + self.tcx.sess.span_err(self.span, &msg); + return true; + } + } + ty::TyProjection(ref proj) => { + let tcx = self.tcx; + if self.check_trait_ref(proj.trait_ref(tcx)) { + return true; + } + } + ty::TyAnon(def_id, ..) => { + for predicate in &self.tcx.predicates_of(def_id).predicates { + let trait_ref = match *predicate { + ty::Predicate::Trait(ref poly_trait_predicate) => { + Some(poly_trait_predicate.skip_binder().trait_ref) + } + ty::Predicate::Projection(ref poly_projection_predicate) => { + if poly_projection_predicate.skip_binder().ty.visit_with(self) { + return true; + } + Some(poly_projection_predicate.skip_binder() + .projection_ty.trait_ref(self.tcx)) + } + ty::Predicate::TypeOutlives(..) => None, + _ => bug!("unexpected predicate: {:?}", predicate), + }; + if let Some(trait_ref) = trait_ref { + if !self.item_is_accessible(trait_ref.def_id) { + let msg = format!("trait `{}` is private", trait_ref); + self.tcx.sess.span_err(self.span, &msg); + return true; + } + // `Self` here is the same `TyAnon`, so skip it to avoid infinite recursion + for subst in trait_ref.substs.iter().skip(1) { + if subst.visit_with(self) { + return true; + } + } + } + } + } + _ => {} + } + + ty.super_visit_with(self) + } +} + /////////////////////////////////////////////////////////////////////////////// /// Obsolete visitors for checking for private items in public interfaces. /// These visitors are supposed to be kept in frozen state and produce an @@ -909,19 +1291,69 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { } fn predicates(&mut self) -> &mut Self { - self.tcx.predicates_of(self.item_def_id).visit_with(self); + let predicates = self.tcx.predicates_of(self.item_def_id); + for predicate in &predicates.predicates { + predicate.visit_with(self); + match predicate { + &ty::Predicate::Trait(poly_predicate) => { + self.check_trait_ref(poly_predicate.skip_binder().trait_ref); + }, + &ty::Predicate::Projection(poly_predicate) => { + let tcx = self.tcx; + self.check_trait_ref( + poly_predicate.skip_binder().projection_ty.trait_ref(tcx) + ); + }, + _ => (), + }; + } self } fn ty(&mut self) -> &mut Self { - self.tcx.type_of(self.item_def_id).visit_with(self); + let ty = self.tcx.type_of(self.item_def_id); + ty.visit_with(self); + if let ty::TyFnDef(def_id, _) = ty.sty { + if def_id == self.item_def_id { + self.tcx.fn_sig(def_id).visit_with(self); + } + } self } fn impl_trait_ref(&mut self) -> &mut Self { - self.tcx.impl_trait_ref(self.item_def_id).visit_with(self); + if let Some(impl_trait_ref) = self.tcx.impl_trait_ref(self.item_def_id) { + self.check_trait_ref(impl_trait_ref); + impl_trait_ref.super_visit_with(self); + } self } + + fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) { + // Non-local means public (private items can't leave their crate, modulo bugs) + if let Some(node_id) = self.tcx.hir.as_local_node_id(trait_ref.def_id) { + let item = self.tcx.hir.expect_item(node_id); + let vis = ty::Visibility::from_hir(&item.vis, node_id, self.tcx); + if !vis.is_at_least(self.min_visibility, self.tcx) { + self.min_visibility = vis; + } + if !vis.is_at_least(self.required_visibility, self.tcx) { + if self.has_pub_restricted || self.has_old_errors { + struct_span_err!(self.tcx.sess, self.span, E0445, + "private trait `{}` in public interface", trait_ref) + .span_label(self.span, format!( + "private trait can't be public")) + .emit(); + } else { + self.tcx.sess.add_lint(lint::builtin::PRIVATE_IN_PUBLIC, + node_id, + self.span, + format!("private trait `{}` in public \ + interface (error E0445)", trait_ref)); + } + } + } + } } impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { @@ -939,8 +1371,8 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<' // free type aliases, but this isn't done yet. return false; } - - Some(proj.trait_ref.def_id) + let trait_ref = proj.trait_ref(self.tcx); + Some(trait_ref.def_id) } _ => None }; @@ -971,42 +1403,7 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<' } } - if let ty::TyProjection(ref proj) = ty.sty { - // Avoid calling `visit_trait_ref` below on the trait, - // as we have already checked the trait itself above. - proj.trait_ref.super_visit_with(self) - } else { - ty.super_visit_with(self) - } - } - - fn visit_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool { - // Non-local means public (private items can't leave their crate, modulo bugs) - if let Some(node_id) = self.tcx.hir.as_local_node_id(trait_ref.def_id) { - let item = self.tcx.hir.expect_item(node_id); - let vis = ty::Visibility::from_hir(&item.vis, node_id, self.tcx); - - if !vis.is_at_least(self.min_visibility, self.tcx) { - self.min_visibility = vis; - } - if !vis.is_at_least(self.required_visibility, self.tcx) { - if self.has_pub_restricted || self.has_old_errors { - struct_span_err!(self.tcx.sess, self.span, E0445, - "private trait `{}` in public interface", trait_ref) - .span_label(self.span, format!( - "private trait can't be public")) - .emit(); - } else { - self.tcx.sess.add_lint(lint::builtin::PRIVATE_IN_PUBLIC, - node_id, - self.span, - format!("private trait `{}` in public \ - interface (error E0445)", trait_ref)); - } - } - } - - trait_ref.super_visit_with(self) + ty.super_visit_with(self) } } @@ -1217,6 +1614,16 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; intravisit::walk_crate(&mut visitor, krate); + // Check privacy of explicitly written types and traits as well as + // inferred types of expressions and patterns. + let mut visitor = TypePrivacyVisitor { + tcx: tcx, + tables: &ty::TypeckTables::empty(), + current_item: DefId::local(CRATE_DEF_INDEX), + span: krate.span, + }; + intravisit::walk_crate(&mut visitor, krate); + // Build up a set of all exported items in the AST. This is a set of all // items which are reachable from external crates based on visibility. let mut visitor = EmbargoVisitor { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 3450f1496e..4b6b754dca 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -149,14 +149,15 @@ impl<'a> Resolver<'a> { resolve_error(self, view_path.span, ResolutionError::SelfImportsOnlyAllowedWithin); - } else if source_name == "$crate" && full_path.segments.len() == 1 { + } else if source_name == keywords::DollarCrate.name() && + full_path.segments.len() == 1 { let crate_root = self.resolve_crate_root(source.ctxt); let crate_name = match crate_root.kind { ModuleKind::Def(_, name) => name, ModuleKind::Block(..) => unreachable!(), }; source.name = crate_name; - if binding.name == "$crate" { + if binding.name == keywords::DollarCrate.name() { binding.name = crate_name; } @@ -478,7 +479,7 @@ impl<'a> Resolver<'a> { span); self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion)); - for child in self.session.cstore.item_children(def_id) { + for child in self.session.cstore.item_children(def_id, self.session) { let ns = if let Def::AssociatedTy(..) = child.def { TypeNS } else { ValueNS }; self.define(module, child.ident, ns, (child.def, ty::Visibility::Public, DUMMY_SP, expansion)); @@ -567,7 +568,7 @@ impl<'a> Resolver<'a> { /// is built, building it if it is not. pub fn populate_module_if_necessary(&mut self, module: Module<'a>) { if module.populated.get() { return } - for child in self.session.cstore.item_children(module.def_id().unwrap()) { + for child in self.session.cstore.item_children(module.def_id().unwrap(), self.session) { self.build_reduced_graph_for_external_crate_def(module, child); } module.populated.set(true) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 1a5cf89f96..9193ac0fcd 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -50,7 +50,7 @@ variable declarations and expression statements. Here is an example that demonstrates the error: -```ignore +``` fn f() { // Variable declaration before import let x = 0; @@ -86,7 +86,7 @@ items under a new local name. An example of this error: -```ignore +``` use foo::baz; use bar::*; // error, do `use foo::baz as quux` instead on the previous line @@ -188,16 +188,16 @@ already been imported. Erroneous code example: ```compile_fail,E0254 -extern crate collections; +extern crate core; mod foo { - pub trait collections { + pub trait core { fn do_something(); } } -use foo::collections; // error: an extern crate named `collections` has already - // been imported in this module +use foo::core; // error: an extern crate named `core` has already + // been imported in this module fn main() {} ``` @@ -205,16 +205,16 @@ fn main() {} To fix issue issue, you have to rename at least one of the two imports. Example: -```ignore -extern crate collections as libcollections; // ok! +``` +extern crate core as libcore; // ok! mod foo { - pub trait collections { + pub trait core { fn do_something(); } } -use foo::collections; +use foo::core; fn main() {} ``` @@ -295,8 +295,9 @@ that has been imported into the current module. Erroneous code example: ```compile_fail,E0259 -extern crate std; -extern crate libc as std; +# #![feature(libc)] +extern crate core; +extern crate libc as core; fn main() {} ``` @@ -306,9 +307,12 @@ external crate imported into the current module. Correct example: -```ignore -extern crate std; +``` +# #![feature(libc)] +extern crate core; extern crate libc as other_name; + +fn main() {} ``` "##, @@ -317,26 +321,26 @@ The name for an item declaration conflicts with an external crate's name. Erroneous code example: -```ignore,E0260 -extern crate abc; +```compile_fail,E0260 +extern crate core; -struct abc; +struct core; ``` There are two possible solutions: Solution #1: Rename the item. -```ignore -extern crate abc; +``` +extern crate core; struct xyz; ``` Solution #2: Import the crate with a different name. -```ignore -extern crate abc as xyz; +``` +extern crate core as xyz; struct abc; ``` @@ -509,7 +513,8 @@ This may require additional type hints in the function body. In case the item is a function inside an `impl`, defining a private helper function might be easier: -```ignore +``` +# struct Foo(T); impl Foo { pub fn foo(&self, x: T) { self.bar(x); @@ -584,7 +589,8 @@ impl SomeTrait for Foo {} // error: trait `SomeTrait` is not in scope Please verify that the name of the trait wasn't misspelled and ensure that it was imported. Example: -```ignore +``` +# #[cfg(for_demonstration_only)] // solution 1: use some_file::SomeTrait; @@ -721,7 +727,7 @@ Here, `y` is bound by-value in one case and by-reference in the other. To fix this error, just use the same mode in both cases. Generally using `ref` or `ref mut` where not already used will fix this: -```ignore +``` let x = (0, 2); match x { (0, ref y) | (ref y, 0) => { /* use y */} @@ -831,7 +837,7 @@ impl Something {} // ok! trait Foo { type N; - fn bar(Self::N); // ok! + fn bar(_: Self::N); // ok! } // or: @@ -905,7 +911,8 @@ match (1, 2) { Or maybe did you mean to unify? Consider using a guard: -```ignore +``` +# let (A, B, C) = (1, 2, 3); match (A, B, C) { (x, x2, see) if x == x2 => { /* A and B are equal, do one thing */ } (y, z, see) => { /* A and B unequal; do another thing */ } @@ -1045,9 +1052,12 @@ let x = unknown_variable; // ok! If the item is not defined in the current module, it must be imported using a `use` statement, like so: -```ignore +``` +# mod foo { pub fn bar() {} } +# fn main() { use foo::bar; bar(); +# } ``` If the item you are importing is not defined in some super-module of the @@ -1130,8 +1140,11 @@ use something::{self, self}; // error: `self` import can only appear once in Please verify you didn't misspell the import name or remove the duplicated `self` import. Example: -```ignore -use something::self; // ok! +``` +# mod something {} +# fn main() { +use something::{self}; // ok! +# } ``` "##, @@ -1164,21 +1177,23 @@ prefixes, respectively. Also verify that you didn't misspell the import name and that the import exists in the module from where you tried to import it. Example: -```ignore +``` use self::something::Foo; // ok! mod something { pub struct Foo; } +# fn main() {} ``` Or, if you tried to use a module from an external crate, you may have missed the `extern crate` declaration (which is usually placed in the crate root): -```ignore -extern crate homura; // Required to use the `homura` crate +``` +extern crate core; // Required to use the `core` crate -use homura::Madoka; +use core::any; +# fn main() {} ``` "##, @@ -1305,8 +1320,6 @@ match the name of any associated constant in the trait. Erroneous code example: ```compile_fail,E0438 -#![feature(associated_consts)] - trait Foo {} impl Foo for i32 { @@ -1339,7 +1352,7 @@ extern crate core as another_crate; This is a syntax error at the level of attribute declarations. The proper syntax for macro imports is the following: -```ignore +```ignore (cannot-doctest-multicrate-project) // In some_crate: #[macro_export] macro_rules! get_tacos { @@ -1383,7 +1396,7 @@ Decide which macros you would like to export and list them properly. These are proper reexport declarations: -```ignore +```ignore (cannot-doctest-multicrate-project) #[macro_reexport(some_macro, another_macro)] extern crate macros_for_good; ``` @@ -1396,9 +1409,9 @@ Example of erroneous code: ```compile_fail,E0468 mod foo { - #[macro_use(helpful_macro)] // error: must be at crate root to import + #[macro_use(debug_assert)] // error: must be at crate root to import extern crate core; // macros from another crate - helpful_macro!(...); + fn run_macro() { debug_assert!(true); } } ``` @@ -1408,13 +1421,14 @@ macros. Either move the macro import to crate root or do without the foreign macros. This will work: -```ignore -#[macro_use(helpful_macro)] -extern crate some_crate; +``` +#[macro_use(debug_assert)] +extern crate core; mod foo { - helpful_macro!(...) + fn run_macro() { debug_assert!(true); } } +# fn main() {} ``` "##, @@ -1425,7 +1439,7 @@ Erroneous code example: ```compile_fail,E0469 #[macro_use(drink, be_merry)] // error: imported macro not found -extern crate collections; +extern crate alloc; fn main() { // ... @@ -1442,7 +1456,7 @@ in question exports them. A working version would be: -```ignore +```ignore (cannot-doctest-multicrate-project) // In some_crate crate: #[macro_export] macro_rules! eat { @@ -1467,7 +1481,7 @@ Erroneous code example: ```compile_fail,E0470 #[macro_reexport(drink, be_merry)] -extern crate collections; +extern crate alloc; fn main() { // ... @@ -1484,7 +1498,7 @@ in question exports them. A working version: -```ignore +```ignore (cannot-doctest-multicrate-project) // In some_crate crate: #[macro_export] macro_rules! eat { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b77d5a2f71..49e6929aee 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -16,12 +16,9 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![deny(warnings)] -#![feature(associated_consts)] #![feature(rustc_diagnostic_macros)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] +#![cfg_attr(stage0, feature(associated_consts))] #[macro_use] extern crate log; @@ -329,7 +326,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, span, E0435, "attempt to use a non-constant value in a constant"); - err.span_label(span, "non-constant used with constant"); + err.span_label(span, "non-constant value"); err } ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, name, binding) => { @@ -2412,13 +2409,15 @@ impl<'a> Resolver<'a> { .map(|suggestion| import_candidate_to_paths(&suggestion)).collect::>(); enum_candidates.sort(); for (sp, variant_path, enum_path) in enum_candidates { - let msg = format!("there is an enum variant `{}`, did you mean to use `{}`?", - variant_path, - enum_path); if sp == DUMMY_SP { + let msg = format!("there is an enum variant `{}`, \ + try using `{}`?", + variant_path, + enum_path); err.help(&msg); } else { - err.span_help(sp, &msg); + err.span_suggestion(span, "you can try using the variant's enum", + enum_path); } } } @@ -2427,18 +2426,20 @@ impl<'a> Resolver<'a> { let self_is_available = this.self_value_is_available(path[0].ctxt, span); match candidate { AssocSuggestion::Field => { - err.span_label(span, format!("did you mean `self.{}`?", path_str)); + err.span_suggestion(span, "try", + format!("self.{}", path_str)); if !self_is_available { err.span_label(span, format!("`self` value is only available in \ methods with `self` parameter")); } } AssocSuggestion::MethodWithSelf if self_is_available => { - err.span_label(span, format!("did you mean `self.{}(...)`?", - path_str)); + err.span_suggestion(span, "try", + format!("self.{}", path_str)); } AssocSuggestion::MethodWithSelf | AssocSuggestion::AssocItem => { - err.span_label(span, format!("did you mean `Self::{}`?", path_str)); + err.span_suggestion(span, "try", + format!("Self::{}", path_str)); } } return err; @@ -2470,9 +2471,9 @@ impl<'a> Resolver<'a> { path_str, ident.node)); return err; } - ExprKind::MethodCall(ident, ..) => { + ExprKind::MethodCall(ref segment, ..) => { err.span_label(parent.span, format!("did you mean `{}::{}(...)`?", - path_str, ident.node)); + path_str, segment.identifier)); return err; } _ => {} @@ -2669,7 +2670,8 @@ impl<'a> Resolver<'a> { }; if path.len() > 1 && !global_by_default && result.base_def() != Def::Err && - path[0].name != keywords::CrateRoot.name() && path[0].name != "$crate" { + path[0].name != keywords::CrateRoot.name() && + path[0].name != keywords::DollarCrate.name() { let unqualified_result = { match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span) { PathResult::NonModule(path_res) => path_res.base_def(), @@ -2722,7 +2724,7 @@ impl<'a> Resolver<'a> { if i == 0 && ns == TypeNS && ident.name == keywords::CrateRoot.name() { module = Some(self.resolve_crate_root(ident.ctxt.modern())); continue - } else if i == 0 && ns == TypeNS && ident.name == "$crate" { + } else if i == 0 && ns == TypeNS && ident.name == keywords::DollarCrate.name() { module = Some(self.resolve_crate_root(ident.ctxt)); continue } @@ -3147,15 +3149,13 @@ impl<'a> Resolver<'a> { ExprKind::Field(ref subexpression, _) => { self.resolve_expr(subexpression, Some(expr)); } - ExprKind::MethodCall(_, ref types, ref arguments) => { + ExprKind::MethodCall(ref segment, ref arguments) => { let mut arguments = arguments.iter(); self.resolve_expr(arguments.next().unwrap(), Some(expr)); for argument in arguments { self.resolve_expr(argument, None); } - for ty in types.iter() { - self.visit_ty(ty); - } + self.visit_path_segment(expr.span, segment); } ExprKind::Repeat(ref element, ref count) => { @@ -3187,10 +3187,10 @@ impl<'a> Resolver<'a> { let traits = self.get_traits_containing_item(name.node, ValueNS); self.trait_map.insert(expr.id, traits); } - ExprKind::MethodCall(name, ..) => { + ExprKind::MethodCall(ref segment, ..) => { debug!("(recording candidate traits for expr) recording traits for {}", expr.id); - let traits = self.get_traits_containing_item(name.node, ValueNS); + let traits = self.get_traits_containing_item(segment.identifier, ValueNS); self.trait_map.insert(expr.id, traits); } _ => { @@ -3454,11 +3454,11 @@ impl<'a> Resolver<'a> { parent: Module, ident: Ident, ns: Namespace, - binding: &NameBinding, + new_binding: &NameBinding, old_binding: &NameBinding) { // Error on the second of two conflicting names - if old_binding.span.lo > binding.span.lo { - return self.report_conflict(parent, ident, ns, old_binding, binding); + if old_binding.span.lo > new_binding.span.lo { + return self.report_conflict(parent, ident, ns, old_binding, new_binding); } let container = match parent.kind { @@ -3468,12 +3468,17 @@ impl<'a> Resolver<'a> { _ => "enum", }; - let (participle, noun) = match old_binding.is_import() { - true => ("imported", "import"), - false => ("defined", "definition"), + let old_noun = match old_binding.is_import() { + true => "import", + false => "definition", }; - let (name, span) = (ident.name, binding.span); + let new_participle = match new_binding.is_import() { + true => "imported", + false => "defined", + }; + + let (name, span) = (ident.name, new_binding.span); if let Some(s) = self.name_already_seen.get(&name) { if s == &span { @@ -3481,36 +3486,47 @@ impl<'a> Resolver<'a> { } } - let msg = { - let kind = match (ns, old_binding.module()) { - (ValueNS, _) => "a value", - (MacroNS, _) => "a macro", - (TypeNS, _) if old_binding.is_extern_crate() => "an extern crate", - (TypeNS, Some(module)) if module.is_normal() => "a module", - (TypeNS, Some(module)) if module.is_trait() => "a trait", - (TypeNS, _) => "a type", - }; - format!("{} named `{}` has already been {} in this {}", - kind, name, participle, container) + let old_kind = match (ns, old_binding.module()) { + (ValueNS, _) => "value", + (MacroNS, _) => "macro", + (TypeNS, _) if old_binding.is_extern_crate() => "extern crate", + (TypeNS, Some(module)) if module.is_normal() => "module", + (TypeNS, Some(module)) if module.is_trait() => "trait", + (TypeNS, _) => "type", }; - let mut err = match (old_binding.is_extern_crate(), binding.is_extern_crate()) { + let namespace = match ns { + ValueNS => "value", + MacroNS => "macro", + TypeNS => "type", + }; + + let msg = format!("the name `{}` is defined multiple times", name); + + let mut err = match (old_binding.is_extern_crate(), new_binding.is_extern_crate()) { (true, true) => struct_span_err!(self.session, span, E0259, "{}", msg), - (true, _) | (_, true) => match binding.is_import() && old_binding.is_import() { + (true, _) | (_, true) => match new_binding.is_import() && old_binding.is_import() { true => struct_span_err!(self.session, span, E0254, "{}", msg), false => struct_span_err!(self.session, span, E0260, "{}", msg), }, - _ => match (old_binding.is_import(), binding.is_import()) { + _ => match (old_binding.is_import(), new_binding.is_import()) { (false, false) => struct_span_err!(self.session, span, E0428, "{}", msg), (true, true) => struct_span_err!(self.session, span, E0252, "{}", msg), _ => struct_span_err!(self.session, span, E0255, "{}", msg), }, }; - err.span_label(span, format!("`{}` already {}", name, participle)); + err.note(&format!("`{}` must be defined only once in the {} namespace of this {}", + name, + namespace, + container)); + + err.span_label(span, format!("`{}` re{} here", name, new_participle)); if old_binding.span != syntax_pos::DUMMY_SP { - err.span_label(old_binding.span, format!("previous {} of `{}` here", noun, name)); + err.span_label(old_binding.span, format!("previous {} of the {} `{}` here", + old_noun, old_kind, name)); } + err.emit(); self.name_already_seen.insert(name, span); } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index a950a9a23e..a993aca92d 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -128,7 +128,7 @@ impl<'a> base::Resolver for Resolver<'a> { impl<'a, 'b> Folder for EliminateCrateVar<'a, 'b> { fn fold_path(&mut self, mut path: ast::Path) -> ast::Path { let ident = path.segments[0].identifier; - if ident.name == "$crate" { + if ident.name == keywords::DollarCrate.name() { path.segments[0].identifier.name = keywords::CrateRoot.name(); let module = self.0.resolve_crate_root(ident.ctxt); if !module.is_local() { @@ -285,10 +285,7 @@ impl<'a> base::Resolver for Resolver<'a> { -> Result>, Determinacy> { let def = match invoc.kind { InvocationKind::Attr { attr: None, .. } => return Ok(None), - _ => match self.resolve_invoc_to_def(invoc, scope, force) { - Ok(def) => def, - Err(determinacy) => return Err(determinacy), - }, + _ => self.resolve_invoc_to_def(invoc, scope, force)?, }; self.macro_defs.insert(invoc.expansion_data.mark, def.def_id()); @@ -661,9 +658,10 @@ impl<'a> Resolver<'a> { if let Some(suggestion) = suggestion { if suggestion != name { if let MacroKind::Bang = kind { - err.help(&format!("did you mean `{}!`?", suggestion)); + err.span_suggestion(span, "you could try the macro", + format!("{}!", suggestion)); } else { - err.help(&format!("did you mean `{}`?", suggestion)); + err.span_suggestion(span, "try", suggestion.to_string()); } } else { err.help("have you added the `#[macro_use]` on the module/import?"); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index a892f9df6a..4bff5da3d6 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -18,7 +18,7 @@ use {names_to_string, module_to_string}; use {resolve_error, ResolutionError}; use rustc::ty; -use rustc::lint::builtin::PRIVATE_IN_PUBLIC; +use rustc::lint::builtin::PUB_USE_OF_PRIVATE_EXTERN_CRATE; use rustc::hir::def_id::DefId; use rustc::hir::def::*; use rustc::util::nodemap::FxHashMap; @@ -296,7 +296,8 @@ impl<'a> Resolver<'a> { pub fn import(&self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>) -> &'a NameBinding<'a> { let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) || - !directive.is_glob() && binding.is_extern_crate() { // c.f. `PRIVATE_IN_PUBLIC` + // c.f. `PUB_USE_OF_PRIVATE_EXTERN_CRATE` + !directive.is_glob() && binding.is_extern_crate() { directive.vis.get() } else { binding.pseudo_vis() @@ -482,6 +483,16 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { if let Some(err) = self.finalize_import(import) { errors = true; + if let SingleImport { source, ref result, .. } = import.subclass { + if source.name == "self" { + // Silence `unresolved import` error if E0429 is already emitted + match result.value_ns.get() { + Err(Determined) => continue, + _ => {}, + } + } + } + // If the error is a single failed import then create a "fake" import // resolution for it so that later resolve stages won't complain. self.import_dummy_binding(import); @@ -725,7 +736,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { let msg = format!("extern crate `{}` is private, and cannot be reexported \ (error E0365), consider declaring with `pub`", ident); - self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg); + self.session.add_lint(PUB_USE_OF_PRIVATE_EXTERN_CRATE, + directive.id, directive.span, msg); } else if ns == TypeNS { struct_span_err!(self.session, directive.span, E0365, "`{}` is private, and cannot be reexported", ident) diff --git a/src/librustc_save_analysis/Cargo.toml b/src/librustc_save_analysis/Cargo.toml index 6d04bff828..1ae666fbc2 100644 --- a/src/librustc_save_analysis/Cargo.toml +++ b/src/librustc_save_analysis/Cargo.toml @@ -14,7 +14,7 @@ rustc = { path = "../librustc" } rustc_typeck = { path = "../librustc_typeck" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } -rls-data = "0.3" +rls-data = "0.7" rls-span = "0.4" # FIXME(#40527) should move rustc serialize out of tree rustc-serialize = "0.3" diff --git a/src/librustc_save_analysis/csv_dumper.rs b/src/librustc_save_analysis/csv_dumper.rs deleted file mode 100644 index 4bab135ff1..0000000000 --- a/src/librustc_save_analysis/csv_dumper.rs +++ /dev/null @@ -1,436 +0,0 @@ -// Copyright 2012-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 std::io::Write; - -use super::external_data::*; -use super::dump::Dump; - -use rls_data::{SpanData, CratePreludeData}; - -pub struct CsvDumper<'b, W: 'b> { - output: &'b mut W -} - -impl<'b, W: Write> CsvDumper<'b, W> { - pub fn new(writer: &'b mut W) -> CsvDumper<'b, W> { - CsvDumper { output: writer } - } - - fn record(&mut self, kind: &str, span: SpanData, values: String) { - let span_str = span_extent_str(span); - if let Err(_) = write!(self.output, "{},{}{}\n", kind, span_str, values) { - error!("Error writing output"); - } - } - - fn record_raw(&mut self, info: &str) { - if let Err(_) = write!(self.output, "{}", info) { - error!("Error writing output '{}'", info); - } - } -} - -impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { - fn crate_prelude(&mut self, data: CratePreludeData) { - let values = make_values_str(&[ - ("name", &data.crate_name), - ("crate_root", &data.crate_root) - ]); - - self.record("crate", data.span, values); - - for c in data.external_crates { - let num = c.num.to_string(); - let values = make_values_str(&[ - ("name", &c.name), - ("crate", &num), - ("file_name", &c.file_name) - ]); - - self.record_raw(&format!("external_crate{}\n", values)); - } - - self.record_raw("end_external_crates\n"); - } - - fn enum_data(&mut self, data: EnumData) { - let id = data.id.index.as_u32().to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("qualname", &data.qualname), - ("scopeid", &scope), - ("value", &data.value) - ]); - - self.record("enum", data.span, values); - } - - fn extern_crate(&mut self, data: ExternCrateData) { - let id = data.id.index.as_u32().to_string(); - let crate_num = data.crate_num.to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("name", &data.name), - ("location", &data.location), - ("crate", &crate_num), - ("scopeid", &scope) - ]); - - self.record("extern_crate", data.span, values); - } - - fn impl_data(&mut self, data: ImplData) { - let self_ref = data.self_ref.unwrap_or(null_def_id()); - let trait_ref = data.trait_ref.unwrap_or(null_def_id()); - - let id = data.id.index.as_u32().to_string(); - let ref_id = self_ref.index.as_usize().to_string(); - let ref_id_crate = self_ref.krate.to_string(); - let trait_id = trait_ref.index.as_usize().to_string(); - let trait_id_crate = trait_ref.krate.to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("refid", &ref_id), - ("refidcrate", &ref_id_crate), - ("traitid", &trait_id), - ("traitidcrate", &trait_id_crate), - ("scopeid", &scope) - ]); - - self.record("impl", data.span, values); - } - - fn inheritance(&mut self, data: InheritanceData) { - let base_id = data.base_id.index.as_usize().to_string(); - let base_crate = data.base_id.krate.to_string(); - let deriv_id = data.deriv_id.index.as_u32().to_string(); - let deriv_crate = data.deriv_id.krate.to_string(); - let values = make_values_str(&[ - ("base", &base_id), - ("basecrate", &base_crate), - ("derived", &deriv_id), - ("derivedcrate", &deriv_crate) - ]); - - self.record("inheritance", data.span, values); - } - - fn function(&mut self, data: FunctionData) { - let (decl_id, decl_crate) = match data.declaration { - Some(id) => (id.index.as_usize().to_string(), id.krate.to_string()), - None => (String::new(), String::new()) - }; - - let id = data.id.index.as_u32().to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("qualname", &data.qualname), - ("declid", &decl_id), - ("declidcrate", &decl_crate), - ("scopeid", &scope) - ]); - - self.record("function", data.span, values); - } - - fn function_ref(&mut self, data: FunctionRefData) { - let ref_id = data.ref_id.index.as_usize().to_string(); - let ref_crate = data.ref_id.krate.to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("refid", &ref_id), - ("refidcrate", &ref_crate), - ("qualname", ""), - ("scopeid", &scope) - ]); - - self.record("fn_ref", data.span, values); - } - - fn function_call(&mut self, data: FunctionCallData) { - let ref_id = data.ref_id.index.as_usize().to_string(); - let ref_crate = data.ref_id.krate.to_string(); - let qualname = String::new(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("refid", &ref_id), - ("refidcrate", &ref_crate), - ("qualname", &qualname), - ("scopeid", &scope) - ]); - - self.record("fn_call", data.span, values); - } - - fn method(&mut self, data: MethodData) { - let id = data.id.index.as_u32().to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("qualname", &data.qualname), - ("scopeid", &scope) - ]); - - self.record("method_decl", data.span, values); - } - - fn method_call(&mut self, data: MethodCallData) { - let (dcn, dck) = match data.decl_id { - Some(declid) => (declid.index.as_usize().to_string(), declid.krate.to_string()), - None => (String::new(), String::new()), - }; - - let ref_id = data.ref_id.unwrap_or(null_def_id()); - - let def_id = ref_id.index.as_usize().to_string(); - let def_crate = ref_id.krate.to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("refid", &def_id), - ("refidcrate", &def_crate), - ("declid", &dcn), - ("declidcrate", &dck), - ("scopeid", &scope) - ]); - - self.record("method_call", data.span, values); - } - - fn macro_data(&mut self, data: MacroData) { - let values = make_values_str(&[ - ("name", &data.name), - ("qualname", &data.qualname) - ]); - - self.record("macro", data.span, values); - } - - fn macro_use(&mut self, data: MacroUseData) { - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("callee_name", &data.name), - ("qualname", &data.qualname), - ("scopeid", &scope) - ]); - - self.record("macro_use", data.span, values); - } - - fn mod_data(&mut self, data: ModData) { - let id = data.id.index.as_u32().to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("qualname", &data.qualname), - ("scopeid", &scope), - ("def_file", &data.filename) - ]); - - self.record("module", data.span, values); - } - - fn mod_ref(&mut self, data: ModRefData) { - let (ref_id, ref_crate) = match data.ref_id { - Some(rid) => (rid.index.as_usize().to_string(), rid.krate.to_string()), - None => (0.to_string(), 0.to_string()) - }; - - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("refid", &ref_id), - ("refidcrate", &ref_crate), - ("qualname", &data.qualname), - ("scopeid", &scope) - ]); - - self.record("mod_ref", data.span, values); - } - - fn struct_data(&mut self, data: StructData) { - let id = data.id.index.as_u32().to_string(); - let ctor_id = data.ctor_id.index.as_u32().to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("ctor_id", &ctor_id), - ("qualname", &data.qualname), - ("scopeid", &scope), - ("value", &data.value) - ]); - - self.record("struct", data.span, values); - } - - fn struct_variant(&mut self, data: StructVariantData) { - let id = data.id.index.as_u32().to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("ctor_id", &id), - ("qualname", &data.qualname), - ("type", &data.type_value), - ("value", &data.value), - ("scopeid", &scope) - ]); - - self.record("variant_struct", data.span, values); - } - - fn trait_data(&mut self, data: TraitData) { - let id = data.id.index.as_u32().to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("qualname", &data.qualname), - ("scopeid", &scope), - ("value", &data.value) - ]); - - self.record("trait", data.span, values); - } - - fn tuple_variant(&mut self, data: TupleVariantData) { - let id = data.id.index.as_u32().to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("name", &data.name), - ("qualname", &data.qualname), - ("type", &data.type_value), - ("value", &data.value), - ("scopeid", &scope) - ]); - - self.record("variant", data.span, values); - } - - fn type_ref(&mut self, data: TypeRefData) { - let (ref_id, ref_crate) = match data.ref_id { - Some(id) => (id.index.as_usize().to_string(), id.krate.to_string()), - None => (0.to_string(), 0.to_string()) - }; - - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("refid", &ref_id), - ("refidcrate", &ref_crate), - ("qualname", &data.qualname), - ("scopeid", &scope) - ]); - - self.record("type_ref", data.span, values); - } - - fn typedef(&mut self, data: TypeDefData) { - let id = data.id.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("qualname", &data.qualname), - ("value", &data.value) - ]); - - self.record("typedef", data.span, values); - } - - fn use_data(&mut self, data: UseData) { - let mod_id = data.mod_id.unwrap_or(null_def_id()); - - let id = data.id.index.as_u32().to_string(); - let ref_id = mod_id.index.as_usize().to_string(); - let ref_crate = mod_id.krate.to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("refid", &ref_id), - ("refidcrate", &ref_crate), - ("name", &data.name), - ("scopeid", &scope) - ]); - - self.record("use_alias", data.span, values); - } - - fn use_glob(&mut self, data: UseGlobData) { - let names = data.names.join(", "); - - let id = data.id.index.as_u32().to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("value", &names), - ("scopeid", &scope) - ]); - - self.record("use_glob", data.span, values); - } - - fn variable(&mut self, data: VariableData) { - let id = data.id.index.as_u32().to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("name", &data.name), - ("qualname", &data.qualname), - ("value", &data.value), - ("type", &data.type_value), - ("scopeid", &scope) - ]); - - self.record("variable", data.span, values); - } - - fn variable_ref(&mut self, data: VariableRefData) { - let ref_id = data.ref_id.index.as_usize().to_string(); - let ref_crate = data.ref_id.krate.to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("refid", &ref_id), - ("refidcrate", &ref_crate), - ("qualname", ""), - ("scopeid", &scope) - ]); - - self.record("var_ref", data.span, values) - } -} - -// Helper function to escape quotes in a string -fn escape(s: String) -> String { - s.replace("\"", "\"\"") -} - -fn make_values_str(pairs: &[(&'static str, &str)]) -> String { - let pairs = pairs.into_iter().map(|&(f, v)| { - // Never take more than 1020 chars - if v.len() > 1020 { - (f, &v[..1020]) - } else { - (f, v) - } - }); - - let strs = pairs.map(|(f, v)| format!(",{},\"{}\"", f, escape(String::from(v)))); - strs.fold(String::new(), |mut s, ss| { - s.push_str(&ss); - s - }) -} - -fn span_extent_str(span: SpanData) -> String { - format!("file_name,\"{}\",file_line,{},file_col,{},byte_start,{},\ - file_line_end,{},file_col_end,{},byte_end,{}", - span.file_name.to_str().unwrap(), span.line_start.0, span.column_start.0, - span.byte_start, span.line_end.0, span.column_end.0, span.byte_end) -} diff --git a/src/librustc_save_analysis/data.rs b/src/librustc_save_analysis/data.rs deleted file mode 100644 index cac1a2e3c5..0000000000 --- a/src/librustc_save_analysis/data.rs +++ /dev/null @@ -1,446 +0,0 @@ -// Copyright 2012-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. - -//! Structs representing the analysis data from a crate. -//! -//! The `Dump` trait can be used together with `DumpVisitor` in order to -//! retrieve the data from a crate. - -use rustc::hir; -use rustc::hir::def_id::{CrateNum, DefId}; -use syntax::ast::{self, Attribute, NodeId}; -use syntax_pos::Span; - -use rls_data::ExternalCrateData; - -pub struct CrateData { - pub name: String, - pub number: u32, - pub span: Span, -} - -/// Data for any entity in the Rust language. The actual data contained varies -/// with the kind of entity being queried. See the nested structs for details. -#[derive(Debug)] -pub enum Data { - /// Data for Enums. - EnumData(EnumData), - /// Data for extern crates. - ExternCrateData(ExternCrateData), - /// Data about a function call. - FunctionCallData(FunctionCallData), - /// Data for all kinds of functions and methods. - FunctionData(FunctionData), - /// Data about a function ref. - FunctionRefData(FunctionRefData), - /// Data for impls. - ImplData(ImplData2), - /// Data for trait inheritance. - InheritanceData(InheritanceData), - /// Data about a macro declaration. - MacroData(MacroData), - /// Data about a macro use. - MacroUseData(MacroUseData), - /// Data about a method call. - MethodCallData(MethodCallData), - /// Data for method declarations (methods with a body are treated as functions). - MethodData(MethodData), - /// Data for modules. - ModData(ModData), - /// Data for a reference to a module. - ModRefData(ModRefData), - /// Data for a struct declaration. - StructData(StructData), - /// Data for a struct variant. - StructVariantDat(StructVariantData), - /// Data for a trait declaration. - TraitData(TraitData), - /// Data for a tuple variant. - TupleVariantData(TupleVariantData), - /// Data for a typedef. - TypeDefData(TypeDefData), - /// Data for a reference to a type or trait. - TypeRefData(TypeRefData), - /// Data for a use statement. - UseData(UseData), - /// Data for a global use statement. - UseGlobData(UseGlobData), - /// Data for local and global variables (consts and statics), and fields. - VariableData(VariableData), - /// Data for the use of some variable (e.g., the use of a local variable, which - /// will refere to that variables declaration). - VariableRefData(VariableRefData), -} - -#[derive(Eq, PartialEq, Clone, Copy, Debug)] -pub enum Visibility { - Public, - Restricted, - Inherited, -} - -impl<'a> From<&'a ast::Visibility> for Visibility { - fn from(v: &'a ast::Visibility) -> Visibility { - match *v { - ast::Visibility::Public => Visibility::Public, - ast::Visibility::Crate(_) => Visibility::Restricted, - ast::Visibility::Restricted { .. } => Visibility::Restricted, - ast::Visibility::Inherited => Visibility::Inherited, - } - } -} - -impl<'a> From<&'a hir::Visibility> for Visibility { - fn from(v: &'a hir::Visibility) -> Visibility { - match *v { - hir::Visibility::Public => Visibility::Public, - hir::Visibility::Crate => Visibility::Restricted, - hir::Visibility::Restricted { .. } => Visibility::Restricted, - hir::Visibility::Inherited => Visibility::Inherited, - } - } -} - -/// Data for the prelude of a crate. -#[derive(Debug)] -pub struct CratePreludeData { - pub crate_name: String, - pub crate_root: String, - pub external_crates: Vec, - pub span: Span, -} - -/// Data for enum declarations. -#[derive(Clone, Debug)] -pub struct EnumData { - pub id: NodeId, - pub name: String, - pub value: String, - pub qualname: String, - pub span: Span, - pub scope: NodeId, - pub variants: Vec, - pub visibility: Visibility, - pub docs: String, - pub sig: Signature, - pub attributes: Vec, -} - -/// Data for extern crates. -#[derive(Debug)] -pub struct ExternCrateData { - pub id: NodeId, - pub name: String, - pub crate_num: CrateNum, - pub location: String, - pub span: Span, - pub scope: NodeId, -} - -/// Data about a function call. -#[derive(Debug)] -pub struct FunctionCallData { - pub span: Span, - pub scope: NodeId, - pub ref_id: DefId, -} - -/// Data for all kinds of functions and methods. -#[derive(Clone, Debug)] -pub struct FunctionData { - pub id: NodeId, - pub name: String, - pub qualname: String, - pub declaration: Option, - pub span: Span, - pub scope: NodeId, - pub value: String, - pub visibility: Visibility, - pub parent: Option, - pub docs: String, - pub sig: Signature, - pub attributes: Vec, -} - -/// Data about a function call. -#[derive(Debug)] -pub struct FunctionRefData { - pub span: Span, - pub scope: NodeId, - pub ref_id: DefId, -} - -#[derive(Debug)] -pub struct ImplData { - pub id: NodeId, - pub span: Span, - pub scope: NodeId, - pub trait_ref: Option, - pub self_ref: Option, -} - -#[derive(Debug)] -// FIXME: this struct should not exist. However, removing it requires heavy -// refactoring of dump_visitor.rs. See PR 31838 for more info. -pub struct ImplData2 { - pub id: NodeId, - pub span: Span, - pub scope: NodeId, - // FIXME: I'm not really sure inline data is the best way to do this. Seems - // OK in this case, but generalising leads to returning chunks of AST, which - // feels wrong. - pub trait_ref: Option, - pub self_ref: Option, -} - -#[derive(Debug)] -pub struct InheritanceData { - pub span: Span, - pub base_id: DefId, - pub deriv_id: NodeId -} - -/// Data about a macro declaration. -#[derive(Debug)] -pub struct MacroData { - pub span: Span, - pub name: String, - pub qualname: String, - pub docs: String, -} - -/// Data about a macro use. -#[derive(Debug)] -pub struct MacroUseData { - pub span: Span, - pub name: String, - pub qualname: String, - // Because macro expansion happens before ref-ids are determined, - // we use the callee span to reference the associated macro definition. - pub callee_span: Span, - pub scope: NodeId, - pub imported: bool, -} - -/// Data about a method call. -#[derive(Debug)] -pub struct MethodCallData { - pub span: Span, - pub scope: NodeId, - pub ref_id: Option, - pub decl_id: Option, -} - -/// Data for method declarations (methods with a body are treated as functions). -#[derive(Clone, Debug)] -pub struct MethodData { - pub id: NodeId, - pub name: String, - pub qualname: String, - pub span: Span, - pub scope: NodeId, - pub value: String, - pub decl_id: Option, - pub parent: Option, - pub visibility: Visibility, - pub docs: String, - pub sig: Signature, - pub attributes: Vec, -} - -/// Data for modules. -#[derive(Debug)] -pub struct ModData { - pub id: NodeId, - pub name: String, - pub qualname: String, - pub span: Span, - pub scope: NodeId, - pub filename: String, - pub items: Vec, - pub visibility: Visibility, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -/// Data for a reference to a module. -#[derive(Debug)] -pub struct ModRefData { - pub span: Span, - pub scope: NodeId, - pub ref_id: Option, - pub qualname: String -} - -#[derive(Debug)] -pub struct StructData { - pub span: Span, - pub name: String, - pub id: NodeId, - pub ctor_id: NodeId, - pub qualname: String, - pub scope: NodeId, - pub value: String, - pub fields: Vec, - pub visibility: Visibility, - pub docs: String, - pub sig: Signature, - pub attributes: Vec, -} - -#[derive(Debug)] -pub struct StructVariantData { - pub span: Span, - pub name: String, - pub id: NodeId, - pub qualname: String, - pub type_value: String, - pub value: String, - pub scope: NodeId, - pub parent: Option, - pub docs: String, - pub sig: Signature, - pub attributes: Vec, -} - -#[derive(Debug)] -pub struct TraitData { - pub span: Span, - pub id: NodeId, - pub name: String, - pub qualname: String, - pub scope: NodeId, - pub value: String, - pub items: Vec, - pub visibility: Visibility, - pub docs: String, - pub sig: Signature, - pub attributes: Vec, -} - -#[derive(Debug)] -pub struct TupleVariantData { - pub span: Span, - pub id: NodeId, - pub name: String, - pub qualname: String, - pub type_value: String, - pub value: String, - pub scope: NodeId, - pub parent: Option, - pub docs: String, - pub sig: Signature, - pub attributes: Vec, -} - -/// Data for a typedef. -#[derive(Debug)] -pub struct TypeDefData { - pub id: NodeId, - pub name: String, - pub span: Span, - pub qualname: String, - pub value: String, - pub visibility: Visibility, - pub parent: Option, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -/// Data for a reference to a type or trait. -#[derive(Clone, Debug)] -pub struct TypeRefData { - pub span: Span, - pub scope: NodeId, - pub ref_id: Option, - pub qualname: String, -} - -#[derive(Debug)] -pub struct UseData { - pub id: NodeId, - pub span: Span, - pub name: String, - pub mod_id: Option, - pub scope: NodeId, - pub visibility: Visibility, -} - -#[derive(Debug)] -pub struct UseGlobData { - pub id: NodeId, - pub span: Span, - pub names: Vec, - pub scope: NodeId, - pub visibility: Visibility, -} - -/// Data for local and global variables (consts and statics). -#[derive(Debug)] -pub struct VariableData { - pub id: NodeId, - pub kind: VariableKind, - pub name: String, - pub qualname: String, - pub span: Span, - pub scope: NodeId, - pub parent: Option, - pub value: String, - pub type_value: String, - pub visibility: Visibility, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -#[derive(Debug)] -pub enum VariableKind { - Static, - Const, - Local, - Field, -} - -/// Data for the use of some item (e.g., the use of a local variable, which -/// will refer to that variables declaration (by ref_id)). -#[derive(Debug)] -pub struct VariableRefData { - pub name: String, - pub span: Span, - pub scope: NodeId, - pub ref_id: DefId, -} - - -/// Encodes information about the signature of a definition. This should have -/// enough information to create a nice display about a definition without -/// access to the source code. -#[derive(Clone, Debug)] -pub struct Signature { - pub span: Span, - pub text: String, - // These identify the main identifier for the defintion as byte offsets into - // `text`. E.g., of `foo` in `pub fn foo(...)` - pub ident_start: usize, - pub ident_end: usize, - pub defs: Vec, - pub refs: Vec, -} - -/// An element of a signature. `start` and `end` are byte offsets into the `text` -/// of the parent `Signature`. -#[derive(Clone, Debug)] -pub struct SigElement { - pub id: DefId, - pub start: usize, - pub end: usize, -} diff --git a/src/librustc_save_analysis/dump.rs b/src/librustc_save_analysis/dump.rs deleted file mode 100644 index 795ff58e20..0000000000 --- a/src/librustc_save_analysis/dump.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2012-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 super::external_data::*; - -use rls_data::CratePreludeData; - -pub trait Dump { - fn crate_prelude(&mut self, _: CratePreludeData) {} - fn enum_data(&mut self, _: EnumData) {} - fn extern_crate(&mut self, _: ExternCrateData) {} - fn impl_data(&mut self, _: ImplData) {} - fn inheritance(&mut self, _: InheritanceData) {} - fn function(&mut self, _: FunctionData) {} - fn function_ref(&mut self, _: FunctionRefData) {} - fn function_call(&mut self, _: FunctionCallData) {} - fn method(&mut self, _: MethodData) {} - fn method_call(&mut self, _: MethodCallData) {} - fn macro_data(&mut self, _: MacroData) {} - fn macro_use(&mut self, _: MacroUseData) {} - fn mod_data(&mut self, _: ModData) {} - fn mod_ref(&mut self, _: ModRefData) {} - fn struct_data(&mut self, _: StructData) {} - fn struct_variant(&mut self, _: StructVariantData) {} - fn trait_data(&mut self, _: TraitData) {} - fn tuple_variant(&mut self, _: TupleVariantData) {} - fn type_ref(&mut self, _: TypeRefData) {} - fn typedef(&mut self, _: TypeDefData) {} - fn use_data(&mut self, _: UseData) {} - fn use_glob(&mut self, _: UseGlobData) {} - fn variable(&mut self, _: VariableData) {} - fn variable_ref(&mut self, _: VariableRefData) {} -} diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index a95236e2a5..cc33d3db8e 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -8,10 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Write the output of rustc's analysis to an implementor of Dump. The data is -//! primarily designed to be used as input to the DXR tool, specifically its -//! Rust plugin. It could also be used by IDEs or other code browsing, search, or -//! cross-referencing tools. +//! Write the output of rustc's analysis to an implementor of Dump. //! //! Dumping the analysis is implemented by walking the AST and getting a bunch of //! info out from all over the place. We use Def IDs to identify objects. The @@ -27,16 +24,12 @@ //! is used for recording the output in a format-agnostic way (see CsvDumper //! for an example). -use rustc::hir; -use rustc::hir::def::Def; -use rustc::hir::def_id::{DefId, LOCAL_CRATE}; -use rustc::hir::map::{Node, NodeItem}; +use rustc::hir::def::Def as HirDef; +use rustc::hir::def_id::DefId; +use rustc::hir::map::Node; use rustc::session::Session; -use rustc::ty::{self, TyCtxt, AssociatedItemContainer}; +use rustc::ty::{self, TyCtxt}; -use std::collections::HashSet; -use std::collections::hash_map::DefaultHasher; -use std::hash::*; use std::path::Path; use syntax::ast::{self, NodeId, PatKind, Attribute, CRATE_NODE_ID}; @@ -48,14 +41,12 @@ use syntax::ptr::P; use syntax::codemap::Spanned; use syntax_pos::*; -use super::{escape, generated_code, SaveContext, PathCollector, docs_for_attrs}; -use super::data::*; -use super::dump::Dump; -use super::external_data::{Lower, make_def_id}; -use super::span_utils::SpanUtils; -use super::recorder; +use {escape, generated_code, SaveContext, PathCollector, docs_for_attrs, lower_attributes, Dump}; +use span_utils::SpanUtils; +use sig; -use rls_data::ExternalCrateData; +use rls_data::{CratePreludeData, Import, ImportKind, SpanData, Ref, RefKind, + Def, DefKind, Relation, RelationKind}; macro_rules! down_cast_data { ($id:ident, $kind:ident, $sp:expr) => { @@ -81,8 +72,7 @@ pub struct DumpVisitor<'l, 'tcx: 'l, 'll, D: 'll> { // of macro use (callsite) spans. We store these to ensure // we only write one macro def per unique macro definition, and // one macro use per unique callsite span. - mac_defs: HashSet, - mac_uses: HashSet, + // mac_defs: HashSet, } impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { @@ -97,8 +87,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { dumper: dumper, span: span_utils.clone(), cur_scope: CRATE_NODE_ID, - mac_defs: HashSet::new(), - mac_uses: HashSet::new(), + // mac_defs: HashSet::new(), } } @@ -126,6 +115,10 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { } } + fn span_from_span(&self, span: Span) -> SpanData { + self.save_ctxt.span_from_span(span) + } + pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) { let source_file = self.tcx.sess.local_crate_source_file.as_ref(); let crate_root = source_file.map(|source_file| { @@ -136,25 +129,14 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { } }); - // Info about all the external crates referenced from this crate. - let external_crates = self.save_ctxt.get_external_crates().into_iter().map(|c| { - let lo_loc = self.span.sess.codemap().lookup_char_pos(c.span.lo); - ExternalCrateData { - name: c.name, - num: c.number, - file_name: SpanUtils::make_path_string(&lo_loc.file.name), - } - }).collect(); - - // The current crate. let data = CratePreludeData { crate_name: name.into(), crate_root: crate_root.unwrap_or("".to_owned()), - external_crates: external_crates, - span: krate.span, + external_crates: self.save_ctxt.get_external_crates(), + span: self.span_from_span(krate.span), }; - self.dumper.crate_prelude(data.lower(self.tcx)); + self.dumper.crate_prelude(data); } // Return all non-empty prefixes of a path. @@ -210,13 +192,13 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { fn write_sub_paths(&mut self, path: &ast::Path) { let sub_paths = self.process_path_prefixes(path); - for (span, qualname) in sub_paths { - self.dumper.mod_ref(ModRefData { - span: span, - qualname: qualname, - scope: self.cur_scope, - ref_id: None - }.lower(self.tcx)); + for (span, _) in sub_paths { + let span = self.span_from_span(span); + self.dumper.dump_ref(Ref { + kind: RefKind::Mod, + span, + ref_id: ::null_id(), + }); } } @@ -229,13 +211,13 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { return; } - for (span, qualname) in sub_paths.into_iter().take(len - 1) { - self.dumper.mod_ref(ModRefData { - span: span, - qualname: qualname, - scope: self.cur_scope, - ref_id: None - }.lower(self.tcx)); + for (span, _) in sub_paths.into_iter().take(len - 1) { + let span = self.span_from_span(span); + self.dumper.dump_ref(Ref { + kind: RefKind::Mod, + span, + ref_id: ::null_id(), + }); } } @@ -250,32 +232,32 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { let sub_paths = &sub_paths[.. (len-1)]; // write the trait part of the sub-path - let (ref span, ref qualname) = sub_paths[len-2]; - self.dumper.type_ref(TypeRefData { - ref_id: None, - span: *span, - qualname: qualname.to_owned(), - scope: CRATE_NODE_ID - }.lower(self.tcx)); + let (ref span, _) = sub_paths[len-2]; + let span = self.span_from_span(*span); + self.dumper.dump_ref(Ref { + kind: RefKind::Type, + ref_id: ::null_id(), + span, + }); // write the other sub-paths if len <= 2 { return; } let sub_paths = &sub_paths[..len-2]; - for &(ref span, ref qualname) in sub_paths { - self.dumper.mod_ref(ModRefData { - span: *span, - qualname: qualname.to_owned(), - scope: self.cur_scope, - ref_id: None - }.lower(self.tcx)); + for &(ref span, _) in sub_paths { + let span = self.span_from_span(*span); + self.dumper.dump_ref(Ref { + kind: RefKind::Mod, + span, + ref_id: ::null_id(), + }); } } fn lookup_def_id(&self, ref_id: NodeId) -> Option { match self.save_ctxt.get_path_def(ref_id) { - Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => None, + HirDef::PrimTy(..) | HirDef::SelfTy(..) | HirDef::Err => None, def => Some(def.def_id()), } } @@ -284,67 +266,67 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { ref_id: NodeId, span: Span, sub_span: Option, - def_id: DefId, - scope: NodeId) { + def_id: DefId) { if self.span.filter_generated(sub_span, span) { return; } let def = self.save_ctxt.get_path_def(ref_id); match def { - Def::Mod(_) => { - self.dumper.mod_ref(ModRefData { - span: sub_span.expect("No span found for mod ref"), - ref_id: Some(def_id), - scope: scope, - qualname: String::new() - }.lower(self.tcx)); + HirDef::Mod(_) => { + let span = self.span_from_span(sub_span.expect("No span found for mod ref")); + self.dumper.dump_ref(Ref { + kind: RefKind::Mod, + span, + ref_id: ::id_from_def_id(def_id), + }); } - Def::Struct(..) | - Def::Variant(..) | - Def::Union(..) | - Def::Enum(..) | - Def::TyAlias(..) | - Def::Trait(_) => { - self.dumper.type_ref(TypeRefData { - span: sub_span.expect("No span found for type ref"), - ref_id: Some(def_id), - scope: scope, - qualname: String::new() - }.lower(self.tcx)); + HirDef::Struct(..) | + HirDef::Variant(..) | + HirDef::Union(..) | + HirDef::Enum(..) | + HirDef::TyAlias(..) | + HirDef::Trait(_) => { + let span = self.span_from_span(sub_span.expect("No span found for type ref")); + self.dumper.dump_ref(Ref { + kind: RefKind::Type, + span, + ref_id: ::id_from_def_id(def_id), + }); } - Def::Static(..) | - Def::Const(..) | - Def::StructCtor(..) | - Def::VariantCtor(..) => { - self.dumper.variable_ref(VariableRefData { - span: sub_span.expect("No span found for var ref"), - ref_id: def_id, - scope: scope, - name: String::new() - }.lower(self.tcx)); + HirDef::Static(..) | + HirDef::Const(..) | + HirDef::StructCtor(..) | + HirDef::VariantCtor(..) => { + let span = self.span_from_span(sub_span.expect("No span found for var ref")); + self.dumper.dump_ref(Ref { + kind: RefKind::Variable, + span, + ref_id: ::id_from_def_id(def_id), + }); } - Def::Fn(..) => { - self.dumper.function_ref(FunctionRefData { - span: sub_span.expect("No span found for fn ref"), - ref_id: def_id, - scope: scope - }.lower(self.tcx)); + HirDef::Fn(..) => { + let span = self.span_from_span(sub_span.expect("No span found for fn ref")); + self.dumper.dump_ref(Ref { + kind: RefKind::Function, + span, + ref_id: ::id_from_def_id(def_id), + }); } // With macros 2.0, we can legitimately get a ref to a macro, but // we don't handle it properly for now (FIXME). - Def::Macro(..) => {} - Def::Local(..) | - Def::Upvar(..) | - Def::SelfTy(..) | - Def::Label(_) | - Def::TyParam(..) | - Def::Method(..) | - Def::AssociatedTy(..) | - Def::AssociatedConst(..) | - Def::PrimTy(_) | - Def::GlobalAsm(_) | - Def::Err => { + HirDef::Macro(..) => {} + HirDef::Local(..) | + HirDef::Upvar(..) | + HirDef::SelfTy(..) | + HirDef::Label(_) | + HirDef::TyParam(..) | + HirDef::Method(..) | + HirDef::AssociatedTy(..) | + HirDef::AssociatedConst(..) | + HirDef::PrimTy(_) | + HirDef::GlobalAsm(_) | + HirDef::Err => { span_bug!(span, "process_def_kind for unexpected item: {:?}", def); @@ -367,21 +349,23 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { // variable name, but who knows?) let sub_span = span_utils.span_for_last_ident(p.span); if !self.span.filter_generated(sub_span, p.span) { - self.dumper.variable(VariableData { - id: id, - kind: VariableKind::Local, - span: sub_span.expect("No span found for variable"), + let id = ::id_from_node_id(id, &self.save_ctxt); + let span = self.span_from_span(sub_span.expect("No span found for variable")); + + self.dumper.dump_def(false, Def { + kind: DefKind::Local, + id, + span, name: path_to_string(p), qualname: format!("{}::{}", qualname, path_to_string(p)), - type_value: typ, - value: String::new(), - scope: CRATE_NODE_ID, + value: typ, parent: None, - visibility: Visibility::Inherited, + children: vec![], + decl_id: None, docs: String::new(), sig: None, - attributes: vec![], - }.lower(self.tcx)); + attributes:vec![], + }); } } } @@ -391,13 +375,12 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { sig: &'l ast::MethodSig, body: Option<&'l ast::Block>, id: ast::NodeId, - name: ast::Name, - vis: Visibility, - attrs: &'l [Attribute], + name: ast::Ident, + vis: ast::Visibility, span: Span) { debug!("process_method: {}:{}", id, name); - if let Some(method_data) = self.save_ctxt.get_method_data(id, name, span) { + if let Some(mut method_data) = self.save_ctxt.get_method_data(id, name.name, span) { let sig_str = ::make_signature(&sig.decl, &sig.generics); if body.is_some() { @@ -406,61 +389,11 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { }); } - // If the method is defined in an impl, then try and find the corresponding - // method decl in a trait, and if there is one, make a decl_id for it. This - // requires looking up the impl, then the trait, then searching for a method - // with the right name. - if !self.span.filter_generated(Some(method_data.span), span) { - let container = - self.tcx.associated_item(self.tcx.hir.local_def_id(id)).container; - let mut trait_id; - let mut decl_id = None; - match container { - AssociatedItemContainer::ImplContainer(id) => { - trait_id = self.tcx.trait_id_of_impl(id); - - match trait_id { - Some(id) => { - for item in self.tcx.associated_items(id) { - if item.kind == ty::AssociatedKind::Method { - if item.name == name { - decl_id = Some(item.def_id); - break; - } - } - } - } - None => { - if let Some(NodeItem(item)) = self.tcx.hir.get_if_local(id) { - if let hir::ItemImpl(_, _, _, _, _, ref ty, _) = item.node { - trait_id = self.lookup_def_id(ty.id); - } - } - } - } - } - AssociatedItemContainer::TraitContainer(id) => { - trait_id = Some(id); - } - } - - self.dumper.method(MethodData { - id: method_data.id, - name: method_data.name, - span: method_data.span, - scope: method_data.scope, - qualname: method_data.qualname.clone(), - value: sig_str, - decl_id: decl_id, - parent: trait_id, - visibility: vis, - docs: docs_for_attrs(attrs), - sig: method_data.sig, - attributes: attrs.to_vec(), - }.lower(self.tcx)); - } - self.process_generic_params(&sig.generics, span, &method_data.qualname, id); + + method_data.value = sig_str; + method_data.sig = sig::method_signature(id, name, sig, &self.save_ctxt); + self.dumper.dump_def(vis == ast::Visibility::Public, method_data); } // walk arg and return types @@ -479,22 +412,17 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { } fn process_trait_ref(&mut self, trait_ref: &'l ast::TraitRef) { - let trait_ref_data = self.save_ctxt.get_trait_ref_data(trait_ref, self.cur_scope); + let trait_ref_data = self.save_ctxt.get_trait_ref_data(trait_ref); if let Some(trait_ref_data) = trait_ref_data { - if !self.span.filter_generated(Some(trait_ref_data.span), trait_ref.path.span) { - self.dumper.type_ref(trait_ref_data.lower(self.tcx)); - } + self.dumper.dump_ref(trait_ref_data); } - self.process_path(trait_ref.ref_id, &trait_ref.path, Some(recorder::TypeRef)); + self.process_path(trait_ref.ref_id, &trait_ref.path); } fn process_struct_field_def(&mut self, field: &ast::StructField, parent_id: NodeId) { let field_data = self.save_ctxt.get_field_data(field, parent_id); - if let Some(mut field_data) = field_data { - if !self.span.filter_generated(Some(field_data.span), field.span) { - field_data.value = String::new(); - self.dumper.variable(field_data.lower(self.tcx)); - } + if let Some(field_data) = field_data { + self.dumper.dump_def(field.vis == ast::Visibility::Public, field_data); } } @@ -518,18 +446,23 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { name, id); if !self.span.filter_generated(Some(param_ss), full_span) { - self.dumper.typedef(TypeDefData { - span: param_ss, - name: name, - id: param.id, - qualname: qualname, + let id = ::id_from_node_id(param.id, &self.save_ctxt); + let span = self.span_from_span(param_ss); + + self.dumper.dump_def(false, Def { + kind: DefKind::Type, + id, + span, + name, + qualname, value: String::new(), - visibility: Visibility::Inherited, parent: None, + children: vec![], + decl_id: None, docs: String::new(), sig: None, attributes: vec![], - }.lower(self.tcx)); + }); } } self.visit_generics(generics); @@ -541,13 +474,10 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { ty_params: &'l ast::Generics, body: &'l ast::Block) { if let Some(fn_data) = self.save_ctxt.get_item_data(item) { - down_cast_data!(fn_data, FunctionData, item.span); - if !self.span.filter_generated(Some(fn_data.span), item.span) { - self.dumper.function(fn_data.clone().lower(self.tcx)); - } - + down_cast_data!(fn_data, DefData, item.span); self.nest_tables(item.id, |v| v.process_formals(&decl.inputs, &fn_data.qualname)); self.process_generic_params(ty_params, item.span, &fn_data.qualname, item.id); + self.dumper.dump_def(item.vis == ast::Visibility::Public, fn_data); } for arg in &decl.inputs { @@ -566,10 +496,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { typ: &'l ast::Ty, expr: &'l ast::Expr) { if let Some(var_data) = self.save_ctxt.get_item_data(item) { - down_cast_data!(var_data, VariableData, item.span); - if !self.span.filter_generated(Some(var_data.span), item.span) { - self.dumper.variable(var_data.lower(self.tcx)); - } + down_cast_data!(var_data, DefData, item.span); + self.dumper.dump_def(item.vis == ast::Visibility::Public, var_data); } self.visit_ty(&typ); self.visit_expr(expr); @@ -580,35 +508,40 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { name: ast::Name, span: Span, typ: &'l ast::Ty, - expr: &'l ast::Expr, + expr: Option<&'l ast::Expr>, parent_id: DefId, - vis: Visibility, + vis: ast::Visibility, attrs: &'l [Attribute]) { let qualname = format!("::{}", self.tcx.node_path_str(id)); let sub_span = self.span.sub_span_after_keyword(span, keywords::Const); if !self.span.filter_generated(sub_span, span) { - self.dumper.variable(VariableData { - span: sub_span.expect("No span found for variable"), - kind: VariableKind::Const, - id: id, + let sig = sig::assoc_const_signature(id, name, typ, expr, &self.save_ctxt); + let id = ::id_from_node_id(id, &self.save_ctxt); + let span = self.span_from_span(sub_span.expect("No span found for variable")); + + self.dumper.dump_def(vis == ast::Visibility::Public, Def { + kind: DefKind::Const, + id, + span, name: name.to_string(), - qualname: qualname, - value: self.span.snippet(expr.span), - type_value: ty_to_string(&typ), - scope: self.cur_scope, - parent: Some(parent_id), - visibility: vis, + qualname, + value: ty_to_string(&typ), + parent: Some(::id_from_def_id(parent_id)), + children: vec![], + decl_id: None, docs: docs_for_attrs(attrs), - sig: None, - attributes: attrs.to_vec(), - }.lower(self.tcx)); + sig, + attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt), + }); } // walk type and init value self.visit_ty(typ); - self.visit_expr(expr); + if let Some(expr) = expr { + self.visit_expr(expr); + } } // FIXME tuple structs should generate tuple-specific data. @@ -620,7 +553,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Struct); - let (val, fields) = + let (value, fields) = if let ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, _), _) = item.node { let fields_str = fields.iter() @@ -629,26 +562,28 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { .unwrap_or(i.to_string())) .collect::>() .join(", "); - (format!("{} {{ {} }}", name, fields_str), fields.iter().map(|f| f.id).collect()) + (format!("{} {{ {} }}", name, fields_str), + fields.iter().map(|f| ::id_from_node_id(f.id, &self.save_ctxt)).collect()) } else { (String::new(), vec![]) }; if !self.span.filter_generated(sub_span, item.span) { - self.dumper.struct_data(StructData { - span: sub_span.expect("No span found for struct"), - id: item.id, - name: name, - ctor_id: def.id(), + let span = self.span_from_span(sub_span.expect("No span found for struct")); + self.dumper.dump_def(item.vis == ast::Visibility::Public, Def { + kind: DefKind::Struct, + id: ::id_from_node_id(item.id, &self.save_ctxt), + span, + name, qualname: qualname.clone(), - scope: self.cur_scope, - value: val, - fields: fields, - visibility: From::from(&item.vis), + value, + parent: None, + children: fields, + decl_id: None, docs: docs_for_attrs(&item.attrs), - sig: self.save_ctxt.sig_base(item), - attributes: item.attrs.clone(), - }.lower(self.tcx)); + sig: sig::item_signature(item, &self.save_ctxt), + attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt), + }); } for field in def.fields() { @@ -668,10 +603,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { None => return, Some(data) => data, }; - down_cast_data!(enum_data, EnumData, item.span); - if !self.span.filter_generated(Some(enum_data.span), item.span) { - self.dumper.enum_data(enum_data.clone().lower(self.tcx)); - } + down_cast_data!(enum_data, DefData, item.span); for variant in &enum_definition.variants { let name = variant.node.name.name.to_string(); @@ -679,18 +611,6 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { qualname.push_str("::"); qualname.push_str(&name); - let text = self.span.signature_string_for_span(variant.span); - let ident_start = text.find(&name).unwrap(); - let ident_end = ident_start + name.len(); - let sig = Signature { - span: variant.span, - text: text, - ident_start: ident_start, - ident_end: ident_end, - defs: vec![], - refs: vec![], - }; - match variant.node.data { ast::VariantData::Struct(ref fields, _) => { let sub_span = self.span.span_for_first_ident(variant.span); @@ -700,48 +620,62 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { .unwrap_or(i.to_string())) .collect::>() .join(", "); - let val = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str); + let value = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str); if !self.span.filter_generated(sub_span, variant.span) { - self.dumper.struct_variant(StructVariantData { - span: sub_span.expect("No span found for struct variant"), - id: variant.node.data.id(), - name: name, - qualname: qualname, - type_value: enum_data.qualname.clone(), - value: val, - scope: enum_data.scope, - parent: Some(make_def_id(item.id, &self.tcx.hir)), + let span = self.span_from_span( + sub_span.expect("No span found for struct variant")); + let id = ::id_from_node_id(variant.node.data.id(), &self.save_ctxt); + let parent = Some(::id_from_node_id(item.id, &self.save_ctxt)); + + self.dumper.dump_def(item.vis == ast::Visibility::Public, Def { + kind: DefKind::Struct, + id, + span, + name, + qualname, + value, + parent, + children: vec![], + decl_id: None, docs: docs_for_attrs(&variant.node.attrs), - sig: sig, - attributes: variant.node.attrs.clone(), - }.lower(self.tcx)); + sig: sig::variant_signature(variant, &self.save_ctxt), + attributes: lower_attributes(variant.node.attrs.clone(), + &self.save_ctxt), + }); } } ref v => { let sub_span = self.span.span_for_first_ident(variant.span); - let mut val = format!("{}::{}", enum_data.name, name); + let mut value = format!("{}::{}", enum_data.name, name); if let &ast::VariantData::Tuple(ref fields, _) = v { - val.push('('); - val.push_str(&fields.iter() - .map(|f| ty_to_string(&f.ty)) - .collect::>() - .join(", ")); - val.push(')'); + value.push('('); + value.push_str(&fields.iter() + .map(|f| ty_to_string(&f.ty)) + .collect::>() + .join(", ")); + value.push(')'); } if !self.span.filter_generated(sub_span, variant.span) { - self.dumper.tuple_variant(TupleVariantData { - span: sub_span.expect("No span found for tuple variant"), - id: variant.node.data.id(), - name: name, - qualname: qualname, - type_value: enum_data.qualname.clone(), - value: val, - scope: enum_data.scope, - parent: Some(make_def_id(item.id, &self.tcx.hir)), + let span = + self.span_from_span(sub_span.expect("No span found for tuple variant")); + let id = ::id_from_node_id(variant.node.data.id(), &self.save_ctxt); + let parent = Some(::id_from_node_id(item.id, &self.save_ctxt)); + + self.dumper.dump_def(item.vis == ast::Visibility::Public, Def { + kind: DefKind::Tuple, + id, + span, + name, + qualname, + value, + parent, + children: vec![], + decl_id: None, docs: docs_for_attrs(&variant.node.attrs), - sig: sig, - attributes: variant.node.attrs.clone(), - }.lower(self.tcx)); + sig: sig::variant_signature(variant, &self.save_ctxt), + attributes: lower_attributes(variant.node.attrs.clone(), + &self.save_ctxt), + }); } } } @@ -752,7 +686,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { self.visit_ty(&field.ty); } } - self.process_generic_params(ty_params, item.span, &enum_data.qualname, enum_data.id); + self.process_generic_params(ty_params, item.span, &enum_data.qualname, item.id); + self.dumper.dump_def(item.vis == ast::Visibility::Public, enum_data); } fn process_impl(&mut self, @@ -762,25 +697,17 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { typ: &'l ast::Ty, impl_items: &'l [ast::ImplItem]) { if let Some(impl_data) = self.save_ctxt.get_item_data(item) { - down_cast_data!(impl_data, ImplData, item.span); - if !self.span.filter_generated(Some(impl_data.span), item.span) { - self.dumper.impl_data(ImplData { - id: impl_data.id, - span: impl_data.span, - scope: impl_data.scope, - trait_ref: impl_data.trait_ref.map(|d| d.ref_id.unwrap()), - self_ref: impl_data.self_ref.map(|d| d.ref_id.unwrap()) - }.lower(self.tcx)); - } + down_cast_data!(impl_data, RelationData, item.span); + self.dumper.dump_relation(impl_data); } self.visit_ty(&typ); if let &Some(ref trait_ref) = trait_ref { - self.process_path(trait_ref.ref_id, &trait_ref.path, Some(recorder::TypeRef)); + self.process_path(trait_ref.ref_id, &trait_ref.path); } self.process_generic_params(type_parameters, item.span, "", item.id); for impl_item in impl_items { let map = &self.tcx.hir; - self.process_impl_item(impl_item, make_def_id(item.id, map)); + self.process_impl_item(impl_item, map.local_def_id(item.id)); } } @@ -801,19 +728,24 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { } let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Trait); if !self.span.filter_generated(sub_span, item.span) { - self.dumper.trait_data(TraitData { - span: sub_span.expect("No span found for trait"), - id: item.id, - name: name, + let id = ::id_from_node_id(item.id, &self.save_ctxt); + let span = self.span_from_span(sub_span.expect("No span found for trait")); + let children = + methods.iter().map(|i| ::id_from_node_id(i.id, &self.save_ctxt)).collect(); + self.dumper.dump_def(item.vis == ast::Visibility::Public, Def { + kind: DefKind::Trait, + id, + span, + name, qualname: qualname.clone(), - scope: self.cur_scope, value: val, - items: methods.iter().map(|i| i.id).collect(), - visibility: From::from(&item.vis), + parent: None, + children, + decl_id: None, docs: docs_for_attrs(&item.attrs), - sig: self.save_ctxt.sig_base(item), - attributes: item.attrs.clone(), - }.lower(self.tcx)); + sig: sig::item_signature(item, &self.save_ctxt), + attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt), + }); } // super-traits @@ -831,21 +763,22 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { if let Some(id) = self.lookup_def_id(trait_ref.ref_id) { let sub_span = self.span.sub_span_for_type_name(trait_ref.path.span); if !self.span.filter_generated(sub_span, trait_ref.path.span) { - self.dumper.type_ref(TypeRefData { - span: sub_span.expect("No span found for trait ref"), - ref_id: Some(id), - scope: self.cur_scope, - qualname: String::new() - }.lower(self.tcx)); + let span = self.span_from_span(sub_span.expect("No span found for trait ref")); + self.dumper.dump_ref(Ref { + kind: RefKind::Type, + span, + ref_id: ::id_from_def_id(id), + }); } if !self.span.filter_generated(sub_span, trait_ref.path.span) { - let sub_span = sub_span.expect("No span for inheritance"); - self.dumper.inheritance(InheritanceData { + let sub_span = self.span_from_span(sub_span.expect("No span for inheritance")); + self.dumper.dump_relation(Relation { + kind: RelationKind::SuperTrait, span: sub_span, - base_id: id, - deriv_id: item.id - }.lower(self.tcx)); + from: ::id_from_def_id(id), + to: ::id_from_node_id(item.id, &self.save_ctxt), + }); } } } @@ -854,21 +787,19 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { self.process_generic_params(generics, item.span, &qualname, item.id); for method in methods { let map = &self.tcx.hir; - self.process_trait_item(method, make_def_id(item.id, map)) + self.process_trait_item(method, map.local_def_id(item.id)) } } // `item` is the module in question, represented as an item. fn process_mod(&mut self, item: &ast::Item) { if let Some(mod_data) = self.save_ctxt.get_item_data(item) { - down_cast_data!(mod_data, ModData, item.span); - if !self.span.filter_generated(Some(mod_data.span), item.span) { - self.dumper.mod_data(mod_data.lower(self.tcx)); - } + down_cast_data!(mod_data, DefData, item.span); + self.dumper.dump_def(item.vis == ast::Visibility::Public, mod_data); } } - fn process_path(&mut self, id: NodeId, path: &ast::Path, ref_kind: Option) { + fn process_path(&mut self, id: NodeId, path: &ast::Path) { let path_data = self.save_ctxt.get_path_data(id, path); if generated_code(path.span) && path_data.is_none() { return; @@ -881,81 +812,29 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { } }; - match path_data { - Data::VariableRefData(vrd) => { - // FIXME: this whole block duplicates the code in process_def_kind - if !self.span.filter_generated(Some(vrd.span), path.span) { - match ref_kind { - Some(recorder::TypeRef) => { - self.dumper.type_ref(TypeRefData { - span: vrd.span, - ref_id: Some(vrd.ref_id), - scope: vrd.scope, - qualname: String::new() - }.lower(self.tcx)); - } - Some(recorder::FnRef) => { - self.dumper.function_ref(FunctionRefData { - span: vrd.span, - ref_id: vrd.ref_id, - scope: vrd.scope - }.lower(self.tcx)); - } - Some(recorder::ModRef) => { - self.dumper.mod_ref( ModRefData { - span: vrd.span, - ref_id: Some(vrd.ref_id), - scope: vrd.scope, - qualname: String::new() - }.lower(self.tcx)); - } - Some(recorder::VarRef) | None - => self.dumper.variable_ref(vrd.lower(self.tcx)) - } - } - - } - Data::TypeRefData(trd) => { - if !self.span.filter_generated(Some(trd.span), path.span) { - self.dumper.type_ref(trd.lower(self.tcx)); - } - } - Data::MethodCallData(mcd) => { - if !self.span.filter_generated(Some(mcd.span), path.span) { - self.dumper.method_call(mcd.lower(self.tcx)); - } - } - Data::FunctionCallData(fcd) => { - if !self.span.filter_generated(Some(fcd.span), path.span) { - self.dumper.function_call(fcd.lower(self.tcx)); - } - } - _ => { - span_bug!(path.span, "Unexpected data: {:?}", path_data); - } - } + self.dumper.dump_ref(path_data); // Modules or types in the path prefix. match self.save_ctxt.get_path_def(id) { - Def::Method(did) => { + HirDef::Method(did) => { let ti = self.tcx.associated_item(did); if ti.kind == ty::AssociatedKind::Method && ti.method_has_self_argument { self.write_sub_path_trait_truncated(path); } } - Def::Fn(..) | - Def::Const(..) | - Def::Static(..) | - Def::StructCtor(..) | - Def::VariantCtor(..) | - Def::AssociatedConst(..) | - Def::Local(..) | - Def::Upvar(..) | - Def::Struct(..) | - Def::Union(..) | - Def::Variant(..) | - Def::TyAlias(..) | - Def::AssociatedTy(..) => self.write_sub_paths_truncated(path), + HirDef::Fn(..) | + HirDef::Const(..) | + HirDef::Static(..) | + HirDef::StructCtor(..) | + HirDef::VariantCtor(..) | + HirDef::AssociatedConst(..) | + HirDef::Local(..) | + HirDef::Upvar(..) | + HirDef::Struct(..) | + HirDef::Union(..) | + HirDef::Variant(..) | + HirDef::TyAlias(..) | + HirDef::AssociatedTy(..) => self.write_sub_paths_truncated(path), _ => {} } } @@ -969,20 +848,15 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { self.write_sub_paths_truncated(path); if let Some(struct_lit_data) = self.save_ctxt.get_expr_data(ex) { - down_cast_data!(struct_lit_data, TypeRefData, ex.span); - if !self.span.filter_generated(Some(struct_lit_data.span), ex.span) { - self.dumper.type_ref(struct_lit_data.lower(self.tcx)); + down_cast_data!(struct_lit_data, RefData, ex.span); + if !generated_code(ex.span) { + self.dumper.dump_ref(struct_lit_data); } - let scope = self.save_ctxt.enclosing_scope(ex.id); - for field in fields { if let Some(field_data) = self.save_ctxt - .get_field_ref_data(field, variant, scope) { - - if !self.span.filter_generated(Some(field_data.span), field.ident.span) { - self.dumper.variable_ref(field_data.lower(self.tcx)); - } + .get_field_ref_data(field, variant) { + self.dumper.dump_ref(field_data); } self.visit_expr(&field.expr) @@ -994,9 +868,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { fn process_method_call(&mut self, ex: &'l ast::Expr, args: &'l [P]) { if let Some(mcd) = self.save_ctxt.get_expr_data(ex) { - down_cast_data!(mcd, MethodCallData, ex.span); - if !self.span.filter_generated(Some(mcd.span), ex.span) { - self.dumper.method_call(mcd.lower(self.tcx)); + down_cast_data!(mcd, RefData, ex.span); + if !generated_code(ex.span) { + self.dumper.dump_ref(mcd); } } @@ -1021,12 +895,13 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { let sub_span = self.span.span_for_first_ident(span); if let Some(f) = variant.find_field_named(field.ident.name) { if !self.span.filter_generated(sub_span, span) { - self.dumper.variable_ref(VariableRefData { - span: sub_span.expect("No span fund for var ref"), - ref_id: f.did, - scope: self.cur_scope, - name: String::new() - }.lower(self.tcx)); + let span = + self.span_from_span(sub_span.expect("No span fund for var ref")); + self.dumper.dump_ref(Ref { + kind: RefKind::Variable, + span, + ref_id: ::id_from_def_id(f.did), + }); } } self.visit_pat(&field.pat); @@ -1044,7 +919,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { collector.visit_pat(&p); self.visit_pat(&p); - for &(id, ref p, immut, _) in &collector.collected_paths { + for &(id, ref p, immut) in &collector.collected_paths { let mut value = match immut { ast::Mutability::Immutable => value.to_string(), _ => String::new(), @@ -1066,21 +941,24 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { let sub_span = self.span.span_for_last_ident(p.span); // Rust uses the id of the pattern for var lookups, so we'll use it too. if !self.span.filter_generated(sub_span, p.span) { - self.dumper.variable(VariableData { - span: sub_span.expect("No span found for variable"), - kind: VariableKind::Local, - id: id, + let qualname = format!("{}${}", path_to_string(p), id); + let id = ::id_from_node_id(id, &self.save_ctxt); + let span = self.span_from_span(sub_span.expect("No span found for variable")); + + self.dumper.dump_def(false, Def { + kind: DefKind::Local, + id, + span, name: path_to_string(p), - qualname: format!("{}${}", path_to_string(p), id), - value: value, - type_value: typ, - scope: CRATE_NODE_ID, + qualname, + value: typ, parent: None, - visibility: Visibility::Inherited, + children: vec![], + decl_id: None, docs: String::new(), sig: None, - attributes: vec![], - }.lower(self.tcx)); + attributes:vec![], + }); } } } @@ -1092,119 +970,120 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { /// If the span is not macro-generated, do nothing, else use callee and /// callsite spans to record macro definition and use data, using the /// mac_uses and mac_defs sets to prevent multiples. - fn process_macro_use(&mut self, span: Span, id: NodeId) { - let data = match self.save_ctxt.get_macro_use_data(span, id) { + fn process_macro_use(&mut self, span: Span) { + let data = match self.save_ctxt.get_macro_use_data(span) { None => return, Some(data) => data, }; - let mut hasher = DefaultHasher::new(); - data.callee_span.hash(&mut hasher); - let hash = hasher.finish(); - let qualname = format!("{}::{}", data.name, hash); + + // FIXME write the macro def + // let mut hasher = DefaultHasher::new(); + // data.callee_span.hash(&mut hasher); + // let hash = hasher.finish(); + // let qualname = format!("{}::{}", data.name, hash); // Don't write macro definition for imported macros - if !self.mac_defs.contains(&data.callee_span) - && !data.imported { - self.mac_defs.insert(data.callee_span); - if let Some(sub_span) = self.span.span_for_macro_def_name(data.callee_span) { - self.dumper.macro_data(MacroData { - span: sub_span, - name: data.name.clone(), - qualname: qualname.clone(), - // FIXME where do macro docs come from? - docs: String::new(), - }.lower(self.tcx)); - } - } - if !self.mac_uses.contains(&data.span) { - self.mac_uses.insert(data.span); - if let Some(sub_span) = self.span.span_for_macro_use_name(data.span) { - self.dumper.macro_use(MacroUseData { - span: sub_span, - name: data.name, - qualname: qualname, - scope: data.scope, - callee_span: data.callee_span, - imported: data.imported, - }.lower(self.tcx)); - } - } + // if !self.mac_defs.contains(&data.callee_span) + // && !data.imported { + // self.mac_defs.insert(data.callee_span); + // if let Some(sub_span) = self.span.span_for_macro_def_name(data.callee_span) { + // self.dumper.macro_data(MacroData { + // span: sub_span, + // name: data.name.clone(), + // qualname: qualname.clone(), + // // FIXME where do macro docs come from? + // docs: String::new(), + // }.lower(self.tcx)); + // } + // } + self.dumper.macro_use(data); } fn process_trait_item(&mut self, trait_item: &'l ast::TraitItem, trait_id: DefId) { - self.process_macro_use(trait_item.span, trait_item.id); + self.process_macro_use(trait_item.span); match trait_item.node { - ast::TraitItemKind::Const(ref ty, Some(ref expr)) => { + ast::TraitItemKind::Const(ref ty, ref expr) => { self.process_assoc_const(trait_item.id, trait_item.ident.name, trait_item.span, &ty, - &expr, + expr.as_ref().map(|e| &**e), trait_id, - Visibility::Public, + ast::Visibility::Public, &trait_item.attrs); } ast::TraitItemKind::Method(ref sig, ref body) => { self.process_method(sig, body.as_ref().map(|x| &**x), trait_item.id, - trait_item.ident.name, - Visibility::Public, - &trait_item.attrs, + trait_item.ident, + ast::Visibility::Public, trait_item.span); } - ast::TraitItemKind::Type(ref _bounds, ref default_ty) => { + ast::TraitItemKind::Type(ref bounds, ref default_ty) => { // FIXME do something with _bounds (for type refs) let name = trait_item.ident.name.to_string(); let qualname = format!("::{}", self.tcx.node_path_str(trait_item.id)); let sub_span = self.span.sub_span_after_keyword(trait_item.span, keywords::Type); if !self.span.filter_generated(sub_span, trait_item.span) { - self.dumper.typedef(TypeDefData { - span: sub_span.expect("No span found for assoc type"), - name: name, - id: trait_item.id, - qualname: qualname, + let span = self.span_from_span(sub_span.expect("No span found for assoc type")); + let id = ::id_from_node_id(trait_item.id, &self.save_ctxt); + + self.dumper.dump_def(true, Def { + kind: DefKind::Type, + id, + span, + name, + qualname, value: self.span.snippet(trait_item.span), - visibility: Visibility::Public, - parent: Some(trait_id), + parent: Some(::id_from_def_id(trait_id)), + children: vec![], + decl_id: None, docs: docs_for_attrs(&trait_item.attrs), - sig: None, - attributes: trait_item.attrs.clone(), - }.lower(self.tcx)); + sig: sig::assoc_type_signature(trait_item.id, + trait_item.ident, + Some(bounds), + default_ty.as_ref().map(|ty| &**ty), + &self.save_ctxt), + attributes: lower_attributes(trait_item.attrs.clone(), &self.save_ctxt), + }); } if let &Some(ref default_ty) = default_ty { self.visit_ty(default_ty) } } - ast::TraitItemKind::Const(ref ty, None) => self.visit_ty(ty), ast::TraitItemKind::Macro(_) => {} } } fn process_impl_item(&mut self, impl_item: &'l ast::ImplItem, impl_id: DefId) { - self.process_macro_use(impl_item.span, impl_item.id); + self.process_macro_use(impl_item.span); match impl_item.node { ast::ImplItemKind::Const(ref ty, ref expr) => { self.process_assoc_const(impl_item.id, impl_item.ident.name, impl_item.span, &ty, - &expr, + Some(expr), impl_id, - From::from(&impl_item.vis), + impl_item.vis.clone(), &impl_item.attrs); } ast::ImplItemKind::Method(ref sig, ref body) => { self.process_method(sig, Some(body), impl_item.id, - impl_item.ident.name, - From::from(&impl_item.vis), - &impl_item.attrs, + impl_item.ident, + impl_item.vis.clone(), impl_item.span); } - ast::ImplItemKind::Type(ref ty) => self.visit_ty(ty), + ast::ImplItemKind::Type(ref ty) => { + // FIXME uses of the assoc type should ideally point to this + // 'def' and the name here should be a ref to the def in the + // trait. + self.visit_ty(ty) + } ast::ImplItemKind::Macro(_) => {} } } @@ -1220,25 +1099,30 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, let cm = self.tcx.sess.codemap(); let filename = cm.span_to_filename(span); - self.dumper.mod_data(ModData { - id: id, + let data_id = ::id_from_node_id(id, &self.save_ctxt); + let children = m.items.iter().map(|i| ::id_from_node_id(i.id, &self.save_ctxt)).collect(); + let span = self.span_from_span(span); + + self.dumper.dump_def(true, Def { + kind: DefKind::Mod, + id: data_id, name: String::new(), - qualname: qualname, - span: span, - scope: id, - filename: filename, - items: m.items.iter().map(|i| i.id).collect(), - visibility: Visibility::Public, + qualname, + span, + value: filename, + children, + parent: None, + decl_id: None, docs: docs_for_attrs(attrs), sig: None, - attributes: attrs.to_owned(), - }.lower(self.tcx)); + attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt), + }); self.nest_scope(id, |v| visit::walk_mod(v, m)); } fn visit_item(&mut self, item: &'l ast::Item) { use syntax::ast::ItemKind::*; - self.process_macro_use(item.span, item.id); + self.process_macro_use(item.span); match item.node { Use(ref use_item) => { match use_item.node { @@ -1246,9 +1130,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, let sub_span = self.span.span_for_last_ident(path.span); let mod_id = match self.lookup_def_id(item.id) { Some(def_id) => { - let scope = self.cur_scope; - self.process_def_kind(item.id, path.span, sub_span, def_id, scope); - + self.process_def_kind(item.id, path.span, sub_span, def_id); Some(def_id) } None => None, @@ -1263,14 +1145,15 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, }; if !self.span.filter_generated(sub_span, path.span) { - self.dumper.use_data(UseData { - span: sub_span.expect("No span found for use"), - id: item.id, - mod_id: mod_id, + let span = + self.span_from_span(sub_span.expect("No span found for use")); + self.dumper.import(item.vis == ast::Visibility::Public, Import { + kind: ImportKind::Use, + ref_id: mod_id.map(|id| ::id_from_def_id(id)), + span, name: ident.to_string(), - scope: self.cur_scope, - visibility: From::from(&item.vis), - }.lower(self.tcx)); + value: String::new(), + }); } self.write_sub_paths_truncated(path); } @@ -1288,23 +1171,24 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, let sub_span = self.span .sub_span_of_token(item.span, token::BinOp(token::Star)); if !self.span.filter_generated(sub_span, item.span) { - self.dumper.use_glob(UseGlobData { - span: sub_span.expect("No span found for use glob"), - id: item.id, - names: names, - scope: self.cur_scope, - visibility: From::from(&item.vis), - }.lower(self.tcx)); + let span = + self.span_from_span(sub_span.expect("No span found for use glob")); + self.dumper.import(item.vis == ast::Visibility::Public, Import { + kind: ImportKind::GlobUse, + ref_id: None, + span, + name: "*".to_owned(), + value: names.join(", "), + }); } self.write_sub_paths(path); } ast::ViewPathList(ref path, ref list) => { for plid in list { - let scope = self.cur_scope; let id = plid.node.id; if let Some(def_id) = self.lookup_def_id(id) { let span = plid.span; - self.process_def_kind(id, span, Some(span), def_id, scope); + self.process_def_kind(id, span, Some(span), def_id); } } @@ -1312,26 +1196,19 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, } } } - ExternCrate(ref s) => { - let location = match *s { - Some(s) => s.to_string(), - None => item.ident.to_string(), - }; + ExternCrate(_) => { let alias_span = self.span.span_for_last_ident(item.span); - let cnum = match self.sess.cstore.extern_mod_stmt_cnum(item.id) { - Some(cnum) => cnum, - None => LOCAL_CRATE, - }; if !self.span.filter_generated(alias_span, item.span) { - self.dumper.extern_crate(ExternCrateData { - id: item.id, + let span = + self.span_from_span(alias_span.expect("No span found for extern crate")); + self.dumper.import(false, Import { + kind: ImportKind::ExternCrate, + ref_id: None, + span, name: item.ident.to_string(), - crate_num: cnum, - location: location, - span: alias_span.expect("No span found for extern crate"), - scope: self.cur_scope, - }.lower(self.tcx)); + value: String::new(), + }); } } Fn(ref decl, .., ref ty_params, ref body) => @@ -1360,18 +1237,23 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, let value = ty_to_string(&ty); let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Type); if !self.span.filter_generated(sub_span, item.span) { - self.dumper.typedef(TypeDefData { - span: sub_span.expect("No span found for typedef"), + let span = self.span_from_span(sub_span.expect("No span found for typedef")); + let id = ::id_from_node_id(item.id, &self.save_ctxt); + + self.dumper.dump_def(item.vis == ast::Visibility::Public, Def { + kind: DefKind::Type, + id, + span, name: item.ident.to_string(), - id: item.id, qualname: qualname.clone(), - value: value, - visibility: From::from(&item.vis), + value, parent: None, + children: vec![], + decl_id: None, docs: docs_for_attrs(&item.attrs), - sig: Some(self.save_ctxt.sig_base(item)), - attributes: item.attrs.clone(), - }.lower(self.tcx)); + sig: sig::item_signature(item, &self.save_ctxt), + attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt), + }); } self.visit_ty(&ty); @@ -1396,7 +1278,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, } fn visit_ty(&mut self, t: &'l ast::Ty) { - self.process_macro_use(t.span, t.id); + self.process_macro_use(t.span); match t.node { ast::TyKind::Path(_, ref path) => { if generated_code(t.span) { @@ -1405,12 +1287,12 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, if let Some(id) = self.lookup_def_id(t.id) { if let Some(sub_span) = self.span.sub_span_for_type_name(t.span) { - self.dumper.type_ref(TypeRefData { - span: sub_span, - ref_id: Some(id), - scope: self.cur_scope, - qualname: String::new() - }.lower(self.tcx)); + let span = self.span_from_span(sub_span); + self.dumper.dump_ref(Ref { + kind: RefKind::Type, + span, + ref_id: ::id_from_def_id(id), + }); } } @@ -1427,7 +1309,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, fn visit_expr(&mut self, ex: &'l ast::Expr) { debug!("visit_expr {:?}", ex.node); - self.process_macro_use(ex.span, ex.id); + self.process_macro_use(ex.span); match ex.node { ast::ExprKind::Struct(ref path, ref fields, ref base) => { let hir_expr = self.save_ctxt.tcx.hir.expect_expr(ex.id); @@ -1446,9 +1328,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, self.visit_expr(&sub_ex); if let Some(field_data) = self.save_ctxt.get_expr_data(ex) { - down_cast_data!(field_data, VariableRefData, ex.span); - if !self.span.filter_generated(Some(field_data.span), ex.span) { - self.dumper.variable_ref(field_data.lower(self.tcx)); + down_cast_data!(field_data, RefData, ex.span); + if !generated_code(ex.span) { + self.dumper.dump_ref(field_data); } } } @@ -1474,12 +1356,13 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, ty::TyAdt(def, _) => { let sub_span = self.span.sub_span_after_token(ex.span, token::Dot); if !self.span.filter_generated(sub_span, ex.span) { - self.dumper.variable_ref(VariableRefData { - span: sub_span.expect("No span found for var ref"), - ref_id: def.struct_variant().fields[idx.node].did, - scope: self.cur_scope, - name: String::new() - }.lower(self.tcx)); + let span = + self.span_from_span(sub_span.expect("No span found for var ref")); + self.dumper.dump_ref(Ref { + kind: RefKind::Variable, + span: span, + ref_id: ::id_from_def_id(def.struct_variant().fields[idx.node].did), + }); } } ty::TyTuple(..) => {} @@ -1540,7 +1423,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, } fn visit_pat(&mut self, p: &'l ast::Pat) { - self.process_macro_use(p.span, p.id); + self.process_macro_use(p.span); self.process_pat(p); } @@ -1556,9 +1439,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, let mut paths_to_process = vec![]; // process collected paths - for &(id, ref p, immut, ref_kind) in &collector.collected_paths { + for &(id, ref p, immut) in &collector.collected_paths { match self.save_ctxt.get_path_def(id) { - Def::Local(def_id) => { + HirDef::Local(def_id) => { let id = self.tcx.hir.as_local_node_id(def_id).unwrap(); let mut value = if immut == ast::Mutability::Immutable { self.span.snippet(p.span).to_string() @@ -1573,53 +1456,56 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, assert!(p.segments.len() == 1, "qualified path for local variable def in arm"); if !self.span.filter_generated(Some(p.span), p.span) { - self.dumper.variable(VariableData { - span: p.span, - kind: VariableKind::Local, - id: id, + let qualname = format!("{}${}", path_to_string(p), id); + let id = ::id_from_node_id(id, &self.save_ctxt); + let span = self.span_from_span(p.span); + + self.dumper.dump_def(false, Def { + kind: DefKind::Local, + id, + span, name: path_to_string(p), - qualname: format!("{}${}", path_to_string(p), id), - value: value, - type_value: typ, - scope: CRATE_NODE_ID, + qualname, + value: typ, parent: None, - visibility: Visibility::Inherited, + children: vec![], + decl_id: None, docs: String::new(), sig: None, - attributes: vec![], - }.lower(self.tcx)); + attributes:vec![], + }); } } - Def::StructCtor(..) | Def::VariantCtor(..) | - Def::Const(..) | Def::AssociatedConst(..) | - Def::Struct(..) | Def::Variant(..) | - Def::TyAlias(..) | Def::AssociatedTy(..) | - Def::SelfTy(..) => { - paths_to_process.push((id, p.clone(), Some(ref_kind))) + HirDef::StructCtor(..) | HirDef::VariantCtor(..) | + HirDef::Const(..) | HirDef::AssociatedConst(..) | + HirDef::Struct(..) | HirDef::Variant(..) | + HirDef::TyAlias(..) | HirDef::AssociatedTy(..) | + HirDef::SelfTy(..) => { + paths_to_process.push((id, p.clone())) } def => error!("unexpected definition kind when processing collected paths: {:?}", def), } } - for &(id, ref path, ref_kind) in &paths_to_process { - self.process_path(id, path, ref_kind); + for &(id, ref path) in &paths_to_process { + self.process_path(id, path); } walk_list!(self, visit_expr, &arm.guard); self.visit_expr(&arm.body); } fn visit_path(&mut self, p: &'l ast::Path, id: NodeId) { - self.process_path(id, p, None); + self.process_path(id, p); } fn visit_stmt(&mut self, s: &'l ast::Stmt) { - self.process_macro_use(s.span, s.id); + self.process_macro_use(s.span); visit::walk_stmt(self, s) } fn visit_local(&mut self, l: &'l ast::Local) { - self.process_macro_use(l.span, l.id); + self.process_macro_use(l.span); let value = l.init.as_ref().map(|i| self.span.snippet(i.span)).unwrap_or(String::new()); self.process_var_decl(&l.pat, value); @@ -1632,14 +1518,12 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, match item.node { ast::ForeignItemKind::Fn(ref decl, ref generics) => { if let Some(fn_data) = self.save_ctxt.get_extern_item_data(item) { - down_cast_data!(fn_data, FunctionData, item.span); - if !self.span.filter_generated(Some(fn_data.span), item.span) { - self.dumper.function(fn_data.clone().lower(self.tcx)); - } + down_cast_data!(fn_data, DefData, item.span); self.nest_tables(item.id, |v| v.process_formals(&decl.inputs, &fn_data.qualname)); self.process_generic_params(generics, item.span, &fn_data.qualname, item.id); + self.dumper.dump_def(item.vis == ast::Visibility::Public, fn_data); } for arg in &decl.inputs { @@ -1652,10 +1536,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, } ast::ForeignItemKind::Static(ref ty, _) => { if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) { - down_cast_data!(var_data, VariableData, item.span); - if !self.span.filter_generated(Some(var_data.span), item.span) { - self.dumper.variable(var_data.lower(self.tcx)); - } + down_cast_data!(var_data, DefData, item.span); + self.dumper.dump_def(item.vis == ast::Visibility::Public, var_data); } self.visit_ty(ty); diff --git a/src/librustc_save_analysis/external_data.rs b/src/librustc_save_analysis/external_data.rs deleted file mode 100644 index 02441a0587..0000000000 --- a/src/librustc_save_analysis/external_data.rs +++ /dev/null @@ -1,775 +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. - -use rustc::hir::def_id::{CrateNum, DefId, DefIndex}; -use rustc::hir::map::Map; -use rustc::ty::TyCtxt; -use syntax::ast::{self, NodeId}; -use syntax::codemap::CodeMap; -use syntax::print::pprust; -use syntax_pos::Span; - -use data::{self, Visibility, SigElement}; - -use rls_data::{SpanData, CratePreludeData, Attribute}; -use rls_span::{Column, Row}; - -// FIXME: this should be pub(crate), but the current snapshot doesn't allow it yet -pub trait Lower { - type Target; - fn lower(self, tcx: TyCtxt) -> Self::Target; -} - -pub fn make_def_id(id: NodeId, map: &Map) -> DefId { - map.opt_local_def_id(id).unwrap_or(null_def_id()) -} - -pub fn null_def_id() -> DefId { - DefId { - krate: CrateNum::from_u32(u32::max_value()), - index: DefIndex::from_u32(u32::max_value()) - } -} - -pub fn span_from_span(span: Span, cm: &CodeMap) -> SpanData { - let start = cm.lookup_char_pos(span.lo); - let end = cm.lookup_char_pos(span.hi); - - SpanData { - file_name: start.file.name.clone().into(), - byte_start: span.lo.0, - byte_end: span.hi.0, - line_start: Row::new_one_indexed(start.line as u32), - line_end: Row::new_one_indexed(end.line as u32), - column_start: Column::new_one_indexed(start.col.0 as u32 + 1), - column_end: Column::new_one_indexed(end.col.0 as u32 + 1), - } -} - -impl Lower for Vec { - type Target = Vec; - - fn lower(self, tcx: TyCtxt) -> Vec { - self.into_iter() - // Only retain real attributes. Doc comments are lowered separately. - .filter(|attr| attr.path != "doc") - .map(|mut attr| { - // Remove the surrounding '#[..]' or '#![..]' of the pretty printed - // attribute. First normalize all inner attribute (#![..]) to outer - // ones (#[..]), then remove the two leading and the one trailing character. - attr.style = ast::AttrStyle::Outer; - let value = pprust::attribute_to_string(&attr); - // This str slicing works correctly, because the leading and trailing characters - // are in the ASCII range and thus exactly one byte each. - let value = value[2..value.len()-1].to_string(); - - Attribute { - value: value, - span: span_from_span(attr.span, tcx.sess.codemap()), - } - }).collect() - } -} - -impl Lower for data::CratePreludeData { - type Target = CratePreludeData; - - fn lower(self, tcx: TyCtxt) -> CratePreludeData { - CratePreludeData { - crate_name: self.crate_name, - crate_root: self.crate_root, - external_crates: self.external_crates, - span: span_from_span(self.span, tcx.sess.codemap()), - } - } -} - -/// Data for enum declarations. -#[derive(Clone, Debug)] -pub struct EnumData { - pub id: DefId, - pub value: String, - pub name: String, - pub qualname: String, - pub span: SpanData, - pub scope: DefId, - pub variants: Vec, - pub visibility: Visibility, - pub docs: String, - pub sig: Signature, - pub attributes: Vec, -} - -impl Lower for data::EnumData { - type Target = EnumData; - - fn lower(self, tcx: TyCtxt) -> EnumData { - EnumData { - id: make_def_id(self.id, &tcx.hir), - name: self.name, - value: self.value, - qualname: self.qualname, - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - variants: self.variants.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(), - visibility: self.visibility, - docs: self.docs, - sig: self.sig.lower(tcx), - attributes: self.attributes.lower(tcx), - } - } -} - -/// Data for extern crates. -#[derive(Debug)] -pub struct ExternCrateData { - pub id: DefId, - pub name: String, - pub crate_num: CrateNum, - pub location: String, - pub span: SpanData, - pub scope: DefId, -} - -impl Lower for data::ExternCrateData { - type Target = ExternCrateData; - - fn lower(self, tcx: TyCtxt) -> ExternCrateData { - ExternCrateData { - id: make_def_id(self.id, &tcx.hir), - name: self.name, - crate_num: self.crate_num, - location: self.location, - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - } - } -} - -/// Data about a function call. -#[derive(Debug)] -pub struct FunctionCallData { - pub span: SpanData, - pub scope: DefId, - pub ref_id: DefId, -} - -impl Lower for data::FunctionCallData { - type Target = FunctionCallData; - - fn lower(self, tcx: TyCtxt) -> FunctionCallData { - FunctionCallData { - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - ref_id: self.ref_id, - } - } -} - -/// Data for all kinds of functions and methods. -#[derive(Clone, Debug)] -pub struct FunctionData { - pub id: DefId, - pub name: String, - pub qualname: String, - pub declaration: Option, - pub span: SpanData, - pub scope: DefId, - pub value: String, - pub visibility: Visibility, - pub parent: Option, - pub docs: String, - pub sig: Signature, - pub attributes: Vec, -} - -impl Lower for data::FunctionData { - type Target = FunctionData; - - fn lower(self, tcx: TyCtxt) -> FunctionData { - FunctionData { - id: make_def_id(self.id, &tcx.hir), - name: self.name, - qualname: self.qualname, - declaration: self.declaration, - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - value: self.value, - visibility: self.visibility, - parent: self.parent, - docs: self.docs, - sig: self.sig.lower(tcx), - attributes: self.attributes.lower(tcx), - } - } -} - -/// Data about a function call. -#[derive(Debug)] -pub struct FunctionRefData { - pub span: SpanData, - pub scope: DefId, - pub ref_id: DefId, -} - -impl Lower for data::FunctionRefData { - type Target = FunctionRefData; - - fn lower(self, tcx: TyCtxt) -> FunctionRefData { - FunctionRefData { - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - ref_id: self.ref_id, - } - } -} -#[derive(Debug)] -pub struct ImplData { - pub id: DefId, - pub span: SpanData, - pub scope: DefId, - pub trait_ref: Option, - pub self_ref: Option, -} - -impl Lower for data::ImplData { - type Target = ImplData; - - fn lower(self, tcx: TyCtxt) -> ImplData { - ImplData { - id: make_def_id(self.id, &tcx.hir), - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - trait_ref: self.trait_ref, - self_ref: self.self_ref, - } - } -} - -#[derive(Debug)] -pub struct InheritanceData { - pub span: SpanData, - pub base_id: DefId, - pub deriv_id: DefId -} - -impl Lower for data::InheritanceData { - type Target = InheritanceData; - - fn lower(self, tcx: TyCtxt) -> InheritanceData { - InheritanceData { - span: span_from_span(self.span, tcx.sess.codemap()), - base_id: self.base_id, - deriv_id: make_def_id(self.deriv_id, &tcx.hir) - } - } -} - -/// Data about a macro declaration. -#[derive(Debug)] -pub struct MacroData { - pub span: SpanData, - pub name: String, - pub qualname: String, - pub docs: String, -} - -impl Lower for data::MacroData { - type Target = MacroData; - - fn lower(self, tcx: TyCtxt) -> MacroData { - MacroData { - span: span_from_span(self.span, tcx.sess.codemap()), - name: self.name, - qualname: self.qualname, - docs: self.docs, - } - } -} - -/// Data about a macro use. -#[derive(Debug)] -pub struct MacroUseData { - pub span: SpanData, - pub name: String, - pub qualname: String, - // Because macro expansion happens before ref-ids are determined, - // we use the callee span to reference the associated macro definition. - pub callee_span: SpanData, - pub scope: DefId, -} - -impl Lower for data::MacroUseData { - type Target = MacroUseData; - - fn lower(self, tcx: TyCtxt) -> MacroUseData { - MacroUseData { - span: span_from_span(self.span, tcx.sess.codemap()), - name: self.name, - qualname: self.qualname, - callee_span: span_from_span(self.callee_span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - } - } -} - -/// Data about a method call. -#[derive(Debug)] -pub struct MethodCallData { - pub span: SpanData, - pub scope: DefId, - pub ref_id: Option, - pub decl_id: Option, -} - -impl Lower for data::MethodCallData { - type Target = MethodCallData; - - fn lower(self, tcx: TyCtxt) -> MethodCallData { - MethodCallData { - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - ref_id: self.ref_id, - decl_id: self.decl_id, - } - } -} - -/// Data for method declarations (methods with a body are treated as functions). -#[derive(Clone, Debug)] -pub struct MethodData { - pub id: DefId, - pub name: String, - pub qualname: String, - pub span: SpanData, - pub scope: DefId, - pub value: String, - pub decl_id: Option, - pub visibility: Visibility, - pub parent: Option, - pub docs: String, - pub sig: Signature, - pub attributes: Vec, -} - -impl Lower for data::MethodData { - type Target = MethodData; - - fn lower(self, tcx: TyCtxt) -> MethodData { - MethodData { - span: span_from_span(self.span, tcx.sess.codemap()), - name: self.name, - scope: make_def_id(self.scope, &tcx.hir), - id: make_def_id(self.id, &tcx.hir), - qualname: self.qualname, - value: self.value, - decl_id: self.decl_id, - visibility: self.visibility, - parent: self.parent, - docs: self.docs, - sig: self.sig.lower(tcx), - attributes: self.attributes.lower(tcx), - } - } -} - -/// Data for modules. -#[derive(Debug)] -pub struct ModData { - pub id: DefId, - pub name: String, - pub qualname: String, - pub span: SpanData, - pub scope: DefId, - pub filename: String, - pub items: Vec, - pub visibility: Visibility, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -impl Lower for data::ModData { - type Target = ModData; - - fn lower(self, tcx: TyCtxt) -> ModData { - ModData { - id: make_def_id(self.id, &tcx.hir), - name: self.name, - qualname: self.qualname, - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - filename: self.filename, - items: self.items.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(), - visibility: self.visibility, - docs: self.docs, - sig: self.sig.map(|s| s.lower(tcx)), - attributes: self.attributes.lower(tcx), - } - } -} - -/// Data for a reference to a module. -#[derive(Debug)] -pub struct ModRefData { - pub span: SpanData, - pub scope: DefId, - pub ref_id: Option, - pub qualname: String -} - -impl Lower for data::ModRefData { - type Target = ModRefData; - - fn lower(self, tcx: TyCtxt) -> ModRefData { - ModRefData { - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - ref_id: self.ref_id, - qualname: self.qualname, - } - } -} - -#[derive(Debug)] -pub struct StructData { - pub span: SpanData, - pub name: String, - pub id: DefId, - pub ctor_id: DefId, - pub qualname: String, - pub scope: DefId, - pub value: String, - pub fields: Vec, - pub visibility: Visibility, - pub docs: String, - pub sig: Signature, - pub attributes: Vec, -} - -impl Lower for data::StructData { - type Target = StructData; - - fn lower(self, tcx: TyCtxt) -> StructData { - StructData { - span: span_from_span(self.span, tcx.sess.codemap()), - name: self.name, - id: make_def_id(self.id, &tcx.hir), - ctor_id: make_def_id(self.ctor_id, &tcx.hir), - qualname: self.qualname, - scope: make_def_id(self.scope, &tcx.hir), - value: self.value, - fields: self.fields.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(), - visibility: self.visibility, - docs: self.docs, - sig: self.sig.lower(tcx), - attributes: self.attributes.lower(tcx), - } - } -} - -#[derive(Debug)] -pub struct StructVariantData { - pub span: SpanData, - pub name: String, - pub id: DefId, - pub qualname: String, - pub type_value: String, - pub value: String, - pub scope: DefId, - pub parent: Option, - pub docs: String, - pub sig: Signature, - pub attributes: Vec, -} - -impl Lower for data::StructVariantData { - type Target = StructVariantData; - - fn lower(self, tcx: TyCtxt) -> StructVariantData { - StructVariantData { - span: span_from_span(self.span, tcx.sess.codemap()), - name: self.name, - id: make_def_id(self.id, &tcx.hir), - qualname: self.qualname, - type_value: self.type_value, - value: self.value, - scope: make_def_id(self.scope, &tcx.hir), - parent: self.parent, - docs: self.docs, - sig: self.sig.lower(tcx), - attributes: self.attributes.lower(tcx), - } - } -} - -#[derive(Debug)] -pub struct TraitData { - pub span: SpanData, - pub name: String, - pub id: DefId, - pub qualname: String, - pub scope: DefId, - pub value: String, - pub items: Vec, - pub visibility: Visibility, - pub docs: String, - pub sig: Signature, - pub attributes: Vec, -} - -impl Lower for data::TraitData { - type Target = TraitData; - - fn lower(self, tcx: TyCtxt) -> TraitData { - TraitData { - span: span_from_span(self.span, tcx.sess.codemap()), - name: self.name, - id: make_def_id(self.id, &tcx.hir), - qualname: self.qualname, - scope: make_def_id(self.scope, &tcx.hir), - value: self.value, - items: self.items.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(), - visibility: self.visibility, - docs: self.docs, - sig: self.sig.lower(tcx), - attributes: self.attributes.lower(tcx), - } - } -} - -#[derive(Debug)] -pub struct TupleVariantData { - pub span: SpanData, - pub id: DefId, - pub name: String, - pub qualname: String, - pub type_value: String, - pub value: String, - pub scope: DefId, - pub parent: Option, - pub docs: String, - pub sig: Signature, - pub attributes: Vec, -} - -impl Lower for data::TupleVariantData { - type Target = TupleVariantData; - - fn lower(self, tcx: TyCtxt) -> TupleVariantData { - TupleVariantData { - span: span_from_span(self.span, tcx.sess.codemap()), - id: make_def_id(self.id, &tcx.hir), - name: self.name, - qualname: self.qualname, - type_value: self.type_value, - value: self.value, - scope: make_def_id(self.scope, &tcx.hir), - parent: self.parent, - docs: self.docs, - sig: self.sig.lower(tcx), - attributes: self.attributes.lower(tcx), - } - } -} - -/// Data for a typedef. -#[derive(Debug)] -pub struct TypeDefData { - pub id: DefId, - pub name: String, - pub span: SpanData, - pub qualname: String, - pub value: String, - pub visibility: Visibility, - pub parent: Option, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -impl Lower for data::TypeDefData { - type Target = TypeDefData; - - fn lower(self, tcx: TyCtxt) -> TypeDefData { - TypeDefData { - id: make_def_id(self.id, &tcx.hir), - name: self.name, - span: span_from_span(self.span, tcx.sess.codemap()), - qualname: self.qualname, - value: self.value, - visibility: self.visibility, - parent: self.parent, - docs: self.docs, - sig: self.sig.map(|s| s.lower(tcx)), - attributes: self.attributes.lower(tcx), - } - } -} - -/// Data for a reference to a type or trait. -#[derive(Clone, Debug)] -pub struct TypeRefData { - pub span: SpanData, - pub scope: DefId, - pub ref_id: Option, - pub qualname: String, -} - -impl Lower for data::TypeRefData { - type Target = TypeRefData; - - fn lower(self, tcx: TyCtxt) -> TypeRefData { - TypeRefData { - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - ref_id: self.ref_id, - qualname: self.qualname, - } - } -} - -#[derive(Debug)] -pub struct UseData { - pub id: DefId, - pub span: SpanData, - pub name: String, - pub mod_id: Option, - pub scope: DefId, - pub visibility: Visibility, -} - -impl Lower for data::UseData { - type Target = UseData; - - fn lower(self, tcx: TyCtxt) -> UseData { - UseData { - id: make_def_id(self.id, &tcx.hir), - span: span_from_span(self.span, tcx.sess.codemap()), - name: self.name, - mod_id: self.mod_id, - scope: make_def_id(self.scope, &tcx.hir), - visibility: self.visibility, - } - } -} - -#[derive(Debug)] -pub struct UseGlobData { - pub id: DefId, - pub span: SpanData, - pub names: Vec, - pub scope: DefId, - pub visibility: Visibility, -} - -impl Lower for data::UseGlobData { - type Target = UseGlobData; - - fn lower(self, tcx: TyCtxt) -> UseGlobData { - UseGlobData { - id: make_def_id(self.id, &tcx.hir), - span: span_from_span(self.span, tcx.sess.codemap()), - names: self.names, - scope: make_def_id(self.scope, &tcx.hir), - visibility: self.visibility, - } - } -} - -/// Data for local and global variables (consts and statics). -#[derive(Debug)] -pub struct VariableData { - pub id: DefId, - pub name: String, - pub kind: data::VariableKind, - pub qualname: String, - pub span: SpanData, - pub scope: DefId, - pub value: String, - pub type_value: String, - pub parent: Option, - pub visibility: Visibility, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -impl Lower for data::VariableData { - type Target = VariableData; - - fn lower(self, tcx: TyCtxt) -> VariableData { - VariableData { - id: make_def_id(self.id, &tcx.hir), - kind: self.kind, - name: self.name, - qualname: self.qualname, - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - value: self.value, - type_value: self.type_value, - parent: self.parent, - visibility: self.visibility, - docs: self.docs, - sig: self.sig.map(|s| s.lower(tcx)), - attributes: self.attributes.lower(tcx), - } - } -} - -/// Data for the use of some item (e.g., the use of a local variable, which -/// will refer to that variables declaration (by ref_id)). -#[derive(Debug)] -pub struct VariableRefData { - pub name: String, - pub span: SpanData, - pub scope: DefId, - pub ref_id: DefId, -} - -impl Lower for data::VariableRefData { - type Target = VariableRefData; - - fn lower(self, tcx: TyCtxt) -> VariableRefData { - VariableRefData { - name: self.name, - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - ref_id: self.ref_id, - } - } -} - -#[derive(Clone, Debug)] -pub struct Signature { - pub span: SpanData, - pub text: String, - // These identify the main identifier for the defintion as byte offsets into - // `text`. E.g., of `foo` in `pub fn foo(...)` - pub ident_start: usize, - pub ident_end: usize, - pub defs: Vec, - pub refs: Vec, -} - -impl Lower for data::Signature { - type Target = Signature; - - fn lower(self, tcx: TyCtxt) -> Signature { - Signature { - span: span_from_span(self.span, tcx.sess.codemap()), - text: self.text, - ident_start: self.ident_start, - ident_end: self.ident_end, - defs: self.defs, - refs: self.refs, - } - } -} diff --git a/src/librustc_save_analysis/json_api_dumper.rs b/src/librustc_save_analysis/json_api_dumper.rs index 49b14f5eca..4b2301fd7f 100644 --- a/src/librustc_save_analysis/json_api_dumper.rs +++ b/src/librustc_save_analysis/json_api_dumper.rs @@ -12,12 +12,9 @@ use std::io::Write; use rustc_serialize::json::as_json; -use external_data::*; -use data::{VariableKind, Visibility}; -use dump::Dump; -use json_dumper::id_from_def_id; +use Dump; -use rls_data::{Analysis, Import, ImportKind, Def, DefKind, CratePreludeData}; +use rls_data::{Analysis, Import, Def, CratePreludeData, Format, Relation}; // A dumper to dump a restricted set of JSON information, designed for use with @@ -33,7 +30,9 @@ pub struct JsonApiDumper<'b, W: Write + 'b> { impl<'b, W: Write> JsonApiDumper<'b, W> { pub fn new(writer: &'b mut W) -> JsonApiDumper<'b, W> { - JsonApiDumper { output: writer, result: Analysis::new() } + let mut result = Analysis::new(); + result.kind = Format::JsonApi; + JsonApiDumper { output: writer, result } } } @@ -45,306 +44,23 @@ impl<'b, W: Write> Drop for JsonApiDumper<'b, W> { } } -macro_rules! impl_fn { - ($fn_name: ident, $data_type: ident, $bucket: ident) => { - fn $fn_name(&mut self, data: $data_type) { - if let Some(datum) = data.into() { - self.result.$bucket.push(datum); - } - } - } -} - impl<'b, W: Write + 'b> Dump for JsonApiDumper<'b, W> { fn crate_prelude(&mut self, data: CratePreludeData) { self.result.prelude = Some(data) } - impl_fn!(use_data, UseData, imports); - impl_fn!(use_glob, UseGlobData, imports); - - impl_fn!(enum_data, EnumData, defs); - impl_fn!(tuple_variant, TupleVariantData, defs); - impl_fn!(struct_variant, StructVariantData, defs); - impl_fn!(struct_data, StructData, defs); - impl_fn!(trait_data, TraitData, defs); - impl_fn!(function, FunctionData, defs); - impl_fn!(method, MethodData, defs); - impl_fn!(macro_data, MacroData, defs); - impl_fn!(mod_data, ModData, defs); - impl_fn!(typedef, TypeDefData, defs); - impl_fn!(variable, VariableData, defs); - - fn impl_data(&mut self, data: ImplData) { - if data.self_ref.is_some() { - self.result.relations.push(data.into()); - } - } - fn inheritance(&mut self, data: InheritanceData) { - self.result.relations.push(data.into()); + fn dump_relation(&mut self, data: Relation) { + self.result.relations.push(data); } -} - -// FIXME methods. The defs have information about possible overriding and the -// refs have decl information (e.g., a trait method where we know the required -// method, but not the supplied method). In both cases, we are currently -// ignoring it. - -impl Into> for UseData { - fn into(self) -> Option { - match self.visibility { - Visibility::Public => Some(Import { - kind: ImportKind::Use, - ref_id: self.mod_id.map(|id| id_from_def_id(id)), - span: self.span, - name: self.name, - value: String::new(), - }), - _ => None, + fn import(&mut self, public: bool, import: Import) { + if public { + self.result.imports.push(import); } } -} -impl Into> for UseGlobData { - fn into(self) -> Option { - match self.visibility { - Visibility::Public => Some(Import { - kind: ImportKind::GlobUse, - ref_id: None, - span: self.span, - name: "*".to_owned(), - value: self.names.join(", "), - }), - _ => None, - } - } -} - -impl Into> for EnumData { - fn into(self) -> Option { - match self.visibility { - Visibility::Public => Some(Def { - kind: DefKind::Enum, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: None, - children: self.variants.into_iter().map(|id| id_from_def_id(id)).collect(), - decl_id: None, - docs: self.docs, - sig: Some(self.sig.into()), - attributes: vec![], - }), - _ => None, - } - } -} - -impl Into> for TupleVariantData { - fn into(self) -> Option { - Some(Def { - kind: DefKind::Tuple, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: self.parent.map(|id| id_from_def_id(id)), - children: vec![], - decl_id: None, - docs: self.docs, - sig: Some(self.sig.into()), - attributes: vec![], - }) - } -} -impl Into> for StructVariantData { - fn into(self) -> Option { - Some(Def { - kind: DefKind::Struct, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: self.parent.map(|id| id_from_def_id(id)), - children: vec![], - decl_id: None, - docs: self.docs, - sig: Some(self.sig.into()), - attributes: vec![], - }) - } -} -impl Into> for StructData { - fn into(self) -> Option { - match self.visibility { - Visibility::Public => Some(Def { - kind: DefKind::Struct, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: None, - children: self.fields.into_iter().map(|id| id_from_def_id(id)).collect(), - decl_id: None, - docs: self.docs, - sig: Some(self.sig.into()), - attributes: vec![], - }), - _ => None, - } - } -} -impl Into> for TraitData { - fn into(self) -> Option { - match self.visibility { - Visibility::Public => Some(Def { - kind: DefKind::Trait, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - children: self.items.into_iter().map(|id| id_from_def_id(id)).collect(), - parent: None, - decl_id: None, - docs: self.docs, - sig: Some(self.sig.into()), - attributes: vec![], - }), - _ => None, - } - } -} -impl Into> for FunctionData { - fn into(self) -> Option { - match self.visibility { - Visibility::Public => Some(Def { - kind: DefKind::Function, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - children: vec![], - parent: self.parent.map(|id| id_from_def_id(id)), - decl_id: None, - docs: self.docs, - sig: Some(self.sig.into()), - attributes: vec![], - }), - _ => None, - } - } -} -impl Into> for MethodData { - fn into(self) -> Option { - match self.visibility { - Visibility::Public => Some(Def { - kind: DefKind::Method, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - children: vec![], - parent: self.parent.map(|id| id_from_def_id(id)), - decl_id: self.decl_id.map(|id| id_from_def_id(id)), - docs: self.docs, - sig: Some(self.sig.into()), - attributes: vec![], - }), - _ => None, - } - } -} -impl Into> for MacroData { - fn into(self) -> Option { - Some(Def { - kind: DefKind::Macro, - id: id_from_def_id(null_def_id()), - span: self.span, - name: self.name, - qualname: self.qualname, - value: String::new(), - children: vec![], - parent: None, - decl_id: None, - docs: self.docs, - sig: None, - attributes: vec![], - }) - } -} -impl Into> for ModData { - fn into(self) -> Option { - match self.visibility { - Visibility::Public => Some(Def { - kind: DefKind::Mod, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.filename, - children: self.items.into_iter().map(|id| id_from_def_id(id)).collect(), - parent: None, - decl_id: None, - docs: self.docs, - sig: self.sig.map(|s| s.into()), - attributes: vec![], - }), - _ => None, - } - } -} -impl Into> for TypeDefData { - fn into(self) -> Option { - match self.visibility { - Visibility::Public => Some(Def { - kind: DefKind::Type, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - children: vec![], - parent: self.parent.map(|id| id_from_def_id(id)), - decl_id: None, - docs: String::new(), - sig: self.sig.map(|s| s.into()), - attributes: vec![], - }), - _ => None, - } - } -} - -impl Into> for VariableData { - fn into(self) -> Option { - match self.visibility { - Visibility::Public => Some(Def { - kind: match self.kind { - VariableKind::Static => DefKind::Static, - VariableKind::Const => DefKind::Const, - VariableKind::Local => { return None } - VariableKind::Field => DefKind::Field, - }, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - children: vec![], - parent: self.parent.map(|id| id_from_def_id(id)), - decl_id: None, - docs: self.docs, - sig: self.sig.map(|s| s.into()), - attributes: vec![], - }), - _ => None, + fn dump_def(&mut self, public: bool, mut data: Def) { + if public { + data.attributes = vec![]; + self.result.defs.push(data); } } } diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index eaa0c0825f..9cd375e985 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -10,17 +10,13 @@ use std::io::Write; -use rustc::hir::def_id::DefId; use rustc_serialize::json::as_json; -use rls_data::{self, Id, Analysis, Import, ImportKind, Def, DefKind, Ref, RefKind, MacroRef, - Relation, RelationKind, Signature, SigElement, CratePreludeData}; +use rls_data::{self, Analysis, Import, Def, DefKind, Ref, RefKind, MacroRef, + Relation, CratePreludeData}; use rls_span::{Column, Row}; -use external_data; -use external_data::*; -use data::{self, VariableKind}; -use dump::Dump; +use Dump; pub struct JsonDumper { result: Analysis, @@ -71,71 +67,35 @@ impl Drop for JsonDumper { } } -macro_rules! impl_fn { - ($fn_name: ident, $data_type: ident, $bucket: ident) => { - fn $fn_name(&mut self, data: $data_type) { - self.result.$bucket.push(data.into()); - } - } -} - impl<'b, O: DumpOutput + 'b> Dump for JsonDumper { fn crate_prelude(&mut self, data: CratePreludeData) { self.result.prelude = Some(data) } - impl_fn!(extern_crate, ExternCrateData, imports); - impl_fn!(use_data, UseData, imports); - impl_fn!(use_glob, UseGlobData, imports); - - impl_fn!(enum_data, EnumData, defs); - impl_fn!(tuple_variant, TupleVariantData, defs); - impl_fn!(struct_variant, StructVariantData, defs); - impl_fn!(struct_data, StructData, defs); - impl_fn!(trait_data, TraitData, defs); - impl_fn!(function, FunctionData, defs); - impl_fn!(method, MethodData, defs); - impl_fn!(macro_data, MacroData, defs); - impl_fn!(typedef, TypeDefData, defs); - impl_fn!(variable, VariableData, defs); - - impl_fn!(function_ref, FunctionRefData, refs); - impl_fn!(function_call, FunctionCallData, refs); - impl_fn!(method_call, MethodCallData, refs); - impl_fn!(mod_ref, ModRefData, refs); - impl_fn!(type_ref, TypeRefData, refs); - impl_fn!(variable_ref, VariableRefData, refs); + fn macro_use(&mut self, data: MacroRef) { + self.result.macro_refs.push(data); + } - impl_fn!(macro_use, MacroUseData, macro_refs); + fn import(&mut self, _: bool, import: Import) { + self.result.imports.push(import); + } - fn mod_data(&mut self, data: ModData) { - let id: Id = id_from_def_id(data.id); - let mut def = Def { - kind: DefKind::Mod, - id: id, - span: data.span.into(), - name: data.name, - qualname: data.qualname, - value: data.filename, - parent: None, - children: data.items.into_iter().map(|id| id_from_def_id(id)).collect(), - decl_id: None, - docs: data.docs, - sig: data.sig.map(|s| s.into()), - attributes: data.attributes.into_iter().map(|a| a.into()).collect(), - }; - if def.span.file_name.to_str().unwrap() != def.value { + fn dump_ref(&mut self, data: Ref) { + self.result.refs.push(data); + } + fn dump_def(&mut self, _: bool, mut data: Def) { + if data.kind == DefKind::Mod && data.span.file_name.to_str().unwrap() != data.value { // If the module is an out-of-line defintion, then we'll make the // defintion the first character in the module's file and turn the // the declaration into a reference to it. let rf = Ref { kind: RefKind::Mod, - span: def.span, - ref_id: id, + span: data.span, + ref_id: data.id, }; self.result.refs.push(rf); - def.span = rls_data::SpanData { - file_name: def.value.clone().into(), + data.span = rls_data::SpanData { + file_name: data.value.clone().into(), byte_start: 0, byte_end: 0, line_start: Row::new_one_indexed(1), @@ -144,362 +104,10 @@ impl<'b, O: DumpOutput + 'b> Dump for JsonDumper { column_end: Column::new_one_indexed(1), } } - - self.result.defs.push(def); + self.result.defs.push(data); } - fn impl_data(&mut self, data: ImplData) { - if data.self_ref.is_some() { - self.result.relations.push(data.into()); - } - } - fn inheritance(&mut self, data: InheritanceData) { - self.result.relations.push(data.into()); - } -} - -// FIXME do we want to change ExternalData to this mode? It will break DXR. -// FIXME methods. The defs have information about possible overriding and the -// refs have decl information (e.g., a trait method where we know the required -// method, but not the supplied method). In both cases, we are currently -// ignoring it. - -// DefId::index is a newtype and so the JSON serialisation is ugly. Therefore -// we use our own Id which is the same, but without the newtype. -pub fn id_from_def_id(id: DefId) -> Id { - Id { - krate: id.krate.as_u32(), - index: id.index.as_u32(), - } -} - -impl Into for ExternCrateData { - fn into(self) -> Import { - Import { - kind: ImportKind::ExternCrate, - ref_id: None, - span: self.span, - name: self.name, - value: String::new(), - } - } -} -impl Into for UseData { - fn into(self) -> Import { - Import { - kind: ImportKind::Use, - ref_id: self.mod_id.map(|id| id_from_def_id(id)), - span: self.span, - name: self.name, - value: String::new(), - } - } -} -impl Into for UseGlobData { - fn into(self) -> Import { - Import { - kind: ImportKind::GlobUse, - ref_id: None, - span: self.span, - name: "*".to_owned(), - value: self.names.join(", "), - } - } -} - -impl Into for EnumData { - fn into(self) -> Def { - Def { - kind: DefKind::Enum, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: None, - children: self.variants.into_iter().map(|id| id_from_def_id(id)).collect(), - decl_id: None, - docs: self.docs, - sig: Some(self.sig.into()), - attributes: self.attributes, - } - } -} - -impl Into for TupleVariantData { - fn into(self) -> Def { - Def { - kind: DefKind::Tuple, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: None, - children: vec![], - decl_id: None, - docs: self.docs, - sig: Some(self.sig.into()), - attributes: self.attributes, - } - } -} -impl Into for StructVariantData { - fn into(self) -> Def { - Def { - kind: DefKind::Struct, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: None, - children: vec![], - decl_id: None, - docs: self.docs, - sig: Some(self.sig.into()), - attributes: self.attributes, - } - } -} -impl Into for StructData { - fn into(self) -> Def { - Def { - kind: DefKind::Struct, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: None, - children: self.fields.into_iter().map(|id| id_from_def_id(id)).collect(), - decl_id: None, - docs: self.docs, - sig: Some(self.sig.into()), - attributes: self.attributes, - } - } -} -impl Into for TraitData { - fn into(self) -> Def { - Def { - kind: DefKind::Trait, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: None, - children: self.items.into_iter().map(|id| id_from_def_id(id)).collect(), - decl_id: None, - docs: self.docs, - sig: Some(self.sig.into()), - attributes: self.attributes, - } - } -} -impl Into for FunctionData { - fn into(self) -> Def { - Def { - kind: DefKind::Function, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: None, - children: vec![], - decl_id: None, - docs: self.docs, - sig: Some(self.sig.into()), - attributes: self.attributes, - } - } -} -impl Into for MethodData { - fn into(self) -> Def { - Def { - kind: DefKind::Method, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: None, - children: vec![], - decl_id: self.decl_id.map(|id| id_from_def_id(id)), - docs: self.docs, - sig: Some(self.sig.into()), - attributes: self.attributes, - } - } -} -impl Into for MacroData { - fn into(self) -> Def { - Def { - kind: DefKind::Macro, - id: id_from_def_id(null_def_id()), - span: self.span, - name: self.name, - qualname: self.qualname, - value: String::new(), - parent: None, - children: vec![], - decl_id: None, - docs: self.docs, - sig: None, - attributes: vec![], - } - } -} -impl Into for TypeDefData { - fn into(self) -> Def { - Def { - kind: DefKind::Type, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: None, - children: vec![], - decl_id: None, - docs: String::new(), - sig: self.sig.map(|s| s.into()), - attributes: self.attributes, - } - } -} -impl Into for VariableData { - fn into(self) -> Def { - Def { - kind: match self.kind { - VariableKind::Static => DefKind::Static, - VariableKind::Const => DefKind::Const, - VariableKind::Local => DefKind::Local, - VariableKind::Field => DefKind::Field, - }, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.type_value, - parent: None, - children: vec![], - decl_id: None, - docs: self.docs, - sig: None, - attributes: self.attributes, - } - } -} - -impl Into for FunctionRefData { - fn into(self) -> Ref { - Ref { - kind: RefKind::Function, - span: self.span, - ref_id: id_from_def_id(self.ref_id), - } - } -} -impl Into for FunctionCallData { - fn into(self) -> Ref { - Ref { - kind: RefKind::Function, - span: self.span, - ref_id: id_from_def_id(self.ref_id), - } - } -} -impl Into for MethodCallData { - fn into(self) -> Ref { - Ref { - kind: RefKind::Function, - span: self.span, - ref_id: id_from_def_id(self.ref_id.or(self.decl_id).unwrap_or(null_def_id())), - } - } -} -impl Into for ModRefData { - fn into(self) -> Ref { - Ref { - kind: RefKind::Mod, - span: self.span, - ref_id: id_from_def_id(self.ref_id.unwrap_or(null_def_id())), - } - } -} -impl Into for TypeRefData { - fn into(self) -> Ref { - Ref { - kind: RefKind::Type, - span: self.span, - ref_id: id_from_def_id(self.ref_id.unwrap_or(null_def_id())), - } - } -} -impl Into for VariableRefData { - fn into(self) -> Ref { - Ref { - kind: RefKind::Variable, - span: self.span, - ref_id: id_from_def_id(self.ref_id), - } - } -} - -impl Into for MacroUseData { - fn into(self) -> MacroRef { - MacroRef { - span: self.span, - qualname: self.qualname, - callee_span: self.callee_span.into(), - } - } -} - -impl Into for ImplData { - fn into(self) -> Relation { - Relation { - span: self.span, - kind: RelationKind::Impl, - from: id_from_def_id(self.self_ref.unwrap_or(null_def_id())), - to: id_from_def_id(self.trait_ref.unwrap_or(null_def_id())), - } - } -} - -impl Into for InheritanceData { - fn into(self) -> Relation { - Relation { - span: self.span, - kind: RelationKind::SuperTrait, - from: id_from_def_id(self.base_id), - to: id_from_def_id(self.deriv_id), - } - } -} - -impl Into for external_data::Signature { - fn into(self) -> Signature { - Signature { - span: self.span, - text: self.text, - ident_start: self.ident_start, - ident_end: self.ident_end, - defs: self.defs.into_iter().map(|s| s.into()).collect(), - refs: self.refs.into_iter().map(|s| s.into()).collect(), - } - } -} - -impl Into for data::SigElement { - fn into(self) -> SigElement { - SigElement { - id: id_from_def_id(self.id), - start: self.start, - end: self.end, - } + fn dump_relation(&mut self, data: Relation) { + self.result.relations.push(data); } } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index b74d3982d6..ac2baa9e8b 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -19,10 +19,6 @@ #![feature(custom_attribute)] #![allow(unused_attributes)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] - #[macro_use] extern crate rustc; #[macro_use] extern crate log; @@ -35,19 +31,16 @@ extern crate rls_data; extern crate rls_span; -mod csv_dumper; mod json_api_dumper; mod json_dumper; -mod data; -mod dump; mod dump_visitor; -pub mod external_data; #[macro_use] -pub mod span_utils; +mod span_utils; +mod sig; use rustc::hir; -use rustc::hir::def::Def; -use rustc::hir::map::Node; +use rustc::hir::def::Def as HirDef; +use rustc::hir::map::{Node, NodeItem}; use rustc::hir::def_id::DefId; use rustc::session::config::CrateType::CrateTypeExecutable; use rustc::session::Session; @@ -61,33 +54,21 @@ use std::path::{Path, PathBuf}; use syntax::ast::{self, NodeId, PatKind, Attribute, CRATE_NODE_ID}; use syntax::parse::lexer::comments::strip_doc_comment_decoration; use syntax::parse::token; +use syntax::print::pprust; use syntax::symbol::keywords; use syntax::visit::{self, Visitor}; use syntax::print::pprust::{ty_to_string, arg_to_string}; use syntax::codemap::MacroAttribute; use syntax_pos::*; -pub use self::csv_dumper::CsvDumper; -pub use self::json_api_dumper::JsonApiDumper; -pub use self::json_dumper::JsonDumper; -pub use self::data::*; -pub use self::external_data::make_def_id; -pub use self::dump::Dump; -pub use self::dump_visitor::DumpVisitor; -use self::span_utils::SpanUtils; - -// FIXME this is legacy code and should be removed -pub mod recorder { - pub use self::Row::*; - - #[derive(Copy, Clone, Debug, Eq, PartialEq)] - pub enum Row { - TypeRef, - ModRef, - VarRef, - FnRef, - } -} +pub use json_api_dumper::JsonApiDumper; +pub use json_dumper::JsonDumper; +use dump_visitor::DumpVisitor; +use span_utils::SpanUtils; + +use rls_data::{Ref, RefKind, SpanData, MacroRef, Def, DefKind, Relation, RelationKind, + ExternalCrateData, Import, CratePreludeData}; + pub struct SaveContext<'l, 'tcx: 'l> { tcx: TyCtxt<'l, 'tcx, 'tcx>, @@ -96,27 +77,64 @@ pub struct SaveContext<'l, 'tcx: 'l> { span_utils: SpanUtils<'tcx>, } +#[derive(Debug)] +pub enum Data { + /// Data about a macro use. + MacroUseData(MacroRef), + RefData(Ref), + DefData(Def), + RelationData(Relation), +} + +pub trait Dump { + fn crate_prelude(&mut self, _: CratePreludeData); + fn macro_use(&mut self, _: MacroRef) {} + fn import(&mut self, _: bool, _: Import); + fn dump_ref(&mut self, _: Ref) {} + fn dump_def(&mut self, _: bool, _: Def); + fn dump_relation(&mut self, data: Relation); +} + macro_rules! option_try( ($e:expr) => (match $e { Some(e) => e, None => return None }) ); impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { + fn span_from_span(&self, span: Span) -> SpanData { + use rls_span::{Row, Column}; + + let cm = self.tcx.sess.codemap(); + let start = cm.lookup_char_pos(span.lo); + let end = cm.lookup_char_pos(span.hi); + + SpanData { + file_name: start.file.name.clone().into(), + byte_start: span.lo.0, + byte_end: span.hi.0, + line_start: Row::new_one_indexed(start.line as u32), + line_end: Row::new_one_indexed(end.line as u32), + column_start: Column::new_one_indexed(start.col.0 as u32 + 1), + column_end: Column::new_one_indexed(end.col.0 as u32 + 1), + } + } + // List external crates used by the current crate. - pub fn get_external_crates(&self) -> Vec { + pub fn get_external_crates(&self) -> Vec { let mut result = Vec::new(); for n in self.tcx.sess.cstore.crates() { - let span = match self.tcx.sess.cstore.extern_crate(n) { + let span = match *self.tcx.extern_crate(n.as_def_id()) { Some(ref c) => c.span, None => { debug!("Skipping crate {}, no data", n); continue; } }; - result.push(CrateData { + let lo_loc = self.span_utils.sess.codemap().lookup_char_pos(span.lo); + result.push(ExternalCrateData { name: self.tcx.sess.cstore.crate_name(n).to_string(), - number: n.as_u32(), - span: span, + num: n.as_u32(), + file_name: SpanUtils::make_path_string(&lo_loc.file.name), }); } @@ -129,39 +147,43 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ast::ForeignItemKind::Fn(ref decl, ref generics) => { let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Fn); filter!(self.span_utils, sub_span, item.span, None); - Some(Data::FunctionData(FunctionData { - id: item.id, + + Some(Data::DefData(Def { + kind: DefKind::Function, + id: id_from_node_id(item.id, self), + span: self.span_from_span(sub_span.unwrap()), name: item.ident.to_string(), - qualname: qualname, - declaration: None, - span: sub_span.unwrap(), - scope: self.enclosing_scope(item.id), + qualname, value: make_signature(decl, generics), - visibility: From::from(&item.vis), parent: None, + children: vec![], + decl_id: None, docs: docs_for_attrs(&item.attrs), - sig: self.sig_base_extern(item), - attributes: item.attrs.clone(), + sig: sig::foreign_item_signature(item, self), + attributes: lower_attributes(item.attrs.clone(), self), })) } ast::ForeignItemKind::Static(ref ty, m) => { let keyword = if m { keywords::Mut } else { keywords::Static }; let sub_span = self.span_utils.sub_span_after_keyword(item.span, keyword); filter!(self.span_utils, sub_span, item.span, None); - Some(Data::VariableData(VariableData { - id: item.id, - kind: VariableKind::Static, + + let id = ::id_from_node_id(item.id, self); + let span = self.span_from_span(sub_span.unwrap()); + + Some(Data::DefData(Def { + kind: DefKind::Static, + id, + span, name: item.ident.to_string(), - qualname: qualname, - span: sub_span.unwrap(), - scope: self.enclosing_scope(item.id), + qualname, + value: ty_to_string(ty), parent: None, - value: String::new(), - type_value: ty_to_string(ty), - visibility: From::from(&item.vis), + children: vec![], + decl_id: None, docs: docs_for_attrs(&item.attrs), - sig: Some(self.sig_base_extern(item)), - attributes: item.attrs.clone(), + sig: sig::foreign_item_signature(item, self), + attributes: lower_attributes(item.attrs.clone(), self), })) } } @@ -173,70 +195,71 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Fn); filter!(self.span_utils, sub_span, item.span, None); - - - Some(Data::FunctionData(FunctionData { - id: item.id, + Some(Data::DefData(Def { + kind: DefKind::Function, + id: id_from_node_id(item.id, self), + span: self.span_from_span(sub_span.unwrap()), name: item.ident.to_string(), - qualname: qualname, - declaration: None, - span: sub_span.unwrap(), - scope: self.enclosing_scope(item.id), + qualname, value: make_signature(decl, generics), - visibility: From::from(&item.vis), parent: None, + children: vec![], + decl_id: None, docs: docs_for_attrs(&item.attrs), - sig: self.sig_base(item), - attributes: item.attrs.clone(), + sig: sig::item_signature(item, self), + attributes: lower_attributes(item.attrs.clone(), self), })) } - ast::ItemKind::Static(ref typ, mt, ref expr) => { + ast::ItemKind::Static(ref typ, mt, _) => { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); - // If the variable is immutable, save the initialising expression. - let (value, keyword) = match mt { - ast::Mutability::Mutable => (String::from(""), keywords::Mut), - ast::Mutability::Immutable => { - (self.span_utils.snippet(expr.span), keywords::Static) - }, + let keyword = match mt { + ast::Mutability::Mutable => keywords::Mut, + ast::Mutability::Immutable => keywords::Static, }; let sub_span = self.span_utils.sub_span_after_keyword(item.span, keyword); filter!(self.span_utils, sub_span, item.span, None); - Some(Data::VariableData(VariableData { - id: item.id, - kind: VariableKind::Static, + + let id = id_from_node_id(item.id, self); + let span = self.span_from_span(sub_span.unwrap()); + + Some(Data::DefData(Def { + kind: DefKind::Static, + id, + span, name: item.ident.to_string(), - qualname: qualname, - span: sub_span.unwrap(), - scope: self.enclosing_scope(item.id), + qualname, + value: ty_to_string(&typ), parent: None, - value: value, - type_value: ty_to_string(&typ), - visibility: From::from(&item.vis), + children: vec![], + decl_id: None, docs: docs_for_attrs(&item.attrs), - sig: Some(self.sig_base(item)), - attributes: item.attrs.clone(), + sig: sig::item_signature(item, self), + attributes: lower_attributes(item.attrs.clone(), self), })) } - ast::ItemKind::Const(ref typ, ref expr) => { + ast::ItemKind::Const(ref typ, _) => { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Const); filter!(self.span_utils, sub_span, item.span, None); - Some(Data::VariableData(VariableData { - id: item.id, - kind: VariableKind::Const, + + let id = id_from_node_id(item.id, self); + let span = self.span_from_span(sub_span.unwrap()); + + Some(Data::DefData(Def { + kind: DefKind::Const, + id, + span, name: item.ident.to_string(), - qualname: qualname, - span: sub_span.unwrap(), - scope: self.enclosing_scope(item.id), + qualname, + value: ty_to_string(typ), parent: None, - value: self.span_utils.snippet(expr.span), - type_value: ty_to_string(&typ), - visibility: From::from(&item.vis), + children: vec![], + decl_id: None, docs: docs_for_attrs(&item.attrs), - sig: Some(self.sig_base(item)), - attributes: item.attrs.clone(), + sig: sig::item_signature(item, self), + attributes: lower_attributes(item.attrs.clone(), self), })) } ast::ItemKind::Mod(ref m) => { @@ -248,18 +271,19 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Mod); filter!(self.span_utils, sub_span, item.span, None); - Some(Data::ModData(ModData { - id: item.id, + Some(Data::DefData(Def { + kind: DefKind::Mod, + id: id_from_node_id(item.id, self), name: item.ident.to_string(), - qualname: qualname, - span: sub_span.unwrap(), - scope: self.enclosing_scope(item.id), - filename: filename, - items: m.items.iter().map(|i| i.id).collect(), - visibility: From::from(&item.vis), + qualname, + span: self.span_from_span(sub_span.unwrap()), + value: filename, + parent: None, + children: m.items.iter().map(|i| id_from_node_id(i.id, self)).collect(), + decl_id: None, docs: docs_for_attrs(&item.attrs), - sig: Some(self.sig_base(item)), - attributes: item.attrs.clone(), + sig: sig::item_signature(item, self), + attributes: lower_attributes(item.attrs.clone(), self), })) } ast::ItemKind::Enum(ref def, _) => { @@ -271,61 +295,47 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { .map(|v| v.node.name.to_string()) .collect::>() .join(", "); - let val = format!("{}::{{{}}}", name, variants_str); - Some(Data::EnumData(EnumData { - id: item.id, - name: name, - value: val, - span: sub_span.unwrap(), - qualname: qualname, - scope: self.enclosing_scope(item.id), - variants: def.variants.iter().map(|v| v.node.data.id()).collect(), - visibility: From::from(&item.vis), + let value = format!("{}::{{{}}}", name, variants_str); + Some(Data::DefData(Def { + kind: DefKind::Enum, + id: id_from_node_id(item.id, self), + span: self.span_from_span(sub_span.unwrap()), + name, + qualname, + value, + parent: None, + children: def.variants + .iter() + .map(|v| id_from_node_id(v.node.data.id(), self)) + .collect(), + decl_id: None, docs: docs_for_attrs(&item.attrs), - sig: self.sig_base(item), - attributes: item.attrs.clone(), + sig: sig::item_signature(item, self), + attributes: lower_attributes(item.attrs.to_owned(), self), })) } ast::ItemKind::Impl(.., ref trait_ref, ref typ, _) => { - let mut type_data = None; - let sub_span; - - let parent = self.enclosing_scope(item.id); - - match typ.node { + if let ast::TyKind::Path(None, ref path) = typ.node { // Common case impl for a struct or something basic. - ast::TyKind::Path(None, ref path) => { - if generated_code(path.span) { - return None; - } - sub_span = self.span_utils.sub_span_for_type_name(path.span); - type_data = self.lookup_ref_id(typ.id).map(|id| { - TypeRefData { - span: sub_span.unwrap(), - scope: parent, - ref_id: Some(id), - qualname: String::new() // FIXME: generate the real qualname - } - }); - } - _ => { - // Less useful case, impl for a compound type. - let span = typ.span; - sub_span = self.span_utils.sub_span_for_type_name(span).or(Some(span)); + if generated_code(path.span) { + return None; } + let sub_span = self.span_utils.sub_span_for_type_name(path.span); + filter!(self.span_utils, sub_span, typ.span, None); + + let type_data = self.lookup_ref_id(typ.id); + type_data.map(|type_data| Data::RelationData(Relation { + kind: RelationKind::Impl, + span: self.span_from_span(sub_span.unwrap()), + from: id_from_def_id(type_data), + to: trait_ref.as_ref() + .and_then(|t| self.lookup_ref_id(t.ref_id)) + .map(id_from_def_id) + .unwrap_or(null_id()), + })) + } else { + None } - - let trait_data = trait_ref.as_ref() - .and_then(|tr| self.get_trait_ref_data(tr, parent)); - - filter!(self.span_utils, sub_span, typ.span, None); - Some(Data::ImplData(ImplData2 { - id: item.id, - span: sub_span.unwrap(), - scope: parent, - trait_ref: trait_data, - self_ref: type_data, - })) } _ => { // FIXME @@ -337,7 +347,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { pub fn get_field_data(&self, field: &ast::StructField, scope: NodeId) - -> Option { + -> Option { if let Some(ident) = field.ident { let name = ident.to_string(); let qualname = format!("::{}::{}", self.tcx.node_path_str(scope), ident); @@ -346,32 +356,23 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let def_id = self.tcx.hir.local_def_id(field.id); let typ = self.tcx.type_of(def_id).to_string(); - let span = field.span; - let text = self.span_utils.snippet(field.span); - let ident_start = text.find(&name).unwrap(); - let ident_end = ident_start + name.len(); - let sig = Signature { - span: span, - text: text, - ident_start: ident_start, - ident_end: ident_end, - defs: vec![], - refs: vec![], - }; - Some(VariableData { - id: field.id, - kind: VariableKind::Field, - name: name, - qualname: qualname, - span: sub_span.unwrap(), - scope: scope, - parent: Some(make_def_id(scope, &self.tcx.hir)), - value: "".to_owned(), - type_value: typ, - visibility: From::from(&field.vis), + + let id = id_from_node_id(field.id, self); + let span = self.span_from_span(sub_span.unwrap()); + + Some(Def { + kind: DefKind::Field, + id, + span, + name, + qualname, + value: typ, + parent: Some(id_from_node_id(scope, self)), + children: vec![], + decl_id: None, docs: docs_for_attrs(&field.attrs), - sig: Some(sig), - attributes: field.attrs.clone(), + sig: sig::field_signature(field, self), + attributes: lower_attributes(field.attrs.clone(), self), }) } else { None @@ -380,11 +381,14 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { // FIXME would be nice to take a MethodItem here, but the ast provides both // trait and impl flavours, so the caller must do the disassembly. - pub fn get_method_data(&self, id: ast::NodeId, - name: ast::Name, span: Span) -> Option { + pub fn get_method_data(&self, + id: ast::NodeId, + name: ast::Name, + span: Span) + -> Option { // The qualname for a method is the trait name or name of the struct in an impl in // which the method is declared in, followed by the method's name. - let (qualname, parent_scope, decl_id, vis, docs, attributes) = + let (qualname, parent_scope, decl_id, docs, attributes) = match self.tcx.impl_of_method(self.tcx.hir.local_def_id(id)) { Some(impl_id) => match self.tcx.hir.get_if_local(impl_id) { Some(Node::NodeItem(item)) => { @@ -393,7 +397,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let mut result = String::from("<"); result.push_str(&self.tcx.hir.node_to_pretty_string(ty.id)); - let trait_id = self.tcx.trait_id_of_impl(impl_id); + let mut trait_id = self.tcx.trait_id_of_impl(impl_id); let mut decl_id = None; if let Some(def_id) = trait_id { result.push_str(" as "); @@ -401,11 +405,16 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { self.tcx.associated_items(def_id) .find(|item| item.name == name) .map(|item| decl_id = Some(item.def_id)); + } else { + if let Some(NodeItem(item)) = self.tcx.hir.find(id) { + if let hir::ItemImpl(_, _, _, _, _, ref ty, _) = item.node { + trait_id = self.lookup_ref_id(ty.id); + } + } } result.push_str(">"); (result, trait_id, decl_id, - From::from(&item.vis), docs_for_attrs(&item.attrs), item.attrs.to_vec()) } @@ -431,7 +440,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { Some(Node::NodeItem(item)) => { (format!("::{}", self.tcx.item_path_str(def_id)), Some(def_id), None, - From::from(&item.vis), docs_for_attrs(&item.attrs), item.attrs.to_vec()) } @@ -459,40 +467,26 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let sub_span = self.span_utils.sub_span_after_keyword(span, keywords::Fn); filter!(self.span_utils, sub_span, span, None); - let name = name.to_string(); - let text = self.span_utils.signature_string_for_span(span); - let ident_start = text.find(&name).unwrap(); - let ident_end = ident_start + name.len(); - let sig = Signature { - span: span, - text: text, - ident_start: ident_start, - ident_end: ident_end, - defs: vec![], - refs: vec![], - }; - - Some(FunctionData { - id: id, - name: name, - qualname: qualname, - declaration: decl_id, - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), + Some(Def { + kind: DefKind::Method, + id: id_from_node_id(id, self), + span: self.span_from_span(sub_span.unwrap()), + name: name.to_string(), + qualname, // FIXME you get better data here by using the visitor. value: String::new(), - visibility: vis, - parent: parent_scope, - docs: docs, - sig: sig, - attributes: attributes, + parent: parent_scope.map(|id| id_from_def_id(id)), + children: vec![], + decl_id: decl_id.map(|id| id_from_def_id(id)), + docs, + sig: None, + attributes: lower_attributes(attributes, self), }) } pub fn get_trait_ref_data(&self, - trait_ref: &ast::TraitRef, - parent: NodeId) - -> Option { + trait_ref: &ast::TraitRef) + -> Option { self.lookup_ref_id(trait_ref.ref_id).and_then(|def_id| { let span = trait_ref.path.span; if generated_code(span) { @@ -500,11 +494,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } let sub_span = self.span_utils.sub_span_for_type_name(span).or(Some(span)); filter!(self.span_utils, sub_span, span, None); - Some(TypeRefData { - span: sub_span.unwrap(), - scope: parent, - ref_id: Some(def_id), - qualname: String::new() // FIXME: generate the real qualname + let span = self.span_from_span(sub_span.unwrap()); + Some(Ref { + kind: RefKind::Type, + span, + ref_id: id_from_def_id(def_id), }) }) } @@ -530,11 +524,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let f = def.struct_variant().field_named(ident.node.name); let sub_span = self.span_utils.span_for_last_ident(expr.span); filter!(self.span_utils, sub_span, expr.span, None); - return Some(Data::VariableRefData(VariableRefData { - name: ident.node.to_string(), - span: sub_span.unwrap(), - scope: self.enclosing_scope(expr.id), - ref_id: f.did, + let span = self.span_from_span(sub_span.unwrap()); + return Some(Data::RefData(Ref { + kind: RefKind::Variable, + span, + ref_id: id_from_def_id(f.did), })); } _ => { @@ -548,11 +542,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ty::TyAdt(def, _) if !def.is_enum() => { let sub_span = self.span_utils.span_for_last_ident(path.span); filter!(self.span_utils, sub_span, path.span, None); - Some(Data::TypeRefData(TypeRefData { - span: sub_span.unwrap(), - scope: self.enclosing_scope(expr.id), - ref_id: Some(def.did), - qualname: String::new() // FIXME: generate the real qualname + let span = self.span_from_span(sub_span.unwrap()); + Some(Data::RefData(Ref { + kind: RefKind::Type, + span, + ref_id: id_from_def_id(def.did), })) } _ => { @@ -571,16 +565,15 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { }; let sub_span = self.span_utils.sub_span_for_meth_name(expr.span); filter!(self.span_utils, sub_span, expr.span, None); - let parent = self.enclosing_scope(expr.id); - Some(Data::MethodCallData(MethodCallData { - span: sub_span.unwrap(), - scope: parent, - ref_id: def_id, - decl_id: decl_id, + let span = self.span_from_span(sub_span.unwrap()); + Some(Data::RefData(Ref { + kind: RefKind::Function, + span, + ref_id: def_id.or(decl_id).map(|id| id_from_def_id(id)).unwrap_or(null_id()), })) } ast::ExprKind::Path(_, ref path) => { - self.get_path_data(expr.id, path) + self.get_path_data(expr.id, path).map(|d| Data::RefData(d)) } _ => { // FIXME @@ -589,7 +582,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } - pub fn get_path_def(&self, id: NodeId) -> Def { + pub fn get_path_def(&self, id: NodeId) -> HirDef { match self.tcx.hir.get(id) { Node::NodeTraitRef(tr) => tr.path.def, @@ -605,7 +598,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } Node::NodeLocal(&hir::Pat { node: hir::PatKind::Binding(_, def_id, ..), .. }) => { - Def::Local(def_id) + HirDef::Local(def_id) } Node::NodeTy(ty) => { @@ -615,61 +608,55 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { hir::QPath::TypeRelative(..) => { let ty = hir_ty_to_ty(self.tcx, ty); if let ty::TyProjection(proj) = ty.sty { - for item in self.tcx.associated_items(proj.trait_ref.def_id) { - if item.kind == ty::AssociatedKind::Type { - if item.name == proj.item_name(self.tcx) { - return Def::AssociatedTy(item.def_id); - } - } - } + return HirDef::AssociatedTy(proj.item_def_id); } - Def::Err + HirDef::Err } } } else { - Def::Err + HirDef::Err } } - _ => Def::Err + _ => HirDef::Err } } - pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option { + pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option { let def = self.get_path_def(id); let sub_span = self.span_utils.span_for_last_ident(path.span); filter!(self.span_utils, sub_span, path.span, None); match def { - Def::Upvar(..) | - Def::Local(..) | - Def::Static(..) | - Def::Const(..) | - Def::AssociatedConst(..) | - Def::StructCtor(..) | - Def::VariantCtor(..) => { - Some(Data::VariableRefData(VariableRefData { - name: self.span_utils.snippet(sub_span.unwrap()), - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - ref_id: def.def_id(), - })) + HirDef::Upvar(..) | + HirDef::Local(..) | + HirDef::Static(..) | + HirDef::Const(..) | + HirDef::AssociatedConst(..) | + HirDef::StructCtor(..) | + HirDef::VariantCtor(..) => { + let span = self.span_from_span(sub_span.unwrap()); + Some(Ref { + kind: RefKind::Variable, + span, + ref_id: id_from_def_id(def.def_id()), + }) } - Def::Struct(def_id) | - Def::Variant(def_id, ..) | - Def::Union(def_id) | - Def::Enum(def_id) | - Def::TyAlias(def_id) | - Def::AssociatedTy(def_id) | - Def::Trait(def_id) | - Def::TyParam(def_id) => { - Some(Data::TypeRefData(TypeRefData { - span: sub_span.unwrap(), - ref_id: Some(def_id), - scope: self.enclosing_scope(id), - qualname: String::new() // FIXME: generate the real qualname - })) + HirDef::Struct(def_id) | + HirDef::Variant(def_id, ..) | + HirDef::Union(def_id) | + HirDef::Enum(def_id) | + HirDef::TyAlias(def_id) | + HirDef::AssociatedTy(def_id) | + HirDef::Trait(def_id) | + HirDef::TyParam(def_id) => { + let span = self.span_from_span(sub_span.unwrap()); + Some(Ref { + kind: RefKind::Type, + span, + ref_id: id_from_def_id(def_id), + }) } - Def::Method(decl_id) => { + HirDef::Method(decl_id) => { let sub_span = self.span_utils.sub_span_for_meth_name(path.span); filter!(self.span_utils, sub_span, path.span, None); let def_id = if decl_id.is_local() { @@ -680,60 +667,60 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } else { None }; - Some(Data::MethodCallData(MethodCallData { - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - ref_id: def_id, - decl_id: Some(decl_id), - })) + let span = self.span_from_span(sub_span.unwrap()); + Some(Ref { + kind: RefKind::Function, + span, + ref_id: id_from_def_id(def_id.unwrap_or(decl_id)), + }) } - Def::Fn(def_id) => { - Some(Data::FunctionCallData(FunctionCallData { - ref_id: def_id, - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - })) + HirDef::Fn(def_id) => { + let span = self.span_from_span(sub_span.unwrap()); + Some(Ref { + kind: RefKind::Function, + span, + ref_id: id_from_def_id(def_id), + }) } - Def::Mod(def_id) => { - Some(Data::ModRefData(ModRefData { - ref_id: Some(def_id), - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - qualname: String::new() // FIXME: generate the real qualname - })) + HirDef::Mod(def_id) => { + let span = self.span_from_span(sub_span.unwrap()); + Some(Ref { + kind: RefKind::Mod, + span, + ref_id: id_from_def_id(def_id), + }) } - Def::PrimTy(..) | - Def::SelfTy(..) | - Def::Label(..) | - Def::Macro(..) | - Def::GlobalAsm(..) | - Def::Err => None, + HirDef::PrimTy(..) | + HirDef::SelfTy(..) | + HirDef::Label(..) | + HirDef::Macro(..) | + HirDef::GlobalAsm(..) | + HirDef::Err => None, } } pub fn get_field_ref_data(&self, field_ref: &ast::Field, - variant: &ty::VariantDef, - parent: NodeId) - -> Option { + variant: &ty::VariantDef) + -> Option { let f = variant.field_named(field_ref.ident.node.name); // We don't really need a sub-span here, but no harm done let sub_span = self.span_utils.span_for_last_ident(field_ref.ident.span); filter!(self.span_utils, sub_span, field_ref.ident.span, None); - Some(VariableRefData { - name: field_ref.ident.node.to_string(), - span: sub_span.unwrap(), - scope: parent, - ref_id: f.did, + let span = self.span_from_span(sub_span.unwrap()); + Some(Ref { + kind: RefKind::Variable, + span, + ref_id: id_from_def_id(f.did), }) } - /// Attempt to return MacroUseData for any AST node. + /// Attempt to return MacroRef for any AST node. /// /// For a given piece of AST defined by the supplied Span and NodeId, /// returns None if the node is not macro-generated or the span is malformed, - /// else uses the expansion callsite and callee to return some MacroUseData. - pub fn get_macro_use_data(&self, span: Span, id: NodeId) -> Option { + /// else uses the expansion callsite and callee to return some MacroRef. + pub fn get_macro_use_data(&self, span: Span) -> Option { if !generated_code(span) { return None; } @@ -741,6 +728,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { // nested expansions and ensure we only generate data for source-visible // macro uses. let callsite = span.source_callsite(); + let callsite_span = self.span_from_span(callsite); let callee = option_try!(span.source_callee()); let callee_span = option_try!(callee.span); @@ -754,68 +742,29 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { // when read in, and no longer correspond to the source. if let Some(mac) = self.tcx.sess.imported_macro_spans.borrow().get(&callee_span) { let &(ref mac_name, mac_span) = mac; - return Some(MacroUseData { - span: callsite, - name: mac_name.clone(), - callee_span: mac_span, - scope: self.enclosing_scope(id), - imported: true, - qualname: String::new()// FIXME: generate the real qualname - }); + let mac_span = self.span_from_span(mac_span); + return Some(MacroRef { + span: callsite_span, + qualname: mac_name.clone(), // FIXME: generate the real qualname + callee_span: mac_span, + }); } - Some(MacroUseData { - span: callsite, - name: callee.name().to_string(), - callee_span: callee_span, - scope: self.enclosing_scope(id), - imported: false, - qualname: String::new() // FIXME: generate the real qualname + let callee_span = self.span_from_span(callee_span); + Some(MacroRef { + span: callsite_span, + qualname: callee.name().to_string(), // FIXME: generate the real qualname + callee_span, }) } - pub fn get_data_for_id(&self, _id: &NodeId) -> Data { - // FIXME - bug!(); - } - fn lookup_ref_id(&self, ref_id: NodeId) -> Option { match self.get_path_def(ref_id) { - Def::PrimTy(_) | Def::SelfTy(..) | Def::Err => None, + HirDef::PrimTy(_) | HirDef::SelfTy(..) | HirDef::Err => None, def => Some(def.def_id()), } } - fn sig_base(&self, item: &ast::Item) -> Signature { - let text = self.span_utils.signature_string_for_span(item.span); - let name = item.ident.to_string(); - let ident_start = text.find(&name).expect("Name not in signature?"); - let ident_end = ident_start + name.len(); - Signature { - span: Span { hi: item.span.lo + BytePos(text.len() as u32), ..item.span }, - text: text, - ident_start: ident_start, - ident_end: ident_end, - defs: vec![], - refs: vec![], - } - } - - fn sig_base_extern(&self, item: &ast::ForeignItem) -> Signature { - let text = self.span_utils.signature_string_for_span(item.span); - let name = item.ident.to_string(); - let ident_start = text.find(&name).expect("Name not in signature?"); - let ident_end = ident_start + name.len(); - Signature { - span: Span { hi: item.span.lo + BytePos(text.len() as u32), ..item.span }, - text: text, - ident_start: ident_start, - ident_end: ident_end, - defs: vec![], - refs: vec![], - } - } - #[inline] pub fn enclosing_scope(&self, id: NodeId) -> NodeId { self.tcx.hir.get_enclosing_scope(id).unwrap_or(CRATE_NODE_ID) @@ -853,7 +802,7 @@ fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String { // An AST visitor for collecting paths from patterns. struct PathCollector { // The Row field identifies the kind of pattern. - collected_paths: Vec<(NodeId, ast::Path, ast::Mutability, recorder::Row)>, + collected_paths: Vec<(NodeId, ast::Path, ast::Mutability)>, } impl PathCollector { @@ -867,12 +816,12 @@ impl<'a> Visitor<'a> for PathCollector { match p.node { PatKind::Struct(ref path, ..) => { self.collected_paths.push((p.id, path.clone(), - ast::Mutability::Mutable, recorder::TypeRef)); + ast::Mutability::Mutable)); } PatKind::TupleStruct(ref path, ..) | PatKind::Path(_, ref path) => { self.collected_paths.push((p.id, path.clone(), - ast::Mutability::Mutable, recorder::VarRef)); + ast::Mutability::Mutable)); } PatKind::Ident(bm, ref path1, _) => { debug!("PathCollector, visit ident in pat {}: {:?} {:?}", @@ -888,7 +837,7 @@ impl<'a> Visitor<'a> for PathCollector { }; // collect path for either visit_local or visit_arm let path = ast::Path::from_ident(path1.span, path1.node); - self.collected_paths.push((p.id, path, immut, recorder::VarRef)); + self.collected_paths.push((p.id, path, immut)); } _ => {} } @@ -917,17 +866,13 @@ fn docs_for_attrs(attrs: &[Attribute]) -> String { #[derive(Clone, Copy, Debug, RustcEncodable)] pub enum Format { - Csv, Json, JsonApi, } impl Format { fn extension(&self) -> &'static str { - match *self { - Format::Csv => ".csv", - Format::Json | Format::JsonApi => ".json", - } + ".json" } } @@ -1010,7 +955,6 @@ impl<'a> SaveHandler for DumpHandler<'a> { let output = &mut self.output_file(&save_ctxt.tcx.sess); match self.format { - Format::Csv => dump!(CsvDumper::new(output)), Format::Json => dump!(JsonDumper::new(output)), Format::JsonApi => dump!(JsonApiDumper::new(output)), } @@ -1076,6 +1020,48 @@ fn escape(s: String) -> String { // Helper function to determine if a span came from a // macro expansion or syntax extension. -pub fn generated_code(span: Span) -> bool { +fn generated_code(span: Span) -> bool { span.ctxt != NO_EXPANSION || span == DUMMY_SP } + +// DefId::index is a newtype and so the JSON serialisation is ugly. Therefore +// we use our own Id which is the same, but without the newtype. +fn id_from_def_id(id: DefId) -> rls_data::Id { + rls_data::Id { + krate: id.krate.as_u32(), + index: id.index.as_u32(), + } +} + +fn id_from_node_id(id: NodeId, scx: &SaveContext) -> rls_data::Id { + let def_id = scx.tcx.hir.opt_local_def_id(id); + def_id.map(|id| id_from_def_id(id)).unwrap_or_else(null_id) +} + +fn null_id() -> rls_data::Id { + rls_data::Id { + krate: u32::max_value(), + index: u32::max_value(), + } +} + +fn lower_attributes(attrs: Vec, scx: &SaveContext) -> Vec { + attrs.into_iter() + // Only retain real attributes. Doc comments are lowered separately. + .filter(|attr| attr.path != "doc") + .map(|mut attr| { + // Remove the surrounding '#[..]' or '#![..]' of the pretty printed + // attribute. First normalize all inner attribute (#![..]) to outer + // ones (#[..]), then remove the two leading and the one trailing character. + attr.style = ast::AttrStyle::Outer; + let value = pprust::attribute_to_string(&attr); + // This str slicing works correctly, because the leading and trailing characters + // are in the ASCII range and thus exactly one byte each. + let value = value[2..value.len()-1].to_string(); + + rls_data::Attribute { + value: value, + span: scx.span_from_span(attr.span), + } + }).collect() +} diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs new file mode 100644 index 0000000000..1d03ab1383 --- /dev/null +++ b/src/librustc_save_analysis/sig.rs @@ -0,0 +1,925 @@ +// 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. + +// A signature is a string representation of an item's type signature, excluding +// any body. It also includes ids for any defs or refs in the signature. For +// example: +// +// ``` +// fn foo(x: String) { +// println!("{}", x); +// } +// ``` +// The signature string is something like "fn foo(x: String) {}" and the signature +// will have defs for `foo` and `x` and a ref for `String`. +// +// All signature text should parse in the correct context (i.e., in a module or +// impl, etc.). Clients may want to trim trailing `{}` or `;`. The text of a +// signature is not guaranteed to be stable (it may improve or change as the +// syntax changes, or whitespace or punctuation may change). It is also likely +// not to be pretty - no attempt is made to prettify the text. It is recommended +// that clients run the text through Rustfmt. +// +// This module generates Signatures for items by walking the AST and looking up +// references. +// +// Signatures do not include visibility info. I'm not sure if this is a feature +// or an ommission (FIXME). +// +// FIXME where clauses need implementing, defs/refs in generics are mostly missing. + +use {SaveContext, id_from_def_id, id_from_node_id}; + +use rls_data::{Signature, SigElement}; + +use rustc::hir::def::Def; +use syntax::ast::{self, NodeId}; +use syntax::print::pprust; + + +pub fn item_signature(item: &ast::Item, scx: &SaveContext) -> Option { + item.make(0, None, scx).ok() +} + +pub fn foreign_item_signature(item: &ast::ForeignItem, scx: &SaveContext) -> Option { + item.make(0, None, scx).ok() +} + +/// Signature for a struct or tuple field declaration. +/// Does not include a trailing comma. +pub fn field_signature(field: &ast::StructField, scx: &SaveContext) -> Option { + field.make(0, None, scx).ok() +} + +/// Does not include a trailing comma. +pub fn variant_signature(variant: &ast::Variant, scx: &SaveContext) -> Option { + variant.node.make(0, None, scx).ok() +} + +pub fn method_signature(id: NodeId, + ident: ast::Ident, + m: &ast::MethodSig, + scx: &SaveContext) + -> Option { + make_method_signature(id, ident, m, scx).ok() +} + +pub fn assoc_const_signature(id: NodeId, + ident: ast::Name, + ty: &ast::Ty, + default: Option<&ast::Expr>, + scx: &SaveContext) + -> Option { + make_assoc_const_signature(id, ident, ty, default, scx).ok() +} + +pub fn assoc_type_signature(id: NodeId, + ident: ast::Ident, + bounds: Option<&ast::TyParamBounds>, + default: Option<&ast::Ty>, + scx: &SaveContext) + -> Option { + make_assoc_type_signature(id, ident, bounds, default, scx).ok() +} + +type Result = ::std::result::Result; + +trait Sig { + fn make(&self, offset: usize, id: Option, scx: &SaveContext) -> Result; +} + +fn extend_sig(mut sig: Signature, + text: String, + defs: Vec, + refs: Vec) + -> Signature { + sig.text = text; + sig.defs.extend(defs.into_iter()); + sig.refs.extend(refs.into_iter()); + sig +} + +fn replace_text(mut sig: Signature, text: String) -> Signature { + sig.text = text; + sig +} + +fn merge_sigs(text: String, sigs: Vec) -> Signature { + let mut result = Signature { + text, + defs: vec![], + refs: vec![], + }; + + let (defs, refs): (Vec<_>, Vec<_>) = sigs.into_iter().map(|s| (s.defs, s.refs)).unzip(); + + result.defs.extend(defs.into_iter().flat_map(|ds| ds.into_iter())); + result.refs.extend(refs.into_iter().flat_map(|rs| rs.into_iter())); + + result +} + +fn text_sig(text: String) -> Signature { + Signature { + text: text, + defs: vec![], + refs: vec![], + } +} + +impl Sig for ast::Ty { + fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext) -> Result { + let id = Some(self.id); + match self.node { + ast::TyKind::Slice(ref ty) => { + let nested = ty.make(offset + 1, id, scx)?; + let text = format!("[{}]", nested.text); + Ok(replace_text(nested, text)) + } + ast::TyKind::Ptr(ref mt) => { + let prefix = match mt.mutbl { + ast::Mutability::Mutable => "*mut ", + ast::Mutability::Immutable => "*const ", + }; + let nested = mt.ty.make(offset + prefix.len(), id, scx)?; + let text = format!("{}{}", prefix, nested.text); + Ok(replace_text(nested, text)) + } + ast::TyKind::Rptr(ref lifetime, ref mt) => { + let mut prefix = "&".to_owned(); + if let &Some(ref l) = lifetime { + prefix.push_str(&l.ident.to_string()); + prefix.push(' '); + } + if let ast::Mutability::Mutable = mt.mutbl { + prefix.push_str("mut "); + }; + + let nested = mt.ty.make(offset + prefix.len(), id, scx)?; + let text = format!("{}{}", prefix, nested.text); + Ok(replace_text(nested, text)) + } + ast::TyKind::Never => { + Ok(text_sig("!".to_owned())) + }, + ast::TyKind::Tup(ref ts) => { + let mut text = "(".to_owned(); + let mut defs = vec![]; + let mut refs = vec![]; + for t in ts { + let nested = t.make(offset + text.len(), id, scx)?; + text.push_str(&nested.text); + text.push(','); + defs.extend(nested.defs.into_iter()); + refs.extend(nested.refs.into_iter()); + } + text.push(')'); + Ok(Signature { text, defs, refs }) + } + ast::TyKind::Paren(ref ty) => { + let nested = ty.make(offset + 1, id, scx)?; + let text = format!("({})", nested.text); + Ok(replace_text(nested, text)) + } + ast::TyKind::BareFn(ref f) => { + let mut text = String::new(); + if !f.lifetimes.is_empty() { + // FIXME defs, bounds on lifetimes + text.push_str("for<"); + text.push_str(&f.lifetimes.iter().map(|l| + l.lifetime.ident.to_string()).collect::>().join(", ")); + text.push('>'); + } + + if f.unsafety == ast::Unsafety::Unsafe { + text.push_str("unsafe "); + } + if f.abi != ::syntax::abi::Abi::Rust { + text.push_str("extern"); + text.push_str(&f.abi.to_string()); + text.push(' '); + } + text.push_str("fn("); + + let mut defs = vec![]; + let mut refs = vec![]; + for i in &f.decl.inputs { + let nested = i.ty.make(offset + text.len(), Some(i.id), scx)?; + text.push_str(&nested.text); + text.push(','); + defs.extend(nested.defs.into_iter()); + refs.extend(nested.refs.into_iter()); + } + text.push(')'); + if let ast::FunctionRetTy::Ty(ref t) = f.decl.output { + text.push_str(" -> "); + let nested = t.make(offset + text.len(), None, scx)?; + text.push_str(&nested.text); + text.push(','); + defs.extend(nested.defs.into_iter()); + refs.extend(nested.refs.into_iter()); + } + + Ok(Signature { text, defs, refs }) + } + ast::TyKind::Path(None, ref path) => { + path.make(offset, id, scx) + } + ast::TyKind::Path(Some(ref qself), ref path) => { + let nested_ty = qself.ty.make(offset + 1, id, scx)?; + let prefix = if qself.position == 0 { + format!("<{}>::", nested_ty.text) + } else if qself.position == 1 { + let first = pprust::path_segment_to_string(&path.segments[0]); + format!("<{} as {}>::", nested_ty.text, first) + } else { + // FIXME handle path instead of elipses. + format!("<{} as ...>::", nested_ty.text) + }; + + let name = pprust::path_segment_to_string(path.segments.last().ok_or("Bad path")?); + let def = scx.get_path_def(id.ok_or("Missing id for Path")?); + let id = id_from_def_id(def.def_id()); + if path.segments.len() - qself.position == 1 { + let start = offset + prefix.len(); + let end = start + name.len(); + + Ok(Signature { + text: prefix + &name, + defs: vec![], + refs: vec![SigElement { id, start, end }], + }) + } else { + let start = offset + prefix.len() + 5; + let end = start + name.len(); + // FIXME should put the proper path in there, not elipses. + Ok(Signature { + text: prefix + "...::" + &name, + defs: vec![], + refs: vec![SigElement { id, start, end }], + }) + } + } + ast::TyKind::TraitObject(ref bounds) => { + // FIXME recurse into bounds + let nested = pprust::bounds_to_string(bounds); + Ok(text_sig(nested)) + } + ast::TyKind::ImplTrait(ref bounds) => { + // FIXME recurse into bounds + let nested = pprust::bounds_to_string(bounds); + Ok(text_sig(format!("impl {}", nested))) + } + ast::TyKind::Array(ref ty, ref v) => { + let nested_ty = ty.make(offset + 1, id, scx)?; + let expr = pprust::expr_to_string(v).replace('\n', " "); + let text = format!("[{}; {}]", nested_ty.text, expr); + Ok(replace_text(nested_ty, text)) + } + ast::TyKind::Typeof(_) | + ast::TyKind::Infer | + ast::TyKind::Err | + ast::TyKind::ImplicitSelf | + ast::TyKind::Mac(_) => Err("Ty"), + } + } +} + +impl Sig for ast::Item { + fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext) -> Result { + let id = Some(self.id); + + match self.node { + ast::ItemKind::Static(ref ty, m, ref expr) => { + let mut text = "static ".to_owned(); + if m == ast::Mutability::Mutable { + text.push_str("mut "); + } + let name = self.ident.to_string(); + let defs = vec![SigElement { + id: id_from_node_id(self.id, scx), + start: offset + text.len(), + end: offset + text.len() + name.len(), + }]; + text.push_str(&name); + text.push_str(": "); + + let ty = ty.make(offset + text.len(), id, scx)?; + text.push_str(&ty.text); + text.push_str(" = "); + + let expr = pprust::expr_to_string(expr).replace('\n', " "); + text.push_str(&expr); + text.push(';'); + + Ok(extend_sig(ty, text, defs, vec![])) + } + ast::ItemKind::Const(ref ty, ref expr) => { + let mut text = "const ".to_owned(); + let name = self.ident.to_string(); + let defs = vec![SigElement { + id: id_from_node_id(self.id, scx), + start: offset + text.len(), + end: offset + text.len() + name.len(), + }]; + text.push_str(&name); + text.push_str(": "); + + let ty = ty.make(offset + text.len(), id, scx)?; + text.push_str(&ty.text); + text.push_str(" = "); + + let expr = pprust::expr_to_string(expr).replace('\n', " "); + text.push_str(&expr); + text.push(';'); + + Ok(extend_sig(ty, text, defs, vec![])) + } + ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, _) => { + let mut text = String::new(); + if constness.node == ast::Constness::Const { + text.push_str("const "); + } + if unsafety == ast::Unsafety::Unsafe { + text.push_str("unsafe "); + } + if abi != ::syntax::abi::Abi::Rust { + text.push_str("extern"); + text.push_str(&abi.to_string()); + text.push(' '); + } + text.push_str("fn "); + + let mut sig = name_and_generics(text, + offset, + generics, + self.id, + self.ident, + scx)?; + + sig.text.push('('); + for i in &decl.inputs { + // FIXME shoudl descend into patterns to add defs. + sig.text.push_str(&pprust::pat_to_string(&i.pat)); + sig.text.push_str(": "); + let nested = i.ty.make(offset + sig.text.len(), Some(i.id), scx)?; + sig.text.push_str(&nested.text); + sig.text.push(','); + sig.defs.extend(nested.defs.into_iter()); + sig.refs.extend(nested.refs.into_iter()); + } + sig.text.push(')'); + + if let ast::FunctionRetTy::Ty(ref t) = decl.output { + sig.text.push_str(" -> "); + let nested = t.make(offset + sig.text.len(), None, scx)?; + sig.text.push_str(&nested.text); + sig.defs.extend(nested.defs.into_iter()); + sig.refs.extend(nested.refs.into_iter()); + } + sig.text.push_str(" {}"); + + Ok(sig) + } + ast::ItemKind::Mod(ref _mod) => { + let mut text = "mod ".to_owned(); + let name = self.ident.to_string(); + let defs = vec![SigElement { + id: id_from_node_id(self.id, scx), + start: offset + text.len(), + end: offset + text.len() + name.len(), + }]; + text.push_str(&name); + // Could be either `mod foo;` or `mod foo { ... }`, but we'll just puck one. + text.push(';'); + + Ok(Signature { + text, + defs, + refs: vec![], + }) + } + ast::ItemKind::Ty(ref ty, ref generics) => { + let text = "type ".to_owned(); + let mut sig = name_and_generics(text, + offset, + generics, + self.id, + self.ident, + scx)?; + + sig.text.push_str(" = "); + let ty = ty.make(offset + sig.text.len(), id, scx)?; + sig.text.push_str(&ty.text); + sig.text.push(';'); + + Ok(merge_sigs(sig.text.clone(), vec![sig, ty])) + } + ast::ItemKind::Enum(_, ref generics) => { + let text = "enum ".to_owned(); + let mut sig = name_and_generics(text, + offset, + generics, + self.id, + self.ident, + scx)?; + sig.text.push_str(" {}"); + Ok(sig) + } + ast::ItemKind::Struct(_, ref generics) => { + let text = "struct ".to_owned(); + let mut sig = name_and_generics(text, + offset, + generics, + self.id, + self.ident, + scx)?; + sig.text.push_str(" {}"); + Ok(sig) + } + ast::ItemKind::Union(_, ref generics) => { + let text = "union ".to_owned(); + let mut sig = name_and_generics(text, + offset, + generics, + self.id, + self.ident, + scx)?; + sig.text.push_str(" {}"); + Ok(sig) + } + ast::ItemKind::Trait(unsafety, ref generics, ref bounds, _) => { + let mut text = String::new(); + if unsafety == ast::Unsafety::Unsafe { + text.push_str("unsafe "); + } + text.push_str("trait "); + let mut sig = name_and_generics(text, + offset, + generics, + self.id, + self.ident, + scx)?; + + if !bounds.is_empty() { + sig.text.push_str(": "); + sig.text.push_str(&pprust::bounds_to_string(bounds)); + } + // FIXME where clause + sig.text.push_str(" {}"); + + Ok(sig) + } + ast::ItemKind::DefaultImpl(unsafety, ref trait_ref) => { + let mut text = String::new(); + if unsafety == ast::Unsafety::Unsafe { + text.push_str("unsafe "); + } + text.push_str("impl "); + let trait_sig = trait_ref.path.make(offset + text.len(), id, scx)?; + text.push_str(&trait_sig.text); + text.push_str(" for .. {}"); + Ok(replace_text(trait_sig, text)) + } + ast::ItemKind::Impl(unsafety, + polarity, + defaultness, + ref generics, + ref opt_trait, + ref ty, + _) => { + let mut text = String::new(); + if let ast::Defaultness::Default = defaultness { + text.push_str("default "); + } + if unsafety == ast::Unsafety::Unsafe { + text.push_str("unsafe "); + } + text.push_str("impl"); + + let generics_sig = generics.make(offset + text.len(), id, scx)?; + text.push_str(&generics_sig.text); + + text.push(' '); + + let trait_sig = if let Some(ref t) = *opt_trait { + if polarity == ast::ImplPolarity::Negative { + text.push('!'); + } + let trait_sig = t.path.make(offset + text.len(), id, scx)?; + text.push_str(&trait_sig.text); + text.push_str(" for "); + trait_sig + } else { + text_sig(String::new()) + }; + + let ty_sig = ty.make(offset + text.len(), id, scx)?; + text.push_str(&ty_sig.text); + + text.push_str(" {}"); + + Ok(merge_sigs(text, vec![generics_sig, trait_sig, ty_sig])) + + // FIXME where clause + } + ast::ItemKind::ForeignMod(_) => Err("extern mod"), + ast::ItemKind::GlobalAsm(_) => Err("glboal asm"), + ast::ItemKind::ExternCrate(_) => Err("extern crate"), + // FIXME should implement this (e.g., pub use). + ast::ItemKind::Use(_) => Err("import"), + ast::ItemKind::Mac(..) | + ast::ItemKind::MacroDef(_) => Err("Macro"), + } + } +} + +impl Sig for ast::Path { + fn make(&self, offset: usize, id: Option, scx: &SaveContext) -> Result { + let def = scx.get_path_def(id.ok_or("Missing id for Path")?); + + let (name, start, end) = match def { + Def::Label(..) | + Def::PrimTy(..) | + Def::SelfTy(..) | + Def::Err => { + return Ok(Signature { + text: pprust::path_to_string(self), + defs: vec![], + refs: vec![], + }) + } + Def::AssociatedConst(..) | + Def::Variant(..) | + Def::VariantCtor(..) => { + let len = self.segments.len(); + if len < 2 { + return Err("Bad path"); + } + // FIXME: really we should descend into the generics here and add SigElements for + // them. + // FIXME: would be nice to have a def for the first path segment. + let seg1 = pprust::path_segment_to_string(&self.segments[len - 2]); + let seg2 = pprust::path_segment_to_string(&self.segments[len - 1]); + let start = offset + seg1.len() + 2; + (format!("{}::{}", seg1, seg2), start, start + seg2.len()) + } + _ => { + let name = pprust::path_segment_to_string(self.segments.last().ok_or("Bad path")?); + let end = offset + name.len(); + (name, offset, end) + } + }; + + let id = id_from_def_id(def.def_id()); + Ok(Signature { + text: name, + defs: vec![], + refs: vec![SigElement { id, start, end }], + }) + } +} + +// This does not cover the where clause, which must be processed separately. +impl Sig for ast::Generics { + fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext) -> Result { + let total = self.lifetimes.len() + self.ty_params.len(); + if total == 0 { + return Ok(text_sig(String::new())); + } + + let mut text = "<".to_owned(); + + let mut defs = vec![]; + for l in &self.lifetimes { + let mut l_text = l.lifetime.ident.to_string(); + defs.push(SigElement { + id: id_from_node_id(l.lifetime.id, scx), + start: offset + text.len(), + end: offset + text.len() + l_text.len(), + }); + + if !l.bounds.is_empty() { + l_text.push_str(": "); + let bounds = l.bounds.iter().map(|l| { + l.ident.to_string() + }).collect::>().join(" + "); + l_text.push_str(&bounds); + // FIXME add lifetime bounds refs. + } + text.push_str(&l_text); + text.push(','); + } + for t in &self.ty_params { + let mut t_text = t.ident.to_string(); + defs.push(SigElement { + id: id_from_node_id(t.id, scx), + start: offset + text.len(), + end: offset + text.len() + t_text.len(), + }); + + if !t.bounds.is_empty() { + t_text.push_str(": "); + t_text.push_str(&pprust::bounds_to_string(&t.bounds)); + // FIXME descend properly into bounds. + } + text.push_str(&t_text); + text.push(','); + } + + text.push('>'); + Ok(Signature {text, defs, refs: vec![] }) + } +} + +impl Sig for ast::StructField { + fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext) -> Result { + let mut text = String::new(); + let mut defs = None; + if let Some(ref ident) = self.ident { + text.push_str(&ident.to_string()); + defs = Some(SigElement { + id: id_from_node_id(self.id, scx), + start: offset, + end: offset + text.len(), + }); + text.push_str(": "); + } + + let mut ty_sig = self.ty.make(offset + text.len(), Some(self.id), scx)?; + text.push_str(&ty_sig.text); + ty_sig.text = text; + ty_sig.defs.extend(defs.into_iter()); + Ok(ty_sig) + } +} + + +impl Sig for ast::Variant_ { + fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext) -> Result { + let mut text = self.name.to_string(); + match self.data { + ast::VariantData::Struct(ref fields, id) => { + let name_def = SigElement { + id: id_from_node_id(id, scx), + start: offset, + end: offset + text.len(), + }; + text.push_str(" { "); + let mut defs = vec![name_def]; + let mut refs = vec![]; + for f in fields { + let field_sig = f.make(offset + text.len(), Some(id), scx)?; + text.push_str(&field_sig.text); + text.push_str(", "); + defs.extend(field_sig.defs.into_iter()); + refs.extend(field_sig.refs.into_iter()); + } + text.push('}'); + Ok(Signature { + text, + defs: defs, + refs: refs, + }) + } + ast::VariantData::Tuple(ref fields, id) => { + let name_def = SigElement { + id: id_from_node_id(id, scx), + start: offset, + end: offset + text.len(), + }; + text.push('('); + let mut defs = vec![name_def]; + let mut refs = vec![]; + for f in fields { + let field_sig = f.make(offset + text.len(), Some(id), scx)?; + text.push_str(&field_sig.text); + text.push_str(", "); + defs.extend(field_sig.defs.into_iter()); + refs.extend(field_sig.refs.into_iter()); + } + text.push(')'); + Ok(Signature { + text, + defs: defs, + refs: refs, + }) + } + ast::VariantData::Unit(id) => { + let name_def = SigElement { + id: id_from_node_id(id, scx), + start: offset, + end: offset + text.len(), + }; + Ok(Signature { + text, + defs: vec![name_def], + refs: vec![], + }) + } + } + } +} + +impl Sig for ast::ForeignItem { + fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext) -> Result { + let id = Some(self.id); + match self.node { + ast::ForeignItemKind::Fn(ref decl, ref generics) => { + let mut text = String::new(); + text.push_str("fn "); + + let mut sig = name_and_generics(text, + offset, + generics, + self.id, + self.ident, + scx)?; + + sig.text.push('('); + for i in &decl.inputs { + // FIXME should descend into patterns to add defs. + sig.text.push_str(&pprust::pat_to_string(&i.pat)); + sig.text.push_str(": "); + let nested = i.ty.make(offset + sig.text.len(), Some(i.id), scx)?; + sig.text.push_str(&nested.text); + sig.text.push(','); + sig.defs.extend(nested.defs.into_iter()); + sig.refs.extend(nested.refs.into_iter()); + } + sig.text.push(')'); + + if let ast::FunctionRetTy::Ty(ref t) = decl.output { + sig.text.push_str(" -> "); + let nested = t.make(offset + sig.text.len(), None, scx)?; + sig.text.push_str(&nested.text); + sig.defs.extend(nested.defs.into_iter()); + sig.refs.extend(nested.refs.into_iter()); + } + sig.text.push(';'); + + Ok(sig) + } + ast::ForeignItemKind::Static(ref ty, m) => { + let mut text = "static ".to_owned(); + if m { + text.push_str("mut "); + } + let name = self.ident.to_string(); + let defs = vec![SigElement { + id: id_from_node_id(self.id, scx), + start: offset + text.len(), + end: offset + text.len() + name.len(), + }]; + text.push_str(&name); + text.push_str(": "); + + let ty_sig = ty.make(offset + text.len(), id, scx)?; + text.push(';'); + + Ok(extend_sig(ty_sig, text, defs, vec![])) + } + } + } +} + +fn name_and_generics(mut text: String, + offset: usize, + generics: &ast::Generics, + id: NodeId, + name: ast::Ident, + scx: &SaveContext) + -> Result { + let name = name.to_string(); + let def = SigElement { + id: id_from_node_id(id, scx), + start: offset + text.len(), + end: offset + text.len() + name.len(), + }; + text.push_str(&name); + let generics: Signature = generics.make(offset + text.len(), Some(id), scx)?; + // FIXME where clause + let text = format!("{}{}", text, generics.text); + Ok(extend_sig(generics, text, vec![def], vec![])) +} + + +fn make_assoc_type_signature(id: NodeId, + ident: ast::Ident, + bounds: Option<&ast::TyParamBounds>, + default: Option<&ast::Ty>, + scx: &SaveContext) + -> Result { + let mut text = "type ".to_owned(); + let name = ident.to_string(); + let mut defs = vec![SigElement { + id: id_from_node_id(id, scx), + start: text.len(), + end: text.len() + name.len(), + }]; + let mut refs = vec![]; + text.push_str(&name); + if let Some(bounds) = bounds { + text.push_str(": "); + // FIXME should descend into bounds + text.push_str(&pprust::bounds_to_string(bounds)); + } + if let Some(default) = default { + text.push_str(" = "); + let ty_sig = default.make(text.len(), Some(id), scx)?; + text.push_str(&ty_sig.text); + defs.extend(ty_sig.defs.into_iter()); + refs.extend(ty_sig.refs.into_iter()); + } + text.push(';'); + Ok(Signature { text, defs, refs }) +} + +fn make_assoc_const_signature(id: NodeId, + ident: ast::Name, + ty: &ast::Ty, + default: Option<&ast::Expr>, + scx: &SaveContext) + -> Result { + let mut text = "const ".to_owned(); + let name = ident.to_string(); + let mut defs = vec![SigElement { + id: id_from_node_id(id, scx), + start: text.len(), + end: text.len() + name.len(), + }]; + let mut refs = vec![]; + text.push_str(&name); + text.push_str(": "); + + let ty_sig = ty.make(text.len(), Some(id), scx)?; + text.push_str(&ty_sig.text); + defs.extend(ty_sig.defs.into_iter()); + refs.extend(ty_sig.refs.into_iter()); + + if let Some(default) = default { + text.push_str(" = "); + text.push_str(&pprust::expr_to_string(default)); + } + text.push(';'); + Ok(Signature { text, defs, refs }) +} + +fn make_method_signature(id: NodeId, + ident: ast::Ident, + m: &ast::MethodSig, + scx: &SaveContext) + -> Result { + // FIXME code dup with function signature + let mut text = String::new(); + if m.constness.node == ast::Constness::Const { + text.push_str("const "); + } + if m.unsafety == ast::Unsafety::Unsafe { + text.push_str("unsafe "); + } + if m.abi != ::syntax::abi::Abi::Rust { + text.push_str("extern"); + text.push_str(&m.abi.to_string()); + text.push(' '); + } + text.push_str("fn "); + + let mut sig = name_and_generics(text, + 0, + &m.generics, + id, + ident, + scx)?; + + sig.text.push('('); + for i in &m.decl.inputs { + // FIXME shoudl descend into patterns to add defs. + sig.text.push_str(&pprust::pat_to_string(&i.pat)); + sig.text.push_str(": "); + let nested = i.ty.make(sig.text.len(), Some(i.id), scx)?; + sig.text.push_str(&nested.text); + sig.text.push(','); + sig.defs.extend(nested.defs.into_iter()); + sig.refs.extend(nested.refs.into_iter()); + } + sig.text.push(')'); + + if let ast::FunctionRetTy::Ty(ref t) = m.decl.output { + sig.text.push_str(" -> "); + let nested = t.make(sig.text.len(), None, scx)?; + sig.text.push_str(&nested.text); + sig.defs.extend(nested.defs.into_iter()); + sig.refs.extend(nested.refs.into_iter()); + } + sig.text.push_str(" {}"); + + Ok(sig) +} diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs index af3efb4809..77cde33e96 100644 --- a/src/librustc_save_analysis/span_utils.rs +++ b/src/librustc_save_analysis/span_utils.rs @@ -20,7 +20,6 @@ use syntax::ast; use syntax::parse::lexer::{self, StringReader}; use syntax::parse::token::{self, Token}; use syntax::symbol::keywords; -use syntax::tokenstream::TokenTree; use syntax_pos::*; #[derive(Clone)] @@ -277,45 +276,6 @@ impl<'a> SpanUtils<'a> { } } - /// `span` must be the span for an item such as a function or struct. This - /// function returns the program text from the start of the span until the - /// end of the 'signature' part, that is up to, but not including an opening - /// brace or semicolon. - pub fn signature_string_for_span(&self, span: Span) -> String { - let mut toks = self.retokenise_span(span); - toks.real_token(); - let mut toks = toks.parse_all_token_trees().unwrap().trees(); - let mut prev = toks.next().unwrap(); - - let first_span = prev.span(); - let mut angle_count = 0; - for tok in toks { - if let TokenTree::Token(_, ref tok) = prev { - angle_count += match *tok { - token::Eof => { break; } - token::Lt => 1, - token::Gt => -1, - token::BinOp(token::Shl) => 2, - token::BinOp(token::Shr) => -2, - _ => 0, - }; - } - if angle_count > 0 { - prev = tok; - continue; - } - if let TokenTree::Token(_, token::Semi) = tok { - return self.snippet(first_span.to(prev.span())); - } else if let TokenTree::Delimited(_, ref d) = tok { - if d.delim == token::Brace { - return self.snippet(first_span.to(prev.span())); - } - } - prev = tok; - } - self.snippet(span) - } - pub fn sub_span_before_token(&self, span: Span, tok: Token) -> Option { let mut toks = self.retokenise_span(span); let mut prev = toks.real_token(); @@ -385,57 +345,44 @@ impl<'a> SpanUtils<'a> { self.spans_with_brackets(span, 1, number) } - pub fn report_span_err(&self, kind: &str, span: Span) { - let loc = self.sess.codemap().lookup_char_pos(span.lo); - info!("({}) Could not find sub_span in `{}` in {}, line {}", - kind, - self.snippet(span), - loc.file.name, - loc.line); - self.err_count.set(self.err_count.get() + 1); - if self.err_count.get() > 1000 { - bug!("span errors reached 1000, giving up"); - } - } - - // Return the name for a macro definition (identifier after first `!`) - pub fn span_for_macro_def_name(&self, span: Span) -> Option { - let mut toks = self.retokenise_span(span); - loop { - let ts = toks.real_token(); - if ts.tok == token::Eof { - return None; - } - if ts.tok == token::Not { - let ts = toks.real_token(); - if ts.tok.is_ident() { - return Some(ts.sp); - } else { - return None; - } - } - } - } - - // Return the name for a macro use (identifier before first `!`). - pub fn span_for_macro_use_name(&self, span:Span) -> Option { - let mut toks = self.retokenise_span(span); - let mut prev = toks.real_token(); - loop { - if prev.tok == token::Eof { - return None; - } - let ts = toks.real_token(); - if ts.tok == token::Not { - if prev.tok.is_ident() { - return Some(prev.sp); - } else { - return None; - } - } - prev = ts; - } - } + // // Return the name for a macro definition (identifier after first `!`) + // pub fn span_for_macro_def_name(&self, span: Span) -> Option { + // let mut toks = self.retokenise_span(span); + // loop { + // let ts = toks.real_token(); + // if ts.tok == token::Eof { + // return None; + // } + // if ts.tok == token::Not { + // let ts = toks.real_token(); + // if ts.tok.is_ident() { + // return Some(ts.sp); + // } else { + // return None; + // } + // } + // } + // } + + // // Return the name for a macro use (identifier before first `!`). + // pub fn span_for_macro_use_name(&self, span:Span) -> Option { + // let mut toks = self.retokenise_span(span); + // let mut prev = toks.real_token(); + // loop { + // if prev.tok == token::Eof { + // return None; + // } + // let ts = toks.real_token(); + // if ts.tok == token::Not { + // if prev.tok.is_ident() { + // return Some(prev.sp); + // } else { + // return None; + // } + // } + // prev = ts; + // } + // } /// Return true if the span is generated code, and /// it is not a subspan of the root callsite. diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml index 7355b39936..c7db2a9a8a 100644 --- a/src/librustc_trans/Cargo.toml +++ b/src/librustc_trans/Cargo.toml @@ -10,10 +10,14 @@ crate-type = ["dylib"] test = false [dependencies] -flate = { path = "../libflate" } +crossbeam = "0.2" +flate2 = "0.2" +jobserver = "0.1.5" log = "0.3" owning_ref = "0.3.3" +rustc-demangle = "0.1.4" rustc = { path = "../librustc" } +rustc_allocator = { path = "../librustc_allocator" } rustc_back = { path = "../librustc_back" } rustc_bitflags = { path = "../librustc_bitflags" } rustc_const_math = { path = "../librustc_const_math" } diff --git a/src/librustc_trans/allocator.rs b/src/librustc_trans/allocator.rs new file mode 100644 index 0000000000..9abb6d66f9 --- /dev/null +++ b/src/librustc_trans/allocator.rs @@ -0,0 +1,117 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::ffi::CString; +use std::ptr; + +use libc::c_uint; +use rustc::middle::allocator::AllocatorKind; +use rustc::ty::TyCtxt; +use rustc_allocator::{ALLOCATOR_METHODS, AllocatorTy}; + +use ModuleLlvm; +use llvm::{self, False, True}; + +pub unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) { + let llcx = mods.llcx; + let llmod = mods.llmod; + let usize = match &tcx.sess.target.target.target_pointer_width[..] { + "16" => llvm::LLVMInt16TypeInContext(llcx), + "32" => llvm::LLVMInt32TypeInContext(llcx), + "64" => llvm::LLVMInt64TypeInContext(llcx), + tws => bug!("Unsupported target word size for int: {}", tws), + }; + let i8 = llvm::LLVMInt8TypeInContext(llcx); + let i8p = llvm::LLVMPointerType(i8, 0); + let usizep = llvm::LLVMPointerType(usize, 0); + let void = llvm::LLVMVoidTypeInContext(llcx); + + for method in ALLOCATOR_METHODS { + let mut args = Vec::new(); + for ty in method.inputs.iter() { + match *ty { + AllocatorTy::Layout => { + args.push(usize); // size + args.push(usize); // align + } + AllocatorTy::LayoutRef => args.push(i8p), + AllocatorTy::Ptr => args.push(i8p), + AllocatorTy::AllocErr => args.push(i8p), + + AllocatorTy::Bang | + AllocatorTy::ResultExcess | + AllocatorTy::ResultPtr | + AllocatorTy::ResultUnit | + AllocatorTy::UsizePair | + AllocatorTy::Unit => panic!("invalid allocator arg"), + } + } + let output = match method.output { + AllocatorTy::UsizePair => { + args.push(usizep); // min + args.push(usizep); // max + None + } + AllocatorTy::Bang => None, + AllocatorTy::ResultExcess => { + args.push(i8p); // excess_ptr + args.push(i8p); // err_ptr + Some(i8p) + } + AllocatorTy::ResultPtr => { + args.push(i8p); // err_ptr + Some(i8p) + } + AllocatorTy::ResultUnit => Some(i8), + AllocatorTy::Unit => None, + + AllocatorTy::AllocErr | + AllocatorTy::Layout | + AllocatorTy::LayoutRef | + AllocatorTy::Ptr => panic!("invalid allocator output"), + }; + let ty = llvm::LLVMFunctionType(output.unwrap_or(void), + args.as_ptr(), + args.len() as c_uint, + False); + let name = CString::new(format!("__rust_{}", method.name)).unwrap(); + let llfn = llvm::LLVMRustGetOrInsertFunction(llmod, + name.as_ptr(), + ty); + + let callee = CString::new(kind.fn_name(method.name)).unwrap(); + let callee = llvm::LLVMRustGetOrInsertFunction(llmod, + callee.as_ptr(), + ty); + + let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, + llfn, + "entry\0".as_ptr() as *const _); + + let llbuilder = llvm::LLVMCreateBuilderInContext(llcx); + llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb); + let args = args.iter().enumerate().map(|(i, _)| { + llvm::LLVMGetParam(llfn, i as c_uint) + }).collect::>(); + let ret = llvm::LLVMRustBuildCall(llbuilder, + callee, + args.as_ptr(), + args.len() as c_uint, + ptr::null_mut(), + "\0".as_ptr() as *const _); + llvm::LLVMSetTailCall(ret, True); + if output.is_some() { + llvm::LLVMBuildRet(llbuilder, ret); + } else { + llvm::LLVMBuildRetVoid(llbuilder); + } + llvm::LLVMDisposeBuilder(llbuilder); + } +} diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs index 6bef31ccf6..839614f4a2 100644 --- a/src/librustc_trans/attributes.rs +++ b/src/librustc_trans/attributes.rs @@ -11,13 +11,14 @@ use std::ffi::{CStr, CString}; +use rustc::session::config::Sanitizer; + use llvm::{self, Attribute, ValueRef}; use llvm::AttributePlace::Function; -pub use syntax::attr::InlineAttr; +pub use syntax::attr::{self, InlineAttr}; use syntax::ast; use context::CrateContext; - /// Mark LLVM function to use provided inline heuristic. #[inline] pub fn inline(val: ValueRef, inline: InlineAttr) { @@ -69,6 +70,28 @@ pub fn set_frame_pointer_elimination(ccx: &CrateContext, llfn: ValueRef) { } } +pub fn set_probestack(ccx: &CrateContext, llfn: ValueRef) { + // Only use stack probes if the target specification indicates that we + // should be using stack probes + if !ccx.sess().target.target.options.stack_probes { + return + } + + // Currently stack probes seem somewhat incompatible with the address + // sanitizer. With asan we're already protected from stack overflow anyway + // so we don't really need stack probes regardless. + match ccx.sess().opts.debugging_opts.sanitizer { + Some(Sanitizer::Address) => return, + _ => {} + } + + // Flag our internal `__rust_probestack` function as the stack probe symbol. + // This is defined in the `compiler-builtins` crate for each architecture. + llvm::AddFunctionAttrStringValue( + llfn, llvm::AttributePlace::Function, + cstr("probe-stack\0"), cstr("__rust_probestack\0")); +} + /// Composite function which sets LLVM attributes for function depending on its AST (#[attribute]) /// attributes. pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRef) { @@ -76,6 +99,7 @@ pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRe inline(llfn, find_inline_attr(Some(ccx.sess().diagnostic()), attrs)); set_frame_pointer_elimination(ccx, llfn); + set_probestack(ccx, llfn); let mut target_features = vec![]; for attr in attrs { if attr.check_name("target_feature") { @@ -95,6 +119,8 @@ pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRe llvm::AttributePlace::ReturnValue(), llfn); } else if attr.check_name("unwind") { unwind(llfn, true); + } else if attr.check_name("allocator_nounwind") { + unwind(llfn, false); } } if !target_features.is_empty() { diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index e57cbb1c91..6cbdae7627 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -23,7 +23,7 @@ use rustc::middle::dependency_format::Linkage; use CrateTranslation; use rustc::util::common::time; use rustc::util::fs::fix_windows_verbatim_for_gcc; -use rustc::dep_graph::DepNode; +use rustc::dep_graph::{DepKind, DepNode}; use rustc::hir::def_id::CrateNum; use rustc::hir::svh::Svh; use rustc_back::tempdir::TempDir; @@ -42,7 +42,8 @@ use std::mem; use std::path::{Path, PathBuf}; use std::process::Command; use std::str; -use flate; +use flate2::Compression; +use flate2::write::DeflateEncoder; use syntax::ast; use syntax::attr; use syntax_pos::Span; @@ -54,6 +55,10 @@ pub const METADATA_MODULE_NAME: &'static str = "crate.metadata"; /// match up with `METADATA_MODULE_NAME`. pub const METADATA_OBJ_NAME: &'static str = "crate.metadata.o"; +// same as for metadata above, but for allocator shim +pub const ALLOCATOR_MODULE_NAME: &'static str = "crate.allocator"; +pub const ALLOCATOR_OBJ_NAME: &'static str = "crate.allocator.o"; + // RLIB LLVM-BYTECODE OBJECT LAYOUT // Version 1 // Bytes Data @@ -134,8 +139,9 @@ pub fn find_crate_name(sess: Option<&Session>, } pub fn build_link_meta(incremental_hashes_map: &IncrementalHashesMap) -> LinkMeta { + let krate_dep_node = &DepNode::new_no_params(DepKind::Krate); let r = LinkMeta { - crate_hash: Svh::new(incremental_hashes_map[&DepNode::Krate].to_smaller_hash()), + crate_hash: Svh::new(incremental_hashes_map[krate_dep_node].to_smaller_hash()), }; info!("{:?}", r); return r; @@ -238,6 +244,9 @@ pub fn link_binary(sess: &Session, } } remove(sess, &outputs.with_extension(METADATA_OBJ_NAME)); + if trans.allocator_module.is_some() { + remove(sess, &outputs.with_extension(ALLOCATOR_OBJ_NAME)); + } } out_filenames @@ -327,34 +336,56 @@ pub fn filename_for_input(sess: &Session, } pub fn each_linked_rlib(sess: &Session, - f: &mut FnMut(CrateNum, &Path)) { + f: &mut FnMut(CrateNum, &Path)) -> Result<(), String> { let crates = sess.cstore.used_crates(LinkagePreference::RequireStatic).into_iter(); let fmts = sess.dependency_formats.borrow(); let fmts = fmts.get(&config::CrateTypeExecutable) .or_else(|| fmts.get(&config::CrateTypeStaticlib)) .or_else(|| fmts.get(&config::CrateTypeCdylib)) .or_else(|| fmts.get(&config::CrateTypeProcMacro)); - let fmts = fmts.unwrap_or_else(|| { - bug!("could not find formats for rlibs"); - }); + let fmts = match fmts { + Some(f) => f, + None => return Err(format!("could not find formats for rlibs")) + }; for (cnum, path) in crates { - match fmts[cnum.as_usize() - 1] { - Linkage::NotLinked | Linkage::IncludedFromDylib => continue, - _ => {} + match fmts.get(cnum.as_usize() - 1) { + Some(&Linkage::NotLinked) | + Some(&Linkage::IncludedFromDylib) => continue, + Some(_) => {} + None => return Err(format!("could not find formats for rlibs")) } let name = sess.cstore.crate_name(cnum).clone(); let path = match path { LibSource::Some(p) => p, LibSource::MetadataOnly => { - sess.fatal(&format!("could not find rlib for: `{}`, found rmeta (metadata) file", - name)); + return Err(format!("could not find rlib for: `{}`, found rmeta (metadata) file", + name)) } LibSource::None => { - sess.fatal(&format!("could not find rlib for: `{}`", name)); + return Err(format!("could not find rlib for: `{}`", name)) } }; f(cnum, &path); } + Ok(()) +} + +/// Returns a boolean indicating whether the specified crate should be ignored +/// during LTO. +/// +/// Crates ignored during LTO are not lumped together in the "massive object +/// file" that we create and are linked in their normal rlib states. See +/// comments below for what crates do not participate in LTO. +/// +/// It's unusual for a crate to not participate in LTO. Typically only +/// compiler-specific and unstable crates have a reason to not participate in +/// LTO. +pub fn ignored_for_lto(sess: &Session, cnum: CrateNum) -> bool { + // `#![no_builtins]` crates don't participate in LTO because the state + // of builtins gets messed up (our crate isn't tagged with no builtins). + // Similarly `#![compiler_builtins]` doesn't participate because we want + // those builtins! + sess.cstore.is_no_builtins(cnum) || sess.cstore.is_compiler_builtins(cnum) } fn out_filename(sess: &Session, @@ -411,11 +442,21 @@ fn link_binary_output(sess: &Session, let out_filename = out_filename(sess, crate_type, outputs, crate_name); match crate_type { config::CrateTypeRlib => { - link_rlib(sess, Some(trans), &objects, &out_filename, + link_rlib(sess, + trans, + RlibFlavor::Normal, + &objects, + outputs, + &out_filename, tmpdir.path()).build(); } config::CrateTypeStaticlib => { - link_staticlib(sess, &objects, &out_filename, tmpdir.path()); + link_staticlib(sess, + trans, + outputs, + &objects, + &out_filename, + tmpdir.path()); } _ => { link_natively(sess, crate_type, &objects, &out_filename, trans, @@ -425,6 +466,10 @@ fn link_binary_output(sess: &Session, out_filenames.push(out_filename); } + if sess.opts.cg.save_temps { + let _ = tmpdir.into_path(); + } + out_filenames } @@ -467,6 +512,11 @@ fn emit_metadata<'a>(sess: &'a Session, trans: &CrateTranslation, out_filename: } } +enum RlibFlavor { + Normal, + StaticlibBase, +} + // Create an 'rlib' // // An rlib in its current incarnation is essentially a renamed .a file. The @@ -474,8 +524,10 @@ fn emit_metadata<'a>(sess: &'a Session, trans: &CrateTranslation, out_filename: // all of the object files from native libraries. This is done by unzipping // native libraries and inserting all of the contents into this archive. fn link_rlib<'a>(sess: &'a Session, - trans: Option<&CrateTranslation>, // None == no metadata/bytecode + trans: &CrateTranslation, + flavor: RlibFlavor, objects: &[PathBuf], + outputs: &OutputFilenames, out_filename: &Path, tmpdir: &Path) -> ArchiveBuilder<'a> { info!("preparing rlib from {:?} to {:?}", objects, out_filename); @@ -536,8 +588,8 @@ fn link_rlib<'a>(sess: &'a Session, // // Basically, all this means is that this code should not move above the // code above. - match trans { - Some(trans) => { + match flavor { + RlibFlavor::Normal => { // Instead of putting the metadata in an object file section, rlibs // contain the metadata in a separate file. We use a temp directory // here so concurrent builds in the same directory don't try to use @@ -569,7 +621,9 @@ fn link_rlib<'a>(sess: &'a Session, e)) } - let bc_data_deflated = flate::deflate_bytes(&bc_data); + let mut bc_data_deflated = Vec::new(); + DeflateEncoder::new(&mut bc_data_deflated, Compression::Fast) + .write_all(&bc_data).unwrap(); let mut bc_file_deflated = match fs::File::create(&bc_deflated_filename) { Ok(file) => file, @@ -608,7 +662,11 @@ fn link_rlib<'a>(sess: &'a Session, } } - None => {} + RlibFlavor::StaticlibBase => { + if trans.allocator_module.is_some() { + ab.add_file(&outputs.with_extension(ALLOCATOR_OBJ_NAME)); + } + } } ab @@ -660,12 +718,22 @@ fn write_rlib_bytecode_object_v1(writer: &mut Write, // There's no need to include metadata in a static archive, so ensure to not // link in the metadata object file (and also don't prepare the archive with a // metadata file). -fn link_staticlib(sess: &Session, objects: &[PathBuf], out_filename: &Path, +fn link_staticlib(sess: &Session, + trans: &CrateTranslation, + outputs: &OutputFilenames, + objects: &[PathBuf], + out_filename: &Path, tempdir: &Path) { - let mut ab = link_rlib(sess, None, objects, out_filename, tempdir); + let mut ab = link_rlib(sess, + trans, + RlibFlavor::StaticlibBase, + objects, + outputs, + out_filename, + tempdir); let mut all_native_libs = vec![]; - each_linked_rlib(sess, &mut |cnum, path| { + let res = each_linked_rlib(sess, &mut |cnum, path| { let name = sess.cstore.crate_name(cnum); let native_libs = sess.cstore.native_libraries(cnum); @@ -686,10 +754,16 @@ fn link_staticlib(sess: &Session, objects: &[PathBuf], out_filename: &Path, let skip_object_files = native_libs.iter().any(|lib| { lib.kind == NativeLibraryKind::NativeStatic && !relevant_lib(sess, lib) }); - ab.add_rlib(path, &name.as_str(), sess.lto(), skip_object_files).unwrap(); + ab.add_rlib(path, + &name.as_str(), + sess.lto() && !ignored_for_lto(sess, cnum), + skip_object_files).unwrap(); all_native_libs.extend(sess.cstore.native_libraries(cnum)); }); + if let Err(e) = res { + sess.fatal(&e); + } ab.update_symbols(); ab.build(); @@ -774,6 +848,9 @@ fn link_natively(sess: &Session, if let Some(args) = sess.target.target.options.post_link_args.get(&flavor) { cmd.args(args); } + for &(ref k, ref v) in &sess.target.target.options.link_env { + cmd.env(k, v); + } if sess.opts.debugging_opts.print_link_args { println!("{:?}", &cmd); @@ -926,6 +1003,10 @@ fn link_args(cmd: &mut Linker, cmd.add_object(&outputs.with_extension(METADATA_OBJ_NAME)); } + if trans.allocator_module.is_some() { + cmd.add_object(&outputs.with_extension(ALLOCATOR_OBJ_NAME)); + } + // Try to strip as much out of the generated object by removing unused // sections if possible. See more comments in linker.rs if !sess.opts.cg.link_dead_code { @@ -1100,6 +1181,9 @@ fn add_upstream_rust_crates(cmd: &mut Linker, // symbols from the dylib. let src = sess.cstore.used_crate_source(cnum); match data[cnum.as_usize() - 1] { + _ if sess.cstore.is_profiler_runtime(cnum) => { + add_static_crate(cmd, sess, tmpdir, crate_type, cnum); + } _ if sess.cstore.is_sanitizer_runtime(cnum) => { link_sanitizer_runtime(cmd, sess, tmpdir, cnum); } @@ -1226,7 +1310,9 @@ fn add_upstream_rust_crates(cmd: &mut Linker, lib.kind == NativeLibraryKind::NativeStatic && !relevant_lib(sess, lib) }); - if !sess.lto() && crate_type != config::CrateTypeDylib && !skip_native { + if (!sess.lto() || ignored_for_lto(sess, cnum)) && + crate_type != config::CrateTypeDylib && + !skip_native { cmd.link_rlib(&fix_windows_verbatim_for_gcc(cratepath)); return } diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index e23ddd2542..c402bdea2b 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -10,19 +10,21 @@ use back::link; use back::write; -use back::symbol_export::{self, ExportedSymbols}; -use rustc::session::{self, config}; +use back::symbol_export; +use rustc::session::config; +use errors::FatalError; use llvm; use llvm::archive_ro::ArchiveRO; use llvm::{ModuleRef, TargetMachineRef, True, False}; use rustc::util::common::time; use rustc::util::common::path2cstr; use rustc::hir::def_id::LOCAL_CRATE; -use back::write::{ModuleConfig, with_llvm_pmb}; +use back::write::{ModuleConfig, with_llvm_pmb, CodegenContext}; use libc; -use flate; +use flate2::read::DeflateDecoder; +use std::io::Read; use std::ffi::CString; use std::path::Path; @@ -38,30 +40,31 @@ pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool { } } -pub fn run(sess: &session::Session, +pub fn run(cgcx: &CodegenContext, llmod: ModuleRef, tm: TargetMachineRef, - exported_symbols: &ExportedSymbols, config: &ModuleConfig, - temp_no_opt_bc_filename: &Path) { - if sess.opts.cg.prefer_dynamic { - sess.struct_err("cannot prefer dynamic linking when performing LTO") + temp_no_opt_bc_filename: &Path) -> Result<(), FatalError> { + let handler = cgcx.handler; + if cgcx.opts.cg.prefer_dynamic { + handler.struct_err("cannot prefer dynamic linking when performing LTO") .note("only 'staticlib', 'bin', and 'cdylib' outputs are \ supported with LTO") .emit(); - sess.abort_if_errors(); + return Err(FatalError) } // Make sure we actually can run LTO - for crate_type in sess.crate_types.borrow().iter() { + for crate_type in cgcx.crate_types.iter() { if !crate_type_allows_lto(*crate_type) { - sess.fatal("lto can only be run for executables, cdylibs and \ - static library outputs"); + let e = handler.fatal("lto can only be run for executables, cdylibs and \ + static library outputs"); + return Err(e) } } let export_threshold = - symbol_export::crates_export_threshold(&sess.crate_types.borrow()); + symbol_export::crates_export_threshold(&cgcx.crate_types); let symbol_filter = &|&(ref name, level): &(String, _)| { if symbol_export::is_below_threshold(level, export_threshold) { @@ -73,7 +76,7 @@ pub fn run(sess: &session::Session, } }; - let mut symbol_white_list: Vec = exported_symbols + let mut symbol_white_list: Vec = cgcx.exported_symbols .exported_symbols(LOCAL_CRATE) .iter() .filter_map(symbol_filter) @@ -82,16 +85,11 @@ pub fn run(sess: &session::Session, // For each of our upstream dependencies, find the corresponding rlib and // load the bitcode from the archive. Then merge it into the current LLVM // module that we've got. - link::each_linked_rlib(sess, &mut |cnum, path| { - // `#![no_builtins]` crates don't participate in LTO. - if sess.cstore.is_no_builtins(cnum) { - return; - } - + for &(cnum, ref path) in cgcx.each_linked_rlib_for_lto.iter() { symbol_white_list.extend( - exported_symbols.exported_symbols(cnum) - .iter() - .filter_map(symbol_filter)); + cgcx.exported_symbols.exported_symbols(cnum) + .iter() + .filter_map(symbol_filter)); let archive = ArchiveRO::open(&path).expect("wanted an rlib"); let bytecodes = archive.iter().filter_map(|child| { @@ -101,7 +99,7 @@ pub fn run(sess: &session::Session, let bc_encoded = data.data(); let bc_decoded = if is_versioned_bytecode_format(bc_encoded) { - time(sess.time_passes(), &format!("decode {}", name), || { + time(cgcx.time_passes, &format!("decode {}", name), || { // Read the version let version = extract_bytecode_format_version(bc_encoded); @@ -112,46 +110,53 @@ pub fn run(sess: &session::Session, link::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET.. (link::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET + data_size as usize)]; - match flate::inflate_bytes(compressed_data) { - Ok(inflated) => inflated, - Err(_) => { - sess.fatal(&format!("failed to decompress bc of `{}`", - name)) - } + let mut inflated = Vec::new(); + let res = DeflateDecoder::new(compressed_data) + .read_to_end(&mut inflated); + if res.is_err() { + let msg = format!("failed to decompress bc of `{}`", + name); + Err(handler.fatal(&msg)) + } else { + Ok(inflated) } } else { - sess.fatal(&format!("Unsupported bytecode format version {}", - version)) + Err(handler.fatal(&format!("Unsupported bytecode format version {}", + version))) } - }) + })? } else { - time(sess.time_passes(), &format!("decode {}", name), || { + time(cgcx.time_passes, &format!("decode {}", name), || { // the object must be in the old, pre-versioning format, so // simply inflate everything and let LLVM decide if it can // make sense of it - match flate::inflate_bytes(bc_encoded) { - Ok(bc) => bc, - Err(_) => { - sess.fatal(&format!("failed to decompress bc of `{}`", - name)) - } + let mut inflated = Vec::new(); + let res = DeflateDecoder::new(bc_encoded) + .read_to_end(&mut inflated); + if res.is_err() { + let msg = format!("failed to decompress bc of `{}`", + name); + Err(handler.fatal(&msg)) + } else { + Ok(inflated) } - }) + })? }; let ptr = bc_decoded.as_ptr(); debug!("linking {}", name); - time(sess.time_passes(), &format!("ll link {}", name), || unsafe { - if !llvm::LLVMRustLinkInExternalBitcode(llmod, - ptr as *const libc::c_char, - bc_decoded.len() as libc::size_t) { - write::llvm_err(sess.diagnostic(), - format!("failed to load bc of `{}`", - name)); + time(cgcx.time_passes, &format!("ll link {}", name), || unsafe { + if llvm::LLVMRustLinkInExternalBitcode(llmod, + ptr as *const libc::c_char, + bc_decoded.len() as libc::size_t) { + Ok(()) + } else { + let msg = format!("failed to load bc of `{}`", name); + Err(write::llvm_err(handler, msg)) } - }); + })?; } - }); + } // Internalize everything but the exported symbols of the current module let arr: Vec<*const libc::c_char> = symbol_white_list.iter() @@ -164,13 +169,13 @@ pub fn run(sess: &session::Session, arr.len() as libc::size_t); } - if sess.no_landing_pads() { + if cgcx.no_landing_pads { unsafe { llvm::LLVMRustMarkAllFunctionsNounwind(llmod); } } - if sess.opts.cg.save_temps { + if cgcx.opts.cg.save_temps { let cstr = path2cstr(temp_no_opt_bc_filename); unsafe { llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr()); @@ -200,12 +205,13 @@ pub fn run(sess: &session::Session, assert!(!pass.is_null()); llvm::LLVMRustAddPass(pm, pass); - time(sess.time_passes(), "LTO passes", || + time(cgcx.time_passes, "LTO passes", || llvm::LLVMRunPassManager(pm, llmod)); llvm::LLVMDisposePassManager(pm); } debug!("lto done"); + Ok(()) } fn is_versioned_bytecode_format(bc: &[u8]) -> bool { diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index ef75de0404..52fe747858 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -92,8 +92,7 @@ impl ExportedSymbols { // Down below we'll hardwire all of the symbols to the `Rust` export // level instead. let special_runtime_crate = - scx.sess().cstore.is_allocator(cnum) || - scx.sess().cstore.is_panic_runtime(cnum) || + scx.tcx().is_panic_runtime(cnum.as_def_id()) || scx.sess().cstore.is_compiler_builtins(cnum); let crate_exports = scx diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index 8e14335cea..10b66fb199 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -154,6 +154,13 @@ fn get_symbol_hash<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, assert!(!item_type.has_erasable_regions()); hasher.visit_ty(item_type); + // If this is a function, we hash the signature as well. + // This is not *strictly* needed, but it may help in some + // situations, see the `run-make/a-b-a-linker-guard` test. + if let ty::TyFnDef(..) = item_type.sty { + item_type.fn_sig(tcx).visit_with(&mut hasher); + } + // also include any type parameters (for generic items) if let Some(substs) = substs { assert!(!substs.has_erasable_regions()); diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 6ed0cb0092..5e227ec467 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -9,7 +9,7 @@ // except according to those terms. use back::lto; -use back::link::{get_linker, remove}; +use back::link::{self, get_linker, remove}; use back::symbol_export::ExportedSymbols; use rustc_incremental::{save_trans_partition, in_incr_comp_dir}; use rustc::session::config::{self, OutputFilenames, OutputType, OutputTypes, Passes, SomePasses, @@ -19,22 +19,28 @@ use llvm; use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef, ContextRef}; use llvm::SMDiagnosticRef; use {CrateTranslation, ModuleLlvm, ModuleSource, ModuleTranslation}; +use rustc::hir::def_id::CrateNum; use rustc::util::common::{time, time_depth, set_time_depth, path2cstr}; use rustc::util::fs::link_or_copy; -use errors::{self, Handler, Level, DiagnosticBuilder}; +use errors::{self, Handler, Level, DiagnosticBuilder, FatalError}; use errors::emitter::Emitter; +use syntax::ext::hygiene::Mark; use syntax_pos::MultiSpan; use context::{is_pie_binary, get_reloc_model}; +use jobserver::{Client, Acquired}; +use crossbeam::{scope, Scope}; +use rustc_demangle; use std::cmp; use std::ffi::CString; use std::fs; +use std::io; +use std::io::Write; use std::path::{Path, PathBuf}; use std::str; -use std::sync::{Arc, Mutex}; -use std::sync::mpsc::channel; -use std::thread; -use libc::{c_uint, c_void}; +use std::sync::mpsc::{channel, Sender}; +use std::slice; +use libc::{c_uint, c_void, c_char, size_t}; pub const RELOC_MODEL_ARGS : [(&'static str, llvm::RelocMode); 7] = [ ("pic", llvm::RelocMode::PIC), @@ -54,10 +60,10 @@ pub const CODE_GEN_MODEL_ARGS : [(&'static str, llvm::CodeModel); 5] = [ ("large", llvm::CodeModel::Large), ]; -pub fn llvm_err(handler: &errors::Handler, msg: String) -> ! { +pub fn llvm_err(handler: &errors::Handler, msg: String) -> FatalError { match llvm::last_error() { - Some(err) => panic!(handler.fatal(&format!("{}: {}", msg, err))), - None => panic!(handler.fatal(&msg)), + Some(err) => handler.fatal(&format!("{}: {}", msg, err)), + None => handler.fatal(&msg), } } @@ -67,73 +73,16 @@ pub fn write_output_file( pm: llvm::PassManagerRef, m: ModuleRef, output: &Path, - file_type: llvm::FileType) { + file_type: llvm::FileType) -> Result<(), FatalError> { unsafe { let output_c = path2cstr(output); let result = llvm::LLVMRustWriteOutputFile( target, pm, m, output_c.as_ptr(), file_type); if result.into_result().is_err() { - llvm_err(handler, format!("could not write output to {}", output.display())); - } - } -} - - -struct Diagnostic { - msg: String, - code: Option, - lvl: Level, -} - -// We use an Arc instead of just returning a list of diagnostics from the -// child thread because we need to make sure that the messages are seen even -// if the child thread panics (for example, when `fatal` is called). -#[derive(Clone)] -struct SharedEmitter { - buffer: Arc>>, -} - -impl SharedEmitter { - fn new() -> SharedEmitter { - SharedEmitter { - buffer: Arc::new(Mutex::new(Vec::new())), - } - } - - fn dump(&mut self, handler: &Handler) { - let mut buffer = self.buffer.lock().unwrap(); - for diag in &*buffer { - match diag.code { - Some(ref code) => { - handler.emit_with_code(&MultiSpan::new(), - &diag.msg, - &code, - diag.lvl); - }, - None => { - handler.emit(&MultiSpan::new(), - &diag.msg, - diag.lvl); - }, - } - } - buffer.clear(); - } -} - -impl Emitter for SharedEmitter { - fn emit(&mut self, db: &DiagnosticBuilder) { - self.buffer.lock().unwrap().push(Diagnostic { - msg: db.message(), - code: db.code.clone(), - lvl: db.level, - }); - for child in &db.children { - self.buffer.lock().unwrap().push(Diagnostic { - msg: child.message(), - code: None, - lvl: child.level, - }); + let msg = format!("could not write output to {}", output.display()); + Err(llvm_err(handler, msg)) + } else { + Ok(()) } } } @@ -231,9 +180,9 @@ pub fn create_target_machine(sess: &Session) -> TargetMachineRef { }; if tm.is_null() { - llvm_err(sess.diagnostic(), - format!("Could not create LLVM TargetMachine for triple: {}", - triple).to_string()); + let msg = format!("Could not create LLVM TargetMachine for triple: {}", + triple); + panic!(llvm_err(sess.diagnostic(), msg)); } else { return tm; }; @@ -333,36 +282,28 @@ impl ModuleConfig { } /// Additional resources used by optimize_and_codegen (not module specific) -struct CodegenContext<'a> { - // Extra resources used for LTO: (sess, reachable). This will be `None` - // when running in a worker thread. - lto_ctxt: Option<(&'a Session, &'a ExportedSymbols)>, +pub struct CodegenContext<'a> { + // Resouces needed when running LTO + pub time_passes: bool, + pub lto: bool, + pub no_landing_pads: bool, + pub exported_symbols: &'a ExportedSymbols, + pub opts: &'a config::Options, + pub crate_types: Vec, + pub each_linked_rlib_for_lto: Vec<(CrateNum, PathBuf)>, // Handler to use for diagnostics produced during codegen. - handler: &'a Handler, + pub handler: &'a Handler, // LLVM passes added by plugins. - plugin_passes: Vec, + pub plugin_passes: Vec, // LLVM optimizations for which we want to print remarks. - remark: Passes, + pub remark: Passes, // Worker thread number - worker: usize, + pub worker: usize, // The incremental compilation session directory, or None if we are not // compiling incrementally - incr_comp_session_dir: Option -} - -impl<'a> CodegenContext<'a> { - fn new_with_session(sess: &'a Session, - exported_symbols: &'a ExportedSymbols) - -> CodegenContext<'a> { - CodegenContext { - lto_ctxt: Some((sess, exported_symbols)), - handler: sess.diagnostic(), - plugin_passes: sess.plugin_llvm_passes.borrow().clone(), - remark: sess.opts.cg.remark.clone(), - worker: 0, - incr_comp_session_dir: sess.incr_comp_session_dir_opt().map(|r| r.clone()) - } - } + pub incr_comp_session_dir: Option, + // Channel back to the main control thread to send messages to + pub tx: Sender, } struct HandlerFreeVars<'a> { @@ -373,22 +314,7 @@ struct HandlerFreeVars<'a> { unsafe extern "C" fn report_inline_asm<'a, 'b>(cgcx: &'a CodegenContext<'a>, msg: &'b str, cookie: c_uint) { - use syntax::ext::hygiene::Mark; - - match cgcx.lto_ctxt { - Some((sess, _)) => { - match Mark::from_u32(cookie).expn_info() { - Some(ei) => sess.span_err(ei.call_site, msg), - None => sess.err(msg), - }; - } - - None => { - cgcx.handler.struct_err(msg) - .note("build without -C codegen-units for more exact errors") - .emit(); - } - } + drop(cgcx.tx.send(Message::InlineAsmError(cookie as u32, msg.to_string()))); } unsafe extern "C" fn inline_asm_handler(diag: SMDiagnosticRef, @@ -437,7 +363,9 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, mtrans: ModuleTranslation, mllvm: ModuleLlvm, config: ModuleConfig, - output_names: OutputFilenames) { + output_names: OutputFilenames) + -> Result<(), FatalError> +{ let llmod = mllvm.llmod; let llcx = mllvm.llcx; let tm = config.tm; @@ -525,25 +453,21 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, llvm::LLVMDisposePassManager(fpm); llvm::LLVMDisposePassManager(mpm); - match cgcx.lto_ctxt { - Some((sess, exported_symbols)) if sess.lto() => { - time(sess.time_passes(), "all lto passes", || { - let temp_no_opt_bc_filename = - output_names.temp_path_ext("no-opt.lto.bc", module_name); - lto::run(sess, - llmod, - tm, - exported_symbols, - &config, - &temp_no_opt_bc_filename); - }); - if config.emit_lto_bc { - let out = output_names.temp_path_ext("lto.bc", module_name); - let out = path2cstr(&out); - llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()); - } - }, - _ => {}, + if cgcx.lto { + time(cgcx.time_passes, "all lto passes", || { + let temp_no_opt_bc_filename = + output_names.temp_path_ext("no-opt.lto.bc", module_name); + lto::run(cgcx, + llmod, + tm, + &config, + &temp_no_opt_bc_filename) + })?; + if config.emit_lto_bc { + let out = output_names.temp_path_ext("lto.bc", module_name); + let out = path2cstr(&out); + llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()); + } } } @@ -555,16 +479,16 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, // pass manager passed to the closure should be ensured to not // escape the closure itself, and the manager should only be // used once. - unsafe fn with_codegen(tm: TargetMachineRef, - llmod: ModuleRef, - no_builtins: bool, - f: F) where - F: FnOnce(PassManagerRef), + unsafe fn with_codegen(tm: TargetMachineRef, + llmod: ModuleRef, + no_builtins: bool, + f: F) -> R + where F: FnOnce(PassManagerRef) -> R, { let cpm = llvm::LLVMCreatePassManager(); llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod); llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins); - f(cpm); + f(cpm) } // Change what we write and cleanup based on whether obj files are @@ -584,12 +508,45 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, llvm::LLVMWriteBitcodeToFile(llmod, bc_out_c.as_ptr()); } - time(config.time_passes, &format!("codegen passes [{}]", cgcx.worker), || { + time(config.time_passes, &format!("codegen passes [{}]", cgcx.worker), + || -> Result<(), FatalError> { if config.emit_ir { let out = output_names.temp_path(OutputType::LlvmAssembly, module_name); let out = path2cstr(&out); + + extern "C" fn demangle_callback(input_ptr: *const c_char, + input_len: size_t, + output_ptr: *mut c_char, + output_len: size_t) -> size_t { + let input = unsafe { + slice::from_raw_parts(input_ptr as *const u8, input_len as usize) + }; + + let input = match str::from_utf8(input) { + Ok(s) => s, + Err(_) => return 0, + }; + + let output = unsafe { + slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize) + }; + let mut cursor = io::Cursor::new(output); + + let demangled = match rustc_demangle::try_demangle(input) { + Ok(d) => d, + Err(_) => return 0, + }; + + if let Err(_) = write!(cursor, "{:#}", demangled) { + // Possible only if provided buffer is not big enough + return 0; + } + + cursor.position() as size_t + } + with_codegen(tm, llmod, config.no_builtins, |cpm| { - llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr()); + llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback); llvm::LLVMDisposePassManager(cpm); }) } @@ -607,8 +564,8 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, }; with_codegen(tm, llmod, config.no_builtins, |cpm| { write_output_file(cgcx.handler, tm, cpm, llmod, &path, - llvm::FileType::AssemblyFile); - }); + llvm::FileType::AssemblyFile) + })?; if config.emit_obj { llvm::LLVMDisposeModule(llmod); } @@ -617,10 +574,12 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, if write_obj { with_codegen(tm, llmod, config.no_builtins, |cpm| { write_output_file(cgcx.handler, tm, cpm, llmod, &obj_out, - llvm::FileType::ObjectFile); - }); + llvm::FileType::ObjectFile) + })?; } - }); + + Ok(()) + })?; if copy_bc_to_obj { debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out); @@ -637,6 +596,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, } llvm::LLVMRustDisposeTargetMachine(tm); + Ok(()) } @@ -684,6 +644,7 @@ pub fn run_passes(sess: &Session, let mut modules_config = ModuleConfig::new(tm, sess.opts.cg.passes.clone()); let mut metadata_config = ModuleConfig::new(tm, vec![]); + let mut allocator_config = ModuleConfig::new(tm, vec![]); if let Some(ref sanitizer) = sess.opts.debugging_opts.sanitizer { match *sanitizer { @@ -701,6 +662,10 @@ pub fn run_passes(sess: &Session, } } + if sess.opts.debugging_opts.profile { + modules_config.passes.push("insert-gcov-profiling".to_owned()) + } + modules_config.opt_level = Some(get_llvm_opt_level(sess.opts.optimize)); modules_config.opt_size = Some(get_llvm_opt_size(sess.opts.optimize)); @@ -710,6 +675,7 @@ pub fn run_passes(sess: &Session, modules_config.emit_bc = true; modules_config.emit_lto_bc = true; metadata_config.emit_bc = true; + allocator_config.emit_bc = true; } // Emit bitcode files for the crate if we're emitting an rlib. @@ -735,6 +701,7 @@ pub fn run_passes(sess: &Session, // in this case we still want the metadata object file. if !sess.opts.output_types.contains_key(&OutputType::Assembly) { metadata_config.emit_obj = true; + allocator_config.emit_obj = true; } } OutputType::Object => { modules_config.emit_obj = true; } @@ -742,6 +709,7 @@ pub fn run_passes(sess: &Session, OutputType::Exe => { modules_config.emit_obj = true; metadata_config.emit_obj = true; + allocator_config.emit_obj = true; }, OutputType::Mir => {} OutputType::DepInfo => {} @@ -750,6 +718,7 @@ pub fn run_passes(sess: &Session, modules_config.set_flags(sess, trans); metadata_config.set_flags(sess, trans); + allocator_config.set_flags(sess, trans); // Populate a buffer with a list of codegen threads. Items are processed in @@ -765,6 +734,14 @@ pub fn run_passes(sess: &Session, work_items.push(work); } + if let Some(allocator) = trans.allocator_module.clone() { + let work = build_work_item(sess, + allocator, + allocator_config.clone(), + crate_output.clone()); + work_items.push(work); + } + for mtrans in trans.modules.iter() { let work = build_work_item(sess, mtrans.clone(), @@ -777,19 +754,16 @@ pub fn run_passes(sess: &Session, dump_incremental_data(&trans); } - // Process the work items, optionally using worker threads. - // NOTE: We are hardcoding a limit of worker threads for now. With - // incremental compilation we can run into situations where we would - // open hundreds of threads otherwise -- which can make things slower - // if things don't fit into memory anymore, or can cause the compiler - // to crash because of too many open file handles. See #39280 for - // some discussion on how to improve this in the future. - let num_workers = cmp::min(work_items.len() - 1, 32); - if num_workers <= 1 { - run_work_singlethreaded(sess, &trans.exported_symbols, work_items); - } else { - run_work_multithreaded(sess, work_items, num_workers); - } + let client = sess.jobserver_from_env.clone().unwrap_or_else(|| { + // Pick a "reasonable maximum" if we don't otherwise have a jobserver in + // our environment, capping out at 32 so we don't take everything down + // by hogging the process run queue. + let num_workers = cmp::min(work_items.len() - 1, 32); + Client::new(num_workers).expect("failed to create jobserver") + }); + scope(|scope| { + execute_work(sess, work_items, client, &trans.exported_symbols, scope); + }); // If in incr. comp. mode, preserve the `.o` files for potential re-use for mtrans in trans.modules.iter() { @@ -944,6 +918,13 @@ pub fn run_passes(sess: &Session, Some(&trans.metadata_module.name)); remove(sess, &path); } + if allocator_config.emit_bc && !user_wants_bitcode { + if let Some(ref module) = trans.allocator_module { + let path = crate_output.temp_path(OutputType::Bitcode, + Some(&module.name)); + remove(sess, &path); + } + } } // We leave the following files around by default: @@ -967,7 +948,7 @@ fn dump_incremental_data(trans: &CrateTranslation) { ModuleSource::Translated(..) => (), } } - println!("incremental: re-using {} out of {} modules", reuse, trans.modules.len()); + eprintln!("incremental: re-using {} out of {} modules", reuse, trans.modules.len()); } struct WorkItem { @@ -991,8 +972,9 @@ fn build_work_item(sess: &Session, } } -fn execute_work_item(cgcx: &CodegenContext, - work_item: WorkItem) { +fn execute_work_item(cgcx: &CodegenContext, work_item: WorkItem) + -> Result<(), FatalError> +{ unsafe { match work_item.mtrans.source { ModuleSource::Translated(mllvm) => { @@ -1001,7 +983,7 @@ fn execute_work_item(cgcx: &CodegenContext, work_item.mtrans, mllvm, work_item.config, - work_item.output_names); + work_item.output_names)?; } ModuleSource::Preexisting(wp) => { let incr_comp_session_dir = cgcx.incr_comp_session_dir @@ -1029,94 +1011,282 @@ fn execute_work_item(cgcx: &CodegenContext, } } } + + Ok(()) } -fn run_work_singlethreaded(sess: &Session, - exported_symbols: &ExportedSymbols, - work_items: Vec) { - let cgcx = CodegenContext::new_with_session(sess, exported_symbols); +pub enum Message { + Token(io::Result), + Diagnostic(Diagnostic), + Done { success: bool }, + InlineAsmError(u32, String), + AbortIfErrors, +} - // Since we're running single-threaded, we can pass the session to - // the proc, allowing `optimize_and_codegen` to perform LTO. - for work in work_items.into_iter().rev() { - execute_work_item(&cgcx, work); - } +pub struct Diagnostic { + msg: String, + code: Option, + lvl: Level, } -fn run_work_multithreaded(sess: &Session, - work_items: Vec, - num_workers: usize) { - assert!(num_workers > 0); - - // Run some workers to process the work items. - let work_items_arc = Arc::new(Mutex::new(work_items)); - let mut diag_emitter = SharedEmitter::new(); - let mut futures = Vec::with_capacity(num_workers); - - for i in 0..num_workers { - let work_items_arc = work_items_arc.clone(); - let diag_emitter = diag_emitter.clone(); - let plugin_passes = sess.plugin_llvm_passes.borrow().clone(); - let remark = sess.opts.cg.remark.clone(); - - let (tx, rx) = channel(); - let mut tx = Some(tx); - futures.push(rx); - - let incr_comp_session_dir = sess.incr_comp_session_dir_opt().map(|r| r.clone()); - - let depth = time_depth(); - thread::Builder::new().name(format!("codegen-{}", i)).spawn(move || { - set_time_depth(depth); - - let diag_handler = Handler::with_emitter(true, false, box diag_emitter); - - // Must construct cgcx inside the proc because it has non-Send - // fields. - let cgcx = CodegenContext { - lto_ctxt: None, - handler: &diag_handler, - plugin_passes: plugin_passes, - remark: remark, - worker: i, - incr_comp_session_dir: incr_comp_session_dir - }; +fn execute_work<'a>(sess: &'a Session, + mut work_items: Vec, + jobserver: Client, + exported_symbols: &'a ExportedSymbols, + scope: &Scope<'a>) { + let (tx, rx) = channel(); + let tx2 = tx.clone(); + + // First up, convert our jobserver into a helper thread so we can use normal + // mpsc channels to manage our messages and such. Once we've got the helper + // thread then request `n-1` tokens because all of our work items are ready + // to go. + // + // Note that the `n-1` is here because we ourselves have a token (our + // process) and we'll use that token to execute at least one unit of work. + // + // After we've requested all these tokens then we'll, when we can, get + // tokens on `rx` above which will get managed in the main loop below. + let helper = jobserver.into_helper_thread(move |token| { + drop(tx2.send(Message::Token(token))); + }).expect("failed to spawn helper thread"); + for _ in 0..work_items.len() - 1 { + helper.request_token(); + } + + // This is the "main loop" of parallel work happening for parallel codegen. + // It's here that we manage parallelism, schedule work, and work with + // messages coming from clients. + // + // Our channel `rx` created above is a channel of messages coming from our + // various worker threads. This includes the jobserver helper thread above + // as well as the work we'll spawn off here. Each turn of this loop starts + // off by trying to spawn as much work as possible. After we've done that we + // then wait for an event and dispatch accordingly once the event is + // received. We're only done once all our work items have been drained and + // nothing is running, at which point we return back up the stack. + // + // ## Parallelism management + // + // It's worth also touching on the management of parallelism here. We don't + // want to just spawn a thread per work item because while that's optimal + // parallelism it may overload a system with too many threads or violate our + // configuration for the maximum amount of cpu to use for this process. To + // manage this we use the `jobserver` crate. + // + // Job servers are an artifact of GNU make and are used to manage + // parallelism between processes. A jobserver is a glorified IPC semaphore + // basically. Whenever we want to run some work we acquire the semaphore, + // and whenever we're done with that work we release the semaphore. In this + // manner we can ensure that the maximum number of parallel workers is + // capped at any one point in time. + // + // The jobserver protocol is a little unique, however. We, as a running + // process, already have an ephemeral token assigned to us. We're not going + // to be doing any productive work in this thread though so we're going to + // give this token to a worker thread (there's no actual token to give, this + // is just conceptually). As a result you'll see a few `+1` and `-1` + // instances below, and it's about working with this ephemeral token. + // + // To acquire tokens we have our `helper` thread above which is just in a + // loop acquiring tokens and sending them to us. We then store all tokens + // locally in a `tokens` vector once they're acquired. Currently we don't + // literally send a token to a worker thread to assist with management of + // our "ephemeral token". + // + // As a result, our "spawn as much work as possible" basically means that we + // fill up the `running` counter up to the limit of the `tokens` list. + // Whenever we get a new token this'll mean a new unit of work is spawned, + // and then whenever a unit of work finishes we relinquish a token, if we + // had one, to maybe get re-acquired later. + // + // Note that there's a race which may mean that we acquire more tokens than + // we originally anticipated. For example let's say we have 2 units of work. + // First we request one token from the helper thread and then we + // immediately spawn one unit of work with our ephemeral token after. We may + // then finish the first piece of work before the token is acquired, but we + // can continue to spawn the second piece of work with our ephemeral token. + // Before that work finishes, however, we may acquire a token. In that case + // we actually wastefully acquired the token, so we relinquish it back to + // the jobserver. + let mut tokens = Vec::new(); + let mut running = 0; + while work_items.len() > 0 || running > 0 { + + // Spin up what work we can, only doing this while we've got available + // parallelism slots and work left to spawn. + while work_items.len() > 0 && running < tokens.len() + 1 { + let item = work_items.pop().unwrap(); + let index = work_items.len(); + spawn_work(sess, exported_symbols, scope, tx.clone(), item, index); + running += 1; + } + + // Relinquish accidentally acquired extra tokens + tokens.truncate(running.saturating_sub(1)); - loop { - // Avoid holding the lock for the entire duration of the match. - let maybe_work = work_items_arc.lock().unwrap().pop(); - match maybe_work { - Some(work) => { - execute_work_item(&cgcx, work); + match rx.recv().unwrap() { + // Save the token locally and the next turn of the loop will use + // this to spawn a new unit of work, or it may get dropped + // immediately if we have no more work to spawn. + Message::Token(token) => { + tokens.push(token.expect("failed to acquire jobserver token")); + } + + // If a thread exits successfully then we drop a token associated + // with that worker and update our `running` count. We may later + // re-acquire a token to continue running more work. We may also not + // actually drop a token here if the worker was running with an + // "ephemeral token" + // + // Note that if the thread failed that means it panicked, so we + // abort immediately. + Message::Done { success: true } => { + drop(tokens.pop()); + running -= 1; + } + Message::Done { success: false } => { + sess.fatal("aborting due to worker thread panic"); + } - // Make sure to fail the worker so the main thread can - // tell that there were errors. - cgcx.handler.abort_if_errors(); + // Our worker wants us to emit an error message, so get ahold of our + // `sess` and print it out + Message::Diagnostic(diag) => { + let handler = sess.diagnostic(); + match diag.code { + Some(ref code) => { + handler.emit_with_code(&MultiSpan::new(), + &diag.msg, + &code, + diag.lvl); } - None => break, + None => { + handler.emit(&MultiSpan::new(), + &diag.msg, + diag.lvl); + } + } + } + Message::InlineAsmError(cookie, msg) => { + match Mark::from_u32(cookie).expn_info() { + Some(ei) => sess.span_err(ei.call_site, &msg), + None => sess.err(&msg), } } - tx.take().unwrap().send(()).unwrap(); - }).unwrap(); + // Sent to us after a worker sends us a batch of error messages, and + // it's the point at which we check for errors. + Message::AbortIfErrors => sess.diagnostic().abort_if_errors(), + } } - let mut panicked = false; - for rx in futures { - match rx.recv() { - Ok(()) => {}, - Err(_) => { - panicked = true; - }, + // Just in case, check this on the way out. + sess.diagnostic().abort_if_errors(); +} + +struct SharedEmitter { + tx: Sender, +} + +impl Emitter for SharedEmitter { + fn emit(&mut self, db: &DiagnosticBuilder) { + drop(self.tx.send(Message::Diagnostic(Diagnostic { + msg: db.message(), + code: db.code.clone(), + lvl: db.level, + }))); + for child in &db.children { + drop(self.tx.send(Message::Diagnostic(Diagnostic { + msg: child.message(), + code: None, + lvl: child.level, + }))); } - // Display any new diagnostics. - diag_emitter.dump(sess.diagnostic()); - } - if panicked { - sess.fatal("aborting due to worker thread panic"); + drop(self.tx.send(Message::AbortIfErrors)); } } +fn spawn_work<'a>(sess: &'a Session, + exported_symbols: &'a ExportedSymbols, + scope: &Scope<'a>, + tx: Sender, + work: WorkItem, + idx: usize) { + let plugin_passes = sess.plugin_llvm_passes.borrow().clone(); + let remark = sess.opts.cg.remark.clone(); + let incr_comp_session_dir = sess.incr_comp_session_dir_opt().map(|r| r.clone()); + let depth = time_depth(); + let lto = sess.lto(); + let crate_types = sess.crate_types.borrow().clone(); + let mut each_linked_rlib_for_lto = Vec::new(); + drop(link::each_linked_rlib(sess, &mut |cnum, path| { + if link::ignored_for_lto(sess, cnum) { + return + } + each_linked_rlib_for_lto.push((cnum, path.to_path_buf())); + })); + let time_passes = sess.time_passes(); + let no_landing_pads = sess.no_landing_pads(); + let opts = &sess.opts; + + scope.spawn(move || { + set_time_depth(depth); + + // Set up a destructor which will fire off a message that we're done as + // we exit. + struct Bomb { + tx: Sender, + success: bool, + } + impl Drop for Bomb { + fn drop(&mut self) { + drop(self.tx.send(Message::Done { success: self.success })); + } + } + let mut bomb = Bomb { + tx: tx.clone(), + success: false, + }; + + // Set up our non-`Send` `CodegenContext` now that we're in a helper + // thread and have all our info available to us. + let emitter = SharedEmitter { tx: tx.clone() }; + let diag_handler = Handler::with_emitter(true, false, Box::new(emitter)); + + let cgcx = CodegenContext { + crate_types: crate_types, + each_linked_rlib_for_lto: each_linked_rlib_for_lto, + lto: lto, + no_landing_pads: no_landing_pads, + opts: opts, + time_passes: time_passes, + exported_symbols: exported_symbols, + handler: &diag_handler, + plugin_passes: plugin_passes, + remark: remark, + worker: idx, + incr_comp_session_dir: incr_comp_session_dir, + tx: tx.clone(), + }; + + // Execute the work itself, and if it finishes successfully then flag + // ourselves as a success as well. + // + // Note that we ignore the result coming out of `execute_work_item` + // which will tell us if the worker failed with a `FatalError`. If that + // has happened, however, then a diagnostic was sent off to the main + // thread, along with an `AbortIfErrors` message. In that case the main + // thread is already exiting anyway most likely. + // + // In any case, there's no need for us to take further action here, so + // we just ignore the result and then send off our message saying that + // we're done, which if `execute_work_item` failed is unlikely to be + // seen by the main thread, but hey we might as well try anyway. + drop(execute_work_item(&cgcx, work).is_err()); + bomb.success = true; + }); +} + pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) { let (pname, mut cmd, _) = get_linker(sess); diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 88c30cd866..ccb4742e45 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -43,10 +43,11 @@ use rustc::dep_graph::AssertDepGraphSafe; use rustc::middle::cstore::LinkMeta; use rustc::hir::map as hir_map; use rustc::util::common::time; -use rustc::session::config::{self, NoDebugInfo}; +use rustc::session::config::{self, NoDebugInfo, OutputFilenames}; use rustc::session::Session; use rustc_incremental::IncrementalHashesMap; use abi; +use allocator; use mir::lvalue::LvalueRef; use attributes; use builder::Builder; @@ -727,7 +728,9 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, link_meta: &LinkMeta, exported_symbols: &NodeSet) -> (ContextRef, ModuleRef, EncodedMetadata) { - use flate; + use std::io::Write; + use flate2::Compression; + use flate2::write::DeflateEncoder; let (metadata_llcx, metadata_llmod) = unsafe { context::create_context_and_module(tcx.sess, "metadata") @@ -767,7 +770,8 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, assert!(kind == MetadataKind::Compressed); let mut compressed = cstore.metadata_encoding_version().to_vec(); - compressed.extend_from_slice(&flate::deflate_bytes(&metadata.raw_data)); + DeflateEncoder::new(&mut compressed, Compression::Fast) + .write_all(&metadata.raw_data).unwrap(); let llmeta = C_bytes_in_context(metadata_llcx, &compressed); let llconst = C_struct_in_context(metadata_llcx, &[llmeta], false); @@ -1049,7 +1053,8 @@ pub fn find_exported_symbols(tcx: TyCtxt, reachable: &NodeSet) -> NodeSet { pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, analysis: ty::CrateAnalysis, - incremental_hashes_map: &IncrementalHashesMap) + incremental_hashes_map: &IncrementalHashesMap, + output_filenames: &OutputFilenames) -> CrateTranslation { // Be careful with this krate: obviously it gives access to the // entire contents of the krate. So if you push any subtasks of @@ -1066,7 +1071,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let shared_ccx = SharedCrateContext::new(tcx, exported_symbols, - check_overflow); + check_overflow, + output_filenames); // Translate the metadata. let (metadata_llcx, metadata_llmod, metadata) = time(tcx.sess.time_passes(), "write metadata", || { @@ -1081,8 +1087,10 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, llmod: metadata_llmod, }), }; + let no_builtins = attr::contains_name(&krate.attrs, "no_builtins"); + // Skip crate items and just output metadata in -Z no-trans mode. if tcx.sess.opts.debugging_opts.no_trans || !tcx.sess.opts.output_types.should_trans() { @@ -1092,6 +1100,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_name: tcx.crate_name(LOCAL_CRATE), modules: vec![], metadata_module: metadata_module, + allocator_module: None, link: link_meta, metadata: metadata, exported_symbols: empty_exported_symbols, @@ -1111,7 +1120,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .into_iter() .map(|cgu| { let dep_node = cgu.work_product_dep_node(); - let (stats, module) = + let ((stats, module), _) = tcx.dep_graph.with_task(dep_node, AssertDepGraphSafe(&shared_ccx), AssertDepGraphSafe(cgu), @@ -1145,9 +1154,9 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Some(work_product) } else { if scx.sess().opts.debugging_opts.incremental_info { - println!("incremental: CGU `{}` invalidated because of \ - changed partitioning hash.", - cgu.name()); + eprintln!("incremental: CGU `{}` invalidated because of \ + changed partitioning hash.", + cgu.name()); } debug!("trans_reuse_previous_work_products: \ not reusing {:?} because hash changed to {:?}", @@ -1291,6 +1300,41 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, create_imps(sess, &llvm_modules); } + // Translate an allocator shim, if any + // + // If LTO is enabled and we've got some previous LLVM module we translated + // above, then we can just translate directly into that LLVM module. If not, + // however, we need to create a separate module and trans into that. Note + // that the separate translation is critical for the standard library where + // the rlib's object file doesn't have allocator functions but the dylib + // links in an object file that has allocator functions. When we're + // compiling a final LTO artifact, though, there's no need to worry about + // this as we're not working with this dual "rlib/dylib" functionality. + let allocator_module = tcx.sess.allocator_kind.get().and_then(|kind| unsafe { + if sess.lto() && llvm_modules.len() > 0 { + time(tcx.sess.time_passes(), "write allocator module", || { + allocator::trans(tcx, &llvm_modules[0], kind) + }); + None + } else { + let (llcx, llmod) = + context::create_context_and_module(tcx.sess, "allocator"); + let modules = ModuleLlvm { + llmod: llmod, + llcx: llcx, + }; + time(tcx.sess.time_passes(), "write allocator module", || { + allocator::trans(tcx, &modules, kind) + }); + + Some(ModuleTranslation { + name: link::ALLOCATOR_MODULE_NAME.to_string(), + symbol_name_hash: 0, // we always rebuild allocator shims + source: ModuleSource::Translated(modules), + }) + } + }); + let linker_info = LinkerInfo::new(&shared_ccx, &exported_symbols); let subsystem = attr::first_attr_value_str_by_name(&krate.attrs, @@ -1308,6 +1352,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_name: tcx.crate_name(LOCAL_CRATE), modules: modules, metadata_module: metadata_module, + allocator_module: allocator_module, link: link_meta, metadata: metadata, exported_symbols: exported_symbols, diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index d723cf3257..a76abcf7b4 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -195,7 +195,7 @@ use rustc::hir::map as hir_map; use rustc::hir::def_id::DefId; use rustc::middle::lang_items::{ExchangeMallocFnLangItem}; use rustc::traits; -use rustc::ty::subst::{Substs, Subst}; +use rustc::ty::subst::Substs; use rustc::ty::{self, TypeFoldable, TyCtxt}; use rustc::ty::adjustment::CustomCoerceUnsized; use rustc::mir::{self, Location}; @@ -304,6 +304,11 @@ fn collect_roots<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, scx.tcx().hir.krate().visit_all_item_likes(&mut visitor); } + // We can only translate items that are instantiable - items all of + // whose predicates hold. Luckily, items that aren't instantiable + // can't actually be used, so we can just skip translating them. + roots.retain(|root| root.is_instantiable(scx.tcx())); + roots } @@ -587,7 +592,7 @@ fn visit_fn_use<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, is_direct_call: bool, output: &mut Vec>) { - if let ty::TyFnDef(def_id, substs, _) = ty.sty { + if let ty::TyFnDef(def_id, substs) = ty.sty { let instance = monomorphize::resolve(scx, def_id, substs); visit_instance_use(scx, instance, is_direct_call, output); } @@ -937,14 +942,9 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(scx: &SharedCrateContext<'a, ' let instance = monomorphize::resolve(scx, method.def_id, callee_substs); - let predicates = tcx.predicates_of(instance.def_id()).predicates - .subst(tcx, instance.substs); - if !traits::normalize_and_test_predicates(tcx, predicates) { - continue; - } - - if should_trans_locally(tcx, &instance) { - output.push(create_fn_trans_item(instance)); + let trans_item = create_fn_trans_item(instance); + if trans_item.is_instantiable(tcx) && should_trans_locally(tcx, &instance) { + output.push(trans_item); } } } diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index a6f3fb709a..9b0803908b 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -495,12 +495,12 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, -> ty::PolyFnSig<'tcx> { match ty.sty { - ty::TyFnDef(_, _, sig) => sig, + ty::TyFnDef(..) | // Shims currently have type TyFnPtr. Not sure this should remain. - ty::TyFnPtr(sig) => sig, + ty::TyFnPtr(_) => ty.fn_sig(ccx.tcx()), ty::TyClosure(def_id, substs) => { let tcx = ccx.tcx(); - let sig = tcx.closure_type(def_id).subst(tcx, substs.substs); + let sig = tcx.fn_sig(def_id).subst(tcx, substs.substs); let env_region = ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrEnv); let env_ty = match tcx.closure_kind(def_id) { diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 6266452419..208e994653 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -23,7 +23,7 @@ use monomorphize::Instance; use partitioning::CodegenUnit; use type_::Type; use rustc_data_structures::base_n; -use rustc::session::config::{self, NoDebugInfo}; +use rustc::session::config::{self, NoDebugInfo, OutputFilenames}; use rustc::session::Session; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; @@ -81,6 +81,8 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> { check_overflow: bool, use_dll_storage_attrs: bool, + + output_filenames: &'a OutputFilenames, } /// The local portion of a `CrateContext`. There is one `LocalCrateContext` @@ -264,7 +266,8 @@ pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (Cont impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>, exported_symbols: NodeSet, - check_overflow: bool) + check_overflow: bool, + output_filenames: &'b OutputFilenames) -> SharedCrateContext<'b, 'tcx> { // An interesting part of Windows which MSVC forces our hand on (and // apparently MinGW didn't) is the usage of `dllimport` and `dllexport` @@ -316,6 +319,7 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { tcx: tcx, check_overflow: check_overflow, use_dll_storage_attrs: use_dll_storage_attrs, + output_filenames: output_filenames, } } @@ -350,6 +354,10 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { pub fn use_dll_storage_attrs(&self) -> bool { self.use_dll_storage_attrs } + + pub fn output_filenames(&self) -> &OutputFilenames { + self.output_filenames + } } impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> { diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index fea24e6da8..61204b88e1 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -14,7 +14,7 @@ use self::MemberDescriptionFactory::*; use self::EnumDiscriminantInfo::*; use super::utils::{debug_context, DIB, span_start, bytes_to_bits, size_and_align_of, - get_namespace_and_span_for_item, create_DIArray, is_node_local_to_unit}; + get_namespace_for_item, create_DIArray, is_node_local_to_unit}; use super::namespace::mangled_name_of_item; use super::type_names::compute_debuginfo_type_name; use super::{CrateDebugContext}; @@ -38,10 +38,12 @@ use rustc::ty::{self, AdtKind, Ty}; use rustc::ty::layout::{self, LayoutTyper}; use rustc::session::{Session, config}; use rustc::util::nodemap::FxHashMap; +use rustc::util::common::path2cstr; use libc::{c_uint, c_longlong}; use std::ffi::CString; use std::ptr; +use std::path::Path; use syntax::ast; use syntax::symbol::{Interner, InternedString, Symbol}; use syntax_pos::{self, Span}; @@ -419,7 +421,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let containing_scope = match trait_type.sty { ty::TyDynamic(ref data, ..) => if let Some(principal) = data.principal() { let def_id = principal.def_id(); - get_namespace_and_span_for_item(cx, def_id).0 + get_namespace_for_item(cx, def_id) } else { NO_SCOPE_METADATA }, @@ -486,7 +488,6 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, debug!("type_metadata: {:?}", t); - let sty = &t.sty; let ptr_metadata = |ty: Ty<'tcx>| { match ty.sty { ty::TySlice(typ) => { @@ -516,7 +517,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } }; - let MetadataCreationResult { metadata, already_stored_in_typemap } = match *sty { + let MetadataCreationResult { metadata, already_stored_in_typemap } = match t.sty { ty::TyNever | ty::TyBool | ty::TyChar | @@ -555,10 +556,10 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, Err(metadata) => return metadata, } } - ty::TyFnDef(.., sig) | ty::TyFnPtr(sig) => { + ty::TyFnDef(..) | ty::TyFnPtr(_) => { let fn_metadata = subroutine_type_metadata(cx, unique_type_id, - sig, + t.fn_sig(cx.tcx()), usage_site_span).metadata; match debug_context(cx).type_map .borrow() @@ -608,7 +609,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, usage_site_span).finalize(cx) } _ => { - bug!("debuginfo: unexpected type in type_metadata: {:?}", sty) + bug!("debuginfo: unexpected type in type_metadata: {:?}", t) } }; @@ -794,7 +795,7 @@ pub fn compile_unit_metadata(scc: &SharedCrateContext, let file_metadata = llvm::LLVMRustDIBuilderCreateFile( debug_context.builder, name_in_debuginfo.as_ptr(), work_dir.as_ptr()); - return llvm::LLVMRustDIBuilderCreateCompileUnit( + let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit( debug_context.builder, DW_LANG_RUST, file_metadata, @@ -802,8 +803,40 @@ pub fn compile_unit_metadata(scc: &SharedCrateContext, sess.opts.optimize != config::OptLevel::No, flags.as_ptr() as *const _, 0, - split_name.as_ptr() as *const _) + split_name.as_ptr() as *const _); + + if sess.opts.debugging_opts.profile { + let cu_desc_metadata = llvm::LLVMRustMetadataAsValue(debug_context.llcontext, + unit_metadata); + + let gcov_cu_info = [ + path_to_mdstring(debug_context.llcontext, + &scc.output_filenames().with_extension("gcno")), + path_to_mdstring(debug_context.llcontext, + &scc.output_filenames().with_extension("gcda")), + cu_desc_metadata, + ]; + let gcov_metadata = llvm::LLVMMDNodeInContext(debug_context.llcontext, + gcov_cu_info.as_ptr(), + gcov_cu_info.len() as c_uint); + + let llvm_gcov_ident = CString::new("llvm.gcov").unwrap(); + llvm::LLVMAddNamedMetadataOperand(debug_context.llmod, + llvm_gcov_ident.as_ptr(), + gcov_metadata); + } + + return unit_metadata; }; + + fn path_to_mdstring(llcx: llvm::ContextRef, path: &Path) -> llvm::ValueRef { + let path_str = path2cstr(path); + unsafe { + llvm::LLVMMDStringInContext(llcx, + path_str.as_ptr(), + path_str.as_bytes().len() as c_uint) + } + } } struct MetadataCreationResult { @@ -938,7 +971,7 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, _ => bug!("prepare_struct_metadata on a non-ADT") }; - let (containing_scope, _) = get_namespace_and_span_for_item(cx, struct_def_id); + let containing_scope = get_namespace_for_item(cx, struct_def_id); let struct_metadata_stub = create_struct_stub(cx, struct_llvm_type, @@ -1063,7 +1096,7 @@ fn prepare_union_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, _ => bug!("prepare_union_metadata on a non-ADT") }; - let (containing_scope, _) = get_namespace_and_span_for_item(cx, union_def_id); + let containing_scope = get_namespace_for_item(cx, union_def_id); let union_metadata_stub = create_union_stub(cx, union_llvm_type, @@ -1450,7 +1483,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, -> RecursiveTypeDescription<'tcx> { let enum_name = compute_debuginfo_type_name(cx, enum_type, false); - let (containing_scope, _) = get_namespace_and_span_for_item(cx, enum_def_id); + let containing_scope = get_namespace_for_item(cx, enum_def_id); // FIXME: This should emit actual file metadata for the enum, but we // currently can't get the necessary information when it comes to types // imported from other crates. Formerly we violated the ODR when performing @@ -1748,7 +1781,8 @@ pub fn create_global_var_metadata(cx: &CrateContext, let tcx = cx.tcx(); let node_def_id = tcx.hir.local_def_id(node_id); - let (var_scope, span) = get_namespace_and_span_for_item(cx, node_def_id); + let var_scope = get_namespace_for_item(cx, node_def_id); + let span = cx.tcx().def_span(node_def_id); let (file_metadata, line_number) = if span != syntax_pos::DUMMY_SP { let loc = span_start(cx, span); diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index 4d781d6f77..68432c22f8 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -43,7 +43,7 @@ use std::ptr; use syntax_pos::{self, Span, Pos}; use syntax::ast; use syntax::symbol::Symbol; -use rustc::ty::layout; +use rustc::ty::layout::{self, LayoutTyper}; pub mod gdb; mod utils; @@ -67,6 +67,7 @@ const DW_TAG_arg_variable: c_uint = 0x101; /// A context object for maintaining all state needed by the debuginfo module. pub struct CrateDebugContext<'tcx> { llcontext: ContextRef, + llmod: ModuleRef, builder: DIBuilderRef, created_files: RefCell>, created_enum_disr_types: RefCell>, @@ -87,6 +88,7 @@ impl<'tcx> CrateDebugContext<'tcx> { let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) }; CrateDebugContext { llcontext: llcontext, + llmod: llmod, builder: builder, created_files: RefCell::new(FxHashMap()), created_enum_disr_types: RefCell::new(FxHashMap()), @@ -318,8 +320,32 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, }; // Arguments types - for &argument_type in inputs { - signature.push(type_metadata(cx, argument_type, syntax_pos::DUMMY_SP)); + if cx.sess().target.target.options.is_like_msvc { + // FIXME(#42800): + // There is a bug in MSDIA that leads to a crash when it encounters + // a fixed-size array of `u8` or something zero-sized in a + // function-type (see #40477). + // As a workaround, we replace those fixed-size arrays with a + // pointer-type. So a function `fn foo(a: u8, b: [u8; 4])` would + // appear as `fn foo(a: u8, b: *const u8)` in debuginfo, + // and a function `fn bar(x: [(); 7])` as `fn bar(x: *const ())`. + // This transformed type is wrong, but these function types are + // already inaccurate due to ABI adjustments (see #42800). + signature.extend(inputs.iter().map(|&t| { + let t = match t.sty { + ty::TyArray(ct, _) + if (ct == cx.tcx().types.u8) || + (cx.layout_of(ct).size(cx).bytes() == 0) => { + cx.tcx().mk_imm_ptr(ct) + } + _ => t + }; + type_metadata(cx, t, syntax_pos::DUMMY_SP) + })); + } else { + signature.extend(inputs.iter().map(|t| { + type_metadata(cx, t, syntax_pos::DUMMY_SP) + })); } if sig.abi == Abi::RustCall && !sig.inputs().is_empty() { diff --git a/src/librustc_trans/debuginfo/namespace.rs b/src/librustc_trans/debuginfo/namespace.rs index 54a129536d..d4dd112f30 100644 --- a/src/librustc_trans/debuginfo/namespace.rs +++ b/src/librustc_trans/debuginfo/namespace.rs @@ -10,8 +10,8 @@ // Namespace Handling. -use super::metadata::{file_metadata, unknown_file_metadata, UNKNOWN_LINE_NUMBER}; -use super::utils::{DIB, debug_context, span_start}; +use super::metadata::{unknown_file_metadata, UNKNOWN_LINE_NUMBER}; +use super::utils::{DIB, debug_context}; use llvm; use llvm::debuginfo::DIScope; @@ -19,10 +19,8 @@ use rustc::hir::def_id::DefId; use rustc::hir::map::DefPathData; use common::CrateContext; -use libc::c_uint; use std::ffi::CString; use std::ptr; -use syntax_pos::DUMMY_SP; pub fn mangled_name_of_item(ccx: &CrateContext, def_id: DefId, extra: &str) -> String { fn fill_nested(ccx: &CrateContext, def_id: DefId, extra: &str, output: &mut String) { @@ -69,21 +67,14 @@ pub fn item_namespace(ccx: &CrateContext, def_id: DefId) -> DIScope { }; let namespace_name = CString::new(namespace_name.as_bytes()).unwrap(); - let span = ccx.tcx().def_span(def_id); - let (file, line) = if span != DUMMY_SP { - let loc = span_start(ccx, span); - (file_metadata(ccx, &loc.file.name, def_id.krate), loc.line as c_uint) - } else { - (unknown_file_metadata(ccx), UNKNOWN_LINE_NUMBER) - }; let scope = unsafe { llvm::LLVMRustDIBuilderCreateNameSpace( DIB(ccx), parent_scope, namespace_name.as_ptr(), - file, - line as c_uint) + unknown_file_metadata(ccx), + UNKNOWN_LINE_NUMBER) }; debug_context(ccx).namespace_map.borrow_mut().insert(def_id, scope); diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index 13ff6646e6..bfca4fec70 100644 --- a/src/librustc_trans/debuginfo/type_names.rs +++ b/src/librustc_trans/debuginfo/type_names.rs @@ -96,8 +96,8 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, push_type_params(cx, principal.substs, output); } }, - ty::TyFnDef(.., sig) | - ty::TyFnPtr(sig) => { + ty::TyFnDef(..) | ty::TyFnPtr(_) => { + let sig = t.fn_sig(cx.tcx()); if sig.unsafety() == hir::Unsafety::Unsafe { output.push_str("unsafe "); } diff --git a/src/librustc_trans/debuginfo/utils.rs b/src/librustc_trans/debuginfo/utils.rs index 0a873767d9..0555714d62 100644 --- a/src/librustc_trans/debuginfo/utils.rs +++ b/src/librustc_trans/debuginfo/utils.rs @@ -73,13 +73,7 @@ pub fn DIB(cx: &CrateContext) -> DIBuilderRef { cx.dbg_cx().as_ref().unwrap().builder } -pub fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: DefId) - -> (DIScope, Span) { - let containing_scope = item_namespace(cx, cx.tcx().parent(def_id) - .expect("get_namespace_and_span_for_item: missing parent?")); - - // Try to get some span information, if we have an inlined item. - let definition_span = cx.tcx().def_span(def_id); - - (containing_scope, definition_span) +pub fn get_namespace_for_item(cx: &CrateContext, def_id: DefId) -> DIScope { + item_namespace(cx, cx.tcx().parent(def_id) + .expect("get_namespace_for_item: missing parent?")) } diff --git a/src/librustc_trans/declare.rs b/src/librustc_trans/declare.rs index 2787812f96..8f9146283e 100644 --- a/src/librustc_trans/declare.rs +++ b/src/librustc_trans/declare.rs @@ -30,7 +30,6 @@ use context::CrateContext; use common; use type_::Type; use value::Value; -use syntax::attr; use std::ffi::CString; @@ -88,16 +87,6 @@ fn declare_raw_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, ty: } } - // If we're compiling the compiler-builtins crate, e.g. the equivalent of - // compiler-rt, then we want to implicitly compile everything with hidden - // visibility as we're going to link this object all over the place but - // don't want the symbols to get exported. - if attr::contains_name(ccx.tcx().hir.krate_attrs(), "compiler_builtins") { - unsafe { - llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden); - } - } - match ccx.tcx().sess.opts.cg.opt_level.as_ref().map(String::as_ref) { Some("s") => { llvm::Attribute::OptimizeForSize.apply_llfn(Function, llfn); diff --git a/src/librustc_trans/diagnostics.rs b/src/librustc_trans/diagnostics.rs index 18d31448b1..df71fd4b19 100644 --- a/src/librustc_trans/diagnostics.rs +++ b/src/librustc_trans/diagnostics.rs @@ -16,7 +16,7 @@ E0511: r##" Invalid monomorphization of an intrinsic function was used. Erroneous code example: -```ignore +```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail) #![feature(platform_intrinsics)] extern "platform-intrinsic" { diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index 367f0398fa..c2f44c089a 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -76,7 +76,7 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, inf } assert!(!info.is_null()); match t.sty { - ty::TyAdt(def, substs) => { + ty::TyAdt(..) | ty::TyTuple(..) => { let ccx = bcx.ccx; // First get the size of all statically known fields. // Don't use size_of because it also rounds up to alignment, which we @@ -101,8 +101,14 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, inf // Recurse to get the size of the dynamically sized field (must be // the last field). - let last_field = def.struct_variant().fields.last().unwrap(); - let field_ty = monomorphize::field_ty(bcx.tcx(), substs, last_field); + let field_ty = match t.sty { + ty::TyAdt(def, substs) => { + let last_field = def.struct_variant().fields.last().unwrap(); + monomorphize::field_ty(bcx.tcx(), substs, last_field) + }, + ty::TyTuple(tys, _) => tys.last().unwrap(), + _ => unreachable!(), + }; let (unsized_size, unsized_align) = size_and_align_of_dst(bcx, field_ty, info); // FIXME (#26403, #27023): We should be adding padding diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index f2e6aa3ef0..9956c28e64 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -95,11 +95,12 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, let ccx = bcx.ccx; let tcx = ccx.tcx(); - let (def_id, substs, sig) = match callee_ty.sty { - ty::TyFnDef(def_id, substs, sig) => (def_id, substs, sig), + let (def_id, substs) = match callee_ty.sty { + ty::TyFnDef(def_id, substs) => (def_id, substs), _ => bug!("expected fn item type, found {}", callee_ty) }; + let sig = callee_ty.fn_sig(tcx); let sig = tcx.erase_late_bound_regions_and_normalize(&sig); let arg_tys = sig.inputs(); let ret_ty = sig.output(); @@ -267,7 +268,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, }; bcx.call(expect, &[llargs[0], C_i32(ccx, rw), llargs[1], C_i32(ccx, cache_type)], None) }, - "ctlz" | "cttz" | "ctpop" | "bswap" | + "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "ctpop" | "bswap" | "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" | "overflowing_add" | "overflowing_sub" | "overflowing_mul" | "unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" => { @@ -280,6 +281,12 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, let llfn = ccx.get_intrinsic(&format!("llvm.{}.i{}", name, width)); bcx.call(llfn, &[llargs[0], y], None) } + "ctlz_nonzero" | "cttz_nonzero" => { + let y = C_bool(bcx.ccx, true); + let llvm_name = &format!("llvm.{}.i{}", &name[..4], width); + let llfn = ccx.get_intrinsic(llvm_name); + bcx.call(llfn, &[llargs[0], y], None) + } "ctpop" => bcx.call(ccx.get_intrinsic(&format!("llvm.ctpop.i{}", width)), &llargs, None), "bswap" => { @@ -980,7 +987,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( let tcx = bcx.tcx(); - let sig = tcx.erase_late_bound_regions_and_normalize(&callee_ty.fn_sig()); + let sig = tcx.erase_late_bound_regions_and_normalize(&callee_ty.fn_sig(tcx)); let arg_tys = sig.inputs(); // every intrinsic takes a SIMD vector as its first argument diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index e655f4eae4..3038c7d6c7 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -22,7 +22,6 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![deny(warnings)] -#![feature(associated_consts)] #![feature(box_patterns)] #![feature(box_syntax)] #![feature(const_fn)] @@ -33,20 +32,19 @@ #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(slice_patterns)] -#![feature(unicode)] #![feature(conservative_impl_trait)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] +#![cfg_attr(stage0, feature(associated_consts))] use rustc::dep_graph::WorkProduct; use syntax_pos::symbol::Symbol; -extern crate flate; +extern crate flate2; +extern crate crossbeam; extern crate libc; extern crate owning_ref; #[macro_use] extern crate rustc; +extern crate rustc_allocator; extern crate rustc_back; extern crate rustc_data_structures; extern crate rustc_incremental; @@ -56,6 +54,8 @@ extern crate rustc_const_math; #[macro_use] #[no_link] extern crate rustc_bitflags; +extern crate rustc_demangle; +extern crate jobserver; #[macro_use] extern crate log; #[macro_use] extern crate syntax; @@ -86,6 +86,7 @@ mod diagnostics; mod abi; mod adt; +mod allocator; mod asm; mod assert_module_sources; mod attributes; @@ -165,6 +166,7 @@ pub struct CrateTranslation { pub crate_name: Symbol, pub modules: Vec, pub metadata_module: ModuleTranslation, + pub allocator_module: Option, pub link: rustc::middle::cstore::LinkMeta, pub metadata: rustc::middle::cstore::EncodedMetadata, pub exported_symbols: back::symbol_export::ExportedSymbols, diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 4926485a12..9bb29c340d 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -28,6 +28,7 @@ use type_of; use type_::Type; use syntax::symbol::Symbol; +use syntax_pos::Pos; use std::cmp; @@ -146,6 +147,13 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { } else { let llret = bcx.call(fn_ptr, &llargs, cleanup_bundle); fn_ty.apply_attrs_callsite(llret); + if this.mir[bb].is_cleanup { + // Cleanup is always the cold path. Don't inline + // drop glue. Also, when there is a deeply-nested + // struct, there are "symmetry" issues that cause + // exponential inlining - see issue #41696. + llvm::Attribute::NoInline.apply_callsite(llvm::AttributePlace::Function, llret); + } if let Some((ret_dest, ret_ty, target)) = destination { let op = OperandRef { @@ -255,7 +263,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { } mir::TerminatorKind::Drop { ref location, target, unwind } => { - let ty = location.ty(&self.mir, bcx.tcx()).to_ty(bcx.tcx()); + let ty = location.ty(self.mir, bcx.tcx()).to_ty(bcx.tcx()); let ty = self.monomorphize(&ty); let drop_fn = monomorphize::resolve_drop_in_place(bcx.ccx.shared(), ty); @@ -326,6 +334,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { let filename = Symbol::intern(&loc.file.name).as_str(); let filename = C_str_slice(bcx.ccx, filename); let line = C_u32(bcx.ccx, loc.line as u32); + let col = C_u32(bcx.ccx, loc.col.to_usize() as u32 + 1); // Put together the arguments to the panic entry point. let (lang_item, args, const_err) = match *msg { @@ -340,29 +349,29 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { index: index as u64 })); - let file_line = C_struct(bcx.ccx, &[filename, line], false); - let align = llalign_of_min(bcx.ccx, common::val_ty(file_line)); - let file_line = consts::addr_of(bcx.ccx, - file_line, - align, - "panic_bounds_check_loc"); + let file_line_col = C_struct(bcx.ccx, &[filename, line, col], false); + let align = llalign_of_min(bcx.ccx, common::val_ty(file_line_col)); + let file_line_col = consts::addr_of(bcx.ccx, + file_line_col, + align, + "panic_bounds_check_loc"); (lang_items::PanicBoundsCheckFnLangItem, - vec![file_line, index, len], + vec![file_line_col, index, len], const_err) } mir::AssertMessage::Math(ref err) => { let msg_str = Symbol::intern(err.description()).as_str(); let msg_str = C_str_slice(bcx.ccx, msg_str); - let msg_file_line = C_struct(bcx.ccx, - &[msg_str, filename, line], + let msg_file_line_col = C_struct(bcx.ccx, + &[msg_str, filename, line, col], false); - let align = llalign_of_min(bcx.ccx, common::val_ty(msg_file_line)); - let msg_file_line = consts::addr_of(bcx.ccx, - msg_file_line, - align, - "panic_loc"); + let align = llalign_of_min(bcx.ccx, common::val_ty(msg_file_line_col)); + let msg_file_line_col = consts::addr_of(bcx.ccx, + msg_file_line_col, + align, + "panic_loc"); (lang_items::PanicFnLangItem, - vec![msg_file_line], + vec![msg_file_line_col], Some(ErrKind::Math(err.clone()))) } }; @@ -397,20 +406,18 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar. let callee = self.trans_operand(&bcx, func); - let (instance, mut llfn, sig) = match callee.ty.sty { - ty::TyFnDef(def_id, substs, sig) => { + let (instance, mut llfn) = match callee.ty.sty { + ty::TyFnDef(def_id, substs) => { (Some(monomorphize::resolve(bcx.ccx.shared(), def_id, substs)), - None, - sig) + None) } - ty::TyFnPtr(sig) => { - (None, - Some(callee.immediate()), - sig) + ty::TyFnPtr(_) => { + (None, Some(callee.immediate())) } _ => bug!("{} is not callable", callee.ty) }; let def = instance.map(|i| i.def); + let sig = callee.ty.fn_sig(bcx.tcx()); let sig = bcx.tcx().erase_late_bound_regions_and_normalize(&sig); let abi = sig.abi; @@ -431,7 +438,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { let extra_args = &args[sig.inputs().len()..]; let extra_args = extra_args.iter().map(|op_arg| { - let op_ty = op_arg.ty(&self.mir, bcx.tcx()); + let op_ty = op_arg.ty(self.mir, bcx.tcx()); self.monomorphize(&op_ty) }).collect::>(); diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 4967ef2f79..fcb4b25e6f 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -284,6 +284,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { } mir::StatementKind::StorageLive(_) | mir::StatementKind::StorageDead(_) | + mir::StatementKind::EndRegion(_) | mir::StatementKind::Nop => {} mir::StatementKind::InlineAsm { .. } | mir::StatementKind::SetDiscriminant{ .. } => { @@ -333,7 +334,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { let fn_ty = func.ty(self.mir, tcx); let fn_ty = self.monomorphize(&fn_ty); let (def_id, substs) = match fn_ty.sty { - ty::TyFnDef(def_id, substs, _) => (def_id, substs), + ty::TyFnDef(def_id, substs) => (def_id, substs), _ => span_bug!(span, "calling {:?} (of type {}) in constant", func, fn_ty) }; @@ -559,7 +560,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { let val = match *kind { mir::CastKind::ReifyFnPointer => { match operand.ty.sty { - ty::TyFnDef(def_id, substs, _) => { + ty::TyFnDef(def_id, substs) => { callee::resolve_and_get_fn(self.ccx, def_id, substs) } _ => { @@ -578,7 +579,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { .find(|it| it.kind == ty::AssociatedKind::Method) .unwrap().def_id; // Now create its substs [Closure, Tuple] - let input = tcx.closure_type(def_id) + let input = tcx.fn_sig(def_id) .subst(tcx, substs.substs).input(0); let input = tcx.erase_late_bound_regions_and_normalize(&input); let substs = tcx.mk_substs([operand.ty, input] diff --git a/src/librustc_trans/mir/lvalue.rs b/src/librustc_trans/mir/lvalue.rs index 88e46b5c99..af8976967a 100644 --- a/src/librustc_trans/mir/lvalue.rs +++ b/src/librustc_trans/mir/lvalue.rs @@ -408,7 +408,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { pub fn monomorphized_lvalue_ty(&self, lvalue: &mir::Lvalue<'tcx>) -> Ty<'tcx> { let tcx = self.ccx.tcx(); - let lvalue_ty = lvalue.ty(&self.mir, tcx); + let lvalue_ty = lvalue.ty(self.mir, tcx); self.monomorphize(&lvalue_ty.to_ty(tcx)) } } diff --git a/src/librustc_trans/mir/operand.rs b/src/librustc_trans/mir/operand.rs index a12d0fec1c..1b8a05b6f6 100644 --- a/src/librustc_trans/mir/operand.rs +++ b/src/librustc_trans/mir/operand.rs @@ -338,8 +338,20 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { let a = base::from_immediate(bcx, a); let b = base::from_immediate(bcx, b); - bcx.store(a, bcx.struct_gep(lldest, ix0), f_align); - bcx.store(b, bcx.struct_gep(lldest, ix1), f_align); + + // See comment above about zero-sized values. + let (a_zst, b_zst) = common::type_pair_fields(bcx.ccx, operand.ty) + .map_or((false, false), |[a_ty, b_ty]| { + (common::type_is_zero_size(bcx.ccx, a_ty), + common::type_is_zero_size(bcx.ccx, b_ty)) + }); + + if !a_zst { + bcx.store(a, bcx.struct_gep(lldest, ix0), f_align); + } + if !b_zst { + bcx.store(b, bcx.struct_gep(lldest, ix1), f_align); + } } } } diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 61e537c9cc..4bd5091a4f 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -180,7 +180,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { let val = match *kind { mir::CastKind::ReifyFnPointer => { match operand.ty.sty { - ty::TyFnDef(def_id, substs, _) => { + ty::TyFnDef(def_id, substs) => { OperandValue::Immediate( callee::resolve_and_get_fn(bcx.ccx, def_id, substs)) } diff --git a/src/librustc_trans/mir/statement.rs b/src/librustc_trans/mir/statement.rs index 52c2afca47..170a76a494 100644 --- a/src/librustc_trans/mir/statement.rs +++ b/src/librustc_trans/mir/statement.rs @@ -86,6 +86,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { asm::trans_inline_asm(&bcx, asm, outputs, input_vals); bcx } + mir::StatementKind::EndRegion(_) | mir::StatementKind::Nop => bcx, } } diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index d27eeb2b64..1f6a262162 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -40,7 +40,7 @@ fn fn_once_adapter_instance<'a, 'tcx>( let self_ty = tcx.mk_closure_from_closure_substs( closure_did, substs); - let sig = tcx.closure_type(closure_did).subst(tcx, substs.substs); + let sig = tcx.fn_sig(closure_did).subst(tcx, substs.substs); let sig = tcx.erase_late_bound_regions_and_normalize(&sig); assert_eq!(sig.inputs().len(), 1); let substs = tcx.mk_substs([ @@ -165,9 +165,11 @@ pub fn resolve<'a, 'tcx>( } else { let item_type = def_ty(scx, def_id, substs); let def = match item_type.sty { - ty::TyFnDef(_, _, f) if - f.abi() == Abi::RustIntrinsic || - f.abi() == Abi::PlatformIntrinsic => + ty::TyFnDef(..) if { + let f = item_type.fn_sig(scx.tcx()); + f.abi() == Abi::RustIntrinsic || + f.abi() == Abi::PlatformIntrinsic + } => { debug!(" => intrinsic"); ty::InstanceDef::Intrinsic(def_id) diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index 2fe463e92a..68b72087b2 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -114,7 +114,6 @@ use rustc::ty::{self, TyCtxt}; use rustc::ty::item_path::characteristic_def_id_of_type; use rustc_incremental::IchHasher; use std::hash::Hash; -use std::sync::Arc; use syntax::ast::NodeId; use syntax::symbol::{Symbol, InternedString}; use trans_item::{TransItem, InstantiationMode}; @@ -164,12 +163,12 @@ impl<'tcx> CodegenUnit<'tcx> { &self.items } - pub fn work_product_id(&self) -> Arc { - Arc::new(WorkProductId(self.name().to_string())) + pub fn work_product_id(&self) -> WorkProductId { + WorkProductId::from_cgu_name(self.name()) } - pub fn work_product_dep_node(&self) -> DepNode { - DepNode::WorkProduct(self.work_product_id()) + pub fn work_product_dep_node(&self) -> DepNode { + self.work_product_id().to_dep_node() } pub fn compute_symbol_name_hash<'a>(&self, @@ -271,6 +270,14 @@ pub fn partition<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>, (&cgu1.name[..]).cmp(&cgu2.name[..]) }); + if scx.sess().opts.enable_dep_node_debug_strs() { + for cgu in &result { + let dep_node = cgu.work_product_dep_node(); + scx.tcx().dep_graph.register_dep_node_debug_str(dep_node, + || cgu.name().to_string()); + } + } + result } diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 392ee71d52..8a77b26580 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -23,11 +23,11 @@ use common; use declare; use llvm; use monomorphize::Instance; -use rustc::dep_graph::DepNode; use rustc::hir; use rustc::hir::def_id::DefId; +use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; -use rustc::ty::subst::Substs; +use rustc::ty::subst::{Subst, Substs}; use syntax::ast::{self, NodeId}; use syntax::attr; use syntax_pos::Span; @@ -63,26 +63,15 @@ impl<'a, 'tcx> TransItem<'tcx> { self.to_raw_string(), ccx.codegen_unit().name()); - // (*) This code executes in the context of a dep-node for the - // entire CGU. In some cases, we introduce dep-nodes for - // particular items that we are translating (these nodes will - // have read edges coming into the CGU node). These smaller - // nodes are not needed for correctness -- we always - // invalidate an entire CGU at a time -- but they enable - // finer-grained testing, since you can write tests that check - // that the incoming edges to a particular fn are from a - // particular set. - match *self { TransItem::Static(node_id) => { - let def_id = ccx.tcx().hir.local_def_id(node_id); - let _task = ccx.tcx().dep_graph.in_task(DepNode::TransCrateItem(def_id)); // (*) - let item = ccx.tcx().hir.expect_item(node_id); + let tcx = ccx.tcx(); + let item = tcx.hir.expect_item(node_id); if let hir::ItemStatic(_, m, _) = item.node { match consts::trans_static(&ccx, m, item.id, &item.attrs) { Ok(_) => { /* Cool, everything's alright. */ }, Err(err) => { - err.report(ccx.tcx(), item.span, "static"); + err.report(tcx, item.span, "static"); } }; } else { @@ -98,9 +87,6 @@ impl<'a, 'tcx> TransItem<'tcx> { } } TransItem::Fn(instance) => { - let _task = ccx.tcx().dep_graph.in_task( - DepNode::TransCrateItem(instance.def_id())); // (*) - base::trans_instance(&ccx, instance); } } @@ -176,6 +162,18 @@ impl<'a, 'tcx> TransItem<'tcx> { llvm::SetUniqueComdat(ccx.llmod(), lldecl); } + // If we're compiling the compiler-builtins crate, e.g. the equivalent of + // compiler-rt, then we want to implicitly compile everything with hidden + // visibility as we're going to link this object all over the place but + // don't want the symbols to get exported. + if linkage != llvm::Linkage::InternalLinkage && + linkage != llvm::Linkage::PrivateLinkage && + attr::contains_name(ccx.tcx().hir.krate_attrs(), "compiler_builtins") { + unsafe { + llvm::LLVMRustSetVisibility(lldecl, llvm::Visibility::Hidden); + } + } + debug!("predefine_fn: mono_ty = {:?} instance = {:?}", mono_ty, instance); if common::is_inline_instance(ccx.tcx(), &instance) { attributes::inline(lldecl, attributes::InlineAttr::Hint); @@ -265,6 +263,44 @@ impl<'a, 'tcx> TransItem<'tcx> { } } + /// Returns whether this instance is instantiable - whether it has no unsatisfied + /// predicates. + /// + /// In order to translate an item, all of its predicates must hold, because + /// otherwise the item does not make sense. Type-checking ensures that + /// the predicates of every item that is *used by* a valid item *do* + /// hold, so we can rely on that. + /// + /// However, we translate collector roots (reachable items) and functions + /// in vtables when they are seen, even if they are not used, and so they + /// might not be instantiable. For example, a programmer can define this + /// public function: + /// + /// pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone { + /// <&mut () as Clone>::clone(&s); + /// } + /// + /// That function can't be translated, because the method `<&mut () as Clone>::clone` + /// does not exist. Luckily for us, that function can't ever be used, + /// because that would require for `&'a mut (): Clone` to hold, so we + /// can just not emit any code, or even a linker reference for it. + /// + /// Similarly, if a vtable method has such a signature, and therefore can't + /// be used, we can just not emit it and have a placeholder (a null pointer, + /// which will never be accessed) in its place. + pub fn is_instantiable(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool { + debug!("is_instantiable({:?})", self); + let (def_id, substs) = match *self { + TransItem::Fn(ref instance) => (instance.def_id(), instance.substs), + TransItem::Static(node_id) => (tcx.hir.local_def_id(node_id), Substs::empty()), + // global asm never has predicates + TransItem::GlobalAsm(..) => return true + }; + + let predicates = tcx.predicates_of(def_id).predicates.subst(tcx, substs); + traits::normalize_and_test_predicates(tcx, predicates) + } + pub fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String { let hir_map = &tcx.hir; @@ -416,8 +452,9 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { output); } }, - ty::TyFnDef(.., sig) | - ty::TyFnPtr(sig) => { + ty::TyFnDef(..) | + ty::TyFnPtr(_) => { + let sig = t.fn_sig(self.tcx); if sig.unsafety() == hir::Unsafety::Unsafe { output.push_str("unsafe "); } @@ -521,7 +558,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { for projection in projections { let projection = projection.skip_binder(); - let name = &projection.item_name.as_str(); + let name = &self.tcx.associated_item(projection.item_def_id).name.as_str(); output.push_str(name); output.push_str("="); self.push_type_name(projection.ty, output); diff --git a/src/librustc_tsan/build.rs b/src/librustc_tsan/build.rs index 5ea52f17a0..641d9c3647 100644 --- a/src/librustc_tsan/build.rs +++ b/src/librustc_tsan/build.rs @@ -32,4 +32,5 @@ fn main() { .build_target("tsan") .build(); } + println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 212461a6d7..bb6e478738 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -66,8 +66,8 @@ pub trait AstConv<'gcx, 'tcx> { /// late-bound regions. fn projected_ty_from_poly_trait_ref(&self, span: Span, - poly_trait_ref: ty::PolyTraitRef<'tcx>, - item_name: ast::Name) + item_def_id: DefId, + poly_trait_ref: ty::PolyTraitRef<'tcx>) -> Ty<'tcx>; /// Normalize an associated type coming from the user. @@ -651,11 +651,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { }); let existential_projections = projection_bounds.iter().map(|bound| { bound.map_bound(|b| { - let p = b.projection_ty; + let trait_ref = self.trait_ref_to_existential(b.projection_ty.trait_ref(tcx)); ty::ExistentialProjection { - trait_ref: self.trait_ref_to_existential(p.trait_ref), - item_name: p.item_name(tcx), - ty: b.ty + ty: b.ty, + item_def_id: b.projection_ty.item_def_id, + substs: trait_ref.substs, } }) }); @@ -676,22 +676,22 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { for tr in traits::supertraits(tcx, principal) { associated_types.extend(tcx.associated_items(tr.def_id()) .filter(|item| item.kind == ty::AssociatedKind::Type) - .map(|item| (tr.def_id(), item.name))); + .map(|item| item.def_id)); } for projection_bound in &projection_bounds { - let pair = (projection_bound.0.projection_ty.trait_ref.def_id, - projection_bound.0.projection_ty.item_name(tcx)); - associated_types.remove(&pair); + associated_types.remove(&projection_bound.0.projection_ty.item_def_id); } - for (trait_def_id, name) in associated_types { + for item_def_id in associated_types { + let assoc_item = tcx.associated_item(item_def_id); + let trait_def_id = assoc_item.container.id(); struct_span_err!(tcx.sess, span, E0191, "the value of the associated type `{}` (from the trait `{}`) must be specified", - name, + assoc_item.name, tcx.item_path_str(trait_def_id)) .span_label(span, format!( - "missing associated type `{}` value", name)) + "missing associated type `{}` value", assoc_item.name)) .emit(); } @@ -896,11 +896,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { }; let trait_did = bound.0.def_id; - let ty = self.projected_ty_from_poly_trait_ref(span, bound, assoc_name); - let ty = self.normalize_ty(span, ty); - let item = tcx.associated_items(trait_did).find(|i| i.name == assoc_name) .expect("missing associated type"); + + let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, bound); + let ty = self.normalize_ty(span, ty); + let def = Def::AssociatedTy(item.def_id); let def_scope = tcx.adjust(assoc_name, item.container.id(), ref_id).1; if !item.vis.is_accessible_from(def_scope, tcx) { @@ -915,12 +916,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { fn qpath_to_ty(&self, span: Span, opt_self_ty: Option>, - trait_def_id: DefId, + item_def_id: DefId, trait_segment: &hir::PathSegment, item_segment: &hir::PathSegment) -> Ty<'tcx> { let tcx = self.tcx(); + let trait_def_id = tcx.parent_def_id(item_def_id).unwrap(); self.prohibit_type_params(slice::ref_slice(item_segment)); @@ -944,7 +946,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { debug!("qpath_to_ty: trait_ref={:?}", trait_ref); - self.normalize_ty(span, tcx.mk_projection(trait_ref, item_segment.name)) + self.normalize_ty(span, tcx.mk_projection(item_def_id, trait_ref.substs)) } pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) { @@ -1050,10 +1052,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } Def::AssociatedTy(def_id) => { self.prohibit_type_params(&path.segments[..path.segments.len()-2]); - let trait_did = tcx.parent_def_id(def_id).unwrap(); self.qpath_to_ty(span, opt_self_ty, - trait_did, + def_id, &path.segments[path.segments.len()-2], path.segments.last().unwrap()) } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 33f0b0282d..68726a7b1c 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -413,7 +413,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // discriminant. This is sort of a workaround, see note (*) in // `check_pat` for some details. discrim_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(discrim.span)); - self.check_expr_has_type(discrim, discrim_ty); + self.check_expr_has_type_or_error(discrim, discrim_ty); }; // If the discriminant diverges, the match is pointless (e.g., @@ -480,7 +480,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() { if let Some(ref e) = arm.guard { self.diverges.set(pats_diverge); - self.check_expr_has_type(e, tcx.types.bool); + self.check_expr_has_type_or_error(e, tcx.types.bool); } self.diverges.set(pats_diverge); @@ -619,7 +619,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Type check the path. let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id); // Replace constructor type with constructed type for tuple struct patterns. - let pat_ty = pat_ty.fn_sig().output(); + let pat_ty = pat_ty.fn_sig(tcx).output(); let pat_ty = tcx.no_late_bound_regions(&pat_ty).expect("expected fn type"); self.demand_eqtype(pat.span, expected, pat_ty); diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index d5ee66a2f0..a0801a7486 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -15,7 +15,7 @@ use super::method::MethodCallee; use hir::def::Def; use hir::def_id::{DefId, LOCAL_CRATE}; use rustc::{infer, traits}; -use rustc::ty::{self, TyCtxt, LvaluePreference, Ty}; +use rustc::ty::{self, TyCtxt, TypeFoldable, LvaluePreference, Ty}; use rustc::ty::subst::Subst; use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow}; use syntax::abi; @@ -108,7 +108,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // haven't yet decided on whether the closure is fn vs // fnmut vs fnonce. If so, we have to defer further processing. if self.closure_kind(def_id).is_none() { - let closure_ty = self.closure_type(def_id).subst(self.tcx, substs.substs); + let closure_ty = self.fn_sig(def_id).subst(self.tcx, substs.substs); let fn_sig = self.replace_late_bound_regions_with_fresh_var(call_expr.span, infer::FnCall, &closure_ty) @@ -196,8 +196,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expected: Expectation<'tcx>) -> Ty<'tcx> { let (fn_sig, def_span) = match callee_ty.sty { - ty::TyFnDef(def_id, .., sig) => { - (sig, self.tcx.hir.span_if_local(def_id)) + ty::TyFnDef(def_id, _) => { + (callee_ty.fn_sig(self.tcx), self.tcx.hir.span_if_local(def_id)) } ty::TyFnPtr(sig) => (sig, None), ref t => { @@ -209,17 +209,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } } - let mut err = if let Some(path) = unit_variant { - let mut err = self.type_error_struct(call_expr.span, |_| { - format!("`{}` is being called, but it is not a function", path) - }, callee_ty); + let mut err = type_error_struct!(self.tcx.sess, call_expr.span, callee_ty, E0618, + "expected function, found `{}`", + if let Some(ref path) = unit_variant { + path.to_string() + } else { + callee_ty.to_string() + }); + if let Some(path) = unit_variant { err.help(&format!("did you mean to write `{}`?", path)); - err - } else { - self.type_error_struct(call_expr.span, |actual| { - format!("expected function, found `{}`", actual) - }, callee_ty) - }; + } if let hir::ExprCall(ref expr, _) = call_expr.node { let def = if let hir::ExprPath(ref qpath) = expr.node { diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 91aeade65a..b3f62de5b5 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -40,9 +40,11 @@ use super::{Diverges, FnCtxt}; -use lint; +use errors::DiagnosticBuilder; use hir::def_id::DefId; +use lint; use rustc::hir; +use rustc::session::Session; use rustc::traits; use rustc::ty::{self, Ty, TypeFoldable}; use rustc::ty::cast::{CastKind, CastTy}; @@ -112,6 +114,18 @@ enum CastError { NonScalar, } +fn make_invalid_casting_error<'a, 'gcx, 'tcx>(sess: &'a Session, + span: Span, + expr_ty: Ty<'tcx>, + cast_ty: Ty<'tcx>, + fcx: &FnCtxt<'a, 'gcx, 'tcx>) + -> DiagnosticBuilder<'a> { + type_error_struct!(sess, span, expr_ty, E0606, + "casting `{}` as `{}` is invalid", + fcx.ty_to_string(expr_ty), + fcx.ty_to_string(cast_ty)) +} + impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>, expr: &'tcx hir::Expr, @@ -146,14 +160,9 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { match e { CastError::NeedDeref => { let error_span = self.span; + let mut err = make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, + self.cast_ty, fcx); let cast_ty = fcx.ty_to_string(self.cast_ty); - let mut err = fcx.type_error_struct(error_span, - |actual| { - format!("casting `{}` as `{}` is invalid", - actual, - cast_ty) - }, - self.expr_ty); err.span_label(error_span, format!("cannot cast `{}` as `{}`", fcx.ty_to_string(self.expr_ty), @@ -166,13 +175,8 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { } CastError::NeedViaThinPtr | CastError::NeedViaPtr => { - let mut err = fcx.type_error_struct(self.span, - |actual| { - format!("casting `{}` as `{}` is invalid", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty); + let mut err = make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, + self.cast_ty, fcx); if self.cast_ty.is_uint() { err.help(&format!("cast through {} first", match e { @@ -184,13 +188,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { err.emit(); } CastError::NeedViaInt => { - fcx.type_error_struct(self.span, - |actual| { - format!("casting `{}` as `{}` is invalid", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty) + make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx) .help(&format!("cast through {} first", match e { CastError::NeedViaInt => "an integer", @@ -198,6 +196,15 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { })) .emit(); } + CastError::IllegalCast => { + make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx) + .emit(); + } + CastError::DifferingKinds => { + make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx) + .note("vtable kinds may not match") + .emit(); + } CastError::CastToBool => { struct_span_err!(fcx.tcx.sess, self.span, E0054, "cannot cast as `bool`") .span_label(self.span, "unsupported cast") @@ -205,51 +212,23 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { .emit(); } CastError::CastToChar => { - fcx.type_error_message(self.span, - |actual| { - format!("only `u8` can be cast as `char`, not `{}`", - actual) - }, - self.expr_ty); + type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0604, + "only `u8` can be cast as `char`, not `{}`", self.expr_ty).emit(); } CastError::NonScalar => { - fcx.type_error_message(self.span, - |actual| { - format!("non-scalar cast: `{}` as `{}`", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty); - } - CastError::IllegalCast => { - fcx.type_error_message(self.span, - |actual| { - format!("casting `{}` as `{}` is invalid", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty); + type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0605, + "non-primitive cast: `{}` as `{}`", + self.expr_ty, + fcx.ty_to_string(self.cast_ty)) + .note("an `as` expression can only be used to convert between \ + primitive types. Consider using the `From` trait") + .emit(); } CastError::SizedUnsizedCast => { - fcx.type_error_message(self.span, - |actual| { - format!("cannot cast thin pointer `{}` to fat pointer \ - `{}`", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty) - } - CastError::DifferingKinds => { - fcx.type_error_struct(self.span, - |actual| { - format!("casting `{}` as `{}` is invalid", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty) - .note("vtable kinds may not match") - .emit(); + type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0607, + "cannot cast thin pointer `{}` to fat pointer `{}`", + self.expr_ty, + fcx.ty_to_string(self.cast_ty)).emit(); } } } @@ -260,12 +239,10 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { } let tstr = fcx.ty_to_string(self.cast_ty); - let mut err = - fcx.type_error_struct(self.span, - |actual| { - format!("cast to unsized type: `{}` as `{}`", actual, tstr) - }, - self.expr_ty); + let mut err = type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0620, + "cast to unsized type: `{}` as `{}`", + fcx.resolve_type_vars_if_possible(&self.expr_ty), + tstr); match self.expr_ty.sty { ty::TyRef(_, ty::TypeAndMut { mutbl: mt, .. }) => { let mtstr = match mt { @@ -276,7 +253,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { match fcx.tcx.sess.codemap().span_to_snippet(self.cast_span) { Ok(s) => { err.span_suggestion(self.cast_span, - "try casting to a reference instead:", + "try casting to a reference instead", format!("&{}{}", mtstr, s)); } Err(_) => { @@ -295,7 +272,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { match fcx.tcx.sess.codemap().span_to_snippet(self.cast_span) { Ok(s) => { err.span_suggestion(self.cast_span, - "try casting to a `Box` instead:", + "try casting to a `Box` instead", format!("Box<{}>", s)); } Err(_) => span_help!(err, self.cast_span, "did you mean `Box<{}>`?", tstr), @@ -377,8 +354,9 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { (Some(t_from), Some(t_cast)) => (t_from, t_cast), // Function item types may need to be reified before casts. (None, Some(t_cast)) => { - if let ty::TyFnDef(.., f) = self.expr_ty.sty { + if let ty::TyFnDef(..) = self.expr_ty.sty { // Attempt a coercion to a fn pointer type. + let f = self.expr_ty.fn_sig(fcx.tcx); let res = fcx.try_coerce(self.expr, self.expr_ty, self.expr_diverges, diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index f041db43e1..802eee91ef 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -156,7 +156,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Given a Projection predicate, we can potentially infer // the complete signature. ty::Predicate::Projection(ref proj_predicate) => { - let trait_ref = proj_predicate.to_poly_trait_ref(); + let trait_ref = proj_predicate.to_poly_trait_ref(self.tcx); self.self_type_matches_expected_vid(trait_ref, expected_vid) .and_then(|_| self.deduce_sig_from_projection(proj_predicate)) } @@ -174,7 +174,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .map(|obligation| &obligation.obligation) .filter_map(|obligation| { let opt_trait_ref = match obligation.predicate { - ty::Predicate::Projection(ref data) => Some(data.to_poly_trait_ref()), + ty::Predicate::Projection(ref data) => Some(data.to_poly_trait_ref(self.tcx)), ty::Predicate::Trait(ref data) => Some(data.to_poly_trait_ref()), ty::Predicate::Equate(..) => None, ty::Predicate::Subtype(..) => None, @@ -211,7 +211,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { debug!("deduce_sig_from_projection({:?})", projection); - let trait_ref = projection.to_poly_trait_ref(); + let trait_ref = projection.to_poly_trait_ref(tcx); if tcx.lang_items.fn_trait_kind(trait_ref.def_id()).is_none() { return None; diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 30ac7b4bfb..f18d52ba40 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -76,6 +76,7 @@ use rustc::ty::relate::RelateResult; use rustc::ty::subst::Subst; use errors::DiagnosticBuilder; use syntax::abi; +use syntax::feature_gate; use syntax::ptr::P; use syntax_pos; @@ -210,13 +211,13 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { } match a.sty { - ty::TyFnDef(.., a_f) => { + ty::TyFnDef(..) => { // Function items are coercible to any closure // type; function pointers are not (that would // require double indirection). // Additionally, we permit coercion of function // items to drop the unsafe qualifier. - self.coerce_from_fn_item(a, a_f, b) + self.coerce_from_fn_item(a, b) } ty::TyFnPtr(a_f) => { // We permit coercion of fn pointers to drop the @@ -520,6 +521,8 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { coerce_source, &[coerce_target])); + let mut has_unsized_tuple_coercion = false; + // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where // inference might unify those two inner type variables later. @@ -527,7 +530,15 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { while let Some(obligation) = queue.pop_front() { debug!("coerce_unsized resolve step: {:?}", obligation); let trait_ref = match obligation.predicate { - ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => tr.clone(), + ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => { + if unsize_did == tr.def_id() { + if let ty::TyTuple(..) = tr.0.input_types().nth(1).unwrap().sty { + debug!("coerce_unsized: found unsized tuple coercion"); + has_unsized_tuple_coercion = true; + } + } + tr.clone() + } _ => { coercion.obligations.push(obligation); continue; @@ -557,6 +568,14 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { } } + if has_unsized_tuple_coercion && !self.tcx.sess.features.borrow().unsized_tuple_coercion { + feature_gate::emit_feature_err(&self.tcx.sess.parse_sess, + "unsized_tuple_coercion", + self.cause.span, + feature_gate::GateIssue::Language, + feature_gate::EXPLAIN_UNSIZED_TUPLE_COERCION); + } + Ok(coercion) } @@ -600,7 +619,6 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { fn coerce_from_fn_item(&self, a: Ty<'tcx>, - fn_ty_a: ty::PolyFnSig<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { //! Attempts to coerce from the type of a Rust function item @@ -612,9 +630,17 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { match b.sty { ty::TyFnPtr(_) => { - let a_fn_pointer = self.tcx.mk_fn_ptr(fn_ty_a); - self.coerce_from_safe_fn(a_fn_pointer, fn_ty_a, b, - simple(Adjust::ReifyFnPointer), simple(Adjust::ReifyFnPointer)) + let a_sig = a.fn_sig(self.tcx); + let InferOk { value: a_sig, mut obligations } = + self.normalize_associated_types_in_as_infer_ok(self.cause.span, &a_sig); + + let a_fn_pointer = self.tcx.mk_fn_ptr(a_sig); + let InferOk { value, obligations: o2 } = + self.coerce_from_safe_fn(a_fn_pointer, a_sig, b, + simple(Adjust::ReifyFnPointer), simple(Adjust::ReifyFnPointer))?; + + obligations.extend(o2); + Ok(InferOk { value, obligations }) } _ => self.unify_and(a, b, identity), } @@ -639,7 +665,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { // `extern "rust-call" fn((arg0,arg1,...)) -> _` // to // `fn(arg0,arg1,...) -> _` - let sig = self.closure_type(def_id_a).subst(self.tcx, substs_a.substs); + let sig = self.fn_sig(def_id_a).subst(self.tcx, substs_a.substs); let converted_sig = sig.map_bound(|s| { let params_iter = match s.inputs()[0].sty { ty::TyTuple(params, _) => { @@ -775,42 +801,40 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Special-case that coercion alone cannot handle: // Two function item types of differing IDs or Substs. - match (&prev_ty.sty, &new_ty.sty) { - (&ty::TyFnDef(a_def_id, a_substs, a_fty), &ty::TyFnDef(b_def_id, b_substs, b_fty)) => { - // The signature must always match. - let fty = self.at(cause, self.param_env) - .trace(prev_ty, new_ty) - .lub(&a_fty, &b_fty) - .map(|ok| self.register_infer_ok_obligations(ok))?; - - if a_def_id == b_def_id { - // Same function, maybe the parameters match. - let substs = self.commit_if_ok(|_| { - self.at(cause, self.param_env) - .trace(prev_ty, new_ty) - .lub(&a_substs, &b_substs) - .map(|ok| self.register_infer_ok_obligations(ok)) - }); - - if let Ok(substs) = substs { - // We have a LUB of prev_ty and new_ty, just return it. - return Ok(self.tcx.mk_fn_def(a_def_id, substs, fty)); - } - } + if let (&ty::TyFnDef(..), &ty::TyFnDef(..)) = (&prev_ty.sty, &new_ty.sty) { + // Don't reify if the function types have a LUB, i.e. they + // are the same function and their parameters have a LUB. + let lub_ty = self.commit_if_ok(|_| { + self.at(cause, self.param_env) + .lub(prev_ty, new_ty) + }).map(|ok| self.register_infer_ok_obligations(ok)); + + if lub_ty.is_ok() { + // We have a LUB of prev_ty and new_ty, just return it. + return lub_ty; + } - // Reify both sides and return the reified fn pointer type. - let fn_ptr = self.tcx.mk_fn_ptr(fty); - for expr in exprs.iter().map(|e| e.as_coercion_site()).chain(Some(new)) { - // The only adjustment that can produce an fn item is - // `NeverToAny`, so this should always be valid. - self.apply_adjustments(expr, vec![Adjustment { - kind: Adjust::ReifyFnPointer, - target: fn_ptr - }]); - } - return Ok(fn_ptr); + // The signature must match. + let a_sig = prev_ty.fn_sig(self.tcx); + let a_sig = self.normalize_associated_types_in(new.span, &a_sig); + let b_sig = new_ty.fn_sig(self.tcx); + let b_sig = self.normalize_associated_types_in(new.span, &b_sig); + let sig = self.at(cause, self.param_env) + .trace(prev_ty, new_ty) + .lub(&a_sig, &b_sig) + .map(|ok| self.register_infer_ok_obligations(ok))?; + + // Reify both sides and return the reified fn pointer type. + let fn_ptr = self.tcx.mk_fn_ptr(sig); + for expr in exprs.iter().map(|e| e.as_coercion_site()).chain(Some(new)) { + // The only adjustment that can produce an fn item is + // `NeverToAny`, so this should always be valid. + self.apply_adjustments(expr, vec![Adjustment { + kind: Adjust::ReifyFnPointer, + target: fn_ptr + }]); } - _ => {} + return Ok(fn_ptr); } let mut coerce = Coerce::new(self, cause.clone()); @@ -859,8 +883,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return self.commit_if_ok(|_| { self.at(cause, self.param_env) .lub(prev_ty, new_ty) - .map(|ok| self.register_infer_ok_obligations(ok)) - }); + }).map(|ok| self.register_infer_ok_obligations(ok)); } } @@ -873,8 +896,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.commit_if_ok(|_| { self.at(cause, self.param_env) .lub(prev_ty, new_ty) - .map(|ok| self.register_infer_ok_obligations(ok)) - }) + }).map(|ok| self.register_infer_ok_obligations(ok)) } } Ok(ok) => { @@ -1162,6 +1184,18 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> "`return;` in a function whose return type is not `()`"); db.span_label(cause.span, "return type is not ()"); } + ObligationCauseCode::BlockTailExpression(blk_id) => { + db = fcx.report_mismatched_types(cause, expected, found, err); + + let expr = expression.unwrap_or_else(|| { + span_bug!(cause.span, + "supposed to be part of a block tail expression, but the \ + expression is empty"); + }); + fcx.suggest_mismatched_types_on_tail(&mut db, expr, + expected, found, + cause.span, blk_id); + } _ => { db = fcx.report_mismatched_types(cause, expected, found, err); } diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 8b76431fd2..bf134f9547 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -219,7 +219,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env, normalize_cause.clone()); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let inh = Inherited::new(infcx, impl_m.def_id); let infcx = &inh.infcx; @@ -256,17 +256,10 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Compute skolemized form of impl and trait method tys. let tcx = infcx.tcx; - let m_sig = |method: &ty::AssociatedItem| { - match tcx.type_of(method.def_id).sty { - ty::TyFnDef(_, _, f) => f, - _ => bug!() - } - }; - let (impl_sig, _) = infcx.replace_late_bound_regions_with_fresh_var(impl_m_span, infer::HigherRankedType, - &m_sig(impl_m)); + &tcx.fn_sig(impl_m.def_id)); let impl_sig = inh.normalize_associated_types_in(impl_m_span, impl_m_node_id, @@ -277,7 +270,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let trait_sig = inh.liberate_late_bound_regions( impl_m.def_id, - &m_sig(trait_m)); + &tcx.fn_sig(trait_m.def_id)); let trait_sig = trait_sig.subst(tcx, trait_to_skol_substs); let trait_sig = @@ -335,7 +328,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Check that all obligations are satisfied by the implementation's // version. if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(errors); + infcx.report_fulfillment_errors(errors, None); return Err(ErrorReported); } @@ -507,8 +500,7 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty::ImplContainer(_) => impl_trait_ref.self_ty(), ty::TraitContainer(_) => tcx.mk_self_type() }; - let method_ty = tcx.type_of(method.def_id); - let self_arg_ty = *method_ty.fn_sig().input(0).skip_binder(); + let self_arg_ty = *tcx.fn_sig(method.def_id).input(0).skip_binder(); match ExplicitSelf::determine(untransformed_self_ty, self_arg_ty) { ExplicitSelf::ByValue => "self".to_string(), ExplicitSelf::ByReference(_, hir::MutImmutable) => "&self".to_string(), @@ -637,14 +629,8 @@ fn compare_number_of_method_arguments<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_m: &ty::AssociatedItem, trait_item_span: Option) -> Result<(), ErrorReported> { - let m_fty = |method: &ty::AssociatedItem| { - match tcx.type_of(method.def_id).sty { - ty::TyFnDef(_, _, f) => f, - _ => bug!() - } - }; - let impl_m_fty = m_fty(impl_m); - let trait_m_fty = m_fty(trait_m); + let impl_m_fty = tcx.fn_sig(impl_m.def_id); + let trait_m_fty = tcx.fn_sig(trait_m.def_id); let trait_number_args = trait_m_fty.inputs().skip_binder().len(); let impl_number_args = impl_m_fty.inputs().skip_binder().len(); if trait_number_args != impl_number_args { @@ -726,7 +712,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_trait_ref: ty::TraitRef<'tcx>) { debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let param_env = ty::ParamEnv::empty(Reveal::UserFacing); let inh = Inherited::new(infcx, impl_c.def_id); let infcx = &inh.infcx; @@ -807,7 +793,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Check that all obligations are satisfied by the implementation's // version. if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(errors); + infcx.report_fulfillment_errors(errors, None); return; } diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 9ed50dd1e4..f54ad54187 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -26,13 +26,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Requires that the two types unify, and prints an error message if // they don't. pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) { + self.demand_suptype_diag(sp, expected, actual).map(|mut e| e.emit()); + } + + pub fn demand_suptype_diag(&self, + sp: Span, + expected: Ty<'tcx>, + actual: Ty<'tcx>) -> Option> { let cause = &self.misc(sp); match self.at(cause, self.param_env).sup(expected, actual) { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations); + None }, Err(e) => { - self.report_mismatched_types(&cause, expected, actual, e).emit(); + Some(self.report_mismatched_types(&cause, expected, actual, e)) } } } @@ -65,15 +73,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } + pub fn demand_coerce(&self, expr: &hir::Expr, checked_ty: Ty<'tcx>, expected: Ty<'tcx>) { + if let Some(mut err) = self.demand_coerce_diag(expr, checked_ty, expected) { + err.emit(); + } + } + // Checks that the type of `expr` can be coerced to `expected`. // // NB: This code relies on `self.diverges` to be accurate. In // particular, assignments to `!` will be permitted if the // diverges flag is currently "always". - pub fn demand_coerce(&self, - expr: &hir::Expr, - checked_ty: Ty<'tcx>, - expected: Ty<'tcx>) { + pub fn demand_coerce_diag(&self, + expr: &hir::Expr, + checked_ty: Ty<'tcx>, + expected: Ty<'tcx>) -> Option> { let expected = self.resolve_type_vars_with_obligations(expected); if let Err(e) = self.try_coerce(expr, checked_ty, self.diverges.get(), expected) { @@ -97,8 +111,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.get_best_match(&suggestions).join("\n"))); } } - err.emit(); + return Some(err); } + None } fn format_method_suggestion(&self, method: &AssociatedItem) -> String { @@ -135,12 +150,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn has_no_input_arg(&self, method: &AssociatedItem) -> bool { match method.def() { Def::Method(def_id) => { - match self.tcx.type_of(def_id).sty { - ty::TypeVariants::TyFnDef(_, _, sig) => { - sig.inputs().skip_binder().len() == 1 - } - _ => false, - } + self.tcx.fn_sig(def_id).inputs().skip_binder().len() == 1 } _ => false, } diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index bff9289de5..ed22cd1333 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -79,7 +79,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( // check that the impl type can be made to match the trait type. - tcx.infer_ctxt(()).enter(|ref infcx| { + tcx.infer_ctxt().enter(|ref infcx| { let impl_param_env = tcx.param_env(self_type_did); let tcx = infcx.tcx; let mut fulfillment_cx = traits::FulfillmentContext::new(); @@ -110,7 +110,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) { // this could be reached when we get lazy normalization - infcx.report_fulfillment_errors(errors); + infcx.report_fulfillment_errors(errors, None); return Err(ErrorReported); } diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index daf202cd79..96643ae72a 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -13,7 +13,6 @@ use intrinsics; use rustc::traits::{ObligationCause, ObligationCauseCode}; -use rustc::ty::subst::Substs; use rustc::ty::{self, TyCtxt, Ty}; use rustc::util::nodemap::FxHashMap; use require_same_types; @@ -35,22 +34,22 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, output: Ty<'tcx>) { let def_id = tcx.hir.local_def_id(it.id); - let substs = Substs::for_item(tcx, def_id, - |_, _| tcx.types.re_erased, - |def, _| tcx.mk_param_from_def(def)); + match it.node { + hir::ForeignItemFn(..) => {} + _ => { + struct_span_err!(tcx.sess, it.span, E0622, + "intrinsic must be a function") + .span_label(it.span, "expected a function") + .emit(); + return; + } + } - let fty = tcx.mk_fn_def(def_id, substs, ty::Binder(tcx.mk_fn_sig( - inputs.into_iter(), - output, - false, - hir::Unsafety::Unsafe, - abi - ))); let i_n_tps = tcx.generics_of(def_id).types.len(); if i_n_tps != n_tps { let span = match it.node { hir::ForeignItemFn(_, _, ref generics) => generics.span, - hir::ForeignItemStatic(..) => it.span + _ => bug!() }; struct_span_err!(tcx.sess, span, E0094, @@ -59,14 +58,18 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, i_n_tps, n_tps) .span_label(span, format!("expected {} type parameter", n_tps)) .emit(); - } else { - require_same_types(tcx, - &ObligationCause::new(it.span, - it.id, - ObligationCauseCode::IntrinsicType), - tcx.type_of(def_id), - fty); + return; } + + let fty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig( + inputs.into_iter(), + output, + false, + hir::Unsafety::Unsafe, + abi + ))); + let cause = ObligationCause::new(it.span, it.id, ObligationCauseCode::IntrinsicType); + require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(def_id)), fty); } /// Remember to add all intrinsics here, in librustc_trans/trans/intrinsic.rs, @@ -272,7 +275,8 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, "volatile_store" => (1, vec![ tcx.mk_mut_ptr(param(0)), param(0) ], tcx.mk_nil()), - "ctpop" | "ctlz" | "cttz" | "bswap" => (1, vec![param(0)], param(0)), + "ctpop" | "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "bswap" => + (1, vec![param(0)], param(0)), "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => (1, vec![param(0), param(0)], @@ -375,7 +379,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut structural_to_nomimal = FxHashMap(); - let sig = tcx.type_of(def_id).fn_sig(); + let sig = tcx.fn_sig(def_id); let sig = tcx.no_late_bound_regions(&sig).unwrap(); if intr.inputs.len() != sig.inputs().len() { span_err!(tcx.sess, it.span, E0444, diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 36bd665738..0829951e12 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -44,15 +44,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { call_expr: &'gcx hir::Expr, unadjusted_self_ty: Ty<'tcx>, pick: probe::Pick<'tcx>, - supplied_method_types: Vec>) + segment: &hir::PathSegment) -> MethodCallee<'tcx> { - debug!("confirm(unadjusted_self_ty={:?}, pick={:?}, supplied_method_types={:?})", + debug!("confirm(unadjusted_self_ty={:?}, pick={:?}, generic_args={:?})", unadjusted_self_ty, pick, - supplied_method_types); + segment.parameters); let mut confirm_cx = ConfirmContext::new(self, span, self_expr, call_expr); - confirm_cx.confirm(unadjusted_self_ty, pick, supplied_method_types) + confirm_cx.confirm(unadjusted_self_ty, pick, segment) } } @@ -73,7 +73,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { fn confirm(&mut self, unadjusted_self_ty: Ty<'tcx>, pick: probe::Pick<'tcx>, - supplied_method_types: Vec>) + segment: &hir::PathSegment) -> MethodCallee<'tcx> { // Adjust the self expression the user provided and obtain the adjusted type. let self_ty = self.adjust_self_ty(unadjusted_self_ty, &pick); @@ -83,7 +83,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // Create substitutions for the method's type parameters. let rcvr_substs = self.fresh_receiver_substs(self_ty, &pick); - let all_substs = self.instantiate_method_substs(&pick, supplied_method_types, rcvr_substs); + let all_substs = self.instantiate_method_substs(&pick, segment, rcvr_substs); debug!("all_substs={:?}", all_substs); @@ -279,9 +279,14 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { fn instantiate_method_substs(&mut self, pick: &probe::Pick<'tcx>, - mut supplied_method_types: Vec>, + segment: &hir::PathSegment, substs: &Substs<'tcx>) -> &'tcx Substs<'tcx> { + let supplied_method_types = match segment.parameters { + hir::AngleBracketedParameters(ref data) => &data.types, + _ => bug!("unexpected generic arguments: {:?}", segment.parameters), + }; + // Determine the values for the generic parameters of the method. // If they were not explicitly supplied, just construct fresh // variables. @@ -312,7 +317,6 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { num_method_types)) .emit(); } - supplied_method_types = vec![self.tcx.types.err; num_method_types]; } // Create subst for early-bound lifetime parameters, combining @@ -331,10 +335,10 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { let i = def.index as usize; if i < substs.len() { substs.type_at(i) - } else if supplied_method_types.is_empty() { - self.type_var_for_def(self.span, def, cur_substs) + } else if let Some(ast_ty) = supplied_method_types.get(i - supplied_start) { + self.to_ty(ast_ty) } else { - supplied_method_types[i - supplied_start] + self.type_var_for_def(self.span, def, cur_substs) } }) } @@ -375,7 +379,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { debug!("method_predicates after subst = {:?}", method_predicates); - let sig = self.tcx.type_of(def_id).fn_sig(); + let sig = self.tcx.fn_sig(def_id); // Instantiate late-bound regions and substitute the trait // parameters into the method type to get the actual method type. diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 73c1215f27..c842e47aaf 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -130,22 +130,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// * `supplied_method_types`: the explicit method type parameters, if any (`T1..Tn`) /// * `self_expr`: the self expression (`foo`) pub fn lookup_method(&self, - span: Span, - method_name: ast::Name, self_ty: ty::Ty<'tcx>, - supplied_method_types: Vec>, + segment: &hir::PathSegment, + span: Span, call_expr: &'gcx hir::Expr, self_expr: &'gcx hir::Expr) -> Result, MethodError<'tcx>> { debug!("lookup(method_name={}, self_ty={:?}, call_expr={:?}, self_expr={:?})", - method_name, + segment.name, self_ty, call_expr, self_expr); let mode = probe::Mode::MethodCall; let self_ty = self.resolve_type_vars_if_possible(&self_ty); - let pick = self.probe_for_name(span, mode, method_name, IsSuggestion(false), + let pick = self.probe_for_name(span, mode, segment.name, IsSuggestion(false), self_ty, call_expr.id)?; if let Some(import_id) = pick.import_id { @@ -161,7 +160,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { call_expr, self_ty, pick, - supplied_method_types)) + segment)) } /// `lookup_method_in_trait` is used for overloaded operators. @@ -235,7 +234,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // NB: Instantiate late-bound regions first so that // `instantiate_type_scheme` can normalize associated types that // may reference those regions. - let fn_sig = tcx.type_of(def_id).fn_sig(); + let fn_sig = tcx.fn_sig(def_id); let fn_sig = self.replace_late_bound_regions_with_fresh_var(span, infer::FnCall, &fn_sig).0; diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 2518a1739f..558cb1add9 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -673,7 +673,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { expected: ty::Ty<'tcx>) -> bool { match method.def() { Def::Method(def_id) => { - let fty = self.tcx.type_of(def_id).fn_sig(); + let fty = self.tcx.fn_sig(def_id); self.probe(|_| { let substs = self.fresh_substs_for_item(self.span, method.def_id); let output = fty.output().subst(self.tcx, substs); @@ -718,10 +718,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { import_id: Option, trait_def_id: DefId, item: ty::AssociatedItem) { - let trait_def = self.tcx.trait_def(trait_def_id); - // FIXME(arielb1): can we use for_each_relevant_impl here? - trait_def.for_each_impl(self.tcx, |impl_def_id| { + self.tcx.for_each_impl(trait_def_id, |impl_def_id| { debug!("assemble_extension_candidates_for_trait_impl: trait_def_id={:?} \ impl_def_id={:?}", trait_def_id, @@ -861,7 +859,10 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { debug!("assemble_projection_candidates: step={:?}", step); let (def_id, substs) = match step.self_ty.sty { - ty::TyProjection(ref data) => (data.trait_ref.def_id, data.trait_ref.substs), + ty::TyProjection(ref data) => { + let trait_ref = data.trait_ref(self.tcx); + (trait_ref.def_id, trait_ref.substs) + }, ty::TyAnon(def_id, substs) => (def_id, substs), _ => continue, }; @@ -1288,7 +1289,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { impl_ty: Ty<'tcx>, substs: &Substs<'tcx>) -> Ty<'tcx> { - let self_ty = self.tcx.type_of(method).fn_sig().input(0); + let self_ty = self.tcx.fn_sig(method).input(0); debug!("xform_self_ty(impl_ty={:?}, self_ty={:?}, substs={:?})", impl_ty, self_ty, diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index f8dd577479..4faf71e0cc 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -526,7 +526,7 @@ pub fn all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> AllTraits<'a> if !external_mods.insert(def_id) { return; } - for child in tcx.sess.cstore.item_children(def_id) { + for child in tcx.sess.cstore.item_children(def_id, tcx.sess) { handle_external_def(tcx, traits, external_mods, child.def) } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 6e1c403cbc..cdbe5e14e9 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -102,15 +102,16 @@ use rustc::ty::maps::Providers; use rustc::ty::util::{Representability, IntTypeExt}; use errors::DiagnosticBuilder; use require_c_abi_if_variadic; -use session::{Session, CompileResult}; +use session::{CompileIncomplete, Session}; use TypeAndSubsts; use lint; use util::common::{ErrorReported, indenter}; use util::nodemap::{DefIdMap, FxHashMap, NodeMap}; -use std::cell::{Cell, RefCell}; +use std::cell::{Cell, RefCell, Ref, RefMut}; use std::collections::hash_map::Entry; use std::cmp; +use std::fmt::Display; use std::mem::replace; use std::ops::{self, Deref}; use syntax::abi::Abi; @@ -120,10 +121,11 @@ use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax::ptr::P; use syntax::symbol::{Symbol, InternedString, keywords}; use syntax::util::lev_distance::find_best_match_for_name; -use syntax_pos::{self, BytePos, Span, DUMMY_SP}; +use syntax_pos::{self, BytePos, Span}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::itemlikevisit::ItemLikeVisitor; +use rustc::hir::map::Node; use rustc::hir::{self, PatKind}; use rustc::middle::lang_items; use rustc_back::slice; @@ -147,6 +149,33 @@ mod compare_method; mod intrinsic; mod op; +/// A wrapper for InferCtxt's `in_progress_tables` field. +#[derive(Copy, Clone)] +struct MaybeInProgressTables<'a, 'tcx: 'a> { + maybe_tables: Option<&'a RefCell>>, +} + +impl<'a, 'tcx> MaybeInProgressTables<'a, 'tcx> { + fn borrow(self) -> Ref<'a, ty::TypeckTables<'tcx>> { + match self.maybe_tables { + Some(tables) => tables.borrow(), + None => { + bug!("MaybeInProgressTables: inh/fcx.tables.borrow() with no tables") + } + } + } + + fn borrow_mut(self) -> RefMut<'a, ty::TypeckTables<'tcx>> { + match self.maybe_tables { + Some(tables) => tables.borrow_mut(), + None => { + bug!("MaybeInProgressTables: inh/fcx.tables.borrow_mut() with no tables") + } + } + } +} + + /// closures defined within the function. For example: /// /// fn foo() { @@ -159,6 +188,8 @@ mod op; pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { infcx: InferCtxt<'a, 'gcx, 'tcx>, + tables: MaybeInProgressTables<'a, 'tcx>, + locals: RefCell>>, fulfillment_cx: RefCell>, @@ -187,6 +218,8 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { /// environment is for an item or something where the "callee" is /// not clear. implicit_region_bound: Option>, + + body_id: Option, } impl<'a, 'gcx, 'tcx> Deref for Inherited<'a, 'gcx, 'tcx> { @@ -203,6 +236,9 @@ pub enum Expectation<'tcx> { /// We know nothing about what type this expression should have. NoExpectation, + /// This expression is an `if` condition, it must resolve to `bool`. + ExpectIfCondition, + /// This expression should have the type given (or some subtype) ExpectHasType(Ty<'tcx>), @@ -281,9 +317,8 @@ impl<'a, 'gcx, 'tcx> Expectation<'tcx> { // no constraints yet present), just returns `None`. fn resolve(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Expectation<'tcx> { match self { - NoExpectation => { - NoExpectation - } + NoExpectation => NoExpectation, + ExpectIfCondition => ExpectIfCondition, ExpectCastableToType(t) => { ExpectCastableToType(fcx.resolve_type_vars_if_possible(&t)) } @@ -299,6 +334,7 @@ impl<'a, 'gcx, 'tcx> Expectation<'tcx> { fn to_option(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Option> { match self.resolve(fcx) { NoExpectation => None, + ExpectIfCondition => Some(fcx.tcx.types.bool), ExpectCastableToType(ty) | ExpectHasType(ty) | ExpectRvalueLikeUnsized(ty) => Some(ty), @@ -312,7 +348,8 @@ impl<'a, 'gcx, 'tcx> Expectation<'tcx> { fn only_has_type(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Option> { match self.resolve(fcx) { ExpectHasType(ty) => Some(ty), - _ => None + ExpectIfCondition => Some(fcx.tcx.types.bool), + NoExpectation | ExpectCastableToType(_) | ExpectRvalueLikeUnsized(_) => None, } } @@ -535,9 +572,8 @@ pub struct InheritedBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, def_id: DefId) -> InheritedBuilder<'a, 'gcx, 'tcx> { - let tables = ty::TypeckTables::empty(); InheritedBuilder { - infcx: tcx.infer_ctxt(tables), + infcx: tcx.infer_ctxt().with_fresh_in_progress_tables(), def_id, } } @@ -562,6 +598,9 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { }); Inherited { + tables: MaybeInProgressTables { + maybe_tables: infcx.in_progress_tables, + }, infcx: infcx, fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()), locals: RefCell::new(NodeMap()), @@ -569,6 +608,7 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { deferred_cast_checks: RefCell::new(Vec::new()), anon_types: RefCell::new(NodeMap()), implicit_region_bound, + body_id, } } @@ -652,30 +692,32 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> { fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) { } } -pub fn check_wf_new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult { +pub fn check_wf_new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> { tcx.sess.track_errors(|| { let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx); tcx.hir.krate().visit_all_item_likes(&mut visit.as_deep_visitor()); }) } -pub fn check_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult { +pub fn check_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> { tcx.sess.track_errors(|| { tcx.hir.krate().visit_all_item_likes(&mut CheckItemTypesVisitor { tcx }); }) } -pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult { +pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), CompileIncomplete> { tcx.typeck_item_bodies(LOCAL_CRATE) } -fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> CompileResult { +fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) + -> Result<(), CompileIncomplete> +{ debug_assert!(crate_num == LOCAL_CRATE); - tcx.sess.track_errors(|| { + Ok(tcx.sess.track_errors(|| { for body_owner_def_id in tcx.body_owners() { tcx.typeck_tables_of(body_owner_def_id); } - }) + })?) } pub fn provide(providers: &mut Providers) { @@ -683,20 +725,12 @@ pub fn provide(providers: &mut Providers) { typeck_item_bodies, typeck_tables_of, has_typeck_tables, - closure_type, closure_kind, adt_destructor, ..*providers }; } -fn closure_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> ty::PolyFnSig<'tcx> { - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - tcx.typeck_tables_of(def_id).closure_tys[&node_id] -} - fn closure_kind<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::ClosureKind { @@ -809,7 +843,7 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Inherited::build(tcx, def_id).enter(|inh| { let param_env = tcx.param_env(def_id); let fcx = if let Some(decl) = fn_decl { - let fn_sig = tcx.type_of(def_id).fn_sig(); + let fn_sig = tcx.fn_sig(def_id); check_abi(tcx, span, fn_sig.abi()); @@ -950,7 +984,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, *fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id); let ret_ty = fn_sig.output(); - fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType); + fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::SizedReturnType); let ret_ty = fcx.instantiate_anon_types(&ret_ty); fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty))); fn_sig = fcx.tcx.mk_fn_sig( @@ -965,16 +999,17 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, // Add formal parameters. for (arg_ty, arg) in fn_sig.inputs().iter().zip(&body.arguments) { - // The type of the argument must be well-formed. - // - // NB -- this is now checked in wfcheck, but that - // currently only results in warnings, so we issue an - // old-style WF obligation here so that we still get the - // errors that we used to get. - fcx.register_old_wf_obligation(arg_ty, arg.pat.span, traits::MiscObligation); - // Check the pattern. fcx.check_pat_arg(&arg.pat, arg_ty, true); + + // Check that argument is Sized. + // The check for a non-trivial pattern is a hack to avoid duplicate warnings + // for simple cases like `fn foo(x: Trait)`, + // where we would error once on the parameter as a whole, and once on the binding `x`. + if arg.pat.simple_name().is_none() { + fcx.require_type_is_sized(arg_ty, decl.output.span(), traits::MiscObligation); + } + fcx.write_ty(arg.id, arg_ty); } @@ -1132,6 +1167,7 @@ fn check_on_unimplemented<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }) { if let Some(istring) = attr.value_str() { let istring = istring.as_str(); + let name = tcx.item_name(def_id).as_str(); let parser = Parser::new(&istring); let types = &generics.types; for token in parser { @@ -1140,13 +1176,14 @@ fn check_on_unimplemented<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Piece::NextArgument(a) => match a.position { // `{Self}` is allowed Position::ArgumentNamed(s) if s == "Self" => (), + // `{ThisTraitsName}` is allowed + Position::ArgumentNamed(s) if s == name => (), // So is `{A}` if A is a type parameter Position::ArgumentNamed(s) => match types.iter().find(|t| { t.name == s }) { Some(_) => (), None => { - let name = tcx.item_name(def_id); span_err!(tcx.sess, attr.span, E0230, "there is no type parameter \ {} on trait {}", @@ -1585,17 +1622,18 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { fn projected_ty_from_poly_trait_ref(&self, span: Span, - poly_trait_ref: ty::PolyTraitRef<'tcx>, - item_name: ast::Name) + item_def_id: DefId, + poly_trait_ref: ty::PolyTraitRef<'tcx>) -> Ty<'tcx> { + let item = self.tcx().associated_item(item_def_id); let (trait_ref, _) = self.replace_late_bound_regions_with_fresh_var( span, - infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name), + infer::LateBoundRegionConversionTime::AssocTypeProjection(item.name), &poly_trait_ref); - self.tcx().mk_projection(trait_ref, item_name) + self.tcx().mk_projection(item_def_id, trait_ref.substs) } fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx> { @@ -1873,7 +1911,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Require that the predicate holds for the concrete type. let cause = traits::ObligationCause::new(span, self.body_id, - traits::ReturnType); + traits::SizedReturnType); self.register_predicate(traits::Obligation::new(cause, self.param_env, predicate)); @@ -1902,14 +1940,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { value) } - pub fn write_nil(&self, node_id: ast::NodeId) { - self.write_ty(node_id, self.tcx.mk_nil()); - } - - pub fn write_error(&self, node_id: ast::NodeId) { - self.write_ty(node_id, self.tcx.types.err); - } - pub fn require_type_meets(&self, ty: Ty<'tcx>, span: Span, @@ -1958,17 +1988,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - /// Registers an obligation for checking later, during regionck, that the type `ty` must - /// outlive the region `r`. - pub fn register_region_obligation(&self, - ty: Ty<'tcx>, - region: ty::Region<'tcx>, - cause: traits::ObligationCause<'tcx>) - { - let mut fulfillment_cx = self.fulfillment_cx.borrow_mut(); - fulfillment_cx.register_region_obligation(ty, region, cause); - } - /// Registers an obligation for checking later, during regionck, that the type `ty` must /// outlive the region `r`. pub fn register_wf_obligation(&self, @@ -1983,21 +2002,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::Predicate::WellFormed(ty))); } - pub fn register_old_wf_obligation(&self, - ty: Ty<'tcx>, - span: Span, - code: traits::ObligationCauseCode<'tcx>) - { - // Registers an "old-style" WF obligation that uses the - // implicator code. This is basically a buggy version of - // `register_wf_obligation` that is being kept around - // temporarily just to help with phasing in the newer rules. - // - // FIXME(#27579) all uses of this should be migrated to register_wf_obligation eventually - let cause = traits::ObligationCause::new(span, self.body_id, code); - self.register_region_obligation(ty, self.tcx.types.re_empty, cause); - } - /// Registers obligations that all types appearing in `substs` are well-formed. pub fn add_wf_bounds(&self, substs: &Substs<'tcx>, expr: &hir::Expr) { @@ -2125,7 +2129,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match fulfillment_cx.select_all_or_error(self) { Ok(()) => { } - Err(errors) => { self.report_fulfillment_errors(&errors); } + Err(errors) => { self.report_fulfillment_errors(&errors, self.inh.body_id); } } } @@ -2133,7 +2137,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn select_obligations_where_possible(&self) { match self.fulfillment_cx.borrow_mut().select_where_possible(self) { Ok(()) => { } - Err(errors) => { self.report_fulfillment_errors(&errors); } + Err(errors) => { self.report_fulfillment_errors(&errors, self.inh.body_id); } } } @@ -2146,7 +2150,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { -> ty::TypeAndMut<'tcx> { // extract method return type, which will be &T; - // all LB regions should have been instantiated during method lookup let ret_ty = method.sig.output(); // method returns &T, but the type as visible to user is T, so deref @@ -2531,42 +2534,32 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // We also need to make sure we at least write the ty of the other // arguments which we skipped above. if variadic { + fn variadic_error<'tcx>(s: &Session, span: Span, t: Ty<'tcx>, cast_ty: &str) { + type_error_struct!(s, span, t, E0617, + "can't pass `{}` to variadic function, cast to `{}`", + t, cast_ty).emit(); + } + for arg in args.iter().skip(expected_arg_count) { let arg_ty = self.check_expr(&arg); // There are a few types which get autopromoted when passed via varargs // in C but we just error out instead and require explicit casts. - let arg_ty = self.structurally_resolved_type(arg.span, - arg_ty); + let arg_ty = self.structurally_resolved_type(arg.span, arg_ty); match arg_ty.sty { ty::TyFloat(ast::FloatTy::F32) => { - self.type_error_message(arg.span, |t| { - format!("can't pass an `{}` to variadic \ - function, cast to `c_double`", t) - }, arg_ty); + variadic_error(tcx.sess, arg.span, arg_ty, "c_double"); } ty::TyInt(ast::IntTy::I8) | ty::TyInt(ast::IntTy::I16) | ty::TyBool => { - self.type_error_message(arg.span, |t| { - format!("can't pass `{}` to variadic \ - function, cast to `c_int`", - t) - }, arg_ty); + variadic_error(tcx.sess, arg.span, arg_ty, "c_int"); } ty::TyUint(ast::UintTy::U8) | ty::TyUint(ast::UintTy::U16) => { - self.type_error_message(arg.span, |t| { - format!("can't pass `{}` to variadic \ - function, cast to `c_uint`", - t) - }, arg_ty); + variadic_error(tcx.sess, arg.span, arg_ty, "c_uint"); } - ty::TyFnDef(.., f) => { - let ptr_ty = self.tcx.mk_fn_ptr(f); + ty::TyFnDef(..) => { + let ptr_ty = self.tcx.mk_fn_ptr(arg_ty.fn_sig(self.tcx)); let ptr_ty = self.resolve_type_vars_if_possible(&ptr_ty); - self.type_error_message(arg.span, - |t| { - format!("can't pass `{}` to variadic \ - function, cast to `{}`", t, ptr_ty) - }, arg_ty); + variadic_error(tcx.sess, arg.span, arg_ty, &format!("{}", ptr_ty)); } _ => {} } @@ -2631,10 +2624,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.demand_eqtype(expr.span, expected, ty); } - pub fn check_expr_has_type(&self, - expr: &'gcx hir::Expr, - expected: Ty<'tcx>) -> Ty<'tcx> { - let mut ty = self.check_expr_with_hint(expr, expected); + pub fn check_expr_has_type_or_error(&self, + expr: &'gcx hir::Expr, + expected: Ty<'tcx>) -> Ty<'tcx> { + self.check_expr_meets_expectation_or_error(expr, ExpectHasType(expected)) + } + + fn check_expr_meets_expectation_or_error(&self, + expr: &'gcx hir::Expr, + expected: Expectation<'tcx>) -> Ty<'tcx> { + let expected_ty = expected.to_option(&self).unwrap_or(self.tcx.types.bool); + let mut ty = self.check_expr_with_expectation(expr, expected); // While we don't allow *arbitrary* coercions here, we *do* allow // coercions from ! to `expected`. @@ -2650,7 +2650,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty = adj_ty; } - self.demand_suptype(expr.span, expected, ty); + if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) { + // Add help to type error if this is an `if` condition with an assignment + match (expected, &expr.node) { + (ExpectIfCondition, &hir::ExprAssign(ref lhs, ref rhs)) => { + let msg = "did you mean to compare equality?"; + if let (Ok(left), Ok(right)) = ( + self.tcx.sess.codemap().span_to_snippet(lhs.span), + self.tcx.sess.codemap().span_to_snippet(rhs.span)) + { + err.span_suggestion(expr.span, msg, format!("{} == {}", left, right)); + } else { + err.help(msg); + } + } + _ => (), + } + err.emit(); + } ty } @@ -2757,22 +2774,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Checks a method call. fn check_method_call(&self, expr: &'gcx hir::Expr, - method_name: Spanned, + segment: &hir::PathSegment, + span: Span, args: &'gcx [hir::Expr], - tps: &[P], expected: Expectation<'tcx>, lvalue_pref: LvaluePreference) -> Ty<'tcx> { let rcvr = &args[0]; let rcvr_t = self.check_expr_with_lvalue_pref(&rcvr, lvalue_pref); - // no need to check for bot/err -- callee does that - let expr_t = self.structurally_resolved_type(expr.span, rcvr_t); + let rcvr_t = self.structurally_resolved_type(expr.span, rcvr_t); - let tps = tps.iter().map(|ast_ty| self.to_ty(&ast_ty)).collect::>(); - let method = match self.lookup_method(method_name.span, - method_name.node, - expr_t, - tps, + let method = match self.lookup_method(rcvr_t, + segment, + span, expr, rcvr) { Ok(method) => { @@ -2780,10 +2794,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Ok(method) } Err(error) => { - if method_name.node != keywords::Invalid.name() { - self.report_method_error(method_name.span, - expr_t, - method_name.node, + if segment.name != keywords::Invalid.name() { + self.report_method_error(span, + rcvr_t, + segment.name, Some(rcvr), error, Some(args)); @@ -2793,7 +2807,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; // Call the generic checker. - self.check_method_argument_types(method_name.span, method, + self.check_method_argument_types(span, method, &args[1..], DontTupleArguments, expected) @@ -2807,10 +2821,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "check_return_expr called outside fn body")); let ret_ty = ret_coercion.borrow().expected_ty(); - let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty); + let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty.clone()); ret_coercion.borrow_mut() .coerce(self, - &self.misc(return_expr.span), + &self.cause(return_expr.span, + ObligationCauseCode::ReturnType(return_expr.id)), return_expr, return_expr_ty, self.diverges.get()); @@ -2825,7 +2840,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { opt_else_expr: Option<&'gcx hir::Expr>, sp: Span, expected: Expectation<'tcx>) -> Ty<'tcx> { - let cond_ty = self.check_expr_has_type(cond_expr, self.tcx.types.bool); + let cond_ty = self.check_expr_meets_expectation_or_error(cond_expr, ExpectIfCondition); let cond_diverges = self.diverges.get(); self.diverges.set(Diverges::Maybe); @@ -2909,8 +2924,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some((did, field_ty)) = private_candidate { let struct_path = self.tcx().item_path_str(did); - let msg = format!("field `{}` of struct `{}` is private", field.node, struct_path); - let mut err = self.tcx().sess.struct_span_err(expr.span, &msg); + let mut err = struct_span_err!(self.tcx().sess, expr.span, E0616, + "field `{}` of struct `{}` is private", + field.node, struct_path); // Also check if an accessible method exists, which is often what is meant. if self.method_exists(field.span, field.node, expr_t, expr.id, false) { err.note(&format!("a method `{}` also exists, perhaps you wish to call it", @@ -2921,39 +2937,41 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else if field.node == keywords::Invalid.name() { self.tcx().types.err } else if self.method_exists(field.span, field.node, expr_t, expr.id, true) { - self.type_error_struct(field.span, |actual| { - format!("attempted to take value of method `{}` on type \ - `{}`", field.node, actual) - }, expr_t) + type_error_struct!(self.tcx().sess, field.span, expr_t, E0615, + "attempted to take value of method `{}` on type `{}`", + field.node, expr_t) .help("maybe a `()` to call it is missing? \ If not, try an anonymous function") .emit(); self.tcx().types.err } else { - let mut err = self.type_error_struct(field.span, |actual| { - format!("no field `{}` on type `{}`", - field.node, actual) - }, expr_t); - match expr_t.sty { - ty::TyAdt(def, _) if !def.is_enum() => { - if let Some(suggested_field_name) = - Self::suggest_field_name(def.struct_variant(), field, vec![]) { - err.span_label(field.span, - format!("did you mean `{}`?", suggested_field_name)); - } else { - err.span_label(field.span, - "unknown field"); - }; - } - ty::TyRawPtr(..) => { - err.note(&format!("`{0}` is a native pointer; perhaps you need to deref with \ - `(*{0}).{1}`", - self.tcx.hir.node_to_pretty_string(base.id), - field.node)); + if !expr_t.is_primitive_ty() { + let mut err = self.no_such_field_err(field.span, &field.node, expr_t); + + match expr_t.sty { + ty::TyAdt(def, _) if !def.is_enum() => { + if let Some(suggested_field_name) = + Self::suggest_field_name(def.struct_variant(), field, vec![]) { + err.span_label(field.span, + format!("did you mean `{}`?", suggested_field_name)); + } else { + err.span_label(field.span, "unknown field"); + }; + } + ty::TyRawPtr(..) => { + err.note(&format!("`{0}` is a native pointer; perhaps you need to deref \ + with `(*{0}).{1}`", + self.tcx.hir.node_to_pretty_string(base.id), + field.node)); + } + _ => {} } - _ => {} - } - err.emit(); + err + } else { + type_error_struct!(self.tcx().sess, field.span, expr_t, E0610, + "`{}` is a primitive type and therefore doesn't have fields", + expr_t) + }.emit(); self.tcx().types.err } } @@ -3035,31 +3053,30 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some((did, field_ty)) = private_candidate { let struct_path = self.tcx().item_path_str(did); - let msg = format!("field `{}` of struct `{}` is private", idx.node, struct_path); - self.tcx().sess.span_err(expr.span, &msg); + struct_span_err!(self.tcx().sess, expr.span, E0611, + "field `{}` of tuple-struct `{}` is private", + idx.node, struct_path).emit(); return field_ty; } - self.type_error_message( - expr.span, - |actual| { - if tuple_like { - format!("attempted out-of-bounds tuple index `{}` on \ - type `{}`", - idx.node, - actual) - } else { - format!("attempted tuple index `{}` on type `{}`, but the \ - type was not a tuple or tuple struct", - idx.node, - actual) - } - }, - expr_t); + if tuple_like { + type_error_struct!(self.tcx().sess, expr.span, expr_t, E0612, + "attempted out-of-bounds tuple index `{}` on type `{}`", + idx.node, expr_t).emit(); + } else { + self.no_such_field_err(expr.span, idx.node, expr_t).emit(); + } self.tcx().types.err } + fn no_such_field_err(&self, span: Span, field: T, expr_t: &ty::TyS) + -> DiagnosticBuilder { + type_error_struct!(self.tcx().sess, span, expr_t, E0609, + "no field `{}` on type `{}`", + field, expr_t) + } + fn report_unknown_field(&self, ty: Ty<'tcx>, variant: &'tcx ty::VariantDef, @@ -3114,11 +3131,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let adt_ty_hint = self.expected_inputs_for_expected_output(span, expected, adt_ty, &[adt_ty]) - .get(0).cloned().unwrap_or(adt_ty); + .get(0).cloned().unwrap_or(adt_ty); + // re-link the regions that EIfEO can erase. + self.demand_eqtype(span, adt_ty_hint, adt_ty); - let (substs, hint_substs, adt_kind, kind_name) = match (&adt_ty.sty, &adt_ty_hint.sty) { - (&ty::TyAdt(adt, substs), &ty::TyAdt(_, hint_substs)) => { - (substs, hint_substs, adt.adt_kind(), adt.variant_descr()) + let (substs, adt_kind, kind_name) = match &adt_ty.sty{ + &ty::TyAdt(adt, substs) => { + (substs, adt.adt_kind(), adt.variant_descr()) } _ => span_bug!(span, "non-ADT passed to check_expr_struct_fields") }; @@ -3134,14 +3153,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Typecheck each field. for field in ast_fields { - let final_field_type; - let field_type_hint; - let ident = tcx.adjust(field.name.node, variant.did, self.body_id).0; - if let Some(v_field) = remaining_fields.remove(&ident) { - final_field_type = self.field_ty(field.span, v_field, substs); - field_type_hint = self.field_ty(field.span, v_field, hint_substs); - + let field_type = if let Some(v_field) = remaining_fields.remove(&ident) { seen_fields.insert(field.name.node, field.span); // we don't look at stability attributes on @@ -3150,16 +3163,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if adt_kind != ty::AdtKind::Enum { tcx.check_stability(v_field.did, expr_id, field.span); } + + self.field_ty(field.span, v_field, substs) } else { error_happened = true; - final_field_type = tcx.types.err; - field_type_hint = tcx.types.err; if let Some(_) = variant.find_field_named(field.name.node) { let mut err = struct_span_err!(self.tcx.sess, - field.name.span, - E0062, - "field `{}` specified more than once", - field.name.node); + field.name.span, + E0062, + "field `{}` specified more than once", + field.name.node); err.span_label(field.name.span, "used more than once"); @@ -3171,12 +3184,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else { self.report_unknown_field(adt_ty, variant, field, ast_fields, kind_name); } - } + + tcx.types.err + }; // Make sure to give a type to the field even if there's // an error, so we can continue typechecking - let ty = self.check_expr_with_hint(&field.expr, field_type_hint); - self.demand_coerce(&field.expr, ty, final_field_type); + self.check_expr_coercable_to_type(&field.expr, field_type); } // Make sure the programmer specified correct number of fields. @@ -3206,15 +3220,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .join(", "); struct_span_err!(tcx.sess, span, E0063, - "missing field{} {}{} in initializer of `{}`", - if remaining_fields.len() == 1 {""} else {"s"}, - remaining_fields_names, - truncated_fields_error, - adt_ty) - .span_label(span, format!("missing {}{}", - remaining_fields_names, - truncated_fields_error)) - .emit(); + "missing field{} {}{} in initializer of `{}`", + if remaining_fields.len() == 1 { "" } else { "s" }, + remaining_fields_names, + truncated_fields_error, + adt_ty) + .span_label(span, format!("missing {}{}", + remaining_fields_names, + truncated_fields_error)) + .emit(); } } @@ -3308,17 +3322,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.check_expr_struct_fields(struct_ty, expected, expr.id, path_span, variant, fields, base_expr.is_none()); if let &Some(ref base_expr) = base_expr { - self.check_expr_has_type(base_expr, struct_ty); + self.check_expr_has_type_or_error(base_expr, struct_ty); match struct_ty.sty { ty::TyAdt(adt, substs) if adt.is_struct() => { - self.tables.borrow_mut().fru_field_types.insert( - expr.id, - adt.struct_variant().fields.iter().map(|f| { - self.normalize_associated_types_in( - expr.span, &f.ty(self.tcx, substs) - ) - }).collect() - ); + let fru_field_types = adt.struct_variant().fields.iter().map(|f| { + self.normalize_associated_types_in(expr.span, &f.ty(self.tcx, substs)) + }).collect(); + self.tables.borrow_mut().fru_field_types.insert(expr.id, fru_field_types); } _ => { span_err!(self.tcx.sess, base_expr.span, E0436, @@ -3451,10 +3461,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { oprnd_t = self.make_overloaded_lvalue_return_type(method).ty; self.write_method_call(expr.id, method); } else { - self.type_error_message(expr.span, |actual| { - format!("type `{}` cannot be \ - dereferenced", actual) - }, oprnd_t); + type_error_struct!(tcx.sess, expr.span, oprnd_t, E0614, + "type `{}` cannot be dereferenced", + oprnd_t).emit(); oprnd_t = tcx.types.err; } } @@ -3625,19 +3634,28 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::ExprAssign(ref lhs, ref rhs) => { let lhs_ty = self.check_expr_with_lvalue_pref(&lhs, PreferMutLvalue); - let tcx = self.tcx; - if !tcx.expr_is_lval(&lhs) { - struct_span_err!( - tcx.sess, expr.span, E0070, - "invalid left-hand side expression") - .span_label( - expr.span, - "left-hand of expression not valid") - .emit(); - } - let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty); + match expected { + ExpectIfCondition => { + self.tcx.sess.delay_span_bug(lhs.span, "invalid lhs expression in if;\ + expected error elsehwere"); + } + _ => { + // Only check this if not in an `if` condition, as the + // mistyped comparison help is more appropriate. + if !self.tcx.expr_is_lval(&lhs) { + struct_span_err!( + self.tcx.sess, expr.span, E0070, + "invalid left-hand side expression") + .span_label( + expr.span, + "left-hand of expression not valid") + .emit(); + } + } + } + self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized); if lhs_ty.references_error() || rhs_ty.references_error() { @@ -3658,7 +3676,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; self.with_breakable_ctxt(expr.id, ctxt, || { - self.check_expr_has_type(&cond, tcx.types.bool); + self.check_expr_has_type_or_error(&cond, tcx.types.bool); let cond_diverging = self.diverges.get(); self.check_block_no_value(&body); @@ -3717,8 +3735,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::ExprCall(ref callee, ref args) => { self.check_call(expr, &callee, args, expected) } - hir::ExprMethodCall(name, ref tps, ref args) => { - self.check_method_call(expr, name, args, &tps[..], expected, lvalue_pref) + hir::ExprMethodCall(ref segment, span, ref args) => { + self.check_method_call(expr, segment, span, args, expected, lvalue_pref) } hir::ExprCast(ref e, ref t) => { // Find the type of `e`. Supply hints based on the type we are casting to, @@ -3796,7 +3814,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } None => { let t: Ty = self.next_ty_var(TypeVariableOrigin::MiscVariable(element.span)); - let element_ty = self.check_expr_has_type(&element, t); + let element_ty = self.check_expr_has_type_or_error(&element, t); (element_ty, t) } }; @@ -3839,6 +3857,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if tuple.references_error() { tcx.types.err } else { + self.require_type_is_sized(tuple, expr.span, traits::TupleInitializerSized); tuple } } @@ -3867,13 +3886,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { element_ty } None => { - let mut err = self.type_error_struct( - expr.span, - |actual| { - format!("cannot index a value of type `{}`", - actual) - }, - base_t); + let mut err = type_error_struct!(tcx.sess, expr.span, base_t, E0608, + "cannot index into a value of type `{}`", + base_t); // Try to give some advice about indexing tuples. if let ty::TyTuple(..) = base_t.sty { let mut needs_note = true; @@ -4021,11 +4036,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn check_stmt(&self, stmt: &'gcx hir::Stmt) { // Don't do all the complex logic below for DeclItem. match stmt.node { - hir::StmtDecl(ref decl, id) => { + hir::StmtDecl(ref decl, _) => { match decl.node { hir::DeclLocal(_) => {} hir::DeclItem(_) => { - self.write_nil(id); return; } } @@ -4041,34 +4055,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.diverges.set(Diverges::Maybe); self.has_errors.set(false); - let (node_id, _span) = match stmt.node { - hir::StmtDecl(ref decl, id) => { - let span = match decl.node { + match stmt.node { + hir::StmtDecl(ref decl, _) => { + match decl.node { hir::DeclLocal(ref l) => { self.check_decl_local(&l); - l.span } - hir::DeclItem(_) => {/* ignore for now */ - DUMMY_SP - } - }; - (id, span) + hir::DeclItem(_) => {/* ignore for now */} + } } - hir::StmtExpr(ref expr, id) => { + hir::StmtExpr(ref expr, _) => { // Check with expected type of () - self.check_expr_has_type(&expr, self.tcx.mk_nil()); - (id, expr.span) + self.check_expr_has_type_or_error(&expr, self.tcx.mk_nil()); } - hir::StmtSemi(ref expr, id) => { + hir::StmtSemi(ref expr, _) => { self.check_expr(&expr); - (id, expr.span) } - }; - - if self.has_errors.get() { - self.write_error(node_id); - } else { - self.write_nil(node_id); } // Combine the diverging and has_error flags. @@ -4143,8 +4145,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut coerce = ctxt.coerce.as_mut().unwrap(); if let Some(tail_expr_ty) = tail_expr_ty { let tail_expr = tail_expr.unwrap(); + let cause = self.cause(tail_expr.span, + ObligationCauseCode::BlockTailExpression(blk.id)); coerce.coerce(self, - &self.misc(tail_expr.span), + &cause, tail_expr, tail_expr_ty, self.diverges.get()); @@ -4183,6 +4187,130 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty } + /// Given a `NodeId`, return the `FnDecl` of the method it is enclosed by and whether it is + /// `fn main` if it is a method, `None` otherwise. + pub fn get_fn_decl(&self, blk_id: ast::NodeId) -> Option<(hir::FnDecl, bool)> { + // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or + // `while` before reaching it, as block tail returns are not available in them. + if let Some(fn_id) = self.tcx.hir.get_return_block(blk_id) { + let parent = self.tcx.hir.get(fn_id); + + if let Node::NodeItem(&hir::Item { + name, node: hir::ItemFn(ref decl, ..), .. + }) = parent { + decl.clone().and_then(|decl| { + // This is less than ideal, it will not present the return type span on any + // method called `main`, regardless of whether it is actually the entry point. + Some((decl, name == Symbol::intern("main"))) + }) + } else if let Node::NodeTraitItem(&hir::TraitItem { + node: hir::TraitItemKind::Method(hir::MethodSig { + ref decl, .. + }, ..), .. + }) = parent { + decl.clone().and_then(|decl| { + Some((decl, false)) + }) + } else { + None + } + } else { + None + } + } + + /// On implicit return expressions with mismatched types, provide the following suggestions: + /// + /// - Point out the method's return type as the reason for the expected type + /// - Possible missing semicolon + /// - Possible missing return type if the return type is the default, and not `fn main()` + pub fn suggest_mismatched_types_on_tail(&self, + err: &mut DiagnosticBuilder<'tcx>, + expression: &'gcx hir::Expr, + expected: Ty<'tcx>, + found: Ty<'tcx>, + cause_span: Span, + blk_id: ast::NodeId) { + self.suggest_missing_semicolon(err, expression, expected, cause_span); + + if let Some((fn_decl, is_main)) = self.get_fn_decl(blk_id) { + // `fn main()` must return `()`, do not suggest changing return type + if !is_main { + self.suggest_missing_return_type(err, &fn_decl, found); + } + } + } + + /// A common error is to forget to add a semicolon at the end of a block: + /// + /// ``` + /// fn foo() { + /// bar_that_returns_u32() + /// } + /// ``` + /// + /// This routine checks if the return expression in a block would make sense on its own as a + /// statement and the return type has been left as defaultor has been specified as `()`. If so, + /// it suggests adding a semicolon. + fn suggest_missing_semicolon(&self, + err: &mut DiagnosticBuilder<'tcx>, + expression: &'gcx hir::Expr, + expected: Ty<'tcx>, + cause_span: Span) { + if expected.is_nil() { + // `BlockTailExpression` only relevant if the tail expr would be + // useful on its own. + match expression.node { + hir::ExprCall(..) | + hir::ExprMethodCall(..) | + hir::ExprIf(..) | + hir::ExprWhile(..) | + hir::ExprLoop(..) | + hir::ExprMatch(..) | + hir::ExprBlock(..) => { + let sp = cause_span.next_point(); + err.span_suggestion(sp, + "did you mean to add a semicolon here?", + ";".to_string()); + } + _ => (), + } + } + } + + + /// A possible error is to forget to add a return type that is needed: + /// + /// ``` + /// fn foo() { + /// bar_that_returns_u32() + /// } + /// ``` + /// + /// This routine checks if the return type is left as default, the method is not part of an + /// `impl` block and that it isn't the `main` method. If so, it suggests setting the return + /// type. + fn suggest_missing_return_type(&self, + err: &mut DiagnosticBuilder<'tcx>, + fn_decl: &hir::FnDecl, + ty: Ty<'tcx>) { + + // Only recommend changing the return type for methods that + // haven't set a return type at all (and aren't `fn main()` or an impl). + if let &hir::FnDecl { + output: hir::FunctionRetTy::DefaultReturn(span), .. + } = fn_decl { + if ty.is_suggestable() { + err.span_suggestion(span, + "possibly return type missing here?", + format!("-> {} ", ty)); + } else { + err.span_label(span, "possibly return type missing here?"); + } + } + } + + /// A common error is to add an extra semicolon: /// /// ``` @@ -4208,7 +4336,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::StmtSemi(ref e, _) => e, _ => return, }; - let last_expr_ty = self.expr_ty(last_expr); + let last_expr_ty = self.node_ty(last_expr.id); if self.can_sub(self.param_env, last_expr_ty, expected_ty).is_err() { return; } @@ -4218,7 +4346,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hi: original_span.hi, ctxt: original_span.ctxt, }; - err.span_help(span_semi, "consider removing this semicolon:"); + err.span_suggestion(span_semi, "consider removing this semicolon", "".to_string()); } // Instantiates the given path, which must refer to an item with the given @@ -4592,9 +4720,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // If not, error. if alternative.is_ty_var() || alternative.references_error() { if !self.is_tainted_by_errors() { - self.type_error_message(sp, |_actual| { - "the type of this value must be known in this context".to_string() - }, ty); + type_error_struct!(self.tcx.sess, sp, ty, E0619, + "the type of this value must be known in this context") + .emit(); } self.demand_suptype(sp, self.tcx.types.err, ty); ty = self.tcx.types.err; diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 4d69b37b11..032e37a34a 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -320,7 +320,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { from a string reference. String concatenation \ appends the string on the right to the string \ on the left and may require reallocation. This \ - requires ownership of the string on the left."), suggestion); + requires ownership of the string on the left"), suggestion); is_string_addition = true; } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 037d172a4d..3437aec892 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -973,18 +973,24 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { } } + /// Create a temporary `MemCategorizationContext` and pass it to the closure. + fn with_mc(&self, f: F) -> R + where F: for<'b> FnOnce(mc::MemCategorizationContext<'b, 'gcx, 'tcx>) -> R + { + f(mc::MemCategorizationContext::with_infer(&self.infcx, + &self.region_maps, + &self.tables.borrow())) + } + /// Invoked on any adjustments that occur. Checks that if this is a region pointer being /// dereferenced, the lifetime of the pointer includes the deref expr. fn constrain_adjustments(&mut self, expr: &hir::Expr) -> mc::McResult> { debug!("constrain_adjustments(expr={:?})", expr); - let mut cmt = { - let mc = mc::MemCategorizationContext::new(self, &self.region_maps); - mc.cat_expr_unadjusted(expr)? - }; + let mut cmt = self.with_mc(|mc| mc.cat_expr_unadjusted(expr))?; - //NOTE(@jroesch): mixed RefCell borrow causes crash - let adjustments = self.tables.borrow().expr_adjustments(&expr).to_vec(); + let tables = self.tables.borrow(); + let adjustments = tables.expr_adjustments(&expr); if adjustments.is_empty() { return Ok(cmt); } @@ -1035,10 +1041,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { expr.id, expr_region); } - { - let mc = mc::MemCategorizationContext::new(self, &self.region_maps); - cmt = mc.cat_expr_adjusted(expr, cmt, &adjustment)?; - } + cmt = self.with_mc(|mc| mc.cat_expr_adjusted(expr, cmt, &adjustment))?; if let Categorization::Deref(_, mc::BorrowedPtr(_, r_ptr)) = cmt.cat { self.mk_subregion_due_to_dereference(expr.span, @@ -1130,10 +1133,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { mutability: hir::Mutability, base: &hir::Expr) { debug!("link_addr_of(expr={:?}, base={:?})", expr, base); - let cmt = { - let mc = mc::MemCategorizationContext::new(self, &self.region_maps); - ignore_err!(mc.cat_expr(base)) - }; + let cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(base))); debug!("link_addr_of: cmt={:?}", cmt); @@ -1149,9 +1149,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { None => { return; } Some(ref expr) => &**expr, }; - let mc = &mc::MemCategorizationContext::new(self, &self.region_maps); - let discr_cmt = ignore_err!(mc.cat_expr(init_expr)); - self.link_pattern(mc, discr_cmt, &local.pat); + let discr_cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(init_expr))); + self.link_pattern(discr_cmt, &local.pat); } /// Computes the guarantors for any ref bindings in a match and @@ -1159,12 +1158,11 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { /// linked to the lifetime of its guarantor (if any). fn link_match(&self, discr: &hir::Expr, arms: &[hir::Arm]) { debug!("regionck::for_match()"); - let mc = &mc::MemCategorizationContext::new(self, &self.region_maps); - let discr_cmt = ignore_err!(mc.cat_expr(discr)); + let discr_cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(discr))); debug!("discr_cmt={:?}", discr_cmt); for arm in arms { for root_pat in &arm.pats { - self.link_pattern(mc, discr_cmt.clone(), &root_pat); + self.link_pattern(discr_cmt.clone(), &root_pat); } } } @@ -1174,30 +1172,28 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { /// linked to the lifetime of its guarantor (if any). fn link_fn_args(&self, body_scope: CodeExtent, args: &[hir::Arg]) { debug!("regionck::link_fn_args(body_scope={:?})", body_scope); - let mc = &mc::MemCategorizationContext::new(self, &self.region_maps); for arg in args { let arg_ty = self.node_ty(arg.id); let re_scope = self.tcx.mk_region(ty::ReScope(body_scope)); - let arg_cmt = mc.cat_rvalue( - arg.id, arg.pat.span, re_scope, arg_ty); + let arg_cmt = self.with_mc(|mc| { + mc.cat_rvalue(arg.id, arg.pat.span, re_scope, arg_ty) + }); debug!("arg_ty={:?} arg_cmt={:?} arg={:?}", arg_ty, arg_cmt, arg); - self.link_pattern(mc, arg_cmt, &arg.pat); + self.link_pattern(arg_cmt, &arg.pat); } } /// Link lifetimes of any ref bindings in `root_pat` to the pointers found /// in the discriminant, if needed. - fn link_pattern<'t>(&self, - mc: &mc::MemCategorizationContext<'a, 'gcx, 'tcx>, - discr_cmt: mc::cmt<'tcx>, - root_pat: &hir::Pat) { + fn link_pattern(&self, discr_cmt: mc::cmt<'tcx>, root_pat: &hir::Pat) { debug!("link_pattern(discr_cmt={:?}, root_pat={:?})", discr_cmt, root_pat); - let _ = mc.cat_pattern(discr_cmt, root_pat, |_, sub_cmt, sub_pat| { + let _ = self.with_mc(|mc| { + mc.cat_pattern(discr_cmt, root_pat, |sub_cmt, sub_pat| { match sub_pat.node { // `ref x` pattern PatKind::Binding(hir::BindByRef(mutbl), ..) => { @@ -1206,7 +1202,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { } _ => {} } - }); + }) + }); } /// Link lifetime of borrowed pointer resulting from autoref to lifetimes in the value being @@ -1364,8 +1361,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // Detect by-ref upvar `x`: let cause = match note { mc::NoteUpvarRef(ref upvar_id) => { - let upvar_capture_map = &self.tables.borrow_mut().upvar_capture_map; - match upvar_capture_map.get(upvar_id) { + match self.tables.borrow().upvar_capture_map.get(upvar_id) { Some(&ty::UpvarCapture::ByRef(ref upvar_borrow)) => { // The mutability of the upvar may have been modified // by the above adjustment, so update our local variable. @@ -1599,15 +1595,15 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // the problem is to add `T: 'r`, which isn't true. So, if there are no // inference variables, we use a verify constraint instead of adding // edges, which winds up enforcing the same condition. - let needs_infer = projection_ty.trait_ref.needs_infer(); + let needs_infer = projection_ty.needs_infer(); if env_bounds.is_empty() && needs_infer { debug!("projection_must_outlive: no declared bounds"); - for component_ty in projection_ty.trait_ref.substs.types() { + for component_ty in projection_ty.substs.types() { self.type_must_outlive(origin.clone(), component_ty, region); } - for r in projection_ty.trait_ref.substs.regions() { + for r in projection_ty.substs.regions() { self.sub_regions(origin.clone(), region, r); } @@ -1625,7 +1621,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { if !env_bounds.is_empty() && env_bounds[1..].iter().all(|b| *b == env_bounds[0]) { let unique_bound = env_bounds[0]; debug!("projection_must_outlive: unique declared bound = {:?}", unique_bound); - if projection_ty.trait_ref.substs.regions().any(|r| env_bounds.contains(&r)) { + if projection_ty.substs.regions().any(|r| env_bounds.contains(&r)) { debug!("projection_must_outlive: unique declared bound appears in trait ref"); self.sub_regions(origin.clone(), region, unique_bound); return; @@ -1695,8 +1691,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { declared_bounds, projection_ty); // see the extensive comment in projection_must_outlive - let item_name = projection_ty.item_name(self.tcx); - let ty = self.tcx.mk_projection(projection_ty.trait_ref, item_name); + let ty = self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs); let recursive_bound = self.recursive_type_bound(span, ty); VerifyBound::AnyRegion(declared_bounds).or(recursive_bound) @@ -1762,9 +1757,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { { debug!("projection_bounds(projection_ty={:?})", projection_ty); - let item_name = projection_ty.item_name(self.tcx); - let ty = self.tcx.mk_projection(projection_ty.trait_ref.clone(), - item_name); + let ty = self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs); // Say we have a projection `>::SomeType`. We are interested // in looking for a trait definition like: @@ -1776,7 +1769,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // ``` // // we can thus deduce that `>::SomeType : 'a`. - let trait_predicates = self.tcx.predicates_of(projection_ty.trait_ref.def_id); + let trait_predicates = self.tcx.predicates_of(projection_ty.trait_ref(self.tcx).def_id); assert_eq!(trait_predicates.parent, None); let predicates = trait_predicates.predicates.as_slice().to_vec(); traits::elaborate_predicates(self.tcx, predicates) @@ -1792,7 +1785,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // apply the substitutions (and normalize any projected types) let outlives = self.instantiate_type_scheme(span, - projection_ty.trait_ref.substs, + projection_ty.substs, &outlives); debug!("projection_bounds: outlives={:?} (2)", @@ -1802,7 +1795,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { let (outlives, _) = self.replace_late_bound_regions_with_fresh_var( span, - infer::AssocTypeProjection(projection_ty.item_name(self.tcx)), + infer::AssocTypeProjection( + self.tcx.associated_item(projection_ty.item_def_id).name), &outlives); debug!("projection_bounds: outlives={:?} (3)", @@ -1811,12 +1805,12 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // check whether this predicate applies to our current projection let cause = self.fcx.misc(span); match self.at(&cause, self.fcx.param_env).eq(outlives.0, ty) { - Ok(ok) => { - self.register_infer_ok_obligations(ok); - Ok(outlives.1) - } - Err(_) => { Err(()) } + Ok(ok) => Ok((ok, outlives.1)), + Err(_) => Err(()) } + }).map(|(ok, result)| { + self.register_infer_ok_obligations(ok); + result }); debug!("projection_bounds: region_result={:?}", diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 25f5418bea..59ca896b34 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -53,31 +53,22 @@ use rustc::hir; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::util::nodemap::NodeMap; -/////////////////////////////////////////////////////////////////////////// -// PUBLIC ENTRY POINTS +use std::collections::hash_map::Entry; impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn closure_analyze(&self, body: &'gcx hir::Body) { - let mut seed = SeedBorrowKind::new(self); - seed.visit_body(body); - - let mut adjust = AdjustBorrowKind::new(self, seed.temp_closure_kinds); - adjust.visit_body(body); + InferBorrowKindVisitor { fcx: self }.visit_body(body); // it's our job to process these. assert!(self.deferred_call_resolutions.borrow().is_empty()); } } -/////////////////////////////////////////////////////////////////////////// -// SEED BORROW KIND - -struct SeedBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { +struct InferBorrowKindVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, - temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>, } -impl<'a, 'gcx, 'tcx> Visitor<'gcx> for SeedBorrowKind<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> Visitor<'gcx> for InferBorrowKindVisitor<'a, 'gcx, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { NestedVisitorMap::None } @@ -87,7 +78,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for SeedBorrowKind<'a, 'gcx, 'tcx> { hir::ExprClosure(cc, _, body_id, _) => { let body = self.fcx.tcx.hir.body(body_id); self.visit_body(body); - self.check_closure(expr, cc); + self.fcx.analyze_closure(expr.id, expr.span, body, cc); } _ => { } @@ -97,26 +88,33 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for SeedBorrowKind<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> SeedBorrowKind<'a, 'gcx, 'tcx> { - fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>) -> SeedBorrowKind<'a, 'gcx, 'tcx> { - SeedBorrowKind { fcx: fcx, temp_closure_kinds: NodeMap() } - } +impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { + fn analyze_closure(&self, + id: ast::NodeId, + span: Span, + body: &hir::Body, + capture_clause: hir::CaptureClause) { + /*! + * Analysis starting point. + */ - fn check_closure(&mut self, - expr: &hir::Expr, - capture_clause: hir::CaptureClause) - { - if !self.fcx.tables.borrow().closure_kinds.contains_key(&expr.id) { - self.temp_closure_kinds.insert(expr.id, (ty::ClosureKind::Fn, None)); - debug!("check_closure: adding closure {:?} as Fn", expr.id); - } + debug!("analyze_closure(id={:?}, body.id={:?})", id, body.id()); - self.fcx.tcx.with_freevars(expr.id, |freevars| { + let infer_kind = match self.tables.borrow_mut().closure_kinds.entry(id) { + Entry::Occupied(_) => false, + Entry::Vacant(entry) => { + debug!("check_closure: adding closure {:?} as Fn", id); + entry.insert((ty::ClosureKind::Fn, None)); + true + } + }; + + self.tcx.with_freevars(id, |freevars| { for freevar in freevars { let def_id = freevar.def.def_id(); - let var_node_id = self.fcx.tcx.hir.as_local_node_id(def_id).unwrap(); + let var_node_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); let upvar_id = ty::UpvarId { var_id: var_node_id, - closure_expr_id: expr.id }; + closure_expr_id: id }; debug!("seed upvar_id {:?}", upvar_id); let capture_kind = match capture_clause { @@ -124,58 +122,41 @@ impl<'a, 'gcx, 'tcx> SeedBorrowKind<'a, 'gcx, 'tcx> { ty::UpvarCapture::ByValue } hir::CaptureByRef => { - let origin = UpvarRegion(upvar_id, expr.span); - let freevar_region = self.fcx.next_region_var(origin); + let origin = UpvarRegion(upvar_id, span); + let freevar_region = self.next_region_var(origin); let upvar_borrow = ty::UpvarBorrow { kind: ty::ImmBorrow, region: freevar_region }; ty::UpvarCapture::ByRef(upvar_borrow) } }; - self.fcx.tables.borrow_mut().upvar_capture_map.insert(upvar_id, capture_kind); + self.tables.borrow_mut().upvar_capture_map.insert(upvar_id, capture_kind); } }); - } -} - -/////////////////////////////////////////////////////////////////////////// -// ADJUST BORROW KIND - -struct AdjustBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, - temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>, -} - -impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { - fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, - temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>) - -> AdjustBorrowKind<'a, 'gcx, 'tcx> { - AdjustBorrowKind { fcx: fcx, temp_closure_kinds: temp_closure_kinds } - } - - fn analyze_closure(&mut self, - id: ast::NodeId, - span: Span, - body: &hir::Body) { - /*! - * Analysis starting point. - */ - - debug!("analyze_closure(id={:?}, body.id={:?})", id, body.id()); { - let body_owner_def_id = self.fcx.tcx.hir.body_owner_def_id(body.id()); - let region_maps = &self.fcx.tcx.region_maps(body_owner_def_id); - let param_env = self.fcx.param_env; - let mut euv = - euv::ExprUseVisitor::with_options(self, - self.fcx, - param_env, - region_maps, - mc::MemCategorizationOptions { - during_closure_kind_inference: true - }); - euv.consume_body(body); + let body_owner_def_id = self.tcx.hir.body_owner_def_id(body.id()); + let region_maps = &self.tcx.region_maps(body_owner_def_id); + let mut delegate = InferBorrowKind { + fcx: self, + adjust_closure_kinds: NodeMap(), + adjust_upvar_captures: ty::UpvarCaptureMap::default(), + }; + euv::ExprUseVisitor::with_infer(&mut delegate, + &self.infcx, + self.param_env, + region_maps, + &self.tables.borrow()) + .consume_body(body); + + // Write the adjusted values back into the main tables. + if infer_kind { + if let Some(kind) = delegate.adjust_closure_kinds.remove(&id) { + self.tables.borrow_mut().closure_kinds.insert(id, kind); + } + } + self.tables.borrow_mut().upvar_capture_map.extend( + delegate.adjust_upvar_captures); } // Now that we've analyzed the closure, we know how each @@ -191,7 +172,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { // inference algorithm will reject it). // Extract the type variables UV0...UVn. - let (def_id, closure_substs) = match self.fcx.node_ty(id).sty { + let (def_id, closure_substs) = match self.node_ty(id).sty { ty::TyClosure(def_id, substs) => (def_id, substs), ref t => { span_bug!( @@ -206,44 +187,41 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { debug!("analyze_closure: id={:?} closure_substs={:?} final_upvar_tys={:?}", id, closure_substs, final_upvar_tys); for (upvar_ty, final_upvar_ty) in - closure_substs.upvar_tys(def_id, self.fcx.tcx).zip(final_upvar_tys) + closure_substs.upvar_tys(def_id, self.tcx).zip(final_upvar_tys) { - self.fcx.demand_eqtype(span, final_upvar_ty, upvar_ty); + self.demand_eqtype(span, final_upvar_ty, upvar_ty); } - // If we are also inferred the closure kind here, update the - // main table and process any deferred resolutions. - if let Some(&(kind, context)) = self.temp_closure_kinds.get(&id) { - self.fcx.tables.borrow_mut().closure_kinds.insert(id, (kind, context)); - let closure_def_id = self.fcx.tcx.hir.local_def_id(id); - debug!("closure_kind({:?}) = {:?}", closure_def_id, kind); - + // If we are also inferred the closure kind here, + // process any deferred resolutions. + if infer_kind { + let closure_def_id = self.tcx.hir.local_def_id(id); let deferred_call_resolutions = - self.fcx.remove_deferred_call_resolutions(closure_def_id); + self.remove_deferred_call_resolutions(closure_def_id); for deferred_call_resolution in deferred_call_resolutions { - deferred_call_resolution.resolve(self.fcx); + deferred_call_resolution.resolve(self); } } } // Returns a list of `ClosureUpvar`s for each upvar. - fn final_upvar_tys(&mut self, closure_id: ast::NodeId) -> Vec> { + fn final_upvar_tys(&self, closure_id: ast::NodeId) -> Vec> { // Presently an unboxed closure type cannot "escape" out of a // function, so we will only encounter ones that originated in the // local crate or were inlined into it along with some function. // This may change if abstract return types of some sort are // implemented. - let tcx = self.fcx.tcx; + let tcx = self.tcx; tcx.with_freevars(closure_id, |freevars| { freevars.iter().map(|freevar| { let def_id = freevar.def.def_id(); let var_id = tcx.hir.as_local_node_id(def_id).unwrap(); - let freevar_ty = self.fcx.node_ty(var_id); + let freevar_ty = self.node_ty(var_id); let upvar_id = ty::UpvarId { var_id: var_id, closure_expr_id: closure_id }; - let capture = self.fcx.upvar_capture(upvar_id).unwrap(); + let capture = self.tables.borrow().upvar_capture(upvar_id); debug!("var_id={:?} freevar_ty={:?} capture={:?}", var_id, freevar_ty, capture); @@ -260,7 +238,15 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { }).collect() }) } +} +struct InferBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, + adjust_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>, + adjust_upvar_captures: ty::UpvarCaptureMap<'tcx>, +} + +impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { fn adjust_upvar_borrow_kind_for_consume(&mut self, cmt: mc::cmt<'tcx>, mode: euv::ConsumeMode) @@ -297,9 +283,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { guarantor.span, tcx.hir.name(upvar_id.var_id)); - let upvar_capture_map = - &mut self.fcx.tables.borrow_mut().upvar_capture_map; - upvar_capture_map.insert(upvar_id, ty::UpvarCapture::ByValue); + self.adjust_upvar_captures.insert(upvar_id, ty::UpvarCapture::ByValue); } mc::NoteClosureEnv(upvar_id) => { // we get just a closureenv ref if this is a @@ -410,11 +394,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { // upvar, then we need to modify the // borrow_kind of the upvar to make sure it // is inferred to mutable if necessary - { - let upvar_capture_map = &mut self.fcx.tables.borrow_mut().upvar_capture_map; - let ub = upvar_capture_map.get_mut(&upvar_id).unwrap(); - self.adjust_upvar_borrow_kind(upvar_id, ub, borrow_kind); - } + self.adjust_upvar_borrow_kind(upvar_id, borrow_kind); // also need to be in an FnMut closure since this is not an ImmBorrow self.adjust_closure_kind(upvar_id.closure_expr_id, @@ -448,22 +428,25 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { /// some particular use. fn adjust_upvar_borrow_kind(&mut self, upvar_id: ty::UpvarId, - upvar_capture: &mut ty::UpvarCapture, kind: ty::BorrowKind) { + let upvar_capture = self.adjust_upvar_captures.get(&upvar_id).cloned() + .unwrap_or_else(|| self.fcx.tables.borrow().upvar_capture(upvar_id)); debug!("adjust_upvar_borrow_kind(upvar_id={:?}, upvar_capture={:?}, kind={:?})", upvar_id, upvar_capture, kind); - match *upvar_capture { + match upvar_capture { ty::UpvarCapture::ByValue => { // Upvar is already by-value, the strongest criteria. } - ty::UpvarCapture::ByRef(ref mut upvar_borrow) => { + ty::UpvarCapture::ByRef(mut upvar_borrow) => { match (upvar_borrow.kind, kind) { // Take RHS: (ty::ImmBorrow, ty::UniqueImmBorrow) | (ty::ImmBorrow, ty::MutBorrow) | (ty::UniqueImmBorrow, ty::MutBorrow) => { upvar_borrow.kind = kind; + self.adjust_upvar_captures.insert(upvar_id, + ty::UpvarCapture::ByRef(upvar_borrow)); } // Take LHS: (ty::ImmBorrow, ty::ImmBorrow) | @@ -484,7 +467,9 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { debug!("adjust_closure_kind(closure_id={}, new_kind={:?}, upvar_span={:?}, var_name={})", closure_id, new_kind, upvar_span, var_name); - if let Some(&(existing_kind, _)) = self.temp_closure_kinds.get(&closure_id) { + let closure_kind = self.adjust_closure_kinds.get(&closure_id).cloned() + .or_else(|| self.fcx.tables.borrow().closure_kinds.get(&closure_id).cloned()); + if let Some((existing_kind, _)) = closure_kind { debug!("adjust_closure_kind: closure_id={}, existing_kind={:?}, new_kind={:?}", closure_id, existing_kind, new_kind); @@ -500,7 +485,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) | (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => { // new kind is stronger than the old kind - self.temp_closure_kinds.insert( + self.adjust_closure_kinds.insert( closure_id, (new_kind, Some((upvar_span, var_name))) ); @@ -510,27 +495,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> Visitor<'gcx> for AdjustBorrowKind<'a, 'gcx, 'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { - NestedVisitorMap::None - } - - fn visit_fn(&mut self, - fn_kind: intravisit::FnKind<'gcx>, - decl: &'gcx hir::FnDecl, - body: hir::BodyId, - span: Span, - id: ast::NodeId) - { - intravisit::walk_fn(self, fn_kind, decl, body, span, id); - - let body = self.fcx.tcx.hir.body(body); - self.visit_body(body); - self.analyze_closure(id, span, body); - } -} - -impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for AdjustBorrowKind<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'gcx, 'tcx> { fn consume(&mut self, _consume_id: ast::NodeId, _consume_span: Span, diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 26f708e934..69cd141462 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -177,12 +177,11 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { } ty::AssociatedKind::Method => { reject_shadowing_type_parameters(fcx.tcx, item.def_id); - let method_ty = fcx.tcx.type_of(item.def_id); - let method_ty = fcx.normalize_associated_types_in(span, &method_ty); + let sig = fcx.tcx.fn_sig(item.def_id); + let sig = fcx.normalize_associated_types_in(span, &sig); let predicates = fcx.tcx.predicates_of(item.def_id) .instantiate_identity(fcx.tcx); let predicates = fcx.normalize_associated_types_in(span, &predicates); - let sig = method_ty.fn_sig(); this.check_fn_or_method(fcx, span, sig, &predicates, item.def_id, &mut implied_bounds); let sig_if_method = sig_if_method.expect("bad signature for method"); @@ -331,9 +330,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { fn check_item_fn(&mut self, item: &hir::Item) { self.for_item(item).with_fcx(|fcx, this| { let def_id = fcx.tcx.hir.local_def_id(item.id); - let ty = fcx.tcx.type_of(def_id); - let item_ty = fcx.normalize_associated_types_in(item.span, &ty); - let sig = item_ty.fn_sig(); + let sig = fcx.tcx.fn_sig(def_id); + let sig = fcx.normalize_associated_types_in(item.span, &sig); let predicates = fcx.tcx.predicates_of(def_id).instantiate_identity(fcx.tcx); let predicates = fcx.normalize_associated_types_in(item.span, &predicates); @@ -461,9 +459,9 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { let span = method_sig.decl.inputs[0].span; - let method_ty = fcx.tcx.type_of(method.def_id); - let fty = fcx.normalize_associated_types_in(span, &method_ty); - let sig = fcx.liberate_late_bound_regions(method.def_id, &fty.fn_sig()); + let sig = fcx.tcx.fn_sig(method.def_id); + let sig = fcx.normalize_associated_types_in(span, &sig); + let sig = fcx.liberate_late_bound_regions(method.def_id, &sig); debug!("check_method_receiver: sig={:?}", sig); @@ -510,7 +508,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { .map(|(index, _)| Parameter(index as u32)) .collect(); - identify_constrained_type_params(ty_predicates.predicates.as_slice(), + identify_constrained_type_params(self.tcx, + ty_predicates.predicates.as_slice(), None, &mut constrained_parameters); diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 012fde16d8..81e5dae547 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -155,11 +155,6 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { NestedVisitorMap::None } - fn visit_stmt(&mut self, s: &'gcx hir::Stmt) { - self.visit_node_id(s.span, s.node.id()); - intravisit::walk_stmt(self, s); - } - fn visit_expr(&mut self, e: &'gcx hir::Expr) { self.fix_scalar_builtin_expr(e); @@ -382,7 +377,7 @@ impl<'cx, 'gcx, 'tcx> Resolver<'cx, 'gcx, 'tcx> { fn report_error(&self, t: Ty<'tcx>) { if !self.tcx.sess.has_errors() { - self.infcx.need_type_info(self.body.id(), self.span.to_span(&self.tcx), t); + self.infcx.need_type_info(Some(self.body.id()), self.span.to_span(&self.tcx), t); } } } diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 377b7b069d..9305eff143 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -208,7 +208,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, source, target); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let cause = ObligationCause::misc(span, impl_node_id); let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>, mt_b: ty::TypeAndMut<'tcx>, @@ -386,7 +386,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Check that all transitive obligations are satisfied. if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(&errors); + infcx.report_fulfillment_errors(&errors, None); } // Finally, resolve all regions. diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs index f7ebc21044..e24d766002 100644 --- a/src/librustc_typeck/coherence/inherent_impls.rs +++ b/src/librustc_typeck/coherence/inherent_impls.rs @@ -17,7 +17,7 @@ //! `tcx.inherent_impls(def_id)`). That value, however, //! is computed by selecting an idea from this table. -use rustc::dep_graph::DepNode; +use rustc::dep_graph::DepKind; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -79,7 +79,8 @@ pub fn inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }); for &impl_def_id in &result[..] { - tcx.dep_graph.read(DepNode::Hir(impl_def_id)); + let def_path_hash = tcx.def_path_hash(impl_def_id); + tcx.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir)); } result diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index afeb85a7a0..078ae34bc5 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -70,7 +70,7 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> { for (i, &impl1_def_id) in impls.iter().enumerate() { for &impl2_def_id in &impls[(i + 1)..] { - self.tcx.infer_ctxt(()).enter(|infcx| { + self.tcx.infer_ctxt().enter(|infcx| { if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id).is_some() { self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id) } diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index ba1d7b18e8..59ebae16d0 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -15,7 +15,6 @@ use rustc::traits; use rustc::ty::{self, TyCtxt, TypeFoldable}; use syntax::ast; -use rustc::dep_graph::DepNode; use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -38,9 +37,6 @@ pub fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) { return } - let _task = - tcx.dep_graph.in_task(DepNode::CoherenceOverlapCheck(trait_def_id)); - // Trigger building the specialization graph for the trait of this impl. // This will detect any overlap errors. tcx.specialization_graph_of(trait_def_id); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index fb3bcd31e2..002a148c45 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -97,6 +97,7 @@ pub fn provide(providers: &mut Providers) { type_param_predicates, trait_def, adt_def, + fn_sig, impl_trait_ref, impl_polarity, is_foreign_item, @@ -224,12 +225,12 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { fn projected_ty_from_poly_trait_ref(&self, span: Span, - poly_trait_ref: ty::PolyTraitRef<'tcx>, - item_name: ast::Name) + item_def_id: DefId, + poly_trait_ref: ty::PolyTraitRef<'tcx>) -> Ty<'tcx> { if let Some(trait_ref) = self.tcx().no_late_bound_regions(&poly_trait_ref) { - self.tcx().mk_projection(trait_ref, item_name) + self.tcx().mk_projection(item_def_id, trait_ref.substs) } else { // no late-bound regions, we can just ignore the binder span_err!(self.tcx().sess, span, E0212, @@ -447,6 +448,9 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); + if let hir::ForeignItemFn(..) = item.node { + tcx.fn_sig(def_id); + } } } hir::ItemEnum(ref enum_definition, _) => { @@ -497,6 +501,9 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); + if let hir::ItemFn(..) = it.node { + tcx.fn_sig(def_id); + } } } } @@ -511,6 +518,9 @@ fn convert_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item_id: ast: hir::TraitItemKind::Type(_, Some(_)) | hir::TraitItemKind::Method(..) => { tcx.type_of(def_id); + if let hir::TraitItemKind::Method(..) = trait_item.node { + tcx.fn_sig(def_id); + } } hir::TraitItemKind::Type(_, None) => {} @@ -524,6 +534,9 @@ fn convert_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item_id: ast::N tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); + if let hir::ImplItemKind::Method(..) = tcx.hir.expect_impl_item(impl_item_id).node { + tcx.fn_sig(def_id); + } } fn convert_variant_ctor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -963,10 +976,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match tcx.hir.get(node_id) { NodeTraitItem(item) => { match item.node { - TraitItemKind::Method(ref sig, _) => { - let fty = AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl); + TraitItemKind::Method(..) => { let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs, fty) + tcx.mk_fn_def(def_id, substs) } TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty), @@ -978,10 +990,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, NodeImplItem(item) => { match item.node { - ImplItemKind::Method(ref sig, _) => { - let fty = AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl); + ImplItemKind::Method(..) => { let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs, fty) + tcx.mk_fn_def(def_id, substs) } ImplItemKind::Const(ref ty, _) => icx.to_ty(ty), ImplItemKind::Type(ref ty) => { @@ -1001,10 +1012,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ItemTy(ref t, _) | ItemImpl(.., ref t, _) => { icx.to_ty(t) } - ItemFn(ref decl, unsafety, _, abi, _, _) => { - let tofd = AstConv::ty_of_fn(&icx, unsafety, abi, &decl); + ItemFn(..) => { let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs, tofd) + tcx.mk_fn_def(def_id, substs) } ItemEnum(..) | ItemStruct(..) | @@ -1029,11 +1039,10 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } NodeForeignItem(foreign_item) => { - let abi = tcx.hir.get_foreign_abi(node_id); - match foreign_item.node { - ForeignItemFn(ref fn_decl, _, _) => { - compute_type_of_foreign_fn_decl(tcx, def_id, fn_decl, abi) + ForeignItemFn(..) => { + let substs = Substs::identity_for_item(tcx, def_id); + tcx.mk_fn_def(def_id, substs) } ForeignItemStatic(ref t, _) => icx.to_ty(t) } @@ -1041,21 +1050,13 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, NodeStructCtor(&ref def) | NodeVariant(&Spanned { node: hir::Variant_ { data: ref def, .. }, .. }) => { - let ty = tcx.type_of(tcx.hir.get_parent_did(node_id)); match *def { - VariantData::Unit(..) | VariantData::Struct(..) => ty, - VariantData::Tuple(ref fields, _) => { - let inputs = fields.iter().map(|f| { - tcx.type_of(tcx.hir.local_def_id(f.id)) - }); + VariantData::Unit(..) | VariantData::Struct(..) => { + tcx.type_of(tcx.hir.get_parent_did(node_id)) + } + VariantData::Tuple(..) => { let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs, ty::Binder(tcx.mk_fn_sig( - inputs, - ty, - false, - hir::Unsafety::Normal, - abi::Abi::Rust - ))) + tcx.mk_fn_def(def_id, substs) } } } @@ -1105,6 +1106,58 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } +fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> ty::PolyFnSig<'tcx> { + use rustc::hir::map::*; + use rustc::hir::*; + + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + + let icx = ItemCtxt::new(tcx, def_id); + + match tcx.hir.get(node_id) { + NodeTraitItem(&hir::TraitItem { node: TraitItemKind::Method(ref sig, _), .. }) | + NodeImplItem(&hir::ImplItem { node: ImplItemKind::Method(ref sig, _), .. }) => { + AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl) + } + + NodeItem(&hir::Item { node: ItemFn(ref decl, unsafety, _, abi, _, _), .. }) => { + AstConv::ty_of_fn(&icx, unsafety, abi, decl) + } + + NodeForeignItem(&hir::ForeignItem { node: ForeignItemFn(ref fn_decl, _, _), .. }) => { + let abi = tcx.hir.get_foreign_abi(node_id); + compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi) + } + + NodeStructCtor(&VariantData::Tuple(ref fields, _)) | + NodeVariant(&Spanned { node: hir::Variant_ { + data: VariantData::Tuple(ref fields, _), .. + }, .. }) => { + let ty = tcx.type_of(tcx.hir.get_parent_did(node_id)); + let inputs = fields.iter().map(|f| { + tcx.type_of(tcx.hir.local_def_id(f.id)) + }); + ty::Binder(tcx.mk_fn_sig( + inputs, + ty, + false, + hir::Unsafety::Normal, + abi::Abi::Rust + )) + } + + NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) => { + tcx.typeck_tables_of(def_id).closure_tys[&node_id] + } + + x => { + bug!("unexpected sort of node in fn_sig(): {:?}", x); + } + } +} + fn impl_trait_ref<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option> { @@ -1385,7 +1438,10 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } }; - let assoc_ty = tcx.mk_projection(self_trait_ref, trait_item.name); + let assoc_ty = tcx.mk_projection( + tcx.hir.local_def_id(trait_item.id), + self_trait_ref.substs, + ); let bounds = compute_bounds(&ItemCtxt::new(tcx, def_id), assoc_ty, @@ -1405,7 +1461,8 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if let NodeItem(&Item { node: ItemImpl(..), .. }) = node { let self_ty = tcx.type_of(def_id); let trait_ref = tcx.impl_trait_ref(def_id); - ctp::setup_constraining_predicates(&mut predicates, + ctp::setup_constraining_predicates(tcx, + &mut predicates, trait_ref, &mut ctp::parameters_for_impl(self_ty, trait_ref)); } @@ -1502,12 +1559,12 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>, } } -fn compute_type_of_foreign_fn_decl<'a, 'tcx>( +fn compute_sig_of_foreign_fn_decl<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, decl: &hir::FnDecl, abi: abi::Abi) - -> Ty<'tcx> + -> ty::PolyFnSig<'tcx> { let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), hir::Unsafety::Unsafe, abi, decl); @@ -1533,8 +1590,7 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>( } } - let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs, fty) + fty } fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs index ee11b774cf..7742194dfe 100644 --- a/src/librustc_typeck/constrained_type_params.rs +++ b/src/librustc_typeck/constrained_type_params.rs @@ -86,12 +86,13 @@ impl<'tcx> TypeVisitor<'tcx> for ParameterCollector { } } -pub fn identify_constrained_type_params<'tcx>(predicates: &[ty::Predicate<'tcx>], +pub fn identify_constrained_type_params<'tcx>(tcx: ty::TyCtxt, + predicates: &[ty::Predicate<'tcx>], impl_trait_ref: Option>, input_parameters: &mut FxHashSet) { let mut predicates = predicates.to_owned(); - setup_constraining_predicates(&mut predicates, impl_trait_ref, input_parameters); + setup_constraining_predicates(tcx, &mut predicates, impl_trait_ref, input_parameters); } @@ -135,7 +136,8 @@ pub fn identify_constrained_type_params<'tcx>(predicates: &[ty::Predicate<'tcx>] /// which is determined by 1, which requires `U`, that is determined /// by 0. I should probably pick a less tangled example, but I can't /// think of any. -pub fn setup_constraining_predicates<'tcx>(predicates: &mut [ty::Predicate<'tcx>], +pub fn setup_constraining_predicates<'tcx>(tcx: ty::TyCtxt, + predicates: &mut [ty::Predicate<'tcx>], impl_trait_ref: Option>, input_parameters: &mut FxHashSet) { @@ -175,7 +177,7 @@ pub fn setup_constraining_predicates<'tcx>(predicates: &mut [ty::Predicate<'tcx> // Special case: watch out for some kind of sneaky attempt // to project out an associated type defined by this very // trait. - let unbound_trait_ref = &projection.projection_ty.trait_ref; + let unbound_trait_ref = projection.projection_ty.trait_ref(tcx); if Some(unbound_trait_ref.clone()) == impl_trait_ref { continue; } @@ -185,8 +187,7 @@ pub fn setup_constraining_predicates<'tcx>(predicates: &mut [ty::Predicate<'tcx> // `<::Baz as Iterator>::Output = ::Output` // Then the projection only applies if `T` is known, but it still // does not determine `U`. - - let inputs = parameters_for(&projection.projection_ty.trait_ref, true); + let inputs = parameters_for(&projection.projection_ty.trait_ref(tcx), true); let relies_only_on_inputs = inputs.iter().all(|p| input_parameters.contains(&p)); if !relies_only_on_inputs { continue; diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 910d5d7402..87e59683fd 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -226,8 +226,10 @@ size of trait implementors isn't fixed, this type has no compile-time size. Therefore, all accesses to trait types must be through pointers. If you encounter this error you should try to avoid dereferencing the pointer. -```ignore -let trait_obj: &SomeTrait = ...; +```compile_fail,E0033 +# trait SomeTrait { fn method_one(&self){} fn method_two(&self){} } +# impl SomeTrait for T {} +let trait_obj: &SomeTrait = &"some_value"; // This tries to implicitly dereference to create an unsized local variable. let &invalid = trait_obj; @@ -237,10 +239,10 @@ trait_obj.method_one(); trait_obj.method_two(); ``` -You can read more about trait objects in the Trait Object section of the -Reference: +You can read more about trait objects in the [Trait Objects] section of the +Reference. -https://doc.rust-lang.org/reference.html#trait-objects +[Trait Objects]: https://doc.rust-lang.org/reference/types.html#trait-objects "##, E0034: r##" @@ -407,7 +409,11 @@ fn main() { Please note on the last example that we could have called `method` like this: -```ignore +``` +# struct Test; +# impl Test { fn method(&self, v: &[T]) -> usize { v.len() } } +# let x = Test; +# let v = &[0]; x.method(v); ``` "##, @@ -684,9 +690,8 @@ External C functions are allowed to be variadic. However, a variadic function takes a minimum number of arguments. For example, consider C's variadic `printf` function: -```ignore -extern crate libc; -use libc::{ c_char, c_int }; +``` +use std::os::raw::{c_char, c_int}; extern "C" { fn printf(_: *const c_char, ...) -> c_int; @@ -696,16 +701,35 @@ extern "C" { Using this declaration, it must be called with at least one argument, so simply calling `printf()` is invalid. But the following uses are allowed: -```ignore +``` +# #![feature(static_nobundle)] +# use std::os::raw::{c_char, c_int}; +# #[cfg_attr(all(windows, target_env = "msvc"), +# link(name = "legacy_stdio_definitions", kind = "static-nobundle"))] +# extern "C" { fn printf(_: *const c_char, ...) -> c_int; } +# fn main() { unsafe { use std::ffi::CString; - printf(CString::new("test\n").unwrap().as_ptr()); - printf(CString::new("number = %d\n").unwrap().as_ptr(), 3); - printf(CString::new("%d, %d\n").unwrap().as_ptr(), 10, 5); + let fmt = CString::new("test\n").unwrap(); + printf(fmt.as_ptr()); + + let fmt = CString::new("number = %d\n").unwrap(); + printf(fmt.as_ptr(), 3); + + let fmt = CString::new("%d, %d\n").unwrap(); + printf(fmt.as_ptr(), 10, 5); } +# } ``` "##, +// ^ Note: On MSVC 2015, the `printf` function is "inlined" in the C code, and +// the C runtime does not contain the `printf` definition. This leads to linker +// error from the doc test (issue #42830). +// This can be fixed by linking to the static library +// `legacy_stdio_definitions.lib` (see https://stackoverflow.com/a/36504365/). +// If this compatibility library is removed in the future, consider changing +// `printf` in this example to another well-known variadic function. E0061: r##" The number of arguments passed to a function must match the number of arguments @@ -850,8 +874,9 @@ lvalue expression represents a memory location and can be a variable (with optional namespacing), a dereference, an indexing expression or a field reference. -More details can be found here: -https://doc.rust-lang.org/reference.html#lvalues-rvalues-and-temporaries +More details can be found in the [Expressions] section of the Reference. + +[Expressions]: https://doc.rust-lang.org/reference/expressions.html#lvalues-rvalues-and-temporaries Now, we can go further. Here are some erroneous code examples: @@ -924,13 +949,15 @@ fn main() { "##, E0073: r##" +#### Note: this error code is no longer emitted by the compiler. + You cannot define a struct (or enum) `Foo` that requires an instance of `Foo` in order to make a new `Foo` value. This is because there would be no way a first instance of `Foo` could be made to initialize another instance! Here's an example of a struct that has this problem: -```ignore +``` struct Foo { x: Box } // error ``` @@ -944,6 +971,8 @@ Now it's possible to create at least one instance of `Foo`: `Foo { x: None }`. "##, E0074: r##" +#### Note: this error code is no longer emitted by the compiler. + When using the `#[simd]` attribute on a tuple struct, the components of the tuple struct must all be of a concrete, nongeneric type so the compiler can reason about how to use SIMD with them. This error will occur if the types @@ -951,7 +980,7 @@ are generic. This will cause an error: -```ignore +``` #![feature(repr_simd)] #[repr(simd)] @@ -1078,13 +1107,16 @@ encountered, so a conflict occurs. "##, E0082: r##" +#### Note: this error code is no longer emitted by the compiler. + When you specify enum discriminants with `=`, the compiler expects `isize` values by default. Or you can add the `repr` attibute to the enum declaration for an explicit choice of the discriminant type. In either cases, the discriminant values must fall within a valid range for the expected type; otherwise this error is raised. For example: -```ignore +```compile_fail +# #![deny(overflowing_literals)] #[repr(u8)] enum Thing { A = 1024, @@ -1095,7 +1127,8 @@ enum Thing { Here, 1024 lies outside the valid range for `u8`, so the discriminant for `A` is invalid. Here is another, more subtle example which depends on target word size: -```ignore +```compile_fail,E0080 +# #[repr(i32)] enum DependsOnPointerSize { A = 1 << 32, } @@ -1448,11 +1481,12 @@ impl Drop for u32 {} To avoid this kind of error, ensure that at least one local type is referenced by the `impl`: -```ignore +``` pub struct Foo; // you define your type in your crate impl Drop for Foo { // and you can implement the trait on it! // code of trait implementation here +# fn drop(&mut self) { } } impl From for i32 { // or you use a type from your crate as @@ -1642,9 +1676,10 @@ fn f() {} It is not possible to declare type parameters on a function that has the `start` attribute. Such a function must have the following type signature (for more -information: http://doc.rust-lang.org/stable/book/no-stdlib.html): +information: http://doc.rust-lang.org/stable/book/first-edition/no-stdlib.html): -```ignore +``` +# let _: fn(isize, *const *const u8) -> isize; ``` @@ -1812,10 +1847,12 @@ information see the [opt-in builtin traits RFC][RFC 19]. "##, E0193: r##" +#### Note: this error code is no longer emitted by the compiler. + `where` clauses must use generic type parameters: it does not make sense to use them otherwise. An example causing this error: -```ignore +``` trait Foo { fn bar(&self); } @@ -2265,17 +2302,20 @@ If `ForeignTrait` is a trait defined in some external crate `foo`, then the following trait `impl` is an error: ```compile_fail,E0210 -extern crate collections; -use collections::range::RangeArgument; - -impl RangeArgument for T { } // error +# #[cfg(for_demonstration_only)] +extern crate foo; +# #[cfg(for_demonstration_only)] +use foo::ForeignTrait; +# use std::panic::UnwindSafe as ForeignTrait; -fn main() {} +impl ForeignTrait for T { } // error +# fn main() {} ``` To work around this, it can be covered with a local type, `MyType`: -```ignore +``` +# use std::panic::UnwindSafe as ForeignTrait; struct MyType(T); impl ForeignTrait for MyType { } // Ok ``` @@ -2286,7 +2326,7 @@ For another example of an error, suppose there's another trait defined in `foo` named `ForeignTrait2` that takes two type parameters. Then this `impl` results in the same rule violation: -```compile_fail +```ignore (cannot-doctest-multicrate-project) struct MyType2; impl ForeignTrait2> for MyType2 { } // error ``` @@ -2297,7 +2337,7 @@ is uncovered, and so runs afoul of the orphan rule. Consider one more example: -```ignore +```ignore (cannot-doctest-multicrate-project) impl ForeignTrait2, T> for MyType2 { } // Ok ``` @@ -2308,7 +2348,7 @@ violate the orphan rule; it is permitted. To see why that last example was allowed, you need to understand the general rule. Unfortunately this rule is a bit tricky to state. Consider an `impl`: -```ignore +```ignore (only-for-syntax-highlight) impl ForeignTrait for T0 { ... } ``` @@ -2437,7 +2477,7 @@ trait T2 { type Bar; // error: Baz is used but not declared - fn return_bool(&self, &Self::Bar, &Self::Baz) -> bool; + fn return_bool(&self, _: &Self::Bar, _: &Self::Baz) -> bool; } ``` @@ -2459,7 +2499,7 @@ trait T2 { type Baz; // we declare `Baz` in our trait. // and now we can use it here: - fn return_bool(&self, &Self::Bar, &Self::Baz) -> bool; + fn return_bool(&self, _: &Self::Bar, _: &Self::Baz) -> bool; } ``` "##, @@ -2590,13 +2630,17 @@ fn baz(x: &>::A) {} To solve this error, please move the type bindings in the type parameter declaration: -```ignore +``` +# struct Bar; +# trait Foo { type A; } fn baz>(x: &::A) {} // ok! ``` Or in the `where` clause: -```ignore +``` +# struct Bar; +# trait Foo { type A; } fn baz(x: &::A) where I: Foo {} ``` "##, @@ -2734,8 +2778,6 @@ An associated const was implemented when another trait item was expected. Erroneous code example: ```compile_fail,E0323 -#![feature(associated_consts)] - trait Foo { type N; } @@ -2767,8 +2809,6 @@ impl Foo for Bar { Or: ``` -#![feature(associated_consts)] - struct Bar; trait Foo { @@ -2786,8 +2826,6 @@ A method was implemented when another trait item was expected. Erroneous code example: ```compile_fail,E0324 -#![feature(associated_consts)] - struct Bar; trait Foo { @@ -2807,8 +2845,6 @@ To fix this error, please verify that the method name wasn't misspelled and verify that you are indeed implementing the correct trait items. Example: ``` -#![feature(associated_consts)] - struct Bar; trait Foo { @@ -2830,8 +2866,6 @@ An associated type was implemented when another trait item was expected. Erroneous code example: ```compile_fail,E0325 -#![feature(associated_consts)] - struct Bar; trait Foo { @@ -2863,8 +2897,6 @@ impl Foo for Bar { Or: ``` -#![feature(associated_consts)] - struct Bar; trait Foo { @@ -2884,8 +2916,6 @@ types in the trait definition. This error indicates that there was a mismatch. Here's an example of this error: ```compile_fail,E0326 -#![feature(associated_consts)] - trait Foo { const BAR: bool; } @@ -2935,14 +2965,19 @@ impl CoerceUnsized> for MyType [`CoerceUnsized`]: https://doc.rust-lang.org/std/ops/trait.CoerceUnsized.html "##, +/* +// Associated consts can now be accessed through generic type parameters, and +// this error is no longer emitted. +// +// FIXME: consider whether to leave it in the error index, or remove it entirely +// as associated consts is not stabilized yet. + E0329: r##" An attempt was made to access an associated constant through either a generic type parameter or `Self`. This is not supported yet. An example causing this error is shown below: -```ignore -#![feature(associated_consts)] - +``` trait Foo { const BAR: f64; } @@ -2961,9 +2996,7 @@ fn get_bar_bad(t: F) -> f64 { Currently, the value of `BAR` for a particular type can only be accessed through a concrete type, as shown below: -```ignore -#![feature(associated_consts)] - +``` trait Foo { const BAR: f64; } @@ -2975,6 +3008,7 @@ fn get_bar_good() -> f64 { } ``` "##, +*/ E0366: r##" An attempt was made to implement `Drop` on a concrete specialization of a @@ -3186,7 +3220,7 @@ impl Baz for Bar { } // Note: This is OK E0374: r##" A struct without a field containing an unsized type cannot implement `CoerceUnsized`. An -[unsized type](https://doc.rust-lang.org/book/unsized-types.html) +[unsized type](https://doc.rust-lang.org/book/first-edition/unsized-types.html) is any type that the compiler doesn't know the length or alignment of at compile time. Any struct containing an unsized type is also unsized. @@ -3245,9 +3279,9 @@ A struct with more than one field containing an unsized type cannot implement `CoerceUnsized`. This only occurs when you are trying to coerce one of the types in your struct to another type in the struct. In this case we try to impl `CoerceUnsized` from `T` to `U` which are both types that the struct -takes. An [unsized type](https://doc.rust-lang.org/book/unsized-types.html) -is any type that the compiler doesn't know the length or alignment of at -compile time. Any struct containing an unsized type is also unsized. +takes. An [unsized type] is any type that the compiler doesn't know the length +or alignment of at compile time. Any struct containing an unsized type is also +unsized. Example of erroneous code: @@ -3292,6 +3326,7 @@ fn coerce_foo, U>(t: T) -> Foo { } ``` +[unsized type]: https://doc.rust-lang.org/book/first-edition/unsized-types.html "##, E0376: r##" @@ -3300,7 +3335,7 @@ The type you are trying to impl `CoerceUnsized` for is not a struct. already able to be coerced without an implementation of `CoerceUnsized` whereas a struct containing an unsized type needs to know the unsized type field it's containing is able to be coerced. An -[unsized type](https://doc.rust-lang.org/book/unsized-types.html) +[unsized type](https://doc.rust-lang.org/book/first-edition/unsized-types.html) is any type that the compiler doesn't know the length or alignment of at compile time. Any struct containing an unsized type is also unsized. @@ -3433,10 +3468,10 @@ struct Foo<'a, T: 'a> { } ``` -PhantomData can also be used to express information about unused type -parameters. You can read more about it in the API documentation: +[PhantomData] can also be used to express information about unused type +parameters. -https://doc.rust-lang.org/std/marker/struct.PhantomData.html +[PhantomData]: https://doc.rust-lang.org/std/marker/struct.PhantomData.html "##, E0393: r##" @@ -3937,6 +3972,46 @@ let s = Simba { mother: 1, father: 0 }; // ok! ``` "##, +E0562: r##" +Abstract return types (written `impl Trait` for some trait `Trait`) are only +allowed as function return types. + +Erroneous code example: + +```compile_fail,E0562 +#![feature(conservative_impl_trait)] + +fn main() { + let count_to_ten: impl Iterator = 0..10; + // error: `impl Trait` not allowed outside of function and inherent method + // return types + for i in count_to_ten { + println!("{}", i); + } +} +``` + +Make sure `impl Trait` only appears in return-type position. + +``` +#![feature(conservative_impl_trait)] + +fn count_to_n(n: usize) -> impl Iterator { + 0..n +} + +fn main() { + for i in count_to_n(10) { // ok! + println!("{}", i); + } +} +``` + +See [RFC 1522] for more details. + +[RFC 1522]: https://github.com/rust-lang/rfcs/blob/master/text/1522-conservative-impl-trait.md +"##, + E0570: r##" The requested ABI is unsupported by the current target. @@ -4095,6 +4170,514 @@ assert_eq!(!Question::No, true); ``` "##, +E0608: r##" +An attempt to index into a type which doesn't implement the `std::ops::Index` +trait was performed. + +Erroneous code example: + +```compile_fail,E0608 +0u8[2]; // error: cannot index into a value of type `u8` +``` + +To be able to index into a type it needs to implement the `std::ops::Index` +trait. Example: + +``` +let v: Vec = vec![0, 1, 2, 3]; + +// The `Vec` type implements the `Index` trait so you can do: +println!("{}", v[2]); +``` +"##, + +E0604: r##" +A cast to `char` was attempted on a type other than `u8`. + +Erroneous code example: + +```compile_fail,E0604 +0u32 as char; // error: only `u8` can be cast as `char`, not `u32` +``` + +As the error message indicates, only `u8` can be cast into `char`. Example: + +``` +let c = 86u8 as char; // ok! +assert_eq!(c, 'V'); +``` + +For more information about casts, take a look at The Book: +https://doc.rust-lang.org/book/first-edition/casting-between-types.html +"##, + +E0605: r##" +An invalid cast was attempted. + +Erroneous code examples: + +```compile_fail,E0605 +let x = 0u8; +x as Vec; // error: non-primitive cast: `u8` as `std::vec::Vec` + +// Another example + +let v = 0 as *const u8; // So here, `v` is a `*const u8`. +v as &u8; // error: non-primitive cast: `*const u8` as `&u8` +``` + +Only primitive types can be cast into each other. Examples: + +``` +let x = 0u8; +x as u32; // ok! + +let v = 0 as *const u8; +v as *const i8; // ok! +``` + +For more information about casts, take a look at The Book: +https://doc.rust-lang.org/book/first-edition/casting-between-types.html +"##, + +E0606: r##" +An incompatible cast was attempted. + +Erroneous code example: + +```compile_fail,E0606 +let x = &0u8; // Here, `x` is a `&u8`. +let y: u32 = x as u32; // error: casting `&u8` as `u32` is invalid +``` + +When casting, keep in mind that only primitive types can be cast into each +other. Example: + +``` +let x = &0u8; +let y: u32 = *x as u32; // We dereference it first and then cast it. +``` + +For more information about casts, take a look at The Book: +https://doc.rust-lang.org/book/first-edition/casting-between-types.html +"##, + +E0607: r##" +A cast between a thin and a fat pointer was attempted. + +Erroneous code example: + +```compile_fail,E0607 +let v = 0 as *const u8; +v as *const [u8]; +``` + +First: what are thin and fat pointers? + +Thin pointers are "simple" pointers: they are purely a reference to a memory +address. + +Fat pointers are pointers referencing Dynamically Sized Types (also called DST). +DST don't have a statically known size, therefore they can only exist behind +some kind of pointers that contain additional information. Slices and trait +objects are DSTs. In the case of slices, the additional information the fat +pointer holds is their size. + +To fix this error, don't try to cast directly between thin and fat pointers. + +For more information about casts, take a look at The Book: +https://doc.rust-lang.org/book/first-edition/casting-between-types.html +"##, + +E0609: r##" +Attempted to access a non-existent field in a struct. + +Erroneous code example: + +```compile_fail,E0609 +struct StructWithFields { + x: u32, +} + +let s = StructWithFields { x: 0 }; +println!("{}", s.foo); // error: no field `foo` on type `StructWithFields` +``` + +To fix this error, check that you didn't misspell the field's name or that the +field actually exists. Example: + +``` +struct StructWithFields { + x: u32, +} + +let s = StructWithFields { x: 0 }; +println!("{}", s.x); // ok! +``` +"##, + +E0610: r##" +Attempted to access a field on a primitive type. + +Erroneous code example: + +```compile_fail,E0610 +let x: u32 = 0; +println!("{}", x.foo); // error: `{integer}` is a primitive type, therefore + // doesn't have fields +``` + +Primitive types are the most basic types available in Rust and don't have +fields. To access data via named fields, struct types are used. Example: + +``` +// We declare struct called `Foo` containing two fields: +struct Foo { + x: u32, + y: i64, +} + +// We create an instance of this struct: +let variable = Foo { x: 0, y: -12 }; +// And we can now access its fields: +println!("x: {}, y: {}", variable.x, variable.y); +``` + +For more information about primitives and structs, take a look at The Book: +https://doc.rust-lang.org/book/first-edition/primitive-types.html +https://doc.rust-lang.org/book/first-edition/structs.html +"##, + +E0611: r##" +Attempted to access a private field on a tuple-struct. + +Erroneous code example: + +```compile_fail,E0611 +mod some_module { + pub struct Foo(u32); + + impl Foo { + pub fn new() -> Foo { Foo(0) } + } +} + +let y = some_module::Foo::new(); +println!("{}", y.0); // error: field `0` of tuple-struct `some_module::Foo` + // is private +``` + +Since the field is private, you have two solutions: + +1) Make the field public: + +``` +mod some_module { + pub struct Foo(pub u32); // The field is now public. + + impl Foo { + pub fn new() -> Foo { Foo(0) } + } +} + +let y = some_module::Foo::new(); +println!("{}", y.0); // So we can access it directly. +``` + +2) Add a getter function to keep the field private but allow for accessing its +value: + +``` +mod some_module { + pub struct Foo(u32); + + impl Foo { + pub fn new() -> Foo { Foo(0) } + + // We add the getter function. + pub fn get(&self) -> &u32 { &self.0 } + } +} + +let y = some_module::Foo::new(); +println!("{}", y.get()); // So we can get the value through the function. +``` +"##, + +E0612: r##" +Attempted out-of-bounds tuple index. + +Erroneous code example: + +```compile_fail,E0612 +struct Foo(u32); + +let y = Foo(0); +println!("{}", y.1); // error: attempted out-of-bounds tuple index `1` + // on type `Foo` +``` + +If a tuple/tuple-struct type has n fields, you can only try to access these n +fields from 0 to (n - 1). So in this case, you can only index `0`. Example: + +``` +struct Foo(u32); + +let y = Foo(0); +println!("{}", y.0); // ok! +``` +"##, + +E0614: r##" +Attempted to dereference a variable which cannot be dereferenced. + +Erroneous code example: + +```compile_fail,E0614 +let y = 0u32; +*y; // error: type `u32` cannot be dereferenced +``` + +Only types implementing `std::ops::Deref` can be dereferenced (such as `&T`). +Example: + +``` +let y = 0u32; +let x = &y; +// So here, `x` is a `&u32`, so we can dereference it: +*x; // ok! +``` +"##, + +E0615: r##" +Attempted to access a method like a field. + +Erroneous code example: + +```compile_fail,E0615 +struct Foo { + x: u32, +} + +impl Foo { + fn method(&self) {} +} + +let f = Foo { x: 0 }; +f.method; // error: attempted to take value of method `method` on type `Foo` +``` + +If you want to use a method, add `()` after it: + +``` +# struct Foo { x: u32 } +# impl Foo { fn method(&self) {} } +# let f = Foo { x: 0 }; +f.method(); +``` + +However, if you wanted to access a field of a struct check that the field name +is spelled correctly. Example: + +``` +# struct Foo { x: u32 } +# impl Foo { fn method(&self) {} } +# let f = Foo { x: 0 }; +println!("{}", f.x); +``` +"##, + +E0616: r##" +Attempted to access a private field on a struct. + +Erroneous code example: + +```compile_fail,E0616 +mod some_module { + pub struct Foo { + x: u32, // So `x` is private in here. + } + + impl Foo { + pub fn new() -> Foo { Foo { x: 0 } } + } +} + +let f = some_module::Foo::new(); +println!("{}", f.x); // error: field `x` of struct `some_module::Foo` is private +``` + +If you want to access this field, you have two options: + +1) Set the field public: + +``` +mod some_module { + pub struct Foo { + pub x: u32, // `x` is now public. + } + + impl Foo { + pub fn new() -> Foo { Foo { x: 0 } } + } +} + +let f = some_module::Foo::new(); +println!("{}", f.x); // ok! +``` + +2) Add a getter function: + +``` +mod some_module { + pub struct Foo { + x: u32, // So `x` is still private in here. + } + + impl Foo { + pub fn new() -> Foo { Foo { x: 0 } } + + // We create the getter function here: + pub fn get_x(&self) -> &u32 { &self.x } + } +} + +let f = some_module::Foo::new(); +println!("{}", f.get_x()); // ok! +``` +"##, + +E0617: r##" +Attempted to pass an invalid type of variable into a variadic function. + +Erroneous code example: + +```compile_fail,E0617 +extern { + fn printf(c: *const i8, ...); +} + +unsafe { + printf(::std::ptr::null(), 0f32); + // error: can't pass an `f32` to variadic function, cast to `c_double` +} +``` + +Certain Rust types must be cast before passing them to a variadic function, +because of arcane ABI rules dictated by the C standard. To fix the error, +cast the value to the type specified by the error message (which you may need +to import from `std::os::raw`). +"##, + +E0618: r##" +Attempted to call something which isn't a function nor a method. + +Erroneous code examples: + +```compile_fail,E0618 +enum X { + Entry, +} + +X::Entry(); // error: expected function, found `X::Entry` + +// Or even simpler: +let x = 0i32; +x(); // error: expected function, found `i32` +``` + +Only functions and methods can be called using `()`. Example: + +``` +// We declare a function: +fn i_am_a_function() {} + +// And we call it: +i_am_a_function(); +``` +"##, + +E0619: r##" +The type-checker needed to know the type of an expression, but that type had not +yet been inferred. + +Erroneous code example: + +```compile_fail,E0619 +let mut x = vec![]; +match x.pop() { + Some(v) => { + // Here, the type of `v` is not (yet) known, so we + // cannot resolve this method call: + v.to_uppercase(); // error: the type of this value must be known in + // this context + } + None => {} +} +``` + +Type inference typically proceeds from the top of the function to the bottom, +figuring out types as it goes. In some cases -- notably method calls and +overloadable operators like `*` -- the type checker may not have enough +information *yet* to make progress. This can be true even if the rest of the +function provides enough context (because the type-checker hasn't looked that +far ahead yet). In this case, type annotations can be used to help it along. + +To fix this error, just specify the type of the variable. Example: + +``` +let mut x: Vec = vec![]; // We precise the type of the vec elements. +match x.pop() { + Some(v) => { + v.to_uppercase(); // Since rustc now knows the type of the vec elements, + // we can use `v`'s methods. + } + None => {} +} +``` +"##, + +E0620: r##" +A cast to an unsized type was attempted. + +Erroneous code example: + +```compile_fail,E0620 +let x = &[1_usize, 2] as [usize]; // error: cast to unsized type: `&[usize; 2]` + // as `[usize]` +``` + +In Rust, some types don't have a known size at compile-time. For example, in a +slice type like `[u32]`, the number of elements is not known at compile-time and +hence the overall size cannot be computed. As a result, such types can only be +manipulated through a reference (e.g., `&T` or `&mut T`) or other pointer-type +(e.g., `Box` or `Rc`). Try casting to a reference instead: + +``` +let x = &[1_usize, 2] as &[usize]; // ok! +``` +"##, + +E0622: r##" +An intrinsic was declared without being a function. + +Erroneous code example: + +```compile_fail,E0622 +#![feature(intrinsics)] +extern "rust-intrinsic" { + pub static breakpoint : unsafe extern "rust-intrinsic" fn(); + // error: intrinsic must be a function +} + +fn main() { unsafe { breakpoint(); } } +``` + +An intrinsic is a function available for use in a given programming language +whose implementation is handled specially by the compiler. In order to fix this +error, just declare a function. +"##, + } register_diagnostics! { @@ -4159,8 +4742,6 @@ register_diagnostics! { E0436, // functional record update requires a struct E0521, // redundant default implementations of trait E0533, // `{}` does not name a unit variant, unit struct or a constant - E0562, // `impl Trait` not allowed outside of function - // and inherent method return types E0563, // cannot determine a type for this `impl Trait`: {} E0564, // only named lifetimes are allowed in `impl Trait`, // but `{}` was found in the type `{}` @@ -4168,4 +4749,5 @@ register_diagnostics! { E0568, // auto-traits can not have predicates, E0588, // packed struct cannot transitively contain a `[repr(align)]` struct E0592, // duplicate definitions with name `{}` +// E0613, // Removed (merged with E0609) } diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index 6b4f08d3d4..14e48b9302 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -102,7 +102,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut input_parameters = ctp::parameters_for_impl(impl_self_ty, impl_trait_ref); ctp::identify_constrained_type_params( - &impl_predicates.predicates.as_slice(), impl_trait_ref, &mut input_parameters); + tcx, &impl_predicates.predicates.as_slice(), impl_trait_ref, &mut input_parameters); // Disallow ANY unconstrained type parameters. for (ty_param, param) in impl_generics.types.iter().zip(&impl_hir_generics.ty_params) { diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 06cb9f948c..9b829e6e3f 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -82,11 +82,6 @@ This API is completely unstable and subject to change. #![feature(rustc_diagnostic_macros)] #![feature(slice_patterns)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] -#![cfg_attr(stage0, feature(loop_break_value))] - #[macro_use] extern crate log; #[macro_use] extern crate syntax; extern crate syntax_pos; @@ -113,7 +108,7 @@ use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::maps::Providers; use rustc::traits::{FulfillmentContext, ObligationCause, ObligationCauseCode, Reveal}; -use session::config; +use session::{CompileIncomplete, config}; use util::common::time; use syntax::ast; @@ -155,7 +150,7 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, expected: Ty<'tcx>, actual: Ty<'tcx>) -> bool { - tcx.infer_ctxt(()).enter(|ref infcx| { + tcx.infer_ctxt().enter(|ref infcx| { let param_env = ty::ParamEnv::empty(Reveal::UserFacing); let mut fulfill_cx = FulfillmentContext::new(); match infcx.at(&cause, param_env).eq(expected, actual) { @@ -171,7 +166,7 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match fulfill_cx.select_all_or_error(infcx) { Ok(()) => true, Err(errors) => { - infcx.report_fulfillment_errors(&errors); + infcx.report_fulfillment_errors(&errors, None); false } } @@ -203,22 +198,21 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } _ => () } - let substs = tcx.intern_substs(&[]); - let se_ty = tcx.mk_fn_def(main_def_id, substs, - ty::Binder(tcx.mk_fn_sig( + let se_ty = tcx.mk_fn_ptr(ty::Binder( + tcx.mk_fn_sig( iter::empty(), tcx.mk_nil(), false, hir::Unsafety::Normal, Abi::Rust - )) - ); + ) + )); require_same_types( tcx, &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType), se_ty, - main_t); + tcx.mk_fn_ptr(tcx.fn_sig(main_def_id))); } _ => { span_bug!(main_span, @@ -253,9 +247,8 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, _ => () } - let substs = tcx.intern_substs(&[]); - let se_ty = tcx.mk_fn_def(start_def_id, substs, - ty::Binder(tcx.mk_fn_sig( + let se_ty = tcx.mk_fn_ptr(ty::Binder( + tcx.mk_fn_sig( [ tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8)) @@ -264,14 +257,14 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, false, hir::Unsafety::Normal, Abi::Rust - )) - ); + ) + )); require_same_types( tcx, &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType), se_ty, - start_t); + tcx.mk_fn_ptr(tcx.fn_sig(start_def_id))); } _ => { span_bug!(start_span, @@ -300,7 +293,8 @@ pub fn provide(providers: &mut Providers) { } pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> Result<(), usize> { + -> Result<(), CompileIncomplete> +{ let time_passes = tcx.sess.time_passes(); // this ensures that later parts of type checking can assume that items @@ -335,12 +329,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) check_unused::check_crate(tcx); check_for_entry_fn(tcx); - let err_count = tcx.sess.err_count(); - if err_count == 0 { - Ok(()) - } else { - Err(err_count) - } + tcx.sess.compile_status() } /// A quasi-deprecated helper used in rustdoc and save-analysis to get diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index cb2ee7dd1b..284c9c5cfc 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -14,11 +14,9 @@ //! We walk the set of items and, for each member, generate new constraints. use hir::def_id::DefId; -use middle::resolve_lifetime as rl; -use rustc::dep_graph::{AssertDepGraphSafe, DepNode}; +use rustc::dep_graph::{AssertDepGraphSafe, DepKind}; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::hir::map as hir_map; use syntax::ast; use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -61,10 +59,10 @@ pub struct Constraint<'a> { /// } /// /// then while we are visiting `Bar`, the `CurrentItem` would have -/// the def-id and generics of `Foo`. -pub struct CurrentItem<'a> { +/// the def-id and the start of `Foo`'s inferreds. +pub struct CurrentItem { def_id: DefId, - generics: &'a ty::Generics, + inferred_start: InferredIndex, } pub fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>) @@ -91,8 +89,59 @@ pub fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>) impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { fn visit_item(&mut self, item: &hir::Item) { + match item.node { + hir::ItemStruct(ref struct_def, _) | + hir::ItemUnion(ref struct_def, _) => { + self.visit_node_helper(item.id); + + if let hir::VariantData::Tuple(..) = *struct_def { + self.visit_node_helper(struct_def.id()); + } + } + + hir::ItemEnum(ref enum_def, _) => { + self.visit_node_helper(item.id); + + for variant in &enum_def.variants { + if let hir::VariantData::Tuple(..) = variant.node.data { + self.visit_node_helper(variant.node.data.id()); + } + } + } + + hir::ItemFn(..) => { + self.visit_node_helper(item.id); + } + + hir::ItemForeignMod(ref foreign_mod) => { + for foreign_item in &foreign_mod.items { + if let hir::ForeignItemFn(..) = foreign_item.node { + self.visit_node_helper(foreign_item.id); + } + } + } + + _ => {} + } + } + + fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) { + if let hir::TraitItemKind::Method(..) = trait_item.node { + self.visit_node_helper(trait_item.id); + } + } + + fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) { + if let hir::ImplItemKind::Method(..) = impl_item.node { + self.visit_node_helper(impl_item.id); + } + } +} + +impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { + fn visit_node_helper(&mut self, id: ast::NodeId) { let tcx = self.terms_cx.tcx; - let def_id = tcx.hir.local_def_id(item.id); + let def_id = tcx.hir.local_def_id(id); // Encapsulate constructing the constraints into a task we can // reference later. This can go away once the red-green @@ -100,19 +149,11 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { // // See README.md for a detailed discussion // on dep-graph management. - match item.node { - hir::ItemEnum(..) | - hir::ItemStruct(..) | - hir::ItemUnion(..) => { - tcx.dep_graph.with_task(DepNode::ItemVarianceConstraints(def_id), - AssertDepGraphSafe(self), - def_id, - visit_item_task); - } - _ => { - // Nothing to do here, skip the task. - } - } + let dep_node = def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints); + tcx.dep_graph.with_task(dep_node, + AssertDepGraphSafe(self), + def_id, + visit_item_task); fn visit_item_task<'a, 'tcx>(ccx: AssertDepGraphSafe<&mut ConstraintContext<'a, 'tcx>>, def_id: DefId) @@ -121,197 +162,57 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { } } - fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { - } - - fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { - } -} - -/// Is `param_id` a lifetime according to `map`? -fn is_lifetime(map: &hir_map::Map, param_id: ast::NodeId) -> bool { - match map.find(param_id) { - Some(hir_map::NodeLifetime(..)) => true, - _ => false, - } -} - -impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.terms_cx.tcx } fn build_constraints_for_item(&mut self, def_id: DefId) { let tcx = self.tcx(); - let id = self.tcx().hir.as_local_node_id(def_id).unwrap(); - let item = tcx.hir.expect_item(id); - debug!("visit_item item={}", tcx.hir.node_to_string(item.id)); + debug!("build_constraints_for_item({})", tcx.item_path_str(def_id)); - match item.node { - hir::ItemEnum(..) | - hir::ItemStruct(..) | - hir::ItemUnion(..) => { - let generics = tcx.generics_of(def_id); - let current_item = &CurrentItem { def_id, generics }; + // Skip items with no generics - there's nothing to infer in them. + if tcx.generics_of(def_id).count() == 0 { + return; + } + let id = tcx.hir.as_local_node_id(def_id).unwrap(); + let inferred_start = self.terms_cx.inferred_starts[&id]; + let current_item = &CurrentItem { def_id, inferred_start }; + match tcx.type_of(def_id).sty { + ty::TyAdt(def, _) => { // Not entirely obvious: constraints on structs/enums do not // affect the variance of their type parameters. See discussion // in comment at top of module. // // self.add_constraints_from_generics(generics); - for field in tcx.adt_def(def_id).all_fields() { + for field in def.all_fields() { self.add_constraints_from_ty(current_item, tcx.type_of(field.did), self.covariant); } } - hir::ItemTrait(..) | - hir::ItemExternCrate(_) | - hir::ItemUse(..) | - hir::ItemStatic(..) | - hir::ItemConst(..) | - hir::ItemFn(..) | - hir::ItemMod(..) | - hir::ItemForeignMod(..) | - hir::ItemGlobalAsm(..) | - hir::ItemTy(..) | - hir::ItemImpl(..) | - hir::ItemDefaultImpl(..) => { - span_bug!(item.span, "`build_constraints_for_item` invoked for non-type-def"); + ty::TyFnDef(..) => { + self.add_constraints_from_sig(current_item, + tcx.fn_sig(def_id), + self.covariant); } - } - } - - /// Load the generics for another item, adding a corresponding - /// relation into the dependencies to indicate that the variance - /// for `current` relies on `def_id`. - fn read_generics(&mut self, current: &CurrentItem, def_id: DefId) -> &'tcx ty::Generics { - let generics = self.tcx().generics_of(def_id); - if self.tcx().dep_graph.is_fully_enabled() { - self.dependencies.add(current.def_id, def_id); - } - generics - } - fn opt_inferred_index(&self, param_id: ast::NodeId) -> Option<&InferredIndex> { - self.terms_cx.inferred_map.get(¶m_id) - } - - fn find_binding_for_lifetime(&self, param_id: ast::NodeId) -> ast::NodeId { - let tcx = self.terms_cx.tcx; - assert!(is_lifetime(&tcx.hir, param_id)); - match tcx.named_region_map.defs.get(¶m_id) { - Some(&rl::Region::EarlyBound(_, lifetime_decl_id)) => lifetime_decl_id, - Some(_) => bug!("should not encounter non early-bound cases"), - - // The lookup should only fail when `param_id` is - // itself a lifetime binding: use it as the decl_id. - None => param_id, - } - - } - - /// Is `param_id` a type parameter for which we infer variance? - fn is_to_be_inferred(&self, param_id: ast::NodeId) -> bool { - let result = self.terms_cx.inferred_map.contains_key(¶m_id); - - // To safe-guard against invalid inferred_map constructions, - // double-check if variance is inferred at some use of a type - // parameter (by inspecting parent of its binding declaration - // to see if it is introduced by a type or by a fn/impl). - - let check_result = |this: &ConstraintContext| -> bool { - let tcx = this.terms_cx.tcx; - let decl_id = this.find_binding_for_lifetime(param_id); - // Currently only called on lifetimes; double-checking that. - assert!(is_lifetime(&tcx.hir, param_id)); - let parent_id = tcx.hir.get_parent(decl_id); - let parent = tcx.hir - .find(parent_id) - .unwrap_or_else(|| bug!("tcx.hir missing entry for id: {}", parent_id)); - - let is_inferred; - macro_rules! cannot_happen { () => { { - bug!("invalid parent: {} for {}", - tcx.hir.node_to_string(parent_id), - tcx.hir.node_to_string(param_id)); - } } } - - match parent { - hir_map::NodeItem(p) => { - match p.node { - hir::ItemTy(..) | - hir::ItemEnum(..) | - hir::ItemStruct(..) | - hir::ItemUnion(..) | - hir::ItemTrait(..) => is_inferred = true, - hir::ItemFn(..) => is_inferred = false, - _ => cannot_happen!(), - } - } - hir_map::NodeTraitItem(..) => is_inferred = false, - hir_map::NodeImplItem(..) => is_inferred = false, - _ => cannot_happen!(), - } - - return is_inferred; - }; - - assert_eq!(result, check_result(self)); - - return result; - } - - /// Returns a variance term representing the declared variance of the type/region parameter - /// with the given id. - fn declared_variance(&self, - param_def_id: DefId, - item_def_id: DefId, - index: usize) - -> VarianceTermPtr<'a> { - assert_eq!(param_def_id.krate, item_def_id.krate); - - if let Some(param_node_id) = self.tcx().hir.as_local_node_id(param_def_id) { - // Parameter on an item defined within current crate: - // variance not yet inferred, so return a symbolic - // variance. - if let Some(&InferredIndex(index)) = self.opt_inferred_index(param_node_id) { - self.terms_cx.inferred_infos[index].term - } else { - // If there is no inferred entry for a type parameter, - // it must be declared on a (locally defiend) trait -- they don't - // get inferreds because they are always invariant. - if cfg!(debug_assertions) { - let item_node_id = self.tcx().hir.as_local_node_id(item_def_id).unwrap(); - let item = self.tcx().hir.expect_item(item_node_id); - let success = match item.node { - hir::ItemTrait(..) => true, - _ => false, - }; - if !success { - bug!("parameter {:?} has no inferred, but declared on non-trait: {:?}", - item_def_id, - item); - } - } - self.invariant + _ => { + span_bug!(tcx.def_span(def_id), + "`build_constraints_for_item` unsupported for this item"); } - } else { - // Parameter on an item defined within another crate: - // variance already inferred, just look it up. - let variances = self.tcx().variances_of(item_def_id); - self.constant_term(variances[index]) } } fn add_constraint(&mut self, - InferredIndex(index): InferredIndex, + current: &CurrentItem, + index: u32, variance: VarianceTermPtr<'a>) { debug!("add_constraint(index={}, variance={:?})", index, variance); self.constraints.push(Constraint { - inferred: InferredIndex(index), + inferred: InferredIndex(current.inferred_start.0 + index as usize), variance: variance, }); } @@ -353,15 +254,26 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { debug!("add_constraints_from_trait_ref: trait_ref={:?} variance={:?}", trait_ref, variance); + self.add_constraints_from_invariant_substs(current, trait_ref.substs, variance); + } - let trait_generics = self.tcx().generics_of(trait_ref.def_id); + fn add_constraints_from_invariant_substs(&mut self, + current: &CurrentItem, + substs: &Substs<'tcx>, + variance: VarianceTermPtr<'a>) { + debug!("add_constraints_from_invariant_substs: substs={:?} variance={:?}", + substs, + variance); - self.add_constraints_from_substs(current, - trait_ref.def_id, - &trait_generics.types, - &trait_generics.regions, - trait_ref.substs, - variance); + // Trait are always invariant so we can take advantage of that. + let variance_i = self.invariant(variance); + for ty in substs.types() { + self.add_constraints_from_ty(current, ty, variance_i); + } + + for region in substs.regions() { + self.add_constraints_from_region(current, region, variance_i); + } } /// Adds constraints appropriate for an instance of `ty` appearing @@ -381,8 +293,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // leaf type -- noop } - ty::TyClosure(..) | - ty::TyAnon(..) => { + ty::TyFnDef(..) | + ty::TyClosure(..) => { bug!("Unexpected closure type in variance computation"); } @@ -408,26 +320,16 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } ty::TyAdt(def, substs) => { - let adt_generics = self.read_generics(current, def.did); - - self.add_constraints_from_substs(current, - def.did, - &adt_generics.types, - &adt_generics.regions, - substs, - variance); + self.add_constraints_from_substs(current, def.did, substs, variance); } ty::TyProjection(ref data) => { - let trait_ref = &data.trait_ref; - let trait_generics = self.tcx().generics_of(trait_ref.def_id); - - self.add_constraints_from_substs(current, - trait_ref.def_id, - &trait_generics.types, - &trait_generics.regions, - trait_ref.substs, - variance); + let tcx = self.tcx(); + self.add_constraints_from_trait_ref(current, data.trait_ref(tcx), variance); + } + + ty::TyAnon(_, substs) => { + self.add_constraints_from_invariant_substs(current, substs, variance); } ty::TyDynamic(ref data, r) => { @@ -446,26 +348,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } ty::TyParam(ref data) => { - assert_eq!(current.generics.parent, None); - let mut i = data.idx as usize; - if !current.generics.has_self || i > 0 { - i -= current.generics.regions.len(); - } - let def_id = current.generics.types[i].def_id; - let node_id = self.tcx().hir.as_local_node_id(def_id).unwrap(); - match self.terms_cx.inferred_map.get(&node_id) { - Some(&index) => { - self.add_constraint(index, variance); - } - None => { - // We do not infer variance for type parameters - // declared on methods. They will not be present - // in the inferred_map. - } - } + self.add_constraint(current, data.idx, variance); } - ty::TyFnDef(.., sig) | ty::TyFnPtr(sig) => { self.add_constraints_from_sig(current, sig, variance); } @@ -488,8 +373,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { fn add_constraints_from_substs(&mut self, current: &CurrentItem, def_id: DefId, - type_param_defs: &[ty::TypeParameterDef], - region_param_defs: &[ty::RegionParameterDef], substs: &Substs<'tcx>, variance: VarianceTermPtr<'a>) { debug!("add_constraints_from_substs(def_id={:?}, substs={:?}, variance={:?})", @@ -497,21 +380,45 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { substs, variance); - for p in type_param_defs { - let variance_decl = self.declared_variance(p.def_id, def_id, p.index as usize); + // We don't record `inferred_starts` entries for empty generics. + if substs.is_empty() { + return; + } + + // Add a corresponding relation into the dependencies to + // indicate that the variance for `current` relies on `def_id`. + if self.tcx().dep_graph.is_fully_enabled() { + self.dependencies.add(current.def_id, def_id); + } + + let (local, remote) = if let Some(id) = self.tcx().hir.as_local_node_id(def_id) { + (Some(self.terms_cx.inferred_starts[&id]), None) + } else { + (None, Some(self.tcx().variances_of(def_id))) + }; + + for (i, k) in substs.iter().enumerate() { + let variance_decl = if let Some(InferredIndex(start)) = local { + // Parameter on an item defined within current crate: + // variance not yet inferred, so return a symbolic + // variance. + self.terms_cx.inferred_terms[start + i] + } else { + // Parameter on an item defined within another crate: + // variance already inferred, just look it up. + self.constant_term(remote.as_ref().unwrap()[i]) + }; let variance_i = self.xform(variance, variance_decl); - let substs_ty = substs.type_for_def(p); debug!("add_constraints_from_substs: variance_decl={:?} variance_i={:?}", variance_decl, variance_i); - self.add_constraints_from_ty(current, substs_ty, variance_i); - } - - for p in region_param_defs { - let variance_decl = self.declared_variance(p.def_id, def_id, p.index as usize); - let variance_i = self.xform(variance, variance_decl); - let substs_r = substs.region_for_def(p); - self.add_constraints_from_region(current, substs_r, variance_i); + if let Some(ty) = k.as_type() { + self.add_constraints_from_ty(current, ty, variance_i); + } else if let Some(r) = k.as_region() { + self.add_constraints_from_region(current, r, variance_i); + } else { + bug!(); + } } } @@ -536,21 +443,14 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { variance: VarianceTermPtr<'a>) { match *region { ty::ReEarlyBound(ref data) => { - assert_eq!(current.generics.parent, None); - let i = data.index as usize - current.generics.has_self as usize; - let def_id = current.generics.regions[i].def_id; - let node_id = self.tcx().hir.as_local_node_id(def_id).unwrap(); - if self.is_to_be_inferred(node_id) { - let &index = self.opt_inferred_index(node_id).unwrap(); - self.add_constraint(index, variance); - } + self.add_constraint(current, data.index, variance); } ty::ReStatic => {} ty::ReLateBound(..) => { - // We do not infer variance for region parameters on - // methods or in fn types. + // Late-bound regions do not get substituted the same + // way early-bound regions do, so we skip them here. } ty::ReFree(..) | diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs index 1afe2725ac..7a9f35545e 100644 --- a/src/librustc_typeck/variance/mod.rs +++ b/src/librustc_typeck/variance/mod.rs @@ -12,7 +12,7 @@ //! parameters. See README.md for details. use arena; -use rustc::dep_graph::DepNode; +use rustc::dep_graph::DepKind; use rustc::hir; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::ty::{self, CrateVariancesMap, TyCtxt}; @@ -54,42 +54,63 @@ fn crate_variances<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId) -> Rc> { - let item_id = tcx.hir.as_local_node_id(item_def_id).expect("expected local def-id"); - let item = tcx.hir.expect_item(item_id); - match item.node { - hir::ItemTrait(..) => { - // Traits are always invariant. - let generics = tcx.generics_of(item_def_id); - assert!(generics.parent.is_none()); - Rc::new(vec![ty::Variance::Invariant; generics.count()]) - } + let id = tcx.hir.as_local_node_id(item_def_id).expect("expected local def-id"); + let unsupported = || { + // Variance not relevant. + span_bug!(tcx.hir.span(id), "asked to compute variance for wrong kind of item") + }; + match tcx.hir.get(id) { + hir::map::NodeItem(item) => match item.node { + hir::ItemEnum(..) | + hir::ItemStruct(..) | + hir::ItemUnion(..) | + hir::ItemFn(..) => {} - hir::ItemEnum(..) | - hir::ItemStruct(..) | - hir::ItemUnion(..) => { - // Everything else must be inferred. - - // Lacking red/green, we read the variances for all items here - // but ignore the dependencies, then re-synthesize the ones we need. - let crate_map = tcx.dep_graph.with_ignore(|| tcx.crate_variances(LOCAL_CRATE)); - tcx.dep_graph.read(DepNode::ItemVarianceConstraints(item_def_id)); - for &dep_def_id in crate_map.dependencies.less_than(&item_def_id) { - if dep_def_id.is_local() { - tcx.dep_graph.read(DepNode::ItemVarianceConstraints(dep_def_id)); - } else { - tcx.dep_graph.read(DepNode::ItemVariances(dep_def_id)); - } - } - - crate_map.variances.get(&item_def_id) - .unwrap_or(&crate_map.empty_variance) - .clone() - } + _ => unsupported() + }, + + hir::map::NodeTraitItem(item) => match item.node { + hir::TraitItemKind::Method(..) => {} + + _ => unsupported() + }, + + hir::map::NodeImplItem(item) => match item.node { + hir::ImplItemKind::Method(..) => {} + + _ => unsupported() + }, - _ => { - // Variance not relevant. - span_bug!(item.span, "asked to compute variance for wrong kind of item") + hir::map::NodeForeignItem(item) => match item.node { + hir::ForeignItemFn(..) => {} + + _ => unsupported() + }, + + hir::map::NodeVariant(_) | hir::map::NodeStructCtor(_) => {} + + _ => unsupported() + } + + // Everything else must be inferred. + + // Lacking red/green, we read the variances for all items here + // but ignore the dependencies, then re-synthesize the ones we need. + let crate_map = tcx.dep_graph.with_ignore(|| tcx.crate_variances(LOCAL_CRATE)); + let dep_node = item_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints); + tcx.dep_graph.read(dep_node); + for &dep_def_id in crate_map.dependencies.less_than(&item_def_id) { + if dep_def_id.is_local() { + let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints); + tcx.dep_graph.read(dep_node); + } else { + let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVariances); + tcx.dep_graph.read(dep_node); } } + + crate_map.variances.get(&item_def_id) + .unwrap_or(&crate_map.empty_variance) + .clone() } diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs index af8ad491ec..495eb95419 100644 --- a/src/librustc_typeck/variance/solve.rs +++ b/src/librustc_typeck/variance/solve.rs @@ -36,15 +36,18 @@ struct SolveContext<'a, 'tcx: 'a> { pub fn solve_constraints(constraints_cx: ConstraintContext) -> ty::CrateVariancesMap { let ConstraintContext { terms_cx, dependencies, constraints, .. } = constraints_cx; - let solutions = terms_cx.inferred_infos - .iter() - .map(|ii| ii.initial_variance) - .collect(); + let mut solutions = vec![ty::Bivariant; terms_cx.inferred_terms.len()]; + for &(id, ref variances) in &terms_cx.lang_items { + let InferredIndex(start) = terms_cx.inferred_starts[&id]; + for (i, &variance) in variances.iter().enumerate() { + solutions[start + i] = variance; + } + } let mut solutions_cx = SolveContext { - terms_cx: terms_cx, - constraints: constraints, - solutions: solutions, + terms_cx, + constraints, + solutions, }; solutions_cx.solve(); let variances = solutions_cx.create_map(); @@ -71,12 +74,9 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { let old_value = self.solutions[inferred]; let new_value = glb(variance, old_value); if old_value != new_value { - debug!("Updating inferred {} (node {}) \ + debug!("Updating inferred {} \ from {:?} to {:?} due to {:?}", inferred, - self.terms_cx - .inferred_infos[inferred] - .param_id, old_value, new_value, term); @@ -89,49 +89,28 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { } fn create_map(&self) -> FxHashMap>> { - // Collect all the variances for a particular item and stick - // them into the variance map. We rely on the fact that we - // generate all the inferreds for a particular item - // consecutively (that is, we collect solutions for an item - // until we see a new item id, and we assume (1) the solutions - // are in the same order as the type parameters were declared - // and (2) all solutions or a given item appear before a new - // item id). - let tcx = self.terms_cx.tcx; - let mut map = FxHashMap(); - let solutions = &self.solutions; - let inferred_infos = &self.terms_cx.inferred_infos; - let mut index = 0; - let num_inferred = self.terms_cx.num_inferred(); - while index < num_inferred { - let item_id = inferred_infos[index].item_id; - - let mut item_variances = vec![]; - - while index < num_inferred && inferred_infos[index].item_id == item_id { - let info = &inferred_infos[index]; - let variance = solutions[index]; - debug!("Index {} Info {} Variance {:?}", - index, - info.index, - variance); - - assert_eq!(item_variances.len(), info.index); - item_variances.push(variance); - index += 1; - } + self.terms_cx.inferred_starts.iter().map(|(&id, &InferredIndex(start))| { + let def_id = tcx.hir.local_def_id(id); + let generics = tcx.generics_of(def_id); - debug!("item_id={} item_variances={:?}", item_id, item_variances); + let mut variances = solutions[start..start+generics.count()].to_vec(); - let item_def_id = tcx.hir.local_def_id(item_id); + debug!("id={} variances={:?}", id, variances); - map.insert(item_def_id, Rc::new(item_variances)); - } + // Functions can have unused type parameters: make those invariant. + if let ty::TyFnDef(..) = tcx.type_of(def_id).sty { + for variance in &mut variances { + if *variance == ty::Bivariant { + *variance = ty::Invariant; + } + } + } - map + (def_id, Rc::new(variances)) + }).collect() } fn evaluate(&self, term: VarianceTermPtr<'a>) -> ty::Variance { diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index ad787c57e7..38457146a9 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -22,7 +22,6 @@ use arena::TypedArena; use rustc::ty::{self, TyCtxt}; use std::fmt; -use std::rc::Rc; use syntax::ast; use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -63,31 +62,17 @@ pub struct TermsContext<'a, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'tcx, 'tcx>, pub arena: &'a TypedArena>, - pub empty_variances: Rc>, - // For marker types, UnsafeCell, and other lang items where // variance is hardcoded, records the item-id and the hardcoded // variance. pub lang_items: Vec<(ast::NodeId, Vec)>, - // Maps from the node id of a type/generic parameter to the - // corresponding inferred index. - pub inferred_map: NodeMap, - - // Maps from an InferredIndex to the info for that variable. - pub inferred_infos: Vec>, -} - -pub struct InferredInfo<'a> { - pub item_id: ast::NodeId, - pub index: usize, - pub param_id: ast::NodeId, - pub term: VarianceTermPtr<'a>, + // Maps from the node id of an item to the first inferred index + // used for its type & region parameters. + pub inferred_starts: NodeMap, - // Initial value to use for this parameter when inferring - // variance. For most parameters, this is Bivariant. But for lang - // items and input type parameters on traits, it is different. - pub initial_variance: ty::Variance, + // Maps from an InferredIndex to the term for that variable. + pub inferred_terms: Vec>, } pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -96,14 +81,10 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx> let mut terms_cx = TermsContext { tcx: tcx, arena: arena, - inferred_map: NodeMap(), - inferred_infos: Vec::new(), + inferred_starts: NodeMap(), + inferred_terms: vec![], lang_items: lang_items(tcx), - - // cache and share the variance struct used for items with - // no type/region parameters - empty_variances: Rc::new(vec![]), }; // See README.md for a discussion on dep-graph management. @@ -135,67 +116,28 @@ fn lang_items(tcx: TyCtxt) -> Vec<(ast::NodeId, Vec)> { } impl<'a, 'tcx> TermsContext<'a, 'tcx> { - fn add_inferreds_for_item(&mut self, - item_id: ast::NodeId, - generics: &hir::Generics) { - //! Add "inferreds" for the generic parameters declared on this - //! item. This has a lot of annoying parameters because we are - //! trying to drive this from the AST, rather than the - //! ty::Generics, so that we can get span info -- but this - //! means we must accommodate syntactic distinctions. - //! + fn add_inferreds_for_item(&mut self, id: ast::NodeId) { + let tcx = self.tcx; + let def_id = tcx.hir.local_def_id(id); + let count = tcx.generics_of(def_id).count(); - // NB: In the code below for writing the results back into the - // `CrateVariancesMap`, we rely on the fact that all inferreds - // for a particular item are assigned continuous indices. - - for (p, i) in generics.lifetimes.iter().zip(0..) { - let id = p.lifetime.id; - self.add_inferred(item_id, i, id); - } - - for (p, i) in generics.ty_params.iter().zip(generics.lifetimes.len()..) { - self.add_inferred(item_id, i, p.id); + if count == 0 { + return; } - } - fn add_inferred(&mut self, item_id: ast::NodeId, index: usize, param_id: ast::NodeId) { - let inf_index = InferredIndex(self.inferred_infos.len()); - let term = self.arena.alloc(InferredTerm(inf_index)); - let initial_variance = self.pick_initial_variance(item_id, index); - self.inferred_infos.push(InferredInfo { - item_id: item_id, - index: index, - param_id: param_id, - term: term, - initial_variance: initial_variance, - }); - let newly_added = self.inferred_map.insert(param_id, inf_index).is_none(); + // Record the start of this item's inferreds. + let start = self.inferred_terms.len(); + let newly_added = self.inferred_starts.insert(id, InferredIndex(start)).is_none(); assert!(newly_added); - debug!("add_inferred(item_path={}, \ - item_id={}, \ - index={}, \ - param_id={}, \ - inf_index={:?}, \ - initial_variance={:?})", - self.tcx.item_path_str(self.tcx.hir.local_def_id(item_id)), - item_id, - index, - param_id, - inf_index, - initial_variance); - } - - fn pick_initial_variance(&self, item_id: ast::NodeId, index: usize) -> ty::Variance { - match self.lang_items.iter().find(|&&(n, _)| n == item_id) { - Some(&(_, ref variances)) => variances[index], - None => ty::Bivariant, - } - } + // NB: In the code below for writing the results back into the + // `CrateVariancesMap`, we rely on the fact that all inferreds + // for a particular item are assigned continuous indices. - pub fn num_inferred(&self) -> usize { - self.inferred_infos.len() + let arena = self.arena; + self.inferred_terms.extend((start..start+count).map(|i| { + &*arena.alloc(InferredTerm(InferredIndex(i))) + })); } } @@ -205,30 +147,50 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> { self.tcx.hir.node_to_string(item.id)); match item.node { - hir::ItemEnum(_, ref generics) | - hir::ItemStruct(_, ref generics) | - hir::ItemUnion(_, ref generics) => { - self.add_inferreds_for_item(item.id, generics); + hir::ItemStruct(ref struct_def, _) | + hir::ItemUnion(ref struct_def, _) => { + self.add_inferreds_for_item(item.id); + + if let hir::VariantData::Tuple(..) = *struct_def { + self.add_inferreds_for_item(struct_def.id()); + } + } + + hir::ItemEnum(ref enum_def, _) => { + self.add_inferreds_for_item(item.id); + + for variant in &enum_def.variants { + if let hir::VariantData::Tuple(..) = variant.node.data { + self.add_inferreds_for_item(variant.node.data.id()); + } + } + } + + hir::ItemFn(..) => { + self.add_inferreds_for_item(item.id); } - hir::ItemTrait(..) | - hir::ItemExternCrate(_) | - hir::ItemUse(..) | - hir::ItemDefaultImpl(..) | - hir::ItemImpl(..) | - hir::ItemStatic(..) | - hir::ItemConst(..) | - hir::ItemFn(..) | - hir::ItemMod(..) | - hir::ItemForeignMod(..) | - hir::ItemGlobalAsm(..) | - hir::ItemTy(..) => {} + hir::ItemForeignMod(ref foreign_mod) => { + for foreign_item in &foreign_mod.items { + if let hir::ForeignItemFn(..) = foreign_item.node { + self.add_inferreds_for_item(foreign_item.id); + } + } + } + + _ => {} } } - fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { + fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) { + if let hir::TraitItemKind::Method(..) = trait_item.node { + self.add_inferreds_for_item(trait_item.id); + } } - fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { + fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) { + if let hir::ImplItemKind::Method(..) = impl_item.node { + self.add_inferreds_for_item(impl_item.id); + } } } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 8f7add14d0..fa5a999adf 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -77,10 +77,10 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name) ret.extend(build_impls(cx, did)); clean::EnumItem(build_enum(cx, did)) } - // Assume that the enum type is reexported next to the variant, and - // variants don't show up in documentation specially. - // Similarly, consider that struct type is reexported next to its constructor. - Def::Variant(..) | + // Never inline enum variants but leave them shown as reexports. + Def::Variant(..) => return None, + // Assume that enum variants and struct types are reexported next to + // their constructors. Def::VariantCtor(..) | Def::StructCtor(..) => return Some(Vec::new()), Def::Mod(did) => { @@ -149,9 +149,9 @@ pub fn build_external_trait(cx: &DocContext, did: DefId) -> clean::Trait { } fn build_external_function(cx: &DocContext, did: DefId) -> clean::Function { - let sig = cx.tcx.type_of(did).fn_sig(); + let sig = cx.tcx.fn_sig(did); - let constness = if cx.tcx.sess.cstore.is_const_fn(did) { + let constness = if cx.tcx.is_const_fn(did) { hir::Constness::Const } else { hir::Constness::NotConst @@ -352,7 +352,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { clean::TyMethodItem(clean::TyMethod { unsafety, decl, generics, abi }) => { - let constness = if tcx.sess.cstore.is_const_fn(item.def_id) { + let constness = if tcx.is_const_fn(item.def_id) { hir::Constness::Const } else { hir::Constness::NotConst @@ -443,7 +443,7 @@ fn build_module(cx: &DocContext, did: DefId) -> clean::Module { // two namespaces, so the target may be listed twice. Make sure we only // visit each node at most once. let mut visited = FxHashSet(); - for item in cx.tcx.sess.cstore.item_children(did) { + for item in cx.tcx.sess.cstore.item_children(did, cx.tcx.sess) { let def_id = item.def.def_id(); if cx.tcx.sess.cstore.visibility(def_id) == ty::Visibility::Public { if !visited.insert(def_id) { continue } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 25e55ff36e..9d0b5b41a9 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -124,6 +124,7 @@ impl<'a, 'tcx> Clean for visit_ast::RustdocVisitor<'a, 'tcx> { let mut r = cx.renderinfo.borrow_mut(); r.deref_trait_did = cx.tcx.lang_items.deref_trait(); r.deref_mut_trait_did = cx.tcx.lang_items.deref_mut_trait(); + r.owned_box_did = cx.tcx.lang_items.owned_box(); } let mut externs = Vec::new(); @@ -240,7 +241,7 @@ impl Clean for CrateNum { } }).collect() } else { - cx.tcx.sess.cstore.item_children(root).iter().map(|item| item.def) + cx.tcx.sess.cstore.item_children(root, cx.tcx.sess).iter().map(|item| item.def) .filter_map(as_primitive).collect() }; @@ -310,6 +311,9 @@ impl Item { pub fn is_ty_method(&self) -> bool { self.type_() == ItemType::TyMethod } + pub fn is_typedef(&self) -> bool { + self.type_() == ItemType::Typedef + } pub fn is_primitive(&self) -> bool { self.type_() == ItemType::Primitive } @@ -948,15 +952,15 @@ impl<'tcx> Clean for ty::ProjectionPredicate<'tcx> { impl<'tcx> Clean for ty::ProjectionTy<'tcx> { fn clean(&self, cx: &DocContext) -> Type { - let trait_ = match self.trait_ref.clean(cx) { + let trait_ = match self.trait_ref(cx.tcx).clean(cx) { TyParamBound::TraitBound(t, _) => t.trait_, TyParamBound::RegionBound(_) => { panic!("cleaning a trait got a region") } }; Type::QPath { - name: self.item_name(cx.tcx).clean(cx), - self_type: box self.trait_ref.self_ty().clean(cx), + name: cx.tcx.associated_item(self.item_def_id).name.clean(cx), + self_type: box self.self_ty().clean(cx), trait_: box trait_ } } @@ -1363,7 +1367,7 @@ impl<'tcx> Clean for ty::AssociatedItem { ty::AssociatedKind::Method => { let generics = (cx.tcx.generics_of(self.def_id), &cx.tcx.predicates_of(self.def_id)).clean(cx); - let sig = cx.tcx.type_of(self.def_id).fn_sig(); + let sig = cx.tcx.fn_sig(self.def_id); let mut decl = (self.def_id, sig).clean(cx); if self.method_has_self_argument { @@ -1780,7 +1784,7 @@ impl Clean for hir::Ty { let mut def = Def::Err; let ty = hir_ty_to_ty(cx.tcx, self); if let ty::TyProjection(proj) = ty.sty { - def = Def::Trait(proj.trait_ref.def_id); + def = Def::Trait(proj.trait_ref(cx.tcx).def_id); } let trait_path = hir::Path { span: self.span, @@ -1838,17 +1842,21 @@ impl<'tcx> Clean for ty::Ty<'tcx> { mutability: mt.mutbl.clean(cx), type_: box mt.ty.clean(cx), }, - ty::TyFnDef(.., sig) | - ty::TyFnPtr(sig) => BareFunction(box BareFunctionDecl { - unsafety: sig.unsafety(), - generics: Generics { - lifetimes: Vec::new(), - type_params: Vec::new(), - where_predicates: Vec::new() - }, - decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), sig).clean(cx), - abi: sig.abi(), - }), + ty::TyFnDef(..) | + ty::TyFnPtr(_) => { + let ty = cx.tcx.lift(self).unwrap(); + let sig = ty.fn_sig(cx.tcx); + BareFunction(box BareFunctionDecl { + unsafety: sig.unsafety(), + generics: Generics { + lifetimes: Vec::new(), + type_params: Vec::new(), + where_predicates: Vec::new() + }, + decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), sig).clean(cx), + abi: sig.abi(), + }) + } ty::TyAdt(def, substs) => { let did = def.did; let kind = match def.adt_kind() { @@ -1893,7 +1901,7 @@ impl<'tcx> Clean for ty::Ty<'tcx> { let mut bindings = vec![]; for ty::Binder(ref pb) in obj.projection_bounds() { bindings.push(TypeBinding { - name: pb.item_name.clean(cx), + name: cx.tcx.associated_item(pb.item_def_id).name.clean(cx), ty: pb.ty.clean(cx) }); } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 9a689ed079..62b91feb09 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -106,7 +106,8 @@ pub fn run_core(search_paths: SearchPaths, input: Input, triple: Option, maybe_sysroot: Option, - allow_warnings: bool) -> (clean::Crate, RenderInfo) + allow_warnings: bool, + force_unstable_if_unmarked: bool) -> (clean::Crate, RenderInfo) { // Parse, resolve, and typecheck the given crate. @@ -128,6 +129,10 @@ pub fn run_core(search_paths: SearchPaths, // Ensure that rustdoc works even if rustc is feature-staged unstable_features: UnstableFeatures::Allow, actually_rustdoc: true, + debugging_opts: config::DebuggingOptions { + force_unstable_if_unmarked: force_unstable_if_unmarked, + ..config::basic_debugging_options() + }, ..config::basic_options().clone() }; diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 86660c28f8..766e76137c 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -459,22 +459,10 @@ pub fn href(did: DefId) -> Option<(String, ItemType, Vec)> { /// rendering function with the necessary arguments for linking to a local path. fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path, print_all: bool, use_absolute: bool) -> fmt::Result { - let empty = clean::PathSegment { - name: String::new(), - params: clean::PathParameters::Parenthesized { - inputs: Vec::new(), - output: None, - } - }; - let last = path.segments.last() - .unwrap_or(&empty); - let rel_root = if path.segments.is_empty() { - None - } else { - match &*path.segments[0].name { - "self" => Some("./".to_string()), - _ => None, - } + let last = path.segments.last().unwrap(); + let rel_root = match &*path.segments[0].name { + "self" => Some("./".to_string()), + _ => None, }; if print_all { @@ -508,7 +496,7 @@ fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path, Some((_, _, fqp)) => { format!("{}::{}", fqp[..fqp.len() - 1].join("::"), - HRef::new(did, fqp.last().unwrap_or(&String::new()))) + HRef::new(did, fqp.last().unwrap())) } None => format!("{}", HRef::new(did, &last.name)), } @@ -740,10 +728,8 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt: } clean::QPath { ref name, ref self_type, ref trait_ } => { let should_show_cast = match *trait_ { - box clean::ResolvedPath { .. } => { - let path = clean::Path::singleton(name.clone()); - !path.segments.is_empty() && &format!("{:#}", trait_) != "()" && - &format!("{:#}", self_type) != "Self" + box clean::ResolvedPath { ref path, .. } => { + !path.segments.is_empty() && !self_type.is_self_type() } _ => true, }; @@ -772,8 +758,18 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt: // everything comes in as a fully resolved QPath (hard to // look at). box clean::ResolvedPath { did, ref typarams, .. } => { - let path = clean::Path::singleton(name.clone()); - resolved_path(f, did, &path, true, use_absolute)?; + match href(did) { + Some((ref url, _, ref path)) if !f.alternate() => { + write!(f, + "{name}", + url = url, + shortty = ItemType::AssociatedType, + name = name, + path = path.join("::"))?; + } + _ => write!(f, "{}", name)?, + } // FIXME: `typarams` are not rendered, and this seems bad? drop(typarams); @@ -1023,7 +1019,11 @@ impl fmt::Display for clean::Import { } } clean::Import::Glob(ref src) => { - write!(f, "use {}::*;", *src) + if src.path.segments.is_empty() { + write!(f, "use *;") + } else { + write!(f, "use {}::*;", *src) + } } } } diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index a40d1e6bdc..89a40b0db9 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -300,7 +300,7 @@ impl<'a> Classifier<'a> { "Some" | "None" | "Ok" | "Err" => Class::PreludeVal, "$crate" => Class::KeyWord, - _ if tas.tok.is_any_keyword() => Class::KeyWord, + _ if tas.tok.is_reserved_ident() => Class::KeyWord, _ => { if self.in_macro_nonterminal { @@ -319,7 +319,7 @@ impl<'a> Classifier<'a> { token::Lifetime(..) => Class::Lifetime, token::Underscore | token::Eof | token::Interpolated(..) | - token::SubstNt(..) | token::Tilde | token::At => Class::None, + token::Tilde | token::At => Class::None, }; // Anything that didn't return above is the simple case where we the diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index ec4a23b041..4b40ee76b4 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -15,7 +15,7 @@ //! functionality through a unit-struct, `Markdown`, which has an implementation //! of `fmt::Display`. Example usage: //! -//! ```rust,ignore +//! ``` //! use rustdoc::html::markdown::Markdown; //! //! let s = "My *markdown* _text_"; @@ -191,8 +191,8 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'a, I> { .map(|l| map_line(l).for_code()) .collect::>().join("\n"); let krate = krate.as_ref().map(|s| &**s); - let test = test::maketest(&test, krate, false, - &Default::default()); + let test = test::make_test(&test, krate, false, + &Default::default()); let channel = if test.contains("#![feature(") { "&version=nightly" } else { @@ -585,8 +585,8 @@ pub fn render(w: &mut fmt::Formatter, .map(|l| map_line(l).for_code()) .collect::>().join("\n"); let krate = krate.as_ref().map(|s| &**s); - let test = test::maketest(&test, krate, false, - &Default::default()); + let test = test::make_test(&test, krate, false, + &Default::default()); let channel = if test.contains("#![feature(") { "&version=nightly" } else { @@ -769,7 +769,7 @@ pub fn old_find_testable_code(doc: &str, tests: &mut ::test::Collector, position block_info.should_panic, block_info.no_run, block_info.ignore, block_info.test_harness, block_info.compile_fail, block_info.error_codes, - line, filename); + line, filename, block_info.allow_fail); } else { tests.add_old_test(text, filename); } @@ -859,7 +859,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp block_info.should_panic, block_info.no_run, block_info.ignore, block_info.test_harness, block_info.compile_fail, block_info.error_codes, - line, filename); + line, filename, block_info.allow_fail); prev_offset = offset; } Event::Start(Tag::Header(level)) => { @@ -889,6 +889,7 @@ struct LangString { test_harness: bool, compile_fail: bool, error_codes: Vec, + allow_fail: bool, } impl LangString { @@ -902,6 +903,7 @@ impl LangString { test_harness: false, compile_fail: false, error_codes: Vec::new(), + allow_fail: false, } } @@ -930,6 +932,7 @@ impl LangString { } "no_run" => { data.no_run = true; seen_rust_tags = !seen_other_tags; } "ignore" => { data.ignore = true; seen_rust_tags = !seen_other_tags; } + "allow_fail" => { data.allow_fail = true; seen_rust_tags = !seen_other_tags; } "rust" => { data.rust = true; seen_rust_tags = true; } "test_harness" => { data.test_harness = true; @@ -1118,7 +1121,7 @@ mod tests { fn test_lang_string_parse() { fn t(s: &str, should_panic: bool, no_run: bool, ignore: bool, rust: bool, test_harness: bool, - compile_fail: bool, error_codes: Vec) { + compile_fail: bool, allow_fail: bool, error_codes: Vec) { assert_eq!(LangString::parse(s), LangString { should_panic: should_panic, no_run: no_run, @@ -1128,25 +1131,31 @@ mod tests { compile_fail: compile_fail, error_codes: error_codes, original: s.to_owned(), + allow_fail: allow_fail, }) } + fn v() -> Vec { + Vec::new() + } + // marker | should_panic| no_run| ignore| rust | test_harness| compile_fail - // | error_codes - t("", false, false, false, true, false, false, Vec::new()); - t("rust", false, false, false, true, false, false, Vec::new()); - t("sh", false, false, false, false, false, false, Vec::new()); - t("ignore", false, false, true, true, false, false, Vec::new()); - t("should_panic", true, false, false, true, false, false, Vec::new()); - t("no_run", false, true, false, true, false, false, Vec::new()); - t("test_harness", false, false, false, true, true, false, Vec::new()); - t("compile_fail", false, true, false, true, false, true, Vec::new()); - t("{.no_run .example}", false, true, false, true, false, false, Vec::new()); - t("{.sh .should_panic}", true, false, false, false, false, false, Vec::new()); - t("{.example .rust}", false, false, false, true, false, false, Vec::new()); - t("{.test_harness .rust}", false, false, false, true, true, false, Vec::new()); - t("text, no_run", false, true, false, false, false, false, Vec::new()); - t("text,no_run", false, true, false, false, false, false, Vec::new()); + // | allow_fail | error_codes + t("", false, false, false, true, false, false, false, v()); + t("rust", false, false, false, true, false, false, false, v()); + t("sh", false, false, false, false, false, false, false, v()); + t("ignore", false, false, true, true, false, false, false, v()); + t("should_panic", true, false, false, true, false, false, false, v()); + t("no_run", false, true, false, true, false, false, false, v()); + t("test_harness", false, false, false, true, true, false, false, v()); + t("compile_fail", false, true, false, true, false, true, false, v()); + t("allow_fail", false, false, false, true, false, false, true, v()); + t("{.no_run .example}", false, true, false, true, false, false, false, v()); + t("{.sh .should_panic}", true, false, false, false, false, false, false, v()); + t("{.example .rust}", false, false, false, true, false, false, false, v()); + t("{.test_harness .rust}", false, false, false, true, true, false, false, v()); + t("text, no_run", false, true, false, false, false, false, false, v()); + t("text,no_run", false, true, false, false, false, false, false, v()); } #[test] diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index a588460d46..9b1d256304 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -262,6 +262,7 @@ pub struct Cache { stripped_mod: bool, deref_trait_did: Option, deref_mut_trait_did: Option, + owned_box_did: Option, // In rare case where a structure is defined in one module but implemented // in another, if the implementing module is parsed before defining module, @@ -280,6 +281,7 @@ pub struct RenderInfo { pub external_typarams: FxHashMap, pub deref_trait_did: Option, pub deref_mut_trait_did: Option, + pub owned_box_did: Option, } /// Helper struct to render all source code to HTML pages @@ -490,7 +492,7 @@ pub fn run(mut krate: clean::Crate, } } } - try_err!(mkdir(&dst), &dst); + try_err!(fs::create_dir_all(&dst), &dst); krate = render_sources(&dst, &mut scx, krate)?; let cx = Context { current: Vec::new(), @@ -507,6 +509,7 @@ pub fn run(mut krate: clean::Crate, external_typarams, deref_trait_did, deref_mut_trait_did, + owned_box_did, } = renderinfo; let external_paths = external_paths.into_iter() @@ -530,6 +533,7 @@ pub fn run(mut krate: clean::Crate, traits: mem::replace(&mut krate.external_traits, FxHashMap()), deref_trait_did: deref_trait_did, deref_mut_trait_did: deref_mut_trait_did, + owned_box_did: owned_box_did, typarams: external_typarams, }; @@ -654,7 +658,7 @@ fn write_shared(cx: &Context, // Write out the shared files. Note that these are shared among all rustdoc // docs placed in the output directory, so this needs to be a synchronized // operation with respect to all other rustdocs running around. - try_err!(mkdir(&cx.dst), &cx.dst); + try_err!(fs::create_dir_all(&cx.dst), &cx.dst); let _lock = flock::Lock::panicking_new(&cx.dst.join(".lock"), true, true, true); // Add all the static files. These may already exist, but we just @@ -804,10 +808,8 @@ fn write_shared(cx: &Context, fn render_sources(dst: &Path, scx: &mut SharedContext, krate: clean::Crate) -> Result { info!("emitting source files"); - let dst = dst.join("src"); - try_err!(mkdir(&dst), &dst); - let dst = dst.join(&krate.name); - try_err!(mkdir(&dst), &dst); + let dst = dst.join("src").join(&krate.name); + try_err!(fs::create_dir_all(&dst), &dst); let mut folder = SourceCollector { dst: dst, scx: scx, @@ -821,19 +823,6 @@ fn write(dst: PathBuf, contents: &[u8]) -> Result<(), Error> { Ok(try_err!(try_err!(File::create(&dst), &dst).write_all(contents), &dst)) } -/// Makes a directory on the filesystem, failing the thread if an error occurs -/// and skipping if the directory already exists. -/// -/// Note that this also handles races as rustdoc is likely to be run -/// concurrently against another invocation. -fn mkdir(path: &Path) -> io::Result<()> { - match fs::create_dir(path) { - Ok(()) => Ok(()), - Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => Ok(()), - Err(e) => Err(e) - } -} - /// Takes a path to a source file and cleans the path to it. This canonicalizes /// things like ".." to components which preserve the "top down" hierarchy of a /// static HTML tree. Each component in the cleaned path will be passed as an @@ -947,7 +936,7 @@ impl<'a> SourceCollector<'a> { let mut href = String::new(); clean_srcpath(&self.scx.src_root, &p, false, |component| { cur.push(component); - mkdir(&cur).unwrap(); + fs::create_dir_all(&cur).unwrap(); root_path.push_str("../"); href.push_str(component); href.push('/'); @@ -1345,7 +1334,7 @@ impl Context { // these modules are recursed into, but not rendered normally // (a flag on the context). if !self.render_redirect_pages { - self.render_redirect_pages = maybe_ignore_item(&item); + self.render_redirect_pages = item.is_stripped(); } if item.is_mod() { @@ -1428,7 +1417,7 @@ impl Context { // BTreeMap instead of HashMap to get a sorted output let mut map = BTreeMap::new(); for item in &m.items { - if maybe_ignore_item(item) { continue } + if item.is_stripped() { continue } let short = item.type_().css_class(); let myname = match item.name { @@ -1639,12 +1628,13 @@ fn plain_summary_line(s: Option<&str>) -> String { fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Result { document_stability(w, cx, item)?; - document_full(w, item, cx.render_type)?; + let prefix = render_assoc_const_value(item); + document_full(w, item, cx.render_type, &prefix)?; Ok(()) } fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLink, - render_type: RenderType) -> fmt::Result { + render_type: RenderType, prefix: &str) -> fmt::Result { if let Some(s) = item.doc_value() { let markdown = if s.contains('\n') { format!("{} [Read more]({})", @@ -1652,42 +1642,33 @@ fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLin } else { format!("{}", &plain_summary_line(Some(s))) }; - write!(w, "

{}
", - Markdown(&markdown, render_type))?; + write!(w, "
{}{}
", prefix, Markdown(&markdown, render_type))?; + } else if !prefix.is_empty() { + write!(w, "
{}
", prefix)?; } Ok(()) } -fn md_render_assoc_item(item: &clean::Item) -> String { +fn render_assoc_const_value(item: &clean::Item) -> String { match item.inner { - clean::AssociatedConstItem(ref ty, ref default) => { - if let Some(default) = default.as_ref() { - format!("```\n{}: {:#} = {}\n```\n\n", item.name.as_ref().unwrap(), ty, default) - } else { - format!("```\n{}: {:#}\n```\n\n", item.name.as_ref().unwrap(), ty) - } + clean::AssociatedConstItem(ref ty, Some(ref default)) => { + highlight::render_with_highlighting( + &format!("{}: {:#} = {}", item.name.as_ref().unwrap(), ty, default), + None, + None, + None, + ) } _ => String::new(), } } -fn get_doc_value(item: &clean::Item) -> Option<&str> { - let x = item.doc_value(); - if x.is_none() { - match item.inner { - clean::AssociatedConstItem(_, _) => Some(""), - _ => None, - } - } else { - x - } -} - fn document_full(w: &mut fmt::Formatter, item: &clean::Item, - render_type: RenderType) -> fmt::Result { - if let Some(s) = get_doc_value(item) { - write!(w, "
{}
", - Markdown(&format!("{}{}", md_render_assoc_item(item), s), render_type))?; + render_type: RenderType, prefix: &str) -> fmt::Result { + if let Some(s) = item.doc_value() { + write!(w, "
{}{}
", prefix, Markdown(s, render_type))?; + } else if !prefix.is_empty() { + write!(w, "
{}
", prefix)?; } Ok(()) } @@ -1729,7 +1710,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, if let clean::DefaultImplItem(..) = items[*i].inner { return false; } - !maybe_ignore_item(&items[*i]) + !items[*i].is_stripped() }).collect::>(); // the order of item types in the listing @@ -1898,17 +1879,6 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, Ok(()) } -fn maybe_ignore_item(it: &clean::Item) -> bool { - match it.inner { - clean::StrippedItem(..) => true, - clean::ModuleItem(ref m) => { - it.doc_value().is_none() && m.items.is_empty() - && it.visibility != Some(clean::Public) - }, - _ => false, - } -} - fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec { let mut stability = vec![]; @@ -2117,15 +2087,19 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, if !consts.is_empty() && !required.is_empty() { w.write_str("\n")?; } - for m in &required { + for (pos, m) in required.iter().enumerate() { write!(w, " ")?; render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait)?; write!(w, ";\n")?; + + if pos < required.len() - 1 { + write!(w, "
")?; + } } if !required.is_empty() && !provided.is_empty() { w.write_str("\n")?; } - for m in &provided { + for (pos, m) in provided.iter().enumerate() { write!(w, " ")?; render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait)?; match m.inner { @@ -2136,6 +2110,9 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, write!(w, " {{ ... }}\n")?; }, } + if pos < provided.len() - 1 { + write!(w, "
")?; + } } write!(w, "}}")?; } @@ -2933,17 +2910,18 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi }; if let Some(self_ty) = self_type_opt { - let by_mut_ref = match self_ty { - SelfTy::SelfBorrowed(_lifetime, mutability) => { - mutability == Mutability::Mutable - }, + let (by_mut_ref, by_box) = match self_ty { + SelfTy::SelfBorrowed(_, mutability) | SelfTy::SelfExplicit(clean::BorrowedRef { mutability, .. }) => { - mutability == Mutability::Mutable + (mutability == Mutability::Mutable, false) }, - _ => false, + SelfTy::SelfExplicit(clean::ResolvedPath { did, .. }) => { + (false, Some(did) == cache().owned_box_did) + }, + _ => (false, false), }; - deref_mut_ || !by_mut_ref + (deref_mut_ || !by_mut_ref) && !by_box } else { false } @@ -2981,14 +2959,6 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi assoc_const(w, item, ty, default.as_ref(), link.anchor(&id))?; write!(w, "\n")?; } - clean::ConstantItem(ref c) => { - let id = derive_id(format!("{}.{}", item_type, name)); - let ns_id = derive_id(format!("{}.{}", name, item_type.name_space())); - write!(w, "

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

\n")?; - } clean::AssociatedTypeItem(ref bounds, ref default) => { let id = derive_id(format!("{}.{}", item_type, name)); let ns_id = derive_id(format!("{}.{}", name, item_type.name_space())); @@ -3002,6 +2972,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi } if render_method_item || render_mode == RenderMode::Normal { + let prefix = render_assoc_const_value(item); if !is_default_item { if let Some(t) = trait_ { // The trait item may have been stripped so we might not @@ -3010,20 +2981,21 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi // We need the stability of the item from the trait // because impls can't have a stability. document_stability(w, cx, it)?; - if get_doc_value(item).is_some() { - document_full(w, item, cx.render_type)?; + if item.doc_value().is_some() { + document_full(w, item, cx.render_type, &prefix)?; } else { // In case the item isn't documented, // provide short documentation from the trait. - document_short(w, it, link, cx.render_type)?; + document_short(w, it, link, cx.render_type, &prefix)?; } } } else { - document(w, cx, item)?; + document_stability(w, cx, item)?; + document_full(w, item, cx.render_type, &prefix)?; } } else { document_stability(w, cx, item)?; - document_short(w, item, link, cx.render_type)?; + document_short(w, item, link, cx.render_type, &prefix)?; } } Ok(()) @@ -3077,7 +3049,13 @@ fn item_typedef(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, where_clause = WhereClause { gens: &t.generics, indent: 0, end_newline: true }, type_ = t.type_)?; - document(w, cx, it) + document(w, cx, it)?; + + // Render any items associated directly to this alias, as otherwise they + // won't be visible anywhere in the docs. It would be nice to also show + // associated items from the aliased type (see discussion in #32077), but + // we need #14072 to make sense of the generics. + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } impl<'a> fmt::Display for Sidebar<'a> { @@ -3087,7 +3065,7 @@ impl<'a> fmt::Display for Sidebar<'a> { let parentlen = cx.current.len() - if it.is_mod() {1} else {0}; if it.is_struct() || it.is_trait() || it.is_primitive() || it.is_union() - || it.is_enum() || it.is_mod() + || it.is_enum() || it.is_mod() || it.is_typedef() { write!(fmt, "

")?; match it.inner { @@ -3096,6 +3074,7 @@ impl<'a> fmt::Display for Sidebar<'a> { clean::PrimitiveItem(..) => write!(fmt, "Primitive Type ")?, clean::UnionItem(..) => write!(fmt, "Union ")?, clean::EnumItem(..) => write!(fmt, "Enum ")?, + clean::TypedefItem(..) => write!(fmt, "Type Definition ")?, clean::ModuleItem(..) => if it.is_crate() { write!(fmt, "Crate ")?; } else { @@ -3112,6 +3091,7 @@ impl<'a> fmt::Display for Sidebar<'a> { clean::PrimitiveItem(ref p) => sidebar_primitive(fmt, it, p)?, clean::UnionItem(ref u) => sidebar_union(fmt, it, u)?, clean::EnumItem(ref e) => sidebar_enum(fmt, it, e)?, + clean::TypedefItem(ref t, _) => sidebar_typedef(fmt, it, t)?, clean::ModuleItem(ref m) => sidebar_module(fmt, it, &m.items)?, _ => (), } @@ -3254,6 +3234,16 @@ fn sidebar_primitive(fmt: &mut fmt::Formatter, it: &clean::Item, Ok(()) } +fn sidebar_typedef(fmt: &mut fmt::Formatter, it: &clean::Item, + _t: &clean::Typedef) -> fmt::Result { + let sidebar = sidebar_assoc_items(it); + + if !sidebar.is_empty() { + write!(fmt, "

    {}
", sidebar)?; + } + Ok(()) +} + fn sidebar_union(fmt: &mut fmt::Formatter, it: &clean::Item, u: &clean::Union) -> fmt::Result { let mut sidebar = String::new(); @@ -3309,7 +3299,7 @@ fn sidebar_module(fmt: &mut fmt::Formatter, _it: &clean::Item, if let clean::DefaultImplItem(..) = it.inner { false } else { - !maybe_ignore_item(it) && !it.is_stripped() && it.type_() == myty + !it.is_stripped() && it.type_() == myty } }) { let (short, name) = match myty { diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 53e341226a..788cd80b07 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -1,12 +1,14 @@ -// 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. +/*! + * 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. + */ /*jslint browser: true, es5: true */ /*globals $: true, rootPath: true */ @@ -1231,21 +1233,24 @@ onEach(e.getElementsByClassName('associatedconstant'), func); }); - var span = document.createElement('span'); - span.className = 'toggle-label'; - span.style.display = 'none'; - span.innerHTML = ' Expand description'; + function createToggle() { + var span = document.createElement('span'); + span.className = 'toggle-label'; + span.style.display = 'none'; + span.innerHTML = ' Expand description'; - var mainToggle = toggle.cloneNode(true); - mainToggle.appendChild(span); + var mainToggle = toggle.cloneNode(true); + mainToggle.appendChild(span); - var wrapper = document.createElement('div'); - wrapper.className = 'toggle-wrapper'; - wrapper.appendChild(mainToggle); + var wrapper = document.createElement('div'); + wrapper.className = 'toggle-wrapper'; + wrapper.appendChild(mainToggle); + return wrapper; + } onEach(document.getElementById('main').getElementsByClassName('docblock'), function(e) { if (e.parentNode.id === "main") { - e.parentNode.insertBefore(wrapper, e); + e.parentNode.insertBefore(createToggle(), e); } }); @@ -1271,18 +1276,22 @@ } }) - var span = document.createElement('span'); - span.className = 'toggle-label'; - span.style.display = 'none'; - span.innerHTML = ' Expand attributes'; - toggle.appendChild(span); + function createToggleWrapper() { + var span = document.createElement('span'); + span.className = 'toggle-label'; + span.style.display = 'none'; + span.innerHTML = ' Expand attributes'; + toggle.appendChild(span); + + var wrapper = document.createElement('div'); + wrapper.className = 'toggle-wrapper toggle-attributes'; + wrapper.appendChild(toggle); + return wrapper; + } - var wrapper = document.createElement('div'); - wrapper.className = 'toggle-wrapper toggle-attributes'; - wrapper.appendChild(toggle); onEach(document.getElementById('main').getElementsByTagName('pre'), function(e) { onEach(e.getElementsByClassName('attributes'), function(i_e) { - i_e.parentNode.insertBefore(wrapper, i_e); + i_e.parentNode.insertBefore(createToggleWrapper(), i_e); collapseDocs(i_e.previousSibling.childNodes[0]); }); }); diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 969cc4eeda..567c8fb971 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -658,6 +658,11 @@ h3 > .collapse-toggle, h4 > .collapse-toggle { padding-left: 10px; } +.item-spacer { + width: 100%; + height: 12px; +} + span.since { position: initial; font-size: 20px; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 380ee9c06a..6c092d01a0 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -26,10 +26,6 @@ #![feature(unicode)] #![feature(vec_remove_item)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] - extern crate arena; extern crate getopts; extern crate env_logger; @@ -120,94 +116,149 @@ fn get_args() -> Option> { .collect() } -fn stable(g: getopts::OptGroup) -> RustcOptGroup { RustcOptGroup::stable(g) } -fn unstable(g: getopts::OptGroup) -> RustcOptGroup { RustcOptGroup::unstable(g) } +fn stable(name: &'static str, f: F) -> RustcOptGroup + where F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static +{ + RustcOptGroup::stable(name, f) +} + +fn unstable(name: &'static str, f: F) -> RustcOptGroup + where F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static +{ + RustcOptGroup::unstable(name, f) +} pub fn opts() -> Vec { - use getopts::*; vec![ - stable(optflag("h", "help", "show this help message")), - stable(optflag("V", "version", "print rustdoc's version")), - stable(optflag("v", "verbose", "use verbose output")), - stable(optopt("r", "input-format", "the input type of the specified file", - "[rust]")), - stable(optopt("w", "output-format", "the output type to write", - "[html]")), - stable(optopt("o", "output", "where to place the output", "PATH")), - stable(optopt("", "crate-name", "specify the name of this crate", "NAME")), - stable(optmulti("L", "library-path", "directory to add to crate search path", - "DIR")), - stable(optmulti("", "cfg", "pass a --cfg to rustc", "")), - stable(optmulti("", "extern", "pass an --extern to rustc", "NAME=PATH")), - stable(optmulti("", "plugin-path", "directory to load plugins from", "DIR")), - stable(optmulti("", "passes", - "list of passes to also run, you might want \ - to pass it multiple times; a value of `list` \ - will print available passes", - "PASSES")), - stable(optmulti("", "plugins", "space separated list of plugins to also load", - "PLUGINS")), - stable(optflag("", "no-defaults", "don't run the default passes")), - stable(optflag("", "test", "run code examples as tests")), - stable(optmulti("", "test-args", "arguments to pass to the test runner", - "ARGS")), - stable(optopt("", "target", "target triple to document", "TRIPLE")), - stable(optmulti("", "markdown-css", - "CSS files to include via in a rendered Markdown file", - "FILES")), - stable(optmulti("", "html-in-header", - "files to include inline in the section of a rendered Markdown file \ - or generated documentation", - "FILES")), - stable(optmulti("", "html-before-content", - "files to include inline between and the content of a rendered \ - Markdown file or generated documentation", - "FILES")), - stable(optmulti("", "html-after-content", - "files to include inline between the content and of a rendered \ - Markdown file or generated documentation", - "FILES")), - unstable(optmulti("", "markdown-before-content", - "files to include inline between and the content of a rendered \ - Markdown file or generated documentation", - "FILES")), - unstable(optmulti("", "markdown-after-content", - "files to include inline between the content and of a rendered \ - Markdown file or generated documentation", - "FILES")), - stable(optopt("", "markdown-playground-url", - "URL to send code snippets to", "URL")), - stable(optflag("", "markdown-no-toc", "don't include table of contents")), - stable(optopt("e", "extend-css", - "To add some CSS rules with a given file to generate doc with your \ - own theme. However, your theme might break if the rustdoc's generated HTML \ - changes, so be careful!", "PATH")), - unstable(optmulti("Z", "", - "internal and debugging options (only on nightly build)", "FLAG")), - stable(optopt("", "sysroot", "Override the system root", "PATH")), - unstable(optopt("", "playground-url", - "URL to send code snippets to, may be reset by --markdown-playground-url \ - or `#![doc(html_playground_url=...)]`", - "URL")), - unstable(optflag("", "enable-commonmark", "to enable commonmark doc rendering/testing")), - unstable(optflag("", "display-warnings", "to print code warnings when testing doc")), + stable("h", |o| o.optflag("h", "help", "show this help message")), + stable("V", |o| o.optflag("V", "version", "print rustdoc's version")), + stable("v", |o| o.optflag("v", "verbose", "use verbose output")), + stable("r", |o| { + o.optopt("r", "input-format", "the input type of the specified file", + "[rust]") + }), + stable("w", |o| { + o.optopt("w", "output-format", "the output type to write", "[html]") + }), + stable("o", |o| o.optopt("o", "output", "where to place the output", "PATH")), + stable("crate-name", |o| { + o.optopt("", "crate-name", "specify the name of this crate", "NAME") + }), + stable("L", |o| { + o.optmulti("L", "library-path", "directory to add to crate search path", + "DIR") + }), + stable("cfg", |o| o.optmulti("", "cfg", "pass a --cfg to rustc", "")), + stable("extern", |o| { + o.optmulti("", "extern", "pass an --extern to rustc", "NAME=PATH") + }), + stable("plugin-path", |o| { + o.optmulti("", "plugin-path", "directory to load plugins from", "DIR") + }), + stable("passes", |o| { + o.optmulti("", "passes", + "list of passes to also run, you might want \ + to pass it multiple times; a value of `list` \ + will print available passes", + "PASSES") + }), + stable("plugins", |o| { + o.optmulti("", "plugins", "space separated list of plugins to also load", + "PLUGINS") + }), + stable("no-default", |o| { + o.optflag("", "no-defaults", "don't run the default passes") + }), + stable("test", |o| o.optflag("", "test", "run code examples as tests")), + stable("test-args", |o| { + o.optmulti("", "test-args", "arguments to pass to the test runner", + "ARGS") + }), + stable("target", |o| o.optopt("", "target", "target triple to document", "TRIPLE")), + stable("markdown-css", |o| { + o.optmulti("", "markdown-css", + "CSS files to include via in a rendered Markdown file", + "FILES") + }), + stable("html-in-header", |o| { + o.optmulti("", "html-in-header", + "files to include inline in the section of a rendered Markdown file \ + or generated documentation", + "FILES") + }), + stable("html-before-content", |o| { + o.optmulti("", "html-before-content", + "files to include inline between and the content of a rendered \ + Markdown file or generated documentation", + "FILES") + }), + stable("html-after-content", |o| { + o.optmulti("", "html-after-content", + "files to include inline between the content and of a rendered \ + Markdown file or generated documentation", + "FILES") + }), + unstable("markdown-before-content", |o| { + o.optmulti("", "markdown-before-content", + "files to include inline between and the content of a rendered \ + Markdown file or generated documentation", + "FILES") + }), + unstable("markdown-after-content", |o| { + o.optmulti("", "markdown-after-content", + "files to include inline between the content and of a rendered \ + Markdown file or generated documentation", + "FILES") + }), + stable("markdown-playground-url", |o| { + o.optopt("", "markdown-playground-url", + "URL to send code snippets to", "URL") + }), + stable("markdown-no-toc", |o| { + o.optflag("", "markdown-no-toc", "don't include table of contents") + }), + stable("e", |o| { + o.optopt("e", "extend-css", + "To add some CSS rules with a given file to generate doc with your \ + own theme. However, your theme might break if the rustdoc's generated HTML \ + changes, so be careful!", "PATH") + }), + unstable("Z", |o| { + o.optmulti("Z", "", + "internal and debugging options (only on nightly build)", "FLAG") + }), + stable("sysroot", |o| { + o.optopt("", "sysroot", "Override the system root", "PATH") + }), + unstable("playground-url", |o| { + o.optopt("", "playground-url", + "URL to send code snippets to, may be reset by --markdown-playground-url \ + or `#![doc(html_playground_url=...)]`", + "URL") + }), + unstable("enable-commonmark", |o| { + o.optflag("", "enable-commonmark", "to enable commonmark doc rendering/testing") + }), + unstable("display-warnings", |o| { + o.optflag("", "display-warnings", "to print code warnings when testing doc") + }), ] } pub fn usage(argv0: &str) { - println!("{}", - getopts::usage(&format!("{} [options] ", argv0), - &opts().into_iter() - .map(|x| x.opt_group) - .collect::>())); + let mut options = getopts::Options::new(); + for option in opts() { + (option.apply)(&mut options); + } + println!("{}", options.usage(&format!("{} [options] ", argv0))); } pub fn main_args(args: &[String]) -> isize { - let all_groups: Vec = opts() - .into_iter() - .map(|x| x.opt_group) - .collect(); - let matches = match getopts::getopts(&args[1..], &all_groups) { + let mut options = getopts::Options::new(); + for option in opts() { + (option.apply)(&mut options); + } + let matches = match options.parse(&args[1..]) { Ok(m) => m, Err(err) => { print_error(err); @@ -414,13 +465,17 @@ where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R { info!("starting to run rustc"); let display_warnings = matches.opt_present("display-warnings"); + let force_unstable_if_unmarked = matches.opt_strs("Z").iter().any(|x| { + *x == "force-unstable-if-unmarked" + }); + let (tx, rx) = channel(); rustc_driver::monitor(move || { use rustc::session::config::Input; let (mut krate, renderinfo) = core::run_core(paths, cfgs, externs, Input::File(cr), triple, maybe_sysroot, - display_warnings); + display_warnings, force_unstable_if_unmarked); info!("finished with rustc"); diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 1cc4f9371c..41fd9efe61 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -83,7 +83,8 @@ impl<'a> fold::DocFolder for Stripper<'a> { clean::TraitItem(..) | clean::FunctionItem(..) | clean::VariantItem(..) | clean::MethodItem(..) | clean::ForeignFunctionItem(..) | clean::ForeignStaticItem(..) | - clean::ConstantItem(..) | clean::UnionItem(..) => { + clean::ConstantItem(..) | clean::UnionItem(..) | + clean::AssociatedConstItem(..) => { if i.def_id.is_local() { if !self.access_levels.is_exported(i.def_id) { return None; @@ -117,8 +118,7 @@ impl<'a> fold::DocFolder for Stripper<'a> { // Primitives are never stripped clean::PrimitiveItem(..) => {} - // Associated consts and types are never stripped - clean::AssociatedConstItem(..) | + // Associated types are never stripped clean::AssociatedTypeItem(..) => {} } @@ -145,20 +145,12 @@ impl<'a> fold::DocFolder for Stripper<'a> { self.fold_item_recur(i) }; - i.and_then(|i| { - match i.inner { - // emptied modules have no need to exist - clean::ModuleItem(ref m) - if m.items.is_empty() && - i.doc_value().is_none() => None, - _ => { - if self.update_retained { - self.retained.insert(i.def_id); - } - Some(i) - } + if let Some(ref i) = i { + if self.update_retained { + self.retained.insert(i.def_id); } - }) + } + i } } diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index cfe2fad0fa..247789726f 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -25,7 +25,7 @@ use rustc_lint; use rustc::dep_graph::DepGraph; use rustc::hir; use rustc::hir::intravisit; -use rustc::session::{self, config}; +use rustc::session::{self, CompileIncomplete, config}; use rustc::session::config::{OutputType, OutputTypes, Externs}; use rustc::session::search_paths::{SearchPaths, PathKind}; use rustc_back::dynamic_lib::DynamicLibrary; @@ -167,16 +167,16 @@ fn scrape_test_config(krate: &::rustc::hir::Crate) -> TestOptions { opts } -fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, - externs: Externs, - should_panic: bool, no_run: bool, as_test_harness: bool, - compile_fail: bool, mut error_codes: Vec, opts: &TestOptions, - maybe_sysroot: Option) { +fn run_test(test: &str, cratename: &str, filename: &str, cfgs: Vec, libs: SearchPaths, + externs: Externs, + should_panic: bool, no_run: bool, as_test_harness: bool, + compile_fail: bool, mut error_codes: Vec, opts: &TestOptions, + maybe_sysroot: Option) { // the test harness wants its own `main` & top level functions, so // never wrap the test in `fn main() { ... }` - let test = maketest(test, Some(cratename), as_test_harness, opts); + let test = make_test(test, Some(cratename), as_test_harness, opts); let input = config::Input::Str { - name: driver::anon_src(), + name: filename.to_owned(), input: test.to_owned(), }; let outputs = OutputTypes::new(&[(OutputType::Exe, None)]); @@ -253,35 +253,25 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, driver::compile_input(&sess, &cstore, &input, &out, &None, None, &control) })); - match res { - Ok(r) => { - match r { - Err(count) => { - if count > 0 && !compile_fail { - sess.fatal("aborting due to previous error(s)") - } else if count == 0 && compile_fail { - panic!("test compiled while it wasn't supposed to") - } - if count > 0 && error_codes.len() > 0 { - let out = String::from_utf8(data.lock().unwrap().to_vec()).unwrap(); - error_codes.retain(|err| !out.contains(err)); - } - } - Ok(()) if compile_fail => { - panic!("test compiled while it wasn't supposed to") - } - _ => {} - } + let compile_result = match res { + Ok(Ok(())) | Ok(Err(CompileIncomplete::Stopped)) => Ok(()), + Err(_) | Ok(Err(CompileIncomplete::Errored(_))) => Err(()) + }; + + match (compile_result, compile_fail) { + (Ok(()), true) => { + panic!("test compiled while it wasn't supposed to") } - Err(_) => { - if !compile_fail { - panic!("couldn't compile the test"); - } + (Ok(()), false) => {} + (Err(()), true) => { if error_codes.len() > 0 { let out = String::from_utf8(data.lock().unwrap().to_vec()).unwrap(); error_codes.retain(|err| !out.contains(err)); } } + (Err(()), false) => { + panic!("couldn't compile the test") + } } if error_codes.len() > 0 { @@ -323,8 +313,11 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, } } -pub fn maketest(s: &str, cratename: Option<&str>, dont_insert_main: bool, - opts: &TestOptions) -> String { +pub fn make_test(s: &str, + cratename: Option<&str>, + dont_insert_main: bool, + opts: &TestOptions) + -> String { let (crate_attrs, everything_else) = partition_source(s); let mut prog = String::new(); @@ -467,7 +460,7 @@ impl Collector { pub fn add_test(&mut self, test: String, should_panic: bool, no_run: bool, should_ignore: bool, as_test_harness: bool, compile_fail: bool, error_codes: Vec, - line: usize, filename: String) { + line: usize, filename: String, allow_fail: bool) { let name = self.generate_name(line, &filename); // to be removed when hoedown is removed if self.render_type == RenderType::Pulldown { @@ -499,6 +492,7 @@ impl Collector { ignore: should_ignore, // compiler failures are test failures should_panic: testing::ShouldPanic::No, + allow_fail: allow_fail, }, testfn: testing::DynTestFn(box move |()| { let panic = io::set_panic(None); @@ -507,18 +501,19 @@ impl Collector { rustc_driver::in_rustc_thread(move || { io::set_panic(panic); io::set_print(print); - runtest(&test, - &cratename, - cfgs, - libs, - externs, - should_panic, - no_run, - as_test_harness, - compile_fail, - error_codes, - &opts, - maybe_sysroot) + run_test(&test, + &cratename, + &filename, + cfgs, + libs, + externs, + should_panic, + no_run, + as_test_harness, + compile_fail, + error_codes, + &opts, + maybe_sysroot) }) } { Ok(()) => (), diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 39ebe490d0..657aab958b 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -329,25 +329,21 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { if !self.view_item_stack.insert(def_node_id) { return false } let ret = match tcx.hir.get(def_node_id) { - hir_map::NodeItem(it) => { + hir_map::NodeItem(&hir::Item { node: hir::ItemMod(ref m), .. }) if glob => { let prev = mem::replace(&mut self.inlining, true); - if glob { - match it.node { - hir::ItemMod(ref m) => { - for i in &m.item_ids { - let i = self.cx.tcx.hir.expect_item(i.id); - self.visit_item(i, None, om); - } - } - hir::ItemEnum(..) => {} - _ => { panic!("glob not mapped to a module or enum"); } - } - } else { - self.visit_item(it, renamed, om); + for i in &m.item_ids { + let i = self.cx.tcx.hir.expect_item(i.id); + self.visit_item(i, None, om); } self.inlining = prev; true } + hir_map::NodeItem(it) if !glob => { + let prev = mem::replace(&mut self.inlining, true); + self.visit_item(it, renamed, om); + self.inlining = prev; + true + } _ => false, }; self.view_item_stack.remove(&def_node_id); diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index 40a6ffe950..5518d85434 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -70,7 +70,7 @@ impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> { return; } - for item in self.cstore.item_children(def_id) { + for item in self.cstore.item_children(def_id, self.cx.tcx.sess) { self.visit_item(item.def); } } diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs index 05cfb6352f..1a99527693 100644 --- a/src/libserialize/collection_impls.rs +++ b/src/libserialize/collection_impls.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Implementations of serialization for structures found in libcollections +//! Implementations of serialization for structures found in liballoc use std::hash::{Hash, BuildHasher}; diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 07417565e3..dae0b5f012 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -36,7 +36,7 @@ //! Arrays are enclosed in square brackets ([ ... ]) and objects in curly brackets ({ ... }). //! A simple JSON document encoding a person, their age, address and phone numbers could look like //! -//! ```ignore +//! ```json //! { //! "FirstName": "John", //! "LastName": "Doe", diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 4eb2cad5c9..c3107d1f19 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -15,9 +15,6 @@ Core encoding and decoding interfaces. */ #![crate_name = "serialize"] -#![cfg_attr(stage0, unstable(feature = "rustc_private", - reason = "deprecated in favor of rustc-serialize on crates.io", - issue = "27812"))] #![crate_type = "rlib"] #![crate_type = "dylib"] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", @@ -28,15 +25,11 @@ Core encoding and decoding interfaces. #![deny(warnings)] #![feature(box_syntax)] -#![feature(collections)] #![feature(core_intrinsics)] #![feature(i128_type)] #![feature(specialization)] -#![cfg_attr(stage0, feature(staged_api))] #![cfg_attr(test, feature(test))] -extern crate collections; - pub use self::serialize::{Decoder, Encoder, Decodable, Encodable}; pub use self::serialize::{SpecializationError, SpecializedEncoder, SpecializedDecoder}; diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index e17918506f..09c1681693 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -19,7 +19,8 @@ collections = { path = "../libcollections" } core = { path = "../libcore" } libc = { path = "../rustc/libc_shim" } rand = { path = "../librand" } -compiler_builtins = { path = "../libcompiler_builtins" } +compiler_builtins = { path = "../rustc/compiler_builtins_shim" } +profiler_builtins = { path = "../libprofiler_builtins", optional = true } std_unicode = { path = "../libstd_unicode" } unwind = { path = "../libunwind" } @@ -43,3 +44,4 @@ debug-jemalloc = ["alloc_jemalloc/debug"] jemalloc = ["alloc_jemalloc"] force_alloc_system = [] panic-unwind = ["panic_unwind"] +profiler = ["profiler_builtins"] diff --git a/src/libstd/build.rs b/src/libstd/build.rs index f84662c3f8..2abd47ab8d 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -41,6 +41,10 @@ fn main() { } else if target.contains("dragonfly") || target.contains("bitrig") || target.contains("netbsd") || target.contains("openbsd") { println!("cargo:rustc-link-lib=pthread"); + } else if target.contains("solaris") { + println!("cargo:rustc-link-lib=socket"); + println!("cargo:rustc-link-lib=posix4"); + println!("cargo:rustc-link-lib=pthread"); } else if target.contains("apple-darwin") { println!("cargo:rustc-link-lib=System"); diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 8c4cbb66b4..746e18047f 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -754,6 +754,8 @@ impl HashMap /// 1) Ensure `new_raw_cap` is enough for all the elements, accounting /// for the load factor. /// 2) Ensure `new_raw_cap` is a power of two or zero. + #[inline(never)] + #[cold] fn resize(&mut self, new_raw_cap: usize) { assert!(self.table.size() <= new_raw_cap); assert!(new_raw_cap.is_power_of_two() || new_raw_cap == 0); @@ -1407,7 +1409,7 @@ impl<'a, K, V> Clone for Keys<'a, K, V> { } #[stable(feature = "std_debug", since = "1.16.0")] -impl<'a, K: Debug, V: Debug> fmt::Debug for Keys<'a, K, V> { +impl<'a, K: Debug, V> fmt::Debug for Keys<'a, K, V> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() .entries(self.clone()) @@ -1436,7 +1438,7 @@ impl<'a, K, V> Clone for Values<'a, K, V> { } #[stable(feature = "std_debug", since = "1.16.0")] -impl<'a, K: Debug, V: Debug> fmt::Debug for Values<'a, K, V> { +impl<'a, K, V: Debug> fmt::Debug for Values<'a, K, V> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() .entries(self.clone()) @@ -2384,7 +2386,7 @@ impl BuildHasher for RandomState { /// [`Hasher`]: ../../hash/trait.Hasher.html #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] #[allow(deprecated)] -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct DefaultHasher(SipHasher13); impl DefaultHasher { diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 50c721db84..06f4f7643e 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use alloc::heap::{allocate, deallocate}; +use alloc::heap::{Heap, Alloc, Layout}; use cmp; use hash::{BuildHasher, Hash, Hasher}; @@ -781,10 +781,8 @@ impl RawTable { .expect("capacity overflow"), "capacity overflow"); - let buffer = allocate(size, alignment); - if buffer.is_null() { - ::alloc::oom() - } + let buffer = Heap.alloc(Layout::from_size_align(size, alignment).unwrap()) + .unwrap_or_else(|e| Heap.oom(e)); let hashes = buffer.offset(hash_offset as isize) as *mut HashUint; @@ -1193,7 +1191,8 @@ unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable { debug_assert!(!oflo, "should be impossible"); unsafe { - deallocate(self.hashes.ptr() as *mut u8, size, align); + Heap.dealloc(self.hashes.ptr() as *mut u8, + Layout::from_size_align(size, align).unwrap()); // Remember how everything was allocated out of one buffer // during initialization? We only need one call to free here. } diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index 506bf71733..b8a6a66eaa 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -420,15 +420,15 @@ #![stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::Bound; +pub use alloc::Bound; #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::{BinaryHeap, BTreeMap, BTreeSet}; +pub use alloc::{BinaryHeap, BTreeMap, BTreeSet}; #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::{LinkedList, VecDeque}; +pub use alloc::{LinkedList, VecDeque}; #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::{binary_heap, btree_map, btree_set}; +pub use alloc::{binary_heap, btree_map, btree_set}; #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::{linked_list, vec_deque}; +pub use alloc::{linked_list, vec_deque}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::hash_map::HashMap; @@ -436,7 +436,7 @@ pub use self::hash_map::HashMap; pub use self::hash_set::HashSet; #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::range; +pub use alloc::range; mod hash; diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 27b40793ff..f81adad3eb 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -367,7 +367,7 @@ fn _remove_var(k: &OsStr) { /// An iterator that splits an environment variable into paths according to /// platform-specific conventions. /// -/// This structure is created by the [`std::env::split_paths`] function See its +/// This structure is created by the [`std::env::split_paths`] function. See its /// documentation for more. /// /// [`std::env::split_paths`]: fn.split_paths.html @@ -438,6 +438,35 @@ pub struct JoinPathsError { /// /// # Examples /// +/// Joining paths on a Unix-like platform: +/// +/// ``` +/// # if cfg!(unix) { +/// use std::env; +/// use std::ffi::OsString; +/// use std::path::Path; +/// +/// let paths = [Path::new("/bin"), Path::new("/usr/bin")]; +/// let path_os_string = env::join_paths(paths.iter()).unwrap(); +/// assert_eq!(path_os_string, OsString::from("/bin:/usr/bin")); +/// # } +/// ``` +/// +/// Joining a path containing a colon on a Unix-like platform results in an error: +/// +/// ``` +/// # if cfg!(unix) { +/// use std::env; +/// use std::path::Path; +/// +/// let paths = [Path::new("/bin"), Path::new("/usr/bi:n")]; +/// assert!(env::join_paths(paths.iter()).is_err()); +/// # } +/// ``` +/// +/// Using `env::join_paths` with `env::spit_paths` to append an item to the `PATH` environment +/// variable: +/// /// ``` /// use std::env; /// use std::path::PathBuf; @@ -605,14 +634,15 @@ pub fn current_exe() -> io::Result { os_imp::current_exe() } -/// An iterator over the arguments of a process, yielding a [`String`] value -/// for each argument. +/// An iterator over the arguments of a process, yielding a [`String`] value for +/// each argument. /// -/// This structure is created through the [`std::env::args`] function. +/// This struct is created by the [`std::env::args`] function. See its +/// documentation for more. /// /// The first element is traditionally the path of the executable, but it can be -/// set to arbitrary text, and may not even exist. This means this property should -/// not be relied upon for security purposes. +/// set to arbitrary text, and may not even exist. This means this property +/// should not be relied upon for security purposes. /// /// [`String`]: ../string/struct.String.html /// [`std::env::args`]: ./fn.args.html @@ -622,11 +652,12 @@ pub struct Args { inner: ArgsOs } /// An iterator over the arguments of a process, yielding an [`OsString`] value /// for each argument. /// -/// This structure is created through the [`std::env::args_os`] function. +/// This struct is created by the [`std::env::args_os`] function. See its +/// documentation for more. /// /// The first element is traditionally the path of the executable, but it can be -/// set to arbitrary text, and may not even exist. This means this property should -/// not be relied upon for security purposes. +/// set to arbitrary text, and may not even exist. This means this property +/// should not be relied upon for security purposes. /// /// [`OsString`]: ../ffi/struct.OsString.html /// [`std::env::args_os`]: ./fn.args_os.html @@ -710,7 +741,9 @@ impl DoubleEndedIterator for Args { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Args { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad("Args { .. }") + f.debug_struct("Args") + .field("inner", &self.inner.inner.inner_debug()) + .finish() } } @@ -735,7 +768,9 @@ impl DoubleEndedIterator for ArgsOs { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for ArgsOs { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad("ArgsOs { .. }") + f.debug_struct("ArgsOs") + .field("inner", &self.inner.inner_debug()) + .finish() } } @@ -914,63 +949,9 @@ mod arch { mod tests { use super::*; - use iter::repeat; - use rand::{self, Rng}; - use ffi::{OsString, OsStr}; + use ffi::OsStr; use path::{Path, PathBuf}; - fn make_rand_name() -> OsString { - let mut rng = rand::thread_rng(); - let n = format!("TEST{}", rng.gen_ascii_chars().take(10) - .collect::()); - let n = OsString::from(n); - assert!(var_os(&n).is_none()); - n - } - - fn eq(a: Option, b: Option<&str>) { - assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s)); - } - - #[test] - fn test_set_var() { - let n = make_rand_name(); - set_var(&n, "VALUE"); - eq(var_os(&n), Some("VALUE")); - } - - #[test] - fn test_remove_var() { - let n = make_rand_name(); - set_var(&n, "VALUE"); - remove_var(&n); - eq(var_os(&n), None); - } - - #[test] - fn test_set_var_overwrite() { - let n = make_rand_name(); - set_var(&n, "1"); - set_var(&n, "2"); - eq(var_os(&n), Some("2")); - set_var(&n, ""); - eq(var_os(&n), Some("")); - } - - #[test] - #[cfg_attr(target_os = "emscripten", ignore)] - fn test_var_big() { - let mut s = "".to_string(); - let mut i = 0; - while i < 100 { - s.push_str("aaaaaaaaaa"); - i += 1; - } - let n = make_rand_name(); - set_var(&n, &s); - eq(var_os(&n), Some(&s)); - } - #[test] #[cfg_attr(target_os = "emscripten", ignore)] fn test_self_exe_path() { @@ -982,32 +963,6 @@ mod tests { assert!(path.is_absolute()); } - #[test] - #[cfg_attr(target_os = "emscripten", ignore)] - fn test_env_set_get_huge() { - let n = make_rand_name(); - let s = repeat("x").take(10000).collect::(); - set_var(&n, &s); - eq(var_os(&n), Some(&s)); - remove_var(&n); - eq(var_os(&n), None); - } - - #[test] - fn test_env_set_var() { - let n = make_rand_name(); - - let mut e = vars_os(); - set_var(&n, "VALUE"); - assert!(!e.any(|(k, v)| { - &*k == &*n && &*v == "VALUE" - })); - - assert!(vars_os().any(|(k, v)| { - &*k == &*n && &*v == "VALUE" - })); - } - #[test] fn test() { assert!((!Path::new("test-path").is_absolute())); @@ -1083,4 +1038,14 @@ mod tests { r#""c:\te;st";c:\"#)); assert!(join_paths([r#"c:\te"st"#].iter().cloned()).is_err()); } + + #[test] + fn args_debug() { + assert_eq!( + format!("Args {{ inner: {:?} }}", args().collect::>()), + format!("{:?}", args())); + assert_eq!( + format!("ArgsOs {{ inner: {:?} }}", args_os().collect::>()), + format!("{:?}", args_os())); } +} diff --git a/src/libstd/error.rs b/src/libstd/error.rs index f56e3a5d78..d1c2bfb96b 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -51,6 +51,7 @@ // coherence challenge (e.g., specialization, neg impls, etc) we can // reconsider what crate these items belong in. +use alloc::allocator; use any::TypeId; use cell; use char; @@ -221,6 +222,24 @@ impl Error for ! { fn description(&self) -> &str { *self } } +#[unstable(feature = "allocator_api", + reason = "the precise API and guarantees it provides may be tweaked.", + issue = "32838")] +impl Error for allocator::AllocErr { + fn description(&self) -> &str { + allocator::AllocErr::description(self) + } +} + +#[unstable(feature = "allocator_api", + reason = "the precise API and guarantees it provides may be tweaked.", + issue = "32838")] +impl Error for allocator::CannotReallocInPlace { + fn description(&self) -> &str { + allocator::CannotReallocInPlace::description(self) + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Error for str::ParseBoolError { fn description(&self) -> &str { "failed to parse bool" } @@ -321,6 +340,14 @@ impl Error for char::CharTryFromError { } } +#[stable(feature = "char_from_str", since = "1.20.0")] +impl Error for char::ParseCharError { + fn description(&self) -> &str { + self.__description() + } +} + + // copied from any.rs impl Error + 'static { /// Returns true if the boxed type is the same as `T` diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index 4abad7e24f..0135cd0a58 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -46,8 +46,6 @@ mod cmath { pub fn erfcf(n: c_float) -> c_float; pub fn expm1f(n: c_float) -> c_float; pub fn fdimf(a: c_float, b: c_float) -> c_float; - pub fn fmaxf(a: c_float, b: c_float) -> c_float; - pub fn fminf(a: c_float, b: c_float) -> c_float; pub fn fmodf(a: c_float, b: c_float) -> c_float; pub fn ilogbf(n: c_float) -> c_int; pub fn logbf(n: c_float) -> c_float; @@ -365,39 +363,29 @@ impl f32 { #[inline] pub fn signum(self) -> f32 { num::Float::signum(self) } - /// Returns `true` if `self`'s sign bit is positive, including - /// `+0.0` and `INFINITY`. + /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with + /// positive sign bit and positive infinity. /// /// ``` - /// use std::f32; - /// - /// let nan = f32::NAN; /// let f = 7.0_f32; /// let g = -7.0_f32; /// /// assert!(f.is_sign_positive()); /// assert!(!g.is_sign_positive()); - /// // Requires both tests to determine if is `NaN` - /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn is_sign_positive(self) -> bool { num::Float::is_sign_positive(self) } - /// Returns `true` if `self`'s sign is negative, including `-0.0` - /// and `NEG_INFINITY`. + /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with + /// negative sign bit and negative infinity. /// /// ``` - /// use std::f32; - /// - /// let nan = f32::NAN; /// let f = 7.0f32; /// let g = -7.0f32; /// /// assert!(!f.is_sign_negative()); /// assert!(g.is_sign_negative()); - /// // Requires both tests to determine if is `NaN`. - /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -673,7 +661,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn max(self, other: f32) -> f32 { - unsafe { cmath::fmaxf(self, other) } + num::Float::max(self, other) } /// Returns the minimum of the two numbers. @@ -689,7 +677,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn min(self, other: f32) -> f32 { - unsafe { cmath::fminf(self, other) } + num::Float::min(self, other) } /// The positive difference of two numbers. @@ -1102,12 +1090,11 @@ impl f32 { /// # Examples /// /// ``` - /// #![feature(float_bits_conv)] /// assert_ne!((1f32).to_bits(), 1f32 as u32); // to_bits() is not casting! /// assert_eq!((12.5f32).to_bits(), 0x41480000); /// /// ``` - #[unstable(feature = "float_bits_conv", reason = "recently added", issue = "40470")] + #[stable(feature = "float_bits_conv", since = "1.20.0")] #[inline] pub fn to_bits(self) -> u32 { unsafe { ::mem::transmute(self) } @@ -1130,7 +1117,6 @@ impl f32 { /// # Examples /// /// ``` - /// #![feature(float_bits_conv)] /// use std::f32; /// let v = f32::from_bits(0x41480000); /// let difference = (v - 12.5).abs(); @@ -1139,17 +1125,20 @@ impl f32 { /// let snan = 0x7F800001; /// assert_ne!(f32::from_bits(snan).to_bits(), snan); /// ``` - #[unstable(feature = "float_bits_conv", reason = "recently added", issue = "40470")] + #[stable(feature = "float_bits_conv", since = "1.20.0")] #[inline] pub fn from_bits(mut v: u32) -> Self { const EXP_MASK: u32 = 0x7F800000; - const QNAN_MASK: u32 = 0x00400000; const FRACT_MASK: u32 = 0x007FFFFF; if v & EXP_MASK == EXP_MASK && v & FRACT_MASK != 0 { - // If we have a NaN value, we - // convert signaling NaN values to quiet NaN - // by setting the the highest bit of the fraction - v |= QNAN_MASK; + // While IEEE 754-2008 specifies encodings for quiet NaNs + // and signaling ones, certain MIPS and PA-RISC + // CPUs treat signaling NaNs differently. + // Therefore to be safe, we pass a known quiet NaN + // if v is any kind of NaN. + // The check above only assumes IEEE 754-1985 to be + // valid. + v = unsafe { ::mem::transmute(NAN) }; } unsafe { ::mem::transmute(v) } } @@ -1186,7 +1175,7 @@ mod tests { assert!(!nan.is_infinite()); assert!(!nan.is_finite()); assert!(!nan.is_normal()); - assert!(!nan.is_sign_positive()); + assert!(nan.is_sign_positive()); assert!(!nan.is_sign_negative()); assert_eq!(Fp::Nan, nan.classify()); } @@ -1430,7 +1419,8 @@ mod tests { assert!(!(-1f32).is_sign_positive()); assert!(!NEG_INFINITY.is_sign_positive()); assert!(!(1f32/NEG_INFINITY).is_sign_positive()); - assert!(!NAN.is_sign_positive()); + assert!(NAN.is_sign_positive()); + assert!(!(-NAN).is_sign_positive()); } #[test] @@ -1443,6 +1433,7 @@ mod tests { assert!(NEG_INFINITY.is_sign_negative()); assert!((1f32/NEG_INFINITY).is_sign_negative()); assert!(!NAN.is_sign_negative()); + assert!((-NAN).is_sign_negative()); } #[test] @@ -1742,8 +1733,15 @@ mod tests { } #[test] fn test_snan_masking() { + // NOTE: this test assumes that our current platform + // implements IEEE 754-2008 that specifies the difference + // in encoding of quiet and signaling NaNs. + // If you are porting Rust to a platform that does not + // implement IEEE 754-2008 (but e.g. IEEE 754-1985, which + // only says that "Signaling NaNs shall be reserved operands" + // but doesn't specify the actual setup), feel free to + // cfg out this test. let snan: u32 = 0x7F801337; - const PAYLOAD_MASK: u32 = 0x003FFFFF; const QNAN_MASK: u32 = 0x00400000; let nan_masked_fl = f32::from_bits(snan); let nan_masked = nan_masked_fl.to_bits(); @@ -1752,7 +1750,5 @@ mod tests { // Ensure that we have a quiet NaN assert_ne!(nan_masked & QNAN_MASK, 0); assert!(nan_masked_fl.is_nan()); - // Ensure the payload wasn't touched during conversion - assert_eq!(nan_masked & PAYLOAD_MASK, snan & PAYLOAD_MASK); } } diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 82e3903eec..d73d7cd2c7 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -51,8 +51,6 @@ mod cmath { pub fn erfc(n: c_double) -> c_double; pub fn expm1(n: c_double) -> c_double; pub fn fdim(a: c_double, b: c_double) -> c_double; - pub fn fmax(a: c_double, b: c_double) -> c_double; - pub fn fmin(a: c_double, b: c_double) -> c_double; pub fn fmod(a: c_double, b: c_double) -> c_double; pub fn frexp(n: c_double, value: &mut c_int) -> c_double; pub fn ilogb(n: c_double) -> c_int; @@ -303,21 +301,15 @@ impl f64 { #[inline] pub fn signum(self) -> f64 { num::Float::signum(self) } - /// Returns `true` if `self`'s sign bit is positive, including - /// `+0.0` and `INFINITY`. + /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with + /// positive sign bit and positive infinity. /// /// ``` - /// use std::f64; - /// - /// let nan: f64 = f64::NAN; - /// /// let f = 7.0_f64; /// let g = -7.0_f64; /// /// assert!(f.is_sign_positive()); /// assert!(!g.is_sign_positive()); - /// // Requires both tests to determine if is `NaN` - /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -328,21 +320,15 @@ impl f64 { #[inline] pub fn is_positive(self) -> bool { num::Float::is_sign_positive(self) } - /// Returns `true` if `self`'s sign is negative, including `-0.0` - /// and `NEG_INFINITY`. + /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with + /// negative sign bit and negative infinity. /// /// ``` - /// use std::f64; - /// - /// let nan = f64::NAN; - /// /// let f = 7.0_f64; /// let g = -7.0_f64; /// /// assert!(!f.is_sign_negative()); /// assert!(g.is_sign_negative()); - /// // Requires both tests to determine if is `NaN`. - /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -587,7 +573,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn max(self, other: f64) -> f64 { - unsafe { cmath::fmax(self, other) } + num::Float::max(self, other) } /// Returns the minimum of the two numbers. @@ -603,7 +589,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn min(self, other: f64) -> f64 { - unsafe { cmath::fmin(self, other) } + num::Float::min(self, other) } /// The positive difference of two numbers. @@ -1019,12 +1005,11 @@ impl f64 { /// # Examples /// /// ``` - /// #![feature(float_bits_conv)] /// assert!((1f64).to_bits() != 1f64 as u64); // to_bits() is not casting! /// assert_eq!((12.5f64).to_bits(), 0x4029000000000000); /// /// ``` - #[unstable(feature = "float_bits_conv", reason = "recently added", issue = "40470")] + #[stable(feature = "float_bits_conv", since = "1.20.0")] #[inline] pub fn to_bits(self) -> u64 { unsafe { ::mem::transmute(self) } @@ -1047,7 +1032,6 @@ impl f64 { /// # Examples /// /// ``` - /// #![feature(float_bits_conv)] /// use std::f64; /// let v = f64::from_bits(0x4029000000000000); /// let difference = (v - 12.5).abs(); @@ -1056,17 +1040,20 @@ impl f64 { /// let snan = 0x7FF0000000000001; /// assert_ne!(f64::from_bits(snan).to_bits(), snan); /// ``` - #[unstable(feature = "float_bits_conv", reason = "recently added", issue = "40470")] + #[stable(feature = "float_bits_conv", since = "1.20.0")] #[inline] pub fn from_bits(mut v: u64) -> Self { const EXP_MASK: u64 = 0x7FF0000000000000; - const QNAN_MASK: u64 = 0x0001000000000000; const FRACT_MASK: u64 = 0x000FFFFFFFFFFFFF; if v & EXP_MASK == EXP_MASK && v & FRACT_MASK != 0 { - // If we have a NaN value, we - // convert signaling NaN values to quiet NaN - // by setting the the highest bit of the fraction - v |= QNAN_MASK; + // While IEEE 754-2008 specifies encodings for quiet NaNs + // and signaling ones, certain MIPS and PA-RISC + // CPUs treat signaling NaNs differently. + // Therefore to be safe, we pass a known quiet NaN + // if v is any kind of NaN. + // The check above only assumes IEEE 754-1985 to be + // valid. + v = unsafe { ::mem::transmute(NAN) }; } unsafe { ::mem::transmute(v) } } @@ -1103,7 +1090,7 @@ mod tests { assert!(!nan.is_infinite()); assert!(!nan.is_finite()); assert!(!nan.is_normal()); - assert!(!nan.is_sign_positive()); + assert!(nan.is_sign_positive()); assert!(!nan.is_sign_negative()); assert_eq!(Fp::Nan, nan.classify()); } @@ -1158,6 +1145,7 @@ mod tests { assert_eq!(Fp::Zero, neg_zero.classify()); } + #[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn test_one() { let one: f64 = 1.0f64; @@ -1210,6 +1198,7 @@ mod tests { assert!((-109.2f64).is_finite()); } + #[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn test_is_normal() { let nan: f64 = NAN; @@ -1227,6 +1216,7 @@ mod tests { assert!(!1e-308f64.is_normal()); } + #[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn test_classify() { let nan: f64 = NAN; @@ -1346,7 +1336,8 @@ mod tests { assert!(!(-1f64).is_sign_positive()); assert!(!NEG_INFINITY.is_sign_positive()); assert!(!(1f64/NEG_INFINITY).is_sign_positive()); - assert!(!NAN.is_sign_positive()); + assert!(NAN.is_sign_positive()); + assert!(!(-NAN).is_sign_positive()); } #[test] @@ -1359,6 +1350,7 @@ mod tests { assert!(NEG_INFINITY.is_sign_negative()); assert!((1f64/NEG_INFINITY).is_sign_negative()); assert!(!NAN.is_sign_negative()); + assert!((-NAN).is_sign_negative()); } #[test] diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 1167c39dba..db64d41011 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -152,6 +152,14 @@ pub struct CStr { /// in the vector provided. /// /// [`CString::new`]: struct.CString.html#method.new +/// +/// # Examples +/// +/// ``` +/// use std::ffi::{CString, NulError}; +/// +/// let _: NulError = CString::new(b"f\0oo".to_vec()).unwrap_err(); +/// ``` #[derive(Clone, PartialEq, Eq, Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct NulError(usize, Vec); @@ -160,6 +168,14 @@ pub struct NulError(usize, Vec); /// byte was found too early in the slice provided or one wasn't found at all. /// /// [`CStr::from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul +/// +/// # Examples +/// +/// ``` +/// use std::ffi::{CStr, FromBytesWithNulError}; +/// +/// let _: FromBytesWithNulError = CStr::from_bytes_with_nul(b"f\0oo").unwrap_err(); +/// ``` #[derive(Clone, PartialEq, Eq, Debug)] #[stable(feature = "cstr_from_bytes", since = "1.10.0")] pub struct FromBytesWithNulError { @@ -271,6 +287,27 @@ impl CString { /// to undefined behavior or allocator corruption. /// /// [`into_raw`]: #method.into_raw + /// + /// # Examples + /// + /// Create a `CString`, pass ownership to an `extern` function (via raw pointer), then retake + /// ownership with `from_raw`: + /// + /// ```no_run + /// use std::ffi::CString; + /// use std::os::raw::c_char; + /// + /// extern { + /// fn some_extern_function(s: *mut c_char); + /// } + /// + /// let c_string = CString::new("Hello!").unwrap(); + /// let raw = c_string.into_raw(); + /// unsafe { + /// some_extern_function(raw); + /// let c_string = CString::from_raw(raw); + /// } + /// ``` #[stable(feature = "cstr_memory", since = "1.4.0")] pub unsafe fn from_raw(ptr: *mut c_char) -> CString { let len = libc::strlen(ptr) + 1; // Including the NUL byte @@ -288,6 +325,27 @@ impl CString { /// Failure to call [`from_raw`] will lead to a memory leak. /// /// [`from_raw`]: #method.from_raw + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CString; + /// + /// let c_string = CString::new("foo").unwrap(); + /// + /// let ptr = c_string.into_raw(); + /// + /// unsafe { + /// assert_eq!(b'f', *ptr as u8); + /// assert_eq!(b'o', *ptr.offset(1) as u8); + /// assert_eq!(b'o', *ptr.offset(2) as u8); + /// assert_eq!(b'\0', *ptr.offset(3) as u8); + /// + /// // retake pointer to free memory + /// let _ = CString::from_raw(ptr); + /// } + /// ``` + #[inline] #[stable(feature = "cstr_memory", since = "1.4.0")] pub fn into_raw(self) -> *mut c_char { Box::into_raw(self.into_inner()) as *mut c_char @@ -311,6 +369,16 @@ impl CString { /// /// The returned buffer does **not** contain the trailing nul separator and /// it is guaranteed to not have any interior nul bytes. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CString; + /// + /// let c_string = CString::new("foo").unwrap(); + /// let bytes = c_string.into_bytes(); + /// assert_eq!(bytes, vec![b'f', b'o', b'o']); + /// ``` #[stable(feature = "cstring_into", since = "1.7.0")] pub fn into_bytes(self) -> Vec { let mut vec = self.into_inner().into_vec(); @@ -323,6 +391,16 @@ impl CString { /// includes the trailing nul byte. /// /// [`into_bytes`]: #method.into_bytes + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CString; + /// + /// let c_string = CString::new("foo").unwrap(); + /// let bytes = c_string.into_bytes_with_nul(); + /// assert_eq!(bytes, vec![b'f', b'o', b'o', b'\0']); + /// ``` #[stable(feature = "cstring_into", since = "1.7.0")] pub fn into_bytes_with_nul(self) -> Vec { self.into_inner().into_vec() @@ -332,6 +410,17 @@ impl CString { /// /// The returned slice does **not** contain the trailing nul separator and /// it is guaranteed to not have any interior nul bytes. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CString; + /// + /// let c_string = CString::new("foo").unwrap(); + /// let bytes = c_string.as_bytes(); + /// assert_eq!(bytes, &[b'f', b'o', b'o']); + /// ``` + #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn as_bytes(&self) -> &[u8] { &self.inner[..self.inner.len() - 1] @@ -341,6 +430,17 @@ impl CString { /// includes the trailing nul byte. /// /// [`as_bytes`]: #method.as_bytes + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CString; + /// + /// let c_string = CString::new("foo").unwrap(); + /// let bytes = c_string.as_bytes_with_nul(); + /// assert_eq!(bytes, &[b'f', b'o', b'o', b'\0']); + /// ``` + #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn as_bytes_with_nul(&self) -> &[u8] { &self.inner @@ -349,7 +449,18 @@ impl CString { /// Extracts a [`CStr`] slice containing the entire string. /// /// [`CStr`]: struct.CStr.html - #[unstable(feature = "as_c_str", issue = "40380")] + /// + /// # Examples + /// + /// ``` + /// use std::ffi::{CString, CStr}; + /// + /// let c_string = CString::new(b"foo".to_vec()).unwrap(); + /// let c_str = c_string.as_c_str(); + /// assert_eq!(c_str, CStr::from_bytes_with_nul(b"foo\0").unwrap()); + /// ``` + #[inline] + #[stable(feature = "as_c_str", since = "1.20.0")] pub fn as_c_str(&self) -> &CStr { &*self } @@ -357,7 +468,17 @@ impl CString { /// Converts this `CString` into a boxed [`CStr`]. /// /// [`CStr`]: struct.CStr.html - #[unstable(feature = "into_boxed_c_str", issue = "40380")] + /// + /// # Examples + /// + /// ``` + /// use std::ffi::{CString, CStr}; + /// + /// let c_string = CString::new(b"foo".to_vec()).unwrap(); + /// let boxed = c_string.into_boxed_c_str(); + /// assert_eq!(&*boxed, CStr::from_bytes_with_nul(b"foo\0").unwrap()); + /// ``` + #[stable(feature = "into_boxed_c_str", since = "1.20.0")] pub fn into_boxed_c_str(self) -> Box { unsafe { mem::transmute(self.into_inner()) } } @@ -389,6 +510,7 @@ impl Drop for CString { impl ops::Deref for CString { type Target = CStr; + #[inline] fn deref(&self) -> &CStr { unsafe { CStr::from_bytes_with_nul_unchecked(self.as_bytes_with_nul()) } } @@ -403,6 +525,7 @@ impl fmt::Debug for CString { #[stable(feature = "cstring_into", since = "1.7.0")] impl From for Vec { + #[inline] fn from(s: CString) -> Vec { s.into_bytes() } @@ -438,6 +561,7 @@ impl Default for CString { #[stable(feature = "cstr_borrow", since = "1.3.0")] impl Borrow for CString { + #[inline] fn borrow(&self) -> &CStr { self } } @@ -451,15 +575,17 @@ impl<'a> From<&'a CStr> for Box { #[stable(feature = "c_string_from_box", since = "1.18.0")] impl From> for CString { + #[inline] fn from(s: Box) -> CString { s.into_c_string() } } -#[stable(feature = "box_from_c_string", since = "1.18.0")] -impl Into> for CString { - fn into(self) -> Box { - self.into_boxed_c_str() +#[stable(feature = "box_from_c_string", since = "1.20.0")] +impl From for Box { + #[inline] + fn from(s: CString) -> Box { + s.into_boxed_c_str() } } @@ -639,6 +765,24 @@ impl CStr { /// let cstr = CStr::from_bytes_with_nul(b"hello\0"); /// assert!(cstr.is_ok()); /// ``` + /// + /// Creating a `CStr` without a trailing nul byte is an error: + /// + /// ``` + /// use std::ffi::CStr; + /// + /// let c_str = CStr::from_bytes_with_nul(b"hello"); + /// assert!(c_str.is_err()); + /// ``` + /// + /// Creating a `CStr` with an interior nul byte is an error: + /// + /// ``` + /// use std::ffi::CStr; + /// + /// let c_str = CStr::from_bytes_with_nul(b"he\0llo\0"); + /// assert!(c_str.is_err()); + /// ``` #[stable(feature = "cstr_from_bytes", since = "1.10.0")] pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&CStr, FromBytesWithNulError> { @@ -670,6 +814,7 @@ impl CStr { /// assert_eq!(cstr, &*cstring); /// } /// ``` + #[inline] #[stable(feature = "cstr_from_bytes", since = "1.10.0")] pub unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr { mem::transmute(bytes) @@ -712,6 +857,7 @@ impl CStr { /// *ptr; /// } /// ``` + #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn as_ptr(&self) -> *const c_char { self.inner.as_ptr() @@ -729,6 +875,16 @@ impl CStr { /// > **Note**: This method is currently implemented as a 0-cost cast, but /// > it is planned to alter its definition in the future to perform the /// > length calculation whenever this method is called. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CStr; + /// + /// let c_str = CStr::from_bytes_with_nul(b"foo\0").unwrap(); + /// assert_eq!(c_str.to_bytes(), b"foo"); + /// ``` + #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn to_bytes(&self) -> &[u8] { let bytes = self.to_bytes_with_nul(); @@ -745,6 +901,16 @@ impl CStr { /// > length calculation whenever this method is called. /// /// [`to_bytes`]: #method.to_bytes + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CStr; + /// + /// let c_str = CStr::from_bytes_with_nul(b"foo\0").unwrap(); + /// assert_eq!(c_str.to_bytes_with_nul(), b"foo\0"); + /// ``` + #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn to_bytes_with_nul(&self) -> &[u8] { unsafe { mem::transmute(&self.inner) } @@ -761,6 +927,15 @@ impl CStr { /// > check whenever this method is called. /// /// [`&str`]: ../primitive.str.html + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CStr; + /// + /// let c_str = CStr::from_bytes_with_nul(b"foo\0").unwrap(); + /// assert_eq!(c_str.to_str(), Ok("foo")); + /// ``` #[stable(feature = "cstr_to_str", since = "1.4.0")] pub fn to_str(&self) -> Result<&str, str::Utf8Error> { // NB: When CStr is changed to perform the length check in .to_bytes() @@ -784,6 +959,31 @@ impl CStr { /// /// [`Cow`]: ../borrow/enum.Cow.html /// [`str`]: ../primitive.str.html + /// + /// # Examples + /// + /// Calling `to_string_lossy` on a `CStr` containing valid UTF-8: + /// + /// ``` + /// use std::borrow::Cow; + /// use std::ffi::CStr; + /// + /// let c_str = CStr::from_bytes_with_nul(b"Hello World\0").unwrap(); + /// assert_eq!(c_str.to_string_lossy(), Cow::Borrowed("Hello World")); + /// ``` + /// + /// Calling `to_string_lossy` on a `CStr` containing invalid UTF-8: + /// + /// ``` + /// use std::borrow::Cow; + /// use std::ffi::CStr; + /// + /// let c_str = CStr::from_bytes_with_nul(b"Hello \xF0\x90\x80World\0").unwrap(); + /// assert_eq!( + /// c_str.to_string_lossy(), + /// Cow::Owned(String::from("Hello �World")) as Cow + /// ); + /// ``` #[stable(feature = "cstr_to_str", since = "1.4.0")] pub fn to_string_lossy(&self) -> Cow { String::from_utf8_lossy(self.to_bytes()) @@ -793,7 +993,17 @@ impl CStr { /// /// [`Box`]: ../boxed/struct.Box.html /// [`CString`]: struct.CString.html - #[unstable(feature = "into_boxed_c_str", issue = "40380")] + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CString; + /// + /// let c_string = CString::new(b"foo".to_vec()).unwrap(); + /// let boxed = c_string.into_boxed_c_str(); + /// assert_eq!(boxed.into_c_string(), CString::new("foo").unwrap()); + /// ``` + #[stable(feature = "into_boxed_c_str", since = "1.20.0")] pub fn into_c_string(self: Box) -> CString { unsafe { mem::transmute(self) } } @@ -848,6 +1058,7 @@ impl ops::Index for CString { #[stable(feature = "cstring_asref", since = "1.7.0")] impl AsRef for CStr { + #[inline] fn as_ref(&self) -> &CStr { self } @@ -855,6 +1066,7 @@ impl AsRef for CStr { #[stable(feature = "cstring_asref", since = "1.7.0")] impl AsRef for CString { + #[inline] fn as_ref(&self) -> &CStr { self } diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index c35288e774..d62e3e905e 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -9,7 +9,7 @@ // except according to those terms. use borrow::{Borrow, Cow}; -use fmt::{self, Debug}; +use fmt; use mem; use ops; use cmp; @@ -29,7 +29,7 @@ use sys_common::{AsInner, IntoInner, FromInner}; /// * On Windows, strings are often arbitrary sequences of non-zero 16-bit /// values, interpreted as UTF-16 when it is valid to do so. /// -/// * In Rust, strings are always valid UTF-8, but may contain zeros. +/// * In Rust, strings are always valid UTF-8, which may contain zeros. /// /// `OsString` and [`OsStr`] bridge this gap by simultaneously representing Rust /// and platform-native string values, and in particular allowing a Rust string @@ -252,15 +252,13 @@ impl OsString { /// # Examples /// /// ``` - /// #![feature(into_boxed_os_str)] - /// /// use std::ffi::{OsString, OsStr}; /// /// let s = OsString::from("hello"); /// /// let b: Box = s.into_boxed_os_str(); /// ``` - #[unstable(feature = "into_boxed_os_str", issue = "40380")] + #[stable(feature = "into_boxed_os_str", since = "1.20.0")] pub fn into_boxed_os_str(self) -> Box { unsafe { mem::transmute(self.inner.into_box()) } } @@ -310,8 +308,8 @@ impl Default for OsString { } #[stable(feature = "rust1", since = "1.0.0")] -impl Debug for OsString { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { +impl fmt::Debug for OsString { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&**self, formatter) } } @@ -511,7 +509,7 @@ impl OsStr { /// /// [`Box`]: ../boxed/struct.Box.html /// [`OsString`]: struct.OsString.html - #[unstable(feature = "into_boxed_os_str", issue = "40380")] + #[stable(feature = "into_boxed_os_str", since = "1.20.0")] pub fn into_os_string(self: Box) -> OsString { let inner: Box = unsafe { mem::transmute(self) }; OsString { inner: Buf::from_box(inner) } @@ -540,10 +538,10 @@ impl From> for OsString { } } -#[stable(feature = "box_from_os_string", since = "1.18.0")] -impl Into> for OsString { - fn into(self) -> Box { - self.into_boxed_os_str() +#[stable(feature = "box_from_os_string", since = "1.20.0")] +impl From for Box { + fn from(s: OsString) -> Box { + s.into_boxed_os_str() } } @@ -667,9 +665,15 @@ impl Hash for OsStr { } #[stable(feature = "rust1", since = "1.0.0")] -impl Debug for OsStr { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - self.inner.fmt(formatter) +impl fmt::Debug for OsStr { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.inner, formatter) + } +} + +impl OsStr { + pub(crate) fn display(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.inner, formatter) } } diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 6984319934..88994b284c 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -19,7 +19,7 @@ use fmt; use ffi::OsString; -use io::{self, SeekFrom, Seek, Read, Write}; +use io::{self, SeekFrom, Seek, Read, Initializer, Write}; use path::{Path, PathBuf}; use sys::fs as fs_imp; use sys_common::{AsInnerMut, FromInner, AsInner, IntoInner}; @@ -446,8 +446,10 @@ impl Read for File { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - self.inner.read_to_end(buf) + + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() } } #[stable(feature = "rust1", since = "1.0.0")] @@ -468,8 +470,10 @@ impl<'a> Read for &'a File { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - self.inner.read_to_end(buf) + + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() } } #[stable(feature = "rust1", since = "1.0.0")] @@ -649,15 +653,29 @@ impl OpenOptions { /// # Errors /// /// This function will return an error under a number of different - /// circumstances, to include but not limited to: - /// - /// * Opening a file that does not exist without setting `create` or - /// `create_new`. - /// * Attempting to open a file with access that the user lacks - /// permissions for - /// * Filesystem-level errors (full disk, etc) - /// * Invalid combinations of open options (truncate without write access, - /// no access mode set, etc) + /// circumstances. Some of these error conditions are listed here, together + /// with their [`ErrorKind`]. The mapping to [`ErrorKind`]s is not part of + /// the compatiblity contract of the function, especially the `Other` kind + /// might change to more specific kinds in the future. + /// + /// * [`NotFound`]: The specified file does not exist and neither `create` + /// or `create_new` is set. + /// * [`NotFound`]: One of the directory components of the file path does + /// not exist. + /// * [`PermissionDenied`]: The user lacks permission to get the specified + /// access rights for the file. + /// * [`PermissionDenied`]: The user lacks permission to open one of the + /// directory components of the specified path. + /// * [`AlreadyExists`]: `create_new` was specified and the file already + /// exists. + /// * [`InvalidInput`]: Invalid combinations of open options (truncate + /// without write access, no access mode set, etc.). + /// * [`Other`]: One of the directory components of the specified file path + /// was not, in fact, a directory. + /// * [`Other`]: Filesystem-level errors: full disk, write permission + /// requested on a read-only file system, exceeded disk quota, too many + /// open files, too long filename, too many symbolic links in the + /// specified path (Unix-like systems only), etc. /// /// # Examples /// @@ -666,6 +684,13 @@ impl OpenOptions { /// /// let file = OpenOptions::new().open("foo.txt"); /// ``` + /// + /// [`ErrorKind`]: ../io/enum.ErrorKind.html + /// [`AlreadyExists`]: ../io/enum.ErrorKind.html#variant.AlreadyExists + /// [`InvalidInput`]: ../io/enum.ErrorKind.html#variant.InvalidInput + /// [`NotFound`]: ../io/enum.ErrorKind.html#variant.NotFound + /// [`Other`]: ../io/enum.ErrorKind.html#variant.Other + /// [`PermissionDenied`]: ../io/enum.ErrorKind.html#variant.PermissionDenied #[stable(feature = "rust1", since = "1.0.0")] pub fn open>(&self, path: P) -> io::Result { self._open(path.as_ref()) diff --git a/src/libstd/heap.rs b/src/libstd/heap.rs new file mode 100644 index 0000000000..83bd3b04b4 --- /dev/null +++ b/src/libstd/heap.rs @@ -0,0 +1,165 @@ +// 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. + +//! dox + +#![unstable(issue = "32838", feature = "allocator_api")] + +pub use alloc::heap::{Heap, Alloc, Layout, Excess, CannotReallocInPlace, AllocErr}; +#[cfg(not(stage0))] +pub use alloc_system::System; + +#[cfg(all(not(stage0), not(test)))] +#[doc(hidden)] +pub mod __default_lib_allocator { + use super::{System, Layout, Alloc, AllocErr}; + use ptr; + + // for symbol names src/librustc/middle/allocator.rs + // for signatures src/librustc_allocator/lib.rs + + // linkage directives are provided as part of the current compiler allocator + // ABI + + #[no_mangle] + pub unsafe extern fn __rdl_alloc(size: usize, + align: usize, + err: *mut u8) -> *mut u8 { + let layout = Layout::from_size_align_unchecked(size, align); + match System.alloc(layout) { + Ok(p) => p, + Err(e) => { + ptr::write(err as *mut AllocErr, e); + 0 as *mut u8 + } + } + } + + #[no_mangle] + pub unsafe extern fn __rdl_oom(err: *const u8) -> ! { + System.oom((*(err as *const AllocErr)).clone()) + } + + #[no_mangle] + pub unsafe extern fn __rdl_dealloc(ptr: *mut u8, + size: usize, + align: usize) { + System.dealloc(ptr, Layout::from_size_align_unchecked(size, align)) + } + + #[no_mangle] + pub unsafe extern fn __rdl_usable_size(layout: *const u8, + min: *mut usize, + max: *mut usize) { + let pair = System.usable_size(&*(layout as *const Layout)); + *min = pair.0; + *max = pair.1; + } + + #[no_mangle] + pub unsafe extern fn __rdl_realloc(ptr: *mut u8, + old_size: usize, + old_align: usize, + new_size: usize, + new_align: usize, + err: *mut u8) -> *mut u8 { + let old_layout = Layout::from_size_align_unchecked(old_size, old_align); + let new_layout = Layout::from_size_align_unchecked(new_size, new_align); + match System.realloc(ptr, old_layout, new_layout) { + Ok(p) => p, + Err(e) => { + ptr::write(err as *mut AllocErr, e); + 0 as *mut u8 + } + } + } + + #[no_mangle] + pub unsafe extern fn __rdl_alloc_zeroed(size: usize, + align: usize, + err: *mut u8) -> *mut u8 { + let layout = Layout::from_size_align_unchecked(size, align); + match System.alloc_zeroed(layout) { + Ok(p) => p, + Err(e) => { + ptr::write(err as *mut AllocErr, e); + 0 as *mut u8 + } + } + } + + #[no_mangle] + pub unsafe extern fn __rdl_alloc_excess(size: usize, + align: usize, + excess: *mut usize, + err: *mut u8) -> *mut u8 { + let layout = Layout::from_size_align_unchecked(size, align); + match System.alloc_excess(layout) { + Ok(p) => { + *excess = p.1; + p.0 + } + Err(e) => { + ptr::write(err as *mut AllocErr, e); + 0 as *mut u8 + } + } + } + + #[no_mangle] + pub unsafe extern fn __rdl_realloc_excess(ptr: *mut u8, + old_size: usize, + old_align: usize, + new_size: usize, + new_align: usize, + excess: *mut usize, + err: *mut u8) -> *mut u8 { + let old_layout = Layout::from_size_align_unchecked(old_size, old_align); + let new_layout = Layout::from_size_align_unchecked(new_size, new_align); + match System.realloc_excess(ptr, old_layout, new_layout) { + Ok(p) => { + *excess = p.1; + p.0 + } + Err(e) => { + ptr::write(err as *mut AllocErr, e); + 0 as *mut u8 + } + } + } + + #[no_mangle] + pub unsafe extern fn __rdl_grow_in_place(ptr: *mut u8, + old_size: usize, + old_align: usize, + new_size: usize, + new_align: usize) -> u8 { + let old_layout = Layout::from_size_align_unchecked(old_size, old_align); + let new_layout = Layout::from_size_align_unchecked(new_size, new_align); + match System.grow_in_place(ptr, old_layout, new_layout) { + Ok(()) => 1, + Err(_) => 0, + } + } + + #[no_mangle] + pub unsafe extern fn __rdl_shrink_in_place(ptr: *mut u8, + old_size: usize, + old_align: usize, + new_size: usize, + new_align: usize) -> u8 { + let old_layout = Layout::from_size_align_unchecked(old_size, old_align); + let new_layout = Layout::from_size_align_unchecked(new_size, new_align); + match System.shrink_in_place(ptr, old_layout, new_layout) { + Ok(()) => 1, + Err(_) => 0, + } + } +} diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 3b82412716..1b83245352 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -15,7 +15,7 @@ use io::prelude::*; use cmp; use error; use fmt; -use io::{self, DEFAULT_BUF_SIZE, Error, ErrorKind, SeekFrom}; +use io::{self, Initializer, DEFAULT_BUF_SIZE, Error, ErrorKind, SeekFrom}; use memchr; /// The `BufReader` struct adds buffering to any reader. @@ -92,11 +92,16 @@ impl BufReader { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn with_capacity(cap: usize, inner: R) -> BufReader { - BufReader { - inner: inner, - buf: vec![0; cap].into_boxed_slice(), - pos: 0, - cap: 0, + unsafe { + let mut buffer = Vec::with_capacity(cap); + buffer.set_len(cap); + inner.initializer().initialize(&mut buffer); + BufReader { + inner: inner, + buf: buffer.into_boxed_slice(), + pos: 0, + cap: 0, + } } } @@ -180,6 +185,11 @@ impl Read for BufReader { self.consume(nread); Ok(nread) } + + // we can't skip unconditionally because of the large buffer case in read. + unsafe fn initializer(&self) -> Initializer { + self.inner.initializer() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -266,7 +276,10 @@ impl Seek for BufReader { /// `BufWriter` keeps an in-memory buffer of data and writes it to an underlying /// writer in large, infrequent batches. /// -/// The buffer will be written out when the writer is dropped. +/// When the `BufWriter` is dropped, the contents of its buffer will be written +/// out. However, any errors that happen in the process of flushing the buffer +/// when the writer is dropped will be ignored. Code that wishes to handle such +/// errors must manually call [`flush`] before the writer is dropped. /// /// # Examples /// @@ -306,6 +319,7 @@ impl Seek for BufReader { /// [`Write`]: ../../std/io/trait.Write.html /// [`Tcpstream::write`]: ../../std/net/struct.TcpStream.html#method.write /// [`TcpStream`]: ../../std/net/struct.TcpStream.html +/// [`flush`]: #method.flush #[stable(feature = "rust1", since = "1.0.0")] pub struct BufWriter { inner: Option, diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index 53347eb14d..616b4f47ed 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -12,7 +12,7 @@ use io::prelude::*; use core::convert::TryInto; use cmp; -use io::{self, SeekFrom, Error, ErrorKind}; +use io::{self, Initializer, SeekFrom, Error, ErrorKind}; /// A `Cursor` wraps another type and provides it with a /// [`Seek`] implementation. @@ -229,6 +229,11 @@ impl Read for Cursor where T: AsRef<[u8]> { self.pos += n as u64; Ok(n) } + + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/io/impls.rs b/src/libstd/io/impls.rs index f691289811..d6b41ceda4 100644 --- a/src/libstd/io/impls.rs +++ b/src/libstd/io/impls.rs @@ -9,7 +9,7 @@ // except according to those terms. use cmp; -use io::{self, SeekFrom, Read, Write, Seek, BufRead, Error, ErrorKind}; +use io::{self, SeekFrom, Read, Initializer, Write, Seek, BufRead, Error, ErrorKind}; use fmt; use mem; @@ -23,6 +23,11 @@ impl<'a, R: Read + ?Sized> Read for &'a mut R { (**self).read(buf) } + #[inline] + unsafe fn initializer(&self) -> Initializer { + (**self).initializer() + } + #[inline] fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { (**self).read_to_end(buf) @@ -87,6 +92,11 @@ impl Read for Box { (**self).read(buf) } + #[inline] + unsafe fn initializer(&self) -> Initializer { + (**self).initializer() + } + #[inline] fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { (**self).read_to_end(buf) @@ -171,6 +181,11 @@ impl<'a> Read for &'a [u8] { Ok(amt) } + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() + } + #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { if buf.len() > self.len() { diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index c872a8e526..9a3036f753 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -263,7 +263,7 @@ //! [`println!`]: ../macro.println.html //! [`Lines`]: struct.Lines.html //! [`io::Result`]: type.Result.html -//! [`?` operator]: ../../book/syntax-index.html +//! [`?` operator]: ../../book/first-edition/syntax-index.html //! [`Read::read`]: trait.Read.html#tymethod.read #![stable(feature = "rust1", since = "1.0.0")] @@ -275,6 +275,7 @@ use fmt; use result; use str; use memchr; +use ptr; #[stable(feature = "rust1", since = "1.0.0")] pub use self::buffered::{BufReader, BufWriter, LineWriter}; @@ -292,7 +293,7 @@ pub use self::stdio::{stdin, stdout, stderr, Stdin, Stdout, Stderr}; pub use self::stdio::{StdoutLock, StderrLock, StdinLock}; #[unstable(feature = "print_internals", issue = "0")] pub use self::stdio::{_print, _eprint}; -#[unstable(feature = "libstd_io_internals", issue = "0")] +#[unstable(feature = "libstd_io_internals", issue = "42788")] #[doc(no_inline, hidden)] pub use self::stdio::{set_panic, set_print}; @@ -307,6 +308,14 @@ mod stdio; const DEFAULT_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE; +struct Guard<'a> { buf: &'a mut Vec, len: usize } + +impl<'a> Drop for Guard<'a> { + fn drop(&mut self) { + unsafe { self.buf.set_len(self.len); } + } +} + // A few methods below (read_to_string, read_line) will append data into a // `String` buffer, but we need to be pretty careful when doing this. The // implementation will just call `.as_mut_vec()` and then delegate to a @@ -328,23 +337,16 @@ const DEFAULT_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE; fn append_to_string(buf: &mut String, f: F) -> Result where F: FnOnce(&mut Vec) -> Result { - struct Guard<'a> { s: &'a mut Vec, len: usize } - impl<'a> Drop for Guard<'a> { - fn drop(&mut self) { - unsafe { self.s.set_len(self.len); } - } - } - unsafe { - let mut g = Guard { len: buf.len(), s: buf.as_mut_vec() }; - let ret = f(g.s); - if str::from_utf8(&g.s[g.len..]).is_err() { + let mut g = Guard { len: buf.len(), buf: buf.as_mut_vec() }; + let ret = f(g.buf); + if str::from_utf8(&g.buf[g.len..]).is_err() { ret.and_then(|_| { Err(Error::new(ErrorKind::InvalidData, "stream did not contain valid UTF-8")) }) } else { - g.len = g.s.len(); + g.len = g.buf.len(); ret } } @@ -356,25 +358,32 @@ fn append_to_string(buf: &mut String, f: F) -> Result // of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every // time is 4,500 times (!) slower than this if the reader has a very small // amount of data to return. +// +// Because we're extending the buffer with uninitialized data for trusted +// readers, we need to make sure to truncate that if any of this panics. fn read_to_end(r: &mut R, buf: &mut Vec) -> Result { let start_len = buf.len(); - let mut len = start_len; + let mut g = Guard { len: buf.len(), buf: buf }; let mut new_write_size = 16; let ret; loop { - if len == buf.len() { + if g.len == g.buf.len() { if new_write_size < DEFAULT_BUF_SIZE { new_write_size *= 2; } - buf.resize(len + new_write_size, 0); + unsafe { + g.buf.reserve(new_write_size); + g.buf.set_len(g.len + new_write_size); + r.initializer().initialize(&mut g.buf[g.len..]); + } } - match r.read(&mut buf[len..]) { + match r.read(&mut g.buf[g.len..]) { Ok(0) => { - ret = Ok(len - start_len); + ret = Ok(g.len - start_len); break; } - Ok(n) => len += n, + Ok(n) => g.len += n, Err(ref e) if e.kind() == ErrorKind::Interrupted => {} Err(e) => { ret = Err(e); @@ -383,13 +392,12 @@ fn read_to_end(r: &mut R, buf: &mut Vec) -> Result } } - buf.truncate(len); ret } /// The `Read` trait allows for reading bytes from a source. /// -/// Implementors of the `Read` trait are sometimes called 'readers'. +/// Implementors of the `Read` trait are called 'readers'. /// /// Readers are defined by one required method, `read()`. Each call to `read` /// will attempt to pull bytes from this source into a provided buffer. A @@ -494,6 +502,31 @@ pub trait Read { #[stable(feature = "rust1", since = "1.0.0")] fn read(&mut self, buf: &mut [u8]) -> Result; + /// Determines if this `Read`er can work with buffers of uninitialized + /// memory. + /// + /// The default implementation returns an initializer which will zero + /// buffers. + /// + /// If a `Read`er guarantees that it can work properly with uninitialized + /// memory, it should call `Initializer::nop()`. See the documentation for + /// `Initializer` for details. + /// + /// The behavior of this method must be independent of the state of the + /// `Read`er - the method only takes `&self` so that it can be used through + /// trait objects. + /// + /// # Unsafety + /// + /// This method is unsafe because a `Read`er could otherwise return a + /// non-zeroing `Initializer` from another `Read` type without an `unsafe` + /// block. + #[unstable(feature = "read_initializer", issue = "42788")] + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::zeroing() + } + /// Read all bytes until EOF in this source, placing them into `buf`. /// /// All bytes read from this source will be appended to the specified buffer @@ -829,6 +862,50 @@ pub trait Read { } } +/// A type used to conditionally initialize buffers passed to `Read` methods. +#[unstable(feature = "read_initializer", issue = "42788")] +#[derive(Debug)] +pub struct Initializer(bool); + +impl Initializer { + /// Returns a new `Initializer` which will zero out buffers. + #[unstable(feature = "read_initializer", issue = "42788")] + #[inline] + pub fn zeroing() -> Initializer { + Initializer(true) + } + + /// Returns a new `Initializer` which will not zero out buffers. + /// + /// # Unsafety + /// + /// This may only be called by `Read`ers which guarantee that they will not + /// read from buffers passed to `Read` methods, and that the return value of + /// the method accurately reflects the number of bytes that have been + /// written to the head of the buffer. + #[unstable(feature = "read_initializer", issue = "42788")] + #[inline] + pub unsafe fn nop() -> Initializer { + Initializer(false) + } + + /// Indicates if a buffer should be initialized. + #[unstable(feature = "read_initializer", issue = "42788")] + #[inline] + pub fn should_initialize(&self) -> bool { + self.0 + } + + /// Initializes a buffer if necessary. + #[unstable(feature = "read_initializer", issue = "42788")] + #[inline] + pub fn initialize(&self, buf: &mut [u8]) { + if self.should_initialize() { + unsafe { ptr::write_bytes(buf.as_mut_ptr(), 0, buf.len()) } + } + } +} + /// A trait for objects which are byte-oriented sinks. /// /// Implementors of the `Write` trait are sometimes called 'writers'. @@ -1512,8 +1589,6 @@ impl Chain { /// # Examples /// /// ``` - /// #![feature(more_io_inner_methods)] - /// /// # use std::io; /// use std::io::prelude::*; /// use std::fs::File; @@ -1527,7 +1602,7 @@ impl Chain { /// # Ok(()) /// # } /// ``` - #[unstable(feature = "more_io_inner_methods", issue="41519")] + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn into_inner(self) -> (T, U) { (self.first, self.second) } @@ -1537,8 +1612,6 @@ impl Chain { /// # Examples /// /// ``` - /// #![feature(more_io_inner_methods)] - /// /// # use std::io; /// use std::io::prelude::*; /// use std::fs::File; @@ -1552,7 +1625,7 @@ impl Chain { /// # Ok(()) /// # } /// ``` - #[unstable(feature = "more_io_inner_methods", issue="41519")] + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_ref(&self) -> (&T, &U) { (&self.first, &self.second) } @@ -1566,8 +1639,6 @@ impl Chain { /// # Examples /// /// ``` - /// #![feature(more_io_inner_methods)] - /// /// # use std::io; /// use std::io::prelude::*; /// use std::fs::File; @@ -1581,7 +1652,7 @@ impl Chain { /// # Ok(()) /// # } /// ``` - #[unstable(feature = "more_io_inner_methods", issue="41519")] + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_mut(&mut self) -> (&mut T, &mut U) { (&mut self.first, &mut self.second) } @@ -1608,6 +1679,15 @@ impl Read for Chain { } self.second.read(buf) } + + unsafe fn initializer(&self) -> Initializer { + let initializer = self.first.initializer(); + if initializer.should_initialize() { + initializer + } else { + self.second.initializer() + } + } } #[stable(feature = "chain_bufread", since = "1.9.0")] @@ -1675,6 +1755,35 @@ impl Take { #[stable(feature = "rust1", since = "1.0.0")] pub fn limit(&self) -> u64 { self.limit } + /// Sets the number of bytes that can be read before this instance will + /// return EOF. This is the same as constructing a new `Take` instance, so + /// the amount of bytes read and the previous limit value don't matter when + /// calling this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(take_set_limit)] + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let f = File::open("foo.txt")?; + /// + /// // read at most five bytes + /// let mut handle = f.take(5); + /// handle.set_limit(10); + /// + /// assert_eq!(handle.limit(), 10); + /// # Ok(()) + /// # } + /// ``` + #[unstable(feature = "take_set_limit", issue = "42781")] + pub fn set_limit(&mut self, limit: u64) { + self.limit = limit; + } + /// Consumes the `Take`, returning the wrapped reader. /// /// # Examples @@ -1705,8 +1814,6 @@ impl Take { /// # Examples /// /// ``` - /// #![feature(more_io_inner_methods)] - /// /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; @@ -1722,7 +1829,7 @@ impl Take { /// # Ok(()) /// # } /// ``` - #[unstable(feature = "more_io_inner_methods", issue="41519")] + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_ref(&self) -> &T { &self.inner } @@ -1736,8 +1843,6 @@ impl Take { /// # Examples /// /// ``` - /// #![feature(more_io_inner_methods)] - /// /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; @@ -1753,7 +1858,7 @@ impl Take { /// # Ok(()) /// # } /// ``` - #[unstable(feature = "more_io_inner_methods", issue="41519")] + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_mut(&mut self) -> &mut T { &mut self.inner } @@ -1772,6 +1877,10 @@ impl Read for Take { self.limit -= n as u64; Ok(n) } + + unsafe fn initializer(&self) -> Initializer { + self.inner.initializer() + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index a8b0bf0071..fb489bf487 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -13,7 +13,7 @@ use io::prelude::*; use cell::RefCell; use fmt; use io::lazy::Lazy; -use io::{self, BufReader, LineWriter}; +use io::{self, Initializer, BufReader, LineWriter}; use sync::{Arc, Mutex, MutexGuard}; use sys::stdio; use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard}; @@ -75,8 +75,10 @@ fn stderr_raw() -> io::Result { stdio::Stderr::new().map(StderrRaw) } impl Read for StdinRaw { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - self.0.read_to_end(buf) + + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() } } impl Write for StdoutRaw { @@ -116,12 +118,6 @@ impl io::Read for Maybe { Maybe::Fake => Ok(0) } } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - match *self { - Maybe::Real(ref mut r) => handle_ebadf(r.read_to_end(buf), 0), - Maybe::Fake => Ok(0) - } - } } fn handle_ebadf(r: io::Result, default: T) -> io::Result { @@ -294,6 +290,10 @@ impl Read for Stdin { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.lock().read(buf) } + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() + } fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { self.lock().read_to_end(buf) } @@ -310,8 +310,9 @@ impl<'a> Read for StdinLock<'a> { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - self.inner.read_to_end(buf) + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() } } diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 078f1ad3f6..88f4214296 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -11,7 +11,8 @@ #![allow(missing_copy_implementations)] use fmt; -use io::{self, Read, Write, ErrorKind, BufRead}; +use io::{self, Read, Initializer, Write, ErrorKind, BufRead}; +use mem; /// Copies the entire contents of a reader into a writer. /// @@ -47,7 +48,12 @@ use io::{self, Read, Write, ErrorKind, BufRead}; pub fn copy(reader: &mut R, writer: &mut W) -> io::Result where R: Read, W: Write { - let mut buf = [0; super::DEFAULT_BUF_SIZE]; + let mut buf = unsafe { + let mut buf: [u8; super::DEFAULT_BUF_SIZE] = mem::uninitialized(); + reader.initializer().initialize(&mut buf); + buf + }; + let mut written = 0; loop { let len = match reader.read(&mut buf) { @@ -90,11 +96,19 @@ pub fn empty() -> Empty { Empty { _priv: () } } #[stable(feature = "rust1", since = "1.0.0")] impl Read for Empty { + #[inline] fn read(&mut self, _buf: &mut [u8]) -> io::Result { Ok(0) } + + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() + } } #[stable(feature = "rust1", since = "1.0.0")] impl BufRead for Empty { + #[inline] fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) } + #[inline] fn consume(&mut self, _n: usize) {} } @@ -133,12 +147,18 @@ pub fn repeat(byte: u8) -> Repeat { Repeat { byte: byte } } #[stable(feature = "rust1", since = "1.0.0")] impl Read for Repeat { + #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result { for slot in &mut *buf { *slot = self.byte; } Ok(buf.len()) } + + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() + } } #[stable(feature = "std_debug", since = "1.16.0")] @@ -176,7 +196,9 @@ pub fn sink() -> Sink { Sink { _priv: () } } #[stable(feature = "rust1", since = "1.0.0")] impl Write for Sink { + #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { Ok(buf.len()) } + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) } } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index b0820d6f05..82262f1551 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -230,11 +230,6 @@ // Tell the compiler to link to either panic_abort or panic_unwind #![needs_panic_runtime] -// Always use alloc_system during stage0 since we don't know if the alloc_* -// crate the stage0 compiler will pick by default is available (most -// obviously, if the user has disabled jemalloc in `./configure`). -#![cfg_attr(any(stage0, feature = "force_alloc_system"), feature(alloc_system))] - // Turn warnings into errors, but only after stage0, where it can be useful for // code to emit warnings during language transitions #![deny(warnings)] @@ -245,16 +240,17 @@ // std is implemented with unstable features, many of which are internal // compiler details that will never be stable #![feature(alloc)] +#![feature(allocator_api)] +#![feature(alloc_system)] +#![feature(allocator_internals)] #![feature(allow_internal_unstable)] #![feature(asm)] -#![feature(associated_consts)] #![feature(box_syntax)] #![feature(cfg_target_has_atomic)] #![feature(cfg_target_thread_local)] #![feature(cfg_target_vendor)] -#![feature(char_escape_debug)] +#![feature(char_error_internals)] #![feature(char_internals)] -#![feature(collections)] #![feature(collections_range)] #![feature(compiler_builtins_lib)] #![feature(const_fn)] @@ -280,6 +276,7 @@ #![feature(link_args)] #![feature(linkage)] #![feature(macro_reexport)] +#![feature(macro_vis_matcher)] #![feature(needs_panic_runtime)] #![feature(needs_drop)] #![feature(never_type)] @@ -306,7 +303,6 @@ #![feature(stmt_expr_attributes)] #![feature(str_char)] #![feature(str_internals)] -#![feature(str_mut_extras)] #![feature(str_utf16)] #![feature(test, rustc_private)] #![feature(thread_local)] @@ -319,7 +315,9 @@ #![feature(unwind_attributes)] #![feature(vec_push_all)] #![cfg_attr(test, feature(update_panic_count))] -#![cfg_attr(test, feature(float_bits_conv))] + +#![cfg_attr(not(stage0), default_lib_allocator)] +#![cfg_attr(stage0, feature(associated_consts))] // Explicitly import the prelude. The compiler uses this same unstable attribute // to import the prelude implicitly when building crates that depend on std. @@ -337,21 +335,17 @@ use prelude::v1::*; debug_assert_ne, unreachable, unimplemented, write, writeln, try)] extern crate core as __core; +#[allow(deprecated)] extern crate rand as core_rand; #[macro_use] #[macro_reexport(vec, format)] -extern crate collections as core_collections; - -#[allow(deprecated)] extern crate rand as core_rand; extern crate alloc; +extern crate alloc_system; extern crate std_unicode; extern crate libc; // We always need an unwinder currently for backtraces extern crate unwind; -#[cfg(any(stage0, feature = "force_alloc_system"))] -extern crate alloc_system; - // compiler-rt intrinsics extern crate compiler_builtins; @@ -430,17 +424,17 @@ pub use alloc::boxed; #[stable(feature = "rust1", since = "1.0.0")] pub use alloc::rc; #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::borrow; +pub use alloc::borrow; #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::fmt; +pub use alloc::fmt; #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::slice; +pub use alloc::slice; #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::str; +pub use alloc::str; #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::string; +pub use alloc::string; #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::vec; +pub use alloc::vec; #[stable(feature = "rust1", since = "1.0.0")] pub use std_unicode::char; #[unstable(feature = "i128", issue = "35118")] @@ -466,6 +460,7 @@ pub mod path; pub mod process; pub mod sync; pub mod time; +pub mod heap; // Platform-abstraction modules #[macro_use] @@ -487,7 +482,7 @@ pub mod rt; // but it may be stabilized long-term. As a result we're exposing a hidden, // unstable module so we can get our build working. #[doc(hidden)] -#[unstable(feature = "rand", issue = "0")] +#[unstable(feature = "rand", issue = "27703")] pub mod __rand { pub use rand::{thread_rng, ThreadRng, Rng}; } diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index df3fce0da7..1545c1f9ab 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -14,6 +14,16 @@ //! library. Each macro is available for use when linking against the standard //! library. +#[macro_export] +// This stability attribute is totally useless. +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(stage0)] +macro_rules! __rust_unstable_column { + () => { + column!() + } +} + /// The entry point for panic of Rust threads. /// /// This macro is used to inject panic into a Rust thread, causing the thread to @@ -24,6 +34,11 @@ /// The multi-argument form of this macro panics with a string and has the /// `format!` syntax for building a string. /// +/// # Current implementation +/// +/// If the main thread panics it will terminate all your threads and end your +/// program with code `101`. +/// /// # Examples /// /// ```should_panic @@ -41,10 +56,11 @@ macro_rules! panic { panic!("explicit panic") }); ($msg:expr) => ({ - $crate::rt::begin_panic($msg, { + $crate::rt::begin_panic_new($msg, { // static requires less code at runtime, more constant data - static _FILE_LINE: (&'static str, u32) = (file!(), line!()); - &_FILE_LINE + static _FILE_LINE_COL: (&'static str, u32, u32) = (file!(), line!(), + __rust_unstable_column!()); + &_FILE_LINE_COL }) }); ($fmt:expr, $($arg:tt)+) => ({ @@ -53,8 +69,9 @@ macro_rules! panic { // used inside a dead function. Just `#[allow(dead_code)]` is // insufficient, since the user may have // `#[forbid(dead_code)]` and which cannot be overridden. - static _FILE_LINE: (&'static str, u32) = (file!(), line!()); - &_FILE_LINE + static _FILE_LINE_COL: (&'static str, u32, u32) = (file!(), line!(), + __rust_unstable_column!()); + &_FILE_LINE_COL }) }); } @@ -238,6 +255,16 @@ macro_rules! assert_approx_eq { /// into libsyntax itself. #[cfg(dox)] pub mod builtin { + + /// Unconditionally causes compilation to fail with the given error message when encountered. + /// + /// For more information, see the [RFC]. + /// + /// [RFC]: https://github.com/rust-lang/rfcs/blob/master/text/1695-add-error-macro.md + #[stable(feature = "compile_error_macro", since = "1.20.0")] + #[macro_export] + macro_rules! compile_error { ($msg:expr) => ({ /* compiler built-in */ }) } + /// The core macro for formatted string creation & output. /// /// This macro produces a value of type [`fmt::Arguments`]. This value can be @@ -434,7 +461,7 @@ pub mod builtin { /// /// # Examples /// - /// ```rust,ignore + /// ```ignore (cannot-doctest-external-file-dependency) /// let secret_key = include_str!("secret-key.ascii"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -451,7 +478,7 @@ pub mod builtin { /// /// # Examples /// - /// ```rust,ignore + /// ```ignore (cannot-doctest-external-file-dependency) /// let secret_key = include_bytes!("secret-key.bin"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -486,7 +513,7 @@ pub mod builtin { /// leads to less duplicated code. /// /// The syntax given to this macro is the same syntax as [the `cfg` - /// attribute](../book/conditional-compilation.html). + /// attribute](../book/first-edition/conditional-compilation.html). /// /// # Examples /// @@ -520,13 +547,13 @@ pub mod builtin { /// /// File 'my_str.in': /// - /// ```ignore + /// ```ignore (only-for-syntax-highlight) /// "Hello World!" /// ``` /// /// File 'main.rs': /// - /// ```ignore + /// ```ignore (cannot-doctest-external-file-dependency) /// fn main() { /// let my_str = include!("my_str.in"); /// println!("{}", my_str); diff --git a/src/libstd/memchr.rs b/src/libstd/memchr.rs index 7c8c97a6ca..98642f86f4 100644 --- a/src/libstd/memchr.rs +++ b/src/libstd/memchr.rs @@ -24,7 +24,7 @@ /// /// This shows how to find the first position of a byte in a byte string. /// -/// ```rust,ignore +/// ```ignore (cannot-doctest-private-modules) /// use memchr::memchr; /// /// let haystack = b"the quick brown fox"; @@ -44,7 +44,7 @@ pub fn memchr(needle: u8, haystack: &[u8]) -> Option { /// /// This shows how to find the last position of a byte in a byte string. /// -/// ```rust,ignore +/// ```ignore (cannot-doctest-private-modules) /// use memchr::memrchr; /// /// let haystack = b"the quick brown fox"; diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index c1493c9c6f..fdeca8bc5c 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -11,7 +11,7 @@ use io::prelude::*; use fmt; -use io; +use io::{self, Initializer}; use net::{ToSocketAddrs, SocketAddr, Shutdown}; use sys_common::net as net_imp; use sys_common::{AsInner, FromInner, IntoInner}; @@ -134,6 +134,24 @@ impl TcpStream { super::each_addr(addr, net_imp::TcpStream::connect).map(TcpStream) } + /// Opens a TCP connection to a remote host with a timeout. + /// + /// Unlike `connect`, `connect_timeout` takes a single [`SocketAddr`] since + /// timeout must be applied to individual addresses. + /// + /// It is an error to pass a zero `Duration` to this function. + /// + /// Unlike other methods on `TcpStream`, this does not correspond to a + /// single system call. It instead calls `connect` in nonblocking mode and + /// then uses an OS-specific mechanism to await the completion of the + /// connection request. + /// + /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html + #[unstable(feature = "tcpstream_connect_timeout", issue = "43709")] + pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result { + net_imp::TcpStream::connect_timeout(addr, timeout).map(TcpStream) + } + /// Returns the socket address of the remote peer of this TCP connection. /// /// # Examples @@ -481,8 +499,10 @@ impl TcpStream { #[stable(feature = "rust1", since = "1.0.0")] impl Read for TcpStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - self.0.read_to_end(buf) + + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() } } #[stable(feature = "rust1", since = "1.0.0")] @@ -493,8 +513,10 @@ impl Write for TcpStream { #[stable(feature = "rust1", since = "1.0.0")] impl<'a> Read for &'a TcpStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - self.0.read_to_end(buf) + + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1505,4 +1527,19 @@ mod tests { t!(txdone.send(())); }) } + + #[test] + fn connect_timeout_unroutable() { + // this IP is unroutable, so connections should always time out. + let addr = "10.255.255.1:80".parse().unwrap(); + let e = TcpStream::connect_timeout(&addr, Duration::from_millis(250)).unwrap_err(); + assert_eq!(e.kind(), io::ErrorKind::TimedOut); + } + + #[test] + fn connect_timeout_valid() { + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); + let addr = listener.local_addr().unwrap(); + TcpStream::connect_timeout(&addr, Duration::from_secs(2)).unwrap(); + } } diff --git a/src/libstd/num.rs b/src/libstd/num.rs index ff89887ac9..a2c133954a 100644 --- a/src/libstd/num.rs +++ b/src/libstd/num.rs @@ -173,7 +173,10 @@ mod tests { fn $test_name() { #![test] assert_eq!((0 as $T).checked_next_power_of_two(), Some(1)); - assert!(($T::MAX / 2).checked_next_power_of_two().is_some()); + let smax = $T::MAX >> 1; + assert_eq!(smax.checked_next_power_of_two(), Some(smax+1)); + assert_eq!((smax + 1).checked_next_power_of_two(), Some(smax + 1)); + assert_eq!((smax + 2).checked_next_power_of_two(), None); assert_eq!(($T::MAX - 1).checked_next_power_of_two(), None); assert_eq!($T::MAX.checked_next_power_of_two(), None); let mut next_power = 1; diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index f99634ecac..58356bc43e 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -112,7 +112,7 @@ pub trait UnwindSafe {} /// This is a "helper marker trait" used to provide impl blocks for the /// `UnwindSafe` trait, for more information see that documentation. #[stable(feature = "catch_unwind", since = "1.9.0")] -#[rustc_on_unimplemented = "the type {Self} contains interior mutability \ +#[rustc_on_unimplemented = "the type {Self} may contain interior mutability \ and a reference may not be safely transferrable \ across a catch_unwind boundary"] pub trait RefUnwindSafe {} diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 6f46a73698..494376b831 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -262,6 +262,7 @@ impl<'a> PanicInfo<'a> { pub struct Location<'a> { file: &'a str, line: u32, + col: u32, } impl<'a> Location<'a> { @@ -308,6 +309,29 @@ impl<'a> Location<'a> { pub fn line(&self) -> u32 { self.line } + + /// Returns the column from which the panic originated. + /// + /// # Examples + /// + /// ```should_panic + /// #![feature(panic_col)] + /// use std::panic; + /// + /// panic::set_hook(Box::new(|panic_info| { + /// if let Some(location) = panic_info.location() { + /// println!("panic occured at column {}", location.column()); + /// } else { + /// println!("panic occured but can't get location information..."); + /// } + /// })); + /// + /// panic!("Normal panic"); + /// ``` + #[unstable(feature = "panic_col", reason = "recently added", issue = "42939")] + pub fn column(&self) -> u32 { + self.col + } } fn default_hook(info: &PanicInfo) { @@ -329,6 +353,7 @@ fn default_hook(info: &PanicInfo) { let file = info.location.file; let line = info.location.line; + let col = info.location.col; let msg = match info.payload.downcast_ref::<&'static str>() { Some(s) => *s, @@ -342,8 +367,8 @@ fn default_hook(info: &PanicInfo) { let name = thread.as_ref().and_then(|t| t.name()).unwrap_or(""); let write = |err: &mut ::io::Write| { - let _ = writeln!(err, "thread '{}' panicked at '{}', {}:{}", - name, msg, file, line); + let _ = writeln!(err, "thread '{}' panicked at '{}', {}:{}:{}", + name, msg, file, line, col); #[cfg(feature = "backtrace")] { @@ -467,8 +492,9 @@ pub fn panicking() -> bool { #[unwind] pub extern fn rust_begin_panic(msg: fmt::Arguments, file: &'static str, - line: u32) -> ! { - begin_panic_fmt(&msg, &(file, line)) + line: u32, + col: u32) -> ! { + begin_panic_fmt(&msg, &(file, line, col)) } /// The entry point for panicking with a formatted message. @@ -482,7 +508,7 @@ pub extern fn rust_begin_panic(msg: fmt::Arguments, issue = "0")] #[inline(never)] #[cold] pub fn begin_panic_fmt(msg: &fmt::Arguments, - file_line: &(&'static str, u32)) -> ! { + file_line_col: &(&'static str, u32, u32)) -> ! { use fmt::Write; // We do two allocations here, unfortunately. But (a) they're @@ -492,7 +518,39 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments, let mut s = String::new(); let _ = s.write_fmt(*msg); - begin_panic(s, file_line) + begin_panic_new(s, file_line_col) +} + +// FIXME: In PR #42938, we have added the column as info passed to the panic +// handling code. For this, we want to break the ABI of begin_panic. +// This is not possible to do directly, as the stage0 compiler is hardcoded +// to emit a call to begin_panic in src/libsyntax/ext/build.rs, only +// with the file and line number being passed, but not the colum number. +// By changing the compiler source, we can only affect behaviour of higher +// stages. We need to perform the switch over two stage0 replacements, using +// a temporary function begin_panic_new while performing the switch: +// 0. Right now, we tell stage1 onward to emit a call to begin_panic_new. +// 1. In the first SNAP, stage0 calls begin_panic_new with the new ABI, +// begin_panic stops being used. Now we can change begin_panic to +// the new ABI, and start emitting calls to begin_panic in higher +// stages again, this time with the new ABI. +// 2. After the second SNAP, stage0 calls begin_panic with the new ABI, +// and we can remove the temporary begin_panic_new function. + +/// This is the entry point of panicking for panic!() and assert!(). +#[unstable(feature = "libstd_sys_internals", + reason = "used by the panic! macro", + issue = "0")] +#[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible +pub fn begin_panic_new(msg: M, file_line_col: &(&'static str, u32, u32)) -> ! { + // Note that this should be the only allocation performed in this code path. + // Currently this means that panic!() on OOM will invoke this code path, + // but then again we're not really ready for panic on OOM anyway. If + // we do start doing this, then we should propagate this allocation to + // be performed in the parent of this thread instead of the thread that's + // panicking. + + rust_panic_with_hook(Box::new(msg), file_line_col) } /// This is the entry point of panicking for panic!() and assert!(). @@ -508,7 +566,10 @@ pub fn begin_panic(msg: M, file_line: &(&'static str, u32)) -> ! // be performed in the parent of this thread instead of the thread that's // panicking. - rust_panic_with_hook(Box::new(msg), file_line) + let (file, line) = *file_line; + let file_line_col = (file, line, 0); + + rust_panic_with_hook(Box::new(msg), &file_line_col) } /// Executes the primary logic for a panic, including checking for recursive @@ -520,8 +581,8 @@ pub fn begin_panic(msg: M, file_line: &(&'static str, u32)) -> ! #[inline(never)] #[cold] fn rust_panic_with_hook(msg: Box, - file_line: &(&'static str, u32)) -> ! { - let (file, line) = *file_line; + file_line_col: &(&'static str, u32, u32)) -> ! { + let (file, line, col) = *file_line_col; let panics = update_panic_count(1); @@ -540,8 +601,9 @@ fn rust_panic_with_hook(msg: Box, let info = PanicInfo { payload: &*msg, location: Location { - file: file, - line: line, + file, + line, + col, }, }; HOOK_LOCK.read(); diff --git a/src/libstd/path.rs b/src/libstd/path.rs index e128a4164d..62ffe746f3 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -135,12 +135,12 @@ use sys::path::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix}; /// get_path_prefix(r"\\?\pictures\kittens")); /// assert_eq!(VerbatimUNC(OsStr::new("server"), OsStr::new("share")), /// get_path_prefix(r"\\?\UNC\server\share")); -/// assert_eq!(VerbatimDisk('C' as u8), get_path_prefix(r"\\?\c:\")); +/// assert_eq!(VerbatimDisk(b'C'), get_path_prefix(r"\\?\c:\")); /// assert_eq!(DeviceNS(OsStr::new("BrainInterface")), /// get_path_prefix(r"\\.\BrainInterface")); /// assert_eq!(UNC(OsStr::new("server"), OsStr::new("share")), /// get_path_prefix(r"\\server\share")); -/// assert_eq!(Disk('C' as u8), get_path_prefix(r"C:\Users\Rust\Pictures\Ferris")); +/// assert_eq!(Disk(b'C'), get_path_prefix(r"C:\Users\Rust\Pictures\Ferris")); /// # } /// ``` #[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)] @@ -235,10 +235,10 @@ impl<'a> Prefix<'a> { /// /// assert!(Verbatim(OsStr::new("pictures")).is_verbatim()); /// assert!(VerbatimUNC(OsStr::new("server"), OsStr::new("share")).is_verbatim()); - /// assert!(VerbatimDisk('C' as u8).is_verbatim()); + /// assert!(VerbatimDisk(b'C').is_verbatim()); /// assert!(!DeviceNS(OsStr::new("BrainInterface")).is_verbatim()); /// assert!(!UNC(OsStr::new("server"), OsStr::new("share")).is_verbatim()); - /// assert!(!Disk('C' as u8).is_verbatim()); + /// assert!(!Disk(b'C').is_verbatim()); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -276,7 +276,7 @@ impl<'a> Prefix<'a> { /// ``` /// use std::path; /// -/// assert!(path::is_separator('/')); +/// assert!(path::is_separator('/')); // '/' works for both Unix and Windows /// assert!(!path::is_separator('❤')); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -401,7 +401,7 @@ enum State { /// let path = Path::new(r"c:\you\later\"); /// match path.components().next().unwrap() { /// Component::Prefix(prefix_component) => { -/// assert_eq!(Prefix::Disk('C' as u8), prefix_component.kind()); +/// assert_eq!(Prefix::Disk(b'C'), prefix_component.kind()); /// assert_eq!(OsStr::new("c:"), prefix_component.as_os_str()); /// } /// _ => unreachable!(), @@ -1040,7 +1040,7 @@ impl<'a> cmp::Ord for Components<'a> { /// [`Deref`]: ../ops/trait.Deref.html /// /// More details about the overall approach can be found in -/// the module documentation. +/// the [module documentation](index.html). /// /// # Examples /// @@ -1186,7 +1186,7 @@ impl PathBuf { self.inner.push(path); } - /// Truncate `self` to [`self.parent`]. + /// Truncates `self` to [`self.parent`]. /// /// Returns `false` and does nothing if [`self.file_name`] is [`None`]. /// Otherwise, returns `true`. @@ -1327,7 +1327,7 @@ impl PathBuf { /// /// [`Box`]: ../../std/boxed/struct.Box.html /// [`Path`]: struct.Path.html - #[unstable(feature = "into_boxed_path", issue = "40380")] + #[stable(feature = "into_boxed_path", since = "1.20.0")] pub fn into_boxed_path(self) -> Box { unsafe { mem::transmute(self.inner.into_boxed_os_str()) } } @@ -1348,10 +1348,10 @@ impl From> for PathBuf { } } -#[stable(feature = "box_from_path_buf", since = "1.18.0")] -impl Into> for PathBuf { - fn into(self) -> Box { - self.into_boxed_path() +#[stable(feature = "box_from_path_buf", since = "1.20.0")] +impl From for Box { + fn from(p: PathBuf) -> Box { + p.into_boxed_path() } } @@ -1499,9 +1499,9 @@ impl AsRef for PathBuf { /// A slice of a path (akin to [`str`]). /// /// This type supports a number of operations for inspecting a path, including -/// breaking the path into its components (separated by `/` or `\`, depending on -/// the platform), extracting the file name, determining whether the path is -/// absolute, and so on. +/// breaking the path into its components (separated by `/` on Unix and by either +/// `/` or `\` on Windows), extracting the file name, determining whether the path +/// is absolute, and so on. /// /// This is an *unsized* type, meaning that it must always be used behind a /// pointer like `&` or [`Box`]. For an owned version of this type, @@ -1512,7 +1512,7 @@ impl AsRef for PathBuf { /// [`PathBuf`]: struct.PathBuf.html /// /// More details about the overall approach can be found in -/// the module documentation. +/// the [module documentation](index.html). /// /// # Examples /// @@ -1520,10 +1520,11 @@ impl AsRef for PathBuf { /// use std::path::Path; /// use std::ffi::OsStr; /// -/// let path = Path::new("/tmp/foo/bar.txt"); +/// // Note: this example does work on Windows +/// let path = Path::new("./foo/bar.txt"); /// /// let parent = path.parent(); -/// assert_eq!(parent, Some(Path::new("/tmp/foo"))); +/// assert_eq!(parent, Some(Path::new("./foo"))); /// /// let file_stem = path.file_stem(); /// assert_eq!(file_stem, Some(OsStr::new("bar"))); @@ -1688,7 +1689,7 @@ impl Path { self.has_root() && (cfg!(unix) || cfg!(target_os = "redox") || self.prefix().is_some()) } - /// Return `false` if the `Path` is relative, i.e. not absolute. + /// Returns `true` if the `Path` is relative, i.e. not absolute. /// /// See [`is_absolute`]'s documentation for more details. /// @@ -2018,7 +2019,7 @@ impl Path { /// * Repeated separators are ignored, so `a/b` and `a//b` both have /// `a` and `b` as components. /// - /// * Occurentces of `.` are normalized away, exept if they are at the + /// * Occurences of `.` are normalized away, except if they are at the /// beginning of the path. For example, `a/./b`, `a/b/`, `a/b/.` and /// `a/b` all have `a` and `b` as components, but `./a/b` starts with /// an additional [`CurDir`] component. @@ -2215,12 +2216,22 @@ impl Path { /// This function will traverse symbolic links to query information about the /// destination file. In case of broken symbolic links this will return `false`. /// + /// If you cannot access the directory containing the file, e.g. because of a + /// permission error, this will return `false`. + /// /// # Examples /// /// ```no_run /// use std::path::Path; /// assert_eq!(Path::new("does_not_exist.txt").exists(), false); /// ``` + /// + /// # See Also + /// + /// This is a convenience function that coerces errors to false. If you want to + /// check errors, call [fs::metadata]. + /// + /// [fs::metadata]: ../../std/fs/fn.metadata.html #[stable(feature = "path_ext", since = "1.5.0")] pub fn exists(&self) -> bool { fs::metadata(self).is_ok() @@ -2231,6 +2242,9 @@ impl Path { /// This function will traverse symbolic links to query information about the /// destination file. In case of broken symbolic links this will return `false`. /// + /// If you cannot access the directory containing the file, e.g. because of a + /// permission error, this will return `false`. + /// /// # Examples /// /// ```no_run @@ -2238,6 +2252,15 @@ impl Path { /// assert_eq!(Path::new("./is_a_directory/").is_file(), false); /// assert_eq!(Path::new("a_file.txt").is_file(), true); /// ``` + /// + /// # See Also + /// + /// This is a convenience function that coerces errors to false. If you want to + /// check errors, call [fs::metadata] and handle its Result. Then call + /// [fs::Metadata::is_file] if it was Ok. + /// + /// [fs::metadata]: ../../std/fs/fn.metadata.html + /// [fs::Metadata::is_file]: ../../std/fs/struct.Metadata.html#method.is_file #[stable(feature = "path_ext", since = "1.5.0")] pub fn is_file(&self) -> bool { fs::metadata(self).map(|m| m.is_file()).unwrap_or(false) @@ -2248,6 +2271,9 @@ impl Path { /// This function will traverse symbolic links to query information about the /// destination file. In case of broken symbolic links this will return `false`. /// + /// If you cannot access the directory containing the file, e.g. because of a + /// permission error, this will return `false`. + /// /// # Examples /// /// ```no_run @@ -2255,6 +2281,15 @@ impl Path { /// assert_eq!(Path::new("./is_a_directory/").is_dir(), true); /// assert_eq!(Path::new("a_file.txt").is_dir(), false); /// ``` + /// + /// # See Also + /// + /// This is a convenience function that coerces errors to false. If you want to + /// check errors, call [fs::metadata] and handle its Result. Then call + /// [fs::Metadata::is_dir] if it was Ok. + /// + /// [fs::metadata]: ../../std/fs/fn.metadata.html + /// [fs::Metadata::is_dir]: ../../std/fs/struct.Metadata.html#method.is_dir #[stable(feature = "path_ext", since = "1.5.0")] pub fn is_dir(&self) -> bool { fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false) @@ -2265,7 +2300,7 @@ impl Path { /// /// [`Box`]: ../../std/boxed/struct.Box.html /// [`PathBuf`]: struct.PathBuf.html - #[unstable(feature = "into_boxed_path", issue = "40380")] + #[stable(feature = "into_boxed_path", since = "1.20.0")] pub fn into_path_buf(self: Box) -> PathBuf { let inner: Box = unsafe { mem::transmute(self) }; PathBuf { inner: OsString::from(inner) } @@ -2281,8 +2316,8 @@ impl AsRef for Path { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for Path { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - self.inner.fmt(formatter) + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.inner, formatter) } } @@ -2314,14 +2349,14 @@ pub struct Display<'a> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a> fmt::Debug for Display<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&self.path.to_string_lossy(), f) + fmt::Debug::fmt(&self.path, f) } } #[stable(feature = "rust1", since = "1.0.0")] impl<'a> fmt::Display for Display<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&self.path.to_string_lossy(), f) + self.path.inner.display(f) } } @@ -3918,4 +3953,10 @@ mod tests { assert_eq!(path, path_buf); assert!(path_buf.into_os_string().capacity() >= 15); } + + #[test] + fn display_format_flags() { + assert_eq!(format!("a{:#<5}b", Path::new("").display()), "a#####b"); + assert_eq!(format!("a{:#<5}b", Path::new("a").display()), "aa####b"); + } } diff --git a/src/libstd/prelude/mod.rs b/src/libstd/prelude/mod.rs index 86e661d794..49cdba21a1 100644 --- a/src/libstd/prelude/mod.rs +++ b/src/libstd/prelude/mod.rs @@ -22,13 +22,14 @@ //! //! On a technical level, Rust inserts //! -//! ```ignore +//! ``` //! extern crate std; //! ``` //! //! into the crate root of every crate, and //! -//! ```ignore +//! ``` +//! # #[allow(unused_imports)] //! use std::prelude::v1::*; //! ``` //! @@ -136,10 +137,10 @@ //! [`std::string`]: ../string/index.html //! [`std::vec`]: ../vec/index.html //! [`to_owned`]: ../borrow/trait.ToOwned.html#tymethod.to_owned -//! [book-closures]: ../../book/closures.html -//! [book-dtor]: ../../book/drop.html -//! [book-enums]: ../../book/enums.html -//! [book-iter]: ../../book/iterators.html +//! [book-closures]: ../../book/first-edition/closures.html +//! [book-dtor]: ../../book/first-edition/drop.html +//! [book-enums]: ../../book/first-edition/enums.html +//! [book-iter]: ../../book/first-edition/iterators.html #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index 61ff8daddf..869299e214 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -320,7 +320,7 @@ mod prim_pointer { } /// /// An array itself is not iterable: /// -/// ```ignore +/// ```compile_fail,E0277 /// let array: [i32; 3] = [0; 3]; /// /// for x in array { } @@ -480,8 +480,10 @@ mod prim_str { } /// Tuples are *heterogeneous*. This means that each element of the tuple can /// have a different type. In that tuple above, it has the type: /// -/// ```rust,ignore +/// ``` +/// # let _: /// (&'static str, i32, char) +/// # = ("hello", 5, 'c'); /// ``` /// /// Tuples are a *sequence*. This means that they can be accessed by position; diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 210b32700a..7adfcc44ad 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -59,7 +59,8 @@ use io::prelude::*; use ffi::OsStr; use fmt; -use io; +use fs; +use io::{self, Initializer}; use path::Path; use str; use sys::pipe::{read2, AnonPipe}; @@ -207,8 +208,9 @@ impl Read for ChildStdout { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - self.inner.read_to_end(buf) + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() } } @@ -249,8 +251,9 @@ impl Read for ChildStderr { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - self.inner.read_to_end(buf) + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() } } @@ -346,15 +349,19 @@ impl Command { /// /// Only one argument can be passed per use. So instead of: /// - /// ```ignore + /// ```no_run + /// # std::process::Command::new("sh") /// .arg("-C /path/to/repo") + /// # ; /// ``` /// /// usage would be: /// - /// ```ignore + /// ```no_run + /// # std::process::Command::new("sh") /// .arg("-C") /// .arg("/path/to/repo") + /// # ; /// ``` /// /// To pass multiple arguments see [`args`]. @@ -542,8 +549,8 @@ impl Command { /// .expect("ls command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] - pub fn stdin(&mut self, cfg: Stdio) -> &mut Command { - self.inner.stdin(cfg.0); + pub fn stdin>(&mut self, cfg: T) -> &mut Command { + self.inner.stdin(cfg.into().0); self } @@ -562,8 +569,8 @@ impl Command { /// .expect("ls command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] - pub fn stdout(&mut self, cfg: Stdio) -> &mut Command { - self.inner.stdout(cfg.0); + pub fn stdout>(&mut self, cfg: T) -> &mut Command { + self.inner.stdout(cfg.into().0); self } @@ -582,8 +589,8 @@ impl Command { /// .expect("ls command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] - pub fn stderr(&mut self, cfg: Stdio) -> &mut Command { - self.inner.stderr(cfg.0); + pub fn stderr>(&mut self, cfg: T) -> &mut Command { + self.inner.stderr(cfg.into().0); self } @@ -751,6 +758,34 @@ impl fmt::Debug for Stdio { } } +#[stable(feature = "stdio_from", since = "1.20.0")] +impl From for Stdio { + fn from(child: ChildStdin) -> Stdio { + Stdio::from_inner(child.into_inner().into()) + } +} + +#[stable(feature = "stdio_from", since = "1.20.0")] +impl From for Stdio { + fn from(child: ChildStdout) -> Stdio { + Stdio::from_inner(child.into_inner().into()) + } +} + +#[stable(feature = "stdio_from", since = "1.20.0")] +impl From for Stdio { + fn from(child: ChildStderr) -> Stdio { + Stdio::from_inner(child.into_inner().into()) + } +} + +#[stable(feature = "stdio_from", since = "1.20.0")] +impl From for Stdio { + fn from(file: fs::File) -> Stdio { + Stdio::from_inner(file.into_inner().into()) + } +} + /// Describes the result of a process after it has terminated. /// /// This `struct` is used to represent the exit status of a child process. diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs index 4f33d72639..8da070e7a4 100644 --- a/src/libstd/rand/mod.rs +++ b/src/libstd/rand/mod.rs @@ -56,7 +56,7 @@ //! between the two sources. (Also note that, on some systems e.g. FreeBSD, both `/dev/random` //! and `/dev/urandom` may block once if the CSPRNG has not seeded yet.) -#![unstable(feature = "rand", issue = "0")] +#![unstable(feature = "rand", issue = "27703")] use cell::RefCell; use fmt; diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index 06fd838ea0..2ee63527c1 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -25,7 +25,7 @@ // Reexport some of our utilities which are expected by other crates. -pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count}; +pub use panicking::{begin_panic_new, begin_panic, begin_panic_fmt, update_panic_count}; #[cfg(not(test))] #[lang = "start"] diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index c120a3045e..5640217581 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -480,9 +480,10 @@ impl Drop for Condvar { mod tests { use sync::mpsc::channel; use sync::{Condvar, Mutex, Arc}; + use sync::atomic::{AtomicBool, Ordering}; use thread; use time::Duration; - use u32; + use u64; #[test] fn smoke() { @@ -547,23 +548,58 @@ mod tests { #[test] #[cfg_attr(target_os = "emscripten", ignore)] - fn wait_timeout_ms() { + fn wait_timeout_wait() { let m = Arc::new(Mutex::new(())); - let m2 = m.clone(); let c = Arc::new(Condvar::new()); - let c2 = c.clone(); - let g = m.lock().unwrap(); - let (g, _no_timeout) = c.wait_timeout(g, Duration::from_millis(1)).unwrap(); - // spurious wakeups mean this isn't necessarily true - // assert!(!no_timeout); - let _t = thread::spawn(move || { - let _g = m2.lock().unwrap(); - c2.notify_one(); - }); - let (g, timeout_res) = c.wait_timeout(g, Duration::from_millis(u32::MAX as u64)).unwrap(); - assert!(!timeout_res.timed_out()); - drop(g); + loop { + let g = m.lock().unwrap(); + let (_g, no_timeout) = c.wait_timeout(g, Duration::from_millis(1)).unwrap(); + // spurious wakeups mean this isn't necessarily true + // so execute test again, if not timeout + if !no_timeout.timed_out() { + continue; + } + + break; + } + } + + #[test] + #[cfg_attr(target_os = "emscripten", ignore)] + fn wait_timeout_wake() { + let m = Arc::new(Mutex::new(())); + let c = Arc::new(Condvar::new()); + + loop { + let g = m.lock().unwrap(); + + let c2 = c.clone(); + let m2 = m.clone(); + + let notified = Arc::new(AtomicBool::new(false)); + let notified_copy = notified.clone(); + + let t = thread::spawn(move || { + let _g = m2.lock().unwrap(); + thread::sleep(Duration::from_millis(1)); + notified_copy.store(true, Ordering::SeqCst); + c2.notify_one(); + }); + let (g, timeout_res) = c.wait_timeout(g, Duration::from_millis(u64::MAX)).unwrap(); + assert!(!timeout_res.timed_out()); + // spurious wakeups mean this isn't necessarily true + // so execute test again, if not notified + if !notified.load(Ordering::SeqCst) { + t.join().unwrap(); + continue; + } + drop(g); + + t.join().unwrap(); + + break; + } } #[test] diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 7d5e1929cd..dcd4c8dfdf 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -499,8 +499,6 @@ unsafe impl Send for Sender { } impl !Sync for Sender { } /// The sending-half of Rust's synchronous [`sync_channel`] type. -/// This half can only be owned by one thread, but it can be cloned -/// to send to other threads. /// /// Messages can be sent through this channel with [`send`] or [`try_send`]. /// @@ -555,9 +553,6 @@ pub struct SyncSender { #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Send for SyncSender {} -#[stable(feature = "rust1", since = "1.0.0")] -impl !Sync for SyncSender {} - /// An error returned from the [`Sender::send`] or [`SyncSender::send`] /// function on **channel**s. /// diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 9a242a96d4..62d8de18f4 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -440,6 +440,13 @@ impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'a, T> { } } +#[stable(feature = "std_guard_impls", since = "1.20.0")] +impl<'a, T: ?Sized + fmt::Display> fmt::Display for MutexGuard<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + (**self).fmt(f) + } +} + pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex { &guard.__lock.inner } diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 95bc8d3093..5c5231f4e8 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -370,6 +370,13 @@ impl<'a, T: fmt::Debug> fmt::Debug for RwLockReadGuard<'a, T> { } } +#[stable(feature = "std_guard_impls", since = "1.20.0")] +impl<'a, T: ?Sized + fmt::Display> fmt::Display for RwLockReadGuard<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + (**self).fmt(f) + } +} + #[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T: fmt::Debug> fmt::Debug for RwLockWriteGuard<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -379,6 +386,13 @@ impl<'a, T: fmt::Debug> fmt::Debug for RwLockWriteGuard<'a, T> { } } +#[stable(feature = "std_guard_impls", since = "1.20.0")] +impl<'a, T: ?Sized + fmt::Display> fmt::Display for RwLockWriteGuard<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + (**self).fmt(f) + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'rwlock, T: ?Sized> Deref for RwLockReadGuard<'rwlock, T> { type Target = T; diff --git a/src/libstd/sys/redox/args.rs b/src/libstd/sys/redox/args.rs index 212895d7b7..6e44ad705f 100644 --- a/src/libstd/sys/redox/args.rs +++ b/src/libstd/sys/redox/args.rs @@ -35,6 +35,12 @@ pub struct Args { _dont_send_or_sync_me: PhantomData<*mut ()>, } +impl Args { + pub fn inner_debug(&self) -> &[OsString] { + self.iter.as_slice() + } +} + impl Iterator for Args { type Item = OsString; fn next(&mut self) -> Option { self.iter.next() } diff --git a/src/libstd/sys/redox/backtrace.rs b/src/libstd/sys/redox/backtrace.rs index 961148fb6b..6cafe3e69b 100644 --- a/src/libstd/sys/redox/backtrace.rs +++ b/src/libstd/sys/redox/backtrace.rs @@ -8,16 +8,25 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use libc; use io; use sys_common::backtrace::Frame; -pub use sys_common::gnu::libbacktrace::*; +pub use sys_common::gnu::libbacktrace::{foreach_symbol_fileline, resolve_symname}; pub struct BacktraceContext; #[inline(never)] -pub fn unwind_backtrace(frames: &mut [Frame]) +pub fn unwind_backtrace(_frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> { Ok((0, BacktraceContext)) } + +pub mod gnu { + use io; + use fs; + use libc::c_char; + + pub fn get_executable_filename() -> io::Result<(Vec, fs::File)> { + Err(io::Error::new(io::ErrorKind::Other, "Not implemented")) + } +} diff --git a/src/libstd/sys/redox/condvar.rs b/src/libstd/sys/redox/condvar.rs index 0ca0987b24..fe4a89c6f3 100644 --- a/src/libstd/sys/redox/condvar.rs +++ b/src/libstd/sys/redox/condvar.rs @@ -13,7 +13,7 @@ use intrinsics::{atomic_cxchg, atomic_xadd, atomic_xchg}; use ptr; use time::Duration; -use sys::mutex::{mutex_lock, mutex_unlock, Mutex}; +use sys::mutex::{mutex_unlock, Mutex}; use sys::syscall::{futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE}; pub struct Condvar { @@ -83,8 +83,6 @@ impl Condvar { while atomic_xchg(*lock, 2) != 0 { let _ = futex(*lock, FUTEX_WAIT, 2, 0, ptr::null_mut()); } - - mutex_lock(*lock); } } diff --git a/src/libstd/sys/redox/ext/fs.rs b/src/libstd/sys/redox/ext/fs.rs index fc81cc737d..9a0d1e06da 100644 --- a/src/libstd/sys/redox/ext/fs.rs +++ b/src/libstd/sys/redox/ext/fs.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Unix-specific extensions to primitives in the `std::fs` module. +//! Redox-specific extensions to primitives in the `std::fs` module. #![stable(feature = "rust1", since = "1.0.0")] @@ -18,23 +18,25 @@ use path::Path; use sys; use sys_common::{FromInner, AsInner, AsInnerMut}; -/// Unix-specific extensions to `Permissions` +/// Redox-specific extensions to `Permissions` #[stable(feature = "fs_ext", since = "1.1.0")] pub trait PermissionsExt { - /// Returns the underlying raw `mode_t` bits that are the standard Unix + /// Returns the underlying raw `mode_t` bits that are the standard Redox /// permissions for this file. /// /// # Examples /// - /// ```rust,ignore + /// ```no_run /// use std::fs::File; - /// use std::os::unix::fs::PermissionsExt; + /// use std::os::redox::fs::PermissionsExt; /// + /// # fn run() -> std::io::Result<()> { /// let f = File::create("foo.txt")?; /// let metadata = f.metadata()?; /// let permissions = metadata.permissions(); /// /// println!("permissions: {}", permissions.mode()); + /// # Ok(()) } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn mode(&self) -> u32; @@ -43,28 +45,30 @@ pub trait PermissionsExt { /// /// # Examples /// - /// ```rust,ignore + /// ```no_run /// use std::fs::File; - /// use std::os::unix::fs::PermissionsExt; + /// use std::os::redox::fs::PermissionsExt; /// + /// # fn run() -> std::io::Result<()> { /// let f = File::create("foo.txt")?; /// let metadata = f.metadata()?; /// let mut permissions = metadata.permissions(); /// /// permissions.set_mode(0o644); // Read/write for owner and read for others. /// assert_eq!(permissions.mode(), 0o644); + /// # Ok(()) } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn set_mode(&mut self, mode: u32); - /// Creates a new instance of `Permissions` from the given set of Unix + /// Creates a new instance of `Permissions` from the given set of Redox /// permission bits. /// /// # Examples /// - /// ```rust,ignore + /// ``` /// use std::fs::Permissions; - /// use std::os::unix::fs::PermissionsExt; + /// use std::os::redox::fs::PermissionsExt; /// /// // Read/write for owner and read for others. /// let permissions = Permissions::from_mode(0o644); @@ -89,7 +93,7 @@ impl PermissionsExt for Permissions { } } -/// Unix-specific extensions to `OpenOptions` +/// Redox-specific extensions to `OpenOptions` #[stable(feature = "fs_ext", since = "1.1.0")] pub trait OpenOptionsExt { /// Sets the mode bits that a new file will be created with. @@ -102,14 +106,17 @@ pub trait OpenOptionsExt { /// /// # Examples /// - /// ```rust,ignore + /// ```no_run + /// # #![feature(libc)] /// extern crate libc; /// use std::fs::OpenOptions; - /// use std::os::unix::fs::OpenOptionsExt; + /// use std::os::redox::fs::OpenOptionsExt; /// + /// # fn main() { /// let mut options = OpenOptions::new(); /// options.mode(0o644); // Give read/write for owner and read for others. /// let file = options.open("foo.txt"); + /// # } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn mode(&mut self, mode: u32) -> &mut Self; @@ -124,17 +131,20 @@ pub trait OpenOptionsExt { /// /// # Examples /// - /// ```rust,ignore + /// ```no_run + /// # #![feature(libc)] /// extern crate libc; /// use std::fs::OpenOptions; - /// use std::os::unix::fs::OpenOptionsExt; + /// use std::os::redox::fs::OpenOptionsExt; /// + /// # fn main() { /// let mut options = OpenOptions::new(); /// options.write(true); - /// if cfg!(unix) { + /// if cfg!(target_os = "redox") { /// options.custom_flags(libc::O_NOFOLLOW); /// } /// let file = options.open("foo.txt"); + /// # } /// ``` #[stable(feature = "open_options_ext", since = "1.10.0")] fn custom_flags(&mut self, flags: i32) -> &mut Self; @@ -167,6 +177,8 @@ pub trait MetadataExt { #[stable(feature = "metadata_ext", since = "1.1.0")] fn mode(&self) -> u32; #[stable(feature = "metadata_ext", since = "1.1.0")] + fn nlink(&self) -> u64; + #[stable(feature = "metadata_ext", since = "1.1.0")] fn uid(&self) -> u32; #[stable(feature = "metadata_ext", since = "1.1.0")] fn gid(&self) -> u32; @@ -184,6 +196,10 @@ pub trait MetadataExt { fn ctime(&self) -> i64; #[stable(feature = "metadata_ext", since = "1.1.0")] fn ctime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext", since = "1.1.0")] + fn blksize(&self) -> u64; + #[stable(feature = "metadata_ext", since = "1.1.0")] + fn blocks(&self) -> u64; } #[stable(feature = "metadata_ext", since = "1.1.0")] @@ -197,6 +213,9 @@ impl MetadataExt for fs::Metadata { fn mode(&self) -> u32 { self.as_inner().as_inner().st_mode as u32 } + fn nlink(&self) -> u64 { + self.as_inner().as_inner().st_nlink as u64 + } fn uid(&self) -> u32 { self.as_inner().as_inner().st_uid as u32 } @@ -224,9 +243,15 @@ impl MetadataExt for fs::Metadata { fn ctime_nsec(&self) -> i64 { self.as_inner().as_inner().st_ctime_nsec as i64 } + fn blksize(&self) -> u64 { + self.as_inner().as_inner().st_blksize as u64 + } + fn blocks(&self) -> u64 { + self.as_inner().as_inner().st_blocks as u64 + } } -/// Add special unix types (block/char device, fifo and socket) +/// Add special Redox types (block/char device, fifo and socket) #[stable(feature = "file_type_ext", since = "1.5.0")] pub trait FileTypeExt { /// Returns whether this file type is a block device. @@ -267,7 +292,7 @@ impl FileTypeExt for fs::FileType { /// # Examples /// /// ``` -/// use std::os::unix::fs; +/// use std::os::redox::fs; /// /// # fn foo() -> std::io::Result<()> { /// fs::symlink("a.txt", "b.txt")?; @@ -281,16 +306,16 @@ pub fn symlink, Q: AsRef>(src: P, dst: Q) -> io::Result<()> } #[stable(feature = "dir_builder", since = "1.6.0")] -/// An extension trait for `fs::DirBuilder` for unix-specific options. +/// An extension trait for `fs::DirBuilder` for Redox-specific options. pub trait DirBuilderExt { /// Sets the mode to create new directories with. This option defaults to /// 0o777. /// /// # Examples /// - /// ```ignore + /// ```no_run /// use std::fs::DirBuilder; - /// use std::os::unix::fs::DirBuilderExt; + /// use std::os::redox::fs::DirBuilderExt; /// /// let mut builder = DirBuilder::new(); /// builder.mode(0o755); diff --git a/src/libstd/sys/redox/fast_thread_local.rs b/src/libstd/sys/redox/fast_thread_local.rs index 7dc61ce665..9f0eee024d 100644 --- a/src/libstd/sys/redox/fast_thread_local.rs +++ b/src/libstd/sys/redox/fast_thread_local.rs @@ -57,7 +57,7 @@ impl Key { } } -unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { +pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { // The fallback implementation uses a vanilla OS-based TLS key to track // the list of destructors that need to be run for this thread. The key // then has its own destructor which runs all the other destructors. @@ -115,3 +115,7 @@ pub unsafe extern fn destroy_value(ptr: *mut u8) { ptr::drop_in_place((*ptr).inner.get()); } } + +pub fn requires_move_before_drop() -> bool { + false +} diff --git a/src/libstd/sys/redox/fd.rs b/src/libstd/sys/redox/fd.rs index b6de68a9dc..1b37aafef5 100644 --- a/src/libstd/sys/redox/fd.rs +++ b/src/libstd/sys/redox/fd.rs @@ -14,7 +14,6 @@ use io::{self, Read}; use mem; use sys::{cvt, syscall}; use sys_common::AsInner; -use sys_common::io::read_to_end_uninitialized; pub struct FileDesc { fd: usize, @@ -78,10 +77,6 @@ impl<'a> Read for &'a FileDesc { fn read(&mut self, buf: &mut [u8]) -> io::Result { (**self).read(buf) } - - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - unsafe { read_to_end_uninitialized(self, buf) } - } } impl AsInner for FileDesc { diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs index a8391d2b89..918893097f 100644 --- a/src/libstd/sys/redox/fs.rs +++ b/src/libstd/sys/redox/fs.rs @@ -119,10 +119,10 @@ impl FilePermissions { impl FileType { pub fn is_dir(&self) -> bool { self.is(syscall::MODE_DIR) } pub fn is_file(&self) -> bool { self.is(syscall::MODE_FILE) } - pub fn is_symlink(&self) -> bool { false /*FIXME: Implement symlink mode*/ } + pub fn is_symlink(&self) -> bool { self.is(syscall::MODE_SYMLINK) } pub fn is(&self, mode: u16) -> bool { - self.mode & (syscall::MODE_DIR | syscall::MODE_FILE) == mode + self.mode & syscall::MODE_TYPE == mode } } @@ -285,10 +285,6 @@ impl File { self.0.read(buf) } - pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { - self.0.read_to_end(buf) - } - pub fn write(&self, buf: &[u8]) -> io::Result { self.0.write(buf) } @@ -387,9 +383,10 @@ pub fn unlink(p: &Path) -> io::Result<()> { Ok(()) } -pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> { - ::sys_common::util::dumb_print(format_args!("Rename\n")); - unimplemented!(); +pub fn rename(old: &Path, new: &Path) -> io::Result<()> { + copy(old, new)?; + unlink(old)?; + Ok(()) } pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { @@ -424,12 +421,19 @@ fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { } pub fn readlink(p: &Path) -> io::Result { - canonicalize(p) -} - -pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> { - ::sys_common::util::dumb_print(format_args!("Symlink\n")); - unimplemented!(); + let fd = cvt(syscall::open(p.to_str().unwrap(), syscall::O_SYMLINK | syscall::O_RDONLY))?; + let mut buf: [u8; 4096] = [0; 4096]; + let count = cvt(syscall::read(fd, &mut buf))?; + cvt(syscall::close(fd))?; + Ok(PathBuf::from(unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) })) +} + +pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> { + let fd = cvt(syscall::open(dst.to_str().unwrap(), + syscall::O_SYMLINK | syscall::O_CREAT | syscall::O_WRONLY | 0o777))?; + cvt(syscall::write(fd, src.to_str().unwrap().as_bytes()))?; + cvt(syscall::close(fd))?; + Ok(()) } pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> { @@ -444,7 +448,10 @@ pub fn stat(p: &Path) -> io::Result { } pub fn lstat(p: &Path) -> io::Result { - stat(p) + let fd = cvt(syscall::open(p.to_str().unwrap(), + syscall::O_CLOEXEC | syscall::O_STAT | syscall::O_NOFOLLOW))?; + let file = File(FileDesc::new(fd)); + file.file_attr() } pub fn canonicalize(p: &Path) -> io::Result { diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs index 31c40ea58b..7c728ebb1a 100644 --- a/src/libstd/sys/redox/mod.rs +++ b/src/libstd/sys/redox/mod.rs @@ -39,25 +39,7 @@ pub mod thread_local; pub mod time; #[cfg(not(test))] -pub fn init() { - use alloc::oom; - - oom::set_oom_handler(oom_handler); - - // A nicer handler for out-of-memory situations than the default one. This - // one prints a message to stderr before aborting. It is critical that this - // code does not allocate any memory since we are in an OOM situation. Any - // errors are ignored while printing since there's nothing we can do about - // them and we are about to exit anyways. - fn oom_handler() -> ! { - use intrinsics; - let msg = "fatal runtime error: out of memory\n"; - unsafe { - let _ = syscall::write(2, msg.as_bytes()); - intrinsics::abort(); - } - } -} +pub fn init() {} pub fn decode_error_kind(errno: i32) -> ErrorKind { match errno { diff --git a/src/libstd/sys/redox/net/tcp.rs b/src/libstd/sys/redox/net/tcp.rs index 936097d7fb..98ec3aa3e2 100644 --- a/src/libstd/sys/redox/net/tcp.rs +++ b/src/libstd/sys/redox/net/tcp.rs @@ -17,7 +17,6 @@ use sys::fs::{File, OpenOptions}; use sys::syscall::TimeSpec; use sys_common::{AsInner, FromInner, IntoInner}; use time::Duration; -use vec::Vec; use super::{path_to_peer_addr, path_to_local_addr}; @@ -33,6 +32,10 @@ impl TcpStream { Ok(TcpStream(File::open(&Path::new(path.as_str()), &options)?)) } + pub fn connect_timeout(_addr: &SocketAddr, _timeout: Duration) -> Result { + Err(Error::new(ErrorKind::Other, "TcpStream::connect_timeout not implemented")) + } + pub fn duplicate(&self) -> Result { Ok(TcpStream(self.0.dup(&[])?)) } @@ -41,10 +44,6 @@ impl TcpStream { self.0.read(buf) } - pub fn read_to_end(&self, buf: &mut Vec) -> Result { - self.0.read_to_end(buf) - } - pub fn write(&self, buf: &[u8]) -> Result { self.0.write(buf) } diff --git a/src/libstd/sys/redox/os.rs b/src/libstd/sys/redox/os.rs index 9d459581dd..e38b7b29f4 100644 --- a/src/libstd/sys/redox/os.rs +++ b/src/libstd/sys/redox/os.rs @@ -179,7 +179,7 @@ pub fn getenv(key: &OsStr) -> io::Result> { pub fn setenv(key: &OsStr, value: &OsStr) -> io::Result<()> { if ! key.is_empty() { - let mut file = ::fs::File::open(&("env:".to_owned() + key.to_str().unwrap()))?; + let mut file = ::fs::File::create(&("env:".to_owned() + key.to_str().unwrap()))?; file.write_all(value.as_bytes())?; file.set_len(value.len() as u64)?; } diff --git a/src/libstd/sys/redox/os_str.rs b/src/libstd/sys/redox/os_str.rs index c2bba07f68..c54286353a 100644 --- a/src/libstd/sys/redox/os_str.rs +++ b/src/libstd/sys/redox/os_str.rs @@ -12,10 +12,11 @@ /// a `Vec`/`[u8]`. use borrow::Cow; -use fmt::{self, Debug}; +use fmt; use str; use mem; use sys_common::{AsInner, IntoInner}; +use std_unicode::lossy::Utf8Lossy; #[derive(Clone, Hash)] pub struct Buf { @@ -26,15 +27,27 @@ pub struct Slice { pub inner: [u8] } -impl Debug for Slice { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - self.to_string_lossy().fmt(formatter) +impl fmt::Debug for Slice { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter) } } -impl Debug for Buf { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - self.as_slice().fmt(formatter) +impl fmt::Display for Slice { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter) + } +} + +impl fmt::Debug for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(self.as_slice(), formatter) + } +} + +impl fmt::Display for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.as_slice(), formatter) } } diff --git a/src/libstd/sys/redox/pipe.rs b/src/libstd/sys/redox/pipe.rs index e7240fbe7b..28645facd9 100644 --- a/src/libstd/sys/redox/pipe.rs +++ b/src/libstd/sys/redox/pipe.rs @@ -34,10 +34,6 @@ impl AnonPipe { self.0.read(buf) } - pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { - self.0.read_to_end(buf) - } - pub fn write(&self, buf: &[u8]) -> io::Result { self.0.write(buf) } @@ -53,8 +49,8 @@ pub fn read2(p1: AnonPipe, //FIXME: Use event based I/O multiplexing //unimplemented!() - p1.read_to_end(v1)?; - p2.read_to_end(v2)?; + p1.0.read_to_end(v1)?; + p2.0.read_to_end(v2)?; Ok(()) diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs index 95e9438cd7..62d873d257 100644 --- a/src/libstd/sys/redox/process.rs +++ b/src/libstd/sys/redox/process.rs @@ -400,6 +400,18 @@ impl Stdio { } } +impl From for Stdio { + fn from(pipe: AnonPipe) -> Stdio { + Stdio::Fd(pipe.into_fd()) + } +} + +impl From for Stdio { + fn from(file: File) -> Stdio { + Stdio::Fd(file.into_fd()) + } +} + impl ChildStdio { fn fd(&self) -> Option { match *self { diff --git a/src/libstd/sys/redox/stdio.rs b/src/libstd/sys/redox/stdio.rs index 607eef051d..c839531cc2 100644 --- a/src/libstd/sys/redox/stdio.rs +++ b/src/libstd/sys/redox/stdio.rs @@ -25,13 +25,6 @@ impl Stdin { fd.into_raw(); ret } - - pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { - let fd = FileDesc::new(0); - let ret = fd.read_to_end(buf); - fd.into_raw(); - ret - } } impl Stdout { diff --git a/src/libstd/sys/redox/syscall/flag.rs b/src/libstd/sys/redox/syscall/flag.rs index 9f0d3e6f77..65ad9842d6 100644 --- a/src/libstd/sys/redox/syscall/flag.rs +++ b/src/libstd/sys/redox/syscall/flag.rs @@ -33,6 +33,7 @@ pub const MAP_WRITE_COMBINE: usize = 2; pub const MODE_TYPE: u16 = 0xF000; pub const MODE_DIR: u16 = 0x4000; pub const MODE_FILE: u16 = 0x8000; +pub const MODE_SYMLINK: u16 = 0xA000; pub const MODE_PERM: u16 = 0x0FFF; pub const MODE_SETUID: u16 = 0o4000; @@ -53,6 +54,8 @@ pub const O_TRUNC: usize = 0x0400_0000; pub const O_EXCL: usize = 0x0800_0000; pub const O_DIRECTORY: usize = 0x1000_0000; pub const O_STAT: usize = 0x2000_0000; +pub const O_SYMLINK: usize = 0x4000_0000; +pub const O_NOFOLLOW: usize = 0x8000_0000; pub const O_ACCMODE: usize = O_RDONLY | O_WRONLY | O_RDWR; pub const SEEK_SET: usize = 0; diff --git a/src/libstd/sys/unix/args.rs b/src/libstd/sys/unix/args.rs index 6e35a47279..bbdcb5d361 100644 --- a/src/libstd/sys/unix/args.rs +++ b/src/libstd/sys/unix/args.rs @@ -35,6 +35,12 @@ pub struct Args { _dont_send_or_sync_me: PhantomData<*mut ()>, } +impl Args { + pub fn inner_debug(&self) -> &[OsString] { + self.iter.as_slice() + } +} + impl Iterator for Args { type Item = OsString; fn next(&mut self) -> Option { self.iter.next() } diff --git a/src/libstd/sys/unix/condvar.rs b/src/libstd/sys/unix/condvar.rs index 27b9f131d1..b9ea573b32 100644 --- a/src/libstd/sys/unix/condvar.rs +++ b/src/libstd/sys/unix/condvar.rs @@ -23,6 +23,14 @@ const TIMESPEC_MAX: libc::timespec = libc::timespec { tv_nsec: 1_000_000_000 - 1, }; +fn saturating_cast_to_time_t(value: u64) -> libc::time_t { + if value > ::max_value() as u64 { + ::max_value() + } else { + value as libc::time_t + } +} + impl Condvar { pub const fn new() -> Condvar { // Might be moved and address is changing it is better to avoid @@ -79,8 +87,7 @@ impl Condvar { // Nanosecond calculations can't overflow because both values are below 1e9. let nsec = dur.subsec_nanos() as libc::c_long + now.tv_nsec as libc::c_long; - // FIXME: Casting u64 into time_t could truncate the value. - let sec = (dur.as_secs() as libc::time_t) + let sec = saturating_cast_to_time_t(dur.as_secs()) .checked_add((nsec / 1_000_000_000) as libc::time_t) .and_then(|s| s.checked_add(now.tv_sec)); let nsec = nsec % 1_000_000_000; @@ -100,10 +107,29 @@ impl Condvar { // https://github.com/llvm-mirror/libcxx/blob/release_35/src/condition_variable.cpp#L46 // https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367 #[cfg(any(target_os = "macos", target_os = "ios", target_os = "android"))] - pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { + pub unsafe fn wait_timeout(&self, mutex: &Mutex, mut dur: Duration) -> bool { use ptr; use time::Instant; + // 1000 years + let max_dur = Duration::from_secs(1000 * 365 * 86400); + + if dur > max_dur { + // OSX implementation of `pthread_cond_timedwait` is buggy + // with super long durations. When duration is greater than + // 0x100_0000_0000_0000 seconds, `pthread_cond_timedwait` + // in macOS Sierra return error 316. + // + // This program demonstrates the issue: + // https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c + // + // To work around this issue, and possible bugs of other OSes, timeout + // is clamped to 1000 years, which is allowable per the API of `wait_timeout` + // because of spurious wakeups. + + dur = max_dur; + } + // First, figure out what time it currently is, in both system and // stable time. pthread_cond_timedwait uses system time, but we want to // report timeout based on stable time. @@ -116,7 +142,7 @@ impl Condvar { (sys_now.tv_usec * 1000) as libc::c_long; let extra = (nsec / 1_000_000_000) as libc::time_t; let nsec = nsec % 1_000_000_000; - let seconds = dur.as_secs() as libc::time_t; + let seconds = saturating_cast_to_time_t(dur.as_secs()); let timeout = sys_now.tv_sec.checked_add(extra).and_then(|s| { s.checked_add(seconds) diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index 17de46636b..26710bf61d 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -73,15 +73,17 @@ pub trait PermissionsExt { /// /// # Examples /// - /// ```rust,ignore + /// ```no_run /// use std::fs::File; /// use std::os::unix::fs::PermissionsExt; /// + /// # fn run() -> std::io::Result<()> { /// let f = File::create("foo.txt")?; /// let metadata = f.metadata()?; /// let permissions = metadata.permissions(); /// /// println!("permissions: {}", permissions.mode()); + /// # Ok(()) } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn mode(&self) -> u32; @@ -90,16 +92,18 @@ pub trait PermissionsExt { /// /// # Examples /// - /// ```rust,ignore + /// ```no_run /// use std::fs::File; /// use std::os::unix::fs::PermissionsExt; /// + /// # fn run() -> std::io::Result<()> { /// let f = File::create("foo.txt")?; /// let metadata = f.metadata()?; /// let mut permissions = metadata.permissions(); /// /// permissions.set_mode(0o644); // Read/write for owner and read for others. /// assert_eq!(permissions.mode(), 0o644); + /// # Ok(()) } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn set_mode(&mut self, mode: u32); @@ -109,7 +113,7 @@ pub trait PermissionsExt { /// /// # Examples /// - /// ```rust,ignore + /// ``` /// use std::fs::Permissions; /// use std::os::unix::fs::PermissionsExt; /// @@ -149,14 +153,17 @@ pub trait OpenOptionsExt { /// /// # Examples /// - /// ```rust,ignore + /// ```no_run + /// # #![feature(libc)] /// extern crate libc; /// use std::fs::OpenOptions; /// use std::os::unix::fs::OpenOptionsExt; /// + /// # fn main() { /// let mut options = OpenOptions::new(); /// options.mode(0o644); // Give read/write for owner and read for others. /// let file = options.open("foo.txt"); + /// # } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn mode(&mut self, mode: u32) -> &mut Self; @@ -171,17 +178,20 @@ pub trait OpenOptionsExt { /// /// # Examples /// - /// ```rust,ignore + /// ```no_run + /// # #![feature(libc)] /// extern crate libc; /// use std::fs::OpenOptions; /// use std::os::unix::fs::OpenOptionsExt; /// + /// # fn main() { /// let mut options = OpenOptions::new(); /// options.write(true); /// if cfg!(unix) { /// options.custom_flags(libc::O_NOFOLLOW); /// } /// let file = options.open("foo.txt"); + /// # } /// ``` #[stable(feature = "open_options_ext", since = "1.10.0")] fn custom_flags(&mut self, flags: i32) -> &mut Self; @@ -353,7 +363,7 @@ pub trait DirBuilderExt { /// /// # Examples /// - /// ```ignore + /// ```no_run /// use std::fs::DirBuilder; /// use std::os::unix::fs::DirBuilderExt; /// diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index d688f2fa50..94b87a6bff 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -17,7 +17,7 @@ use libc; use ascii; use ffi::OsStr; use fmt; -use io; +use io::{self, Initializer}; use mem; use net::Shutdown; use os::unix::ffi::OsStrExt; @@ -516,8 +516,9 @@ impl io::Read for UnixStream { io::Read::read(&mut &*self, buf) } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - io::Read::read_to_end(&mut &*self, buf) + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() } } @@ -527,8 +528,9 @@ impl<'a> io::Read for &'a UnixStream { self.0.read(buf) } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - self.0.read_to_end(buf) + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() } } diff --git a/src/libstd/sys/unix/fast_thread_local.rs b/src/libstd/sys/unix/fast_thread_local.rs index 6b3973de84..6cdbe5df75 100644 --- a/src/libstd/sys/unix/fast_thread_local.rs +++ b/src/libstd/sys/unix/fast_thread_local.rs @@ -11,92 +11,6 @@ #![cfg(target_thread_local)] #![unstable(feature = "thread_local_internals", issue = "0")] -use cell::{Cell, UnsafeCell}; -use fmt; -use mem; -use ptr; - -pub struct Key { - inner: UnsafeCell>, - - // Metadata to keep track of the state of the destructor. Remember that - // these variables are thread-local, not global. - dtor_registered: Cell, - dtor_running: Cell, -} - -impl fmt::Debug for Key { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad("Key { .. }") - } -} - -unsafe impl ::marker::Sync for Key { } - -impl Key { - pub const fn new() -> Key { - Key { - inner: UnsafeCell::new(None), - dtor_registered: Cell::new(false), - dtor_running: Cell::new(false) - } - } - - pub fn get(&'static self) -> Option<&'static UnsafeCell>> { - unsafe { - if mem::needs_drop::() && self.dtor_running.get() { - return None - } - self.register_dtor(); - } - Some(&self.inner) - } - - unsafe fn register_dtor(&self) { - if !mem::needs_drop::() || self.dtor_registered.get() { - return - } - - register_dtor(self as *const _ as *mut u8, - destroy_value::); - self.dtor_registered.set(true); - } -} - -#[cfg(any(target_os = "linux", target_os = "fuchsia"))] -unsafe fn register_dtor_fallback(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { - // The fallback implementation uses a vanilla OS-based TLS key to track - // the list of destructors that need to be run for this thread. The key - // then has its own destructor which runs all the other destructors. - // - // The destructor for DTORS is a little special in that it has a `while` - // loop to continuously drain the list of registered destructors. It - // *should* be the case that this loop always terminates because we - // provide the guarantee that a TLS key cannot be set after it is - // flagged for destruction. - use sys_common::thread_local as os; - - static DTORS: os::StaticKey = os::StaticKey::new(Some(run_dtors)); - type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>; - if DTORS.get().is_null() { - let v: Box = box Vec::new(); - DTORS.set(Box::into_raw(v) as *mut u8); - } - let list: &mut List = &mut *(DTORS.get() as *mut List); - list.push((t, dtor)); - - unsafe extern fn run_dtors(mut ptr: *mut u8) { - while !ptr.is_null() { - let list: Box = Box::from_raw(ptr as *mut List); - for &(ptr, dtor) in list.iter() { - dtor(ptr); - } - ptr = DTORS.get(); - DTORS.set(ptr::null_mut()); - } - } -} - // Since what appears to be glibc 2.18 this symbol has been shipped which // GCC and clang both use to invoke destructors in thread_local globals, so // let's do the same! @@ -107,9 +21,10 @@ unsafe fn register_dtor_fallback(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { // // Due to rust-lang/rust#18804, make sure this is not generic! #[cfg(target_os = "linux")] -unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { - use mem; +pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { use libc; + use mem; + use sys_common::thread_local::register_dtor_fallback; extern { #[linkage = "extern_weak"] @@ -132,7 +47,7 @@ unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { // The disassembly of thread_local globals in C++ (at least produced by // clang) will have this show up in the output. #[cfg(target_os = "macos")] -unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { +pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { extern { fn _tlv_atexit(dtor: unsafe extern fn(*mut u8), arg: *mut u8); @@ -143,17 +58,9 @@ unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { // Just use the thread_local fallback implementation, at least until there's // a more direct implementation. #[cfg(target_os = "fuchsia")] -unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { - register_dtor_fallback(t, dtor); -} - -pub unsafe extern fn destroy_value(ptr: *mut u8) { - let ptr = ptr as *mut Key; - // Right before we run the user destructor be sure to flag the - // destructor as running for this thread so calls to `get` will return - // `None`. - (*ptr).dtor_running.set(true); +pub use sys_common::thread_local::register_dtor_fallback as register_dtor; +pub fn requires_move_before_drop() -> bool { // The macOS implementation of TLS apparently had an odd aspect to it // where the pointer we have may be overwritten while this destructor // is running. Specifically if a TLS destructor re-accesses TLS it may @@ -166,9 +73,5 @@ pub unsafe extern fn destroy_value(ptr: *mut u8) { // // Hence, we use `ptr::read` on macOS (to move to a "safe" location) // instead of drop_in_place. - if cfg!(target_os = "macos") { - ptr::read((*ptr).inner.get()); - } else { - ptr::drop_in_place((*ptr).inner.get()); - } + cfg!(target_os = "macos") } diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index 405fac2b9d..138087f165 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -17,7 +17,6 @@ use mem; use sync::atomic::{AtomicBool, Ordering}; use sys::cvt; use sys_common::AsInner; -use sys_common::io::read_to_end_uninitialized; #[derive(Debug)] pub struct FileDesc { @@ -232,10 +231,6 @@ impl<'a> Read for &'a FileDesc { fn read(&mut self, buf: &mut [u8]) -> io::Result { (**self).read(buf) } - - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - unsafe { read_to_end_uninitialized(self, buf) } - } } impl AsInner for FileDesc { diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index e893a13909..59dceba895 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -491,10 +491,6 @@ impl File { self.0.read(buf) } - pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { - self.0.read_to_end(buf) - } - pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result { self.0.read_at(buf, offset) } diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index 854d380d12..46e5acdf3d 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -59,8 +59,6 @@ pub mod stdio; #[cfg(not(test))] pub fn init() { - use alloc::oom; - // By default, some platforms will send a *signal* when an EPIPE error // would otherwise be delivered. This runtime doesn't install a SIGPIPE // handler, causing it to kill the program, which isn't exactly what we @@ -72,24 +70,6 @@ pub fn init() { reset_sigpipe(); } - oom::set_oom_handler(oom_handler); - - // A nicer handler for out-of-memory situations than the default one. This - // one prints a message to stderr before aborting. It is critical that this - // code does not allocate any memory since we are in an OOM situation. Any - // errors are ignored while printing since there's nothing we can do about - // them and we are about to exit anyways. - fn oom_handler() -> ! { - use intrinsics; - let msg = "fatal runtime error: out of memory\n"; - unsafe { - libc::write(libc::STDERR_FILENO, - msg.as_ptr() as *const libc::c_void, - msg.len()); - intrinsics::abort(); - } - } - #[cfg(not(any(target_os = "nacl", target_os = "emscripten", target_os="fuchsia")))] unsafe fn reset_sigpipe() { assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR); diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index 5efddca110..668b2f92ab 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -17,7 +17,8 @@ use str; use sys::fd::FileDesc; use sys_common::{AsInner, FromInner, IntoInner}; use sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr}; -use time::Duration; +use time::{Duration, Instant}; +use cmp; pub use sys::{cvt, cvt_r}; pub extern crate libc as netc; @@ -122,6 +123,70 @@ impl Socket { } } + pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { + self.set_nonblocking(true)?; + let r = unsafe { + let (addrp, len) = addr.into_inner(); + cvt(libc::connect(self.0.raw(), addrp, len)) + }; + self.set_nonblocking(false)?; + + match r { + Ok(_) => return Ok(()), + // there's no ErrorKind for EINPROGRESS :( + Err(ref e) if e.raw_os_error() == Some(libc::EINPROGRESS) => {} + Err(e) => return Err(e), + } + + let mut pollfd = libc::pollfd { + fd: self.0.raw(), + events: libc::POLLOUT, + revents: 0, + }; + + if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 { + return Err(io::Error::new(io::ErrorKind::InvalidInput, + "cannot set a 0 duration timeout")); + } + + let start = Instant::now(); + + loop { + let elapsed = start.elapsed(); + if elapsed >= timeout { + return Err(io::Error::new(io::ErrorKind::TimedOut, "connection timed out")); + } + + let timeout = timeout - elapsed; + let mut timeout = timeout.as_secs() + .saturating_mul(1_000) + .saturating_add(timeout.subsec_nanos() as u64 / 1_000_000); + if timeout == 0 { + timeout = 1; + } + + let timeout = cmp::min(timeout, c_int::max_value() as u64) as c_int; + + match unsafe { libc::poll(&mut pollfd, 1, timeout) } { + -1 => { + let err = io::Error::last_os_error(); + if err.kind() != io::ErrorKind::Interrupted { + return Err(err); + } + } + 0 => {} + _ => { + if pollfd.revents & libc::POLLOUT == 0 { + if let Some(e) = self.take_error()? { + return Err(e); + } + } + return Ok(()); + } + } + } + } + pub fn accept(&self, storage: *mut sockaddr, len: *mut socklen_t) -> io::Result { // Unfortunately the only known way right now to accept a socket and @@ -198,10 +263,6 @@ impl Socket { self.recv_from_with_flags(buf, MSG_PEEK) } - pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { - self.0.read_to_end(buf) - } - pub fn write(&self, buf: &[u8]) -> io::Result { self.0.write(buf) } diff --git a/src/libstd/sys/unix/os_str.rs b/src/libstd/sys/unix/os_str.rs index f5b942d334..777db17e3e 100644 --- a/src/libstd/sys/unix/os_str.rs +++ b/src/libstd/sys/unix/os_str.rs @@ -12,10 +12,11 @@ /// a `Vec`/`[u8]`. use borrow::Cow; -use fmt::{self, Debug}; +use fmt; use str; use mem; use sys_common::{AsInner, IntoInner}; +use std_unicode::lossy::Utf8Lossy; #[derive(Clone, Hash)] pub struct Buf { @@ -26,15 +27,27 @@ pub struct Slice { pub inner: [u8] } -impl Debug for Slice { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - self.to_string_lossy().fmt(formatter) +impl fmt::Debug for Slice { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter) } } -impl Debug for Buf { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - self.as_slice().fmt(formatter) +impl fmt::Display for Slice { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter) + } +} + +impl fmt::Debug for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(self.as_slice(), formatter) + } +} + +impl fmt::Display for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.as_slice(), formatter) } } diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index ca5ef4bcfc..ec9b6f17dc 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -71,10 +71,6 @@ impl AnonPipe { self.0.read(buf) } - pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { - self.0.read_to_end(buf) - } - pub fn write(&self, buf: &[u8]) -> io::Result { self.0.write(buf) } diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index e9f4100906..32fcee1e46 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -315,6 +315,18 @@ impl Stdio { } } +impl From for Stdio { + fn from(pipe: AnonPipe) -> Stdio { + Stdio::Fd(pipe.into_fd()) + } +} + +impl From for Stdio { + fn from(file: File) -> Stdio { + Stdio::Fd(file.into_fd()) + } +} + impl ChildStdio { pub fn fd(&self) -> Option { match *self { diff --git a/src/libstd/sys/unix/stdio.rs b/src/libstd/sys/unix/stdio.rs index 6d38b00b39..7a8fe25d98 100644 --- a/src/libstd/sys/unix/stdio.rs +++ b/src/libstd/sys/unix/stdio.rs @@ -25,13 +25,6 @@ impl Stdin { fd.into_raw(); ret } - - pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { - let fd = FileDesc::new(libc::STDIN_FILENO); - let ret = fd.read_to_end(buf); - fd.into_raw(); - ret - } } impl Stdout { diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 1642baa34d..1574774661 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -264,23 +264,37 @@ pub mod guard { as *mut libc::c_void; } - // Rellocate the last page of the stack. - // This ensures SIGBUS will be raised on - // stack overflow. - let result = mmap(stackaddr, psize, PROT_NONE, - MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); - - if result != stackaddr || result == MAP_FAILED { - panic!("failed to allocate a guard page"); - } - - let offset = if cfg!(any(target_os = "linux", target_os = "freebsd")) { - 2 + if cfg!(target_os = "linux") { + // Linux doesn't allocate the whole stack right away, and + // the kernel has its own stack-guard mechanism to fault + // when growing too close to an existing mapping. If we map + // our own guard, then the kernel starts enforcing a rather + // large gap above that, rendering much of the possible + // stack space useless. See #43052. + // + // Instead, we'll just note where we expect rlimit to start + // faulting, so our handler can report "stack overflow", and + // trust that the kernel's own stack guard will work. + Some(stackaddr as usize) } else { - 1 - }; + // Reallocate the last page of the stack. + // This ensures SIGBUS will be raised on + // stack overflow. + let result = mmap(stackaddr, psize, PROT_NONE, + MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); + + if result != stackaddr || result == MAP_FAILED { + panic!("failed to allocate a guard page"); + } - Some(stackaddr as usize + offset * psize) + let offset = if cfg!(target_os = "freebsd") { + 2 + } else { + 1 + }; + + Some(stackaddr as usize + offset * psize) + } } #[cfg(target_os = "solaris")] diff --git a/src/libstd/sys/windows/args.rs b/src/libstd/sys/windows/args.rs index aa61f9adb8..4784633edc 100644 --- a/src/libstd/sys/windows/args.rs +++ b/src/libstd/sys/windows/args.rs @@ -16,6 +16,7 @@ use slice; use ops::Range; use ffi::OsString; use libc::{c_int, c_void}; +use fmt; pub unsafe fn init(_argc: isize, _argv: *const *const u8) { } @@ -39,6 +40,36 @@ pub struct Args { cur: *mut *mut u16, } +pub struct ArgsInnerDebug<'a> { + args: &'a Args, +} + +impl<'a> fmt::Debug for ArgsInnerDebug<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("[")?; + let mut first = true; + for i in self.args.range.clone() { + if !first { + f.write_str(", ")?; + } + first = false; + + // Here we do allocation which could be avoided. + fmt::Debug::fmt(&unsafe { os_string_from_ptr(*self.args.cur.offset(i)) }, f)?; + } + f.write_str("]")?; + Ok(()) + } +} + +impl Args { + pub fn inner_debug(&self) -> ArgsInnerDebug { + ArgsInnerDebug { + args: self + } + } +} + unsafe fn os_string_from_ptr(ptr: *mut u16) -> OsString { let mut len = 0; while *ptr.offset(len) != 0 { len += 1; } diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 1646f8cce7..4785cefd6b 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -298,6 +298,8 @@ pub const PIPE_TYPE_BYTE: DWORD = 0x00000000; pub const PIPE_REJECT_REMOTE_CLIENTS: DWORD = 0x00000008; pub const PIPE_READMODE_BYTE: DWORD = 0x00000000; +pub const FD_SETSIZE: usize = 64; + #[repr(C)] #[cfg(target_arch = "x86")] pub struct WSADATA { @@ -837,6 +839,26 @@ pub struct CONSOLE_READCONSOLE_CONTROL { } pub type PCONSOLE_READCONSOLE_CONTROL = *mut CONSOLE_READCONSOLE_CONTROL; +#[repr(C)] +#[derive(Copy)] +pub struct fd_set { + pub fd_count: c_uint, + pub fd_array: [SOCKET; FD_SETSIZE], +} + +impl Clone for fd_set { + fn clone(&self) -> fd_set { + *self + } +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct timeval { + pub tv_sec: c_long, + pub tv_usec: c_long, +} + extern "system" { pub fn WSAStartup(wVersionRequested: WORD, lpWSAData: LPWSADATA) -> c_int; @@ -1125,6 +1147,11 @@ extern "system" { lpOverlapped: LPOVERLAPPED, lpNumberOfBytesTransferred: LPDWORD, bWait: BOOL) -> BOOL; + pub fn select(nfds: c_int, + readfds: *mut fd_set, + writefds: *mut fd_set, + exceptfds: *mut fd_set, + timeout: *const timeval) -> c_int; } // Functions that aren't available on Windows XP, but we still use them and just diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs index 2d00cb38ec..a1c63e3358 100644 --- a/src/libstd/sys/windows/ext/fs.rs +++ b/src/libstd/sys/windows/ext/fs.rs @@ -169,8 +169,10 @@ pub trait OpenOptionsExt { /// /// # Examples /// - /// ```ignore + /// ```no_run + /// # #[cfg(for_demonstration_only)] /// extern crate winapi; + /// # mod winapi { pub const FILE_FLAG_DELETE_ON_CLOSE: u32 = 0x04000000; } /// /// use std::fs::OpenOptions; /// use std::os::windows::prelude::*; @@ -204,8 +206,10 @@ pub trait OpenOptionsExt { /// /// # Examples /// - /// ```ignore + /// ```no_run + /// # #[cfg(for_demonstration_only)] /// extern crate winapi; + /// # mod winapi { pub const FILE_ATTRIBUTE_HIDDEN: u32 = 2; } /// /// use std::fs::OpenOptions; /// use std::os::windows::prelude::*; @@ -473,7 +477,7 @@ pub fn symlink_file, Q: AsRef>(src: P, dst: Q) /// use std::os::windows::fs; /// /// # fn foo() -> std::io::Result<()> { -/// fs::symlink_file("a", "b")?; +/// fs::symlink_dir("a", "b")?; /// # Ok(()) /// # } /// ``` diff --git a/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs b/src/libstd/sys/windows/fast_thread_local.rs similarity index 58% rename from src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs rename to src/libstd/sys/windows/fast_thread_local.rs index 52cd4e8a3e..9fee9bd93b 100644 --- a/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs +++ b/src/libstd/sys/windows/fast_thread_local.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Check that non-constant exprs do fail as count in fixed length vec type +#![unstable(feature = "thread_local_internals", issue = "0")] +#![cfg(target_thread_local)] -fn main() { - fn bar(n: isize) { - let _x: [isize; n]; - //~^ ERROR attempt to use a non-constant value in a constant [E0435] - } +pub use sys_common::thread_local::register_dtor_fallback as register_dtor; + +pub fn requires_move_before_drop() -> bool { + false } diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 4efc68afdc..7f3291cf30 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -324,10 +324,6 @@ impl File { self.handle.read_at(buf, offset) } - pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { - self.handle.read_to_end(buf) - } - pub fn write(&self, buf: &[u8]) -> io::Result { self.handle.write(buf) } diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs index fdb9483fe1..3729d6d653 100644 --- a/src/libstd/sys/windows/handle.rs +++ b/src/libstd/sys/windows/handle.rs @@ -18,7 +18,6 @@ use ops::Deref; use ptr; use sys::c; use sys::cvt; -use sys_common::io::read_to_end_uninitialized; /// An owned container for `HANDLE` object, closing them on Drop. /// @@ -216,8 +215,4 @@ impl<'a> Read for &'a RawHandle { fn read(&mut self, buf: &mut [u8]) -> io::Result { (**self).read(buf) } - - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - unsafe { read_to_end_uninitialized(self, buf) } - } } diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 4424c6c613..ee58efc514 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -26,6 +26,7 @@ pub mod condvar; pub mod dynamic_lib; pub mod env; pub mod ext; +pub mod fast_thread_local; pub mod fs; pub mod handle; pub mod memchr; @@ -46,24 +47,6 @@ pub mod stdio; #[cfg(not(test))] pub fn init() { - ::alloc::oom::set_oom_handler(oom_handler); - - // See comment in sys/unix/mod.rs - fn oom_handler() -> ! { - use intrinsics; - use ptr; - let msg = "fatal runtime error: out of memory\n"; - unsafe { - // WriteFile silently fails if it is passed an invalid handle, so - // there is no need to check the result of GetStdHandle. - c::WriteFile(c::GetStdHandle(c::STD_ERROR_HANDLE), - msg.as_ptr() as c::LPVOID, - msg.len() as c::DWORD, - ptr::null_mut(), - ptr::null_mut()); - intrinsics::abort(); - } - } } pub fn decode_error_kind(errno: i32) -> ErrorKind { diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs index adf6210d82..cd8acff6b0 100644 --- a/src/libstd/sys/windows/net.rs +++ b/src/libstd/sys/windows/net.rs @@ -12,7 +12,7 @@ use cmp; use io::{self, Read}; -use libc::{c_int, c_void, c_ulong}; +use libc::{c_int, c_void, c_ulong, c_long}; use mem; use net::{SocketAddr, Shutdown}; use ptr; @@ -20,7 +20,6 @@ use sync::Once; use sys::c; use sys; use sys_common::{self, AsInner, FromInner, IntoInner}; -use sys_common::io::read_to_end_uninitialized; use sys_common::net; use time::Duration; @@ -116,6 +115,60 @@ impl Socket { Ok(socket) } + pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { + self.set_nonblocking(true)?; + let r = unsafe { + let (addrp, len) = addr.into_inner(); + cvt(c::connect(self.0, addrp, len)) + }; + self.set_nonblocking(false)?; + + match r { + Ok(_) => return Ok(()), + Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {} + Err(e) => return Err(e), + } + + if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 { + return Err(io::Error::new(io::ErrorKind::InvalidInput, + "cannot set a 0 duration timeout")); + } + + let mut timeout = c::timeval { + tv_sec: timeout.as_secs() as c_long, + tv_usec: (timeout.subsec_nanos() / 1000) as c_long, + }; + if timeout.tv_sec == 0 && timeout.tv_usec == 0 { + timeout.tv_usec = 1; + } + + let fds = unsafe { + let mut fds = mem::zeroed::(); + fds.fd_count = 1; + fds.fd_array[0] = self.0; + fds + }; + + let mut writefds = fds; + let mut errorfds = fds; + + let n = unsafe { + cvt(c::select(1, ptr::null_mut(), &mut writefds, &mut errorfds, &timeout))? + }; + + match n { + 0 => Err(io::Error::new(io::ErrorKind::TimedOut, "connection timed out")), + _ => { + if writefds.fd_count != 1 { + if let Some(e) = self.take_error()? { + return Err(e); + } + } + Ok(()) + } + } + } + pub fn accept(&self, storage: *mut c::SOCKADDR, len: *mut c_int) -> io::Result { let socket = unsafe { @@ -200,11 +253,6 @@ impl Socket { self.recv_from_with_flags(buf, c::MSG_PEEK) } - pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { - let mut me = self; - (&mut me).read_to_end(buf) - } - pub fn set_timeout(&self, dur: Option, kind: c_int) -> io::Result<()> { let timeout = match dur { @@ -283,10 +331,6 @@ impl<'a> Read for &'a Socket { fn read(&mut self, buf: &mut [u8]) -> io::Result { (**self).read(buf) } - - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - unsafe { read_to_end_uninitialized(self, buf) } - } } impl Drop for Socket { diff --git a/src/libstd/sys/windows/os_str.rs b/src/libstd/sys/windows/os_str.rs index f401e7b35c..3eb4582718 100644 --- a/src/libstd/sys/windows/os_str.rs +++ b/src/libstd/sys/windows/os_str.rs @@ -12,7 +12,7 @@ /// wrapper around the "WTF-8" encoding; see the `wtf8` module for more. use borrow::Cow; -use fmt::{self, Debug}; +use fmt; use sys_common::wtf8::{Wtf8, Wtf8Buf}; use mem; use sys_common::{AsInner, IntoInner}; @@ -34,9 +34,15 @@ impl AsInner for Buf { } } -impl Debug for Buf { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - self.as_slice().fmt(formatter) +impl fmt::Debug for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(self.as_slice(), formatter) + } +} + +impl fmt::Display for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.as_slice(), formatter) } } @@ -44,9 +50,15 @@ pub struct Slice { pub inner: Wtf8 } -impl Debug for Slice { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - self.inner.fmt(formatter) +impl fmt::Debug for Slice { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.inner, formatter) + } +} + +impl fmt::Display for Slice { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.inner, formatter) } } diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs index 8073473f7f..be7482c4bb 100644 --- a/src/libstd/sys/windows/pipe.rs +++ b/src/libstd/sys/windows/pipe.rs @@ -164,10 +164,6 @@ impl AnonPipe { self.inner.read(buf) } - pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { - self.inner.read_to_end(buf) - } - pub fn write(&self, buf: &[u8]) -> io::Result { self.inner.write(buf) } diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index dfbc1b581e..0d1766d5ae 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -306,6 +306,18 @@ impl Stdio { } } +impl From for Stdio { + fn from(pipe: AnonPipe) -> Stdio { + Stdio::Handle(pipe.into_handle()) + } +} + +impl From for Stdio { + fn from(file: File) -> Stdio { + Stdio::Handle(file.into_handle()) + } +} + //////////////////////////////////////////////////////////////////////////////// // Processes //////////////////////////////////////////////////////////////////////////////// @@ -427,20 +439,22 @@ fn make_command_line(prog: &OsStr, args: &[OsString]) -> io::Result> { // Encode the command and arguments in a command line string such // that the spawned process may recover them using CommandLineToArgvW. let mut cmd: Vec = Vec::new(); - append_arg(&mut cmd, prog)?; + // Always quote the program name so CreateProcess doesn't interpret args as + // part of the name if the binary wasn't found first time. + append_arg(&mut cmd, prog, true)?; for arg in args { cmd.push(' ' as u16); - append_arg(&mut cmd, arg)?; + append_arg(&mut cmd, arg, false)?; } return Ok(cmd); - fn append_arg(cmd: &mut Vec, arg: &OsStr) -> io::Result<()> { + fn append_arg(cmd: &mut Vec, arg: &OsStr, force_quotes: bool) -> io::Result<()> { // If an argument has 0 characters then we need to quote it to ensure // that it actually gets passed through on the command line or otherwise // it will be dropped entirely when parsed on the other end. ensure_no_nuls(arg)?; let arg_bytes = &arg.as_inner().inner.as_inner(); - let quote = arg_bytes.iter().any(|c| *c == b' ' || *c == b'\t') + let quote = force_quotes || arg_bytes.iter().any(|c| *c == b' ' || *c == b'\t') || arg_bytes.is_empty(); if quote { cmd.push('"' as u16); @@ -526,7 +540,7 @@ mod tests { assert_eq!( test_wrapper("prog", &["aaa", "bbb", "ccc"]), - "prog aaa bbb ccc" + "\"prog\" aaa bbb ccc" ); assert_eq!( @@ -539,15 +553,15 @@ mod tests { ); assert_eq!( test_wrapper("echo", &["a b c"]), - "echo \"a b c\"" + "\"echo\" \"a b c\"" ); assert_eq!( test_wrapper("echo", &["\" \\\" \\", "\\"]), - "echo \"\\\" \\\\\\\" \\\\\" \\" + "\"echo\" \"\\\" \\\\\\\" \\\\\" \\" ); assert_eq!( test_wrapper("\u{03c0}\u{042f}\u{97f3}\u{00e6}\u{221e}", &[]), - "\u{03c0}\u{042f}\u{97f3}\u{00e6}\u{221e}" + "\"\u{03c0}\u{042f}\u{97f3}\u{00e6}\u{221e}\"" ); } } diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs index d72e4b4438..b5e5b5760f 100644 --- a/src/libstd/sys/windows/stdio.rs +++ b/src/libstd/sys/windows/stdio.rs @@ -20,7 +20,6 @@ use sync::Mutex; use sys::c; use sys::cvt; use sys::handle::Handle; -use sys_common::io::read_to_end_uninitialized; pub enum Output { Console(c::HANDLE), @@ -151,10 +150,6 @@ impl<'a> Read for &'a Stdin { fn read(&mut self, buf: &mut [u8]) -> io::Result { (**self).read(buf) } - - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - unsafe { read_to_end_uninitialized(self, buf) } - } } impl Stdout { diff --git a/src/libstd/sys_common/io.rs b/src/libstd/sys_common/io.rs index 23daeeb518..ab23936358 100644 --- a/src/libstd/sys_common/io.rs +++ b/src/libstd/sys_common/io.rs @@ -7,51 +7,8 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -use io; -use io::ErrorKind; -use io::Read; -use slice::from_raw_parts_mut; - pub const DEFAULT_BUF_SIZE: usize = 8 * 1024; -// Provides read_to_end functionality over an uninitialized buffer. -// This function is unsafe because it calls the underlying -// read function with a slice into uninitialized memory. The default -// implementation of read_to_end for readers will zero out new memory in -// the buf before passing it to read, but avoiding this zero can often -// lead to a fairly significant performance win. -// -// Implementations using this method have to adhere to two guarantees: -// * The implementation of read never reads the buffer provided. -// * The implementation of read correctly reports how many bytes were written. -pub unsafe fn read_to_end_uninitialized(r: &mut Read, buf: &mut Vec) -> io::Result { - - let start_len = buf.len(); - buf.reserve(16); - - // Always try to read into the empty space of the vector (from the length to the capacity). - // If the vector ever fills up then we reserve an extra byte which should trigger the normal - // reallocation routines for the vector, which will likely double the size. - // - // This function is similar to the read_to_end function in std::io, but the logic about - // reservations and slicing is different enough that this is duplicated here. - loop { - if buf.len() == buf.capacity() { - buf.reserve(1); - } - - let buf_slice = from_raw_parts_mut(buf.as_mut_ptr().offset(buf.len() as isize), - buf.capacity() - buf.len()); - - match r.read(buf_slice) { - Ok(0) => { return Ok(buf.len() - start_len); } - Ok(n) => { let len = buf.len() + n; buf.set_len(len); }, - Err(ref e) if e.kind() == ErrorKind::Interrupted => { } - Err(e) => { return Err(e); } - } - } -} - #[cfg(test)] #[allow(dead_code)] // not used on emscripten pub mod test { @@ -91,89 +48,3 @@ pub mod test { TempDir(ret) } } - -#[cfg(test)] -mod tests { - use io::prelude::*; - use super::*; - use io; - use io::{ErrorKind, Take, Repeat, repeat}; - use slice::from_raw_parts; - - struct ErrorRepeat { - lr: Take - } - - fn error_repeat(byte: u8, limit: u64) -> ErrorRepeat { - ErrorRepeat { lr: repeat(byte).take(limit) } - } - - impl Read for ErrorRepeat { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - let ret = self.lr.read(buf); - if let Ok(0) = ret { - return Err(io::Error::new(ErrorKind::Other, "")) - } - ret - } - } - - fn init_vec_data() -> Vec { - let mut vec = vec![10u8; 200]; - unsafe { vec.set_len(0); } - vec - } - - fn assert_all_eq(buf: &[u8], value: u8) { - for n in buf { - assert_eq!(*n, value); - } - } - - fn validate(buf: &Vec, good_read_len: usize) { - assert_all_eq(buf, 1u8); - let cap = buf.capacity(); - let end_slice = unsafe { from_raw_parts(buf.as_ptr().offset(good_read_len as isize), - cap - good_read_len) }; - assert_all_eq(end_slice, 10u8); - } - - #[test] - fn read_to_end_uninit_error() { - let mut er = error_repeat(1,100); - let mut vec = init_vec_data(); - if let Err(_) = unsafe { read_to_end_uninitialized(&mut er, &mut vec) } { - validate(&vec, 100); - } else { - assert!(false); - } - } - - #[test] - fn read_to_end_uninit_zero_len_vec() { - let mut er = repeat(1).take(100); - let mut vec = Vec::new(); - let n = unsafe{ read_to_end_uninitialized(&mut er, &mut vec).unwrap() }; - assert_all_eq(&vec, 1u8); - assert_eq!(vec.len(), n); - } - - #[test] - fn read_to_end_uninit_good() { - let mut er = repeat(1).take(100); - let mut vec = init_vec_data(); - let n = unsafe{ read_to_end_uninitialized(&mut er, &mut vec).unwrap() }; - validate(&vec, 100); - assert_eq!(vec.len(), n); - } - - #[bench] - #[cfg_attr(target_os = "emscripten", ignore)] - fn bench_uninitialized(b: &mut ::test::Bencher) { - b.iter(|| { - let mut lr = repeat(1).take(10000000); - let mut vec = Vec::with_capacity(1024); - unsafe { read_to_end_uninitialized(&mut lr, &mut vec) } - }); - } -} diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index d4d3365dc0..ccd4b91a7b 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -52,7 +52,8 @@ pub mod net; #[cfg(feature = "backtrace")] #[cfg(any(all(unix, not(any(target_os = "macos", target_os = "ios", target_os = "emscripten"))), - all(windows, target_env = "gnu")))] + all(windows, target_env = "gnu"), + target_os = "redox"))] pub mod gnu; // common error constructors diff --git a/src/libstd/sys_common/net.rs b/src/libstd/sys_common/net.rs index a1897c8bd6..5775dd4f1f 100644 --- a/src/libstd/sys_common/net.rs +++ b/src/libstd/sys_common/net.rs @@ -215,6 +215,14 @@ impl TcpStream { Ok(TcpStream { inner: sock }) } + pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result { + init(); + + let sock = Socket::new(addr, c::SOCK_STREAM)?; + sock.connect_timeout(addr, timeout)?; + Ok(TcpStream { inner: sock }) + } + pub fn socket(&self) -> &Socket { &self.inner } pub fn into_socket(self) -> Socket { self.inner } @@ -243,10 +251,6 @@ impl TcpStream { self.inner.read(buf) } - pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { - self.inner.read_to_end(buf) - } - pub fn write(&self, buf: &[u8]) -> io::Result { let len = cmp::min(buf.len(), ::max_value() as usize) as wrlen_t; let ret = cvt(unsafe { diff --git a/src/libstd/sys_common/thread_info.rs b/src/libstd/sys_common/thread_info.rs index 5ed48ee455..2abb8afa82 100644 --- a/src/libstd/sys_common/thread_info.rs +++ b/src/libstd/sys_common/thread_info.rs @@ -12,7 +12,6 @@ use cell::RefCell; use thread::Thread; -use thread::LocalKeyState; struct ThreadInfo { stack_guard: Option, @@ -23,19 +22,15 @@ thread_local! { static THREAD_INFO: RefCell> = RefCell::new(N impl ThreadInfo { fn with(f: F) -> Option where F: FnOnce(&mut ThreadInfo) -> R { - if THREAD_INFO.state() == LocalKeyState::Destroyed { - return None - } - - THREAD_INFO.with(move |c| { + THREAD_INFO.try_with(move |c| { if c.borrow().is_none() { *c.borrow_mut() = Some(ThreadInfo { stack_guard: None, thread: Thread::new(None), }) } - Some(f(c.borrow_mut().as_mut().unwrap())) - }) + f(c.borrow_mut().as_mut().unwrap()) + }).ok() } } diff --git a/src/libstd/sys_common/thread_local.rs b/src/libstd/sys_common/thread_local.rs index 0ade90e64c..1f889c7070 100644 --- a/src/libstd/sys_common/thread_local.rs +++ b/src/libstd/sys_common/thread_local.rs @@ -33,7 +33,7 @@ //! Using a dynamically allocated TLS key. Note that this key can be shared //! among many threads via an `Arc`. //! -//! ```rust,ignore +//! ```ignore (cannot-doctest-private-modules) //! let key = Key::new(None); //! assert!(key.get().is_null()); //! key.set(1 as *mut u8); @@ -45,7 +45,7 @@ //! Sometimes a statically allocated key is either required or easier to work //! with, however. //! -//! ```rust,ignore +//! ```ignore (cannot-doctest-private-modules) //! static KEY: StaticKey = INIT; //! //! unsafe { @@ -58,8 +58,8 @@ #![unstable(feature = "thread_local_internals", issue = "0")] #![allow(dead_code)] // sys isn't exported yet +use ptr; use sync::atomic::{self, AtomicUsize, Ordering}; - use sys::thread_local as imp; use sys_common::mutex::Mutex; @@ -74,7 +74,7 @@ use sys_common::mutex::Mutex; /// /// # Examples /// -/// ```ignore +/// ```ignore (cannot-doctest-private-modules) /// use tls::os::{StaticKey, INIT}; /// /// static KEY: StaticKey = INIT; @@ -105,7 +105,7 @@ pub struct StaticKey { /// /// # Examples /// -/// ```rust,ignore +/// ```ignore (cannot-doctest-private-modules) /// use tls::os::Key; /// /// let key = Key::new(None); @@ -238,6 +238,39 @@ impl Drop for Key { } } +pub unsafe fn register_dtor_fallback(t: *mut u8, + dtor: unsafe extern fn(*mut u8)) { + // The fallback implementation uses a vanilla OS-based TLS key to track + // the list of destructors that need to be run for this thread. The key + // then has its own destructor which runs all the other destructors. + // + // The destructor for DTORS is a little special in that it has a `while` + // loop to continuously drain the list of registered destructors. It + // *should* be the case that this loop always terminates because we + // provide the guarantee that a TLS key cannot be set after it is + // flagged for destruction. + + static DTORS: StaticKey = StaticKey::new(Some(run_dtors)); + type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>; + if DTORS.get().is_null() { + let v: Box = box Vec::new(); + DTORS.set(Box::into_raw(v) as *mut u8); + } + let list: &mut List = &mut *(DTORS.get() as *mut List); + list.push((t, dtor)); + + unsafe extern fn run_dtors(mut ptr: *mut u8) { + while !ptr.is_null() { + let list: Box = Box::from_raw(ptr as *mut List); + for &(ptr, dtor) in list.iter() { + dtor(ptr); + } + ptr = DTORS.get(); + DTORS.set(ptr::null_mut()); + } + } +} + #[cfg(test)] mod tests { use super::{Key, StaticKey}; diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index df5e4ef1d8..b89a73cd28 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -39,7 +39,7 @@ use slice; use str; use sys_common::AsInner; -const UTF8_REPLACEMENT_CHARACTER: &'static [u8] = b"\xEF\xBF\xBD"; +const UTF8_REPLACEMENT_CHARACTER: &'static str = "\u{FFFD}"; /// A Unicode code point: from U+0000 to U+10FFFF. /// @@ -339,7 +339,7 @@ impl Wtf8Buf { Some((surrogate_pos, _)) => { pos = surrogate_pos + 3; self.bytes[surrogate_pos..pos] - .copy_from_slice(UTF8_REPLACEMENT_CHARACTER); + .copy_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes()); }, None => return unsafe { String::from_utf8_unchecked(self.bytes) } } @@ -438,6 +438,34 @@ impl fmt::Debug for Wtf8 { } } +impl fmt::Display for Wtf8 { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let wtf8_bytes = &self.bytes; + let mut pos = 0; + loop { + match self.next_surrogate(pos) { + Some((surrogate_pos, _)) => { + formatter.write_str(unsafe { + str::from_utf8_unchecked(&wtf8_bytes[pos .. surrogate_pos]) + })?; + formatter.write_str(UTF8_REPLACEMENT_CHARACTER)?; + pos = surrogate_pos + 3; + }, + None => { + let s = unsafe { + str::from_utf8_unchecked(&wtf8_bytes[pos..]) + }; + if pos == 0 { + return s.fmt(formatter) + } else { + return formatter.write_str(s) + } + } + } + } + } +} + impl Wtf8 { /// Creates a WTF-8 slice from a UTF-8 `&str` slice. /// @@ -516,13 +544,13 @@ impl Wtf8 { let wtf8_bytes = &self.bytes; let mut utf8_bytes = Vec::with_capacity(self.len()); utf8_bytes.extend_from_slice(&wtf8_bytes[..surrogate_pos]); - utf8_bytes.extend_from_slice(UTF8_REPLACEMENT_CHARACTER); + utf8_bytes.extend_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes()); let mut pos = surrogate_pos + 3; loop { match self.next_surrogate(pos) { Some((surrogate_pos, _)) => { utf8_bytes.extend_from_slice(&wtf8_bytes[pos .. surrogate_pos]); - utf8_bytes.extend_from_slice(UTF8_REPLACEMENT_CHARACTER); + utf8_bytes.extend_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes()); pos = surrogate_pos + 3; }, None => { @@ -1200,6 +1228,20 @@ mod tests { assert_eq!(string.to_string_lossy(), expected); } + #[test] + fn wtf8_display() { + fn d(b: &[u8]) -> String { + format!("{}", &unsafe { Wtf8::from_bytes_unchecked(b) }) + } + + assert_eq!("", d("".as_bytes())); + assert_eq!("aé 💩", d("aé 💩".as_bytes())); + + let mut string = Wtf8Buf::from_str("aé 💩"); + string.push(CodePoint::from_u32(0xD800).unwrap()); + assert_eq!("aé 💩�", d(string.as_inner())); + } + #[test] fn wtf8_encode_wide() { let mut string = Wtf8Buf::from_str("aé "); diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index c2c6e6cf87..be433e2b81 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -110,12 +110,13 @@ impl fmt::Debug for LocalKey { } } +#[cfg(not(stage0))] /// Declare a new thread local storage key of type [`std::thread::LocalKey`]. /// /// # Syntax /// /// The macro wraps any number of static declarations and makes them thread local. -/// Each static may be public or private, and attributes are allowed. Example: +/// Publicity and attributes for each static are allowed. Example: /// /// ``` /// use std::cell::RefCell; @@ -135,6 +136,60 @@ impl fmt::Debug for LocalKey { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable] +macro_rules! thread_local { + // empty (base case for the recursion) + () => {}; + + // process multiple declarations + ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => ( + __thread_local_inner!($(#[$attr])* $vis $name, $t, $init); + thread_local!($($rest)*); + ); + + // handle a single declaration + ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => ( + __thread_local_inner!($(#[$attr])* $vis $name, $t, $init); + ); +} + +#[cfg(not(stage0))] +#[doc(hidden)] +#[unstable(feature = "thread_local_internals", + reason = "should not be necessary", + issue = "0")] +#[macro_export] +#[allow_internal_unstable] +macro_rules! __thread_local_inner { + ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $init:expr) => { + $(#[$attr])* $vis static $name: $crate::thread::LocalKey<$t> = { + fn __init() -> $t { $init } + + fn __getit() -> $crate::option::Option< + &'static $crate::cell::UnsafeCell< + $crate::option::Option<$t>>> + { + #[thread_local] + #[cfg(target_thread_local)] + static __KEY: $crate::thread::__FastLocalKeyInner<$t> = + $crate::thread::__FastLocalKeyInner::new(); + + #[cfg(not(target_thread_local))] + static __KEY: $crate::thread::__OsLocalKeyInner<$t> = + $crate::thread::__OsLocalKeyInner::new(); + + __KEY.get() + } + + $crate::thread::LocalKey::new(__getit, __init) + }; + } +} + +#[cfg(stage0)] +/// Declare a new thread local storage key of type `std::thread::LocalKey`. +#[macro_export] +#[stable(feature = "rust1", since = "1.0.0")] +#[allow_internal_unstable] macro_rules! thread_local { // rule 0: empty (base case for the recursion) () => {}; @@ -164,6 +219,7 @@ macro_rules! thread_local { ); } +#[cfg(stage0)] #[doc(hidden)] #[unstable(feature = "thread_local_internals", reason = "should not be necessary", @@ -232,6 +288,32 @@ pub enum LocalKeyState { Destroyed, } +/// An error returned by [`LocalKey::try_with`](struct.LocalKey.html#method.try_with). +#[unstable(feature = "thread_local_state", + reason = "state querying was recently added", + issue = "27716")] +pub struct AccessError { + _private: (), +} + +#[unstable(feature = "thread_local_state", + reason = "state querying was recently added", + issue = "27716")] +impl fmt::Debug for AccessError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("AccessError").finish() + } +} + +#[unstable(feature = "thread_local_state", + reason = "state querying was recently added", + issue = "27716")] +impl fmt::Display for AccessError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt("already destroyed", f) + } +} + impl LocalKey { #[doc(hidden)] #[unstable(feature = "thread_local_internals", @@ -258,15 +340,8 @@ impl LocalKey { #[stable(feature = "rust1", since = "1.0.0")] pub fn with(&'static self, f: F) -> R where F: FnOnce(&T) -> R { - unsafe { - let slot = (self.inner)(); - let slot = slot.expect("cannot access a TLS value during or \ - after it is destroyed"); - f(match *slot.get() { - Some(ref inner) => inner, - None => self.init(slot), - }) - } + self.try_with(f).expect("cannot access a TLS value during or \ + after it is destroyed") } unsafe fn init(&self, slot: &UnsafeCell>) -> &T { @@ -331,6 +406,108 @@ impl LocalKey { } } } + + /// Acquires a reference to the value in this TLS key. + /// + /// This will lazily initialize the value if this thread has not referenced + /// this key yet. If the key has been destroyed (which may happen if this is called + /// in a destructor), this function will return a ThreadLocalError. + /// + /// # Panics + /// + /// This function will still `panic!()` if the key is uninitialized and the + /// key's initializer panics. + #[unstable(feature = "thread_local_state", + reason = "state querying was recently added", + issue = "27716")] + pub fn try_with(&'static self, f: F) -> Result + where F: FnOnce(&T) -> R { + unsafe { + let slot = (self.inner)().ok_or(AccessError { + _private: (), + })?; + Ok(f(match *slot.get() { + Some(ref inner) => inner, + None => self.init(slot), + })) + } + } +} + +#[doc(hidden)] +#[cfg(target_thread_local)] +pub mod fast { + use cell::{Cell, UnsafeCell}; + use fmt; + use mem; + use ptr; + use sys::fast_thread_local::{register_dtor, requires_move_before_drop}; + + pub struct Key { + inner: UnsafeCell>, + + // Metadata to keep track of the state of the destructor. Remember that + // these variables are thread-local, not global. + dtor_registered: Cell, + dtor_running: Cell, + } + + impl fmt::Debug for Key { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Key { .. }") + } + } + + unsafe impl ::marker::Sync for Key { } + + impl Key { + pub const fn new() -> Key { + Key { + inner: UnsafeCell::new(None), + dtor_registered: Cell::new(false), + dtor_running: Cell::new(false) + } + } + + pub fn get(&'static self) -> Option<&'static UnsafeCell>> { + unsafe { + if mem::needs_drop::() && self.dtor_running.get() { + return None + } + self.register_dtor(); + } + Some(&self.inner) + } + + unsafe fn register_dtor(&self) { + if !mem::needs_drop::() || self.dtor_registered.get() { + return + } + + register_dtor(self as *const _ as *mut u8, + destroy_value::); + self.dtor_registered.set(true); + } + } + + unsafe extern fn destroy_value(ptr: *mut u8) { + let ptr = ptr as *mut Key; + // Right before we run the user destructor be sure to flag the + // destructor as running for this thread so calls to `get` will return + // `None`. + (*ptr).dtor_running.set(true); + + // Some implementations may require us to move the value before we drop + // it as it could get re-initialized in-place during destruction. + // + // Hence, we use `ptr::read` on those platforms (to move to a "safe" + // location) instead of drop_in_place. + if requires_move_before_drop() { + ptr::read((*ptr).inner.get()); + } else { + ptr::drop_in_place((*ptr).inner.get()); + } + } } #[doc(hidden)] @@ -378,8 +555,8 @@ pub mod os { return Some(&(*ptr).value); } - // If the lookup returned null, we haven't initialized our own local - // copy, so do that now. + // If the lookup returned null, we haven't initialized our own + // local copy, so do that now. let ptr: Box> = box Value { key: self, value: UnsafeCell::new(None), @@ -391,7 +568,7 @@ pub mod os { } } - pub unsafe extern fn destroy_value(ptr: *mut u8) { + unsafe extern fn destroy_value(ptr: *mut u8) { // The OS TLS ensures that this key contains a NULL value when this // destructor starts to run. We set it back to a sentinel value of 1 to // ensure that any future calls to `get` for this thread will return diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 52f0022726..07a3a01ce8 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -159,7 +159,7 @@ use time::Duration; #[macro_use] mod local; #[stable(feature = "rust1", since = "1.0.0")] -pub use self::local::{LocalKey, LocalKeyState}; +pub use self::local::{LocalKey, LocalKeyState, AccessError}; // The types used by the thread_local! macro to access TLS keys. Note that there // are two types, the "OS" type and the "fast" type. The OS thread local key @@ -172,7 +172,7 @@ pub use self::local::{LocalKey, LocalKeyState}; #[unstable(feature = "libstd_thread_internals", issue = "0")] #[cfg(target_thread_local)] -#[doc(hidden)] pub use sys::fast_thread_local::Key as __FastLocalKeyInner; +#[doc(hidden)] pub use self::local::fast::Key as __FastLocalKeyInner; #[unstable(feature = "libstd_thread_internals", issue = "0")] #[doc(hidden)] pub use self::local::os::Key as __OsLocalKeyInner; @@ -787,12 +787,16 @@ pub fn park_timeout_ms(ms: u32) { /// /// let timeout = Duration::from_secs(2); /// let beginning_park = Instant::now(); -/// park_timeout(timeout); /// -/// while beginning_park.elapsed() < timeout { -/// println!("restarting park_timeout after {:?}", beginning_park.elapsed()); -/// let timeout = timeout - beginning_park.elapsed(); -/// park_timeout(timeout); +/// let mut timeout_remaining = timeout; +/// loop { +/// park_timeout(timeout_remaining); +/// let elapsed = beginning_park.elapsed(); +/// if elapsed >= timeout { +/// break; +/// } +/// println!("restarting park_timeout after {:?}", elapsed); +/// timeout_remaining = timeout - elapsed; /// } /// ``` /// diff --git a/src/libstd_unicode/Cargo.toml b/src/libstd_unicode/Cargo.toml index 28fbd3c1aa..b3346dbe2f 100644 --- a/src/libstd_unicode/Cargo.toml +++ b/src/libstd_unicode/Cargo.toml @@ -9,5 +9,9 @@ path = "lib.rs" test = false bench = false +[[test]] +name = "std_unicode_tests" +path = "tests/lib.rs" + [dependencies] core = { path = "../libcore" } diff --git a/src/libstd_unicode/char.rs b/src/libstd_unicode/char.rs index 92e5369758..5cf05bff8c 100644 --- a/src/libstd_unicode/char.rs +++ b/src/libstd_unicode/char.rs @@ -38,6 +38,8 @@ use tables::{conversions, derived_property, general_category, property}; pub use core::char::{MAX, from_digit, from_u32, from_u32_unchecked}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::char::{EscapeDebug, EscapeDefault, EscapeUnicode}; +#[stable(feature = "char_from_str", since = "1.20.0")] +pub use core::char::ParseCharError; // unstable reexports #[unstable(feature = "try_from", issue = "33417")] @@ -324,7 +326,6 @@ impl char { /// As an iterator: /// /// ``` - /// # #![feature(char_escape_debug)] /// for c in '\n'.escape_debug() { /// print!("{}", c); /// } @@ -334,7 +335,6 @@ impl char { /// Using `println!` directly: /// /// ``` - /// # #![feature(char_escape_debug)] /// println!("{}", '\n'.escape_debug()); /// ``` /// @@ -347,10 +347,9 @@ impl char { /// Using `to_string`: /// /// ``` - /// # #![feature(char_escape_debug)] /// assert_eq!('\n'.escape_debug().to_string(), "\\n"); /// ``` - #[unstable(feature = "char_escape_debug", issue = "35068")] + #[stable(feature = "char_escape_debug", since = "1.20.0")] #[inline] pub fn escape_debug(self) -> EscapeDebug { C::escape_debug(self) @@ -599,9 +598,9 @@ impl char { /// 'XID_Start' is a Unicode Derived Property specified in /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications), /// mostly similar to `ID_Start` but modified for closure under `NFKx`. - #[unstable(feature = "unicode", + #[unstable(feature = "rustc_private", reason = "mainly needed for compiler internals", - issue = "0")] + issue = "27812")] #[inline] pub fn is_xid_start(self) -> bool { derived_property::XID_Start(self) @@ -613,9 +612,9 @@ impl char { /// 'XID_Continue' is a Unicode Derived Property specified in /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications), /// mostly similar to 'ID_Continue' but modified for closure under NFKx. - #[unstable(feature = "unicode", + #[unstable(feature = "rustc_private", reason = "mainly needed for compiler internals", - issue = "0")] + issue = "27812")] #[inline] pub fn is_xid_continue(self) -> bool { derived_property::XID_Continue(self) diff --git a/src/libstd_unicode/lib.rs b/src/libstd_unicode/lib.rs index d63878a7a7..d568baa2cd 100644 --- a/src/libstd_unicode/lib.rs +++ b/src/libstd_unicode/lib.rs @@ -32,8 +32,8 @@ #![deny(warnings)] #![no_std] -#![feature(char_escape_debug)] #![feature(core_char_ext)] +#![feature(str_internals)] #![feature(decode_utf8)] #![feature(fused)] #![feature(fn_traits)] @@ -45,6 +45,7 @@ mod tables; mod u_str; pub mod char; +pub mod lossy; #[allow(deprecated)] pub mod str { @@ -52,7 +53,7 @@ pub mod str { pub use u_str::Utf16Encoder; } -// For use in libcollections, not re-exported in libstd. +// For use in liballoc, not re-exported in libstd. pub mod derived_property { pub use tables::derived_property::{Case_Ignorable, Cased}; } diff --git a/src/libstd_unicode/lossy.rs b/src/libstd_unicode/lossy.rs new file mode 100644 index 0000000000..253dcb6a15 --- /dev/null +++ b/src/libstd_unicode/lossy.rs @@ -0,0 +1,212 @@ +// 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. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::str as core_str; +use core::fmt; +use core::fmt::Write; +use char; +use core::mem; + + +/// Lossy UTF-8 string. +#[unstable(feature = "str_internals", issue = "0")] +pub struct Utf8Lossy { + bytes: [u8] +} + +impl Utf8Lossy { + pub fn from_str(s: &str) -> &Utf8Lossy { + Utf8Lossy::from_bytes(s.as_bytes()) + } + + pub fn from_bytes(bytes: &[u8]) -> &Utf8Lossy { + unsafe { mem::transmute(bytes) } + } + + pub fn chunks(&self) -> Utf8LossyChunksIter { + Utf8LossyChunksIter { source: &self.bytes } + } +} + + +/// Iterator over lossy UTF-8 string +#[unstable(feature = "str_internals", issue = "0")] +pub struct Utf8LossyChunksIter<'a> { + source: &'a [u8], +} + +#[unstable(feature = "str_internals", issue = "0")] +#[derive(PartialEq, Eq, Debug)] +pub struct Utf8LossyChunk<'a> { + /// Sequence of valid chars. + /// Can be empty between broken UTF-8 chars. + pub valid: &'a str, + /// Single broken char, empty if none. + /// Empty iff iterator item is last. + pub broken: &'a [u8], +} + +impl<'a> Iterator for Utf8LossyChunksIter<'a> { + type Item = Utf8LossyChunk<'a>; + + fn next(&mut self) -> Option> { + if self.source.len() == 0 { + return None; + } + + const TAG_CONT_U8: u8 = 128; + fn unsafe_get(xs: &[u8], i: usize) -> u8 { + unsafe { *xs.get_unchecked(i) } + } + fn safe_get(xs: &[u8], i: usize) -> u8 { + if i >= xs.len() { 0 } else { unsafe_get(xs, i) } + } + + let mut i = 0; + while i < self.source.len() { + let i_ = i; + + let byte = unsafe_get(self.source, i); + i += 1; + + if byte < 128 { + + } else { + let w = core_str::utf8_char_width(byte); + + macro_rules! error { () => ({ + unsafe { + let r = Utf8LossyChunk { + valid: core_str::from_utf8_unchecked(&self.source[0..i_]), + broken: &self.source[i_..i], + }; + self.source = &self.source[i..]; + return Some(r); + } + })} + + match w { + 2 => { + if safe_get(self.source, i) & 192 != TAG_CONT_U8 { + error!(); + } + i += 1; + } + 3 => { + match (byte, safe_get(self.source, i)) { + (0xE0, 0xA0 ... 0xBF) => (), + (0xE1 ... 0xEC, 0x80 ... 0xBF) => (), + (0xED, 0x80 ... 0x9F) => (), + (0xEE ... 0xEF, 0x80 ... 0xBF) => (), + _ => { + error!(); + } + } + i += 1; + if safe_get(self.source, i) & 192 != TAG_CONT_U8 { + error!(); + } + i += 1; + } + 4 => { + match (byte, safe_get(self.source, i)) { + (0xF0, 0x90 ... 0xBF) => (), + (0xF1 ... 0xF3, 0x80 ... 0xBF) => (), + (0xF4, 0x80 ... 0x8F) => (), + _ => { + error!(); + } + } + i += 1; + if safe_get(self.source, i) & 192 != TAG_CONT_U8 { + error!(); + } + i += 1; + if safe_get(self.source, i) & 192 != TAG_CONT_U8 { + error!(); + } + i += 1; + } + _ => { + error!(); + } + } + } + } + + let r = Utf8LossyChunk { + valid: unsafe { core_str::from_utf8_unchecked(self.source) }, + broken: &[], + }; + self.source = &[]; + return Some(r); + } +} + + +impl fmt::Display for Utf8Lossy { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // If we're the empty string then our iterator won't actually yield + // anything, so perform the formatting manually + if self.bytes.len() == 0 { + return "".fmt(f) + } + + for Utf8LossyChunk { valid, broken } in self.chunks() { + // If we successfully decoded the whole chunk as a valid string then + // we can return a direct formatting of the string which will also + // respect various formatting flags if possible. + if valid.len() == self.bytes.len() { + assert!(broken.is_empty()); + return valid.fmt(f) + } + + f.write_str(valid)?; + if !broken.is_empty() { + f.write_char(char::REPLACEMENT_CHARACTER)?; + } + } + Ok(()) + } +} + +impl fmt::Debug for Utf8Lossy { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_char('"')?; + + for Utf8LossyChunk { valid, broken } in self.chunks() { + + // Valid part. + // Here we partially parse UTF-8 again which is suboptimal. + { + let mut from = 0; + for (i, c) in valid.char_indices() { + let esc = c.escape_debug(); + // If char needs escaping, flush backlog so far and write, else skip + if esc.len() != 1 { + f.write_str(&valid[from..i])?; + for c in esc { + f.write_char(c)?; + } + from = i + c.len_utf8(); + } + } + f.write_str(&valid[from..])?; + } + + // Broken parts of string as hex escape. + for &b in broken { + write!(f, "\\x{:02x}", b)?; + } + } + + f.write_char('"') + } +} diff --git a/src/libstd_unicode/tables.rs b/src/libstd_unicode/tables.rs index 7173040350..0938738b52 100644 --- a/src/libstd_unicode/tables.rs +++ b/src/libstd_unicode/tables.rs @@ -14,7 +14,7 @@ /// The version of [Unicode](http://www.unicode.org/) /// that the unicode parts of `CharExt` and `UnicodeStrPrelude` traits are based on. -pub const UNICODE_VERSION: (u64, u64, u64) = (9, 0, 0); +pub const UNICODE_VERSION: (u64, u64, u64) = (10, 0, 0); // BoolTrie is a trie for representing a set of Unicode codepoints. It is @@ -167,7 +167,7 @@ pub mod general_category { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 7, 0, 0, 8, 0, 0, 0, 6, 0, 0, 0, 0, 0, 8, 0, 8, 0, 0, 0, 0, 0, 8, 0, 9, 6, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, + 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -236,7 +236,7 @@ pub mod derived_property { 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 95, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 96, 97, 36, 36, 36, 36, 98, 99, 36, 100, 101, 36, 102, - 103, 104, 105, 36, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 36, 117, 36, + 103, 104, 105, 36, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 36, 95, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, @@ -244,23 +244,23 @@ pub mod derived_property { 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 118, 119, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 117, 118, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 36, 36, 36, 36, 36, 120, 36, 121, 122, 123, 124, 125, 36, 36, 36, 36, 126, 127, 128, - 129, 31, 130, 36, 131, 132, 133, 113, 134 + 36, 36, 36, 36, 36, 119, 36, 120, 121, 122, 123, 124, 36, 36, 36, 36, 125, 126, 127, + 128, 31, 129, 36, 130, 131, 132, 113, 133 ], r3: &[ - 0x00001ffffcffffff, 0x0000000001ffffff, 0x3fdfffff00000000, 0xffff03f8fff00000, - 0xefffffffffffffff, 0xfffe000fffe1dfff, 0xe3c5fdfffff99fef, 0x0003000fb080599f, - 0xc36dfdfffff987ee, 0x003f00005e021987, 0xe3edfdfffffbbfee, 0x0200000f00011bbf, + 0x00001ffffcffffff, 0x000007ff01ffffff, 0x3fdfffff00000000, 0xffff03f8fff00000, + 0xefffffffffffffff, 0xfffe000fffe1dfff, 0xe3c5fdfffff99fef, 0x1003000fb080599f, + 0xc36dfdfffff987ee, 0x003f00005e021987, 0xe3edfdfffffbbfee, 0x1e00000f00011bbf, 0xe3edfdfffff99fee, 0x0002000fb0c0199f, 0xc3ffc718d63dc7ec, 0x0000000000811dc7, 0xe3fffdfffffddfef, 0x0000000f07601ddf, 0xe3effdfffffddfef, 0x0006000f40601ddf, - 0xe7fffffffffddfee, 0xfc00000f80f05ddf, 0x2ffbfffffc7fffec, 0x000c0000ff5f807f, + 0xe7fffffffffddfef, 0xfc00000f80f05ddf, 0x2ffbfffffc7fffec, 0x000c0000ff5f807f, 0x07fffffffffffffe, 0x000000000000207f, 0x3bffecaefef02596, 0x00000000f000205f, 0x0000000000000001, 0xfffe1ffffffffeff, 0x1ffffffffeffff03, 0x0000000000000000, 0xf97fffffffffffff, 0xffffc1e7ffff0000, 0xffffffff3000407f, 0xf7ffffffffff20bf, @@ -278,74 +278,76 @@ pub mod derived_property { 0x000003ffffffffff, 0xffff7fffffffffff, 0xffffffff7fffffff, 0x000c781fffffffff, 0xffff20bfffffffff, 0x000080ffffffffff, 0x7f7f7f7f007fffff, 0xffffffff7f7f7f7f, 0x0000800000000000, 0x1f3e03fe000000e0, 0xfffffffee07fffff, 0xf7ffffffffffffff, - 0xfffe3fffffffffe0, 0x07ffffff00007fff, 0xffff000000000000, 0x00000000003fffff, + 0xfffe7fffffffffe0, 0x07ffffff00007fff, 0xffff000000000000, 0x000007ffffffffff, 0x0000000000001fff, 0x3fffffffffff0000, 0x00000c00ffff1fff, 0x8ff07fffffffffff, 0x0000ffffffffffff, 0xfffffffcff800000, 0x00ff7ffffffff9ff, 0xff80000000000000, 0x000000fffffff7bb, 0x000fffffffffffff, 0x28fc00000000002f, 0xffff07fffffffc00, 0x1fffffff0007ffff, 0xfff7ffffffffffff, 0x7c00ffdf00008000, 0x007fffffffffffff, 0xc47fffff00003fff, 0x7fffffffffffffff, 0x003cffff38000005, 0xffff7f7f007e7e7e, - 0xffff003ff7ffffff, 0x000007ffffffffff, 0xffff000fffffffff, 0x0ffffffffffff87f, - 0xffff3fffffffffff, 0x0000000003ffffff, 0x5f7ffdffe0f8007f, 0xffffffffffffffdb, - 0x0003ffffffffffff, 0xfffffffffff80000, 0x3fffffffffffffff, 0xffffffffffff0000, - 0xfffffffffffcffff, 0x0fff0000000000ff, 0xffdf000000000000, 0x1fffffffffffffff, - 0x07fffffe00000000, 0xffffffc007fffffe, 0x000000001cfcfcfc + 0xffff003ff7ffffff, 0xffff000fffffffff, 0x0ffffffffffff87f, 0xffff3fffffffffff, + 0x0000000003ffffff, 0x5f7ffdffe0f8007f, 0xffffffffffffffdb, 0x0003ffffffffffff, + 0xfffffffffff80000, 0x3fffffffffffffff, 0xffffffffffff0000, 0xfffffffffffcffff, + 0x0fff0000000000ff, 0xffdf000000000000, 0x1fffffffffffffff, 0x07fffffe00000000, + 0xffffffc007fffffe, 0x000000001cfcfcfc ], r4: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 5, 9, 5, 10, 11, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 13, 14, - 15, 5, 5, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 15, 7, 16, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 ], r5: &[ 0, 1, 2, 3, 4, 5, 4, 4, 4, 4, 6, 7, 8, 9, 10, 11, 2, 2, 12, 13, 14, 15, 4, 4, 2, 2, 2, 2, 16, 17, 4, 4, 18, 19, 20, 21, 22, 4, 23, 4, 24, 25, 26, 27, 28, 29, 30, 4, 2, 31, 32, 32, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 33, 34, 35, 32, 36, 2, 37, 38, 4, 39, 40, 41, 42, 4, 4, 2, 43, 2, 44, 4, 4, 45, 46, 47, 48, 28, 4, 49, 4, 4, 4, 4, 4, 50, 51, 4, 4, 4, - 4, 4, 4, 4, 52, 4, 4, 4, 4, 53, 54, 55, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 56, 4, 2, 57, 2, 2, 2, 58, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 52, 53, 54, 55, 4, 4, 4, 4, 56, 57, 58, 4, 59, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 61, 4, 2, 62, 2, 2, 2, 63, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 57, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 62, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 59, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 64, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, - 2, 2, 2, 2, 52, 20, 4, 60, 16, 61, 62, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 63, 64, - 65, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, + 2, 2, 2, 2, 2, 2, 55, 20, 4, 65, 16, 66, 67, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, + 68, 69, 70, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 66, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 32, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 67, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 71, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 32, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 20, 72, 2, 2, 2, 2, 2, 73, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 2, 68, 69, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 2, 70, 71, 72, 73, 74, 2, 2, 2, 2, 75, 76, 77, 78, 79, 80, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 81, + 4, 4, 4, 4, 4, 4, 4, 2, 74, 75, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 76, 77, 78, 79, 80, 2, 2, 2, 2, 81, 82, 83, 84, 85, 86, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 2, 2, 2, 82, 2, 83, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 84, 85, - 86, 4, 4, 4, 4, 4, 4, 4, 4, 4, 87, 88, 89, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 87, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 2, 2, 2, 88, 2, 89, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 90, 91, 92, 4, 4, 4, 4, 4, 4, 4, 4, 4, 72, 93, 94, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 90, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 95, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 91, 4, 4, 4, + 96, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 97, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 92, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 98, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ], r6: &[ 0xb7ffff7fffffefff, 0x000000003fff3fff, 0xffffffffffffffff, 0x07ffffffffffffff, 0x0000000000000000, 0x001fffffffffffff, 0xffffffff1fffffff, 0x000000000001ffff, - 0xffff0000ffffffff, 0x07ffffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f, + 0xffffe000ffffffff, 0x07ffffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f, 0xffff00003fffffff, 0x0fffffffff0fffff, 0xffff00ffffffffff, 0x0000000fffffffff, 0x007fffffffffffff, 0x000000ff003fffff, 0x91bffffffffffd3f, 0x007fffff003fffff, 0x000000007fffffff, 0x0037ffff00000000, 0x03ffffff003fffff, 0xc0ffffffffffffff, @@ -356,17 +358,18 @@ pub mod derived_property { 0x000001ffffffffff, 0xe3edfdfffff99fef, 0x0000000fe081199f, 0x00000000000007bb, 0x00000000000000b3, 0x7f3fffffffffffff, 0x000000003f000000, 0x7fffffffffffffff, 0x0000000000000011, 0x000007ffe3ffffff, 0xffffffff00000000, 0x80000000ffffffff, - 0x01ffffffffffffff, 0x7f7ffffffffffdff, 0xfffc000000000001, 0x007ffefffffcffff, - 0x0000000003ffffff, 0x00007fffffffffff, 0x000000000000000f, 0x000000000000007f, - 0x00003fffffff0000, 0xe0fffff80000000f, 0x000000000000ffff, 0x7fffffffffff001f, - 0x00000000fff80000, 0x0000000100000000, 0x00001fffffffffff, 0x0000000000000003, - 0x1fff07ffffffffff, 0x0000000043ff01ff, 0xffffffffffdfffff, 0xebffde64dfffffff, - 0xffffffffffffffef, 0x7bffffffdfdfe7bf, 0xfffffffffffdfc5f, 0xffffff3fffffffff, - 0xf7fffffff7fffffd, 0xffdfffffffdfffff, 0xffff7fffffff7fff, 0xfffffdfffffffdff, - 0x0000000000000ff7, 0x000007dbf9ffff7f, 0x000000000000001f, 0x000000000000008f, - 0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, 0xffff000000000000, - 0xffff03ffffff03ff, 0x00000000000003ff, 0x00000000007fffff, 0x00000003ffffffff, - 0x000000003fffffff + 0x7fe7ffffffffffff, 0xffffffffffff0000, 0x0000000000ffffcf, 0x01ffffffffffffff, + 0x7f7ffffffffffdff, 0xfffc000000000001, 0x007ffefffffcffff, 0xb47ffffffffffb7f, + 0x00000000000000cb, 0x0000000003ffffff, 0x00007fffffffffff, 0x000000000000000f, + 0x000000000000007f, 0x00003fffffff0000, 0xe0fffff80000000f, 0x000000000000ffff, + 0x7fffffffffff001f, 0x00000000fff80000, 0x0000000300000000, 0x00001fffffffffff, + 0xffff000000000000, 0x0fffffffffffffff, 0x1fff07ffffffffff, 0x0000000043ff01ff, + 0xffffffffffdfffff, 0xebffde64dfffffff, 0xffffffffffffffef, 0x7bffffffdfdfe7bf, + 0xfffffffffffdfc5f, 0xffffff3fffffffff, 0xf7fffffff7fffffd, 0xffdfffffffdfffff, + 0xffff7fffffff7fff, 0xfffffdfffffffdff, 0x0000000000000ff7, 0x000007dbf9ffff7f, + 0x000000000000001f, 0x000000000000008f, 0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, + 0x0ffffbee0ffffbff, 0xffff03ffffff03ff, 0x00000000000003ff, 0x00000000007fffff, + 0xffff0003ffffffff, 0x00000001ffffffff, 0x000000003fffffff ], }; @@ -426,9 +429,9 @@ pub mod derived_property { r3: &[ 0x00003fffffc00000, 0x000000000e000000, 0x0000000000000000, 0xfffffffffff00000, 0x1400000000000007, 0x0002000c00fe21fe, 0x1000000000000002, 0x0000000c0000201e, - 0x1000000000000006, 0x0023000000023986, 0x0000000c000021be, 0x9000000000000002, + 0x1000000000000006, 0x0023000000023986, 0xfc00000c000021be, 0x9000000000000002, 0x0000000c0040201e, 0x0000000000000004, 0x0000000000002001, 0xc000000000000001, - 0x0000000c00603dc1, 0x0000000c00003040, 0x0000000000000002, 0x00000000005c0400, + 0x0000000c00603dc1, 0x0000000c00003040, 0x1800000000000003, 0x00000000005c0400, 0x07f2000000000000, 0x0000000000007fc0, 0x1bf2000000000000, 0x0000000000003f40, 0x02a0000003000000, 0x7ffe000000000000, 0x1ffffffffeffe0df, 0x0000000000000040, 0x66fde00000000000, 0x001e0001c3000000, 0x0000000020002064, 0x1000000000000000, @@ -437,7 +440,7 @@ pub mod derived_property { 0x0e04018700000000, 0x0000000009800000, 0x9ff81fe57f400000, 0x7fff008000000000, 0x17d000000000000f, 0x000ff80000000004, 0x00003b3c00000003, 0x0003a34000000000, 0x00cff00000000000, 0x3f00000000000000, 0x031021fdfff70000, 0xfffff00000000000, - 0x010007ffffffffff, 0xfffffffff8000000, 0xf83fffffffffffff, 0xa000000000000000, + 0x010007ffffffffff, 0xfffffffff8000000, 0xfbffffffffffffff, 0xa000000000000000, 0x6000e000e000e003, 0x00007c900300f800, 0x8002ffdf00000000, 0x000000001fff0000, 0x0001ffffffff0000, 0x3000000000000000, 0x0003800000000000, 0x8000800000000000, 0xffffffff00000000, 0x0000800000000000, 0x083e3c0000000020, 0x000000007e000000, @@ -465,24 +468,24 @@ pub mod derived_property { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 0, 9, 10, 11, 12, 13, 0, 0, 14, 15, 16, 0, 0, 17, 18, 19, 20, - 0, 0, 21, 22, 23, 24, 25, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 27, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 21, 22, 23, 24, 25, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 28, 29, 0, 0, 0, + 0, 0, 30, 0, 31, 0, 32, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, - 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 35, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 38, 39, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 42, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 35, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 37, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 41, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 45, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 45, - 0, 0, 45, 45, 45, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0 + 50, 51, 0, 0, 51, 51, 51, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 ], r6: &[ 0x0000000000000000, 0x2000000000000000, 0x0000000100000000, 0x07c0000000000000, @@ -491,12 +494,14 @@ pub mod derived_property { 0x0000000000001c00, 0x40d3800000000000, 0x000007f880000000, 0x1000000000000003, 0x001f1fc000000001, 0xff00000000000000, 0x000000000000005c, 0x85f8000000000000, 0x000000000000000d, 0xb03c000000000000, 0x0000000030000001, 0xa7f8000000000000, - 0x0000000000000001, 0x00bf280000000000, 0x00000fbce0000000, 0xbf7f000000000000, - 0x006dfcfffffc0000, 0x001f000000000000, 0x007f000000000000, 0x000000000000000f, - 0x00000000ffff8000, 0x0000000f60000000, 0xfff8038000000000, 0x00003c0000000fe7, - 0x000000000000001c, 0xf87fffffffffffff, 0x00201fffffffffff, 0x0000fffef8000010, - 0x000007dbf9ffff7f, 0x00000000007f0000, 0x00000000000007f0, 0xf800000000000000, - 0xffffffff00000002, 0xffffffffffffffff, 0x0000ffffffffffff + 0x0000000000000001, 0x00bf280000000000, 0x00000fbce0000000, 0x79f800000000067e, + 0x000000000e7e0080, 0x00000000037ffc00, 0xbf7f000000000000, 0x006dfcfffffc0000, + 0xb47e000000000000, 0x00000000000000bf, 0x001f000000000000, 0x007f000000000000, + 0x000000000000000f, 0x00000000ffff8000, 0x0000000300000000, 0x0000000f60000000, + 0xfff8038000000000, 0x00003c0000000fe7, 0x000000000000001c, 0xf87fffffffffffff, + 0x00201fffffffffff, 0x0000fffef8000010, 0x000007dbf9ffff7f, 0x00000000007f0000, + 0x00000000000007f0, 0xf800000000000000, 0xffffffff00000002, 0xffffffffffffffff, + 0x0000ffffffffffff ], }; @@ -851,12 +856,12 @@ pub mod derived_property { 127 ], r3: &[ - 0x00003fffffffffff, 0x000000000fffffff, 0x3fdfffff00000000, 0xfffffffbfff00000, - 0xffffffffffffffff, 0xfffeffcfffffffff, 0xf3c5fdfffff99fef, 0x0003ffcfb080799f, - 0xd36dfdfffff987ee, 0x003fffc05e023987, 0xf3edfdfffffbbfee, 0x0200ffcf00013bbf, + 0x00003fffffffffff, 0x000007ff0fffffff, 0x3fdfffff00000000, 0xfffffffbfff00000, + 0xffffffffffffffff, 0xfffeffcfffffffff, 0xf3c5fdfffff99fef, 0x1003ffcfb080799f, + 0xd36dfdfffff987ee, 0x003fffc05e023987, 0xf3edfdfffffbbfee, 0xfe00ffcf00013bbf, 0xf3edfdfffff99fee, 0x0002ffcfb0c0399f, 0xc3ffc718d63dc7ec, 0x0000ffc000813dc7, 0xe3fffdfffffddfef, 0x0000ffcf07603ddf, 0xf3effdfffffddfef, 0x0006ffcf40603ddf, - 0xe7fffffffffddfee, 0xfc00ffcf80f07ddf, 0x2ffbfffffc7fffec, 0x000cffc0ff5f847f, + 0xfffffffffffddfef, 0xfc00ffcf80f07ddf, 0x2ffbfffffc7fffec, 0x000cffc0ff5f847f, 0x07fffffffffffffe, 0x0000000003ff7fff, 0x3bffecaefef02596, 0x00000000f3ff3f5f, 0xc2a003ff03000001, 0xfffe1ffffffffeff, 0x1ffffffffeffffdf, 0x0000000000000040, 0xffffffffffff03ff, 0xffffffff3fffffff, 0xf7ffffffffff20bf, 0xffffffff3d7f3dff, @@ -867,13 +872,13 @@ pub mod derived_property { 0x003fffffffffffff, 0x0fff0fff7fffffff, 0x001f3fffffffffc0, 0xffff0fffffffffff, 0x0000000007ff03ff, 0xffffffff0fffffff, 0x9fffffff7fffffff, 0x3fff008003ff03ff, 0x0000000000000000, 0x000ff80003ff0fff, 0x000fffffffffffff, 0x3fffffffffffe3ff, - 0x00000000000001ff, 0x037ffffffff70000, 0xf83fffffffffffff, 0xffffffff3f3fffff, + 0x00000000000001ff, 0x03fffffffff70000, 0xfbffffffffffffff, 0xffffffff3f3fffff, 0x3fffffffaaff3f3f, 0x5fdfffffffffffff, 0x1fdc1fff0fcf1fdc, 0x8000000000000000, 0x8002000000100001, 0x000000001fff0000, 0x0001ffe21fff0000, 0xf3fffd503f2ffc84, 0xffffffff000043e0, 0xffff7fffffffffff, 0xffffffff7fffffff, 0x000ff81fffffffff, 0xffff20bfffffffff, 0x800080ffffffffff, 0x7f7f7f7f007fffff, 0xffffffff7f7f7f7f, - 0x1f3efffe000000e0, 0xfffffffee67fffff, 0xf7ffffffffffffff, 0xfffe3fffffffffe0, - 0x07ffffff00007fff, 0xffff000000000000, 0x00000000003fffff, 0x0000000000001fff, + 0x1f3efffe000000e0, 0xfffffffee67fffff, 0xf7ffffffffffffff, 0xfffe7fffffffffe0, + 0x07ffffff00007fff, 0xffff000000000000, 0x000007ffffffffff, 0x0000000000001fff, 0x3fffffffffff0000, 0x00000fffffff1fff, 0xbff0ffffffffffff, 0x0003ffffffffffff, 0xfffffffcff800000, 0x00ff7ffffffff9ff, 0xff80000000000000, 0x000000ffffffffff, 0x28ffffff03ff003f, 0xffff3fffffffffff, 0x1fffffff000fffff, 0x7fffffff03ff8001, @@ -886,60 +891,62 @@ pub mod derived_property { ], r4: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 5, 9, 5, 10, 11, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 13, - 14, 5, 5, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 14, 7, 15, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + 5, 5, 5, 5, 5, 5, 5, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 ], r5: &[ 0, 1, 2, 3, 4, 5, 4, 6, 4, 4, 7, 8, 9, 10, 11, 12, 2, 2, 13, 14, 15, 16, 4, 4, 2, 2, 2, 2, 17, 18, 4, 4, 19, 20, 21, 22, 23, 4, 24, 4, 25, 26, 27, 28, 29, 30, 31, 4, 2, 32, 33, 33, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 34, 3, 35, 36, 37, 2, 38, 39, 4, 40, 41, 42, 43, 4, 4, 2, 44, 2, 45, 4, 4, 46, 47, 2, 48, 49, 50, 51, 4, 4, 4, 4, 4, 52, 53, 4, 4, 4, - 4, 4, 4, 4, 54, 4, 4, 4, 4, 55, 56, 57, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 58, 4, 2, 59, 2, 2, 2, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 54, 55, 56, 57, 4, 4, 4, 4, 58, 59, 60, 4, 61, 62, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 63, 4, 2, 64, 2, 2, 2, 65, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 59, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 64, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 61, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 66, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, - 2, 2, 2, 2, 54, 62, 4, 63, 17, 64, 65, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 66, 67, - 68, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, + 2, 2, 2, 2, 2, 2, 57, 67, 4, 68, 17, 69, 70, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, + 71, 72, 73, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 69, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 33, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 70, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 74, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 33, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 21, 75, 2, 2, 2, 2, 2, 76, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 2, 71, 72, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 73, 74, 4, 4, - 75, 4, 4, 4, 4, 4, 4, 2, 76, 77, 78, 79, 80, 2, 2, 2, 2, 81, 82, 83, 84, 85, 86, 4, 4, - 4, 4, 4, 4, 4, 4, 87, 88, 89, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 90, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 2, 2, 2, 91, 2, 44, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 92, 93, 94, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 95, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 4, 4, 4, 4, 4, 4, 2, 77, 78, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 79, 80, 4, 4, 81, 4, 4, 4, 4, 4, 4, 2, 82, 83, 84, 85, 86, 2, 2, 2, 2, 87, 88, 89, 90, + 91, 92, 4, 4, 4, 4, 4, 4, 4, 4, 93, 94, 95, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 96, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 97, 2, 44, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 98, 99, 100, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 101, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 11, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 11, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 102, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 96, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 103, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 2, 2, 2, 2, 2, 2, 2, 2, 97, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 98, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 104, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 105, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ], r6: &[ 0xb7ffff7fffffefff, 0x000000003fff3fff, 0xffffffffffffffff, 0x07ffffffffffffff, 0x0000000000000000, 0x001fffffffffffff, 0x2000000000000000, 0xffffffff1fffffff, - 0x000000010001ffff, 0xffff0000ffffffff, 0x07ffffffffff07ff, 0xffffffff3fffffff, + 0x000000010001ffff, 0xffffe000ffffffff, 0x07ffffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f, 0xffff03ff3fffffff, 0x0fffffffff0fffff, 0xffff00ffffffffff, 0x0000000fffffffff, 0x007fffffffffffff, 0x000000ff003fffff, 0x91bffffffffffd3f, 0x007fffff003fffff, 0x000000007fffffff, 0x0037ffff00000000, 0x03ffffff003fffff, @@ -950,18 +957,20 @@ pub mod derived_property { 0xffff01ffbfffbd7f, 0x03ff07ffffffffff, 0xf3edfdfffff99fef, 0x001f1fcfe081399f, 0x0000000003ff07ff, 0x0000000003ff00bf, 0xff3fffffffffffff, 0x000000003f000001, 0x0000000003ff0011, 0x00ffffffffffffff, 0x00000000000003ff, 0x03ff0fffe3ffffff, - 0xffffffff00000000, 0x800003ffffffffff, 0x01ffffffffffffff, 0xff7ffffffffffdff, - 0xfffc000003ff0001, 0x007ffefffffcffff, 0x0000000003ffffff, 0x00007fffffffffff, - 0x000000000000000f, 0x000000000000007f, 0x000003ff7fffffff, 0x001f3fffffff0000, - 0xe0fffff803ff000f, 0x000000000000ffff, 0x7fffffffffff001f, 0x00000000ffff8000, - 0x0000000100000000, 0x00001fffffffffff, 0x0000000000000003, 0x1fff07ffffffffff, - 0x0000000063ff01ff, 0xf807e3e000000000, 0x00003c0000000fe7, 0x000000000000001c, - 0xffffffffffdfffff, 0xebffde64dfffffff, 0xffffffffffffffef, 0x7bffffffdfdfe7bf, - 0xfffffffffffdfc5f, 0xffffff3fffffffff, 0xf7fffffff7fffffd, 0xffdfffffffdfffff, - 0xffff7fffffff7fff, 0xfffffdfffffffdff, 0xffffffffffffcff7, 0xf87fffffffffffff, - 0x00201fffffffffff, 0x0000fffef8000010, 0x000007dbf9ffff7f, 0x00000000007f001f, - 0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, 0x00000000007fffff, - 0x00000003ffffffff, 0x000000003fffffff, 0x0000ffffffffffff + 0xffffffff00000000, 0x800003ffffffffff, 0x7fffffffffffffff, 0xffffffffffff0080, + 0x0000000003ffffcf, 0x01ffffffffffffff, 0xff7ffffffffffdff, 0xfffc000003ff0001, + 0x007ffefffffcffff, 0xb47ffffffffffb7f, 0x0000000003ff00ff, 0x0000000003ffffff, + 0x00007fffffffffff, 0x000000000000000f, 0x000000000000007f, 0x000003ff7fffffff, + 0x001f3fffffff0000, 0xe0fffff803ff000f, 0x000000000000ffff, 0x7fffffffffff001f, + 0x00000000ffff8000, 0x0000000300000000, 0x00001fffffffffff, 0xffff000000000000, + 0x0fffffffffffffff, 0x1fff07ffffffffff, 0x0000000063ff01ff, 0xf807e3e000000000, + 0x00003c0000000fe7, 0x000000000000001c, 0xffffffffffdfffff, 0xebffde64dfffffff, + 0xffffffffffffffef, 0x7bffffffdfdfe7bf, 0xfffffffffffdfc5f, 0xffffff3fffffffff, + 0xf7fffffff7fffffd, 0xffdfffffffdfffff, 0xffff7fffffff7fff, 0xfffffdfffffffdff, + 0xffffffffffffcff7, 0xf87fffffffffffff, 0x00201fffffffffff, 0x0000fffef8000010, + 0x000007dbf9ffff7f, 0x00000000007f001f, 0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, + 0x0ffffbee0ffffbff, 0x00000000007fffff, 0xffff0003ffffffff, 0x00000001ffffffff, + 0x000000003fffffff, 0x0000ffffffffffff ], }; @@ -1027,8 +1036,8 @@ pub mod derived_property { 129, 130, 131, 132 ], r3: &[ - 0x00000110043fffff, 0x0000000001ffffff, 0x3fdfffff00000000, 0x0000000000000000, - 0x23fffffffffffff0, 0xfffe0003ff010000, 0x23c5fdfffff99fe1, 0x00030003b0004000, + 0x00000110043fffff, 0x000007ff01ffffff, 0x3fdfffff00000000, 0x0000000000000000, + 0x23fffffffffffff0, 0xfffe0003ff010000, 0x23c5fdfffff99fe1, 0x10030003b0004000, 0x036dfdfffff987e0, 0x001c00005e000000, 0x23edfdfffffbbfe0, 0x0200000300010000, 0x23edfdfffff99fe0, 0x00020003b0000000, 0x03ffc718d63dc7e8, 0x0000000000010000, 0x23fffdfffffddfe0, 0x0000000307000000, 0x23effdfffffddfe1, 0x0006000340000000, @@ -1048,8 +1057,8 @@ pub mod derived_property { 0x1fdc1fff0fcf1fdc, 0x8002000000000000, 0x000000001fff0000, 0xf3fffd503f2ffc84, 0xffffffff000043e0, 0xffff7fffffffffff, 0xffffffff7fffffff, 0x000c781fffffffff, 0xffff20bfffffffff, 0x000080ffffffffff, 0x7f7f7f7f007fffff, 0x000000007f7f7f7f, - 0x1f3e03fe000000e0, 0xfffffffee07fffff, 0xf7ffffffffffffff, 0xfffe3fffffffffe0, - 0x07ffffff00007fff, 0xffff000000000000, 0x00000000003fffff, 0x0000000000001fff, + 0x1f3e03fe000000e0, 0xfffffffee07fffff, 0xf7ffffffffffffff, 0xfffe7fffffffffe0, + 0x07ffffff00007fff, 0xffff000000000000, 0x000007ffffffffff, 0x0000000000001fff, 0x3fffffffffff0000, 0x00000c00ffff1fff, 0x80007fffffffffff, 0xffffffff3fffffff, 0x0000ffffffffffff, 0xfffffffcff800000, 0x00ff7ffffffff9ff, 0xff80000000000000, 0x00000007fffff7bb, 0x000ffffffffffffc, 0x28fc000000000000, 0xffff003ffffffc00, @@ -1064,58 +1073,60 @@ pub mod derived_property { ], r4: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 5, 9, 5, 10, 11, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 13, - 14, 5, 5, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 14, 7, 15, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 ], r5: &[ 0, 1, 2, 3, 4, 5, 4, 4, 4, 4, 6, 7, 8, 9, 10, 11, 2, 2, 12, 13, 14, 15, 4, 4, 2, 2, 2, 2, 16, 17, 4, 4, 18, 19, 20, 21, 22, 4, 23, 4, 24, 25, 26, 27, 28, 29, 30, 4, 2, 31, 32, 32, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 33, 4, 34, 35, 36, 37, 38, 39, 40, 4, 41, 20, 42, 43, 4, 4, 5, 44, 45, 46, 4, 4, 47, 48, 45, 49, 50, 4, 51, 4, 4, 4, 4, 4, 52, 53, 4, - 4, 4, 4, 4, 4, 4, 54, 4, 4, 4, 4, 55, 56, 57, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 51, 4, 2, 47, 2, 2, 2, 58, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 54, 55, 56, 57, 4, 4, 4, 4, 58, 59, 60, 4, 61, 62, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 51, 4, 2, 47, 2, 2, 2, 63, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 47, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 47, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 59, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 64, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, - 2, 2, 2, 2, 2, 2, 54, 20, 4, 60, 45, 61, 57, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, - 62, 63, 64, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 65, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 32, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 66, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 2, 67, 68, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 69, 70, 71, 72, 73, 2, 2, 2, 2, 74, 75, 76, 77, 78, 79, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 57, 20, 4, 65, 45, 66, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 2, 67, 68, 69, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 70, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 32, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 20, 71, 2, 2, 2, 2, 2, + 72, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 2, 73, 74, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 75, 76, 77, 78, 79, 2, 2, 2, 2, 80, 81, 82, 83, 84, + 85, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 2, 2, 2, 80, 2, 58, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 81, 82, 83, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 84, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 86, 2, 63, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 87, 88, 89, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 90, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 91, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 85, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 92, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 2, 2, 2, 2, 2, 2, 2, 2, 86, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 93, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ], r6: &[ 0xb7ffff7fffffefff, 0x000000003fff3fff, 0xffffffffffffffff, 0x07ffffffffffffff, 0x0000000000000000, 0x001fffffffffffff, 0xffffffff1fffffff, 0x000000000001ffff, - 0xffff0000ffffffff, 0x003fffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f, + 0xffffe000ffffffff, 0x003fffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f, 0xffff00003fffffff, 0x0fffffffff0fffff, 0xffff00ffffffffff, 0x0000000fffffffff, 0x007fffffffffffff, 0x000000ff003fffff, 0x91bffffffffffd3f, 0x007fffff003fffff, 0x000000007fffffff, 0x0037ffff00000000, 0x03ffffff003fffff, 0xc0ffffffffffffff, @@ -1126,15 +1137,17 @@ pub mod derived_property { 0x00000ffffffbffff, 0xffff01ffbfffbd7f, 0x23edfdfffff99fe0, 0x00000003e0010000, 0x0000000000000780, 0x0000ffffffffffff, 0x00000000000000b0, 0x00007fffffffffff, 0x000000000f000000, 0x0000000000000010, 0x000007ffffffffff, 0x0000000003ffffff, - 0xffffffff00000000, 0x80000000ffffffff, 0x01ffffffffffffff, 0x00007ffffffffdff, - 0xfffc000000000001, 0x000000000000ffff, 0x000000000000000f, 0x000000000000007f, - 0x00003fffffff0000, 0xe0fffff80000000f, 0x000000000001001f, 0x00000000fff80000, - 0x0000000100000000, 0x00001fffffffffff, 0x0000000000000003, 0x1fff07ffffffffff, - 0x0000000003ff01ff, 0xffffffffffdfffff, 0xebffde64dfffffff, 0xffffffffffffffef, - 0x7bffffffdfdfe7bf, 0xfffffffffffdfc5f, 0xffffff3fffffffff, 0xf7fffffff7fffffd, - 0xffdfffffffdfffff, 0xffff7fffffff7fff, 0xfffffdfffffffdff, 0x0000000000000ff7, - 0x000000000000001f, 0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, - 0x00000000007fffff, 0x00000003ffffffff, 0x000000003fffffff + 0xffffffff00000000, 0x80000000ffffffff, 0x0407fffffffff801, 0xfffffffff0010000, + 0x00000000000003cf, 0x01ffffffffffffff, 0x00007ffffffffdff, 0xfffc000000000001, + 0x000000000000ffff, 0x0001fffffffffb7f, 0x0000000000000040, 0x000000000000000f, + 0x000000000000007f, 0x00003fffffff0000, 0xe0fffff80000000f, 0x000000000001001f, + 0x00000000fff80000, 0x0000000300000000, 0x00001fffffffffff, 0xffff000000000000, + 0x0fffffffffffffff, 0x1fff07ffffffffff, 0x0000000003ff01ff, 0xffffffffffdfffff, + 0xebffde64dfffffff, 0xffffffffffffffef, 0x7bffffffdfdfe7bf, 0xfffffffffffdfc5f, + 0xffffff3fffffffff, 0xf7fffffff7fffffd, 0xffdfffffffdfffff, 0xffff7fffffff7fff, + 0xfffffdfffffffdff, 0x0000000000000ff7, 0x000000000000001f, 0x0af7fe96ffffffef, + 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, 0x00000000007fffff, 0xffff0003ffffffff, + 0x00000001ffffffff, 0x000000003fffffff ], }; diff --git a/src/test/compile-fail/auxiliary/allocator2.rs b/src/libstd_unicode/tests/lib.rs similarity index 72% rename from src/test/compile-fail/auxiliary/allocator2.rs rename to src/libstd_unicode/tests/lib.rs index b24784838d..9535ec1876 100644 --- a/src/test/compile-fail/auxiliary/allocator2.rs +++ b/src/libstd_unicode/tests/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2015 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. // @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// no-prefer-dynamic +#![feature(str_internals, unicode)] -#![feature(allocator)] -#![allocator] -#![crate_type = "rlib"] -#![no_std] +extern crate std_unicode; + +mod lossy; diff --git a/src/libstd_unicode/tests/lossy.rs b/src/libstd_unicode/tests/lossy.rs new file mode 100644 index 0000000000..e05d066855 --- /dev/null +++ b/src/libstd_unicode/tests/lossy.rs @@ -0,0 +1,91 @@ +// 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. +// +// 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_unicode::lossy::*; + +#[test] +fn chunks() { + let mut iter = Utf8Lossy::from_bytes(b"hello").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "hello", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = Utf8Lossy::from_bytes("ศไทย中华Việt Nam".as_bytes()).chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "ศไทย中华Việt Nam", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = Utf8Lossy::from_bytes(b"Hello\xC2 There\xFF Goodbye").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "Hello", broken: b"\xC2", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: " There", broken: b"\xFF", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: " Goodbye", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = Utf8Lossy::from_bytes(b"Hello\xC0\x80 There\xE6\x83 Goodbye").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "Hello", broken: b"\xC0", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: " There", broken: b"\xE6\x83", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: " Goodbye", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = Utf8Lossy::from_bytes(b"\xF5foo\xF5\x80bar").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF5", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF5", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = Utf8Lossy::from_bytes(b"\xF1foo\xF1\x80bar\xF1\x80\x80baz").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF1", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF1\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"\xF1\x80\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "baz", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = Utf8Lossy::from_bytes(b"\xF4foo\xF4\x80bar\xF4\xBFbaz").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF4", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF4\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"\xF4", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "baz", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = Utf8Lossy::from_bytes(b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF0", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "foo\u{10000}bar", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + // surrogates + let mut iter = Utf8Lossy::from_bytes(b"\xED\xA0\x80foo\xED\xBF\xBFbar").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xED", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xA0", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xED", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); +} + +#[test] +fn display() { + assert_eq!( + "Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye", + &format!("{}", Utf8Lossy::from_bytes(b"Hello\xC0\x80 There\xE6\x83 Goodbye"))); +} + +#[test] +fn debug() { + assert_eq!( + "\"Hello\\xc0\\x80 There\\xe6\\x83 Goodbye\\u{10d4ea}\"", + &format!("{:?}", Utf8Lossy::from_bytes( + b"Hello\xC0\x80 There\xE6\x83 Goodbye\xf4\x8d\x93\xaa"))); +} diff --git a/src/libstd_unicode/u_str.rs b/src/libstd_unicode/u_str.rs index 1454168d2d..54a5288a57 100644 --- a/src/libstd_unicode/u_str.rs +++ b/src/libstd_unicode/u_str.rs @@ -32,7 +32,7 @@ pub struct SplitWhitespace<'a> { } /// Methods for Unicode string slices -#[allow(missing_docs)] // docs in libcollections +#[allow(missing_docs)] // docs in liballoc pub trait UnicodeStr { fn split_whitespace<'a>(&'a self) -> SplitWhitespace<'a>; fn is_whitespace(&self) -> bool; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 2eb39bc26b..f7d9d53206 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -97,10 +97,9 @@ impl Path { } pub fn default_to_global(mut self) -> Path { - let name = self.segments[0].identifier.name; - if !self.is_global() && name != "$crate" && - name != keywords::SelfValue.name() && name != keywords::Super.name() { - self.segments.insert(0, PathSegment::crate_root()); + if !self.is_global() && + !::parse::token::Ident(self.segments[0].identifier).is_path_segment_keyword() { + self.segments.insert(0, PathSegment::crate_root(self.span)); } self } @@ -134,10 +133,10 @@ impl PathSegment { pub fn from_ident(ident: Ident, span: Span) -> Self { PathSegment { identifier: ident, span: span, parameters: None } } - pub fn crate_root() -> Self { + pub fn crate_root(span: Span) -> Self { PathSegment { - identifier: keywords::CrateRoot.ident(), - span: DUMMY_SP, + identifier: Ident { ctxt: span.ctxt, ..keywords::CrateRoot.ident() }, + span: span, parameters: None, } } @@ -775,10 +774,10 @@ pub struct Local { /// /// E.g. `0...10 => { println!("match!") }` as in /// -/// ```rust,ignore -/// match n { +/// ``` +/// match 123 { /// 0...10 => { println!("match!") }, -/// // .. +/// _ => { println!("no match!") }, /// } /// ``` #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] @@ -849,19 +848,16 @@ pub enum ExprKind { /// The first field resolves to the function itself, /// and the second field is the list of arguments Call(P, Vec>), - /// A method call (`x.foo::(a, b, c, d)`) + /// A method call (`x.foo::<'static, Bar, Baz>(a, b, c, d)`) /// - /// The `SpannedIdent` is the identifier for the method name. - /// The vector of `Ty`s are the ascripted type parameters for the method + /// The `PathSegment` represents the method name and its generic arguments /// (within the angle brackets). - /// /// The first element of the vector of `Expr`s is the expression that evaluates /// to the object on which the method is being called on (the receiver), /// and the remaining elements are the rest of the arguments. - /// /// Thus, `x.foo::(a, b, c, d)` is represented as - /// `ExprKind::MethodCall(foo, [Bar, Baz], [x, a, b, c, d])`. - MethodCall(SpannedIdent, Vec>, Vec>), + /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`. + MethodCall(PathSegment, Vec>), /// A tuple (`(a, b, c ,d)`) Tup(Vec>), /// A binary operation (For example: `a + b`, `a * b`) @@ -977,7 +973,7 @@ pub enum ExprKind { /// separately. `position` represents the index of the associated /// item qualified with this Self type. /// -/// ```rust,ignore +/// ```ignore (only-for-syntax-highlight) /// as a::b::Trait>::AssociatedItem /// ^~~~~ ~~~~~~~~~~~~~~^ /// ty position = 3 diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 8e63e219c4..a247fe7f8a 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -974,11 +974,11 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec let mut align_error = None; if let ast::LitKind::Int(align, ast::LitIntType::Unsuffixed) = value.node { if align.is_power_of_two() { - // rustc::ty::layout::Align restricts align to <= 32768 - if align <= 32768 { - acc.push(ReprAlign(align as u16)); + // rustc::ty::layout::Align restricts align to <= 2147483647 + if align <= 2147483647 { + acc.push(ReprAlign(align as u32)); } else { - align_error = Some("larger than 32768"); + align_error = Some("larger than 2147483647"); } } else { align_error = Some("not a power of two"); @@ -1027,7 +1027,7 @@ pub enum ReprAttr { ReprExtern, ReprPacked, ReprSimd, - ReprAlign(u16), + ReprAlign(u32), } #[derive(Eq, Hash, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)] @@ -1057,7 +1057,7 @@ impl MetaItem { { let (mut span, name) = match tokens.next() { Some(TokenTree::Token(span, Token::Ident(ident))) => (span, ident.name), - Some(TokenTree::Token(_, Token::Interpolated(ref nt))) => match **nt { + Some(TokenTree::Token(_, Token::Interpolated(ref nt))) => match nt.0 { token::Nonterminal::NtIdent(ident) => (ident.span, ident.node.name), token::Nonterminal::NtMeta(ref meta) => return Some(meta.clone()), _ => return None, @@ -1229,7 +1229,7 @@ impl LitKind { match token { Token::Ident(ident) if ident.name == "true" => Some(LitKind::Bool(true)), Token::Ident(ident) if ident.name == "false" => Some(LitKind::Bool(false)), - Token::Interpolated(ref nt) => match **nt { + Token::Interpolated(ref nt) => match nt.0 { token::NtExpr(ref v) => match v.node { ExprKind::Lit(ref lit) => Some(lit.node.clone()), _ => None, diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 830a457df7..bfdcae7641 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -158,29 +158,13 @@ impl CodeMap { /// Creates a new filemap without setting its line information. If you don't /// intend to set the line information yourself, you should use new_filemap_and_lines. - pub fn new_filemap(&self, filename: FileName, mut src: String) -> Rc { + pub fn new_filemap(&self, filename: FileName, src: String) -> Rc { let start_pos = self.next_start_pos(); let mut files = self.files.borrow_mut(); - // Remove utf-8 BOM if any. - if src.starts_with("\u{feff}") { - src.drain(..3); - } - - let end_pos = start_pos + src.len(); - let (filename, was_remapped) = self.path_mapping.map_prefix(filename); - - let filemap = Rc::new(FileMap { - name: filename, - name_was_remapped: was_remapped, - crate_of_origin: 0, - src: Some(Rc::new(src)), - start_pos: Pos::from_usize(start_pos), - end_pos: Pos::from_usize(end_pos), - lines: RefCell::new(Vec::new()), - multibyte_chars: RefCell::new(Vec::new()), - }); + let filemap = + Rc::new(FileMap::new(filename, was_remapped, src, Pos::from_usize(start_pos))); files.push(filemap.clone()); @@ -210,6 +194,7 @@ impl CodeMap { filename: FileName, name_was_remapped: bool, crate_of_origin: u32, + src_hash: u128, source_len: usize, mut file_local_lines: Vec, mut file_local_multibyte_chars: Vec) @@ -233,6 +218,8 @@ impl CodeMap { name_was_remapped: name_was_remapped, crate_of_origin: crate_of_origin, src: None, + src_hash: src_hash, + external_src: RefCell::new(ExternalSource::AbsentOk), start_pos: start_pos, end_pos: end_pos, lines: RefCell::new(file_local_lines), @@ -428,30 +415,31 @@ impl CodeMap { local_end.fm.start_pos) })); } else { - match local_begin.fm.src { - Some(ref src) => { - let start_index = local_begin.pos.to_usize(); - let end_index = local_end.pos.to_usize(); - let source_len = (local_begin.fm.end_pos - - local_begin.fm.start_pos).to_usize(); - - if start_index > end_index || end_index > source_len { - return Err(SpanSnippetError::MalformedForCodemap( - MalformedCodemapPositions { - name: local_begin.fm.name.clone(), - source_len: source_len, - begin_pos: local_begin.pos, - end_pos: local_end.pos, - })); - } - - return Ok((&src[start_index..end_index]).to_string()) - } - None => { - return Err(SpanSnippetError::SourceNotAvailable { - filename: local_begin.fm.name.clone() - }); - } + self.ensure_filemap_source_present(local_begin.fm.clone()); + + let start_index = local_begin.pos.to_usize(); + let end_index = local_end.pos.to_usize(); + let source_len = (local_begin.fm.end_pos - + local_begin.fm.start_pos).to_usize(); + + if start_index > end_index || end_index > source_len { + return Err(SpanSnippetError::MalformedForCodemap( + MalformedCodemapPositions { + name: local_begin.fm.name.clone(), + source_len: source_len, + begin_pos: local_begin.pos, + end_pos: local_end.pos, + })); + } + + if let Some(ref src) = local_begin.fm.src { + return Ok((&src[start_index..end_index]).to_string()); + } else if let Some(src) = local_begin.fm.external_src.borrow().get_source() { + return Ok((&src[start_index..end_index]).to_string()); + } else { + return Err(SpanSnippetError::SourceNotAvailable { + filename: local_begin.fm.name.clone() + }); } } } @@ -572,6 +560,11 @@ impl CodeMapper for CodeMap { } sp } + fn ensure_filemap_source_present(&self, file_map: Rc) -> bool { + file_map.add_external_src( + || self.file_loader.read_file(Path::new(&file_map.name)).ok() + ) + } } #[derive(Clone)] @@ -617,6 +610,7 @@ impl FilePathMapping { #[cfg(test)] mod tests { use super::*; + use std::borrow::Cow; use std::rc::Rc; #[test] @@ -626,12 +620,12 @@ mod tests { "first line.\nsecond line".to_string()); fm.next_line(BytePos(0)); // Test we can get lines with partial line info. - assert_eq!(fm.get_line(0), Some("first line.")); + assert_eq!(fm.get_line(0), Some(Cow::from("first line."))); // TESTING BROKEN BEHAVIOR: line break declared before actual line break. fm.next_line(BytePos(10)); - assert_eq!(fm.get_line(1), Some(".")); + assert_eq!(fm.get_line(1), Some(Cow::from("."))); fm.next_line(BytePos(12)); - assert_eq!(fm.get_line(2), Some("second line")); + assert_eq!(fm.get_line(2), Some(Cow::from("second line"))); } #[test] diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 2e98c7d962..54e6dde41e 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -223,7 +223,6 @@ impl<'a> StripUnconfigured<'a> { ast::ExprKind::Struct(path, fields, base) => { let fields = fields.into_iter() .filter_map(|field| { - self.visit_struct_field_attrs(field.attrs()); self.configure(field) }) .collect(); @@ -256,17 +255,6 @@ impl<'a> StripUnconfigured<'a> { } pub fn configure_struct_expr_field(&mut self, field: ast::Field) -> Option { - if !self.features.map(|features| features.struct_field_attributes).unwrap_or(true) { - if !field.attrs.is_empty() { - let mut err = feature_err(self.sess, - "struct_field_attributes", - field.span, - GateIssue::Language, - "attributes on struct literal fields are unstable"); - err.emit(); - } - } - self.configure(field) } @@ -275,7 +263,6 @@ impl<'a> StripUnconfigured<'a> { if let ast::PatKind::Struct(path, fields, etc) = pattern.node { let fields = fields.into_iter() .filter_map(|field| { - self.visit_struct_field_attrs(field.attrs()); self.configure(field) }) .collect(); @@ -284,21 +271,6 @@ impl<'a> StripUnconfigured<'a> { pattern }) } - - fn visit_struct_field_attrs(&mut self, attrs: &[ast::Attribute]) { - // flag the offending attributes - for attr in attrs.iter() { - if !self.features.map(|features| features.struct_field_attributes).unwrap_or(true) { - let mut err = feature_err( - self.sess, - "struct_field_attributes", - attr.span, - GateIssue::Language, - "attributes on struct pattern or literal fields are unstable"); - err.emit(); - } - } - } } impl<'a> fold::Folder for StripUnconfigured<'a> { diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs index 01d1277ea6..508feca973 100644 --- a/src/libsyntax/diagnostic_list.rs +++ b/src/libsyntax/diagnostic_list.rs @@ -51,12 +51,14 @@ fn main() {} The parenthesized `inline` attribute requires the parameter to be specified: -```ignore +``` #[inline(always)] fn something() {} +``` -// or: +or: +``` #[inline(never)] fn something() {} ``` diff --git a/src/libsyntax/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs index 13016d7212..e8ecf58072 100644 --- a/src/libsyntax/diagnostics/macros.rs +++ b/src/libsyntax/diagnostics/macros.rs @@ -74,6 +74,17 @@ macro_rules! struct_span_err { }) } +#[macro_export] +macro_rules! type_error_struct { + ($session:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({ + if $typ.references_error() { + $session.diagnostic().struct_dummy() + } else { + struct_span_err!($session, $span, $code, $($message)*) + } + }) +} + #[macro_export] macro_rules! struct_span_warn { ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 8089fad5f3..4881170c1d 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -215,7 +215,7 @@ impl TTMacroExpander for F impl Folder for AvoidInterpolatedIdents { fn fold_tt(&mut self, tt: tokenstream::TokenTree) -> tokenstream::TokenTree { if let tokenstream::TokenTree::Token(_, token::Interpolated(ref nt)) = tt { - if let token::NtIdent(ident) = **nt { + if let token::NtIdent(ident) = nt.0 { return tokenstream::TokenTree::Token(ident.span, token::Ident(ident.node)); } } @@ -578,7 +578,10 @@ impl SyntaxExtension { pub fn is_modern(&self) -> bool { match *self { - SyntaxExtension::DeclMacro(..) => true, + SyntaxExtension::DeclMacro(..) | + SyntaxExtension::ProcMacro(..) | + SyntaxExtension::AttrProcMacro(..) | + SyntaxExtension::ProcMacroDerive(..) => true, _ => false, } } @@ -903,17 +906,3 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt, } Some(es) } - -pub struct ChangeSpan { - pub span: Span -} - -impl Folder for ChangeSpan { - fn new_span(&mut self, _sp: Span) -> Span { - self.span - } - - fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { - fold::noop_fold_mac(mac, self) - } -} diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index a4580ea393..2555bf6dea 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -11,7 +11,7 @@ use abi::Abi; use ast::{self, Ident, Generics, Expr, BlockCheckMode, UnOp, PatKind}; use attr; -use syntax_pos::{Span, DUMMY_SP}; +use syntax_pos::{Pos, Span, DUMMY_SP}; use codemap::{dummy_spanned, respan, Spanned}; use ext::base::ExtCtxt; use ptr::P; @@ -249,6 +249,8 @@ pub trait AstBuilder { name: Ident, attrs: Vec, items: Vec>) -> P; + fn item_extern_crate(&self, span: Span, name: Ident) -> P; + fn item_static(&self, span: Span, name: Ident, @@ -320,7 +322,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let last_identifier = idents.pop().unwrap(); let mut segments: Vec = Vec::new(); if global { - segments.push(ast::PathSegment::crate_root()); + segments.push(ast::PathSegment::crate_root(sp)); } segments.extend(idents.into_iter().map(|i| ast::PathSegment::from_ident(i, sp))); @@ -671,9 +673,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> { expr: P, ident: ast::Ident, mut args: Vec> ) -> P { - let id = Spanned { node: ident, span: span }; args.insert(0, expr); - self.expr(span, ast::ExprKind::MethodCall(id, Vec::new(), args)) + self.expr(span, ast::ExprKind::MethodCall(ast::PathSegment::from_ident(ident, span), args)) } fn expr_block(&self, b: P) -> P { self.expr(b.span, ast::ExprKind::Block(b)) @@ -768,14 +769,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let loc = self.codemap().lookup_char_pos(span.lo); let expr_file = self.expr_str(span, Symbol::intern(&loc.file.name)); let expr_line = self.expr_u32(span, loc.line as u32); - let expr_file_line_tuple = self.expr_tuple(span, vec![expr_file, expr_line]); - let expr_file_line_ptr = self.expr_addr_of(span, expr_file_line_tuple); + let expr_col = self.expr_u32(span, loc.col.to_usize() as u32 + 1); + let expr_loc_tuple = self.expr_tuple(span, vec![expr_file, expr_line, expr_col]); + let expr_loc_ptr = self.expr_addr_of(span, expr_loc_tuple); self.expr_call_global( span, - self.std_path(&["rt", "begin_panic"]), + self.std_path(&["rt", "begin_panic_new"]), vec![ self.expr_str(span, msg), - expr_file_line_ptr]) + expr_loc_ptr]) } fn expr_unreachable(&self, span: Span) -> P { @@ -1094,6 +1096,10 @@ impl<'a> AstBuilder for ExtCtxt<'a> { ) } + fn item_extern_crate(&self, span: Span, name: Ident) -> P { + self.item(span, name, Vec::new(), ast::ItemKind::ExternCrate(None)) + } + fn item_static(&self, span: Span, name: Ident, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index c91c77719e..352b0e5327 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -16,20 +16,20 @@ use config::{is_test_or_bench, StripUnconfigured}; use errors::FatalError; use ext::base::*; use ext::derive::{add_derived_markers, collect_derives}; -use ext::hygiene::Mark; +use ext::hygiene::{Mark, SyntaxContext}; use ext::placeholders::{placeholder, PlaceholderExpander}; use feature_gate::{self, Features, is_builtin_attr}; use fold; use fold::*; -use parse::{filemap_to_stream, ParseSess, DirectoryOwnership, PResult, token}; +use parse::{DirectoryOwnership, PResult}; +use parse::token::{self, Token}; use parse::parser::Parser; -use print::pprust; use ptr::P; use std_inject; use symbol::Symbol; use symbol::keywords; use syntax_pos::{Span, DUMMY_SP}; -use tokenstream::TokenStream; +use tokenstream::{TokenStream, TokenTree}; use util::small_vector::SmallVector; use visit::Visitor; @@ -427,11 +427,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> { kind.expect_from_annotatables(items) } SyntaxExtension::AttrProcMacro(ref mac) => { - let item_toks = stream_for_item(&item, self.cx.parse_sess); - - let span = Span { ctxt: self.cx.backtrace(), ..attr.span }; - let tok_result = mac.expand(self.cx, attr.span, attr.tokens, item_toks); - self.parse_expansion(tok_result, kind, &attr.path, span) + let item_tok = TokenTree::Token(DUMMY_SP, Token::interpolated(match item { + Annotatable::Item(item) => token::NtItem(item), + Annotatable::TraitItem(item) => token::NtTraitItem(item.unwrap()), + Annotatable::ImplItem(item) => token::NtImplItem(item.unwrap()), + })).into(); + let tok_result = mac.expand(self.cx, attr.span, attr.tokens, item_tok); + self.parse_expansion(tok_result, kind, &attr.path, attr.span) } SyntaxExtension::ProcMacroDerive(..) | SyntaxExtension::BuiltinDerive(..) => { self.cx.span_err(attr.span, &format!("`{}` is a derive mode", attr.path)); @@ -470,7 +472,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { Ok(()) }; - let marked_tts = noop_fold_tts(mac.node.stream(), &mut Marker(mark)); let opt_expanded = match *ext { SyntaxExtension::DeclMacro(ref expand, def_span) => { if let Err(msg) = validate_and_set_expn_info(def_span.map(|(_, s)| s), @@ -478,7 +479,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.span_err(path.span, &msg); return kind.dummy(span); } - kind.make_from(expand.expand(self.cx, span, marked_tts)) + kind.make_from(expand.expand(self.cx, span, mac.node.stream())) } NormalTT(ref expandfun, def_info, allow_internal_unstable) => { @@ -487,7 +488,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.span_err(path.span, &msg); return kind.dummy(span); } - kind.make_from(expandfun.expand(self.cx, span, marked_tts)) + kind.make_from(expandfun.expand(self.cx, span, mac.node.stream())) } IdentTT(ref expander, tt_span, allow_internal_unstable) => { @@ -506,7 +507,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } }); - let input: Vec<_> = marked_tts.into_trees().collect(); + let input: Vec<_> = mac.node.stream().into_trees().collect(); kind.make_from(expander.expand(self.cx, span, ident, input)) } @@ -541,21 +542,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }, }); - let tok_result = expandfun.expand(self.cx, span, marked_tts); + let tok_result = expandfun.expand(self.cx, span, mac.node.stream()); Some(self.parse_expansion(tok_result, kind, path, span)) } }; - let expanded = if let Some(expanded) = opt_expanded { - expanded - } else { + unwrap_or!(opt_expanded, { let msg = format!("non-{kind} macro in {kind} position: {name}", name = path.segments[0].identifier.name, kind = kind.name()); self.cx.span_err(path.span, &msg); - return kind.dummy(span); - }; - - expanded.fold_with(&mut Marker(mark)) + kind.dummy(span) + }) } /// Expand a derive invocation. Returns the result of expansion. @@ -621,8 +618,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } }; parser.ensure_complete_parse(path, kind.name(), span); - // FIXME better span info - expansion.fold_with(&mut ChangeSpan { span: span }) + expansion } } @@ -673,7 +669,9 @@ impl<'a> Parser<'a> { if self.token != token::Eof { let msg = format!("macro expansion ignores token `{}` and any following", self.this_token_to_string()); - let mut err = self.diagnostic().struct_span_err(self.span, &msg); + let mut def_site_span = self.span; + def_site_span.ctxt = SyntaxContext::empty(); // Avoid emitting backtrace info twice. + let mut err = self.diagnostic().struct_span_err(def_site_span, &msg); let msg = format!("caused by the macro expansion here; the usage \ of `{}!` is likely invalid in {} context", macro_path, kind_name); @@ -773,28 +771,6 @@ pub fn find_attr_invoc(attrs: &mut Vec) -> Option TokenStream { - let text = match *item { - Annotatable::Item(ref i) => pprust::item_to_string(i), - Annotatable::TraitItem(ref ti) => pprust::trait_item_to_string(ti), - Annotatable::ImplItem(ref ii) => pprust::impl_item_to_string(ii), - }; - string_to_stream(text, parse_sess) -} - -fn string_to_stream(text: String, parse_sess: &ParseSess) -> TokenStream { - let filename = String::from(""); - filemap_to_stream(parse_sess, parse_sess.codemap().new_filemap(filename, text)) -} - impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { fn fold_expr(&mut self, expr: P) -> P { let mut expr = self.cfg.configure_expr(expr).unwrap(); @@ -1069,7 +1045,7 @@ impl<'feat> ExpansionConfig<'feat> { } // A Marker adds the given mark to the syntax context. -struct Marker(Mark); +pub struct Marker(pub Mark); impl Folder for Marker { fn fold_ident(&mut self, mut ident: Ident) -> Ident { diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index f8fac847a0..9907dfe341 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -30,9 +30,9 @@ pub mod rt { use ast; use codemap::Spanned; use ext::base::ExtCtxt; - use parse::{self, token, classify}; + use parse::{self, classify}; + use parse::token::{self, Token}; use ptr::P; - use std::rc::Rc; use symbol::Symbol; use tokenstream::{self, TokenTree, TokenStream}; @@ -82,70 +82,70 @@ pub mod rt { impl ToTokens for ast::Path { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { let nt = token::NtPath(self.clone()); - vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))] + vec![TokenTree::Token(DUMMY_SP, Token::interpolated(nt))] } } impl ToTokens for ast::Ty { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { let nt = token::NtTy(P(self.clone())); - vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] + vec![TokenTree::Token(self.span, Token::interpolated(nt))] } } impl ToTokens for ast::Block { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { let nt = token::NtBlock(P(self.clone())); - vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] + vec![TokenTree::Token(self.span, Token::interpolated(nt))] } } impl ToTokens for ast::Generics { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { let nt = token::NtGenerics(self.clone()); - vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))] + vec![TokenTree::Token(DUMMY_SP, Token::interpolated(nt))] } } impl ToTokens for ast::WhereClause { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { let nt = token::NtWhereClause(self.clone()); - vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))] + vec![TokenTree::Token(DUMMY_SP, Token::interpolated(nt))] } } impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { let nt = token::NtItem(self.clone()); - vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] + vec![TokenTree::Token(self.span, Token::interpolated(nt))] } } impl ToTokens for ast::ImplItem { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { let nt = token::NtImplItem(self.clone()); - vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] + vec![TokenTree::Token(self.span, Token::interpolated(nt))] } } impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { let nt = token::NtImplItem((**self).clone()); - vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] + vec![TokenTree::Token(self.span, Token::interpolated(nt))] } } impl ToTokens for ast::TraitItem { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { let nt = token::NtTraitItem(self.clone()); - vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] + vec![TokenTree::Token(self.span, Token::interpolated(nt))] } } impl ToTokens for ast::Stmt { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { let nt = token::NtStmt(self.clone()); - let mut tts = vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))]; + let mut tts = vec![TokenTree::Token(self.span, Token::interpolated(nt))]; // Some statements require a trailing semicolon. if classify::stmt_ends_with_semi(&self.node) { @@ -159,35 +159,35 @@ pub mod rt { impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { let nt = token::NtExpr(self.clone()); - vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] + vec![TokenTree::Token(self.span, Token::interpolated(nt))] } } impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { let nt = token::NtPat(self.clone()); - vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] + vec![TokenTree::Token(self.span, Token::interpolated(nt))] } } impl ToTokens for ast::Arm { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { let nt = token::NtArm(self.clone()); - vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))] + vec![TokenTree::Token(DUMMY_SP, Token::interpolated(nt))] } } impl ToTokens for ast::Arg { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { let nt = token::NtArg(self.clone()); - vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))] + vec![TokenTree::Token(DUMMY_SP, Token::interpolated(nt))] } } impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { let nt = token::NtBlock(self.clone()); - vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))] + vec![TokenTree::Token(DUMMY_SP, Token::interpolated(nt))] } } @@ -215,7 +215,7 @@ pub mod rt { impl ToTokens for ast::MetaItem { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { let nt = token::NtMeta(self.clone()); - vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))] + vec![TokenTree::Token(DUMMY_SP, Token::interpolated(nt))] } } @@ -364,7 +364,7 @@ pub mod rt { fn parse_tts(&self, s: String) -> Vec { let source_name = "".to_owned(); - parse::parse_stream_from_source_str(source_name, s, self.parse_sess()) + parse::parse_stream_from_source_str(source_name, s, self.parse_sess(), None) .into_trees().collect() } } @@ -700,7 +700,7 @@ fn expr_mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P { token::Underscore => "Underscore", token::Eof => "Eof", - token::Whitespace | token::SubstNt(_) | token::Comment | token::Shebang(_) => { + token::Whitespace | token::Comment | token::Shebang(_) => { panic!("unhandled token in quote!"); } }; diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index 3cdd3a4b2c..95fe41be12 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -52,6 +52,16 @@ pub fn expand_column(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree]) base::MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32)) } +/* __rust_unstable_column!(): expands to the current column number */ +pub fn expand_column_gated(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree]) + -> Box { + if sp.allows_unstable() { + expand_column(cx, sp, tts) + } else { + cx.span_fatal(sp, "the __rust_unstable_column macro is unstable"); + } +} + /// file!(): expands to the current filename */ /// The filemap (`loc.file`) contains a bunch more information we could spit /// out if we wanted. @@ -183,13 +193,14 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::Toke // resolve a file-system path to an absolute file-system path (if it // isn't already) fn res_rel_file(cx: &mut ExtCtxt, sp: syntax_pos::Span, arg: &Path) -> PathBuf { - // NB: relative paths are resolved relative to the compilation unit + // Relative paths are resolved relative to the file in which they are found + // after macro expansion (that is, they are unhygienic). if !arg.is_absolute() { let callsite = sp.source_callsite(); - let mut cu = PathBuf::from(&cx.codemap().span_to_filename(callsite)); - cu.pop(); - cu.push(arg); - cu + let mut path = PathBuf::from(&cx.codemap().span_to_filename(callsite)); + path.pop(); + path.push(arg); + path } else { arg.to_path_buf() } diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 0b6a2eb536..d18961b75c 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -139,27 +139,29 @@ struct MatcherPos { sep: Option, idx: usize, up: Option>, - matches: Vec>>, + matches: Vec>>, match_lo: usize, match_cur: usize, match_hi: usize, sp_lo: BytePos, } +impl MatcherPos { + fn push_match(&mut self, idx: usize, m: NamedMatch) { + let matches = Rc::make_mut(&mut self.matches[idx]); + matches.push(m); + } +} + pub type NamedParseResult = ParseResult>>; pub fn count_names(ms: &[TokenTree]) -> usize { ms.iter().fold(0, |count, elt| { count + match *elt { - TokenTree::Sequence(_, ref seq) => { - seq.num_captures - } - TokenTree::Delimited(_, ref delim) => { - count_names(&delim.tts) - } - TokenTree::MetaVarDecl(..) => { - 1 - } + TokenTree::Sequence(_, ref seq) => seq.num_captures, + TokenTree::Delimited(_, ref delim) => count_names(&delim.tts), + TokenTree::MetaVar(..) => 0, + TokenTree::MetaVarDecl(..) => 1, TokenTree::Token(..) => 0, } }) @@ -199,14 +201,15 @@ fn initial_matcher_pos(ms: Vec, lo: BytePos) -> Box { /// only on the nesting depth of `ast::TTSeq`s in the originating /// token tree it was derived from. +#[derive(Debug, Clone)] pub enum NamedMatch { - MatchedSeq(Vec>, syntax_pos::Span), + MatchedSeq(Rc>, syntax_pos::Span), MatchedNonterminal(Rc) } -fn nameize>>(sess: &ParseSess, ms: &[TokenTree], mut res: I) +fn nameize>(sess: &ParseSess, ms: &[TokenTree], mut res: I) -> NamedParseResult { - fn n_rec>>(sess: &ParseSess, m: &TokenTree, mut res: &mut I, + fn n_rec>(sess: &ParseSess, m: &TokenTree, mut res: &mut I, ret_val: &mut HashMap>) -> Result<(), (syntax_pos::Span, String)> { match *m { @@ -228,14 +231,15 @@ fn nameize>>(sess: &ParseSess, ms: &[TokenTree], TokenTree::MetaVarDecl(sp, bind_name, _) => { match ret_val.entry(bind_name) { Vacant(spot) => { - spot.insert(res.next().unwrap()); + // FIXME(simulacrum): Don't construct Rc here + spot.insert(Rc::new(res.next().unwrap())); } Occupied(..) => { return Err((sp, format!("duplicated bind name: {}", bind_name))) } } } - TokenTree::Token(..) => (), + TokenTree::MetaVar(..) | TokenTree::Token(..) => (), } Ok(()) @@ -280,8 +284,8 @@ fn token_name_eq(t1 : &Token, t2 : &Token) -> bool { } } -fn create_matches(len: usize) -> Vec>> { - (0..len).into_iter().map(|_| Vec::new()).collect() +fn create_matches(len: usize) -> Vec>> { + (0..len).into_iter().map(|_| Rc::new(Vec::new())).collect() } fn inner_parse_loop(sess: &ParseSess, @@ -320,15 +324,10 @@ fn inner_parse_loop(sess: &ParseSess, // update matches (the MBE "parse tree") by appending // each tree as a subtree. - // I bet this is a perf problem: we're preemptively - // doing a lot of array work that will get thrown away - // most of the time. - // Only touch the binders we have actually bound for idx in ei.match_lo..ei.match_hi { let sub = ei.matches[idx].clone(); - new_pos.matches[idx] - .push(Rc::new(MatchedSeq(sub, Span { lo: ei.sp_lo, ..span }))); + new_pos.push_match(idx, MatchedSeq(sub, Span { lo: ei.sp_lo, ..span })); } new_pos.match_cur = ei.match_hi; @@ -362,7 +361,7 @@ fn inner_parse_loop(sess: &ParseSess, new_ei.match_cur += seq.num_captures; new_ei.idx += 1; for idx in ei.match_cur..ei.match_cur + seq.num_captures { - new_ei.matches[idx].push(Rc::new(MatchedSeq(vec![], sp))); + new_ei.push_match(idx, MatchedSeq(Rc::new(vec![]), sp)); } cur_eis.push(new_ei); } @@ -387,12 +386,11 @@ fn inner_parse_loop(sess: &ParseSess, return Error(span, "missing fragment specifier".to_string()); } } - TokenTree::MetaVarDecl(..) => { + TokenTree::MetaVarDecl(_, _, id) => { // Built-in nonterminals never start with these tokens, // so we can eliminate them from consideration. - match *token { - token::CloseDelim(_) => {}, - _ => bb_eis.push(ei), + if may_begin_with(&*id.name.as_str(), token) { + bb_eis.push(ei); } } seq @ TokenTree::Delimited(..) | seq @ TokenTree::Token(_, DocComment(..)) => { @@ -405,12 +403,11 @@ fn inner_parse_loop(sess: &ParseSess, ei.idx = 0; cur_eis.push(ei); } - TokenTree::Token(_, ref t) => { - if token_name_eq(t, token) { - ei.idx += 1; - next_eis.push(ei); - } + TokenTree::Token(_, ref t) if token_name_eq(t, token) => { + ei.idx += 1; + next_eis.push(ei); } + TokenTree::Token(..) | TokenTree::MetaVar(..) => {} } } } @@ -446,7 +443,9 @@ pub fn parse(sess: &ParseSess, /* error messages here could be improved with links to orig. rules */ if token_name_eq(&parser.token, &token::Eof) { if eof_eis.len() == 1 { - let matches = eof_eis[0].matches.iter_mut().map(|mut dv| dv.pop().unwrap()); + let matches = eof_eis[0].matches.iter_mut().map(|mut dv| { + Rc::make_mut(dv).pop().unwrap() + }); return nameize(sess, ms, matches); } else if eof_eis.len() > 1 { return Error(parser.span, "ambiguity: multiple successful parses".to_string()); @@ -479,8 +478,8 @@ pub fn parse(sess: &ParseSess, let mut ei = bb_eis.pop().unwrap(); if let TokenTree::MetaVarDecl(span, _, ident) = ei.top_elts.get_tt(ei.idx) { let match_cur = ei.match_cur; - ei.matches[match_cur].push(Rc::new(MatchedNonterminal( - Rc::new(parse_nt(&mut parser, span, &ident.name.as_str()))))); + ei.push_match(match_cur, + MatchedNonterminal(Rc::new(parse_nt(&mut parser, span, &ident.name.as_str())))); ei.idx += 1; ei.match_cur += 1; } else { @@ -493,6 +492,73 @@ pub fn parse(sess: &ParseSess, } } +/// Checks whether a non-terminal may begin with a particular token. +/// +/// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with that +/// token. Be conservative (return true) if not sure. +fn may_begin_with(name: &str, token: &Token) -> bool { + /// Checks whether the non-terminal may contain a single (non-keyword) identifier. + fn may_be_ident(nt: &token::Nonterminal) -> bool { + match *nt { + token::NtItem(_) | token::NtBlock(_) | token::NtVis(_) => false, + _ => true, + } + } + + match name { + "expr" => token.can_begin_expr(), + "ty" => token.can_begin_type(), + "ident" => token.is_ident(), + "vis" => match *token { // The follow-set of :vis + "priv" keyword + interpolated + Token::Comma | Token::Ident(_) | Token::Interpolated(_) => true, + _ => token.can_begin_type(), + }, + "block" => match *token { + Token::OpenDelim(token::Brace) => true, + Token::Interpolated(ref nt) => match nt.0 { + token::NtItem(_) | + token::NtPat(_) | + token::NtTy(_) | + token::NtIdent(_) | + token::NtMeta(_) | + token::NtPath(_) | + token::NtVis(_) => false, // none of these may start with '{'. + _ => true, + }, + _ => false, + }, + "path" | "meta" => match *token { + Token::ModSep | Token::Ident(_) => true, + Token::Interpolated(ref nt) => match nt.0 { + token::NtPath(_) | token::NtMeta(_) => true, + _ => may_be_ident(&nt.0), + }, + _ => false, + }, + "pat" => match *token { + Token::Ident(_) | // box, ref, mut, and other identifiers (can stricten) + Token::OpenDelim(token::Paren) | // tuple pattern + Token::OpenDelim(token::Bracket) | // slice pattern + Token::BinOp(token::And) | // reference + Token::BinOp(token::Minus) | // negative literal + Token::AndAnd | // double reference + Token::Literal(..) | // literal + Token::DotDot | // range pattern (future compat) + Token::DotDotDot | // range pattern (future compat) + Token::ModSep | // path + Token::Lt | // path (UFCS constant) + Token::BinOp(token::Shl) | // path (double UFCS) + Token::Underscore => true, // placeholder + Token::Interpolated(ref nt) => may_be_ident(&nt.0), + _ => false, + }, + _ => match *token { + token::CloseDelim(_) => false, + _ => true, + }, + } +} + fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal { if name == "tt" { return token::NtTT(p.parse_token_tree()); diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 0472a94e0c..f786b1abb8 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -120,7 +120,7 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt, _ => cx.span_bug(sp, "malformed macro rhs"), }; // rhs has holes ( `$id` and `$(...)` that need filled) - let tts = transcribe(&cx.parse_sess.span_diagnostic, Some(named_matches), rhs); + let tts = transcribe(cx, Some(named_matches), rhs); if cx.trace_macros() { trace_macros_note(cx, sp, format!("to `{}`", tts)); @@ -219,10 +219,10 @@ pub fn compile(sess: &ParseSess, features: &RefCell, def: &ast::Item) let lhses = match *argument_map[&lhs_nm] { MatchedSeq(ref s, _) => { s.iter().map(|m| { - if let MatchedNonterminal(ref nt) = **m { + if let MatchedNonterminal(ref nt) = *m { if let NtTT(ref tt) = **nt { let tt = quoted::parse(tt.clone().into(), true, sess).pop().unwrap(); - valid &= check_lhs_nt_follows(sess, features, &tt); + valid &= check_lhs_nt_follows(sess, features, &def.attrs, &tt); return tt; } } @@ -235,7 +235,7 @@ pub fn compile(sess: &ParseSess, features: &RefCell, def: &ast::Item) let rhses = match *argument_map[&rhs_nm] { MatchedSeq(ref s, _) => { s.iter().map(|m| { - if let MatchedNonterminal(ref nt) = **m { + if let MatchedNonterminal(ref nt) = *m { if let NtTT(ref tt) = **nt { return quoted::parse(tt.clone().into(), false, sess).pop().unwrap(); } @@ -272,11 +272,12 @@ pub fn compile(sess: &ParseSess, features: &RefCell, def: &ast::Item) fn check_lhs_nt_follows(sess: &ParseSess, features: &RefCell, + attrs: &[ast::Attribute], lhs: "ed::TokenTree) -> bool { // lhs is going to be like TokenTree::Delimited(...), where the // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens. if let quoted::TokenTree::Delimited(_, ref tts) = *lhs { - check_matcher(sess, features, &tts.tts) + check_matcher(sess, features, attrs, &tts.tts) } else { let msg = "invalid macro matcher; matchers must be contained in balanced delimiters"; sess.span_diagnostic.span_err(lhs.span(), msg); @@ -292,13 +293,14 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[quoted::TokenTree]) -> bool { use self::quoted::TokenTree; for tt in tts { match *tt { - TokenTree::Token(..) | TokenTree::MetaVarDecl(..) => (), + TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => (), TokenTree::Delimited(_, ref del) => if !check_lhs_no_empty_seq(sess, &del.tts) { return false; }, TokenTree::Sequence(span, ref seq) => { if seq.separator.is_none() && seq.tts.iter().all(|seq_tt| { match *seq_tt { + TokenTree::MetaVarDecl(_, _, id) => id.name == "vis", TokenTree::Sequence(_, ref sub_seq) => sub_seq.op == quoted::KleeneOp::ZeroOrMore, _ => false, @@ -327,11 +329,12 @@ fn check_rhs(sess: &ParseSess, rhs: "ed::TokenTree) -> bool { fn check_matcher(sess: &ParseSess, features: &RefCell, + attrs: &[ast::Attribute], matcher: &[quoted::TokenTree]) -> bool { let first_sets = FirstSets::new(matcher); let empty_suffix = TokenSet::empty(); let err = sess.span_diagnostic.err_count(); - check_matcher_core(sess, features, &first_sets, matcher, &empty_suffix); + check_matcher_core(sess, features, attrs, &first_sets, matcher, &empty_suffix); err == sess.span_diagnostic.err_count() } @@ -372,7 +375,7 @@ impl FirstSets { let mut first = TokenSet::empty(); for tt in tts.iter().rev() { match *tt { - TokenTree::Token(..) | TokenTree::MetaVarDecl(..) => { + TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => { first.replace_with(tt.clone()); } TokenTree::Delimited(span, ref delimited) => { @@ -432,7 +435,7 @@ impl FirstSets { for tt in tts.iter() { assert!(first.maybe_empty); match *tt { - TokenTree::Token(..) | TokenTree::MetaVarDecl(..) => { + TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => { first.add_one(tt.clone()); return first; } @@ -574,6 +577,7 @@ impl TokenSet { // see `FirstSets::new`. fn check_matcher_core(sess: &ParseSess, features: &RefCell, + attrs: &[ast::Attribute], first_sets: &FirstSets, matcher: &[quoted::TokenTree], follow: &TokenSet) -> TokenSet { @@ -602,9 +606,9 @@ fn check_matcher_core(sess: &ParseSess, // First, update `last` so that it corresponds to the set // of NT tokens that might end the sequence `... token`. match *token { - TokenTree::Token(..) | TokenTree::MetaVarDecl(..) => { + TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => { let can_be_followed_by_any; - if let Err(bad_frag) = has_legal_fragment_specifier(sess, features, token) { + if let Err(bad_frag) = has_legal_fragment_specifier(sess, features, attrs, token) { let msg = format!("invalid fragment specifier `{}`", bad_frag); sess.span_diagnostic.struct_span_err(token.span(), &msg) .help("valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, \ @@ -630,7 +634,7 @@ fn check_matcher_core(sess: &ParseSess, } TokenTree::Delimited(span, ref d) => { let my_suffix = TokenSet::singleton(d.close_tt(span)); - check_matcher_core(sess, features, first_sets, &d.tts, &my_suffix); + check_matcher_core(sess, features, attrs, first_sets, &d.tts, &my_suffix); // don't track non NT tokens last.replace_with_irrelevant(); @@ -662,7 +666,12 @@ fn check_matcher_core(sess: &ParseSess, // At this point, `suffix_first` is built, and // `my_suffix` is some TokenSet that we can use // for checking the interior of `seq_rep`. - let next = check_matcher_core(sess, features, first_sets, &seq_rep.tts, my_suffix); + let next = check_matcher_core(sess, + features, + attrs, + first_sets, + &seq_rep.tts, + my_suffix); if next.maybe_empty { last.add_all(&next); } else { @@ -835,12 +844,13 @@ fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> Result, + attrs: &[ast::Attribute], tok: "ed::TokenTree) -> Result<(), String> { debug!("has_legal_fragment_specifier({:?})", tok); if let quoted::TokenTree::MetaVarDecl(_, _, ref frag_spec) = *tok { let frag_name = frag_spec.name.as_str(); let frag_span = tok.span(); - if !is_legal_fragment_specifier(sess, features, &frag_name, frag_span) { + if !is_legal_fragment_specifier(sess, features, attrs, &frag_name, frag_span) { return Err(frag_name.to_string()); } } @@ -849,13 +859,15 @@ fn has_legal_fragment_specifier(sess: &ParseSess, fn is_legal_fragment_specifier(sess: &ParseSess, features: &RefCell, + attrs: &[ast::Attribute], frag_name: &str, frag_span: Span) -> bool { match frag_name { "item" | "block" | "stmt" | "expr" | "pat" | "path" | "ty" | "ident" | "meta" | "tt" | "" => true, "vis" => { - if !features.borrow().macro_vis_matcher { + if !features.borrow().macro_vis_matcher + && !attr::contains_name(attrs, "allow_internal_unstable") { let explain = feature_gate::EXPLAIN_VIS_MATCHER; emit_feature_err(sess, "macro_vis_matcher", @@ -872,6 +884,7 @@ fn is_legal_fragment_specifier(sess: &ParseSess, fn quoted_tt_to_string(tt: "ed::TokenTree) -> String { match *tt { quoted::TokenTree::Token(_, ref tok) => ::print::pprust::token_to_string(tok), + quoted::TokenTree::MetaVar(_, name) => format!("${}", name), quoted::TokenTree::MetaVarDecl(_, name, kind) => format!("${}:{}", name, kind), _ => panic!("unexpected quoted::TokenTree::{{Sequence or Delimited}} \ in follow set checker"), diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index fa65e9501c..74fa85d130 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -12,7 +12,7 @@ use ast; use ext::tt::macro_parser; use parse::{ParseSess, token}; use print::pprust; -use symbol::{keywords, Symbol}; +use symbol::keywords; use syntax_pos::{DUMMY_SP, Span, BytePos}; use tokenstream; @@ -78,9 +78,11 @@ pub enum KleeneOp { pub enum TokenTree { Token(Span, token::Token), Delimited(Span, Rc), - /// A kleene-style repetition sequence with a span + /// A kleene-style repetition sequence Sequence(Span, Rc), - /// Matches a nonterminal. This is only used in the left hand side of MBE macros. + /// E.g. `$var` + MetaVar(Span, ast::Ident), + /// E.g. `$var:expr`. This is only used in the left hand side of MBE macros. MetaVarDecl(Span, ast::Ident /* name to bind */, ast::Ident /* kind of nonterminal */), } @@ -130,6 +132,7 @@ impl TokenTree { pub fn span(&self) -> Span { match *self { TokenTree::Token(sp, _) | + TokenTree::MetaVar(sp, _) | TokenTree::MetaVarDecl(sp, _, _) | TokenTree::Delimited(sp, _) | TokenTree::Sequence(sp, _) => sp, @@ -144,7 +147,7 @@ pub fn parse(input: tokenstream::TokenStream, expect_matchers: bool, sess: &Pars while let Some(tree) = trees.next() { let tree = parse_tree(tree, &mut trees, expect_matchers, sess); match tree { - TokenTree::Token(start_sp, token::SubstNt(ident)) if expect_matchers => { + TokenTree::MetaVar(start_sp, ident) if expect_matchers => { let span = match trees.next() { Some(tokenstream::TokenTree::Token(span, token::Colon)) => match trees.next() { Some(tokenstream::TokenTree::Token(end_sp, ref tok)) => match tok.ident() { @@ -193,19 +196,20 @@ fn parse_tree(tree: tokenstream::TokenTree, num_captures: name_captures, })) } - Some(tokenstream::TokenTree::Token(ident_span, token::Ident(ident))) => { + Some(tokenstream::TokenTree::Token(ident_span, ref token)) if token.is_ident() => { + let ident = token.ident().unwrap(); let span = Span { lo: span.lo, ..ident_span }; if ident.name == keywords::Crate.name() { - let ident = ast::Ident { name: Symbol::intern("$crate"), ..ident }; + let ident = ast::Ident { name: keywords::DollarCrate.name(), ..ident }; TokenTree::Token(span, token::Ident(ident)) } else { - TokenTree::Token(span, token::SubstNt(ident)) + TokenTree::MetaVar(span, ident) } } Some(tokenstream::TokenTree::Token(span, tok)) => { let msg = format!("expected identifier, found `{}`", pprust::token_to_string(&tok)); sess.span_diagnostic.span_err(span, &msg); - TokenTree::Token(span, token::SubstNt(keywords::Invalid.ident())) + TokenTree::MetaVar(span, keywords::Invalid.ident()) } None => TokenTree::Token(span, token::Dollar), }, diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 2a435bdea1..fe3dd83f9d 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -9,10 +9,12 @@ // except according to those terms. use ast::Ident; -use errors::Handler; +use ext::base::ExtCtxt; +use ext::expand::Marker; use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; use ext::tt::quoted; -use parse::token::{self, SubstNt, Token, NtTT}; +use fold::noop_fold_tt; +use parse::token::{self, Token, NtTT}; use syntax_pos::{Span, DUMMY_SP}; use tokenstream::{TokenStream, TokenTree, Delimited}; use util::small_vector::SmallVector; @@ -61,9 +63,9 @@ impl Iterator for Frame { } /// This can do Macro-By-Example transcription. On the other hand, if -/// `src` contains no `TokenTree::{Sequence, Match}`s, or `SubstNt`s, `interp` can +/// `src` contains no `TokenTree::{Sequence, MetaVar, MetaVarDecl}`s, `interp` can /// (and should) be None. -pub fn transcribe(sp_diag: &Handler, +pub fn transcribe(cx: &ExtCtxt, interp: Option>>, src: Vec) -> TokenStream { @@ -120,22 +122,20 @@ pub fn transcribe(sp_diag: &Handler, &interpolations, &repeats) { LockstepIterSize::Unconstrained => { - panic!(sp_diag.span_fatal( - sp, /* blame macro writer */ + cx.span_fatal(sp, /* blame macro writer */ "attempted to repeat an expression \ containing no syntax \ - variables matched as repeating at this depth")); + variables matched as repeating at this depth"); } LockstepIterSize::Contradiction(ref msg) => { // FIXME #2887 blame macro invoker instead - panic!(sp_diag.span_fatal(sp, &msg[..])); + cx.span_fatal(sp, &msg[..]); } LockstepIterSize::Constraint(len, _) => { if len == 0 { if seq.op == quoted::KleeneOp::OneOrMore { // FIXME #2887 blame invoker - panic!(sp_diag.span_fatal(sp, - "this must repeat at least once")); + cx.span_fatal(sp, "this must repeat at least once"); } } else { repeats.push((0, len)); @@ -149,29 +149,37 @@ pub fn transcribe(sp_diag: &Handler, } } // FIXME #2887: think about span stuff here - quoted::TokenTree::Token(sp, SubstNt(ident)) => { - match lookup_cur_matched(ident, &interpolations, &repeats) { - None => result.push(TokenTree::Token(sp, SubstNt(ident)).into()), - Some(cur_matched) => if let MatchedNonterminal(ref nt) = *cur_matched { - match **nt { - NtTT(ref tt) => result.push(tt.clone().into()), - _ => { - let token = TokenTree::Token(sp, token::Interpolated(nt.clone())); - result.push(token.into()); - } + quoted::TokenTree::MetaVar(mut sp, ident) => { + if let Some(cur_matched) = lookup_cur_matched(ident, &interpolations, &repeats) { + if let MatchedNonterminal(ref nt) = *cur_matched { + if let NtTT(ref tt) = **nt { + result.push(tt.clone().into()); + } else { + sp.ctxt = sp.ctxt.apply_mark(cx.current_expansion.mark); + let token = TokenTree::Token(sp, Token::interpolated((**nt).clone())); + result.push(token.into()); } } else { - panic!(sp_diag.span_fatal( - sp, /* blame the macro writer */ - &format!("variable '{}' is still repeating at this depth", ident))); + cx.span_fatal(sp, /* blame the macro writer */ + &format!("variable '{}' is still repeating at this depth", ident)); } + } else { + let ident = + Ident { ctxt: ident.ctxt.apply_mark(cx.current_expansion.mark), ..ident }; + sp.ctxt = sp.ctxt.apply_mark(cx.current_expansion.mark); + result.push(TokenTree::Token(sp, token::Dollar).into()); + result.push(TokenTree::Token(sp, token::Ident(ident)).into()); } } - quoted::TokenTree::Delimited(span, delimited) => { + quoted::TokenTree::Delimited(mut span, delimited) => { + span.ctxt = span.ctxt.apply_mark(cx.current_expansion.mark); stack.push(Frame::Delimited { forest: delimited, idx: 0, span: span }); result_stack.push(mem::replace(&mut result, Vec::new())); } - quoted::TokenTree::Token(span, tok) => result.push(TokenTree::Token(span, tok).into()), + quoted::TokenTree::Token(sp, tok) => { + let mut marker = Marker(cx.current_expansion.mark); + result.push(noop_fold_tt(TokenTree::Token(sp, tok), &mut marker).into()) + } quoted::TokenTree::MetaVarDecl(..) => panic!("unexpected `TokenTree::MetaVarDecl"), } } @@ -182,15 +190,16 @@ fn lookup_cur_matched(ident: Ident, repeats: &[(usize, usize)]) -> Option> { interpolations.get(&ident).map(|matched| { - repeats.iter().fold(matched.clone(), |ad, &(idx, _)| { - match *ad { - MatchedNonterminal(_) => { - // end of the line; duplicate henceforth - ad.clone() - } - MatchedSeq(ref ads, _) => ads[idx].clone() + let mut matched = matched.clone(); + for &(idx, _) in repeats { + let m = matched.clone(); + match *m { + MatchedNonterminal(_) => break, + MatchedSeq(ref ads, _) => matched = Rc::new(ads[idx].clone()), } - }) + } + + matched }) } @@ -239,7 +248,7 @@ fn lockstep_iter_size(tree: "ed::TokenTree, size + lockstep_iter_size(tt, interpolations, repeats) }) }, - TokenTree::Token(_, SubstNt(name)) | TokenTree::MetaVarDecl(_, name, _) => + TokenTree::MetaVar(_, name) | TokenTree::MetaVarDecl(_, name, _) => match lookup_cur_matched(name, interpolations, repeats) { Some(matched) => match *matched { MatchedNonterminal(_) => LockstepIterSize::Unconstrained, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index b2f52d11db..e8de8cf41c 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -38,12 +38,19 @@ use symbol::Symbol; use std::ascii::AsciiExt; use std::env; -macro_rules! setter { +macro_rules! set { + (proc_macro) => {{ + fn f(features: &mut Features, span: Span) { + features.declared_lib_features.push((Symbol::intern("proc_macro"), span)); + features.proc_macro = true; + } + f as fn(&mut Features, Span) + }}; ($field: ident) => {{ - fn f(features: &mut Features) -> &mut bool { - &mut features.$field + fn f(features: &mut Features, _: Span) { + features.$field = true; } - f as fn(&mut Features) -> &mut bool + f as fn(&mut Features, Span) }} } @@ -51,10 +58,9 @@ macro_rules! declare_features { ($((active, $feature: ident, $ver: expr, $issue: expr),)+) => { /// Represents active features that are currently being implemented or /// currently being considered for addition/removal. - const ACTIVE_FEATURES: &'static [(&'static str, &'static str, - Option, fn(&mut Features) -> &mut bool)] = &[ - $((stringify!($feature), $ver, $issue, setter!($feature))),+ - ]; + const ACTIVE_FEATURES: + &'static [(&'static str, &'static str, Option, fn(&mut Features, Span))] = + &[$((stringify!($feature), $ver, $issue, set!($feature))),+]; /// A set of features to be used by later passes. pub struct Features { @@ -136,7 +142,6 @@ declare_features! ( (active, placement_in_syntax, "1.0.0", Some(27779)), (active, unboxed_closures, "1.0.0", Some(29625)), - (active, allocator, "1.0.0", Some(27389)), (active, fundamental, "1.0.0", Some(29635)), (active, main, "1.0.0", Some(29634)), (active, needs_allocator, "1.4.0", Some(27389)), @@ -192,10 +197,6 @@ declare_features! ( // #23121. Array patterns have some hazards yet. (active, slice_patterns, "1.0.0", Some(23121)), - // Allows the definition of associated constants in `trait` or `impl` - // blocks. - (active, associated_consts, "1.0.0", Some(29646)), - // Allows the definition of `const fn` functions. (active, const_fn, "1.2.0", Some(24111)), @@ -312,9 +313,6 @@ declare_features! ( // Declarative macros 2.0 (`macro`). (active, decl_macro, "1.17.0", Some(39412)), - // Allows attributes on struct literal fields. - (active, struct_field_attributes, "1.16.0", Some(38814)), - // Allows #[link(kind="static-nobundle"...] (active, static_nobundle, "1.16.0", Some(37403)), @@ -325,6 +323,10 @@ declare_features! ( // rustc internal (active, sanitizer_runtime, "1.17.0", None), + // Used to identify crates that contain the profiler runtime + // rustc internal + (active, profiler_runtime, "1.18.0", None), + // `extern "x86-interrupt" fn()` (active, abi_x86_interrupt, "1.17.0", Some(40180)), @@ -352,6 +354,16 @@ declare_features! ( // rustc internal (active, abi_thiscall, "1.19.0", None), + + // Allows a test to fail without failing the whole suite + (active, allow_fail, "1.19.0", Some(42219)), + + // Allows unsized tuple coercion. + (active, unsized_tuple_coercion, "1.20.0", Some(42877)), + + // global allocators and their internals + (active, global_allocator, "1.20.0", None), + (active, allocator_internals, "1.20.0", None), ); declare_features! ( @@ -371,6 +383,7 @@ declare_features! ( // rustc internal (removed, unmarked_api, "1.0.0", None), (removed, pushpop_unsafe, "1.2.0", None), + (removed, allocator, "1.0.0", None), ); declare_features! ( @@ -426,6 +439,13 @@ declare_features! ( (accepted, relaxed_adts, "1.19.0", Some(35626)), // Coerces non capturing closures to function pointers (accepted, closure_to_fn_coercion, "1.19.0", Some(39817)), + // Allows attributes on struct literal fields. + (accepted, struct_field_attributes, "1.20.0", Some(38814)), + // Allows the definition of associated constants in `trait` or `impl` + // blocks. + (accepted, associated_consts, "1.20.0", Some(29646)), + // Usage of the `compile_error!` macro + (accepted, compile_error, "1.20.0", Some(40872)), ); // If you change this, please modify src/doc/unstable-book as well. You must @@ -532,7 +552,12 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG ("ignore", Normal, Ungated), ("no_implicit_prelude", Normal, Ungated), ("reexport_test_harness_main", Normal, Ungated), - ("link_args", Normal, Ungated), + ("link_args", Normal, Gated(Stability::Unstable, + "link_args", + "the `link_args` attribute is experimental and not \ + portable across platforms, it is recommended to \ + use `#[link(name = \"foo\")] instead", + cfg_fn!(link_args))), ("macro_escape", Normal, Ungated), // RFC #1445. @@ -575,16 +600,22 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG "the `#[rustc_on_unimplemented]` attribute \ is an experimental feature", cfg_fn!(on_unimplemented))), - ("allocator", Whitelisted, Gated(Stability::Unstable, - "allocator", - "the `#[allocator]` attribute is an experimental feature", - cfg_fn!(allocator))), + ("global_allocator", Normal, Gated(Stability::Unstable, + "global_allocator", + "the `#[global_allocator]` attribute is \ + an experimental feature", + cfg_fn!(global_allocator))), + ("default_lib_allocator", Whitelisted, Gated(Stability::Unstable, + "allocator_internals", + "the `#[default_lib_allocator]` \ + attribute is an experimental feature", + cfg_fn!(allocator_internals))), ("needs_allocator", Normal, Gated(Stability::Unstable, - "needs_allocator", + "allocator_internals", "the `#[needs_allocator]` \ attribute is an experimental \ feature", - cfg_fn!(needs_allocator))), + cfg_fn!(allocator_internals))), ("panic_runtime", Whitelisted, Gated(Stability::Unstable, "panic_runtime", "the `#[panic_runtime]` attribute is \ @@ -691,6 +722,13 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG identify crates that contain the runtime of a \ sanitizer and will never be stable", cfg_fn!(sanitizer_runtime))), + ("profiler_runtime", Whitelisted, Gated(Stability::Unstable, + "profiler_runtime", + "the `#[profiler_runtime]` attribute is used to \ + identify the `profiler_builtins` crate which \ + contains the profiler runtime and will never be \ + stable", + cfg_fn!(profiler_runtime))), ("allow_internal_unstable", Normal, Gated(Stability::Unstable, "allow_internal_unstable", @@ -801,6 +839,11 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG "used internally by rustc", cfg_fn!(rustc_attrs))), + ("allow_fail", Normal, Gated(Stability::Unstable, + "allow_fail", + "allow_fail attribute is currently unstable", + cfg_fn!(allow_fail))), + // Crate level attributes ("crate_name", CrateLevel, Ungated), ("crate_type", CrateLevel, Ungated), @@ -1019,6 +1062,9 @@ pub const EXPLAIN_VIS_MATCHER: &'static str = pub const EXPLAIN_PLACEMENT_IN: &'static str = "placement-in expression syntax is experimental and subject to change."; +pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str = + "Unsized tuple coercion is not stable enough for use and is subject to change"; + struct PostExpansionVisitor<'a> { context: &'a Context<'a>, } @@ -1141,12 +1187,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } ast::ItemKind::ForeignMod(ref foreign_module) => { - if attr::contains_name(&i.attrs[..], "link_args") { - gate_feature_post!(&self, link_args, i.span, - "the `link_args` attribute is not portable \ - across platforms, it is recommended to \ - use `#[link(name = \"foo\")]` instead") - } self.check_abi(foreign_module.abi, i.span); } @@ -1361,11 +1401,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) { match ti.node { - ast::TraitItemKind::Const(..) => { - gate_feature_post!(&self, associated_consts, - ti.span, - "associated constants are experimental") - } ast::TraitItemKind::Method(ref sig, ref block) => { if block.is_none() { self.check_abi(sig.abi, ti.span); @@ -1391,11 +1426,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } match ii.node { - ast::ImplItemKind::Const(..) => { - gate_feature_post!(&self, associated_consts, - ii.span, - "associated constants are experimental") - } ast::ImplItemKind::Method(ref sig, _) => { if sig.constness.node == ast::Constness::Const { gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable"); @@ -1450,9 +1480,9 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> F continue }; - if let Some(&(_, _, _, setter)) = ACTIVE_FEATURES.iter() + if let Some(&(_, _, _, set)) = ACTIVE_FEATURES.iter() .find(|& &(n, _, _, _)| name == n) { - *(setter(&mut features)) = true; + set(&mut features, mi.span); feature_checker.collect(&features, mi.span); } else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter() @@ -1486,7 +1516,7 @@ struct MutexFeatureChecker { impl MutexFeatureChecker { // If this method turns out to be a hotspot due to branching, - // the branching can be eliminated by modifying `setter!()` to set these spans + // the branching can be eliminated by modifying `set!()` to set these spans // only for the features that need to be checked for mutual exclusion. fn collect(&mut self, features: &Features, span: Span) { if features.proc_macro { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 4c6cf49a8d..eaec1eef17 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -22,7 +22,7 @@ use ast::*; use ast; use syntax_pos::Span; use codemap::{Spanned, respan}; -use parse::token; +use parse::token::{self, Token}; use ptr::P; use symbol::keywords; use tokenstream::*; @@ -573,7 +573,7 @@ pub fn noop_fold_tt(tt: TokenTree, fld: &mut T) -> TokenTree { } pub fn noop_fold_tts(tts: TokenStream, fld: &mut T) -> TokenStream { - tts.trees().map(|tt| fld.fold_tt(tt)).collect() + tts.map(|tt| fld.fold_tt(tt)) } // apply ident folder if it's an ident, apply other folds to interpolated nodes @@ -586,9 +586,8 @@ pub fn noop_fold_token(t: token::Token, fld: &mut T) -> token::Token Ok(nt) => nt, Err(nt) => (*nt).clone(), }; - token::Interpolated(Rc::new(fld.fold_interpolated(nt))) + Token::interpolated(fld.fold_interpolated(nt.0)) } - token::SubstNt(ident) => token::SubstNt(fld.fold_ident(ident)), _ => t } } @@ -1152,10 +1151,15 @@ pub fn noop_fold_expr(Expr {id, node, span, attrs}: Expr, folder: &mu ExprKind::Call(folder.fold_expr(f), folder.fold_exprs(args)) } - ExprKind::MethodCall(i, tps, args) => { + ExprKind::MethodCall(seg, args) => { ExprKind::MethodCall( - respan(folder.new_span(i.span), folder.fold_ident(i.node)), - tps.move_map(|x| folder.fold_ty(x)), + PathSegment { + identifier: folder.fold_ident(seg.identifier), + span: folder.new_span(seg.span), + parameters: seg.parameters.map(|ps| { + ps.map(|ps| folder.fold_path_parameters(ps)) + }), + }, folder.fold_exprs(args)) } ExprKind::Binary(binop, lhs, rhs) => { diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index f37dcfdde8..909b0031d6 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -314,7 +314,7 @@ impl DiagnosticSpanLine { h_end: usize) -> DiagnosticSpanLine { DiagnosticSpanLine { - text: fm.get_line(index).unwrap_or("").to_owned(), + text: fm.get_line(index).map_or(String::new(), |l| l.into_owned()), highlight_start: h_start, highlight_end: h_end, } @@ -359,7 +359,7 @@ impl DiagnosticCode { impl JsonEmitter { fn render(&self, suggestion: &CodeSuggestion) -> Vec { - suggestion.splice_lines(&*self.cm) + suggestion.splice_lines(&*self.cm).iter().map(|line| line.0.to_owned()).collect() } } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 32dafcdb58..a8338fccb6 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -27,10 +27,6 @@ #![feature(rustc_diagnostic_macros)] #![feature(i128_type)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] - extern crate serialize; #[macro_use] extern crate log; #[macro_use] extern crate bitflags; diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 082930777e..c99a09ab24 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -151,7 +151,7 @@ impl<'a> Parser<'a> { pub fn parse_path_and_tokens(&mut self) -> PResult<'a, (ast::Path, TokenStream)> { let meta = match self.token { - token::Interpolated(ref nt) => match **nt { + token::Interpolated(ref nt) => match nt.0 { Nonterminal::NtMeta(ref meta) => Some(meta.clone()), _ => None, }, @@ -223,7 +223,7 @@ impl<'a> Parser<'a> { /// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ; pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> { let nt_meta = match self.token { - token::Interpolated(ref nt) => match **nt { + token::Interpolated(ref nt) => match nt.0 { token::NtMeta(ref e) => Some(e.clone()), _ => None, }, diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 0bcd457851..09cdf26bf1 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -66,14 +66,15 @@ pub struct StringReader<'a> { token: token::Token, span: Span, open_braces: Vec<(token::DelimToken, Span)>, -} - -fn mk_sp(lo: BytePos, hi: BytePos) -> Span { - Span { lo: lo, hi: hi, ctxt: NO_EXPANSION } + pub override_span: Option, } impl<'a> StringReader<'a> { - fn next_token(&mut self) -> TokenAndSpan { + fn mk_sp(&self, lo: BytePos, hi: BytePos) -> Span { + unwrap_or!(self.override_span, Span { lo: lo, hi: hi, ctxt: NO_EXPANSION}) + } + + fn next_token(&mut self) -> TokenAndSpan where Self: Sized { let res = self.try_next_token(); self.unwrap_or_abort(res) } @@ -175,6 +176,7 @@ impl<'a> StringReader<'a> { token: token::Eof, span: syntax_pos::DUMMY_SP, open_braces: Vec::new(), + override_span: None, } } @@ -229,12 +231,12 @@ impl<'a> StringReader<'a> { /// Report a fatal error spanning [`from_pos`, `to_pos`). fn fatal_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) -> FatalError { - self.fatal_span(mk_sp(from_pos, to_pos), m) + self.fatal_span(self.mk_sp(from_pos, to_pos), m) } /// Report a lexical error spanning [`from_pos`, `to_pos`). fn err_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) { - self.err_span(mk_sp(from_pos, to_pos), m) + self.err_span(self.mk_sp(from_pos, to_pos), m) } /// Report a lexical error spanning [`from_pos`, `to_pos`), appending an @@ -258,7 +260,7 @@ impl<'a> StringReader<'a> { for c in c.escape_default() { m.push(c) } - self.sess.span_diagnostic.struct_span_fatal(mk_sp(from_pos, to_pos), &m[..]) + self.sess.span_diagnostic.struct_span_fatal(self.mk_sp(from_pos, to_pos), &m[..]) } /// Report a lexical error spanning [`from_pos`, `to_pos`), appending an @@ -282,7 +284,7 @@ impl<'a> StringReader<'a> { for c in c.escape_default() { m.push(c) } - self.sess.span_diagnostic.struct_span_err(mk_sp(from_pos, to_pos), &m[..]) + self.sess.span_diagnostic.struct_span_err(self.mk_sp(from_pos, to_pos), &m[..]) } /// Report a lexical error spanning [`from_pos`, `to_pos`), appending the @@ -306,11 +308,11 @@ impl<'a> StringReader<'a> { None => { if self.is_eof() { self.peek_tok = token::Eof; - self.peek_span = mk_sp(self.filemap.end_pos, self.filemap.end_pos); + self.peek_span = self.mk_sp(self.filemap.end_pos, self.filemap.end_pos); } else { let start_bytepos = self.pos; self.peek_tok = self.next_token_inner()?; - self.peek_span = mk_sp(start_bytepos, self.pos); + self.peek_span = self.mk_sp(start_bytepos, self.pos); }; } } @@ -480,6 +482,15 @@ impl<'a> StringReader<'a> { self.with_str_from(start, |string| { if string == "_" { + self.sess.span_diagnostic + .struct_span_warn(self.mk_sp(start, self.pos), + "underscore literal suffix is not allowed") + .warn("this was previously accepted by the compiler but is \ + being phased out; it will become a hard error in \ + a future release!") + .note("for more information, see issue #42326 \ + ") + .emit(); None } else { Some(Symbol::intern(string)) @@ -493,7 +504,7 @@ impl<'a> StringReader<'a> { if let Some(c) = self.ch { if c.is_whitespace() { let msg = "called consume_any_line_comment, but there was whitespace"; - self.sess.span_diagnostic.span_err(mk_sp(self.pos, self.pos), msg); + self.sess.span_diagnostic.span_err(self.mk_sp(self.pos, self.pos), msg); } } @@ -536,13 +547,13 @@ impl<'a> StringReader<'a> { Some(TokenAndSpan { tok: tok, - sp: mk_sp(start_bpos, self.pos), + sp: self.mk_sp(start_bpos, self.pos), }) }) } else { Some(TokenAndSpan { tok: token::Comment, - sp: mk_sp(start_bpos, self.pos), + sp: self.mk_sp(start_bpos, self.pos), }) } } @@ -575,7 +586,7 @@ impl<'a> StringReader<'a> { } return Some(TokenAndSpan { tok: token::Shebang(self.name_from(start)), - sp: mk_sp(start, self.pos), + sp: self.mk_sp(start, self.pos), }); } } @@ -603,7 +614,7 @@ impl<'a> StringReader<'a> { } let c = Some(TokenAndSpan { tok: token::Whitespace, - sp: mk_sp(start_bpos, self.pos), + sp: self.mk_sp(start_bpos, self.pos), }); debug!("scanning whitespace: {:?}", c); c @@ -665,7 +676,7 @@ impl<'a> StringReader<'a> { Some(TokenAndSpan { tok: tok, - sp: mk_sp(start_bpos, self.pos), + sp: self.mk_sp(start_bpos, self.pos), }) }) } @@ -860,7 +871,7 @@ impl<'a> StringReader<'a> { let valid = if self.ch_is('{') { self.scan_unicode_escape(delim) && !ascii_only } else { - let span = mk_sp(start, self.pos); + let span = self.mk_sp(start, self.pos); self.sess.span_diagnostic .struct_span_err(span, "incorrect unicode escape sequence") .span_help(span, @@ -898,13 +909,13 @@ impl<'a> StringReader<'a> { }, c); if e == '\r' { - err.span_help(mk_sp(escaped_pos, pos), + err.span_help(self.mk_sp(escaped_pos, pos), "this is an isolated carriage return; consider \ checking your editor and version control \ settings"); } if (e == '{' || e == '}') && !ascii_only { - err.span_help(mk_sp(escaped_pos, pos), + err.span_help(self.mk_sp(escaped_pos, pos), "if used in a formatting string, curly braces \ are escaped with `{{` and `}}`"); } @@ -1274,7 +1285,7 @@ impl<'a> StringReader<'a> { }); let keyword_checking_token = &token::Ident(keyword_checking_ident); let last_bpos = self.pos; - if keyword_checking_token.is_any_keyword() && + if keyword_checking_token.is_reserved_ident() && !keyword_checking_token.is_keyword(keywords::Static) { self.err_span_(start, last_bpos, "lifetimes cannot use keyword names"); } diff --git a/src/libsyntax/parse/lexer/tokentrees.rs b/src/libsyntax/parse/lexer/tokentrees.rs index 554a1fcfc7..63a396c14d 100644 --- a/src/libsyntax/parse/lexer/tokentrees.rs +++ b/src/libsyntax/parse/lexer/tokentrees.rs @@ -19,7 +19,9 @@ impl<'a> StringReader<'a> { pub fn parse_all_token_trees(&mut self) -> PResult<'a, TokenStream> { let mut tts = Vec::new(); while self.token != token::Eof { - tts.push(self.parse_token_tree()?.into()); + let tree = self.parse_token_tree()?; + let is_joint = tree.span().hi == self.span.lo && token::is_op(&self.token); + tts.push(if is_joint { tree.joint() } else { tree.into() }); } Ok(TokenStream::concat(tts)) } @@ -31,13 +33,15 @@ impl<'a> StringReader<'a> { if let token::CloseDelim(..) = self.token { return TokenStream::concat(tts); } - match self.parse_token_tree() { - Ok(tt) => tts.push(tt.into()), + let tree = match self.parse_token_tree() { + Ok(tree) => tree, Err(mut e) => { e.emit(); return TokenStream::concat(tts); } - } + }; + let is_joint = tree.span().hi == self.span.lo && token::is_op(&self.token); + tts.push(if is_joint { tree.joint() } else { tree.into() }); } } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 3a68a6ba76..bd9a621c00 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -141,9 +141,10 @@ pub fn parse_stmt_from_source_str(name: String, source: String, sess: &ParseSess new_parser_from_source_str(sess, name, source).parse_stmt() } -pub fn parse_stream_from_source_str(name: String, source: String, sess: &ParseSess) - -> TokenStream { - filemap_to_stream(sess, sess.codemap().new_filemap(name, source)) +pub fn parse_stream_from_source_str(name: String, source: String, sess: &ParseSess, + override_span: Option) + -> TokenStream { + filemap_to_stream(sess, sess.codemap().new_filemap(name, source), override_span) } // Create a new parser from a source string @@ -177,7 +178,7 @@ pub fn new_sub_parser_from_file<'a>(sess: &'a ParseSess, /// Given a filemap and config, return a parser pub fn filemap_to_parser(sess: & ParseSess, filemap: Rc, ) -> Parser { let end_pos = filemap.end_pos; - let mut parser = stream_to_parser(sess, filemap_to_stream(sess, filemap)); + let mut parser = stream_to_parser(sess, filemap_to_stream(sess, filemap, None)); if parser.token == token::Eof && parser.span == syntax_pos::DUMMY_SP { parser.span = Span { lo: end_pos, hi: end_pos, ctxt: NO_EXPANSION }; @@ -212,8 +213,10 @@ fn file_to_filemap(sess: &ParseSess, path: &Path, spanopt: Option) } /// Given a filemap, produce a sequence of token-trees -pub fn filemap_to_stream(sess: &ParseSess, filemap: Rc) -> TokenStream { +pub fn filemap_to_stream(sess: &ParseSess, filemap: Rc, override_span: Option) + -> TokenStream { let mut srdr = lexer::StringReader::new(sess, filemap); + srdr.override_span = override_span; srdr.real_token(); panictry!(srdr.parse_all_token_trees()) } @@ -684,7 +687,7 @@ mod tests { id: ast::DUMMY_NODE_ID, node: ast::ExprKind::Path(None, ast::Path { span: sp(0, 6), - segments: vec![ast::PathSegment::crate_root(), + segments: vec![ast::PathSegment::crate_root(sp(0, 2)), str2seg("a", 2, 3), str2seg("b", 5, 6)] }), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d9cb2b4ab7..573e01eab2 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -9,7 +9,7 @@ // except according to those terms. use abi::{self, Abi}; -use ast::{AttrStyle, BareFnTy}; +use ast::{AngleBracketedParameterData, AttrStyle, BareFnTy}; use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; use ast::Unsafety; use ast::{Mod, Arg, Arm, Attribute, BindingMode, TraitItemKind}; @@ -107,7 +107,7 @@ pub enum BlockMode { macro_rules! maybe_whole_expr { ($p:expr) => { if let token::Interpolated(nt) = $p.token.clone() { - match *nt { + match nt.0 { token::NtExpr(ref e) => { $p.bump(); return Ok((*e).clone()); @@ -134,7 +134,7 @@ macro_rules! maybe_whole_expr { macro_rules! maybe_whole { ($p:expr, $constructor:ident, |$x:ident| $e:expr) => { if let token::Interpolated(nt) = $p.token.clone() { - if let token::$constructor($x) = (*nt).clone() { + if let token::$constructor($x) = nt.0.clone() { $p.bump(); return Ok($e); } @@ -150,18 +150,20 @@ fn maybe_append(mut lhs: Vec, rhs: Option>) lhs } -#[derive(PartialEq)] +#[derive(Clone, Copy, PartialEq)] enum PrevTokenKind { DocComment, Comma, Plus, Interpolated, Eof, + Ident, Other, } /* ident is handled by common.rs */ +#[derive(Clone)] pub struct Parser<'a> { pub sess: &'a ParseSess, /// the current token: @@ -193,11 +195,13 @@ pub struct Parser<'a> { } +#[derive(Clone)] struct TokenCursor { frame: TokenCursorFrame, stack: Vec, } +#[derive(Clone)] struct TokenCursorFrame { delim: token::DelimToken, span: Span, @@ -397,6 +401,7 @@ impl Error { } } +#[derive(Debug)] pub enum LhsExpr { NotYetParsed, AttributesParsed(ThinVec), @@ -507,14 +512,13 @@ impl<'a> Parser<'a> { } pub fn this_token_descr(&self) -> String { - let s = self.this_token_to_string(); - if self.token.is_strict_keyword() { - format!("keyword `{}`", s) - } else if self.token.is_reserved_keyword() { - format!("reserved keyword `{}`", s) - } else { - format!("`{}`", s) - } + let prefix = match &self.token { + t if t.is_special_ident() => "reserved identifier ", + t if t.is_used_keyword() => "keyword ", + t if t.is_unused_keyword() => "reserved keyword ", + _ => "", + }; + format!("{}`{}`", prefix, self.this_token_to_string()) } pub fn unexpected_last(&self, t: &token::Token) -> PResult<'a, T> { @@ -633,10 +637,12 @@ impl<'a> Parser<'a> { } pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> { - self.check_strict_keywords(); - self.check_reserved_keywords(); match self.token { token::Ident(i) => { + if self.token.is_reserved_ident() { + self.span_err(self.span, &format!("expected identifier, found {}", + self.this_token_descr())); + } self.bump(); Ok(i) } @@ -709,25 +715,6 @@ impl<'a> Parser<'a> { } } - /// Signal an error if the given string is a strict keyword - pub fn check_strict_keywords(&mut self) { - if self.token.is_strict_keyword() { - let token_str = self.this_token_to_string(); - let span = self.span; - self.span_err(span, - &format!("expected identifier, found keyword `{}`", - token_str)); - } - } - - /// Signal an error if the current token is a reserved keyword - pub fn check_reserved_keywords(&mut self) { - if self.token.is_reserved_keyword() { - let token_str = self.this_token_to_string(); - self.fatal(&format!("`{}` is a reserved keyword", token_str)).emit() - } - } - fn check_ident(&mut self) -> bool { if self.token.is_ident() { true @@ -1054,6 +1041,7 @@ impl<'a> Parser<'a> { token::BinOp(token::Plus) => PrevTokenKind::Plus, token::Interpolated(..) => PrevTokenKind::Interpolated, token::Eof => PrevTokenKind::Eof, + token::Ident(..) => PrevTokenKind::Ident, _ => PrevTokenKind::Other, }; @@ -1093,6 +1081,16 @@ impl<'a> Parser<'a> { None => token::CloseDelim(self.token_cursor.frame.delim), }) } + fn look_ahead_span(&self, dist: usize) -> Span { + if dist == 0 { + return self.span + } + + match self.token_cursor.frame.tree_cursor.look_ahead(dist - 1) { + Some(TokenTree::Token(span, _)) | Some(TokenTree::Delimited(span, _)) => span, + None => self.look_ahead_span(dist - 1), + } + } pub fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> { self.sess.span_diagnostic.struct_span_fatal(self.span, m) } @@ -1249,10 +1247,7 @@ impl<'a> Parser<'a> { let mac = respan(lo.to(self.prev_span), Mac_ { path: pth, tts: tts }); (keywords::Invalid.ident(), ast::TraitItemKind::Macro(mac)) } else { - let (constness, unsafety, abi) = match self.parse_fn_front_matter() { - Ok(cua) => cua, - Err(e) => return Err(e), - }; + let (constness, unsafety, abi) = self.parse_fn_front_matter()?; let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; @@ -1485,10 +1480,9 @@ impl<'a> Parser<'a> { match ty.node { TyKind::Rptr(ref lifetime, ref mut_ty) => { let sum_with_parens = pprust::to_string(|s| { - use print::pp::word; use print::pprust::PrintState; - word(&mut s.s, "&")?; + s.s.word("&")?; s.print_opt_lifetime(lifetime)?; s.print_mutability(mut_ty.mutbl)?; s.popen()?; @@ -1496,7 +1490,7 @@ impl<'a> Parser<'a> { s.print_bounds(" +", &bounds)?; s.pclose() }); - err.span_suggestion(sum_span, "try adding parentheses:", sum_with_parens); + err.span_suggestion(sum_span, "try adding parentheses", sum_with_parens); } TyKind::Ptr(..) | TyKind::BareFn(..) => { err.span_label(sum_span, "perhaps you forgot parentheses?"); @@ -1619,7 +1613,7 @@ impl<'a> Parser<'a> { /// Matches token_lit = LIT_INTEGER | ... pub fn parse_lit_token(&mut self) -> PResult<'a, LitKind> { let out = match self.token { - token::Interpolated(ref nt) => match **nt { + token::Interpolated(ref nt) => match nt.0 { token::NtExpr(ref v) => match v.node { ExprKind::Lit(ref lit) => { lit.node.clone() } _ => { return self.unexpected_last(&self.token); } @@ -1658,8 +1652,10 @@ impl<'a> Parser<'a> { Ok(codemap::Spanned { node: lit, span: lo.to(self.prev_span) }) } - /// matches '-' lit | lit + /// matches '-' lit | lit (cf. ast_validation::AstValidator::check_expr_within_pat) pub fn parse_pat_literal_maybe_minus(&mut self) -> PResult<'a, P> { + maybe_whole_expr!(self); + let minus_lo = self.span; let minus_present = self.eat(&token::BinOp(token::Minus)); let lo = self.span; @@ -1724,7 +1720,7 @@ impl<'a> Parser<'a> { let segments = match mode { PathStyle::Type => { - self.parse_path_segments_without_colons()? + self.parse_path_segments_without_colons(true)? } PathStyle::Expr => { self.parse_path_segments_with_colons()? @@ -1745,7 +1741,23 @@ impl<'a> Parser<'a> { /// bounds are permitted and whether `::` must precede type parameter /// groups. pub fn parse_path(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> { - maybe_whole!(self, NtPath, |x| x); + self.parse_path_common(mode, true) + } + + pub fn parse_path_without_generics(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> { + self.parse_path_common(mode, false) + } + + fn parse_path_common(&mut self, mode: PathStyle, parse_generics: bool) + -> PResult<'a, ast::Path> + { + maybe_whole!(self, NtPath, |path| { + if mode == PathStyle::Mod && + path.segments.iter().any(|segment| segment.parameters.is_some()) { + self.diagnostic().span_err(path.span, "unexpected generic arguments in path"); + } + path + }); let lo = self.meta_var_span.unwrap_or(self.span); let is_global = self.eat(&token::ModSep); @@ -1755,7 +1767,7 @@ impl<'a> Parser<'a> { // A bound set is a set of type parameter bounds. let mut segments = match mode { PathStyle::Type => { - self.parse_path_segments_without_colons()? + self.parse_path_segments_without_colons(parse_generics)? } PathStyle::Expr => { self.parse_path_segments_with_colons()? @@ -1766,7 +1778,7 @@ impl<'a> Parser<'a> { }; if is_global { - segments.insert(0, PathSegment::crate_root()); + segments.insert(0, PathSegment::crate_root(lo)); } // Assemble the result. @@ -1780,7 +1792,7 @@ impl<'a> Parser<'a> { /// This is used when parsing derive macro paths in `#[derive]` attributes. pub fn parse_path_allowing_meta(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> { let meta_ident = match self.token { - token::Interpolated(ref nt) => match **nt { + token::Interpolated(ref nt) => match nt.0 { token::NtMeta(ref meta) => match meta.node { ast::MetaItemKind::Word => Some(ast::Ident::with_empty_ctxt(meta.name)), _ => None, @@ -1800,7 +1812,9 @@ impl<'a> Parser<'a> { /// - `a::b::c` /// - `a::b::c(V) -> W` /// - `a::b::c(V)` - pub fn parse_path_segments_without_colons(&mut self) -> PResult<'a, Vec> { + pub fn parse_path_segments_without_colons(&mut self, parse_generics: bool) + -> PResult<'a, Vec> + { let mut segments = Vec::new(); loop { // First, parse an identifier. @@ -1819,14 +1833,10 @@ impl<'a> Parser<'a> { } // Parse types, optionally. - let parameters = if self.eat_lt() { + let parameters = if parse_generics && self.eat_lt() { let (lifetimes, types, bindings) = self.parse_generic_args()?; self.expect_gt()?; - ast::AngleBracketedParameterData { - lifetimes: lifetimes, - types: types, - bindings: bindings, - }.into() + AngleBracketedParameterData { lifetimes, types, bindings }.into() } else if self.eat(&token::OpenDelim(token::Paren)) { let lo = self.prev_span; @@ -1889,11 +1899,7 @@ impl<'a> Parser<'a> { segments.push(PathSegment { identifier: identifier, span: ident_span, - parameters: ast::AngleBracketedParameterData { - lifetimes: lifetimes, - types: types, - bindings: bindings, - }.into(), + parameters: AngleBracketedParameterData { lifetimes, types, bindings }.into(), }); // Consumed `a::b::`, check for `::` before proceeding @@ -2014,14 +2020,6 @@ impl<'a> Parser<'a> { ExprKind::Call(f, args) } - fn mk_method_call(&mut self, - ident: ast::SpannedIdent, - tps: Vec>, - args: Vec>) - -> ast::ExprKind { - ExprKind::MethodCall(ident, tps, args) - } - pub fn mk_index(&mut self, expr: P, idx: P) -> ast::ExprKind { ExprKind::Index(expr, idx) } @@ -2286,7 +2284,7 @@ impl<'a> Parser<'a> { ex = ExprKind::Break(lt, e); hi = self.prev_span; } else if self.token.is_keyword(keywords::Let) { - // Catch this syntax error here, instead of in `check_strict_keywords`, so + // Catch this syntax error here, instead of in `parse_ident`, so // that we can explicitly mention that let is not to be used as an expression let mut db = self.fatal("expected expression, found statement (`let`)"); db.note("variable declaration using `let` is a statement"); @@ -2451,7 +2449,7 @@ impl<'a> Parser<'a> { // parsing into an expression. fn parse_dot_suffix(&mut self, ident: Ident, ident_span: Span, self_value: P, lo: Span) -> PResult<'a, P> { - let (_, tys, bindings) = if self.eat(&token::ModSep) { + let (lifetimes, types, bindings) = if self.eat(&token::ModSep) { self.expect_lt()?; let args = self.parse_generic_args()?; self.expect_gt()?; @@ -2460,11 +2458,6 @@ impl<'a> Parser<'a> { (Vec::new(), Vec::new(), Vec::new()) }; - if !bindings.is_empty() { - let prev_span = self.prev_span; - self.span_err(prev_span, "type bindings are only permitted on trait paths"); - } - Ok(match self.token { // expr.f() method call. token::OpenDelim(token::Paren) => { @@ -2477,17 +2470,20 @@ impl<'a> Parser<'a> { let hi = self.prev_span; es.insert(0, self_value); - let id = respan(ident_span.to(ident_span), ident); - let nd = self.mk_method_call(id, tys, es); - self.mk_expr(lo.to(hi), nd, ThinVec::new()) + let seg = PathSegment { + identifier: ident, + span: ident_span.to(ident_span), + parameters: AngleBracketedParameterData { lifetimes, types, bindings }.into(), + }; + self.mk_expr(lo.to(hi), ExprKind::MethodCall(seg, es), ThinVec::new()) } // Field access. _ => { - if !tys.is_empty() { - let prev_span = self.prev_span; - self.span_err(prev_span, - "field expressions may not \ - have type parameters"); + if let Some(generic_arg_span) = lifetimes.get(0).map(|x| x.span).or_else(|| + types.get(0).map(|x| x.span)).or_else(|| + bindings.get(0).map(|x| x.span)) { + self.span_err(generic_arg_span, + "field expressions may not have generic arguments"); } let id = respan(ident_span.to(ident_span), ident); @@ -2551,14 +2547,13 @@ impl<'a> Parser<'a> { }; let sugg = pprust::to_string(|s| { use print::pprust::PrintState; - use print::pp::word; s.popen()?; s.print_expr(&e)?; - word(&mut s.s, ".")?; + s.s.word( ".")?; s.print_usize(float.trunc() as usize)?; s.pclose()?; - word(&mut s.s, ".")?; - word(&mut s.s, fstr.splitn(2, ".").last().unwrap()) + s.s.word(".")?; + s.s.word(fstr.splitn(2, ".").last().unwrap()) }); err.span_suggestion( lo.to(self.prev_span), @@ -2613,13 +2608,16 @@ impl<'a> Parser<'a> { pub fn process_potential_macro_variable(&mut self) { let ident = match self.token { - token::SubstNt(name) => { + token::Dollar if self.span.ctxt != syntax_pos::hygiene::SyntaxContext::empty() && + self.look_ahead(1, |t| t.is_ident()) => { + self.bump(); + let name = match self.token { token::Ident(ident) => ident, _ => unreachable!() }; self.fatal(&format!("unknown macro variable `{}`", name)).emit(); return } token::Interpolated(ref nt) => { self.meta_var_span = Some(self.span); - match **nt { + match nt.0 { token::NtIdent(ident) => ident, _ => return, } @@ -2777,10 +2775,15 @@ impl<'a> Parser<'a> { self.expected_tokens.push(TokenType::Operator); while let Some(op) = AssocOp::from_token(&self.token) { - let lhs_span = if self.prev_token_kind == PrevTokenKind::Interpolated { - self.prev_span - } else { - lhs.span + // Adjust the span for interpolated LHS to point to the `$lhs` token and not to what + // it refers to. Interpolated identifiers are unwrapped early and never show up here + // as `PrevTokenKind::Interpolated` so if LHS is a single identifier we always process + // it as "interpolated", it doesn't change the answer for non-interpolated idents. + let lhs_span = match (self.prev_token_kind, &lhs.node) { + (PrevTokenKind::Interpolated, _) => self.prev_span, + (PrevTokenKind::Ident, &ExprKind::Path(None, ref path)) + if path.segments.len() == 1 => self.prev_span, + _ => lhs.span, }; let cur_op_span = self.span; @@ -2798,12 +2801,10 @@ impl<'a> Parser<'a> { } // Special cases: if op == AssocOp::As { - let rhs = self.parse_ty_no_plus()?; - lhs = self.mk_expr(lhs_span.to(rhs.span), ExprKind::Cast(lhs, rhs), ThinVec::new()); + lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Cast)?; continue } else if op == AssocOp::Colon { - let rhs = self.parse_ty_no_plus()?; - lhs = self.mk_expr(lhs_span.to(rhs.span), ExprKind::Type(lhs, rhs), ThinVec::new()); + lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type)?; continue } else if op == AssocOp::DotDot || op == AssocOp::DotDotDot { // If we didn’t have to handle `x..`/`x...`, it would be pretty easy to @@ -2897,11 +2898,74 @@ impl<'a> Parser<'a> { Ok(lhs) } + fn parse_assoc_op_cast(&mut self, lhs: P, lhs_span: Span, + expr_kind: fn(P, P) -> ExprKind) + -> PResult<'a, P> { + let mk_expr = |this: &mut Self, rhs: P| { + this.mk_expr(lhs_span.to(rhs.span), expr_kind(lhs, rhs), ThinVec::new()) + }; + + // Save the state of the parser before parsing type normally, in case there is a + // LessThan comparison after this cast. + let parser_snapshot_before_type = self.clone(); + match self.parse_ty_no_plus() { + Ok(rhs) => { + Ok(mk_expr(self, rhs)) + } + Err(mut type_err) => { + // Rewind to before attempting to parse the type with generics, to recover + // from situations like `x as usize < y` in which we first tried to parse + // `usize < y` as a type with generic arguments. + let parser_snapshot_after_type = self.clone(); + mem::replace(self, parser_snapshot_before_type); + + match self.parse_path_without_generics(PathStyle::Type) { + Ok(path) => { + // Successfully parsed the type path leaving a `<` yet to parse. + type_err.cancel(); + + // Report non-fatal diagnostics, keep `x as usize` as an expression + // in AST and continue parsing. + let msg = format!("`<` is interpreted as a start of generic \ + arguments for `{}`, not a comparison", path); + let mut err = self.sess.span_diagnostic.struct_span_err(self.span, &msg); + err.span_label(self.look_ahead_span(1).to(parser_snapshot_after_type.span), + "interpreted as generic arguments"); + err.span_label(self.span, "not interpreted as comparison"); + + let expr = mk_expr(self, P(Ty { + span: path.span, + node: TyKind::Path(None, path), + id: ast::DUMMY_NODE_ID + })); + + let expr_str = self.sess.codemap().span_to_snippet(expr.span) + .unwrap_or(pprust::expr_to_string(&expr)); + err.span_suggestion(expr.span, + "if you want to compare the casted value then write:", + format!("({})", expr_str)); + err.emit(); + + Ok(expr) + } + Err(mut path_err) => { + // Couldn't parse as a path, return original error and parser state. + path_err.cancel(); + mem::replace(self, parser_snapshot_after_type); + Err(type_err) + } + } + } + } + } + /// Produce an error if comparison operators are chained (RFC #558). /// We only need to check lhs, not rhs, because all comparison ops /// have same precedence and are left-associative fn check_no_chained_comparison(&mut self, lhs: &Expr, outer_op: &AssocOp) { - debug_assert!(outer_op.is_comparison()); + debug_assert!(outer_op.is_comparison(), + "check_no_chained_comparison: {:?} is not comparison", + outer_op); match lhs.node { ExprKind::Binary(op, _, _) if op.node.is_comparison() => { // respan to include both operators @@ -2925,7 +2989,9 @@ impl<'a> Parser<'a> { fn parse_prefix_range_expr(&mut self, already_parsed_attrs: Option>) -> PResult<'a, P> { - debug_assert!(self.token == token::DotDot || self.token == token::DotDotDot); + debug_assert!(self.token == token::DotDot || self.token == token::DotDotDot, + "parse_prefix_range_expr: token {:?} is not DotDot or DotDotDot", + self.token); let tok = self.token.clone(); let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?; let lo = self.span; @@ -3459,7 +3525,7 @@ impl<'a> Parser<'a> { // Parse box pat let subpat = self.parse_pat()?; pat = PatKind::Box(subpat); - } else if self.token.is_ident() && !self.token.is_any_keyword() && + } else if self.token.is_ident() && !self.token.is_reserved_ident() && self.parse_as_ident() { // Parse ident @ pat // This can give false positives and parse nullary enums, @@ -3734,7 +3800,7 @@ impl<'a> Parser<'a> { fn is_union_item(&self) -> bool { self.token.is_keyword(keywords::Union) && - self.look_ahead(1, |t| t.is_ident() && !t.is_any_keyword()) + self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) } fn is_defaultness(&self) -> bool { @@ -4357,7 +4423,7 @@ impl<'a> Parser<'a> { /// Parses an optional `where` clause and places it in `generics`. /// - /// ```ignore + /// ```ignore (only-for-syntax-highlight) /// where T : Trait + 'b, 'a : 'b /// ``` pub fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> { @@ -5220,7 +5286,7 @@ impl<'a> Parser<'a> { `pub(in path::to::module)`: visible only on the specified path"##; let path = self.parse_path(PathStyle::Mod)?; let path_span = self.prev_span; - let help_msg = format!("make this visible only to module `{}` with `in`:", path); + let help_msg = format!("make this visible only to module `{}` with `in`", path); self.expect(&token::CloseDelim(token::Paren))?; // `)` let mut err = self.span_fatal_help(path_span, msg, suggestion); err.span_suggestion(path_span, &help_msg, format!("in {}", path)); @@ -6105,7 +6171,7 @@ impl<'a> Parser<'a> { // `{foo, bar}`, `::{foo, bar}`, `*`, or `::*`. self.eat(&token::ModSep); let prefix = ast::Path { - segments: vec![PathSegment::crate_root()], + segments: vec![PathSegment::crate_root(lo)], span: lo.to(self.span), }; let view_path_kind = if self.eat(&token::BinOp(token::Star)) { diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 77db604c56..834ac38af9 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -16,10 +16,12 @@ pub use self::Token::*; use ast::{self}; use ptr::P; +use serialize::{Decodable, Decoder, Encodable, Encoder}; use symbol::keywords; -use tokenstream::TokenTree; +use tokenstream::{TokenStream, TokenTree}; -use std::fmt; +use std::cell::Cell; +use std::{cmp, fmt}; use std::rc::Rc; #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)] @@ -87,7 +89,7 @@ impl Lit { fn ident_can_begin_expr(ident: ast::Ident) -> bool { let ident_token: Token = Ident(ident); - !ident_token.is_any_keyword() || + !ident_token.is_reserved_ident() || ident_token.is_path_segment_keyword() || [ keywords::Do.name(), @@ -110,7 +112,7 @@ fn ident_can_begin_expr(ident: ast::Ident) -> bool { fn ident_can_begin_type(ident: ast::Ident) -> bool { let ident_token: Token = Ident(ident); - !ident_token.is_any_keyword() || + !ident_token.is_reserved_ident() || ident_token.is_path_segment_keyword() || [ keywords::For.name(), @@ -167,14 +169,12 @@ pub enum Token { Underscore, Lifetime(ast::Ident), - /* For interpolation */ - Interpolated(Rc), + // The `LazyTokenStream` is a pure function of the `Nonterminal`, + // and so the `LazyTokenStream` can be ignored by Eq, Hash, etc. + Interpolated(Rc<(Nonterminal, LazyTokenStream)>), // Can be expanded into several tokens. /// Doc comment DocComment(ast::Name), - // In right-hand-sides of MBE macros: - /// A syntactic variable that will be filled in by macro expansion. - SubstNt(ast::Ident), // Junk. These carry no data because we don't really care about the data // they *would* carry, and don't really want to allocate a new ident for @@ -190,6 +190,10 @@ pub enum Token { } impl Token { + pub fn interpolated(nt: Nonterminal) -> Token { + Token::Interpolated(Rc::new((nt, LazyTokenStream::new()))) + } + /// Returns `true` if the token starts with '>'. pub fn is_like_gt(&self) -> bool { match *self { @@ -214,7 +218,7 @@ impl Token { Lt | BinOp(Shl) | // associated path ModSep | // global path Pound => true, // expression attributes - Interpolated(ref nt) => match **nt { + Interpolated(ref nt) => match nt.0 { NtIdent(..) | NtExpr(..) | NtBlock(..) | NtPath(..) => true, _ => false, }, @@ -237,7 +241,7 @@ impl Token { Lifetime(..) | // lifetime bound in trait object Lt | BinOp(Shl) | // associated path ModSep => true, // global path - Interpolated(ref nt) => match **nt { + Interpolated(ref nt) => match nt.0 { NtIdent(..) | NtTy(..) | NtPath(..) => true, _ => false, }, @@ -256,7 +260,7 @@ impl Token { pub fn ident(&self) -> Option { match *self { Ident(ident) => Some(ident), - Interpolated(ref nt) => match **nt { + Interpolated(ref nt) => match nt.0 { NtIdent(ident) => Some(ident.node), _ => None, }, @@ -288,7 +292,7 @@ impl Token { /// Returns `true` if the token is an interpolated path. pub fn is_path(&self) -> bool { if let Interpolated(ref nt) = *self { - if let NtPath(..) = **nt { + if let NtPath(..) = nt.0 { return true; } } @@ -315,7 +319,7 @@ impl Token { pub fn is_path_start(&self) -> bool { self == &ModSep || self.is_qpath_start() || self.is_path() || - self.is_path_segment_keyword() || self.is_ident() && !self.is_any_keyword() + self.is_path_segment_keyword() || self.is_ident() && !self.is_reserved_ident() } /// Returns `true` if the token is a given keyword, `kw`. @@ -327,18 +331,23 @@ impl Token { match self.ident() { Some(id) => id.name == keywords::Super.name() || id.name == keywords::SelfValue.name() || - id.name == keywords::SelfType.name(), + id.name == keywords::SelfType.name() || + id.name == keywords::DollarCrate.name(), None => false, } } - /// Returns `true` if the token is either a strict or reserved keyword. - pub fn is_any_keyword(&self) -> bool { - self.is_strict_keyword() || self.is_reserved_keyword() + // Returns true for reserved identifiers used internally for elided lifetimes, + // unnamed method parameters, crate root module, error recovery etc. + pub fn is_special_ident(&self) -> bool { + match self.ident() { + Some(id) => id.name <= keywords::DollarCrate.name(), + _ => false, + } } - /// Returns `true` if the token is a strict keyword. - pub fn is_strict_keyword(&self) -> bool { + /// Returns `true` if the token is a keyword used in the language. + pub fn is_used_keyword(&self) -> bool { match self.ident() { Some(id) => id.name >= keywords::As.name() && id.name <= keywords::While.name(), _ => false, @@ -346,12 +355,71 @@ impl Token { } /// Returns `true` if the token is a keyword reserved for possible future use. - pub fn is_reserved_keyword(&self) -> bool { + pub fn is_unused_keyword(&self) -> bool { match self.ident() { Some(id) => id.name >= keywords::Abstract.name() && id.name <= keywords::Yield.name(), _ => false, } } + + pub fn glue(self, joint: Token) -> Option { + Some(match self { + Eq => match joint { + Eq => EqEq, + Gt => FatArrow, + _ => return None, + }, + Lt => match joint { + Eq => Le, + Lt => BinOp(Shl), + Le => BinOpEq(Shl), + BinOp(Minus) => LArrow, + _ => return None, + }, + Gt => match joint { + Eq => Ge, + Gt => BinOp(Shr), + Ge => BinOpEq(Shr), + _ => return None, + }, + Not => match joint { + Eq => Ne, + _ => return None, + }, + BinOp(op) => match joint { + Eq => BinOpEq(op), + BinOp(And) if op == And => AndAnd, + BinOp(Or) if op == Or => OrOr, + Gt if op == Minus => RArrow, + _ => return None, + }, + Dot => match joint { + Dot => DotDot, + DotDot => DotDotDot, + _ => return None, + }, + DotDot => match joint { + Dot => DotDotDot, + _ => return None, + }, + Colon => match joint { + Colon => ModSep, + _ => return None, + }, + + Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot | Comma | + Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question | + OpenDelim(..) | CloseDelim(..) | Underscore => return None, + + Literal(..) | Ident(..) | Lifetime(..) | Interpolated(..) | DocComment(..) | + Whitespace | Comment | Shebang(..) | Eof => return None, + }) + } + + /// Returns `true` if the token is either a special identifier or a keyword. + pub fn is_reserved_ident(&self) -> bool { + self.is_special_ident() || self.is_used_keyword() || self.is_unused_keyword() + } } #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash)] @@ -401,3 +469,66 @@ impl fmt::Debug for Nonterminal { } } } + +pub fn is_op(tok: &Token) -> bool { + match *tok { + OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | + Ident(..) | Underscore | Lifetime(..) | Interpolated(..) | + Whitespace | Comment | Shebang(..) | Eof => false, + _ => true, + } +} + +pub struct LazyTokenStream(Cell>); + +impl Clone for LazyTokenStream { + fn clone(&self) -> Self { + let opt_stream = self.0.take(); + self.0.set(opt_stream.clone()); + LazyTokenStream(Cell::new(opt_stream)) + } +} + +impl cmp::Eq for LazyTokenStream {} +impl PartialEq for LazyTokenStream { + fn eq(&self, _other: &LazyTokenStream) -> bool { + true + } +} + +impl fmt::Debug for LazyTokenStream { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.clone().0.into_inner(), f) + } +} + +impl LazyTokenStream { + pub fn new() -> Self { + LazyTokenStream(Cell::new(None)) + } + + pub fn force TokenStream>(&self, f: F) -> TokenStream { + let mut opt_stream = self.0.take(); + if opt_stream.is_none() { + opt_stream = Some(f()); + } + self.0.set(opt_stream.clone()); + opt_stream.clone().unwrap() + } +} + +impl Encodable for LazyTokenStream { + fn encode(&self, _: &mut S) -> Result<(), S::Error> { + Ok(()) + } +} + +impl Decodable for LazyTokenStream { + fn decode(_: &mut D) -> Result { + Ok(LazyTokenStream::new()) + } +} + +impl ::std::hash::Hash for LazyTokenStream { + fn hash(&self, _hasher: &mut H) {} +} diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index e893c85924..3ce9e9d07b 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -11,7 +11,7 @@ //! This pretty-printer is a direct reimplementation of Philip Karlton's //! Mesa pretty-printer, as described in appendix A of //! -//! ````ignore +//! ````text //! STAN-CS-79-770: "Pretty Printing", by Derek C. Oppen. //! Stanford Department of Computer Science, 1979. //! ```` @@ -262,7 +262,7 @@ pub fn mk_printer<'a>(out: Box, linewidth: usize) -> Printer<'a> { } pub struct Printer<'a> { - pub out: Box, + out: Box, buf_len: usize, /// Width of lines we're constrained to margin: isize, @@ -577,75 +577,75 @@ impl<'a> Printer<'a> { } } } -} -// Convenience functions to talk to the printer. + // Convenience functions to talk to the printer. -/// "raw box" -pub fn rbox(p: &mut Printer, indent: usize, b: Breaks) -> io::Result<()> { - p.pretty_print(Token::Begin(BeginToken { - offset: indent as isize, - breaks: b - })) -} + /// "raw box" + pub fn rbox(&mut self, indent: usize, b: Breaks) -> io::Result<()> { + self.pretty_print(Token::Begin(BeginToken { + offset: indent as isize, + breaks: b + })) + } -/// Inconsistent breaking box -pub fn ibox(p: &mut Printer, indent: usize) -> io::Result<()> { - rbox(p, indent, Breaks::Inconsistent) -} + /// Inconsistent breaking box + pub fn ibox(&mut self, indent: usize) -> io::Result<()> { + self.rbox(indent, Breaks::Inconsistent) + } -/// Consistent breaking box -pub fn cbox(p: &mut Printer, indent: usize) -> io::Result<()> { - rbox(p, indent, Breaks::Consistent) -} + /// Consistent breaking box + pub fn cbox(&mut self, indent: usize) -> io::Result<()> { + self.rbox(indent, Breaks::Consistent) + } -pub fn break_offset(p: &mut Printer, n: usize, off: isize) -> io::Result<()> { - p.pretty_print(Token::Break(BreakToken { - offset: off, - blank_space: n as isize - })) -} + pub fn break_offset(&mut self, n: usize, off: isize) -> io::Result<()> { + self.pretty_print(Token::Break(BreakToken { + offset: off, + blank_space: n as isize + })) + } -pub fn end(p: &mut Printer) -> io::Result<()> { - p.pretty_print(Token::End) -} + pub fn end(&mut self) -> io::Result<()> { + self.pretty_print(Token::End) + } -pub fn eof(p: &mut Printer) -> io::Result<()> { - p.pretty_print(Token::Eof) -} + pub fn eof(&mut self) -> io::Result<()> { + self.pretty_print(Token::Eof) + } -pub fn word(p: &mut Printer, wrd: &str) -> io::Result<()> { - p.pretty_print(Token::String(wrd.to_string(), wrd.len() as isize)) -} + pub fn word(&mut self, wrd: &str) -> io::Result<()> { + self.pretty_print(Token::String(wrd.to_string(), wrd.len() as isize)) + } -pub fn huge_word(p: &mut Printer, wrd: &str) -> io::Result<()> { - p.pretty_print(Token::String(wrd.to_string(), SIZE_INFINITY)) -} + pub fn huge_word(&mut self, wrd: &str) -> io::Result<()> { + self.pretty_print(Token::String(wrd.to_string(), SIZE_INFINITY)) + } -pub fn zero_word(p: &mut Printer, wrd: &str) -> io::Result<()> { - p.pretty_print(Token::String(wrd.to_string(), 0)) -} + pub fn zero_word(&mut self, wrd: &str) -> io::Result<()> { + self.pretty_print(Token::String(wrd.to_string(), 0)) + } -pub fn spaces(p: &mut Printer, n: usize) -> io::Result<()> { - break_offset(p, n, 0) -} + fn spaces(&mut self, n: usize) -> io::Result<()> { + self.break_offset(n, 0) + } -pub fn zerobreak(p: &mut Printer) -> io::Result<()> { - spaces(p, 0) -} + pub fn zerobreak(&mut self) -> io::Result<()> { + self.spaces(0) + } -pub fn space(p: &mut Printer) -> io::Result<()> { - spaces(p, 1) -} + pub fn space(&mut self) -> io::Result<()> { + self.spaces(1) + } -pub fn hardbreak(p: &mut Printer) -> io::Result<()> { - spaces(p, SIZE_INFINITY as usize) -} + pub fn hardbreak(&mut self) -> io::Result<()> { + self.spaces(SIZE_INFINITY as usize) + } -pub fn hardbreak_tok_offset(off: isize) -> Token { - Token::Break(BreakToken {offset: off, blank_space: SIZE_INFINITY}) -} + pub fn hardbreak_tok_offset(off: isize) -> Token { + Token::Break(BreakToken {offset: off, blank_space: SIZE_INFINITY}) + } -pub fn hardbreak_tok() -> Token { - hardbreak_tok_offset(0) + pub fn hardbreak_tok() -> Token { + Self::hardbreak_tok_offset(0) + } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 073ededcb0..b052b2cdbb 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -21,8 +21,7 @@ use syntax_pos::{self, BytePos}; use parse::token::{self, BinOpToken, Token}; use parse::lexer::comments; use parse::{self, ParseSess}; -use print::pp::{self, break_offset, word, space, zerobreak, hardbreak}; -use print::pp::{Breaks, eof}; +use print::pp::{self, Breaks}; use print::pp::Breaks::{Consistent, Inconsistent}; use ptr::P; use std_inject; @@ -32,7 +31,8 @@ use tokenstream::{self, TokenStream, TokenTree}; use std::ascii; use std::io::{self, Write, Read}; -use std::iter; +use std::iter::{self, Peekable}; +use std::vec; pub enum AnnNode<'a> { NodeIdent(&'a ast::Ident), @@ -54,38 +54,23 @@ pub struct NoAnn; impl PpAnn for NoAnn {} -#[derive(Copy, Clone)] -pub struct CurrentCommentAndLiteral { - pub cur_cmnt: usize, - pub cur_lit: usize, -} - pub struct State<'a> { pub s: pp::Printer<'a>, cm: Option<&'a CodeMap>, comments: Option >, - literals: Option >, - cur_cmnt_and_lit: CurrentCommentAndLiteral, + literals: Peekable>, + cur_cmnt: usize, boxes: Vec, ann: &'a (PpAnn+'a), } -pub fn rust_printer<'a>(writer: Box) -> State<'a> { - static NO_ANN: NoAnn = NoAnn; - rust_printer_annotated(writer, &NO_ANN) -} - -pub fn rust_printer_annotated<'a>(writer: Box, - ann: &'a PpAnn) -> State<'a> { +fn rust_printer<'a>(writer: Box, ann: &'a PpAnn) -> State<'a> { State { s: pp::mk_printer(writer, DEFAULT_COLUMNS), cm: None, comments: None, - literals: None, - cur_cmnt_and_lit: CurrentCommentAndLiteral { - cur_cmnt: 0, - cur_lit: 0 - }, + literals: vec![].into_iter().peekable(), + cur_cmnt: 0, boxes: Vec::new(), ann: ann, } @@ -128,7 +113,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap, s.print_mod(&krate.module, &krate.attrs)?; s.print_remaining_comments()?; - eof(&mut s.s) + s.s.eof() } impl<'a> State<'a> { @@ -161,11 +146,8 @@ impl<'a> State<'a> { s: pp::mk_printer(out, DEFAULT_COLUMNS), cm: Some(cm), comments: comments, - literals: literals, - cur_cmnt_and_lit: CurrentCommentAndLiteral { - cur_cmnt: 0, - cur_lit: 0 - }, + literals: literals.unwrap_or_default().into_iter().peekable(), + cur_cmnt: 0, boxes: Vec::new(), ann: ann, } @@ -177,14 +159,15 @@ pub fn to_string(f: F) -> String where { let mut wr = Vec::new(); { - let mut printer = rust_printer(Box::new(&mut wr)); + let ann = NoAnn; + let mut printer = rust_printer(Box::new(&mut wr), &ann); f(&mut printer).unwrap(); - eof(&mut printer.s).unwrap(); + printer.s.eof().unwrap(); } String::from_utf8(wr).unwrap() } -pub fn binop_to_string(op: BinOpToken) -> &'static str { +fn binop_to_string(op: BinOpToken) -> &'static str { match op { token::Plus => "+", token::Minus => "-", @@ -270,13 +253,12 @@ pub fn token_to_string(tok: &Token) -> String { /* Other */ token::DocComment(s) => s.to_string(), - token::SubstNt(s) => format!("${}", s), token::Eof => "".to_string(), token::Whitespace => " ".to_string(), token::Comment => "/* */".to_string(), token::Shebang(s) => format!("/* shebang: {}*/", s), - token::Interpolated(ref nt) => match **nt { + token::Interpolated(ref nt) => match nt.0 { token::NtExpr(ref e) => expr_to_string(e), token::NtMeta(ref e) => meta_item_to_string(e), token::NtTy(ref e) => ty_to_string(e), @@ -370,6 +352,10 @@ pub fn path_to_string(p: &ast::Path) -> String { to_string(|s| s.print_path(p, false, 0, false)) } +pub fn path_segment_to_string(p: &ast::PathSegment) -> String { + to_string(|s| s.print_path_segment(p, false)) +} + pub fn ident_to_string(id: ast::Ident) -> String { to_string(|s| s.print_ident(id)) } @@ -449,17 +435,18 @@ pub trait PrintState<'a> { fn writer(&mut self) -> &mut pp::Printer<'a>; fn boxes(&mut self) -> &mut Vec; fn comments(&mut self) -> &mut Option>; - fn cur_cmnt_and_lit(&mut self) -> &mut CurrentCommentAndLiteral; - fn literals(&self) -> &Option>; + fn cur_cmnt(&mut self) -> &mut usize; + fn cur_lit(&mut self) -> Option<&comments::Literal>; + fn bump_lit(&mut self) -> Option; fn word_space(&mut self, w: &str) -> io::Result<()> { - word(self.writer(), w)?; - space(self.writer()) + self.writer().word(w)?; + self.writer().space() } - fn popen(&mut self) -> io::Result<()> { word(self.writer(), "(") } + fn popen(&mut self) -> io::Result<()> { self.writer().word("(") } - fn pclose(&mut self) -> io::Result<()> { word(self.writer(), ")") } + fn pclose(&mut self) -> io::Result<()> { self.writer().word(")") } fn is_begin(&mut self) -> bool { match self.writer().last_token() { @@ -482,7 +469,7 @@ pub trait PrintState<'a> { fn hardbreak_if_not_bol(&mut self) -> io::Result<()> { if !self.is_bol() { - hardbreak(self.writer())? + self.writer().hardbreak()? } Ok(()) } @@ -490,17 +477,17 @@ pub trait PrintState<'a> { // "raw box" fn rbox(&mut self, u: usize, b: pp::Breaks) -> io::Result<()> { self.boxes().push(b); - pp::rbox(self.writer(), u, b) + self.writer().rbox(u, b) } fn ibox(&mut self, u: usize) -> io::Result<()> { self.boxes().push(pp::Breaks::Inconsistent); - pp::ibox(self.writer(), u) + self.writer().ibox(u) } fn end(&mut self) -> io::Result<()> { self.boxes().pop().unwrap(); - pp::end(self.writer()) + self.writer().end() } fn commasep(&mut self, b: Breaks, elts: &[T], mut op: F) -> io::Result<()> @@ -516,31 +503,24 @@ pub trait PrintState<'a> { } fn next_lit(&mut self, pos: BytePos) -> Option { - let mut cur_lit = self.cur_cmnt_and_lit().cur_lit; + while let Some(ltrl) = self.cur_lit().cloned() { + if ltrl.pos > pos { break; } - let mut result = None; - - if let Some(ref lits) = *self.literals() { - while cur_lit < lits.len() { - let ltrl = (*lits)[cur_lit].clone(); - if ltrl.pos > pos { break; } - cur_lit += 1; - if ltrl.pos == pos { - result = Some(ltrl); - break; - } + // we don't need the value here since we're forced to clone cur_lit + // due to lack of NLL. + self.bump_lit(); + if ltrl.pos == pos { + return Some(ltrl); } } - self.cur_cmnt_and_lit().cur_lit = cur_lit; - result + None } fn maybe_print_comment(&mut self, pos: BytePos) -> io::Result<()> { while let Some(ref cmnt) = self.next_comment() { if cmnt.pos < pos { self.print_comment(cmnt)?; - self.cur_cmnt_and_lit().cur_cmnt += 1; } else { break } @@ -550,12 +530,12 @@ pub trait PrintState<'a> { fn print_comment(&mut self, cmnt: &comments::Comment) -> io::Result<()> { - match cmnt.style { + let r = match cmnt.style { comments::Mixed => { assert_eq!(cmnt.lines.len(), 1); - zerobreak(self.writer())?; - word(self.writer(), &cmnt.lines[0])?; - zerobreak(self.writer()) + self.writer().zerobreak()?; + self.writer().word(&cmnt.lines[0])?; + self.writer().zerobreak() } comments::Isolated => { self.hardbreak_if_not_bol()?; @@ -563,26 +543,26 @@ pub trait PrintState<'a> { // Don't print empty lines because they will end up as trailing // whitespace if !line.is_empty() { - word(self.writer(), &line[..])?; + self.writer().word(&line[..])?; } - hardbreak(self.writer())?; + self.writer().hardbreak()?; } Ok(()) } comments::Trailing => { if !self.is_bol() { - word(self.writer(), " ")?; + self.writer().word(" ")?; } if cmnt.lines.len() == 1 { - word(self.writer(), &cmnt.lines[0])?; - hardbreak(self.writer()) + self.writer().word(&cmnt.lines[0])?; + self.writer().hardbreak() } else { self.ibox(0)?; for line in &cmnt.lines { if !line.is_empty() { - word(self.writer(), &line[..])?; + self.writer().word(&line[..])?; } - hardbreak(self.writer())?; + self.writer().hardbreak()?; } self.end() } @@ -594,15 +574,22 @@ pub trait PrintState<'a> { _ => false }; if is_semi || self.is_begin() || self.is_end() { - hardbreak(self.writer())?; + self.writer().hardbreak()?; } - hardbreak(self.writer()) + self.writer().hardbreak() + } + }; + match r { + Ok(()) => { + *self.cur_cmnt() = *self.cur_cmnt() + 1; + Ok(()) } + Err(e) => Err(e), } } fn next_comment(&mut self) -> Option { - let cur_cmnt = self.cur_cmnt_and_lit().cur_cmnt; + let cur_cmnt = *self.cur_cmnt(); match *self.comments() { Some(ref cmnts) => { if cur_cmnt < cmnts.len() { @@ -617,8 +604,8 @@ pub trait PrintState<'a> { fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> { self.maybe_print_comment(lit.span.lo)?; - if let Some(ref ltrl) = self.next_lit(lit.span.lo) { - return word(self.writer(), &(*ltrl).lit); + if let Some(ltrl) = self.next_lit(lit.span.lo) { + return self.writer().word(<rl.lit); } match lit.node { ast::LitKind::Str(st, style) => self.print_string(&st.as_str(), style), @@ -626,37 +613,33 @@ pub trait PrintState<'a> { let mut res = String::from("b'"); res.extend(ascii::escape_default(byte).map(|c| c as char)); res.push('\''); - word(self.writer(), &res[..]) + self.writer().word(&res[..]) } ast::LitKind::Char(ch) => { let mut res = String::from("'"); res.extend(ch.escape_default()); res.push('\''); - word(self.writer(), &res[..]) + self.writer().word(&res[..]) } ast::LitKind::Int(i, t) => { match t { ast::LitIntType::Signed(st) => { - word(self.writer(), &st.val_to_string(i as i128)) + self.writer().word(&st.val_to_string(i as i128)) } ast::LitIntType::Unsigned(ut) => { - word(self.writer(), &ut.val_to_string(i)) + self.writer().word(&ut.val_to_string(i)) } ast::LitIntType::Unsuffixed => { - word(self.writer(), &format!("{}", i)) + self.writer().word(&format!("{}", i)) } } } ast::LitKind::Float(ref f, t) => { - word(self.writer(), - &format!( - "{}{}", - &f, - t.ty_to_string())) + self.writer().word(&format!("{}{}", &f, t.ty_to_string())) } - ast::LitKind::FloatUnsuffixed(ref f) => word(self.writer(), &f.as_str()), + ast::LitKind::FloatUnsuffixed(ref f) => self.writer().word(&f.as_str()), ast::LitKind::Bool(val) => { - if val { word(self.writer(), "true") } else { word(self.writer(), "false") } + if val { self.writer().word("true") } else { self.writer().word("false") } } ast::LitKind::ByteStr(ref v) => { let mut escaped: String = String::new(); @@ -664,7 +647,7 @@ pub trait PrintState<'a> { escaped.extend(ascii::escape_default(ch) .map(|c| c as char)); } - word(self.writer(), &format!("b\"{}\"", escaped)) + self.writer().word(&format!("b\"{}\"", escaped)) } } } @@ -681,7 +664,7 @@ pub trait PrintState<'a> { string=st)) } }; - word(self.writer(), &st[..]) + self.writer().word(&st[..]) } fn print_inner_attributes(&mut self, @@ -742,29 +725,29 @@ pub trait PrintState<'a> { } self.maybe_print_comment(attr.span.lo)?; if attr.is_sugared_doc { - word(self.writer(), &attr.value_str().unwrap().as_str())?; - hardbreak(self.writer()) + self.writer().word(&attr.value_str().unwrap().as_str())?; + self.writer().hardbreak() } else { match attr.style { - ast::AttrStyle::Inner => word(self.writer(), "#![")?, - ast::AttrStyle::Outer => word(self.writer(), "#[")?, + ast::AttrStyle::Inner => self.writer().word("#![")?, + ast::AttrStyle::Outer => self.writer().word("#[")?, } if let Some(mi) = attr.meta() { self.print_meta_item(&mi)? } else { for (i, segment) in attr.path.segments.iter().enumerate() { if i > 0 { - word(self.writer(), "::")? + self.writer().word("::")? } if segment.identifier.name != keywords::CrateRoot.name() && - segment.identifier.name != "$crate" { - word(self.writer(), &segment.identifier.name.as_str())?; + segment.identifier.name != keywords::DollarCrate.name() { + self.writer().word(&segment.identifier.name.as_str())?; } } - space(self.writer())?; + self.writer().space()?; self.print_tts(attr.tokens.clone())?; } - word(self.writer(), "]") + self.writer().word("]") } } @@ -783,7 +766,7 @@ pub trait PrintState<'a> { self.ibox(INDENT_UNIT)?; match item.node { ast::MetaItemKind::Word => { - word(self.writer(), &item.name.as_str())?; + self.writer().word(&item.name.as_str())?; } ast::MetaItemKind::NameValue(ref value) => { self.word_space(&item.name.as_str())?; @@ -791,7 +774,7 @@ pub trait PrintState<'a> { self.print_literal(value)?; } ast::MetaItemKind::List(ref items) => { - word(self.writer(), &item.name.as_str())?; + self.writer().word(&item.name.as_str())?; self.popen()?; self.commasep(Consistent, &items[..], @@ -812,20 +795,20 @@ pub trait PrintState<'a> { fn print_tt(&mut self, tt: tokenstream::TokenTree) -> io::Result<()> { match tt { TokenTree::Token(_, ref tk) => { - word(self.writer(), &token_to_string(tk))?; + self.writer().word(&token_to_string(tk))?; match *tk { parse::token::DocComment(..) => { - hardbreak(self.writer()) + self.writer().hardbreak() } _ => Ok(()) } } TokenTree::Delimited(_, ref delimed) => { - word(self.writer(), &token_to_string(&delimed.open_token()))?; - space(self.writer())?; + self.writer().word(&token_to_string(&delimed.open_token()))?; + self.writer().space()?; self.print_tts(delimed.stream())?; - space(self.writer())?; - word(self.writer(), &token_to_string(&delimed.close_token())) + self.writer().space()?; + self.writer().word(&token_to_string(&delimed.close_token())) }, } } @@ -834,7 +817,7 @@ pub trait PrintState<'a> { self.ibox(0)?; for (i, tt) in tts.into_trees().enumerate() { if i != 0 { - space(self.writer())?; + self.writer().space()?; } self.print_tt(tt)?; } @@ -842,11 +825,11 @@ pub trait PrintState<'a> { } fn space_if_not_bol(&mut self) -> io::Result<()> { - if !self.is_bol() { space(self.writer())?; } + if !self.is_bol() { self.writer().space()?; } Ok(()) } - fn nbsp(&mut self) -> io::Result<()> { word(self.writer(), " ") } + fn nbsp(&mut self) -> io::Result<()> { self.writer().word(" ") } } impl<'a> PrintState<'a> for State<'a> { @@ -862,23 +845,27 @@ impl<'a> PrintState<'a> for State<'a> { &mut self.comments } - fn cur_cmnt_and_lit(&mut self) -> &mut CurrentCommentAndLiteral { - &mut self.cur_cmnt_and_lit + fn cur_cmnt(&mut self) -> &mut usize { + &mut self.cur_cmnt + } + + fn cur_lit(&mut self) -> Option<&comments::Literal> { + self.literals.peek() } - fn literals(&self) -> &Option> { - &self.literals + fn bump_lit(&mut self) -> Option { + self.literals.next() } } impl<'a> State<'a> { pub fn cbox(&mut self, u: usize) -> io::Result<()> { self.boxes.push(pp::Breaks::Consistent); - pp::cbox(&mut self.s, u) + self.s.cbox(u) } pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> { - word(&mut self.s, w)?; + self.s.word(w)?; self.nbsp() } @@ -895,7 +882,7 @@ impl<'a> State<'a> { } pub fn bopen(&mut self) -> io::Result<()> { - word(&mut self.s, "{")?; + self.s.word("{")?; self.end() // close the head-box } @@ -907,7 +894,7 @@ impl<'a> State<'a> { indented: usize, close_box: bool) -> io::Result<()> { self.maybe_print_comment(span.hi)?; self.break_offset_if_not_bol(1, -(indented as isize))?; - word(&mut self.s, "}")?; + self.s.word("}")?; if close_box { self.end()?; // close the outer-box } @@ -927,13 +914,13 @@ impl<'a> State<'a> { pub fn break_offset_if_not_bol(&mut self, n: usize, off: isize) -> io::Result<()> { if !self.is_bol() { - break_offset(&mut self.s, n, off) + self.s.break_offset(n, off) } else { if off != 0 && self.s.last_token().is_hardbreak_tok() { // We do something pretty sketchy here: tuck the nonzero // offset-adjustment we were going to deposit along with the // break into the previous hardbreak. - self.s.replace_last_token(pp::hardbreak_tok_offset(off)); + self.s.replace_last_token(pp::Printer::hardbreak_tok_offset(off)); } Ok(()) } @@ -942,11 +929,11 @@ impl<'a> State<'a> { // Synthesizes a comment that was not textually present in the original source // file. pub fn synth_comment(&mut self, text: String) -> io::Result<()> { - word(&mut self.s, "/*")?; - space(&mut self.s)?; - word(&mut self.s, &text[..])?; - space(&mut self.s)?; - word(&mut self.s, "*/") + self.s.word("/*")?; + self.s.space()?; + self.s.word(&text[..])?; + self.s.space()?; + self.s.word("*/") } @@ -967,7 +954,7 @@ impl<'a> State<'a> { op(self, elt)?; i += 1; if i < len { - word(&mut self.s, ",")?; + self.s.word(",")?; self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi))?; self.space_if_not_bol()?; @@ -1013,12 +1000,12 @@ impl<'a> State<'a> { self.ibox(0)?; match ty.node { ast::TyKind::Slice(ref ty) => { - word(&mut self.s, "[")?; + self.s.word("[")?; self.print_type(ty)?; - word(&mut self.s, "]")?; + self.s.word("]")?; } ast::TyKind::Ptr(ref mt) => { - word(&mut self.s, "*")?; + self.s.word("*")?; match mt.mutbl { ast::Mutability::Mutable => self.word_nbsp("mut")?, ast::Mutability::Immutable => self.word_nbsp("const")?, @@ -1026,19 +1013,19 @@ impl<'a> State<'a> { self.print_type(&mt.ty)?; } ast::TyKind::Rptr(ref lifetime, ref mt) => { - word(&mut self.s, "&")?; + self.s.word("&")?; self.print_opt_lifetime(lifetime)?; self.print_mt(mt)?; } ast::TyKind::Never => { - word(&mut self.s, "!")?; + self.s.word("!")?; }, ast::TyKind::Tup(ref elts) => { self.popen()?; self.commasep(Inconsistent, &elts[..], |s, ty| s.print_type(ty))?; if elts.len() == 1 { - word(&mut self.s, ",")?; + self.s.word(",")?; } self.pclose()?; } @@ -1076,25 +1063,25 @@ impl<'a> State<'a> { self.print_bounds("impl ", &bounds[..])?; } ast::TyKind::Array(ref ty, ref v) => { - word(&mut self.s, "[")?; + self.s.word("[")?; self.print_type(ty)?; - word(&mut self.s, "; ")?; + self.s.word("; ")?; self.print_expr(v)?; - word(&mut self.s, "]")?; + self.s.word("]")?; } ast::TyKind::Typeof(ref e) => { - word(&mut self.s, "typeof(")?; + self.s.word("typeof(")?; self.print_expr(e)?; - word(&mut self.s, ")")?; + self.s.word(")")?; } ast::TyKind::Infer => { - word(&mut self.s, "_")?; + self.s.word("_")?; } ast::TyKind::Err => { - word(&mut self.s, "?")?; + self.s.word("?")?; } ast::TyKind::ImplicitSelf => { - word(&mut self.s, "Self")?; + self.s.word("Self")?; } ast::TyKind::Mac(ref m) => { self.print_mac(m, token::Paren)?; @@ -1116,7 +1103,7 @@ impl<'a> State<'a> { Abi::Rust, Some(item.ident), generics, &item.vis)?; self.end()?; // end head-ibox - word(&mut self.s, ";")?; + self.s.word(";")?; self.end() // end the outer fn box } ast::ForeignItemKind::Static(ref t, m) => { @@ -1127,7 +1114,7 @@ impl<'a> State<'a> { self.print_ident(item.ident)?; self.word_space(":")?; self.print_type(t)?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; // end the head-ibox self.end() // end the outer cbox } @@ -1141,17 +1128,17 @@ impl<'a> State<'a> { vis: &ast::Visibility) -> io::Result<()> { - word(&mut self.s, &visibility_qualified(vis, ""))?; + self.s.word(&visibility_qualified(vis, ""))?; self.word_space("const")?; self.print_ident(ident)?; self.word_space(":")?; self.print_type(ty)?; if let Some(expr) = default { - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_expr(expr)?; } - word(&mut self.s, ";") + self.s.word(";") } fn print_associated_type(&mut self, @@ -1165,11 +1152,11 @@ impl<'a> State<'a> { self.print_bounds(":", bounds)?; } if let Some(ty) = ty { - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_type(ty)?; } - word(&mut self.s, ";") + self.s.word(";") } /// Pretty-print an item @@ -1188,19 +1175,19 @@ impl<'a> State<'a> { } else { self.print_name(p)?; } - space(&mut self.s)?; - word(&mut self.s, "as")?; - space(&mut self.s)?; + self.s.space()?; + self.s.word("as")?; + self.s.space()?; } self.print_ident(item.ident)?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; // end inner head-block self.end()?; // end outer head-block } ast::ItemKind::Use(ref vp) => { self.head(&visibility_qualified(&item.vis, "use"))?; self.print_view_path(vp)?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; // end inner head-block self.end()?; // end outer head-block } @@ -1212,12 +1199,12 @@ impl<'a> State<'a> { self.print_ident(item.ident)?; self.word_space(":")?; self.print_type(ty)?; - space(&mut self.s)?; + self.s.space()?; self.end()?; // end the head-ibox self.word_space("=")?; self.print_expr(expr)?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; // end the outer cbox } ast::ItemKind::Const(ref ty, ref expr) => { @@ -1225,12 +1212,12 @@ impl<'a> State<'a> { self.print_ident(item.ident)?; self.word_space(":")?; self.print_type(ty)?; - space(&mut self.s)?; + self.s.space()?; self.end()?; // end the head-ibox self.word_space("=")?; self.print_expr(expr)?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; // end the outer cbox } ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref typarams, ref body) => { @@ -1244,7 +1231,7 @@ impl<'a> State<'a> { typarams, &item.vis )?; - word(&mut self.s, " ")?; + self.s.word(" ")?; self.print_block_with_attrs(body, &item.attrs)?; } ast::ItemKind::Mod(ref _mod) => { @@ -1264,7 +1251,7 @@ impl<'a> State<'a> { } ast::ItemKind::GlobalAsm(ref ga) => { self.head(&visibility_qualified(&item.vis, "global_asm!"))?; - word(&mut self.s, &ga.asm.as_str())?; + self.s.word(&ga.asm.as_str())?; self.end()?; } ast::ItemKind::Ty(ref ty, ref params) => { @@ -1276,10 +1263,10 @@ impl<'a> State<'a> { self.end()?; // end the inner ibox self.print_where_clause(¶ms.where_clause)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_type(ty)?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; // end the outer ibox } ast::ItemKind::Enum(ref enum_definition, ref params) => { @@ -1305,7 +1292,7 @@ impl<'a> State<'a> { self.print_unsafety(unsafety)?; self.word_nbsp("impl")?; self.print_trait_ref(trait_ref)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("for")?; self.word_space("..")?; self.bopen()?; @@ -1326,23 +1313,23 @@ impl<'a> State<'a> { if generics.is_parameterized() { self.print_generics(generics)?; - space(&mut self.s)?; + self.s.space()?; } if polarity == ast::ImplPolarity::Negative { - word(&mut self.s, "!")?; + self.s.word("!")?; } if let Some(ref t) = *opt_trait { self.print_trait_ref(t)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("for")?; } self.print_type(ty)?; self.print_where_clause(&generics.where_clause)?; - space(&mut self.s)?; + self.s.space()?; self.bopen()?; self.print_inner_attributes(&item.attrs)?; for impl_item in impl_items { @@ -1360,7 +1347,7 @@ impl<'a> State<'a> { let mut real_bounds = Vec::with_capacity(bounds.len()); for b in bounds.iter() { if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = *b { - space(&mut self.s)?; + self.s.space()?; self.word_space("for ?")?; self.print_trait_ref(&ptr.trait_ref)?; } else { @@ -1369,7 +1356,7 @@ impl<'a> State<'a> { } self.print_bounds(":", &real_bounds[..])?; self.print_where_clause(&generics.where_clause)?; - word(&mut self.s, " ")?; + self.s.word(" ")?; self.bopen()?; for trait_item in trait_items { self.print_trait_item(trait_item)?; @@ -1378,23 +1365,23 @@ impl<'a> State<'a> { } ast::ItemKind::Mac(codemap::Spanned { ref node, .. }) => { self.print_path(&node.path, false, 0, false)?; - word(&mut self.s, "! ")?; + self.s.word("! ")?; self.print_ident(item.ident)?; self.cbox(INDENT_UNIT)?; self.popen()?; self.print_tts(node.stream())?; self.pclose()?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; } ast::ItemKind::MacroDef(ref tts) => { - word(&mut self.s, "macro_rules! ")?; + self.s.word("macro_rules! ")?; self.print_ident(item.ident)?; self.cbox(INDENT_UNIT)?; self.popen()?; self.print_tts(tts.stream())?; self.pclose()?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; } } @@ -1407,7 +1394,7 @@ impl<'a> State<'a> { fn print_formal_lifetime_list(&mut self, lifetimes: &[ast::LifetimeDef]) -> io::Result<()> { if !lifetimes.is_empty() { - word(&mut self.s, "for<")?; + self.s.word("for<")?; let mut comma = false; for lifetime_def in lifetimes { if comma { @@ -1417,7 +1404,7 @@ impl<'a> State<'a> { self.print_lifetime_bounds(&lifetime_def.lifetime, &lifetime_def.bounds)?; comma = true; } - word(&mut self.s, ">")?; + self.s.word(">")?; } Ok(()) } @@ -1435,7 +1422,7 @@ impl<'a> State<'a> { self.print_ident(ident)?; self.print_generics(generics)?; self.print_where_clause(&generics.where_clause)?; - space(&mut self.s)?; + self.s.space()?; self.print_variants(&enum_definition.variants, span) } @@ -1449,7 +1436,7 @@ impl<'a> State<'a> { self.print_outer_attributes(&v.node.attrs)?; self.ibox(INDENT_UNIT)?; self.print_variant(v)?; - word(&mut self.s, ",")?; + self.s.word(",")?; self.end()?; self.maybe_print_trailing_comment(v.span, None)?; } @@ -1503,7 +1490,7 @@ impl<'a> State<'a> { } self.print_where_clause(&generics.where_clause)?; if print_finalizer { - word(&mut self.s, ";")?; + self.s.word(";")?; } self.end()?; self.end() // close the outer-box @@ -1521,7 +1508,7 @@ impl<'a> State<'a> { self.print_ident(field.ident.unwrap())?; self.word_nbsp(":")?; self.print_type(&field.ty)?; - word(&mut self.s, ",")?; + self.s.word(",")?; } self.bclose(span) @@ -1534,7 +1521,7 @@ impl<'a> State<'a> { 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.s.space()?; self.word_space("=")?; self.print_expr(d) } @@ -1577,7 +1564,7 @@ impl<'a> State<'a> { self.nbsp()?; self.print_block_with_attrs(body, &ti.attrs)?; } else { - word(&mut self.s, ";")?; + self.s.word(";")?; } } ast::TraitItemKind::Type(ref bounds, ref default) => { @@ -1587,12 +1574,12 @@ impl<'a> State<'a> { ast::TraitItemKind::Macro(codemap::Spanned { ref node, .. }) => { // code copied from ItemKind::Mac: self.print_path(&node.path, false, 0, false)?; - word(&mut self.s, "! ")?; + self.s.word("! ")?; self.cbox(INDENT_UNIT)?; self.popen()?; self.print_tts(node.stream())?; self.pclose()?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()? } } @@ -1621,12 +1608,12 @@ impl<'a> State<'a> { ast::ImplItemKind::Macro(codemap::Spanned { ref node, .. }) => { // code copied from ItemKind::Mac: self.print_path(&node.path, false, 0, false)?; - word(&mut self.s, "! ")?; + self.s.word("! ")?; self.cbox(INDENT_UNIT)?; self.popen()?; self.print_tts(node.stream())?; self.pclose()?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()? } } @@ -1650,7 +1637,7 @@ impl<'a> State<'a> { self.word_space("=")?; self.print_expr(init)?; } - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; } ast::StmtKind::Item(ref item) => self.print_item(item)?, @@ -1658,13 +1645,13 @@ impl<'a> State<'a> { self.space_if_not_bol()?; self.print_expr_outer_attr_style(expr, false)?; if parse::classify::expr_requires_semi_to_be_stmt(expr) { - word(&mut self.s, ";")?; + self.s.word(";")?; } } ast::StmtKind::Semi(ref expr) => { self.space_if_not_bol()?; self.print_expr_outer_attr_style(expr, false)?; - word(&mut self.s, ";")?; + self.s.word(";")?; } ast::StmtKind::Mac(ref mac) => { let (ref mac, style, ref attrs) = **mac; @@ -1676,7 +1663,7 @@ impl<'a> State<'a> { }; self.print_mac(mac, delim)?; if style == ast::MacStmtStyle::Semicolon { - word(&mut self.s, ";")?; + self.s.word(";")?; } } } @@ -1747,9 +1734,9 @@ impl<'a> State<'a> { ast::ExprKind::If(ref i, ref then, ref e) => { self.cbox(INDENT_UNIT - 1)?; self.ibox(0)?; - word(&mut self.s, " else if ")?; + self.s.word(" else if ")?; self.print_expr(i)?; - space(&mut self.s)?; + self.s.space()?; self.print_block(then)?; self.print_else(e.as_ref().map(|e| &**e)) } @@ -1757,12 +1744,12 @@ impl<'a> State<'a> { ast::ExprKind::IfLet(ref pat, ref expr, ref then, ref e) => { self.cbox(INDENT_UNIT - 1)?; self.ibox(0)?; - word(&mut self.s, " else if let ")?; + self.s.word(" else if let ")?; self.print_pat(pat)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_expr(expr)?; - space(&mut self.s)?; + self.s.space()?; self.print_block(then)?; self.print_else(e.as_ref().map(|e| &**e)) } @@ -1770,7 +1757,7 @@ impl<'a> State<'a> { ast::ExprKind::Block(ref b) => { self.cbox(INDENT_UNIT - 1)?; self.ibox(0)?; - word(&mut self.s, " else ")?; + self.s.word(" else ")?; self.print_block(b) } // BLEAH, constraints would be great here @@ -1787,7 +1774,7 @@ impl<'a> State<'a> { elseopt: Option<&ast::Expr>) -> io::Result<()> { self.head("if")?; self.print_expr(test)?; - space(&mut self.s)?; + self.s.space()?; self.print_block(blk)?; self.print_else(elseopt) } @@ -1796,10 +1783,10 @@ impl<'a> State<'a> { elseopt: Option<&ast::Expr>) -> io::Result<()> { self.head("if let")?; self.print_pat(pat)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_expr(expr)?; - space(&mut self.s)?; + self.s.space()?; self.print_block(blk)?; self.print_else(elseopt) } @@ -1807,10 +1794,10 @@ impl<'a> State<'a> { pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken) -> io::Result<()> { self.print_path(&m.node.path, false, 0, false)?; - word(&mut self.s, "!")?; + self.s.word("!")?; match delim { token::Paren => self.popen()?, - token::Bracket => word(&mut self.s, "[")?, + token::Bracket => self.s.word("[")?, token::Brace => { self.head("")?; self.bopen()?; @@ -1820,7 +1807,7 @@ impl<'a> State<'a> { self.print_tts(m.node.stream())?; match delim { token::Paren => self.pclose(), - token::Bracket => word(&mut self.s, "]"), + token::Bracket => self.s.word("]"), token::Brace => self.bclose(m.span), token::NoDelim => Ok(()), } @@ -1860,7 +1847,7 @@ impl<'a> State<'a> { place: &ast::Expr, expr: &ast::Expr) -> io::Result<()> { self.print_expr_maybe_paren(place)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("<-")?; self.print_expr_maybe_paren(expr) } @@ -1868,10 +1855,10 @@ impl<'a> State<'a> { fn print_expr_vec(&mut self, exprs: &[P], attrs: &[Attribute]) -> io::Result<()> { self.ibox(INDENT_UNIT)?; - word(&mut self.s, "[")?; + self.s.word("[")?; self.print_inner_attributes_inline(attrs)?; self.commasep_exprs(Inconsistent, &exprs[..])?; - word(&mut self.s, "]")?; + self.s.word("]")?; self.end() } @@ -1880,12 +1867,12 @@ impl<'a> State<'a> { count: &ast::Expr, attrs: &[Attribute]) -> io::Result<()> { self.ibox(INDENT_UNIT)?; - word(&mut self.s, "[")?; + self.s.word("[")?; self.print_inner_attributes_inline(attrs)?; self.print_expr(element)?; self.word_space(";")?; self.print_expr(count)?; - word(&mut self.s, "]")?; + self.s.word("]")?; self.end() } @@ -1895,7 +1882,7 @@ impl<'a> State<'a> { wth: &Option>, attrs: &[Attribute]) -> io::Result<()> { self.print_path(path, true, 0, false)?; - word(&mut self.s, "{")?; + self.s.word("{")?; self.print_inner_attributes_inline(attrs)?; self.commasep_cmnt( Consistent, @@ -1914,18 +1901,18 @@ impl<'a> State<'a> { Some(ref expr) => { self.ibox(INDENT_UNIT)?; if !fields.is_empty() { - word(&mut self.s, ",")?; - space(&mut self.s)?; + self.s.word(",")?; + self.s.space()?; } - word(&mut self.s, "..")?; + self.s.word("..")?; self.print_expr(expr)?; self.end()?; } _ => if !fields.is_empty() { - word(&mut self.s, ",")? + self.s.word(",")? } } - word(&mut self.s, "}")?; + self.s.word("}")?; Ok(()) } @@ -1935,7 +1922,7 @@ impl<'a> State<'a> { self.print_inner_attributes_inline(attrs)?; self.commasep_exprs(Inconsistent, &exprs[..])?; if exprs.len() == 1 { - word(&mut self.s, ",")?; + self.s.word(",")?; } self.pclose() } @@ -1948,18 +1935,14 @@ impl<'a> State<'a> { } fn print_expr_method_call(&mut self, - ident: ast::SpannedIdent, - tys: &[P], + segment: &ast::PathSegment, args: &[P]) -> io::Result<()> { let base_args = &args[1..]; self.print_expr(&args[0])?; - word(&mut self.s, ".")?; - self.print_ident(ident.node)?; - if !tys.is_empty() { - word(&mut self.s, "::<")?; - self.commasep(Inconsistent, tys, - |s, ty| s.print_type(ty))?; - word(&mut self.s, ">")?; + self.s.word(".")?; + self.print_ident(segment.identifier)?; + if let Some(ref parameters) = segment.parameters { + self.print_path_parameters(parameters, true)?; } self.print_call_post(base_args) } @@ -1973,7 +1956,7 @@ impl<'a> State<'a> { } else { self.print_expr(lhs)?; } - space(&mut self.s)?; + self.s.space()?; self.word_space(op.node.to_string())?; if self.check_expr_bin_needs_paren(rhs, op) { self.print_expr_maybe_paren(rhs) @@ -1985,14 +1968,14 @@ impl<'a> State<'a> { fn print_expr_unary(&mut self, op: ast::UnOp, expr: &ast::Expr) -> io::Result<()> { - word(&mut self.s, ast::UnOp::to_string(op))?; + self.s.word(ast::UnOp::to_string(op))?; self.print_expr_maybe_paren(expr) } fn print_expr_addr_of(&mut self, mutability: ast::Mutability, expr: &ast::Expr) -> io::Result<()> { - word(&mut self.s, "&")?; + self.s.word("&")?; self.print_mutability(mutability)?; self.print_expr_maybe_paren(expr) } @@ -2038,8 +2021,8 @@ impl<'a> State<'a> { ast::ExprKind::Call(ref func, ref args) => { self.print_expr_call(func, &args[..])?; } - ast::ExprKind::MethodCall(ident, ref tys, ref args) => { - self.print_expr_method_call(ident, &tys[..], &args[..])?; + ast::ExprKind::MethodCall(ref segment, ref args) => { + self.print_expr_method_call(segment, &args[..])?; } ast::ExprKind::Binary(op, ref lhs, ref rhs) => { self.print_expr_binary(op, lhs, rhs)?; @@ -2059,7 +2042,7 @@ impl<'a> State<'a> { } else { self.print_expr_maybe_paren(expr)?; } - space(&mut self.s)?; + self.s.space()?; self.word_space("as")?; self.print_type(ty)?; } @@ -2081,7 +2064,7 @@ impl<'a> State<'a> { } self.head("while")?; self.print_expr(test)?; - space(&mut self.s)?; + self.s.space()?; self.print_block_with_attrs(blk, attrs)?; } ast::ExprKind::WhileLet(ref pat, ref expr, ref blk, opt_ident) => { @@ -2091,10 +2074,10 @@ impl<'a> State<'a> { } self.head("while let")?; self.print_pat(pat)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_expr(expr)?; - space(&mut self.s)?; + self.s.space()?; self.print_block_with_attrs(blk, attrs)?; } ast::ExprKind::ForLoop(ref pat, ref iter, ref blk, opt_ident) => { @@ -2104,10 +2087,10 @@ impl<'a> State<'a> { } self.head("for")?; self.print_pat(pat)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("in")?; self.print_expr(iter)?; - space(&mut self.s)?; + self.s.space()?; self.print_block_with_attrs(blk, attrs)?; } ast::ExprKind::Loop(ref blk, opt_ident) => { @@ -2116,7 +2099,7 @@ impl<'a> State<'a> { self.word_space(":")?; } self.head("loop")?; - space(&mut self.s)?; + self.s.space()?; self.print_block_with_attrs(blk, attrs)?; } ast::ExprKind::Match(ref expr, ref arms) => { @@ -2124,7 +2107,7 @@ impl<'a> State<'a> { self.ibox(4)?; self.word_nbsp("match")?; self.print_expr(expr)?; - space(&mut self.s)?; + self.s.space()?; self.bopen()?; self.print_inner_attributes_no_trailing_hardbreak(attrs)?; for arm in arms { @@ -2136,7 +2119,7 @@ impl<'a> State<'a> { self.print_capture_clause(capture_clause)?; self.print_fn_block_args(decl)?; - space(&mut self.s)?; + self.s.space()?; self.print_expr(body)?; self.end()?; // need to close a box @@ -2154,41 +2137,41 @@ impl<'a> State<'a> { } ast::ExprKind::Assign(ref lhs, ref rhs) => { self.print_expr(lhs)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_expr(rhs)?; } ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => { self.print_expr(lhs)?; - space(&mut self.s)?; - word(&mut self.s, op.node.to_string())?; + self.s.space()?; + self.s.word(op.node.to_string())?; self.word_space("=")?; self.print_expr(rhs)?; } ast::ExprKind::Field(ref expr, id) => { self.print_expr(expr)?; - word(&mut self.s, ".")?; + self.s.word(".")?; self.print_ident(id.node)?; } ast::ExprKind::TupField(ref expr, id) => { self.print_expr(expr)?; - word(&mut self.s, ".")?; + self.s.word(".")?; self.print_usize(id.node)?; } ast::ExprKind::Index(ref expr, ref index) => { self.print_expr(expr)?; - word(&mut self.s, "[")?; + self.s.word("[")?; self.print_expr(index)?; - word(&mut self.s, "]")?; + self.s.word("]")?; } ast::ExprKind::Range(ref start, ref end, limits) => { if let Some(ref e) = *start { self.print_expr(e)?; } if limits == ast::RangeLimits::HalfOpen { - word(&mut self.s, "..")?; + self.s.word("..")?; } else { - word(&mut self.s, "...")?; + self.s.word("...")?; } if let Some(ref e) = *end { self.print_expr(e)?; @@ -2201,34 +2184,34 @@ impl<'a> State<'a> { self.print_qpath(path, qself, true)? } ast::ExprKind::Break(opt_ident, ref opt_expr) => { - word(&mut self.s, "break")?; - space(&mut self.s)?; + self.s.word("break")?; + self.s.space()?; if let Some(ident) = opt_ident { self.print_ident(ident.node)?; - space(&mut self.s)?; + self.s.space()?; } if let Some(ref expr) = *opt_expr { self.print_expr(expr)?; - space(&mut self.s)?; + self.s.space()?; } } ast::ExprKind::Continue(opt_ident) => { - word(&mut self.s, "continue")?; - space(&mut self.s)?; + self.s.word("continue")?; + self.s.space()?; if let Some(ident) = opt_ident { self.print_ident(ident.node)?; - space(&mut self.s)? + self.s.space()? } } ast::ExprKind::Ret(ref result) => { - word(&mut self.s, "return")?; + self.s.word("return")?; if let Some(ref expr) = *result { - word(&mut self.s, " ")?; + self.s.word(" ")?; self.print_expr(expr)?; } } ast::ExprKind::InlineAsm(ref a) => { - word(&mut self.s, "asm!")?; + self.s.word("asm!")?; self.popen()?; self.print_string(&a.asm.as_str(), a.asm_str_style)?; self.word_space(":")?; @@ -2248,7 +2231,7 @@ impl<'a> State<'a> { s.pclose()?; Ok(()) })?; - space(&mut self.s)?; + self.s.space()?; self.word_space(":")?; self.commasep(Inconsistent, &a.inputs, |s, &(co, ref o)| { @@ -2258,7 +2241,7 @@ impl<'a> State<'a> { s.pclose()?; Ok(()) })?; - space(&mut self.s)?; + self.s.space()?; self.word_space(":")?; self.commasep(Inconsistent, &a.clobbers, @@ -2279,7 +2262,7 @@ impl<'a> State<'a> { } if !options.is_empty() { - space(&mut self.s)?; + self.s.space()?; self.word_space(":")?; self.commasep(Inconsistent, &options, |s, &co| { @@ -2299,11 +2282,11 @@ impl<'a> State<'a> { }, ast::ExprKind::Try(ref e) => { self.print_expr(e)?; - word(&mut self.s, "?")? + self.s.word("?")? } ast::ExprKind::Catch(ref blk) => { self.head("do catch")?; - space(&mut self.s)?; + self.s.space()?; self.print_block_with_attrs(blk, attrs)? } } @@ -2321,23 +2304,23 @@ impl<'a> State<'a> { } pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> { - word(&mut self.s, &ident.name.as_str())?; + self.s.word(&ident.name.as_str())?; self.ann.post(self, NodeIdent(&ident)) } pub fn print_usize(&mut self, i: usize) -> io::Result<()> { - word(&mut self.s, &i.to_string()) + self.s.word(&i.to_string()) } pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> { - word(&mut self.s, &name.as_str())?; + self.s.word(&name.as_str())?; self.ann.post(self, NodeName(&name)) } pub fn print_for_decl(&mut self, loc: &ast::Local, coll: &ast::Expr) -> io::Result<()> { self.print_local_decl(loc)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("in")?; self.print_expr(coll) } @@ -2357,36 +2340,45 @@ impl<'a> State<'a> { } for (i, segment) in segments.enumerate() { if i > 0 { - word(&mut self.s, "::")? - } - if segment.identifier.name != keywords::CrateRoot.name() && - segment.identifier.name != "$crate" { - self.print_ident(segment.identifier)?; - if let Some(ref parameters) = segment.parameters { - self.print_path_parameters(parameters, colons_before_params)?; - } + self.s.word("::")? } + self.print_path_segment(segment, colons_before_params)?; } Ok(()) } + fn print_path_segment(&mut self, + segment: &ast::PathSegment, + colons_before_params: bool) + -> io::Result<()> + { + if segment.identifier.name != keywords::CrateRoot.name() && + segment.identifier.name != keywords::DollarCrate.name() { + self.print_ident(segment.identifier)?; + if let Some(ref parameters) = segment.parameters { + self.print_path_parameters(parameters, colons_before_params)?; + } + } + Ok(()) + } + fn print_qpath(&mut self, path: &ast::Path, qself: &ast::QSelf, colons_before_params: bool) -> io::Result<()> { - word(&mut self.s, "<")?; + self.s.word("<")?; self.print_type(&qself.ty)?; if qself.position > 0 { - space(&mut self.s)?; + self.s.space()?; self.word_space("as")?; let depth = path.segments.len() - qself.position; self.print_path(path, false, depth, false)?; } - word(&mut self.s, ">")?; - word(&mut self.s, "::")?; + self.s.word(">")?; + self.s.word("::")?; let item_segment = path.segments.last().unwrap(); self.print_ident(item_segment.identifier)?; match item_segment.parameters { @@ -2401,12 +2393,12 @@ impl<'a> State<'a> { -> io::Result<()> { if colons_before_params { - word(&mut self.s, "::")? + self.s.word("::")? } match *parameters { ast::PathParameters::AngleBracketed(ref data) => { - word(&mut self.s, "<")?; + self.s.word("<")?; let mut comma = false; for lifetime in &data.lifetimes { @@ -2433,22 +2425,22 @@ impl<'a> State<'a> { self.word_space(",")? } self.print_ident(binding.ident)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_type(&binding.ty)?; comma = true; } - word(&mut self.s, ">")? + self.s.word(">")? } ast::PathParameters::Parenthesized(ref data) => { - word(&mut self.s, "(")?; + self.s.word("(")?; self.commasep( Inconsistent, &data.inputs, |s, ty| s.print_type(ty))?; - word(&mut self.s, ")")?; + self.s.word(")")?; if let Some(ref ty) = data.output { self.space_if_not_bol()?; @@ -2467,7 +2459,7 @@ impl<'a> State<'a> { /* Pat isn't normalized, but the beauty of it is that it doesn't matter */ match pat.node { - PatKind::Wild => word(&mut self.s, "_")?, + PatKind::Wild => self.s.word("_")?, PatKind::Ident(binding_mode, ref path1, ref sub) => { match binding_mode { ast::BindingMode::ByRef(mutbl) => { @@ -2481,7 +2473,7 @@ impl<'a> State<'a> { } self.print_ident(path1.node)?; if let Some(ref p) = *sub { - word(&mut self.s, "@")?; + self.s.word("@")?; self.print_pat(p)?; } } @@ -2493,9 +2485,9 @@ impl<'a> State<'a> { if ddpos != 0 { self.word_space(",")?; } - word(&mut self.s, "..")?; + self.s.word("..")?; if ddpos != elts.len() { - word(&mut self.s, ",")?; + self.s.word(",")?; self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p))?; } } else { @@ -2527,10 +2519,10 @@ impl<'a> State<'a> { |f| f.node.pat.span)?; if etc { if !fields.is_empty() { self.word_space(",")?; } - word(&mut self.s, "..")?; + self.s.word("..")?; } - space(&mut self.s)?; - word(&mut self.s, "}")?; + self.s.space()?; + self.s.word("}")?; } PatKind::Tuple(ref elts, ddpos) => { self.popen()?; @@ -2539,42 +2531,42 @@ impl<'a> State<'a> { if ddpos != 0 { self.word_space(",")?; } - word(&mut self.s, "..")?; + self.s.word("..")?; if ddpos != elts.len() { - word(&mut self.s, ",")?; + self.s.word(",")?; self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p))?; } } else { self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p))?; if elts.len() == 1 { - word(&mut self.s, ",")?; + self.s.word(",")?; } } self.pclose()?; } PatKind::Box(ref inner) => { - word(&mut self.s, "box ")?; + self.s.word("box ")?; self.print_pat(inner)?; } PatKind::Ref(ref inner, mutbl) => { - word(&mut self.s, "&")?; + self.s.word("&")?; if mutbl == ast::Mutability::Mutable { - word(&mut self.s, "mut ")?; + self.s.word("mut ")?; } self.print_pat(inner)?; } PatKind::Lit(ref e) => self.print_expr(&**e)?, PatKind::Range(ref begin, ref end, ref end_kind) => { self.print_expr(begin)?; - space(&mut self.s)?; + self.s.space()?; match *end_kind { - RangeEnd::Included => word(&mut self.s, "...")?, - RangeEnd::Excluded => word(&mut self.s, "..")?, + RangeEnd::Included => self.s.word("...")?, + RangeEnd::Excluded => self.s.word("..")?, } self.print_expr(end)?; } PatKind::Slice(ref before, ref slice, ref after) => { - word(&mut self.s, "[")?; + self.s.word("[")?; self.commasep(Inconsistent, &before[..], |s, p| s.print_pat(p))?; @@ -2583,13 +2575,13 @@ impl<'a> State<'a> { if p.node != PatKind::Wild { self.print_pat(p)?; } - word(&mut self.s, "..")?; + self.s.word("..")?; if !after.is_empty() { self.word_space(",")?; } } self.commasep(Inconsistent, &after[..], |s, p| s.print_pat(p))?; - word(&mut self.s, "]")?; + self.s.word("]")?; } PatKind::Mac(ref m) => self.print_mac(m, token::Paren)?, } @@ -2600,7 +2592,7 @@ impl<'a> State<'a> { // I have no idea why this check is necessary, but here it // is :( if arm.attrs.is_empty() { - space(&mut self.s)?; + self.s.space()?; } self.cbox(INDENT_UNIT)?; self.ibox(0)?; @@ -2611,16 +2603,16 @@ impl<'a> State<'a> { if first { first = false; } else { - space(&mut self.s)?; + self.s.space()?; self.word_space("|")?; } self.print_pat(p)?; } - space(&mut self.s)?; + self.s.space()?; if let Some(ref e) = arm.guard { self.word_space("if")?; self.print_expr(e)?; - space(&mut self.s)?; + self.s.space()?; } self.word_space("=>")?; @@ -2631,13 +2623,13 @@ impl<'a> State<'a> { // If it is a user-provided unsafe block, print a comma after it if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules { - word(&mut self.s, ",")?; + self.s.word(",")?; } } _ => { self.end()?; // close the ibox for the pattern self.print_expr(&arm.body)?; - word(&mut self.s, ",")?; + self.s.word(",")?; } } self.end() // close enclosing cbox @@ -2647,17 +2639,17 @@ impl<'a> State<'a> { match explicit_self.node { SelfKind::Value(m) => { self.print_mutability(m)?; - word(&mut self.s, "self") + self.s.word("self") } SelfKind::Region(ref lt, m) => { - word(&mut self.s, "&")?; + self.s.word("&")?; self.print_opt_lifetime(lt)?; self.print_mutability(m)?; - word(&mut self.s, "self") + self.s.word("self") } SelfKind::Explicit(ref typ, m) => { self.print_mutability(m)?; - word(&mut self.s, "self")?; + self.s.word("self")?; self.word_space(":")?; self.print_type(typ) } @@ -2688,7 +2680,7 @@ impl<'a> State<'a> { self.popen()?; self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, false))?; if decl.variadic { - word(&mut self.s, ", ...")?; + self.s.word(", ...")?; } self.pclose()?; @@ -2699,9 +2691,9 @@ impl<'a> State<'a> { &mut self, decl: &ast::FnDecl) -> io::Result<()> { - word(&mut self.s, "|")?; + self.s.word("|")?; self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, true))?; - word(&mut self.s, "|")?; + self.s.word("|")?; if let ast::FunctionRetTy::Default(..) = decl.output { return Ok(()); @@ -2731,7 +2723,7 @@ impl<'a> State<'a> { bounds: &[ast::TyParamBound]) -> io::Result<()> { if !bounds.is_empty() { - word(&mut self.s, prefix)?; + self.s.word(prefix)?; let mut first = true; for bound in bounds { self.nbsp()?; @@ -2746,7 +2738,7 @@ impl<'a> State<'a> { self.print_poly_trait_ref(tref) } TraitTyParamBound(ref tref, TraitBoundModifier::Maybe) => { - word(&mut self.s, "?")?; + self.s.word("?")?; self.print_poly_trait_ref(tref) } RegionTyParamBound(ref lt) => { @@ -2774,10 +2766,10 @@ impl<'a> State<'a> { { self.print_lifetime(lifetime)?; if !bounds.is_empty() { - word(&mut self.s, ": ")?; + self.s.word(": ")?; for (i, bound) in bounds.iter().enumerate() { if i != 0 { - word(&mut self.s, " + ")?; + self.s.word(" + ")?; } self.print_lifetime(bound)?; } @@ -2794,7 +2786,7 @@ impl<'a> State<'a> { return Ok(()); } - word(&mut self.s, "<")?; + self.s.word("<")?; let mut ints = Vec::new(); for i in 0..total { @@ -2813,7 +2805,7 @@ impl<'a> State<'a> { } })?; - word(&mut self.s, ">")?; + self.s.word(">")?; Ok(()) } @@ -2823,7 +2815,7 @@ impl<'a> State<'a> { self.print_bounds(":", ¶m.bounds)?; match param.default { Some(ref default) => { - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_type(default) } @@ -2837,7 +2829,7 @@ impl<'a> State<'a> { return Ok(()) } - space(&mut self.s)?; + self.s.space()?; self.word_space("where")?; for (i, predicate) in where_clause.predicates.iter().enumerate() { @@ -2863,7 +2855,7 @@ impl<'a> State<'a> { ref rhs_ty, ..}) => { self.print_type(lhs_ty)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_type(rhs_ty)?; } @@ -2880,7 +2872,7 @@ impl<'a> State<'a> { if path.segments.last().unwrap().identifier.name != ident.name { - space(&mut self.s)?; + self.s.space()?; self.word_space("as")?; self.print_ident(ident)?; } @@ -2890,26 +2882,26 @@ impl<'a> State<'a> { ast::ViewPathGlob(ref path) => { self.print_path(path, false, 0, true)?; - word(&mut self.s, "::*") + self.s.word("::*") } ast::ViewPathList(ref path, ref idents) => { if path.segments.is_empty() { - word(&mut self.s, "{")?; + self.s.word("{")?; } else { self.print_path(path, false, 0, true)?; - word(&mut self.s, "::{")?; + self.s.word("::{")?; } self.commasep(Inconsistent, &idents[..], |s, w| { s.print_ident(w.node.name)?; if let Some(ident) = w.node.rename { - space(&mut s.s)?; + s.s.space()?; s.word_space("as")?; s.print_ident(ident)?; } Ok(()) })?; - word(&mut self.s, "}") + self.s.word("}") } } } @@ -2942,8 +2934,8 @@ impl<'a> State<'a> { }; if !invalid { self.print_pat(&input.pat)?; - word(&mut self.s, ":")?; - space(&mut self.s)?; + self.s.word(":")?; + self.s.space()?; } self.print_type(&input.ty)?; } @@ -2982,7 +2974,7 @@ impl<'a> State<'a> { -> io::Result<()> { self.ibox(INDENT_UNIT)?; if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() { - word(&mut self.s, "for")?; + self.s.word("for")?; self.print_generics(generics)?; } let generics = ast::Generics { @@ -3018,7 +3010,6 @@ impl<'a> State<'a> { let next = next_pos.unwrap_or(cmnt.pos + BytePos(1)); if span.hi < cmnt.pos && cmnt.pos < next && span_line.line == comment_line.line { self.print_comment(cmnt)?; - self.cur_cmnt_and_lit.cur_cmnt += 1; } } Ok(()) @@ -3028,11 +3019,10 @@ impl<'a> State<'a> { // If there aren't any remaining comments, then we need to manually // make sure there is a line break at the end. if self.next_comment().is_none() { - hardbreak(&mut self.s)?; + self.s.hardbreak()?; } while let Some(ref cmnt) = self.next_comment() { self.print_comment(cmnt)?; - self.cur_cmnt_and_lit.cur_cmnt += 1; } Ok(()) } @@ -3066,7 +3056,7 @@ impl<'a> State<'a> { constness: ast::Constness, abi: Abi, vis: &ast::Visibility) -> io::Result<()> { - word(&mut self.s, &visibility_qualified(vis, ""))?; + self.s.word(&visibility_qualified(vis, ""))?; match constness { ast::Constness::NotConst => {} @@ -3080,7 +3070,7 @@ impl<'a> State<'a> { self.word_nbsp(&abi.to_string())?; } - word(&mut self.s, "fn") + self.s.word("fn") } pub fn print_unsafety(&mut self, s: ast::Unsafety) -> io::Result<()> { diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index 15111bbba0..d51ff9860a 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -211,10 +211,7 @@ impl Encodable for P<[T]> { impl Decodable for P<[T]> { fn decode(d: &mut D) -> Result, D::Error> { - Ok(P::from_vec(match Decodable::decode(d) { - Ok(t) => t, - Err(e) => return Err(e) - })) + Ok(P::from_vec(Decodable::decode(d)?)) } } diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index a0d1785c6f..bd2c386cb8 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -25,7 +25,6 @@ use std::rc::Rc; use codemap::{self, CodeMap, ExpnInfo, NameAndSpan, MacroAttribute, dummy_spanned}; use errors; -use errors::snippet::{SnippetData}; use config; use entry::{self, EntryPointType}; use ext::base::{ExtCtxt, Resolver}; @@ -52,7 +51,8 @@ struct Test { path: Vec , bench: bool, ignore: bool, - should_panic: ShouldPanic + should_panic: ShouldPanic, + allow_fail: bool, } struct TestCtxt<'a> { @@ -133,7 +133,8 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> { path: self.cx.path.clone(), bench: is_bench_fn(&self.cx, &i), ignore: is_ignored(&i), - should_panic: should_panic(&i, &self.cx) + should_panic: should_panic(&i, &self.cx), + allow_fail: is_allowed_fail(&i), }; self.cx.testfns.push(test); self.tests.push(i.ident); @@ -383,6 +384,10 @@ fn is_ignored(i: &ast::Item) -> bool { i.attrs.iter().any(|attr| attr.check_name("ignore")) } +fn is_allowed_fail(i: &ast::Item) -> bool { + i.attrs.iter().any(|attr| attr.check_name("allow_fail")) +} + fn should_panic(i: &ast::Item, cx: &TestCtxt) -> ShouldPanic { match i.attrs.iter().find(|attr| attr.check_name("should_panic")) { Some(attr) => { @@ -668,6 +673,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P { } } }; + let allow_fail_expr = ecx.expr_bool(span, test.allow_fail); // self::test::TestDesc { ... } let desc_expr = ecx.expr_struct( @@ -675,7 +681,8 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P { test_path("TestDesc"), vec![field("name", name_expr), field("ignore", ignore_expr), - field("should_panic", fail_expr)]); + field("should_panic", fail_expr), + field("allow_fail", allow_fail_expr)]); let mut visible_path = match cx.toplevel_reexport { diff --git a/src/libsyntax/test_snippet.rs b/src/libsyntax/test_snippet.rs index b3fa1e9737..4fae2ff981 100644 --- a/src/libsyntax/test_snippet.rs +++ b/src/libsyntax/test_snippet.rs @@ -735,6 +735,49 @@ error: foo "#); } +#[test] +fn multiple_labels_secondary_without_message_3() { + test_harness(r#" +fn foo() { + a bc d +} +"#, + vec![ + SpanLabel { + start: Position { + string: "a", + count: 1, + }, + end: Position { + string: "b", + count: 1, + }, + label: "`a` is a good letter", + }, + SpanLabel { + start: Position { + string: "c", + count: 1, + }, + end: Position { + string: "d", + count: 1, + }, + label: "", + }, + ], + r#" +error: foo + --> test.rs:3:3 + | +3 | a bc d + | ^^^^---- + | | + | `a` is a good letter + +"#); +} + #[test] fn multiple_labels_without_message() { test_harness(r#" diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 339e7c0b62..8eee25405d 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -138,6 +138,10 @@ impl TokenTree { _ => false, } } + + pub fn joint(self) -> TokenStream { + TokenStream { kind: TokenStreamKind::JointTree(self) } + } } /// # Token Streams @@ -155,6 +159,7 @@ pub struct TokenStream { enum TokenStreamKind { Empty, Tree(TokenTree), + JointTree(TokenTree), Stream(RcSlice), } @@ -199,7 +204,7 @@ impl TokenStream { pub fn concat(mut streams: Vec) -> TokenStream { match streams.len() { 0 => TokenStream::empty(), - 1 => TokenStream::from(streams.pop().unwrap()), + 1 => streams.pop().unwrap(), _ => TokenStream::concat_rc_slice(RcSlice::new(streams)), } } @@ -225,58 +230,164 @@ impl TokenStream { } true } + + /// Precondition: `self` consists of a single token tree. + /// Returns true if the token tree is a joint operation w.r.t. `proc_macro::TokenNode`. + pub fn as_tree(self) -> (TokenTree, bool /* joint? */) { + match self.kind { + TokenStreamKind::Tree(tree) => (tree, false), + TokenStreamKind::JointTree(tree) => (tree, true), + _ => unreachable!(), + } + } + + pub fn map TokenTree>(self, mut f: F) -> TokenStream { + let mut trees = self.into_trees(); + let mut result = Vec::new(); + while let Some(stream) = trees.next_as_stream() { + result.push(match stream.kind { + TokenStreamKind::Tree(tree) => f(tree).into(), + TokenStreamKind::JointTree(tree) => f(tree).joint(), + _ => unreachable!() + }); + } + TokenStream::concat(result) + } + + fn first_tree(&self) -> Option { + match self.kind { + TokenStreamKind::Empty => None, + TokenStreamKind::Tree(ref tree) | + TokenStreamKind::JointTree(ref tree) => Some(tree.clone()), + TokenStreamKind::Stream(ref stream) => stream.first().unwrap().first_tree(), + } + } + + fn last_tree_if_joint(&self) -> Option { + match self.kind { + TokenStreamKind::Empty | TokenStreamKind::Tree(..) => None, + TokenStreamKind::JointTree(ref tree) => Some(tree.clone()), + TokenStreamKind::Stream(ref stream) => stream.last().unwrap().last_tree_if_joint(), + } + } +} + +pub struct TokenStreamBuilder(Vec); + +impl TokenStreamBuilder { + pub fn new() -> TokenStreamBuilder { + TokenStreamBuilder(Vec::new()) + } + + pub fn push>(&mut self, stream: T) { + let stream = stream.into(); + let last_tree_if_joint = self.0.last().and_then(TokenStream::last_tree_if_joint); + if let Some(TokenTree::Token(last_span, last_tok)) = last_tree_if_joint { + if let Some(TokenTree::Token(span, tok)) = stream.first_tree() { + if let Some(glued_tok) = last_tok.glue(tok) { + let last_stream = self.0.pop().unwrap(); + self.push_all_but_last_tree(&last_stream); + let glued_span = last_span.to(span); + self.0.push(TokenTree::Token(glued_span, glued_tok).into()); + self.push_all_but_first_tree(&stream); + return + } + } + } + self.0.push(stream); + } + + pub fn add>(mut self, stream: T) -> Self { + self.push(stream); + self + } + + pub fn build(self) -> TokenStream { + TokenStream::concat(self.0) + } + + fn push_all_but_last_tree(&mut self, stream: &TokenStream) { + if let TokenStreamKind::Stream(ref streams) = stream.kind { + let len = streams.len(); + match len { + 1 => {} + 2 => self.0.push(streams[0].clone().into()), + _ => self.0.push(TokenStream::concat_rc_slice(streams.sub_slice(0 .. len - 1))), + } + self.push_all_but_last_tree(&streams[len - 1]) + } + } + + fn push_all_but_first_tree(&mut self, stream: &TokenStream) { + if let TokenStreamKind::Stream(ref streams) = stream.kind { + let len = streams.len(); + match len { + 1 => {} + 2 => self.0.push(streams[1].clone().into()), + _ => self.0.push(TokenStream::concat_rc_slice(streams.sub_slice(1 .. len))), + } + self.push_all_but_first_tree(&streams[0]) + } + } } +#[derive(Clone)] pub struct Cursor(CursorKind); +#[derive(Clone)] enum CursorKind { Empty, Tree(TokenTree, bool /* consumed? */), + JointTree(TokenTree, bool /* consumed? */), Stream(StreamCursor), } +#[derive(Clone)] struct StreamCursor { stream: RcSlice, index: usize, stack: Vec<(RcSlice, usize)>, } -impl Iterator for Cursor { - type Item = TokenTree; - - fn next(&mut self) -> Option { - let cursor = match self.0 { - CursorKind::Stream(ref mut cursor) => cursor, - CursorKind::Tree(ref tree, ref mut consumed @ false) => { - *consumed = true; - return Some(tree.clone()); - } - _ => return None, - }; +impl StreamCursor { + fn new(stream: RcSlice) -> Self { + StreamCursor { stream: stream, index: 0, stack: Vec::new() } + } + fn next_as_stream(&mut self) -> Option { loop { - if cursor.index < cursor.stream.len() { - match cursor.stream[cursor.index].kind.clone() { - TokenStreamKind::Tree(tree) => { - cursor.index += 1; - return Some(tree); - } - TokenStreamKind::Stream(stream) => { - cursor.stack.push((mem::replace(&mut cursor.stream, stream), - mem::replace(&mut cursor.index, 0) + 1)); - } - TokenStreamKind::Empty => { - cursor.index += 1; - } + if self.index < self.stream.len() { + self.index += 1; + let next = self.stream[self.index - 1].clone(); + match next.kind { + TokenStreamKind::Tree(..) | TokenStreamKind::JointTree(..) => return Some(next), + TokenStreamKind::Stream(stream) => self.insert(stream), + TokenStreamKind::Empty => {} } - } else if let Some((stream, index)) = cursor.stack.pop() { - cursor.stream = stream; - cursor.index = index; + } else if let Some((stream, index)) = self.stack.pop() { + self.stream = stream; + self.index = index; } else { return None; } } } + + fn insert(&mut self, stream: RcSlice) { + self.stack.push((mem::replace(&mut self.stream, stream), + mem::replace(&mut self.index, 0))); + } +} + +impl Iterator for Cursor { + type Item = TokenTree; + + fn next(&mut self) -> Option { + self.next_as_stream().map(|stream| match stream.kind { + TokenStreamKind::Tree(tree) | TokenStreamKind::JointTree(tree) => tree, + _ => unreachable!() + }) + } } impl Cursor { @@ -284,18 +395,49 @@ impl Cursor { Cursor(match stream.kind { TokenStreamKind::Empty => CursorKind::Empty, TokenStreamKind::Tree(tree) => CursorKind::Tree(tree, false), - TokenStreamKind::Stream(stream) => { - CursorKind::Stream(StreamCursor { stream: stream, index: 0, stack: Vec::new() }) - } + TokenStreamKind::JointTree(tree) => CursorKind::JointTree(tree, false), + TokenStreamKind::Stream(stream) => CursorKind::Stream(StreamCursor::new(stream)), }) } - pub fn original_stream(self) -> TokenStream { + pub fn next_as_stream(&mut self) -> Option { + let (stream, consumed) = match self.0 { + CursorKind::Tree(ref tree, ref mut consumed @ false) => + (tree.clone().into(), consumed), + CursorKind::JointTree(ref tree, ref mut consumed @ false) => + (tree.clone().joint(), consumed), + CursorKind::Stream(ref mut cursor) => return cursor.next_as_stream(), + _ => return None, + }; + + *consumed = true; + Some(stream) + } + + pub fn insert(&mut self, stream: TokenStream) { + match self.0 { + _ if stream.is_empty() => return, + CursorKind::Empty => *self = stream.trees(), + CursorKind::Tree(_, consumed) | CursorKind::JointTree(_, consumed) => { + *self = TokenStream::concat(vec![self.original_stream(), stream]).trees(); + if consumed { + self.next(); + } + } + CursorKind::Stream(ref mut cursor) => { + cursor.insert(ThinTokenStream::from(stream).0.unwrap()); + } + } + } + + pub fn original_stream(&self) -> TokenStream { match self.0 { CursorKind::Empty => TokenStream::empty(), - CursorKind::Tree(tree, _) => tree.into(), - CursorKind::Stream(cursor) => TokenStream::concat_rc_slice({ - cursor.stack.get(0).cloned().map(|(stream, _)| stream).unwrap_or(cursor.stream) + CursorKind::Tree(ref tree, _) => tree.clone().into(), + CursorKind::JointTree(ref tree, _) => tree.clone().joint(), + CursorKind::Stream(ref cursor) => TokenStream::concat_rc_slice({ + cursor.stack.get(0).cloned().map(|(stream, _)| stream) + .unwrap_or(cursor.stream.clone()) }), } } @@ -304,8 +446,9 @@ impl Cursor { fn look_ahead(streams: &[TokenStream], mut n: usize) -> Result { for stream in streams { n = match stream.kind { - TokenStreamKind::Tree(ref tree) if n == 0 => return Ok(tree.clone()), - TokenStreamKind::Tree(..) => n - 1, + TokenStreamKind::Tree(ref tree) | TokenStreamKind::JointTree(ref tree) + if n == 0 => return Ok(tree.clone()), + TokenStreamKind::Tree(..) | TokenStreamKind::JointTree(..) => n - 1, TokenStreamKind::Stream(ref stream) => match look_ahead(stream, n) { Ok(tree) => return Ok(tree), Err(n) => n, @@ -313,13 +456,15 @@ impl Cursor { _ => n, }; } - Err(n) } match self.0 { - CursorKind::Empty | CursorKind::Tree(_, true) => Err(n), - CursorKind::Tree(ref tree, false) => look_ahead(&[tree.clone().into()], n), + CursorKind::Empty | + CursorKind::Tree(_, true) | + CursorKind::JointTree(_, true) => Err(n), + CursorKind::Tree(ref tree, false) | + CursorKind::JointTree(ref tree, false) => look_ahead(&[tree.clone().into()], n), CursorKind::Stream(ref cursor) => { look_ahead(&cursor.stream[cursor.index ..], n).or_else(|mut n| { for &(ref stream, index) in cursor.stack.iter().rev() { @@ -347,6 +492,7 @@ impl From for ThinTokenStream { ThinTokenStream(match stream.kind { TokenStreamKind::Empty => None, TokenStreamKind::Tree(tree) => Some(RcSlice::new(vec![tree.into()])), + TokenStreamKind::JointTree(tree) => Some(RcSlice::new(vec![tree.joint()])), TokenStreamKind::Stream(stream) => Some(stream), }) } diff --git a/src/libsyntax/util/parser_testing.rs b/src/libsyntax/util/parser_testing.rs index 2727ab79eb..d993ba14a4 100644 --- a/src/libsyntax/util/parser_testing.rs +++ b/src/libsyntax/util/parser_testing.rs @@ -20,7 +20,7 @@ use std::iter::Peekable; /// Map a string to tts, using a made-up filename: pub fn string_to_stream(source_str: String) -> TokenStream { let ps = ParseSess::new(FilePathMapping::empty()); - filemap_to_stream(&ps, ps.codemap().new_filemap("bogofile".to_string(), source_str)) + filemap_to_stream(&ps, ps.codemap().new_filemap("bogofile".to_string(), source_str), None) } /// Map string to parser (via tts) diff --git a/src/libsyntax/util/rc_slice.rs b/src/libsyntax/util/rc_slice.rs index 2d9fd7aa87..d6939d7112 100644 --- a/src/libsyntax/util/rc_slice.rs +++ b/src/libsyntax/util/rc_slice.rs @@ -9,7 +9,7 @@ // except according to those terms. use std::fmt; -use std::ops::Deref; +use std::ops::{Deref, Range}; use std::rc::Rc; use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult, @@ -30,6 +30,14 @@ impl RcSlice { data: Rc::new(vec.into_boxed_slice()), } } + + pub fn sub_slice(&self, range: Range) -> Self { + RcSlice { + data: self.data.clone(), + offset: self.offset + range.start as u32, + len: (range.end - range.start) as u32, + } + } } impl Deref for RcSlice { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 18a0949af0..f4ac7e341c 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -674,9 +674,8 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { visitor.visit_expr(callee_expression); walk_list!(visitor, visit_expr, arguments); } - ExprKind::MethodCall(ref ident, ref types, ref arguments) => { - visitor.visit_ident(ident.span, ident.node); - walk_list!(visitor, visit_ty, types); + ExprKind::MethodCall(ref segment, ref arguments) => { + visitor.visit_path_segment(expression.span, segment); walk_list!(visitor, visit_expr, arguments); } ExprKind::Binary(_, ref left_expression, ref right_expression) => { diff --git a/src/libsyntax_ext/compile_error.rs b/src/libsyntax_ext/compile_error.rs new file mode 100644 index 0000000000..7bc7afba63 --- /dev/null +++ b/src/libsyntax_ext/compile_error.rs @@ -0,0 +1,30 @@ +// 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. +// +// 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 compiler code necessary to support the compile_error! extension. + +use syntax::ext::base::*; +use syntax::ext::base; +use syntax_pos::Span; +use syntax::tokenstream; + +pub fn expand_compile_error<'cx>(cx: &'cx mut ExtCtxt, + sp: Span, + tts: &[tokenstream::TokenTree]) + -> Box { + let var = match get_single_str_from_tts(cx, sp, tts, "compile_error!") { + None => return DummyResult::expr(sp), + Some(v) => v, + }; + + cx.span_err(sp, &var); + + DummyResult::any(sp) +} diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs index dc4b8eb24c..6f4c112acb 100644 --- a/src/libsyntax_ext/concat_idents.rs +++ b/src/libsyntax_ext/concat_idents.rs @@ -15,6 +15,8 @@ use syntax::feature_gate; use syntax::parse::token; use syntax::ptr::P; use syntax_pos::Span; +use syntax_pos::symbol::Symbol; +use syntax_pos::hygiene::SyntaxContext; use syntax::tokenstream::TokenTree; pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, @@ -50,7 +52,10 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, } } } - let res = ast::Ident::from_str(&res_str); + let res = ast::Ident { + name: Symbol::intern(&res_str), + ctxt: SyntaxContext::empty().apply_mark(cx.current_expansion.mark), + }; struct Result { ident: ast::Ident, diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs index 1993d6ebe5..35a2a2513f 100644 --- a/src/libsyntax_ext/deriving/clone.rs +++ b/src/libsyntax_ext/deriving/clone.rs @@ -167,7 +167,7 @@ fn cs_clone(name: &str, all_fields = af; vdata = vdata_; } - EnumMatching(_, variant, ref af) => { + EnumMatching(.., variant, ref af) => { ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.node.name]); all_fields = af; vdata = &variant.node.data; diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs index b01ef65e5f..fa5537b5d8 100644 --- a/src/libsyntax_ext/deriving/custom.rs +++ b/src/libsyntax_ext/deriving/custom.rs @@ -16,7 +16,6 @@ use syntax::ast::{self, ItemKind, Attribute, Mac}; use syntax::attr::{mark_used, mark_known}; use syntax::codemap::Span; use syntax::ext::base::*; -use syntax::fold::Folder; use syntax::visit::Visitor; struct MarkAttrs<'a>(&'a [ast::Name]); @@ -75,7 +74,7 @@ impl MultiItemModifier for ProcMacroDerive { MarkAttrs(&self.attrs).visit_item(&item); let input = __internal::new_token_stream(ecx.resolver.eliminate_crate_var(item.clone())); - let res = __internal::set_parse_sess(&ecx.parse_sess, || { + let res = __internal::set_sess(ecx, || { let inner = self.inner; panic::catch_unwind(panic::AssertUnwindSafe(|| inner(input))) }); @@ -97,9 +96,9 @@ impl MultiItemModifier for ProcMacroDerive { } }; - let new_items = __internal::set_parse_sess(&ecx.parse_sess, || { + __internal::set_sess(ecx, || { match __internal::token_stream_parse_items(stream) { - Ok(new_items) => new_items, + Ok(new_items) => new_items.into_iter().map(Annotatable::Item).collect(), Err(_) => { // FIXME: handle this better let msg = "proc-macro derive produced unparseable tokens"; @@ -107,12 +106,6 @@ impl MultiItemModifier for ProcMacroDerive { panic!(FatalError); } } - }); - - // Reassign spans of all expanded items to the input `item` - // for better errors here. - new_items.into_iter().map(|item| { - Annotatable::Item(ChangeSpan { span: span }.fold_item(item).expect_one("")) - }).collect() + }) } } diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs index ec4cb81596..38ed596098 100644 --- a/src/libsyntax_ext/deriving/debug.rs +++ b/src/libsyntax_ext/deriving/debug.rs @@ -60,7 +60,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P (substr.type_ident, vdata.is_struct()), - EnumMatching(_, v, _) => (v.node.name, v.node.data.is_struct()), + EnumMatching(_, _, v, _) => (v.node.name, v.node.data.is_struct()), EnumNonMatchingCollapsed(..) | StaticStruct(..) | StaticEnum(..) => cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`"), diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs index 9d155c22ad..1e19cd9941 100644 --- a/src/libsyntax_ext/deriving/encodable.rs +++ b/src/libsyntax_ext/deriving/encodable.rs @@ -14,14 +14,15 @@ //! //! For example, a type like: //! -//! ```ignore +//! ``` //! #[derive(Encodable, Decodable)] //! struct Node { id: usize } //! ``` //! //! would generate two implementations like: //! -//! ```ignore +//! ``` +//! # struct Node { id: usize } //! impl, E> Encodable for Node { //! fn encode(&self, s: &mut S) -> Result<(), E> { //! s.emit_struct("Node", 1, |this| { @@ -48,14 +49,17 @@ //! Other interesting scenarios are when the item has type parameters or //! references other non-built-in types. A type definition like: //! -//! ```ignore +//! ``` +//! # #[derive(Encodable, Decodable)] struct Span; //! #[derive(Encodable, Decodable)] //! struct Spanned { node: T, span: Span } //! ``` //! //! would yield functions like: //! -//! ```ignore +//! ``` +//! # #[derive(Encodable, Decodable)] struct Span; +//! # struct Spanned { node: T, span: Span } //! impl< //! S: Encoder, //! E, @@ -233,7 +237,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, blk]) } - EnumMatching(idx, variant, ref fields) => { + EnumMatching(idx, _, variant, ref fields) => { // We're not generating an AST that the borrow checker is expecting, // so we need to generate a unique local variable to take the // mutable loan out on, otherwise we get conflicts which don't diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index be7883cad5..4acd65bbf8 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -305,10 +305,10 @@ pub enum StaticFields { /// A summary of the possible sets of fields. pub enum SubstructureFields<'a> { Struct(&'a ast::VariantData, Vec>), - /// Matching variants of the enum: variant index, ast::Variant, + /// Matching variants of the enum: variant index, variant count, ast::Variant, /// fields: the field name is only non-`None` in the case of a struct /// variant. - EnumMatching(usize, &'a ast::Variant, Vec>), + EnumMatching(usize, usize, &'a ast::Variant, Vec>), /// Non-matching variants of the enum, but with all state hidden from /// the consequent code. The first component holds `Ident`s for all of @@ -456,7 +456,7 @@ impl<'a> TraitDef<'a> { /// Given that we are deriving a trait `DerivedTrait` for a type like: /// - /// ```ignore + /// ```ignore (only-for-syntax-highlight) /// struct Struct<'a, ..., 'z, A, B: DeclaredTrait, C, ..., Z> where C: WhereTrait { /// a: A, /// b: B::Item, @@ -469,7 +469,7 @@ impl<'a> TraitDef<'a> { /// /// create an impl like: /// - /// ```ignore + /// ```ignore (only-for-syntax-highlight) /// impl<'a, ..., 'z, A, B: DeclaredTrait, C, ... Z> where /// C: WhereTrait, /// A: DerivedTrait + B1 + ... + BN, @@ -933,8 +933,9 @@ impl<'a> MethodDef<'a> { } } - /// ```ignore + /// ``` /// #[derive(PartialEq)] + /// # struct Dummy; /// struct A { x: i32, y: i32 } /// /// // equivalent to: @@ -1040,8 +1041,9 @@ impl<'a> MethodDef<'a> { &StaticStruct(struct_def, summary)) } - /// ```ignore + /// ``` /// #[derive(PartialEq)] + /// # struct Dummy; /// enum A { /// A1, /// A2(i32) @@ -1250,7 +1252,7 @@ impl<'a> MethodDef<'a> { // expressions for referencing every field of every // Self arg, assuming all are instances of VariantK. // Build up code associated with such a case. - let substructure = EnumMatching(index, variant, field_tuples); + let substructure = EnumMatching(index, variants.len(), variant, field_tuples); let arm_expr = self.call_substructure_method(cx, trait_, type_ident, @@ -1267,12 +1269,13 @@ impl<'a> MethodDef<'a> { // We need a default case that handles the fieldless variants. // The index and actual variant aren't meaningful in this case, // so just use whatever + let substructure = EnumMatching(0, variants.len(), v, Vec::new()); Some(self.call_substructure_method(cx, trait_, type_ident, &self_args[..], nonself_args, - &EnumMatching(0, v, Vec::new()))) + &substructure)) } _ if variants.len() > 1 && self_args.len() > 1 => { // Since we know that all the arguments will match if we reach @@ -1624,7 +1627,7 @@ pub fn cs_fold(use_foldl: bool, /// Call the method that is being derived on all the fields, and then /// process the collected results. i.e. /// -/// ```ignore +/// ```ignore (only-for-syntax-highlight) /// f(cx, span, vec![self_1.method(__arg_1_1, __arg_2_1), /// self_2.method(__arg_1_2, __arg_2_2)]) /// ``` diff --git a/src/libsyntax_ext/deriving/hash.rs b/src/libsyntax_ext/deriving/hash.rs index 97d7f2ce80..a341c21d0a 100644 --- a/src/libsyntax_ext/deriving/hash.rs +++ b/src/libsyntax_ext/deriving/hash.rs @@ -81,7 +81,7 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) let mut stmts = Vec::new(); let fields = match *substr.fields { - Struct(_, ref fs) => fs, + Struct(_, ref fs) | EnumMatching(_, 1, .., ref fs) => fs, EnumMatching(.., ref fs) => { let variant_value = deriving::call_intrinsic(cx, trait_span, diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 24c1dfe289..144d1930df 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -20,7 +20,7 @@ use syntax::ext::build::AstBuilder; use syntax::parse::token; use syntax::ptr::P; use syntax::symbol::{Symbol, keywords}; -use syntax_pos::{Span, DUMMY_SP}; +use syntax_pos::Span; use syntax::tokenstream; use std::collections::{HashMap, HashSet}; @@ -117,7 +117,8 @@ struct Context<'a, 'b: 'a> { /// expressions. /// /// If parsing succeeds, the return value is: -/// ```ignore +/// +/// ```text /// Some((fmtstr, parsed arguments, index map for named arguments)) /// ``` fn parse_args(ecx: &mut ExtCtxt, @@ -557,7 +558,9 @@ impl<'a, 'b> Context<'a, 'b> { // passed to this function. for (i, e) in self.args.into_iter().enumerate() { let name = self.ecx.ident_of(&format!("__arg{}", i)); - pats.push(self.ecx.pat_ident(DUMMY_SP, name)); + let span = + Span { ctxt: e.span.ctxt.apply_mark(self.ecx.current_expansion.mark), ..e.span }; + pats.push(self.ecx.pat_ident(span, name)); for ref arg_ty in self.arg_unique_types[i].iter() { locals.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty, name)); } @@ -671,10 +674,10 @@ impl<'a, 'b> Context<'a, 'b> { } pub fn expand_format_args<'cx>(ecx: &'cx mut ExtCtxt, - sp: Span, + mut sp: Span, tts: &[tokenstream::TokenTree]) -> Box { - + sp.ctxt = sp.ctxt.apply_mark(ecx.current_expansion.mark); match parse_args(ecx, sp, tts) { Some((efmt, args, names)) => { MacEager::expr(expand_preparsed_format_args(ecx, sp, efmt, args, names)) @@ -695,7 +698,8 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, // `ArgumentType` does not derive `Clone`. let arg_types: Vec<_> = (0..args.len()).map(|_| Vec::new()).collect(); let arg_unique_types: Vec<_> = (0..args.len()).map(|_| Vec::new()).collect(); - let macsp = ecx.call_site(); + let mut macsp = ecx.call_site(); + macsp.ctxt = macsp.ctxt.apply_mark(ecx.current_expansion.mark); let msg = "format argument must be a string literal."; let fmt = match expr_to_spanned_string(ecx, efmt, msg) { Some(fmt) => fmt, diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 60f5d24ac9..5eab81dd28 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -20,10 +20,6 @@ #![feature(proc_macro_internals)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] - extern crate fmt_macros; extern crate log; #[macro_use] @@ -34,6 +30,7 @@ extern crate rustc_errors as errors; mod asm; mod cfg; +mod compile_error; mod concat; mod concat_idents; mod env; @@ -92,6 +89,7 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, use syntax::ext::source_util::*; register! { line: expand_line, + __rust_unstable_column: expand_column_gated, column: expand_column, file: expand_file, stringify: expand_stringify, @@ -109,6 +107,7 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, option_env: env::expand_option_env, log_syntax: log_syntax::expand_syntax_ext, trace_macros: trace_macros::expand_trace_macros, + compile_error: compile_error::expand_compile_error, } // format_args uses `unstable` things internally. diff --git a/src/libsyntax_ext/proc_macro_impl.rs b/src/libsyntax_ext/proc_macro_impl.rs index f60e5824db..5fcedbf50c 100644 --- a/src/libsyntax_ext/proc_macro_impl.rs +++ b/src/libsyntax_ext/proc_macro_impl.rs @@ -34,7 +34,7 @@ impl base::AttrProcMacro for AttrProcMacro { let annotation = __internal::token_stream_wrap(annotation); let annotated = __internal::token_stream_wrap(annotated); - let res = __internal::set_parse_sess(&ecx.parse_sess, || { + let res = __internal::set_sess(ecx, || { panic::catch_unwind(panic::AssertUnwindSafe(|| (self.inner)(annotation, annotated))) }); @@ -69,7 +69,7 @@ impl base::ProcMacro for BangProcMacro { -> TokenStream { let input = __internal::token_stream_wrap(input); - let res = __internal::set_parse_sess(&ecx.parse_sess, || { + let res = __internal::set_sess(ecx, || { panic::catch_unwind(panic::AssertUnwindSafe(|| (self.inner)(input))) }); diff --git a/src/libsyntax_pos/Cargo.toml b/src/libsyntax_pos/Cargo.toml index 760aaa8a95..dd8129bab5 100644 --- a/src/libsyntax_pos/Cargo.toml +++ b/src/libsyntax_pos/Cargo.toml @@ -10,3 +10,4 @@ crate-type = ["dylib"] [dependencies] serialize = { path = "../libserialize" } +rustc_data_structures = { path = "../librustc_data_structures" } diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index f2ccc3f051..804b91ab09 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -144,24 +144,18 @@ impl SyntaxContext { pub fn apply_mark(self, mark: Mark) -> SyntaxContext { HygieneData::with(|data| { let syntax_contexts = &mut data.syntax_contexts; - let ctxt_data = syntax_contexts[self.0 as usize]; - if mark == ctxt_data.outer_mark { - return ctxt_data.prev_ctxt; - } - - let modern = if data.marks[mark.0 as usize].modern { - *data.markings.entry((ctxt_data.modern, mark)).or_insert_with(|| { - let modern = SyntaxContext(syntax_contexts.len() as u32); + let mut modern = syntax_contexts[self.0 as usize].modern; + if data.marks[mark.0 as usize].modern { + modern = *data.markings.entry((modern, mark)).or_insert_with(|| { + let len = syntax_contexts.len() as u32; syntax_contexts.push(SyntaxContextData { outer_mark: mark, - prev_ctxt: ctxt_data.modern, - modern: modern, + prev_ctxt: modern, + modern: SyntaxContext(len), }); - modern - }) - } else { - ctxt_data.modern - }; + SyntaxContext(len) + }); + } *data.markings.entry((self, mark)).or_insert_with(|| { syntax_contexts.push(SyntaxContextData { diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 25f74aeecf..fc9bd7d762 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -24,20 +24,22 @@ #![feature(const_fn)] #![feature(custom_attribute)] +#![feature(i128_type)] #![feature(optin_builtin_traits)] #![allow(unused_attributes)] #![feature(specialization)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(rustc_private))] -#![cfg_attr(stage0, feature(staged_api))] - +use std::borrow::Cow; use std::cell::{Cell, RefCell}; +use std::cmp; +use std::fmt; +use std::hash::Hasher; use std::ops::{Add, Sub}; use std::rc::Rc; -use std::cmp; -use std::fmt; +use rustc_data_structures::stable_hasher::StableHasher; + +extern crate rustc_data_structures; use serialize::{Encodable, Decodable, Encoder, Decoder}; @@ -184,7 +186,7 @@ impl Span { pub fn to(self, end: Span) -> Span { // FIXME(jseyfried): self.ctxt should always equal end.ctxt here (c.f. issue #23480) - if end.ctxt == SyntaxContext::empty() { + if self.ctxt == SyntaxContext::empty() { Span { lo: self.lo, ..end } } else { Span { hi: end.hi, ..self } @@ -369,6 +371,35 @@ pub struct MultiByteChar { pub bytes: usize, } +/// The state of the lazy external source loading mechanism of a FileMap. +#[derive(PartialEq, Eq, Clone)] +pub enum ExternalSource { + /// The external source has been loaded already. + Present(String), + /// No attempt has been made to load the external source. + AbsentOk, + /// A failed attempt has been made to load the external source. + AbsentErr, + /// No external source has to be loaded, since the FileMap represents a local crate. + Unneeded, +} + +impl ExternalSource { + pub fn is_absent(&self) -> bool { + match *self { + ExternalSource::Present(_) => false, + _ => true, + } + } + + pub fn get_source(&self) -> Option<&str> { + match *self { + ExternalSource::Present(ref src) => Some(src), + _ => None, + } + } +} + /// A single source in the CodeMap. #[derive(Clone)] pub struct FileMap { @@ -382,6 +413,11 @@ pub struct FileMap { pub crate_of_origin: u32, /// The complete source code pub src: Option>, + /// The source code's hash + pub src_hash: u128, + /// The external source code (used for external crates, which will have a `None` + /// value as `self.src`. + pub external_src: RefCell, /// The start position of this source in the CodeMap pub start_pos: BytePos, /// The end position of this source in the CodeMap @@ -394,9 +430,10 @@ pub struct FileMap { impl Encodable for FileMap { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_struct("FileMap", 6, |s| { + s.emit_struct("FileMap", 7, |s| { s.emit_struct_field("name", 0, |s| self.name.encode(s))?; s.emit_struct_field("name_was_remapped", 1, |s| self.name_was_remapped.encode(s))?; + s.emit_struct_field("src_hash", 6, |s| self.src_hash.encode(s))?; s.emit_struct_field("start_pos", 2, |s| self.start_pos.encode(s))?; s.emit_struct_field("end_pos", 3, |s| self.end_pos.encode(s))?; s.emit_struct_field("lines", 4, |s| { @@ -459,7 +496,10 @@ impl Decodable for FileMap { let name: String = d.read_struct_field("name", 0, |d| Decodable::decode(d))?; let name_was_remapped: bool = d.read_struct_field("name_was_remapped", 1, |d| Decodable::decode(d))?; - let start_pos: BytePos = d.read_struct_field("start_pos", 2, |d| Decodable::decode(d))?; + let src_hash: u128 = + d.read_struct_field("src_hash", 6, |d| Decodable::decode(d))?; + let start_pos: BytePos = + d.read_struct_field("start_pos", 2, |d| Decodable::decode(d))?; let end_pos: BytePos = d.read_struct_field("end_pos", 3, |d| Decodable::decode(d))?; let lines: Vec = d.read_struct_field("lines", 4, |d| { let num_lines: u32 = Decodable::decode(d)?; @@ -501,6 +541,8 @@ impl Decodable for FileMap { start_pos: start_pos, end_pos: end_pos, src: None, + src_hash: src_hash, + external_src: RefCell::new(ExternalSource::AbsentOk), lines: RefCell::new(lines), multibyte_chars: RefCell::new(multibyte_chars) }) @@ -515,6 +557,32 @@ impl fmt::Debug for FileMap { } impl FileMap { + pub fn new(name: FileName, + name_was_remapped: bool, + mut src: String, + start_pos: BytePos) -> FileMap { + remove_bom(&mut src); + + let mut hasher: StableHasher = StableHasher::new(); + hasher.write(src.as_bytes()); + let src_hash = hasher.finish(); + + let end_pos = start_pos.to_usize() + src.len(); + + FileMap { + name: name, + name_was_remapped: name_was_remapped, + crate_of_origin: 0, + src: Some(Rc::new(src)), + src_hash: src_hash, + external_src: RefCell::new(ExternalSource::Unneeded), + start_pos: start_pos, + end_pos: Pos::from_usize(end_pos), + lines: RefCell::new(Vec::new()), + multibyte_chars: RefCell::new(Vec::new()), + } + } + /// EFFECT: register a start-of-line offset in the /// table of line-beginnings. /// UNCHECKED INVARIANT: these offsets must be added in the right @@ -532,26 +600,63 @@ impl FileMap { lines.push(pos); } - /// get a line from the list of pre-computed line-beginnings. - /// line-number here is 0-based. - pub fn get_line(&self, line_number: usize) -> Option<&str> { - match self.src { - Some(ref src) => { - let lines = self.lines.borrow(); - lines.get(line_number).map(|&line| { - let begin: BytePos = line - self.start_pos; - let begin = begin.to_usize(); - // We can't use `lines.get(line_number+1)` because we might - // be parsing when we call this function and thus the current - // line is the last one we have line info for. - let slice = &src[begin..]; - match slice.find('\n') { - Some(e) => &slice[..e], - None => slice - } - }) + /// Add externally loaded source. + /// If the hash of the input doesn't match or no input is supplied via None, + /// it is interpreted as an error and the corresponding enum variant is set. + /// The return value signifies whether some kind of source is present. + pub fn add_external_src(&self, get_src: F) -> bool + where F: FnOnce() -> Option + { + if *self.external_src.borrow() == ExternalSource::AbsentOk { + let src = get_src(); + let mut external_src = self.external_src.borrow_mut(); + if let Some(src) = src { + let mut hasher: StableHasher = StableHasher::new(); + hasher.write(src.as_bytes()); + + if hasher.finish() == self.src_hash { + *external_src = ExternalSource::Present(src); + return true; + } + } else { + *external_src = ExternalSource::AbsentErr; } - None => None + + false + } else { + self.src.is_some() || self.external_src.borrow().get_source().is_some() + } + } + + /// Get a line from the list of pre-computed line-beginnings. + /// The line number here is 0-based. + pub fn get_line(&self, line_number: usize) -> Option> { + fn get_until_newline(src: &str, begin: usize) -> &str { + // We can't use `lines.get(line_number+1)` because we might + // be parsing when we call this function and thus the current + // line is the last one we have line info for. + let slice = &src[begin..]; + match slice.find('\n') { + Some(e) => &slice[..e], + None => slice + } + } + + let lines = self.lines.borrow(); + let line = if let Some(line) = lines.get(line_number) { + line + } else { + return None; + }; + let begin: BytePos = *line - self.start_pos; + let begin = begin.to_usize(); + + if let Some(ref src) = self.src { + Some(Cow::from(get_until_newline(src, begin))) + } else if let Some(src) = self.external_src.borrow().get_source() { + Some(Cow::Owned(String::from(get_until_newline(src, begin)))) + } else { + None } } @@ -614,6 +719,13 @@ impl FileMap { } } +/// Remove utf-8 BOM if any. +fn remove_bom(src: &mut String) { + if src.starts_with("\u{feff}") { + src.drain(..3); + } +} + // _____________________________________________________________________________ // Pos, BytePos, CharPos // diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 73c0256f2c..debac70545 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -81,6 +81,7 @@ pub struct Symbol(u32); // The interner in thread-local, so `Symbol` shouldn't move between threads. impl !Send for Symbol { } +impl !Sync for Symbol { } impl Symbol { /// Maps a string to its interned representation. @@ -236,76 +237,76 @@ macro_rules! declare_keywords {( // NB: leaving holes in the ident table is bad! a different ident will get // interned with the id from the hole, but it will be between the min and max // of the reserved words, and thus tagged as "reserved". -// After modifying this list adjust `is_strict_keyword`/`is_reserved_keyword`, +// After modifying this list adjust `is_special_ident`, `is_used_keyword`/`is_unused_keyword`, // this should be rarely necessary though if the keywords are kept in alphabetic order. declare_keywords! { - // Invalid identifier + // Special reserved identifiers used internally for elided lifetimes, + // unnamed method parameters, crate root module, error recovery etc. (0, Invalid, "") - - // Strict keywords used in the language. - (1, As, "as") - (2, Box, "box") - (3, Break, "break") - (4, Const, "const") - (5, Continue, "continue") - (6, Crate, "crate") - (7, Else, "else") - (8, Enum, "enum") - (9, Extern, "extern") - (10, False, "false") - (11, Fn, "fn") - (12, For, "for") - (13, If, "if") - (14, Impl, "impl") - (15, In, "in") - (16, Let, "let") - (17, Loop, "loop") - (18, Match, "match") - (19, Mod, "mod") - (20, Move, "move") - (21, Mut, "mut") - (22, Pub, "pub") - (23, Ref, "ref") - (24, Return, "return") - (25, SelfValue, "self") - (26, SelfType, "Self") - (27, Static, "static") - (28, Struct, "struct") - (29, Super, "super") - (30, Trait, "trait") - (31, True, "true") - (32, Type, "type") - (33, Unsafe, "unsafe") - (34, Use, "use") - (35, Where, "where") - (36, While, "while") + (1, CrateRoot, "{{root}}") + (2, DollarCrate, "$crate") + + // Keywords used in the language. + (3, As, "as") + (4, Box, "box") + (5, Break, "break") + (6, Const, "const") + (7, Continue, "continue") + (8, Crate, "crate") + (9, Else, "else") + (10, Enum, "enum") + (11, Extern, "extern") + (12, False, "false") + (13, Fn, "fn") + (14, For, "for") + (15, If, "if") + (16, Impl, "impl") + (17, In, "in") + (18, Let, "let") + (19, Loop, "loop") + (20, Match, "match") + (21, Mod, "mod") + (22, Move, "move") + (23, Mut, "mut") + (24, Pub, "pub") + (25, Ref, "ref") + (26, Return, "return") + (27, SelfValue, "self") + (28, SelfType, "Self") + (29, Static, "static") + (30, Struct, "struct") + (31, Super, "super") + (32, Trait, "trait") + (33, True, "true") + (34, Type, "type") + (35, Unsafe, "unsafe") + (36, Use, "use") + (37, Where, "where") + (38, While, "while") // Keywords reserved for future use. - (37, Abstract, "abstract") - (38, Alignof, "alignof") - (39, Become, "become") - (40, Do, "do") - (41, Final, "final") - (42, Macro, "macro") - (43, Offsetof, "offsetof") - (44, Override, "override") - (45, Priv, "priv") - (46, Proc, "proc") - (47, Pure, "pure") - (48, Sizeof, "sizeof") - (49, Typeof, "typeof") - (50, Unsized, "unsized") - (51, Virtual, "virtual") - (52, Yield, "yield") + (39, Abstract, "abstract") + (40, Alignof, "alignof") + (41, Become, "become") + (42, Do, "do") + (43, Final, "final") + (44, Macro, "macro") + (45, Offsetof, "offsetof") + (46, Override, "override") + (47, Priv, "priv") + (48, Proc, "proc") + (49, Pure, "pure") + (50, Sizeof, "sizeof") + (51, Typeof, "typeof") + (52, Unsized, "unsized") + (53, Virtual, "virtual") + (54, Yield, "yield") // Weak keywords, have special meaning only in specific contexts. - (53, Default, "default") - (54, StaticLifetime, "'static") - (55, Union, "union") - (56, Catch, "catch") - - // A virtual keyword that resolves to the crate root when used in a lexical scope. - (57, CrateRoot, "{{root}}") + (55, Default, "default") + (56, StaticLifetime, "'static") + (57, Union, "union") + (58, Catch, "catch") } // If an interner exists in TLS, return it. Otherwise, prepare a fresh one. diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index eb0ee6ba15..753dfbe4ce 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -57,9 +57,6 @@ #![feature(custom_attribute)] #![allow(unused_attributes)] -#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] -#![cfg_attr(stage0, feature(staged_api))] - use std::io::prelude::*; pub use terminfo::TerminfoTerminal; diff --git a/src/libtest/Cargo.toml b/src/libtest/Cargo.toml index ecbd5a9c0f..ec77f95338 100644 --- a/src/libtest/Cargo.toml +++ b/src/libtest/Cargo.toml @@ -9,5 +9,5 @@ path = "lib.rs" crate-type = ["dylib", "rlib"] [dependencies] -getopts = { path = "../libgetopts" } +getopts = "0.2" term = { path = "../libterm" } diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index ef048ac8ca..bf71b11fc7 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -16,7 +16,7 @@ //! benchmarks themselves) should be done via the `#[test]` and //! `#[bench]` attributes. //! -//! See the [Testing Chapter](../book/testing.html) of the book for more details. +//! See the [Testing Chapter](../book/first-edition/testing.html) of the book for more details. // Currently, not much of this is meant for users. It is intended to // support the simplest interface possible for representing and @@ -35,9 +35,7 @@ #![feature(asm)] #![feature(libc)] -#![feature(rustc_private)] #![feature(set_stdio)] -#![feature(staged_api)] #![feature(panic_unwind)] extern crate getopts; @@ -212,6 +210,7 @@ pub struct TestDesc { pub name: TestName, pub ignore: bool, pub should_panic: ShouldPanic, + pub allow_fail: bool, } #[derive(Clone)] @@ -372,30 +371,31 @@ impl TestOpts { /// Result of parsing the options. pub type OptRes = Result; -#[cfg_attr(rustfmt, rustfmt_skip)] -fn optgroups() -> Vec { - vec![getopts::optflag("", "ignored", "Run ignored tests"), - getopts::optflag("", "test", "Run tests and not benchmarks"), - getopts::optflag("", "bench", "Run benchmarks instead of tests"), - getopts::optflag("", "list", "List all tests and benchmarks"), - getopts::optflag("h", "help", "Display this message (longer with --help)"), - getopts::optopt("", "logfile", "Write logs to the specified file instead \ - of stdout", "PATH"), - getopts::optflag("", "nocapture", "don't capture stdout/stderr of each \ - task, allow printing directly"), - getopts::optopt("", "test-threads", "Number of threads used for running tests \ - in parallel", "n_threads"), - getopts::optmulti("", "skip", "Skip tests whose names contain FILTER (this flag can \ - be used multiple times)","FILTER"), - getopts::optflag("q", "quiet", "Display one character per test instead of one line"), - getopts::optflag("", "exact", "Exactly match filters rather than by substring"), - getopts::optopt("", "color", "Configure coloring of output: +fn optgroups() -> getopts::Options { + let mut opts = getopts::Options::new(); + opts.optflag("", "ignored", "Run ignored tests") + .optflag("", "test", "Run tests and not benchmarks") + .optflag("", "bench", "Run benchmarks instead of tests") + .optflag("", "list", "List all tests and benchmarks") + .optflag("h", "help", "Display this message (longer with --help)") + .optopt("", "logfile", "Write logs to the specified file instead \ + of stdout", "PATH") + .optflag("", "nocapture", "don't capture stdout/stderr of each \ + task, allow printing directly") + .optopt("", "test-threads", "Number of threads used for running tests \ + in parallel", "n_threads") + .optmulti("", "skip", "Skip tests whose names contain FILTER (this flag can \ + be used multiple times)","FILTER") + .optflag("q", "quiet", "Display one character per test instead of one line") + .optflag("", "exact", "Exactly match filters rather than by substring") + .optopt("", "color", "Configure coloring of output: auto = colorize if stdout is a tty and tests are run on serially (default); always = always colorize output; - never = never colorize output;", "auto|always|never")] + never = never colorize output;", "auto|always|never"); + return opts } -fn usage(binary: &str) { +fn usage(binary: &str, options: &getopts::Options) { let message = format!("Usage: {} [OPTIONS] [FILTER]", binary); println!(r#"{usage} @@ -424,19 +424,19 @@ Test Attributes: test, then the test runner will ignore these tests during normal test runs. Running with --ignored will run these tests."#, - usage = getopts::usage(&message, &optgroups())); + usage = options.usage(&message)); } // Parses command line arguments into test options pub fn parse_opts(args: &[String]) -> Option { - let args_ = &args[1..]; - let matches = match getopts::getopts(args_, &optgroups()) { + let opts = optgroups(); + let matches = match opts.parse(&args[1..]) { Ok(m) => m, Err(f) => return Some(Err(f.to_string())), }; if matches.opt_present("h") { - usage(&args[0]); + usage(&args[0], &opts); return None; } @@ -522,6 +522,7 @@ pub enum TestResult { TrFailed, TrFailedMsg(String), TrIgnored, + TrAllowedFail, TrMetrics(MetricMap), TrBench(BenchSamples), } @@ -542,6 +543,7 @@ struct ConsoleTestState { passed: usize, failed: usize, ignored: usize, + allowed_fail: usize, filtered_out: usize, measured: usize, metrics: MetricMap, @@ -571,6 +573,7 @@ impl ConsoleTestState { passed: 0, failed: 0, ignored: 0, + allowed_fail: 0, filtered_out: 0, measured: 0, metrics: MetricMap::new(), @@ -593,6 +596,10 @@ impl ConsoleTestState { self.write_short_result("ignored", "i", term::color::YELLOW) } + pub fn write_allowed_fail(&mut self) -> io::Result<()> { + self.write_short_result("FAILED (allowed)", "a", term::color::YELLOW) + } + pub fn write_metric(&mut self) -> io::Result<()> { self.write_pretty("metric", term::color::CYAN) } @@ -668,6 +675,7 @@ impl ConsoleTestState { TrOk => self.write_ok(), TrFailed | TrFailedMsg(_) => self.write_failed(), TrIgnored => self.write_ignored(), + TrAllowedFail => self.write_allowed_fail(), TrMetrics(ref mm) => { self.write_metric()?; self.write_plain(&format!(": {}\n", mm.fmt_metrics())) @@ -701,6 +709,7 @@ impl ConsoleTestState { TrFailed => "failed".to_owned(), TrFailedMsg(ref msg) => format!("failed: {}", msg), TrIgnored => "ignored".to_owned(), + TrAllowedFail => "failed (allowed)".to_owned(), TrMetrics(ref mm) => mm.fmt_metrics(), TrBench(ref bs) => fmt_bench_samples(bs), }, @@ -760,7 +769,8 @@ impl ConsoleTestState { } pub fn write_run_finish(&mut self) -> io::Result { - assert!(self.passed + self.failed + self.ignored + self.measured == self.total); + assert!(self.passed + self.failed + self.ignored + self.measured + + self.allowed_fail == self.total); if self.options.display_output { self.write_outputs()?; @@ -777,12 +787,24 @@ impl ConsoleTestState { } else { self.write_pretty("FAILED", term::color::RED)?; } - let s = format!(". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n", - self.passed, - self.failed, - self.ignored, - self.measured, - self.filtered_out); + let s = if self.allowed_fail > 0 { + format!( + ". {} passed; {} failed ({} allowed); {} ignored; {} measured; {} filtered out\n\n", + self.passed, + self.failed + self.allowed_fail, + self.allowed_fail, + self.ignored, + self.measured, + self.filtered_out) + } else { + format!( + ". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n", + self.passed, + self.failed, + self.ignored, + self.measured, + self.filtered_out) + }; self.write_plain(&s)?; return Ok(success); } @@ -890,6 +912,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec) -> io::Resu st.not_failures.push((test, stdout)); } TrIgnored => st.ignored += 1, + TrAllowedFail => st.allowed_fail += 1, TrMetrics(mm) => { let tname = test.name; let MetricMap(mm) = mm; @@ -944,12 +967,14 @@ fn should_sort_failures_before_printing_them() { name: StaticTestName("a"), ignore: false, should_panic: ShouldPanic::No, + allow_fail: false, }; let test_b = TestDesc { name: StaticTestName("b"), ignore: false, should_panic: ShouldPanic::No, + allow_fail: false, }; let mut st = ConsoleTestState { @@ -961,6 +986,7 @@ fn should_sort_failures_before_printing_them() { passed: 0, failed: 0, ignored: 0, + allowed_fail: 0, filtered_out: 0, measured: 0, max_name_len: 10, @@ -1470,8 +1496,13 @@ fn calc_result(desc: &TestDesc, task_result: Result<(), Box>) -> Tes .unwrap_or(false) { TrOk } else { - TrFailedMsg(format!("Panic did not include expected string '{}'", msg)) + if desc.allow_fail { + TrAllowedFail + } else { + TrFailedMsg(format!("Panic did not include expected string '{}'", msg)) + } }, + _ if desc.allow_fail => TrAllowedFail, _ => TrFailed, } } @@ -1705,6 +1736,7 @@ mod tests { name: StaticTestName("whatever"), ignore: true, should_panic: ShouldPanic::No, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| f())), }; @@ -1722,6 +1754,7 @@ mod tests { name: StaticTestName("whatever"), ignore: true, should_panic: ShouldPanic::No, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| f())), }; @@ -1741,6 +1774,7 @@ mod tests { name: StaticTestName("whatever"), ignore: false, should_panic: ShouldPanic::Yes, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| f())), }; @@ -1760,6 +1794,7 @@ mod tests { name: StaticTestName("whatever"), ignore: false, should_panic: ShouldPanic::YesWithMessage("error message"), + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| f())), }; @@ -1781,6 +1816,7 @@ mod tests { name: StaticTestName("whatever"), ignore: false, should_panic: ShouldPanic::YesWithMessage(expected), + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| f())), }; @@ -1798,6 +1834,7 @@ mod tests { name: StaticTestName("whatever"), ignore: false, should_panic: ShouldPanic::Yes, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| f())), }; @@ -1831,6 +1868,7 @@ mod tests { name: StaticTestName("1"), ignore: true, should_panic: ShouldPanic::No, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| {})), }, @@ -1839,6 +1877,7 @@ mod tests { name: StaticTestName("2"), ignore: false, should_panic: ShouldPanic::No, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| {})), }]; @@ -1862,6 +1901,7 @@ mod tests { name: StaticTestName(name), ignore: false, should_panic: ShouldPanic::No, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| {})) }) @@ -1943,6 +1983,7 @@ mod tests { name: DynTestName((*name).clone()), ignore: false, should_panic: ShouldPanic::No, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| testfn())), }; diff --git a/src/rt/miniz.c b/src/rt/miniz.c deleted file mode 100644 index 2daca9378a..0000000000 --- a/src/rt/miniz.c +++ /dev/null @@ -1,1890 +0,0 @@ -/* miniz.c v1.14 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing - See "unlicense" statement at the end of this file. - Rich Geldreich , last updated May 20, 2012 - Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt - - Most API's defined in miniz.c are optional. For example, to disable the archive related functions just define - MINIZ_NO_ARCHIVE_APIS, or to get rid of all stdio usage define MINIZ_NO_STDIO (see the list below for more macros). - - * Change History - 5/20/12 v1.14 - MinGW32/64 GCC 4.6.1 compiler fixes: added MZ_FORCEINLINE, #include (thanks fermtect). - 5/19/12 v1.13 - From jason@cornsyrup.org and kelwert@mtu.edu - Fix mz_crc32() so it doesn't compute the wrong CRC-32's when mz_ulong is 64-bit. - Temporarily/locally slammed in "typedef unsigned long mz_ulong" and re-ran a randomized regression test on ~500k files. - Eliminated a bunch of warnings when compiling with GCC 32-bit/64. - Ran all examples, miniz.c, and tinfl.c through MSVC 2008's /analyze (static analysis) option and fixed all warnings (except for the silly - "Use of the comma-operator in a tested expression.." analysis warning, which I purposely use to work around a MSVC compiler warning). - Created 32-bit and 64-bit Codeblocks projects/workspace. Built and tested Linux executables. The codeblocks workspace is compatible with Linux+Win32/x64. - Added miniz_tester solution/project, which is a useful little app derived from LZHAM's tester app that I use as part of the regression test. - Ran miniz.c and tinfl.c through another series of regression testing on ~500,000 files and archives. - Modified example5.c so it purposely disables a bunch of high-level functionality (MINIZ_NO_STDIO, etc.). (Thanks to corysama for the MINIZ_NO_STDIO bug report.) - Fix ftell() usage in examples so they exit with an error on files which are too large (a limitation of the examples, not miniz itself). - 4/12/12 v1.12 - More comments, added low-level example5.c, fixed a couple minor level_and_flags issues in the archive API's. - level_and_flags can now be set to MZ_DEFAULT_COMPRESSION. Thanks to Bruce Dawson for the feedback/bug report. - 5/28/11 v1.11 - Added statement from unlicense.org - 5/27/11 v1.10 - Substantial compressor optimizations: - Level 1 is now ~4x faster than before. The L1 compressor's throughput now varies between 70-110MB/sec. on a - Core i7 (actual throughput varies depending on the type of data, and x64 vs. x86). - Improved baseline L2-L9 compression perf. Also, greatly improved compression perf. issues on some file types. - Refactored the compression code for better readability and maintainability. - Added level 10 compression level (L10 has slightly better ratio than level 9, but could have a potentially large - drop in throughput on some files). - 5/15/11 v1.09 - Initial stable release. - - * Low-level Deflate/Inflate implementation notes: - - Compression: Use the "tdefl" API's. The compressor supports raw, static, and dynamic blocks, lazy or - greedy parsing, match length filtering, RLE-only, and Huffman-only streams. It performs and compresses - approximately as well as zlib. - - Decompression: Use the "tinfl" API's. The entire decompressor is implemented as a single function - coroutine: see tinfl_decompress(). It supports decompression into a 32KB (or larger power of 2) wrapping buffer, or into a memory - block large enough to hold the entire file. - - The low-level tdefl/tinfl API's do not make any use of dynamic memory allocation. - - * Important: For best perf. be sure to customize the below macros for your target platform: - #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 - #define MINIZ_LITTLE_ENDIAN 1 - #define MINIZ_HAS_64BIT_REGISTERS 1 -*/ - -#ifndef MINIZ_HEADER_INCLUDED -#define MINIZ_HEADER_INCLUDED - -#include - -// Defines to completely disable specific portions of miniz.c: -// If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl. - -// Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc. -// Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc -// callbacks to the zlib and archive API's, and a few stand-alone helper API's which don't provide custom user -// functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work. -//#define MINIZ_NO_MALLOC - -#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) || defined(__ia64__) || defined(__x86_64__) -// MINIZ_X86_OR_X64_CPU is only used to help set the below macros. -#define MINIZ_X86_OR_X64_CPU 1 -#endif - -#if (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU -// Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian. -#define MINIZ_LITTLE_ENDIAN 1 -#endif - -#if MINIZ_X86_OR_X64_CPU -// Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses. -#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0 -#endif - -#if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__) -// Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are reasonably fast (and don't involve compiler generated calls to helper functions). -#define MINIZ_HAS_64BIT_REGISTERS 1 -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -// ------------------- zlib-style API Definitions. - -// For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits! -typedef unsigned long mz_ulong; - -// mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap. -void mz_free(void *p); - -#define MZ_ADLER32_INIT (1) -// mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL. -mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len); - -#define MZ_CRC32_INIT (0) -// mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL. -mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len); - -// Compression strategies. -enum { MZ_DEFAULT_STRATEGY = 0, MZ_FILTERED = 1, MZ_HUFFMAN_ONLY = 2, MZ_RLE = 3, MZ_FIXED = 4 }; - -// Method -#define MZ_DEFLATED 8 - -// ------------------- Types and macros - -typedef unsigned char mz_uint8; -typedef signed short mz_int16; -typedef unsigned short mz_uint16; -typedef unsigned int mz_uint32; -typedef unsigned int mz_uint; -typedef long long mz_int64; -typedef unsigned long long mz_uint64; -typedef int mz_bool; - -#define MZ_FALSE (0) -#define MZ_TRUE (1) - -// Works around MSVC's spammy "warning C4127: conditional expression is constant" message. -#ifdef _MSC_VER - #define MZ_MACRO_END while (0, 0) -#else - #define MZ_MACRO_END while (0) -#endif - -// ------------------- Low-level Decompression API Definitions - -// Decompression flags used by tinfl_decompress(). -// TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream. -// TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input. -// TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB). -// TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes. -enum -{ - TINFL_FLAG_PARSE_ZLIB_HEADER = 1, - TINFL_FLAG_HAS_MORE_INPUT = 2, - TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4, - TINFL_FLAG_COMPUTE_ADLER32 = 8 -}; - -// High level decompression functions: -// tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc(). -// On entry: -// pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress. -// On return: -// Function returns a pointer to the decompressed data, or NULL on failure. -// *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data. -// The caller must call mz_free() on the returned block when it's no longer needed. -void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); - -// tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory. -// Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success. -#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1)) -size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); - -// tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer. -// Returns 1 on success or 0 on failure. -typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser); -int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); - -struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor; - -// Max size of LZ dictionary. -#define TINFL_LZ_DICT_SIZE 32768 - -// Return status. -typedef enum -{ - TINFL_STATUS_BAD_PARAM = -3, - TINFL_STATUS_ADLER32_MISMATCH = -2, - TINFL_STATUS_FAILED = -1, - TINFL_STATUS_DONE = 0, - TINFL_STATUS_NEEDS_MORE_INPUT = 1, - TINFL_STATUS_HAS_MORE_OUTPUT = 2 -} tinfl_status; - -// Initializes the decompressor to its initial state. -#define tinfl_init(r) do { (r)->m_state = 0; } MZ_MACRO_END -#define tinfl_get_adler32(r) (r)->m_check_adler32 - -// Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability. -// This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output. -tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags); - -// Internal/private bits follow. -enum -{ - TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19, - TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS -}; - -typedef struct -{ - mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0]; - mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2]; -} tinfl_huff_table; - -#if MINIZ_HAS_64BIT_REGISTERS - #define TINFL_USE_64BIT_BITBUF 1 -#endif - -#if TINFL_USE_64BIT_BITBUF - typedef mz_uint64 tinfl_bit_buf_t; - #define TINFL_BITBUF_SIZE (64) -#else - typedef mz_uint32 tinfl_bit_buf_t; - #define TINFL_BITBUF_SIZE (32) -#endif - -struct tinfl_decompressor_tag -{ - mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES]; - tinfl_bit_buf_t m_bit_buf; - size_t m_dist_from_out_buf_start; - tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES]; - mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137]; -}; - -// ------------------- Low-level Compression API Definitions - -// Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently). -#define TDEFL_LESS_MEMORY 0 - -// tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search): -// TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression). -enum -{ - TDEFL_HUFFMAN_ONLY = 0, TDEFL_DEFAULT_MAX_PROBES = 128, TDEFL_MAX_PROBES_MASK = 0xFFF -}; - -// TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data. -// TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers). -// TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing. -// TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory). -// TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1) -// TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled. -// TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables. -// TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks. -enum -{ - TDEFL_WRITE_ZLIB_HEADER = 0x01000, - TDEFL_COMPUTE_ADLER32 = 0x02000, - TDEFL_GREEDY_PARSING_FLAG = 0x04000, - TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000, - TDEFL_RLE_MATCHES = 0x10000, - TDEFL_FILTER_MATCHES = 0x20000, - TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000, - TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000 -}; - -// High level compression functions: -// tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc(). -// On entry: -// pSrc_buf, src_buf_len: Pointer and size of source block to compress. -// flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression. -// On return: -// Function returns a pointer to the compressed data, or NULL on failure. -// *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data. -// The caller must free() the returned block when it's no longer needed. -void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); - -// tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory. -// Returns 0 on failure. -size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); - -// Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time. -typedef mz_bool (*tdefl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser); - -// tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally. -mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); - -enum { TDEFL_MAX_HUFF_TABLES = 3, TDEFL_MAX_HUFF_SYMBOLS_0 = 288, TDEFL_MAX_HUFF_SYMBOLS_1 = 32, TDEFL_MAX_HUFF_SYMBOLS_2 = 19, TDEFL_LZ_DICT_SIZE = 32768, TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, TDEFL_MIN_MATCH_LEN = 3, TDEFL_MAX_MATCH_LEN = 258 }; - -// TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes). -#if TDEFL_LESS_MEMORY -enum { TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 12, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS }; -#else -enum { TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 15, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS }; -#endif - -// The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions. -typedef enum -{ - TDEFL_STATUS_BAD_PARAM = -2, - TDEFL_STATUS_PUT_BUF_FAILED = -1, - TDEFL_STATUS_OKAY = 0, - TDEFL_STATUS_DONE = 1, -} tdefl_status; - -// Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums -typedef enum -{ - TDEFL_NO_FLUSH = 0, - TDEFL_SYNC_FLUSH = 2, - TDEFL_FULL_FLUSH = 3, - TDEFL_FINISH = 4 -} tdefl_flush; - -// tdefl's compression state structure. -typedef struct -{ - tdefl_put_buf_func_ptr m_pPut_buf_func; - void *m_pPut_buf_user; - mz_uint m_flags, m_max_probes[2]; - int m_greedy_parsing; - mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size; - mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end; - mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer; - mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish; - tdefl_status m_prev_return_status; - const void *m_pIn_buf; - void *m_pOut_buf; - size_t *m_pIn_buf_size, *m_pOut_buf_size; - tdefl_flush m_flush; - const mz_uint8 *m_pSrc; - size_t m_src_buf_left, m_out_buf_ofs; - mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1]; - mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; - mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; - mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; - mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE]; - mz_uint16 m_next[TDEFL_LZ_DICT_SIZE]; - mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE]; - mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE]; -} tdefl_compressor; - -// Initializes the compressor. -// There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory. -// pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression. -// If pBut_buf_func is NULL the user should always call the tdefl_compress() API. -// flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.) -tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); - -// Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible. -tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush); - -// tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr. -// tdefl_compress_buffer() always consumes the entire input buffer. -tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush); - -tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d); -mz_uint32 tdefl_get_adler32(tdefl_compressor *d); - -#ifdef __cplusplus -} -#endif - -#endif // MINIZ_HEADER_INCLUDED - -// ------------------- End of Header: Implementation follows. (If you only want the header, define MINIZ_HEADER_FILE_ONLY.) - -#ifndef MINIZ_HEADER_FILE_ONLY - -typedef unsigned char mz_validate_uint16[sizeof(mz_uint16)==2 ? 1 : -1]; -typedef unsigned char mz_validate_uint32[sizeof(mz_uint32)==4 ? 1 : -1]; -typedef unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 : -1]; - -#include -#include - -#define MZ_ASSERT(x) assert(x) - -#ifdef MINIZ_NO_MALLOC - #define MZ_MALLOC(x) NULL - #define MZ_FREE(x) (void)x, ((void)0) - #define MZ_REALLOC(p, x) NULL -#else - #define MZ_MALLOC(x) malloc(x) - #define MZ_FREE(x) free(x) - #define MZ_REALLOC(p, x) realloc(p, x) -#endif - -#define MZ_MAX(a,b) (((a)>(b))?(a):(b)) -#define MZ_MIN(a,b) (((a)<(b))?(a):(b)) -#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj)) - -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN - #define MZ_READ_LE16(p) *((const mz_uint16 *)(p)) - #define MZ_READ_LE32(p) *((const mz_uint32 *)(p)) -#else - #define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U)) - #define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U)) -#endif - -#ifdef _MSC_VER - #define MZ_FORCEINLINE __forceinline -#elif defined(__GNUC__) - #define MZ_FORCEINLINE inline __attribute__((__always_inline__)) -#else - #define MZ_FORCEINLINE -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -// ------------------- zlib-style API's - -mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len) -{ - mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); size_t block_len = buf_len % 5552; - if (!ptr) return MZ_ADLER32_INIT; - while (buf_len) { - for (i = 0; i + 7 < block_len; i += 8, ptr += 8) { - s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1; - s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1; - } - for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1; - s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552; - } - return (s2 << 16) + s1; -} - -// Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/ -mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) -{ - static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, - 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c }; - mz_uint32 crcu32 = (mz_uint32)crc; - if (!ptr) return MZ_CRC32_INIT; - crcu32 = ~crcu32; while (buf_len--) { mz_uint8 b = *ptr++; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)]; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)]; } - return ~crcu32; -} - -void mz_free(void *p) -{ - MZ_FREE(p); -} - -// ------------------- Low-level Decompression (completely independent from all compression API's) - -#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l) -#define TINFL_MEMSET(p, c, l) memset(p, c, l) - -#define TINFL_CR_BEGIN switch(r->m_state) { case 0: -#define TINFL_CR_RETURN(state_index, result) do { status = result; r->m_state = state_index; goto common_exit; case state_index:; } MZ_MACRO_END -#define TINFL_CR_RETURN_FOREVER(state_index, result) do { for ( ; ; ) { TINFL_CR_RETURN(state_index, result); } } MZ_MACRO_END -#define TINFL_CR_FINISH } - -// TODO: If the caller has indicated that there's no more input, and we attempt to read beyond the input buf, then something is wrong with the input because the inflator never -// reads ahead more than it needs to. Currently TINFL_GET_BYTE() pads the end of the stream with 0's in this scenario. -#define TINFL_GET_BYTE(state_index, c) do { \ - if (pIn_buf_cur >= pIn_buf_end) { \ - for ( ; ; ) { \ - if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \ - TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \ - if (pIn_buf_cur < pIn_buf_end) { \ - c = *pIn_buf_cur++; \ - break; \ - } \ - } else { \ - c = 0; \ - break; \ - } \ - } \ - } else c = *pIn_buf_cur++; } MZ_MACRO_END - -#define TINFL_NEED_BITS(state_index, n) do { mz_uint c; TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; } while (num_bits < (mz_uint)(n)) -#define TINFL_SKIP_BITS(state_index, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END -#define TINFL_GET_BITS(state_index, b, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } b = bit_buf & ((1 << (n)) - 1); bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END - -// TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2. -// It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a -// Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the -// bit buffer contains >=15 bits (deflate's max. Huffman code size). -#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \ - do { \ - temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \ - if (temp >= 0) { \ - code_len = temp >> 9; \ - if ((code_len) && (num_bits >= code_len)) \ - break; \ - } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \ - code_len = TINFL_FAST_LOOKUP_BITS; \ - do { \ - temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \ - } while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \ - } TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \ - } while (num_bits < 15); - -// TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read -// beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully -// decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32. -// The slow path is only executed at the very end of the input buffer. -#define TINFL_HUFF_DECODE(state_index, sym, pHuff) do { \ - int temp; mz_uint code_len, c; \ - if (num_bits < 15) { \ - if ((pIn_buf_end - pIn_buf_cur) < 2) { \ - TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \ - } else { \ - bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); pIn_buf_cur += 2; num_bits += 16; \ - } \ - } \ - if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \ - code_len = temp >> 9, temp &= 511; \ - else { \ - code_len = TINFL_FAST_LOOKUP_BITS; do { temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; } while (temp < 0); \ - } sym = temp; bit_buf >>= code_len; num_bits -= code_len; } MZ_MACRO_END - -tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags) -{ - static const int s_length_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 }; - static const int s_length_extra[31]= { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; - static const int s_dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; - static const int s_dist_extra[32] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; - static const mz_uint8 s_length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; - static const int s_min_table_sizes[3] = { 257, 1, 4 }; - - tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf; - const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size; - mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size; - size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start; - - // Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter). - if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) { *pIn_buf_size = *pOut_buf_size = 0; return TINFL_STATUS_BAD_PARAM; } - - num_bits = r->m_num_bits; bit_buf = r->m_bit_buf; dist = r->m_dist; counter = r->m_counter; num_extra = r->m_num_extra; dist_from_out_buf_start = r->m_dist_from_out_buf_start; - TINFL_CR_BEGIN - - bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; r->m_z_adler32 = r->m_check_adler32 = 1; - if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) - { - TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1); - counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8)); - if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4))))); - if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); } - } - - do - { - TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1; - if (r->m_type == 0) - { - TINFL_SKIP_BITS(5, num_bits & 7); - for (counter = 0; counter < 4; ++counter) { if (num_bits) TINFL_GET_BITS(6, r->m_raw_header[counter], 8); else TINFL_GET_BYTE(7, r->m_raw_header[counter]); } - if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) { TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); } - while ((counter) && (num_bits)) - { - TINFL_GET_BITS(51, dist, 8); - while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); } - *pOut_buf_cur++ = (mz_uint8)dist; - counter--; - } - while (counter) - { - size_t n; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); } - while (pIn_buf_cur >= pIn_buf_end) - { - if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) - { - TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT); - } - else - { - TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED); - } - } - n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter); - TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); pIn_buf_cur += n; pOut_buf_cur += n; counter -= (mz_uint)n; - } - } - else if (r->m_type == 3) - { - TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED); - } - else - { - if (r->m_type == 1) - { - mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i; - r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32); - for ( i = 0; i <= 143; ++i) *p++ = 8; - for ( ; i <= 255; ++i) *p++ = 9; - for ( ; i <= 279; ++i) *p++ = 7; - for ( ; i <= 287; ++i) *p++ = 8; - } - else - { - for (counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; } - MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; } - r->m_table_sizes[2] = 19; - } - for ( ; (int)r->m_type >= 0; r->m_type--) - { - int tree_next, tree_cur; tinfl_huff_table *pTable; - mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree); - for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++; - used_syms = 0, total = 0; next_code[0] = next_code[1] = 0; - for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); } - if ((65536 != total) && (used_syms > 1)) - { - TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED); - } - for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index) - { - mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; if (!code_size) continue; - cur_code = next_code[code_size]++; for (l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1); - if (code_size <= TINFL_FAST_LOOKUP_BITS) { mz_int16 k = (mz_int16)((code_size << 9) | sym_index); while (rev_code < TINFL_FAST_LOOKUP_SIZE) { pTable->m_look_up[rev_code] = k; rev_code += (1 << code_size); } continue; } - if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) { pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } - rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1); - for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) - { - tree_cur -= ((rev_code >>= 1) & 1); - if (!pTable->m_tree[-tree_cur - 1]) { pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } else tree_cur = pTable->m_tree[-tree_cur - 1]; - } - tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index; - } - if (r->m_type == 2) - { - for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]); ) - { - mz_uint s; TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); if (dist < 16) { r->m_len_codes[counter++] = (mz_uint8)dist; continue; } - if ((dist == 16) && (!counter)) - { - TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED); - } - num_extra = "\02\03\07"[dist - 16]; TINFL_GET_BITS(18, s, num_extra); s += "\03\03\013"[dist - 16]; - TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s; - } - if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter) - { - TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED); - } - TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]); - } - } - for ( ; ; ) - { - mz_uint8 *pSrc; - for ( ; ; ) - { - if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2)) - { - TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]); - if (counter >= 256) - break; - while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); } - *pOut_buf_cur++ = (mz_uint8)counter; - } - else - { - int sym2; mz_uint code_len; -#if TINFL_USE_64BIT_BITBUF - if (num_bits < 30) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); pIn_buf_cur += 4; num_bits += 32; } -#else - if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; } -#endif - if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) - code_len = sym2 >> 9; - else - { - code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0); - } - counter = sym2; bit_buf >>= code_len; num_bits -= code_len; - if (counter & 256) - break; - -#if !TINFL_USE_64BIT_BITBUF - if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; } -#endif - if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) - code_len = sym2 >> 9; - else - { - code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0); - } - bit_buf >>= code_len; num_bits -= code_len; - - pOut_buf_cur[0] = (mz_uint8)counter; - if (sym2 & 256) - { - pOut_buf_cur++; - counter = sym2; - break; - } - pOut_buf_cur[1] = (mz_uint8)sym2; - pOut_buf_cur += 2; - } - } - if ((counter &= 511) == 256) break; - - num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257]; - if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); counter += extra_bits; } - - TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]); - num_extra = s_dist_extra[dist]; dist = s_dist_base[dist]; - if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); dist += extra_bits; } - - dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start; - if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) - { - TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED); - } - - pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask); - - if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) - { - while (counter--) - { - while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); } - *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask]; - } - continue; - } -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES - else if ((counter >= 9) && (counter <= dist)) - { - const mz_uint8 *pSrc_end = pSrc + (counter & ~7); - do - { - ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0]; - ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1]; - pOut_buf_cur += 8; - } while ((pSrc += 8) < pSrc_end); - if ((counter &= 7) < 3) - { - if (counter) - { - pOut_buf_cur[0] = pSrc[0]; - if (counter > 1) - pOut_buf_cur[1] = pSrc[1]; - pOut_buf_cur += counter; - } - continue; - } - } -#endif - do - { - pOut_buf_cur[0] = pSrc[0]; - pOut_buf_cur[1] = pSrc[1]; - pOut_buf_cur[2] = pSrc[2]; - pOut_buf_cur += 3; pSrc += 3; - } while ((int)(counter -= 3) > 2); - if ((int)counter > 0) - { - pOut_buf_cur[0] = pSrc[0]; - if ((int)counter > 1) - pOut_buf_cur[1] = pSrc[1]; - pOut_buf_cur += counter; - } - } - } - } while (!(r->m_final & 1)); - if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) - { - TINFL_SKIP_BITS(32, num_bits & 7); for (counter = 0; counter < 4; ++counter) { mz_uint s; if (num_bits) TINFL_GET_BITS(41, s, 8); else TINFL_GET_BYTE(42, s); r->m_z_adler32 = (r->m_z_adler32 << 8) | s; } - } - TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE); - TINFL_CR_FINISH - -common_exit: - r->m_num_bits = num_bits; r->m_bit_buf = bit_buf; r->m_dist = dist; r->m_counter = counter; r->m_num_extra = num_extra; r->m_dist_from_out_buf_start = dist_from_out_buf_start; - *pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next; - if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0)) - { - const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size; - mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552; - while (buf_len) - { - for (i = 0; i + 7 < block_len; i += 8, ptr += 8) - { - s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1; - s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1; - } - for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1; - s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552; - } - r->m_check_adler32 = (s2 << 16) + s1; if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH; - } - return status; -} - -// Higher level helper functions. -void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) -{ - tinfl_decompressor decomp; void *pBuf = NULL, *pNew_buf; size_t src_buf_ofs = 0, out_buf_capacity = 0; - *pOut_len = 0; - tinfl_init(&decomp); - for ( ; ; ) - { - size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity; - tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8*)pBuf, pBuf ? (mz_uint8*)pBuf + *pOut_len : NULL, &dst_buf_size, - (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); - if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) - { - MZ_FREE(pBuf); *pOut_len = 0; return NULL; - } - src_buf_ofs += src_buf_size; - *pOut_len += dst_buf_size; - if (status == TINFL_STATUS_DONE) break; - new_out_buf_capacity = out_buf_capacity * 2; if (new_out_buf_capacity < 128) new_out_buf_capacity = 128; - pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity); - if (!pNew_buf) - { - MZ_FREE(pBuf); *pOut_len = 0; return NULL; - } - pBuf = pNew_buf; out_buf_capacity = new_out_buf_capacity; - } - return pBuf; -} - -size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) -{ - tinfl_decompressor decomp; tinfl_status status; tinfl_init(&decomp); - status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf, &src_buf_len, (mz_uint8*)pOut_buf, (mz_uint8*)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); - return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len; -} - -int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) -{ - int result = 0; - tinfl_decompressor decomp; - mz_uint8 *pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); size_t in_buf_ofs = 0, dict_ofs = 0; - if (!pDict) - return TINFL_STATUS_FAILED; - tinfl_init(&decomp); - for ( ; ; ) - { - size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs; - tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size, - (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))); - in_buf_ofs += in_buf_size; - if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user))) - break; - if (status != TINFL_STATUS_HAS_MORE_OUTPUT) - { - result = (status == TINFL_STATUS_DONE); - break; - } - dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1); - } - MZ_FREE(pDict); - *pIn_buf_size = in_buf_ofs; - return result; -} - -// ------------------- Low-level Compression (independent from all decompression API's) - -// Purposely making these tables static for faster init and thread safety. -static const mz_uint16 s_tdefl_len_sym[256] = { - 257,258,259,260,261,262,263,264,265,265,266,266,267,267,268,268,269,269,269,269,270,270,270,270,271,271,271,271,272,272,272,272, - 273,273,273,273,273,273,273,273,274,274,274,274,274,274,274,274,275,275,275,275,275,275,275,275,276,276,276,276,276,276,276,276, - 277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278, - 279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280, - 281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281, - 282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282, - 283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283, - 284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,285 }; - -static const mz_uint8 s_tdefl_len_extra[256] = { - 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0 }; - -static const mz_uint8 s_tdefl_small_dist_sym[512] = { - 0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11, - 11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13, - 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14, - 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, - 14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, - 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17 }; - -static const mz_uint8 s_tdefl_small_dist_extra[512] = { - 0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7 }; - -static const mz_uint8 s_tdefl_large_dist_sym[128] = { - 0,0,18,19,20,20,21,21,22,22,22,22,23,23,23,23,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28, - 28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 }; - -static const mz_uint8 s_tdefl_large_dist_extra[128] = { - 0,0,8,8,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, - 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, - 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13 }; - -// Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values. -typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq; -static tdefl_sym_freq* tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq* pSyms0, tdefl_sym_freq* pSyms1) -{ - mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; tdefl_sym_freq* pCur_syms = pSyms0, *pNew_syms = pSyms1; MZ_CLEAR_OBJ(hist); - for (i = 0; i < num_syms; i++) { mz_uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; } - while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--; - for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) - { - const mz_uint32* pHist = &hist[pass << 8]; - mz_uint offsets[256], cur_ofs = 0; - for (i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; } - for (i = 0; i < num_syms; i++) pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i]; - { tdefl_sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t; } - } - return pCur_syms; -} - -// tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. -static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n) -{ - int root, leaf, next, avbl, used, dpth; - if (n==0) return; else if (n==1) { A[0].m_key = 1; return; } - A[0].m_key += A[1].m_key; root = 0; leaf = 2; - for (next=1; next < n-1; next++) - { - if (leaf>=n || A[root].m_key=n || (root=0; next--) A[next].m_key = A[A[next].m_key].m_key+1; - avbl = 1; used = dpth = 0; root = n-2; next = n-1; - while (avbl>0) - { - while (root>=0 && (int)A[root].m_key==dpth) { used++; root--; } - while (avbl>used) { A[next--].m_key = (mz_uint16)(dpth); avbl--; } - avbl = 2*used; dpth++; used = 0; - } -} - -// Limits canonical Huffman code table's max code size. -enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 }; -static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size) -{ - int i; mz_uint32 total = 0; if (code_list_len <= 1) return; - for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i]; - for (i = max_code_size; i > 0; i--) total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i)); - while (total != (1UL << max_code_size)) - { - pNum_codes[max_code_size]--; - for (i = max_code_size - 1; i > 0; i--) if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; } - total--; - } -} - -static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table) -{ - int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; MZ_CLEAR_OBJ(num_codes); - if (static_table) - { - for (i = 0; i < table_len; i++) num_codes[d->m_huff_code_sizes[table_num][i]]++; - } - else - { - tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms; - int num_used_syms = 0; - const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0]; - for (i = 0; i < table_len; i++) if (pSym_count[i]) { syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; syms0[num_used_syms++].m_sym_index = (mz_uint16)i; } - - pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); tdefl_calculate_minimum_redundancy(pSyms, num_used_syms); - - for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++; - - tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit); - - MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); MZ_CLEAR_OBJ(d->m_huff_codes[table_num]); - for (i = 1, j = num_used_syms; i <= code_size_limit; i++) - for (l = num_codes[i]; l > 0; l--) d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i); - } - - next_code[1] = 0; for (j = 0, i = 2; i <= code_size_limit; i++) next_code[i] = j = ((j + num_codes[i - 1]) << 1); - - for (i = 0; i < table_len; i++) - { - mz_uint rev_code = 0, code, code_size; if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue; - code = next_code[code_size]++; for (l = code_size; l > 0; l--, code >>= 1) rev_code = (rev_code << 1) | (code & 1); - d->m_huff_codes[table_num][i] = (mz_uint16)rev_code; - } -} - -#define TDEFL_PUT_BITS(b, l) do { \ - mz_uint bits = b; mz_uint len = l; MZ_ASSERT(bits <= ((1U << len) - 1U)); \ - d->m_bit_buffer |= (bits << d->m_bits_in); d->m_bits_in += len; \ - while (d->m_bits_in >= 8) { \ - if (d->m_pOutput_buf < d->m_pOutput_buf_end) \ - *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \ - d->m_bit_buffer >>= 8; \ - d->m_bits_in -= 8; \ - } \ -} MZ_MACRO_END - -#define TDEFL_RLE_PREV_CODE_SIZE() { if (rle_repeat_count) { \ - if (rle_repeat_count < 3) { \ - d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \ - while (rle_repeat_count--) packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \ - } else { \ - d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); packed_code_sizes[num_packed_code_sizes++] = 16; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \ -} rle_repeat_count = 0; } } - -#define TDEFL_RLE_ZERO_CODE_SIZE() { if (rle_z_count) { \ - if (rle_z_count < 3) { \ - d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); while (rle_z_count--) packed_code_sizes[num_packed_code_sizes++] = 0; \ - } else if (rle_z_count <= 10) { \ - d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); packed_code_sizes[num_packed_code_sizes++] = 17; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \ - } else { \ - d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); packed_code_sizes[num_packed_code_sizes++] = 18; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \ -} rle_z_count = 0; } } - -static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; - -static void tdefl_start_dynamic_block(tdefl_compressor *d) -{ - int num_lit_codes, num_dist_codes, num_bit_lengths; mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index; - mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF; - - d->m_huff_count[0][256] = 1; - - tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE); - tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE); - - for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) if (d->m_huff_code_sizes[0][num_lit_codes - 1]) break; - for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) if (d->m_huff_code_sizes[1][num_dist_codes - 1]) break; - - memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes); - memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes); - total_code_sizes_to_pack = num_lit_codes + num_dist_codes; num_packed_code_sizes = 0; rle_z_count = 0; rle_repeat_count = 0; - - memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2); - for (i = 0; i < total_code_sizes_to_pack; i++) - { - mz_uint8 code_size = code_sizes_to_pack[i]; - if (!code_size) - { - TDEFL_RLE_PREV_CODE_SIZE(); - if (++rle_z_count == 138) { TDEFL_RLE_ZERO_CODE_SIZE(); } - } - else - { - TDEFL_RLE_ZERO_CODE_SIZE(); - if (code_size != prev_code_size) - { - TDEFL_RLE_PREV_CODE_SIZE(); - d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); packed_code_sizes[num_packed_code_sizes++] = code_size; - } - else if (++rle_repeat_count == 6) - { - TDEFL_RLE_PREV_CODE_SIZE(); - } - } - prev_code_size = code_size; - } - if (rle_repeat_count) { TDEFL_RLE_PREV_CODE_SIZE(); } else { TDEFL_RLE_ZERO_CODE_SIZE(); } - - tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE); - - TDEFL_PUT_BITS(2, 2); - - TDEFL_PUT_BITS(num_lit_codes - 257, 5); - TDEFL_PUT_BITS(num_dist_codes - 1, 5); - - for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) break; - num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); TDEFL_PUT_BITS(num_bit_lengths - 4, 4); - for (i = 0; (int)i < num_bit_lengths; i++) TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3); - - for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes; ) - { - mz_uint code = packed_code_sizes[packed_code_sizes_index++]; MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2); - TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]); - if (code >= 16) TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]); - } -} - -static void tdefl_start_static_block(tdefl_compressor *d) -{ - mz_uint i; - mz_uint8 *p = &d->m_huff_code_sizes[0][0]; - - for (i = 0; i <= 143; ++i) *p++ = 8; - for ( ; i <= 255; ++i) *p++ = 9; - for ( ; i <= 279; ++i) *p++ = 7; - for ( ; i <= 287; ++i) *p++ = 8; - - memset(d->m_huff_code_sizes[1], 5, 32); - - tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE); - tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE); - - TDEFL_PUT_BITS(1, 2); -} - -static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; - -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS -static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) -{ - mz_uint flags; - mz_uint8 *pLZ_codes; - mz_uint8 *pOutput_buf = d->m_pOutput_buf; - mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf; - mz_uint64 bit_buffer = d->m_bit_buffer; - mz_uint bits_in = d->m_bits_in; - -#define TDEFL_PUT_BITS_FAST(b, l) { bit_buffer |= (((mz_uint64)(b)) << bits_in); bits_in += (l); } - - flags = 1; - for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1) - { - if (flags == 1) - flags = *pLZ_codes++ | 0x100; - - if (flags & 1) - { - mz_uint s0, s1, n0, n1, sym, num_extra_bits; - mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1); pLZ_codes += 3; - - MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); - TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); - - // This sequence coaxes MSVC into using cmov's vs. jmp's. - s0 = s_tdefl_small_dist_sym[match_dist & 511]; - n0 = s_tdefl_small_dist_extra[match_dist & 511]; - s1 = s_tdefl_large_dist_sym[match_dist >> 8]; - n1 = s_tdefl_large_dist_extra[match_dist >> 8]; - sym = (match_dist < 512) ? s0 : s1; - num_extra_bits = (match_dist < 512) ? n0 : n1; - - MZ_ASSERT(d->m_huff_code_sizes[1][sym]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); - TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); - } - else - { - mz_uint lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); - - if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) - { - flags >>= 1; - lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); - - if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) - { - flags >>= 1; - lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); - } - } - } - - if (pOutput_buf >= d->m_pOutput_buf_end) - return MZ_FALSE; - - *(mz_uint64*)pOutput_buf = bit_buffer; - pOutput_buf += (bits_in >> 3); - bit_buffer >>= (bits_in & ~7); - bits_in &= 7; - } - -#undef TDEFL_PUT_BITS_FAST - - d->m_pOutput_buf = pOutput_buf; - d->m_bits_in = 0; - d->m_bit_buffer = 0; - - while (bits_in) - { - mz_uint32 n = MZ_MIN(bits_in, 16); - TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n); - bit_buffer >>= n; - bits_in -= n; - } - - TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); - - return (d->m_pOutput_buf < d->m_pOutput_buf_end); -} -#else -static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) -{ - mz_uint flags; - mz_uint8 *pLZ_codes; - - flags = 1; - for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1) - { - if (flags == 1) - flags = *pLZ_codes++ | 0x100; - if (flags & 1) - { - mz_uint sym, num_extra_bits; - mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); pLZ_codes += 3; - - MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); - TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); - TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); - - if (match_dist < 512) - { - sym = s_tdefl_small_dist_sym[match_dist]; num_extra_bits = s_tdefl_small_dist_extra[match_dist]; - } - else - { - sym = s_tdefl_large_dist_sym[match_dist >> 8]; num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8]; - } - MZ_ASSERT(d->m_huff_code_sizes[1][sym]); - TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); - TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); - } - else - { - mz_uint lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); - } - } - - TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); - - return (d->m_pOutput_buf < d->m_pOutput_buf_end); -} -#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS - -static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block) -{ - if (static_block) - tdefl_start_static_block(d); - else - tdefl_start_dynamic_block(d); - return tdefl_compress_lz_codes(d); -} - -static int tdefl_flush_block(tdefl_compressor *d, int flush) -{ - mz_uint saved_bit_buf, saved_bits_in; - mz_uint8 *pSaved_output_buf; - mz_bool comp_block_succeeded = MZ_FALSE; - int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size; - mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf; - - d->m_pOutput_buf = pOutput_buf_start; - d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16; - - MZ_ASSERT(!d->m_output_flush_remaining); - d->m_output_flush_ofs = 0; - d->m_output_flush_remaining = 0; - - *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left); - d->m_pLZ_code_buf -= (d->m_num_flags_left == 8); - - if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) - { - TDEFL_PUT_BITS(0x78, 8); TDEFL_PUT_BITS(0x01, 8); - } - - TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1); - - pSaved_output_buf = d->m_pOutput_buf; saved_bit_buf = d->m_bit_buffer; saved_bits_in = d->m_bits_in; - - if (!use_raw_block) - comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48)); - - // If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. - if ( ((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) && - ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size) ) - { - mz_uint i; d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; - TDEFL_PUT_BITS(0, 2); - if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } - for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) - { - TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16); - } - for (i = 0; i < d->m_total_lz_bytes; ++i) - { - TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8); - } - } - // Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. - else if (!comp_block_succeeded) - { - d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; - tdefl_compress_block(d, MZ_TRUE); - } - - if (flush) - { - if (flush == TDEFL_FINISH) - { - if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } - if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) { mz_uint i, a = d->m_adler32; for (i = 0; i < 4; i++) { TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); a <<= 8; } } - } - else - { - mz_uint i, z = 0; TDEFL_PUT_BITS(0, 3); if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } for (i = 2; i; --i, z ^= 0xFFFF) { TDEFL_PUT_BITS(z & 0xFFFF, 16); } - } - } - - MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end); - - memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); - memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); - - d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; d->m_total_lz_bytes = 0; d->m_block_index++; - - if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0) - { - if (d->m_pPut_buf_func) - { - *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; - if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user)) - return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED); - } - else if (pOutput_buf_start == d->m_output_buf) - { - int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs)); - memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy); - d->m_out_buf_ofs += bytes_to_copy; - if ((n -= bytes_to_copy) != 0) - { - d->m_output_flush_ofs = bytes_to_copy; - d->m_output_flush_remaining = n; - } - } - else - { - d->m_out_buf_ofs += n; - } - } - - return d->m_output_flush_remaining; -} - -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES -#define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16*)(p) -static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) -{ - mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; - mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; - const mz_uint16 *s = (const mz_uint16*)(d->m_dict + pos), *p, *q; - mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s); - MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return; - for ( ; ; ) - { - for ( ; ; ) - { - if (--num_probes_left == 0) return; - #define TDEFL_PROBE \ - next_probe_pos = d->m_next[probe_pos]; \ - if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \ - probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ - if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) break; - TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE; - } - if (!dist) break; q = (const mz_uint16*)(d->m_dict + probe_pos); if (TDEFL_READ_UNALIGNED_WORD(q) != s01) continue; p = s; probe_len = 32; - do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && - (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) ); - if (!probe_len) - { - *pMatch_dist = dist; *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN); break; - } - else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const mz_uint8*)q)) > match_len) - { - *pMatch_dist = dist; if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) break; - c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]); - } - } -} -#else -static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) -{ - mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; - mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; - const mz_uint8 *s = d->m_dict + pos, *p, *q; - mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1]; - MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return; - for ( ; ; ) - { - for ( ; ; ) - { - if (--num_probes_left == 0) return; - #define TDEFL_PROBE \ - next_probe_pos = d->m_next[probe_pos]; \ - if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \ - probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ - if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) break; - TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE; - } - if (!dist) break; - p = s; q = d->m_dict + probe_pos; - for (probe_len = 0; probe_len < max_match_len; probe_len++) - if (*p++ != *q++) break; - if (probe_len > match_len) - { - *pMatch_dist = dist; if ((*pMatch_len = match_len = probe_len) == max_match_len) return; - c0 = d->m_dict[pos + match_len]; c1 = d->m_dict[pos + match_len - 1]; - } - } -} -#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES - -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN -static mz_bool tdefl_compress_fast(tdefl_compressor *d) -{ - // Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. - mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left; - mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags; - mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; - - while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) - { - const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096; - mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; - mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size); - d->m_src_buf_left -= num_bytes_to_process; - lookahead_size += num_bytes_to_process; - - while (num_bytes_to_process) - { - mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process); - memcpy(d->m_dict + dst_pos, d->m_pSrc, n); - if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) - memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos)); - d->m_pSrc += n; - dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK; - num_bytes_to_process -= n; - } - - dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size); - if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) break; - - while (lookahead_size >= 4) - { - mz_uint cur_match_dist, cur_match_len = 1; - mz_uint8 *pCur_dict = d->m_dict + cur_pos; - mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF; - mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK; - mz_uint probe_pos = d->m_hash[hash]; - d->m_hash[hash] = (mz_uint16)lookahead_pos; - - if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram)) - { - const mz_uint16 *p = (const mz_uint16 *)pCur_dict; - const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos); - mz_uint32 probe_len = 32; - do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && - (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) ); - cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q); - if (!probe_len) - cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0; - - if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U))) - { - cur_match_len = 1; - *pLZ_code_buf++ = (mz_uint8)first_trigram; - *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); - d->m_huff_count[0][(mz_uint8)first_trigram]++; - } - else - { - mz_uint32 s0, s1; - cur_match_len = MZ_MIN(cur_match_len, lookahead_size); - - MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE)); - - cur_match_dist--; - - pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN); - *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist; - pLZ_code_buf += 3; - *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80); - - s0 = s_tdefl_small_dist_sym[cur_match_dist & 511]; - s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8]; - d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++; - - d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++; - } - } - else - { - *pLZ_code_buf++ = (mz_uint8)first_trigram; - *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); - d->m_huff_count[0][(mz_uint8)first_trigram]++; - } - - if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; } - - total_lz_bytes += cur_match_len; - lookahead_pos += cur_match_len; - dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE); - cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK; - MZ_ASSERT(lookahead_size >= cur_match_len); - lookahead_size -= cur_match_len; - - if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) - { - int n; - d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; - d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; - if ((n = tdefl_flush_block(d, 0)) != 0) - return (n < 0) ? MZ_FALSE : MZ_TRUE; - total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left; - } - } - - while (lookahead_size) - { - mz_uint8 lit = d->m_dict[cur_pos]; - - total_lz_bytes++; - *pLZ_code_buf++ = lit; - *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); - if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; } - - d->m_huff_count[0][lit]++; - - lookahead_pos++; - dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE); - cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; - lookahead_size--; - - if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) - { - int n; - d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; - d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; - if ((n = tdefl_flush_block(d, 0)) != 0) - return (n < 0) ? MZ_FALSE : MZ_TRUE; - total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left; - } - } - } - - d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; - d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; - return MZ_TRUE; -} -#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN - -static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit) -{ - d->m_total_lz_bytes++; - *d->m_pLZ_code_buf++ = lit; - *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; } - d->m_huff_count[0][lit]++; -} - -static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist) -{ - mz_uint32 s0, s1; - - MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE)); - - d->m_total_lz_bytes += match_len; - - d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN); - - match_dist -= 1; - d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF); - d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); d->m_pLZ_code_buf += 3; - - *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; } - - s0 = s_tdefl_small_dist_sym[match_dist & 511]; s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127]; - d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++; - - if (match_len >= TDEFL_MIN_MATCH_LEN) d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++; -} - -static mz_bool tdefl_compress_normal(tdefl_compressor *d) -{ - const mz_uint8 *pSrc = d->m_pSrc; size_t src_buf_left = d->m_src_buf_left; - tdefl_flush flush = d->m_flush; - - while ((src_buf_left) || ((flush) && (d->m_lookahead_size))) - { - mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos; - // Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. - if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1)) - { - mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2; - mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK]; - mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size); - const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process; - src_buf_left -= num_bytes_to_process; - d->m_lookahead_size += num_bytes_to_process; - while (pSrc != pSrc_end) - { - mz_uint8 c = *pSrc++; d->m_dict[dst_pos] = c; if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; - hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); - d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos); - dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; ins_pos++; - } - } - else - { - while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) - { - mz_uint8 c = *pSrc++; - mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; - src_buf_left--; - d->m_dict[dst_pos] = c; - if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) - d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; - if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN) - { - mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2; - mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); - d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos); - } - } - } - d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size); - if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) - break; - - // Simple lazy/greedy parsing state machine. - len_to_move = 1; cur_match_dist = 0; cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; - if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) - { - if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) - { - mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK]; - cur_match_len = 0; while (cur_match_len < d->m_lookahead_size) { if (d->m_dict[cur_pos + cur_match_len] != c) break; cur_match_len++; } - if (cur_match_len < TDEFL_MIN_MATCH_LEN) cur_match_len = 0; else cur_match_dist = 1; - } - } - else - { - tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len); - } - if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5))) - { - cur_match_dist = cur_match_len = 0; - } - if (d->m_saved_match_len) - { - if (cur_match_len > d->m_saved_match_len) - { - tdefl_record_literal(d, (mz_uint8)d->m_saved_lit); - if (cur_match_len >= 128) - { - tdefl_record_match(d, cur_match_len, cur_match_dist); - d->m_saved_match_len = 0; len_to_move = cur_match_len; - } - else - { - d->m_saved_lit = d->m_dict[cur_pos]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len; - } - } - else - { - tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist); - len_to_move = d->m_saved_match_len - 1; d->m_saved_match_len = 0; - } - } - else if (!cur_match_dist) - tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]); - else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128)) - { - tdefl_record_match(d, cur_match_len, cur_match_dist); - len_to_move = cur_match_len; - } - else - { - d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len; - } - // Move the lookahead forward by len_to_move bytes. - d->m_lookahead_pos += len_to_move; - MZ_ASSERT(d->m_lookahead_size >= len_to_move); - d->m_lookahead_size -= len_to_move; - d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE); - // Check if it's time to flush the current LZ codes to the internal output buffer. - if ( (d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) || - ( (d->m_total_lz_bytes > 31*1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) ) - { - int n; - d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left; - if ((n = tdefl_flush_block(d, 0)) != 0) - return (n < 0) ? MZ_FALSE : MZ_TRUE; - } - } - - d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left; - return MZ_TRUE; -} - -static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d) -{ - if (d->m_pIn_buf_size) - { - *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; - } - - if (d->m_pOut_buf_size) - { - size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining); - memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n); - d->m_output_flush_ofs += (mz_uint)n; - d->m_output_flush_remaining -= (mz_uint)n; - d->m_out_buf_ofs += n; - - *d->m_pOut_buf_size = d->m_out_buf_ofs; - } - - return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY; -} - -tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush) -{ - if (!d) - { - if (pIn_buf_size) *pIn_buf_size = 0; - if (pOut_buf_size) *pOut_buf_size = 0; - return TDEFL_STATUS_BAD_PARAM; - } - - d->m_pIn_buf = pIn_buf; d->m_pIn_buf_size = pIn_buf_size; - d->m_pOut_buf = pOut_buf; d->m_pOut_buf_size = pOut_buf_size; - d->m_pSrc = (const mz_uint8 *)(pIn_buf); d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0; - d->m_out_buf_ofs = 0; - d->m_flush = flush; - - if ( ((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) || - (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf) ) - { - if (pIn_buf_size) *pIn_buf_size = 0; - if (pOut_buf_size) *pOut_buf_size = 0; - return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM); - } - d->m_wants_to_finish |= (flush == TDEFL_FINISH); - - if ((d->m_output_flush_remaining) || (d->m_finished)) - return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); - -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN - if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) && - ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) && - ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0)) - { - if (!tdefl_compress_fast(d)) - return d->m_prev_return_status; - } - else -#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN - { - if (!tdefl_compress_normal(d)) - return d->m_prev_return_status; - } - - if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf)) - d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf); - - if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining)) - { - if (tdefl_flush_block(d, flush) < 0) - return d->m_prev_return_status; - d->m_finished = (flush == TDEFL_FINISH); - if (flush == TDEFL_FULL_FLUSH) { MZ_CLEAR_OBJ(d->m_hash); MZ_CLEAR_OBJ(d->m_next); d->m_dict_size = 0; } - } - - return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); -} - -tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush) -{ - MZ_ASSERT(d->m_pPut_buf_func); return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush); -} - -tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) -{ - d->m_pPut_buf_func = pPut_buf_func; d->m_pPut_buf_user = pPut_buf_user; - d->m_flags = (mz_uint)(flags); d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0; - d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3; - if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(d->m_hash); - d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0; - d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0; - d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; - d->m_pOutput_buf = d->m_output_buf; d->m_pOutput_buf_end = d->m_output_buf; d->m_prev_return_status = TDEFL_STATUS_OKAY; - d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; d->m_adler32 = 1; - d->m_pIn_buf = NULL; d->m_pOut_buf = NULL; - d->m_pIn_buf_size = NULL; d->m_pOut_buf_size = NULL; - d->m_flush = TDEFL_NO_FLUSH; d->m_pSrc = NULL; d->m_src_buf_left = 0; d->m_out_buf_ofs = 0; - memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); - memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); - return TDEFL_STATUS_OKAY; -} - -tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d) -{ - return d->m_prev_return_status; -} - -mz_uint32 tdefl_get_adler32(tdefl_compressor *d) -{ - return d->m_adler32; -} - -mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) -{ - tdefl_compressor *pComp; mz_bool succeeded; if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) return MZ_FALSE; - pComp = (tdefl_compressor*)MZ_MALLOC(sizeof(tdefl_compressor)); if (!pComp) return MZ_FALSE; - succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY); - succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE); - MZ_FREE(pComp); return succeeded; -} - -typedef struct -{ - size_t m_size, m_capacity; - mz_uint8 *m_pBuf; - mz_bool m_expandable; -} tdefl_output_buffer; - -static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser) -{ - tdefl_output_buffer *p = (tdefl_output_buffer *)pUser; - size_t new_size = p->m_size + len; - if (new_size > p->m_capacity) - { - size_t new_capacity = p->m_capacity; mz_uint8 *pNew_buf; if (!p->m_expandable) return MZ_FALSE; - do { new_capacity = MZ_MAX(128U, new_capacity << 1U); } while (new_size > new_capacity); - pNew_buf = (mz_uint8*)MZ_REALLOC(p->m_pBuf, new_capacity); if (!pNew_buf) return MZ_FALSE; - p->m_pBuf = pNew_buf; p->m_capacity = new_capacity; - } - memcpy((mz_uint8*)p->m_pBuf + p->m_size, pBuf, len); p->m_size = new_size; - return MZ_TRUE; -} - -void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) -{ - tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf); - if (!pOut_len) return MZ_FALSE; else *pOut_len = 0; - out_buf.m_expandable = MZ_TRUE; - if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return NULL; - *pOut_len = out_buf.m_size; return out_buf.m_pBuf; -} - -size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) -{ - tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf); - if (!pOut_buf) return 0; - out_buf.m_pBuf = (mz_uint8*)pOut_buf; out_buf.m_capacity = out_buf_len; - if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return 0; - return out_buf.m_size; -} - -#ifdef __cplusplus -} -#endif - -#endif // MINIZ_HEADER_FILE_ONLY - -/* - This is free and unencumbered software released into the public domain. - - Anyone is free to copy, modify, publish, use, compile, sell, or - distribute this software, either in source code form or as a compiled - binary, for any purpose, commercial or non-commercial, and by any - means. - - In jurisdictions that recognize copyright laws, the author or authors - of this software dedicate any and all copyright interest in the - software to the public domain. We make this dedication for the benefit - of the public at large and to the detriment of our heirs and - successors. We intend this dedication to be an overt act of - relinquishment in perpetuity of all present and future rights to this - software under copyright law. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR - OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - - For more information, please refer to -*/ diff --git a/src/rustc/compiler_builtins_shim/Cargo.toml b/src/rustc/compiler_builtins_shim/Cargo.toml new file mode 100644 index 0000000000..e0026078a5 --- /dev/null +++ b/src/rustc/compiler_builtins_shim/Cargo.toml @@ -0,0 +1,24 @@ +# See libc_shim/Cargo.toml for why this exists + +[package] +name = "compiler_builtins" +authors = ["The Rust Project Developers"] +version = "0.0.0" +build = "../../libcompiler_builtins/build.rs" + +[lib] +path = "../../libcompiler_builtins/src/lib.rs" +test = false +doctest = false + +[dependencies] +core = { path = "../../libcore" } + +[build-dependencies] +gcc = "0.3" + +[features] +c = [] +default = ["c", "rustbuild", "compiler-builtins"] +rustbuild = [] +compiler-builtins = [] diff --git a/src/libflate/build.rs b/src/rustc/compiler_builtins_shim/build.rs similarity index 74% rename from src/libflate/build.rs rename to src/rustc/compiler_builtins_shim/build.rs index 78d2ef1e37..546f60482e 100644 --- a/src/libflate/build.rs +++ b/src/rustc/compiler_builtins_shim/build.rs @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate gcc; +#![deny(warnings)] + +// See comments in Cargo.toml for why this exists fn main() { - println!("cargo:rerun-if-changed=../rt/miniz.c"); - gcc::Config::new() - .file("../rt/miniz.c") - .compile("libminiz.a"); + println!("cargo:rustc-cfg=stdbuild"); + println!("cargo:rerun-if-changed=build.rs"); } diff --git a/src/rustllvm/.editorconfig b/src/rustllvm/.editorconfig new file mode 100644 index 0000000000..865cd45f70 --- /dev/null +++ b/src/rustllvm/.editorconfig @@ -0,0 +1,6 @@ +[*.{h,cpp}] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = space +indent_size = 2 diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index fdbe4e5f7a..7fb1eafb30 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -10,11 +10,14 @@ #include +#include + #include "rustllvm.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/AutoUpgrade.h" +#include "llvm/IR/AssemblyAnnotationWriter.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" @@ -503,8 +506,129 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, return LLVMRustResult::Success; } + +// Callback to demangle function name +// Parameters: +// * name to be demangled +// * name len +// * output buffer +// * output buffer len +// Returns len of demangled string, or 0 if demangle failed. +typedef size_t (*DemangleFn)(const char*, size_t, char*, size_t); + + +namespace { + +class RustAssemblyAnnotationWriter : public AssemblyAnnotationWriter { + DemangleFn Demangle; + std::vector Buf; + +public: + RustAssemblyAnnotationWriter(DemangleFn Demangle) : Demangle(Demangle) {} + + // Return empty string if demangle failed + // or if name does not need to be demangled + StringRef CallDemangle(StringRef name) { + if (!Demangle) { + return StringRef(); + } + + if (Buf.size() < name.size() * 2) { + // Semangled name usually shorter than mangled, + // but allocate twice as much memory just in case + Buf.resize(name.size() * 2); + } + + auto R = Demangle(name.data(), name.size(), Buf.data(), Buf.size()); + if (!R) { + // Demangle failed. + return StringRef(); + } + + auto Demangled = StringRef(Buf.data(), R); + if (Demangled == name) { + // Do not print anything if demangled name is equal to mangled. + return StringRef(); + } + + return Demangled; + } + + void emitFunctionAnnot(const Function *F, + formatted_raw_ostream &OS) override { + StringRef Demangled = CallDemangle(F->getName()); + if (Demangled.empty()) { + return; + } + + OS << "; " << Demangled << "\n"; + } + + void emitInstructionAnnot(const Instruction *I, + formatted_raw_ostream &OS) override { + const char *Name; + const Value *Value; + if (const CallInst *CI = dyn_cast(I)) { + Name = "call"; + Value = CI->getCalledValue(); + } else if (const InvokeInst* II = dyn_cast(I)) { + Name = "invoke"; + Value = II->getCalledValue(); + } else { + // Could demangle more operations, e. g. + // `store %place, @function`. + return; + } + + if (!Value->hasName()) { + return; + } + + StringRef Demangled = CallDemangle(Value->getName()); + if (Demangled.empty()) { + return; + } + + OS << "; " << Name << " " << Demangled << "\n"; + } +}; + +class RustPrintModulePass : public ModulePass { + raw_ostream* OS; + DemangleFn Demangle; +public: + static char ID; + RustPrintModulePass() : ModulePass(ID), OS(nullptr), Demangle(nullptr) {} + RustPrintModulePass(raw_ostream &OS, DemangleFn Demangle) + : ModulePass(ID), OS(&OS), Demangle(Demangle) {} + + bool runOnModule(Module &M) override { + RustAssemblyAnnotationWriter AW(Demangle); + + M.print(*OS, &AW, false); + + return false; + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } + + static StringRef name() { return "RustPrintModulePass"; } +}; + +} // namespace + +namespace llvm { + void initializeRustPrintModulePassPass(PassRegistry&); +} + +char RustPrintModulePass::ID = 0; +INITIALIZE_PASS(RustPrintModulePass, "print-rust-module", + "Print rust module to stderr", false, false) + extern "C" void LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M, - const char *Path) { + const char *Path, DemangleFn Demangle) { llvm::legacy::PassManager *PM = unwrap(PMR); std::string ErrorInfo; @@ -515,7 +639,7 @@ extern "C" void LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M, formatted_raw_ostream FOS(OS); - PM->add(createPrintModulePass(FOS)); + PM->add(new RustPrintModulePass(FOS, Demangle)); PM->run(*unwrap(M)); } diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 838c180c70..c11c5f4186 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -466,6 +466,10 @@ extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *Name, unwrap(M)->addModuleFlag(Module::Warning, Name, Value); } +extern "C" void LLVMRustMetadataAsValue(LLVMContextRef C, LLVMRustMetadataRef MD) { + wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD))); +} + extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) { return new DIBuilder(*unwrap(M)); } diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger index 82715fd964..6b410502e4 100644 --- a/src/rustllvm/llvm-rebuild-trigger +++ b/src/rustllvm/llvm-rebuild-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2017-06-28 +2017-07-12 diff --git a/src/stage0.txt b/src/stage0.txt index ea53c719bf..c884a217a6 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,9 +12,9 @@ # source tarball for a stable release you'll likely see `1.x.0` for rustc and # `0.x.0` for Cargo where they were released on `date`. -date: 2017-06-08 -rustc: 1.18.0 -cargo: 0.19.0 +date: 2017-07-20 +rustc: 1.19.0 +cargo: 0.20.0 # When making a stable release the process currently looks like: # diff --git a/src/test/COMPILER_TESTS.md b/src/test/COMPILER_TESTS.md index 58df1aae6d..0380454b82 100644 --- a/src/test/COMPILER_TESTS.md +++ b/src/test/COMPILER_TESTS.md @@ -37,7 +37,7 @@ The error levels that you can have are: Header commands specify something about the entire test file as a whole, instead of just a few lines inside the test. -* `ignore-X` where `X` is an architecture, OS or stage will ignore the test accordingly +* `ignore-X` where `X` is a target detail or stage will ignore the test accordingly (see below) * `ignore-pretty` will not compile the pretty-printed test (this is done to test the pretty-printer, but might not always work) * `ignore-test` always ignores the test * `ignore-lldb` and `ignore-gdb` will skip the debuginfo tests @@ -50,6 +50,14 @@ whole, instead of just a few lines inside the test. feature is attempted without the proper `#![feature(X)]` tag. Each unstable lang feature is required to have a gate test. +Some examples of `X` in `ignore-X`: + +* Architecture: `aarch64`, `arm`, `asmjs`, `mips`, `wasm32`, `x86_64`, `x86`, ... +* OS: `android`, `emscripten`, `freebsd`, `ios`, `linux`, `macos`, `windows`, ... +* Environment (fourth word of the target triple): `gnu`, `msvc`, `musl`. +* Pointer width: `32bit`, `64bit`. +* Stage: `stage0`, `stage1`, `stage2`. + ## Revisions Certain classes of tests support "revisions" (as of the time of this @@ -86,3 +94,66 @@ For example, the `ignore-test` header (and all "ignore" headers) currently only apply to the test as a whole, not to particular revisions. The only headers that are intended to really work when customized to a revision are error patterns and compiler flags. + +## Guide to the UI Tests + +The UI tests are intended to capture the compiler's complete output, +so that we can test all aspects of the presentation. They work by +compiling a file (e.g., `ui/hello_world/main.rs`), capturing the output, +and then applying some normalization (see below). This normalized +result is then compared against reference files named +`ui/hello_world/main.stderr` and `ui/hello_world/main.stdout`. If either of +those files doesn't exist, the output must be empty. If the test run +fails, we will print out the current output, but it is also saved in +`build//test/ui/hello_world/main.stdout` (this path is +printed as part of the test failure mesage), so you can run `diff` and +so forth. + +### Editing and updating the reference files + +If you have changed the compiler's output intentionally, or you are +making a new test, you can use the script `ui/update-references.sh` to +update the references. When you run the test framework, it will report +various errors: in those errors is a command you can use to run the +`ui/update-references.sh` script, which will then copy over the files +from the build directory and use them as the new reference. You can +also just run `ui/update-all-references.sh`. In both cases, you can run +the script with `--help` to get a help message. + +### Normalization + +The normalization applied is aimed at eliminating output difference +between platforms, mainly about filenames: + +- the test directory is replaced with `$DIR` +- all backslashes (`\`) are converted to forward slashes (`/`) (for Windows) +- all CR LF newlines are converted to LF + +Sometimes these built-in normalizations are not enough. In such cases, you +may provide custom normalization rules using the header commands, e.g. + +``` +// normalize-stderr-32bit: "fn() (32 bits)" -> "fn() ($PTR bits)" +// normalize-stderr-64bit: "fn() (64 bits)" -> "fn() ($PTR bits)" +``` + +This tells the test, on 32-bit platforms, whenever the compiler writes +`fn() (32 bits)` to stderr, it should be normalized to read `fn() ($PTR bits)` +instead. Similar for 64-bit. + +The corresponding reference file will use the normalized output to test both +32-bit and 64-bit platforms: + +``` +... + | + = note: source type: fn() ($PTR bits) + = note: target type: u16 (16 bits) +... +``` + +Please see `ui/transmute/main.rs` and `.stderr` for a concrete usage example. + +Besides `normalize-stderr-32bit` and `-64bit`, one may use any target +information or stage supported by `ignore-X` here as well (e.g. +`normalize-stderr-windows`). diff --git a/src/test/codegen-units/item-collection/function-as-argument.rs b/src/test/codegen-units/item-collection/function-as-argument.rs index c4aed7465b..c3d46ff531 100644 --- a/src/test/codegen-units/item-collection/function-as-argument.rs +++ b/src/test/codegen-units/item-collection/function-as-argument.rs @@ -28,12 +28,12 @@ fn main() { //~ TRANS_ITEM fn function_as_argument::take_fn_once[0] //~ TRANS_ITEM fn function_as_argument::function[0] - //~ TRANS_ITEM fn core::ops[0]::FnOnce[0]::call_once[0] + //~ TRANS_ITEM fn core::ops[0]::function[0]::FnOnce[0]::call_once[0] take_fn_once(function, 0u32, "abc"); //~ TRANS_ITEM fn function_as_argument::take_fn_once[0] //~ TRANS_ITEM fn function_as_argument::function[0] - //~ TRANS_ITEM fn core::ops[0]::FnOnce[0]::call_once[0] + //~ TRANS_ITEM fn core::ops[0]::function[0]::FnOnce[0]::call_once[0] take_fn_once(function, 'c', 0f64); //~ TRANS_ITEM fn function_as_argument::take_fn_pointer[0] diff --git a/src/test/codegen-units/item-collection/trait-method-as-argument.rs b/src/test/codegen-units/item-collection/trait-method-as-argument.rs index f095b637a8..21c9c254e5 100644 --- a/src/test/codegen-units/item-collection/trait-method-as-argument.rs +++ b/src/test/codegen-units/item-collection/trait-method-as-argument.rs @@ -40,27 +40,27 @@ fn take_foo_mut T>(mut f: F, arg: T) -> T { fn main() { //~ TRANS_ITEM fn trait_method_as_argument::take_foo_once[0] u32> //~ TRANS_ITEM fn trait_method_as_argument::{{impl}}[0]::foo[0] - //~ TRANS_ITEM fn core::ops[0]::FnOnce[0]::call_once[0] u32, (u32)> + //~ TRANS_ITEM fn core::ops[0]::function[0]::FnOnce[0]::call_once[0] u32, (u32)> take_foo_once(Trait::foo, 0u32); //~ TRANS_ITEM fn trait_method_as_argument::take_foo_once[0] char> //~ TRANS_ITEM fn trait_method_as_argument::Trait[0]::foo[0] - //~ TRANS_ITEM fn core::ops[0]::FnOnce[0]::call_once[0] char, (char)> + //~ TRANS_ITEM fn core::ops[0]::function[0]::FnOnce[0]::call_once[0] char, (char)> take_foo_once(Trait::foo, 'c'); //~ TRANS_ITEM fn trait_method_as_argument::take_foo[0] u32> - //~ TRANS_ITEM fn core::ops[0]::Fn[0]::call[0] u32, (u32)> + //~ TRANS_ITEM fn core::ops[0]::function[0]::Fn[0]::call[0] u32, (u32)> take_foo(Trait::foo, 0u32); //~ TRANS_ITEM fn trait_method_as_argument::take_foo[0] char> - //~ TRANS_ITEM fn core::ops[0]::Fn[0]::call[0] char, (char)> + //~ TRANS_ITEM fn core::ops[0]::function[0]::Fn[0]::call[0] char, (char)> take_foo(Trait::foo, 'c'); //~ TRANS_ITEM fn trait_method_as_argument::take_foo_mut[0] u32> - //~ TRANS_ITEM fn core::ops[0]::FnMut[0]::call_mut[0] char, (char)> + //~ TRANS_ITEM fn core::ops[0]::function[0]::FnMut[0]::call_mut[0] char, (char)> take_foo_mut(Trait::foo, 0u32); //~ TRANS_ITEM fn trait_method_as_argument::take_foo_mut[0] char> - //~ TRANS_ITEM fn core::ops[0]::FnMut[0]::call_mut[0] u32, (u32)> + //~ TRANS_ITEM fn core::ops[0]::function[0]::FnMut[0]::call_mut[0] u32, (u32)> take_foo_mut(Trait::foo, 'c'); } diff --git a/src/test/codegen/alloc-optimisation.rs b/src/test/codegen/alloc-optimisation.rs new file mode 100644 index 0000000000..07dc135071 --- /dev/null +++ b/src/test/codegen/alloc-optimisation.rs @@ -0,0 +1,22 @@ +// 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. +// +// no-system-llvm +// compile-flags: -O +#![crate_type="lib"] + +#[no_mangle] +pub fn alloc_test(data: u32) { + // CHECK-LABEL: @alloc_test + // CHECK-NEXT: start: + // CHECK-NEXT: ret void + let x = Box::new(data); + drop(x); +} diff --git a/src/test/codegen/dealloc-no-unwind.rs b/src/test/codegen/dealloc-no-unwind.rs new file mode 100644 index 0000000000..551b66e103 --- /dev/null +++ b/src/test/codegen/dealloc-no-unwind.rs @@ -0,0 +1,32 @@ +// 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. +// +// no-system-llvm +// compile-flags: -O + +#![crate_type="lib"] + +struct A; + +impl Drop for A { + fn drop(&mut self) { + extern { fn foo(); } + unsafe { foo(); } + } +} + +#[no_mangle] +pub fn a(a: Box) { + // CHECK-LABEL: define void @a + // CHECK: call void @__rust_dealloc + // CHECK-NEXT: call void @foo + let _a = A; + drop(a); +} diff --git a/src/test/codegen/drop.rs b/src/test/codegen/drop.rs index d7e2cb6d9a..1961060c2c 100644 --- a/src/test/codegen/drop.rs +++ b/src/test/codegen/drop.rs @@ -32,9 +32,9 @@ pub fn droppy() { // CHECK-NOT: invoke{{.*}}drop{{.*}}SomeUniqueName // CHECK: call{{.*}}drop{{.*}}SomeUniqueName // CHECK: call{{.*}}drop{{.*}}SomeUniqueName -// CHECK: call{{.*}}drop{{.*}}SomeUniqueName // CHECK-NOT: call{{.*}}drop{{.*}}SomeUniqueName // CHECK: invoke{{.*}}drop{{.*}}SomeUniqueName +// CHECK: call{{.*}}drop{{.*}}SomeUniqueName // CHECK: invoke{{.*}}drop{{.*}}SomeUniqueName // CHECK: call{{.*}}drop{{.*}}SomeUniqueName // CHECK-NOT: {{(call|invoke).*}}drop{{.*}}SomeUniqueName diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs index bc84ac49da..d8bbcd9b73 100644 --- a/src/test/codegen/function-arguments.rs +++ b/src/test/codegen/function-arguments.rs @@ -11,7 +11,7 @@ // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] -#![feature(allocator)] +#![feature(custom_attribute)] pub struct S { _field: [i64; 4], diff --git a/src/test/codegen/issue-37945.rs b/src/test/codegen/issue-37945.rs new file mode 100644 index 0000000000..e7c91f3091 --- /dev/null +++ b/src/test/codegen/issue-37945.rs @@ -0,0 +1,36 @@ +// 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. + +// min-llvm-version 4.0 +// compile-flags: -O +// ignore-x86 +// ignore-arm +// ignore-emscripten +// ignore 32-bit platforms (LLVM has a bug with them) + +// See issue #37945. + +#![crate_type = "lib"] + +use std::slice::Iter; + +// CHECK-LABEL: @is_empty_1 +#[no_mangle] +pub fn is_empty_1(xs: Iter) -> bool { +// CHECK-NOT: icmp eq float* {{.*}}, null + {xs}.next().is_none() +} + +// CHECK-LABEL: @is_empty_2 +#[no_mangle] +pub fn is_empty_2(xs: Iter) -> bool { +// CHECK-NOT: icmp eq float* {{.*}}, null + xs.map(|&x| x).next().is_none() +} diff --git a/src/test/codegen/mir_zst_stores.rs b/src/test/codegen/mir_zst_stores.rs index a2cedc853a..36602196ce 100644 --- a/src/test/codegen/mir_zst_stores.rs +++ b/src/test/codegen/mir_zst_stores.rs @@ -13,13 +13,15 @@ #![crate_type = "lib"] use std::marker::PhantomData; - +#[derive(Copy, Clone)] struct Zst { phantom: PhantomData } // CHECK-LABEL: @mir +// CHECK-NOT: store{{.*}}undef #[no_mangle] -fn mir(){ - // CHECK-NOT: getelementptr - // CHECK-NOT: store{{.*}}undef +fn mir() { let x = Zst { phantom: PhantomData }; + let y = (x, 0); + drop(y); + drop((0, x)); } diff --git a/src/test/compile-fail/allocator-depends-on-needs-allocators.rs b/src/test/codegen/stack-probes.rs similarity index 53% rename from src/test/compile-fail/allocator-depends-on-needs-allocators.rs rename to src/test/codegen/stack-probes.rs index 7f420ff735..b7c794f447 100644 --- a/src/test/compile-fail/allocator-depends-on-needs-allocators.rs +++ b/src/test/codegen/stack-probes.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,14 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: `allocator3` cannot depend on a crate that needs an allocator -// aux-build:needs_allocator.rs -// aux-build:allocator3.rs +// ignore-arm +// ignore-wasm +// ignore-emscripten +// ignore-windows +// no-system-llvm +// compile-flags: -C no-prepopulate-passes -// The needs_allocator crate is a dependency of the allocator crate allocator3, -// which is not allowed +#![crate_type = "lib"] -extern crate allocator3; - -fn main() { +#[no_mangle] +pub fn foo() { +// CHECK: @foo() unnamed_addr #0 +// CHECK: attributes #0 = { {{.*}}"probe-stack"="__rust_probestack"{{.*}} } } diff --git a/src/test/codegen/vec-optimizes-away.rs b/src/test/codegen/vec-optimizes-away.rs new file mode 100644 index 0000000000..261564ed51 --- /dev/null +++ b/src/test/codegen/vec-optimizes-away.rs @@ -0,0 +1,21 @@ +// 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. +// +// no-system-llvm +// compile-flags: -O +#![crate_type="lib"] + +#[no_mangle] +pub fn sum_me() -> i32 { + // CHECK-LABEL: @sum_me + // CHECK-NEXT: {{^.*:$}} + // CHECK-NEXT: ret i32 6 + vec![1, 2, 3].iter().sum::() +} diff --git a/src/test/compile-fail-fulldeps/auxiliary/use_from_trait_xc.rs b/src/test/compile-fail-fulldeps/auxiliary/use_from_trait_xc.rs index 7024c9dad7..9a6d176d08 100644 --- a/src/test/compile-fail-fulldeps/auxiliary/use_from_trait_xc.rs +++ b/src/test/compile-fail-fulldeps/auxiliary/use_from_trait_xc.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] pub use self::sub::{Bar, Baz}; diff --git a/src/test/compile-fail-fulldeps/derive-no-std-not-supported.rs b/src/test/compile-fail-fulldeps/derive-no-std-not-supported.rs index 6ae5544d68..1e97cb07f8 100644 --- a/src/test/compile-fail-fulldeps/derive-no-std-not-supported.rs +++ b/src/test/compile-fail-fulldeps/derive-no-std-not-supported.rs @@ -10,7 +10,6 @@ #![no_std] -extern crate rand; extern crate serialize as rustc_serialize; #[derive(RustcEncodable)] //~ ERROR this trait cannot be derived diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/bang_proc_macro2.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/bang_proc_macro2.rs new file mode 100644 index 0000000000..5fc20bcda8 --- /dev/null +++ b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/bang_proc_macro2.rs @@ -0,0 +1,23 @@ +// 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. + +// force-host +// no-prefer-dynamic +#![feature(proc_macro)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro] +pub fn bang_proc_macro2(_: TokenStream) -> TokenStream { + "let x = foobar2;".parse().unwrap() +} diff --git a/src/test/compile-fail-fulldeps/proc-macro/lints_in_proc_macros.rs b/src/test/compile-fail-fulldeps/proc-macro/lints_in_proc_macros.rs new file mode 100644 index 0000000000..93dead1a15 --- /dev/null +++ b/src/test/compile-fail-fulldeps/proc-macro/lints_in_proc_macros.rs @@ -0,0 +1,26 @@ +// 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. + +// aux-build:bang_proc_macro2.rs + +#![feature(proc_macro)] +#![allow(unused_macros)] + +extern crate bang_proc_macro2; + +use bang_proc_macro2::bang_proc_macro2; + +fn main() { + let foobar = 42; + bang_proc_macro2!(); + //~^ ERROR cannot find value `foobar2` in this scope + //~^^ did you mean `foobar`? + println!("{}", x); +} diff --git a/src/test/compile-fail-fulldeps/proc-macro/shadow.rs b/src/test/compile-fail-fulldeps/proc-macro/shadow.rs index d76cf003ed..9bff1c57ae 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/shadow.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/shadow.rs @@ -13,6 +13,6 @@ #[macro_use] extern crate derive_a; #[macro_use] -extern crate derive_a; //~ ERROR `derive_a` has already been imported +extern crate derive_a; //~ ERROR the name `derive_a` is defined multiple times fn main() {} diff --git a/src/test/compile-fail/E0164.rs b/src/test/compile-fail/E0164.rs index 8d21cde84d..cf6cf15115 100644 --- a/src/test/compile-fail/E0164.rs +++ b/src/test/compile-fail/E0164.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] enum Foo {} diff --git a/src/test/compile-fail/E0254.rs b/src/test/compile-fail/E0254.rs index fe7ee1c129..89227f6b01 100644 --- a/src/test/compile-fail/E0254.rs +++ b/src/test/compile-fail/E0254.rs @@ -8,19 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections)] +#![feature(alloc)] -extern crate collections; -//~^ NOTE previous import of `collections` here +extern crate alloc; +//~^ NOTE previous import of the extern crate `alloc` here mod foo { - pub trait collections { + pub trait alloc { fn do_something(); } } -use foo::collections; +use foo::alloc; //~^ ERROR E0254 -//~| NOTE already imported +//~| NOTE `alloc` reimported here +//~| NOTE `alloc` must be defined only once in the type namespace of this module fn main() {} diff --git a/src/test/compile-fail/E0259.rs b/src/test/compile-fail/E0259.rs index b2129902ef..60bcd2ae07 100644 --- a/src/test/compile-fail/E0259.rs +++ b/src/test/compile-fail/E0259.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections, libc)] +#![feature(alloc, libc)] -extern crate collections; -//~^ NOTE previous import of `collections` here +extern crate alloc; +//~^ NOTE previous import of the extern crate `alloc` here -extern crate libc as collections; +extern crate libc as alloc; //~^ ERROR E0259 -//~| NOTE `collections` already imported +//~| NOTE `alloc` reimported here +//~| NOTE `alloc` must be defined only once in the type namespace of this module fn main() {} diff --git a/src/test/compile-fail/E0260.rs b/src/test/compile-fail/E0260.rs index ae018d2ada..5e802bbbe3 100644 --- a/src/test/compile-fail/E0260.rs +++ b/src/test/compile-fail/E0260.rs @@ -8,14 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections)] +#![feature(alloc)] -extern crate collections; -//~^ NOTE previous import of `collections` here +extern crate alloc; +//~^ NOTE previous import of the extern crate `alloc` here -mod collections { -//~^ ERROR `collections` has already been imported in this module [E0260] -//~| NOTE `collections` already imported +mod alloc { +//~^ ERROR the name `alloc` is defined multiple times [E0260] +//~| NOTE `alloc` redefined here +//~| NOTE `alloc` must be defined only once in the type namespace of this module pub trait MyTrait { fn do_something(); } diff --git a/src/test/compile-fail/E0428.rs b/src/test/compile-fail/E0428.rs index f8502140c4..4042219b5c 100644 --- a/src/test/compile-fail/E0428.rs +++ b/src/test/compile-fail/E0428.rs @@ -8,9 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Bar; //~ previous definition of `Bar` here +struct Bar; //~ previous definition of the type `Bar` here struct Bar; //~ ERROR E0428 - //~| NOTE already defined + //~| NOTE `Bar` redefined here + //~| NOTE `Bar` must be defined only once in the type namespace of this module fn main () { } diff --git a/src/test/compile-fail/E0429.rs b/src/test/compile-fail/E0429.rs index a7d19744f3..f1cad200be 100644 --- a/src/test/compile-fail/E0429.rs +++ b/src/test/compile-fail/E0429.rs @@ -9,7 +9,6 @@ // except according to those terms. use std::fmt::self; //~ ERROR E0429 - //~^ ERROR E0432 fn main () { } diff --git a/src/test/compile-fail/E0435.rs b/src/test/compile-fail/E0435.rs index b15bf44fbd..50a6d174e2 100644 --- a/src/test/compile-fail/E0435.rs +++ b/src/test/compile-fail/E0435.rs @@ -11,5 +11,5 @@ fn main () { let foo = 42u32; let _: [u8; foo]; //~ ERROR E0435 - //~| NOTE non-constant used with constant + //~| NOTE non-constant value } diff --git a/src/test/compile-fail/E0438.rs b/src/test/compile-fail/E0438.rs index 2e2df4bee5..99e0dbbcea 100644 --- a/src/test/compile-fail/E0438.rs +++ b/src/test/compile-fail/E0438.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] trait Bar {} diff --git a/src/test/compile-fail/E0512.rs b/src/test/compile-fail/E0512.rs index 2b89873ee4..25f9627164 100644 --- a/src/test/compile-fail/E0512.rs +++ b/src/test/compile-fail/E0512.rs @@ -12,5 +12,4 @@ fn takes_u8(_: u8) {} fn main() { unsafe { takes_u8(::std::mem::transmute(0u16)); } //~ ERROR E0512 - //~| transmuting between 16 bits and 8 bits } diff --git a/src/test/compile-fail/E0602.rs b/src/test/compile-fail/E0602.rs new file mode 100644 index 0000000000..cc3e436d43 --- /dev/null +++ b/src/test/compile-fail/E0602.rs @@ -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. + +// compile-flags:-D bogus + +// error-pattern:E0602 +// error-pattern:requested on the command line with `-D bogus` + +fn main() {} diff --git a/src/test/compile-fail/E0604.rs b/src/test/compile-fail/E0604.rs new file mode 100644 index 0000000000..c5bf3a77b6 --- /dev/null +++ b/src/test/compile-fail/E0604.rs @@ -0,0 +1,13 @@ +// 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. + +fn main() { + 1u32 as char; //~ ERROR E0604 +} diff --git a/src/test/compile-fail/E0605.rs b/src/test/compile-fail/E0605.rs new file mode 100644 index 0000000000..add3fd8fd8 --- /dev/null +++ b/src/test/compile-fail/E0605.rs @@ -0,0 +1,19 @@ +// 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. + +fn main() { + let x = 0u8; + x as Vec; //~ ERROR E0605 + //~| NOTE an `as` expression can only be used to convert between primitive types + + let v = 0 as *const u8; + v as &u8; //~ ERROR E0605 + //~| NOTE an `as` expression can only be used to convert between primitive types +} diff --git a/src/test/compile-fail/E0606.rs b/src/test/compile-fail/E0606.rs new file mode 100644 index 0000000000..55071736bf --- /dev/null +++ b/src/test/compile-fail/E0606.rs @@ -0,0 +1,13 @@ +// 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. + +fn main() { + &0u8 as u8; //~ ERROR E0606 +} diff --git a/src/test/compile-fail/E0607.rs b/src/test/compile-fail/E0607.rs new file mode 100644 index 0000000000..fa761f2c17 --- /dev/null +++ b/src/test/compile-fail/E0607.rs @@ -0,0 +1,14 @@ +// 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. + +fn main() { + let v = 0 as *const u8; + v as *const [u8]; //~ ERROR E0607 +} diff --git a/src/test/compile-fail/E0608.rs b/src/test/compile-fail/E0608.rs new file mode 100644 index 0000000000..d47356a97e --- /dev/null +++ b/src/test/compile-fail/E0608.rs @@ -0,0 +1,13 @@ +// 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. + +fn main() { + 0u8[2]; //~ ERROR E0608 +} diff --git a/src/test/compile-fail/E0609.rs b/src/test/compile-fail/E0609.rs new file mode 100644 index 0000000000..ddfd9d5f21 --- /dev/null +++ b/src/test/compile-fail/E0609.rs @@ -0,0 +1,22 @@ +// 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. + +struct Foo { + x: u32, +} +struct Bar; + +fn main() { + let x = Foo { x: 0 }; + let _ = x.foo; //~ ERROR E0609 + + let y = Bar; + y.1; //~ ERROR E0609 +} diff --git a/src/test/compile-fail/E0610.rs b/src/test/compile-fail/E0610.rs new file mode 100644 index 0000000000..522d8b0b94 --- /dev/null +++ b/src/test/compile-fail/E0610.rs @@ -0,0 +1,14 @@ +// 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. + +fn main() { + let x = 0; + let _ = x.foo; //~ ERROR E0610 +} diff --git a/src/test/compile-fail/E0611.rs b/src/test/compile-fail/E0611.rs new file mode 100644 index 0000000000..1e392d194b --- /dev/null +++ b/src/test/compile-fail/E0611.rs @@ -0,0 +1,22 @@ +// 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. + +mod a { + pub struct Foo(u32); + + impl Foo { + pub fn new() -> Foo { Foo(0) } + } +} + +fn main() { + let y = a::Foo::new(); + y.0; //~ ERROR E0611 +} diff --git a/src/test/compile-fail/E0612.rs b/src/test/compile-fail/E0612.rs new file mode 100644 index 0000000000..429a8bb7eb --- /dev/null +++ b/src/test/compile-fail/E0612.rs @@ -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. + +struct Foo(u32); + +fn main() { + let y = Foo(0); + y.1; //~ ERROR E0612 +} diff --git a/src/test/compile-fail/E0614.rs b/src/test/compile-fail/E0614.rs new file mode 100644 index 0000000000..909f0eb828 --- /dev/null +++ b/src/test/compile-fail/E0614.rs @@ -0,0 +1,14 @@ +// 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. + +fn main() { + let y = 0u32; + *y; //~ ERROR E0614 +} diff --git a/src/test/compile-fail/E0615.rs b/src/test/compile-fail/E0615.rs new file mode 100644 index 0000000000..abfa93d2fd --- /dev/null +++ b/src/test/compile-fail/E0615.rs @@ -0,0 +1,22 @@ +// 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. + +struct Foo { + x: u32, +} + +impl Foo { + fn method(&self) {} +} + +fn main() { + let f = Foo { x: 0 }; + f.method; //~ ERROR E0615 +} diff --git a/src/test/compile-fail/E0616.rs b/src/test/compile-fail/E0616.rs new file mode 100644 index 0000000000..2fd9f94763 --- /dev/null +++ b/src/test/compile-fail/E0616.rs @@ -0,0 +1,24 @@ +// 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. + +mod a { + pub struct Foo { + x: u32, + } + + impl Foo { + pub fn new() -> Foo { Foo { x: 0 } } + } +} + +fn main() { + let f = a::Foo::new(); + f.x; //~ ERROR E0616 +} diff --git a/src/test/compile-fail/E0617.rs b/src/test/compile-fail/E0617.rs new file mode 100644 index 0000000000..7b769ff4ae --- /dev/null +++ b/src/test/compile-fail/E0617.rs @@ -0,0 +1,32 @@ +// 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. + +// ignore-tidy-linelength + +extern { + fn printf(c: *const i8, ...); +} + +fn main() { + unsafe { + printf(::std::ptr::null(), 0f32); + //~^ ERROR can't pass `f32` to variadic function, cast to `c_double` [E0617] + printf(::std::ptr::null(), 0i8); + //~^ ERROR can't pass `i8` to variadic function, cast to `c_int` [E0617] + printf(::std::ptr::null(), 0i16); + //~^ ERROR can't pass `i16` to variadic function, cast to `c_int` [E0617] + printf(::std::ptr::null(), 0u8); + //~^ ERROR can't pass `u8` to variadic function, cast to `c_uint` [E0617] + printf(::std::ptr::null(), 0u16); + //~^ ERROR can't pass `u16` to variadic function, cast to `c_uint` [E0617] + printf(::std::ptr::null(), printf); + //~^ ERROR can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function, cast to `unsafe extern "C" fn(*const i8, ...)` [E0617] + } +} diff --git a/src/test/run-pass/allocator-default.rs b/src/test/compile-fail/E0618.rs similarity index 58% rename from src/test/run-pass/allocator-default.rs rename to src/test/compile-fail/E0618.rs index 0a02e8072b..1ba2e8e2e5 100644 --- a/src/test/run-pass/allocator-default.rs +++ b/src/test/compile-fail/E0618.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,12 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(alloc_jemalloc)] - -#[cfg(any(all(target_os = "linux", any(target_arch = "x86", target_arch = "x86_64")), - target_os = "macos"))] -extern crate alloc_jemalloc; +enum X { + Entry, +} fn main() { - println!("{:?}", Box::new(3)); + X::Entry(); //~ ERROR expected function, found `X::Entry` [E0618] + //~| HELP did you mean to write `X::Entry`? + let x = 0i32; + x(); //~ ERROR expected function, found `i32` [E0618] } diff --git a/src/test/compile-fail/E0619.rs b/src/test/compile-fail/E0619.rs new file mode 100644 index 0000000000..a5a5ff7218 --- /dev/null +++ b/src/test/compile-fail/E0619.rs @@ -0,0 +1,19 @@ +// 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. + +fn main() { + let x; + + match x { + (..) => {} //~ ERROR E0619 + _ => {} + } +} + diff --git a/src/test/compile-fail/E0620.rs b/src/test/compile-fail/E0620.rs new file mode 100644 index 0000000000..5e945dfa5c --- /dev/null +++ b/src/test/compile-fail/E0620.rs @@ -0,0 +1,13 @@ +// 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. + +fn main() { + let _foo = &[1_usize, 2] as [usize]; //~ ERROR E0620 +} diff --git a/src/test/compile-fail/E0621-does-not-trigger-for-closures.rs b/src/test/compile-fail/E0621-does-not-trigger-for-closures.rs new file mode 100644 index 0000000000..980461beda --- /dev/null +++ b/src/test/compile-fail/E0621-does-not-trigger-for-closures.rs @@ -0,0 +1,28 @@ +// 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. + +// Test that we give the generic E0495 when one of the free regions is +// bound in a closure (rather than suggesting a change to the signature +// of the closure, which is not specified in `foo` but rather in `invoke`). + +// FIXME - This might be better as a UI test, but the finer details +// of the error seem to vary on different machines. +fn invoke<'a, F>(x: &'a i32, f: F) -> &'a i32 +where F: FnOnce(&'a i32, &i32) -> &'a i32 +{ + let y = 22; + f(x, &y) +} + +fn foo<'a>(x: &'a i32) { + invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495 +} + +fn main() {} diff --git a/src/test/compile-fail/invalid-intrinsic.rs b/src/test/compile-fail/E0622.rs similarity index 86% rename from src/test/compile-fail/invalid-intrinsic.rs rename to src/test/compile-fail/E0622.rs index 2aa2546cb9..f2bde5b036 100644 --- a/src/test/compile-fail/invalid-intrinsic.rs +++ b/src/test/compile-fail/E0622.rs @@ -11,6 +11,6 @@ #![feature(intrinsics)] extern "rust-intrinsic" { pub static breakpoint : unsafe extern "rust-intrinsic" fn(); - //~^ ERROR intrinsic has wrong type + //~^ ERROR intrinsic must be a function [E0622] } -fn main() { unsafe { breakpoint(); } } \ No newline at end of file +fn main() { unsafe { breakpoint(); } } diff --git a/src/test/compile-fail/allocator-dylib-is-system.rs b/src/test/compile-fail/allocator-dylib-is-system.rs deleted file mode 100644 index 31009554c6..0000000000 --- a/src/test/compile-fail/allocator-dylib-is-system.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// ignore-musl no dylibs -// aux-build:allocator-dylib.rs -// aux-build:allocator1.rs -// no-prefer-dynamic -// error-pattern: cannot link together two allocators - -// Verify that the allocator for statically linked dynamic libraries is the -// system allocator. Do this by linking in jemalloc and making sure that we get -// an error. - -// ignore-emscripten FIXME: What "other allocator" should we use for emcc? - -#![feature(alloc_jemalloc)] - -extern crate allocator_dylib; - -// The main purpose of this test is to ensure that `alloc_jemalloc` **fails** -// here (specifically the jemalloc allocator), but currently jemalloc is -// disabled on quite a few platforms (bsds, emscripten, msvc, etc). To ensure -// that this just passes on those platforms we link in some other allocator to -// ensure we get the same error. -// -// So long as we CI linux/macOS we should be good. -#[cfg(any(target_os = "linux", target_os = "macos"))] -extern crate alloc_jemalloc; -#[cfg(not(any(target_os = "linux", target_os = "macos")))] -extern crate allocator1; - -fn main() { - allocator_dylib::foo(); -} diff --git a/src/test/compile-fail/allocator-rust-dylib-is-jemalloc.rs b/src/test/compile-fail/allocator-rust-dylib-is-jemalloc.rs deleted file mode 100644 index 68e01bad96..0000000000 --- a/src/test/compile-fail/allocator-rust-dylib-is-jemalloc.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// ignore-musl no dylibs -// aux-build:allocator-dylib2.rs -// aux-build:allocator1.rs -// error-pattern: cannot link together two allocators - -// Ensure that rust dynamic libraries use jemalloc as their allocator, verifying -// by linking in the system allocator here and ensuring that we get a complaint. - -// ignore-emscripten FIXME: What "other allocator" is correct for emscripten? - -#![feature(alloc_system)] - -extern crate allocator_dylib2; - -// The main purpose of this test is to ensure that `alloc_system` **fails** -// here (specifically the system allocator), but currently system is -// disabled on quite a few platforms (bsds, emscripten, msvc, etc). To ensure -// that this just passes on those platforms we link in some other allocator to -// ensure we get the same error. -// -// So long as we CI linux/macOS we should be good. -#[cfg(any(all(target_os = "linux", any(target_arch = "x86", target_arch = "x86_64")), - target_os = "macos"))] -extern crate alloc_system; -#[cfg(not(any(all(target_os = "linux", any(target_arch = "x86", target_arch = "x86_64")), - target_os = "macos")))] -extern crate allocator1; - -fn main() { - allocator_dylib2::foo(); -} diff --git a/src/test/compile-fail/auxiliary/allocator3.rs b/src/test/compile-fail/allocator/auxiliary/system-allocator.rs similarity index 71% rename from src/test/compile-fail/auxiliary/allocator3.rs rename to src/test/compile-fail/allocator/auxiliary/system-allocator.rs index d3eb1f6f7a..4761dc421d 100644 --- a/src/test/compile-fail/auxiliary/allocator3.rs +++ b/src/test/compile-fail/allocator/auxiliary/system-allocator.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -10,10 +10,10 @@ // no-prefer-dynamic -#![feature(allocator)] -#![no_std] -#![allocator] +#![feature(global_allocator, allocator_api)] #![crate_type = "rlib"] -extern crate needs_allocator; +use std::heap::System; +#[global_allocator] +static A: System = System; diff --git a/src/test/compile-fail/allocator/auxiliary/system-allocator2.rs b/src/test/compile-fail/allocator/auxiliary/system-allocator2.rs new file mode 100644 index 0000000000..4761dc421d --- /dev/null +++ b/src/test/compile-fail/allocator/auxiliary/system-allocator2.rs @@ -0,0 +1,19 @@ +// 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. + +// no-prefer-dynamic + +#![feature(global_allocator, allocator_api)] +#![crate_type = "rlib"] + +use std::heap::System; + +#[global_allocator] +static A: System = System; diff --git a/src/test/compile-fail/allocator/function-allocator.rs b/src/test/compile-fail/allocator/function-allocator.rs new file mode 100644 index 0000000000..50f82607b5 --- /dev/null +++ b/src/test/compile-fail/allocator/function-allocator.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. + +#![feature(global_allocator)] + +#[global_allocator] +fn foo() {} //~ ERROR: allocators must be statics + +fn main() {} diff --git a/src/test/compile-fail/allocator/not-an-allocator.rs b/src/test/compile-fail/allocator/not-an-allocator.rs new file mode 100644 index 0000000000..e430143506 --- /dev/null +++ b/src/test/compile-fail/allocator/not-an-allocator.rs @@ -0,0 +1,26 @@ +// 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. + +#![feature(global_allocator, heap_api)] + +#[global_allocator] +static A: usize = 0; +//~^ the trait bound `&usize: +//~| the trait bound `&usize: +//~| the trait bound `&usize: +//~| the trait bound `&usize: +//~| the trait bound `&usize: +//~| the trait bound `&usize: +//~| the trait bound `&usize: +//~| the trait bound `&usize: +//~| the trait bound `&usize: +//~| the trait bound `&usize: + +fn main() {} diff --git a/src/test/compile-fail/allocator/two-allocators.rs b/src/test/compile-fail/allocator/two-allocators.rs new file mode 100644 index 0000000000..b46ba6334a --- /dev/null +++ b/src/test/compile-fail/allocator/two-allocators.rs @@ -0,0 +1,22 @@ +// 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. + +#![feature(global_allocator, allocator_api)] + +use std::heap::System; + +#[global_allocator] +static A: System = System; +#[global_allocator] +static B: System = System; +//~^ ERROR: cannot define more than one #[global_allocator] + +fn main() {} + diff --git a/src/test/compile-fail/allocator/two-allocators2.rs b/src/test/compile-fail/allocator/two-allocators2.rs new file mode 100644 index 0000000000..e342c1f9c4 --- /dev/null +++ b/src/test/compile-fail/allocator/two-allocators2.rs @@ -0,0 +1,25 @@ +// 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. + +// aux-build:system-allocator.rs +// no-prefer-dynamic +// error-pattern: the #[global_allocator] in + +#![feature(global_allocator, allocator_api)] + +extern crate system_allocator; + +use std::heap::System; + +#[global_allocator] +static A: System = System; + +fn main() {} + diff --git a/src/test/compile-fail/allocator/two-allocators3.rs b/src/test/compile-fail/allocator/two-allocators3.rs new file mode 100644 index 0000000000..c310d94f6d --- /dev/null +++ b/src/test/compile-fail/allocator/two-allocators3.rs @@ -0,0 +1,21 @@ +// 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. + +// aux-build:system-allocator.rs +// aux-build:system-allocator2.rs +// no-prefer-dynamic +// error-pattern: the #[global_allocator] in + +#![feature(global_allocator)] + +extern crate system_allocator; +extern crate system_allocator2; + +fn main() {} diff --git a/src/test/compile-fail/asm-out-assign-imm.rs b/src/test/compile-fail/asm-out-assign-imm.rs index 3c4a5dcb7b..f95e441038 100644 --- a/src/test/compile-fail/asm-out-assign-imm.rs +++ b/src/test/compile-fail/asm-out-assign-imm.rs @@ -28,7 +28,6 @@ pub fn main() { asm!("mov $1, $0" : "=r"(x) : "r"(5)); //~^ ERROR re-assignment of immutable variable `x` //~| NOTE re-assignment of immutable - //~| NOTE in this expansion of asm! } foo(x); } diff --git a/src/test/compile-fail/asm-src-loc-codegen-units.rs b/src/test/compile-fail/asm-src-loc-codegen-units.rs index df1a6d52f5..6c5c5b0077 100644 --- a/src/test/compile-fail/asm-src-loc-codegen-units.rs +++ b/src/test/compile-fail/asm-src-loc-codegen-units.rs @@ -7,17 +7,16 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -// + // WONTFIX(#20184) Needs landing pads (not present in stage1) or the compiler hangs. // ignore-stage1 // compile-flags: -C codegen-units=2 -// error-pattern: build without -C codegen-units for more exact errors // ignore-emscripten #![feature(asm)] fn main() { unsafe { - asm!("nowayisthisavalidinstruction"); + asm!("nowayisthisavalidinstruction"); //~ ERROR instruction } } diff --git a/src/test/compile-fail/associated-const-ambiguity-report.rs b/src/test/compile-fail/associated-const-ambiguity-report.rs index 22292a6da9..5051e78d1b 100644 --- a/src/test/compile-fail/associated-const-ambiguity-report.rs +++ b/src/test/compile-fail/associated-const-ambiguity-report.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] trait Foo { const ID: i32; diff --git a/src/test/compile-fail/associated-const-array-len.rs b/src/test/compile-fail/associated-const-array-len.rs index 7f77ae2ec1..2cc10f0f95 100644 --- a/src/test/compile-fail/associated-const-array-len.rs +++ b/src/test/compile-fail/associated-const-array-len.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] trait Foo { const ID: usize; diff --git a/src/test/compile-fail/associated-const-dead-code.rs b/src/test/compile-fail/associated-const-dead-code.rs index 1ed156d45f..42db13f4f3 100644 --- a/src/test/compile-fail/associated-const-dead-code.rs +++ b/src/test/compile-fail/associated-const-dead-code.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] #![deny(dead_code)] struct MyFoo; diff --git a/src/test/compile-fail/associated-const-generic-obligations.rs b/src/test/compile-fail/associated-const-generic-obligations.rs index 90afe8d733..45f53418dc 100644 --- a/src/test/compile-fail/associated-const-generic-obligations.rs +++ b/src/test/compile-fail/associated-const-generic-obligations.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] trait Foo { type Out: Sized; diff --git a/src/test/compile-fail/associated-const-impl-wrong-lifetime.rs b/src/test/compile-fail/associated-const-impl-wrong-lifetime.rs index 834f346069..51681a4bb8 100644 --- a/src/test/compile-fail/associated-const-impl-wrong-lifetime.rs +++ b/src/test/compile-fail/associated-const-impl-wrong-lifetime.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] trait Foo { const NAME: &'static str; diff --git a/src/test/compile-fail/associated-const-impl-wrong-type.rs b/src/test/compile-fail/associated-const-impl-wrong-type.rs index ec495c87b1..e38851ccd6 100644 --- a/src/test/compile-fail/associated-const-impl-wrong-type.rs +++ b/src/test/compile-fail/associated-const-impl-wrong-type.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] trait Foo { const BAR: u32; //~ NOTE type in trait diff --git a/src/test/compile-fail/associated-const-no-item.rs b/src/test/compile-fail/associated-const-no-item.rs index 89d1ac1308..f9a57cd6d7 100644 --- a/src/test/compile-fail/associated-const-no-item.rs +++ b/src/test/compile-fail/associated-const-no-item.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] trait Foo { const ID: i32; diff --git a/src/test/compile-fail/associated-const-private-impl.rs b/src/test/compile-fail/associated-const-private-impl.rs index 6ebe80b570..b5accfff5b 100644 --- a/src/test/compile-fail/associated-const-private-impl.rs +++ b/src/test/compile-fail/associated-const-private-impl.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] mod bar1 { pub use self::bar2::Foo; diff --git a/src/test/compile-fail/associated-const-type-parameter-arms.rs b/src/test/compile-fail/associated-const-type-parameter-arms.rs index f564157b49..52bb4a1b46 100644 --- a/src/test/compile-fail/associated-const-type-parameter-arms.rs +++ b/src/test/compile-fail/associated-const-type-parameter-arms.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] pub enum EFoo { A, B, C, D } diff --git a/src/test/compile-fail/associated-const-type-parameter-arrays-2.rs b/src/test/compile-fail/associated-const-type-parameter-arrays-2.rs index e284a61eb2..d196cf2215 100644 --- a/src/test/compile-fail/associated-const-type-parameter-arrays-2.rs +++ b/src/test/compile-fail/associated-const-type-parameter-arrays-2.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] pub trait Foo { const Y: usize; diff --git a/src/test/compile-fail/associated-const-type-parameter-arrays.rs b/src/test/compile-fail/associated-const-type-parameter-arrays.rs index 848ea65a9c..0b24cab2a6 100644 --- a/src/test/compile-fail/associated-const-type-parameter-arrays.rs +++ b/src/test/compile-fail/associated-const-type-parameter-arrays.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] pub trait Foo { const Y: usize; diff --git a/src/test/compile-fail/associated-const-upper-case-lint.rs b/src/test/compile-fail/associated-const-upper-case-lint.rs index 752691fa1c..497ff426b2 100644 --- a/src/test/compile-fail/associated-const-upper-case-lint.rs +++ b/src/test/compile-fail/associated-const-upper-case-lint.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] #![deny(non_upper_case_globals)] #![allow(dead_code)] diff --git a/src/test/compile-fail/associated-item-duplicate-names-2.rs b/src/test/compile-fail/associated-item-duplicate-names-2.rs index ab903591fb..85ea949b9c 100644 --- a/src/test/compile-fail/associated-item-duplicate-names-2.rs +++ b/src/test/compile-fail/associated-item-duplicate-names-2.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] struct Foo; diff --git a/src/test/compile-fail/associated-item-duplicate-names.rs b/src/test/compile-fail/associated-item-duplicate-names.rs index 85868f5c02..a2fc1bc017 100644 --- a/src/test/compile-fail/associated-item-duplicate-names.rs +++ b/src/test/compile-fail/associated-item-duplicate-names.rs @@ -10,7 +10,6 @@ // Test for issue #23969 -#![feature(associated_consts)] trait Foo { type Ty; diff --git a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs index 5a19aecf66..74a388e726 100644 --- a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs +++ b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs @@ -25,7 +25,7 @@ pub trait Sized { trait Add { type Output; - fn add(self, RHS) -> Self::Output; + fn add(self, _: RHS) -> Self::Output; } fn ice(a: A) { diff --git a/src/test/compile-fail/associated-types-overridden-default.rs b/src/test/compile-fail/associated-types-overridden-default.rs index 19f13f5fc2..946a4b2f73 100644 --- a/src/test/compile-fail/associated-types-overridden-default.rs +++ b/src/test/compile-fail/associated-types-overridden-default.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] #![feature(associated_type_defaults)] pub trait Tr { diff --git a/src/test/compile-fail/associated-types-path-2.rs b/src/test/compile-fail/associated-types-path-2.rs index cdb7dff692..d62f6b0f1a 100644 --- a/src/test/compile-fail/associated-types-path-2.rs +++ b/src/test/compile-fail/associated-types-path-2.rs @@ -38,11 +38,13 @@ pub fn f1_int_uint() { pub fn f1_uint_uint() { f1(2u32, 4u32); //~^ ERROR `u32: Foo` is not satisfied + //~| ERROR `u32: Foo` is not satisfied } pub fn f1_uint_int() { f1(2u32, 4i32); //~^ ERROR `u32: Foo` is not satisfied + //~| ERROR `u32: Foo` is not satisfied } pub fn f2_int() { diff --git a/src/test/compile-fail/attempted-access-non-fatal.rs b/src/test/compile-fail/attempted-access-non-fatal.rs index fe8e793ed7..3d6c46f5ce 100644 --- a/src/test/compile-fail/attempted-access-non-fatal.rs +++ b/src/test/compile-fail/attempted-access-non-fatal.rs @@ -11,6 +11,6 @@ // Check that bogus field access is non-fatal fn main() { let x = 0; - let _ = x.foo; //~ no field `foo` on type `{integer}` - let _ = x.bar; //~ no field `bar` on type `{integer}` + let _ = x.foo; //~ `{integer}` is a primitive type and therefore doesn't have fields [E0610] + let _ = x.bar; //~ `{integer}` is a primitive type and therefore doesn't have fields [E0610] } diff --git a/src/test/compile-fail/auxiliary/issue-36881-aux.rs b/src/test/compile-fail/auxiliary/issue-36881-aux.rs new file mode 100644 index 0000000000..33ac11feb2 --- /dev/null +++ b/src/test/compile-fail/auxiliary/issue-36881-aux.rs @@ -0,0 +1,11 @@ +// 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. + +pub trait Foo {} diff --git a/src/test/compile-fail/auxiliary/issue_41549.rs b/src/test/compile-fail/auxiliary/issue_41549.rs index 77b203997b..5a6db78928 100644 --- a/src/test/compile-fail/auxiliary/issue_41549.rs +++ b/src/test/compile-fail/auxiliary/issue_41549.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] pub trait Trait { const CONST: u32; diff --git a/src/test/compile-fail/auxiliary/allocator-dylib.rs b/src/test/compile-fail/auxiliary/lint_unused_extern_crate2.rs similarity index 78% rename from src/test/compile-fail/auxiliary/allocator-dylib.rs rename to src/test/compile-fail/auxiliary/lint_unused_extern_crate2.rs index 568b247ecd..b61667cfd8 100644 --- a/src/test/compile-fail/auxiliary/allocator-dylib.rs +++ b/src/test/compile-fail/auxiliary/lint_unused_extern_crate2.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,8 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// no-prefer-dynamic - -#![crate_type = "dylib"] - pub fn foo() {} diff --git a/src/test/compile-fail/auxiliary/lint_unused_extern_crate3.rs b/src/test/compile-fail/auxiliary/lint_unused_extern_crate3.rs new file mode 100644 index 0000000000..b61667cfd8 --- /dev/null +++ b/src/test/compile-fail/auxiliary/lint_unused_extern_crate3.rs @@ -0,0 +1,11 @@ +// 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. + +pub fn foo() {} diff --git a/src/test/compile-fail/auxiliary/lint_unused_extern_crate4.rs b/src/test/compile-fail/auxiliary/lint_unused_extern_crate4.rs new file mode 100644 index 0000000000..fc4bca865c --- /dev/null +++ b/src/test/compile-fail/auxiliary/lint_unused_extern_crate4.rs @@ -0,0 +1,9 @@ +// 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. diff --git a/src/test/compile-fail/auxiliary/private-inferred-type.rs b/src/test/compile-fail/auxiliary/private-inferred-type.rs new file mode 100644 index 0000000000..7627f5dc0c --- /dev/null +++ b/src/test/compile-fail/auxiliary/private-inferred-type.rs @@ -0,0 +1,44 @@ +// 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. + +#![feature(decl_macro)] + +fn priv_fn() {} +enum PrivEnum { Variant } +pub enum PubEnum { Variant } +trait PrivTrait { fn method() {} } +impl PrivTrait for u8 {} +pub trait PubTrait { fn method() {} } +impl PubTrait for u8 {} +struct PrivTupleStruct(u8); +pub struct PubTupleStruct(u8); +impl PubTupleStruct { fn method() {} } + +struct Priv; +pub type Alias = Priv; +pub struct Pub(pub T); + +impl Pub { + pub fn static_method() {} +} +impl Pub { + fn priv_method(&self) {} +} + +pub macro m() { + priv_fn; + PrivEnum::Variant; + PubEnum::Variant; + ::method; + ::method; + PrivTupleStruct; + PubTupleStruct; + Pub(0u8).priv_method(); +} diff --git a/src/test/compile-fail/auxiliary/use_from_trait_xc.rs b/src/test/compile-fail/auxiliary/use_from_trait_xc.rs index 7024c9dad7..9a6d176d08 100644 --- a/src/test/compile-fail/auxiliary/use_from_trait_xc.rs +++ b/src/test/compile-fail/auxiliary/use_from_trait_xc.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] pub use self::sub::{Bar, Baz}; diff --git a/src/test/compile-fail/blind-item-block-item-shadow.rs b/src/test/compile-fail/blind-item-block-item-shadow.rs index 2d53aee39e..eeadecf627 100644 --- a/src/test/compile-fail/blind-item-block-item-shadow.rs +++ b/src/test/compile-fail/blind-item-block-item-shadow.rs @@ -14,6 +14,6 @@ fn main() { { struct Bar; use foo::Bar; - //~^ ERROR a type named `Bar` has already been defined in this block + //~^ ERROR the name `Bar` is defined multiple times } } diff --git a/src/test/compile-fail/blind-item-item-shadow.rs b/src/test/compile-fail/blind-item-item-shadow.rs index e9df8868a1..af3abe5e05 100644 --- a/src/test/compile-fail/blind-item-item-shadow.rs +++ b/src/test/compile-fail/blind-item-item-shadow.rs @@ -8,10 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -mod foo { pub mod foo { } } //~ NOTE previous definition of `foo` here +mod foo { pub mod foo { } } //~ NOTE previous definition of the module `foo` here use foo::foo; -//~^ ERROR a module named `foo` has already been defined in this module -//~| `foo` already defined +//~^ ERROR the name `foo` is defined multiple times +//~| `foo` reimported here +//~| NOTE `foo` must be defined only once in the type namespace of this module fn main() {} diff --git a/src/test/compile-fail/cast-from-nil.rs b/src/test/compile-fail/cast-from-nil.rs index 4c6dcaccc9..ab22d35248 100644 --- a/src/test/compile-fail/cast-from-nil.rs +++ b/src/test/compile-fail/cast-from-nil.rs @@ -8,5 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: non-scalar cast: `()` as `u32` +// error-pattern: non-primitive cast: `()` as `u32` fn main() { let u = (assert!(true) as u32); } diff --git a/src/test/compile-fail/cast-to-bare-fn.rs b/src/test/compile-fail/cast-to-bare-fn.rs index 7cc5c727bc..d5a998c6e4 100644 --- a/src/test/compile-fail/cast-to-bare-fn.rs +++ b/src/test/compile-fail/cast-to-bare-fn.rs @@ -13,8 +13,8 @@ fn foo(_x: isize) { } fn main() { let v: u64 = 5; let x = foo as extern "C" fn() -> isize; - //~^ ERROR non-scalar cast + //~^ ERROR non-primitive cast let y = v as extern "Rust" fn(isize) -> (isize, isize); - //~^ ERROR non-scalar cast + //~^ ERROR non-primitive cast y(x()); } diff --git a/src/test/compile-fail/cast-to-nil.rs b/src/test/compile-fail/cast-to-nil.rs index e5fd5bb33e..27d9e8a42b 100644 --- a/src/test/compile-fail/cast-to-nil.rs +++ b/src/test/compile-fail/cast-to-nil.rs @@ -8,5 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: non-scalar cast: `u32` as `()` +// error-pattern: non-primitive cast: `u32` as `()` fn main() { let u = 0u32 as (); } diff --git a/src/test/compile-fail/cast-to-unsized-trait-object-suggestion.rs b/src/test/compile-fail/cast-to-unsized-trait-object-suggestion.rs deleted file mode 100644 index d18746cdf0..0000000000 --- a/src/test/compile-fail/cast-to-unsized-trait-object-suggestion.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn main() { - &1 as Send; - //~^ ERROR cast to unsized type - //~| HELP try casting to a reference instead: - //~| SUGGESTION &1 as &Send; - Box::new(1) as Send; - //~^ ERROR cast to unsized type - //~| HELP try casting to a `Box` instead: - //~| SUGGESTION Box::new(1) as Box; -} diff --git a/src/test/compile-fail/closure-no-fn-3.rs b/src/test/compile-fail/closure-no-fn-3.rs index 85dbc89920..6584c16c9d 100644 --- a/src/test/compile-fail/closure-no-fn-3.rs +++ b/src/test/compile-fail/closure-no-fn-3.rs @@ -14,5 +14,5 @@ fn main() { let b = 0u8; let baz: fn() -> u8 = (|| { b }) as fn() -> u8; - //~^ ERROR non-scalar cast + //~^ ERROR non-primitive cast } diff --git a/src/test/compile-fail/coerce-to-bang-cast.rs b/src/test/compile-fail/coerce-to-bang-cast.rs index 57d2192e63..0479f5cce6 100644 --- a/src/test/compile-fail/coerce-to-bang-cast.rs +++ b/src/test/compile-fail/coerce-to-bang-cast.rs @@ -17,7 +17,7 @@ fn cast_a() { } fn cast_b() { - let y = 22 as !; //~ ERROR non-scalar cast + let y = 22 as !; //~ ERROR non-primitive cast } fn main() { } diff --git a/src/test/compile-fail/compile_error_macro.rs b/src/test/compile-fail/compile_error_macro.rs new file mode 100644 index 0000000000..e9c5993098 --- /dev/null +++ b/src/test/compile-fail/compile_error_macro.rs @@ -0,0 +1,13 @@ +// 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. + +fn main() { + compile_error!("a very descriptive error message"); //~ ERROR: a very descriptive error message +} diff --git a/src/test/compile-fail/defaulted-unit-warning.rs b/src/test/compile-fail/defaulted-unit-warning.rs index ed6263d0fd..3f4e1cce54 100644 --- a/src/test/compile-fail/defaulted-unit-warning.rs +++ b/src/test/compile-fail/defaulted-unit-warning.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(dead_code)] -#![allow(unreachable_code)] -#![deny(resolve_trait_on_defaulted_unit)] +#![allow(unused)] trait Deserialize: Sized { fn deserialize() -> Result; @@ -38,4 +36,3 @@ fn smeg() { fn main() { smeg(); } - diff --git a/src/test/compile-fail/dep-graph-assoc-type-trans.rs b/src/test/compile-fail/dep-graph-assoc-type-trans.rs index fe76a4d439..007a80008a 100644 --- a/src/test/compile-fail/dep-graph-assoc-type-trans.rs +++ b/src/test/compile-fail/dep-graph-assoc-type-trans.rs @@ -36,7 +36,6 @@ mod y { use Foo; #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK - #[rustc_then_this_would_need(TransCrateItem)] //~ ERROR OK pub fn use_char_assoc() { // Careful here: in the representation, ::T gets // normalized away, so at a certain point we had no edge to diff --git a/src/test/compile-fail/dep-graph-caller-callee.rs b/src/test/compile-fail/dep-graph-caller-callee.rs index 9cb8788680..222c197200 100644 --- a/src/test/compile-fail/dep-graph-caller-callee.rs +++ b/src/test/compile-fail/dep-graph-caller-callee.rs @@ -28,7 +28,6 @@ mod y { // These dependencies SHOULD exist: #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK - #[rustc_then_this_would_need(TransCrateItem)] //~ ERROR OK pub fn y() { x::x(); } @@ -40,7 +39,6 @@ mod z { // These are expected to yield errors, because changes to `x` // affect the BODY of `y`, but not its signature. #[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path - #[rustc_then_this_would_need(TransCrateItem)] //~ ERROR no path pub fn z() { y::y(); } diff --git a/src/test/compile-fail/dep-graph-struct-signature.rs b/src/test/compile-fail/dep-graph-struct-signature.rs index 3f568194e2..647605ae43 100644 --- a/src/test/compile-fail/dep-graph-struct-signature.rs +++ b/src/test/compile-fail/dep-graph-struct-signature.rs @@ -34,54 +34,64 @@ struct WontChange { mod signatures { use WillChange; - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path + #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR no path + #[rustc_then_this_would_need(AssociatedItems)] //~ ERROR no path + #[rustc_then_this_would_need(TraitDefOfItem)] //~ ERROR no path trait Bar { - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK fn do_something(x: WillChange); } - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK + #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK fn some_fn(x: WillChange) { } - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK + #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK fn new_foo(x: u32, y: u32) -> WillChange { WillChange { x: x, y: y } } - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR OK impl WillChange { + #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK + #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK fn new(x: u32, y: u32) -> WillChange { loop { } } } - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR OK impl WillChange { + #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK + #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK fn method(&self, x: u32) { } } struct WillChanges { - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR OK x: WillChange, - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR OK y: WillChange } // The fields change, not the type itself. - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path + #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR no path fn indirect(x: WillChanges) { } } mod invalid_signatures { use WontChange; - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path + #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR no path trait A { + #[rustc_then_this_would_need(FnSignature)] //~ ERROR no path fn do_something_else_twice(x: WontChange); } - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path + #[rustc_then_this_would_need(FnSignature)] //~ ERROR no path + #[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path fn b(x: WontChange) { } - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path from `WillChange` + #[rustc_then_this_would_need(FnSignature)] //~ ERROR no path from `WillChange` + #[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path from `WillChange` fn c(x: u32) { } } - diff --git a/src/test/compile-fail/dep-graph-trait-impl.rs b/src/test/compile-fail/dep-graph-trait-impl.rs index c0f9f05462..85b3e69065 100644 --- a/src/test/compile-fail/dep-graph-trait-impl.rs +++ b/src/test/compile-fail/dep-graph-trait-impl.rs @@ -35,25 +35,21 @@ mod y { use Foo; #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK - #[rustc_then_this_would_need(TransCrateItem)] //~ ERROR OK pub fn with_char() { char::method('a'); } #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK - #[rustc_then_this_would_need(TransCrateItem)] //~ ERROR OK pub fn take_foo_with_char() { take_foo::('a'); } #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK - #[rustc_then_this_would_need(TransCrateItem)] //~ ERROR OK pub fn with_u32() { u32::method(22); } #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK - #[rustc_then_this_would_need(TransCrateItem)] //~ ERROR OK pub fn take_foo_with_u32() { take_foo::(22); } @@ -67,7 +63,6 @@ mod z { // These are expected to yield errors, because changes to `x` // affect the BODY of `y`, but not its signature. #[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path - #[rustc_then_this_would_need(TransCrateItem)] //~ ERROR no path pub fn z() { y::with_char(); y::with_u32(); diff --git a/src/test/compile-fail/dep-graph-type-alias.rs b/src/test/compile-fail/dep-graph-type-alias.rs index 56636a00a3..dca1fa4d98 100644 --- a/src/test/compile-fail/dep-graph-type-alias.rs +++ b/src/test/compile-fail/dep-graph-type-alias.rs @@ -25,40 +25,42 @@ type TypeAlias = u32; // The type alias directly affects the type of the field, // not the enclosing struct: -#[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path +#[rustc_then_this_would_need(TypeOfItem)] //~ ERROR no path struct Struct { - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR OK x: TypeAlias, y: u32 } -#[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path +#[rustc_then_this_would_need(TypeOfItem)] //~ ERROR no path enum Enum { Variant1 { - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR OK t: TypeAlias }, Variant2(i32) } -#[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path +#[rustc_then_this_would_need(TypeOfItem)] //~ ERROR no path trait Trait { - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK fn method(&self, _: TypeAlias); } struct SomeType; -#[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path +#[rustc_then_this_would_need(TypeOfItem)] //~ ERROR no path impl SomeType { - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK + #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK fn method(&self, _: TypeAlias) {} } -#[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK +#[rustc_then_this_would_need(TypeOfItem)] //~ ERROR OK type TypeAlias2 = TypeAlias; -#[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK +#[rustc_then_this_would_need(FnSignature)] //~ ERROR OK +#[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK fn function(_: TypeAlias) { } diff --git a/src/test/compile-fail/directory_ownership/backcompat-warnings.rs b/src/test/compile-fail/directory_ownership/backcompat-warnings.rs index 75e3426a39..519792dfa3 100644 --- a/src/test/compile-fail/directory_ownership/backcompat-warnings.rs +++ b/src/test/compile-fail/directory_ownership/backcompat-warnings.rs @@ -10,12 +10,8 @@ // error-pattern: cannot declare a new module at this location // error-pattern: will become a hard error -// error-pattern: compilation successful - -#![feature(rustc_attrs)] #[path="mod_file_not_owning_aux3.rs"] mod foo; -#[rustc_error] fn main() {} diff --git a/src/test/compile-fail/two-allocators-2.rs b/src/test/compile-fail/dollar-crate-is-keyword-2.rs similarity index 56% rename from src/test/compile-fail/two-allocators-2.rs rename to src/test/compile-fail/dollar-crate-is-keyword-2.rs index d6fcbcb513..e221fc6e9e 100644 --- a/src/test/compile-fail/two-allocators-2.rs +++ b/src/test/compile-fail/dollar-crate-is-keyword-2.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,14 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: cannot link together two allocators: allocator1 and allocator2 -// aux-build:allocator1.rs -// aux-build:allocator2.rs +mod a {} -// Make sure we can't link together two explicit allocators. +macro_rules! m { + () => { + use a::$crate; //~ ERROR unresolved import `a::$crate` + use a::$crate::b; //~ ERROR unresolved import `a::$crate::b` + type A = a::$crate; //~ ERROR cannot find type `$crate` in module `a` + } +} -extern crate allocator1; -extern crate allocator2; +m!(); fn main() {} - diff --git a/src/test/compile-fail/dollar-crate-is-keyword.rs b/src/test/compile-fail/dollar-crate-is-keyword.rs new file mode 100644 index 0000000000..70597a230a --- /dev/null +++ b/src/test/compile-fail/dollar-crate-is-keyword.rs @@ -0,0 +1,24 @@ +// 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. + +macro_rules! m { + () => { + struct $crate {} //~ ERROR expected identifier, found reserved identifier `$crate` + + use $crate; // OK + //~^ WARN `$crate` may not be imported + use $crate as $crate; //~ ERROR expected identifier, found reserved identifier `$crate` + //~^ WARN `$crate` may not be imported + } +} + +m!(); + +fn main() {} diff --git a/src/test/compile-fail/double-import.rs b/src/test/compile-fail/double-import.rs index bd190a6df8..21b8ded6d9 100644 --- a/src/test/compile-fail/double-import.rs +++ b/src/test/compile-fail/double-import.rs @@ -19,8 +19,9 @@ mod sub2 { pub fn foo() {} // implementation 2 } -use sub1::foo; //~ NOTE previous import of `foo` here -use sub2::foo; //~ ERROR a value named `foo` has already been imported in this module [E0252] - //~| NOTE already imported +use sub1::foo; //~ NOTE previous import of the value `foo` here +use sub2::foo; //~ ERROR the name `foo` is defined multiple times + //~| NOTE `foo` reimported here + //~| NOTE `foo` must be defined only once in the value namespace of this module fn main() {} diff --git a/src/test/compile-fail/double-type-import.rs b/src/test/compile-fail/double-type-import.rs index 760612c05c..9629da735b 100644 --- a/src/test/compile-fail/double-type-import.rs +++ b/src/test/compile-fail/double-type-import.rs @@ -11,7 +11,7 @@ mod foo { pub use self::bar::X; use self::bar::X; - //~^ ERROR a type named `X` has already been imported in this module + //~^ ERROR the name `X` is defined multiple times mod bar { pub struct X; diff --git a/src/test/compile-fail/dst-bad-assign-3.rs b/src/test/compile-fail/dst-bad-assign-3.rs new file mode 100644 index 0000000000..1c3bad5ba5 --- /dev/null +++ b/src/test/compile-fail/dst-bad-assign-3.rs @@ -0,0 +1,50 @@ +// 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. + +// Forbid assignment into a dynamically sized type. + +#![feature(unsized_tuple_coercion)] + +type Fat = (isize, &'static str, T); +//~^ WARNING trait bounds are not (yet) enforced + +#[derive(PartialEq,Eq)] +struct Bar; + +#[derive(PartialEq,Eq)] +struct Bar1 { + f: isize +} + +trait ToBar { + fn to_bar(&self) -> Bar; + fn to_val(&self) -> isize; +} + +impl ToBar for Bar1 { + fn to_bar(&self) -> Bar { + Bar + } + fn to_val(&self) -> isize { + self.f + } +} + +pub fn main() { + // Assignment. + let f5: &mut Fat = &mut (5, "some str", Bar1 {f :42}); + let z: Box = Box::new(Bar1 {f: 36}); + f5.2 = Bar1 {f: 36}; + //~^ ERROR mismatched types + //~| expected type `ToBar` + //~| found type `Bar1` + //~| expected trait ToBar, found struct `Bar1` + //~| ERROR `ToBar: std::marker::Sized` is not satisfied +} diff --git a/src/test/compile-fail/dst-bad-coerce1.rs b/src/test/compile-fail/dst-bad-coerce1.rs index 9a3ea54a3a..b0de84a530 100644 --- a/src/test/compile-fail/dst-bad-coerce1.rs +++ b/src/test/compile-fail/dst-bad-coerce1.rs @@ -10,6 +10,8 @@ // Attempt to change the type as well as unsizing. +#![feature(unsized_tuple_coercion)] + struct Fat { ptr: T } @@ -29,4 +31,16 @@ pub fn main() { let f2: &Fat = &f1; let f3: &Fat = f2; //~^ ERROR `Foo: Bar` is not satisfied + + // Tuple with a vec of isize. + let f1 = ([1, 2, 3],); + let f2: &([isize; 3],) = &f1; + let f3: &([usize],) = f2; + //~^ ERROR mismatched types + + // Tuple with a trait. + let f1 = (Foo,); + let f2: &(Foo,) = &f1; + let f3: &(Bar,) = f2; + //~^ ERROR `Foo: Bar` is not satisfied } diff --git a/src/test/compile-fail/dst-bad-coerce2.rs b/src/test/compile-fail/dst-bad-coerce2.rs index 160197368d..9e92f649b2 100644 --- a/src/test/compile-fail/dst-bad-coerce2.rs +++ b/src/test/compile-fail/dst-bad-coerce2.rs @@ -28,4 +28,14 @@ pub fn main() { let f1 = Fat { ptr: Foo }; let f2: &Fat = &f1; let f3: &mut Fat = f2; //~ ERROR mismatched types + + // Tuple with a vec of ints. + let f1 = ([1, 2, 3],); + let f2: &([isize; 3],) = &f1; + let f3: &mut ([isize],) = f2; //~ ERROR mismatched types + + // Tuple with a trait. + let f1 = (Foo,); + let f2: &(Foo,) = &f1; + let f3: &mut (Bar,) = f2; //~ ERROR mismatched types } diff --git a/src/test/compile-fail/dst-bad-coerce3.rs b/src/test/compile-fail/dst-bad-coerce3.rs index 7bad3bd69d..35a147c15b 100644 --- a/src/test/compile-fail/dst-bad-coerce3.rs +++ b/src/test/compile-fail/dst-bad-coerce3.rs @@ -10,6 +10,8 @@ // Attempt to extend the lifetime as well as unsizing. +#![feature(unsized_tuple_coercion)] + struct Fat { ptr: T } @@ -28,6 +30,16 @@ fn baz<'a>() { let f1 = Fat { ptr: Foo }; let f2: &Fat = &f1; //~ ERROR `f1` does not live long enough let f3: &'a Fat = f2; + + // Tuple with a vec of ints. + let f1 = ([1, 2, 3],); + let f2: &([isize; 3],) = &f1; //~ ERROR `f1` does not live long enough + let f3: &'a ([isize],) = f2; + + // Tuple with a trait. + let f1 = (Foo,); + let f2: &(Foo,) = &f1; //~ ERROR `f1` does not live long enough + let f3: &'a (Bar,) = f2; } pub fn main() { diff --git a/src/test/compile-fail/dst-bad-coerce4.rs b/src/test/compile-fail/dst-bad-coerce4.rs index 9d4d56cf79..874b7588ff 100644 --- a/src/test/compile-fail/dst-bad-coerce4.rs +++ b/src/test/compile-fail/dst-bad-coerce4.rs @@ -10,6 +10,8 @@ // Attempt to coerce from unsized to sized. +#![feature(unsized_tuple_coercion)] + struct Fat { ptr: T } @@ -22,4 +24,12 @@ pub fn main() { //~| expected type `&Fat<[isize; 3]>` //~| found type `&Fat<[isize]>` //~| expected array of 3 elements, found slice + + // Tuple with a vec of isizes. + let f1: &([isize],) = &([1, 2, 3],); + let f2: &([isize; 3],) = f1; + //~^ ERROR mismatched types + //~| expected type `&([isize; 3],)` + //~| found type `&([isize],)` + //~| expected array of 3 elements, found slice } diff --git a/src/test/run-make/no-duplicate-libs/bar.rs b/src/test/compile-fail/dst-bad-deep-2.rs similarity index 50% rename from src/test/run-make/no-duplicate-libs/bar.rs rename to src/test/compile-fail/dst-bad-deep-2.rs index b82fdeb8f3..0c812b1d81 100644 --- a/src/test/run-make/no-duplicate-libs/bar.rs +++ b/src/test/compile-fail/dst-bad-deep-2.rs @@ -8,18 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(lang_items, libc, compiler_builtins_lib)] -#![crate_type = "dylib"] -#![no_std] +// Try to initialise a DST struct where the lost information is deeply nested. +// This is an error because it requires an unsized rvalue. This is a problem +// because it would require stack allocation of an unsized temporary (*g in the +// test). -extern crate libc; -extern crate compiler_builtins; +#![feature(unsized_tuple_coercion)] -#[no_mangle] -pub extern fn bar() {} - -#[lang = "eh_personality"] fn eh_personality() {} -#[lang = "eh_unwind_resume"] fn eh_unwind_resume() {} -#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} } -#[no_mangle] pub extern fn rust_eh_register_frames () {} -#[no_mangle] pub extern fn rust_eh_unregister_frames () {} +pub fn main() { + let f: ([isize; 3],) = ([5, 6, 7],); + let g: &([isize],) = &f; + let h: &(([isize],),) = &(*g,); + //~^ ERROR `[isize]: std::marker::Sized` is not satisfied +} diff --git a/src/test/compile-fail/empty-struct-unit-expr.rs b/src/test/compile-fail/empty-struct-unit-expr.rs index 273ce91a7c..9655007604 100644 --- a/src/test/compile-fail/empty-struct-unit-expr.rs +++ b/src/test/compile-fail/empty-struct-unit-expr.rs @@ -24,10 +24,10 @@ enum E { fn main() { let e2 = Empty2(); //~ ERROR expected function, found `Empty2` let e4 = E::Empty4(); - //~^ ERROR `E::Empty4` is being called, but it is not a function + //~^ ERROR expected function, found `E::Empty4` [E0618] //~| HELP did you mean to write `E::Empty4`? let xe2 = XEmpty2(); //~ ERROR expected function, found `empty_struct::XEmpty2` let xe4 = XE::XEmpty4(); - //~^ ERROR `XE::XEmpty4` is being called, but it is not a function + //~^ ERROR expected function, found `XE::XEmpty4` [E0618] //~| HELP did you mean to write `XE::XEmpty4`? } diff --git a/src/test/compile-fail/enum-and-module-in-same-scope.rs b/src/test/compile-fail/enum-and-module-in-same-scope.rs index 527ac7505a..59b4d715c2 100644 --- a/src/test/compile-fail/enum-and-module-in-same-scope.rs +++ b/src/test/compile-fail/enum-and-module-in-same-scope.rs @@ -8,12 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -enum Foo { //~ NOTE previous definition of `Foo` here +enum Foo { //~ NOTE previous definition of the type `Foo` here X } -mod Foo { //~ ERROR a type named `Foo` has already been defined - //~| NOTE already defined +mod Foo { //~ ERROR the name `Foo` is defined multiple times + //~| NOTE `Foo` redefined here + //~| NOTE `Foo` must be defined only once in the type namespace of this module pub static X: isize = 42; fn f() { f() } // Check that this does not result in a resolution error } diff --git a/src/test/compile-fail/extern-wrong-value-type.rs b/src/test/compile-fail/extern-wrong-value-type.rs index 576368aef3..66b06c505e 100644 --- a/src/test/compile-fail/extern-wrong-value-type.rs +++ b/src/test/compile-fail/extern-wrong-value-type.rs @@ -18,5 +18,4 @@ fn main() { let _x: extern "C" fn() = f; // OK is_fn(f); //~^ ERROR `extern "C" fn() {f}: std::ops::Fn<()>` is not satisfied - //~| ERROR `extern "C" fn() {f}: std::ops::FnOnce<()>` is not satisfied } diff --git a/src/test/compile-fail/fail-simple.rs b/src/test/compile-fail/fail-simple.rs index e889d35477..a20ff86470 100644 --- a/src/test/compile-fail/fail-simple.rs +++ b/src/test/compile-fail/fail-simple.rs @@ -9,5 +9,5 @@ // except according to those terms. fn main() { - panic!(@); //~ ERROR expected expression, found `@` + panic!(@); //~ ERROR no rules expected the token `@` } diff --git a/src/test/compile-fail/fat-ptr-cast.rs b/src/test/compile-fail/fat-ptr-cast.rs index c62987a5b9..bc2dc1cc5d 100644 --- a/src/test/compile-fail/fat-ptr-cast.rs +++ b/src/test/compile-fail/fat-ptr-cast.rs @@ -22,7 +22,7 @@ fn main() { a as isize; //~ ERROR casting a as i16; //~ ERROR casting `&[i32]` as `i16` is invalid a as u32; //~ ERROR casting `&[i32]` as `u32` is invalid - b as usize; //~ ERROR non-scalar cast + b as usize; //~ ERROR non-primitive cast p as usize; //~^ ERROR casting //~^^ HELP cast through a thin pointer diff --git a/src/test/run-pass/auxiliary/clibrary.rs b/src/test/compile-fail/feature-gate-allocator_internals.rs similarity index 81% rename from src/test/run-pass/auxiliary/clibrary.rs rename to src/test/compile-fail/feature-gate-allocator_internals.rs index 7438ba21bf..b519a985ec 100644 --- a/src/test/run-pass/auxiliary/clibrary.rs +++ b/src/test/compile-fail/feature-gate-allocator_internals.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// no-prefer-dynamic -#![crate_type = "staticlib"] +#![default_lib_allocator] //~ ERROR: attribute is an experimental feature + +fn main() {} -#[no_mangle] -pub extern "C" fn foo(x:i32) -> i32 { x } diff --git a/src/test/run-pass/allocator-system.rs b/src/test/compile-fail/feature-gate-allow_fail.rs similarity index 75% rename from src/test/run-pass/allocator-system.rs rename to src/test/compile-fail/feature-gate-allow_fail.rs index 4585003d57..1124740280 100644 --- a/src/test/run-pass/allocator-system.rs +++ b/src/test/compile-fail/feature-gate-allow_fail.rs @@ -8,12 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// no-prefer-dynamic +// check that #[allow_fail] is feature-gated -#![feature(alloc_system)] - -extern crate alloc_system; - -fn main() { - println!("{:?}", Box::new(3)); +#[allow_fail] //~ ERROR allow_fail attribute is currently unstable +fn ok_to_fail() { + assert!(false); } + diff --git a/src/test/compile-fail/feature-gate-global_allocator.rs b/src/test/compile-fail/feature-gate-global_allocator.rs new file mode 100644 index 0000000000..ff3c342f9e --- /dev/null +++ b/src/test/compile-fail/feature-gate-global_allocator.rs @@ -0,0 +1,14 @@ +// 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. + +#[global_allocator] //~ ERROR: attribute is an experimental feature +static A: usize = 0; + +fn main() {} diff --git a/src/test/compile-fail/feature-gate-profiler-runtime.rs b/src/test/compile-fail/feature-gate-profiler-runtime.rs new file mode 100644 index 0000000000..c6b2cb2eb0 --- /dev/null +++ b/src/test/compile-fail/feature-gate-profiler-runtime.rs @@ -0,0 +1,13 @@ +// 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. + +#![profiler_runtime] //~ ERROR the `#[profiler_runtime]` attribute is + +fn main() {} diff --git a/src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs b/src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs new file mode 100644 index 0000000000..4ddde01126 --- /dev/null +++ b/src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs @@ -0,0 +1,14 @@ +// 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. + +fn main() { + let _ : &(Send,) = &((),); + //~^ ERROR Unsized tuple coercion is not stable enough +} diff --git a/src/test/compile-fail/fn-trait-formatting.rs b/src/test/compile-fail/fn-trait-formatting.rs index 6377550d3d..6d70f54edb 100644 --- a/src/test/compile-fail/fn-trait-formatting.rs +++ b/src/test/compile-fail/fn-trait-formatting.rs @@ -28,5 +28,4 @@ fn main() { needs_fn(1); //~^ ERROR : std::ops::Fn<(isize,)>` - //~| ERROR : std::ops::FnOnce<(isize,)>` } diff --git a/src/test/compile-fail/gated-link-args.rs b/src/test/compile-fail/gated-link-args.rs index d34057e290..82f5db3042 100644 --- a/src/test/compile-fail/gated-link-args.rs +++ b/src/test/compile-fail/gated-link-args.rs @@ -9,12 +9,22 @@ // except according to those terms. // Test that `#[link_args]` attribute is gated by `link_args` -// feature gate. +// feature gate, both when it occurs where expected (atop +// `extern { }` blocks) and where unexpected. // gate-test-link_args -#[link_args = "aFdEfSeVEEE"] +// sidestep warning (which is correct, but misleading for +// purposes of this test) +#![allow(unused_attributes)] + +#![link_args = "-l unexpected_use_as_inner_attr_on_mod"] +//~^ ERROR the `link_args` attribute is experimental + +#[link_args = "-l expected_use_case"] +//~^ ERROR the `link_args` attribute is experimental extern {} -//~^ ERROR the `link_args` attribute is not portable across platforms -fn main() { } +#[link_args = "-l unexected_use_on_non_extern_item"] +//~^ ERROR: the `link_args` attribute is experimental +fn main() {} diff --git a/src/test/run-pass/hygiene/auxiliary/intercrate.rs b/src/test/compile-fail/hygiene/auxiliary/intercrate.rs similarity index 100% rename from src/test/run-pass/hygiene/auxiliary/intercrate.rs rename to src/test/compile-fail/hygiene/auxiliary/intercrate.rs diff --git a/src/test/run-pass/hygiene/fields.rs b/src/test/compile-fail/hygiene/fields.rs similarity index 78% rename from src/test/run-pass/hygiene/fields.rs rename to src/test/compile-fail/hygiene/fields.rs index d7f99ba211..64217770b1 100644 --- a/src/test/run-pass/hygiene/fields.rs +++ b/src/test/compile-fail/hygiene/fields.rs @@ -22,11 +22,11 @@ mod foo { x: i32, } - let s = S { x: 0 }; - let _ = s.x; + let s = S { x: 0 }; //~ ERROR type `foo::S` is private + let _ = s.x; //~ ERROR type `foo::S` is private - let t = T(0); - let _ = t.0; + let t = T(0); //~ ERROR type `foo::T` is private + let _ = t.0; //~ ERROR type `foo::T` is private let s = $S { $x: 0, x: 1 }; assert_eq!((s.$x, s.x), (0, 1)); diff --git a/src/test/run-pass/hygiene/impl_items.rs b/src/test/compile-fail/hygiene/impl_items.rs similarity index 91% rename from src/test/run-pass/hygiene/impl_items.rs rename to src/test/compile-fail/hygiene/impl_items.rs index a5780a573a..445aa62f23 100644 --- a/src/test/run-pass/hygiene/impl_items.rs +++ b/src/test/compile-fail/hygiene/impl_items.rs @@ -19,7 +19,7 @@ mod foo { } pub macro m() { - let _: () = S.f(); + let _: () = S.f(); //~ ERROR type `fn(&foo::S) {foo::S::f}` is private } } diff --git a/src/test/run-pass/hygiene/intercrate.rs b/src/test/compile-fail/hygiene/intercrate.rs similarity index 89% rename from src/test/run-pass/hygiene/intercrate.rs rename to src/test/compile-fail/hygiene/intercrate.rs index 3a75085f22..50fc985ba3 100644 --- a/src/test/run-pass/hygiene/intercrate.rs +++ b/src/test/compile-fail/hygiene/intercrate.rs @@ -12,6 +12,8 @@ // aux-build:intercrate.rs +// error-pattern:type `fn() -> u32 {intercrate::foo::bar::f}` is private + #![feature(decl_macro)] extern crate intercrate; diff --git a/src/test/compile-fail/import-ty-params.rs b/src/test/compile-fail/import-ty-params.rs index 7344f31535..a345523ded 100644 --- a/src/test/compile-fail/import-ty-params.rs +++ b/src/test/compile-fail/import-ty-params.rs @@ -20,6 +20,6 @@ macro_rules! import { ($p: path) => (use $p;); } -import! { a::b::c::S } //~ERROR type or lifetime parameters in import path +import! { a::b::c::S } //~ERROR unexpected generic arguments in path fn main() {} diff --git a/src/test/compile-fail/imports/duplicate.rs b/src/test/compile-fail/imports/duplicate.rs index f857f018f6..4b2a64155e 100644 --- a/src/test/compile-fail/imports/duplicate.rs +++ b/src/test/compile-fail/imports/duplicate.rs @@ -21,9 +21,10 @@ mod c { } mod d { - use a::foo; //~ NOTE previous import - use a::foo; //~ ERROR `foo` has already been imported - //~| NOTE already imported + use a::foo; //~ NOTE previous import of the value `foo` here + use a::foo; //~ ERROR the name `foo` is defined multiple times + //~| NOTE `foo` reimported here + //~| NOTE `foo` must be defined only once in the value namespace of this module } mod e { diff --git a/src/test/compile-fail/imports/rfc-1560-warning-cycle.rs b/src/test/compile-fail/imports/rfc-1560-warning-cycle.rs index 1d67bf3a1c..95bdf5e9b1 100644 --- a/src/test/compile-fail/imports/rfc-1560-warning-cycle.rs +++ b/src/test/compile-fail/imports/rfc-1560-warning-cycle.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(rustc_attrs)] #![allow(unused)] pub struct Foo; @@ -20,12 +19,11 @@ mod bar { use *; //~ NOTE `Foo` could refer to the name imported here use bar::*; //~ NOTE `Foo` could also refer to the name imported here fn f(_: Foo) {} - //~^ WARN `Foo` is ambiguous + //~^ ERROR `Foo` is ambiguous //~| WARN hard error in a future release //~| NOTE see issue #38260 - //~| NOTE #[warn(legacy_imports)] on by default + //~| NOTE #[deny(legacy_imports)] on by default } } -#[rustc_error] -fn main() {} //~ ERROR compilation successful +fn main() {} diff --git a/src/test/compile-fail/index-bot.rs b/src/test/compile-fail/index-bot.rs index 05b0472330..fc88ff6f47 100644 --- a/src/test/compile-fail/index-bot.rs +++ b/src/test/compile-fail/index-bot.rs @@ -9,5 +9,5 @@ // except according to those terms. fn main() { - (return)[0]; //~ ERROR cannot index a value of type `!` + (return)[0]; //~ ERROR cannot index into a value of type `!` } diff --git a/src/test/compile-fail/index_message.rs b/src/test/compile-fail/index_message.rs index 26dd98757a..b9daad936c 100644 --- a/src/test/compile-fail/index_message.rs +++ b/src/test/compile-fail/index_message.rs @@ -10,5 +10,5 @@ fn main() { let z = (); - let _ = z[0]; //~ ERROR cannot index a value of type `()` + let _ = z[0]; //~ ERROR cannot index into a value of type `()` } diff --git a/src/test/compile-fail/issue-10991.rs b/src/test/compile-fail/issue-10991.rs index 25060b94dc..2d00f339f3 100644 --- a/src/test/compile-fail/issue-10991.rs +++ b/src/test/compile-fail/issue-10991.rs @@ -10,5 +10,5 @@ fn main() { let nil = (); - let _t = nil as usize; //~ ERROR: non-scalar cast: `()` as `usize` + let _t = nil as usize; //~ ERROR: non-primitive cast: `()` as `usize` } diff --git a/src/test/compile-fail/issue-11740.rs b/src/test/compile-fail/issue-11740.rs new file mode 100644 index 0000000000..0bda06be9e --- /dev/null +++ b/src/test/compile-fail/issue-11740.rs @@ -0,0 +1,38 @@ +// 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. + +#![feature(rustc_attrs)] +#![allow(warnings)] + +struct Attr { + name: String, + value: String, +} + +struct Element { + attrs: Vec>, +} + +impl Element { + pub unsafe fn get_attr<'a>(&'a self, name: &str) { + self.attrs + .iter() + .find(|attr| { + let attr: &&Box = std::mem::transmute(attr); + true + }); + } +} + +#[rustc_error] +fn main() { //~ ERROR compilation successful + let element = Element { attrs: Vec::new() }; + let _ = unsafe { element.get_attr("foo") }; +} diff --git a/src/test/compile-fail/issue-13853-5.rs b/src/test/compile-fail/issue-13853-5.rs index 6a017f7bb3..78b079a7c4 100644 --- a/src/test/compile-fail/issue-13853-5.rs +++ b/src/test/compile-fail/issue-13853-5.rs @@ -11,7 +11,7 @@ trait Deserializer<'a> { } trait Deserializable { - fn deserialize_token<'a, D: Deserializer<'a>>(D, &'a str) -> Self; + fn deserialize_token<'a, D: Deserializer<'a>>(_: D, _: &'a str) -> Self; } impl<'a, T: Deserializable> Deserializable for &'a str { diff --git a/src/test/compile-fail/issue-17718-const-borrow.rs b/src/test/compile-fail/issue-17718-const-borrow.rs index ec6d1141c1..327b694682 100644 --- a/src/test/compile-fail/issue-17718-const-borrow.rs +++ b/src/test/compile-fail/issue-17718-const-borrow.rs @@ -14,13 +14,13 @@ use std::cell::UnsafeCell; const A: UnsafeCell = UnsafeCell::new(1); const B: &'static UnsafeCell = &A; -//~^ ERROR: cannot borrow a constant which contains interior mutability +//~^ ERROR: cannot borrow a constant which may contain interior mutability struct C { a: UnsafeCell } const D: C = C { a: UnsafeCell::new(1) }; const E: &'static UnsafeCell = &D.a; -//~^ ERROR: cannot borrow a constant which contains interior mutability +//~^ ERROR: cannot borrow a constant which may contain interior mutability const F: &'static C = &D; -//~^ ERROR: cannot borrow a constant which contains interior mutability +//~^ ERROR: cannot borrow a constant which may contain interior mutability fn main() {} diff --git a/src/test/compile-fail/issue-18400.rs b/src/test/compile-fail/issue-18400.rs index f8d85f9393..dd17189aee 100644 --- a/src/test/compile-fail/issue-18400.rs +++ b/src/test/compile-fail/issue-18400.rs @@ -9,8 +9,8 @@ // except according to those terms. trait Set { - fn contains(&self, T) -> bool; - fn set(&mut self, T); + fn contains(&self, _: T) -> bool; + fn set(&mut self, _: T); } impl<'a, T, S> Set<&'a [T]> for S where diff --git a/src/test/compile-fail/issue-19498.rs b/src/test/compile-fail/issue-19498.rs index 88e804fb8a..7de16e5ecf 100644 --- a/src/test/compile-fail/issue-19498.rs +++ b/src/test/compile-fail/issue-19498.rs @@ -8,16 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use self::A; //~ NOTE previous import of `A` here -use self::B; //~ NOTE previous import of `B` here -mod A {} //~ ERROR a module named `A` has already been imported in this module -//~| `A` already imported -pub mod B {} //~ ERROR a module named `B` has already been imported in this module -//~| `B` already imported +use self::A; //~ NOTE previous import of the module `A` here +use self::B; //~ NOTE previous import of the module `B` here +mod A {} //~ ERROR the name `A` is defined multiple times +//~| `A` redefined here +//~| NOTE `A` must be defined only once in the type namespace of this module +pub mod B {} //~ ERROR the name `B` is defined multiple times +//~| `B` redefined here +//~| NOTE `B` must be defined only once in the type namespace of this module mod C { - use C::D; //~ NOTE previous import of `D` here - mod D {} //~ ERROR a module named `D` has already been imported in this module - //~| `D` already imported + use C::D; //~ NOTE previous import of the module `D` here + mod D {} //~ ERROR the name `D` is defined multiple times + //~| `D` redefined here + //~| NOTE `D` must be defined only once in the type namespace of this module } fn main() {} diff --git a/src/test/compile-fail/issue-19601.rs b/src/test/compile-fail/issue-19601.rs new file mode 100644 index 0000000000..02b4932cea --- /dev/null +++ b/src/test/compile-fail/issue-19601.rs @@ -0,0 +1,19 @@ +// 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. + +#![feature(rustc_attrs)] +#![allow(warnings)] + +trait A {} +struct B where B: A> { t: T } + +#[rustc_error] +fn main() { //~ ERROR compilation successful +} diff --git a/src/test/compile-fail/issue-20831-debruijn.rs b/src/test/compile-fail/issue-20831-debruijn.rs index dac1625159..323cd24d8d 100644 --- a/src/test/compile-fail/issue-20831-debruijn.rs +++ b/src/test/compile-fail/issue-20831-debruijn.rs @@ -22,7 +22,7 @@ pub trait Subscriber { pub trait Publisher<'a> { type Output; - fn subscribe(&mut self, Box + 'a>); + fn subscribe(&mut self, _: Box + 'a>); } pub trait Processor<'a> : Subscriber + Publisher<'a> { } diff --git a/src/test/compile-fail/issue-21174.rs b/src/test/compile-fail/issue-21174.rs index c92a404b71..9d9b7e4804 100644 --- a/src/test/compile-fail/issue-21174.rs +++ b/src/test/compile-fail/issue-21174.rs @@ -15,7 +15,7 @@ trait Trait<'a> { fn foo<'a, T: Trait<'a>>(value: T::A) { let new: T::B = unsafe { std::mem::transmute(value) }; -//~^ ERROR: transmute called with differently sized types +//~^ ERROR: transmute called with types of different sizes } fn main() { } diff --git a/src/test/compile-fail/issue-21546.rs b/src/test/compile-fail/issue-21546.rs index d103d45bc4..b7dbc7c721 100644 --- a/src/test/compile-fail/issue-21546.rs +++ b/src/test/compile-fail/issue-21546.rs @@ -12,60 +12,66 @@ #[allow(non_snake_case)] mod Foo { } -//~^ NOTE previous definition of `Foo` here +//~^ NOTE previous definition of the module `Foo` here #[allow(dead_code)] struct Foo; -//~^ ERROR a module named `Foo` has already been defined in this module -//~| NOTE already defined +//~^ ERROR the name `Foo` is defined multiple times +//~| NOTE `Foo` redefined here +//~| NOTE `Foo` must be defined only once in the type namespace of this module #[allow(non_snake_case)] mod Bar { } -//~^ NOTE previous definition of `Bar` here +//~^ NOTE previous definition of the module `Bar` here #[allow(dead_code)] struct Bar(i32); -//~^ ERROR a module named `Bar` has already been defined -//~| NOTE already defined +//~^ ERROR the name `Bar` is defined multiple times +//~| NOTE `Bar` redefined here +//~| NOTE `Bar` must be defined only once in the type namespace of this module #[allow(dead_code)] struct Baz(i32); -//~^ NOTE previous definition +//~^ NOTE previous definition of the type `Baz` here #[allow(non_snake_case)] mod Baz { } -//~^ ERROR a type named `Baz` has already been defined -//~| NOTE already defined +//~^ ERROR the name `Baz` is defined multiple times +//~| NOTE `Baz` redefined here +//~| NOTE `Baz` must be defined only once in the type namespace of this module #[allow(dead_code)] struct Qux { x: bool } -//~^ NOTE previous definition +//~^ NOTE previous definition of the type `Qux` here #[allow(non_snake_case)] mod Qux { } -//~^ ERROR a type named `Qux` has already been defined -//~| NOTE already defined +//~^ ERROR the name `Qux` is defined multiple times +//~| NOTE `Qux` redefined here +//~| NOTE `Qux` must be defined only once in the type namespace of this module #[allow(dead_code)] struct Quux; -//~^ NOTE previous definition +//~^ NOTE previous definition of the type `Quux` here #[allow(non_snake_case)] mod Quux { } -//~^ ERROR a type named `Quux` has already been defined -//~| NOTE already defined +//~^ ERROR the name `Quux` is defined multiple times +//~| NOTE `Quux` redefined here +//~| NOTE `Quux` must be defined only once in the type namespace of this module #[allow(dead_code)] enum Corge { A, B } -//~^ NOTE previous definition +//~^ NOTE previous definition of the type `Corge` here #[allow(non_snake_case)] mod Corge { } -//~^ ERROR a type named `Corge` has already been defined -//~| NOTE already defined +//~^ ERROR the name `Corge` is defined multiple times +//~| NOTE `Corge` redefined here +//~| NOTE `Corge` must be defined only once in the type namespace of this module fn main() { } diff --git a/src/test/compile-fail/issue-22034.rs b/src/test/compile-fail/issue-22034.rs index dfa9520f38..5271ea7991 100644 --- a/src/test/compile-fail/issue-22034.rs +++ b/src/test/compile-fail/issue-22034.rs @@ -17,6 +17,5 @@ fn main() { let _: &mut Fn() = unsafe { &mut *(ptr as *mut Fn()) //~^ ERROR `(): std::ops::Fn<()>` is not satisfied - //~| ERROR `(): std::ops::FnOnce<()>` is not satisfied }; } diff --git a/src/test/compile-fail/issue-22289.rs b/src/test/compile-fail/issue-22289.rs index bcbc414d35..c23fc4f334 100644 --- a/src/test/compile-fail/issue-22289.rs +++ b/src/test/compile-fail/issue-22289.rs @@ -9,5 +9,5 @@ // except according to those terms. fn main() { - 0 as &std::any::Any; //~ ERROR non-scalar cast + 0 as &std::any::Any; //~ ERROR non-primitive cast } diff --git a/src/test/compile-fail/issue-22312.rs b/src/test/compile-fail/issue-22312.rs index 4d6e6eded2..2128c42063 100644 --- a/src/test/compile-fail/issue-22312.rs +++ b/src/test/compile-fail/issue-22312.rs @@ -19,7 +19,7 @@ pub trait Array2D: Index { } let i = y * self.columns() + x; let indexer = &(*self as &Index>::Output>); - //~^ERROR non-scalar cast + //~^ERROR non-primitive cast Some(indexer.index(i)) } } diff --git a/src/test/compile-fail/issue-22603.rs b/src/test/compile-fail/issue-22603.rs new file mode 100644 index 0000000000..d08f916b87 --- /dev/null +++ b/src/test/compile-fail/issue-22603.rs @@ -0,0 +1,23 @@ +// 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. + +#![feature(unboxed_closures, fn_traits, rustc_attrs)] + +struct Foo; + +impl FnOnce<(A,)> for Foo { + type Output = (); + extern "rust-call" fn call_once(self, (_,): (A,)) { + } +} +#[rustc_error] +fn main() { //~ ERROR compilation successful + println!("{:?}", Foo("bar")); +} diff --git a/src/test/compile-fail/issue-22789.rs b/src/test/compile-fail/issue-22789.rs new file mode 100644 index 0000000000..cba1c367bb --- /dev/null +++ b/src/test/compile-fail/issue-22789.rs @@ -0,0 +1,17 @@ +// 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. + +#![feature(unboxed_closures, fn_traits, rustc_attrs)] + +#[rustc_error] +fn main() { //~ ERROR compilation successful + let k = |x: i32| { x + 1 }; + Fn::call(&k, (0,)); +} diff --git a/src/test/compile-fail/issue-23046.rs b/src/test/compile-fail/issue-23046.rs index 28109747b7..129f7c8b1e 100644 --- a/src/test/compile-fail/issue-23046.rs +++ b/src/test/compile-fail/issue-23046.rs @@ -24,7 +24,7 @@ pub fn let_<'var, VAR, F: for<'v: 'var> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>> } fn main() { - let ex = |x| { - let_(add(x,x), |y| { //~ ERROR type annotations needed + let ex = |x| { //~ ERROR type annotations needed + let_(add(x,x), |y| { let_(add(x, x), |x|x)})}; } diff --git a/src/test/compile-fail/issue-23966.rs b/src/test/compile-fail/issue-23966.rs index 7f9c7a292f..544d3c8af2 100644 --- a/src/test/compile-fail/issue-23966.rs +++ b/src/test/compile-fail/issue-23966.rs @@ -11,5 +11,4 @@ fn main() { "".chars().fold(|_, _| (), ()); //~^ ERROR E0277 - //~| ERROR E0277 } diff --git a/src/test/compile-fail/issue-24081.rs b/src/test/compile-fail/issue-24081.rs index 26bb72b862..dc8fc01bbf 100644 --- a/src/test/compile-fail/issue-24081.rs +++ b/src/test/compile-fail/issue-24081.rs @@ -8,21 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::ops::Add; //~ NOTE previous import -use std::ops::Sub; //~ NOTE previous import -use std::ops::Mul; //~ NOTE previous import -use std::ops::Div; //~ NOTE previous import -use std::ops::Rem; //~ NOTE previous import +use std::ops::Add; //~ NOTE previous import of the trait `Add` here +use std::ops::Sub; //~ NOTE previous import of the trait `Sub` here +use std::ops::Mul; //~ NOTE previous import of the trait `Mul` here +use std::ops::Div; //~ NOTE previous import of the trait `Div` here +use std::ops::Rem; //~ NOTE previous import of the trait `Rem` here -type Add = bool; //~ ERROR a trait named `Add` has already been imported in this module -//~| `Add` already imported -struct Sub { x: f32 } //~ ERROR a trait named `Sub` has already been imported in this module -//~| `Sub` already imported -enum Mul { A, B } //~ ERROR a trait named `Mul` has already been imported in this module -//~| `Mul` already imported -mod Div { } //~ ERROR a trait named `Div` has already been imported in this module -//~| `Div` already imported -trait Rem { } //~ ERROR a trait named `Rem` has already been imported in this module -//~| `Rem` already imported +type Add = bool; //~ ERROR the name `Add` is defined multiple times +//~| `Add` redefined here +//~| NOTE `Add` must be defined only once in the type namespace of this module +struct Sub { x: f32 } //~ ERROR the name `Sub` is defined multiple times +//~| `Sub` redefined here +//~| NOTE `Sub` must be defined only once in the type namespace of this module +enum Mul { A, B } //~ ERROR the name `Mul` is defined multiple times +//~| `Mul` redefined here +//~| NOTE `Mul` must be defined only once in the type namespace of this module +mod Div { } //~ ERROR the name `Div` is defined multiple times +//~| `Div` redefined here +//~| NOTE `Div` must be defined only once in the type namespace of this module +trait Rem { } //~ ERROR the name `Rem` is defined multiple times +//~| `Rem` redefined here +//~| NOTE `Rem` must be defined only once in the type namespace of this module fn main() {} diff --git a/src/test/compile-fail/issue-24363.rs b/src/test/compile-fail/issue-24363.rs index 03cae6e64e..619ad74ad0 100644 --- a/src/test/compile-fail/issue-24363.rs +++ b/src/test/compile-fail/issue-24363.rs @@ -9,7 +9,7 @@ // except according to those terms. fn main() { - 1.create_a_type_error[ //~ no field `create_a_type_error` on type `{integer}` + 1.create_a_type_error[ //~ `{integer}` is a primitive type and therefore doesn't have fields ()+() //~ ERROR binary operation `+` cannot be applied // ^ ensure that we typeck the inner expression ^ ]; diff --git a/src/test/compile-fail/issue-25396.rs b/src/test/compile-fail/issue-25396.rs index ec77e6ebd7..7cfcbc5471 100644 --- a/src/test/compile-fail/issue-25396.rs +++ b/src/test/compile-fail/issue-25396.rs @@ -9,16 +9,16 @@ // except according to those terms. use foo::baz; -use bar::baz; //~ ERROR a module named `baz` has already been imported +use bar::baz; //~ ERROR the name `baz` is defined multiple times use foo::Quux; -use bar::Quux; //~ ERROR a trait named `Quux` has already been imported +use bar::Quux; //~ ERROR the name `Quux` is defined multiple times use foo::blah; -use bar::blah; //~ ERROR a type named `blah` has already been imported +use bar::blah; //~ ERROR the name `blah` is defined multiple times use foo::WOMP; -use bar::WOMP; //~ ERROR a value named `WOMP` has already been imported +use bar::WOMP; //~ ERROR the name `WOMP` is defined multiple times fn main() {} diff --git a/src/test/compile-fail/dep-graph-unrelated.rs b/src/test/compile-fail/issue-26614.rs similarity index 57% rename from src/test/compile-fail/dep-graph-unrelated.rs rename to src/test/compile-fail/issue-26614.rs index 079f2b52fd..c128fb3b47 100644 --- a/src/test/compile-fail/dep-graph-unrelated.rs +++ b/src/test/compile-fail/issue-26614.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,15 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that two unrelated functions have no trans dependency. +#![feature(rustc_attrs)] +#![allow(warnings)] -// compile-flags: -Z query-dep-graph +trait Mirror { + type It; +} -#![feature(rustc_attrs)] -#![allow(dead_code)] +impl Mirror for T { + type It = Self; +} -#[rustc_if_this_changed] -fn main() { } -#[rustc_then_this_would_need(TransCrateItem)] //~ ERROR no path from `main` -fn bar() { } +#[rustc_error] +fn main() { //~ ERROR compilation successful + let c: ::It = 5; + const CCCC: ::It = 5; +} diff --git a/src/test/compile-fail/issue-26638.rs b/src/test/compile-fail/issue-26638.rs index f918f0aed7..9b8c7b2507 100644 --- a/src/test/compile-fail/issue-26638.rs +++ b/src/test/compile-fail/issue-26638.rs @@ -10,7 +10,7 @@ fn parse_type(iter: Box+'static>) -> &str { iter.next() } //~^ ERROR missing lifetime specifier [E0106] -//~^^ HELP 2 elided lifetimes +//~^^ HELP 2 lifetimes fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() } //~^ ERROR missing lifetime specifier [E0106] diff --git a/src/test/compile-fail/issue-26886.rs b/src/test/compile-fail/issue-26886.rs index 46e82363c8..9b19506019 100644 --- a/src/test/compile-fail/issue-26886.rs +++ b/src/test/compile-fail/issue-26886.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::sync::{self, Arc}; //~ NOTE previous import - //~^ NOTE previous import -use std::sync::Arc; //~ ERROR a type named - //~| NOTE already imported -use std::sync; //~ ERROR a module named - //~| NOTE already imported +use std::sync::{self, Arc}; //~ NOTE previous import of the type `Arc` here + //~^ NOTE previous import of the module `sync` here +use std::sync::Arc; //~ ERROR the name `Arc` is defined multiple times + //~| NOTE `Arc` reimported here + //~| `Arc` must be defined only once in the type namespace of this module +use std::sync; //~ ERROR the name `sync` is defined multiple times + //~| NOTE `sync` reimported here + //~| `sync` must be defined only once in the type namespace of this module fn main() { } diff --git a/src/test/compile-fail/issue-27842.rs b/src/test/compile-fail/issue-27842.rs index f7cd4e03c3..8c71761df2 100644 --- a/src/test/compile-fail/issue-27842.rs +++ b/src/test/compile-fail/issue-27842.rs @@ -12,13 +12,13 @@ fn main() { let tup = (0, 1, 2); // the case where we show a suggestion let _ = tup[0]; - //~^ ERROR cannot index a value of type + //~^ ERROR cannot index into a value of type //~| HELP to access tuple elements, use //~| SUGGESTION let _ = tup.0 // the case where we show just a general hint let i = 0_usize; let _ = tup[i]; - //~^ ERROR cannot index a value of type + //~^ ERROR cannot index into a value of type //~| HELP to access tuple elements, use tuple indexing syntax (e.g. `tuple.0`) } diff --git a/src/test/compile-fail/issue-28472.rs b/src/test/compile-fail/issue-28472.rs index ca5bd9c671..837de8eddc 100644 --- a/src/test/compile-fail/issue-28472.rs +++ b/src/test/compile-fail/issue-28472.rs @@ -13,10 +13,10 @@ extern { fn foo(); - pub //~ ERROR a value named `foo` has already been defined + pub //~ ERROR the name `foo` is defined multiple times fn foo(); - pub //~ ERROR a value named `foo` has already been defined + pub //~ ERROR the name `foo` is defined multiple times static mut foo: u32; } diff --git a/src/test/compile-fail/issue-28625.rs b/src/test/compile-fail/issue-28625.rs index c332e4ea45..dc9155ed66 100644 --- a/src/test/compile-fail/issue-28625.rs +++ b/src/test/compile-fail/issue-28625.rs @@ -17,7 +17,7 @@ struct ArrayPeano { } fn foo(a: &ArrayPeano) -> &[T] where T: Bar { - unsafe { std::mem::transmute(a) } //~ ERROR transmute called with differently sized types + unsafe { std::mem::transmute(a) } //~ ERROR transmute called with types of different sizes } impl Bar for () { diff --git a/src/test/compile-fail/issue-28992-empty.rs b/src/test/compile-fail/issue-28992-empty.rs index 48aabce708..536784508b 100644 --- a/src/test/compile-fail/issue-28992-empty.rs +++ b/src/test/compile-fail/issue-28992-empty.rs @@ -10,7 +10,6 @@ // Can't use constants as tuple struct patterns -#![feature(associated_consts)] const C1: i32 = 0; diff --git a/src/test/compile-fail/issue-2995.rs b/src/test/compile-fail/issue-2995.rs index 8fbf97411c..d735e184d5 100644 --- a/src/test/compile-fail/issue-2995.rs +++ b/src/test/compile-fail/issue-2995.rs @@ -9,7 +9,7 @@ // except according to those terms. fn bad (p: *const isize) { - let _q: &isize = p as &isize; //~ ERROR non-scalar cast + let _q: &isize = p as &isize; //~ ERROR non-primitive cast } fn main() { } diff --git a/src/test/compile-fail/issue-30255.rs b/src/test/compile-fail/issue-30255.rs index 1daa6a61f7..e3f55ae51e 100644 --- a/src/test/compile-fail/issue-30255.rs +++ b/src/test/compile-fail/issue-30255.rs @@ -17,19 +17,19 @@ struct S<'a> { fn f(a: &S, b: i32) -> &i32 { //~^ ERROR missing lifetime specifier [E0106] -//~^^ HELP does not say which one of `a`'s 2 elided lifetimes it is borrowed from +//~^^ HELP does not say which one of `a`'s 2 lifetimes it is borrowed from panic!(); } fn g(a: &S, b: bool, c: &i32) -> &i32 { //~^ ERROR missing lifetime specifier [E0106] -//~^^ HELP does not say whether it is borrowed from one of `a`'s 2 elided lifetimes or `c` +//~^^ HELP does not say whether it is borrowed from one of `a`'s 2 lifetimes or `c` panic!(); } fn h(a: &bool, b: bool, c: &S, d: &i32) -> &i32 { //~^ ERROR missing lifetime specifier [E0106] -//~^^ HELP does not say whether it is borrowed from `a`, one of `c`'s 2 elided lifetimes, or `d` +//~^^ HELP does not say whether it is borrowed from `a`, one of `c`'s 2 lifetimes, or `d` panic!(); } diff --git a/src/test/compile-fail/issue-3099-a.rs b/src/test/compile-fail/issue-3099-a.rs index cc7de01b06..db60d70ca9 100644 --- a/src/test/compile-fail/issue-3099-a.rs +++ b/src/test/compile-fail/issue-3099-a.rs @@ -10,6 +10,6 @@ enum a { b, c } -enum a { d, e } //~ ERROR a type named `a` has already been defined in this module +enum a { d, e } //~ ERROR the name `a` is defined multiple times fn main() {} diff --git a/src/test/compile-fail/issue-3099-b.rs b/src/test/compile-fail/issue-3099-b.rs index ae66734102..956d218675 100644 --- a/src/test/compile-fail/issue-3099-b.rs +++ b/src/test/compile-fail/issue-3099-b.rs @@ -10,6 +10,6 @@ pub mod a {} -pub mod a {} //~ ERROR a module named `a` has already been defined in this module +pub mod a {} //~ ERROR the name `a` is defined multiple times fn main() {} diff --git a/src/test/compile-fail/issue-3099.rs b/src/test/compile-fail/issue-3099.rs index 34bc21833e..4276653355 100644 --- a/src/test/compile-fail/issue-3099.rs +++ b/src/test/compile-fail/issue-3099.rs @@ -12,7 +12,7 @@ fn a(x: String) -> String { format!("First function with {}", x) } -fn a(x: String, y: String) -> String { //~ ERROR a value named `a` has already been defined +fn a(x: String, y: String) -> String { //~ ERROR the name `a` is defined multiple times format!("Second function with {} and {}", x, y) } diff --git a/src/test/compile-fail/issue-31910.rs b/src/test/compile-fail/issue-31910.rs index aac8b89e88..7524049c5d 100644 --- a/src/test/compile-fail/issue-31910.rs +++ b/src/test/compile-fail/issue-31910.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] enum Enum { X = Trait::Number, diff --git a/src/test/compile-fail/issue-32377.rs b/src/test/compile-fail/issue-32377.rs index 6e8126348d..5091ba4ee1 100644 --- a/src/test/compile-fail/issue-32377.rs +++ b/src/test/compile-fail/issue-32377.rs @@ -21,7 +21,7 @@ struct Bar { fn foo(x: [usize; 2]) -> Bar { unsafe { mem::transmute(x) } - //~^ ERROR transmute called with differently sized types + //~^ ERROR transmute called with types of different sizes } fn main() {} diff --git a/src/test/compile-fail/issue-32995-2.rs b/src/test/compile-fail/issue-32995-2.rs index cb68d52ef9..0e917ad95d 100644 --- a/src/test/compile-fail/issue-32995-2.rs +++ b/src/test/compile-fail/issue-32995-2.rs @@ -8,23 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![deny(parenthesized_params_in_types_and_modules)] -//~^ NOTE lint level defined here -//~| NOTE lint level defined here -//~| NOTE lint level defined here -#![allow(dead_code, unused_variables)] #![feature(conservative_impl_trait)] +#![allow(unused)] fn main() { { fn f() {} } //~^ ERROR parenthesized parameters may only be used with a trait //~| WARN previously accepted - //~| NOTE issue #42238 { fn f() -> impl ::std::marker()::Send { } } //~^ ERROR parenthesized parameters may only be used with a trait //~| WARN previously accepted - //~| NOTE issue #42238 } #[derive(Clone)] @@ -33,4 +27,3 @@ struct X; impl ::std::marker()::Copy for X {} //~^ ERROR parenthesized parameters may only be used with a trait //~| WARN previously accepted -//~| NOTE issue #42238 diff --git a/src/test/compile-fail/issue-32995.rs b/src/test/compile-fail/issue-32995.rs index f2ed8bf53e..4b7f82943b 100644 --- a/src/test/compile-fail/issue-32995.rs +++ b/src/test/compile-fail/issue-32995.rs @@ -8,26 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![deny(parenthesized_params_in_types_and_modules)] -//~^ NOTE lint level defined here -//~| NOTE lint level defined here -//~| NOTE lint level defined here -//~| NOTE lint level defined here -//~| NOTE lint level defined here -//~| NOTE lint level defined here -//~| NOTE lint level defined here -#![allow(dead_code, unused_variables)] +#![allow(unused)] fn main() { let x: usize() = 1; //~^ ERROR parenthesized parameters may only be used with a trait //~| WARN previously accepted - //~| NOTE issue #42238 let b: ::std::boxed()::Box<_> = Box::new(1); //~^ ERROR parenthesized parameters may only be used with a trait //~| WARN previously accepted - //~| NOTE issue #42238 macro_rules! pathexpr { ($p:path) => { $p } @@ -36,27 +26,22 @@ fn main() { let p = pathexpr!(::std::str()::from_utf8)(b"foo").unwrap(); //~^ ERROR parenthesized parameters may only be used with a trait //~| WARN previously accepted - //~| NOTE issue #42238 let p = pathexpr!(::std::str::from_utf8())(b"foo").unwrap(); //~^ ERROR parenthesized parameters may only be used with a trait //~| WARN previously accepted - //~| NOTE issue #42238 let o : Box<::std::marker()::Send> = Box::new(1); //~^ ERROR parenthesized parameters may only be used with a trait //~| WARN previously accepted - //~| NOTE issue #42238 let o : Box = Box::new(1); //~^ ERROR parenthesized parameters may only be used with a trait //~| WARN previously accepted - //~| NOTE issue #42238 } fn foo() { let d : X() = Default::default(); //~^ ERROR parenthesized parameters may only be used with a trait //~| WARN previously accepted - //~| NOTE issue #42238 } diff --git a/src/test/compile-fail/issue-34222-1.rs b/src/test/compile-fail/issue-34222-1.rs new file mode 100644 index 0000000000..6c85414860 --- /dev/null +++ b/src/test/compile-fail/issue-34222-1.rs @@ -0,0 +1,13 @@ +// 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. + +fn main() { + /// comment //~ ERROR found a documentation comment that doesn't document anything +} diff --git a/src/test/compile-fail/issue-34222.rs b/src/test/compile-fail/issue-34222.rs new file mode 100644 index 0000000000..4609c0ccb1 --- /dev/null +++ b/src/test/compile-fail/issue-34222.rs @@ -0,0 +1,18 @@ +// 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. + +#![feature(rustc_attrs)] +#![allow(warnings)] + +#[rustc_error] +fn main() { //~ ERROR compilation successful + /// crash + let x = 0; +} diff --git a/src/test/compile-fail/issue-34373.rs b/src/test/compile-fail/issue-34373.rs new file mode 100644 index 0000000000..7bbc680197 --- /dev/null +++ b/src/test/compile-fail/issue-34373.rs @@ -0,0 +1,21 @@ +// 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. + +#![allow(warnings)] + +trait Trait { + fn foo(_: T) {} +} + +pub struct Foo>>; +type DefaultFoo = Foo; //~ ERROR unsupported cyclic reference + +fn main() { +} diff --git a/src/test/compile-fail/issue-35570.rs b/src/test/compile-fail/issue-35570.rs new file mode 100644 index 0000000000..092bf00ddd --- /dev/null +++ b/src/test/compile-fail/issue-35570.rs @@ -0,0 +1,40 @@ +// 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. + +#![feature(rustc_attrs)] + +use std::mem; + +trait Trait1 {} +trait Trait2<'a> { + type Ty; +} + +fn _ice(param: Box Trait1<<() as Trait2<'a>>::Ty>>) { + let _e: (usize, usize) = unsafe{mem::transmute(param)}; +} + +trait Lifetime<'a> { + type Out; +} +impl<'a> Lifetime<'a> for () { + type Out = &'a (); +} +fn foo<'a>(x: &'a ()) -> <() as Lifetime<'a>>::Out { + x +} + +fn takes_lifetime(_f: for<'a> fn(&'a ()) -> <() as Lifetime<'a>>::Out) { +} + +#[rustc_error] +fn main() { //~ ERROR compilation successful + takes_lifetime(foo); +} diff --git a/src/test/compile-fail/issue-35675.rs b/src/test/compile-fail/issue-35675.rs index 001c1f2edd..c09e56cbc5 100644 --- a/src/test/compile-fail/issue-35675.rs +++ b/src/test/compile-fail/issue-35675.rs @@ -12,14 +12,13 @@ enum Fruit { //~ HELP possible candidate is found in another module, you can import it into scope //~^ HELP possible candidate is found in another module, you can import it into scope Apple(i64), - //~^ HELP there is an enum variant `Fruit::Apple`, did you mean to use `Fruit`? - //~| HELP there is an enum variant `Fruit::Apple`, did you mean to use `Fruit`? Orange(i64), } fn should_return_fruit() -> Apple { //~^ ERROR cannot find type `Apple` in this scope //~| NOTE not found in this scope + //~| HELP you can try using the variant's enum Apple(5) //~^ ERROR cannot find function `Apple` in this scope //~| NOTE not found in this scope @@ -27,6 +26,7 @@ fn should_return_fruit() -> Apple { fn should_return_fruit_too() -> Fruit::Apple { //~^ ERROR expected type, found variant `Fruit::Apple` + //~| HELP you can try using the variant's enum //~| NOTE not a type Apple(5) //~^ ERROR cannot find function `Apple` in this scope @@ -43,6 +43,7 @@ fn foo() -> Ok { fn bar() -> Variant3 { //~^ ERROR cannot find type `Variant3` in this scope + //~| HELP you can try using the variant's enum //~| NOTE not found in this scope } @@ -61,7 +62,6 @@ mod x { Variant1, Variant2(), Variant3(usize), - //~^ HELP there is an enum variant `x::Enum::Variant3`, did you mean to use `x::Enum`? Variant4 {}, } } diff --git a/src/test/compile-fail/issue-35869.rs b/src/test/compile-fail/issue-35869.rs index d1d6390cce..1942fd38d1 100644 --- a/src/test/compile-fail/issue-35869.rs +++ b/src/test/compile-fail/issue-35869.rs @@ -11,9 +11,9 @@ #![feature(conservative_impl_trait)] trait Foo { - fn foo(fn(u8) -> ()); //~ NOTE type in trait - fn bar(Option); //~ NOTE type in trait - fn baz((u8, u16)); //~ NOTE type in trait + fn foo(_: fn(u8) -> ()); //~ NOTE type in trait + fn bar(_: Option); //~ NOTE type in trait + fn baz(_: (u8, u16)); //~ NOTE type in trait fn qux() -> u8; //~ NOTE type in trait } diff --git a/src/test/compile-fail/issue-36839.rs b/src/test/compile-fail/issue-36839.rs new file mode 100644 index 0000000000..3e34b25067 --- /dev/null +++ b/src/test/compile-fail/issue-36839.rs @@ -0,0 +1,32 @@ +// 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. + +#![feature(rustc_attrs)] + +pub trait Foo { + type Bar; +} + +pub trait Broken { + type Assoc; + fn broken(&self) where Self::Assoc: Foo; +} + +impl Broken for T { + type Assoc = (); + fn broken(&self) where Self::Assoc: Foo { + let _x: ::Bar; + } +} + +#[rustc_error] +fn main() { //~ ERROR compilation successful + let _m: &Broken = &(); +} diff --git a/src/test/compile-fail/issue-36881.rs b/src/test/compile-fail/issue-36881.rs index d75ac0c7f2..e05dc06619 100644 --- a/src/test/compile-fail/issue-36881.rs +++ b/src/test/compile-fail/issue-36881.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(rand)] +// aux-build:issue-36881-aux.rs fn main() { - extern crate rand; - use rand::Rng; //~ ERROR unresolved import + extern crate issue_36881_aux; + use issue_36881_aux::Foo; //~ ERROR unresolved import } diff --git a/src/test/compile-fail/issue-37051.rs b/src/test/compile-fail/issue-37051.rs new file mode 100644 index 0000000000..ab08e1899a --- /dev/null +++ b/src/test/compile-fail/issue-37051.rs @@ -0,0 +1,29 @@ +// 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. + +#![feature(rustc_attrs, associated_type_defaults)] +#![allow(warnings)] + +trait State: Sized { + type NextState: State = StateMachineEnded; + fn execute(self) -> Option; +} + +struct StateMachineEnded; + +impl State for StateMachineEnded { + fn execute(self) -> Option { + None + } +} + +#[rustc_error] +fn main() { //~ ERROR compilation successful +} diff --git a/src/test/compile-fail/issue-37323.rs b/src/test/compile-fail/issue-37323.rs new file mode 100644 index 0000000000..98806cdd1b --- /dev/null +++ b/src/test/compile-fail/issue-37323.rs @@ -0,0 +1,28 @@ +// 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. + +#![feature(rustc_attrs)] +#![allow(warnings)] + +#[derive(Debug)] +struct Point { +} + +struct NestedA<'a, 'b> { + x: &'a NestedB<'b> + //~^ ERROR E0491 +} + +struct NestedB<'a> { + x: &'a i32, +} + +fn main() { +} diff --git a/src/test/compile-fail/issue-37366.rs b/src/test/compile-fail/issue-37366.rs new file mode 100644 index 0000000000..2a4808fb18 --- /dev/null +++ b/src/test/compile-fail/issue-37366.rs @@ -0,0 +1,26 @@ +// 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. + +// ignore-emscripten + +#![feature(rustc_attrs, asm)] + +macro_rules! interrupt_handler { + () => { + unsafe fn _interrupt_handler() { + asm!("pop eax" :::: "intel"); + } + } +} +interrupt_handler!{} + +#[rustc_error] +fn main() { //~ ERROR compilation successful +} diff --git a/src/test/compile-fail/issue-37510.rs b/src/test/compile-fail/issue-37510.rs new file mode 100644 index 0000000000..53c91f323d --- /dev/null +++ b/src/test/compile-fail/issue-37510.rs @@ -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. + +#![feature(rustc_attrs)] + +fn foo(_: &mut i32) -> bool { true } + +#[rustc_error] +fn main() { //~ ERROR compilation successful + let opt = Some(92); + let mut x = 62; + + if let Some(_) = opt { + + } else if foo(&mut x) { + + } +} diff --git a/src/test/compile-fail/issue-37515.rs b/src/test/compile-fail/issue-37515.rs new file mode 100644 index 0000000000..fa452d6e74 --- /dev/null +++ b/src/test/compile-fail/issue-37515.rs @@ -0,0 +1,18 @@ +// 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. + +#![feature(rustc_attrs)] + +type Z = for<'x> Send; +//~^ WARN type alias is never used + +#[rustc_error] +fn main() { //~ ERROR compilation successful +} diff --git a/src/test/compile-fail/issue-38293.rs b/src/test/compile-fail/issue-38293.rs index bf24621a86..bd352b204b 100644 --- a/src/test/compile-fail/issue-38293.rs +++ b/src/test/compile-fail/issue-38293.rs @@ -11,7 +11,6 @@ // Test that `fn foo::bar::{self}` only imports `bar` in the type namespace. #![allow(unused)] -#![deny(legacy_imports)] mod foo { pub fn f() { } diff --git a/src/test/compile-fail/issue-38381.rs b/src/test/compile-fail/issue-38381.rs new file mode 100644 index 0000000000..6b7dde117d --- /dev/null +++ b/src/test/compile-fail/issue-38381.rs @@ -0,0 +1,18 @@ +// 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. + +#![feature(rustc_attrs)] + +use std::ops::Deref; + +#[rustc_error] +fn main() { //~ ERROR compilation successful + let _x: fn(&i32) -> <&i32 as Deref>::Target = unimplemented!(); +} diff --git a/src/test/compile-fail/issue-38954.rs b/src/test/compile-fail/issue-38954.rs index 65b17a3db0..896728b6da 100644 --- a/src/test/compile-fail/issue-38954.rs +++ b/src/test/compile-fail/issue-38954.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(rustc_attrs)] - fn _test(ref _p: str) {} +//~^ ERROR the trait bound `str: std::marker::Sized` is not satisfied [E0277] -#[rustc_error] -fn main() { } //~ ERROR compilation successful +fn main() { } diff --git a/src/test/compile-fail/issue-39404.rs b/src/test/compile-fail/issue-39404.rs index 8b49772494..56bfe27a4f 100644 --- a/src/test/compile-fail/issue-39404.rs +++ b/src/test/compile-fail/issue-39404.rs @@ -8,12 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![deny(missing_fragment_specifier)] //~ NOTE lint level defined here -#![allow(unused_macros)] +#![allow(unused)] macro_rules! m { ($i) => {} } //~^ ERROR missing fragment specifier //~| WARN previously accepted -//~| NOTE issue #40107 fn main() {} diff --git a/src/test/compile-fail/issue-40861.rs b/src/test/compile-fail/issue-40861.rs index e525b3954f..75d58c5853 100644 --- a/src/test/compile-fail/issue-40861.rs +++ b/src/test/compile-fail/issue-40861.rs @@ -12,5 +12,5 @@ fn f(_: &[f32]) {} fn main() { ()[f(&[1.0])]; - //~^ ERROR cannot index a value of type `()` + //~^ ERROR cannot index into a value of type `()` } diff --git a/src/test/compile-fail/issue-41549.rs b/src/test/compile-fail/issue-41549.rs index c4aab4bcab..67be194c8e 100644 --- a/src/test/compile-fail/issue-41549.rs +++ b/src/test/compile-fail/issue-41549.rs @@ -10,7 +10,6 @@ // aux-build:issue_41549.rs -#![feature(associated_consts)] extern crate issue_41549; diff --git a/src/test/compile-fail/issue-41998.rs b/src/test/compile-fail/issue-41998.rs new file mode 100644 index 0000000000..406aadcd21 --- /dev/null +++ b/src/test/compile-fail/issue-41998.rs @@ -0,0 +1,20 @@ +// 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. + +#![feature(rustc_attrs)] + +#[rustc_error] +fn main() { //~ ERROR compilation successful + if ('x' as char) < ('y' as char) { + print!("x"); + } else { + print!("y"); + } +} diff --git a/src/test/compile-fail/issue-42312.rs b/src/test/compile-fail/issue-42312.rs new file mode 100644 index 0000000000..06573b42b5 --- /dev/null +++ b/src/test/compile-fail/issue-42312.rs @@ -0,0 +1,21 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::ops::Deref; + +pub trait Foo { + fn baz(_: Self::Target) where Self: Deref {} + //~^ ERROR `::Target: std::marker::Sized` is not satisfied +} + +pub fn f(_: ToString) {} +//~^ ERROR the trait bound `std::string::ToString + 'static: std::marker::Sized` is not satisfied + +fn main() { } diff --git a/src/test/compile-fail/issue-42755.rs b/src/test/compile-fail/issue-42755.rs new file mode 100644 index 0000000000..7547c4a17b --- /dev/null +++ b/src/test/compile-fail/issue-42755.rs @@ -0,0 +1,17 @@ +// 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. + +#![feature(macro_vis_matcher)] + +macro_rules! foo { + ($($p:vis)*) => {} //~ ERROR repetition matches empty token tree +} + +foo!(a); diff --git a/src/test/compile-fail/issue-42880.rs b/src/test/compile-fail/issue-42880.rs new file mode 100644 index 0000000000..ebb1ec425d --- /dev/null +++ b/src/test/compile-fail/issue-42880.rs @@ -0,0 +1,18 @@ +// 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. + +type Value = String; + +fn main() { + let f = |&Value::String(_)| (); //~ ERROR no associated item named + + let vec: Vec = Vec::new(); + vec.last().map(f); +} diff --git a/src/test/compile-fail/issue-43250.rs b/src/test/compile-fail/issue-43250.rs new file mode 100644 index 0000000000..e1d34f339d --- /dev/null +++ b/src/test/compile-fail/issue-43250.rs @@ -0,0 +1,23 @@ +// 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. + +fn main() { + let mut y; + const C: u32 = 0; + macro_rules! m { + ($a:expr) => { + let $a = 0; + } + } + m!(y); + //~^ ERROR arbitrary expressions aren't allowed in patterns + m!(C); + //~^ ERROR arbitrary expressions aren't allowed in patterns +} diff --git a/src/test/compile-fail/issue-43424.rs b/src/test/compile-fail/issue-43424.rs new file mode 100644 index 0000000000..431fc8a5aa --- /dev/null +++ b/src/test/compile-fail/issue-43424.rs @@ -0,0 +1,22 @@ +// 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. + +#![allow(unused)] + +macro_rules! m { + ($attr_path: path) => { + #[$attr_path] + fn f() {} + } +} + +m!(inline); //~ ERROR: unexpected generic arguments in path + +fn main() {} diff --git a/src/test/compile-fail/issue-6936.rs b/src/test/compile-fail/issue-6936.rs index c8021a2299..8eb16edcbd 100644 --- a/src/test/compile-fail/issue-6936.rs +++ b/src/test/compile-fail/issue-6936.rs @@ -12,17 +12,17 @@ struct T; mod t1 { type Foo = ::T; - mod Foo {} //~ ERROR: `Foo` has already been defined + mod Foo {} //~ ERROR the name `Foo` is defined multiple times } mod t2 { type Foo = ::T; - struct Foo; //~ ERROR: `Foo` has already been defined + struct Foo; //~ ERROR the name `Foo` is defined multiple times } mod t3 { type Foo = ::T; - enum Foo {} //~ ERROR: `Foo` has already been defined + enum Foo {} //~ ERROR the name `Foo` is defined multiple times } mod t4 { @@ -32,7 +32,7 @@ mod t4 { mod t5 { type Bar = T; - mod Bar {} //~ ERROR: `Bar` has already been defined + mod Bar {} //~ ERROR the name `Bar` is defined multiple times } mod t6 { diff --git a/src/test/compile-fail/issue-7044.rs b/src/test/compile-fail/issue-7044.rs index 06573bea13..9b72c24935 100644 --- a/src/test/compile-fail/issue-7044.rs +++ b/src/test/compile-fail/issue-7044.rs @@ -9,6 +9,6 @@ // except according to those terms. static X: isize = 0; -struct X; //~ ERROR `X` has already been defined +struct X; //~ ERROR the name `X` is defined multiple times fn main() {} diff --git a/src/test/compile-fail/issue-8640.rs b/src/test/compile-fail/issue-8640.rs index e469e05a24..c4ca3acf08 100644 --- a/src/test/compile-fail/issue-8640.rs +++ b/src/test/compile-fail/issue-8640.rs @@ -13,7 +13,7 @@ mod foo { use baz::bar; mod bar {} - //~^ ERROR a module named `bar` has already been imported + //~^ ERROR the name `bar` is defined multiple times } mod baz { pub mod bar {} } diff --git a/src/test/compile-fail/lifetime-elision-return-type-requires-explicit-lifetime.rs b/src/test/compile-fail/lifetime-elision-return-type-requires-explicit-lifetime.rs index 43371eb634..2d9de57a26 100644 --- a/src/test/compile-fail/lifetime-elision-return-type-requires-explicit-lifetime.rs +++ b/src/test/compile-fail/lifetime-elision-return-type-requires-explicit-lifetime.rs @@ -28,7 +28,7 @@ struct Foo<'a> { // Lifetime annotation needed because we have two lifetimes: one as a parameter // and one on the reference. fn h(_x: &Foo) -> &isize { //~ ERROR missing lifetime specifier -//~^ HELP the signature does not say which one of `_x`'s 2 elided lifetimes it is borrowed from +//~^ HELP the signature does not say which one of `_x`'s 2 lifetimes it is borrowed from panic!() } diff --git a/src/test/compile-fail/lint-unused-extern-crate.rs b/src/test/compile-fail/lint-unused-extern-crate.rs index 40671353f8..b12ef6277b 100644 --- a/src/test/compile-fail/lint-unused-extern-crate.rs +++ b/src/test/compile-fail/lint-unused-extern-crate.rs @@ -9,34 +9,34 @@ // except according to those terms. // aux-build:lint_unused_extern_crate.rs +// aux-build:lint_unused_extern_crate2.rs +// aux-build:lint_unused_extern_crate3.rs +// aux-build:lint_unused_extern_crate4.rs #![deny(unused_extern_crates)] #![allow(unused_variables)] #![allow(deprecated)] -#![feature(libc)] -#![feature(collections)] -#![feature(rand)] -extern crate libc; //~ ERROR: unused extern crate +extern crate lint_unused_extern_crate4; //~ ERROR: unused extern crate -extern crate collections as collecs; // no error, it is used +extern crate lint_unused_extern_crate3; // no error, it is used -extern crate rand; // no error, the use marks it as used - // even if imported objects aren't used +extern crate lint_unused_extern_crate2; // no error, the use marks it as used + // even if imported objects aren't used extern crate lint_unused_extern_crate as other; // no error, the use * marks it as used #[allow(unused_imports)] -use rand::isaac::IsaacRng; +use lint_unused_extern_crate2::foo as bar; use other::*; mod foo { - // Test that this is unused even though an earler `extern crate rand` is used. - extern crate rand; //~ ERROR unused extern crate + // Test that this is unused even though an earler `extern crate` is used. + extern crate lint_unused_extern_crate2; //~ ERROR unused extern crate } fn main() { - let x: collecs::vec::Vec = Vec::new(); + lint_unused_extern_crate3::foo(); let y = foo(); } diff --git a/src/test/compile-fail/macro-context.rs b/src/test/compile-fail/macro-context.rs index 80802e19f8..cc714a6e43 100644 --- a/src/test/compile-fail/macro-context.rs +++ b/src/test/compile-fail/macro-context.rs @@ -23,5 +23,5 @@ fn main() { m!() => {} //~ NOTE the usage of `m!` is likely invalid in pattern context } - m!(); + m!(); //~ NOTE in this expansion } diff --git a/src/test/compile-fail/method-call-type-binding.rs b/src/test/compile-fail/method-call-type-binding.rs new file mode 100644 index 0000000000..acffb06ebe --- /dev/null +++ b/src/test/compile-fail/method-call-type-binding.rs @@ -0,0 +1,13 @@ +// 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. + +fn main() { + 0.clone::(); //~ ERROR type bindings cannot be used in method calls +} diff --git a/src/test/compile-fail/no-patterns-in-args-2.rs b/src/test/compile-fail/no-patterns-in-args-2.rs index 385d012cad..967c292fa6 100644 --- a/src/test/compile-fail/no-patterns-in-args-2.rs +++ b/src/test/compile-fail/no-patterns-in-args-2.rs @@ -17,6 +17,7 @@ trait Tr { //~^ WARN was previously accepted fn g1(arg: u8); // OK fn g2(_: u8); // OK + #[allow(anonymous_parameters)] fn g3(u8); // OK } diff --git a/src/test/compile-fail/no-std-inject.rs b/src/test/compile-fail/no-std-inject.rs index f2a27dc528..f384eafa34 100644 --- a/src/test/compile-fail/no-std-inject.rs +++ b/src/test/compile-fail/no-std-inject.rs @@ -10,7 +10,7 @@ #![no_std] -extern crate core; //~ ERROR: an extern crate named `core` has already +extern crate core; //~ ERROR: the name `core` is defined multiple times extern crate std; fn main() {} diff --git a/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs b/src/test/compile-fail/non-constant-expr-for-arr-len.rs similarity index 84% rename from src/test/compile-fail/non-constant-expr-for-vec-repeat.rs rename to src/test/compile-fail/non-constant-expr-for-arr-len.rs index 1eda508778..17df7ae234 100644 --- a/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs +++ b/src/test/compile-fail/non-constant-expr-for-arr-len.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Check that non constant exprs fail for vector repeat syntax +// Check that non constant exprs fail for array repeat syntax fn main() { fn bar(n: usize) { let _x = [0; n]; //~^ ERROR attempt to use a non-constant value in a constant [E0435] - //~| NOTE non-constant used with constant + //~| NOTE non-constant value } } diff --git a/src/test/compile-fail/nonscalar-cast.rs b/src/test/compile-fail/nonscalar-cast.rs index d6f274da96..0abbc05eef 100644 --- a/src/test/compile-fail/nonscalar-cast.rs +++ b/src/test/compile-fail/nonscalar-cast.rs @@ -8,13 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:non-scalar cast - #[derive(Debug)] struct foo { x: isize } fn main() { - println!("{}", foo{ x: 1 } as isize); + println!("{}", foo{ x: 1 } as isize); //~ non-primitive cast: `foo` as `isize` [E0605] } diff --git a/src/test/compile-fail/not-sync.rs b/src/test/compile-fail/not-sync.rs index aa7a83a7ba..12c2927917 100644 --- a/src/test/compile-fail/not-sync.rs +++ b/src/test/compile-fail/not-sync.rs @@ -10,7 +10,7 @@ use std::cell::{Cell, RefCell}; use std::rc::{Rc, Weak}; -use std::sync::mpsc::{Receiver, Sender, SyncSender}; +use std::sync::mpsc::{Receiver, Sender}; fn test() {} @@ -29,6 +29,4 @@ fn main() { //~^ ERROR `std::sync::mpsc::Receiver: std::marker::Sync` is not satisfied test::>(); //~^ ERROR `std::sync::mpsc::Sender: std::marker::Sync` is not satisfied - test::>(); - //~^ ERROR `std::sync::mpsc::SyncSender: std::marker::Sync` is not satisfied } diff --git a/src/test/compile-fail/object-safety-associated-consts.rs b/src/test/compile-fail/object-safety-associated-consts.rs index c442cd4083..ebb52face0 100644 --- a/src/test/compile-fail/object-safety-associated-consts.rs +++ b/src/test/compile-fail/object-safety-associated-consts.rs @@ -11,7 +11,6 @@ // Check that we correctly prevent users from making trait objects // from traits with associated consts. -#![feature(associated_consts)] trait Bar { const X: usize; diff --git a/src/test/compile-fail/packed-struct-generic-transmute.rs b/src/test/compile-fail/packed-struct-generic-transmute.rs index 2c345e6c8a..c96184d598 100644 --- a/src/test/compile-fail/packed-struct-generic-transmute.rs +++ b/src/test/compile-fail/packed-struct-generic-transmute.rs @@ -13,7 +13,7 @@ // the error points to the start of the file, not the line with the // transmute -// error-pattern: transmute called with differently sized types +// error-pattern: transmute called with types of different sizes use std::mem; diff --git a/src/test/compile-fail/packed-struct-transmute.rs b/src/test/compile-fail/packed-struct-transmute.rs index 94f2522f3e..abb02dd39e 100644 --- a/src/test/compile-fail/packed-struct-transmute.rs +++ b/src/test/compile-fail/packed-struct-transmute.rs @@ -13,7 +13,7 @@ // the error points to the start of the file, not the line with the // transmute -// error-pattern: transmute called with differently sized types +// error-pattern: transmute called with types of different sizes use std::mem; diff --git a/src/test/compile-fail/parse-error-correct.rs b/src/test/compile-fail/parse-error-correct.rs index 17b58a9f7c..7dedfcf272 100644 --- a/src/test/compile-fail/parse-error-correct.rs +++ b/src/test/compile-fail/parse-error-correct.rs @@ -17,5 +17,5 @@ fn main() { let y = 42; let x = y.; //~ ERROR unexpected token let x = y.(); //~ ERROR unexpected token - let x = y.foo; //~ ERROR no field + let x = y.foo; //~ ERROR `{integer}` is a primitive type and therefore doesn't have fields [E061 } diff --git a/src/test/compile-fail/patkind-litrange-no-expr.rs b/src/test/compile-fail/patkind-litrange-no-expr.rs new file mode 100644 index 0000000000..afb2cbb7db --- /dev/null +++ b/src/test/compile-fail/patkind-litrange-no-expr.rs @@ -0,0 +1,36 @@ +// 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. + +macro_rules! enum_number { + ($name:ident { $($variant:ident = $value:expr, )* }) => { + enum $name { + $($variant = $value,)* + } + + fn foo(value: i32) -> Option<$name> { + match value { + $( $value => Some($name::$variant), )* // PatKind::Lit + $( $value ... 42 => Some($name::$variant), )* // PatKind::Range + _ => None + } + } + } +} + +enum_number!(Change { + Pos = 1, + Neg = -1, + Arith = 1 + 1, //~ ERROR arbitrary expressions aren't allowed in patterns + //~^ ERROR arbitrary expressions aren't allowed in patterns + //~^^ ERROR only char and numeric types are allowed in range patterns +}); + +fn main() {} + diff --git a/src/test/compile-fail/privacy-sanity.rs b/src/test/compile-fail/privacy-sanity.rs index 063848f62a..933ec3837d 100644 --- a/src/test/compile-fail/privacy-sanity.rs +++ b/src/test/compile-fail/privacy-sanity.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] #![feature(optin_builtin_traits)] trait MarkerTr {} diff --git a/src/test/compile-fail/privacy/restricted/ty-params.rs b/src/test/compile-fail/privacy/restricted/ty-params.rs index c83a4e5685..5708d31998 100644 --- a/src/test/compile-fail/privacy/restricted/ty-params.rs +++ b/src/test/compile-fail/privacy/restricted/ty-params.rs @@ -13,7 +13,7 @@ macro_rules! m { } struct S(T); -m!{ S } //~ ERROR type or lifetime parameters in visibility path +m!{ S } //~ ERROR unexpected generic arguments in path //~^ ERROR expected module, found struct `S` fn main() {} diff --git a/src/test/compile-fail/private-in-public-warn.rs b/src/test/compile-fail/private-in-public-warn.rs index 92d96595fd..f030012b17 100644 --- a/src/test/compile-fail/private-in-public-warn.rs +++ b/src/test/compile-fail/private-in-public-warn.rs @@ -11,7 +11,6 @@ // Private types and traits are not allowed in public interfaces. // This test also ensures that the checks are performed even inside private modules. -#![feature(associated_consts)] #![feature(associated_type_defaults)] #![deny(private_in_public)] #![allow(unused)] diff --git a/src/test/compile-fail/private-in-public.rs b/src/test/compile-fail/private-in-public.rs index b819ef116e..b865e391d2 100644 --- a/src/test/compile-fail/private-in-public.rs +++ b/src/test/compile-fail/private-in-public.rs @@ -11,7 +11,6 @@ // Private types and traits are not allowed in public interfaces. // This test also ensures that the checks are performed even inside private modules. -#![feature(associated_consts)] #![feature(associated_type_defaults)] mod types { diff --git a/src/test/compile-fail/private-inferred-type-1.rs b/src/test/compile-fail/private-inferred-type-1.rs new file mode 100644 index 0000000000..ba8b3d1810 --- /dev/null +++ b/src/test/compile-fail/private-inferred-type-1.rs @@ -0,0 +1,28 @@ +// 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. + +trait Arr0 { + fn arr0_secret(&self); +} +trait TyParam { + fn ty_param_secret(&self); +} + +mod m { + struct Priv; + + impl ::Arr0 for [Priv; 0] { fn arr0_secret(&self) {} } + impl ::TyParam for Option { fn ty_param_secret(&self) {} } +} + +fn main() { + [].arr0_secret(); //~ ERROR type `m::Priv` is private + None.ty_param_secret(); //~ ERROR type `m::Priv` is private +} diff --git a/src/test/compile-fail/private-inferred-type-2.rs b/src/test/compile-fail/private-inferred-type-2.rs new file mode 100644 index 0000000000..e981f12575 --- /dev/null +++ b/src/test/compile-fail/private-inferred-type-2.rs @@ -0,0 +1,29 @@ +// 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. + +// aux-build:private-inferred-type.rs + +extern crate private_inferred_type as ext; + +mod m { + struct Priv; + pub struct Pub(pub T); + + impl Pub { + pub fn get_priv() -> Priv { Priv } + pub fn static_method() {} + } +} + +fn main() { + m::Pub::get_priv; //~ ERROR type `m::Priv` is private + m::Pub::static_method; //~ ERROR type `m::Priv` is private + ext::Pub::static_method; //~ ERROR type `ext::Priv` is private +} diff --git a/src/test/compile-fail/private-inferred-type-3.rs b/src/test/compile-fail/private-inferred-type-3.rs new file mode 100644 index 0000000000..fdd9166ef2 --- /dev/null +++ b/src/test/compile-fail/private-inferred-type-3.rs @@ -0,0 +1,26 @@ +// 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. + +// aux-build:private-inferred-type.rs + +// error-pattern:type `fn() {ext::priv_fn}` is private +// error-pattern:type `ext::PrivEnum` is private +// error-pattern:type `fn() {::method}` is private +// error-pattern:type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct::{{constructor}}}` is pr +// error-pattern:type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct::{{constructor}}}` is priv +// error-pattern:type `fn(&ext::Pub) {>::priv_method}` is private + +#![feature(decl_macro)] + +extern crate private_inferred_type as ext; + +fn main() { + ext::m!(); +} diff --git a/src/test/compile-fail/private-inferred-type.rs b/src/test/compile-fail/private-inferred-type.rs new file mode 100644 index 0000000000..140891027d --- /dev/null +++ b/src/test/compile-fail/private-inferred-type.rs @@ -0,0 +1,139 @@ +// 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. + +#![feature(associated_consts)] +#![feature(conservative_impl_trait)] +#![feature(decl_macro)] + +mod m { + fn priv_fn() {} + enum PrivEnum { Variant } + pub enum PubEnum { Variant } + trait PrivTrait { fn method() {} } + impl PrivTrait for u8 {} + pub trait PubTrait { fn method() {} } + impl PubTrait for u8 {} + struct PrivTupleStruct(u8); + pub struct PubTupleStruct(u8); + impl PubTupleStruct { fn method() {} } + + struct Priv; + pub type Alias = Priv; + pub struct Pub(pub T); + + impl Pub { + pub fn static_method() {} + pub const INHERENT_ASSOC_CONST: u8 = 0; + } + impl Pub { + pub fn static_method_generic_self() {} + pub const INHERENT_ASSOC_CONST_GENERIC_SELF: u8 = 0; + } + impl Pub { + fn priv_method(&self) {} + pub fn method_with_substs(&self) {} + pub fn method_with_priv_params(&self, _: Priv) {} + } + impl TraitWithAssocConst for Priv {} + impl TraitWithAssocTy for Priv { type AssocTy = u8; } + + pub macro m() { + priv_fn; //~ ERROR type `fn() {m::priv_fn}` is private + PrivEnum::Variant; //~ ERROR type `m::PrivEnum` is private + PubEnum::Variant; // OK + ::method; //~ ERROR type `fn() {::method}` is private + ::method; // OK + PrivTupleStruct; + //~^ ERROR type `fn(u8) -> m::PrivTupleStruct {m::PrivTupleStruct::{{constructor}}}` is priv + PubTupleStruct; + //~^ ERROR type `fn(u8) -> m::PubTupleStruct {m::PubTupleStruct::{{constructor}}}` is privat + Pub(0u8).priv_method(); + //~^ ERROR type `fn(&m::Pub) {>::priv_method}` is private + } + + trait Trait {} + pub trait TraitWithTyParam {} + pub trait TraitWithTyParam2 { fn pub_method() {} } + pub trait TraitWithAssocTy { type AssocTy; } + pub trait TraitWithAssocConst { const TRAIT_ASSOC_CONST: u8 = 0; } + impl Trait for u8 {} + impl TraitWithTyParam for u8 {} + impl TraitWithTyParam2 for u8 {} + impl TraitWithAssocTy for u8 { type AssocTy = Priv; } + + pub fn leak_anon1() -> impl Trait + 'static { 0 } + pub fn leak_anon2() -> impl TraitWithTyParam { 0 } + pub fn leak_anon3() -> impl TraitWithAssocTy { 0 } + + pub fn leak_dyn1() -> Box { Box::new(0) } + pub fn leak_dyn2() -> Box> { Box::new(0) } + pub fn leak_dyn3() -> Box> { Box::new(0) } +} + +mod adjust { + // Construct a chain of derefs with a private type in the middle + use std::ops::Deref; + + pub struct S1; + struct S2; + pub type S2Alias = S2; + pub struct S3; + + impl Deref for S1 { + type Target = S2Alias; + fn deref(&self) -> &Self::Target { loop {} } + } + impl Deref for S2 { + type Target = S3; + fn deref(&self) -> &Self::Target { loop {} } + } + + impl S3 { + pub fn method_s3(&self) {} + } +} + +fn main() { + let _: m::Alias; //~ ERROR type `m::Priv` is private + let _: ::AssocTy; // FIXME + m::Alias {}; //~ ERROR type `m::Priv` is private + m::Pub { 0: m::Alias {} }; //~ ERROR type `m::Priv` is private + m::Pub { 0: loop {} }; // FIXME + m::Pub::static_method; //~ ERROR type `m::Priv` is private + m::Pub::INHERENT_ASSOC_CONST; //~ ERROR type `m::Priv` is private + m::Pub(0u8).method_with_substs::(); //~ ERROR type `m::Priv` is private + m::Pub(0u8).method_with_priv_params(loop{}); //~ ERROR type `m::Priv` is private + ::TRAIT_ASSOC_CONST; //~ ERROR type `m::Priv` is private + >::INHERENT_ASSOC_CONST; //~ ERROR type `m::Priv` is private + >::INHERENT_ASSOC_CONST_GENERIC_SELF; //~ ERROR type `m::Priv` is private + >::static_method_generic_self; //~ ERROR type `m::Priv` is private + use m::TraitWithTyParam2; + u8::pub_method; //~ ERROR type `m::Priv` is private + + adjust::S1.method_s3(); //~ ERROR type `adjust::S2` is private + + m::m!(); + + m::leak_anon1(); //~ ERROR trait `m::Trait` is private + m::leak_anon2(); //~ ERROR type `m::Priv` is private + m::leak_anon3(); //~ ERROR type `m::Priv` is private + + m::leak_dyn1(); //~ ERROR type `m::Trait + 'static` is private + m::leak_dyn2(); //~ ERROR type `m::Priv` is private + m::leak_dyn3(); //~ ERROR type `m::Priv` is private + + // Check that messages are not duplicated for various kinds of assignments + let a = m::Alias {}; //~ ERROR type `m::Priv` is private + let mut b = a; //~ ERROR type `m::Priv` is private + b = a; //~ ERROR type `m::Priv` is private + match a { //~ ERROR type `m::Priv` is private + _ => {} + } +} diff --git a/src/test/compile-fail/private-type-in-interface.rs b/src/test/compile-fail/private-type-in-interface.rs new file mode 100644 index 0000000000..925d692f8a --- /dev/null +++ b/src/test/compile-fail/private-type-in-interface.rs @@ -0,0 +1,41 @@ +// 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. + +// aux-build:private-inferred-type.rs + +#![feature(conservative_impl_trait)] + +extern crate private_inferred_type as ext; + +mod m { + struct Priv; + pub type Alias = Priv; + + pub trait Trait { type X; } + impl Trait for Priv { type X = u8; } +} + +fn f(_: m::Alias) {} //~ ERROR type `m::Priv` is private + //~^ ERROR type `m::Priv` is private +fn f_ext(_: ext::Alias) {} //~ ERROR type `ext::Priv` is private + //~^ ERROR type `ext::Priv` is private + +trait Tr1 {} +impl m::Alias {} //~ ERROR type `m::Priv` is private +impl Tr1 for ext::Alias {} //~ ERROR type `ext::Priv` is private + //~^ ERROR type `ext::Priv` is private +type A = ::X; //~ ERROR type `m::Priv` is private + +trait Tr2 {} +impl Tr2 for u8 {} +fn g() -> impl Tr2 { 0 } //~ ERROR type `m::Priv` is private +fn g_ext() -> impl Tr2 { 0 } //~ ERROR type `ext::Priv` is private + +fn main() {} diff --git a/src/test/compile-fail/pub-reexport-priv-extern-crate.rs b/src/test/compile-fail/pub-reexport-priv-extern-crate.rs index 185da37969..5479be5453 100644 --- a/src/test/compile-fail/pub-reexport-priv-extern-crate.rs +++ b/src/test/compile-fail/pub-reexport-priv-extern-crate.rs @@ -9,7 +9,6 @@ // except according to those terms. #![allow(unused)] -#![deny(private_in_public)] extern crate core; pub use core as reexported_core; //~ ERROR `core` is private, and cannot be reexported diff --git a/src/test/compile-fail/range-1.rs b/src/test/compile-fail/range-1.rs index dc6833163a..58794e3b35 100644 --- a/src/test/compile-fail/range-1.rs +++ b/src/test/compile-fail/range-1.rs @@ -18,7 +18,6 @@ pub fn main() { // Bool => does not implement iterator. for i in false..true {} //~^ ERROR `bool: std::iter::Step` is not satisfied - //~^^ ERROR `for<'a> &'a bool: std::ops::Add` is not satisfied // Unsized type. let arr: &[_] = &[1, 2, 3]; diff --git a/src/test/compile-fail/range_traits-1.rs b/src/test/compile-fail/range_traits-1.rs index 8521971775..cf5c40bd17 100644 --- a/src/test/compile-fail/range_traits-1.rs +++ b/src/test/compile-fail/range_traits-1.rs @@ -17,8 +17,8 @@ use std::ops::*; struct AllTheRanges { a: Range, //~^ ERROR PartialOrd - //~^^ ERROR PartialOrd - //~^^^ ERROR Ord + //~^^ ERROR Ord + //~^^^ ERROR binary operation //~^^^^ ERROR binary operation //~^^^^^ ERROR binary operation //~^^^^^^ ERROR binary operation @@ -26,11 +26,10 @@ struct AllTheRanges { //~^^^^^^^^ ERROR binary operation //~^^^^^^^^^ ERROR binary operation //~^^^^^^^^^^ ERROR binary operation - //~^^^^^^^^^^^ ERROR binary operation b: RangeTo, //~^ ERROR PartialOrd - //~^^ ERROR PartialOrd - //~^^^ ERROR Ord + //~^^ ERROR Ord + //~^^^ ERROR binary operation //~^^^^ ERROR binary operation //~^^^^^ ERROR binary operation //~^^^^^^ ERROR binary operation @@ -38,11 +37,10 @@ struct AllTheRanges { //~^^^^^^^^ ERROR binary operation //~^^^^^^^^^ ERROR binary operation //~^^^^^^^^^^ ERROR binary operation - //~^^^^^^^^^^^ ERROR binary operation c: RangeFrom, //~^ ERROR PartialOrd - //~^^ ERROR PartialOrd - //~^^^ ERROR Ord + //~^^ ERROR Ord + //~^^^ ERROR binary operation //~^^^^ ERROR binary operation //~^^^^^ ERROR binary operation //~^^^^^^ ERROR binary operation @@ -50,11 +48,10 @@ struct AllTheRanges { //~^^^^^^^^ ERROR binary operation //~^^^^^^^^^ ERROR binary operation //~^^^^^^^^^^ ERROR binary operation - //~^^^^^^^^^^^ ERROR binary operation d: RangeFull, //~^ ERROR PartialOrd - //~^^ ERROR PartialOrd - //~^^^ ERROR Ord + //~^^ ERROR Ord + //~^^^ ERROR binary operation //~^^^^ ERROR binary operation //~^^^^^ ERROR binary operation //~^^^^^^ ERROR binary operation @@ -62,11 +59,10 @@ struct AllTheRanges { //~^^^^^^^^ ERROR binary operation //~^^^^^^^^^ ERROR binary operation //~^^^^^^^^^^ ERROR binary operation - //~^^^^^^^^^^^ ERROR binary operation e: RangeInclusive, //~^ ERROR PartialOrd - //~^^ ERROR PartialOrd - //~^^^ ERROR Ord + //~^^ ERROR Ord + //~^^^ ERROR binary operation //~^^^^ ERROR binary operation //~^^^^^ ERROR binary operation //~^^^^^^ ERROR binary operation @@ -74,11 +70,10 @@ struct AllTheRanges { //~^^^^^^^^ ERROR binary operation //~^^^^^^^^^ ERROR binary operation //~^^^^^^^^^^ ERROR binary operation - //~^^^^^^^^^^^ ERROR binary operation f: RangeToInclusive, //~^ ERROR PartialOrd - //~^^ ERROR PartialOrd - //~^^^ ERROR Ord + //~^^ ERROR Ord + //~^^^ ERROR binary operation //~^^^^ ERROR binary operation //~^^^^^ ERROR binary operation //~^^^^^^ ERROR binary operation @@ -86,8 +81,6 @@ struct AllTheRanges { //~^^^^^^^^ ERROR binary operation //~^^^^^^^^^ ERROR binary operation //~^^^^^^^^^^ ERROR binary operation - //~^^^^^^^^^^^ ERROR binary operation } fn main() {} - diff --git a/src/test/compile-fail/repr-align.rs b/src/test/compile-fail/repr-align.rs index eb0b27fe9c..bc9cf065e5 100644 --- a/src/test/compile-fail/repr-align.rs +++ b/src/test/compile-fail/repr-align.rs @@ -17,7 +17,7 @@ struct A(i32); #[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute: not a power of two struct B(i32); -#[repr(align(65536))] //~ ERROR: invalid `repr(align)` attribute: larger than 32768 +#[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute: larger than 2147483647 struct C(i32); fn main() {} diff --git a/src/test/compile-fail/resolve-conflict-extern-crate-vs-extern-crate.rs b/src/test/compile-fail/resolve-conflict-extern-crate-vs-extern-crate.rs index c05d0cc1b0..87a17c0f19 100644 --- a/src/test/compile-fail/resolve-conflict-extern-crate-vs-extern-crate.rs +++ b/src/test/compile-fail/resolve-conflict-extern-crate-vs-extern-crate.rs @@ -9,6 +9,6 @@ // except according to those terms. extern crate std; -//~^ ERROR an extern crate named `std` has already been imported +//~^ ERROR the name `std` is defined multiple times fn main(){} diff --git a/src/test/compile-fail/resolve-conflict-import-vs-extern-crate.rs b/src/test/compile-fail/resolve-conflict-import-vs-extern-crate.rs index 6cbc728c03..91cf1d3595 100644 --- a/src/test/compile-fail/resolve-conflict-import-vs-extern-crate.rs +++ b/src/test/compile-fail/resolve-conflict-import-vs-extern-crate.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::slice as std; //~ ERROR an extern crate named `std` has already been imported +use std::slice as std; //~ ERROR the name `std` is defined multiple times fn main() { } diff --git a/src/test/compile-fail/resolve-conflict-import-vs-import.rs b/src/test/compile-fail/resolve-conflict-import-vs-import.rs index 10afe82f2e..8db9023310 100644 --- a/src/test/compile-fail/resolve-conflict-import-vs-import.rs +++ b/src/test/compile-fail/resolve-conflict-import-vs-import.rs @@ -10,7 +10,7 @@ use std::mem::transmute; use std::mem::transmute; -//~^ ERROR a value named `transmute` has already been imported +//~^ ERROR the name `transmute` is defined multiple times fn main() { } diff --git a/src/test/compile-fail/resolve-conflict-item-vs-extern-crate.rs b/src/test/compile-fail/resolve-conflict-item-vs-extern-crate.rs index b0954ee157..b50a60d39c 100644 --- a/src/test/compile-fail/resolve-conflict-item-vs-extern-crate.rs +++ b/src/test/compile-fail/resolve-conflict-item-vs-extern-crate.rs @@ -9,7 +9,7 @@ // except according to those terms. fn std() {} -mod std {} //~ ERROR an extern crate named `std` has already been imported +mod std {} //~ ERROR the name `std` is defined multiple times fn main() { } diff --git a/src/test/compile-fail/resolve-conflict-item-vs-import.rs b/src/test/compile-fail/resolve-conflict-item-vs-import.rs index 2083d98e09..c91657bb46 100644 --- a/src/test/compile-fail/resolve-conflict-item-vs-import.rs +++ b/src/test/compile-fail/resolve-conflict-item-vs-import.rs @@ -9,10 +9,11 @@ // except according to those terms. use std::mem::transmute; -//~^ NOTE previous import of `transmute` here +//~^ NOTE previous import of the value `transmute` here fn transmute() {} -//~^ ERROR a value named `transmute` has already been imported in this module -//~| `transmute` already imported +//~^ ERROR the name `transmute` is defined multiple times +//~| `transmute` redefined here +//~| `transmute` must be defined only once in the value namespace of this module fn main() { } diff --git a/src/test/compile-fail/resolve-conflict-type-vs-import.rs b/src/test/compile-fail/resolve-conflict-type-vs-import.rs index aa7e47e223..bbb6ee622b 100644 --- a/src/test/compile-fail/resolve-conflict-type-vs-import.rs +++ b/src/test/compile-fail/resolve-conflict-type-vs-import.rs @@ -11,7 +11,7 @@ use std::slice::Iter; struct Iter; -//~^ ERROR a type named `Iter` has already been imported in this module +//~^ ERROR the name `Iter` is defined multiple times fn main() { } diff --git a/src/test/compile-fail/resolve_self_super_hint.rs b/src/test/compile-fail/resolve_self_super_hint.rs index 530dc873f7..d49f136f11 100644 --- a/src/test/compile-fail/resolve_self_super_hint.rs +++ b/src/test/compile-fail/resolve_self_super_hint.rs @@ -8,25 +8,25 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections)] +#![feature(alloc)] mod a { - extern crate collections; - use collections::HashMap; - //~^ ERROR unresolved import `collections::HashMap` [E0432] - //~| Did you mean `self::collections`? + extern crate alloc; + use alloc::HashMap; + //~^ ERROR unresolved import `alloc::HashMap` [E0432] + //~| Did you mean `self::alloc`? mod b { - use collections::HashMap; - //~^ ERROR unresolved import `collections::HashMap` [E0432] - //~| Did you mean `a::collections`? + use alloc::HashMap; + //~^ ERROR unresolved import `alloc::HashMap` [E0432] + //~| Did you mean `a::alloc`? mod c { - use collections::HashMap; - //~^ ERROR unresolved import `collections::HashMap` [E0432] - //~| Did you mean `a::collections`? + use alloc::HashMap; + //~^ ERROR unresolved import `alloc::HashMap` [E0432] + //~| Did you mean `a::alloc`? mod d { - use collections::HashMap; - //~^ ERROR unresolved import `collections::HashMap` [E0432] - //~| Did you mean `a::collections`? + use alloc::HashMap; + //~^ ERROR unresolved import `alloc::HashMap` [E0432] + //~| Did you mean `a::alloc`? } } } diff --git a/src/test/compile-fail/rust-unstable-column-gated.rs b/src/test/compile-fail/rust-unstable-column-gated.rs new file mode 100644 index 0000000000..abc92c86ee --- /dev/null +++ b/src/test/compile-fail/rust-unstable-column-gated.rs @@ -0,0 +1,14 @@ +// 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. + +fn main() { + println!("{}", __rust_unstable_column!()); + //~^ERROR the __rust_unstable_column macro is unstable +} diff --git a/src/test/compile-fail/safe-extern-statics-mut.rs b/src/test/compile-fail/safe-extern-statics-mut.rs index b5f3b4535d..ed8d590077 100644 --- a/src/test/compile-fail/safe-extern-statics-mut.rs +++ b/src/test/compile-fail/safe-extern-statics-mut.rs @@ -10,9 +10,6 @@ // aux-build:extern-statics.rs -#![allow(unused)] -#![deny(safe_extern_statics)] - extern crate extern_statics; use extern_statics::*; diff --git a/src/test/compile-fail/safe-extern-statics.rs b/src/test/compile-fail/safe-extern-statics.rs index 7e96897ee8..4d939f33c4 100644 --- a/src/test/compile-fail/safe-extern-statics.rs +++ b/src/test/compile-fail/safe-extern-statics.rs @@ -11,7 +11,6 @@ // aux-build:extern-statics.rs #![allow(unused)] -#![deny(safe_extern_statics)] extern crate extern_statics; use extern_statics::*; diff --git a/src/test/compile-fail/slice-2.rs b/src/test/compile-fail/slice-2.rs index 99dc3e68c8..44b9d94c56 100644 --- a/src/test/compile-fail/slice-2.rs +++ b/src/test/compile-fail/slice-2.rs @@ -14,8 +14,8 @@ struct Foo; fn main() { let x = Foo; - &x[..]; //~ ERROR cannot index a value of type `Foo` - &x[Foo..]; //~ ERROR cannot index a value of type `Foo` - &x[..Foo]; //~ ERROR cannot index a value of type `Foo` - &x[Foo..Foo]; //~ ERROR cannot index a value of type `Foo` + &x[..]; //~ ERROR cannot index into a value of type `Foo` + &x[Foo..]; //~ ERROR cannot index into a value of type `Foo` + &x[..Foo]; //~ ERROR cannot index into a value of type `Foo` + &x[Foo..Foo]; //~ ERROR cannot index into a value of type `Foo` } diff --git a/src/test/compile-fail/stmt_expr_attrs_no_feature.rs b/src/test/compile-fail/stmt_expr_attrs_no_feature.rs index 2fda2ee090..d8626dfd39 100644 --- a/src/test/compile-fail/stmt_expr_attrs_no_feature.rs +++ b/src/test/compile-fail/stmt_expr_attrs_no_feature.rs @@ -9,7 +9,6 @@ // except according to those terms. #![feature(custom_attribute)] -#![feature(associated_consts)] macro_rules! stmt_mac { () => { diff --git a/src/test/compile-fail/str-mut-idx.rs b/src/test/compile-fail/str-mut-idx.rs index 8851e5e079..219fcdfd70 100644 --- a/src/test/compile-fail/str-mut-idx.rs +++ b/src/test/compile-fail/str-mut-idx.rs @@ -15,8 +15,7 @@ fn mutate(s: &mut str) { //~^ ERROR `str: std::marker::Sized` is not satisfied //~| ERROR `str: std::marker::Sized` is not satisfied s[1usize] = bot(); - //~^ ERROR `str: std::ops::Index` is not satisfied - //~| ERROR `str: std::ops::IndexMut` is not satisfied + //~^ ERROR `str: std::ops::IndexMut` is not satisfied } pub fn main() {} diff --git a/src/test/compile-fail/struct-field-cfg.rs b/src/test/compile-fail/struct-field-cfg.rs index 9fb130f4d5..974d500d9c 100644 --- a/src/test/compile-fail/struct-field-cfg.rs +++ b/src/test/compile-fail/struct-field-cfg.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(struct_field_attributes)] - struct Foo { present: (), } diff --git a/src/test/compile-fail/struct-field-privacy.rs b/src/test/compile-fail/struct-field-privacy.rs index f487ef62aa..5b2e04e25a 100644 --- a/src/test/compile-fail/struct-field-privacy.rs +++ b/src/test/compile-fail/struct-field-privacy.rs @@ -42,7 +42,7 @@ fn test(a: A, b: inner::A, c: inner::B, d: xc::A, e: xc::B, z: inner::Z) { e.b; //~ ERROR: field `b` of struct `xc::B` is private z.0; - z.1; //~ ERROR: field `1` of struct `inner::Z` is private + z.1; //~ ERROR: field `1` of tuple-struct `inner::Z` is private } fn main() {} diff --git a/src/test/compile-fail/tag-variant-cast-non-nullary.rs b/src/test/compile-fail/tag-variant-cast-non-nullary.rs index b010632912..220537633e 100644 --- a/src/test/compile-fail/tag-variant-cast-non-nullary.rs +++ b/src/test/compile-fail/tag-variant-cast-non-nullary.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//error-pattern: non-scalar cast - enum non_nullary { nullary, other(isize), @@ -17,5 +15,5 @@ enum non_nullary { fn main() { let v = non_nullary::nullary; - let val = v as isize; + let val = v as isize; //~ ERROR non-primitive cast: `non_nullary` as `isize` [E0605] } diff --git a/src/test/compile-fail/trait-duplicate-methods.rs b/src/test/compile-fail/trait-duplicate-methods.rs index 7bcab1f6ac..b8e628dd47 100644 --- a/src/test/compile-fail/trait-duplicate-methods.rs +++ b/src/test/compile-fail/trait-duplicate-methods.rs @@ -9,9 +9,10 @@ // except according to those terms. trait Foo { - fn orange(&self); //~ NOTE previous definition of `orange` here - fn orange(&self); //~ ERROR a value named `orange` has already been defined in this trait - //~| NOTE already define + fn orange(&self); //~ NOTE previous definition of the value `orange` here + fn orange(&self); //~ ERROR the name `orange` is defined multiple times + //~| NOTE `orange` redefined here +//~| NOTE `orange` must be defined only once in the value namespace of this trait } fn main() {} diff --git a/src/test/compile-fail/trait-impl-can-not-have-untraitful-items.rs b/src/test/compile-fail/trait-impl-can-not-have-untraitful-items.rs index 0ed4e62778..cc143a6209 100644 --- a/src/test/compile-fail/trait-impl-can-not-have-untraitful-items.rs +++ b/src/test/compile-fail/trait-impl-can-not-have-untraitful-items.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] trait A { } diff --git a/src/test/compile-fail/trait-item-privacy.rs b/src/test/compile-fail/trait-item-privacy.rs index e915ca05f6..b8d83e5adf 100644 --- a/src/test/compile-fail/trait-item-privacy.rs +++ b/src/test/compile-fail/trait-item-privacy.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] #![feature(associated_type_defaults)] struct S; diff --git a/src/test/compile-fail/transmute-different-sizes.rs b/src/test/compile-fail/transmute-different-sizes.rs index 5fab271efc..113e2ed4c8 100644 --- a/src/test/compile-fail/transmute-different-sizes.rs +++ b/src/test/compile-fail/transmute-different-sizes.rs @@ -17,12 +17,12 @@ use std::mem::transmute; unsafe fn f() { let _: i8 = transmute(16i16); - //~^ ERROR transmute called with differently sized types + //~^ ERROR transmute called with types of different sizes } unsafe fn g(x: &T) { let _: i8 = transmute(x); - //~^ ERROR transmute called with differently sized types + //~^ ERROR transmute called with types of different sizes } trait Specializable { type Output; } @@ -33,7 +33,7 @@ impl Specializable for T { unsafe fn specializable(x: u16) -> ::Output { transmute(x) - //~^ ERROR transmute called with differently sized types + //~^ ERROR transmute called with types of different sizes } fn main() {} diff --git a/src/test/compile-fail/transmute-fat-pointers.rs b/src/test/compile-fail/transmute-fat-pointers.rs index f7324247f3..59027fc778 100644 --- a/src/test/compile-fail/transmute-fat-pointers.rs +++ b/src/test/compile-fail/transmute-fat-pointers.rs @@ -15,11 +15,11 @@ use std::mem::transmute; fn a(x: &[T]) -> &U { - unsafe { transmute(x) } //~ ERROR transmute called with differently sized types + unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes } fn b(x: &T) -> &U { - unsafe { transmute(x) } //~ ERROR transmute called with differently sized types + unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes } fn c(x: &T) -> &U { @@ -31,11 +31,11 @@ fn d(x: &[T]) -> &[U] { } fn e(x: &T) -> &U { - unsafe { transmute(x) } //~ ERROR transmute called with differently sized types + unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes } fn f(x: &T) -> &U { - unsafe { transmute(x) } //~ ERROR transmute called with differently sized types + unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes } fn main() { } diff --git a/src/test/compile-fail/transmute-impl.rs b/src/test/compile-fail/transmute-impl.rs index 55cebbd6cf..2f8f9e46e1 100644 --- a/src/test/compile-fail/transmute-impl.rs +++ b/src/test/compile-fail/transmute-impl.rs @@ -26,7 +26,7 @@ impl Foo { fn n(x: &T) -> &isize { // Not OK here, because T : Sized is not in scope. - unsafe { transmute(x) } //~ ERROR transmute called with differently sized types + unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes } } diff --git a/src/test/compile-fail/tuple-index-not-tuple.rs b/src/test/compile-fail/tuple-index-not-tuple.rs index bf2a63abbf..471104d687 100644 --- a/src/test/compile-fail/tuple-index-not-tuple.rs +++ b/src/test/compile-fail/tuple-index-not-tuple.rs @@ -14,7 +14,7 @@ struct Empty; fn main() { let origin = Point { x: 0, y: 0 }; origin.0; - //~^ ERROR attempted tuple index `0` on type `Point`, but the type was not + //~^ ERROR no field `0` on type `Point` Empty.0; - //~^ ERROR attempted tuple index `0` on type `Empty`, but the type was not + //~^ ERROR no field `0` on type `Empty` } diff --git a/src/test/compile-fail/two-allocators-3.rs b/src/test/compile-fail/two-allocators-3.rs deleted file mode 100644 index 965e4e0e2e..0000000000 --- a/src/test/compile-fail/two-allocators-3.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:allocator1.rs -// error-pattern: cannot link together two allocators -// ignore-musl no dylibs on musl yet -// ignore-emscripten - -// We're linking std dynamically (via -C prefer-dynamic for this test) which -// has an allocator and then we're also linking in a new allocator (allocator1) -// and this should be an error - -extern crate allocator1; - -fn main() { -} diff --git a/src/test/compile-fail/type-parameter-invalid-lint.rs b/src/test/compile-fail/type-parameter-invalid-lint.rs index c7a1197372..f424cbf0c3 100644 --- a/src/test/compile-fail/type-parameter-invalid-lint.rs +++ b/src/test/compile-fail/type-parameter-invalid-lint.rs @@ -10,7 +10,6 @@ // gate-test-default_type_parameter_fallback -#![deny(invalid_type_param_default)] #![allow(unused)] fn avg(_: T) {} diff --git a/src/test/compile-fail/type-params-in-different-spaces-2.rs b/src/test/compile-fail/type-params-in-different-spaces-2.rs index d07282763d..7de061eaf0 100644 --- a/src/test/compile-fail/type-params-in-different-spaces-2.rs +++ b/src/test/compile-fail/type-params-in-different-spaces-2.rs @@ -12,7 +12,7 @@ // type parameters on a trait correctly. trait Tr : Sized { - fn op(T) -> Self; + fn op(_: T) -> Self; } trait A: Tr { diff --git a/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs b/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs index 2b0a8baf4f..5ba93bf483 100644 --- a/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs +++ b/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs @@ -21,13 +21,11 @@ fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 - //~| ERROR E0277 } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 - //~| ERROR E0277 } fn c() { diff --git a/src/test/compile-fail/unboxed-closures-wrong-abi.rs b/src/test/compile-fail/unboxed-closures-wrong-abi.rs index f6ba25f436..ff06f7c559 100644 --- a/src/test/compile-fail/unboxed-closures-wrong-abi.rs +++ b/src/test/compile-fail/unboxed-closures-wrong-abi.rs @@ -21,13 +21,11 @@ fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 - //~| ERROR E0277 } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 - //~| ERROR E0277 } fn c() { diff --git a/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs b/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs index 9d907ffc17..d77750d2a0 100644 --- a/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs +++ b/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs @@ -22,13 +22,11 @@ fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 - //~| ERROR E0277 } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 - //~| ERROR E0277 } fn c() { diff --git a/src/test/compile-fail/uninhabited-enum-cast.rs b/src/test/compile-fail/uninhabited-enum-cast.rs index b4df5fb1e2..2a5d25e6b9 100644 --- a/src/test/compile-fail/uninhabited-enum-cast.rs +++ b/src/test/compile-fail/uninhabited-enum-cast.rs @@ -11,7 +11,7 @@ enum E {} fn f(e: E) { - println!("{}", (e as isize).to_string()); //~ ERROR non-scalar cast + println!("{}", (e as isize).to_string()); //~ ERROR non-primitive cast } fn main() {} diff --git a/src/test/compile-fail/unresolved-extern-mod-suggestion.rs b/src/test/compile-fail/unresolved-extern-mod-suggestion.rs index cc328d8c9e..714b73ec73 100644 --- a/src/test/compile-fail/unresolved-extern-mod-suggestion.rs +++ b/src/test/compile-fail/unresolved-extern-mod-suggestion.rs @@ -10,6 +10,6 @@ extern crate core; use core; -//~^ ERROR an extern crate named `core` has already been imported in this module +//~^ ERROR the name `core` is defined multiple times fn main() {} diff --git a/src/test/compile-fail/unsized3.rs b/src/test/compile-fail/unsized3.rs index 9b6ccf22c8..e96e0ea3ae 100644 --- a/src/test/compile-fail/unsized3.rs +++ b/src/test/compile-fail/unsized3.rs @@ -54,6 +54,7 @@ fn f9(x1: Box>) { fn f10(x1: Box>) { f5(&(32, *x1)); //~^ ERROR `X: std::marker::Sized` is not satisfied + //~| ERROR `X: std::marker::Sized` is not satisfied } pub fn main() { diff --git a/src/test/compile-fail/unsized6.rs b/src/test/compile-fail/unsized6.rs index 462d760a60..dec8699f46 100644 --- a/src/test/compile-fail/unsized6.rs +++ b/src/test/compile-fail/unsized6.rs @@ -12,15 +12,15 @@ trait T {} -fn f1(x: &X) { - let _: X; // <-- this is OK, no bindings created, no initializer. +fn f1(x: &X) { + let _: W; // <-- this is OK, no bindings created, no initializer. let _: (isize, (X, isize)); //~ERROR `X: std::marker::Sized` is not satisfie - let y: X; //~ERROR `X: std::marker::Sized` is not satisfied - let y: (isize, (X, usize)); + let y: Y; //~ERROR `Y: std::marker::Sized` is not satisfied + let y: (isize, (Z, usize)); //~ERROR `Z: std::marker::Sized` is not satisfied } -fn f2(x: &X) { +fn f2(x: &X) { let y: X; //~ERROR `X: std::marker::Sized` is not satisfied - let y: (isize, (X, isize)); //~ERROR `X: std::marker::Sized` is not satisfied + let y: (isize, (Y, isize)); //~ERROR `Y: std::marker::Sized` is not satisfied } fn f3(x1: Box, x2: Box, x3: Box) { diff --git a/src/test/compile-fail/unused-result.rs b/src/test/compile-fail/unused-result.rs index 6ed3b081c9..0c6c7fc5a0 100644 --- a/src/test/compile-fail/unused-result.rs +++ b/src/test/compile-fail/unused-result.rs @@ -26,8 +26,8 @@ fn qux() -> MustUseMsg { return foo::(); } #[allow(unused_results)] fn test() { foo::(); - foo::(); //~ ERROR: unused result which must be used - foo::(); //~ ERROR: unused result which must be used: some message + foo::(); //~ ERROR: unused `MustUse` which must be used + foo::(); //~ ERROR: unused `MustUseMsg` which must be used: some message } #[allow(unused_results, unused_must_use)] @@ -39,8 +39,8 @@ fn test2() { fn main() { foo::(); //~ ERROR: unused result - foo::(); //~ ERROR: unused result which must be used - foo::(); //~ ERROR: unused result which must be used: some message + foo::(); //~ ERROR: unused `MustUse` which must be used + foo::(); //~ ERROR: unused `MustUseMsg` which must be used: some message let _ = foo::(); let _ = foo::(); diff --git a/src/test/compile-fail/use-from-trait.rs b/src/test/compile-fail/use-from-trait.rs index 58e37bbfa3..33adc2b5bf 100644 --- a/src/test/compile-fail/use-from-trait.rs +++ b/src/test/compile-fail/use-from-trait.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] use Trait::foo; //~^ ERROR `foo` is not directly importable diff --git a/src/test/compile-fail/use-keyword.rs b/src/test/compile-fail/use-keyword.rs index 6df20d414a..aff54f18c1 100644 --- a/src/test/compile-fail/use-keyword.rs +++ b/src/test/compile-fail/use-keyword.rs @@ -13,9 +13,8 @@ mod a { mod b { - use self as A; //~ ERROR `self` imports are only allowed within a { } list - //~^ ERROR unresolved import `self` [E0432] - //~| no `self` in the root + use self as A; + //~^ ERROR `self` imports are only allowed within a { } list use super as B; //~^ ERROR unresolved import `super` [E0432] //~| no `super` in the root diff --git a/src/test/compile-fail/use-mod-4.rs b/src/test/compile-fail/use-mod-4.rs index 146d37f41d..f102a68c2c 100644 --- a/src/test/compile-fail/use-mod-4.rs +++ b/src/test/compile-fail/use-mod-4.rs @@ -11,4 +11,7 @@ use foo::self; //~ ERROR unresolved import `foo::self` //~^ ERROR `self` imports are only allowed within a { } list +use std::mem::self; +//~^ ERROR `self` imports are only allowed within a { } list + fn main() {} diff --git a/src/test/compile-fail/use-mod.rs b/src/test/compile-fail/use-mod.rs index 6be878dce1..485a75f0f9 100644 --- a/src/test/compile-fail/use-mod.rs +++ b/src/test/compile-fail/use-mod.rs @@ -11,12 +11,13 @@ use foo::bar::{ self, //~^ ERROR `self` import can only appear once in the list -//~^^ NOTE previous import of `bar` here +//~^^ NOTE previous import of the module `bar` here Bar, self //~^ NOTE another `self` import appears here -//~| ERROR a module named `bar` has already been imported in this module -//~| NOTE already imported +//~| ERROR the name `bar` is defined multiple times +//~| NOTE `bar` reimported here +//~| NOTE `bar` must be defined only once in the type namespace of this module }; use {self}; diff --git a/src/test/compile-fail/use-paths-as-items.rs b/src/test/compile-fail/use-paths-as-items.rs index 8a10eef60e..db69bb33ae 100644 --- a/src/test/compile-fail/use-paths-as-items.rs +++ b/src/test/compile-fail/use-paths-as-items.rs @@ -14,6 +14,6 @@ // Related issue: #25763 use std::{mem, ptr}; -use std::mem; //~ ERROR has already been imported +use std::mem; //~ ERROR the name `mem` is defined multiple times fn main() {} diff --git a/src/test/compile-fail/use-self-type.rs b/src/test/compile-fail/use-self-type.rs new file mode 100644 index 0000000000..6b5286bf0a --- /dev/null +++ b/src/test/compile-fail/use-self-type.rs @@ -0,0 +1,21 @@ +// 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. + +struct S; + +impl S { + fn f() {} + fn g() { + use Self::f; //~ ERROR unresolved import + pub(in Self::f) struct Z; //~ ERROR Use of undeclared type or module `Self` + } +} + +fn main() {} diff --git a/src/test/compile-fail/variadic-ffi-3.rs b/src/test/compile-fail/variadic-ffi-3.rs index 565d8549b3..fb10202718 100644 --- a/src/test/compile-fail/variadic-ffi-3.rs +++ b/src/test/compile-fail/variadic-ffi-3.rs @@ -35,11 +35,11 @@ fn main() { //~| found type `extern "C" fn(isize, u8) {bar}` //~| NOTE: expected variadic fn, found non-variadic function - foo(1, 2, 3f32); //~ ERROR: can't pass an `f32` to variadic function, cast to `c_double` - foo(1, 2, true); //~ ERROR: can't pass `bool` to variadic function, cast to `c_int` - foo(1, 2, 1i8); //~ ERROR: can't pass `i8` to variadic function, cast to `c_int` - foo(1, 2, 1u8); //~ ERROR: can't pass `u8` to variadic function, cast to `c_uint` - foo(1, 2, 1i16); //~ ERROR: can't pass `i16` to variadic function, cast to `c_int` - foo(1, 2, 1u16); //~ ERROR: can't pass `u16` to variadic function, cast to `c_uint` + foo(1, 2, 3f32); //~ ERROR can't pass `f32` to variadic function, cast to `c_double` + foo(1, 2, true); //~ ERROR can't pass `bool` to variadic function, cast to `c_int` + foo(1, 2, 1i8); //~ ERROR can't pass `i8` to variadic function, cast to `c_int` + foo(1, 2, 1u8); //~ ERROR can't pass `u8` to variadic function, cast to `c_uint` + foo(1, 2, 1i16); //~ ERROR can't pass `i16` to variadic function, cast to `c_int` + foo(1, 2, 1u16); //~ ERROR can't pass `u16` to variadic function, cast to `c_uint` } } diff --git a/src/test/compile-fail/variadic-ffi.rs b/src/test/compile-fail/variadic-ffi.rs index 125177efc5..f245306f4d 100644 --- a/src/test/compile-fail/variadic-ffi.rs +++ b/src/test/compile-fail/variadic-ffi.rs @@ -9,6 +9,7 @@ // except according to those terms. // ignore-arm stdcall isn't suppported +// ignore-aarch64 stdcall isn't suppported extern "stdcall" { fn printf(_: *const u8, ...); //~ ERROR: variadic function must have C or cdecl calling diff --git a/src/test/compile-fail/variance-trait-bounds.rs b/src/test/compile-fail/variance-trait-bounds.rs index 58fb785c48..ff446f175b 100644 --- a/src/test/compile-fail/variance-trait-bounds.rs +++ b/src/test/compile-fail/variance-trait-bounds.rs @@ -14,14 +14,12 @@ // Check that bounds on type parameters (other than `Self`) do not // influence variance. -#[rustc_variance] -trait Getter { //~ ERROR [o, o] +trait Getter { fn get(&self) -> T; } -#[rustc_variance] -trait Setter { //~ ERROR [o, o] - fn get(&self, T); +trait Setter { + fn get(&self, _: T); } #[rustc_variance] @@ -34,20 +32,6 @@ enum TestEnum> { //~ ERROR [*, +] Foo(T) } -#[rustc_variance] -trait TestTrait> { //~ ERROR [o, o, o] - fn getter(&self, u: U) -> T; -} - -#[rustc_variance] -trait TestTrait2 : Getter { //~ ERROR [o, o] -} - -#[rustc_variance] -trait TestTrait3 { //~ ERROR [o, o] - fn getter>(&self); -} - #[rustc_variance] struct TestContraStruct> { //~ ERROR [*, +] t: T diff --git a/src/test/compile-fail/variance-types-bounds.rs b/src/test/compile-fail/variance-types-bounds.rs index 2df94cc907..5075dd2cee 100644 --- a/src/test/compile-fail/variance-types-bounds.rs +++ b/src/test/compile-fail/variance-types-bounds.rs @@ -36,37 +36,14 @@ struct TestIndirect2 { //~ ERROR [o, o] m: TestMut } -#[rustc_variance] -trait Getter { //~ ERROR [o, o] +trait Getter { fn get(&self) -> A; } -#[rustc_variance] -trait Setter { //~ ERROR [o, o] - fn set(&mut self, a: A); -} - -#[rustc_variance] -trait GetterSetter { //~ ERROR [o, o] - fn get(&self) -> A; +trait Setter { fn set(&mut self, a: A); } -#[rustc_variance] -trait GetterInTypeBound { //~ ERROR [o, o] - // Here, the use of `A` in the method bound *does* affect - // variance. Think of it as if the method requested a dictionary - // for `T:Getter`. Since this dictionary is an input, it is - // contravariant, and the Getter is covariant w/r/t A, yielding an - // overall contravariant result. - fn do_it>(&self); -} - -#[rustc_variance] -trait SetterInTypeBound { //~ ERROR [o, o] - fn do_it>(&self); -} - #[rustc_variance] struct TestObject { //~ ERROR [o, o] n: Box+Send>, diff --git a/src/test/compile-fail/variant-namespacing.rs b/src/test/compile-fail/variant-namespacing.rs index 44e9260770..58bfd91550 100644 --- a/src/test/compile-fail/variant-namespacing.rs +++ b/src/test/compile-fail/variant-namespacing.rs @@ -32,12 +32,12 @@ const XUnit: u8 = 0; extern crate variant_namespacing; pub use variant_namespacing::XE::{XStruct, XTuple, XUnit}; -//~^ ERROR `XStruct` has already been defined -//~| ERROR `XTuple` has already been defined -//~| ERROR `XUnit` has already been defined +//~^ ERROR the name `XStruct` is defined multiple times +//~| ERROR the name `XTuple` is defined multiple times +//~| ERROR the name `XUnit` is defined multiple times pub use E::{Struct, Tuple, Unit}; -//~^ ERROR `Struct` has already been defined -//~| ERROR `Tuple` has already been defined -//~| ERROR `Unit` has already been defined +//~^ ERROR the name `Struct` is defined multiple times +//~| ERROR the name `Tuple` is defined multiple times +//~| ERROR the name `Unit` is defined multiple times fn main() {} diff --git a/src/test/compile-fail/vec-macro-with-comma-only.rs b/src/test/compile-fail/vec-macro-with-comma-only.rs index 96f58666fd..c79e67a376 100644 --- a/src/test/compile-fail/vec-macro-with-comma-only.rs +++ b/src/test/compile-fail/vec-macro-with-comma-only.rs @@ -9,5 +9,5 @@ // except according to those terms. pub fn main() { - vec![,]; //~ ERROR expected expression, found `,` + vec![,]; //~ ERROR no rules expected the token `,` } diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs index 153f0c8271..9596f0287b 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -38,6 +38,12 @@ // gdbg-check:$6 = None // gdbr-check:$6 = core::option::Option::None +// gdb-command: print os_string +// gdb-check:$7 = "IAMA OS string 😃" + +// gdb-command: print some_string +// gdb-check:$8 = Some = {"IAMA optional string!"} + // === LLDB TESTS ================================================================================== @@ -63,6 +69,8 @@ #![allow(unused_variables)] +use std::ffi::OsString; + fn main() { @@ -78,10 +86,15 @@ fn main() { // String let string = "IAMA string!".to_string(); + // OsString + let os_string = OsString::from("IAMA OS string \u{1F603}"); + // Option let some = Some(8i16); let none: Option = None; + let some_string = Some("IAMA optional string!".to_owned()); + zzz(); // #break } diff --git a/src/test/incremental/dirty_clean.rs b/src/test/incremental/dirty_clean.rs index 9f20128de4..b828cc9c70 100644 --- a/src/test/incremental/dirty_clean.rs +++ b/src/test/incremental/dirty_clean.rs @@ -36,19 +36,15 @@ mod y { use x; #[rustc_clean(label="TypeckTables", cfg="cfail2")] - #[rustc_clean(label="TransCrateItem", cfg="cfail2")] pub fn y() { - //[cfail2]~^ ERROR `TypeckTables("y::y")` not found in dep graph, but should be clean - //[cfail2]~| ERROR `TransCrateItem("y::y")` not found in dep graph, but should be clean + //[cfail2]~^ ERROR `TypeckTables(y::y)` not found in dep graph, but should be clean x::x(); } } mod z { #[rustc_dirty(label="TypeckTables", cfg="cfail2")] - #[rustc_dirty(label="TransCrateItem", cfg="cfail2")] pub fn z() { - //[cfail2]~^ ERROR `TypeckTables("z::z")` found in dep graph, but should be dirty - //[cfail2]~| ERROR `TransCrateItem("z::z")` found in dep graph, but should be dirty + //[cfail2]~^ ERROR `TypeckTables(z::z)` found in dep graph, but should be dirty } } diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs index 61a2be054a..e47556a790 100644 --- a/src/test/incremental/hashes/trait_defs.rs +++ b/src/test/incremental/hashes/trait_defs.rs @@ -30,7 +30,6 @@ #![crate_type="rlib"] #![feature(associated_type_defaults)] #![feature(intrinsics)] -#![feature(associated_consts)] // Change trait visibility -------------------------------------------------------- diff --git a/src/test/incremental/issue-42602.rs b/src/test/incremental/issue-42602.rs new file mode 100644 index 0000000000..cb2236d375 --- /dev/null +++ b/src/test/incremental/issue-42602.rs @@ -0,0 +1,45 @@ +// 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. + +// Regression test for #42602. It used to be that we had +// a dep-graph like +// +// typeck(foo) -> FnOnce -> typeck(bar) +// +// This was fixed by improving the resolution of the `FnOnce` trait +// selection node. + +// revisions:cfail1 +// compile-flags:-Zquery-dep-graph + +#![feature(rustc_attrs)] + +fn main() { + a::foo(); + b::bar(); +} + +mod a { + #[rustc_if_this_changed(HirBody)] + pub fn foo() { + let x = vec![1, 2, 3]; + let v = || ::std::mem::drop(x); + v(); + } +} + +mod b { + #[rustc_then_this_would_need(TypeckTables)] //[cfail1]~ ERROR no path + pub fn bar() { + let x = vec![1, 2, 3]; + let v = || ::std::mem::drop(x); + v(); + } +} diff --git a/src/test/incremental/krate-inlined.rs b/src/test/incremental/krate-inlined.rs index ba32b41983..043cb761da 100644 --- a/src/test/incremental/krate-inlined.rs +++ b/src/test/incremental/krate-inlined.rs @@ -9,20 +9,22 @@ // except according to those terms. // Regr. test that using HIR inlined from another krate does *not* add -// a dependency from the local Krate node. +// a dependency from the local Krate node. We can't easily test that +// directly anymore, so now we test that we get reuse. -// revisions: cfail1 +// revisions: rpass1 rpass2 // compile-flags: -Z query-dep-graph #![allow(warnings)] #![feature(rustc_attrs)] +#![rustc_partition_reused(module="krate_inlined-x", cfg="rpass2")] -#![rustc_if_this_changed(Krate)] - -fn main() { } +fn main() { + #[cfg(rpass2)] + () +} mod x { - #[rustc_then_this_would_need(TransCrateItem)] //[cfail1]~ ERROR no path fn method() { // use some methods that require inlining HIR from another crate: let mut v = vec![]; diff --git a/src/test/incremental/remapped_paths_cc/main.rs b/src/test/incremental/remapped_paths_cc/main.rs index be4764c7d9..701c5fec49 100644 --- a/src/test/incremental/remapped_paths_cc/main.rs +++ b/src/test/incremental/remapped_paths_cc/main.rs @@ -25,8 +25,6 @@ extern crate extern_crate; -#[rustc_clean(label="TransCrateItem", cfg="rpass2")] -#[rustc_clean(label="TransCrateItem", cfg="rpass3")] fn main() { some_mod::some_fn(); } @@ -34,8 +32,6 @@ fn main() { mod some_mod { use extern_crate; - #[rustc_clean(label="TransCrateItem", cfg="rpass2")] - #[rustc_dirty(label="TransCrateItem", cfg="rpass3")] pub fn some_fn() { extern_crate::inline_fn(); } diff --git a/src/test/incremental/spans_in_type_debuginfo.rs b/src/test/incremental/spans_in_type_debuginfo.rs new file mode 100644 index 0000000000..7d8e6c9d9d --- /dev/null +++ b/src/test/incremental/spans_in_type_debuginfo.rs @@ -0,0 +1,63 @@ +// 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. + +// Test that moving a type definition within a source file does not affect +// re-compilation. + +// revisions:rpass1 rpass2 +// compile-flags: -Z query-dep-graph -g + +#![rustc_partition_reused(module="spans_in_type_debuginfo", cfg="rpass2")] +#![rustc_partition_reused(module="spans_in_type_debuginfo-structs", cfg="rpass2")] +#![rustc_partition_reused(module="spans_in_type_debuginfo-enums", cfg="rpass2")] + +#![feature(rustc_attrs)] + +mod structs { + #[cfg(rpass1)] + pub struct X { + pub x: u32, + } + + #[cfg(rpass2)] + pub struct X { + pub x: u32, + } + + pub fn foo(x: X) -> u32 { + x.x + } +} + +mod enums { + #[cfg(rpass1)] + pub enum X { + A { x: u32 }, + B(u32), + } + + #[cfg(rpass2)] + pub enum X { + A { x: u32 }, + B(u32), + } + + pub fn foo(x: X) -> u32 { + match x { + X::A { x } => x, + X::B(x) => x, + } + } +} + +pub fn main() { + let _ = structs::foo(structs::X { x: 1 }); + let _ = enums::foo(enums::X::A { x: 2 }); +} diff --git a/src/test/incremental/string_constant.rs b/src/test/incremental/string_constant.rs index 669d001cc6..36a26cf175 100644 --- a/src/test/incremental/string_constant.rs +++ b/src/test/incremental/string_constant.rs @@ -28,7 +28,6 @@ mod x { #[cfg(rpass2)] #[rustc_dirty(label="TypeckTables", cfg="rpass2")] - #[rustc_dirty(label="TransCrateItem", cfg="rpass2")] pub fn x() { println!("{}", "2"); } @@ -38,7 +37,6 @@ mod y { use x; #[rustc_clean(label="TypeckTables", cfg="rpass2")] - #[rustc_clean(label="TransCrateItem", cfg="rpass2")] pub fn y() { x::x(); } @@ -48,7 +46,6 @@ mod z { use y; #[rustc_clean(label="TypeckTables", cfg="rpass2")] - #[rustc_clean(label="TransCrateItem", cfg="rpass2")] pub fn z() { y::y(); } diff --git a/src/test/mir-opt/README.md b/src/test/mir-opt/README.md index 9144e9757f..28a124e3c6 100644 --- a/src/test/mir-opt/README.md +++ b/src/test/mir-opt/README.md @@ -22,7 +22,32 @@ All the test information is in comments so the test is runnable. For each $file_name, compiletest expects [$expected_line_0, ..., $expected_line_N] to appear in the dumped MIR in order. Currently it allows -other non-matched lines before, after and in-between. +other non-matched lines before, after and in-between. Note that this includes +lines that end basic blocks or begin new ones; it is good practice +in your tests to include the terminator for each of your basic blocks as an +internal sanity check guarding against a test like: + +``` +bb0: { + StorageLive(_1); + _1 = const true; + StorageDead(_1); +} +``` + +that will inadvertantly pattern-matching against: + +``` +bb0: { + StorageLive(_1); + _1 = const true; + goto -> bb1 +} +bb1: { + StorageDead(_1); + return; +} +``` Lines match ignoring whitespace, and the prefix "//" is removed. diff --git a/src/test/mir-opt/basic_assignment.rs b/src/test/mir-opt/basic_assignment.rs index e4eb1aeaf9..ef5158a403 100644 --- a/src/test/mir-opt/basic_assignment.rs +++ b/src/test/mir-opt/basic_assignment.rs @@ -50,7 +50,7 @@ fn main() { // StorageLive(_6); // StorageLive(_7); // _7 = _4; -// replace(_6 <- _7) -> [return: bb5, unwind: bb4]; +// replace(_6 <- _7) -> [return: bb6, unwind: bb7]; // } // bb1: { // resume; @@ -59,24 +59,30 @@ fn main() { // drop(_4) -> bb1; // } // bb3: { -// drop(_6) -> bb2; +// goto -> bb2; // } // bb4: { -// drop(_7) -> bb3; +// drop(_6) -> bb3; // } // bb5: { -// drop(_7) -> [return: bb6, unwind: bb3]; +// goto -> bb4; // } // bb6: { +// drop(_7) -> [return: bb8, unwind: bb4]; +// } +// bb7: { +// drop(_7) -> bb5; +// } +// bb8: { // StorageDead(_7); // _0 = (); -// drop(_6) -> [return: bb7, unwind: bb2]; +// drop(_6) -> [return: bb9, unwind: bb2]; // } -// bb7: { +// bb9: { // StorageDead(_6); -// drop(_4) -> bb8; +// drop(_4) -> bb10; // } -// bb8: { +// bb10: { // StorageDead(_4); // StorageDead(_2); // StorageDead(_1); diff --git a/src/test/mir-opt/end_region_1.rs b/src/test/mir-opt/end_region_1.rs new file mode 100644 index 0000000000..55dac44402 --- /dev/null +++ b/src/test/mir-opt/end_region_1.rs @@ -0,0 +1,38 @@ +// 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. + +// compile-flags: -Z identify_regions +// ignore-tidy-linelength + +// This is just about the simplest program that exhibits an EndRegion. + +fn main() { + let a = 3; + let b = &a; +} + +// END RUST SOURCE +// START rustc.node4.SimplifyCfg-qualify-consts.after.mir +// let mut _0: (); +// let _1: i32; +// let _2: &'6_1rce i32; +// +// bb0: { +// StorageLive(_1); +// _1 = const 3i32; +// StorageLive(_2); +// _2 = &'6_1rce _1; +// _0 = (); +// StorageDead(_2); +// EndRegion('6_1rce); +// StorageDead(_1); +// return; +// } +// END rustc.node4.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_2.rs b/src/test/mir-opt/end_region_2.rs new file mode 100644 index 0000000000..a1386ec47a --- /dev/null +++ b/src/test/mir-opt/end_region_2.rs @@ -0,0 +1,66 @@ +// 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. + +// compile-flags: -Z identify_regions +// ignore-tidy-linelength + +// We will EndRegion for borrows in a loop that occur before break but +// not those after break. + +fn main() { + loop { + let a = true; + let b = &a; + if a { break; } + let c = &a; + } +} + +// END RUST SOURCE +// START rustc.node4.SimplifyCfg-qualify-consts.after.mir +// let mut _0: (); +// let _2: bool; +// let _3: &'7_1rce bool; +// let _7: &'7_3rce bool; +// let mut _4: (); +// let mut _5: bool; +// bb0: { +// goto -> bb1; +// } +// bb1: { +// StorageLive(_2); +// _2 = const true; +// StorageLive(_3); +// _3 = &'7_1rce _2; +// StorageLive(_5); +// _5 = _2; +// switchInt(_5) -> [0u8: bb3, otherwise: bb2]; +// } +// bb2: { +// _0 = (); +// StorageDead(_5); +// StorageDead(_3); +// EndRegion('7_1rce); +// StorageDead(_2); +// return; +// } +// bb3: { +// StorageDead(_5); +// StorageLive(_7); +// _7 = &'7_3rce _2; +// _1 = (); +// StorageDead(_7); +// EndRegion('7_3rce); +// StorageDead(_3); +// EndRegion('7_1rce); +// StorageDead(_2); +// goto -> bb1; +// } +// END rustc.node4.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_3.rs b/src/test/mir-opt/end_region_3.rs new file mode 100644 index 0000000000..b3d2809e76 --- /dev/null +++ b/src/test/mir-opt/end_region_3.rs @@ -0,0 +1,69 @@ +// 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. + +// compile-flags: -Z identify_regions +// ignore-tidy-linelength + +// Binding the borrow's subject outside the loop does not increase the +// scope of the borrow. + +fn main() { + let mut a; + loop { + a = true; + let b = &a; + if a { break; } + let c = &a; + } +} + +// END RUST SOURCE +// START rustc.node4.SimplifyCfg-qualify-consts.after.mir +// let mut _0: (); +// let mut _1: bool; +// let _3: &'9_1rce bool; +// let _7: &'9_3rce bool; +// let mut _2: (); +// let mut _4: (); +// let mut _5: bool; +// +// bb0: { +// StorageLive(_1); +// goto -> bb1; +// } +// bb1: { +// _1 = const true; +// StorageLive(_3); +// _3 = &'9_1rce _1; +// StorageLive(_5); +// _5 = _1; +// switchInt(_5) -> [0u8: bb3, otherwise: bb2]; +// } +// bb2: { +// _0 = (); +// StorageDead(_5); +// StorageDead(_3); +// EndRegion('9_1rce); +// StorageDead(_1); +// return; +// } +// bb3: { +// _4 = (); +// StorageDead(_5); +// StorageLive(_7); +// _7 = &'9_3rce _1; +// _2 = (); +// StorageDead(_7); +// EndRegion('9_3rce); +// StorageDead(_3); +// EndRegion('9_1rce); +// goto -> bb1; +// } +// END rustc.node4.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_4.rs b/src/test/mir-opt/end_region_4.rs new file mode 100644 index 0000000000..16ade9f96f --- /dev/null +++ b/src/test/mir-opt/end_region_4.rs @@ -0,0 +1,75 @@ +// 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. + +// compile-flags: -Z identify_regions +// ignore-tidy-linelength + +// Unwinding should EndRegion for in-scope borrows: Direct borrows. + +fn main() { + let d = D(0); + let a = 0; + let b = &a; + foo(*b); + let c = &a; +} + +struct D(i32); +impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } } + +fn foo(i: i32) { + if i > 0 { panic!("im positive"); } +} + +// END RUST SOURCE +// START rustc.node4.SimplifyCfg-qualify-consts.after.mir +// let mut _0: (); +// let _1: D; +// let _3: i32; +// let _4: &'6_2rce i32; +// let _7: &'6_4rce i32; +// let mut _5: (); +// let mut _6: i32; +// +// bb0: { +// StorageLive(_1); +// _1 = D::{{constructor}}(const 0i32,); +// StorageLive(_3); +// _3 = const 0i32; +// StorageLive(_4); +// _4 = &'6_2rce _3; +// StorageLive(_6); +// _6 = (*_4); +// _5 = const foo(_6) -> [return: bb2, unwind: bb3]; +// } +// bb1: { +// resume; +// } +// bb2: { +// StorageDead(_6); +// StorageLive(_7); +// _7 = &'6_4rce _3; +// _0 = (); +// StorageDead(_7); +// EndRegion('6_4rce); +// StorageDead(_4); +// EndRegion('6_2rce); +// StorageDead(_3); +// drop(_1) -> bb4; +// } +// bb3: { +// EndRegion('6_2rce); +// drop(_1) -> bb1; +// } +// bb4: { +// StorageDead(_1); +// return; +// } +// END rustc.node4.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_5.rs b/src/test/mir-opt/end_region_5.rs new file mode 100644 index 0000000000..513632a4cd --- /dev/null +++ b/src/test/mir-opt/end_region_5.rs @@ -0,0 +1,80 @@ +// 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. + +// compile-flags: -Z identify_regions -Z span_free_formats +// ignore-tidy-linelength + +// Unwinding should EndRegion for in-scope borrows: Borrowing via by-ref closure. + +fn main() { + let d = D(0); + foo(|| -> i32 { d.0 }); +} + +struct D(i32); +impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } } + +fn foo(f: F) where F: FnOnce() -> i32 { + if f() > 0 { panic!("im positive"); } +} + +// END RUST SOURCE +// START rustc.node4.SimplifyCfg-qualify-consts.after.mir +// fn main() -> () { +// let mut _0: (); +// let _1: D; +// let mut _2: (); +// let mut _3: (); +// let mut _4: [closure@NodeId(18) d: &'19mce D]; +// let mut _5: &'19mce D; +// +// bb0: { +// StorageLive(_1); +// _1 = D::{{constructor}}(const 0i32,); +// StorageLive(_4); +// StorageLive(_5); +// _5 = &'19mce _1; +// _4 = [closure@NodeId(18)] { d: _5 }; +// StorageDead(_5); +// _3 = const foo(_4) -> [return: bb2, unwind: bb3]; +// } +// bb1: { +// resume; +// } +// bb2: { +// StorageDead(_4); +// EndRegion('19mce); +// _0 = (); +// drop(_1) -> bb4; +// } +// bb3: { +// EndRegion('19mce); +// drop(_1) -> bb1; +// } +// bb4: { +// StorageDead(_1); +// return; +// } +// } +// END rustc.node4.SimplifyCfg-qualify-consts.after.mir + +// START rustc.node18.SimplifyCfg-qualify-consts.after.mir +// fn main::{{closure}}(_1: [closure@NodeId(18) d:&'19mce D]) -> i32 { +// let mut _0: i32; +// let mut _2: i32; +// +// bb0: { +// StorageLive(_2); +// _2 = ((*(_1.0: &'19mce D)).0: i32); +// _0 = _2; +// StorageDead(_2); +// return; +// } +// END rustc.node18.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_6.rs b/src/test/mir-opt/end_region_6.rs new file mode 100644 index 0000000000..e82556f3ce --- /dev/null +++ b/src/test/mir-opt/end_region_6.rs @@ -0,0 +1,83 @@ +// 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. + +// compile-flags: -Z identify_regions -Z span_free_formats +// ignore-tidy-linelength + +// Unwinding should EndRegion for in-scope borrows: 2nd borrow within by-ref closure. + +fn main() { + let d = D(0); + foo(|| -> i32 { let r = &d; r.0 }); +} + +struct D(i32); +impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } } + +fn foo(f: F) where F: FnOnce() -> i32 { + if f() > 0 { panic!("im positive"); } +} + +// END RUST SOURCE +// START rustc.node4.SimplifyCfg-qualify-consts.after.mir +// let mut _0: (); +// let _1: D; +// let mut _2: (); +// let mut _3: (); +// let mut _4: [closure@NodeId(22) d:&'23mce D]; +// let mut _5: &'23mce D; +// +// bb0: { +// StorageLive(_1); +// _1 = D::{{constructor}}(const 0i32,); +// StorageLive(_4); +// StorageLive(_5); +// _5 = &'23mce _1; +// _4 = [closure@NodeId(22)] { d: _5 }; +// StorageDead(_5); +// _3 = const foo(_4) -> [return: bb2, unwind: bb3]; +// } +// bb1: { +// resume; +// } +// bb2: { +// StorageDead(_4); +// EndRegion('23mce); +// _0 = (); +// drop(_1) -> bb4; +// } +// bb3: { +// EndRegion('23mce); +// drop(_1) -> bb1; +// } +// bb4: { +// StorageDead(_1); +// return; +// } +// END rustc.node4.SimplifyCfg-qualify-consts.after.mir + +// START rustc.node22.SimplifyCfg-qualify-consts.after.mir +// fn main::{{closure}}(_1: [closure@NodeId(22) d:&'23mce D]) -> i32 { +// let mut _0: i32; +// let _2: &'14_0rce D; +// let mut _3: i32; +// +// bb0: { +// StorageLive(_2); +// _2 = &'14_0rce (*(_1.0: &'23mce D)); +// StorageLive(_3); +// _3 = ((*_2).0: i32); +// _0 = _3; +// StorageDead(_3); +// StorageDead(_2); +// EndRegion('14_0rce); +// return; +// } +// END rustc.node22.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_7.rs b/src/test/mir-opt/end_region_7.rs new file mode 100644 index 0000000000..3fbd3f3686 --- /dev/null +++ b/src/test/mir-opt/end_region_7.rs @@ -0,0 +1,97 @@ +// 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. + +// compile-flags: -Z identify_regions -Z span_free_formats +// ignore-tidy-linelength + +// Unwinding should EndRegion for in-scope borrows: Borrow of moved data. + +fn main() { + let d = D(0); + foo(move || -> i32 { let r = &d; r.0 }); +} + +struct D(i32); +impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } } + +fn foo(f: F) where F: FnOnce() -> i32 { + if f() > 0 { panic!("im positive"); } +} + +// END RUST SOURCE +// START rustc.node4.SimplifyCfg-qualify-consts.after.mir +// fn main() -> () { +// let mut _0: (); +// let _1: D; +// let mut _2: (); +// let mut _3: (); +// let mut _4: [closure@NodeId(22) d:D]; +// let mut _5: D; +// +// bb0: { +// StorageLive(_1); +// _1 = D::{{constructor}}(const 0i32,); +// StorageLive(_4); +// StorageLive(_5); +// _5 = _1; +// _4 = [closure@NodeId(22)] { d: _5 }; +// drop(_5) -> [return: bb4, unwind: bb3]; +// } +// bb1: { +// resume; +// } +// bb2: { +// drop(_1) -> bb1; +// } +// bb3: { +// drop(_4) -> bb2; +// } +// bb4: { +// StorageDead(_5); +// _3 = const foo(_4) -> [return: bb5, unwind: bb3]; +// } +// bb5: { +// drop(_4) -> [return: bb6, unwind: bb2]; +// } +// bb6: { +// StorageDead(_4); +// _0 = (); +// drop(_1) -> bb7; +// } +// bb7: { +// StorageDead(_1); +// return; +// } +// } +// END rustc.node4.SimplifyCfg-qualify-consts.after.mir + +// START rustc.node22.SimplifyCfg-qualify-consts.after.mir +// fn main::{{closure}}(_1: [closure@NodeId(22) d:D]) -> i32 { +// let mut _0: i32; +// let _2: &'14_0rce D; +// let mut _3: (); +// let mut _4: i32; +// +// bb0: { +// StorageLive(_2); +// _2 = &'14_0rce (_1.0: D); +// StorageLive(_4); +// _4 = ((*_2).0: i32); +// _0 = _4; +// StorageDead(_4); +// StorageDead(_2); +// EndRegion('14_0rce); +// drop(_1) -> bb1; +// } +// bb1: { +// return; +// } +// } +// END rustc.node22.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_8.rs b/src/test/mir-opt/end_region_8.rs new file mode 100644 index 0000000000..7fb3f0b911 --- /dev/null +++ b/src/test/mir-opt/end_region_8.rs @@ -0,0 +1,86 @@ +// 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. + +// compile-flags: -Z identify_regions -Z span_free_formats +// ignore-tidy-linelength + +// Unwinding should EndRegion for in-scope borrows: Move of borrow into closure. + +fn main() { + let d = D(0); + let r = &d; + foo(move || -> i32 { r.0 }); +} + +struct D(i32); +impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } } + +fn foo(f: F) where F: FnOnce() -> i32 { + if f() > 0 { panic!("im positive"); } +} + +// END RUST SOURCE +// START rustc.node4.SimplifyCfg-qualify-consts.after.mir +// fn main() -> () { +// let mut _0: (); +// let _1: D; +// let _3: &'6_1rce D; +// let mut _2: (); +// let mut _4: (); +// let mut _5: [closure@NodeId(22) r:&'6_1rce D]; +// let mut _6: &'6_1rce D; +// +// bb0: { +// StorageLive(_1); +// _1 = D::{{constructor}}(const 0i32,); +// StorageLive(_3); +// _3 = &'6_1rce _1; +// StorageLive(_5); +// StorageLive(_6); +// _6 = _3; +// _5 = [closure@NodeId(22)] { r: _6 }; +// StorageDead(_6); +// _4 = const foo(_5) -> [return: bb2, unwind: bb3]; +// } +// bb1: { +// resume; +// } +// bb2: { +// StorageDead(_5); +// _0 = (); +// StorageDead(_3); +// EndRegion('6_1rce); +// drop(_1) -> bb4; +// } +// bb3: { +// EndRegion('6_1rce); +// drop(_1) -> bb1; +// } +// bb4: { +// StorageDead(_1); +// return; +// } +// } +// END rustc.node4.SimplifyCfg-qualify-consts.after.mir + +// START rustc.node22.SimplifyCfg-qualify-consts.after.mir +// fn main::{{closure}}(_1: [closure@NodeId(22) r:&'6_1rce D]) -> i32 { +// let mut _0: i32; +// let mut _2: i32; +// +// bb0: { +// StorageLive(_2); +// _2 = ((*(_1.0: &'6_1rce D)).0: i32); +// _0 = _2; +// StorageDead(_2); +// return; +// } +// } +// END rustc.node22.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_9.rs b/src/test/mir-opt/end_region_9.rs new file mode 100644 index 0000000000..deff984e4d --- /dev/null +++ b/src/test/mir-opt/end_region_9.rs @@ -0,0 +1,85 @@ +// 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. + +// compile-flags: -Z identify_regions -Z span_free_formats +// ignore-tidy-linelength + +// This test models a scenario that arielb1 found during review. +// Namely, any filtering of EndRegions must ensure to continue to emit +// any necessary EndRegions that occur earlier in the source than the +// first borrow involving that region. +// +// It is tricky to actually construct examples of this, which is the +// main reason that I am keeping this test even though I have now +// removed the pre-filter that motivated the test in the first place. + +fn main() { + let mut second_iter = false; + let x = 3; + 'a: loop { + let mut y; + loop { + if second_iter { + break 'a; // want to generate `EndRegion('a)` here + } else { + y = &/*'a*/ x; + } + second_iter = true; + } + } +} + +// END RUST SOURCE +// START rustc.node4.SimplifyCfg-qualify-consts.after.mir +// fn main() -> () { +// let mut _0: (); +// let mut _1: bool; +// let _2: i32; +// let mut _4: &'13_0rce i32; +// let mut _3: (); +// let mut _5: !; +// let mut _6: (); +// let mut _7: bool; +// let mut _8: !; +// +// bb0: { +// StorageLive(_1); +// _1 = const false; +// StorageLive(_2); +// _2 = const 3i32; +// StorageLive(_4); +// goto -> bb1; +// } +// +// bb1: { +// StorageLive(_7); +// _7 = _1; +// switchInt(_7) -> [0u8: bb3, otherwise: bb2]; +// } +// +// bb2: { +// _0 = (); +// StorageDead(_7); +// StorageDead(_4); +// EndRegion('13_0rce); +// StorageDead(_2); +// StorageDead(_1); +// return; +// } +// +// bb3: { +// _4 = &'13_0rce _2; +// _6 = (); +// StorageDead(_7); +// _1 = const true; +// _3 = (); +// goto -> bb1; +// } +// } diff --git a/src/test/parse-fail/macro-keyword.rs b/src/test/parse-fail/macro-keyword.rs index 6a7ccff155..c7dcaf4137 100644 --- a/src/test/parse-fail/macro-keyword.rs +++ b/src/test/parse-fail/macro-keyword.rs @@ -10,7 +10,7 @@ // compile-flags: -Z parse-only -fn macro() { //~ ERROR `macro` is a reserved keyword +fn macro() { //~ ERROR expected identifier, found reserved keyword `macro` } pub fn main() { diff --git a/src/test/parse-fail/type-parameters-in-field-exprs.rs b/src/test/parse-fail/type-parameters-in-field-exprs.rs index 9b160434e3..e904e8b544 100644 --- a/src/test/parse-fail/type-parameters-in-field-exprs.rs +++ b/src/test/parse-fail/type-parameters-in-field-exprs.rs @@ -21,5 +21,5 @@ fn main() { y: 2, }; f.x::; - //~^ ERROR field expressions may not have type parameters + //~^ ERROR field expressions may not have generic arguments } diff --git a/src/test/parse-fail/underscore-suffix-for-string.rs b/src/test/parse-fail/underscore-suffix-for-string.rs new file mode 100644 index 0000000000..05de5f8e19 --- /dev/null +++ b/src/test/parse-fail/underscore-suffix-for-string.rs @@ -0,0 +1,20 @@ +// 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. + +fn main() { + let _ = "Foo"_; + //~^ WARNING underscore literal suffix is not allowed + //~| WARNING this was previously accepted + //~| NOTE issue #42326 +} + +FAIL +//~^ ERROR +//~| NOTE diff --git a/src/test/run-fail/assert-eq-macro-panic.rs b/src/test/run-fail/assert-eq-macro-panic.rs index a3e0a1f904..fed2ee0bea 100644 --- a/src/test/run-fail/assert-eq-macro-panic.rs +++ b/src/test/run-fail/assert-eq-macro-panic.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:assertion failed: `(left == right)` (left: `14`, right: `15`) +// error-pattern:assertion failed: `(left == right)` +// error-pattern: left: `14` +// error-pattern:right: `15` fn main() { assert_eq!(14, 15); diff --git a/src/test/compile-fail/variance-region-bounds.rs b/src/test/run-fail/assert-ne-macro-panic.rs similarity index 66% rename from src/test/compile-fail/variance-region-bounds.rs rename to src/test/run-fail/assert-ne-macro-panic.rs index 41d204a541..d57bb0fb67 100644 --- a/src/test/compile-fail/variance-region-bounds.rs +++ b/src/test/run-fail/assert-ne-macro-panic.rs @@ -8,18 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Check that `T:'a` is contravariant in T. +// error-pattern:assertion failed: `(left != right)` +// error-pattern: left: `14` +// error-pattern:right: `14` -#![feature(rustc_attrs)] - -#[rustc_variance] -trait Foo: 'static { //~ ERROR [o] -} - -#[rustc_variance] -trait Bar { //~ ERROR [o, o] - fn do_it(&self) - where T: 'static; +fn main() { + assert_ne!(14, 14); } - -fn main() { } diff --git a/src/test/run-make/llvm-phase/test.rs b/src/test/run-make/llvm-phase/test.rs index ca58e00785..a75dc7e57a 100644 --- a/src/test/run-make/llvm-phase/test.rs +++ b/src/test/run-make/llvm-phase/test.rs @@ -85,6 +85,6 @@ fn main() { let (result, _) = rustc_driver::run_compiler( &args, &mut JitCalls, Some(box JitLoader), None); if let Err(n) = result { - panic!("Error {}", n); + panic!("Error {:?}", n); } } diff --git a/src/test/run-make/no-duplicate-libs/Makefile b/src/test/run-make/no-duplicate-libs/Makefile index 3f6a28c251..13d8366c60 100644 --- a/src/test/run-make/no-duplicate-libs/Makefile +++ b/src/test/run-make/no-duplicate-libs/Makefile @@ -4,9 +4,7 @@ ifdef IS_MSVC # FIXME(#27979) all: else -all: - $(RUSTC) foo.rs - $(RUSTC) bar.rs +all: $(call STATICLIB,foo) $(call STATICLIB,bar) $(RUSTC) main.rs $(call RUN,main) endif diff --git a/src/test/compile-fail/auxiliary/allocator1.rs b/src/test/run-make/no-duplicate-libs/bar.c similarity index 72% rename from src/test/compile-fail/auxiliary/allocator1.rs rename to src/test/run-make/no-duplicate-libs/bar.c index b24784838d..b9dcd0f5e5 100644 --- a/src/test/compile-fail/auxiliary/allocator1.rs +++ b/src/test/run-make/no-duplicate-libs/bar.c @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// no-prefer-dynamic +extern void foo(); -#![feature(allocator)] -#![allocator] -#![crate_type = "rlib"] -#![no_std] +void bar() { + foo(); +} diff --git a/src/test/run-make/no-duplicate-libs/foo.c b/src/test/run-make/no-duplicate-libs/foo.c new file mode 100644 index 0000000000..906cd5682b --- /dev/null +++ b/src/test/run-make/no-duplicate-libs/foo.c @@ -0,0 +1,11 @@ +// 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. + +void foo() {} diff --git a/src/test/run-make/no-duplicate-libs/main.rs b/src/test/run-make/no-duplicate-libs/main.rs index 12ddce3458..824946fe9c 100644 --- a/src/test/run-make/no-duplicate-libs/main.rs +++ b/src/test/run-make/no-duplicate-libs/main.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[link(name = "foo")] -#[link(name = "bar")] -#[link(name = "foo")] +#[link(name = "foo")] // linker should drop this library, no symbols used +#[link(name = "bar")] // symbol comes from this library +#[link(name = "foo")] // now linker picks up `foo` b/c `bar` library needs it extern { fn bar(); } diff --git a/src/test/run-make/profile/Makefile b/src/test/run-make/profile/Makefile new file mode 100644 index 0000000000..7300bfc955 --- /dev/null +++ b/src/test/run-make/profile/Makefile @@ -0,0 +1,9 @@ +-include ../tools.mk + +all: +ifeq ($(PROFILER_SUPPORT),1) + $(RUSTC) -g -Z profile test.rs + $(call RUN,test) || exit 1 + [ -e "$(TMPDIR)/test.gcno" ] || (echo "No .gcno file"; exit 1) + [ -e "$(TMPDIR)/test.gcda" ] || (echo "No .gcda file"; exit 1) +endif diff --git a/src/test/run-make/profile/test.rs b/src/test/run-make/profile/test.rs new file mode 100644 index 0000000000..046d27a9f0 --- /dev/null +++ b/src/test/run-make/profile/test.rs @@ -0,0 +1,11 @@ +// 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. + +fn main() {} diff --git a/src/test/run-make/rustdoc-output-path/Makefile b/src/test/run-make/rustdoc-output-path/Makefile new file mode 100644 index 0000000000..4e570718a6 --- /dev/null +++ b/src/test/run-make/rustdoc-output-path/Makefile @@ -0,0 +1,4 @@ +-include ../tools.mk + +all: + $(HOST_RPATH_ENV) '$(RUSTDOC)' -o "$(TMPDIR)/foo/bar/doc" foo.rs diff --git a/src/test/run-make/rustdoc-output-path/foo.rs b/src/test/run-make/rustdoc-output-path/foo.rs new file mode 100644 index 0000000000..11fc2cd2b8 --- /dev/null +++ b/src/test/run-make/rustdoc-output-path/foo.rs @@ -0,0 +1,11 @@ +// 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. + +pub struct Foo; diff --git a/src/test/run-make/sanitizer-address/overflow.rs b/src/test/run-make/sanitizer-address/overflow.rs index e35c3873f7..1f3c64c8c3 100644 --- a/src/test/run-make/sanitizer-address/overflow.rs +++ b/src/test/run-make/sanitizer-address/overflow.rs @@ -10,5 +10,5 @@ fn main() { let xs = [0, 1, 2, 3]; - let y = unsafe { *xs.as_ptr().offset(4) }; + let _y = unsafe { *xs.as_ptr().offset(4) }; } diff --git a/src/test/run-make/sanitizer-cdylib-link/Makefile b/src/test/run-make/sanitizer-cdylib-link/Makefile new file mode 100644 index 0000000000..9b0470fb27 --- /dev/null +++ b/src/test/run-make/sanitizer-cdylib-link/Makefile @@ -0,0 +1,19 @@ +-include ../tools.mk + +# This test builds a shared object, then an executable that links it as a native +# rust library (constrast to an rlib). The shared library and executable both +# are compiled with address sanitizer, and we assert that a fault in the cdylib +# is correctly detected. + +ifeq ($(TARGET),x86_64-unknown-linux-gnu) +ASAN_SUPPORT=$(SANITIZER_SUPPORT) +EXTRA_RUSTFLAG= +endif + +all: +ifeq ($(ASAN_SUPPORT),1) + $(RUSTC) -g -Z sanitizer=address --crate-type cdylib --target $(TARGET) library.rs + $(RUSTC) -g -Z sanitizer=address --crate-type bin --target $(TARGET) -llibrary program.rs + LD_LIBRARY_PATH=$(TMPDIR) $(TMPDIR)/program 2>&1 | grep -q stack-buffer-overflow +endif + diff --git a/src/test/run-make/sanitizer-cdylib-link/library.rs b/src/test/run-make/sanitizer-cdylib-link/library.rs new file mode 100644 index 0000000000..4ceef5d3f5 --- /dev/null +++ b/src/test/run-make/sanitizer-cdylib-link/library.rs @@ -0,0 +1,15 @@ +// 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. + +#[no_mangle] +pub extern fn overflow() { + let xs = [0, 1, 2, 3]; + let _y = unsafe { *xs.as_ptr().offset(4) }; +} diff --git a/src/test/run-make/sanitizer-cdylib-link/program.rs b/src/test/run-make/sanitizer-cdylib-link/program.rs new file mode 100644 index 0000000000..9f52817c85 --- /dev/null +++ b/src/test/run-make/sanitizer-cdylib-link/program.rs @@ -0,0 +1,17 @@ +// 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. + +extern { + fn overflow(); +} + +fn main() { + unsafe { overflow() } +} diff --git a/src/test/run-make/sanitizer-dylib-link/Makefile b/src/test/run-make/sanitizer-dylib-link/Makefile new file mode 100644 index 0000000000..d75241f097 --- /dev/null +++ b/src/test/run-make/sanitizer-dylib-link/Makefile @@ -0,0 +1,19 @@ +-include ../tools.mk + +# This test builds a shared object, then an executable that links it as a native +# rust library (constrast to an rlib). The shared library and executable both +# are compiled with address sanitizer, and we assert that a fault in the dylib +# is correctly detected. + +ifeq ($(TARGET),x86_64-unknown-linux-gnu) +ASAN_SUPPORT=$(SANITIZER_SUPPORT) +EXTRA_RUSTFLAG= +endif + +all: +ifeq ($(ASAN_SUPPORT),1) + $(RUSTC) -g -Z sanitizer=address --crate-type dylib --target $(TARGET) library.rs + $(RUSTC) -g -Z sanitizer=address --crate-type bin --target $(TARGET) -llibrary program.rs + LD_LIBRARY_PATH=$(TMPDIR) $(TMPDIR)/program 2>&1 | grep -q stack-buffer-overflow +endif + diff --git a/src/test/run-make/sanitizer-dylib-link/library.rs b/src/test/run-make/sanitizer-dylib-link/library.rs new file mode 100644 index 0000000000..4ceef5d3f5 --- /dev/null +++ b/src/test/run-make/sanitizer-dylib-link/library.rs @@ -0,0 +1,15 @@ +// 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. + +#[no_mangle] +pub extern fn overflow() { + let xs = [0, 1, 2, 3]; + let _y = unsafe { *xs.as_ptr().offset(4) }; +} diff --git a/src/test/run-make/sanitizer-dylib-link/program.rs b/src/test/run-make/sanitizer-dylib-link/program.rs new file mode 100644 index 0000000000..9f52817c85 --- /dev/null +++ b/src/test/run-make/sanitizer-dylib-link/program.rs @@ -0,0 +1,17 @@ +// 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. + +extern { + fn overflow(); +} + +fn main() { + unsafe { overflow() } +} diff --git a/src/test/run-make/sanitizer-dylib/Makefile b/src/test/run-make/sanitizer-dylib/Makefile deleted file mode 100644 index 835d5b0d9d..0000000000 --- a/src/test/run-make/sanitizer-dylib/Makefile +++ /dev/null @@ -1,8 +0,0 @@ --include ../tools.mk - -ifeq ($(TARGET),x86_64-unknown-linux-gnu) -all: - $(RUSTC) -Z sanitizer=leak --crate-type dylib --target $(TARGET) hello.rs 2>&1 | grep -q 'Only executables and rlibs can be compiled with `-Z sanitizer`' -else -all: -endif diff --git a/src/test/run-make/sanitizer-invalid-cratetype/Makefile b/src/test/run-make/sanitizer-invalid-cratetype/Makefile new file mode 100644 index 0000000000..d03bbf84c1 --- /dev/null +++ b/src/test/run-make/sanitizer-invalid-cratetype/Makefile @@ -0,0 +1,18 @@ +-include ../tools.mk + +# NOTE the address sanitizer only supports x86_64 linux and macOS + +ifeq ($(TARGET),x86_64-apple-darwin) +ASAN_SUPPORT=$(SANITIZER_SUPPORT) +EXTRA_RUSTFLAG=-C rpath +else +ifeq ($(TARGET),x86_64-unknown-linux-gnu) +ASAN_SUPPORT=$(SANITIZER_SUPPORT) +EXTRA_RUSTFLAG= +endif +endif + +all: +ifeq ($(ASAN_SUPPORT),1) + $(RUSTC) -Z sanitizer=address --crate-type proc-macro --target $(TARGET) hello.rs 2>&1 | grep -q -- '-Z sanitizer' +endif diff --git a/src/test/run-make/sanitizer-dylib/hello.rs b/src/test/run-make/sanitizer-invalid-cratetype/hello.rs similarity index 100% rename from src/test/run-make/sanitizer-dylib/hello.rs rename to src/test/run-make/sanitizer-invalid-cratetype/hello.rs diff --git a/src/test/run-make/sanitizer-staticlib-link/Makefile b/src/test/run-make/sanitizer-staticlib-link/Makefile new file mode 100644 index 0000000000..f92dc52b44 --- /dev/null +++ b/src/test/run-make/sanitizer-staticlib-link/Makefile @@ -0,0 +1,18 @@ +-include ../tools.mk + +# This test builds a staticlib, then an executable that links to it. +# The staticlib and executable both are compiled with address sanitizer, +# and we assert that a fault in the staticlib is correctly detected. + +ifeq ($(TARGET),x86_64-unknown-linux-gnu) +ASAN_SUPPORT=$(SANITIZER_SUPPORT) +EXTRA_RUSTFLAG= +endif + +all: +ifeq ($(ASAN_SUPPORT),1) + $(RUSTC) -g -Z sanitizer=address --crate-type staticlib --target $(TARGET) library.rs + $(CC) program.c $(call STATICLIB,library) $(call OUT_EXE,program) $(EXTRACFLAGS) $(EXTRACXXFLAGS) + LD_LIBRARY_PATH=$(TMPDIR) $(TMPDIR)/program 2>&1 | grep -q stack-buffer-overflow +endif + diff --git a/src/test/run-make/sanitizer-staticlib-link/library.rs b/src/test/run-make/sanitizer-staticlib-link/library.rs new file mode 100644 index 0000000000..4ceef5d3f5 --- /dev/null +++ b/src/test/run-make/sanitizer-staticlib-link/library.rs @@ -0,0 +1,15 @@ +// 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. + +#[no_mangle] +pub extern fn overflow() { + let xs = [0, 1, 2, 3]; + let _y = unsafe { *xs.as_ptr().offset(4) }; +} diff --git a/src/test/run-make/sanitizer-staticlib-link/program.c b/src/test/run-make/sanitizer-staticlib-link/program.c new file mode 100644 index 0000000000..abd5d508e7 --- /dev/null +++ b/src/test/run-make/sanitizer-staticlib-link/program.c @@ -0,0 +1,8 @@ +// ignore-license +void overflow(); + +int main() { + overflow(); + return 0; +} + diff --git a/src/test/run-make/save-analysis-fail/foo.rs b/src/test/run-make/save-analysis-fail/foo.rs index a996aa4fad..8a1b579398 100644 --- a/src/test/run-make/save-analysis-fail/foo.rs +++ b/src/test/run-make/save-analysis-fail/foo.rs @@ -17,7 +17,6 @@ extern crate graphviz; extern crate krate2; extern crate krate2 as krate3; -extern crate flate as myflate; use graphviz::RenderOption; use std::collections::{HashMap,HashSet}; @@ -51,7 +50,6 @@ fn test_alias(i: Option<::Item>) { krate2::hello(); krate3::hello(); - myflate::deflate_bytes(&[]); let x = (3isize, 4usize); let y = x.1; diff --git a/src/test/run-make/save-analysis/Makefile b/src/test/run-make/save-analysis/Makefile index 3711b6ea89..9ebc40d401 100644 --- a/src/test/run-make/save-analysis/Makefile +++ b/src/test/run-make/save-analysis/Makefile @@ -3,6 +3,5 @@ all: code krate2: krate2.rs $(RUSTC) $< code: foo.rs krate2 - $(RUSTC) foo.rs -Zsave-analysis-csv $(RUSTC) foo.rs -Zsave-analysis $(RUSTC) foo.rs -Zsave-analysis-api diff --git a/src/test/run-make/save-analysis/foo.rs b/src/test/run-make/save-analysis/foo.rs index 3fe1479f5f..5cb363ac34 100644 --- a/src/test/run-make/save-analysis/foo.rs +++ b/src/test/run-make/save-analysis/foo.rs @@ -18,7 +18,6 @@ extern crate graphviz; extern crate krate2; extern crate krate2 as krate3; -extern crate flate as myflate; use graphviz::RenderOption; use std::collections::{HashMap,HashSet}; @@ -52,7 +51,6 @@ fn test_alias(i: Option<::Item>) { krate2::hello(); krate3::hello(); - myflate::deflate_bytes(&[]); let x = (3isize, 4usize); let y = x.1; diff --git a/src/test/run-make/type-mismatch-same-crate-name/Makefile b/src/test/run-make/type-mismatch-same-crate-name/Makefile new file mode 100644 index 0000000000..1044d73fd1 --- /dev/null +++ b/src/test/run-make/type-mismatch-same-crate-name/Makefile @@ -0,0 +1,19 @@ +-include ../tools.mk + +all: + # compile two different versions of crateA + $(RUSTC) --crate-type=rlib crateA.rs -C metadata=-1 -C extra-filename=-1 + $(RUSTC) --crate-type=rlib crateA.rs -C metadata=-2 -C extra-filename=-2 + # make crateB depend on version 1 of crateA + $(RUSTC) --crate-type=rlib crateB.rs --extern crateA=$(TMPDIR)/libcrateA-1.rlib + # make crateC depend on version 2 of crateA + $(RUSTC) crateC.rs --extern crateA=$(TMPDIR)/libcrateA-2.rlib 2>&1 | \ + tr -d '\r\n' | grep \ + "mismatched types.*\ + crateB::try_foo(foo2);.*\ + expected struct \`crateA::foo::Foo\`, found struct \`crateA::Foo\`.*\ + different versions of crate \`crateA\`.*\ + mismatched types.*\ + crateB::try_bar(bar2);.*\ + expected trait \`crateA::bar::Bar\`, found trait \`crateA::Bar\`.*\ + different versions of crate \`crateA\`" diff --git a/src/test/run-make/type-mismatch-same-crate-name/crateA.rs b/src/test/run-make/type-mismatch-same-crate-name/crateA.rs new file mode 100644 index 0000000000..e40266bb4c --- /dev/null +++ b/src/test/run-make/type-mismatch-same-crate-name/crateA.rs @@ -0,0 +1,26 @@ +// 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. + +mod foo { + pub struct Foo; +} + +mod bar { + pub trait Bar{} + + pub fn bar() -> Box { + unimplemented!() + } +} + +// This makes the publicly accessible path +// differ from the internal one. +pub use foo::Foo; +pub use bar::{Bar, bar}; diff --git a/src/test/run-make/type-mismatch-same-crate-name/crateB.rs b/src/test/run-make/type-mismatch-same-crate-name/crateB.rs new file mode 100644 index 0000000000..da4ea1c938 --- /dev/null +++ b/src/test/run-make/type-mismatch-same-crate-name/crateB.rs @@ -0,0 +1,14 @@ +// 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. + +extern crate crateA; + +pub fn try_foo(x: crateA::Foo){} +pub fn try_bar(x: Box){} diff --git a/src/test/run-make/type-mismatch-same-crate-name/crateC.rs b/src/test/run-make/type-mismatch-same-crate-name/crateC.rs new file mode 100644 index 0000000000..da869d2145 --- /dev/null +++ b/src/test/run-make/type-mismatch-same-crate-name/crateC.rs @@ -0,0 +1,35 @@ +// 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. + +// This tests the extra note reported when a type error deals with +// seemingly identical types. +// The main use case of this error is when there are two crates +// (generally different versions of the same crate) with the same name +// causing a type mismatch. + +// The test is nearly the same as the one in +// compile-fail/type-mismatch-same-crate-name.rs +// but deals with the case where one of the crates +// is only introduced as an indirect dependency. +// and the type is accessed via a reexport. +// This is similar to how the error can be introduced +// when using cargo's automatic dependency resolution. + +extern crate crateA; + +fn main() { + let foo2 = crateA::Foo; + let bar2 = crateA::bar(); + { + extern crate crateB; + crateB::try_foo(foo2); + crateB::try_bar(bar2); + } +} diff --git a/src/test/run-make/windows-spawn/Makefile b/src/test/run-make/windows-spawn/Makefile new file mode 100644 index 0000000000..f0d4242260 --- /dev/null +++ b/src/test/run-make/windows-spawn/Makefile @@ -0,0 +1,14 @@ +-include ../tools.mk + +ifdef IS_WINDOWS + +all: + $(RUSTC) -o "$(TMPDIR)/hopefullydoesntexist bar.exe" hello.rs + $(RUSTC) spawn.rs + $(TMPDIR)/spawn.exe + +else + +all: + +endif diff --git a/src/test/run-make/windows-spawn/hello.rs b/src/test/run-make/windows-spawn/hello.rs new file mode 100644 index 0000000000..b177f41941 --- /dev/null +++ b/src/test/run-make/windows-spawn/hello.rs @@ -0,0 +1,13 @@ +// 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. + +fn main() { + println!("Hello World!"); +} diff --git a/src/test/run-make/windows-spawn/spawn.rs b/src/test/run-make/windows-spawn/spawn.rs new file mode 100644 index 0000000000..2913cbe226 --- /dev/null +++ b/src/test/run-make/windows-spawn/spawn.rs @@ -0,0 +1,22 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::io::ErrorKind; +use std::process::Command; + +fn main() { + // Make sure it doesn't try to run "hopefullydoesntexist bar.exe". + assert_eq!(Command::new("hopefullydoesntexist") + .arg("bar") + .spawn() + .unwrap_err() + .kind(), + ErrorKind::NotFound); +} diff --git a/src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs b/src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs index 0433b95865..e2c68a626f 100644 --- a/src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs +++ b/src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs @@ -8,50 +8,37 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unused_parens)] -#![feature(plugin)] -#![feature(plugin_registrar)] -#![feature(rustc_private)] -#![plugin(proc_macro_plugin)] +// no-prefer-dynamic -extern crate rustc_plugin; -extern crate syntax; +#![crate_type = "proc-macro"] +#![feature(proc_macro)] -use rustc_plugin::Registry; +extern crate proc_macro; -use syntax::ext::base::SyntaxExtension; -use syntax::parse::token::Token; -use syntax::symbol::Symbol; -use syntax::tokenstream::{TokenTree, TokenStream}; +use proc_macro::{TokenStream, TokenNode, quote}; -#[plugin_registrar] -pub fn plugin_registrar(reg: &mut Registry) { - reg.register_syntax_extension(Symbol::intern("cond"), - SyntaxExtension::ProcMacro(Box::new(cond))); -} - -fn cond(input: TokenStream) -> TokenStream { +#[proc_macro] +pub fn cond(input: TokenStream) -> TokenStream { let mut conds = Vec::new(); - let mut input = input.trees().peekable(); + let mut input = input.into_iter().peekable(); while let Some(tree) = input.next() { - let mut cond = match tree { - TokenTree::Delimited(_, ref delimited) => delimited.stream(), + let cond = match tree.kind { + TokenNode::Group(_, cond) => cond, _ => panic!("Invalid input"), }; - let mut trees = cond.trees(); - let test = trees.next(); - let rhs = trees.collect::(); + let mut cond_trees = cond.clone().into_iter(); + let test = cond_trees.next().expect("Unexpected empty condition in `cond!`"); + let rhs = cond_trees.collect::(); if rhs.is_empty() { panic!("Invalid macro usage in cond: {}", cond); } - let is_else = match test { - Some(TokenTree::Token(_, Token::Ident(ident))) if ident.name == "else" => true, + let is_else = match test.kind { + TokenNode::Term(word) => word.as_str() == "else", _ => false, }; conds.push(if is_else || input.peek().is_none() { quote!({ $rhs }) } else { - let test = test.unwrap(); quote!(if $test { $rhs } else) }); } diff --git a/src/test/run-pass-fulldeps/auxiliary/hello_macro.rs b/src/test/run-pass-fulldeps/auxiliary/hello_macro.rs index 9522592a5e..cf6584e961 100644 --- a/src/test/run-pass-fulldeps/auxiliary/hello_macro.rs +++ b/src/test/run-pass-fulldeps/auxiliary/hello_macro.rs @@ -8,29 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(plugin)] -#![feature(plugin_registrar)] -#![feature(rustc_private)] -#![plugin(proc_macro_plugin)] +// no-prefer-dynamic -extern crate rustc_plugin; -extern crate syntax; +#![crate_type = "proc-macro"] +#![feature(proc_macro, proc_macro_lib)] -use rustc_plugin::Registry; -use syntax::ext::base::SyntaxExtension; -use syntax::symbol::Symbol; -use syntax::tokenstream::TokenStream; +extern crate proc_macro; -#[plugin_registrar] -pub fn plugin_registrar(reg: &mut Registry) { - reg.register_syntax_extension(Symbol::intern("hello"), - SyntaxExtension::ProcMacro(Box::new(hello))); -} +use proc_macro::{TokenStream, quote}; // This macro is not very interesting, but it does contain delimited tokens with // no content - `()` and `{}` - which has caused problems in the past. // Also, it tests that we can escape `$` via `$$`. -fn hello(_: TokenStream) -> TokenStream { +#[proc_macro] +pub fn hello(_: TokenStream) -> TokenStream { quote!({ fn hello() {} macro_rules! m { ($$($$t:tt)*) => { $$($$t)* } } diff --git a/src/test/run-pass-fulldeps/auxiliary/proc_macro_def.rs b/src/test/run-pass-fulldeps/auxiliary/proc_macro_def.rs index 0e37a7a5dc..1b47043884 100644 --- a/src/test/run-pass-fulldeps/auxiliary/proc_macro_def.rs +++ b/src/test/run-pass-fulldeps/auxiliary/proc_macro_def.rs @@ -8,47 +8,37 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(plugin, plugin_registrar, rustc_private)] -#![plugin(proc_macro_plugin)] - -extern crate rustc_plugin; -extern crate syntax; - -use rustc_plugin::Registry; -use syntax::ext::base::SyntaxExtension; -use syntax::tokenstream::TokenStream; -use syntax::symbol::Symbol; - -#[plugin_registrar] -pub fn plugin_registrar(reg: &mut Registry) { - reg.register_syntax_extension(Symbol::intern("attr_tru"), - SyntaxExtension::AttrProcMacro(Box::new(attr_tru))); - reg.register_syntax_extension(Symbol::intern("attr_identity"), - SyntaxExtension::AttrProcMacro(Box::new(attr_identity))); - reg.register_syntax_extension(Symbol::intern("tru"), - SyntaxExtension::ProcMacro(Box::new(tru))); - reg.register_syntax_extension(Symbol::intern("ret_tru"), - SyntaxExtension::ProcMacro(Box::new(ret_tru))); - reg.register_syntax_extension(Symbol::intern("identity"), - SyntaxExtension::ProcMacro(Box::new(identity))); -} +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro, proc_macro_lib)] + +extern crate proc_macro; + +use proc_macro::{TokenStream, quote}; -fn attr_tru(_attr: TokenStream, _item: TokenStream) -> TokenStream { - quote!(fn f1() -> bool { true }) +#[proc_macro_attribute] +pub fn attr_tru(_attr: TokenStream, item: TokenStream) -> TokenStream { + let name = item.into_iter().skip(1).next().unwrap(); + quote!(fn $name() -> bool { true }) } -fn attr_identity(_attr: TokenStream, item: TokenStream) -> TokenStream { +#[proc_macro_attribute] +pub fn attr_identity(_attr: TokenStream, item: TokenStream) -> TokenStream { quote!($item) } -fn tru(_ts: TokenStream) -> TokenStream { +#[proc_macro] +pub fn tru(_ts: TokenStream) -> TokenStream { quote!(true) } -fn ret_tru(_ts: TokenStream) -> TokenStream { +#[proc_macro] +pub fn ret_tru(_ts: TokenStream) -> TokenStream { quote!(return true;) } -fn identity(ts: TokenStream) -> TokenStream { +#[proc_macro] +pub fn identity(ts: TokenStream) -> TokenStream { quote!($ts) } diff --git a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs index c9fa96b83c..b5d6ff595a 100644 --- a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs +++ b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs @@ -54,7 +54,7 @@ fn expand_mbe_matches(cx: &mut ExtCtxt, _: Span, args: &[TokenTree]) let mac_expr = match (&*matched_nt, &*map[&Ident::from_str("pat")]) { (&NtExpr(ref matched_expr), &MatchedSeq(ref pats, seq_sp)) => { let pats: Vec> = pats.iter().map(|pat_nt| { - match **pat_nt { + match *pat_nt { MatchedNonterminal(ref nt) => match **nt { NtPat(ref pat) => pat.clone(), _ => unreachable!(), diff --git a/src/test/run-pass-fulldeps/issue-2804.rs b/src/test/run-pass-fulldeps/issue-2804.rs index a2b4e218a0..f999d2d0ed 100644 --- a/src/test/run-pass-fulldeps/issue-2804.rs +++ b/src/test/run-pass-fulldeps/issue-2804.rs @@ -8,10 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections)] #![feature(rustc_private)] -extern crate collections; extern crate serialize; use std::collections::HashMap; diff --git a/src/test/run-pass-fulldeps/macro-quote-1.rs b/src/test/run-pass-fulldeps/macro-quote-1.rs deleted file mode 100644 index e7d0a83017..0000000000 --- a/src/test/run-pass-fulldeps/macro-quote-1.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2012-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. - -// ignore-stage1 - -#![feature(plugin)] -#![feature(rustc_private)] -#![plugin(proc_macro_plugin)] - -extern crate syntax; -extern crate syntax_pos; - -use syntax::ast::{Ident, Name}; -use syntax::parse::token::{self, Token, Lit}; -use syntax::tokenstream::TokenTree; - -fn main() { - let true_tok = token::Ident(Ident::from_str("true")); - assert!(quote!(true).eq_unspanned(&true_tok.into())); - - // issue #35829, extended check to proc_macro. - let triple_dot_tok = Token::DotDotDot; - assert!(quote!(...).eq_unspanned(&triple_dot_tok.into())); - - let byte_str_tok = Token::Literal(Lit::ByteStr(Name::intern("one")), None); - assert!(quote!(b"one").eq_unspanned(&byte_str_tok.into())); - - let byte_str_raw_tok = Token::Literal(Lit::ByteStrRaw(Name::intern("#\"two\"#"), 3), None); - assert!(quote!(br###"#"two"#"###).eq_unspanned(&byte_str_raw_tok.into())); - - let str_raw_tok = Token::Literal(Lit::StrRaw(Name::intern("#\"three\"#"), 2), None); - assert!(quote!(r##"#"three"#"##).eq_unspanned(&str_raw_tok.into())); -} diff --git a/src/test/run-pass-fulldeps/macro-quote-cond.rs b/src/test/run-pass-fulldeps/macro-quote-cond.rs index fa969b6a08..cff743bdae 100644 --- a/src/test/run-pass-fulldeps/macro-quote-cond.rs +++ b/src/test/run-pass-fulldeps/macro-quote-cond.rs @@ -11,9 +11,11 @@ // aux-build:cond_plugin.rs // ignore-stage1 -#![feature(plugin)] -#![feature(rustc_private)] -#![plugin(cond_plugin)] +#![feature(proc_macro)] + +extern crate cond_plugin; + +use cond_plugin::cond; fn fact(n : i64) -> i64 { if n == 0 { diff --git a/src/test/run-pass-fulldeps/macro-quote-test.rs b/src/test/run-pass-fulldeps/macro-quote-test.rs index bdbea8a419..eb77895e2d 100644 --- a/src/test/run-pass-fulldeps/macro-quote-test.rs +++ b/src/test/run-pass-fulldeps/macro-quote-test.rs @@ -13,10 +13,10 @@ // aux-build:hello_macro.rs // ignore-stage1 -#![feature(plugin)] -#![feature(rustc_private)] -#![plugin(hello_macro)] +#![feature(proc_macro)] + +extern crate hello_macro; fn main() { - hello!(); + hello_macro::hello!(); } diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-args.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-args.rs index 989c77f108..93815d1683 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-args.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-args.rs @@ -24,7 +24,7 @@ pub fn attr_with_args(args: TokenStream, input: TokenStream) -> TokenStream { let input = input.to_string(); - assert_eq!(input, "fn foo ( ) { }"); + assert_eq!(input, "fn foo() { }"); r#" fn foo() -> &'static str { "Hello, world!" } diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/count_compound_ops.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/count_compound_ops.rs new file mode 100644 index 0000000000..ec2ff0d1e2 --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/count_compound_ops.rs @@ -0,0 +1,36 @@ +// 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. + +// no-prefer-dynamic + +#![feature(proc_macro)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenNode, Spacing, Literal, quote}; + +#[proc_macro] +pub fn count_compound_ops(input: TokenStream) -> TokenStream { + assert_eq!(count_compound_ops_helper(quote!(++ (&&) 4@a)), 3); + TokenNode::Literal(Literal::u32(count_compound_ops_helper(input))).into() +} + +fn count_compound_ops_helper(input: TokenStream) -> u32 { + let mut count = 0; + for token in input { + match token.kind { + TokenNode::Op(c, Spacing::Alone) => count += 1, + TokenNode::Group(_, tokens) => count += count_compound_ops_helper(tokens), + _ => {} + } + } + count +} diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/hygiene_example.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/hygiene_example.rs new file mode 100644 index 0000000000..8ffa7abe6f --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/hygiene_example.rs @@ -0,0 +1,19 @@ +// 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. + +#![feature(proc_macro)] + +extern crate hygiene_example_codegen; + +pub use hygiene_example_codegen::hello; + +pub fn print(string: &str) { + println!("{}", string); +} diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/hygiene_example_codegen.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/hygiene_example_codegen.rs new file mode 100644 index 0000000000..055e4e2fad --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/hygiene_example_codegen.rs @@ -0,0 +1,36 @@ +// 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. + +// no-prefer-dynamic + +#![feature(proc_macro)] +#![crate_type = "proc-macro"] + +extern crate proc_macro as proc_macro_renamed; // This does not break `quote!` + +use proc_macro_renamed::{TokenStream, quote}; + +#[proc_macro] +pub fn hello(input: TokenStream) -> TokenStream { + quote!(hello_helper!($input)) + //^ `hello_helper!` always resolves to the following proc macro, + //| no matter where `hello!` is used. +} + +#[proc_macro] +pub fn hello_helper(input: TokenStream) -> TokenStream { + quote! { + extern crate hygiene_example; // This is never a conflict error + let string = format!("hello {}", $input); + //^ `format!` always resolves to the prelude macro, + //| even if a different `format!` is in scope where `hello!` is used. + hygiene_example::print(&string) + } +} diff --git a/src/test/run-pass-fulldeps/proc-macro/count_compound_ops.rs b/src/test/run-pass-fulldeps/proc-macro/count_compound_ops.rs new file mode 100644 index 0000000000..1a2b144e47 --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/count_compound_ops.rs @@ -0,0 +1,20 @@ +// 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. + +// aux-build:count_compound_ops.rs + +#![feature(proc_macro)] + +extern crate count_compound_ops; +use count_compound_ops::count_compound_ops; + +fn main() { + assert_eq!(count_compound_ops!(foo<=>bar << or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:hygiene_example_codegen.rs +// aux-build:hygiene_example.rs + +#![feature(proc_macro)] + +extern crate hygiene_example; +use hygiene_example::hello; + +fn main() { + mod hygiene_example {} // no conflict with `extern crate hygiene_example;` from the proc macro + macro_rules! format { () => {} } // does not interfere with `format!` from the proc macro + macro_rules! hello_helper { () => {} } // similarly does not intefere with the proc macro + + let string = "world"; // no conflict with `string` from the proc macro + hello!(string); + hello!(string); +} diff --git a/src/test/run-pass-fulldeps/proc_macro.rs b/src/test/run-pass-fulldeps/proc_macro.rs index 22cc9f0f8d..cdda723585 100644 --- a/src/test/run-pass-fulldeps/proc_macro.rs +++ b/src/test/run-pass-fulldeps/proc_macro.rs @@ -12,10 +12,11 @@ // ignore-stage1 // ignore-cross-compile -#![feature(plugin, custom_attribute)] -#![feature(type_macros)] +#![feature(proc_macro)] -#![plugin(proc_macro_def)] +extern crate proc_macro_def; + +use proc_macro_def::{attr_tru, attr_identity, identity, ret_tru, tru}; #[attr_tru] fn f1() -> bool { diff --git a/src/test/run-pass-fulldeps/regions-mock-tcx.rs b/src/test/run-pass-fulldeps/regions-mock-tcx.rs index ed3cec465e..670f5380d8 100644 --- a/src/test/run-pass-fulldeps/regions-mock-tcx.rs +++ b/src/test/run-pass-fulldeps/regions-mock-tcx.rs @@ -15,10 +15,9 @@ // - Multiple lifetime parameters // - Arenas -#![feature(rustc_private, libc, collections)] +#![feature(rustc_private, libc)] extern crate arena; -extern crate collections; extern crate libc; use TypeStructure::{TypeInt, TypeFunction}; diff --git a/src/test/run-pass-fulldeps/stdio-from.rs b/src/test/run-pass-fulldeps/stdio-from.rs new file mode 100644 index 0000000000..f64bbf9312 --- /dev/null +++ b/src/test/run-pass-fulldeps/stdio-from.rs @@ -0,0 +1,83 @@ +// 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. + +// ignore-cross-compile + +#![feature(rustc_private)] + +extern crate rustc_back; + +use std::env; +use std::fs::File; +use std::io; +use std::io::{Read, Write}; +use std::process::{Command, Stdio}; + +use rustc_back::tempdir::TempDir; + +fn main() { + if env::args().len() > 1 { + child().unwrap() + } else { + parent().unwrap() + } +} + +fn parent() -> io::Result<()> { + let td = TempDir::new("foo").unwrap(); + let input = td.path().join("input"); + let output = td.path().join("output"); + + File::create(&input)?.write_all(b"foo\n")?; + + // Set up this chain: + // $ me file + // ... to duplicate each line 8 times total. + + let mut child1 = Command::new(env::current_exe()?) + .arg("first") + .stdin(File::open(&input)?) // tests File::into() + .stdout(Stdio::piped()) + .spawn()?; + + let mut child3 = Command::new(env::current_exe()?) + .arg("third") + .stdin(Stdio::piped()) + .stdout(File::create(&output)?) // tests File::into() + .spawn()?; + + // Started out of order so we can test both `ChildStdin` and `ChildStdout`. + let mut child2 = Command::new(env::current_exe()?) + .arg("second") + .stdin(child1.stdout.take().unwrap()) // tests ChildStdout::into() + .stdout(child3.stdin.take().unwrap()) // tests ChildStdin::into() + .spawn()?; + + assert!(child1.wait()?.success()); + assert!(child2.wait()?.success()); + assert!(child3.wait()?.success()); + + let mut data = String::new(); + File::open(&output)?.read_to_string(&mut data)?; + for line in data.lines() { + assert_eq!(line, "foo"); + } + assert_eq!(data.lines().count(), 8); + Ok(()) +} + +fn child() -> io::Result<()> { + // double everything + let mut input = vec![]; + io::stdin().read_to_end(&mut input)?; + io::stdout().write_all(&input)?; + io::stdout().write_all(&input)?; + Ok(()) +} diff --git a/src/test/run-make/no-duplicate-libs/foo.rs b/src/test/run-pass-valgrind/dst-dtor-3.rs similarity index 51% rename from src/test/run-make/no-duplicate-libs/foo.rs rename to src/test/run-pass-valgrind/dst-dtor-3.rs index cbdee35683..1ae66a28a8 100644 --- a/src/test/run-make/no-duplicate-libs/foo.rs +++ b/src/test/run-pass-valgrind/dst-dtor-3.rs @@ -8,18 +8,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(lang_items, libc, compiler_builtins_lib)] -#![no_std] -#![crate_type = "dylib"] +// no-prefer-dynamic -extern crate libc; -extern crate compiler_builtins; +#![feature(unsized_tuple_coercion)] -#[no_mangle] -pub extern fn foo() {} +static mut DROP_RAN: bool = false; -#[lang = "eh_personality"] fn eh_personality() {} -#[lang = "eh_unwind_resume"] fn eh_unwind_resume() {} -#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} } -#[no_mangle] pub extern fn rust_eh_register_frames () {} -#[no_mangle] pub extern fn rust_eh_unregister_frames () {} +struct Foo; +impl Drop for Foo { + fn drop(&mut self) { + unsafe { DROP_RAN = true; } + } +} + +trait Trait { fn dummy(&self) { } } +impl Trait for Foo {} + +pub fn main() { + { + let _x: Box<(i32, Trait)> = Box::<(i32, Foo)>::new((42, Foo)); + } + unsafe { + assert!(DROP_RAN); + } +} diff --git a/src/test/run-pass-valgrind/dst-dtor-4.rs b/src/test/run-pass-valgrind/dst-dtor-4.rs new file mode 100644 index 0000000000..e416f25bc0 --- /dev/null +++ b/src/test/run-pass-valgrind/dst-dtor-4.rs @@ -0,0 +1,31 @@ +// 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. + +// no-prefer-dynamic + +#![feature(unsized_tuple_coercion)] + +static mut DROP_RAN: isize = 0; + +struct Foo; +impl Drop for Foo { + fn drop(&mut self) { + unsafe { DROP_RAN += 1; } + } +} + +pub fn main() { + { + let _x: Box<(i32, [Foo])> = Box::<(i32, [Foo; 3])>::new((42, [Foo, Foo, Foo])); + } + unsafe { + assert_eq!(DROP_RAN, 3); + } +} diff --git a/src/test/run-pass/align-struct.rs b/src/test/run-pass/align-struct.rs index 0b9a359450..59d0539916 100644 --- a/src/test/run-pass/align-struct.rs +++ b/src/test/run-pass/align-struct.rs @@ -9,6 +9,7 @@ // except according to those terms. #![feature(attr_literals)] #![feature(repr_align)] +#![feature(box_syntax)] use std::mem; @@ -60,6 +61,13 @@ struct AlignContainsPacked { b: Packed, } +// The align limit was originally smaller (2^15). +// Check that it works with big numbers. +#[repr(align(0x10000))] +struct AlignLarge { + stuff: [u8; 0x10000], +} + impl Align16 { // return aligned type pub fn new(i: i32) -> Align16 { @@ -193,4 +201,15 @@ pub fn main() { assert_eq!(mem::align_of_val(&a.b), 1); assert_eq!(mem::size_of_val(&a), 16); assert!(is_aligned_to(&a, 16)); + + let mut large = box AlignLarge { + stuff: [0; 0x10000], + }; + large.stuff[0] = 132; + *large.stuff.last_mut().unwrap() = 102; + assert_eq!(large.stuff[0], 132); + assert_eq!(large.stuff.last(), Some(&102)); + assert_eq!(mem::align_of::(), 0x10000); + assert_eq!(mem::align_of_val(&*large), 0x10000); + assert!(is_aligned_to(&*large, 0x10000)); } diff --git a/src/test/run-pass/allocator-alloc-one.rs b/src/test/run-pass/allocator-alloc-one.rs new file mode 100644 index 0000000000..712fa2d600 --- /dev/null +++ b/src/test/run-pass/allocator-alloc-one.rs @@ -0,0 +1,24 @@ +// 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. + +#![feature(allocator_api, unique)] + +use std::heap::{Heap, Alloc}; + +fn main() { + unsafe { + let ptr = Heap.alloc_one::().unwrap_or_else(|e| { + Heap.oom(e) + }); + *ptr.as_ptr() = 4; + assert_eq!(*ptr.as_ptr(), 4); + Heap.dealloc_one(ptr); + } +} diff --git a/src/test/run-pass/allocator-override.rs b/src/test/run-pass/allocator-override.rs deleted file mode 100644 index ca2dbdf2b3..0000000000 --- a/src/test/run-pass/allocator-override.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// no-prefer-dynamic -// aux-build:allocator-dummy.rs -// ignore-emscripten - -#![feature(test)] - -extern crate allocator_dummy; -extern crate test; - -fn main() { - unsafe { - let before = allocator_dummy::HITS; - let mut b = Box::new(3); - test::black_box(&mut b); // Make sure the allocation is not optimized away - assert_eq!(allocator_dummy::HITS - before, 1); - drop(b); - assert_eq!(allocator_dummy::HITS - before, 2); - } -} diff --git a/src/test/run-pass/allocator/auxiliary/custom-as-global.rs b/src/test/run-pass/allocator/auxiliary/custom-as-global.rs new file mode 100644 index 0000000000..538f36faad --- /dev/null +++ b/src/test/run-pass/allocator/auxiliary/custom-as-global.rs @@ -0,0 +1,27 @@ +// 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. + +// no-prefer-dynamic + +#![feature(global_allocator)] +#![crate_type = "rlib"] + +extern crate custom; + +use std::sync::atomic::{ATOMIC_USIZE_INIT, Ordering}; + +use custom::A; + +#[global_allocator] +static ALLOCATOR: A = A(ATOMIC_USIZE_INIT); + +pub fn get() -> usize { + ALLOCATOR.0.load(Ordering::SeqCst) +} diff --git a/src/test/run-pass/allocator/auxiliary/custom.rs b/src/test/run-pass/allocator/auxiliary/custom.rs new file mode 100644 index 0000000000..8f4fbcd5ab --- /dev/null +++ b/src/test/run-pass/allocator/auxiliary/custom.rs @@ -0,0 +1,31 @@ +// 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. + +// no-prefer-dynamic + +#![feature(heap_api, allocator_api)] +#![crate_type = "rlib"] + +use std::heap::{Alloc, System, AllocErr, Layout}; +use std::sync::atomic::{AtomicUsize, Ordering}; + +pub struct A(pub AtomicUsize); + +unsafe impl<'a> Alloc for &'a A { + unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { + self.0.fetch_add(1, Ordering::SeqCst); + System.alloc(layout) + } + + unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) { + self.0.fetch_add(1, Ordering::SeqCst); + System.dealloc(ptr, layout) + } +} diff --git a/src/test/compile-fail/auxiliary/needs_allocator.rs b/src/test/run-pass/allocator/auxiliary/helper.rs similarity index 77% rename from src/test/compile-fail/auxiliary/needs_allocator.rs rename to src/test/run-pass/allocator/auxiliary/helper.rs index 5100316042..e75a432710 100644 --- a/src/test/compile-fail/auxiliary/needs_allocator.rs +++ b/src/test/run-pass/allocator/auxiliary/helper.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -10,7 +10,10 @@ // no-prefer-dynamic -#![feature(needs_allocator)] -#![no_std] -#![needs_allocator] #![crate_type = "rlib"] + +use std::fmt; + +pub fn work_with(p: &fmt::Debug) { + drop(p); +} diff --git a/src/test/run-pass/allocator/custom.rs b/src/test/run-pass/allocator/custom.rs new file mode 100644 index 0000000000..b46f024b5b --- /dev/null +++ b/src/test/run-pass/allocator/custom.rs @@ -0,0 +1,68 @@ +// 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. + +// aux-build:helper.rs +// no-prefer-dynamic + +#![feature(global_allocator, heap_api, allocator_api)] + +extern crate helper; + +use std::env; +use std::heap::{Heap, Alloc, System, Layout, AllocErr}; +use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; + +static HITS: AtomicUsize = ATOMIC_USIZE_INIT; + +struct A; + +unsafe impl<'a> Alloc for &'a A { + unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { + HITS.fetch_add(1, Ordering::SeqCst); + System.alloc(layout) + } + + unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) { + HITS.fetch_add(1, Ordering::SeqCst); + System.dealloc(ptr, layout) + } +} + +#[global_allocator] +static GLOBAL: A = A; + +fn main() { + env::set_var("FOO", "bar"); + drop(env::var("FOO")); + + let n = HITS.load(Ordering::SeqCst); + assert!(n > 0); + unsafe { + let layout = Layout::from_size_align(4, 2).unwrap(); + + let ptr = Heap.alloc(layout.clone()).unwrap(); + helper::work_with(&ptr); + assert_eq!(HITS.load(Ordering::SeqCst), n + 1); + Heap.dealloc(ptr, layout.clone()); + assert_eq!(HITS.load(Ordering::SeqCst), n + 2); + + let s = String::with_capacity(10); + helper::work_with(&s); + assert_eq!(HITS.load(Ordering::SeqCst), n + 3); + drop(s); + assert_eq!(HITS.load(Ordering::SeqCst), n + 4); + + let ptr = System.alloc(layout.clone()).unwrap(); + assert_eq!(HITS.load(Ordering::SeqCst), n + 4); + helper::work_with(&ptr); + System.dealloc(ptr, layout); + assert_eq!(HITS.load(Ordering::SeqCst), n + 4); + } +} diff --git a/src/test/run-pass/allocator/xcrate-use.rs b/src/test/run-pass/allocator/xcrate-use.rs new file mode 100644 index 0000000000..4b987b9223 --- /dev/null +++ b/src/test/run-pass/allocator/xcrate-use.rs @@ -0,0 +1,44 @@ +// 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. + +// aux-build:custom.rs +// aux-build:helper.rs +// no-prefer-dynamic + +#![feature(global_allocator, heap_api, allocator_api)] + +extern crate custom; +extern crate helper; + +use std::env; +use std::heap::{Heap, Alloc, System, Layout}; +use std::sync::atomic::{Ordering, ATOMIC_USIZE_INIT}; + +#[global_allocator] +static GLOBAL: custom::A = custom::A(ATOMIC_USIZE_INIT); + +fn main() { + unsafe { + let n = GLOBAL.0.load(Ordering::SeqCst); + let layout = Layout::from_size_align(4, 2).unwrap(); + + let ptr = Heap.alloc(layout.clone()).unwrap(); + helper::work_with(&ptr); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1); + Heap.dealloc(ptr, layout.clone()); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2); + + let ptr = System.alloc(layout.clone()).unwrap(); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2); + helper::work_with(&ptr); + System.dealloc(ptr, layout); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2); + } +} diff --git a/src/test/run-pass/allocator/xcrate-use2.rs b/src/test/run-pass/allocator/xcrate-use2.rs new file mode 100644 index 0000000000..7e6cd9fdf4 --- /dev/null +++ b/src/test/run-pass/allocator/xcrate-use2.rs @@ -0,0 +1,57 @@ +// 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. + +// aux-build:custom.rs +// aux-build:custom-as-global.rs +// aux-build:helper.rs +// no-prefer-dynamic + +#![feature(heap_api, allocator_api)] + +extern crate custom; +extern crate custom_as_global; +extern crate helper; + +use std::env; +use std::heap::{Heap, Alloc, System, Layout}; +use std::sync::atomic::{Ordering, ATOMIC_USIZE_INIT}; + +static GLOBAL: custom::A = custom::A(ATOMIC_USIZE_INIT); + +fn main() { + unsafe { + let n = custom_as_global::get(); + let layout = Layout::from_size_align(4, 2).unwrap(); + + // Global allocator routes to the `custom_as_global` global + let ptr = Heap.alloc(layout.clone()).unwrap(); + helper::work_with(&ptr); + assert_eq!(custom_as_global::get(), n + 1); + Heap.dealloc(ptr, layout.clone()); + assert_eq!(custom_as_global::get(), n + 2); + + // Usage of the system allocator avoids all globals + let ptr = System.alloc(layout.clone()).unwrap(); + helper::work_with(&ptr); + assert_eq!(custom_as_global::get(), n + 2); + System.dealloc(ptr, layout.clone()); + assert_eq!(custom_as_global::get(), n + 2); + + // Usage of our personal allocator doesn't affect other instances + let ptr = (&GLOBAL).alloc(layout.clone()).unwrap(); + helper::work_with(&ptr); + assert_eq!(custom_as_global::get(), n + 2); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), 1); + (&GLOBAL).dealloc(ptr, layout); + assert_eq!(custom_as_global::get(), n + 2); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), 2); + } +} + diff --git a/src/test/run-pass/asm-concat-src.rs b/src/test/run-pass/asm-concat-src.rs index ea3d0c3aa0..fb257bf7b5 100644 --- a/src/test/run-pass/asm-concat-src.rs +++ b/src/test/run-pass/asm-concat-src.rs @@ -9,7 +9,7 @@ // except according to those terms. // pretty-expanded FIXME #23616 -// ignore-asmjs +// ignore-emscripten #![feature(asm)] diff --git a/src/test/run-pass/associated-const-const-eval.rs b/src/test/run-pass/associated-const-const-eval.rs index 0b230df414..9c36a42527 100644 --- a/src/test/run-pass/associated-const-const-eval.rs +++ b/src/test/run-pass/associated-const-const-eval.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] trait Foo { const NUM: usize; diff --git a/src/test/run-pass/associated-const-cross-crate-const-eval.rs b/src/test/run-pass/associated-const-cross-crate-const-eval.rs index 7d31bb5b1a..c2758b1aed 100644 --- a/src/test/run-pass/associated-const-cross-crate-const-eval.rs +++ b/src/test/run-pass/associated-const-cross-crate-const-eval.rs @@ -10,7 +10,6 @@ // aux-build:associated-const-cc-lib.rs -#![feature(associated_consts)] extern crate associated_const_cc_lib as foolib; diff --git a/src/test/run-pass/associated-const-cross-crate-defaults.rs b/src/test/run-pass/associated-const-cross-crate-defaults.rs index 92d2aae61c..084c448ba2 100644 --- a/src/test/run-pass/associated-const-cross-crate-defaults.rs +++ b/src/test/run-pass/associated-const-cross-crate-defaults.rs @@ -10,7 +10,6 @@ // aux-build:associated-const-cc-lib.rs -#![feature(associated_consts)] extern crate associated_const_cc_lib as foolib; diff --git a/src/test/run-pass/associated-const-cross-crate.rs b/src/test/run-pass/associated-const-cross-crate.rs index 73d5dc5df9..a882d6ae23 100644 --- a/src/test/run-pass/associated-const-cross-crate.rs +++ b/src/test/run-pass/associated-const-cross-crate.rs @@ -10,7 +10,6 @@ // aux-build:associated-const-cc-lib.rs -#![feature(associated_consts)] extern crate associated_const_cc_lib as foolib; diff --git a/src/test/run-pass/associated-const-in-global-const.rs b/src/test/run-pass/associated-const-in-global-const.rs index e3a1e29d20..b7fb4d7325 100644 --- a/src/test/run-pass/associated-const-in-global-const.rs +++ b/src/test/run-pass/associated-const-in-global-const.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] struct Foo; diff --git a/src/test/run-pass/associated-const-inherent-impl.rs b/src/test/run-pass/associated-const-inherent-impl.rs index 5c9abf982b..86454a4a09 100644 --- a/src/test/run-pass/associated-const-inherent-impl.rs +++ b/src/test/run-pass/associated-const-inherent-impl.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] struct Foo; diff --git a/src/test/run-pass/associated-const-marks-live-code.rs b/src/test/run-pass/associated-const-marks-live-code.rs index ea91a95312..bfeb78ddfe 100644 --- a/src/test/run-pass/associated-const-marks-live-code.rs +++ b/src/test/run-pass/associated-const-marks-live-code.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] #![deny(dead_code)] diff --git a/src/test/run-pass/associated-const-match-patterns.rs b/src/test/run-pass/associated-const-match-patterns.rs index 01d1b27bfc..54603e6e0d 100644 --- a/src/test/run-pass/associated-const-match-patterns.rs +++ b/src/test/run-pass/associated-const-match-patterns.rs @@ -10,7 +10,6 @@ // aux-build:empty-struct.rs -#![feature(associated_consts)] extern crate empty_struct; use empty_struct::XEmpty2 as XFoo; diff --git a/src/test/run-pass/associated-const-outer-ty-refs.rs b/src/test/run-pass/associated-const-outer-ty-refs.rs index 2e6fb11a12..987c64dbff 100644 --- a/src/test/run-pass/associated-const-outer-ty-refs.rs +++ b/src/test/run-pass/associated-const-outer-ty-refs.rs @@ -7,7 +7,6 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] trait Lattice { const BOTTOM: Self; diff --git a/src/test/run-pass/associated-const-overwrite-default.rs b/src/test/run-pass/associated-const-overwrite-default.rs index 0846ad9a57..bb594cfa0f 100644 --- a/src/test/run-pass/associated-const-overwrite-default.rs +++ b/src/test/run-pass/associated-const-overwrite-default.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] trait Foo { const ID: i32 = 2; diff --git a/src/test/run-pass/associated-const-public-impl.rs b/src/test/run-pass/associated-const-public-impl.rs index b1d071799e..5ff363844a 100644 --- a/src/test/run-pass/associated-const-public-impl.rs +++ b/src/test/run-pass/associated-const-public-impl.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] mod bar1 { pub use self::bar2::Foo; diff --git a/src/test/run-pass/associated-const-range-match-patterns.rs b/src/test/run-pass/associated-const-range-match-patterns.rs index d38ccca689..d72e1efc4d 100644 --- a/src/test/run-pass/associated-const-range-match-patterns.rs +++ b/src/test/run-pass/associated-const-range-match-patterns.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] struct Foo; diff --git a/src/test/run-pass/associated-const-resolution-order.rs b/src/test/run-pass/associated-const-resolution-order.rs index 98b7164ab7..5fa49b4820 100644 --- a/src/test/run-pass/associated-const-resolution-order.rs +++ b/src/test/run-pass/associated-const-resolution-order.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] struct MyType; diff --git a/src/test/run-pass/associated-const-self-type.rs b/src/test/run-pass/associated-const-self-type.rs index d3add976b5..16ccb5b395 100644 --- a/src/test/run-pass/associated-const-self-type.rs +++ b/src/test/run-pass/associated-const-self-type.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] trait MyInt { const ONE: Self; diff --git a/src/test/run-pass/associated-const-type-parameters.rs b/src/test/run-pass/associated-const-type-parameters.rs index df20835306..7859a87e01 100644 --- a/src/test/run-pass/associated-const-type-parameters.rs +++ b/src/test/run-pass/associated-const-type-parameters.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] trait Foo { const X: i32; diff --git a/src/test/run-pass/associated-const-ufcs-infer-trait.rs b/src/test/run-pass/associated-const-ufcs-infer-trait.rs index aa3e14a939..b226306782 100644 --- a/src/test/run-pass/associated-const-ufcs-infer-trait.rs +++ b/src/test/run-pass/associated-const-ufcs-infer-trait.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] trait Foo { const ID: i32; diff --git a/src/test/run-pass/associated-const-use-default.rs b/src/test/run-pass/associated-const-use-default.rs index 5813d86742..5ed9a6dea3 100644 --- a/src/test/run-pass/associated-const-use-default.rs +++ b/src/test/run-pass/associated-const-use-default.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] trait Foo { const ID: i32 = 1; diff --git a/src/test/run-pass/associated-const-use-impl-of-same-trait.rs b/src/test/run-pass/associated-const-use-impl-of-same-trait.rs index 62658470ba..986f160f3c 100644 --- a/src/test/run-pass/associated-const-use-impl-of-same-trait.rs +++ b/src/test/run-pass/associated-const-use-impl-of-same-trait.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] // The main purpose of this test is to ensure that different impls of the same // trait can refer to each other without setting off the static recursion check diff --git a/src/test/run-pass/associated-const.rs b/src/test/run-pass/associated-const.rs index d906544500..3c84f4a833 100644 --- a/src/test/run-pass/associated-const.rs +++ b/src/test/run-pass/associated-const.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] trait Foo { const ID: i32; diff --git a/src/test/run-pass/associated-types-projection-in-object-type.rs b/src/test/run-pass/associated-types-projection-in-object-type.rs index 3b146792fd..14e94dbff6 100644 --- a/src/test/run-pass/associated-types-projection-in-object-type.rs +++ b/src/test/run-pass/associated-types-projection-in-object-type.rs @@ -26,7 +26,7 @@ pub trait Subscriber { pub trait Publisher<'a> { type Output; - fn subscribe(&mut self, Box + 'a>); + fn subscribe(&mut self, _: Box + 'a>); } pub trait Processor<'a> : Subscriber + Publisher<'a> { } diff --git a/src/test/run-pass/associated-types-sugar-path.rs b/src/test/run-pass/associated-types-sugar-path.rs index 587fb3f80d..d8d42f2cba 100644 --- a/src/test/run-pass/associated-types-sugar-path.rs +++ b/src/test/run-pass/associated-types-sugar-path.rs @@ -15,8 +15,6 @@ use std::ops::Deref; pub trait Foo { type A; fn boo(&self) -> Self::A; - - fn baz(_: Self::Target) where Self: Deref {} } impl Foo for isize { diff --git a/src/test/run-pass/auxiliary/allocator-dummy.rs b/src/test/run-pass/auxiliary/allocator-dummy.rs index 1133ace275..f4a32a93df 100644 --- a/src/test/run-pass/auxiliary/allocator-dummy.rs +++ b/src/test/run-pass/auxiliary/allocator-dummy.rs @@ -10,33 +10,42 @@ // no-prefer-dynamic -#![feature(allocator, core_intrinsics, libc)] +#![feature(allocator, core_intrinsics, panic_unwind)] #![allocator] #![crate_type = "rlib"] #![no_std] -extern crate libc; +extern crate unwind; pub static mut HITS: usize = 0; +type size_t = usize; + +extern { + fn malloc(size: usize) -> *mut u8; + fn free(ptr: *mut u8); + fn calloc(size: usize, amt: usize) -> *mut u8; + fn realloc(ptr: *mut u8, size: usize) -> *mut u8; +} + #[no_mangle] pub extern fn __rust_allocate(size: usize, align: usize) -> *mut u8 { unsafe { HITS += 1; - libc::malloc(size as libc::size_t) as *mut u8 + malloc(size as size_t) as *mut u8 } } #[no_mangle] pub extern fn __rust_allocate_zeroed(size: usize, _align: usize) -> *mut u8 { - unsafe { libc::calloc(size as libc::size_t, 1) as *mut u8 } + unsafe { calloc(size as size_t, 1) as *mut u8 } } #[no_mangle] pub extern fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) { unsafe { HITS += 1; - libc::free(ptr as *mut _) + free(ptr as *mut _) } } @@ -44,7 +53,7 @@ pub extern fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) { pub extern fn __rust_reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 { unsafe { - libc::realloc(ptr as *mut _, size as libc::size_t) as *mut u8 + realloc(ptr as *mut _, size as size_t) as *mut u8 } } diff --git a/src/test/run-pass/auxiliary/associated-const-cc-lib.rs b/src/test/run-pass/auxiliary/associated-const-cc-lib.rs index 1fd8fee011..e4cada40db 100644 --- a/src/test/run-pass/auxiliary/associated-const-cc-lib.rs +++ b/src/test/run-pass/auxiliary/associated-const-cc-lib.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] #![crate_type="lib"] diff --git a/src/test/run-pass/auxiliary/issue_3979_traits.rs b/src/test/run-pass/auxiliary/issue_3979_traits.rs index 5c306be69c..46035731c3 100644 --- a/src/test/run-pass/auxiliary/issue_3979_traits.rs +++ b/src/test/run-pass/auxiliary/issue_3979_traits.rs @@ -13,7 +13,7 @@ #![crate_type = "lib"] pub trait Positioned { - fn SetX(&mut self, isize); + fn SetX(&mut self, _: isize); fn X(&self) -> isize; } diff --git a/src/test/run-pass/auxiliary/xcrate-trait-lifetime-param.rs b/src/test/run-pass/auxiliary/xcrate-trait-lifetime-param.rs index e8e5cc53aa..66c0300e26 100644 --- a/src/test/run-pass/auxiliary/xcrate-trait-lifetime-param.rs +++ b/src/test/run-pass/auxiliary/xcrate-trait-lifetime-param.rs @@ -9,5 +9,5 @@ // except according to those terms. pub trait FromBuf<'a> { - fn from_buf(&'a [u8]) -> Self; + fn from_buf(_: &'a [u8]) -> Self; } diff --git a/src/test/run-pass/conditional-compile-arch.rs b/src/test/run-pass/conditional-compile-arch.rs index 24c461d5f5..6e3e4be0d8 100644 --- a/src/test/run-pass/conditional-compile-arch.rs +++ b/src/test/run-pass/conditional-compile-arch.rs @@ -36,3 +36,6 @@ pub fn main() { } #[cfg(target_arch = "asmjs")] pub fn main() { } + +#[cfg(target_arch = "wasm32")] +pub fn main() { } diff --git a/src/test/run-pass/deriving-hash.rs b/src/test/run-pass/deriving-hash.rs index 91bfc2f920..18b2fbe015 100644 --- a/src/test/run-pass/deriving-hash.rs +++ b/src/test/run-pass/deriving-hash.rs @@ -45,8 +45,8 @@ impl<'a> Hasher for FakeHasher<'a> { } } -fn fake_hash(v: &mut Vec, e: E) { - e.hash(&mut FakeHasher(v)); +fn fake_hash(v: &mut Vec, a: A) { + a.hash(&mut FakeHasher(v)); } fn main() { @@ -69,4 +69,13 @@ fn main() { fake_hash(&mut va, E::A); fake_hash(&mut vb, E::B); assert!(va != vb); + + // issue #39137: single variant enum hash should not hash discriminant + #[derive(Hash)] + enum SingleVariantEnum { + A(u8), + } + let mut v = vec![]; + fake_hash(&mut v, SingleVariantEnum::A(17)); + assert_eq!(vec![17], v); } diff --git a/src/test/run-pass/drop-with-type-ascription-2.rs b/src/test/run-pass/drop-with-type-ascription-2.rs index 53005ea529..1f486c1834 100644 --- a/src/test/run-pass/drop-with-type-ascription-2.rs +++ b/src/test/run-pass/drop-with-type-ascription-2.rs @@ -9,8 +9,6 @@ // except according to those terms. -#![feature(collections)] - fn main() { let args = vec!["foobie", "asdf::asdf"]; let arr: Vec<&str> = args[1].split("::").collect(); diff --git a/src/test/run-pass/dropck_legal_cycles.rs b/src/test/run-pass/dropck_legal_cycles.rs index 2f8ecbe693..b6e640ab5b 100644 --- a/src/test/run-pass/dropck_legal_cycles.rs +++ b/src/test/run-pass/dropck_legal_cycles.rs @@ -442,7 +442,7 @@ pub fn main() { } trait Named { - fn new(&'static str) -> Self; + fn new(_: &'static str) -> Self; fn name(&self) -> &str; } @@ -932,9 +932,9 @@ trait Context { } trait PrePost { - fn pre(&mut self, &T); - fn post(&mut self, &T); - fn hit_limit(&mut self, &T); + fn pre(&mut self, _: &T); + fn post(&mut self, _: &T); + fn hit_limit(&mut self, _: &T); } trait Children<'a> { diff --git a/src/test/run-pass/dst-irrefutable-bind.rs b/src/test/run-pass/dst-irrefutable-bind.rs index 9f8067f372..b1d6c732e7 100644 --- a/src/test/run-pass/dst-irrefutable-bind.rs +++ b/src/test/run-pass/dst-irrefutable-bind.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(unsized_tuple_coercion)] + struct Test(T); fn main() { @@ -21,4 +23,14 @@ fn main() { let slice = &[1,2,3]; let x = Test(&slice); let Test(&_slice) = x; + + + let x = (10, [1,2,3]); + let x : &(i32, [i32]) = &x; + + let & ref _y = x; + + let slice = &[1,2,3]; + let x = (10, &slice); + let (_, &_slice) = x; } diff --git a/src/test/run-pass/dst-raw.rs b/src/test/run-pass/dst-raw.rs index 3a74626b02..9ebfbee8a3 100644 --- a/src/test/run-pass/dst-raw.rs +++ b/src/test/run-pass/dst-raw.rs @@ -11,6 +11,8 @@ // Test DST raw pointers +#![feature(unsized_tuple_coercion)] + trait Trait { fn foo(&self) -> isize; } @@ -45,6 +47,14 @@ pub fn main() { }; assert_eq!(r, 42); + // raw DST tuple + let p = (A { f: 42 },); + let o: *const (Trait,) = &p; + let r = unsafe { + (&*o).0.foo() + }; + assert_eq!(r, 42); + // raw slice let a: *const [_] = &[1, 2, 3]; unsafe { @@ -72,6 +82,15 @@ pub fn main() { assert_eq!(len, 3); } + // raw DST tuple with slice + let c: *const ([_],) = &([1, 2, 3],); + unsafe { + let b = (&*c).0[0]; + assert_eq!(b, 1); + let len = (&*c).0.len(); + assert_eq!(len, 3); + } + // all of the above with *mut let mut x = A { f: 42 }; let z: *mut Trait = &mut x; @@ -87,6 +106,13 @@ pub fn main() { }; assert_eq!(r, 42); + let mut p = (A { f: 42 },); + let o: *mut (Trait,) = &mut p; + let r = unsafe { + (&*o).0.foo() + }; + assert_eq!(r, 42); + let a: *mut [_] = &mut [1, 2, 3]; unsafe { let b = (*a)[2]; @@ -110,4 +136,12 @@ pub fn main() { let len = (&*c).f.len(); assert_eq!(len, 3); } + + let c: *mut ([_],) = &mut ([1, 2, 3],); + unsafe { + let b = (&*c).0[0]; + assert_eq!(b, 1); + let len = (&*c).0.len(); + assert_eq!(len, 3); + } } diff --git a/src/test/run-pass/dst-trait-tuple.rs b/src/test/run-pass/dst-trait-tuple.rs new file mode 100644 index 0000000000..9803e26f5f --- /dev/null +++ b/src/test/run-pass/dst-trait-tuple.rs @@ -0,0 +1,111 @@ +// 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. + + +#![allow(unused_features)] +#![feature(box_syntax)] +#![feature(unsized_tuple_coercion)] + +type Fat = (isize, &'static str, T); + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +#[derive(Copy, Clone, PartialEq, Eq)] +struct Bar1 { + f: isize +} + +trait ToBar { + fn to_bar(&self) -> Bar; + fn to_val(&self) -> isize; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } + fn to_val(&self) -> isize { + 0 + } +} +impl ToBar for Bar1 { + fn to_bar(&self) -> Bar { + Bar + } + fn to_val(&self) -> isize { + self.f + } +} + +// x is a fat pointer +fn foo(x: &Fat) { + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); + assert_eq!(x.2.to_bar(), Bar); + assert_eq!(x.2.to_val(), 42); + + let y = &x.2; + assert_eq!(y.to_bar(), Bar); + assert_eq!(y.to_val(), 42); +} + +fn bar(x: &ToBar) { + assert_eq!(x.to_bar(), Bar); + assert_eq!(x.to_val(), 42); +} + +fn baz(x: &Fat>) { + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); + assert_eq!((x.2).0, 8); + assert_eq!((x.2).1, "deep str"); + assert_eq!((x.2).2.to_bar(), Bar); + assert_eq!((x.2).2.to_val(), 42); + + let y = &(x.2).2; + assert_eq!(y.to_bar(), Bar); + assert_eq!(y.to_val(), 42); + +} + +pub fn main() { + let f1 = (5, "some str", Bar1 {f :42}); + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat = f2; + foo(f3); + let f4: &Fat = &f1; + foo(f4); + let f5: &Fat = &(5, "some str", Bar1 {f :42}); + foo(f5); + + // Zero size object. + let f6: &Fat = &(5, "some str", Bar); + assert_eq!(f6.2.to_bar(), Bar); + + // &* + // + let f7: Box = Box::new(Bar1 {f :42}); + bar(&*f7); + + // Deep nesting + let f1 = (5, "some str", (8, "deep str", Bar1 {f :42})); + baz(&f1); + let f2 = &f1; + baz(f2); + let f3: &Fat> = f2; + baz(f3); + let f4: &Fat> = &f1; + baz(f4); + let f5: &Fat> = &(5, "some str", (8, "deep str", Bar1 {f :42})); + baz(f5); +} diff --git a/src/test/run-pass/dst-tuple-sole.rs b/src/test/run-pass/dst-tuple-sole.rs new file mode 100644 index 0000000000..a788e25218 --- /dev/null +++ b/src/test/run-pass/dst-tuple-sole.rs @@ -0,0 +1,85 @@ +// 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. + +// As dst-tuple.rs, but the unsized field is the only field in the tuple. + + +#![feature(unsized_tuple_coercion)] + +type Fat = (T,); + +// x is a fat pointer +fn foo(x: &Fat<[isize]>) { + let y = &x.0; + assert_eq!(x.0.len(), 3); + assert_eq!(y[0], 1); + assert_eq!(x.0[1], 2); +} + +fn foo2(x: &Fat<[T]>) { + let y = &x.0; + let bar = Bar; + assert_eq!(x.0.len(), 3); + assert_eq!(y[0].to_bar(), bar); + assert_eq!(x.0[1].to_bar(), bar); +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +trait ToBar { + fn to_bar(&self) -> Bar; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } +} + +pub fn main() { + // With a vec of ints. + let f1 = ([1, 2, 3],); + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat<[isize]> = f2; + foo(f3); + let f4: &Fat<[isize]> = &f1; + foo(f4); + let f5: &Fat<[isize]> = &([1, 2, 3],); + foo(f5); + + // With a vec of Bars. + let bar = Bar; + let f1 = ([bar, bar, bar],); + foo2(&f1); + let f2 = &f1; + foo2(f2); + let f3: &Fat<[Bar]> = f2; + foo2(f3); + let f4: &Fat<[Bar]> = &f1; + foo2(f4); + let f5: &Fat<[Bar]> = &([bar, bar, bar],); + foo2(f5); + + // Assignment. + let f5: &mut Fat<[isize]> = &mut ([1, 2, 3],); + f5.0[1] = 34; + assert_eq!(f5.0[0], 1); + assert_eq!(f5.0[1], 34); + assert_eq!(f5.0[2], 3); + + // Zero size vec. + let f5: &Fat<[isize]> = &([],); + assert!(f5.0.is_empty()); + let f5: &Fat<[Bar]> = &([],); + assert!(f5.0.is_empty()); +} diff --git a/src/test/run-pass/dst-tuple.rs b/src/test/run-pass/dst-tuple.rs new file mode 100644 index 0000000000..2f5b28495b --- /dev/null +++ b/src/test/run-pass/dst-tuple.rs @@ -0,0 +1,129 @@ +// 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. + + +#![allow(unknown_features)] +#![feature(box_syntax)] +#![feature(unsized_tuple_coercion)] + +type Fat = (isize, &'static str, T); + +// x is a fat pointer +fn foo(x: &Fat<[isize]>) { + let y = &x.2; + assert_eq!(x.2.len(), 3); + assert_eq!(y[0], 1); + assert_eq!(x.2[1], 2); + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); +} + +fn foo2(x: &Fat<[T]>) { + let y = &x.2; + let bar = Bar; + assert_eq!(x.2.len(), 3); + assert_eq!(y[0].to_bar(), bar); + assert_eq!(x.2[1].to_bar(), bar); + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); +} + +fn foo3(x: &Fat>) { + let y = &(x.2).2; + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); + assert_eq!((x.2).0, 8); + assert_eq!((x.2).1, "deep str"); + assert_eq!((x.2).2.len(), 3); + assert_eq!(y[0], 1); + assert_eq!((x.2).2[1], 2); +} + + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +trait ToBar { + fn to_bar(&self) -> Bar; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } +} + +pub fn main() { + // With a vec of ints. + let f1 = (5, "some str", [1, 2, 3]); + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat<[isize]> = f2; + foo(f3); + let f4: &Fat<[isize]> = &f1; + foo(f4); + let f5: &Fat<[isize]> = &(5, "some str", [1, 2, 3]); + foo(f5); + + // With a vec of Bars. + let bar = Bar; + let f1 = (5, "some str", [bar, bar, bar]); + foo2(&f1); + let f2 = &f1; + foo2(f2); + let f3: &Fat<[Bar]> = f2; + foo2(f3); + let f4: &Fat<[Bar]> = &f1; + foo2(f4); + let f5: &Fat<[Bar]> = &(5, "some str", [bar, bar, bar]); + foo2(f5); + + // Assignment. + let f5: &mut Fat<[isize]> = &mut (5, "some str", [1, 2, 3]); + f5.2[1] = 34; + assert_eq!(f5.2[0], 1); + assert_eq!(f5.2[1], 34); + assert_eq!(f5.2[2], 3); + + // Zero size vec. + let f5: &Fat<[isize]> = &(5, "some str", []); + assert!(f5.2.is_empty()); + let f5: &Fat<[Bar]> = &(5, "some str", []); + assert!(f5.2.is_empty()); + + // Deeply nested. + let f1 = (5, "some str", (8, "deep str", [1, 2, 3])); + foo3(&f1); + let f2 = &f1; + foo3(f2); + let f3: &Fat> = f2; + foo3(f3); + let f4: &Fat> = &f1; + foo3(f4); + let f5: &Fat> = &(5, "some str", (8, "deep str", [1, 2, 3])); + foo3(f5); + + // Box. + let f1 = Box::new([1, 2, 3]); + assert_eq!((*f1)[1], 2); + let f2: Box<[isize]> = f1; + assert_eq!((*f2)[1], 2); + + // Nested Box. + let f1 : Box> = box (5, "some str", [1, 2, 3]); + foo(&*f1); + let f2 : Box> = f1; + foo(&*f2); + + let f3 : Box> = + Box::>::new((5, "some str", [1, 2, 3])); + foo(&*f3); +} diff --git a/src/test/run-pass/dynamic-drop.rs b/src/test/run-pass/dynamic-drop.rs index 6725a0c547..bdcd3eecc6 100644 --- a/src/test/run-pass/dynamic-drop.rs +++ b/src/test/run-pass/dynamic-drop.rs @@ -106,6 +106,18 @@ fn struct_dynamic_drop(a: &Allocator, c0: bool, c1: bool, c: bool) { } } +fn field_assignment(a: &Allocator, c0: bool) { + let mut x = (TwoPtrs(a.alloc(), a.alloc()), a.alloc()); + + x.1 = a.alloc(); + x.1 = a.alloc(); + + let f = (x.0).0; + if c0 { + (x.0).0 = f; + } +} + fn assignment2(a: &Allocator, c0: bool, c1: bool) { let mut _v = a.alloc(); let mut _w = a.alloc(); @@ -207,5 +219,8 @@ fn main() { run_test(|a| struct_dynamic_drop(a, true, true, false)); run_test(|a| struct_dynamic_drop(a, true, true, true)); + run_test(|a| field_assignment(a, false)); + run_test(|a| field_assignment(a, true)); + run_test_nopanic(|a| union1(a)); } diff --git a/src/test/run-pass/env.rs b/src/test/run-pass/env.rs new file mode 100644 index 0000000000..e602fb2d7d --- /dev/null +++ b/src/test/run-pass/env.rs @@ -0,0 +1,98 @@ +// 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. + +// compile-flags: --test + +#![feature(rand, std_panic)] + +use std::env::*; +use std::__rand as rand; +use std::__rand::Rng; +use std::iter::repeat; +use std::ffi::{OsString, OsStr}; + + +fn make_rand_name() -> OsString { + let mut rng = rand::thread_rng(); + let n = format!("TEST{}", rng.gen_ascii_chars().take(10) + .collect::()); + let n = OsString::from(n); + assert!(var_os(&n).is_none()); + n +} + +fn eq(a: Option, b: Option<&str>) { + assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s)); +} + +#[test] +fn test_set_var() { + let n = make_rand_name(); + set_var(&n, "VALUE"); + eq(var_os(&n), Some("VALUE")); +} + +#[test] +fn test_remove_var() { + let n = make_rand_name(); + set_var(&n, "VALUE"); + remove_var(&n); + eq(var_os(&n), None); +} + +#[test] +fn test_set_var_overwrite() { + let n = make_rand_name(); + set_var(&n, "1"); + set_var(&n, "2"); + eq(var_os(&n), Some("2")); + set_var(&n, ""); + eq(var_os(&n), Some("")); +} + +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +fn test_var_big() { + let mut s = "".to_string(); + let mut i = 0; + while i < 100 { + s.push_str("aaaaaaaaaa"); + i += 1; + } + let n = make_rand_name(); + set_var(&n, &s); + eq(var_os(&n), Some(&s)); +} + +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +fn test_env_set_get_huge() { + let n = make_rand_name(); + let s = repeat("x").take(10000).collect::(); + set_var(&n, &s); + eq(var_os(&n), Some(&s)); + remove_var(&n); + eq(var_os(&n), None); +} + +#[test] +fn test_env_set_var() { + let n = make_rand_name(); + + let mut e = vars_os(); + set_var(&n, "VALUE"); + assert!(!e.any(|(k, v)| { + &*k == &*n && &*v == "VALUE" + })); + + assert!(vars_os().any(|(k, v)| { + &*k == &*n && &*v == "VALUE" + })); +} diff --git a/src/test/run-pass/for-loop-no-std.rs b/src/test/run-pass/for-loop-no-std.rs index 73de1fa9c0..856857156c 100644 --- a/src/test/run-pass/for-loop-no-std.rs +++ b/src/test/run-pass/for-loop-no-std.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(lang_items, start, collections)] +#![feature(lang_items, start, alloc)] #![no_std] extern crate std as other; -#[macro_use] extern crate collections; +#[macro_use] extern crate alloc; #[start] fn start(_argc: isize, _argv: *const *const u8) -> isize { diff --git a/src/test/run-pass/foreach-external-iterators-hashmap-break-restart.rs b/src/test/run-pass/foreach-external-iterators-hashmap-break-restart.rs index cedb960143..232af7eca4 100644 --- a/src/test/run-pass/foreach-external-iterators-hashmap-break-restart.rs +++ b/src/test/run-pass/foreach-external-iterators-hashmap-break-restart.rs @@ -9,10 +9,6 @@ // except according to those terms. -#![feature(collections)] - -extern crate collections; - use std::collections::HashMap; // This is a fancy one: it uses an external iterator established diff --git a/src/test/run-pass/foreach-external-iterators-hashmap.rs b/src/test/run-pass/foreach-external-iterators-hashmap.rs index 79304fce5c..2ef420187d 100644 --- a/src/test/run-pass/foreach-external-iterators-hashmap.rs +++ b/src/test/run-pass/foreach-external-iterators-hashmap.rs @@ -9,10 +9,6 @@ // except according to those terms. -#![feature(collections)] - -extern crate collections; - use std::collections::HashMap; pub fn main() { diff --git a/src/test/run-pass/format-no-std.rs b/src/test/run-pass/format-no-std.rs index 1b9b4ab32c..9e8a321851 100644 --- a/src/test/run-pass/format-no-std.rs +++ b/src/test/run-pass/format-no-std.rs @@ -10,14 +10,14 @@ // ignore-emscripten missing rust_begin_unwind -#![feature(lang_items, start, collections)] +#![feature(lang_items, start, alloc)] #![no_std] extern crate std as other; -#[macro_use] extern crate collections; +#[macro_use] extern crate alloc; -use collections::string::ToString; +use alloc::string::ToString; #[start] fn start(_argc: isize, _argv: *const *const u8) -> isize { diff --git a/src/test/run-pass/getopts_ref.rs b/src/test/run-pass/getopts_ref.rs deleted file mode 100644 index 90726c21fa..0000000000 --- a/src/test/run-pass/getopts_ref.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012-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. - - -#![feature(rustc_private)] - -extern crate getopts; - -use getopts::{optopt, getopts}; - -pub fn main() { - let args = Vec::new(); - let opts = vec![optopt("b", "", "something", "SMTHNG")]; - - match getopts(&args, &opts) { - Ok(ref m) => - assert!(!m.opt_present("b")), - Err(ref f) => panic!("{}", *f) - }; - -} diff --git a/src/test/run-pass/i128-ffi.rs b/src/test/run-pass/i128-ffi.rs index d07fb7b4a7..d989210dd7 100644 --- a/src/test/run-pass/i128-ffi.rs +++ b/src/test/run-pass/i128-ffi.rs @@ -13,12 +13,7 @@ // should look like. // ignore-windows - -// Ignore 32 bit targets: -// ignore-x86 -// ignore-arm - -// ignore-emscripten +// ignore-32bit #![feature(i128_type)] diff --git a/src/test/run-pass/i128.rs b/src/test/run-pass/i128.rs index c5057f70c0..7c14d34b0e 100644 --- a/src/test/run-pass/i128.rs +++ b/src/test/run-pass/i128.rs @@ -109,4 +109,8 @@ fn main() { assert_eq!(b(-87559967289969187895646876466835277875_i128) / b(84285771033834995895337664386045050880_i128), -1i128); + + // iter-arithmetic traits + assert_eq!(10i128, [1i128, 2, 3, 4].iter().sum()); + assert_eq!(24i128, [1i128, 2, 3, 4].iter().product()); } diff --git a/src/test/run-pass/impl-trait/example-calendar.rs b/src/test/run-pass/impl-trait/example-calendar.rs index 2a9af26881..84d86cfdf6 100644 --- a/src/test/run-pass/impl-trait/example-calendar.rs +++ b/src/test/run-pass/impl-trait/example-calendar.rs @@ -162,22 +162,10 @@ impl<'a, 'b> std::ops::Add<&'b NaiveDate> for &'a NaiveDate { } impl std::iter::Step for NaiveDate { - fn step(&self, by: &Self) -> Option { - Some(self + by) - } - - fn steps_between(_: &Self, _: &Self, _: &Self) -> Option { - unimplemented!() - } - - fn steps_between_by_one(_: &Self, _: &Self) -> Option { + fn steps_between(_: &Self, _: &Self) -> Option { unimplemented!() } - fn is_negative(&self) -> bool { - false - } - fn replace_one(&mut self) -> Self { mem::replace(self, NaiveDate(0, 0, 1)) } @@ -193,6 +181,10 @@ impl std::iter::Step for NaiveDate { fn sub_one(&self) -> Self { unimplemented!() } + + fn add_usize(&self, _: usize) -> Option { + unimplemented!() + } } #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] diff --git a/src/test/run-pass/intrinsics-integer.rs b/src/test/run-pass/intrinsics-integer.rs index 759dc51545..4896f02da2 100644 --- a/src/test/run-pass/intrinsics-integer.rs +++ b/src/test/run-pass/intrinsics-integer.rs @@ -14,7 +14,9 @@ mod rusti { extern "rust-intrinsic" { pub fn ctpop(x: T) -> T; pub fn ctlz(x: T) -> T; + pub fn ctlz_nonzero(x: T) -> T; pub fn cttz(x: T) -> T; + pub fn cttz_nonzero(x: T) -> T; pub fn bswap(x: T) -> T; } } @@ -68,6 +70,21 @@ pub fn main() { assert_eq!(ctlz(100u32), 25); assert_eq!(ctlz(100i32), 25); assert_eq!(ctlz(100u64), 57); assert_eq!(ctlz(100i64), 57); + assert_eq!(ctlz_nonzero(1u8), 7); assert_eq!(ctlz_nonzero(1i8), 7); + assert_eq!(ctlz_nonzero(1u16), 15); assert_eq!(ctlz_nonzero(1i16), 15); + assert_eq!(ctlz_nonzero(1u32), 31); assert_eq!(ctlz_nonzero(1i32), 31); + assert_eq!(ctlz_nonzero(1u64), 63); assert_eq!(ctlz_nonzero(1i64), 63); + + assert_eq!(ctlz_nonzero(10u8), 4); assert_eq!(ctlz_nonzero(10i8), 4); + assert_eq!(ctlz_nonzero(10u16), 12); assert_eq!(ctlz_nonzero(10i16), 12); + assert_eq!(ctlz_nonzero(10u32), 28); assert_eq!(ctlz_nonzero(10i32), 28); + assert_eq!(ctlz_nonzero(10u64), 60); assert_eq!(ctlz_nonzero(10i64), 60); + + assert_eq!(ctlz_nonzero(100u8), 1); assert_eq!(ctlz_nonzero(100i8), 1); + assert_eq!(ctlz_nonzero(100u16), 9); assert_eq!(ctlz_nonzero(100i16), 9); + assert_eq!(ctlz_nonzero(100u32), 25); assert_eq!(ctlz_nonzero(100i32), 25); + assert_eq!(ctlz_nonzero(100u64), 57); assert_eq!(ctlz_nonzero(100i64), 57); + assert_eq!(cttz(-1i8 as u8), 0); assert_eq!(cttz(-1i8), 0); assert_eq!(cttz(-1i16 as u16), 0); assert_eq!(cttz(-1i16), 0); assert_eq!(cttz(-1i32 as u32), 0); assert_eq!(cttz(-1i32), 0); @@ -93,6 +110,26 @@ pub fn main() { assert_eq!(cttz(100u32), 2); assert_eq!(cttz(100i32), 2); assert_eq!(cttz(100u64), 2); assert_eq!(cttz(100i64), 2); + assert_eq!(cttz_nonzero(-1i8 as u8), 0); assert_eq!(cttz_nonzero(-1i8), 0); + assert_eq!(cttz_nonzero(-1i16 as u16), 0); assert_eq!(cttz_nonzero(-1i16), 0); + assert_eq!(cttz_nonzero(-1i32 as u32), 0); assert_eq!(cttz_nonzero(-1i32), 0); + assert_eq!(cttz_nonzero(-1i64 as u64), 0); assert_eq!(cttz_nonzero(-1i64), 0); + + assert_eq!(cttz_nonzero(1u8), 0); assert_eq!(cttz_nonzero(1i8), 0); + assert_eq!(cttz_nonzero(1u16), 0); assert_eq!(cttz_nonzero(1i16), 0); + assert_eq!(cttz_nonzero(1u32), 0); assert_eq!(cttz_nonzero(1i32), 0); + assert_eq!(cttz_nonzero(1u64), 0); assert_eq!(cttz_nonzero(1i64), 0); + + assert_eq!(cttz_nonzero(10u8), 1); assert_eq!(cttz_nonzero(10i8), 1); + assert_eq!(cttz_nonzero(10u16), 1); assert_eq!(cttz_nonzero(10i16), 1); + assert_eq!(cttz_nonzero(10u32), 1); assert_eq!(cttz_nonzero(10i32), 1); + assert_eq!(cttz_nonzero(10u64), 1); assert_eq!(cttz_nonzero(10i64), 1); + + assert_eq!(cttz_nonzero(100u8), 2); assert_eq!(cttz_nonzero(100i8), 2); + assert_eq!(cttz_nonzero(100u16), 2); assert_eq!(cttz_nonzero(100i16), 2); + assert_eq!(cttz_nonzero(100u32), 2); assert_eq!(cttz_nonzero(100i32), 2); + assert_eq!(cttz_nonzero(100u64), 2); assert_eq!(cttz_nonzero(100i64), 2); + assert_eq!(bswap(0x0Au8), 0x0A); // no-op assert_eq!(bswap(0x0Ai8), 0x0A); // no-op assert_eq!(bswap(0x0A0Bu16), 0x0B0A); diff --git a/src/test/run-pass/issue-12860.rs b/src/test/run-pass/issue-12860.rs index 5c9ee74472..58ce390cac 100644 --- a/src/test/run-pass/issue-12860.rs +++ b/src/test/run-pass/issue-12860.rs @@ -8,10 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections)] - -extern crate collections; - use std::collections::HashSet; #[derive(Copy, Clone, PartialEq, Eq, Hash)] diff --git a/src/test/run-pass/issue-13105.rs b/src/test/run-pass/issue-13105.rs index ca68272d2d..f2a606a8bb 100644 --- a/src/test/run-pass/issue-13105.rs +++ b/src/test/run-pass/issue-13105.rs @@ -11,6 +11,7 @@ // pretty-expanded FIXME #23616 trait Foo { + #[allow(anonymous_parameters)] fn quux(u8) {} } diff --git a/src/test/run-pass/issue-13775.rs b/src/test/run-pass/issue-13775.rs index 3b70bea719..c69ae6a15c 100644 --- a/src/test/run-pass/issue-13775.rs +++ b/src/test/run-pass/issue-13775.rs @@ -11,6 +11,7 @@ // pretty-expanded FIXME #23616 trait Foo { + #[allow(anonymous_parameters)] fn bar(&self, isize) {} } diff --git a/src/test/run-pass/issue-14919.rs b/src/test/run-pass/issue-14919.rs index df5d62e769..5d0fde0179 100644 --- a/src/test/run-pass/issue-14919.rs +++ b/src/test/run-pass/issue-14919.rs @@ -26,7 +26,7 @@ impl<'a, 'b> Matcher for CharPredMatcher<'a, 'b> { } trait IntoMatcher<'a, T> { - fn into_matcher(self, &'a str) -> T; + fn into_matcher(self, _: &'a str) -> T; } impl<'a, 'b, F> IntoMatcher<'a, CharPredMatcher<'a, 'b>> for F where F: FnMut(char) -> bool + 'b { diff --git a/src/test/run-pass/issue-1696.rs b/src/test/run-pass/issue-1696.rs index 4c6c200c71..b06285b06a 100644 --- a/src/test/run-pass/issue-1696.rs +++ b/src/test/run-pass/issue-1696.rs @@ -8,10 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections)] - -extern crate collections; - use std::collections::HashMap; pub fn main() { diff --git a/src/test/run-pass/issue-19098.rs b/src/test/run-pass/issue-19098.rs index e54fdfb5b5..e526dd2903 100644 --- a/src/test/run-pass/issue-19098.rs +++ b/src/test/run-pass/issue-19098.rs @@ -9,7 +9,7 @@ // except according to those terms. pub trait Handler { - fn handle(&self, &mut String); + fn handle(&self, _: &mut String); } impl Handler for F where F: for<'a, 'b> Fn(&'a mut String) { diff --git a/src/test/run-pass/issue-19811-escape-unicode.rs b/src/test/run-pass/issue-19811-escape-unicode.rs index cff431065f..b447ffd69b 100644 --- a/src/test/run-pass/issue-19811-escape-unicode.rs +++ b/src/test/run-pass/issue-19811-escape-unicode.rs @@ -9,8 +9,6 @@ // except according to those terms. -#![feature(collections)] - fn main() { let mut escaped = String::from(""); for c in '\u{10401}'.escape_unicode() { diff --git a/src/test/run-pass/issue-21726.rs b/src/test/run-pass/issue-21726.rs index e1d1b908e0..9fdd89e25a 100644 --- a/src/test/run-pass/issue-21726.rs +++ b/src/test/run-pass/issue-21726.rs @@ -23,7 +23,7 @@ fn foo<'a>(s: &'a str) { trait IntoRef<'a> { type T: Clone; - fn into_ref(self, &'a str) -> Self::T; + fn into_ref(self, _: &'a str) -> Self::T; } impl<'a> IntoRef<'a> for () { diff --git a/src/test/run-pass/issue-23808.rs b/src/test/run-pass/issue-23808.rs index 0302b11fdb..1435a1b5d3 100644 --- a/src/test/run-pass/issue-23808.rs +++ b/src/test/run-pass/issue-23808.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] #![deny(dead_code)] // use different types / traits to test all combinations diff --git a/src/test/run-pass/issue-2383.rs b/src/test/run-pass/issue-2383.rs index 9c400aac1d..a497a9fda6 100644 --- a/src/test/run-pass/issue-2383.rs +++ b/src/test/run-pass/issue-2383.rs @@ -10,9 +10,6 @@ // pretty-expanded FIXME #23616 -#![feature(collections)] - -extern crate collections; use std::collections::VecDeque; pub fn main() { diff --git a/src/test/run-pass/issue-24947.rs b/src/test/run-pass/issue-24947.rs index 2b0c90c4d1..19a364a93f 100644 --- a/src/test/run-pass/issue-24947.rs +++ b/src/test/run-pass/issue-24947.rs @@ -10,7 +10,6 @@ // #24947 ICE using a trait-associated const in an array size -#![feature(associated_consts)] struct Foo; diff --git a/src/test/run-pass/issue-25145.rs b/src/test/run-pass/issue-25145.rs index 6f02f27838..d5d23012e0 100644 --- a/src/test/run-pass/issue-25145.rs +++ b/src/test/run-pass/issue-25145.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] struct S; diff --git a/src/test/run-pass/issue-26095.rs b/src/test/run-pass/issue-26095.rs index f34685c693..9d8d9c3ff2 100644 --- a/src/test/run-pass/issue-26095.rs +++ b/src/test/run-pass/issue-26095.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] trait HasNumber { const Number: usize; diff --git a/src/test/run-pass/issue-27859.rs b/src/test/run-pass/issue-27859.rs index 900614be61..56036caca1 100644 --- a/src/test/run-pass/issue-27859.rs +++ b/src/test/run-pass/issue-27859.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32 issue 42629 + #[inline(never)] fn foo(a: f32, b: f32) -> f32 { a % b diff --git a/src/test/run-pass/issue-2804-2.rs b/src/test/run-pass/issue-2804-2.rs index 6afb31619d..e428ecd4e5 100644 --- a/src/test/run-pass/issue-2804-2.rs +++ b/src/test/run-pass/issue-2804-2.rs @@ -11,10 +11,6 @@ // Minimized version of issue-2804.rs. Both check that callee IDs don't // clobber the previous node ID in a macro expr -#![feature(collections)] - -extern crate collections; - use std::collections::HashMap; fn add_interfaces(managed_ip: String, device: HashMap) { diff --git a/src/test/run-pass/issue-3026.rs b/src/test/run-pass/issue-3026.rs index d8499992f9..7c0dc8a004 100644 --- a/src/test/run-pass/issue-3026.rs +++ b/src/test/run-pass/issue-3026.rs @@ -10,10 +10,7 @@ // pretty-expanded FIXME #23616 -#![allow(unknown_features)] -#![feature(box_syntax, collections)] - -extern crate collections; +#![feature(box_syntax)] use std::collections::HashMap; diff --git a/src/test/run-pass/issue-30490.rs b/src/test/run-pass/issue-30490.rs index 035911302c..7658abc00c 100644 --- a/src/test/run-pass/issue-30490.rs +++ b/src/test/run-pass/issue-30490.rs @@ -69,8 +69,8 @@ fn main() { Command::new(name) .arg("--child") .stdin(Stdio::inherit()) - .stdout(unsafe { FromRawFd::from_raw_fd(libc::STDERR_FILENO) }) - .stderr(unsafe { FromRawFd::from_raw_fd(libc::STDOUT_FILENO) }) + .stdout(unsafe { Stdio::from_raw_fd(libc::STDERR_FILENO) }) + .stderr(unsafe { Stdio::from_raw_fd(libc::STDOUT_FILENO) }) .spawn() }; diff --git a/src/test/run-pass/issue-31260.rs b/src/test/run-pass/issue-31260.rs index e771fc7464..d21ffb96be 100644 --- a/src/test/run-pass/issue-31260.rs +++ b/src/test/run-pass/issue-31260.rs @@ -12,9 +12,12 @@ pub struct Struct { pub field: K, } -// Partial fix for #31260, doesn't work without {...}. static STRUCT: Struct<&'static [u8]> = Struct { field: {&[1]} }; +static STRUCT2: Struct<&'static [u8]> = Struct { + field: &[1] +}; + fn main() {} diff --git a/src/test/run-pass/issue-31267-additional.rs b/src/test/run-pass/issue-31267-additional.rs index a6b4252588..06ab310f6d 100644 --- a/src/test/run-pass/issue-31267-additional.rs +++ b/src/test/run-pass/issue-31267-additional.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] #[derive(Clone, Copy, Debug)] struct Bar; diff --git a/src/test/run-pass/issue-31267.rs b/src/test/run-pass/issue-31267.rs index 90eb0f6c84..9cbdde4049 100644 --- a/src/test/run-pass/issue-31267.rs +++ b/src/test/run-pass/issue-31267.rs @@ -10,7 +10,6 @@ // Regression test for issue #31267 -#![feature(associated_consts)] struct Foo; diff --git a/src/test/run-pass/issue-34074.rs b/src/test/run-pass/issue-34074.rs index 169a87f0b1..17d2bee746 100644 --- a/src/test/run-pass/issue-34074.rs +++ b/src/test/run-pass/issue-34074.rs @@ -8,9 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Make sure several unnamed function arguments don't conflict with each other +// Make sure several unnamed function parameters don't conflict with each other trait Tr { + #[allow(anonymous_parameters)] fn f(u8, u8) {} } diff --git a/src/test/run-pass/issue-3559.rs b/src/test/run-pass/issue-3559.rs index c2ea24ac6b..64f053d9a8 100644 --- a/src/test/run-pass/issue-3559.rs +++ b/src/test/run-pass/issue-3559.rs @@ -8,10 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections)] - -extern crate collections; - use std::collections::HashMap; fn check_strs(actual: &str, expected: &str) -> bool { diff --git a/src/test/run-pass/issue-37725.rs b/src/test/run-pass/issue-37725.rs new file mode 100644 index 0000000000..5ed1295c85 --- /dev/null +++ b/src/test/run-pass/issue-37725.rs @@ -0,0 +1,14 @@ +// 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. + +pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone { + s.clone(); +} +fn main() {} diff --git a/src/test/run-pass/issue-3979-generics.rs b/src/test/run-pass/issue-3979-generics.rs index 6ba566012c..2b56799f6b 100644 --- a/src/test/run-pass/issue-3979-generics.rs +++ b/src/test/run-pass/issue-3979-generics.rs @@ -12,7 +12,7 @@ use std::ops::Add; trait Positioned { - fn SetX(&mut self, S); + fn SetX(&mut self, _: S); fn X(&self) -> S; } diff --git a/src/test/run-pass/issue-3979.rs b/src/test/run-pass/issue-3979.rs index 184682255d..9b5f7296ab 100644 --- a/src/test/run-pass/issue-3979.rs +++ b/src/test/run-pass/issue-3979.rs @@ -10,7 +10,7 @@ trait Positioned { - fn SetX(&mut self, isize); + fn SetX(&mut self, _: isize); fn X(&self) -> isize; } diff --git a/src/test/run-pass/issue-40136.rs b/src/test/run-pass/issue-40136.rs index db642812b4..488754af06 100644 --- a/src/test/run-pass/issue-40136.rs +++ b/src/test/run-pass/issue-40136.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] macro_rules! m { () => { 0 } } diff --git a/src/test/compile-fail/struct-field-attr-feature-gate.rs b/src/test/run-pass/issue-40847.rs similarity index 60% rename from src/test/compile-fail/struct-field-attr-feature-gate.rs rename to src/test/run-pass/issue-40847.rs index 47495be4ad..2fa9998440 100644 --- a/src/test/compile-fail/struct-field-attr-feature-gate.rs +++ b/src/test/run-pass/issue-40847.rs @@ -8,15 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-struct_field_attributes - -struct Foo { - present: (), +macro_rules! gen { + ($name:ident ( $($dol:tt $var:ident)* ) $($body:tt)*) => { + macro_rules! $name { + ($($dol $var:ident)*) => { + $($body)* + } + } + } } +gen!(m($var) $var); + fn main() { - let foo = Foo { #[cfg(all())] present: () }; - //~^ ERROR attributes on struct pattern or literal fields are unstable - let Foo { #[cfg(all())] present: () } = foo; - //~^ ERROR attributes on struct pattern or literal fields are unstable + let x = 1; + assert_eq!(m!(x), 1); } diff --git a/src/test/run-pass/issue-40883.rs b/src/test/run-pass/issue-40883.rs new file mode 100644 index 0000000000..feb4a88a1d --- /dev/null +++ b/src/test/run-pass/issue-40883.rs @@ -0,0 +1,102 @@ +// 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. + +// check that we don't have linear stack usage with multiple calls to `push` +// min-llvm-version 4.0 + +#![feature(test)] + +extern crate test; +use std::mem; + +fn meal() -> Big { + if test::black_box(false) { + panic!() + } + Big { drop_me: [ + None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, + ]} +} + +pub struct Big { + drop_me: [Option>; 48], +} + +#[inline] +fn push(out: &mut Vec) { + out.push(meal()); +} + +#[inline(never)] +pub fn supersize_me(out: &mut Vec) { + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); // 16 calls to `push` + + verify_stack_usage(out); + + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); // 16 calls to `push` +} + +#[inline(never)] +fn verify_stack_usage(before_ptr: *mut Vec) { + // to check stack usage, create locals before and after + // and check the difference in addresses between them. + let mut stack_var: Vec = vec![]; + test::black_box(&mut stack_var); + let stack_usage = isize::abs( + (&mut stack_var as *mut _ as isize) - + (before_ptr as isize)) as usize; + // give space for 2 copies of `Big` + 128 "misc" bytes. + if stack_usage > mem::size_of::() * 2 + 128 { + panic!("used {} bytes of stack, but `struct Big` is only {} bytes", + stack_usage, mem::size_of::()); + } + +} + +pub fn main() { + let mut v = vec![]; + test::black_box(&mut v); + supersize_me(&mut v); +} diff --git a/src/test/run-pass/issue-4107.rs b/src/test/run-pass/issue-4107.rs index fa5ed26847..6c5f4bf36d 100644 --- a/src/test/run-pass/issue-4107.rs +++ b/src/test/run-pass/issue-4107.rs @@ -13,7 +13,7 @@ pub fn main() { let _id: &Mat2 = &Matrix::identity(1.0); } -pub trait Index { fn get(&self, Index) -> Result { panic!() } } +pub trait Index { fn get(&self, _: Index) -> Result { panic!() } } pub trait Dimensional: Index { } pub struct Mat2 { x: T } diff --git a/src/test/run-pass/issue-41696.rs b/src/test/run-pass/issue-41696.rs index ae57e0cf25..1888be58c5 100644 --- a/src/test/run-pass/issue-41696.rs +++ b/src/test/run-pass/issue-41696.rs @@ -9,7 +9,6 @@ // except according to those terms. // this used to cause exponential code-size blowup during LLVM passes. -// min-llvm-version 3.9 #![feature(test)] diff --git a/src/test/run-pass/issue-42679.rs b/src/test/run-pass/issue-42679.rs new file mode 100644 index 0000000000..312835225e --- /dev/null +++ b/src/test/run-pass/issue-42679.rs @@ -0,0 +1,31 @@ +// 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. + +#![feature(box_syntax)] +#![feature(box_patterns)] + +#[derive(Debug, PartialEq)] +enum Test { + Foo(usize), + Bar(isize), +} + +fn main() { + let a = box Test::Foo(10); + let b = box Test::Bar(-20); + match (a, b) { + (_, box Test::Foo(_)) => unreachable!(), + (box Test::Foo(x), b) => { + assert_eq!(x, 10); + assert_eq!(b, box Test::Bar(-20)); + }, + _ => unreachable!(), + } +} diff --git a/src/test/run-pass/issue-42747.rs b/src/test/run-pass/issue-42747.rs new file mode 100644 index 0000000000..05043ae6b2 --- /dev/null +++ b/src/test/run-pass/issue-42747.rs @@ -0,0 +1,55 @@ +// 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. + +macro_rules! fooN { + ($cur:ident $prev:ty) => { + #[allow(dead_code)] + enum $cur { + Empty, + First($prev), + Second($prev), + Third($prev), + Fourth($prev), + } + } +} + +fooN!(Foo0 ()); +fooN!(Foo1 Foo0); +fooN!(Foo2 Foo1); +fooN!(Foo3 Foo2); +fooN!(Foo4 Foo3); +fooN!(Foo5 Foo4); +fooN!(Foo6 Foo5); +fooN!(Foo7 Foo6); +fooN!(Foo8 Foo7); +fooN!(Foo9 Foo8); +fooN!(Foo10 Foo9); +fooN!(Foo11 Foo10); +fooN!(Foo12 Foo11); +fooN!(Foo13 Foo12); +fooN!(Foo14 Foo13); +fooN!(Foo15 Foo14); +fooN!(Foo16 Foo15); +fooN!(Foo17 Foo16); +fooN!(Foo18 Foo17); +fooN!(Foo19 Foo18); +fooN!(Foo20 Foo19); +fooN!(Foo21 Foo20); +fooN!(Foo22 Foo21); +fooN!(Foo23 Foo22); +fooN!(Foo24 Foo23); +fooN!(Foo25 Foo24); +fooN!(Foo26 Foo25); +fooN!(Foo27 Foo26); + +fn main() { + let _foo = Foo27::Empty; +} diff --git a/src/test/run-pass/issue-43057.rs b/src/test/run-pass/issue-43057.rs new file mode 100644 index 0000000000..152ddfb193 --- /dev/null +++ b/src/test/run-pass/issue-43057.rs @@ -0,0 +1,23 @@ +// 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. + +#![allow(unused)] + +macro_rules! column { + ($i:ident) => { + $i + }; +} + +fn foo() -> ! { + panic!(); +} + +fn main() {} diff --git a/src/test/run-pass/issue-43923.rs b/src/test/run-pass/issue-43923.rs new file mode 100644 index 0000000000..e1992e4fc5 --- /dev/null +++ b/src/test/run-pass/issue-43923.rs @@ -0,0 +1,19 @@ +// 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. + +struct A { ptr: T } + +fn foo(x: &A<[T]>) {} + +fn main() { + let a = foo; + let b = A { ptr: [a, a, a] }; + a(&A { ptr: [()] }); +} diff --git a/src/test/run-pass/issue-6128.rs b/src/test/run-pass/issue-6128.rs index 5fb24fe3ef..b52900746e 100644 --- a/src/test/run-pass/issue-6128.rs +++ b/src/test/run-pass/issue-6128.rs @@ -9,17 +9,13 @@ // except according to those terms. -#![allow(unknown_features)] -#![feature(box_syntax, collections)] - -extern crate collections; +#![feature(box_syntax)] use std::collections::HashMap; trait Graph { - fn f(&self, Edge); - fn g(&self, Node); - + fn f(&self, _: Edge); + fn g(&self, _: Node); } impl Graph for HashMap { diff --git a/src/test/run-pass/issue-6157.rs b/src/test/run-pass/issue-6157.rs index c7832ae41e..2c5bc48abe 100644 --- a/src/test/run-pass/issue-6157.rs +++ b/src/test/run-pass/issue-6157.rs @@ -10,7 +10,7 @@ // pretty-expanded FIXME #23616 -pub trait OpInt { fn call(&mut self, isize, isize) -> isize; } +pub trait OpInt { fn call(&mut self, _: isize, _: isize) -> isize; } impl OpInt for F where F: FnMut(isize, isize) -> isize { fn call(&mut self, a:isize, b:isize) -> isize { diff --git a/src/test/run-pass/issue-7660.rs b/src/test/run-pass/issue-7660.rs index b0ebc6c9cc..3f3e11a2dd 100644 --- a/src/test/run-pass/issue-7660.rs +++ b/src/test/run-pass/issue-7660.rs @@ -13,10 +13,6 @@ // pretty-expanded FIXME #23616 -#![feature(collections)] - -extern crate collections; - use std::collections::HashMap; struct A(isize, isize); diff --git a/src/test/run-pass/issue-9129.rs b/src/test/run-pass/issue-9129.rs index c46e8494e7..a9f29fdb38 100644 --- a/src/test/run-pass/issue-9129.rs +++ b/src/test/run-pass/issue-9129.rs @@ -13,7 +13,7 @@ #![allow(unknown_features)] #![feature(box_syntax)] -pub trait bomb { fn boom(&self, Ident); } +pub trait bomb { fn boom(&self, _: Ident); } pub struct S; impl bomb for S { fn boom(&self, _: Ident) { } } diff --git a/src/test/run-pass/istr.rs b/src/test/run-pass/istr.rs index 3197d7f016..7ebeb79f56 100644 --- a/src/test/run-pass/istr.rs +++ b/src/test/run-pass/istr.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections)] - use std::string::String; fn test_stack_assign() { diff --git a/src/test/run-pass/lib-defaults.rs b/src/test/run-pass/lib-defaults.rs index a38080f8cf..6e5dccae0a 100644 --- a/src/test/run-pass/lib-defaults.rs +++ b/src/test/run-pass/lib-defaults.rs @@ -8,16 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:clibrary.rs -// compile-flags: -lclibrary +// compile-flags: -lrust_test_helpers -#[link(name = "clibrary", kind = "static")] +#[link(name = "rust_test_helpers", kind = "static")] extern "C" { - pub fn foo(x:i32) -> i32; + pub fn rust_dbg_extern_identity_u32(x: u32) -> u32; } fn main() { unsafe { - foo(42); + rust_dbg_extern_identity_u32(42); } } diff --git a/src/test/run-pass/linkage1.rs b/src/test/run-pass/linkage1.rs index 17abf9cb1f..591610e88b 100644 --- a/src/test/run-pass/linkage1.rs +++ b/src/test/run-pass/linkage1.rs @@ -32,7 +32,9 @@ fn main() { // discarded. By adding and calling `other::bar`, we get around this problem. other::bar(); - assert!(!foo.is_null()); - assert_eq!(unsafe { *foo }, 3); - assert!(something_that_should_never_exist.is_null()); + unsafe { + assert!(!foo.is_null()); + assert_eq!(*foo, 3); + assert!(something_that_should_never_exist.is_null()); + } } diff --git a/src/test/run-pass/macro-first-set.rs b/src/test/run-pass/macro-first-set.rs new file mode 100644 index 0000000000..99e5d22fb4 --- /dev/null +++ b/src/test/run-pass/macro-first-set.rs @@ -0,0 +1,245 @@ +// 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. + +#![feature(macro_vis_matcher)] + +//{{{ issue 40569 ============================================================== + +macro_rules! my_struct { + ($(#[$meta:meta])* $ident:ident) => { + $(#[$meta])* struct $ident; + } +} + +my_struct!(#[derive(Debug, PartialEq)] Foo40569); + +fn test_40569() { + assert_eq!(Foo40569, Foo40569); +} + +//}}} + +//{{{ issue 26444 ============================================================== + +macro_rules! foo_26444 { + ($($beginning:ident),*; $middle:ident; $($end:ident),*) => { + stringify!($($beginning,)* $middle $(,$end)*) + } +} + +fn test_26444() { + assert_eq!("a , b , c , d , e", foo_26444!(a, b; c; d, e)); + assert_eq!("f", foo_26444!(; f ;)); +} + +macro_rules! pat_26444 { + ($fname:ident $($arg:pat)* =) => {} +} + +pat_26444!(foo 1 2 5...7 =); +pat_26444!(bar Some(ref x) Ok(ref mut y) &(w, z) =); + +//}}} + +//{{{ issue 40984 ============================================================== + +macro_rules! thread_local_40984 { + () => {}; + ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => { + thread_local_40984!($($rest)*); + }; + ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => {}; +} + +thread_local_40984! { + // no docs + #[allow(unused)] + static FOO: i32 = 42; + /// docs + pub static BAR: String = String::from("bar"); + + // look at these restrictions!! + pub(crate) static BAZ: usize = 0; + pub(in foo) static QUUX: usize = 0; +} + +//}}} + +//{{{ issue 35650 ============================================================== + +macro_rules! size { + ($ty:ty) => { + std::mem::size_of::<$ty>() + }; + ($size:tt) => { + $size + }; +} + +fn test_35650() { + assert_eq!(size!(u64), 8); + assert_eq!(size!(5), 5); +} + +//}}} + +//{{{ issue 27832 ============================================================== + +macro_rules! m { + ( $i:ident ) => (); + ( $t:tt $j:tt ) => (); +} + +m!(c); +m!(t 9); +m!(0 9); +m!(struct); +m!(struct Foo); + +macro_rules! m2 { + ( $b:expr ) => (); + ( $t:tt $u:tt ) => (); +} + +m2!(3); +m2!(1 2); +m2!(_ 1); +m2!(enum Foo); + +//}}} + +//{{{ issue 39964 ============================================================== + +macro_rules! foo_39964 { + ($a:ident) => {}; + (_) => {}; +} + +foo_39964!(_); + +//}}} + +//{{{ issue 34030 ============================================================== + +macro_rules! foo_34030 { + ($($t:ident),* /) => {}; +} + +foo_34030!(a, b/); +foo_34030!(a/); +foo_34030!(/); + +//}}} + +//{{{ issue 24189 ============================================================== + +macro_rules! foo_24189 { + ( + pub enum $name:ident { + $( #[$attr:meta] )* $var:ident + } + ) => { + pub enum $name { + $( #[$attr] )* $var + } + }; +} + +foo_24189! { + pub enum Foo24189 { + #[doc = "Bar"] Baz + } +} + +macro_rules! serializable { + ( + $(#[$struct_meta:meta])* + pub struct $name:ident { + $( + $(#[$field_meta:meta])* + $field:ident: $type_:ty + ),* , + } + ) => { + $(#[$struct_meta])* + pub struct $name { + $( + $(#[$field_meta])* + $field: $type_ + ),* , + } + } +} + +serializable! { + #[allow(dead_code)] + /// This is a test + pub struct Tester { + #[allow(dead_code)] + name: String, + } +} + +macro_rules! foo_24189_c { + ( $( > )* $x:ident ) => { }; +} +foo_24189_c!( > a ); + +fn test_24189() { + let _ = Foo24189::Baz; + let _ = Tester { name: "".to_owned() }; +} + +//}}} + +//{{{ some more tests ========================================================== + +macro_rules! test_block { + (< $($b:block)* >) => {} +} + +test_block!(<>); +test_block!(<{}>); +test_block!(<{1}{2}>); + +macro_rules! test_ty { + ($($t:ty),* $(,)*) => {} +} + +test_ty!(); +test_ty!(,); +test_ty!(u8); +test_ty!(u8,); + +macro_rules! test_path { + ($($t:path),* $(,)*) => {} +} + +test_path!(); +test_path!(,); +test_path!(::std); +test_path!(std::u8,); +test_path!(any, super, super::super::self::path, X::Z<'a, T=U>); + +macro_rules! test_meta_block { + ($($m:meta)* $b:block) => {}; +} + +test_meta_block!(windows {}); + +//}}} + +fn main() { + test_26444(); + test_40569(); + test_35650(); + test_24189(); +} + diff --git a/src/test/run-pass/macro-pat-neg-lit.rs b/src/test/run-pass/macro-pat-neg-lit.rs new file mode 100644 index 0000000000..43ac697edc --- /dev/null +++ b/src/test/run-pass/macro-pat-neg-lit.rs @@ -0,0 +1,35 @@ +// 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. + +macro_rules! enum_number { + ($name:ident { $($variant:ident = $value:expr, )* }) => { + enum $name { + $($variant = $value,)* + } + + fn foo(value: i32) -> Option<$name> { + match value { + $( $value => Some($name::$variant), )* + _ => None + } + } + } +} + +enum_number!(Change { + Down = -1, + None = 0, + Up = 1, +}); + +fn main() { + if let Some(Change::Down) = foo(-1) {} else { panic!() } +} + diff --git a/src/test/run-pass/new-unicode-escapes.rs b/src/test/run-pass/new-unicode-escapes.rs index 83c2dadcd2..2c04175760 100644 --- a/src/test/run-pass/new-unicode-escapes.rs +++ b/src/test/run-pass/new-unicode-escapes.rs @@ -9,8 +9,6 @@ // except according to those terms. -#![feature(collections)] - pub fn main() { let s = "\u{2603}"; assert_eq!(s, "☃"); diff --git a/src/test/run-pass/option-ext.rs b/src/test/run-pass/option-ext.rs index 03ba6097cd..c054171ff0 100644 --- a/src/test/run-pass/option-ext.rs +++ b/src/test/run-pass/option-ext.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections)] - pub fn main() { let thing = "{{ f }}"; let f = thing.find("{{"); diff --git a/src/test/run-pass/out-of-stack.rs b/src/test/run-pass/out-of-stack.rs index a7748b6d6a..7e70c4a7ab 100644 --- a/src/test/run-pass/out-of-stack.rs +++ b/src/test/run-pass/out-of-stack.rs @@ -10,7 +10,7 @@ // ignore-android: FIXME (#20004) // ignore-musl -// ignore-asmjs +// ignore-emscripten #![feature(asm)] #![feature(libc)] diff --git a/src/test/run-pass/overloaded-autoderef.rs b/src/test/run-pass/overloaded-autoderef.rs index 97da5fc8c0..d9ffbe51aa 100644 --- a/src/test/run-pass/overloaded-autoderef.rs +++ b/src/test/run-pass/overloaded-autoderef.rs @@ -9,7 +9,7 @@ // except according to those terms. #![allow(unknown_features)] -#![feature(box_syntax, collections, core)] +#![feature(box_syntax, core)] use std::cell::RefCell; use std::rc::Rc; diff --git a/src/test/run-pass/overloaded-deref.rs b/src/test/run-pass/overloaded-deref.rs index e2ca880719..9cdf45b485 100644 --- a/src/test/run-pass/overloaded-deref.rs +++ b/src/test/run-pass/overloaded-deref.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections)] - use std::cell::RefCell; use std::rc::Rc; use std::string::String; diff --git a/src/test/run-pass/range_inclusive.rs b/src/test/run-pass/range_inclusive.rs index 372d4a8b73..f6119e7099 100644 --- a/src/test/run-pass/range_inclusive.rs +++ b/src/test/run-pass/range_inclusive.rs @@ -10,7 +10,7 @@ // Test inclusive range syntax. -#![feature(inclusive_range_syntax, inclusive_range, step_by)] +#![feature(inclusive_range_syntax, inclusive_range, iterator_step_by)] use std::ops::{RangeInclusive, RangeToInclusive}; diff --git a/src/test/run-pass/realloc-16687.rs b/src/test/run-pass/realloc-16687.rs index b32d42df6b..eddcd5a584 100644 --- a/src/test/run-pass/realloc-16687.rs +++ b/src/test/run-pass/realloc-16687.rs @@ -13,11 +13,9 @@ // Ideally this would be revised to use no_std, but for now it serves // well enough to reproduce (and illustrate) the bug from #16687. -#![feature(heap_api, alloc, oom)] +#![feature(heap_api, allocator_api)] -extern crate alloc; - -use alloc::heap; +use std::heap::{Heap, Alloc, Layout}; use std::ptr; fn main() { @@ -47,38 +45,39 @@ unsafe fn test_triangle() -> bool { static PRINT : bool = false; - unsafe fn allocate(size: usize, align: usize) -> *mut u8 { - if PRINT { println!("allocate(size={} align={})", size, align); } + unsafe fn allocate(layout: Layout) -> *mut u8 { + if PRINT { + println!("allocate({:?})", layout); + } - let ret = heap::allocate(size, align); - if ret.is_null() { alloc::oom() } + let ret = Heap.alloc(layout.clone()).unwrap_or_else(|e| Heap.oom(e)); - if PRINT { println!("allocate(size={} align={}) ret: 0x{:010x}", - size, align, ret as usize); + if PRINT { + println!("allocate({:?}) = {:?}", layout, ret); } ret } - unsafe fn deallocate(ptr: *mut u8, size: usize, align: usize) { - if PRINT { println!("deallocate(ptr=0x{:010x} size={} align={})", - ptr as usize, size, align); + + unsafe fn deallocate(ptr: *mut u8, layout: Layout) { + if PRINT { + println!("deallocate({:?}, {:?}", ptr, layout); } - heap::deallocate(ptr, size, align); + Heap.dealloc(ptr, layout); } - unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 { + + unsafe fn reallocate(ptr: *mut u8, old: Layout, new: Layout) -> *mut u8 { if PRINT { - println!("reallocate(ptr=0x{:010x} old_size={} size={} align={})", - ptr as usize, old_size, size, align); + println!("reallocate({:?}, old={:?}, new={:?})", ptr, old, new); } - let ret = heap::reallocate(ptr, old_size, size, align); - if ret.is_null() { alloc::oom() } + let ret = Heap.realloc(ptr, old.clone(), new.clone()) + .unwrap_or_else(|e| Heap.oom(e)); if PRINT { - println!("reallocate(ptr=0x{:010x} old_size={} size={} align={}) \ - ret: 0x{:010x}", - ptr as usize, old_size, size, align, ret as usize); + println!("reallocate({:?}, old={:?}, new={:?}) = {:?}", + ptr, old, new, ret); } ret } @@ -91,8 +90,8 @@ unsafe fn test_triangle() -> bool { // way.) for i in 0..COUNT / 2 { let size = idx_to_size(i); - ascend[2*i] = allocate(size, ALIGN); - ascend[2*i+1] = allocate(size, ALIGN); + ascend[2*i] = allocate(Layout::from_size_align(size, ALIGN).unwrap()); + ascend[2*i+1] = allocate(Layout::from_size_align(size, ALIGN).unwrap()); } // Initialize each pair of rows to distinct value. @@ -112,8 +111,8 @@ unsafe fn test_triangle() -> bool { for i in 0..COUNT / 2 { let size = idx_to_size(i); - deallocate(ascend[2*i], size, ALIGN); - deallocate(ascend[2*i+1], size, ALIGN); + deallocate(ascend[2*i], Layout::from_size_align(size, ALIGN).unwrap()); + deallocate(ascend[2*i+1], Layout::from_size_align(size, ALIGN).unwrap()); } return true; @@ -124,14 +123,16 @@ unsafe fn test_triangle() -> bool { // rows as we go. unsafe fn test_1(ascend: &mut [*mut u8]) { let new_size = idx_to_size(COUNT-1); + let new = Layout::from_size_align(new_size, ALIGN).unwrap(); for i in 0..COUNT / 2 { let (p0, p1, old_size) = (ascend[2*i], ascend[2*i+1], idx_to_size(i)); assert!(old_size < new_size); + let old = Layout::from_size_align(old_size, ALIGN).unwrap(); - ascend[2*i] = reallocate(p0, old_size, new_size, ALIGN); + ascend[2*i] = reallocate(p0, old.clone(), new.clone()); sanity_check(&*ascend); - ascend[2*i+1] = reallocate(p1, old_size, new_size, ALIGN); + ascend[2*i+1] = reallocate(p1, old.clone(), new.clone()); sanity_check(&*ascend); } } @@ -139,14 +140,16 @@ unsafe fn test_triangle() -> bool { // Test 2: turn the square back into a triangle, top to bottom. unsafe fn test_2(ascend: &mut [*mut u8]) { let old_size = idx_to_size(COUNT-1); + let old = Layout::from_size_align(old_size, ALIGN).unwrap(); for i in 0..COUNT / 2 { let (p0, p1, new_size) = (ascend[2*i], ascend[2*i+1], idx_to_size(i)); assert!(new_size < old_size); + let new = Layout::from_size_align(new_size, ALIGN).unwrap(); - ascend[2*i] = reallocate(p0, old_size, new_size, ALIGN); + ascend[2*i] = reallocate(p0, old.clone(), new.clone()); sanity_check(&*ascend); - ascend[2*i+1] = reallocate(p1, old_size, new_size, ALIGN); + ascend[2*i+1] = reallocate(p1, old.clone(), new.clone()); sanity_check(&*ascend); } } @@ -154,14 +157,16 @@ unsafe fn test_triangle() -> bool { // Test 3: turn triangle into a square, bottom to top. unsafe fn test_3(ascend: &mut [*mut u8]) { let new_size = idx_to_size(COUNT-1); + let new = Layout::from_size_align(new_size, ALIGN).unwrap(); for i in (0..COUNT / 2).rev() { let (p0, p1, old_size) = (ascend[2*i], ascend[2*i+1], idx_to_size(i)); assert!(old_size < new_size); + let old = Layout::from_size_align(old_size, ALIGN).unwrap(); - ascend[2*i+1] = reallocate(p1, old_size, new_size, ALIGN); + ascend[2*i+1] = reallocate(p1, old.clone(), new.clone()); sanity_check(&*ascend); - ascend[2*i] = reallocate(p0, old_size, new_size, ALIGN); + ascend[2*i] = reallocate(p0, old.clone(), new.clone()); sanity_check(&*ascend); } } @@ -169,14 +174,16 @@ unsafe fn test_triangle() -> bool { // Test 4: turn the square back into a triangle, bottom to top. unsafe fn test_4(ascend: &mut [*mut u8]) { let old_size = idx_to_size(COUNT-1); + let old = Layout::from_size_align(old_size, ALIGN).unwrap(); for i in (0..COUNT / 2).rev() { let (p0, p1, new_size) = (ascend[2*i], ascend[2*i+1], idx_to_size(i)); assert!(new_size < old_size); + let new = Layout::from_size_align(new_size, ALIGN).unwrap(); - ascend[2*i+1] = reallocate(p1, old_size, new_size, ALIGN); + ascend[2*i+1] = reallocate(p1, old.clone(), new.clone()); sanity_check(&*ascend); - ascend[2*i] = reallocate(p0, old_size, new_size, ALIGN); + ascend[2*i] = reallocate(p0, old.clone(), new.clone()); sanity_check(&*ascend); } } diff --git a/src/test/run-pass/regions-early-bound-trait-param.rs b/src/test/run-pass/regions-early-bound-trait-param.rs index 4ba04aa709..86fcfb9e6d 100644 --- a/src/test/run-pass/regions-early-bound-trait-param.rs +++ b/src/test/run-pass/regions-early-bound-trait-param.rs @@ -63,7 +63,7 @@ fn make_val() -> T { } trait RefMakerTrait<'q> { - fn mk(Self) -> &'q Self; + fn mk(_: Self) -> &'q Self; } fn make_ref<'r, T:RefMakerTrait<'r>>(t:T) -> &'r T { diff --git a/src/test/run-pass/rfc1717/library-override.rs b/src/test/run-pass/rfc1717/library-override.rs index d6ef96c5ad..26713a2554 100644 --- a/src/test/run-pass/rfc1717/library-override.rs +++ b/src/test/run-pass/rfc1717/library-override.rs @@ -8,16 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:clibrary.rs -// compile-flags: -lstatic=wronglibrary:clibrary +// compile-flags: -lstatic=wronglibrary:rust_test_helpers #[link(name = "wronglibrary", kind = "dylib")] extern "C" { - pub fn foo(x:i32) -> i32; + pub fn rust_dbg_extern_identity_u32(x: u32) -> u32; } fn main() { unsafe { - foo(42); + rust_dbg_extern_identity_u32(42); } } diff --git a/src/test/run-pass/rfc1857-drop-order.rs b/src/test/run-pass/rfc1857-drop-order.rs new file mode 100644 index 0000000000..42f989538c --- /dev/null +++ b/src/test/run-pass/rfc1857-drop-order.rs @@ -0,0 +1,231 @@ +// 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. + +#![allow(dead_code, unreachable_code)] + +use std::cell::RefCell; +use std::rc::Rc; +use std::panic::{self, AssertUnwindSafe, UnwindSafe}; + +// This struct is used to record the order in which elements are dropped +struct PushOnDrop { + vec: Rc>>, + val: u32 +} + +impl PushOnDrop { + fn new(val: u32, vec: Rc>>) -> PushOnDrop { + PushOnDrop { vec, val } + } +} + +impl Drop for PushOnDrop { + fn drop(&mut self) { + self.vec.borrow_mut().push(self.val) + } +} + +impl UnwindSafe for PushOnDrop { } + +// Structs +struct TestStruct { + x: PushOnDrop, + y: PushOnDrop, + z: PushOnDrop +} + +// Tuple structs +struct TestTupleStruct(PushOnDrop, PushOnDrop, PushOnDrop); + +// Enum variants +enum TestEnum { + Tuple(PushOnDrop, PushOnDrop, PushOnDrop), + Struct { x: PushOnDrop, y: PushOnDrop, z: PushOnDrop } +} + +fn test_drop_tuple() { + // Tuple fields are dropped in the same order they are declared + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let test_tuple = (PushOnDrop::new(1, dropped_fields.clone()), + PushOnDrop::new(2, dropped_fields.clone())); + drop(test_tuple); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); + + // Panic during construction means that fields are treated as local variables + // Therefore they are dropped in reverse order of initialization + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + (PushOnDrop::new(2, cloned.clone()), + PushOnDrop::new(1, cloned.clone()), + panic!("this panic is catched :D")); + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); +} + +fn test_drop_struct() { + // Struct fields are dropped in the same order they are declared + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let test_struct = TestStruct { + x: PushOnDrop::new(1, dropped_fields.clone()), + y: PushOnDrop::new(2, dropped_fields.clone()), + z: PushOnDrop::new(3, dropped_fields.clone()), + }; + drop(test_struct); + assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]); + + // The same holds for tuple structs + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let test_tuple_struct = TestTupleStruct(PushOnDrop::new(1, dropped_fields.clone()), + PushOnDrop::new(2, dropped_fields.clone()), + PushOnDrop::new(3, dropped_fields.clone())); + drop(test_tuple_struct); + assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]); + + // Panic during struct construction means that fields are treated as local variables + // Therefore they are dropped in reverse order of initialization + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + TestStruct { + x: PushOnDrop::new(2, cloned.clone()), + y: PushOnDrop::new(1, cloned.clone()), + z: panic!("this panic is catched :D") + }; + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); + + // Test with different initialization order + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + TestStruct { + y: PushOnDrop::new(2, cloned.clone()), + x: PushOnDrop::new(1, cloned.clone()), + z: panic!("this panic is catched :D") + }; + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); + + // The same holds for tuple structs + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + TestTupleStruct(PushOnDrop::new(2, cloned.clone()), + PushOnDrop::new(1, cloned.clone()), + panic!("this panic is catched :D")); + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); +} + +fn test_drop_enum() { + // Enum variants are dropped in the same order they are declared + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let test_struct_enum = TestEnum::Struct { + x: PushOnDrop::new(1, dropped_fields.clone()), + y: PushOnDrop::new(2, dropped_fields.clone()), + z: PushOnDrop::new(3, dropped_fields.clone()) + }; + drop(test_struct_enum); + assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]); + + // The same holds for tuple enum variants + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let test_tuple_enum = TestEnum::Tuple(PushOnDrop::new(1, dropped_fields.clone()), + PushOnDrop::new(2, dropped_fields.clone()), + PushOnDrop::new(3, dropped_fields.clone())); + drop(test_tuple_enum); + assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]); + + // Panic during enum construction means that fields are treated as local variables + // Therefore they are dropped in reverse order of initialization + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + TestEnum::Struct { + x: PushOnDrop::new(2, cloned.clone()), + y: PushOnDrop::new(1, cloned.clone()), + z: panic!("this panic is catched :D") + }; + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); + + // Test with different initialization order + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + TestEnum::Struct { + y: PushOnDrop::new(2, cloned.clone()), + x: PushOnDrop::new(1, cloned.clone()), + z: panic!("this panic is catched :D") + }; + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); + + // The same holds for tuple enum variants + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + TestEnum::Tuple(PushOnDrop::new(2, cloned.clone()), + PushOnDrop::new(1, cloned.clone()), + panic!("this panic is catched :D")); + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); +} + +fn test_drop_list() { + // Elements in a Vec are dropped in the same order they are pushed + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let xs = vec![PushOnDrop::new(1, dropped_fields.clone()), + PushOnDrop::new(2, dropped_fields.clone()), + PushOnDrop::new(3, dropped_fields.clone())]; + drop(xs); + assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]); + + // The same holds for arrays + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let xs = [PushOnDrop::new(1, dropped_fields.clone()), + PushOnDrop::new(2, dropped_fields.clone()), + PushOnDrop::new(3, dropped_fields.clone())]; + drop(xs); + assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]); + + // Panic during vec construction means that fields are treated as local variables + // Therefore they are dropped in reverse order of initialization + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + vec![ + PushOnDrop::new(2, cloned.clone()), + PushOnDrop::new(1, cloned.clone()), + panic!("this panic is catched :D") + ]; + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); + + // The same holds for arrays + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + [ + PushOnDrop::new(2, cloned.clone()), + PushOnDrop::new(1, cloned.clone()), + panic!("this panic is catched :D") + ]; + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); +} + +fn main() { + test_drop_tuple(); + test_drop_struct(); + test_drop_enum(); + test_drop_list(); +} diff --git a/src/test/compile-fail/feature-gate-allocator.rs b/src/test/run-pass/rustc-rust-log.rs similarity index 79% rename from src/test/compile-fail/feature-gate-allocator.rs rename to src/test/run-pass/rustc-rust-log.rs index 6490216d01..629387d4cb 100644 --- a/src/test/compile-fail/feature-gate-allocator.rs +++ b/src/test/run-pass/rustc-rust-log.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,6 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allocator] //~ ERROR: experimental feature +// rustc-env:RUST_LOG=debug fn main() {} diff --git a/src/test/run-pass/smallest-hello-world.rs b/src/test/run-pass/smallest-hello-world.rs index b11970560d..bcbd3fd378 100644 --- a/src/test/run-pass/smallest-hello-world.rs +++ b/src/test/run-pass/smallest-hello-world.rs @@ -10,31 +10,32 @@ // Smallest "hello world" with a libc runtime -// pretty-expanded FIXME #23616 +// ignore-windows +// ignore-android -#![feature(intrinsics, lang_items, start, no_core, libc)] -#![no_core] +#![feature(intrinsics, lang_items, start, no_core, alloc_system)] +#![feature(global_allocator, allocator_api)] +#![no_std] -extern crate libc; +extern crate alloc_system; -extern { fn puts(s: *const u8); } -extern "rust-intrinsic" { fn transmute(t: T) -> U; } +use alloc_system::System; -#[lang = "eh_personality"] extern fn eh_personality() {} -#[lang = "eh_unwind_resume"] extern fn eh_unwind_resume() {} +#[global_allocator] +static A: System = System; + +extern { + fn puts(s: *const u8); +} + +#[no_mangle] +#[lang = "eh_personality"] pub extern fn rust_eh_personality() {} #[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} } -#[no_mangle] pub extern fn rust_eh_register_frames () {} -#[no_mangle] pub extern fn rust_eh_unregister_frames () {} #[start] fn main(_: isize, _: *const *const u8) -> isize { unsafe { - let (ptr, _): (*const u8, usize) = transmute("Hello!\0"); - puts(ptr); + puts("Hello!\0".as_ptr() as *const u8); } - return 0; + return 0 } - -#[cfg(target_os = "android")] -#[link(name="gcc")] -extern { } diff --git a/src/test/run-pass/stack-probes-lto.rs b/src/test/run-pass/stack-probes-lto.rs new file mode 100644 index 0000000000..045ba40813 --- /dev/null +++ b/src/test/run-pass/stack-probes-lto.rs @@ -0,0 +1,20 @@ +// 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. + +// ignore-arm +// ignore-wasm +// ignore-emscripten +// ignore-musl FIXME #31506 +// ignore-pretty +// no-system-llvm +// compile-flags: -C lto +// no-prefer-dynamic + +include!("stack-probes.rs"); diff --git a/src/test/run-pass/stack-probes.rs b/src/test/run-pass/stack-probes.rs new file mode 100644 index 0000000000..36aacea937 --- /dev/null +++ b/src/test/run-pass/stack-probes.rs @@ -0,0 +1,68 @@ +// 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. + +// ignore-arm +// ignore-wasm +// ignore-emscripten +// ignore-musl FIXME #31506 +// no-system-llvm + +use std::mem; +use std::process::Command; +use std::thread; +use std::env; + +#[link(name = "rust_test_helpers", kind = "static")] +extern { + #[link_name = "rust_dbg_extern_identity_u64"] + fn black_box(u: u64); +} + +fn main() { + let args = env::args().skip(1).collect::>(); + if args.len() > 0 { + match &args[0][..] { + "main-thread" => recurse(&[]), + "child-thread" => thread::spawn(|| recurse(&[])).join().unwrap(), + _ => panic!(), + } + return + } + + let me = env::current_exe().unwrap(); + + // The linux kernel has some different behavior for the main thread because + // the main thread's stack can typically grow. We can't always guarantee + // that we report stack overflow on the main thread, see #43052 for some + // details + if cfg!(not(target_os = "linux")) { + assert_overflow(Command::new(&me).arg("main-thread")); + } + assert_overflow(Command::new(&me).arg("child-thread")); +} + +#[allow(unconditional_recursion)] +fn recurse(array: &[u64]) { + unsafe { black_box(array.as_ptr() as u64); } + let local: [_; 1024] = unsafe { mem::uninitialized() }; + recurse(&local); +} + +fn assert_overflow(cmd: &mut Command) { + let output = cmd.output().unwrap(); + assert!(!output.status.success()); + let stdout = String::from_utf8_lossy(&output.stdout); + let stderr = String::from_utf8_lossy(&output.stderr); + println!("status: {}", output.status); + println!("stdout: {}", stdout); + println!("stderr: {}", stderr); + assert!(stdout.is_empty()); + assert!(stderr.contains("has overflowed its stack\n")); +} diff --git a/src/test/run-pass/supertrait-default-generics.rs b/src/test/run-pass/supertrait-default-generics.rs index e014ce1966..8351cc50fd 100644 --- a/src/test/run-pass/supertrait-default-generics.rs +++ b/src/test/run-pass/supertrait-default-generics.rs @@ -14,7 +14,7 @@ use std::ops::Add; trait Positioned { - fn SetX(&mut self, S); + fn SetX(&mut self, _: S); fn X(&self) -> S; } diff --git a/src/test/run-pass/sync-send-iterators-in-libcollections.rs b/src/test/run-pass/sync-send-iterators-in-libcollections.rs index ea154590de..903532e9bc 100644 --- a/src/test/run-pass/sync-send-iterators-in-libcollections.rs +++ b/src/test/run-pass/sync-send-iterators-in-libcollections.rs @@ -9,21 +9,16 @@ // except according to those terms. #![allow(warnings)] -#![feature(collections)] #![feature(drain, collections_bound, btree_range, vecmap)] -extern crate collections; - -use collections::BinaryHeap; -use collections::{BTreeMap, BTreeSet}; -use collections::LinkedList; -use collections::String; -use collections::Vec; -use collections::VecDeque; +use std::collections::BinaryHeap; +use std::collections::{BTreeMap, BTreeSet}; +use std::collections::LinkedList; +use std::collections::VecDeque; use std::collections::HashMap; use std::collections::HashSet; -use collections::Bound::Included; +use std::collections::Bound::Included; use std::mem; fn is_sync(_: T) where T: Sync {} diff --git a/src/test/run-pass/sync-send-iterators-in-libcore.rs b/src/test/run-pass/sync-send-iterators-in-libcore.rs index d12bdf182f..c11a0d391a 100644 --- a/src/test/run-pass/sync-send-iterators-in-libcore.rs +++ b/src/test/run-pass/sync-send-iterators-in-libcore.rs @@ -14,7 +14,7 @@ #![feature(iter_empty)] #![feature(iter_once)] #![feature(iter_unfold)] -#![feature(step_by)] +#![feature(iterator_step_by)] #![feature(str_escape)] use std::iter::{empty, once, repeat}; diff --git a/src/test/run-pass/test-allow-fail-attr.rs b/src/test/run-pass/test-allow-fail-attr.rs new file mode 100644 index 0000000000..aa9cf76617 --- /dev/null +++ b/src/test/run-pass/test-allow-fail-attr.rs @@ -0,0 +1,24 @@ +// 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. + +// compile-flags: --test +#![feature(allow_fail)] + +#[test] +#[allow_fail] +fn test1() { + panic!(); +} + +#[test] +#[allow_fail] +fn test2() { + assert!(true); +} diff --git a/src/test/run-pass/thread-local-extern-static.rs b/src/test/run-pass/thread-local-extern-static.rs index 92a95cad0d..87188db9dc 100644 --- a/src/test/run-pass/thread-local-extern-static.rs +++ b/src/test/run-pass/thread-local-extern-static.rs @@ -22,5 +22,7 @@ extern { } fn main() { - assert_eq!(FOO, 3); + unsafe { + assert_eq!(FOO, 3); + } } diff --git a/src/test/run-pass/thread-local-syntax.rs b/src/test/run-pass/thread-local-syntax.rs index a5967249b5..373824122f 100644 --- a/src/test/run-pass/thread-local-syntax.rs +++ b/src/test/run-pass/thread-local-syntax.rs @@ -11,13 +11,21 @@ #![deny(missing_docs)] //! this tests the syntax of `thread_local!` -thread_local! { - // no docs - #[allow(unused)] - static FOO: i32 = 42; - /// docs - pub static BAR: String = String::from("bar"); +mod foo { + mod bar { + thread_local! { + // no docs + #[allow(unused)] + static FOO: i32 = 42; + /// docs + pub static BAR: String = String::from("bar"); + + // look at these restrictions!! + pub(crate) static BAZ: usize = 0; + pub(in foo) static QUUX: usize = 0; + } + thread_local!(static SPLOK: u32 = 0); + } } -thread_local!(static BAZ: u32 = 0); fn main() {} diff --git a/src/test/run-pass/tls-try-with.rs b/src/test/run-pass/tls-try-with.rs new file mode 100644 index 0000000000..c072ec0679 --- /dev/null +++ b/src/test/run-pass/tls-try-with.rs @@ -0,0 +1,37 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten no threads support + +#![feature(thread_local_state)] + +use std::thread; + +static mut DROP_RUN: bool = false; + +struct Foo; + +thread_local!(static FOO: Foo = Foo {}); + +impl Drop for Foo { + fn drop(&mut self) { + assert!(FOO.try_with(|_| panic!("`try_with` closure run")).is_err()); + unsafe { DROP_RUN = true; } + } +} + +fn main() { + thread::spawn(|| { + assert_eq!(FOO.try_with(|_| { + 132 + }).expect("`try_with` failed"), 132); + }).join().unwrap(); + assert!(unsafe { DROP_RUN }); +} diff --git a/src/test/run-pass/trait-inheritance-static.rs b/src/test/run-pass/trait-inheritance-static.rs index 8e56582951..aae6b76087 100644 --- a/src/test/run-pass/trait-inheritance-static.rs +++ b/src/test/run-pass/trait-inheritance-static.rs @@ -10,7 +10,7 @@ pub trait MyNum { - fn from_int(isize) -> Self; + fn from_int(_: isize) -> Self; } pub trait NumExt: MyNum { } diff --git a/src/test/run-pass/trait-inheritance-static2.rs b/src/test/run-pass/trait-inheritance-static2.rs index 67bea3864a..dd942fbfa0 100644 --- a/src/test/run-pass/trait-inheritance-static2.rs +++ b/src/test/run-pass/trait-inheritance-static2.rs @@ -11,7 +11,7 @@ pub trait MyEq {} pub trait MyNum { - fn from_int(isize) -> Self; + fn from_int(_: isize) -> Self; } pub trait NumExt: MyEq + MyNum { } diff --git a/src/test/run-pass/trait-object-generics.rs b/src/test/run-pass/trait-object-generics.rs index 33bee3ea06..61d32bd6ff 100644 --- a/src/test/run-pass/trait-object-generics.rs +++ b/src/test/run-pass/trait-object-generics.rs @@ -41,7 +41,7 @@ impl Impl { enum Type { Constant(T) } trait Trait { - fn method(&self,Type<(K,V)>) -> isize; + fn method(&self, _: Type<(K,V)>) -> isize; } impl Trait for () { diff --git a/src/test/run-pass/u128.rs b/src/test/run-pass/u128.rs index cfd616c56b..b16f6c7b6a 100644 --- a/src/test/run-pass/u128.rs +++ b/src/test/run-pass/u128.rs @@ -122,4 +122,8 @@ fn main() { assert_eq!(b(0x679289ac23bb334f_36144401cf882172_u128) / b(0x7b0b271b64865f05_f54a7b72746c062f_u128), 0u128); + + // iter-arithmetic traits + assert_eq!(10u128, [1u128, 2, 3, 4].iter().sum()); + assert_eq!(24u128, [1u128, 2, 3, 4].iter().product()); } diff --git a/src/test/run-pass/unsized-tuple-impls.rs b/src/test/run-pass/unsized-tuple-impls.rs new file mode 100644 index 0000000000..591b19f89e --- /dev/null +++ b/src/test/run-pass/unsized-tuple-impls.rs @@ -0,0 +1,29 @@ +// 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. + +#![feature(unsized_tuple_coercion)] + +use std::collections::HashSet; + +fn main() { + let x : &(i32, i32, [i32]) = &(0, 1, [2, 3]); + let y : &(i32, i32, [i32]) = &(0, 1, [2, 3, 4]); + let mut a = [y, x]; + a.sort(); + assert_eq!(a, [x, y]); + + assert_eq!(&format!("{:?}", a), "[(0, 1, [2, 3]), (0, 1, [2, 3, 4])]"); + + let mut h = HashSet::new(); + h.insert(x); + h.insert(y); + assert!(h.contains(x)); + assert!(h.contains(y)); +} diff --git a/src/test/run-pass/utf8_chars.rs b/src/test/run-pass/utf8_chars.rs index 0a984429fa..b54aed7966 100644 --- a/src/test/run-pass/utf8_chars.rs +++ b/src/test/run-pass/utf8_chars.rs @@ -9,7 +9,7 @@ // except according to those terms. // -#![feature(collections, core, str_char)] +#![feature(core, str_char)] use std::str; diff --git a/src/test/run-pass/vec-macro-no-std.rs b/src/test/run-pass/vec-macro-no-std.rs index a51ef73226..f21027afac 100644 --- a/src/test/run-pass/vec-macro-no-std.rs +++ b/src/test/run-pass/vec-macro-no-std.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(lang_items, start, libc, collections)] +// ignore-emscripten missing rust_begin_unwind + +#![feature(lang_items, start, libc, alloc)] #![no_std] extern crate std as other; @@ -16,9 +18,9 @@ extern crate std as other; extern crate libc; #[macro_use] -extern crate collections; +extern crate alloc; -use collections::vec::Vec; +use alloc::vec::Vec; // Issue #16806 diff --git a/src/test/run-pass/vector-sort-panic-safe.rs b/src/test/run-pass/vector-sort-panic-safe.rs index 8ad6ca0abb..4387a43f03 100644 --- a/src/test/run-pass/vector-sort-panic-safe.rs +++ b/src/test/run-pass/vector-sort-panic-safe.rs @@ -10,14 +10,17 @@ // ignore-emscripten no threads support -#![feature(rand)] #![feature(const_fn)] +#![feature(rand)] +#![feature(sort_unstable)] use std::__rand::{thread_rng, Rng}; +use std::cell::Cell; +use std::cmp::Ordering; use std::panic; -use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize}; +use std::sync::atomic::Ordering::Relaxed; use std::thread; -use std::cell::Cell; const MAX_LEN: usize = 80; @@ -45,54 +48,85 @@ static DROP_COUNTS: [AtomicUsize; MAX_LEN] = [ AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), ]; -#[derive(Clone, PartialEq, PartialOrd, Eq, Ord)] +static VERSIONS: AtomicUsize = ATOMIC_USIZE_INIT; + +#[derive(Clone, Eq)] struct DropCounter { x: u32, id: usize, + version: Cell, +} + +impl PartialEq for DropCounter { + fn eq(&self, other: &Self) -> bool { + self.partial_cmp(other) == Some(Ordering::Equal) + } +} + +impl PartialOrd for DropCounter { + fn partial_cmp(&self, other: &Self) -> Option { + self.version.set(self.version.get() + 1); + other.version.set(other.version.get() + 1); + VERSIONS.fetch_add(2, Relaxed); + self.x.partial_cmp(&other.x) + } +} + +impl Ord for DropCounter { + fn cmp(&self, other: &Self) -> Ordering { + self.partial_cmp(other).unwrap() + } } impl Drop for DropCounter { fn drop(&mut self) { - DROP_COUNTS[self.id].fetch_add(1, Ordering::Relaxed); + DROP_COUNTS[self.id].fetch_add(1, Relaxed); + VERSIONS.fetch_sub(self.version.get(), Relaxed); } } -fn test(input: &[DropCounter]) { - let len = input.len(); - - // Work out the total number of comparisons required to sort - // this array... - let mut count = 0usize; - input.to_owned().sort_by(|a, b| { count += 1; a.cmp(b) }); +macro_rules! test { + ($input:ident, $func:ident) => { + let len = $input.len(); + + // Work out the total number of comparisons required to sort + // this array... + let mut count = 0usize; + $input.to_owned().$func(|a, b| { count += 1; a.cmp(b) }); + + // ... and then panic on each and every single one. + for panic_countdown in 0..count { + // Refresh the counters. + VERSIONS.store(0, Relaxed); + for i in 0..len { + DROP_COUNTS[i].store(0, Relaxed); + } - // ... and then panic on each and every single one. - for panic_countdown in 0..count { - // Refresh the counters. - for i in 0..len { - DROP_COUNTS[i].store(0, Ordering::Relaxed); - } + let v = $input.to_owned(); + let _ = thread::spawn(move || { + let mut v = v; + let mut panic_countdown = panic_countdown; + v.$func(|a, b| { + if panic_countdown == 0 { + SILENCE_PANIC.with(|s| s.set(true)); + panic!(); + } + panic_countdown -= 1; + a.cmp(b) + }) + }).join(); + + // Check that the number of things dropped is exactly + // what we expect (i.e. the contents of `v`). + for (i, c) in DROP_COUNTS.iter().enumerate().take(len) { + let count = c.load(Relaxed); + assert!(count == 1, + "found drop count == {} for i == {}, len == {}", + count, i, len); + } - let v = input.to_owned(); - let _ = thread::spawn(move || { - let mut v = v; - let mut panic_countdown = panic_countdown; - v.sort_by(|a, b| { - if panic_countdown == 0 { - SILENCE_PANIC.with(|s| s.set(true)); - panic!(); - } - panic_countdown -= 1; - a.cmp(b) - }) - }).join(); - - // Check that the number of things dropped is exactly - // what we expect (i.e. the contents of `v`). - for (i, c) in DROP_COUNTS.iter().enumerate().take(len) { - let count = c.load(Ordering::Relaxed); - assert!(count == 1, - "found drop count == {} for i == {}, len == {}", - count, i, len); + // Check that the most recent versions of values were dropped. + assert_eq!(VERSIONS.load(Relaxed), 0); } } } @@ -106,33 +140,41 @@ fn main() { prev(info); } })); + + let mut rng = thread_rng(); + for len in (1..20).chain(70..MAX_LEN) { - // Test on a random array. - let mut rng = thread_rng(); - let input = (0..len).map(|id| { - DropCounter { - x: rng.next_u32(), - id: id, - } - }).collect::>(); - test(&input); - - // Test on a sorted array with two elements randomly swapped, creating several natural - // runs of random lengths. Such arrays have very high chances of hitting all code paths in - // the merge procedure. - for _ in 0..5 { - let mut input = (0..len).map(|i| - DropCounter { - x: i as u32, - id: i, + for &modulus in &[5, 20, 50] { + for &has_runs in &[false, true] { + let mut input = (0..len) + .map(|id| { + DropCounter { + x: rng.next_u32() % modulus, + id: id, + version: Cell::new(0), + } + }) + .collect::>(); + + if has_runs { + for c in &mut input { + c.x = c.id as u32; + } + + for _ in 0..5 { + let a = rng.gen::() % len; + let b = rng.gen::() % len; + if a < b { + input[a..b].reverse(); + } else { + input.swap(a, b); + } + } } - ).collect::>(); - - let a = rng.gen::() % len; - let b = rng.gen::() % len; - input.swap(a, b); - test(&input); + test!(input, sort_by); + test!(input, sort_unstable_by); + } } } } diff --git a/src/test/run-pass/weird-exprs.rs b/src/test/run-pass/weird-exprs.rs index b28760e6c9..20f58301d4 100644 --- a/src/test/run-pass/weird-exprs.rs +++ b/src/test/run-pass/weird-exprs.rs @@ -77,6 +77,36 @@ fn angrydome() { fn evil_lincoln() { let _evil = println!("lincoln"); } +fn dots() { + assert_eq!(String::from(".................................................."), + format!("{:?}", .. .. .. .. .. .. .. .. .. .. .. .. .. + .. .. .. .. .. .. .. .. .. .. .. ..)); +} + +fn you_eight() { + assert_eq!(8, { + macro_rules! u8 { + (u8) => { + mod u8 { + pub fn u8<'u8>(u8: &'u8 u8) -> &'u8 u8 { + "u8"; + u8 + } + } + }; + } + + u8!(u8); + let &u8: &u8 = u8::u8(&8u8); + u8 + }); +} + +fn fishy() { + assert_eq!(String::from("><>"), + String::<>::from::<>("><>").chars::<>().rev::<>().collect::()); +} + pub fn main() { strange(); funny(); @@ -86,4 +116,7 @@ pub fn main() { canttouchthis(); angrydome(); evil_lincoln(); + dots(); + you_eight(); + fishy(); } diff --git a/src/test/run-pass/where-clause-bounds-inconsistency.rs b/src/test/run-pass/where-clause-bounds-inconsistency.rs index d4823b8a33..fa07861d79 100644 --- a/src/test/run-pass/where-clause-bounds-inconsistency.rs +++ b/src/test/run-pass/where-clause-bounds-inconsistency.rs @@ -15,10 +15,10 @@ trait Bound { } trait Trait { - fn a(&self, T) where T: Bound; - fn b(&self, T) where T: Bound; - fn c(&self, T); - fn d(&self, T); + fn a(&self, _: T) where T: Bound; + fn b(&self, _: T) where T: Bound; + fn c(&self, _: T); + fn d(&self, _: T); } impl Trait for bool { diff --git a/src/test/run-pass/while-prelude-drop.rs b/src/test/run-pass/while-prelude-drop.rs index e4ca551565..39ed4f53cf 100644 --- a/src/test/run-pass/while-prelude-drop.rs +++ b/src/test/run-pass/while-prelude-drop.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections)] - use std::string::String; #[derive(PartialEq)] diff --git a/src/test/rustdoc/assoc-consts.rs b/src/test/rustdoc/assoc-consts.rs index 04709407e5..2edf61288f 100644 --- a/src/test/rustdoc/assoc-consts.rs +++ b/src/test/rustdoc/assoc-consts.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] pub trait Foo { // @has assoc_consts/trait.Foo.html '//*[@class="rust trait"]' \ @@ -16,10 +15,28 @@ pub trait Foo { // @has - '//*[@id="associatedconstant.FOO"]' 'const FOO: usize' // @has - '//*[@class="docblock"]' 'FOO: usize = 12' const FOO: usize = 12; + // @has - '//*[@id="associatedconstant.FOO_NO_DEFAULT"]' 'const FOO_NO_DEFAULT: bool' + const FOO_NO_DEFAULT: bool; + // @!has - FOO_HIDDEN + #[doc(hidden)] + const FOO_HIDDEN: u8 = 0; } pub struct Bar; +impl Foo for Bar { + // @has assoc_consts/struct.Bar.html '//code' 'impl Foo for Bar' + // @has - '//*[@id="associatedconstant.FOO"]' 'const FOO: usize' + // @has - '//*[@class="docblock"]' 'FOO: usize = 12' + const FOO: usize = 12; + // @has - '//*[@id="associatedconstant.FOO_NO_DEFAULT"]' 'const FOO_NO_DEFAULT: bool' + // @has - '//*[@class="docblock"]' 'FOO_NO_DEFAULT: bool = false' + const FOO_NO_DEFAULT: bool = false; + // @!has - FOO_HIDDEN + #[doc(hidden)] + const FOO_HIDDEN: u8 = 0; +} + impl Bar { // @has assoc_consts/struct.Bar.html '//*[@id="associatedconstant.BAR"]' \ // 'const BAR: usize' @@ -44,3 +61,64 @@ impl Bar { // @has - '//*[@class="docblock"]' "F: fn(_: &(ToString + 'static)) = f" pub const F: fn(_: &(ToString + 'static)) = f; } + +impl Bar { + // @!has assoc_consts/struct.Bar.html 'BAR_PRIVATE' + const BAR_PRIVATE: char = 'a'; + // @!has assoc_consts/struct.Bar.html 'BAR_HIDDEN' + #[doc(hidden)] + pub const BAR_HIDDEN: &'static str = "a"; +} + +// @has assoc_consts/trait.Qux.html +pub trait Qux { + // @has - '//*[@id="associatedconstant.QUX0"]' 'const QUX0: u8' + // @has - '//*[@class="docblock"]' "Docs for QUX0 in trait." + /// Docs for QUX0 in trait. + const QUX0: u8; + // @has - '//*[@id="associatedconstant.QUX1"]' 'const QUX1: i8' + // @has - '//*[@class="docblock"]' "Docs for QUX1 in trait." + /// Docs for QUX1 in trait. + const QUX1: i8; + // @has - '//*[@id="associatedconstant.QUX_DEFAULT0"]' 'const QUX_DEFAULT0: u16' + // @has - '//*[@class="docblock"]' "QUX_DEFAULT0: u16 = 1" + // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT0 in trait." + /// Docs for QUX_DEFAULT0 in trait. + const QUX_DEFAULT0: u16 = 1; + // @has - '//*[@id="associatedconstant.QUX_DEFAULT1"]' 'const QUX_DEFAULT1: i16' + // @has - '//*[@class="docblock"]' "QUX_DEFAULT1: i16 = 2" + // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT1 in trait." + /// Docs for QUX_DEFAULT1 in trait. + const QUX_DEFAULT1: i16 = 2; + // @has - '//*[@id="associatedconstant.QUX_DEFAULT2"]' 'const QUX_DEFAULT2: u32' + // @has - '//*[@class="docblock"]' "QUX_DEFAULT2: u32 = 3" + // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT2 in trait." + /// Docs for QUX_DEFAULT2 in trait. + const QUX_DEFAULT2: u32 = 3; +} + +// @has assoc_consts/struct.Bar.html '//code' 'impl Qux for Bar' +impl Qux for Bar { + // @has - '//*[@id="associatedconstant.QUX0"]' 'const QUX0: u8' + // @has - '//*[@class="docblock"]' "QUX0: u8 = 4" + // @has - '//*[@class="docblock"]' "Docs for QUX0 in trait." + /// Docs for QUX0 in trait. + const QUX0: u8 = 4; + // @has - '//*[@id="associatedconstant.QUX1"]' 'const QUX1: i8' + // @has - '//*[@class="docblock"]' "QUX1: i8 = 5" + // @has - '//*[@class="docblock"]' "Docs for QUX1 in impl." + /// Docs for QUX1 in impl. + const QUX1: i8 = 5; + // @has - '//*[@id="associatedconstant.QUX_DEFAULT0"]' 'const QUX_DEFAULT0: u16' + // @has - '//*[@class="docblock"]' "QUX_DEFAULT0: u16 = 6" + // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT0 in trait." + const QUX_DEFAULT0: u16 = 6; + // @has - '//*[@id="associatedconstant.QUX_DEFAULT1"]' 'const QUX_DEFAULT1: i16' + // @has - '//*[@class="docblock"]' "QUX_DEFAULT1: i16 = 7" + // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT1 in impl." + /// Docs for QUX_DEFAULT1 in impl. + const QUX_DEFAULT1: i16 = 7; + // @has - '//*[@id="associatedconstant.QUX_DEFAULT2"]' 'const QUX_DEFAULT2: u32' + // @has - '//*[@class="docblock"]' "QUX_DEFAULT2: u32 = 3" + // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT2 in trait." +} diff --git a/src/test/rustdoc/assoc-types.rs b/src/test/rustdoc/assoc-types.rs index e5485c356c..d152be33f4 100644 --- a/src/test/rustdoc/assoc-types.rs +++ b/src/test/rustdoc/assoc-types.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-linelength + #![crate_type="lib"] // @has assoc_types/trait.Index.html @@ -18,11 +20,14 @@ pub trait Index { // @has - '//*[@id="index.v"]//code' 'fn index' // @has - '//*[@id="tymethod.index"]//code' \ // "fn index<'a>(&'a self, index: I) -> &'a Self::Output" + // @has - '//*[@id="tymethod.index"]//code//a[@href="../assoc_types/trait.Index.html#associatedtype.Output"]' \ + // "Output" fn index<'a>(&'a self, index: I) -> &'a Self::Output; } // @has assoc_types/fn.use_output.html // @has - '//*[@class="rust fn"]' '-> &T::Output' +// @has - '//*[@class="rust fn"]//a[@href="../assoc_types/trait.Index.html#associatedtype.Output"]' 'Output' pub fn use_output>(obj: &T, index: usize) -> &T::Output { obj.index(index) } @@ -33,10 +38,12 @@ pub trait Feed { // @has assoc_types/fn.use_input.html // @has - '//*[@class="rust fn"]' 'T::Input' +// @has - '//*[@class="rust fn"]//a[@href="../assoc_types/trait.Feed.html#associatedtype.Input"]' 'Input' pub fn use_input(_feed: &T, _element: T::Input) { } // @has assoc_types/fn.cmp_input.html // @has - '//*[@class="rust fn"]' 'where T::Input: PartialEq' +// @has - '//*[@class="rust fn"]//a[@href="../assoc_types/trait.Feed.html#associatedtype.Input"]' 'Input' pub fn cmp_input(a: &T::Input, b: &U::Input) -> bool where T::Input: PartialEq { diff --git a/src/test/rustdoc/auxiliary/issue-36031.rs b/src/test/rustdoc/auxiliary/issue-36031.rs index 6b8a4b9f13..6611cc428b 100644 --- a/src/test/rustdoc/auxiliary/issue-36031.rs +++ b/src/test/rustdoc/auxiliary/issue-36031.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] pub trait Foo { const FOO: usize; diff --git a/src/test/rustdoc/const-doc.rs b/src/test/rustdoc/const-doc.rs index 9f70fe4317..9884e3d2c1 100644 --- a/src/test/rustdoc/const-doc.rs +++ b/src/test/rustdoc/const-doc.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] use std::marker::PhantomData; diff --git a/src/test/rustdoc/empty-mod-private.rs b/src/test/rustdoc/empty-mod-private.rs new file mode 100644 index 0000000000..6b86af62a6 --- /dev/null +++ b/src/test/rustdoc/empty-mod-private.rs @@ -0,0 +1,27 @@ +// 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. + +// ignore-tidy-linelength +// compile-flags: --no-defaults --passes collapse-docs --passes unindent-comments --passes strip-priv-imports + +// @has 'empty_mod_private/index.html' '//a[@href="foo/index.html"]' 'foo' +// @has 'empty_mod_private/sidebar-items.js' 'foo' +// @matches 'empty_mod_private/foo/index.html' '//h1' 'Module empty_mod_private::foo' +mod foo {} + +// @has 'empty_mod_private/index.html' '//a[@href="bar/index.html"]' 'bar' +// @has 'empty_mod_private/sidebar-items.js' 'bar' +// @matches 'empty_mod_private/bar/index.html' '//h1' 'Module empty_mod_private::bar' +mod bar { + // @has 'empty_mod_private/bar/index.html' '//a[@href="baz/index.html"]' 'baz' + // @has 'empty_mod_private/bar/sidebar-items.js' 'baz' + // @matches 'empty_mod_private/bar/baz/index.html' '//h1' 'Module empty_mod_private::bar::baz' + mod baz {} +} diff --git a/src/test/rustdoc/empty-mod-public.rs b/src/test/rustdoc/empty-mod-public.rs new file mode 100644 index 0000000000..413fe16142 --- /dev/null +++ b/src/test/rustdoc/empty-mod-public.rs @@ -0,0 +1,24 @@ +// 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. + +// @has 'empty_mod_public/index.html' '//a[@href="foo/index.html"]' 'foo' +// @has 'empty_mod_public/sidebar-items.js' 'foo' +// @matches 'empty_mod_public/foo/index.html' '//h1' 'Module empty_mod_public::foo' +pub mod foo {} + +// @has 'empty_mod_public/index.html' '//a[@href="bar/index.html"]' 'bar' +// @has 'empty_mod_public/sidebar-items.js' 'bar' +// @matches 'empty_mod_public/bar/index.html' '//h1' 'Module empty_mod_public::bar' +pub mod bar { + // @has 'empty_mod_public/bar/index.html' '//a[@href="baz/index.html"]' 'baz' + // @has 'empty_mod_public/bar/sidebar-items.js' 'baz' + // @matches 'empty_mod_public/bar/baz/index.html' '//h1' 'Module empty_mod_public::bar::baz' + pub mod baz {} +} diff --git a/src/test/rustdoc/issue-28478.rs b/src/test/rustdoc/issue-28478.rs index 493c08693e..c1141cb031 100644 --- a/src/test/rustdoc/issue-28478.rs +++ b/src/test/rustdoc/issue-28478.rs @@ -9,7 +9,6 @@ // except according to those terms. #![feature(associated_type_defaults)] -#![feature(associated_consts)] // @has issue_28478/trait.Bar.html pub trait Bar { diff --git a/src/test/rustdoc/issue-31808.rs b/src/test/rustdoc/issue-31808.rs index 46be8229d7..20105babfd 100644 --- a/src/test/rustdoc/issue-31808.rs +++ b/src/test/rustdoc/issue-31808.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts, associated_types)] - // Test that associated item impls on primitive types don't crash rustdoc pub trait Foo { diff --git a/src/test/rustdoc/issue-33302.rs b/src/test/rustdoc/issue-33302.rs index a34ee908ef..a6ff001b96 100644 --- a/src/test/rustdoc/issue-33302.rs +++ b/src/test/rustdoc/issue-33302.rs @@ -11,7 +11,6 @@ // Ensure constant and array length values are not taken from source // code, which wreaks havoc with macros. -#![feature(associated_consts)] macro_rules! make { ($n:expr) => { diff --git a/src/test/rustdoc/issue-35169-2.rs b/src/test/rustdoc/issue-35169-2.rs index d738fb2925..b19fbaa5b9 100644 --- a/src/test/rustdoc/issue-35169-2.rs +++ b/src/test/rustdoc/issue-35169-2.rs @@ -19,6 +19,8 @@ impl Foo { pub fn by_explicit_ref(self: &Foo) {} pub fn by_mut_ref(&mut self) {} pub fn by_explicit_mut_ref(self: &mut Foo) {} + pub fn by_explicit_box(self: Box) {} + pub fn by_explicit_self_box(self: Box) {} pub fn static_foo() {} } @@ -41,5 +43,9 @@ impl DerefMut for Bar { // @has - '//*[@id="method.by_mut_ref"]' 'fn by_mut_ref(&mut self)' // @has - '//*[@id="by_explicit_mut_ref.v"]' 'fn by_explicit_mut_ref(self: &mut Foo)' // @has - '//*[@id="method.by_explicit_mut_ref"]' 'fn by_explicit_mut_ref(self: &mut Foo)' +// @!has - '//*[@id="by_explicit_box.v"]' 'fn by_explicit_box(self: Box)' +// @!has - '//*[@id="method.by_explicit_box"]' 'fn by_explicit_box(self: Box)' +// @!has - '//*[@id="by_explicit_self_box.v"]' 'fn by_explicit_self_box(self: Box)' +// @!has - '//*[@id="method.by_explicit_self_box"]' 'fn by_explicit_self_box(self: Box)' // @!has - '//*[@id="static_foo.v"]' 'fn static_foo()' // @!has - '//*[@id="method.static_foo"]' 'fn static_foo()' diff --git a/src/test/rustdoc/issue-35169.rs b/src/test/rustdoc/issue-35169.rs index 8764e4a390..95231f282e 100644 --- a/src/test/rustdoc/issue-35169.rs +++ b/src/test/rustdoc/issue-35169.rs @@ -18,6 +18,8 @@ impl Foo { pub fn by_explicit_ref(self: &Foo) {} pub fn by_mut_ref(&mut self) {} pub fn by_explicit_mut_ref(self: &mut Foo) {} + pub fn by_explicit_box(self: Box) {} + pub fn by_explicit_self_box(self: Box) {} pub fn static_foo() {} } @@ -36,5 +38,9 @@ impl Deref for Bar { // @!has - '//*[@id="method.by_mut_ref"]' 'fn by_mut_ref(&mut self)' // @!has - '//*[@id="by_explicit_mut_ref.v"]' 'fn by_explicit_mut_ref(self: &mut Foo)' // @!has - '//*[@id="method.by_explicit_mut_ref"]' 'fn by_explicit_mut_ref(self: &mut Foo)' +// @!has - '//*[@id="by_explicit_box.v"]' 'fn by_explicit_box(self: Box)' +// @!has - '//*[@id="method.by_explicit_box"]' 'fn by_explicit_box(self: Box)' +// @!has - '//*[@id="by_explicit_self_box.v"]' 'fn by_explicit_self_box(self: Box)' +// @!has - '//*[@id="method.by_explicit_self_box"]' 'fn by_explicit_self_box(self: Box)' // @!has - '//*[@id="static_foo.v"]' 'fn static_foo()' // @!has - '//*[@id="method.static_foo"]' 'fn static_foo()' diff --git a/src/test/rustdoc/issue-35488.rs b/src/test/rustdoc/issue-35488.rs new file mode 100644 index 0000000000..f24166a65f --- /dev/null +++ b/src/test/rustdoc/issue-35488.rs @@ -0,0 +1,23 @@ +// 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. + +mod foo { + pub enum Foo { + Bar, + } + pub use self::Foo::*; +} + +// @has 'issue_35488/index.html' '//code' 'pub use self::Foo::*;' +// @has 'issue_35488/enum.Foo.html' +pub use self::foo::*; + +// @has 'issue_35488/index.html' '//code' 'pub use std::option::Option::None;' +pub use std::option::Option::None; diff --git a/src/test/rustdoc/issue-42875.rs b/src/test/rustdoc/issue-42875.rs new file mode 100644 index 0000000000..ebf7056755 --- /dev/null +++ b/src/test/rustdoc/issue-42875.rs @@ -0,0 +1,23 @@ +// 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. + +// compile-flags: --no-defaults + +#![crate_name = "foo"] + +// @has foo/a/index.html '//code' 'use *;' +mod a { + use *; +} + +// @has foo/b/index.html '//code' 'pub use *;' +pub mod b { + pub use *; +} diff --git a/src/test/compile-fail/gated-associated_consts.rs b/src/test/rustdoc/issue-43153.rs similarity index 58% rename from src/test/compile-fail/gated-associated_consts.rs rename to src/test/rustdoc/issue-43153.rs index ee4422faf3..6ac341d8b0 100644 --- a/src/test/compile-fail/gated-associated_consts.rs +++ b/src/test/rustdoc/issue-43153.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,16 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-associated_consts +// Test that `include!` in a doc test searches relative to the directory in +// which the test is declared. -trait MyTrait { - const C: bool; - //~^ associated constants are experimental -} +// compile-flags:--test -struct Foo; - -impl Foo { - const C: bool = true; - //~^ associated constants are experimental -} +/// ```rust +/// include!("auxiliary/empty.rs"); +/// fn main() {} +/// ``` +pub struct Foo; diff --git a/src/test/rustdoc/typedef.rs b/src/test/rustdoc/typedef.rs new file mode 100644 index 0000000000..4ac91d3545 --- /dev/null +++ b/src/test/rustdoc/typedef.rs @@ -0,0 +1,35 @@ +// 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. + +pub trait MyTrait { + fn method_on_mytrait() {} +} + +pub struct MyStruct; + +impl MyStruct { + pub fn method_on_mystruct() {} +} + +// @has typedef/type.MyAlias.html +// @has - '//*[@class="impl"]//code' 'impl MyAlias' +// @has - '//*[@class="impl"]//code' 'impl MyTrait for MyAlias' +// @has - 'Alias docstring' +// @has - '//*[@class="sidebar"]//p[@class="location"]' 'Type Definition MyAlias' +// @has - '//*[@class="sidebar"]//a[@href="#methods"]' 'Methods' +// @has - '//*[@class="sidebar"]//a[@href="#implementations"]' 'Trait Implementations' +/// Alias docstring +pub type MyAlias = MyStruct; + +impl MyAlias { + pub fn method_on_myalias() {} +} + +impl MyTrait for MyAlias {} diff --git a/src/test/ui-fulldeps/auxiliary/attr_proc_macro.rs b/src/test/ui-fulldeps/auxiliary/attr_proc_macro.rs new file mode 100644 index 0000000000..db0c19e96f --- /dev/null +++ b/src/test/ui-fulldeps/auxiliary/attr_proc_macro.rs @@ -0,0 +1,23 @@ +// 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. + +// force-host +// no-prefer-dynamic +#![feature(proc_macro)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn attr_proc_macro(_: TokenStream, input: TokenStream) -> TokenStream { + input +} diff --git a/src/test/ui-fulldeps/auxiliary/bang_proc_macro.rs b/src/test/ui-fulldeps/auxiliary/bang_proc_macro.rs new file mode 100644 index 0000000000..89ac11b309 --- /dev/null +++ b/src/test/ui-fulldeps/auxiliary/bang_proc_macro.rs @@ -0,0 +1,23 @@ +// 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. + +// force-host +// no-prefer-dynamic +#![feature(proc_macro)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro] +pub fn bang_proc_macro(input: TokenStream) -> TokenStream { + input +} diff --git a/src/test/ui-fulldeps/auxiliary/derive-clona.rs b/src/test/ui-fulldeps/auxiliary/derive-clona.rs new file mode 100644 index 0000000000..719fbdb15e --- /dev/null +++ b/src/test/ui-fulldeps/auxiliary/derive-clona.rs @@ -0,0 +1,23 @@ +// 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. + +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Clona)] +pub fn derive_clonea(input: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/src/test/ui-fulldeps/auxiliary/derive-foo.rs b/src/test/ui-fulldeps/auxiliary/derive-foo.rs new file mode 100644 index 0000000000..64dcf72ba2 --- /dev/null +++ b/src/test/ui-fulldeps/auxiliary/derive-foo.rs @@ -0,0 +1,23 @@ +// 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. + +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(FooWithLongName)] +pub fn derive_foo(input: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs b/src/test/ui-fulldeps/resolve-error.rs similarity index 57% rename from src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs rename to src/test/ui-fulldeps/resolve-error.rs index ddd8631f02..dfaa1d7a32 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs +++ b/src/test/ui-fulldeps/resolve-error.rs @@ -35,46 +35,29 @@ macro_rules! attr_proc_mac { } #[derive(FooWithLongNan)] -//~^ ERROR cannot find derive macro `FooWithLongNan` in this scope -//~^^ HELP did you mean `FooWithLongName`? struct Foo; #[attr_proc_macra] -//~^ ERROR cannot find attribute macro `attr_proc_macra` in this scope -//~^^ HELP did you mean `attr_proc_macro`? struct Bar; #[FooWithLongNan] -//~^ ERROR cannot find attribute macro `FooWithLongNan` in this scope struct Asdf; #[derive(Dlone)] -//~^ ERROR cannot find derive macro `Dlone` in this scope -//~^^ HELP did you mean `Clone`? struct A; #[derive(Dlona)] -//~^ ERROR cannot find derive macro `Dlona` in this scope -//~^^ HELP did you mean `Clona`? struct B; #[derive(attr_proc_macra)] -//~^ ERROR cannot find derive macro `attr_proc_macra` in this scope struct C; fn main() { FooWithLongNama!(); - //~^ ERROR cannot find macro `FooWithLongNama!` in this scope - //~^^ HELP did you mean `FooWithLongNam!`? attr_proc_macra!(); - //~^ ERROR cannot find macro `attr_proc_macra!` in this scope - //~^^ HELP did you mean `attr_proc_mac!`? Dlona!(); - //~^ ERROR cannot find macro `Dlona!` in this scope bang_proc_macrp!(); - //~^ ERROR cannot find macro `bang_proc_macrp!` in this scope - //~^^ HELP did you mean `bang_proc_macro!`? } diff --git a/src/test/ui-fulldeps/resolve-error.stderr b/src/test/ui-fulldeps/resolve-error.stderr new file mode 100644 index 0000000000..754f6bc4f1 --- /dev/null +++ b/src/test/ui-fulldeps/resolve-error.stderr @@ -0,0 +1,62 @@ +error: cannot find derive macro `FooWithLongNan` in this scope + --> $DIR/resolve-error.rs:37:10 + | +37 | #[derive(FooWithLongNan)] + | ^^^^^^^^^^^^^^ help: try: `FooWithLongName` + +error: cannot find attribute macro `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:40:3 + | +40 | #[attr_proc_macra] + | ^^^^^^^^^^^^^^^ help: try: `attr_proc_macro` + +error: cannot find attribute macro `FooWithLongNan` in this scope + --> $DIR/resolve-error.rs:43:3 + | +43 | #[FooWithLongNan] + | ^^^^^^^^^^^^^^ + +error: cannot find derive macro `Dlone` in this scope + --> $DIR/resolve-error.rs:46:10 + | +46 | #[derive(Dlone)] + | ^^^^^ help: try: `Clone` + +error: cannot find derive macro `Dlona` in this scope + --> $DIR/resolve-error.rs:49:10 + | +49 | #[derive(Dlona)] + | ^^^^^ help: try: `Clona` + +error: cannot find derive macro `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:52:10 + | +52 | #[derive(attr_proc_macra)] + | ^^^^^^^^^^^^^^^ + +error: cannot find macro `FooWithLongNama!` in this scope + --> $DIR/resolve-error.rs:56:5 + | +56 | FooWithLongNama!(); + | ^^^^^^^^^^^^^^^ help: you could try the macro: `FooWithLongNam!` + +error: cannot find macro `attr_proc_macra!` in this scope + --> $DIR/resolve-error.rs:58:5 + | +58 | attr_proc_macra!(); + | ^^^^^^^^^^^^^^^ help: you could try the macro: `attr_proc_mac!` + +error: cannot find macro `Dlona!` in this scope + --> $DIR/resolve-error.rs:60:5 + | +60 | Dlona!(); + | ^^^^^ + +error: cannot find macro `bang_proc_macrp!` in this scope + --> $DIR/resolve-error.rs:62:5 + | +62 | bang_proc_macrp!(); + | ^^^^^^^^^^^^^^^ help: you could try the macro: `bang_proc_macro!` + +error: aborting due to 10 previous errors + diff --git a/src/test/ui/README.md b/src/test/ui/README.md deleted file mode 100644 index dcdeabd803..0000000000 --- a/src/test/ui/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# Guide to the UI Tests - -The UI tests are intended to capture the compiler's complete output, -so that we can test all aspects of the presentation. They work by -compiling a file (e.g., `hello_world/main.rs`), capturing the output, -and then applying some normalization (see below). This normalized -result is then compared against reference files named -`hello_world/main.stderr` and `hello_world/main.stdout`. If either of -those files doesn't exist, the output must be empty. If the test run -fails, we will print out the current output, but it is also saved in -`build//test/ui/hello_world/main.stdout` (this path is -printed as part of the test failure mesage), so you can run `diff` and -so forth. - -# Editing and updating the reference files - -If you have changed the compiler's output intentionally, or you are -making a new test, you can use the script `update-references.sh` to -update the references. When you run the test framework, it will report -various errors: in those errors is a command you can use to run the -`update-references.sh` script, which will then copy over the files -from the build directory and use them as the new reference. You can -also just run `update-all-references.sh`. In both cases, you can run -the script with `--help` to get a help message. - -# Normalization - -The normalization applied is aimed at filenames: - -- the test directory is replaced with `$DIR` -- all backslashes (\) are converted to forward slashes (/) (for windows) diff --git a/src/test/compile-fail/block-must-not-have-result-do.rs b/src/test/ui/block-result/block-must-not-have-result-do.rs similarity index 100% rename from src/test/compile-fail/block-must-not-have-result-do.rs rename to src/test/ui/block-result/block-must-not-have-result-do.rs diff --git a/src/test/ui/block-result/block-must-not-have-result-do.stderr b/src/test/ui/block-result/block-must-not-have-result-do.stderr new file mode 100644 index 0000000000..d4024f41c2 --- /dev/null +++ b/src/test/ui/block-result/block-must-not-have-result-do.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/block-must-not-have-result-do.rs:13:9 + | +13 | true //~ ERROR mismatched types + | ^^^^ expected (), found bool + | + = note: expected type `()` + found type `bool` + +error: aborting due to previous error + diff --git a/src/test/compile-fail/block-must-not-have-result-res.rs b/src/test/ui/block-result/block-must-not-have-result-res.rs similarity index 100% rename from src/test/compile-fail/block-must-not-have-result-res.rs rename to src/test/ui/block-result/block-must-not-have-result-res.rs diff --git a/src/test/ui/block-result/block-must-not-have-result-res.stderr b/src/test/ui/block-result/block-must-not-have-result-res.stderr new file mode 100644 index 0000000000..f60a0c2e5f --- /dev/null +++ b/src/test/ui/block-result/block-must-not-have-result-res.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/block-must-not-have-result-res.rs:15:9 + | +15 | true //~ ERROR mismatched types + | ^^^^ expected (), found bool + | + = note: expected type `()` + found type `bool` + +error: aborting due to previous error + diff --git a/src/test/compile-fail/block-must-not-have-result-while.rs b/src/test/ui/block-result/block-must-not-have-result-while.rs similarity index 100% rename from src/test/compile-fail/block-must-not-have-result-while.rs rename to src/test/ui/block-result/block-must-not-have-result-while.rs diff --git a/src/test/ui/block-result/block-must-not-have-result-while.stderr b/src/test/ui/block-result/block-must-not-have-result-while.stderr new file mode 100644 index 0000000000..888a64c1bb --- /dev/null +++ b/src/test/ui/block-result/block-must-not-have-result-while.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/block-must-not-have-result-while.rs:13:9 + | +13 | true //~ ERROR mismatched types + | ^^^^ expected (), found bool + | + = note: expected type `()` + found type `bool` + +error: aborting due to previous error + diff --git a/src/test/compile-fail/consider-removing-last-semi.rs b/src/test/ui/block-result/consider-removing-last-semi.rs similarity index 100% rename from src/test/compile-fail/consider-removing-last-semi.rs rename to src/test/ui/block-result/consider-removing-last-semi.rs diff --git a/src/test/ui/block-result/consider-removing-last-semi.stderr b/src/test/ui/block-result/consider-removing-last-semi.stderr new file mode 100644 index 0000000000..5905cfa932 --- /dev/null +++ b/src/test/ui/block-result/consider-removing-last-semi.stderr @@ -0,0 +1,30 @@ +error[E0308]: mismatched types + --> $DIR/consider-removing-last-semi.rs:11:18 + | +11 | fn f() -> String { //~ ERROR mismatched types + | __________________^ +12 | | 0u8; +13 | | "bla".to_string(); //~ HELP consider removing this semicolon + | | - help: consider removing this semicolon +14 | | } + | |_^ expected struct `std::string::String`, found () + | + = note: expected type `std::string::String` + found type `()` + +error[E0308]: mismatched types + --> $DIR/consider-removing-last-semi.rs:16:18 + | +16 | fn g() -> String { //~ ERROR mismatched types + | __________________^ +17 | | "this won't work".to_string(); +18 | | "removeme".to_string(); //~ HELP consider removing this semicolon + | | - help: consider removing this semicolon +19 | | } + | |_^ expected struct `std::string::String`, found () + | + = note: expected type `std::string::String` + found type `()` + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/issue-11714.rs b/src/test/ui/block-result/issue-11714.rs similarity index 100% rename from src/test/compile-fail/issue-11714.rs rename to src/test/ui/block-result/issue-11714.rs diff --git a/src/test/ui/block-result/issue-11714.stderr b/src/test/ui/block-result/issue-11714.stderr new file mode 100644 index 0000000000..376834beab --- /dev/null +++ b/src/test/ui/block-result/issue-11714.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/issue-11714.rs:11:18 + | +11 | fn blah() -> i32 { //~ ERROR mismatched types + | __________________^ +12 | | 1 +13 | | +14 | | ; //~ HELP consider removing this semicolon: + | | - help: consider removing this semicolon +15 | | } + | |_^ expected i32, found () + | + = note: expected type `i32` + found type `()` + +error: aborting due to previous error + diff --git a/src/test/compile-fail/issue-13428.rs b/src/test/ui/block-result/issue-13428.rs similarity index 100% rename from src/test/compile-fail/issue-13428.rs rename to src/test/ui/block-result/issue-13428.rs diff --git a/src/test/ui/block-result/issue-13428.stderr b/src/test/ui/block-result/issue-13428.stderr new file mode 100644 index 0000000000..7bd4529c46 --- /dev/null +++ b/src/test/ui/block-result/issue-13428.stderr @@ -0,0 +1,33 @@ +error[E0308]: mismatched types + --> $DIR/issue-13428.rs:13:20 + | +13 | fn foo() -> String { //~ ERROR mismatched types + | ____________________^ +14 | | format!("Hello {}", +15 | | "world") +16 | | // Put the trailing semicolon on its own line to test that the +17 | | // note message gets the offending semicolon exactly +18 | | ; //~ HELP consider removing this semicolon + | | - help: consider removing this semicolon +19 | | } + | |_^ expected struct `std::string::String`, found () + | + = note: expected type `std::string::String` + found type `()` + +error[E0308]: mismatched types + --> $DIR/issue-13428.rs:21:20 + | +21 | fn bar() -> String { //~ ERROR mismatched types + | ____________________^ +22 | | "foobar".to_string() +23 | | ; //~ HELP consider removing this semicolon + | | - help: consider removing this semicolon +24 | | } + | |_^ expected struct `std::string::String`, found () + | + = note: expected type `std::string::String` + found type `()` + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/issue-13624.rs b/src/test/ui/block-result/issue-13624.rs similarity index 100% rename from src/test/compile-fail/issue-13624.rs rename to src/test/ui/block-result/issue-13624.rs diff --git a/src/test/ui/block-result/issue-13624.stderr b/src/test/ui/block-result/issue-13624.stderr new file mode 100644 index 0000000000..41113eb7a5 --- /dev/null +++ b/src/test/ui/block-result/issue-13624.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/issue-13624.rs:17:5 + | +17 | Enum::EnumStructVariant { x: 1, y: 2, z: 3 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum` + | + = note: expected type `()` + found type `a::Enum` + +error[E0308]: mismatched types + --> $DIR/issue-13624.rs:32:9 + | +32 | a::Enum::EnumStructVariant { x, y, z } => { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum` + | + = note: expected type `()` + found type `a::Enum` + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/issue-20862.rs b/src/test/ui/block-result/issue-20862.rs similarity index 100% rename from src/test/compile-fail/issue-20862.rs rename to src/test/ui/block-result/issue-20862.rs diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr new file mode 100644 index 0000000000..7c88d789fd --- /dev/null +++ b/src/test/ui/block-result/issue-20862.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/issue-20862.rs:12:5 + | +11 | fn foo(x: i32) { + | - possibly return type missing here? +12 | |y| x + y + | ^^^^^^^^^ expected (), found closure + | + = note: expected type `()` + found type `[closure@$DIR/issue-20862.rs:12:5: 12:14 x:_]` + +error[E0618]: expected function, found `()` + --> $DIR/issue-20862.rs:17:13 + | +17 | let x = foo(5)(2); + | ^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/issue-22645.rs b/src/test/ui/block-result/issue-22645.rs similarity index 100% rename from src/test/compile-fail/issue-22645.rs rename to src/test/ui/block-result/issue-22645.rs diff --git a/src/test/ui/block-result/issue-22645.stderr b/src/test/ui/block-result/issue-22645.stderr new file mode 100644 index 0000000000..a9bcc8bea9 --- /dev/null +++ b/src/test/ui/block-result/issue-22645.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `{integer}: Scalar` is not satisfied + --> $DIR/issue-22645.rs:25:5 + | +25 | b + 3 //~ ERROR E0277 + | ^ the trait `Scalar` is not implemented for `{integer}` + | + = help: the following implementations were found: + + = note: required because of the requirements on the impl of `std::ops::Add<{integer}>` for `Bob` + +error[E0308]: mismatched types + --> $DIR/issue-22645.rs:25:3 + | +25 | b + 3 //~ ERROR E0277 + | ^^^^^ expected (), found struct `Bob` + | + = note: expected type `()` + found type `Bob` + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/issue-3563.rs b/src/test/ui/block-result/issue-3563.rs similarity index 100% rename from src/test/compile-fail/issue-3563.rs rename to src/test/ui/block-result/issue-3563.rs diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr new file mode 100644 index 0000000000..4b1f8b032b --- /dev/null +++ b/src/test/ui/block-result/issue-3563.stderr @@ -0,0 +1,19 @@ +error[E0599]: no method named `b` found for type `&Self` in the current scope + --> $DIR/issue-3563.rs:13:17 + | +13 | || self.b() + | ^ + +error[E0308]: mismatched types + --> $DIR/issue-3563.rs:13:9 + | +12 | fn a(&self) { + | - possibly return type missing here? +13 | || self.b() + | ^^^^^^^^^^^ expected (), found closure + | + = note: expected type `()` + found type `[closure@$DIR/issue-3563.rs:13:9: 13:20 self:_]` + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/issue-5500.rs b/src/test/ui/block-result/issue-5500.rs similarity index 100% rename from src/test/compile-fail/issue-5500.rs rename to src/test/ui/block-result/issue-5500.rs diff --git a/src/test/ui/block-result/issue-5500.stderr b/src/test/ui/block-result/issue-5500.stderr new file mode 100644 index 0000000000..bd670a14f2 --- /dev/null +++ b/src/test/ui/block-result/issue-5500.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/issue-5500.rs:12:5 + | +12 | &panic!() + | ^^^^^^^^^ expected (), found reference + | + = note: expected type `()` + found type `&_` + +error: aborting due to previous error + diff --git a/src/test/ui/block-result/unexpected-return-on-unit.rs b/src/test/ui/block-result/unexpected-return-on-unit.rs new file mode 100644 index 0000000000..291b7a16f1 --- /dev/null +++ b/src/test/ui/block-result/unexpected-return-on-unit.rs @@ -0,0 +1,24 @@ +// 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. + +// Test that we do some basic error correcton in the tokeniser (and don't spew +// too many bogus errors). + +fn foo() -> usize { + 3 +} + +fn bar() { + foo() +} + +fn main() { + bar() +} diff --git a/src/test/ui/block-result/unexpected-return-on-unit.stderr b/src/test/ui/block-result/unexpected-return-on-unit.stderr new file mode 100644 index 0000000000..c8743c72e3 --- /dev/null +++ b/src/test/ui/block-result/unexpected-return-on-unit.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/unexpected-return-on-unit.rs:19:5 + | +19 | foo() + | ^^^^^ expected (), found usize + | + = note: expected type `()` + found type `usize` +help: did you mean to add a semicolon here? + | +19 | foo(); + | ^ +help: possibly return type missing here? + | +18 | fn bar() -> usize { + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/borrowck/borrowck-in-static.stderr b/src/test/ui/borrowck/borrowck-in-static.stderr index a30d4cbd64..6083a82b1b 100644 --- a/src/test/ui/borrowck/borrowck-in-static.stderr +++ b/src/test/ui/borrowck/borrowck-in-static.stderr @@ -6,5 +6,5 @@ error[E0507]: cannot move out of captured outer variable in an `Fn` closure 15 | Box::new(|| x) //~ ERROR cannot move out of captured outer variable | ^ cannot move out of captured outer variable in an `Fn` closure -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr index a13971d32d..dbfcb2e0c2 100644 --- a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr +++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr @@ -7,5 +7,5 @@ error[E0507]: cannot move out of captured outer variable in an `Fn` closure 21 | y.into_iter(); | ^ cannot move out of captured outer variable in an `Fn` closure -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/compile-fail/auxiliary/allocator-dylib2.rs b/src/test/ui/cast-to-unsized-trait-object-suggestion.rs similarity index 89% rename from src/test/compile-fail/auxiliary/allocator-dylib2.rs rename to src/test/ui/cast-to-unsized-trait-object-suggestion.rs index 0d76c0e5eb..c793454798 100644 --- a/src/test/compile-fail/auxiliary/allocator-dylib2.rs +++ b/src/test/ui/cast-to-unsized-trait-object-suggestion.rs @@ -8,5 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub fn foo() {} - +fn main() { + &1 as Send; + Box::new(1) as Send; +} diff --git a/src/test/ui/cast-to-unsized-trait-object-suggestion.stderr b/src/test/ui/cast-to-unsized-trait-object-suggestion.stderr new file mode 100644 index 0000000000..4d4eb7b4ec --- /dev/null +++ b/src/test/ui/cast-to-unsized-trait-object-suggestion.stderr @@ -0,0 +1,18 @@ +error[E0620]: cast to unsized type: `&{integer}` as `std::marker::Send` + --> $DIR/cast-to-unsized-trait-object-suggestion.rs:12:5 + | +12 | &1 as Send; + | ^^^^^^---- + | | + | help: try casting to a reference instead: `&Send` + +error[E0620]: cast to unsized type: `std::boxed::Box<{integer}>` as `std::marker::Send` + --> $DIR/cast-to-unsized-trait-object-suggestion.rs:13:5 + | +13 | Box::new(1) as Send; + | ^^^^^^^^^^^^^^^---- + | | + | help: try casting to a `Box` instead: `Box` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/check_match/issue-35609.stderr b/src/test/ui/check_match/issue-35609.stderr index 0cb264ff35..0aafe3f17b 100644 --- a/src/test/ui/check_match/issue-35609.stderr +++ b/src/test/ui/check_match/issue-35609.stderr @@ -46,5 +46,5 @@ error[E0004]: non-exhaustive patterns: `Some(B)`, `Some(C)`, `Some(D)` and 2 mor 49 | match Some(A) { | ^^^^^^^ patterns `Some(B)`, `Some(C)`, `Some(D)` and 2 more not covered -error: aborting due to previous error(s) +error: aborting due to 8 previous errors diff --git a/src/test/ui/check_match/issue-43253.rs b/src/test/ui/check_match/issue-43253.rs new file mode 100644 index 0000000000..c77fa74f6e --- /dev/null +++ b/src/test/ui/check_match/issue-43253.rs @@ -0,0 +1,51 @@ +// 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. + +#![feature(exclusive_range_pattern)] + +fn main() { + // These cases should generate no warning. + match 10 { + 1..10 => {}, + 10 => {}, + _ => {}, + } + + match 10 { + 1..10 => {}, + 9...10 => {}, + _ => {}, + } + + match 10 { + 1..10 => {}, + 10...10 => {}, + _ => {}, + } + + // These cases should generate an "unreachable pattern" warning. + match 10 { + 1..10 => {}, + 9 => {}, + _ => {}, + } + + match 10 { + 1..10 => {}, + 8...9 => {}, + _ => {}, + } + + match 10 { + 1..10 => {}, + 9...9 => {}, + _ => {}, + } +} \ No newline at end of file diff --git a/src/test/ui/check_match/issue-43253.stderr b/src/test/ui/check_match/issue-43253.stderr new file mode 100644 index 0000000000..0d4a2ecf51 --- /dev/null +++ b/src/test/ui/check_match/issue-43253.stderr @@ -0,0 +1,20 @@ +warning: unreachable pattern + --> $DIR/issue-43253.rs:36:9 + | +36 | 9 => {}, + | ^ + | + = note: #[warn(unreachable_patterns)] on by default + +warning: unreachable pattern + --> $DIR/issue-43253.rs:42:9 + | +42 | 8...9 => {}, + | ^^^^^ + +warning: unreachable pattern + --> $DIR/issue-43253.rs:48:9 + | +48 | 9...9 => {}, + | ^^^^^ + diff --git a/src/test/ui/closure_context/issue-26046-fn-mut.rs b/src/test/ui/closure_context/issue-26046-fn-mut.rs new file mode 100644 index 0000000000..5ed7ace543 --- /dev/null +++ b/src/test/ui/closure_context/issue-26046-fn-mut.rs @@ -0,0 +1,21 @@ +// 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. + +fn foo() -> Box { + let num = 5; + + let closure = || { + num += 1; + }; + + Box::new(closure) +} + +fn main() {} diff --git a/src/test/ui/closure_context/issue-26046-fn-mut.stderr b/src/test/ui/closure_context/issue-26046-fn-mut.stderr new file mode 100644 index 0000000000..42fc2909df --- /dev/null +++ b/src/test/ui/closure_context/issue-26046-fn-mut.stderr @@ -0,0 +1,20 @@ +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut` + --> $DIR/issue-26046-fn-mut.rs:14:19 + | +14 | let closure = || { + | ___________________^ +15 | | num += 1; +16 | | }; + | |_____^ +17 | +18 | Box::new(closure) + | ----------------- the requirement to implement `Fn` derives from here + | +note: closure is `FnMut` because it mutates the variable `num` here + --> $DIR/issue-26046-fn-mut.rs:15:9 + | +15 | num += 1; + | ^^^ + +error: aborting due to previous error + diff --git a/src/test/compile-fail/two-allocators.rs b/src/test/ui/closure_context/issue-26046-fn-once.rs similarity index 65% rename from src/test/compile-fail/two-allocators.rs rename to src/test/ui/closure_context/issue-26046-fn-once.rs index a34f77de24..de06de530c 100644 --- a/src/test/compile-fail/two-allocators.rs +++ b/src/test/ui/closure_context/issue-26046-fn-once.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: cannot link together two allocators +fn get_closure() -> Box Vec> { + let vec = vec![1u8, 2u8]; -// aux-build:allocator1.rs -// aux-build:allocator2.rs + let closure = move || { + vec + }; -extern crate allocator1; -extern crate allocator2; + Box::new(closure) +} fn main() {} diff --git a/src/test/ui/closure_context/issue-26046-fn-once.stderr b/src/test/ui/closure_context/issue-26046-fn-once.stderr new file mode 100644 index 0000000000..7bfe72d3d6 --- /dev/null +++ b/src/test/ui/closure_context/issue-26046-fn-once.stderr @@ -0,0 +1,20 @@ +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` + --> $DIR/issue-26046-fn-once.rs:14:19 + | +14 | let closure = move || { + | ___________________^ +15 | | vec +16 | | }; + | |_____^ +17 | +18 | Box::new(closure) + | ----------------- the requirement to implement `Fn` derives from here + | +note: closure is `FnOnce` because it moves the variable `vec` out of its environment + --> $DIR/issue-26046-fn-once.rs:15:9 + | +15 | vec + | ^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/fn_once-moved.rs b/src/test/ui/closure_context/issue-42065.rs similarity index 100% rename from src/test/ui/fn_once-moved.rs rename to src/test/ui/closure_context/issue-42065.rs diff --git a/src/test/ui/fn_once-moved.stderr b/src/test/ui/closure_context/issue-42065.stderr similarity index 78% rename from src/test/ui/fn_once-moved.stderr rename to src/test/ui/closure_context/issue-42065.stderr index 27b7d91d1d..c195940ade 100644 --- a/src/test/ui/fn_once-moved.stderr +++ b/src/test/ui/closure_context/issue-42065.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `debug_dump_dict` - --> $DIR/fn_once-moved.rs:21:5 + --> $DIR/issue-42065.rs:21:5 | 20 | debug_dump_dict(); | --------------- value moved here @@ -7,10 +7,10 @@ error[E0382]: use of moved value: `debug_dump_dict` | ^^^^^^^^^^^^^^^ value used here after move | note: closure cannot be invoked more than once because it moves the variable `dict` out of its environment - --> $DIR/fn_once-moved.rs:16:29 + --> $DIR/issue-42065.rs:16:29 | 16 | for (key, value) in dict { | ^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/bad-format-args.stderr b/src/test/ui/codemap_tests/bad-format-args.stderr index cddc7df85a..87255dfe77 100644 --- a/src/test/ui/codemap_tests/bad-format-args.stderr +++ b/src/test/ui/codemap_tests/bad-format-args.stderr @@ -22,5 +22,5 @@ error: expected token: `,` | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr b/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr index 1c32ce4410..7f1ab929c6 100644 --- a/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr +++ b/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr @@ -6,5 +6,5 @@ error[E0592]: duplicate definitions with name `f` 15 | impl C { fn f() {} } | --------- other definition for `f` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/empty_span.stderr b/src/test/ui/codemap_tests/empty_span.stderr index 84e6e336b9..b33dee6b4a 100644 --- a/src/test/ui/codemap_tests/empty_span.stderr +++ b/src/test/ui/codemap_tests/empty_span.stderr @@ -4,5 +4,5 @@ error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, 17 | unsafe impl Send for &'static Foo { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/huge_multispan_highlight.stderr b/src/test/ui/codemap_tests/huge_multispan_highlight.stderr index 46b3db18e8..914db98c78 100644 --- a/src/test/ui/codemap_tests/huge_multispan_highlight.stderr +++ b/src/test/ui/codemap_tests/huge_multispan_highlight.stderr @@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable local variable `x` as mutable 100 | let y = &mut x; | ^ cannot borrow mutably -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/issue-11715.stderr b/src/test/ui/codemap_tests/issue-11715.stderr index dcc21672c5..4947cbedd2 100644 --- a/src/test/ui/codemap_tests/issue-11715.stderr +++ b/src/test/ui/codemap_tests/issue-11715.stderr @@ -8,5 +8,5 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time 101 | } | - first borrow ends here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/issue-28308.stderr b/src/test/ui/codemap_tests/issue-28308.stderr index 43743b796d..7a1478104f 100644 --- a/src/test/ui/codemap_tests/issue-28308.stderr +++ b/src/test/ui/codemap_tests/issue-28308.stderr @@ -6,5 +6,5 @@ error[E0600]: cannot apply unary operator `!` to type `&'static str` | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/one_line.stderr b/src/test/ui/codemap_tests/one_line.stderr index e2e0537226..a73575a8d5 100644 --- a/src/test/ui/codemap_tests/one_line.stderr +++ b/src/test/ui/codemap_tests/one_line.stderr @@ -7,5 +7,5 @@ error[E0499]: cannot borrow `v` as mutable more than once at a time | | second mutable borrow occurs here | first mutable borrow occurs here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr b/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr index 0af8c06cfd..de8a24cf33 100644 --- a/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr +++ b/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr @@ -25,5 +25,5 @@ error[E0592]: duplicate definitions with name `baz` 43 | fn baz(&self) {} | ---------------- other definition for `baz` -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/codemap_tests/overlapping_spans.stderr b/src/test/ui/codemap_tests/overlapping_spans.stderr index 9778015766..d32b18d670 100644 --- a/src/test/ui/codemap_tests/overlapping_spans.stderr +++ b/src/test/ui/codemap_tests/overlapping_spans.stderr @@ -7,5 +7,5 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait | | hint: to prevent move, use `ref _s` or `ref mut _s` | cannot move out of here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/tab.stderr b/src/test/ui/codemap_tests/tab.stderr index a3b76159b4..657deca4e6 100644 --- a/src/test/ui/codemap_tests/tab.stderr +++ b/src/test/ui/codemap_tests/tab.stderr @@ -4,5 +4,5 @@ error[E0425]: cannot find value `bar` in this scope 14 | \tbar; | \t^^^ not found in this scope -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/unicode.stderr b/src/test/ui/codemap_tests/unicode.stderr index 0f1e008d58..0828fd28b5 100644 --- a/src/test/ui/codemap_tests/unicode.stderr +++ b/src/test/ui/codemap_tests/unicode.stderr @@ -4,5 +4,5 @@ error: invalid ABI: expected one of [cdecl, stdcall, fastcall, vectorcall, thisc 11 | extern "路濫狼á́́" fn foo() {} | ^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/coercion-missing-tail-expected-type.rs b/src/test/ui/coercion-missing-tail-expected-type.rs index 489ad817ea..15ce79a054 100644 --- a/src/test/ui/coercion-missing-tail-expected-type.rs +++ b/src/test/ui/coercion-missing-tail-expected-type.rs @@ -14,6 +14,10 @@ fn plus_one(x: i32) -> i32 { x + 1; } +fn foo() -> Result { + Ok(1); +} + fn main() { let x = plus_one(5); println!("X = {}", x); diff --git a/src/test/ui/coercion-missing-tail-expected-type.stderr b/src/test/ui/coercion-missing-tail-expected-type.stderr index 28a99e58ec..0de0a25e68 100644 --- a/src/test/ui/coercion-missing-tail-expected-type.stderr +++ b/src/test/ui/coercion-missing-tail-expected-type.stderr @@ -4,16 +4,25 @@ error[E0308]: mismatched types 13 | fn plus_one(x: i32) -> i32 { | ____________________________^ 14 | | x + 1; + | | - help: consider removing this semicolon 15 | | } | |_^ expected i32, found () | = note: expected type `i32` found type `()` -help: consider removing this semicolon: - --> $DIR/coercion-missing-tail-expected-type.rs:14:10 + +error[E0308]: mismatched types + --> $DIR/coercion-missing-tail-expected-type.rs:17:29 | -14 | x + 1; - | ^ +17 | fn foo() -> Result { + | _____________________________^ +18 | | Ok(1); + | | - help: consider removing this semicolon +19 | | } + | |_^ expected enum `std::result::Result`, found () + | + = note: expected type `std::result::Result` + found type `()` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/compare-method/proj-outlives-region.rs b/src/test/ui/compare-method/proj-outlives-region.rs index 54cfe4be9c..eab01e9e98 100644 --- a/src/test/ui/compare-method/proj-outlives-region.rs +++ b/src/test/ui/compare-method/proj-outlives-region.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(dead_code)] -#![deny(extra_requirement_in_impl)] - // Test that we elaborate `Type: 'region` constraints and infer various important things. trait Master<'a, T: ?Sized, U> { diff --git a/src/test/ui/compare-method/proj-outlives-region.stderr b/src/test/ui/compare-method/proj-outlives-region.stderr index 63c48ffe26..b1b5aedea7 100644 --- a/src/test/ui/compare-method/proj-outlives-region.stderr +++ b/src/test/ui/compare-method/proj-outlives-region.stderr @@ -1,15 +1,15 @@ error[E0276]: impl has stricter requirements than trait - --> $DIR/proj-outlives-region.rs:22:5 + --> $DIR/proj-outlives-region.rs:19:5 | -17 | fn foo() where T: 'a; +14 | fn foo() where T: 'a; | --------------------- definition of `foo` from trait ... -22 | fn foo() where U: 'a { } //~ ERROR E0276 +19 | fn foo() where U: 'a { } //~ ERROR E0276 | ^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `U: 'a` | = note: #[deny(extra_requirement_in_impl)] on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #37166 -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/compare-method/region-extra-2.stderr b/src/test/ui/compare-method/region-extra-2.stderr index 7adcc66d75..af974d5018 100644 --- a/src/test/ui/compare-method/region-extra-2.stderr +++ b/src/test/ui/compare-method/region-extra-2.stderr @@ -10,5 +10,5 @@ error[E0276]: impl has stricter requirements than trait 22 | | } | |_____^ impl has extra requirement `'a: 'b` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/compare-method/region-extra.rs b/src/test/ui/compare-method/region-extra.rs index d61d025021..e359f08096 100644 --- a/src/test/ui/compare-method/region-extra.rs +++ b/src/test/ui/compare-method/region-extra.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(dead_code)] -#![deny(extra_requirement_in_impl)] - // Test that you cannot add an extra where clause in the impl relating // two regions. diff --git a/src/test/ui/compare-method/region-extra.stderr b/src/test/ui/compare-method/region-extra.stderr index a29a292ac6..bc42b50581 100644 --- a/src/test/ui/compare-method/region-extra.stderr +++ b/src/test/ui/compare-method/region-extra.stderr @@ -1,11 +1,11 @@ error[E0276]: impl has stricter requirements than trait - --> $DIR/region-extra.rs:22:5 + --> $DIR/region-extra.rs:19:5 | -18 | fn foo(); +15 | fn foo(); | --------- definition of `foo` from trait ... -22 | fn foo() where 'a: 'b { } +19 | fn foo() where 'a: 'b { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `'a: 'b` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/compare-method/region-unrelated.rs b/src/test/ui/compare-method/region-unrelated.rs index 8f79b30bd5..719e15fdb6 100644 --- a/src/test/ui/compare-method/region-unrelated.rs +++ b/src/test/ui/compare-method/region-unrelated.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(dead_code)] -#![deny(extra_requirement_in_impl)] - // Test that we elaborate `Type: 'region` constraints and infer various important things. trait Master<'a, T: ?Sized, U> { diff --git a/src/test/ui/compare-method/region-unrelated.stderr b/src/test/ui/compare-method/region-unrelated.stderr index 04de54cd05..b02aa5eeb2 100644 --- a/src/test/ui/compare-method/region-unrelated.stderr +++ b/src/test/ui/compare-method/region-unrelated.stderr @@ -1,15 +1,15 @@ error[E0276]: impl has stricter requirements than trait - --> $DIR/region-unrelated.rs:22:5 + --> $DIR/region-unrelated.rs:19:5 | -17 | fn foo() where T: 'a; +14 | fn foo() where T: 'a; | --------------------- definition of `foo` from trait ... -22 | fn foo() where V: 'a { } +19 | fn foo() where V: 'a { } | ^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `V: 'a` | = note: #[deny(extra_requirement_in_impl)] on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #37166 -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/compare-method/reordered-type-param.stderr b/src/test/ui/compare-method/reordered-type-param.stderr index b5e9c89f2f..4620248e2e 100644 --- a/src/test/ui/compare-method/reordered-type-param.stderr +++ b/src/test/ui/compare-method/reordered-type-param.stderr @@ -10,5 +10,5 @@ error[E0053]: method `b` has an incompatible type for trait = note: expected type `fn(&E, F) -> F` found type `fn(&E, G) -> G` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr b/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr index c4a4921289..7112a00c7b 100644 --- a/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr +++ b/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr @@ -7,5 +7,5 @@ error[E0276]: impl has stricter requirements than trait 25 | fn b(&self, _x: F) -> F { panic!() } //~ ERROR E0276 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `F: std::marker::Sync` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/compare-method/traits-misc-mismatch-1.stderr b/src/test/ui/compare-method/traits-misc-mismatch-1.stderr index 6374b83e79..f221ebe330 100644 --- a/src/test/ui/compare-method/traits-misc-mismatch-1.stderr +++ b/src/test/ui/compare-method/traits-misc-mismatch-1.stderr @@ -61,5 +61,5 @@ error[E0276]: impl has stricter requirements than trait 76 | fn method>(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `G: Getter` -error: aborting due to previous error(s) +error: aborting due to 7 previous errors diff --git a/src/test/ui/compare-method/traits-misc-mismatch-2.stderr b/src/test/ui/compare-method/traits-misc-mismatch-2.stderr index 7ff2d93d82..622e144c53 100644 --- a/src/test/ui/compare-method/traits-misc-mismatch-2.stderr +++ b/src/test/ui/compare-method/traits-misc-mismatch-2.stderr @@ -10,5 +10,5 @@ error[E0276]: impl has stricter requirements than trait 26 | | } | |_____^ impl has extra requirement `U: Iterator` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/cross-crate-macro-backtrace/main.stderr b/src/test/ui/cross-crate-macro-backtrace/main.stderr index 3642a702a8..84db85ac09 100644 --- a/src/test/ui/cross-crate-macro-backtrace/main.stderr +++ b/src/test/ui/cross-crate-macro-backtrace/main.stderr @@ -6,5 +6,5 @@ error: invalid reference to argument `0` (no arguments given) | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/E0178.stderr b/src/test/ui/did_you_mean/E0178.stderr index bcf00df983..15e7131cfd 100644 --- a/src/test/ui/did_you_mean/E0178.stderr +++ b/src/test/ui/did_you_mean/E0178.stderr @@ -22,5 +22,5 @@ error[E0178]: expected a path on the left-hand side of `+`, not `fn() -> Foo` 17 | z: fn() -> Foo + 'a, | ^^^^^^^^^^^^^^^^ perhaps you forgot parentheses? -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr index 73b8e06183..9010de081d 100644 --- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr +++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr @@ -8,5 +8,5 @@ error[E0277]: the trait bound `Bar: Foo` is not satisfied > > -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr index e1e4e14b21..e9591a6478 100644 --- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr +++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr @@ -11,5 +11,5 @@ error[E0277]: the trait bound `Bar: Foo` is not satisfied > and 2 others -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-31424.stderr b/src/test/ui/did_you_mean/issue-31424.stderr index eecb164a83..c7d43a0fc0 100644 --- a/src/test/ui/did_you_mean/issue-31424.stderr +++ b/src/test/ui/did_you_mean/issue-31424.stderr @@ -15,5 +15,5 @@ error[E0596]: cannot borrow immutable argument `self` as mutable 23 | (&mut self).bar(); | ^^^^ cannot borrow mutably -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/did_you_mean/issue-34126.stderr b/src/test/ui/did_you_mean/issue-34126.stderr index d5d6ee133b..63d59a5923 100644 --- a/src/test/ui/did_you_mean/issue-34126.stderr +++ b/src/test/ui/did_you_mean/issue-34126.stderr @@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable argument `self` as mutable | try removing `&mut` here | cannot reborrow mutably -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-34337.stderr b/src/test/ui/did_you_mean/issue-34337.stderr index 2769c74be5..9eb88cdedd 100644 --- a/src/test/ui/did_you_mean/issue-34337.stderr +++ b/src/test/ui/did_you_mean/issue-34337.stderr @@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable local variable `key` as mutable | try removing `&mut` here | cannot reborrow mutably -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-35937.stderr b/src/test/ui/did_you_mean/issue-35937.stderr index 4760d28566..1cd1fb76aa 100644 --- a/src/test/ui/did_you_mean/issue-35937.stderr +++ b/src/test/ui/did_you_mean/issue-35937.stderr @@ -22,5 +22,5 @@ error[E0594]: cannot assign to immutable field `s.x` 30 | s.x += 1; | ^^^^^^^^ cannot mutably borrow immutable field -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/did_you_mean/issue-36798.stderr b/src/test/ui/did_you_mean/issue-36798.stderr index ea628f10e0..72fd09c035 100644 --- a/src/test/ui/did_you_mean/issue-36798.stderr +++ b/src/test/ui/did_you_mean/issue-36798.stderr @@ -1,8 +1,8 @@ -error: no field `baz` on type `Foo` +error[E0609]: no field `baz` on type `Foo` --> $DIR/issue-36798.rs:17:7 | 17 | f.baz; | ^^^ did you mean `bar`? -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr b/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr index a9090e3911..82e3eab083 100644 --- a/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr +++ b/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr @@ -1,8 +1,8 @@ -error: no field `zz` on type `Foo` +error[E0609]: no field `zz` on type `Foo` --> $DIR/issue-36798_unknown_field.rs:17:7 | 17 | f.zz; | ^^ unknown field -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-37139.stderr b/src/test/ui/did_you_mean/issue-37139.stderr index 6debbaadb1..4348b6fca6 100644 --- a/src/test/ui/did_you_mean/issue-37139.stderr +++ b/src/test/ui/did_you_mean/issue-37139.stderr @@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable local variable `x` as mutable | try removing `&mut` here | cannot reborrow mutably -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr index 10f5972e36..325f55e686 100644 --- a/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr +++ b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr @@ -10,5 +10,5 @@ error[E0432]: unresolved import `Foo1` 13 | use Foo1; | ^^^^ no `Foo1` in the root -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/did_you_mean/issue-38147-1.stderr b/src/test/ui/did_you_mean/issue-38147-1.stderr index 85eecd037d..e9f2b1dad8 100644 --- a/src/test/ui/did_you_mean/issue-38147-1.stderr +++ b/src/test/ui/did_you_mean/issue-38147-1.stderr @@ -6,5 +6,5 @@ error[E0389]: cannot borrow data mutably in a `&` reference 27 | self.s.push('x'); | ^^^^^^ assignment into an immutable reference -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-38147-2.stderr b/src/test/ui/did_you_mean/issue-38147-2.stderr index 2834fc6262..e81bc722fa 100644 --- a/src/test/ui/did_you_mean/issue-38147-2.stderr +++ b/src/test/ui/did_you_mean/issue-38147-2.stderr @@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable borrowed content `*self.s` as mutable 17 | self.s.push('x'); | ^^^^^^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-38147-3.stderr b/src/test/ui/did_you_mean/issue-38147-3.stderr index d950e82003..749795f4d8 100644 --- a/src/test/ui/did_you_mean/issue-38147-3.stderr +++ b/src/test/ui/did_you_mean/issue-38147-3.stderr @@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable borrowed content `*self.s` as mutable 17 | self.s.push('x'); | ^^^^^^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-38147-4.stderr b/src/test/ui/did_you_mean/issue-38147-4.stderr index 6fa152c970..9a8853f4fb 100644 --- a/src/test/ui/did_you_mean/issue-38147-4.stderr +++ b/src/test/ui/did_you_mean/issue-38147-4.stderr @@ -6,5 +6,5 @@ error[E0389]: cannot borrow data mutably in a `&` reference 16 | f.s.push('x'); | ^^^ assignment into an immutable reference -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-39544.stderr b/src/test/ui/did_you_mean/issue-39544.stderr index 94afe896d5..28aaab97bd 100644 --- a/src/test/ui/did_you_mean/issue-39544.stderr +++ b/src/test/ui/did_you_mean/issue-39544.stderr @@ -96,5 +96,5 @@ error[E0594]: cannot assign to immutable borrowed content `*x.0` 58 | *x.0 = 1; | ^^^^^^^^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to 12 previous errors diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr index 6a0e94bf13..4ea4adfcfe 100644 --- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr +++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr @@ -39,5 +39,5 @@ error[E0277]: the trait bound `bool: Foo` is not satisfied and 2 others = note: required by `Foo::bar` -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index b1dab01d81..3b7f32cf89 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -64,5 +64,5 @@ error[E0038]: the trait `X` cannot be made into an object | = note: method `xxx` has no receiver -error: aborting due to previous error(s) +error: aborting due to 9 previous errors diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr index daee8df7ed..1a0c74dc01 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -30,5 +30,5 @@ error: chained comparison operators require parentheses | = help: use `::<...>` instead of `<...>` if you meant to specify type arguments -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/did_you_mean/issue-40823.stderr b/src/test/ui/did_you_mean/issue-40823.stderr index a034ea8096..7daab09c09 100644 --- a/src/test/ui/did_you_mean/issue-40823.stderr +++ b/src/test/ui/did_you_mean/issue-40823.stderr @@ -4,5 +4,5 @@ error[E0596]: cannot borrow immutable borrowed content `*buf` as mutable 13 | buf.iter_mut(); | ^^^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-41679.stderr b/src/test/ui/did_you_mean/issue-41679.stderr index 4f210bb0b1..2abbbf65ba 100644 --- a/src/test/ui/did_you_mean/issue-41679.stderr +++ b/src/test/ui/did_you_mean/issue-41679.stderr @@ -6,5 +6,5 @@ error: `~` can not be used as a unary operator | = help: use `!` instead of `~` if you meant to perform bitwise negation -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/recursion_limit.stderr b/src/test/ui/did_you_mean/recursion_limit.stderr index 32f9d90ec2..d157c5de6c 100644 --- a/src/test/ui/did_you_mean/recursion_limit.stderr +++ b/src/test/ui/did_you_mean/recursion_limit.stderr @@ -17,5 +17,5 @@ error[E0275]: overflow evaluating the requirement `K: std::marker::Send` = note: required because it appears within the type `A` = note: required by `is_send` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.stderr b/src/test/ui/did_you_mean/recursion_limit_deref.stderr index ba8d381518..57b28d0373 100644 --- a/src/test/ui/did_you_mean/recursion_limit_deref.stderr +++ b/src/test/ui/did_you_mean/recursion_limit_deref.stderr @@ -19,5 +19,5 @@ error[E0308]: mismatched types = note: expected type `&Bottom` found type `&Top` -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr b/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr index 50e296a1bc..498255cb9e 100644 --- a/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr +++ b/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr @@ -18,5 +18,5 @@ error[E0038]: the trait `std::marker::Copy` cannot be made into an object | = note: the trait cannot require that `Self : Sized` -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr b/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr index a5a3c48ab9..62ce3209c9 100644 --- a/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr +++ b/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr @@ -42,5 +42,5 @@ error[E0597]: `c` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr index e1bfb4d8c1..2c788e952e 100644 --- a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr +++ b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr @@ -20,5 +20,5 @@ error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attri 43 | | } | |_^ -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/dropck/dropck-eyepatch-reorder.stderr b/src/test/ui/dropck/dropck-eyepatch-reorder.stderr index de04a1c428..d94808bbcb 100644 --- a/src/test/ui/dropck/dropck-eyepatch-reorder.stderr +++ b/src/test/ui/dropck/dropck-eyepatch-reorder.stderr @@ -42,5 +42,5 @@ error[E0597]: `c` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/dropck/dropck-eyepatch.stderr b/src/test/ui/dropck/dropck-eyepatch.stderr index 26fee852fb..811eee0e85 100644 --- a/src/test/ui/dropck/dropck-eyepatch.stderr +++ b/src/test/ui/dropck/dropck-eyepatch.stderr @@ -42,5 +42,5 @@ error[E0597]: `c` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/enum-size-variance.rs b/src/test/ui/enum-size-variance.rs index 075bd9acf5..582998a986 100644 --- a/src/test/ui/enum-size-variance.rs +++ b/src/test/ui/enum-size-variance.rs @@ -9,10 +9,6 @@ // except according to those terms. // run-pass -// ignore-x86 -// ignore-arm -// ignore-emscripten -// ^ ignore 32-bit targets, as the error message is target-dependent. see PR #41968. #![warn(variant_size_differences)] #![allow(dead_code)] @@ -24,26 +20,26 @@ enum Enum1 { } enum Enum2 { A, B, C } -enum Enum3 { D(isize), E, F } +enum Enum3 { D(i64), E, F } -enum Enum4 { H(isize), I(isize), J } +enum Enum4 { H(i64), I(i64), J } enum Enum5 { - L(isize, isize, isize, isize), //~ WARNING three times larger - M(isize), + L(i64, i64, i64, i64), //~ WARNING three times larger + M(i64), N } enum Enum6 { O(T), P(U), - Q(isize) + Q(i64) } #[allow(variant_size_differences)] enum Enum7 { - R(isize, isize, isize, isize), - S(isize), + R(i64, i64, i64, i64), + S(i64), T } pub fn main() { } diff --git a/src/test/ui/enum-size-variance.stderr b/src/test/ui/enum-size-variance.stderr index 5745b9344b..a21243a499 100644 --- a/src/test/ui/enum-size-variance.stderr +++ b/src/test/ui/enum-size-variance.stderr @@ -1,12 +1,12 @@ warning: enum variant is more than three times larger (32 bytes) than the next largest - --> $DIR/enum-size-variance.rs:32:5 + --> $DIR/enum-size-variance.rs:28:5 | -32 | L(isize, isize, isize, isize), //~ WARNING three times larger - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +28 | L(i64, i64, i64, i64), //~ WARNING three times larger + | ^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/enum-size-variance.rs:17:9 + --> $DIR/enum-size-variance.rs:13:9 | -17 | #![warn(variant_size_differences)] +13 | #![warn(variant_size_differences)] | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/explain.rs b/src/test/ui/explain.rs new file mode 100644 index 0000000000..17fb59935d --- /dev/null +++ b/src/test/ui/explain.rs @@ -0,0 +1,11 @@ +// 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. + +// compile-flags: --explain E0591 diff --git a/src/test/ui/explain.stdout b/src/test/ui/explain.stdout new file mode 100644 index 0000000000..0bbbd95320 --- /dev/null +++ b/src/test/ui/explain.stdout @@ -0,0 +1,63 @@ +Per [RFC 401][rfc401], if you have a function declaration `foo`: + +``` +// For the purposes of this explanation, all of these +// different kinds of `fn` declarations are equivalent: +struct S; +fn foo(x: S) { /* ... */ } +extern "C" { fn foo(x: S); } +impl S { fn foo(self) { /* ... */ } } +``` + +the type of `foo` is **not** `fn(S)`, as one might expect. +Rather, it is a unique, zero-sized marker type written here as `typeof(foo)`. +However, `typeof(foo)` can be _coerced_ to a function pointer `fn(S)`, +so you rarely notice this: + +``` +let x: fn(S) = foo; // OK, coerces +``` + +The reason that this matter is that the type `fn(S)` is not specific to +any particular function: it's a function _pointer_. So calling `x()` results +in a virtual call, whereas `foo()` is statically dispatched, because the type +of `foo` tells us precisely what function is being called. + +As noted above, coercions mean that most code doesn't have to be +concerned with this distinction. However, you can tell the difference +when using **transmute** to convert a fn item into a fn pointer. + +This is sometimes done as part of an FFI: + +``` +extern "C" fn foo(userdata: Box) { + /* ... */ +} + +let f: extern "C" fn(*mut i32) = transmute(foo); +callback(f); +``` + +Here, transmute is being used to convert the types of the fn arguments. +This pattern is incorrect because, because the type of `foo` is a function +**item** (`typeof(foo)`), which is zero-sized, and the target type (`fn()`) +is a function pointer, which is not zero-sized. +This pattern should be rewritten. There are a few possible ways to do this: + +- change the original fn declaration to match the expected signature, + and do the cast in the fn body (the prefered option) +- cast the fn item fo a fn pointer before calling transmute, as shown here: + + ``` + let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_)); + let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too + ``` + +The same applies to transmutes to `*mut fn()`, which were observedin practice. +Note though that use of this type is generally incorrect. +The intention is typically to describe a function pointer, but just `fn()` +alone suffices for that. `*mut fn()` is a pointer to a fn pointer. +(Since these values are typically just passed to C code, however, this rarely +makes a difference in practice.) + +[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md diff --git a/src/test/ui/fmt/format-string-error.stderr b/src/test/ui/fmt/format-string-error.stderr index 2466d2b43b..58b392f0b8 100644 --- a/src/test/ui/fmt/format-string-error.stderr +++ b/src/test/ui/fmt/format-string-error.stderr @@ -16,5 +16,5 @@ error: invalid format string: unmatched `}` found = note: if you intended to print `}`, you can escape it using `}}` = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index 2206234b77..3fc08a0900 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -51,5 +51,5 @@ error[E0308]: mismatched types = note: expected type `impl Foo` (i32) found type `impl Foo` (u32) -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr b/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr index 1b1e0eaf20..3bc281726e 100644 --- a/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr +++ b/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr @@ -8,5 +8,5 @@ error[E0599]: no method named `foo` found for type `Bar` in the current scope = note: the following trait defines an item `foo`, perhaps you need to implement it: candidate #1: `Foo` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr index fa08c3bee9..d3dbb77490 100644 --- a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr +++ b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr @@ -10,5 +10,5 @@ error[E0599]: no method named `is_empty` found for type `Foo` in the current sco candidate #2: `core::slice::SliceExt` candidate #3: `core::str::StrExt` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr index 95d3007a4f..fc441f9484 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -226,5 +226,5 @@ error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::bo 131 | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3(); | ^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 24 previous errors diff --git a/src/test/ui/impl-trait/trait_type.stderr b/src/test/ui/impl-trait/trait_type.stderr index cc7a7153a3..9216c6e290 100644 --- a/src/test/ui/impl-trait/trait_type.stderr +++ b/src/test/ui/impl-trait/trait_type.stderr @@ -31,5 +31,5 @@ error[E0046]: not all trait items implemented, missing: `fmt` | = note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>` -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/interior-mutability/interior-mutability.rs b/src/test/ui/interior-mutability/interior-mutability.rs new file mode 100644 index 0000000000..60d85d1b3b --- /dev/null +++ b/src/test/ui/interior-mutability/interior-mutability.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. + +use std::cell::Cell; +use std::panic::catch_unwind; +fn main() { + let mut x = Cell::new(22); + catch_unwind(|| { x.set(23); }); +} diff --git a/src/test/ui/interior-mutability/interior-mutability.stderr b/src/test/ui/interior-mutability/interior-mutability.stderr new file mode 100644 index 0000000000..76362f1f49 --- /dev/null +++ b/src/test/ui/interior-mutability/interior-mutability.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `std::cell::UnsafeCell: std::panic::RefUnwindSafe` is not satisfied in `std::cell::Cell` + --> $DIR/interior-mutability.rs:15:5 + | +15 | catch_unwind(|| { x.set(23); }); + | ^^^^^^^^^^^^ the type std::cell::UnsafeCell may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + | + = help: within `std::cell::Cell`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell` + = note: required because it appears within the type `std::cell::Cell` + = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `&std::cell::Cell` + = note: required because it appears within the type `[closure@$DIR/interior-mutability.rs:15:18: 15:35 x:&std::cell::Cell]` + = note: required by `std::panic::catch_unwind` + +error: aborting due to previous error + diff --git a/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr index a444d5f5a4..3e9b21cdb7 100644 --- a/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr +++ b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr @@ -10,5 +10,5 @@ note: maybe move this module `$DIR/auxiliary/foo/bar.rs` to its own directory vi 11 | pub mod baz; | ^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/issue-22644.rs b/src/test/ui/issue-22644.rs new file mode 100644 index 0000000000..b482d0595f --- /dev/null +++ b/src/test/ui/issue-22644.rs @@ -0,0 +1,39 @@ +// 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. + +fn main() { + let a : u32 = 0; + let long_name : usize = 0; + + println!("{}", a as usize > long_name); + println!("{}", a as usize < long_name); + println!("{}{}", a as usize < long_name, long_name); + println!("{}", a as usize < 4); + println!("{}", a: usize > long_name); + println!("{}{}", a: usize < long_name, long_name); + println!("{}", a: usize < 4); + + println!("{}", a + as + usize + < + 4); + println!("{}", a + + + as + + + usize + < + 5); + + println!("{}", a: &mut 4); +} diff --git a/src/test/ui/issue-22644.stderr b/src/test/ui/issue-22644.stderr new file mode 100644 index 0000000000..144c5ef1ed --- /dev/null +++ b/src/test/ui/issue-22644.stderr @@ -0,0 +1,104 @@ +error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison + --> $DIR/issue-22644.rs:16:31 + | +16 | println!("{}", a as usize < long_name); + | ^ --------- interpreted as generic arguments + | | + | not interpreted as comparison + | +help: if you want to compare the casted value then write: + | +16 | println!("{}", (a as usize) < long_name); + | ^^^^^^^^^^^^ + +error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison + --> $DIR/issue-22644.rs:17:33 + | +17 | println!("{}{}", a as usize < long_name, long_name); + | ^ -------------------- interpreted as generic arguments + | | + | not interpreted as comparison + | +help: if you want to compare the casted value then write: + | +17 | println!("{}{}", (a as usize) < long_name, long_name); + | ^^^^^^^^^^^^ + +error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison + --> $DIR/issue-22644.rs:18:31 + | +18 | println!("{}", a as usize < 4); + | ^ - interpreted as generic arguments + | | + | not interpreted as comparison + | +help: if you want to compare the casted value then write: + | +18 | println!("{}", (a as usize) < 4); + | ^^^^^^^^^^^^ + +error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison + --> $DIR/issue-22644.rs:20:31 + | +20 | println!("{}{}", a: usize < long_name, long_name); + | ^ -------------------- interpreted as generic arguments + | | + | not interpreted as comparison + | +help: if you want to compare the casted value then write: + | +20 | println!("{}{}", (a: usize) < long_name, long_name); + | ^^^^^^^^^^ + +error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison + --> $DIR/issue-22644.rs:21:29 + | +21 | println!("{}", a: usize < 4); + | ^ - interpreted as generic arguments + | | + | not interpreted as comparison + | +help: if you want to compare the casted value then write: + | +21 | println!("{}", (a: usize) < 4); + | ^^^^^^^^^^ + +error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison + --> $DIR/issue-22644.rs:26:20 + | +26 | < + | ^ not interpreted as comparison +27 | 4); + | - interpreted as generic arguments + | +help: if you want to compare the casted value then write: + | +23 | println!("{}", (a +24 | as +25 | usize) + | + +error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison + --> $DIR/issue-22644.rs:35:20 + | +35 | < + | ^ not interpreted as comparison +36 | 5); + | - interpreted as generic arguments + | +help: if you want to compare the casted value then write: + | +28 | println!("{}", (a +29 | +30 | +31 | as +32 | +33 | + ... + +error: expected type, found `4` + --> $DIR/issue-22644.rs:38:28 + | +38 | println!("{}", a: &mut 4); + | ^ + diff --git a/src/test/ui/issue-26548.stderr b/src/test/ui/issue-26548.stderr index c27ad7680a..8bfe4ac733 100644 --- a/src/test/ui/issue-26548.stderr +++ b/src/test/ui/issue-26548.stderr @@ -5,5 +5,5 @@ note: ...which then requires computing layout of `std::option::Option<::It`... = note: ...which then again requires computing layout of `S`, completing the cycle. -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/issue-33525.rs b/src/test/ui/issue-33525.rs new file mode 100644 index 0000000000..0e777fe8a9 --- /dev/null +++ b/src/test/ui/issue-33525.rs @@ -0,0 +1,15 @@ +// 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. + +fn main() { + a; + "".lorem; + "".ipsum; +} diff --git a/src/test/ui/issue-33525.stderr b/src/test/ui/issue-33525.stderr new file mode 100644 index 0000000000..5de2d98f86 --- /dev/null +++ b/src/test/ui/issue-33525.stderr @@ -0,0 +1,20 @@ +error[E0425]: cannot find value `a` in this scope + --> $DIR/issue-33525.rs:12:5 + | +12 | a; + | ^ not found in this scope + +error[E0609]: no field `lorem` on type `&'static str` + --> $DIR/issue-33525.rs:13:8 + | +13 | "".lorem; + | ^^^^^ + +error[E0609]: no field `ipsum` on type `&'static str` + --> $DIR/issue-33525.rs:14:8 + | +14 | "".ipsum; + | ^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/issue-35675.rs b/src/test/ui/issue-35675.rs new file mode 100644 index 0000000000..391e1f2db5 --- /dev/null +++ b/src/test/ui/issue-35675.rs @@ -0,0 +1,51 @@ +// 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. + +// these two HELPs are actually in a new line between this line and the `enum Fruit` line +enum Fruit { //~ HELP possible candidate is found in another module, you can import it into scope + //~^ HELP possible candidate is found in another module, you can import it into scope + Apple(i64), + //~^ HELP there is an enum variant `Fruit::Apple`, did you mean to use `Fruit`? + //~| HELP there is an enum variant `Fruit::Apple`, did you mean to use `Fruit`? + Orange(i64), +} + +fn should_return_fruit() -> Apple { + //~^ ERROR cannot find type `Apple` in this scope + //~| NOTE not found in this scope + Apple(5) + //~^ ERROR cannot find function `Apple` in this scope + //~| NOTE not found in this scope +} + +fn should_return_fruit_too() -> Fruit::Apple { + //~^ ERROR expected type, found variant `Fruit::Apple` + //~| NOTE not a type + Apple(5) + //~^ ERROR cannot find function `Apple` in this scope + //~| NOTE not found in this scope +} + +fn bar() -> Variant3 { + //~^ ERROR cannot find type `Variant3` in this scope + //~| NOTE not found in this scope +} + +fn main() {} + +mod x { + enum Enum { + Variant1, + Variant2(), + Variant3(usize), + //~^ HELP there is an enum variant `x::Enum::Variant3`, did you mean to use `x::Enum`? + Variant4 {}, + } +} diff --git a/src/test/ui/issue-35675.stderr b/src/test/ui/issue-35675.stderr new file mode 100644 index 0000000000..c2c1072464 --- /dev/null +++ b/src/test/ui/issue-35675.stderr @@ -0,0 +1,51 @@ +error[E0412]: cannot find type `Apple` in this scope + --> $DIR/issue-35675.rs:20:29 + | +20 | fn should_return_fruit() -> Apple { + | ^^^^^ + | | + | not found in this scope + | help: you can try using the variant's enum: `Fruit` + +error[E0425]: cannot find function `Apple` in this scope + --> $DIR/issue-35675.rs:23:5 + | +23 | Apple(5) + | ^^^^^ not found in this scope + | +help: possible candidate is found in another module, you can import it into scope + | +12 | use Fruit::Apple; + | + +error[E0573]: expected type, found variant `Fruit::Apple` + --> $DIR/issue-35675.rs:28:33 + | +28 | fn should_return_fruit_too() -> Fruit::Apple { + | ^^^^^^^^^^^^ + | | + | not a type + | help: you can try using the variant's enum: `Fruit` + +error[E0425]: cannot find function `Apple` in this scope + --> $DIR/issue-35675.rs:31:5 + | +31 | Apple(5) + | ^^^^^ not found in this scope + | +help: possible candidate is found in another module, you can import it into scope + | +12 | use Fruit::Apple; + | + +error[E0412]: cannot find type `Variant3` in this scope + --> $DIR/issue-35675.rs:36:13 + | +36 | fn bar() -> Variant3 { + | ^^^^^^^^ + | | + | not found in this scope + | help: you can try using the variant's enum: `x::Enum` + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/issue-37311-type-length-limit/issue-37311.stderr b/src/test/ui/issue-37311-type-length-limit/issue-37311.stderr index 62223c553e..b51b683a1a 100644 --- a/src/test/ui/issue-37311-type-length-limit/issue-37311.stderr +++ b/src/test/ui/issue-37311-type-length-limit/issue-37311.stderr @@ -8,5 +8,5 @@ error: reached the type-length limit while instantiating `<(&(&(&(&(&( | = note: consider adding a `#![type_length_limit="2097152"]` attribute to your crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/issue-38875/auxiliary/issue_38875_b.rs b/src/test/ui/issue-38875/auxiliary/issue_38875_b.rs new file mode 100644 index 0000000000..dd58735209 --- /dev/null +++ b/src/test/ui/issue-38875/auxiliary/issue_38875_b.rs @@ -0,0 +1,11 @@ +// 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. + +pub const FOO: usize = *&0; diff --git a/src/test/ui/issue-38875/issue_38875.rs b/src/test/ui/issue-38875/issue_38875.rs new file mode 100644 index 0000000000..42e3c05a38 --- /dev/null +++ b/src/test/ui/issue-38875/issue_38875.rs @@ -0,0 +1,17 @@ +// 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. + +// aux-build:issue_38875_b.rs + +extern crate issue_38875_b; + +fn main() { + let test_x = [0; issue_38875_b::FOO]; +} diff --git a/src/test/ui/issue-38875/issue_38875.stderr b/src/test/ui/issue-38875/issue_38875.stderr new file mode 100644 index 0000000000..10bb61ee22 --- /dev/null +++ b/src/test/ui/issue-38875/issue_38875.stderr @@ -0,0 +1,14 @@ +error[E0080]: constant evaluation error + --> $DIR/auxiliary/issue_38875_b.rs:11:24 + | +11 | pub const FOO: usize = *&0; + | ^^^ unimplemented constant expression: deref operation + | +note: for repeat count here + --> $DIR/issue_38875.rs:16:22 + | +16 | let test_x = [0; issue_38875_b::FOO]; + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr b/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr index 80f608c1d3..26f150811b 100644 --- a/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr +++ b/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr @@ -4,8 +4,8 @@ error[E0507]: cannot move out of indexed content 19 | let e = f.v[0]; | ^^^^^^ | | - | help: consider using a reference instead `&f.v[0]` + | help: consider using a reference instead: `&f.v[0]` | cannot move out of indexed content -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/issue-40402-ref-hints/issue-40402-2.stderr b/src/test/ui/issue-40402-ref-hints/issue-40402-2.stderr index d35800ac1e..0060b683bb 100644 --- a/src/test/ui/issue-40402-ref-hints/issue-40402-2.stderr +++ b/src/test/ui/issue-40402-ref-hints/issue-40402-2.stderr @@ -7,5 +7,5 @@ error[E0507]: cannot move out of indexed content | | ...and here (use `ref b` or `ref mut b`) | hint: to prevent move, use `ref a` or `ref mut a` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/issue-41652/issue_41652.stderr b/src/test/ui/issue-41652/issue_41652.stderr index 4625e9269c..8a55c9989e 100644 --- a/src/test/ui/issue-41652/issue_41652.stderr +++ b/src/test/ui/issue-41652/issue_41652.stderr @@ -6,7 +6,12 @@ error[E0599]: no method named `f` found for type `{integer}` in the current scop | = note: found the following associated functions; to be used as methods, functions must have a `self` parameter note: candidate #1 is defined in the trait `issue_41652_b::Tr` + --> $DIR/auxiliary/issue_41652_b.rs:14:5 + | +14 | / fn f() +15 | | where Self: Sized; + | |__________________________^ = help: to disambiguate the method call, write `issue_41652_b::Tr::f(3)` instead -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/issue-42954.rs b/src/test/ui/issue-42954.rs new file mode 100644 index 0000000000..bdfdf44c0e --- /dev/null +++ b/src/test/ui/issue-42954.rs @@ -0,0 +1,20 @@ +// 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. + +macro_rules! is_plainly_printable { + ($i: ident) => { + $i as u32 < 0 + }; +} + +fn main() { + let c = 'a'; + is_plainly_printable!(c); +} diff --git a/src/test/ui/issue-42954.stderr b/src/test/ui/issue-42954.stderr new file mode 100644 index 0000000000..35995749d3 --- /dev/null +++ b/src/test/ui/issue-42954.stderr @@ -0,0 +1,18 @@ +error: `<` is interpreted as a start of generic arguments for `u32`, not a comparison + --> $DIR/issue-42954.rs:13:19 + | +13 | $i as u32 < 0 + | ^ - interpreted as generic arguments + | | + | not interpreted as comparison +... +19 | is_plainly_printable!(c); + | ------------------------- in this macro invocation + | +help: if you want to compare the casted value then write: + | +13 | ($i as u32) < 0 + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs new file mode 100644 index 0000000000..a1716c4e79 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs @@ -0,0 +1,15 @@ +// 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. + +fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { + if x > y { x } else { y } +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr new file mode 100644 index 0000000000..83716b7791 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr @@ -0,0 +1,10 @@ +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/ex1-return-one-existing-name-if-else-2.rs:12:16 + | +11 | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { + | - consider changing the type of `x` to `&'a i32` +12 | if x > y { x } else { y } + | ^ lifetime `'a` required + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs new file mode 100644 index 0000000000..7bd32d8761 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs @@ -0,0 +1,15 @@ +// 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. + +fn foo<'a>((x, y): (&'a i32, &i32)) -> &'a i32 { + if x > y { x } else { y } +} + +fn main () { } diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr new file mode 100644 index 0000000000..6d5e94a5e7 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr @@ -0,0 +1,10 @@ +error[E0621]: explicit lifetime required in parameter type + --> $DIR/ex1-return-one-existing-name-if-else-3.rs:12:27 + | +11 | fn foo<'a>((x, y): (&'a i32, &i32)) -> &'a i32 { + | ------ consider changing type to `(&'a i32, &'a i32)` +12 | if x > y { x } else { y } + | ^ lifetime `'a` required + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs new file mode 100644 index 0000000000..8849f7084b --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs @@ -0,0 +1,18 @@ +// 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. + +trait Foo { + +fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { + if x > y { x } else { y } + } +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr new file mode 100644 index 0000000000..4288fdf89a --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr @@ -0,0 +1,10 @@ +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/ex1-return-one-existing-name-if-else-using-impl-2.rs:14:15 + | +13 | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { + | - consider changing the type of `x` to `&'a i32` +14 | if x > y { x } else { y } + | ^ lifetime `'a` required + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs new file mode 100644 index 0000000000..362290ff3f --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs @@ -0,0 +1,24 @@ +// 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. + +struct Foo { + field: i32 +} + +impl Foo { + fn foo<'a>(&'a self, x: &i32) -> &i32 { + + if true { &self.field } else { x } + + } + +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr new file mode 100644 index 0000000000..95076bfbdc --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr @@ -0,0 +1,11 @@ +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:18:36 + | +16 | fn foo<'a>(&'a self, x: &i32) -> &i32 { + | - consider changing the type of `x` to `&'a i32` +17 | +18 | if true { &self.field } else { x } + | ^ lifetime `'a` required + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.rs new file mode 100644 index 0000000000..36d956a399 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.rs @@ -0,0 +1,27 @@ +// 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. + +trait Foo { + + fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32; + +} + +impl Foo for () { + + fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { + + if x > y { x } else { y } + + } + +} + +fn main() {} diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr new file mode 100644 index 0000000000..9e4f6c4217 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr @@ -0,0 +1,27 @@ +error[E0312]: lifetime of reference outlives lifetime of borrowed content... + --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:21:20 + | +21 | if x > y { x } else { y } + | ^ + | +note: ...the reference is valid for the lifetime 'a as defined on the method body at 19:5... + --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:19:5 + | +19 | / fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { +20 | | +21 | | if x > y { x } else { y } +22 | | +23 | | } + | |_____^ +note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the method body at 19:5 + --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:19:5 + | +19 | / fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { +20 | | +21 | | if x > y { x } else { y } +22 | | +23 | | } + | |_____^ + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr index 0ab24b0b3e..5d1336c7c3 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr @@ -1,23 +1,10 @@ -error[E0312]: lifetime of reference outlives lifetime of borrowed content... +error[E0621]: explicit lifetime required in the type of `y` --> $DIR/ex1-return-one-existing-name-if-else.rs:12:27 | +11 | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { + | - consider changing the type of `y` to `&'a i32` 12 | if x > y { x } else { y } - | ^ - | -note: ...the reference is valid for the lifetime 'a as defined on the function body at 11:1... - --> $DIR/ex1-return-one-existing-name-if-else.rs:11:1 - | -11 | / fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { -12 | | if x > y { x } else { y } -13 | | } - | |_^ -note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the function body at 11:1 - --> $DIR/ex1-return-one-existing-name-if-else.rs:11:1 - | -11 | / fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { -12 | | if x > y { x } else { y } -13 | | } - | |_^ + | ^ lifetime `'a` required -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs new file mode 100644 index 0000000000..96b733be9b --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs @@ -0,0 +1,24 @@ +// 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. + +struct Foo { + field: i32 +} + +impl Foo { + fn foo<'a>(&self, x: &'a i32) -> &i32 { + + x + + } + +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr new file mode 100644 index 0000000000..e3fd019205 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr @@ -0,0 +1,27 @@ +error[E0312]: lifetime of reference outlives lifetime of borrowed content... + --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:18:5 + | +18 | x + | ^ + | +note: ...the reference is valid for the anonymous lifetime #1 defined on the method body at 16:3... + --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:16:3 + | +16 | / fn foo<'a>(&self, x: &'a i32) -> &i32 { +17 | | +18 | | x +19 | | +20 | | } + | |___^ +note: ...but the borrowed content is only valid for the lifetime 'a as defined on the method body at 16:3 + --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:16:3 + | +16 | / fn foo<'a>(&self, x: &'a i32) -> &i32 { +17 | | +18 | | x +19 | | +20 | | } + | |___^ + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs new file mode 100644 index 0000000000..a8ce60c47b --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs @@ -0,0 +1,23 @@ +// 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. + +struct Foo { + field: i32, +} + +impl Foo { + fn foo<'a>(&self, x: &'a Foo) -> &'a Foo { + + if true { x } else { self } + + } +} + +fn main() {} diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr new file mode 100644 index 0000000000..8551f015db --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr @@ -0,0 +1,27 @@ +error[E0312]: lifetime of reference outlives lifetime of borrowed content... + --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:18:30 + | +18 | if true { x } else { self } + | ^^^^ + | +note: ...the reference is valid for the lifetime 'a as defined on the method body at 16:5... + --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:16:5 + | +16 | / fn foo<'a>(&self, x: &'a Foo) -> &'a Foo { +17 | | +18 | | if true { x } else { self } +19 | | +20 | | } + | |_____^ +note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the method body at 16:5 + --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:16:5 + | +16 | / fn foo<'a>(&self, x: &'a Foo) -> &'a Foo { +17 | | +18 | | if true { x } else { self } +19 | | +20 | | } + | |_____^ + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr b/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr index d005eeb404..fccc44caac 100644 --- a/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr +++ b/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr @@ -6,5 +6,5 @@ error[E0106]: missing lifetime specifier | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.rs b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.rs new file mode 100644 index 0000000000..dd34e1aa6d --- /dev/null +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.rs @@ -0,0 +1,19 @@ +// 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. + +struct Ref<'a, T: 'a> { + data: &'a T +} + +fn foo<'a>(x: Ref, y: &mut Vec>) { + y.push(x); +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr new file mode 100644 index 0000000000..8dba0c33f2 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr @@ -0,0 +1,10 @@ +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/ex2a-push-one-existing-name-2.rs:16:12 + | +15 | fn foo<'a>(x: Ref, y: &mut Vec>) { + | - consider changing the type of `x` to `Ref<'a, i32>` +16 | y.push(x); + | ^ lifetime `'a` required + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr index 7d0947b364..e529d6ffe4 100644 --- a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr @@ -1,25 +1,10 @@ -error[E0308]: mismatched types +error[E0621]: explicit lifetime required in the type of `y` --> $DIR/ex2a-push-one-existing-name.rs:16:12 | +15 | fn foo<'a>(x: &mut Vec>, y: Ref) { + | - consider changing the type of `y` to `Ref<'a, i32>` 16 | x.push(y); - | ^ lifetime mismatch - | - = note: expected type `Ref<'a, _>` - found type `Ref<'_, _>` -note: the anonymous lifetime #2 defined on the function body at 15:1... - --> $DIR/ex2a-push-one-existing-name.rs:15:1 - | -15 | / fn foo<'a>(x: &mut Vec>, y: Ref) { -16 | | x.push(y); -17 | | } - | |_^ -note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 15:1 - --> $DIR/ex2a-push-one-existing-name.rs:15:1 - | -15 | / fn foo<'a>(x: &mut Vec>, y: Ref) { -16 | | x.push(y); -17 | | } - | |_^ + | ^ lifetime `'a` required -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr index 6380a885f4..6764c58f4b 100644 --- a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr +++ b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr @@ -21,5 +21,5 @@ note: ...does not necessarily outlive the anonymous lifetime #2 defined on the f 17 | | } | |_^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr index b28a3c0c13..7356fc1186 100644 --- a/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr +++ b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr @@ -31,5 +31,5 @@ note: ...so that expression is assignable (expected Ref<'b, _>, found Ref<'_, _> 17 | x.push(z); | ^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr b/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr index dd716bac51..38b0acf933 100644 --- a/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr +++ b/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr @@ -33,5 +33,5 @@ note: ...so that expression is assignable (expected &mut std::vec::Vec> = x; | ^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr b/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr index 141f5a7c45..035e516e86 100644 --- a/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr +++ b/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr @@ -33,5 +33,5 @@ note: ...so that expression is assignable (expected &mut std::vec::Vec> = x; | ^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr index 2bc0acd626..d1ba924658 100644 --- a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr +++ b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr @@ -10,5 +10,5 @@ error[E0597]: borrowed value does not live long enough | = note: consider using a `let` binding to increase its lifetime -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lint/command-line-lint-group-deny.stderr b/src/test/ui/lint/command-line-lint-group-deny.stderr index d441702374..23fac66cc6 100644 --- a/src/test/ui/lint/command-line-lint-group-deny.stderr +++ b/src/test/ui/lint/command-line-lint-group-deny.stderr @@ -6,5 +6,5 @@ error: variable `_InappropriateCamelCasing` should have a snake case name such a | = note: `-D non-snake-case` implied by `-D bad-style` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lint/command-line-lint-group-forbid.stderr b/src/test/ui/lint/command-line-lint-group-forbid.stderr index 9d4d0b12b1..0babd7f6fe 100644 --- a/src/test/ui/lint/command-line-lint-group-forbid.stderr +++ b/src/test/ui/lint/command-line-lint-group-forbid.stderr @@ -6,5 +6,5 @@ error: variable `_InappropriateCamelCasing` should have a snake case name such a | = note: `-F non-snake-case` implied by `-F bad-style` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lint/lint-group-style.stderr b/src/test/ui/lint/lint-group-style.stderr index dec44c317e..862e94b873 100644 --- a/src/test/ui/lint/lint-group-style.stderr +++ b/src/test/ui/lint/lint-group-style.stderr @@ -4,12 +4,12 @@ error: function `CamelCase` should have a snake case name such as `camel_case` 14 | fn CamelCase() {} | ^^^^^^^^^^^^^^^^^ | - = note: #[deny(non_snake_case)] implied by #[deny(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:11:9 | 11 | #![deny(bad_style)] | ^^^^^^^^^ + = note: #[deny(non_snake_case)] implied by #[deny(bad_style)] error: function `CamelCase` should have a snake case name such as `camel_case` --> $DIR/lint-group-style.rs:22:9 @@ -17,12 +17,12 @@ error: function `CamelCase` should have a snake case name such as `camel_case` 22 | fn CamelCase() {} | ^^^^^^^^^^^^^^^^^ | - = note: #[forbid(non_snake_case)] implied by #[forbid(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:20:14 | 20 | #[forbid(bad_style)] | ^^^^^^^^^ + = note: #[forbid(non_snake_case)] implied by #[forbid(bad_style)] error: static variable `bad` should have an upper case name such as `BAD` --> $DIR/lint-group-style.rs:24:9 @@ -30,12 +30,12 @@ error: static variable `bad` should have an upper case name such as `BAD` 24 | static bad: isize = 1; | ^^^^^^^^^^^^^^^^^^^^^^ | - = note: #[forbid(non_upper_case_globals)] implied by #[forbid(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:20:14 | 20 | #[forbid(bad_style)] | ^^^^^^^^^ + = note: #[forbid(non_upper_case_globals)] implied by #[forbid(bad_style)] warning: function `CamelCase` should have a snake case name such as `camel_case` --> $DIR/lint-group-style.rs:30:9 @@ -43,12 +43,12 @@ warning: function `CamelCase` should have a snake case name such as `camel_case` 30 | fn CamelCase() {} | ^^^^^^^^^^^^^^^^^ | - = note: #[warn(non_snake_case)] implied by #[warn(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:28:17 | 28 | #![warn(bad_style)] | ^^^^^^^^^ + = note: #[warn(non_snake_case)] implied by #[warn(bad_style)] warning: type `snake_case` should have a camel case name such as `SnakeCase` --> $DIR/lint-group-style.rs:32:9 @@ -56,12 +56,12 @@ warning: type `snake_case` should have a camel case name such as `SnakeCase` 32 | struct snake_case; | ^^^^^^^^^^^^^^^^^^ | - = note: #[warn(non_camel_case_types)] implied by #[warn(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:28:17 | 28 | #![warn(bad_style)] | ^^^^^^^^^ + = note: #[warn(non_camel_case_types)] implied by #[warn(bad_style)] -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/outer-forbid.rs b/src/test/ui/lint/outer-forbid.rs new file mode 100644 index 0000000000..d71da58829 --- /dev/null +++ b/src/test/ui/lint/outer-forbid.rs @@ -0,0 +1,22 @@ +// 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. + +// Forbidding a group (here, `unused`) overrules subsequent allowance of both +// the group, and an individual lint in the group (here, `unused_variables`); +// and, forbidding an individual lint (here, `non_snake_case`) overrules +// subsequent allowance of a lint group containing it (here, `bad_style`). See +// Issue #42873. + +#![forbid(unused, non_snake_case)] + +#[allow(unused, unused_variables, bad_style)] +fn main() { + println!("hello forbidden world") +} diff --git a/src/test/ui/lint/outer-forbid.stderr b/src/test/ui/lint/outer-forbid.stderr new file mode 100644 index 0000000000..df62f5acc0 --- /dev/null +++ b/src/test/ui/lint/outer-forbid.stderr @@ -0,0 +1,29 @@ +error[E0453]: allow(unused) overruled by outer forbid(unused) + --> $DIR/outer-forbid.rs:19:9 + | +17 | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +18 | +19 | #[allow(unused, unused_variables, bad_style)] + | ^^^^^^ overruled by previous forbid + +error[E0453]: allow(unused_variables) overruled by outer forbid(unused) + --> $DIR/outer-forbid.rs:19:17 + | +17 | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +18 | +19 | #[allow(unused, unused_variables, bad_style)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + +error[E0453]: allow(bad_style) overruled by outer forbid(non_snake_case) + --> $DIR/outer-forbid.rs:19:35 + | +17 | #![forbid(unused, non_snake_case)] + | -------------- `forbid` level set here +18 | +19 | #[allow(unused, unused_variables, bad_style)] + | ^^^^^^^^^ overruled by previous forbid + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/loop-break-value-no-repeat.stderr b/src/test/ui/loop-break-value-no-repeat.stderr index 7a4a9c3f01..c154ea6f8c 100644 --- a/src/test/ui/loop-break-value-no-repeat.stderr +++ b/src/test/ui/loop-break-value-no-repeat.stderr @@ -4,5 +4,5 @@ error[E0571]: `break` with value from a `for` loop 22 | break 22 | ^^^^^^^^ can only break with a value inside `loop` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/macros/bad_hello.stderr b/src/test/ui/macros/bad_hello.stderr index b8337c8183..bffb33f468 100644 --- a/src/test/ui/macros/bad_hello.stderr +++ b/src/test/ui/macros/bad_hello.stderr @@ -4,5 +4,5 @@ error: expected a literal 12 | println!(3 + 4); | ^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/macros/format-foreign.stderr b/src/test/ui/macros/format-foreign.stderr index a964b92712..0283052a89 100644 --- a/src/test/ui/macros/format-foreign.stderr +++ b/src/test/ui/macros/format-foreign.stderr @@ -48,5 +48,5 @@ error: named argument never used = help: `$NAME` should be written as `{NAME}` = note: shell formatting not supported; see the documentation for `std::fmt` -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr index 2c83a84f00..c80c0fce35 100644 --- a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr +++ b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr @@ -7,7 +7,7 @@ error[E0599]: no method named `fake` found for type `{integer}` in the current s 50 | fake_method_stmt!(); | -------------------- in this macro invocation -error: no field `fake` on type `{integer}` +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields --> $DIR/macro-backtrace-invalid-internals.rs:21:13 | 21 | 1.fake @@ -16,7 +16,7 @@ error: no field `fake` on type `{integer}` 51 | fake_field_stmt!(); | ------------------- in this macro invocation -error: attempted tuple index `0` on type `{integer}`, but the type was not a tuple or tuple struct +error[E0609]: no field `0` on type `{integer}` --> $DIR/macro-backtrace-invalid-internals.rs:27:11 | 27 | (1).0 @@ -34,7 +34,7 @@ error[E0599]: no method named `fake` found for type `{integer}` in the current s 54 | let _ = fake_method_expr!(); | ------------------- in this macro invocation -error: no field `fake` on type `{integer}` +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields --> $DIR/macro-backtrace-invalid-internals.rs:39:13 | 39 | 1.fake @@ -43,7 +43,7 @@ error: no field `fake` on type `{integer}` 55 | let _ = fake_field_expr!(); | ------------------ in this macro invocation -error: attempted tuple index `0` on type `{integer}`, but the type was not a tuple or tuple struct +error[E0609]: no field `0` on type `{integer}` --> $DIR/macro-backtrace-invalid-internals.rs:45:11 | 45 | (1).0 @@ -52,5 +52,5 @@ error: attempted tuple index `0` on type `{integer}`, but the type was not a tup 56 | let _ = fake_anon_field_expr!(); | ----------------------- in this macro invocation -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/macros/macro-backtrace-nested.stderr b/src/test/ui/macros/macro-backtrace-nested.stderr index 7835b85eaf..8b69d112d4 100644 --- a/src/test/ui/macros/macro-backtrace-nested.stderr +++ b/src/test/ui/macros/macro-backtrace-nested.stderr @@ -16,5 +16,5 @@ error[E0425]: cannot find value `fake` in this scope 28 | call_nested_expr_sum!(); | ------------------------ in this macro invocation -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/macros/macro-backtrace-println.stderr b/src/test/ui/macros/macro-backtrace-println.stderr index 4177240d97..f21253bb67 100644 --- a/src/test/ui/macros/macro-backtrace-println.stderr +++ b/src/test/ui/macros/macro-backtrace-println.stderr @@ -7,5 +7,5 @@ error: invalid reference to argument `0` (no arguments given) 28 | myprintln!("{}"); | ----------------- in this macro invocation -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/compile-fail/macro-name-typo.rs b/src/test/ui/macros/macro-name-typo.rs similarity index 87% rename from src/test/compile-fail/macro-name-typo.rs rename to src/test/ui/macros/macro-name-typo.rs index 4840205fee..ec8d27f913 100644 --- a/src/test/compile-fail/macro-name-typo.rs +++ b/src/test/ui/macros/macro-name-typo.rs @@ -10,6 +10,4 @@ fn main() { printlx!("oh noes!"); - //~^ ERROR cannot find macro - //~^^ HELP did you mean `println!`? } diff --git a/src/test/ui/macros/macro-name-typo.stderr b/src/test/ui/macros/macro-name-typo.stderr new file mode 100644 index 0000000000..7c83250fe8 --- /dev/null +++ b/src/test/ui/macros/macro-name-typo.stderr @@ -0,0 +1,8 @@ +error: cannot find macro `printlx!` in this scope + --> $DIR/macro-name-typo.rs:12:5 + | +12 | printlx!("oh noes!"); + | ^^^^^^^ help: you could try the macro: `println!` + +error: aborting due to previous error + diff --git a/src/test/compile-fail/macro_undefined.rs b/src/test/ui/macros/macro_undefined.rs similarity index 74% rename from src/test/compile-fail/macro_undefined.rs rename to src/test/ui/macros/macro_undefined.rs index 00c8d44f30..db93ba5e2c 100644 --- a/src/test/compile-fail/macro_undefined.rs +++ b/src/test/ui/macros/macro_undefined.rs @@ -19,9 +19,5 @@ mod m { fn main() { k!(); - //~^ ERROR cannot find macro `k!` in this scope - //~^^ HELP did you mean `kl!`? kl!(); - //~^ ERROR cannot find macro `kl!` in this scope - //~^^ HELP have you added the `#[macro_use]` on the module/import? } diff --git a/src/test/ui/macros/macro_undefined.stderr b/src/test/ui/macros/macro_undefined.stderr new file mode 100644 index 0000000000..5c33ae9973 --- /dev/null +++ b/src/test/ui/macros/macro_undefined.stderr @@ -0,0 +1,16 @@ +error: cannot find macro `kl!` in this scope + --> $DIR/macro_undefined.rs:22:5 + | +22 | kl!(); + | ^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find macro `k!` in this scope + --> $DIR/macro_undefined.rs:21:5 + | +21 | k!(); + | ^ help: you could try the macro: `kl!` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/mismatched_types/E0053.stderr b/src/test/ui/mismatched_types/E0053.stderr index 2ba2069677..d9871b8970 100644 --- a/src/test/ui/mismatched_types/E0053.stderr +++ b/src/test/ui/mismatched_types/E0053.stderr @@ -22,5 +22,5 @@ error[E0053]: method `bar` has an incompatible type for trait = note: expected type `fn(&Bar)` found type `fn(&mut Bar)` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/E0281.stderr b/src/test/ui/mismatched_types/E0281.stderr index fab48e9a74..887412d1be 100644 --- a/src/test/ui/mismatched_types/E0281.stderr +++ b/src/test/ui/mismatched_types/E0281.stderr @@ -9,16 +9,5 @@ error[E0281]: type mismatch: `[closure@$DIR/E0281.rs:14:9: 14:24]` implements th | = note: required by `foo` -error[E0281]: type mismatch: `[closure@$DIR/E0281.rs:14:9: 14:24]` implements the trait `std::ops::FnOnce<(std::string::String,)>`, but the trait `std::ops::FnOnce<(usize,)>` is required - --> $DIR/E0281.rs:14:5 - | -14 | foo(|y: String| { }); - | ^^^ --------------- implements `std::ops::FnOnce<(std::string::String,)>` - | | - | requires `std::ops::FnOnce<(usize,)>` - | expected usize, found struct `std::string::String` - | - = note: required by `foo` - -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/E0409.stderr b/src/test/ui/mismatched_types/E0409.stderr index a5f63aca13..cc7c017907 100644 --- a/src/test/ui/mismatched_types/E0409.stderr +++ b/src/test/ui/mismatched_types/E0409.stderr @@ -15,5 +15,5 @@ error[E0308]: mismatched types = note: expected type `&{integer}` found type `{integer}` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/abridged.rs b/src/test/ui/mismatched_types/abridged.rs index c448ad955f..03f889224b 100644 --- a/src/test/ui/mismatched_types/abridged.rs +++ b/src/test/ui/mismatched_types/abridged.rs @@ -39,23 +39,25 @@ fn c() -> Result { } fn d() -> X, String> { - X { + let x = X { x: X { x: "".to_string(), y: 2, }, y: 3, - } + }; + x } fn e() -> X, String> { - X { + let x = X { x: X { x: "".to_string(), y: 2, }, y: "".to_string(), - } + }; + x } fn main() {} diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr index 78b5dcda1d..d40bc3b333 100644 --- a/src/test/ui/mismatched_types/abridged.stderr +++ b/src/test/ui/mismatched_types/abridged.stderr @@ -35,34 +35,22 @@ error[E0308]: mismatched types found type `Foo` error[E0308]: mismatched types - --> $DIR/abridged.rs:42:5 + --> $DIR/abridged.rs:49:5 | -42 | / X { -43 | | x: X { -44 | | x: "".to_string(), -45 | | y: 2, -46 | | }, -47 | | y: 3, -48 | | } - | |_____^ expected struct `std::string::String`, found integral variable +49 | x + | ^ expected struct `std::string::String`, found integral variable | = note: expected type `X, std::string::String>` found type `X, {integer}>` error[E0308]: mismatched types - --> $DIR/abridged.rs:52:5 + --> $DIR/abridged.rs:60:5 | -52 | / X { -53 | | x: X { -54 | | x: "".to_string(), -55 | | y: 2, -56 | | }, -57 | | y: "".to_string(), -58 | | } - | |_____^ expected struct `std::string::String`, found integral variable +60 | x + | ^ expected struct `std::string::String`, found integral variable | = note: expected type `X, _>` found type `X, _>` -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/mismatched_types/binops.stderr b/src/test/ui/mismatched_types/binops.stderr index 1faf72cd76..6d1a39e0d9 100644 --- a/src/test/ui/mismatched_types/binops.stderr +++ b/src/test/ui/mismatched_types/binops.stderr @@ -30,14 +30,6 @@ error[E0277]: the trait bound `{integer}: std::ops::Div<&str>` is not satisfied | = help: the trait `std::ops::Div<&str>` is not implemented for `{integer}` -error[E0277]: the trait bound `{integer}: std::cmp::PartialEq` is not satisfied - --> $DIR/binops.rs:16:7 - | -16 | 5 < String::new(); - | ^ can't compare `{integer}` with `std::string::String` - | - = help: the trait `std::cmp::PartialEq` is not implemented for `{integer}` - error[E0277]: the trait bound `{integer}: std::cmp::PartialOrd` is not satisfied --> $DIR/binops.rs:16:7 | @@ -54,5 +46,5 @@ error[E0277]: the trait bound `{integer}: std::cmp::PartialEq>` is not implemented for `{integer}` -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr index 8d31dd7500..fb363c388b 100644 --- a/src/test/ui/mismatched_types/cast-rfc0401.stderr +++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr @@ -1,4 +1,4 @@ -error: casting `*const U` as `*const V` is invalid +error[E0606]: casting `*const U` as `*const V` is invalid --> $DIR/cast-rfc0401.rs:13:5 | 13 | u as *const V @@ -6,7 +6,7 @@ error: casting `*const U` as `*const V` is invalid | = note: vtable kinds may not match -error: casting `*const U` as `*const str` is invalid +error[E0606]: casting `*const U` as `*const str` is invalid --> $DIR/cast-rfc0401.rs:18:5 | 18 | u as *const str @@ -14,55 +14,65 @@ error: casting `*const U` as `*const str` is invalid | = note: vtable kinds may not match -error: no field `f` on type `fn() {main}` +error[E0609]: no field `f` on type `fn() {main}` --> $DIR/cast-rfc0401.rs:75:18 | 75 | let _ = main.f as *const u32; | ^ -error: non-scalar cast: `*const u8` as `&u8` +error[E0605]: non-primitive cast: `*const u8` as `&u8` --> $DIR/cast-rfc0401.rs:39:13 | 39 | let _ = v as &u8; | ^^^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: non-scalar cast: `*const u8` as `E` +error[E0605]: non-primitive cast: `*const u8` as `E` --> $DIR/cast-rfc0401.rs:40:13 | 40 | let _ = v as E; | ^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: non-scalar cast: `*const u8` as `fn()` +error[E0605]: non-primitive cast: `*const u8` as `fn()` --> $DIR/cast-rfc0401.rs:41:13 | 41 | let _ = v as fn(); | ^^^^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: non-scalar cast: `*const u8` as `(u32,)` +error[E0605]: non-primitive cast: `*const u8` as `(u32,)` --> $DIR/cast-rfc0401.rs:42:13 | 42 | let _ = v as (u32,); | ^^^^^^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: non-scalar cast: `std::option::Option<&*const u8>` as `*const u8` +error[E0605]: non-primitive cast: `std::option::Option<&*const u8>` as `*const u8` --> $DIR/cast-rfc0401.rs:43:13 | 43 | let _ = Some(&v) as *const u8; | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: casting `*const u8` as `f32` is invalid +error[E0606]: casting `*const u8` as `f32` is invalid --> $DIR/cast-rfc0401.rs:45:13 | 45 | let _ = v as f32; | ^^^^^^^^ -error: casting `fn() {main}` as `f64` is invalid +error[E0606]: casting `fn() {main}` as `f64` is invalid --> $DIR/cast-rfc0401.rs:46:13 | 46 | let _ = main as f64; | ^^^^^^^^^^^ -error: casting `&*const u8` as `usize` is invalid +error[E0606]: casting `&*const u8` as `usize` is invalid --> $DIR/cast-rfc0401.rs:47:13 | 47 | let _ = &v as usize; @@ -70,7 +80,7 @@ error: casting `&*const u8` as `usize` is invalid | = help: cast through a raw pointer first -error: casting `f32` as `*const u8` is invalid +error[E0606]: casting `f32` as `*const u8` is invalid --> $DIR/cast-rfc0401.rs:48:13 | 48 | let _ = f as *const u8; @@ -92,13 +102,13 @@ error[E0054]: cannot cast as `bool` | = help: compare with zero instead -error: only `u8` can be cast as `char`, not `u32` +error[E0604]: only `u8` can be cast as `char`, not `u32` --> $DIR/cast-rfc0401.rs:51:13 | 51 | let _ = 0x61u32 as char; | ^^^^^^^^^^^^^^^ -error: casting `bool` as `f32` is invalid +error[E0606]: casting `bool` as `f32` is invalid --> $DIR/cast-rfc0401.rs:53:13 | 53 | let _ = false as f32; @@ -106,7 +116,7 @@ error: casting `bool` as `f32` is invalid | = help: cast through an integer first -error: casting `E` as `f32` is invalid +error[E0606]: casting `E` as `f32` is invalid --> $DIR/cast-rfc0401.rs:54:13 | 54 | let _ = E::A as f32; @@ -114,7 +124,7 @@ error: casting `E` as `f32` is invalid | = help: cast through an integer first -error: casting `char` as `f32` is invalid +error[E0606]: casting `char` as `f32` is invalid --> $DIR/cast-rfc0401.rs:55:13 | 55 | let _ = 'a' as f32; @@ -122,67 +132,67 @@ error: casting `char` as `f32` is invalid | = help: cast through an integer first -error: casting `bool` as `*const u8` is invalid +error[E0606]: casting `bool` as `*const u8` is invalid --> $DIR/cast-rfc0401.rs:57:13 | 57 | let _ = false as *const u8; | ^^^^^^^^^^^^^^^^^^ -error: casting `E` as `*const u8` is invalid +error[E0606]: casting `E` as `*const u8` is invalid --> $DIR/cast-rfc0401.rs:58:13 | 58 | let _ = E::A as *const u8; | ^^^^^^^^^^^^^^^^^ -error: casting `char` as `*const u8` is invalid +error[E0606]: casting `char` as `*const u8` is invalid --> $DIR/cast-rfc0401.rs:59:13 | 59 | let _ = 'a' as *const u8; | ^^^^^^^^^^^^^^^^ -error: casting `usize` as `*const [u8]` is invalid +error[E0606]: casting `usize` as `*const [u8]` is invalid --> $DIR/cast-rfc0401.rs:61:13 | 61 | let _ = 42usize as *const [u8]; | ^^^^^^^^^^^^^^^^^^^^^^ -error: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]` +error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]` --> $DIR/cast-rfc0401.rs:62:13 | 62 | let _ = v as *const [u8]; | ^^^^^^^^^^^^^^^^ -error: casting `&Foo` as `*const str` is invalid +error[E0606]: casting `&Foo` as `*const str` is invalid --> $DIR/cast-rfc0401.rs:64:13 | 64 | let _ = foo as *const str; | ^^^^^^^^^^^^^^^^^ -error: casting `&Foo` as `*mut str` is invalid +error[E0606]: casting `&Foo` as `*mut str` is invalid --> $DIR/cast-rfc0401.rs:65:13 | 65 | let _ = foo as *mut str; | ^^^^^^^^^^^^^^^ -error: casting `fn() {main}` as `*mut str` is invalid +error[E0606]: casting `fn() {main}` as `*mut str` is invalid --> $DIR/cast-rfc0401.rs:66:13 | 66 | let _ = main as *mut str; | ^^^^^^^^^^^^^^^^ -error: casting `&f32` as `*mut f32` is invalid +error[E0606]: casting `&f32` as `*mut f32` is invalid --> $DIR/cast-rfc0401.rs:67:13 | 67 | let _ = &f as *mut f32; | ^^^^^^^^^^^^^^ -error: casting `&f32` as `*const f64` is invalid +error[E0606]: casting `&f32` as `*const f64` is invalid --> $DIR/cast-rfc0401.rs:68:13 | 68 | let _ = &f as *const f64; | ^^^^^^^^^^^^^^^^ -error: casting `*const [i8]` as `usize` is invalid +error[E0606]: casting `*const [i8]` as `usize` is invalid --> $DIR/cast-rfc0401.rs:69:13 | 69 | let _ = fat_sv as usize; @@ -190,7 +200,7 @@ error: casting `*const [i8]` as `usize` is invalid | = help: cast through a thin pointer first -error: casting `*const Foo` as `*const [u16]` is invalid +error[E0606]: casting `*const Foo` as `*const [u16]` is invalid --> $DIR/cast-rfc0401.rs:78:13 | 78 | let _ = cf as *const [u16]; @@ -198,7 +208,7 @@ error: casting `*const Foo` as `*const [u16]` is invalid | = note: vtable kinds may not match -error: casting `*const Foo` as `*const Bar` is invalid +error[E0606]: casting `*const Foo` as `*const Bar` is invalid --> $DIR/cast-rfc0401.rs:79:13 | 79 | let _ = cf as *const Bar; @@ -224,7 +234,7 @@ error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied = help: the trait `std::marker::Sized` is not implemented for `str` = note: required for the cast to the object type `Foo` -error: casting `&{float}` as `f32` is invalid +error[E0606]: casting `&{float}` as `f32` is invalid --> $DIR/cast-rfc0401.rs:81:30 | 81 | vec![0.0].iter().map(|s| s as f32).collect::>(); @@ -236,5 +246,5 @@ help: did you mean `*s`? 81 | vec![0.0].iter().map(|s| s as f32).collect::>(); | ^ -error: aborting due to previous error(s) +error: aborting due to 34 previous errors diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index cd16e5d70b..ca71154e87 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -6,22 +6,6 @@ error[E0593]: closure takes 0 arguments but 2 arguments are required | | | expected closure that takes 2 arguments -error[E0593]: closure takes 0 arguments but 2 arguments are required - --> $DIR/closure-arg-count.rs:12:15 - | -12 | [1, 2, 3].sort_by(|| panic!()); - | ^^^^^^^ ----------- takes 0 arguments - | | - | expected closure that takes 2 arguments - -error[E0593]: closure takes 1 argument but 2 arguments are required - --> $DIR/closure-arg-count.rs:13:15 - | -13 | [1, 2, 3].sort_by(|tuple| panic!()); - | ^^^^^^^ ---------------- takes 1 argument - | | - | expected closure that takes 2 arguments - error[E0593]: closure takes 1 argument but 2 arguments are required --> $DIR/closure-arg-count.rs:13:15 | @@ -47,13 +31,5 @@ error[E0593]: closure takes 1 argument but 2 arguments are required | | | expected closure that takes 2 arguments -error[E0593]: closure takes 1 argument but 2 arguments are required - --> $DIR/closure-arg-count.rs:14:15 - | -14 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!()); - | ^^^^^^^ -------------------------- takes 1 argument - | | - | expected closure that takes 2 arguments - -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr index 2c9c918168..5b3eb59318 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -20,5 +20,5 @@ error[E0281]: type mismatch: `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]` im = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]` = note: required by `baz` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/const-fn-in-trait.stderr b/src/test/ui/mismatched_types/const-fn-in-trait.stderr index 5f67a66eb3..f7b7635e41 100644 --- a/src/test/ui/mismatched_types/const-fn-in-trait.stderr +++ b/src/test/ui/mismatched_types/const-fn-in-trait.stderr @@ -10,5 +10,5 @@ error[E0379]: trait fns cannot be declared const 21 | const fn f() -> u32 { 22 } | ^^^^^ trait fns cannot be const -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/fn-variance-1.stderr b/src/test/ui/mismatched_types/fn-variance-1.stderr index 2030ad6c13..120fb87cdc 100644 --- a/src/test/ui/mismatched_types/fn-variance-1.stderr +++ b/src/test/ui/mismatched_types/fn-variance-1.stderr @@ -14,5 +14,5 @@ error[E0281]: type mismatch: `fn(&isize) {takes_imm}` implements the trait `for< | = note: required by `apply` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/compile-fail/for-loop-has-unit-body.rs b/src/test/ui/mismatched_types/for-loop-has-unit-body.rs similarity index 100% rename from src/test/compile-fail/for-loop-has-unit-body.rs rename to src/test/ui/mismatched_types/for-loop-has-unit-body.rs diff --git a/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr b/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr new file mode 100644 index 0000000000..4a619804a6 --- /dev/null +++ b/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/for-loop-has-unit-body.rs:13:9 + | +13 | x //~ ERROR mismatched types + | ^ expected (), found integral variable + | + = note: expected type `()` + found type `{integer}` + +error: aborting due to previous error + diff --git a/src/test/ui/mismatched_types/issue-19109.stderr b/src/test/ui/mismatched_types/issue-19109.stderr index cbce4f810c..2d8d557d9f 100644 --- a/src/test/ui/mismatched_types/issue-19109.stderr +++ b/src/test/ui/mismatched_types/issue-19109.stderr @@ -1,11 +1,13 @@ error[E0308]: mismatched types --> $DIR/issue-19109.rs:14:5 | +13 | fn function(t: &mut Trait) { + | - help: possibly return type missing here?: `-> *mut Trait ` 14 | t as *mut Trait | ^^^^^^^^^^^^^^^ expected (), found *-ptr | = note: expected type `()` found type `*mut Trait` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/issue-26480.stderr b/src/test/ui/mismatched_types/issue-26480.stderr index dc3764a376..fae831ffb8 100644 --- a/src/test/ui/mismatched_types/issue-26480.stderr +++ b/src/test/ui/mismatched_types/issue-26480.stderr @@ -7,7 +7,7 @@ error[E0308]: mismatched types 37 | write!(hello); | -------------- in this macro invocation -error: non-scalar cast: `{integer}` as `()` +error[E0605]: non-primitive cast: `{integer}` as `()` --> $DIR/issue-26480.rs:32:19 | 32 | ($x:expr) => ($x as ()) @@ -15,6 +15,8 @@ error: non-scalar cast: `{integer}` as `()` ... 38 | cast!(2); | --------- in this macro invocation + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/issue-35030.stderr b/src/test/ui/mismatched_types/issue-35030.stderr index 463d9fdf17..46d690c5f0 100644 --- a/src/test/ui/mismatched_types/issue-35030.stderr +++ b/src/test/ui/mismatched_types/issue-35030.stderr @@ -7,5 +7,5 @@ error[E0308]: mismatched types = note: expected type `bool` (type parameter) found type `bool` (bool) -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 8b756814ce..51acdb719b 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -17,14 +17,5 @@ error[E0281]: type mismatch: `[closure@$DIR/issue-36053-2.rs:17:39: 17:53]` impl | requires `for<'r> std::ops::FnMut<(&'r &str,)>` | expected &str, found str -error[E0281]: type mismatch: `[closure@$DIR/issue-36053-2.rs:17:39: 17:53]` implements the trait `for<'r> std::ops::FnOnce<(&'r str,)>`, but the trait `for<'r> std::ops::FnOnce<(&'r &str,)>` is required - --> $DIR/issue-36053-2.rs:17:32 - | -17 | once::<&str>("str").fuse().filter(|a: &str| true).count(); - | ^^^^^^ -------------- implements `for<'r> std::ops::FnOnce<(&'r str,)>` - | | - | requires `for<'r> std::ops::FnOnce<(&'r &str,)>` - | expected &str, found str - -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/issue-38371.stderr b/src/test/ui/mismatched_types/issue-38371.stderr index 76ffa6e50e..9efee4cc55 100644 --- a/src/test/ui/mismatched_types/issue-38371.stderr +++ b/src/test/ui/mismatched_types/issue-38371.stderr @@ -32,5 +32,5 @@ error[E0529]: expected an array or slice, found `u32` 34 | fn ugh(&[bar]: &u32) { | ^^^^^ pattern cannot match with input type `u32` -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/mismatched_types/main.stderr b/src/test/ui/mismatched_types/main.stderr index b4e688e025..c8941fbf95 100644 --- a/src/test/ui/mismatched_types/main.stderr +++ b/src/test/ui/mismatched_types/main.stderr @@ -9,5 +9,5 @@ error[E0308]: mismatched types = note: expected type `u32` found type `()` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr index 80f95da0bb..ab5b3e1791 100644 --- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr +++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr @@ -7,5 +7,5 @@ error[E0599]: no method named `unwrap` found for type `std::result::Result<(), F = note: the method `unwrap` exists but the following trait bounds were not satisfied: `Foo : std::fmt::Debug` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/overloaded-calls-bad.stderr b/src/test/ui/mismatched_types/overloaded-calls-bad.stderr index 7c644e3a72..cd05684f15 100644 --- a/src/test/ui/mismatched_types/overloaded-calls-bad.stderr +++ b/src/test/ui/mismatched_types/overloaded-calls-bad.stderr @@ -19,5 +19,5 @@ error[E0057]: this function takes 1 parameter but 2 parameters were supplied 45 | let ans = s("burma", "shave"); | ^^^^^^^^^^^^^^^^ expected 1 parameter -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr b/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr index 9e7f79df35..ccc9fb5677 100644 --- a/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr +++ b/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr @@ -7,5 +7,5 @@ error[E0308]: mismatched types = note: expected type `std::boxed::Box` found type `std::boxed::Box` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr index 8741589f84..349432f64b 100644 --- a/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr +++ b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr @@ -22,5 +22,5 @@ error[E0053]: method `bar` has an incompatible type for trait = note: expected type `fn(&mut Bar, &mut Bar)` found type `fn(&mut Bar, &Bar)` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs index 7400a27fb6..693a158532 100644 --- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs +++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs @@ -24,7 +24,6 @@ pub fn main() { //~| NOTE implements let z = call_it(3, f); //~^ ERROR type mismatch - //~| ERROR type mismatch //~| NOTE expected isize, found usize //~| NOTE expected isize, found usize //~| NOTE requires diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr index c5bfb6e45e..995a125845 100644 --- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr +++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr @@ -12,19 +12,5 @@ error[E0281]: type mismatch: `[closure@$DIR/unboxed-closures-vtable-mismatch.rs: | = note: required by `call_it` -error[E0281]: type mismatch: `[closure@$DIR/unboxed-closures-vtable-mismatch.rs:22:23: 22:73]` implements the trait `std::ops::FnOnce<(usize, isize)>`, but the trait `std::ops::FnOnce<(isize, isize)>` is required - --> $DIR/unboxed-closures-vtable-mismatch.rs:25:13 - | -22 | let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y }); - | -------------------------------------------------- implements `std::ops::FnOnce<(usize, isize)>` -... -25 | let z = call_it(3, f); - | ^^^^^^^ - | | - | requires `std::ops::FnOnce<(isize, isize)>` - | expected isize, found usize - | - = note: required by `call_it` - -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/missing-items/auxiliary/m1.rs b/src/test/ui/missing-items/auxiliary/m1.rs index f838969226..49fc586d6b 100644 --- a/src/test/ui/missing-items/auxiliary/m1.rs +++ b/src/test/ui/missing-items/auxiliary/m1.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] pub trait X { const CONSTANT: u32; diff --git a/src/test/ui/missing-items/issue-40221.stderr b/src/test/ui/missing-items/issue-40221.stderr index 8785449379..fc90c8a2b2 100644 --- a/src/test/ui/missing-items/issue-40221.stderr +++ b/src/test/ui/missing-items/issue-40221.stderr @@ -4,5 +4,5 @@ error[E0004]: non-exhaustive patterns: `C(QA)` not covered 21 | match proto { | ^^^^^ pattern `C(QA)` not covered -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/missing-items/m2.rs b/src/test/ui/missing-items/m2.rs index fc09039640..ffd7ff7f43 100644 --- a/src/test/ui/missing-items/m2.rs +++ b/src/test/ui/missing-items/m2.rs @@ -10,7 +10,6 @@ // aux-build:m1.rs -#![feature(associated_consts)] extern crate m1; diff --git a/src/test/ui/missing-items/m2.stderr b/src/test/ui/missing-items/m2.stderr index 2d699c6635..ce061bd167 100644 --- a/src/test/ui/missing-items/m2.stderr +++ b/src/test/ui/missing-items/m2.stderr @@ -1,15 +1,15 @@ error[E0601]: main function not found error[E0046]: not all trait items implemented, missing: `CONSTANT`, `Type`, `method` - --> $DIR/m2.rs:20:1 + --> $DIR/m2.rs:19:1 | -20 | / impl m1::X for X { -21 | | } +19 | / impl m1::X for X { +20 | | } | |_^ missing `CONSTANT`, `Type`, `method` in implementation | = note: `CONSTANT` from trait: `const CONSTANT: u32;` = note: `Type` from trait: `type Type;` = note: `method` from trait: `fn(&Self, std::string::String) -> ::Type` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/missing-items/missing-type-parameter.stderr b/src/test/ui/missing-items/missing-type-parameter.stderr index ce38178bf8..a16ae5538b 100644 --- a/src/test/ui/missing-items/missing-type-parameter.stderr +++ b/src/test/ui/missing-items/missing-type-parameter.stderr @@ -4,5 +4,5 @@ error[E0282]: type annotations needed 14 | foo(); | ^^^ cannot infer type for `X` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/compile-fail/on-unimplemented/bad-annotation.rs b/src/test/ui/on-unimplemented/bad-annotation.rs similarity index 100% rename from src/test/compile-fail/on-unimplemented/bad-annotation.rs rename to src/test/ui/on-unimplemented/bad-annotation.rs diff --git a/src/test/ui/on-unimplemented/bad-annotation.stderr b/src/test/ui/on-unimplemented/bad-annotation.stderr new file mode 100644 index 0000000000..8599477e8e --- /dev/null +++ b/src/test/ui/on-unimplemented/bad-annotation.stderr @@ -0,0 +1,22 @@ +error[E0232]: this attribute must have a value + --> $DIR/bad-annotation.rs:26:1 + | +26 | #[rustc_on_unimplemented] //~ ERROR this attribute must have a value + | ^^^^^^^^^^^^^^^^^^^^^^^^^ attribute requires a value + | + = note: eg `#[rustc_on_unimplemented = "foo"]` + +error[E0230]: there is no type parameter C on trait BadAnnotation2 + --> $DIR/bad-annotation.rs:30:1 + | +30 | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0231]: only named substitution parameters are allowed + --> $DIR/bad-annotation.rs:35:1 + | +35 | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{}>`"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/compile-fail/on-unimplemented/multiple-impls.rs b/src/test/ui/on-unimplemented/multiple-impls.rs similarity index 90% rename from src/test/compile-fail/on-unimplemented/multiple-impls.rs rename to src/test/ui/on-unimplemented/multiple-impls.rs index 0df8c41ffe..15375936b8 100644 --- a/src/test/compile-fail/on-unimplemented/multiple-impls.rs +++ b/src/test/ui/on-unimplemented/multiple-impls.rs @@ -44,12 +44,18 @@ fn main() { //~^ ERROR E0277 //~| NOTE trait message //~| NOTE required by + //~| ERROR E0277 + //~| NOTE trait message Index::index(&[] as &[i32], Foo(2u32)); //~^ ERROR E0277 //~| NOTE on impl for Foo //~| NOTE required by + //~| ERROR E0277 + //~| NOTE on impl for Foo Index::index(&[] as &[i32], Bar(2u32)); //~^ ERROR E0277 //~| NOTE on impl for Bar //~| NOTE required by + //~| ERROR E0277 + //~| NOTE on impl for Bar } diff --git a/src/test/ui/on-unimplemented/multiple-impls.stderr b/src/test/ui/on-unimplemented/multiple-impls.stderr new file mode 100644 index 0000000000..a1fa8b720a --- /dev/null +++ b/src/test/ui/on-unimplemented/multiple-impls.stderr @@ -0,0 +1,53 @@ +error[E0277]: the trait bound `[i32]: Index` is not satisfied + --> $DIR/multiple-impls.rs:43:5 + | +43 | Index::index(&[] as &[i32], 2u32); + | ^^^^^^^^^^^^ trait message + | + = help: the trait `Index` is not implemented for `[i32]` + = note: required by `Index::index` + +error[E0277]: the trait bound `[i32]: Index` is not satisfied + --> $DIR/multiple-impls.rs:43:5 + | +43 | Index::index(&[] as &[i32], 2u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait message + | + = help: the trait `Index` is not implemented for `[i32]` + +error[E0277]: the trait bound `[i32]: Index>` is not satisfied + --> $DIR/multiple-impls.rs:49:5 + | +49 | Index::index(&[] as &[i32], Foo(2u32)); + | ^^^^^^^^^^^^ on impl for Foo + | + = help: the trait `Index>` is not implemented for `[i32]` + = note: required by `Index::index` + +error[E0277]: the trait bound `[i32]: Index>` is not satisfied + --> $DIR/multiple-impls.rs:49:5 + | +49 | Index::index(&[] as &[i32], Foo(2u32)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Foo + | + = help: the trait `Index>` is not implemented for `[i32]` + +error[E0277]: the trait bound `[i32]: Index>` is not satisfied + --> $DIR/multiple-impls.rs:55:5 + | +55 | Index::index(&[] as &[i32], Bar(2u32)); + | ^^^^^^^^^^^^ on impl for Bar + | + = help: the trait `Index>` is not implemented for `[i32]` + = note: required by `Index::index` + +error[E0277]: the trait bound `[i32]: Index>` is not satisfied + --> $DIR/multiple-impls.rs:55:5 + | +55 | Index::index(&[] as &[i32], Bar(2u32)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Bar + | + = help: the trait `Index>` is not implemented for `[i32]` + +error: aborting due to 6 previous errors + diff --git a/src/test/compile-fail/on-unimplemented/on-impl.rs b/src/test/ui/on-unimplemented/on-impl.rs similarity index 95% rename from src/test/compile-fail/on-unimplemented/on-impl.rs rename to src/test/ui/on-unimplemented/on-impl.rs index 79021cd03c..66d612baab 100644 --- a/src/test/compile-fail/on-unimplemented/on-impl.rs +++ b/src/test/ui/on-unimplemented/on-impl.rs @@ -33,4 +33,6 @@ fn main() { //~^ ERROR E0277 //~| NOTE a usize is required //~| NOTE required by + //~| ERROR E0277 + //~| NOTE a usize is required } diff --git a/src/test/ui/on-unimplemented/on-impl.stderr b/src/test/ui/on-unimplemented/on-impl.stderr new file mode 100644 index 0000000000..c8c06bf44f --- /dev/null +++ b/src/test/ui/on-unimplemented/on-impl.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `[i32]: Index` is not satisfied + --> $DIR/on-impl.rs:32:5 + | +32 | Index::::index(&[1, 2, 3] as &[i32], 2u32); + | ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice + | + = help: the trait `Index` is not implemented for `[i32]` + = note: required by `Index::index` + +error[E0277]: the trait bound `[i32]: Index` is not satisfied + --> $DIR/on-impl.rs:32:5 + | +32 | Index::::index(&[1, 2, 3] as &[i32], 2u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice + | + = help: the trait `Index` is not implemented for `[i32]` + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/on-unimplemented/on-trait.rs b/src/test/ui/on-unimplemented/on-trait.rs similarity index 90% rename from src/test/compile-fail/on-unimplemented/on-trait.rs rename to src/test/ui/on-unimplemented/on-trait.rs index a8daef356a..ed7ec9b143 100644 --- a/src/test/compile-fail/on-unimplemented/on-trait.rs +++ b/src/test/ui/on-unimplemented/on-trait.rs @@ -11,9 +11,12 @@ #![feature(on_unimplemented)] -#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}`"] -trait Foo -{} +pub mod Bar { + #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}` in `{Foo}`"] + pub trait Foo {} +} + +use Bar::Foo; fn foobar>() -> T { panic!() diff --git a/src/test/ui/on-unimplemented/on-trait.stderr b/src/test/ui/on-unimplemented/on-trait.stderr new file mode 100644 index 0000000000..84986c1ecf --- /dev/null +++ b/src/test/ui/on-unimplemented/on-trait.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `std::option::Option>: MyFromIterator<&u8>` is not satisfied + --> $DIR/on-trait.rs:37:30 + | +37 | let y: Option> = collect(x.iter()); // this should give approximately the same error for x.iter().collect() + | ^^^^^^^ a collection of type `std::option::Option>` cannot be built from an iterator over elements of type `&u8` + | + = help: the trait `MyFromIterator<&u8>` is not implemented for `std::option::Option>` + = note: required by `collect` + +error[E0277]: the trait bound `std::string::String: Bar::Foo` is not satisfied + --> $DIR/on-trait.rs:42:21 + | +42 | let x: String = foobar(); //~ ERROR + | ^^^^^^ test error `std::string::String` with `u8` `_` `u32` in `Bar::Foo` + | + = help: the trait `Bar::Foo` is not implemented for `std::string::String` + = note: required by `foobar` + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/on-unimplemented/slice-index.rs b/src/test/ui/on-unimplemented/slice-index.rs similarity index 100% rename from src/test/compile-fail/on-unimplemented/slice-index.rs rename to src/test/ui/on-unimplemented/slice-index.rs diff --git a/src/test/ui/on-unimplemented/slice-index.stderr b/src/test/ui/on-unimplemented/slice-index.stderr new file mode 100644 index 0000000000..68789f77f7 --- /dev/null +++ b/src/test/ui/on-unimplemented/slice-index.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `i32: std::slice::SliceIndex<[i32]>` is not satisfied + --> $DIR/slice-index.rs:21:5 + | +21 | x[1i32]; //~ ERROR E0277 + | ^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `std::slice::SliceIndex<[i32]>` is not implemented for `i32` + = note: required because of the requirements on the impl of `std::ops::Index` for `[i32]` + +error[E0277]: the trait bound `std::ops::RangeTo: std::slice::SliceIndex<[i32]>` is not satisfied + --> $DIR/slice-index.rs:24:5 + | +24 | x[..1i32]; //~ ERROR E0277 + | ^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `std::slice::SliceIndex<[i32]>` is not implemented for `std::ops::RangeTo` + = note: required because of the requirements on the impl of `std::ops::Index>` for `[i32]` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/path-lookahead.stderr b/src/test/ui/path-lookahead.stderr index 1e19977e84..8fd1b8de68 100644 --- a/src/test/ui/path-lookahead.stderr +++ b/src/test/ui/path-lookahead.stderr @@ -23,6 +23,4 @@ warning: function is never used: `no_parens` 20 | | return ::to_string(&arg); 21 | | } | |_^ - | - = note: #[warn(dead_code)] on by default diff --git a/src/test/ui/pub/pub-restricted-error-fn.stderr b/src/test/ui/pub/pub-restricted-error-fn.stderr index 94fc8f15c2..470e833124 100644 --- a/src/test/ui/pub/pub-restricted-error-fn.stderr +++ b/src/test/ui/pub/pub-restricted-error-fn.stderr @@ -4,5 +4,5 @@ error: unmatched visibility `pub` 13 | pub(crate) () fn foo() {} | ^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/pub/pub-restricted-error.stderr b/src/test/ui/pub/pub-restricted-error.stderr index eebb2428ba..b8b4c80778 100644 --- a/src/test/ui/pub/pub-restricted-error.stderr +++ b/src/test/ui/pub/pub-restricted-error.stderr @@ -4,5 +4,5 @@ error: expected identifier, found `(` 16 | pub(crate) () foo: usize, | ^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/pub/pub-restricted-non-path.stderr b/src/test/ui/pub/pub-restricted-non-path.stderr index 865b1d409e..ebfccc4d72 100644 --- a/src/test/ui/pub/pub-restricted-non-path.stderr +++ b/src/test/ui/pub/pub-restricted-non-path.stderr @@ -4,5 +4,5 @@ error: expected identifier, found `.` 13 | pub (.) fn afn() {} | ^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/pub/pub-restricted.stderr b/src/test/ui/pub/pub-restricted.stderr index 34cc80fcc7..ae283f1fb6 100644 --- a/src/test/ui/pub/pub-restricted.stderr +++ b/src/test/ui/pub/pub-restricted.stderr @@ -48,5 +48,5 @@ error: visibilities can only be restricted to ancestor modules 33 | pub (in x) non_parent_invalid: usize, | ^ -error: aborting due to previous error(s) +error: aborting due to 5 previous errors diff --git a/src/test/ui/reachable/expr_add.stderr b/src/test/ui/reachable/expr_add.stderr index cbcbf88d86..1a2cc25205 100644 --- a/src/test/ui/reachable/expr_add.stderr +++ b/src/test/ui/reachable/expr_add.stderr @@ -10,5 +10,5 @@ note: lint level defined here 13 | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_again.stderr b/src/test/ui/reachable/expr_again.stderr index 20640c0a89..bf4e4dc471 100644 --- a/src/test/ui/reachable/expr_again.stderr +++ b/src/test/ui/reachable/expr_again.stderr @@ -11,5 +11,5 @@ note: lint level defined here | ^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_array.stderr b/src/test/ui/reachable/expr_array.stderr index c778aec081..f8dbdb5f8b 100644 --- a/src/test/ui/reachable/expr_array.stderr +++ b/src/test/ui/reachable/expr_array.stderr @@ -16,5 +16,5 @@ error: unreachable expression 25 | let x: [usize; 2] = [22, return]; | ^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_assign.stderr b/src/test/ui/reachable/expr_assign.stderr index 9310c00019..807f6a1c1d 100644 --- a/src/test/ui/reachable/expr_assign.stderr +++ b/src/test/ui/reachable/expr_assign.stderr @@ -22,5 +22,5 @@ error: unreachable expression 36 | *{return; &mut i} = 22; | ^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/reachable/expr_block.stderr b/src/test/ui/reachable/expr_block.stderr index ea7b962e19..542ce1c3fd 100644 --- a/src/test/ui/reachable/expr_block.stderr +++ b/src/test/ui/reachable/expr_block.stderr @@ -18,5 +18,5 @@ error: unreachable statement | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_box.stderr b/src/test/ui/reachable/expr_box.stderr index ee89104df9..78ba231cef 100644 --- a/src/test/ui/reachable/expr_box.stderr +++ b/src/test/ui/reachable/expr_box.stderr @@ -10,5 +10,5 @@ note: lint level defined here 13 | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_call.stderr b/src/test/ui/reachable/expr_call.stderr index 5e072ed1dc..5526827f59 100644 --- a/src/test/ui/reachable/expr_call.stderr +++ b/src/test/ui/reachable/expr_call.stderr @@ -16,5 +16,5 @@ error: unreachable expression 28 | bar(return); | ^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_cast.stderr b/src/test/ui/reachable/expr_cast.stderr index a8668dc735..a22300dcc1 100644 --- a/src/test/ui/reachable/expr_cast.stderr +++ b/src/test/ui/reachable/expr_cast.stderr @@ -10,5 +10,5 @@ note: lint level defined here 14 | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_if.stderr b/src/test/ui/reachable/expr_if.stderr index 7f901511f7..2cf17474f6 100644 --- a/src/test/ui/reachable/expr_if.stderr +++ b/src/test/ui/reachable/expr_if.stderr @@ -11,5 +11,5 @@ note: lint level defined here | ^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_loop.stderr b/src/test/ui/reachable/expr_loop.stderr index 4fb6392f40..6e98e754c5 100644 --- a/src/test/ui/reachable/expr_loop.stderr +++ b/src/test/ui/reachable/expr_loop.stderr @@ -27,5 +27,5 @@ error: unreachable statement | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/reachable/expr_match.stderr b/src/test/ui/reachable/expr_match.stderr index 387f7900f4..f5857a5b34 100644 --- a/src/test/ui/reachable/expr_match.stderr +++ b/src/test/ui/reachable/expr_match.stderr @@ -26,5 +26,5 @@ error: unreachable statement | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/reachable/expr_method.stderr b/src/test/ui/reachable/expr_method.stderr index 68fd497341..177d4352a3 100644 --- a/src/test/ui/reachable/expr_method.stderr +++ b/src/test/ui/reachable/expr_method.stderr @@ -16,5 +16,5 @@ error: unreachable expression 31 | Foo.bar(return); | ^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_repeat.stderr b/src/test/ui/reachable/expr_repeat.stderr index 01b2e1009e..19afc5dd7b 100644 --- a/src/test/ui/reachable/expr_repeat.stderr +++ b/src/test/ui/reachable/expr_repeat.stderr @@ -10,5 +10,5 @@ note: lint level defined here 14 | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_return.stderr b/src/test/ui/reachable/expr_return.stderr index ee958aa908..3eb70a4dd7 100644 --- a/src/test/ui/reachable/expr_return.stderr +++ b/src/test/ui/reachable/expr_return.stderr @@ -10,5 +10,5 @@ note: lint level defined here 14 | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_struct.stderr b/src/test/ui/reachable/expr_struct.stderr index 08866bf32b..4b7ac66041 100644 --- a/src/test/ui/reachable/expr_struct.stderr +++ b/src/test/ui/reachable/expr_struct.stderr @@ -28,5 +28,5 @@ error: unreachable expression 40 | let x = Foo { a: 22, b: return }; | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/reachable/expr_tup.stderr b/src/test/ui/reachable/expr_tup.stderr index 780fb02f79..63f477fd0c 100644 --- a/src/test/ui/reachable/expr_tup.stderr +++ b/src/test/ui/reachable/expr_tup.stderr @@ -16,5 +16,5 @@ error: unreachable expression 25 | let x: (usize, usize) = (2, return); | ^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_type.stderr b/src/test/ui/reachable/expr_type.stderr index 1216ec2676..6ed79974cc 100644 --- a/src/test/ui/reachable/expr_type.stderr +++ b/src/test/ui/reachable/expr_type.stderr @@ -10,5 +10,5 @@ note: lint level defined here 14 | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_unary.stderr b/src/test/ui/reachable/expr_unary.stderr index f47791455a..328b75fd23 100644 --- a/src/test/ui/reachable/expr_unary.stderr +++ b/src/test/ui/reachable/expr_unary.stderr @@ -4,5 +4,5 @@ error[E0600]: cannot apply unary operator `!` to type `!` 18 | let x: ! = ! { return; 22 }; | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_while.stderr b/src/test/ui/reachable/expr_while.stderr index 3da057f4bb..066cfc86c6 100644 --- a/src/test/ui/reachable/expr_while.stderr +++ b/src/test/ui/reachable/expr_while.stderr @@ -27,5 +27,5 @@ error: unreachable statement | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/regions-fn-subtyping-return-static.stderr b/src/test/ui/regions-fn-subtyping-return-static.stderr index 121a50d0ed..0c7b44af94 100644 --- a/src/test/ui/regions-fn-subtyping-return-static.stderr +++ b/src/test/ui/regions-fn-subtyping-return-static.stderr @@ -9,5 +9,5 @@ error[E0308]: mismatched types = note: lifetime parameter `'b` declared on fn `bar` appears only in the return type, but here is required to be higher-ranked, which means that `'b` must appear in both argument and return types = note: this error is the result of a recent bug fix; for more information, see issue #33685 -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve-error.stderr b/src/test/ui/resolve-error.stderr new file mode 100644 index 0000000000..27f9393924 --- /dev/null +++ b/src/test/ui/resolve-error.stderr @@ -0,0 +1,62 @@ +error: cannot find derive macro `FooWithLongNan` in this scope + --> $DIR/resolve-error.rs:37:10 + | +37 | #[derive(FooWithLongNan)] + | ^^^^^^^^^^^^^^ help: try: `FooWithLongName` + +error: cannot find attribute macro `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:40:3 + | +40 | #[attr_proc_macra] + | ^^^^^^^^^^^^^^^ help: try: `attr_proc_macro` + +error: cannot find attribute macro `FooWithLongNan` in this scope + --> $DIR/resolve-error.rs:43:3 + | +43 | #[FooWithLongNan] + | ^^^^^^^^^^^^^^ + +error: cannot find derive macro `Dlone` in this scope + --> $DIR/resolve-error.rs:46:10 + | +46 | #[derive(Dlone)] + | ^^^^^ help: try: `Clone` + +error: cannot find derive macro `Dlona` in this scope + --> $DIR/resolve-error.rs:49:10 + | +49 | #[derive(Dlona)] + | ^^^^^ help: try: `Clona` + +error: cannot find derive macro `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:52:10 + | +52 | #[derive(attr_proc_macra)] + | ^^^^^^^^^^^^^^^ + +error: cannot find macro `FooWithLongNama!` in this scope + --> $DIR/resolve-error.rs:56:5 + | +56 | FooWithLongNama!(); + | ^^^^^^^^^^^^^^^ help: you could try the macro: `FooWithLongNam!` + +error: cannot find macro `attr_proc_macra!` in this scope + --> $DIR/resolve-error.rs:58:5 + | +58 | attr_proc_macra!(); + | ^^^^^^^^^^^^^^^ help: you could try the macro: `attr_proc_mac!` + +error: cannot find macro `Dlona!` in this scope + --> $DIR/resolve-error.rs:60:5 + | +60 | Dlona!(); + | ^^^^^ + +error: cannot find macro `bang_proc_macrp!` in this scope + --> $DIR/resolve-error.rs:62:5 + | +62 | bang_proc_macrp!(); + | ^^^^^^^^^^^^^^^ help: you could try the macro: `bang_proc_macro!` + +error: aborting due to previous error(s) + diff --git a/src/test/ui/resolve/enums-are-namespaced-xc.stderr b/src/test/ui/resolve/enums-are-namespaced-xc.stderr index 03e80046f6..4b32ecff2f 100644 --- a/src/test/ui/resolve/enums-are-namespaced-xc.stderr +++ b/src/test/ui/resolve/enums-are-namespaced-xc.stderr @@ -5,7 +5,9 @@ error[E0425]: cannot find value `A` in module `namespaced_enums` | ^ not found in `namespaced_enums` | help: possible candidate is found in another module, you can import it into scope - | use namespaced_enums::Foo::A; + | +12 | use namespaced_enums::Foo::A; + | error[E0425]: cannot find function `B` in module `namespaced_enums` --> $DIR/enums-are-namespaced-xc.rs:18:31 @@ -14,7 +16,9 @@ error[E0425]: cannot find function `B` in module `namespaced_enums` | ^ not found in `namespaced_enums` | help: possible candidate is found in another module, you can import it into scope - | use namespaced_enums::Foo::B; + | +12 | use namespaced_enums::Foo::B; + | error[E0422]: cannot find struct, variant or union type `C` in module `namespaced_enums` --> $DIR/enums-are-namespaced-xc.rs:21:31 @@ -23,7 +27,9 @@ error[E0422]: cannot find struct, variant or union type `C` in module `namespace | ^ not found in `namespaced_enums` | help: possible candidate is found in another module, you can import it into scope - | use namespaced_enums::Foo::C; + | +12 | use namespaced_enums::Foo::C; + | -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/resolve/issue-14254.stderr b/src/test/ui/resolve/issue-14254.stderr index 009d969fc2..7aa0c2707b 100644 --- a/src/test/ui/resolve/issue-14254.stderr +++ b/src/test/ui/resolve/issue-14254.stderr @@ -2,7 +2,7 @@ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:29:9 | 29 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `a` in this scope --> $DIR/issue-14254.rs:32:9 @@ -14,19 +14,19 @@ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:40:9 | 40 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `x` in this scope --> $DIR/issue-14254.rs:43:9 | 43 | x; - | ^ did you mean `self.x`? + | ^ help: try: `self.x` error[E0425]: cannot find value `y` in this scope --> $DIR/issue-14254.rs:46:9 | 46 | y; - | ^ did you mean `self.y`? + | ^ help: try: `self.y` error[E0425]: cannot find value `a` in this scope --> $DIR/issue-14254.rs:49:9 @@ -38,7 +38,7 @@ error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:52:9 | 52 | bah; - | ^^^ did you mean `Self::bah`? + | ^^^ help: try: `Self::bah` error[E0425]: cannot find value `b` in this scope --> $DIR/issue-14254.rs:55:9 @@ -50,19 +50,19 @@ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:63:9 | 63 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `x` in this scope --> $DIR/issue-14254.rs:66:9 | 66 | x; - | ^ did you mean `self.x`? + | ^ help: try: `self.x` error[E0425]: cannot find value `y` in this scope --> $DIR/issue-14254.rs:69:9 | 69 | y; - | ^ did you mean `self.y`? + | ^ help: try: `self.y` error[E0425]: cannot find value `a` in this scope --> $DIR/issue-14254.rs:72:9 @@ -74,7 +74,7 @@ error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:75:9 | 75 | bah; - | ^^^ did you mean `Self::bah`? + | ^^^ help: try: `Self::bah` error[E0425]: cannot find value `b` in this scope --> $DIR/issue-14254.rs:78:9 @@ -86,63 +86,63 @@ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:86:9 | 86 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:89:9 | 89 | bah; - | ^^^ did you mean `Self::bah`? + | ^^^ help: try: `Self::bah` error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:97:9 | 97 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:100:9 | 100 | bah; - | ^^^ did you mean `Self::bah`? + | ^^^ help: try: `Self::bah` error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:108:9 | 108 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:111:9 | 111 | bah; - | ^^^ did you mean `Self::bah`? + | ^^^ help: try: `Self::bah` error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:119:9 | 119 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:122:9 | 122 | bah; - | ^^^ did you mean `Self::bah`? + | ^^^ help: try: `Self::bah` error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:130:9 | 130 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:133:9 | 133 | bah; - | ^^^ did you mean `Self::bah`? + | ^^^ help: try: `Self::bah` error[E0601]: main function not found -error: aborting due to previous error(s) +error: aborting due to 25 previous errors diff --git a/src/test/ui/resolve/issue-16058.stderr b/src/test/ui/resolve/issue-16058.stderr index 2fbf7d7185..6d7406f891 100644 --- a/src/test/ui/resolve/issue-16058.stderr +++ b/src/test/ui/resolve/issue-16058.stderr @@ -5,9 +5,13 @@ error[E0574]: expected struct, variant or union type, found enum `Result` | ^^^^^^ not a struct, variant or union type | help: possible better candidates are found in other modules, you can import them into scope - | use std::fmt::Result; - | use std::io::Result; - | use std::thread::Result; + | +12 | use std::fmt::Result; + | +12 | use std::io::Result; + | +12 | use std::thread::Result; + | -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-17518.stderr b/src/test/ui/resolve/issue-17518.stderr index 69eeb178df..2f94dbdc2c 100644 --- a/src/test/ui/resolve/issue-17518.stderr +++ b/src/test/ui/resolve/issue-17518.stderr @@ -5,7 +5,9 @@ error[E0422]: cannot find struct, variant or union type `E` in this scope | ^ not found in this scope | help: possible candidate is found in another module, you can import it into scope - | use SomeEnum::E; + | +11 | use SomeEnum::E; + | -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-18252.stderr b/src/test/ui/resolve/issue-18252.stderr index 225e31010d..edc7196d84 100644 --- a/src/test/ui/resolve/issue-18252.stderr +++ b/src/test/ui/resolve/issue-18252.stderr @@ -4,5 +4,5 @@ error[E0423]: expected function, found struct variant `Foo::Variant` 16 | let f = Foo::Variant(42); | ^^^^^^^^^^^^ did you mean `Foo::Variant { /* fields */ }`? -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-19452.stderr b/src/test/ui/resolve/issue-19452.stderr index 25ee3a0214..7b14d49af5 100644 --- a/src/test/ui/resolve/issue-19452.stderr +++ b/src/test/ui/resolve/issue-19452.stderr @@ -10,5 +10,5 @@ error[E0423]: expected value, found struct variant `issue_19452_aux::Homura::Mad 22 | let homura = issue_19452_aux::Homura::Madoka; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ did you mean `issue_19452_aux::Homura::Madoka { /* fields */ }`? -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/resolve/issue-21221-1.stderr b/src/test/ui/resolve/issue-21221-1.stderr index 7315d295f7..ddaee451e9 100644 --- a/src/test/ui/resolve/issue-21221-1.stderr +++ b/src/test/ui/resolve/issue-21221-1.stderr @@ -5,9 +5,13 @@ error[E0405]: cannot find trait `Mul` in this scope | ^^^ not found in this scope | help: possible candidates are found in other modules, you can import them into scope - | use mul1::Mul; - | use mul2::Mul; - | use std::ops::Mul; + | +11 | use mul1::Mul; + | +11 | use mul2::Mul; + | +11 | use std::ops::Mul; + | error[E0412]: cannot find type `Mul` in this scope --> $DIR/issue-21221-1.rs:72:16 @@ -16,10 +20,15 @@ error[E0412]: cannot find type `Mul` in this scope | ^^^ not found in this scope | help: possible candidates are found in other modules, you can import them into scope - | use mul1::Mul; - | use mul2::Mul; - | use mul3::Mul; - | use mul4::Mul; + | +11 | use mul1::Mul; + | +11 | use mul2::Mul; + | +11 | use mul3::Mul; + | +11 | use mul4::Mul; + | and 2 other candidates error[E0405]: cannot find trait `ThisTraitReallyDoesntExistInAnyModuleReally` in this scope @@ -35,7 +44,9 @@ error[E0405]: cannot find trait `Div` in this scope | ^^^ not found in this scope | help: possible candidate is found in another module, you can import it into scope - | use std::ops::Div; + | +11 | use std::ops::Div; + | error: cannot continue compilation due to previous error diff --git a/src/test/ui/resolve/issue-21221-2.stderr b/src/test/ui/resolve/issue-21221-2.stderr index b35f1bd267..a759116c6a 100644 --- a/src/test/ui/resolve/issue-21221-2.stderr +++ b/src/test/ui/resolve/issue-21221-2.stderr @@ -5,7 +5,9 @@ error[E0405]: cannot find trait `T` in this scope | ^ not found in this scope | help: possible candidate is found in another module, you can import it into scope - | use foo::bar::T; + | +11 | use foo::bar::T; + | error[E0601]: main function not found diff --git a/src/test/ui/resolve/issue-21221-3.stderr b/src/test/ui/resolve/issue-21221-3.stderr index a4a2496b19..f4d183192b 100644 --- a/src/test/ui/resolve/issue-21221-3.stderr +++ b/src/test/ui/resolve/issue-21221-3.stderr @@ -5,7 +5,9 @@ error[E0405]: cannot find trait `OuterTrait` in this scope | ^^^^^^^^^^ not found in this scope | help: possible candidate is found in another module, you can import it into scope - | use issue_21221_3::outer::OuterTrait; + | +16 | use issue_21221_3::outer::OuterTrait; + | error: cannot continue compilation due to previous error diff --git a/src/test/ui/resolve/issue-21221-4.stderr b/src/test/ui/resolve/issue-21221-4.stderr index dc2f227173..eb71ee893c 100644 --- a/src/test/ui/resolve/issue-21221-4.stderr +++ b/src/test/ui/resolve/issue-21221-4.stderr @@ -5,7 +5,9 @@ error[E0405]: cannot find trait `T` in this scope | ^ not found in this scope | help: possible candidate is found in another module, you can import it into scope - | use issue_21221_4::T; + | +16 | use issue_21221_4::T; + | error: cannot continue compilation due to previous error diff --git a/src/test/ui/resolve/issue-23305.stderr b/src/test/ui/resolve/issue-23305.stderr index 2ca541c161..fda87de9b9 100644 --- a/src/test/ui/resolve/issue-23305.stderr +++ b/src/test/ui/resolve/issue-23305.stderr @@ -11,5 +11,5 @@ note: the cycle begins when processing ``, completing the cycle. -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-2356.stderr b/src/test/ui/resolve/issue-2356.stderr index 559598dd38..9c683f4418 100644 --- a/src/test/ui/resolve/issue-2356.stderr +++ b/src/test/ui/resolve/issue-2356.stderr @@ -8,13 +8,13 @@ error[E0425]: cannot find function `clone` in this scope --> $DIR/issue-2356.rs:35:5 | 35 | clone(); - | ^^^^^ did you mean `self.clone(...)`? + | ^^^^^ help: try: `self.clone` error[E0425]: cannot find function `default` in this scope --> $DIR/issue-2356.rs:43:5 | 43 | default(); - | ^^^^^^^ did you mean `Self::default`? + | ^^^^^^^ help: try: `Self::default` error[E0425]: cannot find value `whiskers` in this scope --> $DIR/issue-2356.rs:52:5 @@ -22,14 +22,14 @@ error[E0425]: cannot find value `whiskers` in this scope 52 | whiskers -= other; | ^^^^^^^^ | | - | did you mean `self.whiskers`? + | help: try: `self.whiskers` | `self` value is only available in methods with `self` parameter error[E0425]: cannot find function `shave` in this scope --> $DIR/issue-2356.rs:57:5 | 57 | shave(4); - | ^^^^^ did you mean `Self::shave`? + | ^^^^^ help: try: `Self::shave` error[E0425]: cannot find function `purr` in this scope --> $DIR/issue-2356.rs:60:5 @@ -83,7 +83,7 @@ error[E0425]: cannot find value `whiskers` in this scope --> $DIR/issue-2356.rs:104:5 | 104 | whiskers = 0; - | ^^^^^^^^ did you mean `self.whiskers`? + | ^^^^^^^^ help: try: `self.whiskers` error[E0425]: cannot find value `whiskers` in this scope --> $DIR/issue-2356.rs:110:5 @@ -91,7 +91,7 @@ error[E0425]: cannot find value `whiskers` in this scope 110 | whiskers = 4; | ^^^^^^^^ | | - | did you mean `self.whiskers`? + | help: try: `self.whiskers` | `self` value is only available in methods with `self` parameter error[E0425]: cannot find function `purr_louder` in this scope @@ -106,5 +106,5 @@ error[E0424]: expected value, found module `self` 122 | self += 1; | ^^^^ `self` value is only available in methods with `self` parameter -error: aborting due to previous error(s) +error: aborting due to 17 previous errors diff --git a/src/test/ui/resolve/issue-24968.stderr b/src/test/ui/resolve/issue-24968.stderr index 14a2413fee..111710d515 100644 --- a/src/test/ui/resolve/issue-24968.stderr +++ b/src/test/ui/resolve/issue-24968.stderr @@ -4,5 +4,5 @@ error[E0411]: cannot find type `Self` in this scope 11 | fn foo(_: Self) { | ^^^^ `Self` is only available in traits and impls -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-33876.stderr b/src/test/ui/resolve/issue-33876.stderr index a950075715..5dbecc4f0c 100644 --- a/src/test/ui/resolve/issue-33876.stderr +++ b/src/test/ui/resolve/issue-33876.stderr @@ -4,5 +4,5 @@ error[E0423]: expected value, found trait `Bar` 20 | let any: &Any = &Bar; //~ ERROR expected value, found trait `Bar` | ^^^ not a value -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-3907-2.stderr b/src/test/ui/resolve/issue-3907-2.stderr index 4e1ef25f80..2ef8c830eb 100644 --- a/src/test/ui/resolve/issue-3907-2.stderr +++ b/src/test/ui/resolve/issue-3907-2.stderr @@ -6,5 +6,5 @@ error[E0038]: the trait `issue_3907::Foo` cannot be made into an object | = note: method `bar` has no receiver -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-3907.stderr b/src/test/ui/resolve/issue-3907.stderr index 0bf39dc55c..70b4599dbf 100644 --- a/src/test/ui/resolve/issue-3907.stderr +++ b/src/test/ui/resolve/issue-3907.stderr @@ -5,7 +5,9 @@ error[E0404]: expected trait, found type alias `Foo` | ^^^ type aliases cannot be used for traits | help: possible better candidate is found in another module, you can import it into scope - | use issue_3907::Foo; + | +12 | use issue_3907::Foo; + | error: cannot continue compilation due to previous error diff --git a/src/test/ui/resolve/issue-39226.stderr b/src/test/ui/resolve/issue-39226.stderr index 134a4540a8..f6ee0b025b 100644 --- a/src/test/ui/resolve/issue-39226.stderr +++ b/src/test/ui/resolve/issue-39226.stderr @@ -7,5 +7,5 @@ error[E0423]: expected value, found struct `Handle` | did you mean `handle`? | did you mean `Handle { /* fields */ }`? -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-5035-2.stderr b/src/test/ui/resolve/issue-5035-2.stderr index 9bdd7ee4fd..791b20725f 100644 --- a/src/test/ui/resolve/issue-5035-2.stderr +++ b/src/test/ui/resolve/issue-5035-2.stderr @@ -7,5 +7,5 @@ error[E0277]: the trait bound `I + 'static: std::marker::Sized` is not satisfied = help: the trait `std::marker::Sized` is not implemented for `I + 'static` = note: all local variables must have a statically known size -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-6702.stderr b/src/test/ui/resolve/issue-6702.stderr index 620958190c..b50295752f 100644 --- a/src/test/ui/resolve/issue-6702.stderr +++ b/src/test/ui/resolve/issue-6702.stderr @@ -4,5 +4,5 @@ error[E0423]: expected function, found struct `Monster` 17 | let _m = Monster(); //~ ERROR expected function, found struct `Monster` | ^^^^^^^ did you mean `Monster { /* fields */ }`? -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/levenshtein.stderr b/src/test/ui/resolve/levenshtein.stderr index d25c52eeab..4dff262031 100644 --- a/src/test/ui/resolve/levenshtein.stderr +++ b/src/test/ui/resolve/levenshtein.stderr @@ -46,5 +46,5 @@ error[E0425]: cannot find value `second` in module `m` 32 | let b: m::first = m::second; // Misspelled item in module. | ^^^^^^ did you mean `Second`? -error: aborting due to previous error(s) +error: aborting due to 8 previous errors diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr index a1ec5f0b71..57b143d34d 100644 --- a/src/test/ui/resolve/privacy-struct-ctor.stderr +++ b/src/test/ui/resolve/privacy-struct-ctor.stderr @@ -9,7 +9,9 @@ error[E0423]: expected value, found struct `Z` | constructor is not visible here due to private fields | help: possible better candidate is found in another module, you can import it into scope - | use m::n::Z; + | +15 | use m::n::Z; + | error[E0423]: expected value, found struct `S` --> $DIR/privacy-struct-ctor.rs:36:5 @@ -21,7 +23,9 @@ error[E0423]: expected value, found struct `S` | constructor is not visible here due to private fields | help: possible better candidate is found in another module, you can import it into scope - | use m::S; + | +13 | use m::S; + | error[E0423]: expected value, found struct `xcrate::S` --> $DIR/privacy-struct-ctor.rs:42:5 @@ -33,7 +37,9 @@ error[E0423]: expected value, found struct `xcrate::S` | constructor is not visible here due to private fields | help: possible better candidate is found in another module, you can import it into scope - | use m::S; + | +13 | use m::S; + | error[E0603]: tuple struct `Z` is private --> $DIR/privacy-struct-ctor.rs:25:9 @@ -65,5 +71,5 @@ error[E0603]: tuple struct `Z` is private 45 | xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private | ^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 8 previous errors diff --git a/src/test/ui/resolve/resolve-assoc-suggestions.stderr b/src/test/ui/resolve/resolve-assoc-suggestions.stderr index c346612a68..77aa545e2a 100644 --- a/src/test/ui/resolve/resolve-assoc-suggestions.stderr +++ b/src/test/ui/resolve/resolve-assoc-suggestions.stderr @@ -14,13 +14,13 @@ error[E0425]: cannot find value `field` in this scope --> $DIR/resolve-assoc-suggestions.rs:32:9 | 32 | field; - | ^^^^^ did you mean `self.field`? + | ^^^^^ help: try: `self.field` error[E0412]: cannot find type `Type` in this scope --> $DIR/resolve-assoc-suggestions.rs:36:16 | 36 | let _: Type; - | ^^^^ did you mean `Self::Type`? + | ^^^^ help: try: `Self::Type` error[E0531]: cannot find tuple struct/variant `Type` in this scope --> $DIR/resolve-assoc-suggestions.rs:39:13 @@ -50,7 +50,7 @@ error[E0425]: cannot find value `method` in this scope --> $DIR/resolve-assoc-suggestions.rs:52:9 | 52 | method; - | ^^^^^^ did you mean `self.method(...)`? + | ^^^^^^ help: try: `self.method` -error: aborting due to previous error(s) +error: aborting due to 9 previous errors diff --git a/src/test/ui/resolve/resolve-hint-macro.stderr b/src/test/ui/resolve/resolve-hint-macro.stderr index 92f13f705b..ffb3f84843 100644 --- a/src/test/ui/resolve/resolve-hint-macro.stderr +++ b/src/test/ui/resolve/resolve-hint-macro.stderr @@ -4,5 +4,5 @@ error[E0423]: expected function, found macro `assert` 12 | assert(true); | ^^^^^^ did you mean `assert!(...)`? -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/resolve-speculative-adjustment.stderr b/src/test/ui/resolve/resolve-speculative-adjustment.stderr index 04c8087ace..3e1b075679 100644 --- a/src/test/ui/resolve/resolve-speculative-adjustment.stderr +++ b/src/test/ui/resolve/resolve-speculative-adjustment.stderr @@ -14,13 +14,13 @@ error[E0425]: cannot find value `field` in this scope --> $DIR/resolve-speculative-adjustment.rs:35:9 | 35 | field; - | ^^^^^ did you mean `self.field`? + | ^^^^^ help: try: `self.field` error[E0425]: cannot find function `method` in this scope --> $DIR/resolve-speculative-adjustment.rs:38:9 | 38 | method(); - | ^^^^^^ did you mean `self.method(...)`? + | ^^^^^^ help: try: `self.method` -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr index a34c27a47d..d1794d19f6 100644 --- a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr +++ b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr @@ -74,5 +74,5 @@ error[E0423]: expected function, found module `a::b` error[E0601]: main function not found -error: aborting due to previous error(s) +error: aborting due to 10 previous errors diff --git a/src/test/ui/resolve/token-error-correct-2.stderr b/src/test/ui/resolve/token-error-correct-2.stderr index 7307f19c74..feb12612e6 100644 --- a/src/test/ui/resolve/token-error-correct-2.stderr +++ b/src/test/ui/resolve/token-error-correct-2.stderr @@ -16,5 +16,5 @@ error[E0425]: cannot find value `foo` in this scope 14 | if foo { | ^^^ not found in this scope -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/resolve/token-error-correct-3.stderr b/src/test/ui/resolve/token-error-correct-3.stderr index d234c8538f..2e8cc40dc5 100644 --- a/src/test/ui/resolve/token-error-correct-3.stderr +++ b/src/test/ui/resolve/token-error-correct-3.stderr @@ -35,10 +35,12 @@ error[E0308]: mismatched types --> $DIR/token-error-correct-3.rs:25:13 | 25 | fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `std::result::Result` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: did you mean to add a semicolon here?: `;` + | | + | expected (), found enum `std::result::Result` | = note: expected type `()` found type `std::result::Result` -error: aborting due to previous error(s) +error: aborting due to 5 previous errors diff --git a/src/test/ui/resolve/token-error-correct.stderr b/src/test/ui/resolve/token-error-correct.stderr index 1dd263affd..226fa6469b 100644 --- a/src/test/ui/resolve/token-error-correct.stderr +++ b/src/test/ui/resolve/token-error-correct.stderr @@ -52,5 +52,5 @@ error[E0425]: cannot find function `bar` in this scope 14 | foo(bar(; | ^^^ not found in this scope -error: aborting due to previous error(s) +error: aborting due to 7 previous errors diff --git a/src/test/ui/resolve/tuple-struct-alias.stderr b/src/test/ui/resolve/tuple-struct-alias.stderr index 2fc5979a60..e2ef8f0e56 100644 --- a/src/test/ui/resolve/tuple-struct-alias.stderr +++ b/src/test/ui/resolve/tuple-struct-alias.stderr @@ -28,5 +28,5 @@ error[E0532]: expected tuple struct/variant, found type alias `A` | did you mean `S`? | did you mean `A { /* fields */ }`? -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/resolve/unresolved_static_type_field.stderr b/src/test/ui/resolve/unresolved_static_type_field.stderr index ff6bcf2a53..e598851e36 100644 --- a/src/test/ui/resolve/unresolved_static_type_field.stderr +++ b/src/test/ui/resolve/unresolved_static_type_field.stderr @@ -4,8 +4,8 @@ error[E0425]: cannot find value `cx` in this scope 19 | f(cx); | ^^ | | - | did you mean `self.cx`? + | help: try: `self.cx` | `self` value is only available in methods with `self` parameter -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/compile-fail/shadowed-type-parameter.rs b/src/test/ui/shadowed-type-parameter.rs similarity index 100% rename from src/test/compile-fail/shadowed-type-parameter.rs rename to src/test/ui/shadowed-type-parameter.rs diff --git a/src/test/ui/shadowed-type-parameter.stderr b/src/test/ui/shadowed-type-parameter.stderr new file mode 100644 index 0000000000..a16a9c0244 --- /dev/null +++ b/src/test/ui/shadowed-type-parameter.stderr @@ -0,0 +1,28 @@ +error[E0194]: type parameter `T` shadows another type parameter of the same name + --> $DIR/shadowed-type-parameter.rs:30:27 + | +27 | trait Bar { + | - first `T` declared here +... +30 | fn shadow_in_required(&self); + | ^ shadows another type parameter + +error[E0194]: type parameter `T` shadows another type parameter of the same name + --> $DIR/shadowed-type-parameter.rs:33:27 + | +27 | trait Bar { + | - first `T` declared here +... +33 | fn shadow_in_provided(&self) {} + | ^ shadows another type parameter + +error[E0194]: type parameter `T` shadows another type parameter of the same name + --> $DIR/shadowed-type-parameter.rs:18:25 + | +17 | impl Foo { + | - first `T` declared here +18 | fn shadow_in_method(&self) {} + | ^ shadows another type parameter + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/span/E0046.stderr b/src/test/ui/span/E0046.stderr index f722908ec1..729a515612 100644 --- a/src/test/ui/span/E0046.stderr +++ b/src/test/ui/span/E0046.stderr @@ -7,5 +7,5 @@ error[E0046]: not all trait items implemented, missing: `foo` 18 | impl Foo for Bar {} | ^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/E0057.stderr b/src/test/ui/span/E0057.stderr index bc3a3908dc..0d6b0a552e 100644 --- a/src/test/ui/span/E0057.stderr +++ b/src/test/ui/span/E0057.stderr @@ -10,5 +10,5 @@ error[E0057]: this function takes 1 parameter but 2 parameters were supplied 15 | let c = f(2, 3); //~ ERROR E0057 | ^^^^ expected 1 parameter -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/E0072.stderr b/src/test/ui/span/E0072.stderr index 14e6bcb73b..1f6dd6b1d1 100644 --- a/src/test/ui/span/E0072.stderr +++ b/src/test/ui/span/E0072.stderr @@ -9,5 +9,5 @@ error[E0072]: recursive type `ListNode` has infinite size | = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/E0204.stderr b/src/test/ui/span/E0204.stderr index fab2436922..4fe6afaca8 100644 --- a/src/test/ui/span/E0204.stderr +++ b/src/test/ui/span/E0204.stderr @@ -34,5 +34,5 @@ error[E0204]: the trait `Copy` may not be implemented for this type 31 | Bar(&'a mut bool), | ------------- this field does not implement `Copy` -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/span/E0493.stderr b/src/test/ui/span/E0493.stderr index 5f8b57294d..afcc9a240e 100644 --- a/src/test/ui/span/E0493.stderr +++ b/src/test/ui/span/E0493.stderr @@ -7,5 +7,5 @@ error[E0493]: constants are not allowed to have destructors 27 | const F : Foo = Foo { a : 0 }; | ^^^^^^^^^^^^^ constants cannot have destructors -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/E0535.stderr b/src/test/ui/span/E0535.stderr index 64c0016085..23070e1555 100644 --- a/src/test/ui/span/E0535.stderr +++ b/src/test/ui/span/E0535.stderr @@ -4,5 +4,5 @@ error[E0535]: invalid argument 11 | #[inline(unknown)] //~ ERROR E0535 | ^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/E0536.stderr b/src/test/ui/span/E0536.stderr index 8a4cf34e56..b2da0c6a29 100644 --- a/src/test/ui/span/E0536.stderr +++ b/src/test/ui/span/E0536.stderr @@ -4,5 +4,5 @@ error[E0536]: expected 1 cfg-pattern 11 | #[cfg(not())] //~ ERROR E0536 | ^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/E0537.stderr b/src/test/ui/span/E0537.stderr index 1bd54a6a00..29873943f4 100644 --- a/src/test/ui/span/E0537.stderr +++ b/src/test/ui/span/E0537.stderr @@ -4,5 +4,5 @@ error[E0537]: invalid predicate `unknown` 11 | #[cfg(unknown())] //~ ERROR E0537 | ^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr index 4b01f5bea7..2d580e7c20 100644 --- a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr +++ b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr @@ -82,5 +82,5 @@ error[E0596]: cannot borrow immutable borrowed content `*x` as mutable 143 | *x.y_mut() = 3; //~ ERROR cannot borrow | ^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to 10 previous errors diff --git a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr index 886cc14203..3d380a9a2e 100644 --- a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr +++ b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr @@ -30,5 +30,5 @@ error[E0596]: cannot borrow immutable borrowed content `*x` as mutable 63 | **x = 3; //~ ERROR cannot borrow | ^^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr index a26ca490dd..6e7d0c17f1 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr @@ -47,5 +47,5 @@ error[E0507]: cannot move out of captured outer variable in an `FnMut` closure 72 | foo(f); | ^ cannot move out of captured outer variable in an `FnMut` closure -error: aborting due to previous error(s) +error: aborting due to 5 previous errors diff --git a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr index dea95d6bf6..a57cc94b9b 100644 --- a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr +++ b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr @@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable borrowed content `*x` as mutable 27 | x.h(); //~ ERROR cannot borrow | ^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/borrowck-fn-in-const-b.stderr b/src/test/ui/span/borrowck-fn-in-const-b.stderr index 3bf56881c5..45712d1a71 100644 --- a/src/test/ui/span/borrowck-fn-in-const-b.stderr +++ b/src/test/ui/span/borrowck-fn-in-const-b.stderr @@ -6,5 +6,5 @@ error[E0596]: cannot borrow immutable borrowed content `*x` as mutable 17 | x.push(format!("this is broken")); | ^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr index 04dbcd2ef4..6ed1b7c262 100644 --- a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr +++ b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr @@ -48,5 +48,5 @@ error[E0597]: borrowed value does not live long enough | = note: consider using a `let` binding to increase its lifetime -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/span/borrowck-object-mutability.stderr b/src/test/ui/span/borrowck-object-mutability.stderr index 877b17dc27..530993f399 100644 --- a/src/test/ui/span/borrowck-object-mutability.stderr +++ b/src/test/ui/span/borrowck-object-mutability.stderr @@ -16,5 +16,5 @@ error[E0596]: cannot borrow immutable `Box` content `*x` as mutable 29 | x.borrowed_mut(); //~ ERROR cannot borrow | ^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/borrowck-ref-into-rvalue.stderr b/src/test/ui/span/borrowck-ref-into-rvalue.stderr index e0a484bcb3..ced1f762af 100644 --- a/src/test/ui/span/borrowck-ref-into-rvalue.stderr +++ b/src/test/ui/span/borrowck-ref-into-rvalue.stderr @@ -12,5 +12,5 @@ error[E0597]: borrowed value does not live long enough | = note: consider using a `let` binding to increase its lifetime -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/coerce-suggestions.stderr b/src/test/ui/span/coerce-suggestions.stderr index e3bc64a2cf..b703632bf9 100644 --- a/src/test/ui/span/coerce-suggestions.stderr +++ b/src/test/ui/span/coerce-suggestions.stderr @@ -58,5 +58,5 @@ error[E0308]: mismatched types = help: try with `&mut format!("foo")` = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/span/destructor-restrictions.stderr b/src/test/ui/span/destructor-restrictions.stderr index 1472a36486..ee88545416 100644 --- a/src/test/ui/span/destructor-restrictions.stderr +++ b/src/test/ui/span/destructor-restrictions.stderr @@ -8,5 +8,5 @@ error[E0597]: `*a` does not live long enough | | | `*a` dropped here while still borrowed -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/dropck-object-cycle.stderr b/src/test/ui/span/dropck-object-cycle.stderr index d0fceb2a03..49115b244e 100644 --- a/src/test/ui/span/dropck-object-cycle.stderr +++ b/src/test/ui/span/dropck-object-cycle.stderr @@ -9,5 +9,5 @@ error[E0597]: `*m` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/dropck_arr_cycle_checked.stderr b/src/test/ui/span/dropck_arr_cycle_checked.stderr index 2a9c2c8413..4179ac1a94 100644 --- a/src/test/ui/span/dropck_arr_cycle_checked.stderr +++ b/src/test/ui/span/dropck_arr_cycle_checked.stderr @@ -63,5 +63,5 @@ error[E0597]: `b2` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/span/dropck_direct_cycle_with_drop.stderr b/src/test/ui/span/dropck_direct_cycle_with_drop.stderr index e6421cd478..597d42aabd 100644 --- a/src/test/ui/span/dropck_direct_cycle_with_drop.stderr +++ b/src/test/ui/span/dropck_direct_cycle_with_drop.stderr @@ -19,5 +19,5 @@ error[E0597]: `d1` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/dropck_misc_variants.stderr b/src/test/ui/span/dropck_misc_variants.stderr index 7fbdcba7eb..958f229f65 100644 --- a/src/test/ui/span/dropck_misc_variants.stderr +++ b/src/test/ui/span/dropck_misc_variants.stderr @@ -19,5 +19,5 @@ error[E0597]: `v` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/dropck_vec_cycle_checked.stderr b/src/test/ui/span/dropck_vec_cycle_checked.stderr index 3861b145c1..d7d0fe5323 100644 --- a/src/test/ui/span/dropck_vec_cycle_checked.stderr +++ b/src/test/ui/span/dropck_vec_cycle_checked.stderr @@ -63,5 +63,5 @@ error[E0597]: `c2` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/span/impl-wrong-item-for-trait.rs b/src/test/ui/span/impl-wrong-item-for-trait.rs index 54ed42af5d..091df1d5dc 100644 --- a/src/test/ui/span/impl-wrong-item-for-trait.rs +++ b/src/test/ui/span/impl-wrong-item-for-trait.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] use std::fmt::Debug; diff --git a/src/test/ui/span/impl-wrong-item-for-trait.stderr b/src/test/ui/span/impl-wrong-item-for-trait.stderr index ca7286f502..5812cab0d0 100644 --- a/src/test/ui/span/impl-wrong-item-for-trait.stderr +++ b/src/test/ui/span/impl-wrong-item-for-trait.stderr @@ -1,89 +1,89 @@ error[E0437]: type `bar` is not a member of trait `Foo` - --> $DIR/impl-wrong-item-for-trait.rs:47:5 + --> $DIR/impl-wrong-item-for-trait.rs:46:5 | -47 | type bar = u64; +46 | type bar = u64; | ^^^^^^^^^^^^^^^ not a member of trait `Foo` error[E0323]: item `bar` is an associated const, which doesn't match its trait `Foo` - --> $DIR/impl-wrong-item-for-trait.rs:25:5 + --> $DIR/impl-wrong-item-for-trait.rs:24:5 | -16 | fn bar(&self); +15 | fn bar(&self); | -------------- item in trait ... -25 | const bar: u64 = 1; +24 | const bar: u64 = 1; | ^^^^^^^^^^^^^^^^^^^ does not match trait error[E0046]: not all trait items implemented, missing: `bar` - --> $DIR/impl-wrong-item-for-trait.rs:22:1 + --> $DIR/impl-wrong-item-for-trait.rs:21:1 | -16 | fn bar(&self); +15 | fn bar(&self); | -------------- `bar` from trait ... -22 | / impl Foo for FooConstForMethod { -23 | | //~^ ERROR E0046 -24 | | //~| NOTE missing `bar` in implementation -25 | | const bar: u64 = 1; +21 | / impl Foo for FooConstForMethod { +22 | | //~^ ERROR E0046 +23 | | //~| NOTE missing `bar` in implementation +24 | | const bar: u64 = 1; ... | -28 | | const MY_CONST: u32 = 1; -29 | | } +27 | | const MY_CONST: u32 = 1; +28 | | } | |_^ missing `bar` in implementation error[E0324]: item `MY_CONST` is an associated method, which doesn't match its trait `Foo` - --> $DIR/impl-wrong-item-for-trait.rs:37:5 + --> $DIR/impl-wrong-item-for-trait.rs:36:5 | -17 | const MY_CONST: u32; +16 | const MY_CONST: u32; | -------------------- item in trait ... -37 | fn MY_CONST() {} +36 | fn MY_CONST() {} | ^^^^^^^^^^^^^^^^ does not match trait error[E0046]: not all trait items implemented, missing: `MY_CONST` - --> $DIR/impl-wrong-item-for-trait.rs:33:1 + --> $DIR/impl-wrong-item-for-trait.rs:32:1 | -17 | const MY_CONST: u32; +16 | const MY_CONST: u32; | -------------------- `MY_CONST` from trait ... -33 | / impl Foo for FooMethodForConst { -34 | | //~^ ERROR E0046 -35 | | //~| NOTE missing `MY_CONST` in implementation -36 | | fn bar(&self) {} +32 | / impl Foo for FooMethodForConst { +33 | | //~^ ERROR E0046 +34 | | //~| NOTE missing `MY_CONST` in implementation +35 | | fn bar(&self) {} ... | -39 | | //~| NOTE does not match trait -40 | | } +38 | | //~| NOTE does not match trait +39 | | } | |_^ missing `MY_CONST` in implementation error[E0325]: item `bar` is an associated type, which doesn't match its trait `Foo` - --> $DIR/impl-wrong-item-for-trait.rs:47:5 + --> $DIR/impl-wrong-item-for-trait.rs:46:5 | -16 | fn bar(&self); +15 | fn bar(&self); | -------------- item in trait ... -47 | type bar = u64; +46 | type bar = u64; | ^^^^^^^^^^^^^^^ does not match trait error[E0046]: not all trait items implemented, missing: `bar` - --> $DIR/impl-wrong-item-for-trait.rs:44:1 + --> $DIR/impl-wrong-item-for-trait.rs:43:1 | -16 | fn bar(&self); +15 | fn bar(&self); | -------------- `bar` from trait ... -44 | / impl Foo for FooTypeForMethod { -45 | | //~^ ERROR E0046 -46 | | //~| NOTE missing `bar` in implementation -47 | | type bar = u64; +43 | / impl Foo for FooTypeForMethod { +44 | | //~^ ERROR E0046 +45 | | //~| NOTE missing `bar` in implementation +46 | | type bar = u64; ... | -50 | | const MY_CONST: u32 = 1; -51 | | } +49 | | const MY_CONST: u32 = 1; +50 | | } | |_^ missing `bar` in implementation error[E0046]: not all trait items implemented, missing: `fmt` - --> $DIR/impl-wrong-item-for-trait.rs:53:1 + --> $DIR/impl-wrong-item-for-trait.rs:52:1 | -53 | / impl Debug for FooTypeForMethod { -54 | | } +52 | / impl Debug for FooTypeForMethod { +53 | | } | |_^ missing `fmt` in implementation | = note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>` -error: aborting due to previous error(s) +error: aborting due to 8 previous errors diff --git a/src/test/ui/span/issue-11925.stderr b/src/test/ui/span/issue-11925.stderr index 67d60fe085..6b2942bc7a 100644 --- a/src/test/ui/span/issue-11925.stderr +++ b/src/test/ui/span/issue-11925.stderr @@ -10,5 +10,5 @@ error[E0597]: `x` does not live long enough 23 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-15480.stderr b/src/test/ui/span/issue-15480.stderr index f5f987c823..ce1c6e81b9 100644 --- a/src/test/ui/span/issue-15480.stderr +++ b/src/test/ui/span/issue-15480.stderr @@ -11,5 +11,5 @@ error[E0597]: borrowed value does not live long enough | = note: consider using a `let` binding to increase its lifetime -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr index e564b7ccef..02c0331537 100644 --- a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr +++ b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr @@ -18,5 +18,5 @@ error[E0597]: `y` does not live long enough | | | `y` dropped here while still borrowed -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-23729.stderr b/src/test/ui/span/issue-23729.stderr index d6aed36c8f..d9f4bacce3 100644 --- a/src/test/ui/span/issue-23729.stderr +++ b/src/test/ui/span/issue-23729.stderr @@ -12,5 +12,5 @@ error[E0046]: not all trait items implemented, missing: `Item` | = note: `Item` from trait: `type Item;` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-23827.stderr b/src/test/ui/span/issue-23827.stderr index a1d3f5c11d..3127af157a 100644 --- a/src/test/ui/span/issue-23827.stderr +++ b/src/test/ui/span/issue-23827.stderr @@ -12,5 +12,5 @@ error[E0046]: not all trait items implemented, missing: `Output` | = note: `Output` from trait: `type Output;` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-24356.stderr b/src/test/ui/span/issue-24356.stderr index 771ea78730..71ab82d98b 100644 --- a/src/test/ui/span/issue-24356.stderr +++ b/src/test/ui/span/issue-24356.stderr @@ -11,5 +11,5 @@ error[E0046]: not all trait items implemented, missing: `Target` | = note: `Target` from trait: `type Target;` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-24690.stderr b/src/test/ui/span/issue-24690.stderr index 598f9f5130..8332ba50a7 100644 --- a/src/test/ui/span/issue-24690.stderr +++ b/src/test/ui/span/issue-24690.stderr @@ -4,20 +4,18 @@ error: variable `theTwo` should have a snake case name such as `the_two` 19 | let theTwo = 2; | ^^^^^^ | - = note: #[deny(non_snake_case)] implied by #[deny(warnings)] note: lint level defined here --> $DIR/issue-24690.rs:16:9 | 16 | #![deny(warnings)] | ^^^^^^^^ + = note: #[deny(non_snake_case)] implied by #[deny(warnings)] error: variable `theOtherTwo` should have a snake case name such as `the_other_two` --> $DIR/issue-24690.rs:20:9 | 20 | let theOtherTwo = 2; | ^^^^^^^^^^^ - | - = note: #[deny(non_snake_case)] implied by #[deny(warnings)] error: unused variable: `theOtherTwo` --> $DIR/issue-24690.rs:20:9 @@ -25,12 +23,12 @@ error: unused variable: `theOtherTwo` 20 | let theOtherTwo = 2; | ^^^^^^^^^^^ | - = note: #[deny(unused_variables)] implied by #[deny(warnings)] note: lint level defined here --> $DIR/issue-24690.rs:16:9 | 16 | #![deny(warnings)] | ^^^^^^^^ + = note: #[deny(unused_variables)] implied by #[deny(warnings)] -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr index 314ef0ecbb..29587b7fbd 100644 --- a/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr +++ b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr @@ -9,5 +9,5 @@ error[E0597]: `d1` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr b/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr index 66f22d1457..c88d4a0202 100644 --- a/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr +++ b/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr @@ -28,5 +28,5 @@ error[E0597]: `d1` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/span/issue-24895-copy-clone-dropck.stderr b/src/test/ui/span/issue-24895-copy-clone-dropck.stderr index cfa8359088..7f80e6e115 100644 --- a/src/test/ui/span/issue-24895-copy-clone-dropck.stderr +++ b/src/test/ui/span/issue-24895-copy-clone-dropck.stderr @@ -8,5 +8,5 @@ error[E0597]: `d1` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-25199.stderr b/src/test/ui/span/issue-25199.stderr index 999871db09..4f403b38f5 100644 --- a/src/test/ui/span/issue-25199.stderr +++ b/src/test/ui/span/issue-25199.stderr @@ -19,5 +19,5 @@ error[E0597]: `container` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-26656.stderr b/src/test/ui/span/issue-26656.stderr index b4f0195f6a..748fcae48f 100644 --- a/src/test/ui/span/issue-26656.stderr +++ b/src/test/ui/span/issue-26656.stderr @@ -8,5 +8,5 @@ error[E0597]: `ticking` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-27522.stderr b/src/test/ui/span/issue-27522.stderr index 443595c6d2..117b109780 100644 --- a/src/test/ui/span/issue-27522.stderr +++ b/src/test/ui/span/issue-27522.stderr @@ -7,5 +7,5 @@ error[E0308]: mismatched method receiver = note: expected type `&Self` found type `&SomeType` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-29106.stderr b/src/test/ui/span/issue-29106.stderr index b645cbf402..f146028c2f 100644 --- a/src/test/ui/span/issue-29106.stderr +++ b/src/test/ui/span/issue-29106.stderr @@ -18,5 +18,5 @@ error[E0597]: `x` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-29595.rs b/src/test/ui/span/issue-29595.rs index 79704619cc..ed7f2d1a92 100644 --- a/src/test/ui/span/issue-29595.rs +++ b/src/test/ui/span/issue-29595.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_consts)] trait Tr { const C: Self; diff --git a/src/test/ui/span/issue-29595.stderr b/src/test/ui/span/issue-29595.stderr index 4065c4fb85..81ba0057d7 100644 --- a/src/test/ui/span/issue-29595.stderr +++ b/src/test/ui/span/issue-29595.stderr @@ -1,10 +1,10 @@ error[E0277]: the trait bound `u8: Tr` is not satisfied - --> $DIR/issue-29595.rs:18:17 + --> $DIR/issue-29595.rs:17:17 | -18 | let a: u8 = Tr::C; //~ ERROR the trait bound `u8: Tr` is not satisfied +17 | let a: u8 = Tr::C; //~ ERROR the trait bound `u8: Tr` is not satisfied | ^^^^^ the trait `Tr` is not implemented for `u8` | = note: required by `Tr::C` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-33884.stderr b/src/test/ui/span/issue-33884.stderr index 38256ec944..2a874181c7 100644 --- a/src/test/ui/span/issue-33884.stderr +++ b/src/test/ui/span/issue-33884.stderr @@ -8,5 +8,5 @@ error[E0308]: mismatched types found type `std::string::String` = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr index 48ed0b4ac8..e25caacac8 100644 --- a/src/test/ui/span/issue-34264.stderr +++ b/src/test/ui/span/issue-34264.stderr @@ -45,5 +45,5 @@ error[E0061]: this function takes 2 parameters but 3 parameters were supplied 19 | bar(1, 2, 3); | ^^^^^^^ expected 2 parameters -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/span/issue-35987.stderr b/src/test/ui/span/issue-35987.stderr index a2597aba0b..0cd7e1046f 100644 --- a/src/test/ui/span/issue-35987.stderr +++ b/src/test/ui/span/issue-35987.stderr @@ -5,7 +5,9 @@ error[E0404]: expected trait, found type parameter `Add` | ^^^ not a trait | help: possible better candidate is found in another module, you can import it into scope - | use std::ops::Add; + | +11 | use std::ops::Add; + | error[E0601]: main function not found diff --git a/src/test/ui/span/issue-36530.stderr b/src/test/ui/span/issue-36530.stderr index 5dc9bd8b79..dc6190c2e7 100644 --- a/src/test/ui/span/issue-36530.stderr +++ b/src/test/ui/span/issue-36530.stderr @@ -14,5 +14,5 @@ error: The attribute `foo` is currently unknown to the compiler and may have mea | = help: add #![feature(custom_attribute)] to the crate attributes to enable -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-36537.stderr b/src/test/ui/span/issue-36537.stderr index df06cd1d0e..803e476b74 100644 --- a/src/test/ui/span/issue-36537.stderr +++ b/src/test/ui/span/issue-36537.stderr @@ -8,5 +8,5 @@ error[E0597]: `a` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-37767.stderr b/src/test/ui/span/issue-37767.stderr index bd271641e7..7cf74eaab8 100644 --- a/src/test/ui/span/issue-37767.stderr +++ b/src/test/ui/span/issue-37767.stderr @@ -55,5 +55,5 @@ note: candidate #2 is defined in the trait `F` | ^^^^^^^^^^^^^^^ = help: to disambiguate the method call, write `F::foo(a)` instead -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr index f0b940cdf3..d87fc122d8 100644 --- a/src/test/ui/span/issue-39018.stderr +++ b/src/test/ui/span/issue-39018.stderr @@ -4,8 +4,10 @@ error[E0369]: binary operation `+` cannot be applied to type `&'static str` 12 | let x = "Hello " + "World!"; | ^^^^^^^^^^^^^^^^^^^ `+` can't be used to concatenate two `&str` strings | -help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. - | let x = "Hello ".to_owned() + "World!"; +help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left + | +12 | let x = "Hello ".to_owned() + "World!"; + | ^^^^^^^^^^^^^^^^^^^ error[E0369]: binary operation `+` cannot be applied to type `World` --> $DIR/issue-39018.rs:17:13 @@ -15,5 +17,5 @@ error[E0369]: binary operation `+` cannot be applied to type `World` | = note: an implementation of `std::ops::Add` might be missing for `World` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-39698.stderr b/src/test/ui/span/issue-39698.stderr index 0d0a07629c..97d802f839 100644 --- a/src/test/ui/span/issue-39698.stderr +++ b/src/test/ui/span/issue-39698.stderr @@ -38,5 +38,5 @@ error[E0408]: variable `c` is not bound in all patterns | | pattern doesn't bind `c` | pattern doesn't bind `c` -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/span/issue-40157.stderr b/src/test/ui/span/issue-40157.stderr index 50183aa3bd..b689bef63f 100644 --- a/src/test/ui/span/issue-40157.stderr +++ b/src/test/ui/span/issue-40157.stderr @@ -10,5 +10,5 @@ error[E0597]: `foo` does not live long enough | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-7575.rs b/src/test/ui/span/issue-7575.rs index 2d271f0bf1..b74036c4f5 100644 --- a/src/test/ui/span/issue-7575.rs +++ b/src/test/ui/span/issue-7575.rs @@ -12,12 +12,12 @@ // ignore-tidy-linelength trait CtxtFn { - fn f8(self, usize) -> usize; - fn f9(usize) -> usize; //~ NOTE candidate + fn f8(self, _: usize) -> usize; + fn f9(_: usize) -> usize; //~ NOTE candidate } trait OtherTrait { - fn f9(usize) -> usize; //~ NOTE candidate + fn f9(_: usize) -> usize; //~ NOTE candidate } // Note: this trait is not implemented, but we can't really tell @@ -26,7 +26,7 @@ trait OtherTrait { // candidate. This seems not unreasonable -- perhaps the user meant to // implement it, after all. trait UnusedTrait { - fn f9(usize) -> usize; //~ NOTE candidate + fn f9(_: usize) -> usize; //~ NOTE candidate } impl CtxtFn for usize { diff --git a/src/test/ui/span/issue-7575.stderr b/src/test/ui/span/issue-7575.stderr index 9bf00b1b57..ff62adbfbd 100644 --- a/src/test/ui/span/issue-7575.stderr +++ b/src/test/ui/span/issue-7575.stderr @@ -8,20 +8,20 @@ error[E0599]: no method named `f9` found for type `usize` in the current scope note: candidate #1 is defined in the trait `CtxtFn` --> $DIR/issue-7575.rs:16:5 | -16 | fn f9(usize) -> usize; //~ NOTE candidate - | ^^^^^^^^^^^^^^^^^^^^^^ +16 | fn f9(_: usize) -> usize; //~ NOTE candidate + | ^^^^^^^^^^^^^^^^^^^^^^^^^ = help: to disambiguate the method call, write `CtxtFn::f9(u, 342)` instead note: candidate #2 is defined in the trait `OtherTrait` --> $DIR/issue-7575.rs:20:5 | -20 | fn f9(usize) -> usize; //~ NOTE candidate - | ^^^^^^^^^^^^^^^^^^^^^^ +20 | fn f9(_: usize) -> usize; //~ NOTE candidate + | ^^^^^^^^^^^^^^^^^^^^^^^^^ = help: to disambiguate the method call, write `OtherTrait::f9(u, 342)` instead note: candidate #3 is defined in the trait `UnusedTrait` --> $DIR/issue-7575.rs:29:5 | -29 | fn f9(usize) -> usize; //~ NOTE candidate - | ^^^^^^^^^^^^^^^^^^^^^^ +29 | fn f9(_: usize) -> usize; //~ NOTE candidate + | ^^^^^^^^^^^^^^^^^^^^^^^^^ = help: to disambiguate the method call, write `UnusedTrait::f9(u, 342)` instead = help: items from traits can only be used if the trait is implemented and in scope = note: the following traits define an item `f9`, perhaps you need to implement one of them: @@ -63,5 +63,5 @@ note: candidate #1 is defined in the trait `ManyImplTrait` = note: the following trait defines an item `is_str`, perhaps you need to implement it: candidate #1: `ManyImplTrait` -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/span/issue28498-reject-ex1.stderr b/src/test/ui/span/issue28498-reject-ex1.stderr index a2ef99f9d7..6beb3109c7 100644 --- a/src/test/ui/span/issue28498-reject-ex1.stderr +++ b/src/test/ui/span/issue28498-reject-ex1.stderr @@ -19,5 +19,5 @@ error[E0597]: `foo.data` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue28498-reject-lifetime-param.stderr b/src/test/ui/span/issue28498-reject-lifetime-param.stderr index cb77cd3dc9..358fa9b7c4 100644 --- a/src/test/ui/span/issue28498-reject-lifetime-param.stderr +++ b/src/test/ui/span/issue28498-reject-lifetime-param.stderr @@ -20,5 +20,5 @@ error[E0597]: `first_dropped` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue28498-reject-passed-to-fn.stderr b/src/test/ui/span/issue28498-reject-passed-to-fn.stderr index 49116c340e..0aaf2b27f6 100644 --- a/src/test/ui/span/issue28498-reject-passed-to-fn.stderr +++ b/src/test/ui/span/issue28498-reject-passed-to-fn.stderr @@ -20,5 +20,5 @@ error[E0597]: `first_dropped` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue28498-reject-trait-bound.stderr b/src/test/ui/span/issue28498-reject-trait-bound.stderr index bb4de82422..27a4d2384a 100644 --- a/src/test/ui/span/issue28498-reject-trait-bound.stderr +++ b/src/test/ui/span/issue28498-reject-trait-bound.stderr @@ -20,5 +20,5 @@ error[E0597]: `first_dropped` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/lint-unused-unsafe.stderr b/src/test/ui/span/lint-unused-unsafe.stderr index 2f5e60a1b3..f4998e0890 100644 --- a/src/test/ui/span/lint-unused-unsafe.stderr +++ b/src/test/ui/span/lint-unused-unsafe.stderr @@ -106,5 +106,5 @@ note: because it's nested under this `unsafe` fn 44 | | } | |_^ -error: aborting due to previous error(s) +error: aborting due to 8 previous errors diff --git a/src/test/ui/span/loan-extend.stderr b/src/test/ui/span/loan-extend.stderr index 036c4bd6b8..91bdd8a8ca 100644 --- a/src/test/ui/span/loan-extend.stderr +++ b/src/test/ui/span/loan-extend.stderr @@ -9,5 +9,5 @@ error[E0597]: `short` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/move-closure.stderr b/src/test/ui/span/move-closure.stderr index f76c5b049c..2294e6476d 100644 --- a/src/test/ui/span/move-closure.stderr +++ b/src/test/ui/span/move-closure.stderr @@ -7,5 +7,5 @@ error[E0308]: mismatched types = note: expected type `()` found type `[closure@$DIR/move-closure.rs:15:17: 15:27]` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/multiline-span-E0072.stderr b/src/test/ui/span/multiline-span-E0072.stderr index 881c2f5df4..a06cbd04de 100644 --- a/src/test/ui/span/multiline-span-E0072.stderr +++ b/src/test/ui/span/multiline-span-E0072.stderr @@ -12,5 +12,5 @@ error[E0072]: recursive type `ListNode` has infinite size | = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/multiline-span-simple.stderr b/src/test/ui/span/multiline-span-simple.stderr index 0224cef8da..3915f1b655 100644 --- a/src/test/ui/span/multiline-span-simple.stderr +++ b/src/test/ui/span/multiline-span-simple.stderr @@ -6,5 +6,5 @@ error[E0277]: the trait bound `u32: std::ops::Add<()>` is not satisfied | = help: the trait `std::ops::Add<()>` is not implemented for `u32` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/mut-arg-hint.stderr b/src/test/ui/span/mut-arg-hint.stderr index 754e96aa80..f8584c6739 100644 --- a/src/test/ui/span/mut-arg-hint.stderr +++ b/src/test/ui/span/mut-arg-hint.stderr @@ -22,5 +22,5 @@ error[E0596]: cannot borrow immutable borrowed content `*a` as mutable 25 | a.push_str("foo"); | ^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr b/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr index 5bd6a786cf..007a9fad83 100644 --- a/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr +++ b/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr @@ -8,5 +8,5 @@ error[E0597]: `b` does not live long enough 20 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/pub-struct-field.stderr b/src/test/ui/span/pub-struct-field.stderr index 835b08f890..c66361c854 100644 --- a/src/test/ui/span/pub-struct-field.stderr +++ b/src/test/ui/span/pub-struct-field.stderr @@ -15,5 +15,5 @@ error[E0124]: field `bar` is already declared 17 | pub(crate) bar: u8, | ^^^^^^^^^^^^^^^^^^ field already declared -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/range-2.stderr b/src/test/ui/span/range-2.stderr index 465a663a74..285ab4aee4 100644 --- a/src/test/ui/span/range-2.stderr +++ b/src/test/ui/span/range-2.stderr @@ -20,5 +20,5 @@ error[E0597]: `b` does not live long enough 21 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/recursive-type-field.stderr b/src/test/ui/span/recursive-type-field.stderr index 7217775468..b4d0b5a6a2 100644 --- a/src/test/ui/span/recursive-type-field.stderr +++ b/src/test/ui/span/recursive-type-field.stderr @@ -27,5 +27,5 @@ error[E0072]: recursive type `Bar` has infinite size | = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr b/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr index 80dadd97a1..29848412e4 100644 --- a/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr +++ b/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr @@ -9,5 +9,5 @@ error[E0597]: `c` does not live long enough 20 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr index 25386cb30b..e671f1daf6 100644 --- a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr +++ b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr @@ -9,5 +9,5 @@ error[E0597]: borrowed value does not live long enough 23 | } | - temporary value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/regions-close-over-type-parameter-2.stderr b/src/test/ui/span/regions-close-over-type-parameter-2.stderr index 9b5383877a..a89127b143 100644 --- a/src/test/ui/span/regions-close-over-type-parameter-2.stderr +++ b/src/test/ui/span/regions-close-over-type-parameter-2.stderr @@ -9,5 +9,5 @@ error[E0597]: `tmp0` does not live long enough | | | `tmp0` dropped here while still borrowed -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/regions-escape-loop-via-variable.stderr b/src/test/ui/span/regions-escape-loop-via-variable.stderr index 9f8c91cb9c..cfdd1c8b15 100644 --- a/src/test/ui/span/regions-escape-loop-via-variable.stderr +++ b/src/test/ui/span/regions-escape-loop-via-variable.stderr @@ -8,5 +8,5 @@ error[E0597]: `x` does not live long enough 23 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/regions-escape-loop-via-vec.stderr b/src/test/ui/span/regions-escape-loop-via-vec.stderr index 4f0e61f113..b61df82e8a 100644 --- a/src/test/ui/span/regions-escape-loop-via-vec.stderr +++ b/src/test/ui/span/regions-escape-loop-via-vec.stderr @@ -37,5 +37,5 @@ error[E0506]: cannot assign to `x` because it is borrowed 24 | x += 1; //~ ERROR cannot assign | ^^^^^^ assignment to borrowed `x` occurs here -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr b/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr index 43103e619a..0960f5e1b2 100644 --- a/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr +++ b/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr @@ -10,5 +10,5 @@ error[E0597]: `*x` does not live long enough 30 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/send-is-not-static-ensures-scoping.stderr b/src/test/ui/span/send-is-not-static-ensures-scoping.stderr index b5e55adfb4..02fc982049 100644 --- a/src/test/ui/span/send-is-not-static-ensures-scoping.stderr +++ b/src/test/ui/span/send-is-not-static-ensures-scoping.stderr @@ -24,5 +24,5 @@ error[E0597]: `y` does not live long enough 35 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/send-is-not-static-std-sync-2.stderr b/src/test/ui/span/send-is-not-static-std-sync-2.stderr index 2845c4f6bd..318dab599f 100644 --- a/src/test/ui/span/send-is-not-static-std-sync-2.stderr +++ b/src/test/ui/span/send-is-not-static-std-sync-2.stderr @@ -32,5 +32,5 @@ error[E0597]: `x` does not live long enough 44 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/span/send-is-not-static-std-sync.stderr b/src/test/ui/span/send-is-not-static-std-sync.stderr index 3d75a1b717..988ff22810 100644 --- a/src/test/ui/span/send-is-not-static-std-sync.stderr +++ b/src/test/ui/span/send-is-not-static-std-sync.stderr @@ -52,5 +52,5 @@ error[E0505]: cannot move out of `y` because it is borrowed 49 | drop(y); //~ ERROR cannot move out | ^ move out of `y` occurs here -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/span/slice-borrow.stderr b/src/test/ui/span/slice-borrow.stderr index 0c07d068d2..b60ccd0fbf 100644 --- a/src/test/ui/span/slice-borrow.stderr +++ b/src/test/ui/span/slice-borrow.stderr @@ -9,5 +9,5 @@ error[E0597]: borrowed value does not live long enough 19 | } | - temporary value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/suggestion-non-ascii.stderr b/src/test/ui/span/suggestion-non-ascii.stderr index b6353c0f6a..c67a8fe32b 100644 --- a/src/test/ui/span/suggestion-non-ascii.stderr +++ b/src/test/ui/span/suggestion-non-ascii.stderr @@ -1,8 +1,8 @@ -error: cannot index a value of type `({integer},)` +error[E0608]: cannot index into a value of type `({integer},)` --> $DIR/suggestion-non-ascii.rs:14:21 | 14 | println!("☃{}", tup[0]); - | ^^^^^^ help: to access tuple elements, use `tup.0` + | ^^^^^^ help: to access tuple elements, use: `tup.0` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/type-binding.stderr b/src/test/ui/span/type-binding.stderr index afe069e7aa..dc37acaf3f 100644 --- a/src/test/ui/span/type-binding.stderr +++ b/src/test/ui/span/type-binding.stderr @@ -4,5 +4,5 @@ error[E0220]: associated type `Trget` not found for `std::ops::Deref` 16 | fn homura>(_: T) {} | ^^^^^^^^^^^ associated type `Trget` not found -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/typo-suggestion.stderr b/src/test/ui/span/typo-suggestion.stderr index 6556e5b4c0..dca0a93f89 100644 --- a/src/test/ui/span/typo-suggestion.stderr +++ b/src/test/ui/span/typo-suggestion.stderr @@ -10,5 +10,5 @@ error[E0425]: cannot find value `fob` in this scope 18 | println!("Hello {}", fob); | ^^^ did you mean `foo`? -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr b/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr index 0efbd8472a..f7c94ed9f7 100644 --- a/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr +++ b/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr @@ -19,5 +19,5 @@ error[E0597]: `c1` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/vec_refs_data_with_early_death.stderr b/src/test/ui/span/vec_refs_data_with_early_death.stderr index 0dee15b423..282e5caf20 100644 --- a/src/test/ui/span/vec_refs_data_with_early_death.stderr +++ b/src/test/ui/span/vec_refs_data_with_early_death.stderr @@ -20,5 +20,5 @@ error[E0597]: `y` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/wf-method-late-bound-regions.stderr b/src/test/ui/span/wf-method-late-bound-regions.stderr index d5e663ff26..a37b5d17aa 100644 --- a/src/test/ui/span/wf-method-late-bound-regions.stderr +++ b/src/test/ui/span/wf-method-late-bound-regions.stderr @@ -9,5 +9,5 @@ error[E0597]: `pointer` does not live long enough 33 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/static-lifetime.stderr b/src/test/ui/static-lifetime.stderr index 89008828ac..f73dff4f73 100644 --- a/src/test/ui/static-lifetime.stderr +++ b/src/test/ui/static-lifetime.stderr @@ -6,5 +6,5 @@ error[E0477]: the type `std::borrow::Cow<'a, A>` does not fulfill the required l | = note: type must satisfy the static lifetime -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr index b69d90cf8f..0ca6112763 100644 --- a/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr +++ b/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr @@ -6,5 +6,5 @@ error[E0599]: no method named `closure` found for type `Obj<[closure@$DIR/issue- | = help: use `(o.closure)(...)` if you meant to call the function stored in the `closure` field -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr index 2186532390..c6f134f118 100644 --- a/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr +++ b/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr @@ -86,5 +86,5 @@ error[E0599]: no method named `f3` found for type `FuncContainer` in the current | = help: use `((*self.container).f3)(...)` if you meant to call the function stored in the `f3` field -error: aborting due to previous error(s) +error: aborting due to 11 previous errors diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr index f1d8df8163..a45e70d48c 100644 --- a/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr +++ b/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr @@ -6,5 +6,5 @@ error[E0599]: no method named `example` found for type `Example` in the current | = help: use `(demo.example)(...)` if you meant to call the function stored in the `example` field -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr index 7918fc1e89..d41f7cbdf5 100644 --- a/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr +++ b/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr @@ -22,5 +22,5 @@ error[E0599]: no method named `c_fn_ptr` found for type `&D` in the current scop | = help: use `(s.c_fn_ptr)(...)` if you meant to call the function stored in the `c_fn_ptr` field -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/suggestions/confuse-field-and-method/private-field.stderr b/src/test/ui/suggestions/confuse-field-and-method/private-field.stderr index 5b1c63822f..9451926626 100644 --- a/src/test/ui/suggestions/confuse-field-and-method/private-field.stderr +++ b/src/test/ui/suggestions/confuse-field-and-method/private-field.stderr @@ -4,5 +4,5 @@ error[E0599]: no method named `dog_age` found for type `animal::Dog` in the curr 26 | let dog_age = dog.dog_age(); | ^^^^^^^ private field, not a method -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/suggestions/try-operator-on-main.rs b/src/test/ui/suggestions/try-operator-on-main.rs new file mode 100644 index 0000000000..55154e3507 --- /dev/null +++ b/src/test/ui/suggestions/try-operator-on-main.rs @@ -0,0 +1,13 @@ +// 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. + +fn main() { + std::fs::File::open("foo")?; +} diff --git a/src/test/ui/suggestions/try-operator-on-main.stderr b/src/test/ui/suggestions/try-operator-on-main.stderr new file mode 100644 index 0000000000..cf0481bdab --- /dev/null +++ b/src/test/ui/suggestions/try-operator-on-main.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `(): std::ops::Try` is not satisfied + --> $DIR/try-operator-on-main.rs:12:5 + | +12 | std::fs::File::open("foo")?; + | --------------------------- + | | + | the `?` operator can only be used in a function that returns `Result` (or another type that implements `std::ops::Try`) + | in this macro invocation + | + = help: the trait `std::ops::Try` is not implemented for `()` + = note: required by `std::ops::Try::from_error` + +error: aborting due to previous error + diff --git a/src/test/ui/suggestions/tuple-float-index.stderr b/src/test/ui/suggestions/tuple-float-index.stderr index 47a1b53cc6..4b1be26c86 100644 --- a/src/test/ui/suggestions/tuple-float-index.stderr +++ b/src/test/ui/suggestions/tuple-float-index.stderr @@ -5,7 +5,7 @@ error: unexpected token: `1.1` | ------------^^^ | | | | | unexpected token - | help: try parenthesizing the first index `((1, (2, 3)).1).1` + | help: try parenthesizing the first index: `((1, (2, 3)).1).1` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/token/bounds-obj-parens.stderr b/src/test/ui/token/bounds-obj-parens.stderr index 15e4d4c72b..4d60be15ec 100644 --- a/src/test/ui/token/bounds-obj-parens.stderr +++ b/src/test/ui/token/bounds-obj-parens.stderr @@ -4,5 +4,5 @@ error: expected one of `!` or `::`, found `` 15 | FAIL | ^^^^ expected one of `!` or `::` here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/token/issue-10636-2.stderr b/src/test/ui/token/issue-10636-2.stderr index 4b0b05ca65..48bbeac75d 100644 --- a/src/test/ui/token/issue-10636-2.stderr +++ b/src/test/ui/token/issue-10636-2.stderr @@ -24,5 +24,5 @@ error: expected expression, found `)` error[E0601]: main function not found -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/token/issue-41155.stderr b/src/test/ui/token/issue-41155.stderr index 56f71a2995..50a38da9d8 100644 --- a/src/test/ui/token/issue-41155.stderr +++ b/src/test/ui/token/issue-41155.stderr @@ -14,5 +14,5 @@ error[E0412]: cannot find type `S` in this scope error[E0601]: main function not found -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/token/macro-incomplete-parse.rs b/src/test/ui/token/macro-incomplete-parse.rs index 47374fc3c6..0874937343 100644 --- a/src/test/ui/token/macro-incomplete-parse.rs +++ b/src/test/ui/token/macro-incomplete-parse.rs @@ -32,7 +32,7 @@ macro_rules! ignored_pat { ignored_item!(); //~ NOTE caused by the macro expansion here fn main() { - ignored_expr!(); + ignored_expr!(); //~ NOTE in this expansion match 1 { ignored_pat!() => (), //~ NOTE caused by the macro expansion here _ => (), diff --git a/src/test/ui/token/macro-incomplete-parse.stderr b/src/test/ui/token/macro-incomplete-parse.stderr index 14a7186aab..6bce09af05 100644 --- a/src/test/ui/token/macro-incomplete-parse.stderr +++ b/src/test/ui/token/macro-incomplete-parse.stderr @@ -15,6 +15,9 @@ error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,` | 22 | () => ( 1, //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `,` | ^ expected one of `.`, `;`, `?`, `}`, or an operator here +... +35 | ignored_expr!(); //~ NOTE in this expansion + | ---------------- in this macro invocation error: macro expansion ignores token `,` and any following --> $DIR/macro-incomplete-parse.rs:29:14 @@ -28,5 +31,5 @@ note: caused by the macro expansion here; the usage of `ignored_pat!` is likely 37 | ignored_pat!() => (), //~ NOTE caused by the macro expansion here | ^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/token/trailing-plus-in-bounds.stderr b/src/test/ui/token/trailing-plus-in-bounds.stderr index 5fe0b3594f..c765a434b8 100644 --- a/src/test/ui/token/trailing-plus-in-bounds.stderr +++ b/src/test/ui/token/trailing-plus-in-bounds.stderr @@ -4,5 +4,5 @@ error: expected one of `!` or `::`, found `` 19 | FAIL | ^^^^ expected one of `!` or `::` here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/transmute/main.rs b/src/test/ui/transmute/main.rs new file mode 100644 index 0000000000..ab448de656 --- /dev/null +++ b/src/test/ui/transmute/main.rs @@ -0,0 +1,42 @@ +// 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. + +// normalize-stderr-32bit: "&str (64 bits)" -> "&str ($STR bits)" +// normalize-stderr-64bit: "&str (128 bits)" -> "&str ($STR bits)" + + + +#![feature(untagged_unions)] +use std::mem::transmute; + +pub trait TypeConstructor<'a> { + type T; +} + +unsafe fn transmute_lifetime<'a, 'b, C>(x: >::T) + -> >::T +where for<'z> C: TypeConstructor<'z> { + transmute(x) //~ ERROR transmute called with types of different sizes +} + +unsafe fn sizes() { + let x: u8 = transmute(10u16); //~ ERROR transmute called with types of different sizes +} + +unsafe fn ptrs() { + let x: u8 = transmute("test"); //~ ERROR transmute called with types of different sizes +} + +union Foo { x: () } +unsafe fn vary() { + let x: Foo = transmute(10); //~ ERROR transmute called with types of different sizes +} + +fn main() {} diff --git a/src/test/ui/transmute/main.stderr b/src/test/ui/transmute/main.stderr new file mode 100644 index 0000000000..b7e34d3e0b --- /dev/null +++ b/src/test/ui/transmute/main.stderr @@ -0,0 +1,38 @@ +error[E0512]: transmute called with types of different sizes + --> $DIR/main.rs:26:5 + | +26 | transmute(x) //~ ERROR transmute called with types of different sizes + | ^^^^^^^^^ + | + = note: source type: >::T (size can vary because of ::T) + = note: target type: >::T (size can vary because of ::T) + +error[E0512]: transmute called with types of different sizes + --> $DIR/main.rs:30:17 + | +30 | let x: u8 = transmute(10u16); //~ ERROR transmute called with types of different sizes + | ^^^^^^^^^ + | + = note: source type: u16 (16 bits) + = note: target type: u8 (8 bits) + +error[E0512]: transmute called with types of different sizes + --> $DIR/main.rs:34:17 + | +34 | let x: u8 = transmute("test"); //~ ERROR transmute called with types of different sizes + | ^^^^^^^^^ + | + = note: source type: &str ($STR bits) + = note: target type: u8 (8 bits) + +error[E0512]: transmute called with types of different sizes + --> $DIR/main.rs:39:18 + | +39 | let x: Foo = transmute(10); //~ ERROR transmute called with types of different sizes + | ^^^^^^^^^ + | + = note: source type: i32 (32 bits) + = note: target type: Foo (0 bits) + +error: aborting due to 4 previous errors + diff --git a/src/test/compile-fail/transmute-from-fn-item-types-error.rs b/src/test/ui/transmute/transmute-from-fn-item-types-error.rs similarity index 92% rename from src/test/compile-fail/transmute-from-fn-item-types-error.rs rename to src/test/ui/transmute/transmute-from-fn-item-types-error.rs index c3fe1de895..d60c97f1d5 100644 --- a/src/test/compile-fail/transmute-from-fn-item-types-error.rs +++ b/src/test/ui/transmute/transmute-from-fn-item-types-error.rs @@ -10,7 +10,7 @@ use std::mem; -unsafe fn foo() -> (isize, *const (), Option) { +unsafe fn foo() -> (i8, *const (), Option) { let i = mem::transmute(bar); //~^ ERROR is zero-sized and can't be transmuted //~^^ NOTE cast with `as` to a pointer instead @@ -29,8 +29,8 @@ unsafe fn foo() -> (isize, *const (), Option) { unsafe fn bar() { // Error as usual if the resulting type is not pointer-sized. mem::transmute::<_, u8>(main); - //~^ ERROR transmute called with differently sized types - //~^^ NOTE transmuting between 0 bits and 8 bits + //~^ ERROR transmute called with types of different sizes + //~^^ NOTE transmuting between fn() {main} and u8 mem::transmute::<_, *mut ()>(foo); //~^ ERROR is zero-sized and can't be transmuted diff --git a/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr b/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr new file mode 100644 index 0000000000..197daf1b79 --- /dev/null +++ b/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr @@ -0,0 +1,90 @@ +error[E0512]: transmute called with types of different sizes + --> $DIR/transmute-from-fn-item-types-error.rs:14:13 + | +14 | let i = mem::transmute(bar); + | ^^^^^^^^^^^^^^ + | + = note: source type: unsafe fn() {bar} (0 bits) + = note: target type: i8 (8 bits) + +error[E0591]: can't transmute zero-sized type + --> $DIR/transmute-from-fn-item-types-error.rs:18:13 + | +18 | let p = mem::transmute(foo); + | ^^^^^^^^^^^^^^ + | + = note: source type: unsafe fn() -> (i8, *const (), std::option::Option) {foo} + = note: target type: *const () + = help: cast with `as` to a pointer instead + +error[E0591]: can't transmute zero-sized type + --> $DIR/transmute-from-fn-item-types-error.rs:22:14 + | +22 | let of = mem::transmute(main); + | ^^^^^^^^^^^^^^ + | + = note: source type: fn() {main} + = note: target type: std::option::Option + = help: cast with `as` to a pointer instead + +error[E0512]: transmute called with types of different sizes + --> $DIR/transmute-from-fn-item-types-error.rs:31:5 + | +31 | mem::transmute::<_, u8>(main); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: fn() {main} (0 bits) + = note: target type: u8 (8 bits) + +error[E0591]: can't transmute zero-sized type + --> $DIR/transmute-from-fn-item-types-error.rs:35:5 + | +35 | mem::transmute::<_, *mut ()>(foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: unsafe fn() -> (i8, *const (), std::option::Option) {foo} + = note: target type: *mut () + = help: cast with `as` to a pointer instead + +error[E0591]: can't transmute zero-sized type + --> $DIR/transmute-from-fn-item-types-error.rs:39:5 + | +39 | mem::transmute::<_, fn()>(bar); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: unsafe fn() {bar} + = note: target type: fn() + = help: cast with `as` to a pointer instead + +error[E0591]: can't transmute zero-sized type + --> $DIR/transmute-from-fn-item-types-error.rs:48:5 + | +48 | mem::transmute::<_, *mut ()>(Some(foo)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: unsafe fn() -> (i8, *const (), std::option::Option) {foo} + = note: target type: *mut () + = help: cast with `as` to a pointer instead + +error[E0591]: can't transmute zero-sized type + --> $DIR/transmute-from-fn-item-types-error.rs:52:5 + | +52 | mem::transmute::<_, fn()>(Some(bar)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: unsafe fn() {bar} + = note: target type: fn() + = help: cast with `as` to a pointer instead + +error[E0591]: can't transmute zero-sized type + --> $DIR/transmute-from-fn-item-types-error.rs:56:5 + | +56 | mem::transmute::<_, Option>(Some(baz)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: unsafe fn() {baz} + = note: target type: std::option::Option + = help: cast with `as` to a pointer instead + +error: aborting due to 9 previous errors + diff --git a/src/test/compile-fail/transmute-type-parameters.rs b/src/test/ui/transmute/transmute-type-parameters.rs similarity index 69% rename from src/test/compile-fail/transmute-type-parameters.rs rename to src/test/ui/transmute/transmute-type-parameters.rs index b6e7e32663..117fc2cc5d 100644 --- a/src/test/compile-fail/transmute-type-parameters.rs +++ b/src/test/ui/transmute/transmute-type-parameters.rs @@ -8,23 +8,28 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + + + + + // Tests that `transmute` cannot be called on type parameters. use std::mem::transmute; unsafe fn f(x: T) { - let _: isize = transmute(x); -//~^ ERROR differently sized types: T (size can vary) to isize + let _: i32 = transmute(x); +//~^ ERROR differently sized types: T (size can vary) to i32 } -unsafe fn g(x: (T, isize)) { - let _: isize = transmute(x); -//~^ ERROR differently sized types: (T, isize) (size can vary because of T) to isize +unsafe fn g(x: (T, i32)) { + let _: i32 = transmute(x); +//~^ ERROR differently sized types: (T, i32) (size can vary because of T) to i32 } unsafe fn h(x: [T; 10]) { - let _: isize = transmute(x); -//~^ ERROR differently sized types: [T; 10] (size can vary because of T) to isize + let _: i32 = transmute(x); +//~^ ERROR differently sized types: [T; 10] (size can vary because of T) to i32 } struct Bad { @@ -32,8 +37,8 @@ struct Bad { } unsafe fn i(x: Bad) { - let _: isize = transmute(x); -//~^ ERROR differently sized types: Bad (size can vary because of T) to isize + let _: i32 = transmute(x); +//~^ ERROR differently sized types: Bad (size can vary because of T) to i32 } enum Worse { @@ -42,13 +47,13 @@ enum Worse { } unsafe fn j(x: Worse) { - let _: isize = transmute(x); -//~^ ERROR differently sized types: Worse (size can vary because of T) to isize + let _: i32 = transmute(x); +//~^ ERROR differently sized types: Worse (size can vary because of T) to i32 } unsafe fn k(x: Option) { - let _: isize = transmute(x); -//~^ ERROR differently sized types: std::option::Option (size can vary because of T) to isize + let _: i32 = transmute(x); +//~^ ERROR differently sized types: std::option::Option (size can vary because of T) to i32 } fn main() {} diff --git a/src/test/ui/transmute/transmute-type-parameters.stderr b/src/test/ui/transmute/transmute-type-parameters.stderr new file mode 100644 index 0000000000..816c62812f --- /dev/null +++ b/src/test/ui/transmute/transmute-type-parameters.stderr @@ -0,0 +1,56 @@ +error[E0512]: transmute called with types of different sizes + --> $DIR/transmute-type-parameters.rs:21:18 + | +21 | let _: i32 = transmute(x); + | ^^^^^^^^^ + | + = note: source type: T (this type's size can vary) + = note: target type: i32 (32 bits) + +error[E0512]: transmute called with types of different sizes + --> $DIR/transmute-type-parameters.rs:26:18 + | +26 | let _: i32 = transmute(x); + | ^^^^^^^^^ + | + = note: source type: (T, i32) (size can vary because of T) + = note: target type: i32 (32 bits) + +error[E0512]: transmute called with types of different sizes + --> $DIR/transmute-type-parameters.rs:31:18 + | +31 | let _: i32 = transmute(x); + | ^^^^^^^^^ + | + = note: source type: [T; 10] (size can vary because of T) + = note: target type: i32 (32 bits) + +error[E0512]: transmute called with types of different sizes + --> $DIR/transmute-type-parameters.rs:40:18 + | +40 | let _: i32 = transmute(x); + | ^^^^^^^^^ + | + = note: source type: Bad (size can vary because of T) + = note: target type: i32 (32 bits) + +error[E0512]: transmute called with types of different sizes + --> $DIR/transmute-type-parameters.rs:50:18 + | +50 | let _: i32 = transmute(x); + | ^^^^^^^^^ + | + = note: source type: Worse (size can vary because of T) + = note: target type: i32 (32 bits) + +error[E0512]: transmute called with types of different sizes + --> $DIR/transmute-type-parameters.rs:55:18 + | +55 | let _: i32 = transmute(x); + | ^^^^^^^^^ + | + = note: source type: std::option::Option (size can vary because of T) + = note: target type: i32 (32 bits) + +error: aborting due to 6 previous errors + diff --git a/src/test/compile-fail/issue-17283.rs b/src/test/ui/type-check/assignment-in-if.rs similarity index 71% rename from src/test/compile-fail/issue-17283.rs rename to src/test/ui/type-check/assignment-in-if.rs index 98208bcfdb..98dc55c666 100644 --- a/src/test/compile-fail/issue-17283.rs +++ b/src/test/ui/type-check/assignment-in-if.rs @@ -24,25 +24,29 @@ fn main() { // `x { ... }` should not be interpreted as a struct literal here if x = x { //~^ ERROR mismatched types - //~| expected type `bool` - //~| found type `()` - //~| expected bool, found () + //~| HELP did you mean to compare equality? println!("{}", x); } // Explicit parentheses on the left should match behavior of above if (x = x) { //~^ ERROR mismatched types - //~| expected type `bool` - //~| found type `()` - //~| expected bool, found () + //~| HELP did you mean to compare equality? println!("{}", x); } // The struct literal interpretation is fine with explicit parentheses on the right if y = (Foo { foo: x }) { //~^ ERROR mismatched types - //~| expected type `bool` - //~| found type `()` - //~| expected bool, found () + //~| HELP did you mean to compare equality? + println!("{}", x); + } + // "invalid left-hand side expression" error is suppresed + if 3 = x { + //~^ ERROR mismatched types + //~| HELP did you mean to compare equality? + println!("{}", x); + } + if (if true { x = 4 } else { x = 5 }) { + //~^ ERROR mismatched types println!("{}", x); } } diff --git a/src/test/ui/type-check/assignment-in-if.stderr b/src/test/ui/type-check/assignment-in-if.stderr new file mode 100644 index 0000000000..b740a1b776 --- /dev/null +++ b/src/test/ui/type-check/assignment-in-if.stderr @@ -0,0 +1,59 @@ +error[E0308]: mismatched types + --> $DIR/assignment-in-if.rs:25:8 + | +25 | if x = x { + | ^^^^^ + | | + | help: did you mean to compare equality?: `x == x` + | expected bool, found () + | + = note: expected type `bool` + found type `()` + +error[E0308]: mismatched types + --> $DIR/assignment-in-if.rs:31:8 + | +31 | if (x = x) { + | ^^^^^^^ + | | + | help: did you mean to compare equality?: `x == x` + | expected bool, found () + | + = note: expected type `bool` + found type `()` + +error[E0308]: mismatched types + --> $DIR/assignment-in-if.rs:37:8 + | +37 | if y = (Foo { foo: x }) { + | ^^^^^^^^^^^^^^^^^^^^ + | | + | help: did you mean to compare equality?: `y == (Foo { foo: x })` + | expected bool, found () + | + = note: expected type `bool` + found type `()` + +error[E0308]: mismatched types + --> $DIR/assignment-in-if.rs:43:8 + | +43 | if 3 = x { + | ^^^^^ + | | + | help: did you mean to compare equality?: `3 == x` + | expected bool, found () + | + = note: expected type `bool` + found type `()` + +error[E0308]: mismatched types + --> $DIR/assignment-in-if.rs:48:8 + | +48 | if (if true { x = 4 } else { x = 5 }) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected bool, found () + | + = note: expected type `bool` + found type `()` + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/type-check/cannot_infer_local_or_array.stderr b/src/test/ui/type-check/cannot_infer_local_or_array.stderr index 007480dc44..8c52bb5a1d 100644 --- a/src/test/ui/type-check/cannot_infer_local_or_array.stderr +++ b/src/test/ui/type-check/cannot_infer_local_or_array.stderr @@ -6,5 +6,5 @@ error[E0282]: type annotations needed | | | consider giving `x` a type -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/type-check/cannot_infer_local_or_vec.stderr b/src/test/ui/type-check/cannot_infer_local_or_vec.stderr index 4650df5411..4788fad208 100644 --- a/src/test/ui/type-check/cannot_infer_local_or_vec.stderr +++ b/src/test/ui/type-check/cannot_infer_local_or_vec.stderr @@ -8,5 +8,5 @@ error[E0282]: type annotations needed | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr b/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr index 08b5ae4bbb..ccffadebe9 100644 --- a/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr +++ b/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr @@ -8,5 +8,5 @@ error[E0282]: type annotations needed | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/type-check/issue-22897.stderr b/src/test/ui/type-check/issue-22897.stderr index b3c736c3b6..9568411885 100644 --- a/src/test/ui/type-check/issue-22897.stderr +++ b/src/test/ui/type-check/issue-22897.stderr @@ -4,5 +4,5 @@ error[E0282]: type annotations needed 14 | []; | ^^ cannot infer type for `[_; 0]` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/type-check/issue-40294.stderr b/src/test/ui/type-check/issue-40294.stderr index bf03e52369..bb3a371b26 100644 --- a/src/test/ui/type-check/issue-40294.stderr +++ b/src/test/ui/type-check/issue-40294.stderr @@ -1,4 +1,4 @@ -error[E0282]: type annotations needed +error[E0283]: type annotations required: cannot resolve `&'a T: Foo` --> $DIR/issue-40294.rs:15:1 | 15 | / fn foo<'a,'b,T>(x: &'a T, y: &'b T) @@ -8,7 +8,9 @@ error[E0282]: type annotations needed 19 | | x.foo(); 20 | | y.foo(); 21 | | } - | |_^ cannot infer type for `&'a T` + | |_^ + | + = note: required by `Foo` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/type-check/unknown_type_for_closure.stderr b/src/test/ui/type-check/unknown_type_for_closure.stderr index 200864dfbf..afbd15ca48 100644 --- a/src/test/ui/type-check/unknown_type_for_closure.stderr +++ b/src/test/ui/type-check/unknown_type_for_closure.stderr @@ -4,5 +4,5 @@ error[E0282]: type annotations needed 12 | let x = |_| { }; | ^ consider giving this closure parameter a type -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 985f60bd7e..90b294138f 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -240,6 +240,7 @@ impl Builder { self.package("rust-std", &mut manifest.pkg, TARGETS); self.package("rust-docs", &mut manifest.pkg, TARGETS); self.package("rust-src", &mut manifest.pkg, &["*"]); + self.package("rls", &mut manifest.pkg, HOSTS); self.package("rust-analysis", &mut manifest.pkg, TARGETS); let mut pkg = Package { @@ -275,6 +276,10 @@ impl Builder { }); } + extensions.push(Component { + pkg: "rls".to_string(), + target: host.to_string(), + }); extensions.push(Component { pkg: "rust-analysis".to_string(), target: host.to_string(), diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index 59d83de578..f8282cc5f8 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -4,8 +4,10 @@ name = "compiletest" version = "0.0.0" [dependencies] -log = "0.3" +diff = "0.1.10" env_logger = { version = "0.4", default-features = false } -rustc-serialize = "0.3" filetime = "0.1" -diff = "0.1.10" +getopts = "0.2" +log = "0.3" +rustc-serialize = "0.3" +libc = "0.2" diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 92f6f36d69..cc95e1b893 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -166,6 +166,9 @@ pub struct Config { // Version of LLVM pub llvm_version: Option, + // Is LLVM a system LLVM + pub system_llvm: bool, + // Path to the android tools pub android_cross_path: PathBuf, diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index 29ca54fda8..0b9b9599be 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -35,7 +35,7 @@ impl FromStr for ErrorKind { "ERROR" => Ok(ErrorKind::Error), "NOTE" => Ok(ErrorKind::Note), "SUGGESTION" => Ok(ErrorKind::Suggestion), - "WARN" => Ok(ErrorKind::Warning), + "WARN" | "WARNING" => Ok(ErrorKind::Warning), _ => Err(()), } @@ -95,7 +95,7 @@ pub fn load_errors(testfile: &Path, cfg: Option<&str>) -> Vec { let tag = match cfg { Some(rev) => format!("//[{}]~", rev), - None => format!("//~"), + None => "//~".to_string(), }; rdr.lines() @@ -153,7 +153,7 @@ fn parse_expected(last_nonfollow_error: Option, let msg = msg.trim().to_owned(); let (which, line_num) = if follow { - assert!(adjusts == 0, "use either //~| or //~^, not both."); + assert_eq!(adjusts, 0, "use either //~| or //~^, not both."); let line_num = last_nonfollow_error.expect("encountered //~| without \ preceding //~^ line."); (FollowPrevious(line_num), line_num) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index c503ca7d8c..bb9bf57d55 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -40,15 +40,8 @@ impl EarlyProps { None, &mut |ln| { props.ignore = - props.ignore || config.parse_name_directive(ln, "ignore-test") || - config.parse_name_directive(ln, &ignore_target(config)) || - config.parse_name_directive(ln, &ignore_architecture(config)) || - config.parse_name_directive(ln, &ignore_stage(config)) || - config.parse_name_directive(ln, &ignore_env(config)) || - (config.mode == common::Pretty && - config.parse_name_directive(ln, "ignore-pretty")) || - (config.target != config.host && - config.parse_name_directive(ln, "ignore-cross-compile")) || + props.ignore || + config.parse_cfg_name_directive(ln, "ignore") || ignore_gdb(config, ln) || ignore_lldb(config, ln) || ignore_llvm(config, ln); @@ -62,28 +55,11 @@ impl EarlyProps { return props; - fn ignore_target(config: &Config) -> String { - format!("ignore-{}", util::get_os(&config.target)) - } - fn ignore_architecture(config: &Config) -> String { - format!("ignore-{}", util::get_arch(&config.target)) - } - fn ignore_stage(config: &Config) -> String { - format!("ignore-{}", config.stage_id.split('-').next().unwrap()) - } - fn ignore_env(config: &Config) -> String { - format!("ignore-{}", - util::get_env(&config.target).unwrap_or("")) - } fn ignore_gdb(config: &Config, line: &str) -> bool { if config.mode != common::DebugInfoGdb { return false; } - if config.parse_name_directive(line, "ignore-gdb") { - return true; - } - if let Some(actual_version) = config.gdb_version { if line.starts_with("min-gdb-version") { let (start_ver, end_ver) = extract_gdb_version_range(line); @@ -144,10 +120,6 @@ impl EarlyProps { return false; } - if config.parse_name_directive(line, "ignore-lldb") { - return true; - } - if let Some(ref actual_version) = config.lldb_version { if line.starts_with("min-lldb-version") { let min_version = line.trim_right() @@ -166,6 +138,9 @@ impl EarlyProps { } fn ignore_llvm(config: &Config, line: &str) -> bool { + if config.system_llvm && line.starts_with("no-system-llvm") { + return true; + } if let Some(ref actual_version) = config.llvm_version { if line.starts_with("min-llvm-version") { let min_version = line.trim_right() @@ -236,6 +211,9 @@ pub struct TestProps { // The test must be compiled and run successfully. Only used in UI tests for // now. pub run_pass: bool, + // customized normalization rules + pub normalize_stdout: Vec<(String, String)>, + pub normalize_stderr: Vec<(String, String)>, } impl TestProps { @@ -255,13 +233,15 @@ impl TestProps { check_stdout: false, no_prefer_dynamic: false, pretty_expanded: false, - pretty_mode: format!("normal"), + pretty_mode: "normal".to_string(), pretty_compare_only: false, forbid_output: vec![], incremental_dir: None, must_compile_successfully: false, check_test_line_numbers_match: false, run_pass: false, + normalize_stdout: vec![], + normalize_stderr: vec![], } } @@ -376,16 +356,20 @@ impl TestProps { if !self.run_pass { self.run_pass = config.parse_run_pass(ln); } + + if let Some(rule) = config.parse_custom_normalization(ln, "normalize-stdout") { + self.normalize_stdout.push(rule); + } + if let Some(rule) = config.parse_custom_normalization(ln, "normalize-stderr") { + self.normalize_stderr.push(rule); + } }); - for key in vec!["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] { - match env::var(key) { - Ok(val) => { - if self.exec_env.iter().find(|&&(ref x, _)| *x == key).is_none() { - self.exec_env.push((key.to_owned(), val)) - } + for key in &["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] { + if let Ok(val) = env::var(key) { + if self.exec_env.iter().find(|&&(ref x, _)| x == key).is_none() { + self.exec_env.push(((*key).to_owned(), val)) } - Err(..) => {} } } } @@ -406,7 +390,7 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut FnMut(&str)) { return; } else if ln.starts_with("//[") { // A comment like `//[foo]` is specific to revision `foo` - if let Some(close_brace) = ln.find("]") { + if let Some(close_brace) = ln.find(']') { let lncfg = &ln[3..close_brace]; let matches = match cfg { Some(s) => s == &lncfg[..], @@ -427,7 +411,6 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut FnMut(&str)) { } impl Config { - fn parse_error_pattern(&self, line: &str) -> Option { self.parse_name_value_directive(line, "error-pattern") } @@ -518,12 +501,50 @@ impl Config { fn parse_pp_exact(&self, line: &str, testfile: &Path) -> Option { if let Some(s) = self.parse_name_value_directive(line, "pp-exact") { Some(PathBuf::from(&s)) + } else if self.parse_name_directive(line, "pp-exact") { + testfile.file_name().map(PathBuf::from) } else { - if self.parse_name_directive(line, "pp-exact") { - testfile.file_name().map(PathBuf::from) - } else { - None - } + None + } + } + + fn parse_custom_normalization(&self, mut line: &str, prefix: &str) -> Option<(String, String)> { + if self.parse_cfg_name_directive(line, prefix) { + let from = match parse_normalization_string(&mut line) { + Some(s) => s, + None => return None, + }; + let to = match parse_normalization_string(&mut line) { + Some(s) => s, + None => return None, + }; + Some((from, to)) + } else { + None + } + } + + /// Parses a name-value directive which contains config-specific information, e.g. `ignore-x86` + /// or `normalize-stderr-32bit`. Returns `true` if the line matches it. + fn parse_cfg_name_directive(&self, line: &str, prefix: &str) -> bool { + if line.starts_with(prefix) && line.as_bytes().get(prefix.len()) == Some(&b'-') { + let name = line[prefix.len()+1 ..].split(&[':', ' '][..]).next().unwrap(); + + name == "test" || + name == util::get_os(&self.target) || // target + name == util::get_arch(&self.target) || // architecture + name == util::get_pointer_width(&self.target) || // pointer width + name == self.stage_id.split('-').next().unwrap() || // stage + Some(name) == util::get_env(&self.target) || // env + match self.mode { + common::DebugInfoGdb => name == "gdb", + common::DebugInfoLldb => name == "lldb", + common::Pretty => name == "pretty", + _ => false, + } || + (self.target != self.host && name == "cross-compile") + } else { + false } } @@ -551,9 +572,7 @@ impl Config { pub fn lldb_version_to_int(version_string: &str) -> isize { let error_string = format!("Encountered LLDB version string with unexpected format: {}", version_string); - let error_string = error_string; - let major: isize = version_string.parse().ok().expect(&error_string); - return major; + version_string.parse().expect(&error_string) } fn expand_variables(mut value: String, config: &Config) -> String { @@ -576,3 +595,29 @@ fn expand_variables(mut value: String, config: &Config) -> String { value } + +/// Finds the next quoted string `"..."` in `line`, and extract the content from it. Move the `line` +/// variable after the end of the quoted string. +/// +/// # Examples +/// +/// ``` +/// let mut s = "normalize-stderr-32bit: \"something (32 bits)\" -> \"something ($WORD bits)\"."; +/// let first = parse_normalization_string(&mut s); +/// assert_eq!(first, Some("something (32 bits)".to_owned())); +/// assert_eq!(s, " -> \"something ($WORD bits)\"."); +/// ``` +fn parse_normalization_string(line: &mut &str) -> Option { + // FIXME support escapes in strings. + let begin = match line.find('"') { + Some(i) => i + 1, + None => return None, + }; + let end = match line[begin..].find('"') { + Some(i) => i + begin, + None => return None, + }; + let result = line[begin..end].to_owned(); + *line = &line[end+1..]; + Some(result) +} diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index 06cbd9a3df..23782c3ccc 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -65,7 +65,7 @@ pub fn parse_output(file_name: &str, output: &str, proc_res: &ProcRes) -> Vec Vec { // The compiler sometimes intermingles non-JSON stuff into the // output. This hack just skips over such lines. Yuck. - if line.chars().next() == Some('{') { + if line.starts_with('{') { match json::decode::(line) { Ok(diagnostic) => { let mut expected_errors = vec![]; diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 1bb0b765f9..91f80a7afe 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -10,10 +10,7 @@ #![crate_name = "compiletest"] -#![feature(box_syntax)] -#![feature(rustc_private)] #![feature(test)] -#![feature(libc)] #![deny(warnings)] @@ -34,7 +31,7 @@ use std::io; use std::path::{Path, PathBuf}; use std::process::Command; use filetime::FileTime; -use getopts::{optopt, optflag, reqopt}; +use getopts::Options; use common::Config; use common::{Pretty, DebugInfoGdb, DebugInfoLldb, Mode}; use test::{TestPaths, ColorConfig}; @@ -66,67 +63,68 @@ fn main() { pub fn parse_config(args: Vec ) -> Config { - let groups : Vec = - vec![reqopt("", "compile-lib-path", "path to host shared libraries", "PATH"), - reqopt("", "run-lib-path", "path to target shared libraries", "PATH"), - reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH"), - reqopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH"), - reqopt("", "lldb-python", "path to python to use for doc tests", "PATH"), - reqopt("", "docck-python", "path to python to use for doc tests", "PATH"), - optopt("", "valgrind-path", "path to Valgrind executable for Valgrind tests", "PROGRAM"), - optflag("", "force-valgrind", "fail if Valgrind tests cannot be run under Valgrind"), - optopt("", "llvm-filecheck", "path to LLVM's FileCheck binary", "DIR"), - reqopt("", "src-base", "directory to scan for test files", "PATH"), - reqopt("", "build-base", "directory to deposit test outputs", "PATH"), - reqopt("", "stage-id", "the target-stage identifier", "stageN-TARGET"), - reqopt("", "mode", "which sort of compile tests to run", - "(compile-fail|parse-fail|run-fail|run-pass|\ - run-pass-valgrind|pretty|debug-info|incremental|mir-opt)"), - optflag("", "ignored", "run tests marked as ignored"), - optflag("", "exact", "filters match exactly"), - optopt("", "runtool", "supervisor program to run tests under \ - (eg. emulator, valgrind)", "PROGRAM"), - optopt("", "host-rustcflags", "flags to pass to rustc for host", "FLAGS"), - optopt("", "target-rustcflags", "flags to pass to rustc for target", "FLAGS"), - optflag("", "verbose", "run tests verbosely, showing all output"), - optflag("", "quiet", "print one character per test instead of one line"), - optopt("", "color", "coloring: auto, always, never", "WHEN"), - optopt("", "logfile", "file to log test execution to", "FILE"), - optopt("", "target", "the target to build for", "TARGET"), - optopt("", "host", "the host to build for", "HOST"), - optopt("", "gdb", "path to GDB to use for GDB debuginfo tests", "PATH"), - optopt("", "lldb-version", "the version of LLDB used", "VERSION STRING"), - optopt("", "llvm-version", "the version of LLVM used", "VERSION STRING"), - optopt("", "android-cross-path", "Android NDK standalone path", "PATH"), - optopt("", "adb-path", "path to the android debugger", "PATH"), - optopt("", "adb-test-dir", "path to tests for the android debugger", "PATH"), - optopt("", "lldb-python-dir", "directory containing LLDB's python module", "PATH"), - reqopt("", "cc", "path to a C compiler", "PATH"), - reqopt("", "cxx", "path to a C++ compiler", "PATH"), - reqopt("", "cflags", "flags for the C compiler", "FLAGS"), - reqopt("", "llvm-components", "list of LLVM components built in", "LIST"), - reqopt("", "llvm-cxxflags", "C++ flags for LLVM", "FLAGS"), - optopt("", "nodejs", "the name of nodejs", "PATH"), - optopt("", "remote-test-client", "path to the remote test client", "PATH"), - optflag("h", "help", "show this message")]; + let mut opts = Options::new(); + opts.reqopt("", "compile-lib-path", "path to host shared libraries", "PATH") + .reqopt("", "run-lib-path", "path to target shared libraries", "PATH") + .reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH") + .reqopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH") + .reqopt("", "lldb-python", "path to python to use for doc tests", "PATH") + .reqopt("", "docck-python", "path to python to use for doc tests", "PATH") + .optopt("", "valgrind-path", "path to Valgrind executable for Valgrind tests", "PROGRAM") + .optflag("", "force-valgrind", "fail if Valgrind tests cannot be run under Valgrind") + .optopt("", "llvm-filecheck", "path to LLVM's FileCheck binary", "DIR") + .reqopt("", "src-base", "directory to scan for test files", "PATH") + .reqopt("", "build-base", "directory to deposit test outputs", "PATH") + .reqopt("", "stage-id", "the target-stage identifier", "stageN-TARGET") + .reqopt("", "mode", "which sort of compile tests to run", + "(compile-fail|parse-fail|run-fail|run-pass|\ + run-pass-valgrind|pretty|debug-info|incremental|mir-opt)") + .optflag("", "ignored", "run tests marked as ignored") + .optflag("", "exact", "filters match exactly") + .optopt("", "runtool", "supervisor program to run tests under \ + (eg. emulator, valgrind)", "PROGRAM") + .optopt("", "host-rustcflags", "flags to pass to rustc for host", "FLAGS") + .optopt("", "target-rustcflags", "flags to pass to rustc for target", "FLAGS") + .optflag("", "verbose", "run tests verbosely, showing all output") + .optflag("", "quiet", "print one character per test instead of one line") + .optopt("", "color", "coloring: auto, always, never", "WHEN") + .optopt("", "logfile", "file to log test execution to", "FILE") + .optopt("", "target", "the target to build for", "TARGET") + .optopt("", "host", "the host to build for", "HOST") + .optopt("", "gdb", "path to GDB to use for GDB debuginfo tests", "PATH") + .optopt("", "lldb-version", "the version of LLDB used", "VERSION STRING") + .optopt("", "llvm-version", "the version of LLVM used", "VERSION STRING") + .optflag("", "system-llvm", "is LLVM the system LLVM") + .optopt("", "android-cross-path", "Android NDK standalone path", "PATH") + .optopt("", "adb-path", "path to the android debugger", "PATH") + .optopt("", "adb-test-dir", "path to tests for the android debugger", "PATH") + .optopt("", "lldb-python-dir", "directory containing LLDB's python module", "PATH") + .reqopt("", "cc", "path to a C compiler", "PATH") + .reqopt("", "cxx", "path to a C++ compiler", "PATH") + .reqopt("", "cflags", "flags for the C compiler", "FLAGS") + .reqopt("", "llvm-components", "list of LLVM components built in", "LIST") + .reqopt("", "llvm-cxxflags", "C++ flags for LLVM", "FLAGS") + .optopt("", "nodejs", "the name of nodejs", "PATH") + .optopt("", "remote-test-client", "path to the remote test client", "PATH") + .optflag("h", "help", "show this message"); let (argv0, args_) = args.split_first().unwrap(); if args.len() == 1 || args[1] == "-h" || args[1] == "--help" { let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0); - println!("{}", getopts::usage(&message, &groups)); + println!("{}", opts.usage(&message)); println!(""); panic!() } let matches = - &match getopts::getopts(args_, &groups) { + &match opts.parse(args_) { Ok(m) => m, Err(f) => panic!("{:?}", f) }; if matches.opt_present("h") || matches.opt_present("help") { let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0); - println!("{}", getopts::usage(&message, &groups)); + println!("{}", opts.usage(&message)); println!(""); panic!() } @@ -168,7 +166,7 @@ pub fn parse_config(args: Vec ) -> Config { src_base: opt_path(matches, "src-base"), build_base: opt_path(matches, "build-base"), stage_id: matches.opt_str("stage-id").unwrap(), - mode: matches.opt_str("mode").unwrap().parse().ok().expect("invalid mode"), + mode: matches.opt_str("mode").unwrap().parse().expect("invalid mode"), run_ignored: matches.opt_present("ignored"), filter: matches.free.first().cloned(), filter_exact: matches.opt_present("exact"), @@ -183,6 +181,7 @@ pub fn parse_config(args: Vec ) -> Config { gdb_native_rust: gdb_native_rust, lldb_version: extract_lldb_version(matches.opt_str("lldb-version")), llvm_version: matches.opt_str("llvm-version"), + system_llvm: matches.opt_present("system-llvm"), android_cross_path: opt_path(matches, "android-cross-path"), adb_path: opt_str2(matches.opt_str("adb-path")), adb_test_dir: opt_str2(matches.opt_str("adb-test-dir")), @@ -207,7 +206,7 @@ pub fn parse_config(args: Vec ) -> Config { pub fn log_config(config: &Config) { let c = config; - logv(c, format!("configuration:")); + logv(c, "configuration:".to_string()); logv(c, format!("compile_lib_path: {:?}", config.compile_lib_path)); logv(c, format!("run_lib_path: {:?}", config.run_lib_path)); logv(c, format!("rustc_path: {:?}", config.rustc_path.display())); @@ -237,10 +236,10 @@ pub fn log_config(config: &Config) { config.adb_device_status)); logv(c, format!("verbose: {}", config.verbose)); logv(c, format!("quiet: {}", config.quiet)); - logv(c, format!("\n")); + logv(c, "\n".to_string()); } -pub fn opt_str<'a>(maybestr: &'a Option) -> &'a str { +pub fn opt_str(maybestr: &Option) -> &str { match *maybestr { None => "(none)", Some(ref s) => s, @@ -464,17 +463,16 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn }; // Debugging emscripten code doesn't make sense today - let mut ignore = early_props.ignore || !up_to_date(config, testpaths, &early_props); - if (config.mode == DebugInfoGdb || config.mode == DebugInfoLldb) && - config.target.contains("emscripten") { - ignore = true; - } + let ignore = early_props.ignore || !up_to_date(config, testpaths, &early_props) || + (config.mode == DebugInfoGdb || config.mode == DebugInfoLldb) && + config.target.contains("emscripten"); test::TestDescAndFn { desc: test::TestDesc { name: make_test_name(config, testpaths), ignore: ignore, should_panic: should_panic, + allow_fail: false, }, testfn: make_test_closure(config, testpaths), } @@ -486,7 +484,7 @@ fn stamp(config: &Config, testpaths: &TestPaths) -> PathBuf { .to_str().unwrap(), config.stage_id); config.build_base.canonicalize() - .unwrap_or(config.build_base.clone()) + .unwrap_or_else(|_| config.build_base.clone()) .join(stamp_name) } @@ -511,7 +509,7 @@ fn up_to_date(config: &Config, testpaths: &TestPaths, props: &EarlyProps) -> boo fn mtime(path: &Path) -> FileTime { fs::metadata(path).map(|f| { FileTime::from_last_modification_time(&f) - }).unwrap_or(FileTime::zero()) + }).unwrap_or_else(|_| FileTime::zero()) } pub fn make_test_name(config: &Config, testpaths: &TestPaths) -> test::TestName { @@ -559,7 +557,7 @@ fn analyze_gdb(gdb: Option) -> (Option, Option, bool) { let gdb_native_rust = version.map_or(false, |v| v >= MIN_GDB_WITH_RUST); - return (Some(gdb.to_owned()), version, gdb_native_rust); + (Some(gdb.to_owned()), version, gdb_native_rust) } fn extract_gdb_version(full_version_line: &str) -> Option { @@ -599,7 +597,8 @@ fn extract_gdb_version(full_version_line: &str) -> Option { Some(idx) => if line.as_bytes()[idx] == b'.' { let patch = &line[idx + 1..]; - let patch_len = patch.find(|c: char| !c.is_digit(10)).unwrap_or(patch.len()); + let patch_len = patch.find(|c: char| !c.is_digit(10)) + .unwrap_or_else(|| patch.len()); let patch = &patch[..patch_len]; let patch = if patch_len > 3 || patch_len == 0 { None } else { Some(patch) }; diff --git a/src/tools/compiletest/src/procsrv.rs b/src/tools/compiletest/src/procsrv.rs index dbda8f4d80..35f6ed243f 100644 --- a/src/tools/compiletest/src/procsrv.rs +++ b/src/tools/compiletest/src/procsrv.rs @@ -9,7 +9,6 @@ // except according to those terms. use std::env; -use std::ffi::OsString; use std::io::prelude::*; use std::io; use std::path::PathBuf; @@ -31,7 +30,7 @@ fn add_target_env(cmd: &mut Command, lib_path: &str, aux_path: Option<&str>) { // Need to be sure to put both the lib_path and the aux path in the dylib // search path for the child. let var = dylib_env_var(); - let mut path = env::split_paths(&env::var_os(var).unwrap_or(OsString::new())) + let mut path = env::split_paths(&env::var_os(var).unwrap_or_default()) .collect::>(); if let Some(p) = aux_path { path.insert(0, PathBuf::from(p)) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 01419c4257..45a733d411 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -68,7 +68,7 @@ pub fn run(config: Config, testpaths: &TestPaths) { } else { for revision in &base_props.revisions { let mut revision_props = base_props.clone(); - revision_props.load_from(&testpaths.file, Some(&revision), &config); + revision_props.load_from(&testpaths.file, Some(revision), &config); let rev_cx = TestCx { config: &config, props: &revision_props, @@ -81,7 +81,7 @@ pub fn run(config: Config, testpaths: &TestPaths) { base_cx.complete_all(); - File::create(::stamp(&config, &testpaths)).unwrap(); + File::create(::stamp(&config, testpaths)).unwrap(); } struct TestCx<'test> { @@ -101,9 +101,8 @@ impl<'test> TestCx<'test> { /// invoked once before any revisions have been processed fn init_all(&self) { assert!(self.revision.is_none(), "init_all invoked for a revision"); - match self.config.mode { - Incremental => self.init_incremental_test(), - _ => { } + if let Incremental = self.config.mode { + self.init_incremental_test() } } @@ -111,7 +110,7 @@ impl<'test> TestCx<'test> { /// revisions, exactly once, with revision == None). fn run_revision(&self) { match self.config.mode { - CompileFail => self.run_cfail_test(), + CompileFail | ParseFail => self.run_cfail_test(), RunFail => self.run_rfail_test(), RunPass => self.run_rpass_test(), @@ -352,10 +351,10 @@ impl<'test> TestCx<'test> { aux_dir.to_str().unwrap().to_owned()]; args.extend(self.split_maybe_args(&self.config.target_rustcflags)); args.extend(self.props.compile_flags.iter().cloned()); - return ProcArgs { + ProcArgs { prog: self.config.rustc_path.to_str().unwrap().to_owned(), args: args, - }; + } } fn compare_source(&self, @@ -407,17 +406,17 @@ actual:\n\ aux_dir.to_str().unwrap().to_owned()]; if let Some(revision) = self.revision { args.extend(vec![ - format!("--cfg"), - format!("{}", revision), + "--cfg".to_string(), + revision.to_string(), ]); } args.extend(self.split_maybe_args(&self.config.target_rustcflags)); args.extend(self.props.compile_flags.iter().cloned()); // FIXME (#9639): This needs to handle non-utf8 paths - return ProcArgs { + ProcArgs { prog: self.config.rustc_path.to_str().unwrap().to_owned(), args: args, - }; + } } fn run_debuginfo_gdb_test(&self) { @@ -692,7 +691,7 @@ actual:\n\ } if !debugger_run_result.status.success() { - self.fatal("gdb failed to execute"); + self.fatal_proc_rec("gdb failed to execute", &debugger_run_result); } self.check_debugger_output(&debugger_run_result, &check_lines); @@ -708,7 +707,7 @@ actual:\n\ } } - return None; + None } fn run_debuginfo_lldb_test(&self) { @@ -875,13 +874,13 @@ actual:\n\ for &(ref command_directive, ref check_directive) in &directives { self.config.parse_name_value_directive( &line, - &command_directive).map(|cmd| { + command_directive).map(|cmd| { commands.push(cmd) }); self.config.parse_name_value_directive( &line, - &check_directive).map(|cmd| { + check_directive).map(|cmd| { check_lines.push(cmd) }); } @@ -962,8 +961,7 @@ actual:\n\ (line, 0) }; - for fragment_index in first_fragment .. check_fragments.len() { - let current_fragment = check_fragments[fragment_index]; + for current_fragment in &check_fragments[first_fragment..] { match rest.find(current_fragment) { Some(pos) => { rest = &rest[pos + current_fragment.len() .. ]; @@ -976,7 +974,7 @@ actual:\n\ return false; } - return true; + true } } @@ -1059,7 +1057,7 @@ actual:\n\ let expect_note = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Note)); // Parse the JSON output from the compiler and extract out the messages. - let actual_errors = json::parse_output(&file_name, &proc_res.stderr, &proc_res); + let actual_errors = json::parse_output(&file_name, &proc_res.stderr, proc_res); let mut unexpected = Vec::new(); let mut found = vec![false; expected_errors.len()]; for actual_error in &actual_errors { @@ -1092,7 +1090,7 @@ actual:\n\ .map_or(String::from("message"), |k| k.to_string()), actual_error.msg)); - unexpected.push(actual_error.clone()); + unexpected.push(actual_error); } } } @@ -1110,20 +1108,20 @@ actual:\n\ .map_or("message".into(), |k| k.to_string()), expected_error.msg)); - not_found.push(expected_error.clone()); + not_found.push(expected_error); } } - if unexpected.len() > 0 || not_found.len() > 0 { + if !unexpected.is_empty() || !not_found.is_empty() { self.error( &format!("{} unexpected errors found, {} expected errors not found", unexpected.len(), not_found.len())); - print!("status: {}\ncommand: {}\n", + println!("status: {}\ncommand: {}", proc_res.status, proc_res.cmdline); - if unexpected.len() > 0 { + if !unexpected.is_empty() { println!("unexpected errors (from JSON output): {:#?}\n", unexpected); } - if not_found.len() > 0 { + if !not_found.is_empty() { println!("not found errors (from test file): {:#?}\n", not_found); } panic!(); @@ -1142,9 +1140,9 @@ actual:\n\ match actual_error.kind { Some(ErrorKind::Help) => expect_help, Some(ErrorKind::Note) => expect_note, - Some(ErrorKind::Error) => true, + Some(ErrorKind::Error) | Some(ErrorKind::Warning) => true, - Some(ErrorKind::Suggestion) => false, + Some(ErrorKind::Suggestion) | None => false } } @@ -1287,7 +1285,8 @@ actual:\n\ self.config); let mut crate_type = if aux_props.no_prefer_dynamic { Vec::new() - } else { + } else if (self.config.target.contains("musl") && !aux_props.force_host) || + self.config.target.contains("emscripten") { // We primarily compile all auxiliary libraries as dynamic libraries // to avoid code size bloat and large binaries as much as possible // for the test suite (otherwise including libstd statically in all @@ -1297,13 +1296,9 @@ actual:\n\ // dynamic libraries so we just go back to building a normal library. Note, // however, that for MUSL if the library is built with `force_host` then // it's ok to be a dylib as the host should always support dylibs. - if (self.config.target.contains("musl") && !aux_props.force_host) || - self.config.target.contains("emscripten") - { - vec!["--crate-type=lib".to_owned()] - } else { - vec!["--crate-type=dylib".to_owned()] - } + vec!["--crate-type=lib".to_owned()] + } else { + vec!["--crate-type=dylib".to_owned()] }; crate_type.extend(extra_link_args.clone()); let aux_output = { @@ -1338,14 +1333,13 @@ actual:\n\ input) } - fn compose_and_run(&self, ProcArgs{ args, prog }: ProcArgs, procenv: Vec<(String, String)> , lib_path: &str, aux_path: Option<&str>, input: Option) -> ProcRes { - return self.program_output(lib_path, prog, aux_path, args, procenv, input); + self.program_output(lib_path, prog, aux_path, args, procenv, input) } fn make_compile_args(&self, @@ -1368,7 +1362,7 @@ actual:\n\ // Optionally prevent default --target if specified in test compile-flags. let custom_target = self.props.compile_flags .iter() - .fold(false, |acc, ref x| acc || x.starts_with("--target")); + .fold(false, |acc, x| acc || x.starts_with("--target")); if !custom_target { args.extend(vec![ @@ -1378,14 +1372,14 @@ actual:\n\ if let Some(revision) = self.revision { args.extend(vec![ - format!("--cfg"), - format!("{}", revision), + "--cfg".to_string(), + revision.to_string(), ]); } if let Some(ref incremental_dir) = self.props.incremental_dir { args.extend(vec![ - format!("-Z"), + "-Z".to_string(), format!("incremental={}", incremental_dir.display()), ]); } @@ -1458,10 +1452,10 @@ actual:\n\ args.extend(self.split_maybe_args(&self.config.target_rustcflags)); } args.extend(self.props.compile_flags.iter().cloned()); - return ProcArgs { + ProcArgs { prog: self.config.rustc_path.to_str().unwrap().to_owned(), args: args, - }; + } } fn make_lib_name(&self, auxfile: &Path) -> PathBuf { @@ -1509,10 +1503,10 @@ actual:\n\ args.extend(self.split_maybe_args(&self.props.run_flags)); let prog = args.remove(0); - return ProcArgs { + ProcArgs { prog: prog, args: args, - }; + } } fn split_maybe_args(&self, argstr: &Option) -> Vec { @@ -1559,12 +1553,12 @@ actual:\n\ env, input).expect(&format!("failed to exec `{}`", prog)); self.dump_output(&out, &err); - return ProcRes { + ProcRes { status: status, stdout: out, stderr: err, cmdline: cmdline, - }; + } } fn make_cmdline(&self, libpath: &str, prog: &str, args: &[String]) -> String { @@ -1765,7 +1759,7 @@ actual:\n\ self.fatal_proc_rec("rustdoc failed!", &proc_res); } - if self.props.check_test_line_numbers_match == true { + if self.props.check_test_line_numbers_match { self.check_rustdoc_test_option(proc_res); } else { let root = self.find_rust_src_root().unwrap(); @@ -1792,7 +1786,7 @@ actual:\n\ .filter_map(|(line_nb, line)| { if (line.trim_left().starts_with("pub mod ") || line.trim_left().starts_with("mod ")) && - line.ends_with(";") { + line.ends_with(';') { if let Some(ref mut other_files) = other_files { other_files.push(line.rsplit("mod ") .next() @@ -1841,7 +1835,7 @@ actual:\n\ } let mut tested = 0; - for _ in res.stdout.split("\n") + for _ in res.stdout.split('\n') .filter(|s| s.starts_with("test ")) .inspect(|s| { let tmp: Vec<&str> = s.split(" - ").collect(); @@ -1854,7 +1848,7 @@ actual:\n\ iter.next(); let line = iter.next() .unwrap_or(")") - .split(")") + .split(')') .next() .unwrap_or("0") .parse() @@ -1874,7 +1868,7 @@ actual:\n\ self.fatal_proc_rec(&format!("No test has been found... {:?}", files), &res); } else { for (entry, v) in &files { - if v.len() != 0 { + if !v.is_empty() { self.fatal_proc_rec(&format!("Not found test at line{} \"{}\":{:?}", if v.len() > 1 { "s" } else { "" }, entry, v), &res); @@ -1917,11 +1911,10 @@ actual:\n\ .find(|ti| ti.name == expected_item.name); if let Some(actual_item) = actual_item_with_same_name { - if !expected_item.codegen_units.is_empty() { - // Also check for codegen units - if expected_item.codegen_units != actual_item.codegen_units { - wrong_cgus.push((expected_item.clone(), actual_item.clone())); - } + if !expected_item.codegen_units.is_empty() && + // Also check for codegen units + expected_item.codegen_units != actual_item.codegen_units { + wrong_cgus.push((expected_item.clone(), actual_item.clone())); } } else { missing.push(expected_item.string.clone()); @@ -2006,7 +1999,7 @@ actual:\n\ let cgus = if parts.len() > 1 { let cgus_str = parts[1]; - cgus_str.split(" ") + cgus_str.split(' ') .map(str::trim) .filter(|s| !s.is_empty()) .map(str::to_owned) @@ -2235,8 +2228,10 @@ actual:\n\ let expected_stdout_path = self.expected_output_path("stdout"); let expected_stdout = self.load_expected_output(&expected_stdout_path); - let normalized_stdout = self.normalize_output(&proc_res.stdout); - let normalized_stderr = self.normalize_output(&proc_res.stderr); + let normalized_stdout = + self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout); + let normalized_stderr = + self.normalize_output(&proc_res.stderr, &self.props.normalize_stderr); let mut errors = 0; errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout); @@ -2324,7 +2319,7 @@ actual:\n\ } } - fn compare_mir_test_output(&self, test_name: &str, expected_content: &Vec<&str>) { + fn compare_mir_test_output(&self, test_name: &str, expected_content: &[&str]) { let mut output_file = PathBuf::new(); output_file.push(self.get_mir_dump_dir()); output_file.push(test_name); @@ -2382,13 +2377,17 @@ actual:\n\ mir_dump_dir } - fn normalize_output(&self, output: &str) -> String { + fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> String { let parent_dir = self.testpaths.file.parent().unwrap(); let parent_dir_str = parent_dir.display().to_string(); - output.replace(&parent_dir_str, "$DIR") + let mut normalized = output.replace(&parent_dir_str, "$DIR") .replace("\\", "/") // normalize for paths on windows .replace("\r\n", "\n") // normalize for linebreaks on windows - .replace("\t", "\\t") // makes tabs visible + .replace("\t", "\\t"); // makes tabs visible + for rule in custom_rules { + normalized = normalized.replace(&rule.0, &rule.1); + } + normalized } fn expected_output_path(&self, kind: &str) -> PathBuf { diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 4202356bd9..85fa38bbd3 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -72,6 +72,14 @@ pub fn get_env(triple: &str) -> Option<&str> { triple.split('-').nth(3) } +pub fn get_pointer_width(triple: &str) -> &'static str { + if triple.contains("64") || triple.starts_with("s390x") { + "64bit" + } else { + "32bit" + } +} + pub fn make_new_path(path: &str) -> String { assert!(cfg!(windows)); // Windows just uses PATH as the library search path, so we have to diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 1b55dc792c..3ea2e6313a 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -118,15 +118,15 @@ fn check(cache: &mut Cache, return None; } // FIXME(#32553) - if file.ends_with("collections/string/struct.String.html") { + if file.ends_with("string/struct.String.html") { return None; } // FIXME(#32130) if file.ends_with("btree_set/struct.BTreeSet.html") || - file.ends_with("collections/struct.BTreeSet.html") || - file.ends_with("collections/btree_map/struct.BTreeMap.html") || - file.ends_with("collections/hash_map/struct.HashMap.html") || - file.ends_with("collections/hash_set/struct.HashSet.html") { + file.ends_with("struct.BTreeSet.html") || + file.ends_with("btree_map/struct.BTreeMap.html") || + file.ends_with("hash_map/struct.HashMap.html") || + file.ends_with("hash_set/struct.HashSet.html") { return None; } diff --git a/src/tools/rust-installer/test/rust-installer-v1/README.md b/src/tools/rust-installer/test/rust-installer-v1/README.md new file mode 100644 index 0000000000..f541504be6 --- /dev/null +++ b/src/tools/rust-installer/test/rust-installer-v1/README.md @@ -0,0 +1,30 @@ +A generator for the install.sh script commonly used to install Rust in +Unix environments. It is used By Rust, Cargo, and is intended to be +used by a future combined installer of Rust + Cargo. + +# Usage + +``` +./gen-installer.sh --product-name=Rust \ + --verify-bin=rustc \ + --rel-manifest-dir=rustlib \ + --success-message=Rust-is-ready-to-roll. \ + --image-dir=./install-image \ + --work-dir=./temp \ + --output-dir=./dist \ + --non-installed-prefixes="foo,bin/bar,lib/baz" \ + --package-name=rustc-nightly-i686-apple-darwin +``` + +Or, to just generate the script. + +``` +./gen-install-script.sh --product-name=Rust \ + --verify-bin=rustc \ + --rel-manifest-dir=rustlib \ + --success-message=Rust-is-ready-to-roll. \ + --output-script=install.sh +``` + +*Note: the dashes in `success-message` are converted to spaces. The +script's argument handling is broken with spaces.* \ No newline at end of file diff --git a/src/tools/rust-installer/test/rust-installer-v1/gen-install-script.sh b/src/tools/rust-installer/test/rust-installer-v1/gen-install-script.sh new file mode 100755 index 0000000000..4c7e327ab1 --- /dev/null +++ b/src/tools/rust-installer/test/rust-installer-v1/gen-install-script.sh @@ -0,0 +1,253 @@ +#!/bin/sh +# Copyright 2014 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +msg() { + echo "gen-install-script: $1" +} + +step_msg() { + msg + msg "$1" + msg +} + +warn() { + echo "gen-install-script: WARNING: $1" +} + +err() { + echo "gen-install-script: error: $1" + exit 1 +} + +need_ok() { + if [ $? -ne 0 ] + then + err "$1" + fi +} + +need_cmd() { + if command -v $1 >/dev/null 2>&1 + then msg "found $1" + else err "need $1" + fi +} + +putvar() { + local T + eval T=\$$1 + eval TLEN=\${#$1} + if [ $TLEN -gt 35 ] + then + printf "gen-install-script: %-20s := %.35s ...\n" $1 "$T" + else + printf "gen-install-script: %-20s := %s %s\n" $1 "$T" "$2" + fi +} + +valopt() { + VAL_OPTIONS="$VAL_OPTIONS $1" + + local OP=$1 + local DEFAULT=$2 + shift + shift + local DOC="$*" + if [ $HELP -eq 0 ] + then + local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_') + local V="CFG_${UOP}" + eval $V="$DEFAULT" + for arg in $CFG_ARGS + do + if echo "$arg" | grep -q -- "--$OP=" + then + val=$(echo "$arg" | cut -f2 -d=) + eval $V=$val + fi + done + putvar $V + else + if [ -z "$DEFAULT" ] + then + DEFAULT="" + fi + OP="${OP}=[${DEFAULT}]" + printf " --%-30s %s\n" "$OP" "$DOC" + fi +} + +opt() { + BOOL_OPTIONS="$BOOL_OPTIONS $1" + + local OP=$1 + local DEFAULT=$2 + shift + shift + local DOC="$*" + local FLAG="" + + if [ $DEFAULT -eq 0 ] + then + FLAG="enable" + else + FLAG="disable" + DOC="don't $DOC" + fi + + if [ $HELP -eq 0 ] + then + for arg in $CFG_ARGS + do + if [ "$arg" = "--${FLAG}-${OP}" ] + then + OP=$(echo $OP | tr 'a-z-' 'A-Z_') + FLAG=$(echo $FLAG | tr 'a-z' 'A-Z') + local V="CFG_${FLAG}_${OP}" + eval $V=1 + putvar $V + fi + done + else + if [ ! -z "$META" ] + then + OP="$OP=<$META>" + fi + printf " --%-30s %s\n" "$FLAG-$OP" "$DOC" + fi +} + +flag() { + BOOL_OPTIONS="$BOOL_OPTIONS $1" + + local OP=$1 + shift + local DOC="$*" + + if [ $HELP -eq 0 ] + then + for arg in $CFG_ARGS + do + if [ "$arg" = "--${OP}" ] + then + OP=$(echo $OP | tr 'a-z-' 'A-Z_') + local V="CFG_${OP}" + eval $V=1 + putvar $V + fi + done + else + if [ ! -z "$META" ] + then + OP="$OP=<$META>" + fi + printf " --%-30s %s\n" "$OP" "$DOC" + fi +} + +validate_opt () { + for arg in $CFG_ARGS + do + isArgValid=0 + for option in $BOOL_OPTIONS + do + if test --disable-$option = $arg + then + isArgValid=1 + fi + if test --enable-$option = $arg + then + isArgValid=1 + fi + if test --$option = $arg + then + isArgValid=1 + fi + done + for option in $VAL_OPTIONS + do + if echo "$arg" | grep -q -- "--$option=" + then + isArgValid=1 + fi + done + if [ "$arg" = "--help" ] + then + echo + echo "No more help available for Configure options," + echo "check the Wiki or join our IRC channel" + break + else + if test $isArgValid -eq 0 + then + err "Option '$arg' is not recognized" + fi + fi + done +} + +msg "looking for install programs" +msg + +need_cmd sed +need_cmd chmod +need_cmd cat + +CFG_SRC_DIR="$(cd $(dirname $0) && pwd)" +CFG_SELF="$0" +CFG_ARGS="$@" + +HELP=0 +if [ "$1" = "--help" ] +then + HELP=1 + shift + echo + echo "Usage: $CFG_SELF [options]" + echo + echo "Options:" + echo +else + step_msg "processing $CFG_SELF args" +fi + +valopt product-name "Product" "The name of the product, for display" +valopt verify-bin "program" "The command to run with --version to verify the install works" +valopt rel-manifest-dir "${CFG_VERIFY_BIN}lib" "The directory under lib/ where the manifest lives" +valopt success-message "Installed." "The string to print after successful installation" +valopt output-script "${CFG_SRC_DIR}/install.sh" "The name of the output script" + +if [ $HELP -eq 1 ] +then + echo + exit 0 +fi + +step_msg "validating $CFG_SELF args" +validate_opt + +# Replace dashes in the success message with spaces (our arg handling botches spaces) +CFG_SUCCESS_MESSAGE=`echo "$CFG_SUCCESS_MESSAGE" | sed "s/-/ /g"` + +SCRIPT_TEMPLATE=`cat "${CFG_SRC_DIR}/install-template.sh"` + +# Using /bin/echo because under sh emulation dash *seems* to escape \n, which screws up the template +SCRIPT=`/bin/echo "${SCRIPT_TEMPLATE}"` +SCRIPT=`/bin/echo "${SCRIPT}" | sed "s/%%TEMPLATE_PRODUCT_NAME%%/${CFG_PRODUCT_NAME}/"` +SCRIPT=`/bin/echo "${SCRIPT}" | sed "s/%%TEMPLATE_VERIFY_BIN%%/${CFG_VERIFY_BIN}/"` +SCRIPT=`/bin/echo "${SCRIPT}" | sed "s/%%TEMPLATE_REL_MANIFEST_DIR%%/${CFG_REL_MANIFEST_DIR}/"` +SCRIPT=`/bin/echo "${SCRIPT}" | sed "s/%%TEMPLATE_SUCCESS_MESSAGE%%/\"${CFG_SUCCESS_MESSAGE}\"/"` + +/bin/echo "${SCRIPT}" > "${CFG_OUTPUT_SCRIPT}" +need_ok "couldn't write script" +chmod u+x "${CFG_OUTPUT_SCRIPT}" +need_ok "couldn't chmod script" diff --git a/src/tools/rust-installer/test/rust-installer-v1/gen-installer.sh b/src/tools/rust-installer/test/rust-installer-v1/gen-installer.sh new file mode 100755 index 0000000000..c88eebee98 --- /dev/null +++ b/src/tools/rust-installer/test/rust-installer-v1/gen-installer.sh @@ -0,0 +1,303 @@ +#!/bin/sh +# Copyright 2014 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +msg() { + echo "gen-installer: $1" +} + +step_msg() { + msg + msg "$1" + msg +} + +warn() { + echo "gen-installer: WARNING: $1" +} + +err() { + echo "gen-installer: error: $1" + exit 1 +} + +need_ok() { + if [ $? -ne 0 ] + then + err "$1" + fi +} + +need_cmd() { + if command -v $1 >/dev/null 2>&1 + then msg "found $1" + else err "need $1" + fi +} + +putvar() { + local T + eval T=\$$1 + eval TLEN=\${#$1} + if [ $TLEN -gt 35 ] + then + printf "gen-installer: %-20s := %.35s ...\n" $1 "$T" + else + printf "gen-installer: %-20s := %s %s\n" $1 "$T" "$2" + fi +} + +valopt() { + VAL_OPTIONS="$VAL_OPTIONS $1" + + local OP=$1 + local DEFAULT=$2 + shift + shift + local DOC="$*" + if [ $HELP -eq 0 ] + then + local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_') + local V="CFG_${UOP}" + eval $V="$DEFAULT" + for arg in $CFG_ARGS + do + if echo "$arg" | grep -q -- "--$OP=" + then + val=$(echo "$arg" | cut -f2 -d=) + eval $V=$val + fi + done + putvar $V + else + if [ -z "$DEFAULT" ] + then + DEFAULT="" + fi + OP="${OP}=[${DEFAULT}]" + printf " --%-30s %s\n" "$OP" "$DOC" + fi +} + +opt() { + BOOL_OPTIONS="$BOOL_OPTIONS $1" + + local OP=$1 + local DEFAULT=$2 + shift + shift + local DOC="$*" + local FLAG="" + + if [ $DEFAULT -eq 0 ] + then + FLAG="enable" + else + FLAG="disable" + DOC="don't $DOC" + fi + + if [ $HELP -eq 0 ] + then + for arg in $CFG_ARGS + do + if [ "$arg" = "--${FLAG}-${OP}" ] + then + OP=$(echo $OP | tr 'a-z-' 'A-Z_') + FLAG=$(echo $FLAG | tr 'a-z' 'A-Z') + local V="CFG_${FLAG}_${OP}" + eval $V=1 + putvar $V + fi + done + else + if [ ! -z "$META" ] + then + OP="$OP=<$META>" + fi + printf " --%-30s %s\n" "$FLAG-$OP" "$DOC" + fi +} + +flag() { + BOOL_OPTIONS="$BOOL_OPTIONS $1" + + local OP=$1 + shift + local DOC="$*" + + if [ $HELP -eq 0 ] + then + for arg in $CFG_ARGS + do + if [ "$arg" = "--${OP}" ] + then + OP=$(echo $OP | tr 'a-z-' 'A-Z_') + local V="CFG_${OP}" + eval $V=1 + putvar $V + fi + done + else + if [ ! -z "$META" ] + then + OP="$OP=<$META>" + fi + printf " --%-30s %s\n" "$OP" "$DOC" + fi +} + +validate_opt () { + for arg in $CFG_ARGS + do + isArgValid=0 + for option in $BOOL_OPTIONS + do + if test --disable-$option = $arg + then + isArgValid=1 + fi + if test --enable-$option = $arg + then + isArgValid=1 + fi + if test --$option = $arg + then + isArgValid=1 + fi + done + for option in $VAL_OPTIONS + do + if echo "$arg" | grep -q -- "--$option=" + then + isArgValid=1 + fi + done + if [ "$arg" = "--help" ] + then + echo + echo "No more help available for Configure options," + echo "check the Wiki or join our IRC channel" + break + else + if test $isArgValid -eq 0 + then + err "Option '$arg' is not recognized" + fi + fi + done +} + +msg "looking for programs" +msg + +need_cmd tar +need_cmd cp +need_cmd rm +need_cmd mkdir +need_cmd echo +need_cmd tr + +CFG_SRC_DIR="$(cd $(dirname $0) && pwd)" +CFG_SELF="$0" +CFG_ARGS="$@" + +HELP=0 +if [ "$1" = "--help" ] +then + HELP=1 + shift + echo + echo "Usage: $CFG_SELF [options]" + echo + echo "Options:" + echo +else + step_msg "processing $CFG_SELF args" +fi + +valopt product-name "Product" "The name of the product, for display" +valopt package-name "package" "The name of the package, tarball" +valopt verify-bin "program" "The command to run with --version to verify the install works" +valopt rel-manifest-dir "${CFG_VERIFY_BIN}lib" "The directory under lib/ where the manifest lives" +valopt success-message "Installed." "The string to print after successful installation" +valopt non-installed-prefixes "" "Path prefixes that should be included but not installed" +valopt image-dir "./install-image" "The directory containing the installation medium" +valopt work-dir "./workdir" "The directory to do temporary work" +valopt output-dir "./dist" "The location to put the final image and tarball" +opt tarball 1 "Disable tarball generation, leaving output in the temp dir" + +if [ $HELP -eq 1 ] +then + echo + exit 0 +fi + +step_msg "validating $CFG_SELF args" +validate_opt + +GEN_INSTALL_SCRIPT="$CFG_SRC_DIR/gen-install-script.sh" + +if [ ! -d "$CFG_IMAGE_DIR" ] +then + err "image dir $CFG_IMAGE_DIR does not exist" +fi + +mkdir -p "$CFG_WORK_DIR" +need_ok "couldn't create work dir" + +rm -Rf "$CFG_WORK_DIR/$CFG_PACKAGE_NAME" +need_ok "couldn't delete work package dir" + +mkdir -p "$CFG_WORK_DIR/$CFG_PACKAGE_NAME" +need_ok "couldn't create work package dir" + +cp -r "$CFG_IMAGE_DIR/"* "$CFG_WORK_DIR/$CFG_PACKAGE_NAME" +need_ok "couldn't copy source image" + +# Split non_installed_files into lines for later iteration +NON_INSTALLED_PREFIXES=`echo "$CFG_NON_INSTALLED_PREFIXES" | tr "," "\n"` + +# Create the manifest +MANIFEST=`(cd "$CFG_WORK_DIR/$CFG_PACKAGE_NAME" && find . -type f | sed 's/^\.\///') | sort` + +# Remove non-installed files from manifest +NON_INSTALLED_PREFIXES=`echo "$CFG_NON_INSTALLED_PREFIXES" | tr "," " "` +for prefix in $NON_INSTALLED_PREFIXES; do + MANIFEST=`echo "$MANIFEST" | sed /^$prefix/d` +done + +MANIFEST_NAME="$CFG_WORK_DIR/$CFG_PACKAGE_NAME/lib/$CFG_REL_MANIFEST_DIR/manifest.in" + +mkdir -p "$CFG_WORK_DIR/$CFG_PACKAGE_NAME/lib/$CFG_REL_MANIFEST_DIR" +need_ok "couldn't create manifest dir" + +# Write the manifest +echo "$MANIFEST" > "$MANIFEST_NAME" + +# Generate the install script +"$CFG_SRC_DIR/gen-install-script.sh" \ + --product-name="$CFG_PRODUCT_NAME" \ + --verify-bin="$CFG_VERIFY_BIN" \ + --rel-manifest-dir="$CFG_REL_MANIFEST_DIR" \ + --success-message="$CFG_SUCCESS_MESSAGE" \ + --output-script="$CFG_WORK_DIR/$CFG_PACKAGE_NAME/install.sh" + +need_ok "failed to generate install script" + +mkdir -p "$CFG_OUTPUT_DIR" +need_ok "couldn't create output dir" + +rm -Rf "$CFG_OUTPUT_DIR/$CFG_PACKAGE_NAME.tar.gz" +need_ok "couldn't delete old tarball" + +# Make a tarball +tar -czf "$CFG_OUTPUT_DIR/$CFG_PACKAGE_NAME.tar.gz" -C "$CFG_WORK_DIR" "$CFG_PACKAGE_NAME" +need_ok "failed to tar" diff --git a/src/tools/rust-installer/test/rust-installer-v1/install-template.sh b/src/tools/rust-installer/test/rust-installer-v1/install-template.sh new file mode 100644 index 0000000000..545de670d5 --- /dev/null +++ b/src/tools/rust-installer/test/rust-installer-v1/install-template.sh @@ -0,0 +1,554 @@ +#!/bin/sh +# Copyright 2014 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +msg() { + echo "install: $1" +} + +step_msg() { + msg + msg "$1" + msg +} + +warn() { + echo "install: WARNING: $1" +} + +err() { + echo "install: error: $1" + exit 1 +} + +need_ok() { + if [ $? -ne 0 ] + then + err "$1" + fi +} + +need_cmd() { + if command -v $1 >/dev/null 2>&1 + then msg "found $1" + else err "need $1" + fi +} + +putvar() { + local T + eval T=\$$1 + eval TLEN=\${#$1} + if [ $TLEN -gt 35 ] + then + printf "install: %-20s := %.35s ...\n" $1 "$T" + else + printf "install: %-20s := %s %s\n" $1 "$T" "$2" + fi +} + +valopt() { + VAL_OPTIONS="$VAL_OPTIONS $1" + + local OP=$1 + local DEFAULT=$2 + shift + shift + local DOC="$*" + if [ $HELP -eq 0 ] + then + local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_') + local V="CFG_${UOP}" + eval $V="$DEFAULT" + for arg in $CFG_ARGS + do + if echo "$arg" | grep -q -- "--$OP=" + then + val=$(echo "$arg" | cut -f2 -d=) + eval $V=$val + fi + done + putvar $V + else + if [ -z "$DEFAULT" ] + then + DEFAULT="" + fi + OP="${OP}=[${DEFAULT}]" + printf " --%-30s %s\n" "$OP" "$DOC" + fi +} + +opt() { + BOOL_OPTIONS="$BOOL_OPTIONS $1" + + local OP=$1 + local DEFAULT=$2 + shift + shift + local DOC="$*" + local FLAG="" + + if [ $DEFAULT -eq 0 ] + then + FLAG="enable" + else + FLAG="disable" + DOC="don't $DOC" + fi + + if [ $HELP -eq 0 ] + then + for arg in $CFG_ARGS + do + if [ "$arg" = "--${FLAG}-${OP}" ] + then + OP=$(echo $OP | tr 'a-z-' 'A-Z_') + FLAG=$(echo $FLAG | tr 'a-z' 'A-Z') + local V="CFG_${FLAG}_${OP}" + eval $V=1 + putvar $V + fi + done + else + if [ ! -z "$META" ] + then + OP="$OP=<$META>" + fi + printf " --%-30s %s\n" "$FLAG-$OP" "$DOC" + fi +} + +flag() { + BOOL_OPTIONS="$BOOL_OPTIONS $1" + + local OP=$1 + shift + local DOC="$*" + + if [ $HELP -eq 0 ] + then + for arg in $CFG_ARGS + do + if [ "$arg" = "--${OP}" ] + then + OP=$(echo $OP | tr 'a-z-' 'A-Z_') + local V="CFG_${OP}" + eval $V=1 + putvar $V + fi + done + else + if [ ! -z "$META" ] + then + OP="$OP=<$META>" + fi + printf " --%-30s %s\n" "$OP" "$DOC" + fi +} + +validate_opt () { + for arg in $CFG_ARGS + do + isArgValid=0 + for option in $BOOL_OPTIONS + do + if test --disable-$option = $arg + then + isArgValid=1 + fi + if test --enable-$option = $arg + then + isArgValid=1 + fi + if test --$option = $arg + then + isArgValid=1 + fi + done + for option in $VAL_OPTIONS + do + if echo "$arg" | grep -q -- "--$option=" + then + isArgValid=1 + fi + done + if [ "$arg" = "--help" ] + then + echo + echo "No more help available for Configure options," + echo "check the Wiki or join our IRC channel" + break + else + if test $isArgValid -eq 0 + then + err "Option '$arg' is not recognized" + fi + fi + done +} + +absolutify() { + FILE_PATH="${1}" + FILE_PATH_DIRNAME="$(dirname ${FILE_PATH})" + FILE_PATH_BASENAME="$(basename ${FILE_PATH})" + FILE_ABS_PATH="$(cd ${FILE_PATH_DIRNAME} && pwd)" + FILE_PATH="${FILE_ABS_PATH}/${FILE_PATH_BASENAME}" + # This is the return value + ABSOLUTIFIED="${FILE_PATH}" +} + +msg "looking for install programs" +msg + +need_cmd mkdir +need_cmd printf +need_cmd cut +need_cmd grep +need_cmd uname +need_cmd tr +need_cmd sed + +CFG_SRC_DIR="$(cd $(dirname $0) && pwd)" +CFG_SELF="$0" +CFG_ARGS="$@" + +HELP=0 +if [ "$1" = "--help" ] +then + HELP=1 + shift + echo + echo "Usage: $CFG_SELF [options]" + echo + echo "Options:" + echo +else + step_msg "processing $CFG_SELF args" +fi + +# Check for mingw or cygwin in order to special case $CFG_LIBDIR_RELATIVE. +# This logic is duplicated from configure in order to get the correct libdir +# for Windows installs. +CFG_OSTYPE=$(uname -s) + +case $CFG_OSTYPE in + + Linux) + CFG_OSTYPE=unknown-linux-gnu + ;; + + FreeBSD) + CFG_OSTYPE=unknown-freebsd + ;; + + DragonFly) + CFG_OSTYPE=unknown-dragonfly + ;; + + Darwin) + CFG_OSTYPE=apple-darwin + ;; + + MINGW*) + # msys' `uname` does not print gcc configuration, but prints msys + # configuration. so we cannot believe `uname -m`: + # msys1 is always i686 and msys2 is always x86_64. + # instead, msys defines $MSYSTEM which is MINGW32 on i686 and + # MINGW64 on x86_64. + CFG_CPUTYPE=i686 + CFG_OSTYPE=pc-windows-gnu + if [ "$MSYSTEM" = MINGW64 ] + then + CFG_CPUTYPE=x86_64 + fi + ;; + + MSYS*) + CFG_OSTYPE=pc-windows-gnu + ;; + +# Thad's Cygwin identifers below + +# Vista 32 bit + CYGWIN_NT-6.0) + CFG_OSTYPE=pc-windows-gnu + CFG_CPUTYPE=i686 + ;; + +# Vista 64 bit + CYGWIN_NT-6.0-WOW64) + CFG_OSTYPE=pc-windows-gnu + CFG_CPUTYPE=x86_64 + ;; + +# Win 7 32 bit + CYGWIN_NT-6.1) + CFG_OSTYPE=pc-windows-gnu + CFG_CPUTYPE=i686 + ;; + +# Win 7 64 bit + CYGWIN_NT-6.1-WOW64) + CFG_OSTYPE=pc-windows-gnu + CFG_CPUTYPE=x86_64 + ;; +esac + +OPTIONS="" +BOOL_OPTIONS="" +VAL_OPTIONS="" + +if [ "$CFG_OSTYPE" = "pc-windows-gnu" ] +then + CFG_LD_PATH_VAR=PATH + CFG_OLD_LD_PATH_VAR=$PATH +elif [ "$CFG_OSTYPE" = "apple-darwin" ] +then + CFG_LD_PATH_VAR=DYLD_LIBRARY_PATH + CFG_OLD_LD_PATH_VAR=$DYLD_LIBRARY_PATH +else + CFG_LD_PATH_VAR=LD_LIBRARY_PATH + CFG_OLD_LD_PATH_VAR=$LD_LIBRARY_PATH +fi + +flag uninstall "only uninstall from the installation prefix" +valopt destdir "" "set installation root" +opt verify 1 "verify that the installed binaries run correctly" +valopt prefix "/usr/local" "set installation prefix" +# NB This isn't quite the same definition as in `configure`. +# just using 'lib' instead of configure's CFG_LIBDIR_RELATIVE +valopt libdir "${CFG_DESTDIR}${CFG_PREFIX}/lib" "install libraries" +valopt mandir "${CFG_DESTDIR}${CFG_PREFIX}/share/man" "install man pages in PATH" + +if [ $HELP -eq 1 ] +then + echo + exit 0 +fi + +step_msg "validating $CFG_SELF args" +validate_opt + + + +# Template configuration. +# These names surrounded by '%%` are replaced by sed when generating install.sh + +# Rust or Cargo +TEMPLATE_PRODUCT_NAME=%%TEMPLATE_PRODUCT_NAME%% +# rustc or cargo +TEMPLATE_VERIFY_BIN=%%TEMPLATE_VERIFY_BIN%% +# rustlib or cargo +TEMPLATE_REL_MANIFEST_DIR=%%TEMPLATE_REL_MANIFEST_DIR%% +# 'Rust is ready to roll.' or 'Cargo is cool to cruise.' +TEMPLATE_SUCCESS_MESSAGE=%%TEMPLATE_SUCCESS_MESSAGE%% + +# OK, let's get installing ... + +# Sanity check: can we run the binaries? +if [ -z "${CFG_DISABLE_VERIFY}" ] +then + # Don't do this if uninstalling. Failure here won't help in any way. + if [ -z "${CFG_UNINSTALL}" ] + then + msg "verifying platform can run binaries" + export $CFG_LD_PATH_VAR="${CFG_SRC_DIR}/lib:$CFG_OLD_LD_PATH_VAR" + "${CFG_SRC_DIR}/bin/${TEMPLATE_VERIFY_BIN}" --version 2> /dev/null 1> /dev/null + if [ $? -ne 0 ] + then + err "can't execute rustc binary on this platform" + fi + export $CFG_LD_PATH_VAR="$CFG_OLD_LD_PATH_VAR" + fi +fi + +# Sanity check: can we can write to the destination? +msg "verifying destination is writable" +umask 022 && mkdir -p "${CFG_LIBDIR}" +need_ok "can't write to destination. consider \`sudo\`." +touch "${CFG_LIBDIR}/rust-install-probe" > /dev/null +if [ $? -ne 0 ] +then + err "can't write to destination. consider \`sudo\`." +fi +rm -f "${CFG_LIBDIR}/rust-install-probe" +need_ok "failed to remove install probe" + +# Sanity check: don't install to the directory containing the installer. +# That would surely cause chaos. +msg "verifying destination is not the same as source" +INSTALLER_DIR="$(cd $(dirname $0) && pwd)" +PREFIX_DIR="$(cd ${CFG_PREFIX} && pwd)" +if [ "${INSTALLER_DIR}" = "${PREFIX_DIR}" ] +then + err "can't install to same directory as installer" +fi + +# Using an absolute path to libdir in a few places so that the status +# messages are consistently using absolute paths. +absolutify "${CFG_LIBDIR}" +ABS_LIBDIR="${ABSOLUTIFIED}" + +# The file name of the manifest we're going to create during install +INSTALLED_MANIFEST="${ABS_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}/manifest" + +# First, uninstall from the installation prefix. +# Errors are warnings - try to rm everything in the manifest even if some fail. +if [ -f "${INSTALLED_MANIFEST}" ] +then + msg + + # Iterate through installed manifest and remove files + while read p; do + # The installed manifest contains absolute paths + msg "removing $p" + if [ -f "$p" ] + then + rm -f "$p" + if [ $? -ne 0 ] + then + warn "failed to remove $p" + fi + else + warn "supposedly installed file $p does not exist!" + fi + done < "${INSTALLED_MANIFEST}" + + # If we fail to remove $TEMPLATE_REL_MANIFEST_DIR below, then the + # installed manifest will still be full; the installed manifest + # needs to be empty before install. + msg "removing ${INSTALLED_MANIFEST}" + rm -f "${INSTALLED_MANIFEST}" + # For the above reason, this is a hard error + need_ok "failed to remove installed manifest" + + # Remove $TEMPLATE_REL_MANIFEST_DIR directory + msg "removing ${ABS_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}" + rm -Rf "${ABS_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}" + if [ $? -ne 0 ] + then + warn "failed to remove ${TEMPLATE_REL_MANIFEST_DIR}" + fi +else + # There's no manifest. If we were asked to uninstall, then that's a problem. + if [ -n "${CFG_UNINSTALL}" ] + then + err "unable to find installation manifest at ${CFG_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}" + fi +fi + +# If we're only uninstalling then exit +if [ -n "${CFG_UNINSTALL}" ] +then + echo + echo " ${TEMPLATE_PRODUCT_NAME} is uninstalled." + echo + exit 0 +fi + +# Create the installed manifest, which we will fill in with absolute file paths +mkdir -p "${CFG_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}" +need_ok "failed to create ${TEMPLATE_REL_MANIFEST_DIR}" +touch "${INSTALLED_MANIFEST}" +need_ok "failed to create installed manifest" + +msg + +# Now install, iterate through the new manifest and copy files +while read p; do + + # Decide the destination of the file + FILE_INSTALL_PATH="${CFG_DESTDIR}${CFG_PREFIX}/$p" + + if echo "$p" | grep "^lib/" > /dev/null + then + pp=`echo $p | sed 's/^lib\///'` + FILE_INSTALL_PATH="${CFG_LIBDIR}/$pp" + fi + + if echo "$p" | grep "^share/man/" > /dev/null + then + pp=`echo $p | sed 's/^share\/man\///'` + FILE_INSTALL_PATH="${CFG_MANDIR}/$pp" + fi + + # Make sure there's a directory for it + umask 022 && mkdir -p "$(dirname ${FILE_INSTALL_PATH})" + need_ok "directory creation failed" + + # Make the path absolute so we can uninstall it later without + # starting from the installation cwd + absolutify "${FILE_INSTALL_PATH}" + FILE_INSTALL_PATH="${ABSOLUTIFIED}" + + # Install the file + msg "installing ${FILE_INSTALL_PATH}" + if echo "$p" | grep "^bin/" > /dev/null + then + install -m755 "${CFG_SRC_DIR}/$p" "${FILE_INSTALL_PATH}" + else + install -m644 "${CFG_SRC_DIR}/$p" "${FILE_INSTALL_PATH}" + fi + need_ok "file creation failed" + + # Update the manifest + echo "${FILE_INSTALL_PATH}" >> "${INSTALLED_MANIFEST}" + need_ok "failed to update manifest" + +# The manifest lists all files to install +done < "${CFG_SRC_DIR}/lib/${TEMPLATE_REL_MANIFEST_DIR}/manifest.in" + +msg + +# Run ldconfig to make dynamic libraries available to the linker +if [ "$CFG_OSTYPE" = "unknown-linux-gnu" ] + then + ldconfig + if [ $? -ne 0 ] + then + warn "failed to run ldconfig." + warn "this may happen when not installing as root and may be fine" + fi +fi + +# Sanity check: can we run the installed binaries? +# +# As with the verification above, make sure the right LD_LIBRARY_PATH-equivalent +# is in place. Try first without this variable, and if that fails try again with +# the variable. If the second time tries, print a hopefully helpful message to +# add something to the appropriate environment variable. +if [ -z "${CFG_DISABLE_VERIFY}" ] +then + msg "verifying installed binaries are executable" + "${CFG_PREFIX}/bin/${TEMPLATE_VERIFY_BIN}" --version 2> /dev/null 1> /dev/null + if [ $? -ne 0 ] + then + export $CFG_LD_PATH_VAR="${CFG_PREFIX}/lib:$CFG_OLD_LD_PATH_VAR" + "${CFG_PREFIX}/bin/${TEMPLATE_VERIFY_BIN}" --version > /dev/null + if [ $? -ne 0 ] + then + ERR="can't execute installed binaries. " + ERR="${ERR}installation may be broken. " + ERR="${ERR}if this is expected then rerun install.sh with \`--disable-verify\` " + ERR="${ERR}or \`make install\` with \`--disable-verify-install\`" + err "${ERR}" + else + echo + echo " Note: please ensure '${CFG_PREFIX}/lib' is added to ${CFG_LD_PATH_VAR}" + fi + fi +fi + +echo +echo " ${TEMPLATE_SUCCESS_MESSAGE}" +echo + + diff --git a/src/tools/rust-installer/test/rust-installer-v2/.travis.yml b/src/tools/rust-installer/test/rust-installer-v2/.travis.yml new file mode 100644 index 0000000000..7e341882a2 --- /dev/null +++ b/src/tools/rust-installer/test/rust-installer-v2/.travis.yml @@ -0,0 +1,2 @@ +script: + - ./test.sh diff --git a/src/tools/rust-installer/test/rust-installer-v2/README.md b/src/tools/rust-installer/test/rust-installer-v2/README.md new file mode 100644 index 0000000000..e2588f26bf --- /dev/null +++ b/src/tools/rust-installer/test/rust-installer-v2/README.md @@ -0,0 +1,74 @@ +[![Build Status](https://travis-ci.org/rust-lang/rust-installer.svg?branch=master)](https://travis-ci.org/rust-lang/rust-installer) + +A generator for the install.sh script commonly used to install Rust in +Unix environments. It is used By Rust, Cargo, and is intended to be +used by a future combined installer of Rust + Cargo. + +# Usage + +``` +./gen-installer.sh --product-name=Rust \ + --verify-bin=rustc \ + --rel-manifest-dir=rustlib \ + --success-message=Rust-is-ready-to-roll. \ + --image-dir=./install-image \ + --work-dir=./temp \ + --output-dir=./dist \ + --non-installed-prefixes=foo,bin/bar,lib/baz \ + --package-name=rustc-nightly-i686-apple-darwin \ + --component-name=rustc \ + --legacy-manifest-dirs=rustlib \ + --bulk-dirs=share/doc +``` + +Or, to just generate the script. + +``` +./gen-install-script.sh --product-name=Rust \ + --verify-bin=rustc \ + --rel-manifest-dir=rustlib \ + --success-message=Rust-is-ready-to-roll. \ + --output-script=install.sh \ + --legacy-manifest-dirs=rustlib +``` + +*Note: the dashes in `success-message` are converted to spaces. The +script's argument handling is broken with spaces.* + +To combine installers. + +``` +./combine-installers.sh --product-name=Rust \ + --verify-bin=rustc \ + --rel-manifest-dir=rustlib \ + --success-message=Rust-is-ready-to-roll. \ + --work-dir=./temp \ + --output-dir=./dist \ + --non-installed-overlay=./overlay \ + --package-name=rustc-nightly-i686-apple-darwin \ + --legacy-manifest-dirs=rustlib \ + --input-tarballs=./rustc.tar.gz,cargo.tar.gz +``` + +# Future work + +* Make install.sh not have to be customized, pull it's data from a + config file. +* Install an uninstall.sh script. +* Allow components to be selected during install. +* Allow components to be modified from an existing install. +* Be more resiliant to installation failures, particularly if the disk + is full. +* Pre-install and post-uninstall scripts. +* Make the verify-bin a per-component option. +* Be more thoughtful about overwriting existing files. +* Allow components to depend on or contradict other components. +* Sanity check that expected destination dirs (bin, lib, share exist)? +* Add --docdir flag. Is there a standard name for this? +* Remove empty directories on uninstall. +* Detect mismatches in --prefix, --mandir, etc. in follow-on + installs/uninstalls. +* Fix argument handling for spaces. +* Add --bindir. +* Store components in their own directories for cases where they + contain the same files. \ No newline at end of file diff --git a/src/tools/rust-installer/test/rust-installer-v2/combine-installers.sh b/src/tools/rust-installer/test/rust-installer-v2/combine-installers.sh new file mode 100644 index 0000000000..d135d2b0c9 --- /dev/null +++ b/src/tools/rust-installer/test/rust-installer-v2/combine-installers.sh @@ -0,0 +1,347 @@ +#!/bin/sh +# Copyright 2014 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +msg() { + echo "combine-installers: $1" +} + +step_msg() { + msg + msg "$1" + msg +} + +warn() { + echo "combine-installers: WARNING: $1" +} + +err() { + echo "combine-installers: error: $1" + exit 1 +} + +need_ok() { + if [ $? -ne 0 ] + then + err "$1" + fi +} + +need_cmd() { + if command -v $1 >/dev/null 2>&1 + then msg "found $1" + else err "need $1" + fi +} + +putvar() { + local T + eval T=\$$1 + eval TLEN=\${#$1} + if [ $TLEN -gt 35 ] + then + printf "combine-installers: %-20s := %.35s ...\n" $1 "$T" + else + printf "combine-installers: %-20s := %s %s\n" $1 "$T" "$2" + fi +} + +valopt() { + VAL_OPTIONS="$VAL_OPTIONS $1" + + local OP=$1 + local DEFAULT=$2 + shift + shift + local DOC="$*" + if [ $HELP -eq 0 ] + then + local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_') + local V="CFG_${UOP}" + eval $V="$DEFAULT" + for arg in $CFG_ARGS + do + if echo "$arg" | grep -q -- "--$OP=" + then + val=$(echo "$arg" | cut -f2 -d=) + eval $V=$val + fi + done + putvar $V + else + if [ -z "$DEFAULT" ] + then + DEFAULT="" + fi + OP="${OP}=[${DEFAULT}]" + printf " --%-30s %s\n" "$OP" "$DOC" + fi +} + +opt() { + BOOL_OPTIONS="$BOOL_OPTIONS $1" + + local OP=$1 + local DEFAULT=$2 + shift + shift + local DOC="$*" + local FLAG="" + + if [ $DEFAULT -eq 0 ] + then + FLAG="enable" + else + FLAG="disable" + DOC="don't $DOC" + fi + + if [ $HELP -eq 0 ] + then + for arg in $CFG_ARGS + do + if [ "$arg" = "--${FLAG}-${OP}" ] + then + OP=$(echo $OP | tr 'a-z-' 'A-Z_') + FLAG=$(echo $FLAG | tr 'a-z' 'A-Z') + local V="CFG_${FLAG}_${OP}" + eval $V=1 + putvar $V + fi + done + else + if [ ! -z "$META" ] + then + OP="$OP=<$META>" + fi + printf " --%-30s %s\n" "$FLAG-$OP" "$DOC" + fi +} + +flag() { + BOOL_OPTIONS="$BOOL_OPTIONS $1" + + local OP=$1 + shift + local DOC="$*" + + if [ $HELP -eq 0 ] + then + for arg in $CFG_ARGS + do + if [ "$arg" = "--${OP}" ] + then + OP=$(echo $OP | tr 'a-z-' 'A-Z_') + local V="CFG_${OP}" + eval $V=1 + putvar $V + fi + done + else + if [ ! -z "$META" ] + then + OP="$OP=<$META>" + fi + printf " --%-30s %s\n" "$OP" "$DOC" + fi +} + +validate_opt () { + for arg in $CFG_ARGS + do + isArgValid=0 + for option in $BOOL_OPTIONS + do + if test --disable-$option = $arg + then + isArgValid=1 + fi + if test --enable-$option = $arg + then + isArgValid=1 + fi + if test --$option = $arg + then + isArgValid=1 + fi + done + for option in $VAL_OPTIONS + do + if echo "$arg" | grep -q -- "--$option=" + then + isArgValid=1 + fi + done + if [ "$arg" = "--help" ] + then + echo + echo "No more help available for Configure options," + echo "check the Wiki or join our IRC channel" + break + else + if test $isArgValid -eq 0 + then + err "Option '$arg' is not recognized" + fi + fi + done +} + +msg "looking for programs" +msg + +need_cmd tar +need_cmd cp +need_cmd rm +need_cmd mkdir +need_cmd echo +need_cmd tr + +CFG_SRC_DIR="$(cd $(dirname $0) && pwd)" +CFG_SELF="$0" +CFG_ARGS="$@" + +HELP=0 +if [ "$1" = "--help" ] +then + HELP=1 + shift + echo + echo "Usage: $CFG_SELF [options]" + echo + echo "Options:" + echo +else + step_msg "processing $CFG_SELF args" +fi + +valopt product-name "Product" "The name of the product, for display" +valopt package-name "package" "The name of the package, tarball" +valopt verify-bin "" "The command to run with --version to verify the install works" +valopt rel-manifest-dir "${CFG_PACKAGE_NAME}lib" "The directory under lib/ where the manifest lives" +valopt success-message "Installed." "The string to print after successful installation" +valopt legacy-manifest-dirs "" "Places to look for legacy manifests to uninstall" +valopt input-tarballs "" "Installers to combine" +valopt non-installed-overlay "" "Directory containing files that should not be installed" +valopt work-dir "./workdir" "The directory to do temporary work and put the final image" +valopt output-dir "./dist" "The location to put the final tarball" + +if [ $HELP -eq 1 ] +then + echo + exit 0 +fi + +step_msg "validating $CFG_SELF args" +validate_opt + +RUST_INSTALLER_VERSION=`cat "$CFG_SRC_DIR/rust-installer-version"` + +# Create the work directory for the new installer +mkdir -p "$CFG_WORK_DIR" +need_ok "couldn't create work dir" + +rm -Rf "$CFG_WORK_DIR/$CFG_PACKAGE_NAME" +need_ok "couldn't delete work package dir" + +mkdir -p "$CFG_WORK_DIR/$CFG_PACKAGE_NAME" +need_ok "couldn't create work package dir" + +INPUT_TARBALLS=`echo "$CFG_INPUT_TARBALLS" | sed 's/,/ /g'` + +# Merge each installer into the work directory of the new installer +for input_tarball in $INPUT_TARBALLS; do + + # Extract the input tarballs + tar xzf $input_tarball -C "$CFG_WORK_DIR" + need_ok "failed to extract tarball" + + # Verify the version number + PKG_NAME=`echo "$input_tarball" | sed s/\.tar\.gz//g` + PKG_NAME=`basename $PKG_NAME` + VERSION=`cat "$CFG_WORK_DIR/$PKG_NAME/rust-installer-version"` + if [ "$RUST_INSTALLER_VERSION" != "$VERSION" ]; then + err "incorrect installer version in $input_tarball" + fi + + # Interpret the manifest to copy the contents to the new installer + COMPONENTS=`cat "$CFG_WORK_DIR/$PKG_NAME/components"` + for component in $COMPONENTS; do + while read directive; do + COMMAND=`echo $directive | cut -f1 -d:` + FILE=`echo $directive | cut -f2 -d:` + + NEW_FILE_PATH="$CFG_WORK_DIR/$CFG_PACKAGE_NAME/$FILE" + mkdir -p "$(dirname $NEW_FILE_PATH)" + + case "$COMMAND" in + file | dir) + if [ -e "$NEW_FILE_PATH" ]; then + err "file $NEW_FILE_PATH already exists" + fi + cp -R "$CFG_WORK_DIR/$PKG_NAME/$FILE" "$NEW_FILE_PATH" + need_ok "failed to copy file $FILE" + ;; + + * ) + err "unknown command" + ;; + + esac + done < "$CFG_WORK_DIR/$PKG_NAME/manifest-$component.in" + + # Copy the manifest + if [ -e "$CFG_WORK_DIR/$CFG_PACKAGE_NAME/manifest-$component.in" ]; then + err "manifest for $component already exists" + fi + cp "$CFG_WORK_DIR/$PKG_NAME/manifest-$component.in" "$CFG_WORK_DIR/$CFG_PACKAGE_NAME/manifest-$component.in" + need_ok "failed to copy manifest for $component" + + # Merge the component name + echo "$component" >> "$CFG_WORK_DIR/$CFG_PACKAGE_NAME/components" + need_ok "failed to merge component $component" + done +done + +# Write the version number +echo "$RUST_INSTALLER_VERSION" > "$CFG_WORK_DIR/$CFG_PACKAGE_NAME/rust-installer-version" + +# Copy the overlay +if [ -n "$CFG_NON_INSTALLED_OVERLAY" ]; then + OVERLAY_FILES=`(cd "$CFG_NON_INSTALLED_OVERLAY" && find . -type f)` + for f in $OVERLAY_FILES; do + if [ -e "$CFG_WORK_DIR/$CFG_PACKAGE_NAME/$f" ]; then err "overlay $f exists"; fi + + cp "$CFG_NON_INSTALLED_OVERLAY/$f" "$CFG_WORK_DIR/$CFG_PACKAGE_NAME/$f" + need_ok "failed to copy overlay $f" + done +fi + +# Generate the install script +"$CFG_SRC_DIR/gen-install-script.sh" \ + --product-name="$CFG_PRODUCT_NAME" \ + --verify-bin="$CFG_VERIFY_BIN" \ + --rel-manifest-dir="$CFG_REL_MANIFEST_DIR" \ + --success-message="$CFG_SUCCESS_MESSAGE" \ + --legacy-manifest-dirs="$CFG_LEGACY_MANIFEST_DIRS" \ + --output-script="$CFG_WORK_DIR/$CFG_PACKAGE_NAME/install.sh" + +need_ok "failed to generate install script" + +mkdir -p "$CFG_OUTPUT_DIR" +need_ok "couldn't create output dir" + +rm -Rf "$CFG_OUTPUT_DIR/$CFG_PACKAGE_NAME.tar.gz" +need_ok "couldn't delete old tarball" + +# Make a tarball +tar -czf "$CFG_OUTPUT_DIR/$CFG_PACKAGE_NAME.tar.gz" -C "$CFG_WORK_DIR" "$CFG_PACKAGE_NAME" +need_ok "failed to tar" diff --git a/src/tools/rust-installer/test/rust-installer-v2/gen-install-script.sh b/src/tools/rust-installer/test/rust-installer-v2/gen-install-script.sh new file mode 100755 index 0000000000..e00185e6a8 --- /dev/null +++ b/src/tools/rust-installer/test/rust-installer-v2/gen-install-script.sh @@ -0,0 +1,261 @@ +#!/bin/sh +# Copyright 2014 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +msg() { + echo "gen-install-script: $1" +} + +step_msg() { + msg + msg "$1" + msg +} + +warn() { + echo "gen-install-script: WARNING: $1" +} + +err() { + echo "gen-install-script: error: $1" + exit 1 +} + +need_ok() { + if [ $? -ne 0 ] + then + err "$1" + fi +} + +need_cmd() { + if command -v $1 >/dev/null 2>&1 + then msg "found $1" + else err "need $1" + fi +} + +putvar() { + local T + eval T=\$$1 + eval TLEN=\${#$1} + if [ $TLEN -gt 35 ] + then + printf "gen-install-script: %-20s := %.35s ...\n" $1 "$T" + else + printf "gen-install-script: %-20s := %s %s\n" $1 "$T" "$2" + fi +} + +valopt() { + VAL_OPTIONS="$VAL_OPTIONS $1" + + local OP=$1 + local DEFAULT=$2 + shift + shift + local DOC="$*" + if [ $HELP -eq 0 ] + then + local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_') + local V="CFG_${UOP}" + eval $V="$DEFAULT" + for arg in $CFG_ARGS + do + if echo "$arg" | grep -q -- "--$OP=" + then + val=$(echo "$arg" | cut -f2 -d=) + eval $V=$val + fi + done + putvar $V + else + if [ -z "$DEFAULT" ] + then + DEFAULT="" + fi + OP="${OP}=[${DEFAULT}]" + printf " --%-30s %s\n" "$OP" "$DOC" + fi +} + +opt() { + BOOL_OPTIONS="$BOOL_OPTIONS $1" + + local OP=$1 + local DEFAULT=$2 + shift + shift + local DOC="$*" + local FLAG="" + + if [ $DEFAULT -eq 0 ] + then + FLAG="enable" + else + FLAG="disable" + DOC="don't $DOC" + fi + + if [ $HELP -eq 0 ] + then + for arg in $CFG_ARGS + do + if [ "$arg" = "--${FLAG}-${OP}" ] + then + OP=$(echo $OP | tr 'a-z-' 'A-Z_') + FLAG=$(echo $FLAG | tr 'a-z' 'A-Z') + local V="CFG_${FLAG}_${OP}" + eval $V=1 + putvar $V + fi + done + else + if [ ! -z "$META" ] + then + OP="$OP=<$META>" + fi + printf " --%-30s %s\n" "$FLAG-$OP" "$DOC" + fi +} + +flag() { + BOOL_OPTIONS="$BOOL_OPTIONS $1" + + local OP=$1 + shift + local DOC="$*" + + if [ $HELP -eq 0 ] + then + for arg in $CFG_ARGS + do + if [ "$arg" = "--${OP}" ] + then + OP=$(echo $OP | tr 'a-z-' 'A-Z_') + local V="CFG_${OP}" + eval $V=1 + putvar $V + fi + done + else + if [ ! -z "$META" ] + then + OP="$OP=<$META>" + fi + printf " --%-30s %s\n" "$OP" "$DOC" + fi +} + +validate_opt () { + for arg in $CFG_ARGS + do + isArgValid=0 + for option in $BOOL_OPTIONS + do + if test --disable-$option = $arg + then + isArgValid=1 + fi + if test --enable-$option = $arg + then + isArgValid=1 + fi + if test --$option = $arg + then + isArgValid=1 + fi + done + for option in $VAL_OPTIONS + do + if echo "$arg" | grep -q -- "--$option=" + then + isArgValid=1 + fi + done + if [ "$arg" = "--help" ] + then + echo + echo "No more help available for Configure options," + echo "check the Wiki or join our IRC channel" + break + else + if test $isArgValid -eq 0 + then + err "Option '$arg' is not recognized" + fi + fi + done +} + +msg "looking for install programs" +msg + +need_cmd sed +need_cmd chmod +need_cmd cat + +CFG_SRC_DIR="$(cd $(dirname $0) && pwd)" +CFG_SELF="$0" +CFG_ARGS="$@" + +HELP=0 +if [ "$1" = "--help" ] +then + HELP=1 + shift + echo + echo "Usage: $CFG_SELF [options]" + echo + echo "Options:" + echo +else + step_msg "processing $CFG_SELF args" +fi + +valopt product-name "Product" "The name of the product, for display" +valopt verify-bin "" "The command to run with --version to verify the install works" +valopt rel-manifest-dir "${CFG_VERIFY_BIN}lib" "The directory under lib/ where the manifest lives" +valopt success-message "Installed." "The string to print after successful installation" +valopt output-script "${CFG_SRC_DIR}/install.sh" "The name of the output script" +valopt legacy-manifest-dirs "" "Places to look for legacy manifests to uninstall" + +if [ $HELP -eq 1 ] +then + echo + exit 0 +fi + +step_msg "validating $CFG_SELF args" +validate_opt + +RUST_INSTALLER_VERSION=`cat "$CFG_SRC_DIR/rust-installer-version"` + +# Replace dashes in the success message with spaces (our arg handling botches spaces) +CFG_PRODUCT_NAME=`echo "$CFG_PRODUCT_NAME" | sed "s/-/ /g"` + +# Replace dashes in the success message with spaces (our arg handling botches spaces) +CFG_SUCCESS_MESSAGE=`echo "$CFG_SUCCESS_MESSAGE" | sed "s/-/ /g"` + +SCRIPT_TEMPLATE=`cat "${CFG_SRC_DIR}/install-template.sh"` + +# Using /bin/echo because under sh emulation dash *seems* to escape \n, which screws up the template +SCRIPT=`/bin/echo "${SCRIPT_TEMPLATE}"` +SCRIPT=`/bin/echo "${SCRIPT}" | sed "s/%%TEMPLATE_PRODUCT_NAME%%/\"${CFG_PRODUCT_NAME}\"/"` +SCRIPT=`/bin/echo "${SCRIPT}" | sed "s/%%TEMPLATE_VERIFY_BIN%%/${CFG_VERIFY_BIN}/"` +SCRIPT=`/bin/echo "${SCRIPT}" | sed "s/%%TEMPLATE_REL_MANIFEST_DIR%%/${CFG_REL_MANIFEST_DIR}/"` +SCRIPT=`/bin/echo "${SCRIPT}" | sed "s/%%TEMPLATE_SUCCESS_MESSAGE%%/\"${CFG_SUCCESS_MESSAGE}\"/"` +SCRIPT=`/bin/echo "${SCRIPT}" | sed "s/%%TEMPLATE_LEGACY_MANIFEST_DIRS%%/\"${CFG_LEGACY_MANIFEST_DIRS}\"/"` +SCRIPT=`/bin/echo "${SCRIPT}" | sed "s/%%TEMPLATE_RUST_INSTALLER_VERSION%%/\"$RUST_INSTALLER_VERSION\"/"` + +/bin/echo "${SCRIPT}" > "${CFG_OUTPUT_SCRIPT}" +need_ok "couldn't write script" +chmod u+x "${CFG_OUTPUT_SCRIPT}" +need_ok "couldn't chmod script" diff --git a/src/tools/rust-installer/test/rust-installer-v2/gen-installer.sh b/src/tools/rust-installer/test/rust-installer-v2/gen-installer.sh new file mode 100755 index 0000000000..67eaf39899 --- /dev/null +++ b/src/tools/rust-installer/test/rust-installer-v2/gen-installer.sh @@ -0,0 +1,332 @@ +#!/bin/sh +# Copyright 2014 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +msg() { + echo "gen-installer: $1" +} + +step_msg() { + msg + msg "$1" + msg +} + +warn() { + echo "gen-installer: WARNING: $1" +} + +err() { + echo "gen-installer: error: $1" + exit 1 +} + +need_ok() { + if [ $? -ne 0 ] + then + err "$1" + fi +} + +need_cmd() { + if command -v $1 >/dev/null 2>&1 + then msg "found $1" + else err "need $1" + fi +} + +putvar() { + local T + eval T=\$$1 + eval TLEN=\${#$1} + if [ $TLEN -gt 35 ] + then + printf "gen-installer: %-20s := %.35s ...\n" $1 "$T" + else + printf "gen-installer: %-20s := %s %s\n" $1 "$T" "$2" + fi +} + +valopt() { + VAL_OPTIONS="$VAL_OPTIONS $1" + + local OP=$1 + local DEFAULT=$2 + shift + shift + local DOC="$*" + if [ $HELP -eq 0 ] + then + local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_') + local V="CFG_${UOP}" + eval $V="$DEFAULT" + for arg in $CFG_ARGS + do + if echo "$arg" | grep -q -- "--$OP=" + then + val=$(echo "$arg" | cut -f2 -d=) + eval $V=$val + fi + done + putvar $V + else + if [ -z "$DEFAULT" ] + then + DEFAULT="" + fi + OP="${OP}=[${DEFAULT}]" + printf " --%-30s %s\n" "$OP" "$DOC" + fi +} + +opt() { + BOOL_OPTIONS="$BOOL_OPTIONS $1" + + local OP=$1 + local DEFAULT=$2 + shift + shift + local DOC="$*" + local FLAG="" + + if [ $DEFAULT -eq 0 ] + then + FLAG="enable" + else + FLAG="disable" + DOC="don't $DOC" + fi + + if [ $HELP -eq 0 ] + then + for arg in $CFG_ARGS + do + if [ "$arg" = "--${FLAG}-${OP}" ] + then + OP=$(echo $OP | tr 'a-z-' 'A-Z_') + FLAG=$(echo $FLAG | tr 'a-z' 'A-Z') + local V="CFG_${FLAG}_${OP}" + eval $V=1 + putvar $V + fi + done + else + if [ ! -z "$META" ] + then + OP="$OP=<$META>" + fi + printf " --%-30s %s\n" "$FLAG-$OP" "$DOC" + fi +} + +flag() { + BOOL_OPTIONS="$BOOL_OPTIONS $1" + + local OP=$1 + shift + local DOC="$*" + + if [ $HELP -eq 0 ] + then + for arg in $CFG_ARGS + do + if [ "$arg" = "--${OP}" ] + then + OP=$(echo $OP | tr 'a-z-' 'A-Z_') + local V="CFG_${OP}" + eval $V=1 + putvar $V + fi + done + else + if [ ! -z "$META" ] + then + OP="$OP=<$META>" + fi + printf " --%-30s %s\n" "$OP" "$DOC" + fi +} + +validate_opt () { + for arg in $CFG_ARGS + do + isArgValid=0 + for option in $BOOL_OPTIONS + do + if test --disable-$option = $arg + then + isArgValid=1 + fi + if test --enable-$option = $arg + then + isArgValid=1 + fi + if test --$option = $arg + then + isArgValid=1 + fi + done + for option in $VAL_OPTIONS + do + if echo "$arg" | grep -q -- "--$option=" + then + isArgValid=1 + fi + done + if [ "$arg" = "--help" ] + then + echo + echo "No more help available for Configure options," + echo "check the Wiki or join our IRC channel" + break + else + if test $isArgValid -eq 0 + then + err "Option '$arg' is not recognized" + fi + fi + done +} + +msg "looking for programs" +msg + +need_cmd tar +need_cmd cp +need_cmd rm +need_cmd mkdir +need_cmd echo +need_cmd tr +need_cmd awk + +CFG_SRC_DIR="$(cd $(dirname $0) && pwd)" +CFG_SELF="$0" +CFG_ARGS="$@" + +HELP=0 +if [ "$1" = "--help" ] +then + HELP=1 + shift + echo + echo "Usage: $CFG_SELF [options]" + echo + echo "Options:" + echo +else + step_msg "processing $CFG_SELF args" +fi + +valopt product-name "Product" "The name of the product, for display" +valopt component-name "component" "The name of the component, distinct from other installed components" +valopt package-name "package" "The name of the package, tarball" +valopt verify-bin "" "The command to run with --version to verify the install works" +valopt rel-manifest-dir "${CFG_PACKAGE_NAME}lib" "The directory under lib/ where the manifest lives" +valopt success-message "Installed." "The string to print after successful installation" +valopt legacy-manifest-dirs "" "Places to look for legacy manifests to uninstall" +valopt non-installed-prefixes "" "Path prefixes that should be included but not installed" +valopt bulk-dirs "" "Path prefixes of directories that should be installed/uninstalled in bulk" +valopt image-dir "./install-image" "The directory containing the installation medium" +valopt work-dir "./workdir" "The directory to do temporary work" +valopt output-dir "./dist" "The location to put the final image and tarball" + +if [ $HELP -eq 1 ] +then + echo + exit 0 +fi + +step_msg "validating $CFG_SELF args" +validate_opt + +RUST_INSTALLER_VERSION=`cat "$CFG_SRC_DIR/rust-installer-version"` + +if [ ! -d "$CFG_IMAGE_DIR" ] +then + err "image dir $CFG_IMAGE_DIR does not exist" +fi + +mkdir -p "$CFG_WORK_DIR" +need_ok "couldn't create work dir" + +rm -Rf "$CFG_WORK_DIR/$CFG_PACKAGE_NAME" +need_ok "couldn't delete work package dir" + +mkdir -p "$CFG_WORK_DIR/$CFG_PACKAGE_NAME" +need_ok "couldn't create work package dir" + +cp -r "$CFG_IMAGE_DIR/"* "$CFG_WORK_DIR/$CFG_PACKAGE_NAME" +need_ok "couldn't copy source image" + +# Create the manifest +MANIFEST=`(cd "$CFG_WORK_DIR/$CFG_PACKAGE_NAME" && find . -type f | sed 's/^\.\///') | sort` + +# Remove non-installed files from manifest +NON_INSTALLED_PREFIXES=`echo "$CFG_NON_INSTALLED_PREFIXES" | tr "," " "` +for prefix in $NON_INSTALLED_PREFIXES; do + # This adds the escapes to '/' in paths to make them '\/' so sed doesn't puke. + # I figured this out by adding backslashes until it worked. Holy shit. + prefix=`echo "$prefix" | sed s/\\\//\\\\\\\\\\\//g` + MANIFEST=`echo "$MANIFEST" | sed /^$prefix/d` +done + +# Remove files in bulk dirs +BULK_DIRS=`echo "$CFG_BULK_DIRS" | tr "," " "` +for bulk_dir in $BULK_DIRS; do + bulk_dir=`echo "$bulk_dir" | sed s/\\\//\\\\\\\\\\\//g` + MANIFEST=`echo "$MANIFEST" | sed /^$bulk_dir/d` +done + +# Add 'file:' installation directives. +# The -n prevents adding a blank file: if the manifest is empty +MANIFEST=`/bin/echo -n "$MANIFEST" | sed s/^/file:/` + +# Add 'dir:' directives +for bulk_dir in $BULK_DIRS; do + MANIFEST=`echo "$MANIFEST" && echo "dir:$bulk_dir"` +done + +# The above step may have left a leading empty line if there were only +# bulk dirs. Remove it. +MANIFEST=`echo "$MANIFEST" | sed /^$/d` + +MANIFEST_FILE="$CFG_WORK_DIR/$CFG_PACKAGE_NAME/manifest-$CFG_COMPONENT_NAME.in" +COMPONENT_FILE="$CFG_WORK_DIR/$CFG_PACKAGE_NAME/components" +VERSION_FILE="$CFG_WORK_DIR/$CFG_PACKAGE_NAME/rust-installer-version" + +# Write the manifest +echo "$MANIFEST" > "$MANIFEST_FILE" + +# Write the component name +echo "$CFG_COMPONENT_NAME" > "$COMPONENT_FILE" + +# Write the installer version (only used by combine-installers.sh) +echo "$RUST_INSTALLER_VERSION" > "$VERSION_FILE" + +# Generate the install script +"$CFG_SRC_DIR/gen-install-script.sh" \ + --product-name="$CFG_PRODUCT_NAME" \ + --verify-bin="$CFG_VERIFY_BIN" \ + --rel-manifest-dir="$CFG_REL_MANIFEST_DIR" \ + --success-message="$CFG_SUCCESS_MESSAGE" \ + --legacy-manifest-dirs="$CFG_LEGACY_MANIFEST_DIRS" \ + --output-script="$CFG_WORK_DIR/$CFG_PACKAGE_NAME/install.sh" + +need_ok "failed to generate install script" + +mkdir -p "$CFG_OUTPUT_DIR" +need_ok "couldn't create output dir" + +rm -Rf "$CFG_OUTPUT_DIR/$CFG_PACKAGE_NAME.tar.gz" +need_ok "couldn't delete old tarball" + +# Make a tarball +tar -czf "$CFG_OUTPUT_DIR/$CFG_PACKAGE_NAME.tar.gz" -C "$CFG_WORK_DIR" "$CFG_PACKAGE_NAME" +need_ok "failed to tar" diff --git a/src/tools/rust-installer/test/rust-installer-v2/install-template.sh b/src/tools/rust-installer/test/rust-installer-v2/install-template.sh new file mode 100644 index 0000000000..98d449af8e --- /dev/null +++ b/src/tools/rust-installer/test/rust-installer-v2/install-template.sh @@ -0,0 +1,743 @@ +#!/bin/sh +# Copyright 2014 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +msg() { + echo "install: $1" +} + +step_msg() { + msg + msg "$1" + msg +} + +warn() { + echo "install: WARNING: $1" +} + +err() { + echo "install: error: $1" + exit 1 +} + +need_ok() { + if [ $? -ne 0 ] + then + err "$1" + fi +} + +need_cmd() { + if command -v $1 >/dev/null 2>&1 + then msg "found $1" + else err "need $1" + fi +} + +putvar() { + local T + eval T=\$$1 + eval TLEN=\${#$1} + if [ $TLEN -gt 35 ] + then + printf "install: %-20s := %.35s ...\n" $1 "$T" + else + printf "install: %-20s := %s %s\n" $1 "$T" "$2" + fi +} + +valopt() { + VAL_OPTIONS="$VAL_OPTIONS $1" + + local OP=$1 + local DEFAULT=$2 + shift + shift + local DOC="$*" + if [ $HELP -eq 0 ] + then + local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_') + local V="CFG_${UOP}" + eval $V="$DEFAULT" + for arg in $CFG_ARGS + do + if echo "$arg" | grep -q -- "--$OP=" + then + val=$(echo "$arg" | cut -f2 -d=) + eval $V=$val + fi + done + putvar $V + else + if [ -z "$DEFAULT" ] + then + DEFAULT="" + fi + OP="${OP}=[${DEFAULT}]" + printf " --%-30s %s\n" "$OP" "$DOC" + fi +} + +opt() { + BOOL_OPTIONS="$BOOL_OPTIONS $1" + + local OP=$1 + local DEFAULT=$2 + shift + shift + local DOC="$*" + local FLAG="" + + if [ $DEFAULT -eq 0 ] + then + FLAG="enable" + else + FLAG="disable" + DOC="don't $DOC" + fi + + if [ $HELP -eq 0 ] + then + for arg in $CFG_ARGS + do + if [ "$arg" = "--${FLAG}-${OP}" ] + then + OP=$(echo $OP | tr 'a-z-' 'A-Z_') + FLAG=$(echo $FLAG | tr 'a-z' 'A-Z') + local V="CFG_${FLAG}_${OP}" + eval $V=1 + putvar $V + fi + done + else + if [ ! -z "$META" ] + then + OP="$OP=<$META>" + fi + printf " --%-30s %s\n" "$FLAG-$OP" "$DOC" + fi +} + +flag() { + BOOL_OPTIONS="$BOOL_OPTIONS $1" + + local OP=$1 + shift + local DOC="$*" + + if [ $HELP -eq 0 ] + then + for arg in $CFG_ARGS + do + if [ "$arg" = "--${OP}" ] + then + OP=$(echo $OP | tr 'a-z-' 'A-Z_') + local V="CFG_${OP}" + eval $V=1 + putvar $V + fi + done + else + if [ ! -z "$META" ] + then + OP="$OP=<$META>" + fi + printf " --%-30s %s\n" "$OP" "$DOC" + fi +} + +validate_opt () { + for arg in $CFG_ARGS + do + isArgValid=0 + for option in $BOOL_OPTIONS + do + if test --disable-$option = $arg + then + isArgValid=1 + fi + if test --enable-$option = $arg + then + isArgValid=1 + fi + if test --$option = $arg + then + isArgValid=1 + fi + done + for option in $VAL_OPTIONS + do + if echo "$arg" | grep -q -- "--$option=" + then + isArgValid=1 + fi + done + if [ "$arg" = "--help" ] + then + echo + echo "No more help available for Configure options," + echo "check the Wiki or join our IRC channel" + break + else + if test $isArgValid -eq 0 + then + err "Option '$arg' is not recognized" + fi + fi + done +} + +absolutify() { + FILE_PATH="${1}" + FILE_PATH_DIRNAME="$(dirname ${FILE_PATH})" + FILE_PATH_BASENAME="$(basename ${FILE_PATH})" + FILE_ABS_PATH="$(cd ${FILE_PATH_DIRNAME} && pwd)" + FILE_PATH="${FILE_ABS_PATH}/${FILE_PATH_BASENAME}" + # This is the return value + ABSOLUTIFIED="${FILE_PATH}" +} + +msg "looking for install programs" +msg + +need_cmd mkdir +need_cmd printf +need_cmd cut +need_cmd grep +need_cmd uname +need_cmd tr +need_cmd sed +need_cmd chmod + +CFG_SRC_DIR="$(cd $(dirname $0) && pwd)" +CFG_SELF="$0" +CFG_ARGS="$@" + +HELP=0 +if [ "$1" = "--help" ] +then + HELP=1 + shift + echo + echo "Usage: $CFG_SELF [options]" + echo + echo "Options:" + echo +else + step_msg "processing $CFG_SELF args" +fi + +# Check for mingw or cygwin in order to special case $CFG_LIBDIR_RELATIVE. +# This logic is duplicated from configure in order to get the correct libdir +# for Windows installs. +CFG_OSTYPE=$(uname -s) + +case $CFG_OSTYPE in + + Linux) + CFG_OSTYPE=unknown-linux-gnu + ;; + + FreeBSD) + CFG_OSTYPE=unknown-freebsd + ;; + + DragonFly) + CFG_OSTYPE=unknown-dragonfly + ;; + + Darwin) + CFG_OSTYPE=apple-darwin + ;; + + MINGW*) + # msys' `uname` does not print gcc configuration, but prints msys + # configuration. so we cannot believe `uname -m`: + # msys1 is always i686 and msys2 is always x86_64. + # instead, msys defines $MSYSTEM which is MINGW32 on i686 and + # MINGW64 on x86_64. + CFG_CPUTYPE=i686 + CFG_OSTYPE=pc-windows-gnu + if [ "$MSYSTEM" = MINGW64 ] + then + CFG_CPUTYPE=x86_64 + fi + ;; + + MSYS*) + CFG_OSTYPE=pc-windows-gnu + ;; + +# Thad's Cygwin identifers below + +# Vista 32 bit + CYGWIN_NT-6.0) + CFG_OSTYPE=pc-windows-gnu + CFG_CPUTYPE=i686 + ;; + +# Vista 64 bit + CYGWIN_NT-6.0-WOW64) + CFG_OSTYPE=pc-windows-gnu + CFG_CPUTYPE=x86_64 + ;; + +# Win 7 32 bit + CYGWIN_NT-6.1) + CFG_OSTYPE=pc-windows-gnu + CFG_CPUTYPE=i686 + ;; + +# Win 7 64 bit + CYGWIN_NT-6.1-WOW64) + CFG_OSTYPE=pc-windows-gnu + CFG_CPUTYPE=x86_64 + ;; +esac + +OPTIONS="" +BOOL_OPTIONS="" +VAL_OPTIONS="" + +if [ "$CFG_OSTYPE" = "pc-windows-gnu" ] +then + CFG_LD_PATH_VAR=PATH + CFG_OLD_LD_PATH_VAR=$PATH +elif [ "$CFG_OSTYPE" = "apple-darwin" ] +then + CFG_LD_PATH_VAR=DYLD_LIBRARY_PATH + CFG_OLD_LD_PATH_VAR=$DYLD_LIBRARY_PATH +else + CFG_LD_PATH_VAR=LD_LIBRARY_PATH + CFG_OLD_LD_PATH_VAR=$LD_LIBRARY_PATH +fi + +flag uninstall "only uninstall from the installation prefix" +valopt destdir "" "set installation root" +opt verify 1 "verify that the installed binaries run correctly" +valopt prefix "/usr/local" "set installation prefix" +# NB This isn't quite the same definition as in `configure`. +# just using 'lib' instead of configure's CFG_LIBDIR_RELATIVE +valopt libdir "${CFG_DESTDIR}${CFG_PREFIX}/lib" "install libraries" +valopt mandir "${CFG_DESTDIR}${CFG_PREFIX}/share/man" "install man pages in PATH" +opt ldconfig 1 "run ldconfig after installation (Linux only)" + +if [ $HELP -eq 1 ] +then + echo + exit 0 +fi + +step_msg "validating $CFG_SELF args" +validate_opt + +# Template configuration. +# These names surrounded by '%%` are replaced by sed when generating install.sh +# FIXME: Might want to consider loading this from a file and not generating install.sh + +# Rust or Cargo +TEMPLATE_PRODUCT_NAME=%%TEMPLATE_PRODUCT_NAME%% +# rustc or cargo +TEMPLATE_VERIFY_BIN=%%TEMPLATE_VERIFY_BIN%% +# rustlib or cargo +TEMPLATE_REL_MANIFEST_DIR=%%TEMPLATE_REL_MANIFEST_DIR%% +# 'Rust is ready to roll.' or 'Cargo is cool to cruise.' +TEMPLATE_SUCCESS_MESSAGE=%%TEMPLATE_SUCCESS_MESSAGE%% +# Locations to look for directories containing legacy, pre-versioned manifests +TEMPLATE_LEGACY_MANIFEST_DIRS=%%TEMPLATE_LEGACY_MANIFEST_DIRS%% +# The installer version +TEMPLATE_RUST_INSTALLER_VERSION=%%TEMPLATE_RUST_INSTALLER_VERSION%% + +# OK, let's get installing ... + +# If we don't have a verify bin then disable verify +if [ -z "$TEMPLATE_VERIFY_BIN" ]; then + CFG_DISABLE_VERIFY=1 +fi + +# Sanity check: can we run the binaries? +if [ -z "${CFG_DISABLE_VERIFY}" ] +then + # Don't do this if uninstalling. Failure here won't help in any way. + if [ -z "${CFG_UNINSTALL}" ] + then + msg "verifying platform can run binaries" + export $CFG_LD_PATH_VAR="${CFG_SRC_DIR}/lib:$CFG_OLD_LD_PATH_VAR" + "${CFG_SRC_DIR}/bin/${TEMPLATE_VERIFY_BIN}" --version 2> /dev/null 1> /dev/null + if [ $? -ne 0 ] + then + err "can't execute binaries on this platform" + fi + export $CFG_LD_PATH_VAR="$CFG_OLD_LD_PATH_VAR" + fi +fi + +# Sanity check: can we can write to the destination? +msg "verifying destination is writable" +umask 022 && mkdir -p "${CFG_LIBDIR}" +need_ok "can't write to destination. consider \`sudo\`." +touch "${CFG_LIBDIR}/rust-install-probe" > /dev/null +if [ $? -ne 0 ] +then + err "can't write to destination. consider \`sudo\`." +fi +rm -f "${CFG_LIBDIR}/rust-install-probe" +need_ok "failed to remove install probe" + +# Sanity check: don't install to the directory containing the installer. +# That would surely cause chaos. +msg "verifying destination is not the same as source" +INSTALLER_DIR="$(cd $(dirname $0) && pwd)" +PREFIX_DIR="$(cd ${CFG_PREFIX} && pwd)" +if [ "${INSTALLER_DIR}" = "${PREFIX_DIR}" ] +then + err "can't install to same directory as installer" +fi + +# Open the components file to get the list of components to install +COMPONENTS=`cat "$CFG_SRC_DIR/components"` + +# Sanity check: do we have components? +if [ ! -n "$COMPONENTS" ]; then + err "unable to find installation components" +fi + +# Using an absolute path to libdir in a few places so that the status +# messages are consistently using absolute paths. +absolutify "${CFG_LIBDIR}" +ABS_LIBDIR="${ABSOLUTIFIED}" + +# Replace commas in legacy manifest list with spaces +LEGACY_MANIFEST_DIRS=`echo "$TEMPLATE_LEGACY_MANIFEST_DIRS" | sed "s/,/ /g"` + +# Uninstall from legacy manifests +for md in $LEGACY_MANIFEST_DIRS; do + # First, uninstall from the installation prefix. + # Errors are warnings - try to rm everything in the manifest even if some fail. + if [ -f "$ABS_LIBDIR/$md/manifest" ] + then + + # Iterate through installed manifest and remove files + while read p; do + # The installed manifest contains absolute paths + msg "removing legacy file $p" + if [ -f "$p" ] + then + rm -f "$p" + if [ $? -ne 0 ] + then + warn "failed to remove $p" + fi + else + warn "supposedly installed file $p does not exist!" + fi + done < "$ABS_LIBDIR/$md/manifest" + + # If we fail to remove $md below, then the + # installed manifest will still be full; the installed manifest + # needs to be empty before install. + msg "removing legacy manifest $ABS_LIBDIR/$md/manifest" + rm -f "$ABS_LIBDIR/$md/manifest" + # For the above reason, this is a hard error + need_ok "failed to remove installed manifest" + + # Remove $TEMPLATE_REL_MANIFEST_DIR directory + msg "removing legacy manifest dir ${ABS_LIBDIR}/$md" + rm -Rf "${ABS_LIBDIR}/$md" + if [ $? -ne 0 ] + then + warn "failed to remove $md" + fi + + UNINSTALLED_SOMETHING=1 + fi +done + +# Load the version of the installed installer +if [ -f "$ABS_LIBDIR/$TEMPLATE_REL_MANIFEST_DIR/rust-installer-version" ]; then + INSTALLED_VERSION=`cat "$ABS_LIBDIR/$TEMPLATE_REL_MANIFEST_DIR/rust-installer-version"` + + # Sanity check + if [ ! -n "$INSTALLED_VERSION" ]; then err "rust installer version is empty"; fi +fi + +# If there's something installed, then uninstall +if [ -n "$INSTALLED_VERSION" ]; then + # Check the version of the installed installer + case "$INSTALLED_VERSION" in + + # TODO: If this is a previous version, then upgrade in place to the + # current version before uninstalling. No need to do this yet because + # there is no prior version (only the legacy 'unversioned' installer + # which we've already dealt with). + + # This is the current version. Nothing need to be done except uninstall. + "$TEMPLATE_RUST_INSTALLER_VERSION") + ;; + + # TODO: If this is an unknown (future) version then bail. + *) + echo "The copy of $TEMPLATE_PRODUCT_NAME at $CFG_PREFIX was installed using an" + echo "unknown version ($INSTALLED_VERSION) of rust-installer." + echo "Uninstall it first with the installer used for the original installation" + echo "before continuing." + exit 1 + ;; + esac + + MD="$ABS_LIBDIR/$TEMPLATE_REL_MANIFEST_DIR" + INSTALLED_COMPONENTS=`cat $MD/components` + + # Uninstall (our components only) before reinstalling + for available_component in $COMPONENTS; do + for installed_component in $INSTALLED_COMPONENTS; do + if [ "$available_component" = "$installed_component" ]; then + COMPONENT_MANIFEST="$MD/manifest-$installed_component" + + # Sanity check: there should be a component manifest + if [ ! -f "$COMPONENT_MANIFEST" ]; then + err "installed component '$installed_component' has no manifest" + fi + + # Iterate through installed component manifest and remove files + while read directive; do + + COMMAND=`echo $directive | cut -f1 -d:` + FILE=`echo $directive | cut -f2 -d:` + + # Sanity checks + if [ ! -n "$COMMAND" ]; then err "malformed installation directive"; fi + if [ ! -n "$FILE" ]; then err "malformed installation directive"; fi + + case "$COMMAND" in + file) + msg "removing file $FILE" + if [ -f "$FILE" ]; then + rm -f "$FILE" + if [ $? -ne 0 ]; then + warn "failed to remove $FILE" + fi + else + warn "supposedly installed file $FILE does not exist!" + fi + ;; + + dir) + msg "removing directory $FILE" + rm -Rf "$FILE" + if [ $? -ne 0 ]; then + warn "unable to remove directory $FILE" + fi + ;; + + *) + err "unknown installation directive" + ;; + esac + + done < "$COMPONENT_MANIFEST" + + # Remove the installed component manifest + msg "removing component manifest $COMPONENT_MANIFEST" + rm -f "$COMPONENT_MANIFEST" + # This is a hard error because the installation is unrecoverable + need_ok "failed to remove installed manifest for component '$installed_component'" + + # Update the installed component list + MODIFIED_COMPONENTS=`sed /^$installed_component\$/d $MD/components` + echo "$MODIFIED_COMPONENTS" > "$MD/components" + need_ok "failed to update installed component list" + fi + done + done + + # If there are no remaining components delete the manifest directory + REMAINING_COMPONENTS=`cat $MD/components` + if [ ! -n "$REMAINING_COMPONENTS" ]; then + msg "removing manifest directory $MD" + rm -Rf "$MD" + if [ $? -ne 0 ]; then + warn "failed to remove $MD" + fi + fi + + UNINSTALLED_SOMETHING=1 +fi + +# There's no installed version. If we were asked to uninstall, then that's a problem. +if [ -n "${CFG_UNINSTALL}" -a ! -n "$UNINSTALLED_SOMETHING" ] +then + err "unable to find installation manifest at ${CFG_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}" +fi + +# If we're only uninstalling then exit +if [ -n "${CFG_UNINSTALL}" ] +then + echo + echo " ${TEMPLATE_PRODUCT_NAME} is uninstalled." + echo + exit 0 +fi + +# Create the directory to contain the manifests +mkdir -p "${CFG_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}" +need_ok "failed to create ${TEMPLATE_REL_MANIFEST_DIR}" + +# Install each component +for component in $COMPONENTS; do + + # The file name of the manifest we're installing from + INPUT_MANIFEST="${CFG_SRC_DIR}/manifest-$component.in" + + # The installed manifest directory + MD="$ABS_LIBDIR/$TEMPLATE_REL_MANIFEST_DIR" + + # The file name of the manifest we're going to create during install + INSTALLED_MANIFEST="$MD/manifest-$component" + + # Create the installed manifest, which we will fill in with absolute file paths + touch "${INSTALLED_MANIFEST}" + need_ok "failed to create installed manifest" + + # Sanity check: do we have our input manifests? + if [ ! -f "$INPUT_MANIFEST" ]; then + err "manifest for $component does not exist at $INPUT_MANIFEST" + fi + + # Now install, iterate through the new manifest and copy files + while read directive; do + + COMMAND=`echo $directive | cut -f1 -d:` + FILE=`echo $directive | cut -f2 -d:` + + # Sanity checks + if [ ! -n "$COMMAND" ]; then err "malformed installation directive"; fi + if [ ! -n "$FILE" ]; then err "malformed installation directive"; fi + + # Decide the destination of the file + FILE_INSTALL_PATH="${CFG_DESTDIR}${CFG_PREFIX}/$FILE" + + if echo "$FILE" | grep "^lib/" > /dev/null + then + f=`echo $FILE | sed 's/^lib\///'` + FILE_INSTALL_PATH="${CFG_LIBDIR}/$f" + fi + + if echo "$FILE" | grep "^share/man/" > /dev/null + then + f=`echo $FILE | sed 's/^share\/man\///'` + FILE_INSTALL_PATH="${CFG_MANDIR}/$f" + fi + + # Make sure there's a directory for it + umask 022 && mkdir -p "$(dirname ${FILE_INSTALL_PATH})" + need_ok "directory creation failed" + + # Make the path absolute so we can uninstall it later without + # starting from the installation cwd + absolutify "${FILE_INSTALL_PATH}" + FILE_INSTALL_PATH="${ABSOLUTIFIED}" + + case "$COMMAND" in + file) + + # Install the file + msg "copying file $FILE_INSTALL_PATH" + if echo "$FILE" | grep "^bin/" > /dev/null + then + install -m755 "${CFG_SRC_DIR}/$FILE" "${FILE_INSTALL_PATH}" + else + install -m644 "${CFG_SRC_DIR}/$FILE" "${FILE_INSTALL_PATH}" + fi + need_ok "file creation failed" + + # Update the manifest + echo "file:${FILE_INSTALL_PATH}" >> "${INSTALLED_MANIFEST}" + need_ok "failed to update manifest" + + ;; + + dir) + + # Copy the dir + msg "copying directory $FILE_INSTALL_PATH" + + # Sanity check: bulk dirs are supposed to be uniquely ours and should not exist + if [ -e "$FILE_INSTALL_PATH" ]; then + err "$FILE_INSTALL_PATH already exists" + fi + + cp -R "$CFG_SRC_DIR/$FILE" "$FILE_INSTALL_PATH" + need_ok "failed to copy directory" + + # Set permissions. 0755 for dirs, 644 for files + chmod -R u+rwX,go+rX,go-w "$FILE_INSTALL_PATH" + need_ok "failed to set permissions on directory" + + # Update the manifest + echo "dir:$FILE_INSTALL_PATH" >> "$INSTALLED_MANIFEST" + need_ok "failed to update manifest" + ;; + + *) + err "unknown installation directive" + ;; + esac + done < "$INPUT_MANIFEST" + + # Update the components + echo "$component" >> "$MD/components" + need_ok "failed to update components list for $component" + +done + +# Drop the version number into the manifest dir +echo "$TEMPLATE_RUST_INSTALLER_VERSION" > "${ABS_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}/rust-installer-version" + +# Run ldconfig to make dynamic libraries available to the linker +if [ "$CFG_OSTYPE" = "unknown-linux-gnu" -a ! -n "$CFG_DISABLE_LDCONFIG" ]; then + msg "running ldconfig" + ldconfig + if [ $? -ne 0 ] + then + warn "failed to run ldconfig." + warn "this may happen when not installing as root and may be fine" + fi +fi + +# Sanity check: can we run the installed binaries? +# +# As with the verification above, make sure the right LD_LIBRARY_PATH-equivalent +# is in place. Try first without this variable, and if that fails try again with +# the variable. If the second time tries, print a hopefully helpful message to +# add something to the appropriate environment variable. +if [ -z "${CFG_DISABLE_VERIFY}" ] +then + export $CFG_LD_PATH_VAR="${CFG_PREFIX}/lib:$CFG_OLD_LD_PATH_VAR" + "${CFG_PREFIX}/bin/${TEMPLATE_VERIFY_BIN}" --version > /dev/null + if [ $? -ne 0 ] + then + ERR="can't execute installed binaries. " + ERR="${ERR}installation may be broken. " + ERR="${ERR}if this is expected then rerun install.sh with \`--disable-verify\` " + ERR="${ERR}or \`make install\` with \`--disable-verify-install\`" + err "${ERR}" + else + echo + echo " Note: please ensure '${CFG_PREFIX}/lib' is added to ${CFG_LD_PATH_VAR}" + fi +fi + +echo +echo " ${TEMPLATE_SUCCESS_MESSAGE}" +echo + + diff --git a/src/tools/rust-installer/test/rust-installer-v2/rust-installer-version b/src/tools/rust-installer/test/rust-installer-v2/rust-installer-version new file mode 100644 index 0000000000..d8263ee986 --- /dev/null +++ b/src/tools/rust-installer/test/rust-installer-v2/rust-installer-version @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/src/tools/rust-installer/test/rust-installer-v2/test.sh b/src/tools/rust-installer/test/rust-installer-v2/test.sh new file mode 100755 index 0000000000..87dcdcb55b --- /dev/null +++ b/src/tools/rust-installer/test/rust-installer-v2/test.sh @@ -0,0 +1,588 @@ +#!/bin/sh + +S="$(cd $(dirname $0) && pwd)" + +TEST_DIR="$S/test" +TMP_DIR="$S/tmp" +WORK_DIR="$TMP_DIR/workdir" +OUT_DIR="$TMP_DIR/outdir" +PREFIX_DIR="$TMP_DIR/prefix" + +case $(uname -s) in + + MINGW* | MSYS*) + WINDOWS=1 + ;; +esac + +pre() { + echo + echo "test: $1" + echo + rm -Rf "$WORK_DIR" + rm -Rf "$OUT_DIR" + rm -Rf "$PREFIX_DIR" + mkdir -p "$WORK_DIR" + mkdir -p "$OUT_DIR" + mkdir -p "$PREFIX_DIR" +} + +post() { + rm -Rf "$WORK_DIR" + rm -Rf "$OUT_DIR" + rm -Rf "$PREFIX_DIR" +} + +need_ok() { + if [ $? -ne 0 ] + then + echo + echo "TEST FAILED!" + echo + exit 1 + fi +} + +try() { + cmd="$@" + echo \$ "$cmd" + OUTPUT=`$@` + if [ $? -ne 0 ]; then + echo + # Using /bin/echo to avoid escaping + /bin/echo "$OUTPUT" + echo + echo "TEST FAILED!" + echo + exit 1 + fi +} + +expect_fail() { + cmd="$@" + echo \$ "$cmd" + OUTPUT=`$@` + if [ $? -eq 0 ]; then + echo + # Using /bin/echo to avoid escaping + /bin/echo "$OUTPUT" + echo + echo "TEST FAILED!" + echo + exit 1 + fi +} + +# Installation tests + +pre "basic install" +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" +try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" +try test -e "$PREFIX_DIR/something-to-install" +try test -e "$PREFIX_DIR/dir-to-install/foo" +try test -e "$PREFIX_DIR/bin/program" +try test -e "$PREFIX_DIR/bin/program2" +try test -e "$PREFIX_DIR/bin/bad-bin" +post + +pre "basic uninstall" +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" +try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" +try "$WORK_DIR/package/install.sh --uninstall" --prefix="$PREFIX_DIR" +try test ! -e "$PREFIX_DIR/something-to-install" +try test ! -e "$PREFIX_DIR/dir-to-install/foo" +try test ! -e "$PREFIX_DIR/bin/program" +try test ! -e "$PREFIX_DIR/bin/program2" +try test ! -e "$PREFIX_DIR/bin/bad-bin" +try test ! -e "$PREFIX_DIR/lib/packagelib" +post + +pre "not installed files" +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --non-installed-prefixes=something-to-not-install,dir-to-not-install +try test -e "$WORK_DIR/package/something-to-not-install" +try test -e "$WORK_DIR/package/dir-to-not-install" +try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" +try test ! -e "$PREFIX_DIR/something-to-not-install" +try test ! -e "$PREFIX_DIR/dir-to-not-install" +post + +pre "verify override" +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --verify-bin=program2 +try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" +post + +pre "tarball with package name" +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc-nightly +try "$WORK_DIR/rustc-nightly/install.sh" --prefix="$PREFIX_DIR" +try test -e "$OUT_DIR/rustc-nightly.tar.gz" +post + +pre "bulk directory" +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --bulk-dirs=dir-to-install +try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" +try test -e "$PREFIX_DIR/something-to-install" +try test -e "$PREFIX_DIR/dir-to-install/foo" +try test -e "$PREFIX_DIR/bin/program" +try test -e "$PREFIX_DIR/bin/program2" +try test -e "$PREFIX_DIR/bin/bad-bin" +try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" --uninstall +try test ! -e "$PREFIX_DIR/dir-to-install" +post + +pre "nested bulk directory" +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --bulk-dirs=dir-to-install/qux +try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" +try test -e "$PREFIX_DIR/dir-to-install/qux/bar" +try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" --uninstall +try test ! -e "$PREFIX_DIR/dir-to-install/qux" +post + +pre "only bulk directory, no files" +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image5" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --bulk-dirs=dir-to-install +try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" +try test -e "$PREFIX_DIR/dir-to-install/foo" +try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" --uninstall +try test ! -e "$PREFIX_DIR/dir-to-install/foo" +post + +pre "nested not installed files" +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --non-installed-prefixes=dir-to-install/qux/bar +try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" +try test ! -e "$PREFIX_DIR/dir-to-install/qux/bar" +post + +# Upgrade tests + +pre "upgrade v1 -> v2" +mkdir "$WORK_DIR/v1" +try sh "$S/test/rust-installer-v1/gen-installer.sh" \ + --image-dir="$TEST_DIR/image2" \ + --work-dir="$WORK_DIR/v1" \ + --output-dir="$OUT_DIR/v1" \ + --verify-bin=oldprogram \ + --rel-manifest-dir=packagelib +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --rel-manifest-dir=packagelib \ + --legacy-manifest-dirs=packagelib +try "$WORK_DIR/v1/package/install.sh" --prefix="$PREFIX_DIR" +try test -e "$PREFIX_DIR/something-to-install" +try test -e "$PREFIX_DIR/dir-to-install/bar" +try test -e "$PREFIX_DIR/bin/oldprogram" +try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" +try test ! -e "$PREFIX_DIR/dir-to-install/bar" +try test ! -e "$PREFIX_DIR/bin/oldprogram" +try test -e "$PREFIX_DIR/something-to-install" +try test -e "$PREFIX_DIR/dir-to-install/foo" +try test -e "$PREFIX_DIR/bin/program" +try test -e "$PREFIX_DIR/bin/program2" +try test -e "$PREFIX_DIR/bin/bad-bin" +try "$WORK_DIR/package/install.sh --uninstall" --prefix="$PREFIX_DIR" +try test ! -e "$PREFIX_DIR/something-to-install" +try test ! -e "$PREFIX_DIR/dir-to-install/foo" +try test ! -e "$PREFIX_DIR/bin/program" +try test ! -e "$PREFIX_DIR/bin/program2" +try test ! -e "$PREFIX_DIR/bin/bad-bin" +try test ! -e "$PREFIX_DIR/lib/packagelib" +post + +pre "upgrade v1 -> v2 with multiple legacy manifests" +mkdir "$WORK_DIR/v1" +try sh "$S/test/rust-installer-v1/gen-installer.sh" \ + --image-dir="$TEST_DIR/image2" \ + --work-dir="$WORK_DIR/v1" \ + --output-dir="$OUT_DIR/v1" \ + --verify-bin=oldprogram \ + --rel-manifest-dir=rustlib +try sh "$S/test/rust-installer-v1/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR/v1b" \ + --output-dir="$OUT_DIR/v1b" \ + --verify-bin=cargo \ + --rel-manifest-dir=cargo +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --rel-manifest-dir=packagelib \ + --legacy-manifest-dirs=rustlib,cargo +try "$WORK_DIR/v1/package/install.sh" --prefix="$PREFIX_DIR" +try "$WORK_DIR/v1b/package/install.sh" --prefix="$PREFIX_DIR" +try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" +try test ! -e "$PREFIX_DIR/dir-to-install/bar" +try test ! -e "$PREFIX_DIR/bin/oldprogram" +try test ! -e "$PREFIX_DIR/bin/cargo" +try test ! -e "$PREFIX_DIR/lib/cargo" +try test -e "$PREFIX_DIR/something-to-install" +try test -e "$PREFIX_DIR/dir-to-install/foo" +try test -e "$PREFIX_DIR/bin/program" +try test -e "$PREFIX_DIR/bin/program2" +try test -e "$PREFIX_DIR/bin/bad-bin" +try "$WORK_DIR/package/install.sh --uninstall" --prefix="$PREFIX_DIR" +try test ! -e "$PREFIX_DIR/something-to-install" +try test ! -e "$PREFIX_DIR/dir-to-install/foo" +try test ! -e "$PREFIX_DIR/bin/program" +try test ! -e "$PREFIX_DIR/bin/program2" +try test ! -e "$PREFIX_DIR/bin/bad-bin" +try test ! -e "$PREFIX_DIR/lib/packagelib" +post + +pre "multiple components" +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR/c1" \ + --output-dir="$OUT_DIR/c1" \ + --component-name=rustc +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR/c2" \ + --output-dir="$OUT_DIR/c2" \ + --verify-bin=cargo \ + --component-name=cargo +try "$WORK_DIR/c1/package/install.sh" --prefix="$PREFIX_DIR" +try "$WORK_DIR/c2/package/install.sh" --prefix="$PREFIX_DIR" +try test -e "$PREFIX_DIR/something-to-install" +try test -e "$PREFIX_DIR/dir-to-install/foo" +try test -e "$PREFIX_DIR/bin/program" +try test -e "$PREFIX_DIR/bin/program2" +try test -e "$PREFIX_DIR/bin/bad-bin" +try test -e "$PREFIX_DIR/bin/cargo" +try "$WORK_DIR/c1/package/install.sh" --prefix="$PREFIX_DIR" --uninstall +try test ! -e "$PREFIX_DIR/something-to-install" +try test ! -e "$PREFIX_DIR/dir-to-install/foo" +try test ! -e "$PREFIX_DIR/bin/program" +try test ! -e "$PREFIX_DIR/bin/program2" +try test ! -e "$PREFIX_DIR/bin/bad-bin" +try "$WORK_DIR/c2/package/install.sh" --prefix="$PREFIX_DIR" --uninstall +try test ! -e "$PREFIX_DIR/bin/cargo" +try test ! -e "$PREFIX_DIR/lib/packagelib" +post + +# Combined installer tests + +pre "combine installers" +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --verify-bin=cargo \ + --package-name=cargo \ + --component-name=cargo +try sh "$S/combine-installers.sh" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" +try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" +try test -e "$PREFIX_DIR/something-to-install" +try test -e "$PREFIX_DIR/dir-to-install/foo" +try test -e "$PREFIX_DIR/bin/program" +try test -e "$PREFIX_DIR/bin/program2" +try test -e "$PREFIX_DIR/bin/bad-bin" +try test -e "$PREFIX_DIR/bin/cargo" +try "$WORK_DIR/rust/install.sh --uninstall" --prefix="$PREFIX_DIR" +try test ! -e "$PREFIX_DIR/something-to-install" +try test ! -e "$PREFIX_DIR/dir-to-install/foo" +try test ! -e "$PREFIX_DIR/bin/program" +try test ! -e "$PREFIX_DIR/bin/program2" +try test ! -e "$PREFIX_DIR/bin/bad-bin" +try test ! -e "$PREFIX_DIR/bin/cargo" +try test ! -e "$PREFIX_DIR/lib/packagelib" +post + +pre "combine three installers" +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --verify-bin=cargo \ + --package-name=cargo \ + --component-name=cargo +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust-docs \ + --component-name=rust-docs +try sh "$S/combine-installers.sh" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" +try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" +try test -e "$PREFIX_DIR/something-to-install" +try test -e "$PREFIX_DIR/dir-to-install/foo" +try test -e "$PREFIX_DIR/bin/program" +try test -e "$PREFIX_DIR/bin/program2" +try test -e "$PREFIX_DIR/bin/bad-bin" +try test -e "$PREFIX_DIR/bin/cargo" +try test -e "$PREFIX_DIR/dir-to-install/qux/bar" +try "$WORK_DIR/rust/install.sh --uninstall" --prefix="$PREFIX_DIR" +try test ! -e "$PREFIX_DIR/something-to-install" +try test ! -e "$PREFIX_DIR/dir-to-install/foo" +try test ! -e "$PREFIX_DIR/bin/program" +try test ! -e "$PREFIX_DIR/bin/program2" +try test ! -e "$PREFIX_DIR/bin/bad-bin" +try test ! -e "$PREFIX_DIR/bin/cargo" +try test ! -e "$PREFIX_DIR/lib/packagelib" +try test ! -e "$PREFIX_DIR/dir-to-install/qux/bar" +post + +pre "combine installers with overlay" +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --verify-bin=cargo \ + --package-name=cargo \ + --component-name=cargo +mkdir -p "$WORK_DIR/overlay" +touch "$WORK_DIR/overlay/README" +try sh "$S/combine-installers.sh" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" \ + --non-installed-overlay="$WORK_DIR/overlay" +try test -e "$WORK_DIR/rust/README" +try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" +try test ! -e "$PREFIX_DIR/README" +post + +pre "combined with bulk dirs" +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc \ + --bulk-dirs=dir-to-install +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --verify-bin=cargo \ + --package-name=cargo \ + --component-name=cargo +try sh "$S/combine-installers.sh" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" +try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" +try test -e "$PREFIX_DIR/dir-to-install/foo" +try "$WORK_DIR/rust/install.sh --uninstall" --prefix="$PREFIX_DIR" +try test ! -e "$PREFIX_DIR/dir-to-install" +post + +pre "combine install with separate uninstall" +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc \ + --rel-manifest-dir=rustlib +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --verify-bin=cargo \ + --package-name=cargo \ + --component-name=cargo \ + --rel-manifest-dir=rustlib +try sh "$S/combine-installers.sh" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" \ + --rel-manifest-dir=rustlib +try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" +try test -e "$PREFIX_DIR/something-to-install" +try test -e "$PREFIX_DIR/dir-to-install/foo" +try test -e "$PREFIX_DIR/bin/program" +try test -e "$PREFIX_DIR/bin/program2" +try test -e "$PREFIX_DIR/bin/bad-bin" +try test -e "$PREFIX_DIR/bin/cargo" +try "$WORK_DIR/rustc/install.sh --uninstall" --prefix="$PREFIX_DIR" +try test ! -e "$PREFIX_DIR/something-to-install" +try test ! -e "$PREFIX_DIR/dir-to-install/foo" +try test ! -e "$PREFIX_DIR/bin/program" +try test ! -e "$PREFIX_DIR/bin/program2" +try test ! -e "$PREFIX_DIR/bin/bad-bin" +try "$WORK_DIR/cargo/install.sh --uninstall" --prefix="$PREFIX_DIR" +try test ! -e "$PREFIX_DIR/bin/cargo" +try test ! -e "$PREFIX_DIR/lib/packagelib" +post + +pre "combined v1 -> v2 upgrade" +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc \ + --rel-manifest-dir=rustlib +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --verify-bin=cargo \ + --package-name=cargo \ + --component-name=cargo \ + --rel-manifest-dir=rustlib +try sh "$S/combine-installers.sh" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" \ + --rel-manifest-dir=rustlib \ + --legacy-manifest-dirs=cargo,rustlib +try sh "$S/test/rust-installer-v1/gen-installer.sh" \ + --image-dir="$TEST_DIR/image2" \ + --work-dir="$WORK_DIR/v1" \ + --output-dir="$OUT_DIR/v1" \ + --verify-bin=oldprogram \ + --rel-manifest-dir=rustlib +try sh "$S/test/rust-installer-v1/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR/v1b" \ + --output-dir="$OUT_DIR/v1b" \ + --verify-bin=cargo \ + --rel-manifest-dir=cargo +try "$WORK_DIR/v1/package//install.sh" --prefix="$PREFIX_DIR" +try "$WORK_DIR/v1b/package//install.sh" --prefix="$PREFIX_DIR" +try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" +try test ! -e "$PREFIX_DIR/dir-to-install/bar" +try test ! -e "$PREFIX_DIR/bin/oldprogram" +try test ! -e "$PREFIX_DIR/lib/cargo" +try test -e "$PREFIX_DIR/something-to-install" +try test -e "$PREFIX_DIR/dir-to-install/foo" +try test -e "$PREFIX_DIR/bin/program" +try test -e "$PREFIX_DIR/bin/program2" +try test -e "$PREFIX_DIR/bin/bad-bin" +try test -e "$PREFIX_DIR/bin/cargo" +try test -e "$PREFIX_DIR/lib/rustlib" +try "$WORK_DIR/rust/install.sh --uninstall" --prefix="$PREFIX_DIR" +try test ! -e "$PREFIX_DIR/something-to-install" +try test ! -e "$PREFIX_DIR/dir-to-install/foo" +try test ! -e "$PREFIX_DIR/bin/program" +try test ! -e "$PREFIX_DIR/bin/program2" +try test ! -e "$PREFIX_DIR/bin/bad-bin" +try test ! -e "$PREFIX_DIR/bin/cargo" +try test ! -e "$PREFIX_DIR/lib/rustlib" +post + +# Smoke tests + +pre "can't run bins error" +try sh "$S/gen-installer.sh" \ + --verify-bin=bad-bin \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" +expect_fail "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" +post + +if [ ! -n "$WINDOWS" ]; then + # chmod doesn't work on windows + pre "can't write error" + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" + chmod u-w "$PREFIX_DIR" + expect_fail "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" + chmod u+w "$PREFIX_DIR" + post +fi + +pre "can't install to installer" +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=my-package +expect_fail "$WORK_DIR/my-package/install.sh" --prefix="$WORK_DIR/my-package" +post + +pre "upgrade from future installer error" +try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --rel-manifest-dir=rustlib +try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" +echo 100 > "$PREFIX_DIR/lib/rustlib/rust-installer-version" +expect_fail "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" +post + +pre "disable-verify" +try sh "$S/gen-installer.sh" \ + --verify-bin=bad-bin \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" +try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" --disable-verify +post + +# TODO: DESTDIR +# TODO: mandir/libdir/bindir, etc. + +echo +echo "TOTAL SUCCESS!" +echo diff --git a/src/tools/rust-installer/test/rust-installer-v2/test/image1/bin/bad-bin b/src/tools/rust-installer/test/rust-installer-v2/test/image1/bin/bad-bin new file mode 100644 index 0000000000..b5b0e3234b --- /dev/null +++ b/src/tools/rust-installer/test/rust-installer-v2/test/image1/bin/bad-bin @@ -0,0 +1 @@ +#!/bin/bogus \ No newline at end of file diff --git a/src/tools/rust-installer/test/rust-installer-v2/test/image1/bin/program b/src/tools/rust-installer/test/rust-installer-v2/test/image1/bin/program new file mode 100755 index 0000000000..96b4b06ad4 --- /dev/null +++ b/src/tools/rust-installer/test/rust-installer-v2/test/image1/bin/program @@ -0,0 +1 @@ +#!/bin/sh \ No newline at end of file diff --git a/src/tools/rust-installer/test/rust-installer-v2/test/image1/bin/program2 b/src/tools/rust-installer/test/rust-installer-v2/test/image1/bin/program2 new file mode 100755 index 0000000000..96b4b06ad4 --- /dev/null +++ b/src/tools/rust-installer/test/rust-installer-v2/test/image1/bin/program2 @@ -0,0 +1 @@ +#!/bin/sh \ No newline at end of file diff --git a/src/doc/unstable-book/src/library-features/manually-drop.md b/src/tools/rust-installer/test/rust-installer-v2/test/image1/dir-to-install/foo similarity index 100% rename from src/doc/unstable-book/src/library-features/manually-drop.md rename to src/tools/rust-installer/test/rust-installer-v2/test/image1/dir-to-install/foo diff --git a/src/vendor/bitflags-0.5.0/.cargo-ok b/src/tools/rust-installer/test/rust-installer-v2/test/image1/dir-to-not-install/foo similarity index 100% rename from src/vendor/bitflags-0.5.0/.cargo-ok rename to src/tools/rust-installer/test/rust-installer-v2/test/image1/dir-to-not-install/foo diff --git a/src/vendor/bitflags-0.7.0/.cargo-ok b/src/tools/rust-installer/test/rust-installer-v2/test/image1/something-to-install similarity index 100% rename from src/vendor/bitflags-0.7.0/.cargo-ok rename to src/tools/rust-installer/test/rust-installer-v2/test/image1/something-to-install diff --git a/src/vendor/error-chain/.cargo-ok b/src/tools/rust-installer/test/rust-installer-v2/test/image1/something-to-not-install similarity index 100% rename from src/vendor/error-chain/.cargo-ok rename to src/tools/rust-installer/test/rust-installer-v2/test/image1/something-to-not-install diff --git a/src/tools/rust-installer/test/rust-installer-v2/test/image2/bin/oldprogram b/src/tools/rust-installer/test/rust-installer-v2/test/image2/bin/oldprogram new file mode 100755 index 0000000000..96b4b06ad4 --- /dev/null +++ b/src/tools/rust-installer/test/rust-installer-v2/test/image2/bin/oldprogram @@ -0,0 +1 @@ +#!/bin/sh \ No newline at end of file diff --git a/src/vendor/pulldown-cmark-0.0.8/.cargo-ok b/src/tools/rust-installer/test/rust-installer-v2/test/image2/dir-to-install/bar similarity index 100% rename from src/vendor/pulldown-cmark-0.0.8/.cargo-ok rename to src/tools/rust-installer/test/rust-installer-v2/test/image2/dir-to-install/bar diff --git a/src/vendor/serde-0.9.15/.cargo-ok b/src/tools/rust-installer/test/rust-installer-v2/test/image2/something-to-install similarity index 100% rename from src/vendor/serde-0.9.15/.cargo-ok rename to src/tools/rust-installer/test/rust-installer-v2/test/image2/something-to-install diff --git a/src/tools/rust-installer/test/rust-installer-v2/test/image3/bin/cargo b/src/tools/rust-installer/test/rust-installer-v2/test/image3/bin/cargo new file mode 100755 index 0000000000..96b4b06ad4 --- /dev/null +++ b/src/tools/rust-installer/test/rust-installer-v2/test/image3/bin/cargo @@ -0,0 +1 @@ +#!/bin/sh \ No newline at end of file diff --git a/src/vendor/serde_json-0.9.10/.cargo-ok b/src/tools/rust-installer/test/rust-installer-v2/test/image4/baz similarity index 100% rename from src/vendor/serde_json-0.9.10/.cargo-ok rename to src/tools/rust-installer/test/rust-installer-v2/test/image4/baz diff --git a/src/vendor/strsim-0.5.2/.cargo-ok b/src/tools/rust-installer/test/rust-installer-v2/test/image4/dir-to-install/qux/bar similarity index 100% rename from src/vendor/strsim-0.5.2/.cargo-ok rename to src/tools/rust-installer/test/rust-installer-v2/test/image4/dir-to-install/qux/bar diff --git a/src/vendor/thread-id/.cargo-ok b/src/tools/rust-installer/test/rust-installer-v2/test/image5/dir-to-install/foo similarity index 100% rename from src/vendor/thread-id/.cargo-ok rename to src/tools/rust-installer/test/rust-installer-v2/test/image5/dir-to-install/foo diff --git a/src/tools/rust-installer/test/rust-installer-v2/test/rust-installer-v1/README.md b/src/tools/rust-installer/test/rust-installer-v2/test/rust-installer-v1/README.md new file mode 100644 index 0000000000..f541504be6 --- /dev/null +++ b/src/tools/rust-installer/test/rust-installer-v2/test/rust-installer-v1/README.md @@ -0,0 +1,30 @@ +A generator for the install.sh script commonly used to install Rust in +Unix environments. It is used By Rust, Cargo, and is intended to be +used by a future combined installer of Rust + Cargo. + +# Usage + +``` +./gen-installer.sh --product-name=Rust \ + --verify-bin=rustc \ + --rel-manifest-dir=rustlib \ + --success-message=Rust-is-ready-to-roll. \ + --image-dir=./install-image \ + --work-dir=./temp \ + --output-dir=./dist \ + --non-installed-prefixes="foo,bin/bar,lib/baz" \ + --package-name=rustc-nightly-i686-apple-darwin +``` + +Or, to just generate the script. + +``` +./gen-install-script.sh --product-name=Rust \ + --verify-bin=rustc \ + --rel-manifest-dir=rustlib \ + --success-message=Rust-is-ready-to-roll. \ + --output-script=install.sh +``` + +*Note: the dashes in `success-message` are converted to spaces. The +script's argument handling is broken with spaces.* \ No newline at end of file diff --git a/src/tools/rust-installer/test/rust-installer-v2/test/rust-installer-v1/gen-install-script.sh b/src/tools/rust-installer/test/rust-installer-v2/test/rust-installer-v1/gen-install-script.sh new file mode 100755 index 0000000000..4c7e327ab1 --- /dev/null +++ b/src/tools/rust-installer/test/rust-installer-v2/test/rust-installer-v1/gen-install-script.sh @@ -0,0 +1,253 @@ +#!/bin/sh +# Copyright 2014 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +msg() { + echo "gen-install-script: $1" +} + +step_msg() { + msg + msg "$1" + msg +} + +warn() { + echo "gen-install-script: WARNING: $1" +} + +err() { + echo "gen-install-script: error: $1" + exit 1 +} + +need_ok() { + if [ $? -ne 0 ] + then + err "$1" + fi +} + +need_cmd() { + if command -v $1 >/dev/null 2>&1 + then msg "found $1" + else err "need $1" + fi +} + +putvar() { + local T + eval T=\$$1 + eval TLEN=\${#$1} + if [ $TLEN -gt 35 ] + then + printf "gen-install-script: %-20s := %.35s ...\n" $1 "$T" + else + printf "gen-install-script: %-20s := %s %s\n" $1 "$T" "$2" + fi +} + +valopt() { + VAL_OPTIONS="$VAL_OPTIONS $1" + + local OP=$1 + local DEFAULT=$2 + shift + shift + local DOC="$*" + if [ $HELP -eq 0 ] + then + local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_') + local V="CFG_${UOP}" + eval $V="$DEFAULT" + for arg in $CFG_ARGS + do + if echo "$arg" | grep -q -- "--$OP=" + then + val=$(echo "$arg" | cut -f2 -d=) + eval $V=$val + fi + done + putvar $V + else + if [ -z "$DEFAULT" ] + then + DEFAULT="" + fi + OP="${OP}=[${DEFAULT}]" + printf " --%-30s %s\n" "$OP" "$DOC" + fi +} + +opt() { + BOOL_OPTIONS="$BOOL_OPTIONS $1" + + local OP=$1 + local DEFAULT=$2 + shift + shift + local DOC="$*" + local FLAG="" + + if [ $DEFAULT -eq 0 ] + then + FLAG="enable" + else + FLAG="disable" + DOC="don't $DOC" + fi + + if [ $HELP -eq 0 ] + then + for arg in $CFG_ARGS + do + if [ "$arg" = "--${FLAG}-${OP}" ] + then + OP=$(echo $OP | tr 'a-z-' 'A-Z_') + FLAG=$(echo $FLAG | tr 'a-z' 'A-Z') + local V="CFG_${FLAG}_${OP}" + eval $V=1 + putvar $V + fi + done + else + if [ ! -z "$META" ] + then + OP="$OP=<$META>" + fi + printf " --%-30s %s\n" "$FLAG-$OP" "$DOC" + fi +} + +flag() { + BOOL_OPTIONS="$BOOL_OPTIONS $1" + + local OP=$1 + shift + local DOC="$*" + + if [ $HELP -eq 0 ] + then + for arg in $CFG_ARGS + do + if [ "$arg" = "--${OP}" ] + then + OP=$(echo $OP | tr 'a-z-' 'A-Z_') + local V="CFG_${OP}" + eval $V=1 + putvar $V + fi + done + else + if [ ! -z "$META" ] + then + OP="$OP=<$META>" + fi + printf " --%-30s %s\n" "$OP" "$DOC" + fi +} + +validate_opt () { + for arg in $CFG_ARGS + do + isArgValid=0 + for option in $BOOL_OPTIONS + do + if test --disable-$option = $arg + then + isArgValid=1 + fi + if test --enable-$option = $arg + then + isArgValid=1 + fi + if test --$option = $arg + then + isArgValid=1 + fi + done + for option in $VAL_OPTIONS + do + if echo "$arg" | grep -q -- "--$option=" + then + isArgValid=1 + fi + done + if [ "$arg" = "--help" ] + then + echo + echo "No more help available for Configure options," + echo "check the Wiki or join our IRC channel" + break + else + if test $isArgValid -eq 0 + then + err "Option '$arg' is not recognized" + fi + fi + done +} + +msg "looking for install programs" +msg + +need_cmd sed +need_cmd chmod +need_cmd cat + +CFG_SRC_DIR="$(cd $(dirname $0) && pwd)" +CFG_SELF="$0" +CFG_ARGS="$@" + +HELP=0 +if [ "$1" = "--help" ] +then + HELP=1 + shift + echo + echo "Usage: $CFG_SELF [options]" + echo + echo "Options:" + echo +else + step_msg "processing $CFG_SELF args" +fi + +valopt product-name "Product" "The name of the product, for display" +valopt verify-bin "program" "The command to run with --version to verify the install works" +valopt rel-manifest-dir "${CFG_VERIFY_BIN}lib" "The directory under lib/ where the manifest lives" +valopt success-message "Installed." "The string to print after successful installation" +valopt output-script "${CFG_SRC_DIR}/install.sh" "The name of the output script" + +if [ $HELP -eq 1 ] +then + echo + exit 0 +fi + +step_msg "validating $CFG_SELF args" +validate_opt + +# Replace dashes in the success message with spaces (our arg handling botches spaces) +CFG_SUCCESS_MESSAGE=`echo "$CFG_SUCCESS_MESSAGE" | sed "s/-/ /g"` + +SCRIPT_TEMPLATE=`cat "${CFG_SRC_DIR}/install-template.sh"` + +# Using /bin/echo because under sh emulation dash *seems* to escape \n, which screws up the template +SCRIPT=`/bin/echo "${SCRIPT_TEMPLATE}"` +SCRIPT=`/bin/echo "${SCRIPT}" | sed "s/%%TEMPLATE_PRODUCT_NAME%%/${CFG_PRODUCT_NAME}/"` +SCRIPT=`/bin/echo "${SCRIPT}" | sed "s/%%TEMPLATE_VERIFY_BIN%%/${CFG_VERIFY_BIN}/"` +SCRIPT=`/bin/echo "${SCRIPT}" | sed "s/%%TEMPLATE_REL_MANIFEST_DIR%%/${CFG_REL_MANIFEST_DIR}/"` +SCRIPT=`/bin/echo "${SCRIPT}" | sed "s/%%TEMPLATE_SUCCESS_MESSAGE%%/\"${CFG_SUCCESS_MESSAGE}\"/"` + +/bin/echo "${SCRIPT}" > "${CFG_OUTPUT_SCRIPT}" +need_ok "couldn't write script" +chmod u+x "${CFG_OUTPUT_SCRIPT}" +need_ok "couldn't chmod script" diff --git a/src/tools/rust-installer/test/rust-installer-v2/test/rust-installer-v1/gen-installer.sh b/src/tools/rust-installer/test/rust-installer-v2/test/rust-installer-v1/gen-installer.sh new file mode 100755 index 0000000000..c88eebee98 --- /dev/null +++ b/src/tools/rust-installer/test/rust-installer-v2/test/rust-installer-v1/gen-installer.sh @@ -0,0 +1,303 @@ +#!/bin/sh +# Copyright 2014 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +msg() { + echo "gen-installer: $1" +} + +step_msg() { + msg + msg "$1" + msg +} + +warn() { + echo "gen-installer: WARNING: $1" +} + +err() { + echo "gen-installer: error: $1" + exit 1 +} + +need_ok() { + if [ $? -ne 0 ] + then + err "$1" + fi +} + +need_cmd() { + if command -v $1 >/dev/null 2>&1 + then msg "found $1" + else err "need $1" + fi +} + +putvar() { + local T + eval T=\$$1 + eval TLEN=\${#$1} + if [ $TLEN -gt 35 ] + then + printf "gen-installer: %-20s := %.35s ...\n" $1 "$T" + else + printf "gen-installer: %-20s := %s %s\n" $1 "$T" "$2" + fi +} + +valopt() { + VAL_OPTIONS="$VAL_OPTIONS $1" + + local OP=$1 + local DEFAULT=$2 + shift + shift + local DOC="$*" + if [ $HELP -eq 0 ] + then + local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_') + local V="CFG_${UOP}" + eval $V="$DEFAULT" + for arg in $CFG_ARGS + do + if echo "$arg" | grep -q -- "--$OP=" + then + val=$(echo "$arg" | cut -f2 -d=) + eval $V=$val + fi + done + putvar $V + else + if [ -z "$DEFAULT" ] + then + DEFAULT="" + fi + OP="${OP}=[${DEFAULT}]" + printf " --%-30s %s\n" "$OP" "$DOC" + fi +} + +opt() { + BOOL_OPTIONS="$BOOL_OPTIONS $1" + + local OP=$1 + local DEFAULT=$2 + shift + shift + local DOC="$*" + local FLAG="" + + if [ $DEFAULT -eq 0 ] + then + FLAG="enable" + else + FLAG="disable" + DOC="don't $DOC" + fi + + if [ $HELP -eq 0 ] + then + for arg in $CFG_ARGS + do + if [ "$arg" = "--${FLAG}-${OP}" ] + then + OP=$(echo $OP | tr 'a-z-' 'A-Z_') + FLAG=$(echo $FLAG | tr 'a-z' 'A-Z') + local V="CFG_${FLAG}_${OP}" + eval $V=1 + putvar $V + fi + done + else + if [ ! -z "$META" ] + then + OP="$OP=<$META>" + fi + printf " --%-30s %s\n" "$FLAG-$OP" "$DOC" + fi +} + +flag() { + BOOL_OPTIONS="$BOOL_OPTIONS $1" + + local OP=$1 + shift + local DOC="$*" + + if [ $HELP -eq 0 ] + then + for arg in $CFG_ARGS + do + if [ "$arg" = "--${OP}" ] + then + OP=$(echo $OP | tr 'a-z-' 'A-Z_') + local V="CFG_${OP}" + eval $V=1 + putvar $V + fi + done + else + if [ ! -z "$META" ] + then + OP="$OP=<$META>" + fi + printf " --%-30s %s\n" "$OP" "$DOC" + fi +} + +validate_opt () { + for arg in $CFG_ARGS + do + isArgValid=0 + for option in $BOOL_OPTIONS + do + if test --disable-$option = $arg + then + isArgValid=1 + fi + if test --enable-$option = $arg + then + isArgValid=1 + fi + if test --$option = $arg + then + isArgValid=1 + fi + done + for option in $VAL_OPTIONS + do + if echo "$arg" | grep -q -- "--$option=" + then + isArgValid=1 + fi + done + if [ "$arg" = "--help" ] + then + echo + echo "No more help available for Configure options," + echo "check the Wiki or join our IRC channel" + break + else + if test $isArgValid -eq 0 + then + err "Option '$arg' is not recognized" + fi + fi + done +} + +msg "looking for programs" +msg + +need_cmd tar +need_cmd cp +need_cmd rm +need_cmd mkdir +need_cmd echo +need_cmd tr + +CFG_SRC_DIR="$(cd $(dirname $0) && pwd)" +CFG_SELF="$0" +CFG_ARGS="$@" + +HELP=0 +if [ "$1" = "--help" ] +then + HELP=1 + shift + echo + echo "Usage: $CFG_SELF [options]" + echo + echo "Options:" + echo +else + step_msg "processing $CFG_SELF args" +fi + +valopt product-name "Product" "The name of the product, for display" +valopt package-name "package" "The name of the package, tarball" +valopt verify-bin "program" "The command to run with --version to verify the install works" +valopt rel-manifest-dir "${CFG_VERIFY_BIN}lib" "The directory under lib/ where the manifest lives" +valopt success-message "Installed." "The string to print after successful installation" +valopt non-installed-prefixes "" "Path prefixes that should be included but not installed" +valopt image-dir "./install-image" "The directory containing the installation medium" +valopt work-dir "./workdir" "The directory to do temporary work" +valopt output-dir "./dist" "The location to put the final image and tarball" +opt tarball 1 "Disable tarball generation, leaving output in the temp dir" + +if [ $HELP -eq 1 ] +then + echo + exit 0 +fi + +step_msg "validating $CFG_SELF args" +validate_opt + +GEN_INSTALL_SCRIPT="$CFG_SRC_DIR/gen-install-script.sh" + +if [ ! -d "$CFG_IMAGE_DIR" ] +then + err "image dir $CFG_IMAGE_DIR does not exist" +fi + +mkdir -p "$CFG_WORK_DIR" +need_ok "couldn't create work dir" + +rm -Rf "$CFG_WORK_DIR/$CFG_PACKAGE_NAME" +need_ok "couldn't delete work package dir" + +mkdir -p "$CFG_WORK_DIR/$CFG_PACKAGE_NAME" +need_ok "couldn't create work package dir" + +cp -r "$CFG_IMAGE_DIR/"* "$CFG_WORK_DIR/$CFG_PACKAGE_NAME" +need_ok "couldn't copy source image" + +# Split non_installed_files into lines for later iteration +NON_INSTALLED_PREFIXES=`echo "$CFG_NON_INSTALLED_PREFIXES" | tr "," "\n"` + +# Create the manifest +MANIFEST=`(cd "$CFG_WORK_DIR/$CFG_PACKAGE_NAME" && find . -type f | sed 's/^\.\///') | sort` + +# Remove non-installed files from manifest +NON_INSTALLED_PREFIXES=`echo "$CFG_NON_INSTALLED_PREFIXES" | tr "," " "` +for prefix in $NON_INSTALLED_PREFIXES; do + MANIFEST=`echo "$MANIFEST" | sed /^$prefix/d` +done + +MANIFEST_NAME="$CFG_WORK_DIR/$CFG_PACKAGE_NAME/lib/$CFG_REL_MANIFEST_DIR/manifest.in" + +mkdir -p "$CFG_WORK_DIR/$CFG_PACKAGE_NAME/lib/$CFG_REL_MANIFEST_DIR" +need_ok "couldn't create manifest dir" + +# Write the manifest +echo "$MANIFEST" > "$MANIFEST_NAME" + +# Generate the install script +"$CFG_SRC_DIR/gen-install-script.sh" \ + --product-name="$CFG_PRODUCT_NAME" \ + --verify-bin="$CFG_VERIFY_BIN" \ + --rel-manifest-dir="$CFG_REL_MANIFEST_DIR" \ + --success-message="$CFG_SUCCESS_MESSAGE" \ + --output-script="$CFG_WORK_DIR/$CFG_PACKAGE_NAME/install.sh" + +need_ok "failed to generate install script" + +mkdir -p "$CFG_OUTPUT_DIR" +need_ok "couldn't create output dir" + +rm -Rf "$CFG_OUTPUT_DIR/$CFG_PACKAGE_NAME.tar.gz" +need_ok "couldn't delete old tarball" + +# Make a tarball +tar -czf "$CFG_OUTPUT_DIR/$CFG_PACKAGE_NAME.tar.gz" -C "$CFG_WORK_DIR" "$CFG_PACKAGE_NAME" +need_ok "failed to tar" diff --git a/src/tools/rust-installer/test/rust-installer-v2/test/rust-installer-v1/install-template.sh b/src/tools/rust-installer/test/rust-installer-v2/test/rust-installer-v1/install-template.sh new file mode 100644 index 0000000000..545de670d5 --- /dev/null +++ b/src/tools/rust-installer/test/rust-installer-v2/test/rust-installer-v1/install-template.sh @@ -0,0 +1,554 @@ +#!/bin/sh +# Copyright 2014 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +msg() { + echo "install: $1" +} + +step_msg() { + msg + msg "$1" + msg +} + +warn() { + echo "install: WARNING: $1" +} + +err() { + echo "install: error: $1" + exit 1 +} + +need_ok() { + if [ $? -ne 0 ] + then + err "$1" + fi +} + +need_cmd() { + if command -v $1 >/dev/null 2>&1 + then msg "found $1" + else err "need $1" + fi +} + +putvar() { + local T + eval T=\$$1 + eval TLEN=\${#$1} + if [ $TLEN -gt 35 ] + then + printf "install: %-20s := %.35s ...\n" $1 "$T" + else + printf "install: %-20s := %s %s\n" $1 "$T" "$2" + fi +} + +valopt() { + VAL_OPTIONS="$VAL_OPTIONS $1" + + local OP=$1 + local DEFAULT=$2 + shift + shift + local DOC="$*" + if [ $HELP -eq 0 ] + then + local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_') + local V="CFG_${UOP}" + eval $V="$DEFAULT" + for arg in $CFG_ARGS + do + if echo "$arg" | grep -q -- "--$OP=" + then + val=$(echo "$arg" | cut -f2 -d=) + eval $V=$val + fi + done + putvar $V + else + if [ -z "$DEFAULT" ] + then + DEFAULT="" + fi + OP="${OP}=[${DEFAULT}]" + printf " --%-30s %s\n" "$OP" "$DOC" + fi +} + +opt() { + BOOL_OPTIONS="$BOOL_OPTIONS $1" + + local OP=$1 + local DEFAULT=$2 + shift + shift + local DOC="$*" + local FLAG="" + + if [ $DEFAULT -eq 0 ] + then + FLAG="enable" + else + FLAG="disable" + DOC="don't $DOC" + fi + + if [ $HELP -eq 0 ] + then + for arg in $CFG_ARGS + do + if [ "$arg" = "--${FLAG}-${OP}" ] + then + OP=$(echo $OP | tr 'a-z-' 'A-Z_') + FLAG=$(echo $FLAG | tr 'a-z' 'A-Z') + local V="CFG_${FLAG}_${OP}" + eval $V=1 + putvar $V + fi + done + else + if [ ! -z "$META" ] + then + OP="$OP=<$META>" + fi + printf " --%-30s %s\n" "$FLAG-$OP" "$DOC" + fi +} + +flag() { + BOOL_OPTIONS="$BOOL_OPTIONS $1" + + local OP=$1 + shift + local DOC="$*" + + if [ $HELP -eq 0 ] + then + for arg in $CFG_ARGS + do + if [ "$arg" = "--${OP}" ] + then + OP=$(echo $OP | tr 'a-z-' 'A-Z_') + local V="CFG_${OP}" + eval $V=1 + putvar $V + fi + done + else + if [ ! -z "$META" ] + then + OP="$OP=<$META>" + fi + printf " --%-30s %s\n" "$OP" "$DOC" + fi +} + +validate_opt () { + for arg in $CFG_ARGS + do + isArgValid=0 + for option in $BOOL_OPTIONS + do + if test --disable-$option = $arg + then + isArgValid=1 + fi + if test --enable-$option = $arg + then + isArgValid=1 + fi + if test --$option = $arg + then + isArgValid=1 + fi + done + for option in $VAL_OPTIONS + do + if echo "$arg" | grep -q -- "--$option=" + then + isArgValid=1 + fi + done + if [ "$arg" = "--help" ] + then + echo + echo "No more help available for Configure options," + echo "check the Wiki or join our IRC channel" + break + else + if test $isArgValid -eq 0 + then + err "Option '$arg' is not recognized" + fi + fi + done +} + +absolutify() { + FILE_PATH="${1}" + FILE_PATH_DIRNAME="$(dirname ${FILE_PATH})" + FILE_PATH_BASENAME="$(basename ${FILE_PATH})" + FILE_ABS_PATH="$(cd ${FILE_PATH_DIRNAME} && pwd)" + FILE_PATH="${FILE_ABS_PATH}/${FILE_PATH_BASENAME}" + # This is the return value + ABSOLUTIFIED="${FILE_PATH}" +} + +msg "looking for install programs" +msg + +need_cmd mkdir +need_cmd printf +need_cmd cut +need_cmd grep +need_cmd uname +need_cmd tr +need_cmd sed + +CFG_SRC_DIR="$(cd $(dirname $0) && pwd)" +CFG_SELF="$0" +CFG_ARGS="$@" + +HELP=0 +if [ "$1" = "--help" ] +then + HELP=1 + shift + echo + echo "Usage: $CFG_SELF [options]" + echo + echo "Options:" + echo +else + step_msg "processing $CFG_SELF args" +fi + +# Check for mingw or cygwin in order to special case $CFG_LIBDIR_RELATIVE. +# This logic is duplicated from configure in order to get the correct libdir +# for Windows installs. +CFG_OSTYPE=$(uname -s) + +case $CFG_OSTYPE in + + Linux) + CFG_OSTYPE=unknown-linux-gnu + ;; + + FreeBSD) + CFG_OSTYPE=unknown-freebsd + ;; + + DragonFly) + CFG_OSTYPE=unknown-dragonfly + ;; + + Darwin) + CFG_OSTYPE=apple-darwin + ;; + + MINGW*) + # msys' `uname` does not print gcc configuration, but prints msys + # configuration. so we cannot believe `uname -m`: + # msys1 is always i686 and msys2 is always x86_64. + # instead, msys defines $MSYSTEM which is MINGW32 on i686 and + # MINGW64 on x86_64. + CFG_CPUTYPE=i686 + CFG_OSTYPE=pc-windows-gnu + if [ "$MSYSTEM" = MINGW64 ] + then + CFG_CPUTYPE=x86_64 + fi + ;; + + MSYS*) + CFG_OSTYPE=pc-windows-gnu + ;; + +# Thad's Cygwin identifers below + +# Vista 32 bit + CYGWIN_NT-6.0) + CFG_OSTYPE=pc-windows-gnu + CFG_CPUTYPE=i686 + ;; + +# Vista 64 bit + CYGWIN_NT-6.0-WOW64) + CFG_OSTYPE=pc-windows-gnu + CFG_CPUTYPE=x86_64 + ;; + +# Win 7 32 bit + CYGWIN_NT-6.1) + CFG_OSTYPE=pc-windows-gnu + CFG_CPUTYPE=i686 + ;; + +# Win 7 64 bit + CYGWIN_NT-6.1-WOW64) + CFG_OSTYPE=pc-windows-gnu + CFG_CPUTYPE=x86_64 + ;; +esac + +OPTIONS="" +BOOL_OPTIONS="" +VAL_OPTIONS="" + +if [ "$CFG_OSTYPE" = "pc-windows-gnu" ] +then + CFG_LD_PATH_VAR=PATH + CFG_OLD_LD_PATH_VAR=$PATH +elif [ "$CFG_OSTYPE" = "apple-darwin" ] +then + CFG_LD_PATH_VAR=DYLD_LIBRARY_PATH + CFG_OLD_LD_PATH_VAR=$DYLD_LIBRARY_PATH +else + CFG_LD_PATH_VAR=LD_LIBRARY_PATH + CFG_OLD_LD_PATH_VAR=$LD_LIBRARY_PATH +fi + +flag uninstall "only uninstall from the installation prefix" +valopt destdir "" "set installation root" +opt verify 1 "verify that the installed binaries run correctly" +valopt prefix "/usr/local" "set installation prefix" +# NB This isn't quite the same definition as in `configure`. +# just using 'lib' instead of configure's CFG_LIBDIR_RELATIVE +valopt libdir "${CFG_DESTDIR}${CFG_PREFIX}/lib" "install libraries" +valopt mandir "${CFG_DESTDIR}${CFG_PREFIX}/share/man" "install man pages in PATH" + +if [ $HELP -eq 1 ] +then + echo + exit 0 +fi + +step_msg "validating $CFG_SELF args" +validate_opt + + + +# Template configuration. +# These names surrounded by '%%` are replaced by sed when generating install.sh + +# Rust or Cargo +TEMPLATE_PRODUCT_NAME=%%TEMPLATE_PRODUCT_NAME%% +# rustc or cargo +TEMPLATE_VERIFY_BIN=%%TEMPLATE_VERIFY_BIN%% +# rustlib or cargo +TEMPLATE_REL_MANIFEST_DIR=%%TEMPLATE_REL_MANIFEST_DIR%% +# 'Rust is ready to roll.' or 'Cargo is cool to cruise.' +TEMPLATE_SUCCESS_MESSAGE=%%TEMPLATE_SUCCESS_MESSAGE%% + +# OK, let's get installing ... + +# Sanity check: can we run the binaries? +if [ -z "${CFG_DISABLE_VERIFY}" ] +then + # Don't do this if uninstalling. Failure here won't help in any way. + if [ -z "${CFG_UNINSTALL}" ] + then + msg "verifying platform can run binaries" + export $CFG_LD_PATH_VAR="${CFG_SRC_DIR}/lib:$CFG_OLD_LD_PATH_VAR" + "${CFG_SRC_DIR}/bin/${TEMPLATE_VERIFY_BIN}" --version 2> /dev/null 1> /dev/null + if [ $? -ne 0 ] + then + err "can't execute rustc binary on this platform" + fi + export $CFG_LD_PATH_VAR="$CFG_OLD_LD_PATH_VAR" + fi +fi + +# Sanity check: can we can write to the destination? +msg "verifying destination is writable" +umask 022 && mkdir -p "${CFG_LIBDIR}" +need_ok "can't write to destination. consider \`sudo\`." +touch "${CFG_LIBDIR}/rust-install-probe" > /dev/null +if [ $? -ne 0 ] +then + err "can't write to destination. consider \`sudo\`." +fi +rm -f "${CFG_LIBDIR}/rust-install-probe" +need_ok "failed to remove install probe" + +# Sanity check: don't install to the directory containing the installer. +# That would surely cause chaos. +msg "verifying destination is not the same as source" +INSTALLER_DIR="$(cd $(dirname $0) && pwd)" +PREFIX_DIR="$(cd ${CFG_PREFIX} && pwd)" +if [ "${INSTALLER_DIR}" = "${PREFIX_DIR}" ] +then + err "can't install to same directory as installer" +fi + +# Using an absolute path to libdir in a few places so that the status +# messages are consistently using absolute paths. +absolutify "${CFG_LIBDIR}" +ABS_LIBDIR="${ABSOLUTIFIED}" + +# The file name of the manifest we're going to create during install +INSTALLED_MANIFEST="${ABS_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}/manifest" + +# First, uninstall from the installation prefix. +# Errors are warnings - try to rm everything in the manifest even if some fail. +if [ -f "${INSTALLED_MANIFEST}" ] +then + msg + + # Iterate through installed manifest and remove files + while read p; do + # The installed manifest contains absolute paths + msg "removing $p" + if [ -f "$p" ] + then + rm -f "$p" + if [ $? -ne 0 ] + then + warn "failed to remove $p" + fi + else + warn "supposedly installed file $p does not exist!" + fi + done < "${INSTALLED_MANIFEST}" + + # If we fail to remove $TEMPLATE_REL_MANIFEST_DIR below, then the + # installed manifest will still be full; the installed manifest + # needs to be empty before install. + msg "removing ${INSTALLED_MANIFEST}" + rm -f "${INSTALLED_MANIFEST}" + # For the above reason, this is a hard error + need_ok "failed to remove installed manifest" + + # Remove $TEMPLATE_REL_MANIFEST_DIR directory + msg "removing ${ABS_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}" + rm -Rf "${ABS_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}" + if [ $? -ne 0 ] + then + warn "failed to remove ${TEMPLATE_REL_MANIFEST_DIR}" + fi +else + # There's no manifest. If we were asked to uninstall, then that's a problem. + if [ -n "${CFG_UNINSTALL}" ] + then + err "unable to find installation manifest at ${CFG_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}" + fi +fi + +# If we're only uninstalling then exit +if [ -n "${CFG_UNINSTALL}" ] +then + echo + echo " ${TEMPLATE_PRODUCT_NAME} is uninstalled." + echo + exit 0 +fi + +# Create the installed manifest, which we will fill in with absolute file paths +mkdir -p "${CFG_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}" +need_ok "failed to create ${TEMPLATE_REL_MANIFEST_DIR}" +touch "${INSTALLED_MANIFEST}" +need_ok "failed to create installed manifest" + +msg + +# Now install, iterate through the new manifest and copy files +while read p; do + + # Decide the destination of the file + FILE_INSTALL_PATH="${CFG_DESTDIR}${CFG_PREFIX}/$p" + + if echo "$p" | grep "^lib/" > /dev/null + then + pp=`echo $p | sed 's/^lib\///'` + FILE_INSTALL_PATH="${CFG_LIBDIR}/$pp" + fi + + if echo "$p" | grep "^share/man/" > /dev/null + then + pp=`echo $p | sed 's/^share\/man\///'` + FILE_INSTALL_PATH="${CFG_MANDIR}/$pp" + fi + + # Make sure there's a directory for it + umask 022 && mkdir -p "$(dirname ${FILE_INSTALL_PATH})" + need_ok "directory creation failed" + + # Make the path absolute so we can uninstall it later without + # starting from the installation cwd + absolutify "${FILE_INSTALL_PATH}" + FILE_INSTALL_PATH="${ABSOLUTIFIED}" + + # Install the file + msg "installing ${FILE_INSTALL_PATH}" + if echo "$p" | grep "^bin/" > /dev/null + then + install -m755 "${CFG_SRC_DIR}/$p" "${FILE_INSTALL_PATH}" + else + install -m644 "${CFG_SRC_DIR}/$p" "${FILE_INSTALL_PATH}" + fi + need_ok "file creation failed" + + # Update the manifest + echo "${FILE_INSTALL_PATH}" >> "${INSTALLED_MANIFEST}" + need_ok "failed to update manifest" + +# The manifest lists all files to install +done < "${CFG_SRC_DIR}/lib/${TEMPLATE_REL_MANIFEST_DIR}/manifest.in" + +msg + +# Run ldconfig to make dynamic libraries available to the linker +if [ "$CFG_OSTYPE" = "unknown-linux-gnu" ] + then + ldconfig + if [ $? -ne 0 ] + then + warn "failed to run ldconfig." + warn "this may happen when not installing as root and may be fine" + fi +fi + +# Sanity check: can we run the installed binaries? +# +# As with the verification above, make sure the right LD_LIBRARY_PATH-equivalent +# is in place. Try first without this variable, and if that fails try again with +# the variable. If the second time tries, print a hopefully helpful message to +# add something to the appropriate environment variable. +if [ -z "${CFG_DISABLE_VERIFY}" ] +then + msg "verifying installed binaries are executable" + "${CFG_PREFIX}/bin/${TEMPLATE_VERIFY_BIN}" --version 2> /dev/null 1> /dev/null + if [ $? -ne 0 ] + then + export $CFG_LD_PATH_VAR="${CFG_PREFIX}/lib:$CFG_OLD_LD_PATH_VAR" + "${CFG_PREFIX}/bin/${TEMPLATE_VERIFY_BIN}" --version > /dev/null + if [ $? -ne 0 ] + then + ERR="can't execute installed binaries. " + ERR="${ERR}installation may be broken. " + ERR="${ERR}if this is expected then rerun install.sh with \`--disable-verify\` " + ERR="${ERR}or \`make install\` with \`--disable-verify-install\`" + err "${ERR}" + else + echo + echo " Note: please ensure '${CFG_PREFIX}/lib' is added to ${CFG_LD_PATH_VAR}" + fi + fi +fi + +echo +echo " ${TEMPLATE_SUCCESS_MESSAGE}" +echo + + diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml index 2d5d163d40..e759e0bc13 100644 --- a/src/tools/rustbook/Cargo.toml +++ b/src/tools/rustbook/Cargo.toml @@ -5,8 +5,8 @@ version = "0.1.0" license = "MIT/Apache-2.0" [dependencies] -clap = "2.19.3" +clap = "2.25.0" [dependencies.mdbook] -version = "0.0.21" +version = "0.0.22" default-features = false diff --git a/src/tools/tidy/src/cargo.rs b/src/tools/tidy/src/cargo.rs index c8c6cb0ee6..f40fea60f4 100644 --- a/src/tools/tidy/src/cargo.rs +++ b/src/tools/tidy/src/cargo.rs @@ -91,14 +91,6 @@ fn verify(tomlfile: &Path, libfile: &Path, bad: &mut bool) { continue } - // We want the compiler to depend on the proc_macro_plugin crate so - // that it is built and included in the end, but we don't want to - // actually use it in the compiler. - if toml.contains("name = \"rustc_driver\"") && - krate == "proc_macro_plugin" { - continue - } - if !librs.contains(&format!("extern crate {}", krate)) { tidy_error!(bad, "{} doesn't have `extern crate {}`, but Cargo.toml \ depends on it", libfile.display(), krate); diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index ba02ee0c6d..8b7da2267c 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -32,7 +32,6 @@ static EXCEPTIONS: &'static [&'static str] = &[ "openssl", // BSD+advertising clause, cargo, mdbook "pest", // MPL2, mdbook via handlebars "thread-id", // Apache-2.0, mdbook - "strings", // this is actually MIT/Apache-2.0 but it's not in the manifest yet ]; pub fn check(path: &Path, bad: &mut bool) { diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index e34821e358..4c94ade98d 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -24,7 +24,7 @@ use std::fs::File; use std::io::prelude::*; use std::path::Path; -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum Status { Stable, Removed, @@ -42,18 +42,21 @@ impl fmt::Display for Status { } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Feature { pub level: Status, pub since: String, pub has_gate_test: bool, + pub tracking_issue: Option, } +pub type Features = HashMap; + pub fn check(path: &Path, bad: &mut bool, quiet: bool) { let mut features = collect_lang_features(path); assert!(!features.is_empty()); - let lib_features = collect_lib_features(path, bad, &features); + let lib_features = get_and_check_lib_features(path, bad, &features); assert!(!lib_features.is_empty()); let mut contents = String::new(); @@ -168,8 +171,7 @@ fn find_attr_val<'a>(line: &'a str, attr: &str) -> Option<&'a str> { .map(|(i, j)| &line[i..j]) } -fn test_filen_gate(filen_underscore: &str, - features: &mut HashMap) -> bool { +fn test_filen_gate(filen_underscore: &str, features: &mut Features) -> bool { if filen_underscore.starts_with("feature_gate") { for (n, f) in features.iter_mut() { if filen_underscore == format!("feature_gate_{}", n) { @@ -181,7 +183,7 @@ fn test_filen_gate(filen_underscore: &str, return false; } -pub fn collect_lang_features(base_src_path: &Path) -> HashMap { +pub fn collect_lang_features(base_src_path: &Path) -> Features { let mut contents = String::new(); let path = base_src_path.join("libsyntax/feature_gate.rs"); t!(t!(File::open(path)).read_to_string(&mut contents)); @@ -197,20 +199,79 @@ pub fn collect_lang_features(base_src_path: &Path) -> HashMap { }; let name = parts.next().unwrap().trim(); let since = parts.next().unwrap().trim().trim_matches('"'); + let issue_str = parts.next().unwrap().trim(); + let tracking_issue = if issue_str.starts_with("None") { + None + } else { + let s = issue_str.split("(").nth(1).unwrap().split(")").nth(0).unwrap(); + Some(s.parse().unwrap()) + }; Some((name.to_owned(), Feature { - level: level, + level, since: since.to_owned(), has_gate_test: false, + tracking_issue, })) }) .collect() } -pub fn collect_lib_features(base_src_path: &Path, - bad: &mut bool, - features: &HashMap) -> HashMap { - let mut lib_features = HashMap::::new(); +pub fn collect_lib_features(base_src_path: &Path) -> Features { + let mut lib_features = Features::new(); + map_lib_features(base_src_path, + &mut |res, _, _| { + match res { + Ok((name, feature)) => { + if lib_features.get(name).is_some() { + return; + } + lib_features.insert(name.to_owned(), feature); + }, + Err(_) => (), + } + }); + lib_features +} + +fn get_and_check_lib_features(base_src_path: &Path, + bad: &mut bool, + lang_features: &Features) -> Features { + let mut lib_features = Features::new(); + map_lib_features(base_src_path, + &mut |res, file, line| { + match res { + Ok((name, f)) => { + let mut err = |msg: &str| { + tidy_error!(bad, "{}:{}: {}", file.display(), line, msg); + }; + if lang_features.contains_key(name) && name != "proc_macro" { + err("duplicating a lang feature"); + } + if let Some(ref s) = lib_features.get(name) { + if s.level != f.level { + err("different stability level than before"); + } + if s.since != f.since { + err("different `since` than before"); + } + if s.tracking_issue != f.tracking_issue { + err("different `tracking_issue` than before"); + } + } + lib_features.insert(name.to_owned(), f); + }, + Err(msg) => { + tidy_error!(bad, "{}:{}: {}", file.display(), line, msg); + }, + } + + }); + lib_features +} + +fn map_lib_features(base_src_path: &Path, + mf: &mut FnMut(Result<(&str, Feature), &str>, &Path, usize)) { let mut contents = String::new(); super::walk(base_src_path, &mut |path| super::filter_dirs(path) || path.ends_with("src/test"), @@ -224,10 +285,35 @@ pub fn collect_lib_features(base_src_path: &Path, contents.truncate(0); t!(t!(File::open(&file), &file).read_to_string(&mut contents)); + let mut becoming_feature: Option<(String, Feature)> = None; for (i, line) in contents.lines().enumerate() { - let mut err = |msg: &str| { - tidy_error!(bad, "{}:{}: {}", file.display(), i + 1, msg); + macro_rules! err { + ($msg:expr) => {{ + mf(Err($msg), file, i + 1); + continue; + }}; }; + if let Some((ref name, ref mut f)) = becoming_feature { + if f.tracking_issue.is_none() { + f.tracking_issue = find_attr_val(line, "issue") + .map(|s| s.parse().unwrap()); + } + if line.ends_with("]") { + mf(Ok((name, f.clone())), file, i + 1); + } else if !line.ends_with(",") && !line.ends_with("\\") { + // We need to bail here because we might have missed the + // end of a stability attribute above because the "]" + // might not have been at the end of the line. + // We could then get into the very unfortunate situation that + // we continue parsing the file assuming the current stability + // attribute has not ended, and ignoring possible feature + // attributes in the process. + err!("malformed stability attribute"); + } else { + continue; + } + } + becoming_feature = None; let level = if line.contains("[unstable(") { Status::Unstable } else if line.contains("[stable(") { @@ -237,39 +323,28 @@ pub fn collect_lib_features(base_src_path: &Path, }; let feature_name = match find_attr_val(line, "feature") { Some(name) => name, - None => { - err("malformed stability attribute"); - continue; - } + None => err!("malformed stability attribute"), }; let since = match find_attr_val(line, "since") { Some(name) => name, None if level == Status::Stable => { - err("malformed stability attribute"); - continue; + err!("malformed stability attribute"); } None => "None", }; + let tracking_issue = find_attr_val(line, "issue").map(|s| s.parse().unwrap()); - if features.contains_key(feature_name) { - err("duplicating a lang feature"); - } - if let Some(ref s) = lib_features.get(feature_name) { - if s.level != level { - err("different stability level than before"); - } - if s.since != since { - err("different `since` than before"); - } - continue; + let feature = Feature { + level, + since: since.to_owned(), + has_gate_test: false, + tracking_issue, + }; + if line.contains("]") { + mf(Ok((feature_name, feature)), file, i + 1); + } else { + becoming_feature = Some((feature_name.to_owned(), feature)); } - lib_features.insert(feature_name.to_owned(), - Feature { - level: level, - since: since.to_owned(), - has_gate_test: false, - }); } }); - lib_features } diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs new file mode 100644 index 0000000000..020570e61d --- /dev/null +++ b/src/tools/tidy/src/lib.rs @@ -0,0 +1,89 @@ +// 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. + +//! Library used by tidy and other tools +//! +//! This library contains the tidy lints and exposes it +//! to be used by tools. + +#![deny(warnings)] + +use std::fs; + +use std::path::Path; + +macro_rules! t { + ($e:expr, $p:expr) => (match $e { + Ok(e) => e, + Err(e) => panic!("{} failed on {} with {}", stringify!($e), ($p).display(), e), + }); + + ($e:expr) => (match $e { + Ok(e) => e, + Err(e) => panic!("{} failed with {}", stringify!($e), e), + }) +} + +macro_rules! tidy_error { + ($bad:expr, $fmt:expr, $($arg:tt)*) => ({ + use std::io::Write; + *$bad = true; + write!(::std::io::stderr(), "tidy error: ").expect("could not write to stderr"); + writeln!(::std::io::stderr(), $fmt, $($arg)*).expect("could not write to stderr"); + }); +} + +pub mod bins; +pub mod style; +pub mod errors; +pub mod features; +pub mod cargo; +pub mod pal; +pub mod deps; +pub mod unstable_book; + +fn filter_dirs(path: &Path) -> bool { + let skip = [ + "src/jemalloc", + "src/llvm", + "src/libbacktrace", + "src/libcompiler_builtins", + "src/compiler-rt", + "src/rustllvm", + "src/liblibc", + "src/vendor", + "src/rt/hoedown", + "src/tools/cargo", + "src/tools/rls", + "src/tools/rust-installer", + ]; + skip.iter().any(|p| path.ends_with(p)) +} + +fn walk_many(paths: &[&Path], skip: &mut FnMut(&Path) -> bool, f: &mut FnMut(&Path)) { + for path in paths { + walk(path, skip, f); + } +} + +fn walk(path: &Path, skip: &mut FnMut(&Path) -> bool, f: &mut FnMut(&Path)) { + for entry in t!(fs::read_dir(path), path) { + let entry = t!(entry); + let kind = t!(entry.file_type()); + let path = entry.path(); + if kind.is_dir() { + if !skip(&path) { + walk(&path, skip, f); + } + } else { + f(&path); + } + } +} diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 23a31131f7..433192a21e 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -8,47 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Tidy checks for source code in this repository +//! Tidy checks source code in this repository //! //! This program runs all of the various tidy checks for style, cleanliness, //! etc. This is run by default on `make check` and as part of the auto //! builders. -use std::env; -use std::fs; -use std::io::{self, Write}; -use std::path::{PathBuf, Path}; -use std::process; +#![deny(warnings)] -macro_rules! t { - ($e:expr, $p:expr) => (match $e { - Ok(e) => e, - Err(e) => panic!("{} failed on {} with {}", stringify!($e), ($p).display(), e), - }); - - ($e:expr) => (match $e { - Ok(e) => e, - Err(e) => panic!("{} failed with {}", stringify!($e), e), - }) -} +extern crate tidy; +use tidy::*; -macro_rules! tidy_error { - ($bad:expr, $fmt:expr, $($arg:tt)*) => ({ - use std::io::Write; - *$bad = true; - write!(::std::io::stderr(), "tidy error: ").expect("could not write to stderr"); - writeln!(::std::io::stderr(), $fmt, $($arg)*).expect("could not write to stderr"); - }); -} - -mod bins; -mod style; -mod errors; -mod features; -mod cargo; -mod pal; -mod deps; -mod unstable_book; +use std::process; +use std::path::PathBuf; +use std::env; +use std::io::{self, Write}; fn main() { let path = env::args_os().skip(1).next().expect("need an argument"); @@ -74,41 +48,3 @@ fn main() { process::exit(1); } } - -fn filter_dirs(path: &Path) -> bool { - let skip = [ - "src/jemalloc", - "src/llvm", - "src/libbacktrace", - "src/compiler-rt", - "src/rustllvm", - "src/liblibc", - "src/vendor", - "src/rt/hoedown", - "src/tools/cargo", - "src/tools/rls", - "src/tools/rust-installer", - ]; - skip.iter().any(|p| path.ends_with(p)) -} - -fn walk_many(paths: &[&Path], skip: &mut FnMut(&Path) -> bool, f: &mut FnMut(&Path)) { - for path in paths { - walk(path, skip, f); - } -} - -fn walk(path: &Path, skip: &mut FnMut(&Path) -> bool, f: &mut FnMut(&Path)) { - for entry in t!(fs::read_dir(path), path) { - let entry = t!(entry); - let kind = t!(entry.file_type()); - let path = entry.path(); - if kind.is_dir() { - if !skip(&path) { - walk(&path, skip, f); - } - } else { - f(&path); - } - } -} diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 8bf683de87..b42beb3782 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -18,6 +18,7 @@ //! * No CR characters //! * No `TODO` or `XXX` directives //! * A valid license header is at the top +//! * No unexplained ` ```ignore ` or ` ```rust,ignore ` doc tests //! //! A number of these checks can be opted-out of with various directives like //! `// ignore-tidy-linelength`. @@ -38,6 +39,17 @@ http://www.apache.org/licenses/LICENSE-2.0> or the MIT license option. This file may not be copied, modified, or distributed except according to those terms."; +const UNEXPLAINED_IGNORE_DOCTEST_INFO: &str = r#"unexplained "```ignore" doctest; try one: + +* make the test actually pass, by adding necessary imports and declarations, or +* use "```text", if the code is not Rust code, or +* use "```compile_fail,Ennnn", if the code is expected to fail at compile time, or +* use "```should_panic", if the code is expected to fail at run time, or +* use "```no_run", if the code should type-check but not necessary linkable/runnable, or +* explain it like "```ignore (cannot-test-this-because-xxxx)", if the annotation cannot be avoided. + +"#; + /// Parser states for line_is_url. #[derive(PartialEq)] #[allow(non_camel_case_types)] @@ -101,9 +113,6 @@ pub fn check(path: &Path, bad: &mut bool) { filename.starts_with(".#") { return } - if filename == "miniz.c" { - return - } contents.truncate(0); t!(t!(File::open(file), file).read_to_string(&mut contents)); @@ -141,6 +150,9 @@ pub fn check(path: &Path, bad: &mut bool) { err("XXX is deprecated; use FIXME") } } + if line.ends_with("```ignore") || line.ends_with("```rust,ignore") { + err(UNEXPLAINED_IGNORE_DOCTEST_INFO); + } } if !licenseck(file, &contents) { tidy_error!(bad, "{}: incorrect license", file.display()); @@ -169,8 +181,10 @@ fn licenseck(file: &Path, contents: &str) -> bool { lines.windows(LICENSE.lines().count()).any(|window| { let offset = if window.iter().all(|w| w.starts_with("//")) { 2 - } else if window.iter().all(|w| w.starts_with("#")) { + } else if window.iter().all(|w| w.starts_with('#')) { 1 + } else if window.iter().all(|w| w.starts_with(" *")) { + 2 } else { return false }; diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs index 5a6524b3e8..ff032b14ad 100644 --- a/src/tools/tidy/src/unstable_book.rs +++ b/src/tools/tidy/src/unstable_book.rs @@ -8,29 +8,31 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::collections::HashSet; +use std::collections::BTreeSet; use std::fs; use std::path; -use features::{collect_lang_features, collect_lib_features, Status}; +use features::{collect_lang_features, collect_lib_features, Features, Status}; -const PATH_STR: &'static str = "doc/unstable-book/src"; +pub const PATH_STR: &str = "doc/unstable-book/src"; -const LANG_FEATURES_DIR: &'static str = "language-features"; +pub const COMPILER_FLAGS_DIR: &str = "compiler-flags"; -const LIB_FEATURES_DIR: &'static str = "library-features"; +pub const LANG_FEATURES_DIR: &str = "language-features"; + +pub const LIB_FEATURES_DIR: &str = "library-features"; /// Build the path to the Unstable Book source directory from the Rust 'src' directory -fn unstable_book_path(base_src_path: &path::Path) -> path::PathBuf { +pub fn unstable_book_path(base_src_path: &path::Path) -> path::PathBuf { base_src_path.join(PATH_STR) } /// Directory where the features are documented within the Unstable Book source directory -fn unstable_book_lang_features_path(base_src_path: &path::Path) -> path::PathBuf { +pub fn unstable_book_lang_features_path(base_src_path: &path::Path) -> path::PathBuf { unstable_book_path(base_src_path).join(LANG_FEATURES_DIR) } /// Directory where the features are documented within the Unstable Book source directory -fn unstable_book_lib_features_path(base_src_path: &path::Path) -> path::PathBuf { +pub fn unstable_book_lib_features_path(base_src_path: &path::Path) -> path::PathBuf { unstable_book_path(base_src_path).join(LIB_FEATURES_DIR) } @@ -42,27 +44,16 @@ fn dir_entry_is_file(dir_entry: &fs::DirEntry) -> bool { .is_file() } -/// Retrieve names of all lang-related unstable features -fn collect_unstable_lang_feature_names(base_src_path: &path::Path) -> HashSet { - collect_lang_features(base_src_path) - .into_iter() - .filter(|&(_, ref f)| f.level == Status::Unstable) - .map(|(ref name, _)| name.to_owned()) - .collect() -} - -/// Retrieve names of all lib-related unstable features -fn collect_unstable_lib_feature_names(base_src_path: &path::Path) -> HashSet { - let mut bad = true; - let lang_features = collect_lang_features(base_src_path); - collect_lib_features(base_src_path, &mut bad, &lang_features) - .into_iter() +/// Retrieve names of all unstable features +pub fn collect_unstable_feature_names(features: &Features) -> BTreeSet { + features + .iter() .filter(|&(_, ref f)| f.level == Status::Unstable) - .map(|(ref name, _)| name.to_owned()) + .map(|(name, _)| name.to_owned()) .collect() } -fn collect_unstable_book_section_file_names(dir: &path::Path) -> HashSet { +pub fn collect_unstable_book_section_file_names(dir: &path::Path) -> BTreeSet { fs::read_dir(dir) .expect("could not read directory") .into_iter() @@ -78,7 +69,7 @@ fn collect_unstable_book_section_file_names(dir: &path::Path) -> HashSet /// * hyphens replaced by underscores /// * the markdown suffix ('.md') removed fn collect_unstable_book_lang_features_section_file_names(base_src_path: &path::Path) - -> HashSet { + -> BTreeSet { collect_unstable_book_section_file_names(&unstable_book_lang_features_path(base_src_path)) } @@ -87,7 +78,7 @@ fn collect_unstable_book_lang_features_section_file_names(base_src_path: &path:: /// * hyphens replaced by underscores /// * the markdown suffix ('.md') removed fn collect_unstable_book_lib_features_section_file_names(base_src_path: &path::Path) - -> HashSet { + -> BTreeSet { collect_unstable_book_section_file_names(&unstable_book_lib_features_path(base_src_path)) } @@ -95,19 +86,13 @@ pub fn check(path: &path::Path, bad: &mut bool) { // Library features - let unstable_lib_feature_names = collect_unstable_lib_feature_names(path); + let lang_features = collect_lang_features(path); + let lib_features = collect_lib_features(path); + + let unstable_lib_feature_names = collect_unstable_feature_names(&lib_features); let unstable_book_lib_features_section_file_names = collect_unstable_book_lib_features_section_file_names(path); - // Check for unstable features that don't have Unstable Book sections - for feature_name in &unstable_lib_feature_names - - &unstable_book_lib_features_section_file_names { - tidy_error!(bad, - "Unstable library feature '{}' needs to have a section within the \ - 'library features' section of The Unstable Book", - feature_name); - } - // Check for Unstable Book sections that don't have a corresponding unstable feature for feature_name in &unstable_book_lib_features_section_file_names - &unstable_lib_feature_names { @@ -119,18 +104,10 @@ pub fn check(path: &path::Path, bad: &mut bool) { // Language features - let unstable_lang_feature_names = collect_unstable_lang_feature_names(path); + let unstable_lang_feature_names = collect_unstable_feature_names(&lang_features); let unstable_book_lang_features_section_file_names = collect_unstable_book_lang_features_section_file_names(path); - for feature_name in &unstable_lang_feature_names - - &unstable_book_lang_features_section_file_names { - tidy_error!(bad, - "Unstable language feature '{}' needs to have a section within the \ - 'language features' section of The Unstable Book", - feature_name); - } - // Check for Unstable Book sections that don't have a corresponding unstable feature for feature_name in &unstable_book_lang_features_section_file_names - &unstable_lang_feature_names { @@ -139,4 +116,20 @@ pub fn check(path: &path::Path, bad: &mut bool) { correspond to an unstable language feature", feature_name) } + + // List unstable features that don't have Unstable Book sections + // Remove the comment marker if you want the list printed + /* + println!("Lib features without unstable book sections:"); + for feature_name in &unstable_lang_feature_names - + &unstable_book_lang_features_section_file_names { + println!(" * {} {:?}", feature_name, lib_features[&feature_name].tracking_issue); + } + + println!("Lang features without unstable book sections:"); + for feature_name in &unstable_lib_feature_names- + &unstable_book_lib_features_section_file_names { + println!(" * {} {:?}", feature_name, lang_features[&feature_name].tracking_issue); + } + // */ } diff --git a/src/tools/unstable-book-gen/Cargo.toml b/src/tools/unstable-book-gen/Cargo.toml new file mode 100644 index 0000000000..4751a5e415 --- /dev/null +++ b/src/tools/unstable-book-gen/Cargo.toml @@ -0,0 +1,9 @@ +[package] +authors = ["est31 ", + "The Rust Project Developers"] +name = "unstable-book-gen" +version = "0.1.0" +license = "MIT/Apache-2.0" + +[dependencies] +tidy = { path = "../tidy" } diff --git a/src/tools/unstable-book-gen/src/SUMMARY.md b/src/tools/unstable-book-gen/src/SUMMARY.md new file mode 100644 index 0000000000..933c928e2f --- /dev/null +++ b/src/tools/unstable-book-gen/src/SUMMARY.md @@ -0,0 +1,8 @@ +[The Unstable Book](the-unstable-book.md) + +- [Compiler flags](compiler-flags.md) +{compiler_flags} +- [Language features](language-features.md) +{language_features} +- [Library Features](library-features.md) +{library_features} diff --git a/src/tools/unstable-book-gen/src/main.rs b/src/tools/unstable-book-gen/src/main.rs new file mode 100644 index 0000000000..5c2bd1e3e0 --- /dev/null +++ b/src/tools/unstable-book-gen/src/main.rs @@ -0,0 +1,148 @@ +// 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. + +//! Auto-generate stub docs for the unstable book + +#![deny(warnings)] + +extern crate tidy; + +use tidy::features::{Feature, Features, collect_lib_features, collect_lang_features}; +use tidy::unstable_book::{collect_unstable_feature_names, collect_unstable_book_section_file_names, + PATH_STR, LANG_FEATURES_DIR, LIB_FEATURES_DIR}; +use std::collections::BTreeSet; +use std::io::Write; +use std::fs::{self, File}; +use std::env; +use std::path::Path; + +/// A helper macro to `unwrap` a result except also print out details like: +/// +/// * The file/line of the panic +/// * The expression that failed +/// * The error itself +macro_rules! t { + ($e:expr) => (match $e { + Ok(e) => e, + Err(e) => panic!("{} failed with {}", stringify!($e), e), + }) +} + +fn generate_stub_issue(path: &Path, name: &str, issue: u32) { + let mut file = t!(File::create(path)); + t!(file.write_fmt(format_args!(include_str!("stub-issue.md"), + name = name, + issue = issue))); +} + +fn generate_stub_no_issue(path: &Path, name: &str) { + let mut file = t!(File::create(path)); + t!(file.write_fmt(format_args!(include_str!("stub-no-issue.md"), + name = name))); +} + +fn set_to_summary_str(set: &BTreeSet, dir: &str +) -> String { + set + .iter() + .map(|ref n| format!(" - [{}]({}/{}.md)", + n, + dir, + n.replace('_', "-"))) + .fold("".to_owned(), |s, a| s + &a + "\n") +} + +fn generate_summary(path: &Path, lang_features: &Features, lib_features: &Features) { + let compiler_flags = collect_unstable_book_section_file_names( + &path.join("compiler-flags")); + + let compiler_flags_str = set_to_summary_str(&compiler_flags, + "compiler-flags"); + + let unstable_lang_features = collect_unstable_feature_names(&lang_features); + let unstable_lib_features = collect_unstable_feature_names(&lib_features); + + let lang_features_str = set_to_summary_str(&unstable_lang_features, + LANG_FEATURES_DIR); + let lib_features_str = set_to_summary_str(&unstable_lib_features, + LIB_FEATURES_DIR); + + let mut file = t!(File::create(&path.join("SUMMARY.md"))); + t!(file.write_fmt(format_args!(include_str!("SUMMARY.md"), + compiler_flags = compiler_flags_str, + language_features = lang_features_str, + library_features = lib_features_str))); + +} + +fn has_valid_tracking_issue(f: &Feature) -> bool { + if let Some(n) = f.tracking_issue { + if n > 0 { + return true; + } + } + false +} + +fn generate_unstable_book_files(src :&Path, out: &Path, features :&Features) { + let unstable_features = collect_unstable_feature_names(features); + let unstable_section_file_names = collect_unstable_book_section_file_names(src); + t!(fs::create_dir_all(&out)); + for feature_name in &unstable_features - &unstable_section_file_names { + let file_name = format!("{}.md", feature_name.replace('_', "-")); + let out_file_path = out.join(&file_name); + let feature = &features[&feature_name]; + + if has_valid_tracking_issue(&feature) { + generate_stub_issue(&out_file_path, &feature_name, feature.tracking_issue.unwrap()); + } else { + generate_stub_no_issue(&out_file_path, &feature_name); + } + } +} + +fn copy_recursive(path: &Path, to: &Path) { + for entry in t!(fs::read_dir(path)) { + let e = t!(entry); + let t = t!(e.metadata()); + let dest = &to.join(e.file_name()); + if t.is_file() { + t!(fs::copy(&e.path(), dest)); + } else if t.is_dir() { + t!(fs::create_dir_all(dest)); + copy_recursive(&e.path(), dest); + } + } +} + +fn main() { + let src_path_str = env::args_os().skip(1).next().expect("source path required"); + let dest_path_str = env::args_os().skip(2).next().expect("destination path required"); + let src_path = Path::new(&src_path_str); + let dest_path = Path::new(&dest_path_str).join("src"); + + let lang_features = collect_lang_features(src_path); + let lib_features = collect_lib_features(src_path); + + let doc_src_path = src_path.join(PATH_STR); + + t!(fs::create_dir_all(&dest_path)); + + generate_unstable_book_files(&doc_src_path.join(LANG_FEATURES_DIR), + &dest_path.join(LANG_FEATURES_DIR), + &lang_features); + generate_unstable_book_files(&doc_src_path.join(LIB_FEATURES_DIR), + &dest_path.join(LIB_FEATURES_DIR), + &lib_features); + + copy_recursive(&doc_src_path, &dest_path); + + generate_summary(&dest_path, &lang_features, &lib_features); +} diff --git a/src/tools/unstable-book-gen/src/stub-issue.md b/src/tools/unstable-book-gen/src/stub-issue.md new file mode 100644 index 0000000000..8698fb7278 --- /dev/null +++ b/src/tools/unstable-book-gen/src/stub-issue.md @@ -0,0 +1,7 @@ +# `{name}` + +The tracking issue for this feature is: [#{issue}] + +[#{issue}]: https://github.com/rust-lang/rust/issues/{issue} + +------------------------ diff --git a/src/tools/unstable-book-gen/src/stub-no-issue.md b/src/tools/unstable-book-gen/src/stub-no-issue.md new file mode 100644 index 0000000000..3da140633d --- /dev/null +++ b/src/tools/unstable-book-gen/src/stub-no-issue.md @@ -0,0 +1,5 @@ +# `{name}` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ diff --git a/src/vendor/atty/.cargo-checksum.json b/src/vendor/atty/.cargo-checksum.json new file mode 100644 index 0000000000..910e34a5e1 --- /dev/null +++ b/src/vendor/atty/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"7a3d49ec6b768c90a70ae9c97fdcda96f90849b3e38164db8d3239f79a53c3e4",".travis.yml":"4752c993a36dc8b271f25998b2c0b34af65f82fb61f7d71d0e34612a8a7cd5b0","CHANGELOG.md":"a182831141a059342664a8aaf40b9fd7828e8004094fb42e1b17129a090899ec","Cargo.toml":"5fa1586ac82ee945f057b87c81acae6e588de2303536445b4a766028633347e0","LICENSE":"235760c32039b0a6b23207918b71c1aa5d8318ee651c0f245d290ba1f47631cf","README.md":"b23f66e15c8311e11cbc3b10bfc87a7cb10bc4d758c6a352b155127b48b970d7","appveyor.yml":"dfe3d3eddd762a3cc76174e03ea91c93f544ce7fa05fbca4975f1624757d65e4","examples/atty.rs":"1551387a71474d9ac1b5153231f884e9e05213badcfaa3494ad2cb7ea958374a","src/lib.rs":"4530fe39e123b042eb023e4cf98a81d5184d06c938d3604b002f418101beb524"},"package":"d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159"} \ No newline at end of file diff --git a/src/vendor/toml-0.3.2/.cargo-ok b/src/vendor/atty/.cargo-ok similarity index 100% rename from src/vendor/toml-0.3.2/.cargo-ok rename to src/vendor/atty/.cargo-ok diff --git a/src/vendor/atty/.gitignore b/src/vendor/atty/.gitignore new file mode 100644 index 0000000000..afc9901273 --- /dev/null +++ b/src/vendor/atty/.gitignore @@ -0,0 +1,3 @@ +target +Cargo.lock +*.bk diff --git a/src/vendor/atty/.travis.yml b/src/vendor/atty/.travis.yml new file mode 100644 index 0000000000..46e22162ab --- /dev/null +++ b/src/vendor/atty/.travis.yml @@ -0,0 +1,44 @@ +sudo: false +language: rust +matrix: + fast_finish: true + include: + - rust: nightly + - rust: beta + - rust: stable + - rust: 1.8.0 +os: + - linux + - osx +script: + - cargo build + - cargo test +cache: + apt: true + directories: + - target/debug/deps + - target/debug/build +addons: + apt: + packages: + - libcurl4-openssl-dev + - libelf-dev + - libdw-dev + - binutils-dev # required for `kcov --verify` + - libbfd-dev # required for `kcov --verify` +after_success: | + [ $TRAVIS_RUST_VERSION = stable ] && + wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz && + tar xzf master.tar.gz && mkdir kcov-master/build && cd kcov-master/build && cmake .. && make && make install DESTDIR=../tmp && cd ../.. && + ls target/debug && + ./kcov-master/tmp/usr/local/bin/kcov --verify --coveralls-id=$TRAVIS_JOB_ID --exclude-pattern=/.cargo target/kcov target/debug/atty-* && + [ $TRAVIS_BRANCH = master ] && + [ $TRAVIS_PULL_REQUEST = false ] && + cargo doc --no-deps && + echo "" > target/doc/index.html && + pip install --user ghp-import && + /home/travis/.local/bin/ghp-import -n target/doc && + git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages +env: + global: + secure: acjXoBFG4yFklz/iW4q9PLaMmTgug0c8hOov4uiaXYjDkVGhnEePBozGc8ctKuFv2BVlwBSzvE1neE9dHcCS6il0x+G79sVTekfVN5dERja3UpwrC0/QodJuDmErIUpb6zylupPnUGq5pzZabRPNKyAnsFS5wYhLMSLxGPu4pfYdW0Eu8CEPIgPYsI6o2pfKgNpXbeizdHRLMeZCN4cbEPohO1odc+Z6WJvgKn2xEkpAcfhAuaroqGGxRtmDiJZ/JaBijAKY/O9Q3Xq1GSGOPT5lmwJSp3Fxw5dgmeX6LmN0ZODASdnEoYfoqUDUFzkCON3Sk4a7hugxlkZ7cx1tfqXxMg+0BgYIUdGQNloDJnuusWvXPBFdB2jxMsfcbrCjNsrJ8kjN6uBsW9yy0kqN7a8eOJckwh5fYRWfNta0R+BrveNXWmGp4u4aBq/85jEiHi30XKTzaEUbF0Y3cIONweWeWwBOcAvPBhO63Y07TRRe+SSk1NYm7QHGW9RsHhz89OSbaIXqn+r/o+6DZcw5XaO73DtZ62Kx48NErej9kVqcIJ6HnyvCJ/fJoT7h1ixSRI/WmS30l2S/q33Q2G4C/IZ4ZZRD/1thSltAxeA6OAUnr8ITZyW47CqOmyL1IUptrdAb9OLEedYV/QrOhcg2RJLXyP66xnItOwMp014bEp4= diff --git a/src/vendor/atty/CHANGELOG.md b/src/vendor/atty/CHANGELOG.md new file mode 100644 index 0000000000..974776020f --- /dev/null +++ b/src/vendor/atty/CHANGELOG.md @@ -0,0 +1,25 @@ +# 0.2.2 + +* use target specific dependencies [#11](https://github.com/softprops/atty/pull/11) +* Add tty detection for MSYS terminals [#12](https://github.com/softprops/atty/pull/12) + +# 0.2.1 + +* fix windows bug + +# 0.2.0 + +* support for various stream types + +# 0.1.2 + +* windows support (with automated testing) +* automated code coverage + +# 0.1.1 + +* bumped libc dep from `0.1` to `0.2` + +# 0.1.0 + +* initial release diff --git a/src/vendor/atty/Cargo.toml b/src/vendor/atty/Cargo.toml new file mode 100644 index 0000000000..3b2214c567 --- /dev/null +++ b/src/vendor/atty/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "atty" +version = "0.2.2" +authors = ["softprops "] +description = "A simple interface for querying atty" +documentation = "http://softprops.github.io/atty" +homepage = "https://github.com/softprops/atty" +repository = "https://github.com/softprops/atty" +keywords = ["terminal", "tty"] +license = "MIT" + +[target.'cfg(not(windows))'.dependencies] +libc = "0.2" + +[target.'cfg(windows)'.dependencies] +kernel32-sys = "0.2" +winapi = "0.2" diff --git a/src/vendor/atty/LICENSE b/src/vendor/atty/LICENSE new file mode 100644 index 0000000000..ec1bc5497e --- /dev/null +++ b/src/vendor/atty/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2015-2016 Doug Tangren + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/vendor/atty/README.md b/src/vendor/atty/README.md new file mode 100644 index 0000000000..a85764ffc5 --- /dev/null +++ b/src/vendor/atty/README.md @@ -0,0 +1,78 @@ +# atty + +[![Build Status](https://travis-ci.org/softprops/atty.svg?branch=master)](https://travis-ci.org/softprops/atty) [![Build status](https://ci.appveyor.com/api/projects/status/geggrsnsjsuse8cv?svg=true)](https://ci.appveyor.com/project/softprops/atty) [![Coverage Status](https://coveralls.io/repos/softprops/atty/badge.svg?branch=master&service=github)](https://coveralls.io/github/softprops/atty?branch=master) [![crates.io](http://meritbadge.herokuapp.com/atty)](https://crates.io/crates/atty) + +> are you or are you not a tty? + + +[Api documentation](http://softprops.github.io/atty) + +## usage + +```rust +extern crate atty; + +use atty::Stream; + +fn main() { + if atty::is(Stream::Stdout) { + println!("I'm a terminal"); + } else { + println!("I'm not"); + } +} +``` + +## install + +Add the following to your `Cargo.toml` + +```toml +[dependencies] +atty = "0.2" +``` + +## testing + +This library has been unit tested on both unix and windows platforms (via appveyor). + + +A simple example program is provided in this repo to test various tty's. By default. + +It prints + +```bash +$ cargo run --example atty +stdout? true +stderr? true +stdin? true +``` + +To test std in, pipe some text to the program + +```bash +$ echo "test" | cargo run --example atty +stdout? true +stderr? true +stdin? false +``` + +To test std out, pipe the program to something + +```bash +$ cargo run --example atty | grep std +stdout? false +stderr? true +stdin? true +``` + +To test std err, pipe the program to something redirecting std err + +```bash +$ cargo run --example atty 2>&1 | grep std +stdout? false +stderr? false +stdin? true +``` + +Doug Tangren (softprops) 2015 diff --git a/src/vendor/atty/appveyor.yml b/src/vendor/atty/appveyor.yml new file mode 100644 index 0000000000..6958e13872 --- /dev/null +++ b/src/vendor/atty/appveyor.yml @@ -0,0 +1,17 @@ +environment: + matrix: + - TARGET: nightly-x86_64-pc-windows-msvc + - TARGET: nightly-i686-pc-windows-msvc + - TARGET: nightly-x86_64-pc-windows-gnu + - TARGET: nightly-i686-pc-windows-gnu + - TARGET: 1.8.0-x86_64-pc-windows-gnu +install: + - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-${env:TARGET}.exe" -FileName "rust-install.exe" + - ps: .\rust-install.exe /VERYSILENT /NORESTART /DIR="C:\rust" | Out-Null + - ps: $env:PATH="$env:PATH;C:\rust\bin" + - call "%VCVARS%" || ver>nul + - rustc -vV + - cargo -vV +build: false +test_script: + - cargo test --verbose diff --git a/src/vendor/atty/examples/atty.rs b/src/vendor/atty/examples/atty.rs new file mode 100644 index 0000000000..3b3635e59c --- /dev/null +++ b/src/vendor/atty/examples/atty.rs @@ -0,0 +1,9 @@ +extern crate atty; + +use atty::{is, Stream}; + +fn main() { + println!("stdout? {}", is(Stream::Stdout)); + println!("stderr? {}", is(Stream::Stderr)); + println!("stdin? {}", is(Stream::Stdin)); +} diff --git a/src/vendor/atty/src/lib.rs b/src/vendor/atty/src/lib.rs new file mode 100644 index 0000000000..b0756ca827 --- /dev/null +++ b/src/vendor/atty/src/lib.rs @@ -0,0 +1,183 @@ +//! atty is a simple utility that answers one question +//! > is this a tty? +//! +//! usage is just as simple +//! +//! ``` +//! if atty::is(atty::Stream::Stdout) { +//! println!("i'm a tty") +//! } +//! ``` +//! +//! ``` +//! if atty::isnt(atty::Stream::Stdout) { +//! println!("i'm not a tty") +//! } +//! ``` + +#[cfg(windows)] +extern crate kernel32; +#[cfg(not(windows))] +extern crate libc; +#[cfg(windows)] +extern crate winapi; + +#[cfg(windows)] +use winapi::minwindef::DWORD; + +/// possible stream sources +#[derive(Clone, Copy, Debug)] +pub enum Stream { + Stdout, + Stderr, + Stdin, +} + +/// returns true if this is a tty +#[cfg(unix)] +pub fn is(stream: Stream) -> bool { + extern crate libc; + + let fd = match stream { + Stream::Stdout => libc::STDOUT_FILENO, + Stream::Stderr => libc::STDERR_FILENO, + Stream::Stdin => libc::STDIN_FILENO, + }; + unsafe { libc::isatty(fd) != 0 } +} + +/// returns true if this is a tty +#[cfg(windows)] +pub fn is(stream: Stream) -> bool { + use winapi::{ + STD_INPUT_HANDLE as STD_INPUT, + STD_ERROR_HANDLE as STD_ERROR, + STD_OUTPUT_HANDLE as STD_OUTPUT + }; + + let (fd, others) = match stream { + Stream::Stdin => (STD_INPUT, [STD_ERROR, STD_OUTPUT]), + Stream::Stderr => (STD_ERROR, [STD_INPUT, STD_OUTPUT]), + Stream::Stdout => (STD_OUTPUT, [STD_INPUT, STD_ERROR]), + }; + if unsafe { console_on_any(&[fd]) } { + // False positives aren't possible. If we got a console then + // we definitely have a tty on stdin. + return true; + } + + // At this point, we *could* have a false negative. We can determine that + // this is true negative if we can detect the presence of a console on + // any of the other streams. If another stream has a console, then we know + // we're in a Windows console and can therefore trust the negative. + if unsafe { console_on_any(&others) } { + return false; + } + + // Otherwise, we fall back to a very strange msys hack to see if we can + // sneakily detect the presence of a tty. + unsafe { msys_tty_on(fd) } +} + +/// returns true if this is _not_ a tty +pub fn isnt(stream: Stream) -> bool { + !is(stream) +} + +/// Returns true if any of the given fds are on a console. +#[cfg(windows)] +unsafe fn console_on_any(fds: &[DWORD]) -> bool { + for &fd in fds { + let mut out = 0; + let handle = kernel32::GetStdHandle(fd); + if kernel32::GetConsoleMode(handle, &mut out) != 0 { + return true; + } + } + false +} + +/// Returns true if there is an MSYS tty on the given handle. +#[cfg(windows)] +unsafe fn msys_tty_on(fd: DWORD) -> bool { + use std::ffi::OsString; + use std::mem; + use std::os::raw::c_void; + use std::os::windows::ffi::OsStringExt; + use std::slice; + + use kernel32::GetFileInformationByHandleEx; + use winapi::fileapi::FILE_NAME_INFO; + use winapi::minwinbase::FileNameInfo; + use winapi::minwindef::MAX_PATH; + + let size = mem::size_of::(); + let mut name_info_bytes = vec![0u8; size + MAX_PATH]; + let res = GetFileInformationByHandleEx( + kernel32::GetStdHandle(fd), + FileNameInfo, + &mut *name_info_bytes as *mut _ as *mut c_void, + name_info_bytes.len() as u32); + if res == 0 { + return true; + } + let name_info: FILE_NAME_INFO = + *(name_info_bytes[0..size].as_ptr() as *const FILE_NAME_INFO); + let name_bytes = + &name_info_bytes[size..size + name_info.FileNameLength as usize]; + let name_u16 = slice::from_raw_parts( + name_bytes.as_ptr() as *const u16, name_bytes.len() / 2); + let name = OsString::from_wide(name_u16) + .as_os_str().to_string_lossy().into_owned(); + name.contains("msys-") || name.contains("-pty") +} + +#[cfg(test)] +mod tests { + use super::{is, Stream}; + + #[test] + #[cfg(windows)] + fn is_err() { + // appveyor pipes its output + assert!(!is(Stream::Stderr)) + } + + #[test] + #[cfg(windows)] + fn is_out() { + // appveyor pipes its output + assert!(!is(Stream::Stdout)) + } + + #[test] + #[cfg(windows)] + fn is_in() { + assert!(is(Stream::Stdin)) + } + + #[test] + #[cfg(unix)] + fn is_err() { + assert!(is(Stream::Stderr)) + } + + #[test] + #[cfg(unix)] + fn is_out() { + assert!(is(Stream::Stdout)) + } + + #[test] + #[cfg(target_os = "macos")] + fn is_in() { + // macos on travis seems to pipe its input + assert!(!is(Stream::Stdin)) + } + + #[test] + #[cfg(all(not(target_os = "macos"), unix))] + fn is_in() { + assert!(is(Stream::Stdin)) + } +} diff --git a/src/vendor/backtrace-sys/.cargo-checksum.json b/src/vendor/backtrace-sys/.cargo-checksum.json index ed811c91d3..70f4a4ce28 100644 --- a/src/vendor/backtrace-sys/.cargo-checksum.json +++ b/src/vendor/backtrace-sys/.cargo-checksum.json @@ -1 +1 @@ -{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"749f043da5cdbd988e2068e94feb3e75ed326945a99cf288c94ae444f5328680","build.rs":"2cf7c28f03f85c8e68969bcb5b076c8effa8543d39a12fe651ff332ac6a394c7","src/lib.rs":"cb45ba047240bceac6ea74da50c2f48ae81a965b578c833a766a3ea0db1075f3","src/libbacktrace/ChangeLog":"ad6f9058524b950aed734db83419e0624df55a48af8091c8bcad7a125aeeffdd","src/libbacktrace/ChangeLog.jit":"ee143b5c9dc571d9aca006be246a83b1f019c39a3fd7b0025eb37463e30200ce","src/libbacktrace/Makefile.am":"74d0036c9715cb7fa6c749cead794ba96283f47d243cf2b25bc6fac8f04667d5","src/libbacktrace/Makefile.in":"9ca92df95c8d62b8a0e106357a796ef4d2c5ec7fd02ab133fd0a65de1984e096","src/libbacktrace/README":"3d1a15714583197945df8db054da6f30613316ec311c5ec2d68b92fab12364a2","src/libbacktrace/aclocal.m4":"e3a6dfa4ce929624ac289b260987a7fa9b512cfbf3ff6f39c5d1e38cbad1a0ea","src/libbacktrace/alloc.c":"829ceab369210fc60758f339807fe0bf55832c77adb3a4450fae586a90a9673d","src/libbacktrace/ansidecl.h":"14acfcd6c044bc73de85b120cbc3e626771a01712911ee1f6137585fd710fb1e","src/libbacktrace/atomic.c":"3e1882a520e0e1115107e194fbd97daa8d3feef15a70047969f4976e7542c263","src/libbacktrace/backtrace-supported.h.in":"42277f3c383386b6cfa3d3d889336e92303fac0ae1a9fb8a6a56737245dfb8f3","src/libbacktrace/backtrace.c":"76bdabddc4eb8a46a7eec98ce610c86909c89c629eb850a0cde98f5a78c9b99d","src/libbacktrace/backtrace.h":"cd2db6474556b655e42c0a973b871c1b6cb4796809490bf59cc8d3d0e8c083f5","src/libbacktrace/btest.c":"fff55e4acf6ad02a6f719046fc4e3f8bf795166ed9956122a79e17c6be266738","src/libbacktrace/config.guess":"8131853dbc8c3be5171fa96353de7a884a79d3f1d6b3fbf48f99037f5f95fe27","src/libbacktrace/config.h.in":"9b0d30416c93906e5c0ce36c95a7426bfd41228114f381949e89d263305b5b65","src/libbacktrace/config.sub":"3b739084e4b409aacf8531f87b57efa602eccdd17b5cddbc4ae1313a2c866f34","src/libbacktrace/configure":"2b45c89d06809c6ed49d70bfdf51a93e44370fc81f689169a073f47b14b366e5","src/libbacktrace/configure.ac":"360b1a033e33d2c58d2f36aaa6644a2aac0dd8960417df6d64202cc099a1c3f3","src/libbacktrace/dwarf.c":"b969c3abb07a09aa4ac5094dba5777d2c23fee77ade4ec0934142d6b81049785","src/libbacktrace/dwarf2.def":"d947302d8b259f0abdd9dd2f50a0713f4e7395c05ce88ddfdb37a7145b045d82","src/libbacktrace/dwarf2.h":"b3b13fa412a1573e3ee8dcb1d603ec33de7140f00b3bbbaa5292724f0087ace3","src/libbacktrace/elf.c":"728d7e47bf077de4dad6eecc76c134b4b4898dc5866572587692848f29aaec5c","src/libbacktrace/fileline.c":"bae25b6662bfd01a43bccc645206e00aeea27f18a51f6303f00f4fa1d9f2e861","src/libbacktrace/filenames.h":"bce400200dbc7452ca2a7f27dd36516949c4c94a135a6a322f011f3ce7817377","src/libbacktrace/filetype.awk":"9dd5352f288c3737fccd24a2c7583f4d0dbca2b95b2735a90a26b644478018af","src/libbacktrace/hashtab.h":"4cb7f68db5c2e8ff1190ecf859e7feb58447ea20bd9818bb1f447b46e2813c58","src/libbacktrace/install-sh":"d7c113e5484fce8b48f9a34a7a91e385ec279247d415b0b7d749bd56ad8ee8a2","src/libbacktrace/internal.h":"ed657e14aa33b4b5217919435e69019c5a677a00a9c134bf0297f000f146b093","src/libbacktrace/ltmain.sh":"ee4019f80b993cdb1bd13bf39434ad4f1ef15ae57a97594c53fb7b1d76d776a4","src/libbacktrace/missing":"b1a337b731bbb58846d31ca2f5143c293a455fa41b481e236e89a9016d96b034","src/libbacktrace/mmap.c":"fec72286a2d8a0c53fd56ea61b3766b87031f6f803f6de6c3c656e39bc85cdc2","src/libbacktrace/mmapio.c":"32a672fd2b8b3395c8a16ef11d839437ca35570fbc235bb0e2e70ef8097a12fc","src/libbacktrace/nounwind.c":"7694636af38ef488c814ab9b71854d6a259c1f3f635bd4c3ed99a88ca2beb5f1","src/libbacktrace/pecoff.c":"00cf6976cfc1e018f5e5473d4fbef4ae86de825dd2749897c45dfcebcefc6abf","src/libbacktrace/posix.c":"73754fcfa0a5b0342e8fe32166e7228b61e022699a8a3c9a2ef8e46260736704","src/libbacktrace/print.c":"ec1e80e17e27130bf9412470e8dc9155a0dc9ca3a78125081f5073b438b54157","src/libbacktrace/read.c":"399458fb06389aa4bd5ce376c4620cf733b5555d1dabe7ef19f185da1e37e614","src/libbacktrace/simple.c":"686d976c2bdb1a074f9be05af026d4b4c7a4978c2602268747d492563f18e0dc","src/libbacktrace/sort.c":"1a1e44af4e4d02fc568b318aa1517792edd6972a27029ba78e938856ef8ba1a0","src/libbacktrace/state.c":"49d547f5622b0ea0c39bc873b09a7dce276fdc6469118f5ab2e72c55bd0457fb","src/libbacktrace/stest.c":"aa1b90fe2d6dc8ac65ac0168776c2d242efc6460ac596deb14ac1e72bf764871","src/libbacktrace/unknown.c":"914aa113cd17ed678d40927391b35f6027e87b3a02e36e9f1822ec1efe9c0e20","symbol-map":"b941b2516efbb9e46521eeb166c60b31d52b2a4aaaf35d7f9af24946bbe1328a"},"package":"d192fd129132fbc97497c1f2ec2c2c5174e376b95f535199ef4fe0a293d33842"} \ No newline at end of file +{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"f8d7b705ce625488f8ce9b7222a3284e83ae3243111f452a617efeed0b7e0c50","build.rs":"8ed75592a0040ea0051fb22ac9095b8fe2f2f921e9a142ed866d4500f70b26dd","src/lib.rs":"cb45ba047240bceac6ea74da50c2f48ae81a965b578c833a766a3ea0db1075f3","src/libbacktrace/ChangeLog":"ad6f9058524b950aed734db83419e0624df55a48af8091c8bcad7a125aeeffdd","src/libbacktrace/ChangeLog.jit":"ee143b5c9dc571d9aca006be246a83b1f019c39a3fd7b0025eb37463e30200ce","src/libbacktrace/Makefile.am":"74d0036c9715cb7fa6c749cead794ba96283f47d243cf2b25bc6fac8f04667d5","src/libbacktrace/Makefile.in":"9ca92df95c8d62b8a0e106357a796ef4d2c5ec7fd02ab133fd0a65de1984e096","src/libbacktrace/README":"3d1a15714583197945df8db054da6f30613316ec311c5ec2d68b92fab12364a2","src/libbacktrace/aclocal.m4":"e3a6dfa4ce929624ac289b260987a7fa9b512cfbf3ff6f39c5d1e38cbad1a0ea","src/libbacktrace/alloc.c":"829ceab369210fc60758f339807fe0bf55832c77adb3a4450fae586a90a9673d","src/libbacktrace/ansidecl.h":"14acfcd6c044bc73de85b120cbc3e626771a01712911ee1f6137585fd710fb1e","src/libbacktrace/atomic.c":"3e1882a520e0e1115107e194fbd97daa8d3feef15a70047969f4976e7542c263","src/libbacktrace/backtrace-supported.h.in":"42277f3c383386b6cfa3d3d889336e92303fac0ae1a9fb8a6a56737245dfb8f3","src/libbacktrace/backtrace.c":"76bdabddc4eb8a46a7eec98ce610c86909c89c629eb850a0cde98f5a78c9b99d","src/libbacktrace/backtrace.h":"cd2db6474556b655e42c0a973b871c1b6cb4796809490bf59cc8d3d0e8c083f5","src/libbacktrace/btest.c":"fff55e4acf6ad02a6f719046fc4e3f8bf795166ed9956122a79e17c6be266738","src/libbacktrace/config.guess":"8131853dbc8c3be5171fa96353de7a884a79d3f1d6b3fbf48f99037f5f95fe27","src/libbacktrace/config.h.in":"9b0d30416c93906e5c0ce36c95a7426bfd41228114f381949e89d263305b5b65","src/libbacktrace/config.sub":"3b739084e4b409aacf8531f87b57efa602eccdd17b5cddbc4ae1313a2c866f34","src/libbacktrace/configure":"2b45c89d06809c6ed49d70bfdf51a93e44370fc81f689169a073f47b14b366e5","src/libbacktrace/configure.ac":"360b1a033e33d2c58d2f36aaa6644a2aac0dd8960417df6d64202cc099a1c3f3","src/libbacktrace/dwarf.c":"b969c3abb07a09aa4ac5094dba5777d2c23fee77ade4ec0934142d6b81049785","src/libbacktrace/dwarf2.def":"d947302d8b259f0abdd9dd2f50a0713f4e7395c05ce88ddfdb37a7145b045d82","src/libbacktrace/dwarf2.h":"b3b13fa412a1573e3ee8dcb1d603ec33de7140f00b3bbbaa5292724f0087ace3","src/libbacktrace/elf.c":"728d7e47bf077de4dad6eecc76c134b4b4898dc5866572587692848f29aaec5c","src/libbacktrace/fileline.c":"bae25b6662bfd01a43bccc645206e00aeea27f18a51f6303f00f4fa1d9f2e861","src/libbacktrace/filenames.h":"bce400200dbc7452ca2a7f27dd36516949c4c94a135a6a322f011f3ce7817377","src/libbacktrace/filetype.awk":"9dd5352f288c3737fccd24a2c7583f4d0dbca2b95b2735a90a26b644478018af","src/libbacktrace/hashtab.h":"4cb7f68db5c2e8ff1190ecf859e7feb58447ea20bd9818bb1f447b46e2813c58","src/libbacktrace/install-sh":"d7c113e5484fce8b48f9a34a7a91e385ec279247d415b0b7d749bd56ad8ee8a2","src/libbacktrace/internal.h":"ed657e14aa33b4b5217919435e69019c5a677a00a9c134bf0297f000f146b093","src/libbacktrace/ltmain.sh":"ee4019f80b993cdb1bd13bf39434ad4f1ef15ae57a97594c53fb7b1d76d776a4","src/libbacktrace/missing":"b1a337b731bbb58846d31ca2f5143c293a455fa41b481e236e89a9016d96b034","src/libbacktrace/mmap.c":"fec72286a2d8a0c53fd56ea61b3766b87031f6f803f6de6c3c656e39bc85cdc2","src/libbacktrace/mmapio.c":"32a672fd2b8b3395c8a16ef11d839437ca35570fbc235bb0e2e70ef8097a12fc","src/libbacktrace/nounwind.c":"7694636af38ef488c814ab9b71854d6a259c1f3f635bd4c3ed99a88ca2beb5f1","src/libbacktrace/pecoff.c":"00cf6976cfc1e018f5e5473d4fbef4ae86de825dd2749897c45dfcebcefc6abf","src/libbacktrace/posix.c":"73754fcfa0a5b0342e8fe32166e7228b61e022699a8a3c9a2ef8e46260736704","src/libbacktrace/print.c":"ec1e80e17e27130bf9412470e8dc9155a0dc9ca3a78125081f5073b438b54157","src/libbacktrace/read.c":"399458fb06389aa4bd5ce376c4620cf733b5555d1dabe7ef19f185da1e37e614","src/libbacktrace/simple.c":"686d976c2bdb1a074f9be05af026d4b4c7a4978c2602268747d492563f18e0dc","src/libbacktrace/sort.c":"1a1e44af4e4d02fc568b318aa1517792edd6972a27029ba78e938856ef8ba1a0","src/libbacktrace/state.c":"49d547f5622b0ea0c39bc873b09a7dce276fdc6469118f5ab2e72c55bd0457fb","src/libbacktrace/stest.c":"aa1b90fe2d6dc8ac65ac0168776c2d242efc6460ac596deb14ac1e72bf764871","src/libbacktrace/unknown.c":"914aa113cd17ed678d40927391b35f6027e87b3a02e36e9f1822ec1efe9c0e20","symbol-map":"b941b2516efbb9e46521eeb166c60b31d52b2a4aaaf35d7f9af24946bbe1328a"},"package":"3a0d842ea781ce92be2bf78a9b38883948542749640b8378b3b2f03d1fd9f1ff"} \ No newline at end of file diff --git a/src/vendor/backtrace-sys/Cargo.toml b/src/vendor/backtrace-sys/Cargo.toml index 9682d4d2f6..f3e0bee462 100644 --- a/src/vendor/backtrace-sys/Cargo.toml +++ b/src/vendor/backtrace-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "backtrace-sys" -version = "0.1.10" +version = "0.1.11" authors = ["Alex Crichton "] build = "build.rs" license = "MIT/Apache-2.0" diff --git a/src/vendor/backtrace-sys/build.rs b/src/vendor/backtrace-sys/build.rs index f29c704da0..c98389d4c4 100644 --- a/src/vendor/backtrace-sys/build.rs +++ b/src/vendor/backtrace-sys/build.rs @@ -35,6 +35,7 @@ fn find_tool(compiler: &gcc::Tool, cc: &str, tool: &str) -> PathBuf { } let tool_suffix = format!("-{}", tool); try_tool(compiler, cc, "-gcc", &tool_suffix) + .or_else(|| try_tool(compiler, cc, "-clang", &tool_suffix)) .or_else(|| try_tool(compiler, cc, "-cc", &tool_suffix)) .unwrap_or_else(|| PathBuf::from(tool)) } @@ -71,7 +72,8 @@ fn main() { flags.push(flag); } let ar = find_tool(&compiler, cc, "ar"); - run(Command::new(src.join("src/libbacktrace/configure")) + run(Command::new("sh") + .arg(src.join("src/libbacktrace/configure")) .current_dir(&dst) .env("CC", compiler.path()) .env("CFLAGS", flags) @@ -79,8 +81,8 @@ fn main() { .arg("--disable-multilib") .arg("--disable-shared") .arg("--disable-host-shared") - .arg(format!("--target={}", target)) - .arg(format!("--host={}", host)), + .arg(format!("--host={}", target)) + .arg(format!("--build={}", host)), "sh"); run(Command::new("make") .current_dir(&dst) diff --git a/src/vendor/backtrace/.cargo-checksum.json b/src/vendor/backtrace/.cargo-checksum.json index a00867d734..c977f753e7 100644 --- a/src/vendor/backtrace/.cargo-checksum.json +++ b/src/vendor/backtrace/.cargo-checksum.json @@ -1 +1 @@ -{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"f9b1ca6ae27d1c18215265024629a8960c31379f206d9ed20f64e0b2dcf79805",".travis.yml":"1614061f3d279a69e20dfbeebc677bb5af33052eb0b5f715ef65cc2189255062","Cargo.toml":"54a3087b5ae466b5880c5593e15fd7cadd934eb6536a52c3931f83e7fe973d9a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"5fe38a76870e0348448335131e62ce07334e6667f4fdb9a9f9f601509eb2b45e","appveyor.yml":"29d9f44137560479a75b02a7953cfa0c378c2577ed1925f579b400295c7937e3","build.rs":"a6e3764760d185153dd1a08c0ee2d70d45f06cb257b52f609979a145db71cbb9","examples/backtrace.rs":"fd6e1cc6c3378ec7d41cd03b2bef187051298dceb01147e71f207dbb8a0c4867","examples/raw.rs":"f07be26d1f97cd7ac79290ac99d19c4eec5d27031fe270ab5364c25d9c2ad9e0","src/backtrace/dbghelp.rs":"45c5052763857d4a3727c3082be1b2f6c28f7973afd66706657defda5d97c6ec","src/backtrace/libunwind.rs":"cc9cdc1d389571cdedf43dfc2d39b8c3af85531a3965ed700c724f436afb213e","src/backtrace/mod.rs":"d00f4a574fae44df81b1d40bf44acea84addb70b4c76c85bfaa1f3ab0bcd7f0d","src/backtrace/noop.rs":"dc4a6602e9852b945c382194402314d3d68c8ca90199af9a8159419fb91a3c99","src/backtrace/unix_backtrace.rs":"1bb4a4a2f1e56f8ac04002dd77411116d8b4920f905d1ddfcb289e242f939a86","src/capture.rs":"b863c00930f4570928fb47fa3d0b9b4b7494c096e7f4fc027e1e8e8686b45aed","src/dylib.rs":"bb1627030160f4e78124c0dca4653bf5b7569a0daf75062c92c4321f70996269","src/lib.rs":"3f8c7407acda3770d6161a56f72ab9f2a2b5bd3e2f8b5d3c9d2ef6c3c72eab45","src/symbolize/coresymbolication.rs":"7b378e41c5595ba5a85f2c83eb2923685960b40d6f7b01f1722d9d0bce907bdd","src/symbolize/dbghelp.rs":"d743545bb3e64eafc4903e3e7aec115b64da2174e75afd7b465bc0b89573b88a","src/symbolize/dladdr.rs":"8287cbca440a9e92e74d88c5a7b920f6b4cf6d8f50bc8b0f61aca5ba42d5b5ec","src/symbolize/libbacktrace.rs":"f41f91415c1fd145f56538bd76d1e2bf271c5ae812aa6c1dbcf444b164b4cef7","src/symbolize/mod.rs":"b7958a3635ef1f70b1618af5918aed703bc87fbccd36272c2424e32f60137420","src/symbolize/noop.rs":"b622fcecb4e22b42c3d3e2ef5dc5a6ab14601fec83c7797ee1fbbacc12fe6ca1","tests/smoke.rs":"e0d1bb572940e56ae7d80b5bb6890d0e81a4f80d8aebb3176f473fa1bf607247"},"package":"f551bc2ddd53aea015d453ef0b635af89444afa5ed2405dd0b2062ad5d600d80"} \ No newline at end of file +{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"f9b1ca6ae27d1c18215265024629a8960c31379f206d9ed20f64e0b2dcf79805",".travis.yml":"6f11d19317924088c90d605e1d13e4af230b10e289c5df6139c40a62409eabd9","Cargo.toml":"f893b7b701611e48ab80db25670342084b11d8d4ed3f3471b68842c490d247b8","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"11061a4c1e27fde148b5b1fb6df553f8eb464e279be0f5e278d262bf35d7b0f8","appveyor.yml":"29d9f44137560479a75b02a7953cfa0c378c2577ed1925f579b400295c7937e3","examples/backtrace.rs":"fd6e1cc6c3378ec7d41cd03b2bef187051298dceb01147e71f207dbb8a0c4867","examples/raw.rs":"f07be26d1f97cd7ac79290ac99d19c4eec5d27031fe270ab5364c25d9c2ad9e0","src/backtrace/dbghelp.rs":"45c5052763857d4a3727c3082be1b2f6c28f7973afd66706657defda5d97c6ec","src/backtrace/libunwind.rs":"cc9cdc1d389571cdedf43dfc2d39b8c3af85531a3965ed700c724f436afb213e","src/backtrace/mod.rs":"d00f4a574fae44df81b1d40bf44acea84addb70b4c76c85bfaa1f3ab0bcd7f0d","src/backtrace/noop.rs":"dc4a6602e9852b945c382194402314d3d68c8ca90199af9a8159419fb91a3c99","src/backtrace/unix_backtrace.rs":"1bb4a4a2f1e56f8ac04002dd77411116d8b4920f905d1ddfcb289e242f939a86","src/capture.rs":"de3250fcb9ff941391dea24decc8166d058f17abe77d25ff82b766ac384f00ea","src/dylib.rs":"09f3d7f32849cf0daa4de9df48f8e4a4d5ba62e20723c79578201bd271dc4777","src/lib.rs":"7ccd8cc3679435f0e39efd26f23d9d7a01094ab09ba6d411c6587b2420c6886b","src/symbolize/coresymbolication.rs":"99280684791694f560824b39291ee7ad78a2b53f82e5972ff3d9b77b43671f60","src/symbolize/dbghelp.rs":"d743545bb3e64eafc4903e3e7aec115b64da2174e75afd7b465bc0b89573b88a","src/symbolize/dladdr.rs":"8287cbca440a9e92e74d88c5a7b920f6b4cf6d8f50bc8b0f61aca5ba42d5b5ec","src/symbolize/libbacktrace.rs":"0cdad7de2501baef9da193ee6aab21c453d26348a2071c805a133efe1209eaa1","src/symbolize/mod.rs":"7f2efe54ce40f42ba38673614cff2a510632123cb6d1bc3da88566f12bcba588","src/symbolize/noop.rs":"b622fcecb4e22b42c3d3e2ef5dc5a6ab14601fec83c7797ee1fbbacc12fe6ca1","tests/smoke.rs":"fc882d7db0f4842e4415e3319774a33ba27c4d6412a62f8ee194a5dafd8a6128"},"package":"72f9b4182546f4b04ebc4ab7f84948953a118bd6021a1b6a6c909e3e94f6be76"} \ No newline at end of file diff --git a/src/vendor/backtrace/.travis.yml b/src/vendor/backtrace/.travis.yml index b6785585cb..c56985a739 100644 --- a/src/vendor/backtrace/.travis.yml +++ b/src/vendor/backtrace/.travis.yml @@ -4,6 +4,8 @@ rust: - beta - nightly sudo: false +before_script: + - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH script: - cargo test - cargo test --no-default-features @@ -16,24 +18,22 @@ script: - cargo test --no-default-features --features 'serialize-serde' - cargo test --no-default-features --features 'serialize-rustc' - cargo test --no-default-features --features 'serialize-rustc serialize-serde' + - cargo test --no-default-features --features 'cpp_demangle' + - cd ./cpp_smoke_test && cargo test && cd .. + - cargo clean && cargo build - rustdoc --test README.md -L target/debug/deps -L target/debug - cargo doc --no-deps notifications: email: on_success: never -after_success: | - [ $TRAVIS_BRANCH = master ] && - [ $TRAVIS_PULL_REQUEST = false ] && - [ $TRAVIS_RUST_VERSION = nightly ] && - echo '' > target/doc/index.html && - pip install ghp-import --user $USER && - $HOME/.local/bin/ghp-import -n target/doc && - git push -qf https://${TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages +after_success: + - travis-cargo --only nightly doc-upload env: global: # serde-codegen has historically needed a large stack to expand - RUST_MIN_STACK=16777216 - - secure: g5hE6I1aheSevWUkVZxL/DUS6cbx2nCrKFcaCpfpvT6zf4uA/FOX2UlaUQO2wAqULj77TVIpOEZG5KyZmFw2yHt8I61z54JQvz8WsaHI4+EzNCBVF542kbNQehDJA7BcevJTL88bGwsZttSBD4GcDw8GkLUfY4Ce1nUydu3haf+iLOmTpdzE9OnNnNcrbQ5l17Lokq3vpIw3FxyUypU1v2FQqTDEtcgS2y3ZSg/qn02f4rU/jds/QhO65PZ2ViXVg2Jn/LbwaOLjFfRuC4OPBXyY318jJkvIcmCjwGWwVaEZOzJDqnCSKkgqEmktv/GoXTWaGuLuFsNcl/qervja3Ixi8bb41lklqBsv6Moyt2pSoeCXbWf4tPWfCAOxE0DCfAkutcrJx0v0etsbLTGh4WnfqwcFEW1NcGxAsoTzaww7S9lM6pyHoyaQ5TnTqGftMTQ8IcaVYsjLG7UwHfkHQqgAcYZ1yukPuxM+DdpOFIHEivzjjSFvpHtQpxCoFS+n72AW8dk+pl2PHpVdWa7TTsIA5QIJoCZ7m4PjG872+ofcriW1Ib5LiwhYlRMhjbQUGFLVZVKRvYiPQubTLBwT62rOaljzz9TrfB+NXHZ+ykcqs1aXavPwGWgBwOks17ApnOInYBUV7j5jm7Pt7pCwsaMg8iMdPxdBu8xk3N1C1Wg= + - secure: "Kuf3j6gC3MhR+F7g8/5J4+3tu+FXJP/SqKjsUVVjs/qjniIVX3MwZPhtP/pVtdRvYjW0NzLw5Nufb4o1cyY4uKwR8BHHNuEUE/h3mPShjWHqzLyn5QiBumPozsFCa32H4gconRmp3+s0YrBT7nLoGvUZZS0dkldMkpvvrPL/yUKXLS8HEP4L1GO5iMQQYG6i3sbWTbHikE6ZQogW/iZommyqUkVB/s/SQvdH9SXu89ttNXlm/F+EIsgsgyzpbULp5sD34GRDPJe+H1m+sgA1kTRrzmuBGNmz9mx6GyIKaqACTm1gRcb06nFjTPVTQioJBNnoV7TEqZCvjuSsUjcGmP4Aeissafo93ADzV+bd0uoWIScE9ltSVS+RgCDV+sd0GHz5U6FjhgZp0amaVl3d6hPp8lbTfK/gfj1i9ktQfKZbG7rB4tfIU1KeQRkyE9vb/TaKp8nwBbc4SVQ4EKFOlRbE1S1FooaKZweW8w57d2u+sMMMVJbO28/Ap8tk9xDSOl4shPaT0iM0U9/heF8FmCZB1OKXLKn6TAaNFnaMTvdTHl+Tjrf6Vzd/oPXJ7GuaB6eLxXYjXvZHuKiLkSZriOzhL7PbijNILbSgZt7+Fa0vcnXP8zgD4dmupx/CoIHLN9NP4o9cGXuBcaJ/iFryJ4i5LKGFNEUHtXkavDrcgcA=" + os: - linux diff --git a/src/vendor/backtrace/Cargo.toml b/src/vendor/backtrace/Cargo.toml index 5d47309614..f23135e50e 100644 --- a/src/vendor/backtrace/Cargo.toml +++ b/src/vendor/backtrace/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "backtrace" -version = "0.3.0" +version = "0.3.2" authors = ["Alex Crichton ", "The Rust Project Developers"] license = "MIT/Apache-2.0" @@ -11,23 +11,26 @@ documentation = "http://alexcrichton.com/backtrace-rs" description = """ A library to acquire a stack trace (backtrace) at runtime in a Rust program. """ -build = "build.rs" - [dependencies] libc = "0.2" -backtrace-sys = { path = "backtrace-sys", version = "0.1.3", optional = true } -kernel32-sys = { version = "0.2", optional = true } -winapi = { version = "0.2.5", optional = true } -dbghelp-sys = { version = "0.2", optional = true } cfg-if = "0.1" -rustc-demangle = "0.1" +rustc-demangle = "0.1.4" # Optionally enable the ability to serialize a `Backtrace` -serde = { version = "0.8", optional = true } +serde = { version = "1.0", optional = true } +serde_derive = { version = "1.0", optional = true } rustc-serialize = { version = "0.3", optional = true } -[build-dependencies] -serde_codegen = { version = "0.8", optional = true } +# Optionally demangle C++ frames' symbols in backtraces. +cpp_demangle = { default-features = false, version = "0.2.3", optional = true } + +[target.'cfg(windows)'.dependencies] +dbghelp-sys = { version = "0.2", optional = true } +kernel32-sys = { version = "0.2", optional = true } +winapi = { version = "0.2.5", optional = true } + +[target.'cfg(all(unix, not(target_os = "emscripten"), not(target_os = "macos"), not(target_os = "ios")))'.dependencies] +backtrace-sys = { path = "backtrace-sys", version = "0.1.3", optional = true } # Each feature controls the two phases of finding a backtrace: getting a # backtrace and then resolving instruction pointers to symbols. The default @@ -81,4 +84,4 @@ default = ["libunwind", "libbacktrace", "coresymbolication", "dladdr", "dbghelp" # # Various features used for enabling rustc-serialize or syntex codegen. serialize-rustc = ["rustc-serialize"] - serialize-serde = ["serde", "serde_codegen"] + serialize-serde = ["serde", "serde_derive"] diff --git a/src/vendor/backtrace/README.md b/src/vendor/backtrace/README.md index 56abd412a5..1c96cd2326 100644 --- a/src/vendor/backtrace/README.md +++ b/src/vendor/backtrace/README.md @@ -13,13 +13,16 @@ more stable and programmatic interface. ```toml [dependencies] -backtrace = "0.2" +backtrace = "0.3" ``` ```rust extern crate backtrace; ``` +Note that this crate requires `make`, `objcopy`, and `ar` to be present on Linux +systems. + ## Usage To simply capture a backtrace and defer dealing with it until a later time, diff --git a/src/vendor/backtrace/build.rs b/src/vendor/backtrace/build.rs deleted file mode 100644 index a7c5870681..0000000000 --- a/src/vendor/backtrace/build.rs +++ /dev/null @@ -1,51 +0,0 @@ -#[cfg(feature = "serialize-serde")] -extern crate serde_codegen; - -use std::env; -use std::fs::{self, File}; -use std::io::prelude::*; -use std::path::Path; - -// See src/capture.rs for what in the world this build script is doing. - -fn main() { - let out_dir = env::var_os("OUT_DIR").unwrap(); - let out_dir = Path::new(&out_dir); - - if cfg!(feature = "serialize-rustc") { - let mut s = String::new(); - File::open("src/capture.rs").unwrap() - .read_to_string(&mut s).unwrap(); - let s = s.replace("//~ HACK1 ", ""); - File::create(out_dir.join("capture.rs")).unwrap() - .write_all(s.as_bytes()).unwrap(); - } else { - fs::copy("src/capture.rs", out_dir.join("capture.rs")).unwrap(); - } - - expand_serde(out_dir); - println!("cargo:rerun-if-changed=src/capture.rs"); -} - -#[cfg(not(feature = "serialize-serde"))] -fn expand_serde(_out_dir: &Path) {} - -#[cfg(feature = "serialize-serde")] -fn expand_serde(out_dir: &Path) { - use std::thread; - - let dst = out_dir.join("capture.rs"); - - let mut input = File::open(&dst).unwrap(); - let mut tmp = File::create(out_dir.join("tmp.rs")).unwrap(); - let mut s = String::new(); - input.read_to_string(&mut s).unwrap(); - tmp.write_all(s.replace("//~ HACK2 ", "").as_bytes()).unwrap(); - - // This has been seen to overflow the stack on travis, so just use a - // dedicated big-stack thread. - let out_dir = out_dir.to_path_buf(); - thread::Builder::new().stack_size(16 * 1024 * 1024).spawn(move || { - serde_codegen::expand(&out_dir.join("tmp.rs"), &dst).unwrap(); - }).unwrap().join().unwrap(); -} diff --git a/src/vendor/backtrace/src/capture.rs b/src/vendor/backtrace/src/capture.rs index 58ae0aad42..8846ea47e1 100644 --- a/src/vendor/backtrace/src/capture.rs +++ b/src/vendor/backtrace/src/capture.rs @@ -5,28 +5,13 @@ use std::path::{Path, PathBuf}; use {trace, resolve, SymbolName}; -// Ok so the `//~ HACK` directives here are, well, hacks. Right now we want to -// compile on stable for serde support, but we also want to use -// #[derive(Serialize, Deserialize)] macros *along* with the -// `#[derive(RustcEncodable, RustcDecodable)]` macros. In theory both of these -// can be behind a #[cfg_attr], but that unfortunately doesn't work for two -// reasons: -// -// 1. rust-lang/rust#32957 - means the include! of this module doesn't expand -// the RustcDecodable/RustcEncodable blocks. -// 2. serde-rs/serde#148 - means that Serialize/Deserialize won't get expanded. -// -// We just hack around it by doing #[cfg_attr] manually essentially. Our build -// script will just strip the `//~ HACKn` prefixes here if the corresponding -// feature is enabled. - /// Representation of an owned and self-contained backtrace. /// /// This structure can be used to capture a backtrace at various points in a /// program and later used to inspect what the backtrace was at that time. #[derive(Clone)] -//~ HACK1 #[derive(RustcDecodable, RustcEncodable)] -//~ HACK2 #[derive(Deserialize, Serialize)] +#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))] +#[cfg_attr(feature = "serialize-serde", derive(Deserialize, Serialize))] pub struct Backtrace { frames: Vec, } @@ -36,8 +21,8 @@ pub struct Backtrace { /// This type is returned as a list from `Backtrace::frames` and represents one /// stack frame in a captured backtrace. #[derive(Clone)] -//~ HACK1 #[derive(RustcDecodable, RustcEncodable)] -//~ HACK2 #[derive(Deserialize, Serialize)] +#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))] +#[cfg_attr(feature = "serialize-serde", derive(Deserialize, Serialize))] pub struct BacktraceFrame { ip: usize, symbol_address: usize, @@ -49,8 +34,8 @@ pub struct BacktraceFrame { /// This type is returned as a list from `BacktraceFrame::symbols` and /// represents the metadata for a symbol in a backtrace. #[derive(Clone)] -//~ HACK1 #[derive(RustcDecodable, RustcEncodable)] -//~ HACK2 #[derive(Deserialize, Serialize)] +#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))] +#[cfg_attr(feature = "serialize-serde", derive(Deserialize, Serialize))] pub struct BacktraceSymbol { name: Option>, addr: Option, diff --git a/src/vendor/backtrace/src/dylib.rs b/src/vendor/backtrace/src/dylib.rs index 10f8c1cebf..34fb0bf16e 100644 --- a/src/vendor/backtrace/src/dylib.rs +++ b/src/vendor/backtrace/src/dylib.rs @@ -3,7 +3,7 @@ use std::marker; use std::mem; use std::sync::atomic::{AtomicUsize, Ordering}; -use libc::{self, c_void}; +use libc::{self, c_char, c_void}; pub struct Dylib { pub init: AtomicUsize, @@ -27,7 +27,7 @@ impl Dylib { return true } let name = CString::new(path).unwrap(); - let ptr = libc::dlopen(name.as_ptr(), libc::RTLD_LAZY); + let ptr = libc::dlopen(name.as_ptr() as *const c_char, libc::RTLD_LAZY); if ptr.is_null() { return false } @@ -68,16 +68,3 @@ unsafe fn fetch(handle: *mut c_void, name: *const u8) -> usize { ptr as usize } } - -macro_rules! dlsym { - (extern { - $(fn $name:ident($($arg:ident: $t:ty),*) -> $ret:ty;)* - }) => ($( - static $name: ::dylib::Symbol $ret> = - ::dylib::Symbol { - name: concat!(stringify!($name), "\0"), - addr: ::std::sync::atomic::ATOMIC_USIZE_INIT, - _marker: ::std::marker::PhantomData, - }; - )*) -} diff --git a/src/vendor/backtrace/src/lib.rs b/src/vendor/backtrace/src/lib.rs index e69b56a7ca..c9b9c4eb1b 100644 --- a/src/vendor/backtrace/src/lib.rs +++ b/src/vendor/backtrace/src/lib.rs @@ -70,13 +70,17 @@ #![deny(warnings)] extern crate libc; -#[cfg(feature = "kernel32-sys")] extern crate kernel32; -#[cfg(feature = "winapi")] extern crate winapi; -#[cfg(feature = "dbghelp")] extern crate dbghelp; +#[cfg(all(windows, feature = "kernel32-sys"))] extern crate kernel32; +#[cfg(all(windows, feature = "winapi"))] extern crate winapi; +#[cfg(all(windows, feature = "dbghelp"))] extern crate dbghelp; #[cfg(feature = "serde")] extern crate serde; +#[cfg(feature = "serde_derive")] +#[cfg_attr(feature = "serde_derive", macro_use)] +extern crate serde_derive; + #[cfg(feature = "rustc-serialize")] extern crate rustc_serialize; @@ -85,6 +89,9 @@ extern crate cfg_if; extern crate rustc_demangle; +#[cfg(feature = "cpp_demangle")] +extern crate cpp_demangle; + #[allow(dead_code)] // not used everywhere #[cfg(unix)] #[macro_use] @@ -97,9 +104,7 @@ pub use symbolize::{resolve, Symbol, SymbolName}; mod symbolize; pub use capture::{Backtrace, BacktraceFrame, BacktraceSymbol}; -mod capture { - include!(concat!(env!("OUT_DIR"), "/capture.rs")); -} +mod capture; #[allow(dead_code)] struct Bomb { diff --git a/src/vendor/backtrace/src/symbolize/coresymbolication.rs b/src/vendor/backtrace/src/symbolize/coresymbolication.rs index f0c21376b7..d26835d7f4 100644 --- a/src/vendor/backtrace/src/symbolize/coresymbolication.rs +++ b/src/vendor/backtrace/src/symbolize/coresymbolication.rs @@ -95,6 +95,19 @@ impl Symbol { static CORESYMBOLICATION: Dylib = Dylib { init: ATOMIC_USIZE_INIT }; +macro_rules! dlsym { + (extern { + $(fn $name:ident($($arg:ident: $t:ty),*) -> $ret:ty;)* + }) => ($( + static $name: ::dylib::Symbol $ret> = + ::dylib::Symbol { + name: concat!(stringify!($name), "\0"), + addr: ::std::sync::atomic::ATOMIC_USIZE_INIT, + _marker: ::std::marker::PhantomData, + }; + )*) +} + dlsym! { extern { fn CSSymbolicatorCreateWithPid(pid: c_int) -> CSTypeRef; diff --git a/src/vendor/backtrace/src/symbolize/libbacktrace.rs b/src/vendor/backtrace/src/symbolize/libbacktrace.rs index d1c14f67b7..865f691810 100644 --- a/src/vendor/backtrace/src/symbolize/libbacktrace.rs +++ b/src/vendor/backtrace/src/symbolize/libbacktrace.rs @@ -22,8 +22,6 @@ use std::sync::{ONCE_INIT, Once}; use SymbolName; -type FileLine = (*const c_char, c_int); - pub enum Symbol { Syminfo { pc: uintptr_t, diff --git a/src/vendor/backtrace/src/symbolize/mod.rs b/src/vendor/backtrace/src/symbolize/mod.rs index cf81c6d31a..23c1c69719 100644 --- a/src/vendor/backtrace/src/symbolize/mod.rs +++ b/src/vendor/backtrace/src/symbolize/mod.rs @@ -1,8 +1,10 @@ use std::fmt; +#[cfg(not(feature = "cpp_demangle"))] +use std::marker::PhantomData; use std::os::raw::c_void; use std::path::Path; use std::str; -use rustc_demangle::{demangle, Demangle}; +use rustc_demangle::{try_demangle, Demangle}; /// Resolve an address to a symbol, passing the symbol to the specified /// closure. @@ -108,26 +110,76 @@ impl fmt::Debug for Symbol { } } + +cfg_if! { + if #[cfg(feature = "cpp_demangle")] { + // Maybe a parsed C++ symbol, if parsing the mangled symbol as Rust + // failed. + struct OptionCppSymbol<'a>(Option<::cpp_demangle::BorrowedSymbol<'a>>); + + impl<'a> OptionCppSymbol<'a> { + fn parse(input: &'a [u8]) -> OptionCppSymbol<'a> { + OptionCppSymbol(::cpp_demangle::BorrowedSymbol::new(input).ok()) + } + + fn none() -> OptionCppSymbol<'a> { + OptionCppSymbol(None) + } + } + } else { + // Make sure to keep this zero-sized, so that the `cpp_demangle` feature + // has no cost when disabled. + struct OptionCppSymbol<'a>(PhantomData<&'a ()>); + + impl<'a> OptionCppSymbol<'a> { + fn parse(_: &'a [u8]) -> OptionCppSymbol<'a> { + OptionCppSymbol(PhantomData) + } + + fn none() -> OptionCppSymbol<'a> { + OptionCppSymbol(PhantomData) + } + } + } +} + /// A wrapper around a symbol name to provide ergonomic accessors to the /// demangled name, the raw bytes, the raw string, etc. +// Allow dead code for when the `cpp_demangle` feature is not enabled. +#[allow(dead_code)] pub struct SymbolName<'a> { bytes: &'a [u8], demangled: Option>, + cpp_demangled: OptionCppSymbol<'a>, } impl<'a> SymbolName<'a> { /// Creates a new symbol name from the raw underlying bytes. pub fn new(bytes: &'a [u8]) -> SymbolName<'a> { - let demangled = str::from_utf8(bytes).ok().map(demangle); + let str_bytes = str::from_utf8(bytes).ok(); + let demangled = str_bytes.and_then(|s| try_demangle(s).ok()); + + let cpp = if demangled.is_none() { + OptionCppSymbol::parse(bytes) + } else { + OptionCppSymbol::none() + }; + SymbolName { bytes: bytes, demangled: demangled, + cpp_demangled: cpp, } } - /// Returns the raw symbol name as `&str` if the symbols is valid utf-8. + /// Returns the raw symbol name as a `str` if the symbols is valid utf-8. pub fn as_str(&self) -> Option<&'a str> { - self.demangled.as_ref().map(|s| s.as_str()) + self.demangled + .as_ref() + .map(|s| s.as_str()) + .or_else(|| { + str::from_utf8(self.bytes).ok() + }) } /// Returns the raw symbol name as a list of bytes @@ -136,22 +188,64 @@ impl<'a> SymbolName<'a> { } } -impl<'a> fmt::Display for SymbolName<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if let Some(ref s) = self.demangled { - s.fmt(f) - } else { - String::from_utf8_lossy(self.bytes).fmt(f) +cfg_if! { + if #[cfg(feature = "cpp_demangle")] { + impl<'a> fmt::Display for SymbolName<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if let Some(ref s) = self.demangled { + s.fmt(f) + } else if let Some(ref cpp) = self.cpp_demangled.0 { + cpp.fmt(f) + } else { + String::from_utf8_lossy(self.bytes).fmt(f) + } + } + } + } else { + impl<'a> fmt::Display for SymbolName<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if let Some(ref s) = self.demangled { + s.fmt(f) + } else { + String::from_utf8_lossy(self.bytes).fmt(f) + } + } } } } -impl<'a> fmt::Debug for SymbolName<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if let Some(ref s) = self.demangled { - s.fmt(f) - } else { - String::from_utf8_lossy(self.bytes).fmt(f) +cfg_if! { + if #[cfg(feature = "cpp_demangle")] { + impl<'a> fmt::Debug for SymbolName<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use std::fmt::Write; + + if let Some(ref s) = self.demangled { + return s.fmt(f) + } + + // This may to print if the demangled symbol isn't actually + // valid, so handle the error here gracefully by not propagating + // it outwards. + if let Some(ref cpp) = self.cpp_demangled.0 { + let mut s = String::new(); + if write!(s, "{}", cpp).is_ok() { + return s.fmt(f) + } + } + + String::from_utf8_lossy(self.bytes).fmt(f) + } + } + } else { + impl<'a> fmt::Debug for SymbolName<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if let Some(ref s) = self.demangled { + s.fmt(f) + } else { + String::from_utf8_lossy(self.bytes).fmt(f) + } + } } } } @@ -164,12 +258,14 @@ cfg_if! { } else if #[cfg(all(feature = "libbacktrace", unix, not(target_os = "emscripten"), - not(target_os = "macos")))] { + not(target_os = "macos"), + not(target_os = "ios")))] { mod libbacktrace; use self::libbacktrace::resolve as resolve_imp; use self::libbacktrace::Symbol as SymbolImp; } else if #[cfg(all(feature = "coresymbolication", - target_os = "macos"))] { + any(target_os = "macos", + target_os = "ios")))] { mod coresymbolication; use self::coresymbolication::resolve as resolve_imp; use self::coresymbolication::Symbol as SymbolImp; @@ -185,4 +281,3 @@ cfg_if! { use self::noop::Symbol as SymbolImp; } } - diff --git a/src/vendor/backtrace/tests/smoke.rs b/src/vendor/backtrace/tests/smoke.rs index 19495bf2f9..bef71af37e 100644 --- a/src/vendor/backtrace/tests/smoke.rs +++ b/src/vendor/backtrace/tests/smoke.rs @@ -6,8 +6,8 @@ use std::thread; static LIBUNWIND: bool = cfg!(all(unix, feature = "libunwind")); static UNIX_BACKTRACE: bool = cfg!(all(unix, feature = "unix-backtrace")); static LIBBACKTRACE: bool = cfg!(all(unix, feature = "libbacktrace")) && - !cfg!(target_os = "macos"); -static CORESYMBOLICATION: bool = cfg!(all(target_os = "macos", + !cfg!(target_os = "macos") && !cfg!(target_os = "ios"); +static CORESYMBOLICATION: bool = cfg!(all(any(target_os = "macos", target_os = "ios"), feature = "coresymbolication")); static DLADDR: bool = cfg!(all(unix, feature = "dladdr")); static DBGHELP: bool = cfg!(all(windows, feature = "dbghelp")); @@ -160,7 +160,7 @@ fn is_serde() { extern crate serde; fn is_serialize() {} - fn is_deserialize() {} + fn is_deserialize() {} is_serialize::(); is_deserialize::(); diff --git a/src/vendor/bitflags-0.5.0/.cargo-checksum.json b/src/vendor/bitflags-0.5.0/.cargo-checksum.json deleted file mode 100644 index 4ade2ef41e..0000000000 --- a/src/vendor/bitflags-0.5.0/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"c1e953ee360e77de57f7b02f1b7880bd6a3dc22d1a69e953c2ac2c52cc52d247",".travis.yml":"42b20b53c70c4a9cbcb92d43cad2b6cb038eed9b0b080fef05b1ddbc5997fbd8","Cargo.toml":"7ffae436f3607c3745813ba353b058e1e954ba70ae8d38fc1c591382f93e071e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"2f134d4b4304d7754dc97f44e3d5082930e4994da29c93fad85993c6fc6247b3","src/lib.rs":"89e2153afde8f23a7a67d3e20f060fb6b5669cb68a556e4f76d26c25093aac75","tests/external.rs":"cfd86bac515bf6ea24c9d0687ec2af23da48833d1bcf4f753f75c2ad3cc2de60","tests/external_no_std.rs":"60bdc06f04727a6fa8bd19649e2a08c105b132c5e1e30ac900ce50c21dc6db7b"},"package":"4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23"} \ No newline at end of file diff --git a/src/vendor/bitflags-0.5.0/.travis.yml b/src/vendor/bitflags-0.5.0/.travis.yml deleted file mode 100644 index e2141c8902..0000000000 --- a/src/vendor/bitflags-0.5.0/.travis.yml +++ /dev/null @@ -1,30 +0,0 @@ -language: rust -rust: - - stable - - beta - - nightly -sudo: false -script: - - cargo build --verbose - - cargo test --verbose - - | - [ "$TRAVIS_RUST_VERSION" = "1.0.0" ] || cargo test --verbose --features no_std - - if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then - cargo test --verbose --features assignment_operators; - cargo test --verbose --features "no_std assignment_operators"; - fi - - cargo doc -after_success: | - [ $TRAVIS_BRANCH = master ] && - [ $TRAVIS_PULL_REQUEST = false ] && - [ $TRAVIS_RUST_VERSION = nightly ] && - echo '' > target/doc/index.html && - pip install ghp-import --user $USER && - $HOME/.local/bin/ghp-import -n target/doc && - git push -qf https://${TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages -env: - global: - secure: d+l63TtlF6cfFVDGauYRexgx4lBww4ORqqK4Vt75nWbiCbjZYsKXbcTUdhAr193nIVGiNW50A8SekM01F3EngHwHwr6u5kFleOggm+HA0kkBVeX+k2A4WCVVfYI+gth+zk99WaF8h46MA0evhx6FYDoqeyl9oqmVifI4kaqhMwc= -notifications: - email: - on_success: never diff --git a/src/vendor/bitflags-0.5.0/Cargo.toml b/src/vendor/bitflags-0.5.0/Cargo.toml deleted file mode 100644 index dc89932ee7..0000000000 --- a/src/vendor/bitflags-0.5.0/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] - -name = "bitflags" -version = "0.5.0" -authors = ["The Rust Project Developers"] -license = "MIT/Apache-2.0" -readme = "README.md" -repository = "https://github.com/rust-lang/bitflags" -homepage = "https://github.com/rust-lang/bitflags" -documentation = "https://doc.rust-lang.org/bitflags" -description = """ -A macro to generate structures which behave like bitflags. -""" - -[features] -no_std = [] -assignment_operators = [] diff --git a/src/vendor/bitflags-0.5.0/README.md b/src/vendor/bitflags-0.5.0/README.md deleted file mode 100644 index a273a6cd30..0000000000 --- a/src/vendor/bitflags-0.5.0/README.md +++ /dev/null @@ -1,25 +0,0 @@ -bitflags -======== - -A Rust macro to generate structures which behave like a set of bitflags - -[![Build Status](https://travis-ci.org/rust-lang-nursery/bitflags.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/bitflags) - -[Documentation](https://doc.rust-lang.org/bitflags) - -## Usage - -Add this to your `Cargo.toml`: - -```toml -[dependencies] - -bitflags = "0.3" -``` - -and this to your crate root: - -```rust -#[macro_use] -extern crate bitflags; -``` diff --git a/src/vendor/bitflags-0.5.0/src/lib.rs b/src/vendor/bitflags-0.5.0/src/lib.rs deleted file mode 100644 index 91c362b1cd..0000000000 --- a/src/vendor/bitflags-0.5.0/src/lib.rs +++ /dev/null @@ -1,771 +0,0 @@ -// 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. - -//! A typesafe bitmask flag generator. - -// Compile the crate with no_std if possible. The "no_std" feature can be -// removed once no_std becomes available in 1.6.0 stable. In the meantime no_std -// must be disabled by default to allow the crate to work on older rust versions. -#![cfg_attr(all(feature = "no_std", not(test)), no_std)] - -#![cfg_attr(feature = "assignment_operators", feature(augmented_assignments))] -#![cfg_attr(all(feature = "assignment_operators", test), feature(op_assign_traits))] - -#[cfg(all(feature = "no_std", not(test)))] -#[macro_use] -extern crate core as std; - -// Re-export libstd/libcore using an alias so that the macros can work in no_std -// crates while remaining compatible with normal crates. -#[doc(hidden)] -pub use std as __core; - -/// The `bitflags!` macro generates a `struct` that holds a set of C-style -/// bitmask flags. It is useful for creating typesafe wrappers for C APIs. -/// -/// The flags should only be defined for integer types, otherwise unexpected -/// type errors may occur at compile time. -/// -/// # Example -/// -/// ```{.rust} -/// #![cfg_attr(feature = "assignment_operators", feature(augmented_assignments, op_assign_traits))] -/// #[macro_use] -/// extern crate bitflags; -/// -/// bitflags! { -/// flags Flags: u32 { -/// const FLAG_A = 0b00000001, -/// const FLAG_B = 0b00000010, -/// const FLAG_C = 0b00000100, -/// const FLAG_ABC = FLAG_A.bits -/// | FLAG_B.bits -/// | FLAG_C.bits, -/// } -/// } -/// -/// fn main() { -/// let e1 = FLAG_A | FLAG_C; -/// let e2 = FLAG_B | FLAG_C; -/// assert!((e1 | e2) == FLAG_ABC); // union -/// assert!((e1 & e2) == FLAG_C); // intersection -/// assert!((e1 - e2) == FLAG_A); // set difference -/// assert!(!e2 == FLAG_A); // set complement -/// } -/// ``` -/// -/// The generated `struct`s can also be extended with type and trait -/// implementations: -/// -/// ```{.rust} -/// #![cfg_attr(feature = "assignment_operators", feature(augmented_assignments, op_assign_traits))] -/// #[macro_use] -/// extern crate bitflags; -/// -/// use std::fmt; -/// -/// bitflags! { -/// flags Flags: u32 { -/// const FLAG_A = 0b00000001, -/// const FLAG_B = 0b00000010, -/// } -/// } -/// -/// impl Flags { -/// pub fn clear(&mut self) { -/// self.bits = 0; // The `bits` field can be accessed from within the -/// // same module where the `bitflags!` macro was invoked. -/// } -/// } -/// -/// impl fmt::Display for Flags { -/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -/// write!(f, "hi!") -/// } -/// } -/// -/// fn main() { -/// let mut flags = FLAG_A | FLAG_B; -/// flags.clear(); -/// assert!(flags.is_empty()); -/// assert_eq!(format!("{}", flags), "hi!"); -/// assert_eq!(format!("{:?}", FLAG_A | FLAG_B), "FLAG_A | FLAG_B"); -/// assert_eq!(format!("{:?}", FLAG_B), "FLAG_B"); -/// } -/// ``` -/// -/// # Visibility -/// -/// The generated struct and its associated flag constants are not exported -/// out of the current module by default. A definition can be exported out of -/// the current module by adding `pub` before `flags`: -/// -/// ```{.rust},ignore -/// #[macro_use] -/// extern crate bitflags; -/// -/// mod example { -/// bitflags! { -/// pub flags Flags1: u32 { -/// const FLAG_A = 0b00000001, -/// } -/// } -/// bitflags! { -/// flags Flags2: u32 { -/// const FLAG_B = 0b00000010, -/// } -/// } -/// } -/// -/// fn main() { -/// let flag1 = example::FLAG_A; -/// let flag2 = example::FLAG_B; // error: const `FLAG_B` is private -/// } -/// ``` -/// -/// # Attributes -/// -/// Attributes can be attached to the generated `struct` by placing them -/// before the `flags` keyword. -/// -/// # Trait implementations -/// -/// The `Copy`, `Clone`, `PartialEq`, `Eq`, `PartialOrd`, `Ord` and `Hash` -/// traits automatically derived for the `struct` using the `derive` attribute. -/// Additional traits can be derived by providing an explicit `derive` -/// attribute on `flags`. -/// -/// The `FromIterator` trait is implemented for the `struct`, too, calculating -/// the union of the instances of the `struct` iterated over. -/// -/// The `Debug` trait is also implemented by displaying the bits value of the -/// internal struct. -/// -/// ## Operators -/// -/// The following operator traits are implemented for the generated `struct`: -/// -/// - `BitOr` and `BitOrAssign`: union -/// - `BitAnd` and `BitAndAssign`: intersection -/// - `BitXor` and `BitXorAssign`: toggle -/// - `Sub` and `SubAssign`: set difference -/// - `Not`: set complement -/// -/// As long as the assignment operators are unstable rust feature they are only -/// available with the crate feature `assignment_ops` enabled. -/// -/// # Methods -/// -/// The following methods are defined for the generated `struct`: -/// -/// - `empty`: an empty set of flags -/// - `all`: the set of all flags -/// - `bits`: the raw value of the flags currently stored -/// - `from_bits`: convert from underlying bit representation, unless that -/// representation contains bits that do not correspond to a flag -/// - `from_bits_truncate`: convert from underlying bit representation, dropping -/// any bits that do not correspond to flags -/// - `is_empty`: `true` if no flags are currently stored -/// - `is_all`: `true` if all flags are currently set -/// - `intersects`: `true` if there are flags common to both `self` and `other` -/// - `contains`: `true` all of the flags in `other` are contained within `self` -/// - `insert`: inserts the specified flags in-place -/// - `remove`: removes the specified flags in-place -/// - `toggle`: the specified flags will be inserted if not present, and removed -/// if they are. -#[macro_export] -macro_rules! bitflags { - ($(#[$attr:meta])* pub flags $BitFlags:ident: $T:ty { - $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+ - }) => { - #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)] - $(#[$attr])* - pub struct $BitFlags { - bits: $T, - } - - $($(#[$Flag_attr])* pub const $Flag: $BitFlags = $BitFlags { bits: $value };)+ - - bitflags! { - @_impl flags $BitFlags: $T { - $($(#[$Flag_attr])* const $Flag = $value),+ - } - } - }; - ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty { - $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+ - }) => { - #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)] - $(#[$attr])* - struct $BitFlags { - bits: $T, - } - - $($(#[$Flag_attr])* const $Flag: $BitFlags = $BitFlags { bits: $value };)+ - - bitflags! { - @_impl flags $BitFlags: $T { - $($(#[$Flag_attr])* const $Flag = $value),+ - } - } - }; - (@_impl flags $BitFlags:ident: $T:ty { - $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+ - }) => { - impl $crate::__core::fmt::Debug for $BitFlags { - fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result { - // This convoluted approach is to handle #[cfg]-based flag - // omission correctly. Some of the $Flag variants may not be - // defined in this module so we create an inner module which - // defines *all* flags to the value of 0. We then create a - // second inner module that defines all of the flags with #[cfg] - // to their real values. Afterwards the glob will import - // variants from the second inner module, shadowing all - // defined variants, leaving only the undefined ones with the - // bit value of 0. - #[allow(dead_code)] - #[allow(unused_assignments)] - mod dummy { - // We can't use the real $BitFlags struct because it may be - // private, which prevents us from using it to define - // public constants. - pub struct $BitFlags { - bits: $T, - } - mod real_flags { - use super::$BitFlags; - $($(#[$Flag_attr])* pub const $Flag: $BitFlags = $BitFlags { bits: $value };)+ - } - // Now we define the "undefined" versions of the flags. - // This way, all the names exist, even if some are #[cfg]ed - // out. - $(const $Flag: $BitFlags = $BitFlags { bits: 0 };)+ - - #[inline] - pub fn fmt(self_: $T, - f: &mut $crate::__core::fmt::Formatter) - -> $crate::__core::fmt::Result { - // Now we import the real values for the flags. - // Only ones that are #[cfg]ed out will be 0. - use self::real_flags::*; - - let mut first = true; - $( - // $Flag.bits == 0 means that $Flag doesn't exist - if $Flag.bits != 0 && self_ & $Flag.bits == $Flag.bits { - if !first { - try!(f.write_str(" | ")); - } - first = false; - try!(f.write_str(stringify!($Flag))); - } - )+ - Ok(()) - } - } - dummy::fmt(self.bits, f) - } - } - - #[allow(dead_code)] - impl $BitFlags { - /// Returns an empty set of flags. - #[inline] - pub fn empty() -> $BitFlags { - $BitFlags { bits: 0 } - } - - /// Returns the set containing all flags. - #[inline] - pub fn all() -> $BitFlags { - // See above `dummy` module for why this approach is taken. - #[allow(dead_code)] - mod dummy { - pub struct $BitFlags { - bits: $T, - } - mod real_flags { - use super::$BitFlags; - $($(#[$Flag_attr])* pub const $Flag: $BitFlags = $BitFlags { bits: $value };)+ - } - $(const $Flag: $BitFlags = $BitFlags { bits: 0 };)+ - - #[inline] - pub fn all() -> $T { - use self::real_flags::*; - $($Flag.bits)|+ - } - } - $BitFlags { bits: dummy::all() } - } - - /// Returns the raw value of the flags currently stored. - #[inline] - pub fn bits(&self) -> $T { - self.bits - } - - /// Convert from underlying bit representation, unless that - /// representation contains bits that do not correspond to a flag. - #[inline] - pub fn from_bits(bits: $T) -> $crate::__core::option::Option<$BitFlags> { - if (bits & !$BitFlags::all().bits()) != 0 { - $crate::__core::option::Option::None - } else { - $crate::__core::option::Option::Some($BitFlags { bits: bits }) - } - } - - /// Convert from underlying bit representation, dropping any bits - /// that do not correspond to flags. - #[inline] - pub fn from_bits_truncate(bits: $T) -> $BitFlags { - $BitFlags { bits: bits } & $BitFlags::all() - } - - /// Returns `true` if no flags are currently stored. - #[inline] - pub fn is_empty(&self) -> bool { - *self == $BitFlags::empty() - } - - /// Returns `true` if all flags are currently set. - #[inline] - pub fn is_all(&self) -> bool { - *self == $BitFlags::all() - } - - /// Returns `true` if there are flags common to both `self` and `other`. - #[inline] - pub fn intersects(&self, other: $BitFlags) -> bool { - !(*self & other).is_empty() - } - - /// Returns `true` all of the flags in `other` are contained within `self`. - #[inline] - pub fn contains(&self, other: $BitFlags) -> bool { - (*self & other) == other - } - - /// Inserts the specified flags in-place. - #[inline] - pub fn insert(&mut self, other: $BitFlags) { - self.bits |= other.bits; - } - - /// Removes the specified flags in-place. - #[inline] - pub fn remove(&mut self, other: $BitFlags) { - self.bits &= !other.bits; - } - - /// Toggles the specified flags in-place. - #[inline] - pub fn toggle(&mut self, other: $BitFlags) { - self.bits ^= other.bits; - } - } - - impl $crate::__core::ops::BitOr for $BitFlags { - type Output = $BitFlags; - - /// Returns the union of the two sets of flags. - #[inline] - fn bitor(self, other: $BitFlags) -> $BitFlags { - $BitFlags { bits: self.bits | other.bits } - } - } - - #[cfg(feature="assignment_operators")] - impl $crate::__core::ops::BitOrAssign for $BitFlags { - - /// Adds the set of flags. - #[inline] - fn bitor_assign(&mut self, other: $BitFlags) { - self.bits |= other.bits; - } - } - - impl $crate::__core::ops::BitXor for $BitFlags { - type Output = $BitFlags; - - /// Returns the left flags, but with all the right flags toggled. - #[inline] - fn bitxor(self, other: $BitFlags) -> $BitFlags { - $BitFlags { bits: self.bits ^ other.bits } - } - } - - #[cfg(feature="assignment_operators")] - impl $crate::__core::ops::BitXorAssign for $BitFlags { - - /// Toggles the set of flags. - #[inline] - fn bitxor_assign(&mut self, other: $BitFlags) { - self.bits ^= other.bits; - } - } - - impl $crate::__core::ops::BitAnd for $BitFlags { - type Output = $BitFlags; - - /// Returns the intersection between the two sets of flags. - #[inline] - fn bitand(self, other: $BitFlags) -> $BitFlags { - $BitFlags { bits: self.bits & other.bits } - } - } - - #[cfg(feature="assignment_operators")] - impl $crate::__core::ops::BitAndAssign for $BitFlags { - - /// Disables all flags disabled in the set. - #[inline] - fn bitand_assign(&mut self, other: $BitFlags) { - self.bits &= other.bits; - } - } - - impl $crate::__core::ops::Sub for $BitFlags { - type Output = $BitFlags; - - /// Returns the set difference of the two sets of flags. - #[inline] - fn sub(self, other: $BitFlags) -> $BitFlags { - $BitFlags { bits: self.bits & !other.bits } - } - } - - #[cfg(feature="assignment_operators")] - impl $crate::__core::ops::SubAssign for $BitFlags { - - /// Disables all flags enabled in the set. - #[inline] - fn sub_assign(&mut self, other: $BitFlags) { - self.bits &= !other.bits; - } - } - - impl $crate::__core::ops::Not for $BitFlags { - type Output = $BitFlags; - - /// Returns the complement of this set of flags. - #[inline] - fn not(self) -> $BitFlags { - $BitFlags { bits: !self.bits } & $BitFlags::all() - } - } - - impl $crate::__core::iter::FromIterator<$BitFlags> for $BitFlags { - fn from_iter>(iterator: T) -> $BitFlags { - let mut result = Self::empty(); - for item in iterator { - result.insert(item) - } - result - } - } - }; - ($(#[$attr:meta])* pub flags $BitFlags:ident: $T:ty { - $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+, - }) => { - bitflags! { - $(#[$attr])* - pub flags $BitFlags: $T { - $($(#[$Flag_attr])* const $Flag = $value),+ - } - } - }; - ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty { - $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+, - }) => { - bitflags! { - $(#[$attr])* - flags $BitFlags: $T { - $($(#[$Flag_attr])* const $Flag = $value),+ - } - } - }; -} - -#[cfg(test)] -#[allow(non_upper_case_globals, dead_code)] -mod tests { - use std::hash::{SipHasher, Hash, Hasher}; - - bitflags! { - #[doc = "> The first principle is that you must not fool yourself — and"] - #[doc = "> you are the easiest person to fool."] - #[doc = "> "] - #[doc = "> - Richard Feynman"] - flags Flags: u32 { - const FlagA = 0b00000001, - #[doc = " macros are way better at generating code than trans is"] - const FlagB = 0b00000010, - const FlagC = 0b00000100, - #[doc = "* cmr bed"] - #[doc = "* strcat table"] - #[doc = " wait what?"] - const FlagABC = FlagA.bits - | FlagB.bits - | FlagC.bits, - } - } - - bitflags! { - flags _CfgFlags: u32 { - #[cfg(windows)] - const _CfgA = 0b01, - #[cfg(unix)] - const _CfgB = 0b01, - #[cfg(windows)] - const _CfgC = _CfgA.bits | 0b10, - } - } - - bitflags! { - flags AnotherSetOfFlags: i8 { - const AnotherFlag = -1_i8, - } - } - - #[test] - fn test_bits(){ - assert_eq!(Flags::empty().bits(), 0b00000000); - assert_eq!(FlagA.bits(), 0b00000001); - assert_eq!(FlagABC.bits(), 0b00000111); - - assert_eq!(AnotherSetOfFlags::empty().bits(), 0b00); - assert_eq!(AnotherFlag.bits(), !0_i8); - } - - #[test] - fn test_from_bits() { - assert!(Flags::from_bits(0) == Some(Flags::empty())); - assert!(Flags::from_bits(0b1) == Some(FlagA)); - assert!(Flags::from_bits(0b10) == Some(FlagB)); - assert!(Flags::from_bits(0b11) == Some(FlagA | FlagB)); - assert!(Flags::from_bits(0b1000) == None); - - assert!(AnotherSetOfFlags::from_bits(!0_i8) == Some(AnotherFlag)); - } - - #[test] - fn test_from_bits_truncate() { - assert!(Flags::from_bits_truncate(0) == Flags::empty()); - assert!(Flags::from_bits_truncate(0b1) == FlagA); - assert!(Flags::from_bits_truncate(0b10) == FlagB); - assert!(Flags::from_bits_truncate(0b11) == (FlagA | FlagB)); - assert!(Flags::from_bits_truncate(0b1000) == Flags::empty()); - assert!(Flags::from_bits_truncate(0b1001) == FlagA); - - assert!(AnotherSetOfFlags::from_bits_truncate(0_i8) == AnotherSetOfFlags::empty()); - } - - #[test] - fn test_is_empty(){ - assert!(Flags::empty().is_empty()); - assert!(!FlagA.is_empty()); - assert!(!FlagABC.is_empty()); - - assert!(!AnotherFlag.is_empty()); - } - - #[test] - fn test_is_all() { - assert!(Flags::all().is_all()); - assert!(!FlagA.is_all()); - assert!(FlagABC.is_all()); - - assert!(AnotherFlag.is_all()); - } - - #[test] - fn test_two_empties_do_not_intersect() { - let e1 = Flags::empty(); - let e2 = Flags::empty(); - assert!(!e1.intersects(e2)); - - assert!(AnotherFlag.intersects(AnotherFlag)); - } - - #[test] - fn test_empty_does_not_intersect_with_full() { - let e1 = Flags::empty(); - let e2 = FlagABC; - assert!(!e1.intersects(e2)); - } - - #[test] - fn test_disjoint_intersects() { - let e1 = FlagA; - let e2 = FlagB; - assert!(!e1.intersects(e2)); - } - - #[test] - fn test_overlapping_intersects() { - let e1 = FlagA; - let e2 = FlagA | FlagB; - assert!(e1.intersects(e2)); - } - - #[test] - fn test_contains() { - let e1 = FlagA; - let e2 = FlagA | FlagB; - assert!(!e1.contains(e2)); - assert!(e2.contains(e1)); - assert!(FlagABC.contains(e2)); - - assert!(AnotherFlag.contains(AnotherFlag)); - } - - #[test] - fn test_insert(){ - let mut e1 = FlagA; - let e2 = FlagA | FlagB; - e1.insert(e2); - assert!(e1 == e2); - - let mut e3 = AnotherSetOfFlags::empty(); - e3.insert(AnotherFlag); - assert!(e3 == AnotherFlag); - } - - #[test] - fn test_remove(){ - let mut e1 = FlagA | FlagB; - let e2 = FlagA | FlagC; - e1.remove(e2); - assert!(e1 == FlagB); - - let mut e3 = AnotherFlag; - e3.remove(AnotherFlag); - assert!(e3 == AnotherSetOfFlags::empty()); - } - - #[test] - fn test_operators() { - let e1 = FlagA | FlagC; - let e2 = FlagB | FlagC; - assert!((e1 | e2) == FlagABC); // union - assert!((e1 & e2) == FlagC); // intersection - assert!((e1 - e2) == FlagA); // set difference - assert!(!e2 == FlagA); // set complement - assert!(e1 ^ e2 == FlagA | FlagB); // toggle - let mut e3 = e1; - e3.toggle(e2); - assert!(e3 == FlagA | FlagB); - - let mut m4 = AnotherSetOfFlags::empty(); - m4.toggle(AnotherSetOfFlags::empty()); - assert!(m4 == AnotherSetOfFlags::empty()); - } - - #[cfg(feature="assignment_operators")] - #[test] - fn test_assignment_operators() { - let mut m1 = Flags::empty(); - let e1 = FlagA | FlagC; - // union - m1 |= FlagA; - assert!(m1 == FlagA); - // intersection - m1 &= e1; - assert!(m1 == FlagA); - // set difference - m1 -= m1; - assert!(m1 == Flags::empty()); - // toggle - m1 ^= e1; - assert!(m1 == e1); - } - - #[test] - fn test_from_iterator() { - assert_eq!([].iter().cloned().collect::(), Flags::empty()); - assert_eq!([FlagA, FlagB].iter().cloned().collect::(), FlagA | FlagB); - assert_eq!([FlagA, FlagABC].iter().cloned().collect::(), FlagABC); - } - - #[test] - fn test_lt() { - let mut a = Flags::empty(); - let mut b = Flags::empty(); - - assert!(!(a < b) && !(b < a)); - b = FlagB; - assert!(a < b); - a = FlagC; - assert!(!(a < b) && b < a); - b = FlagC | FlagB; - assert!(a < b); - } - - #[test] - fn test_ord() { - let mut a = Flags::empty(); - let mut b = Flags::empty(); - - assert!(a <= b && a >= b); - a = FlagA; - assert!(a > b && a >= b); - assert!(b < a && b <= a); - b = FlagB; - assert!(b > a && b >= a); - assert!(a < b && a <= b); - } - - fn hash(t: &T) -> u64 { - let mut s = SipHasher::new_with_keys(0, 0); - t.hash(&mut s); - s.finish() - } - - #[test] - fn test_hash() { - let mut x = Flags::empty(); - let mut y = Flags::empty(); - assert!(hash(&x) == hash(&y)); - x = Flags::all(); - y = FlagABC; - assert!(hash(&x) == hash(&y)); - } - - #[test] - fn test_debug() { - assert_eq!(format!("{:?}", FlagA | FlagB), "FlagA | FlagB"); - assert_eq!(format!("{:?}", FlagABC), "FlagA | FlagB | FlagC | FlagABC"); - } - - mod submodule { - bitflags! { - pub flags PublicFlags: i8 { - const FlagX = 0, - } - } - bitflags! { - flags PrivateFlags: i8 { - const FlagY = 0, - } - } - - #[test] - fn test_private() { - let _ = FlagY; - } - } - - #[test] - fn test_public() { - let _ = submodule::FlagX; - } -} diff --git a/src/vendor/bitflags-0.5.0/tests/external.rs b/src/vendor/bitflags-0.5.0/tests/external.rs deleted file mode 100644 index 8e06e1612b..0000000000 --- a/src/vendor/bitflags-0.5.0/tests/external.rs +++ /dev/null @@ -1,22 +0,0 @@ -#![allow(dead_code)] -#![cfg_attr(all(feature = "assignment_operators", test), feature(op_assign_traits))] - -#[macro_use] -extern crate bitflags; - -bitflags! { - /// baz - flags Flags: u32 { - const A = 0b00000001, - #[doc = "bar"] - const B = 0b00000010, - const C = 0b00000100, - #[doc = "foo"] - const ABC = A.bits | B.bits | C.bits, - } -} - -#[test] -fn smoke() { - assert_eq!(ABC, A | B | C); -} diff --git a/src/vendor/bitflags-0.5.0/tests/external_no_std.rs b/src/vendor/bitflags-0.5.0/tests/external_no_std.rs deleted file mode 100644 index 0b73a96c9d..0000000000 --- a/src/vendor/bitflags-0.5.0/tests/external_no_std.rs +++ /dev/null @@ -1,24 +0,0 @@ -#![cfg(feature = "no_std")] -#![allow(dead_code)] -#![no_std] -#![cfg_attr(all(feature = "assignment_operators", test), feature(op_assign_traits))] - -#[macro_use] -extern crate bitflags; - -bitflags! { - /// baz - flags Flags: u32 { - const A = 0b00000001, - #[doc = "bar"] - const B = 0b00000010, - const C = 0b00000100, - #[doc = "foo"] - const ABC = A.bits | B.bits | C.bits, - } -} - -#[test] -fn smoke() { - assert_eq!(ABC, A | B | C); -} diff --git a/src/vendor/bitflags-0.7.0/.cargo-checksum.json b/src/vendor/bitflags-0.7.0/.cargo-checksum.json deleted file mode 100644 index c2012b5454..0000000000 --- a/src/vendor/bitflags-0.7.0/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"c1e953ee360e77de57f7b02f1b7880bd6a3dc22d1a69e953c2ac2c52cc52d247",".travis.yml":"2b615144d3f4b2e63ba6ec435cc18df7d76354aa07c2a02d6c707028cc448784","Cargo.toml":"db8c2e9ea912c5f3d2d89cf4cf936c448300e356b0fb533db8875923cb135256","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"8cfbc986af45867d9e620188af2392320fe6e0d9536753ba415c94ab522f5fb5","src/lib.rs":"618ce383bb219725363fba174fc66beb4874d9682e5da953f9e3e9cb3f786d5f","tests/external.rs":"546e549ec831876a5dc272bd0537adc9e9886c6da54656c825e7bffc079e2c74","tests/external_no_std.rs":"48929f5109aabc156442d5ae2ab07b4bce5d648488bf49dba725f6ab23bcb48a"},"package":"aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"} \ No newline at end of file diff --git a/src/vendor/bitflags-0.7.0/.gitignore b/src/vendor/bitflags-0.7.0/.gitignore deleted file mode 100644 index 4fffb2f89c..0000000000 --- a/src/vendor/bitflags-0.7.0/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/target -/Cargo.lock diff --git a/src/vendor/bitflags-0.7.0/.travis.yml b/src/vendor/bitflags-0.7.0/.travis.yml deleted file mode 100644 index 60344466a1..0000000000 --- a/src/vendor/bitflags-0.7.0/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -language: rust -rust: - - stable - - beta - - nightly -sudo: false -script: - - cargo build --verbose - - cargo test --verbose - - cargo doc -after_success: | - [ $TRAVIS_BRANCH = master ] && - [ $TRAVIS_PULL_REQUEST = false ] && - [ $TRAVIS_RUST_VERSION = nightly ] && - echo '' > target/doc/index.html && - pip install ghp-import --user $USER && - $HOME/.local/bin/ghp-import -n target/doc && - git push -qf https://${TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages -env: - global: - secure: d+l63TtlF6cfFVDGauYRexgx4lBww4ORqqK4Vt75nWbiCbjZYsKXbcTUdhAr193nIVGiNW50A8SekM01F3EngHwHwr6u5kFleOggm+HA0kkBVeX+k2A4WCVVfYI+gth+zk99WaF8h46MA0evhx6FYDoqeyl9oqmVifI4kaqhMwc= -notifications: - email: - on_success: never diff --git a/src/vendor/bitflags-0.7.0/Cargo.toml b/src/vendor/bitflags-0.7.0/Cargo.toml deleted file mode 100644 index 042497e9ca..0000000000 --- a/src/vendor/bitflags-0.7.0/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] - -name = "bitflags" -version = "0.7.0" -authors = ["The Rust Project Developers"] -license = "MIT/Apache-2.0" -readme = "README.md" -repository = "https://github.com/rust-lang/bitflags" -homepage = "https://github.com/rust-lang/bitflags" -documentation = "https://doc.rust-lang.org/bitflags" -description = """ -A macro to generate structures which behave like bitflags. -""" diff --git a/src/vendor/bitflags/.cargo-checksum.json b/src/vendor/bitflags/.cargo-checksum.json new file mode 100644 index 0000000000..b22367f34d --- /dev/null +++ b/src/vendor/bitflags/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"c1e953ee360e77de57f7b02f1b7880bd6a3dc22d1a69e953c2ac2c52cc52d247",".travis.yml":"e7a77c1800f9852e4c9a2acb9df041773ecd0bc005bd1b0657ae0512c67100ac","Cargo.toml":"f35826eec96c765ae8aee4f8a66c6b3cb0d918b49935baf05bae79b6df8e1077","Cargo.toml.orig":"46baf2141cf0a39944cd90ff114df4e42570b781e704589da2a6abf4e8ba723f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"602c63819e332e93c85dc8426db4855f18fe0fabbd642c5b2303ed83f1ba926f","src/example_generated.rs":"161b69d92cf6e5fa4b5dc30f06031f3a0fb590b44be2bcf0f31cb8be4fab36fa","src/lib.rs":"56e86a16356d9322fa6b4e9b910041e2e7558c08b52ffbdacc647eba36b37abc","tests/conflicting_trait_impls.rs":"79993ea67ef09a5f99fddd69d8b73b1c137e41d0e8f8535f03865d6766dcc498","tests/external.rs":"15f7901698e286197666ccd309ad1debd3c35eaff680ca090368494e8b06ccf2","tests/external_no_std.rs":"c3556fd19dd91d1b093eb6a65d09a9d0985544f0377ba3d30c0e265c956f7237","tests/i128_bitflags.rs":"c955ef2c9fd385848195bb416e660e946ccbe59acc87862ef2646eb082d82e3f"},"package":"4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"} \ No newline at end of file diff --git a/src/vendor/toml-0.3.2/tests/valid/empty.toml b/src/vendor/bitflags/.cargo-ok similarity index 100% rename from src/vendor/toml-0.3.2/tests/valid/empty.toml rename to src/vendor/bitflags/.cargo-ok diff --git a/src/vendor/bitflags-0.5.0/.gitignore b/src/vendor/bitflags/.gitignore similarity index 100% rename from src/vendor/bitflags-0.5.0/.gitignore rename to src/vendor/bitflags/.gitignore diff --git a/src/vendor/bitflags/.travis.yml b/src/vendor/bitflags/.travis.yml new file mode 100644 index 0000000000..5eb31843a7 --- /dev/null +++ b/src/vendor/bitflags/.travis.yml @@ -0,0 +1,29 @@ +os: + - linux + - osx +language: rust +rust: + - stable + - beta + - nightly +sudo: false +before_script: + - pip install -v 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH + - if [[ -e ~/Library/Python/2.7/bin ]]; then export PATH=~/Library/Python/2.7/bin:$PATH; fi +script: + - cargo build --verbose + - cargo test --verbose + - travis-cargo --only nightly test + - cargo doc --no-deps +after_success: + - travis-cargo --only nightly doc-upload +env: + global: + - TRAVIS_CARGO_NIGHTLY_FEATURE=unstable_testing + - secure: "DoZ8g8iPs+X3xEEucke0Ae02JbkQ1qd1SSv/L2aQqxULmREtRcbzRauhiT+ToQO5Ft1Lul8uck14nPfs4gMr/O3jFFBhEBVpSlbkJx7eNL3kwUdp95UNroA8I43xPN/nccJaHDN6TMTD3+uajTQTje2SyzOQP+1gvdKg17kguvE=" + + + +notifications: + email: + on_success: never diff --git a/src/vendor/bitflags/Cargo.toml b/src/vendor/bitflags/Cargo.toml new file mode 100644 index 0000000000..8ac9adbfc1 --- /dev/null +++ b/src/vendor/bitflags/Cargo.toml @@ -0,0 +1,31 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g. crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "bitflags" +version = "0.9.1" +authors = ["The Rust Project Developers"] +description = "A macro to generate structures which behave like bitflags.\n" +homepage = "https://github.com/rust-lang-nursery/bitflags" +documentation = "https://docs.rs/bitflags" +readme = "README.md" +keywords = ["bit", "bitmask", "bitflags"] +categories = ["no-std"] +license = "MIT/Apache-2.0" +repository = "https://github.com/rust-lang-nursery/bitflags" + +[features] +example_generated = [] +unstable_testing = [] +default = ["example_generated"] +[badges.travis-ci] +repository = "rust-lang-nursery/bitflags" diff --git a/src/vendor/bitflags/Cargo.toml.orig b/src/vendor/bitflags/Cargo.toml.orig new file mode 100644 index 0000000000..261bdee2e0 --- /dev/null +++ b/src/vendor/bitflags/Cargo.toml.orig @@ -0,0 +1,26 @@ +[package] + +name = "bitflags" +# NB: When modifying, also modify: +# 1. html_root_url in lib.rs +# 2. number in readme (for breaking changes) +version = "0.9.1" +authors = ["The Rust Project Developers"] +license = "MIT/Apache-2.0" +keywords = ["bit", "bitmask", "bitflags"] +readme = "README.md" +repository = "https://github.com/rust-lang-nursery/bitflags" +homepage = "https://github.com/rust-lang-nursery/bitflags" +documentation = "https://docs.rs/bitflags" +categories = ["no-std"] +description = """ +A macro to generate structures which behave like bitflags. +""" + +[badges] +travis-ci = { repository = "rust-lang-nursery/bitflags" } + +[features] +default = ["example_generated"] +unstable_testing = [] +example_generated = [] diff --git a/src/vendor/bitflags-0.5.0/LICENSE-APACHE b/src/vendor/bitflags/LICENSE-APACHE similarity index 100% rename from src/vendor/bitflags-0.5.0/LICENSE-APACHE rename to src/vendor/bitflags/LICENSE-APACHE diff --git a/src/vendor/bitflags-0.5.0/LICENSE-MIT b/src/vendor/bitflags/LICENSE-MIT similarity index 100% rename from src/vendor/bitflags-0.5.0/LICENSE-MIT rename to src/vendor/bitflags/LICENSE-MIT diff --git a/src/vendor/bitflags-0.7.0/README.md b/src/vendor/bitflags/README.md similarity index 84% rename from src/vendor/bitflags-0.7.0/README.md rename to src/vendor/bitflags/README.md index 3edd8a361e..714ca9d9e5 100644 --- a/src/vendor/bitflags-0.7.0/README.md +++ b/src/vendor/bitflags/README.md @@ -5,7 +5,7 @@ A Rust macro to generate structures which behave like a set of bitflags [![Build Status](https://travis-ci.org/rust-lang-nursery/bitflags.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/bitflags) -[Documentation](https://doc.rust-lang.org/bitflags) +[Documentation](https://docs.rs/bitflags) ## Usage @@ -13,7 +13,7 @@ Add this to your `Cargo.toml`: ```toml [dependencies] -bitflags = "0.6" +bitflags = "0.9" ``` and this to your crate root: diff --git a/src/vendor/bitflags/src/example_generated.rs b/src/vendor/bitflags/src/example_generated.rs new file mode 100644 index 0000000000..05b99e8f04 --- /dev/null +++ b/src/vendor/bitflags/src/example_generated.rs @@ -0,0 +1,16 @@ +//! This module shows an example of code generated by the macro. **IT MUST NOT BE USED OUTSIDE THIS +//! CRATE**. + +bitflags! { + /// This is the same `Flags` struct defined in the [crate level example](../index.html#example). + /// Note that this struct is just for documentation purposes only, it must not be used outside + /// this crate. + pub struct Flags: u32 { + const FLAG_A = 0b00000001; + const FLAG_B = 0b00000010; + const FLAG_C = 0b00000100; + const FLAG_ABC = FLAG_A.bits + | FLAG_B.bits + | FLAG_C.bits; + } +} diff --git a/src/vendor/bitflags-0.7.0/src/lib.rs b/src/vendor/bitflags/src/lib.rs similarity index 52% rename from src/vendor/bitflags-0.7.0/src/lib.rs rename to src/vendor/bitflags/src/lib.rs index 698799dab2..5840643a82 100644 --- a/src/vendor/bitflags-0.7.0/src/lib.rs +++ b/src/vendor/bitflags/src/lib.rs @@ -8,40 +8,249 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! A typesafe bitmask flag generator. +//! A typesafe bitmask flag generator useful for sets of C-style bitmask flags. +//! It can be used for creating typesafe wrappers around C APIs. +//! +//! The `bitflags!` macro generates a `struct` that manages a set of flags. The +//! flags should only be defined for integer types, otherwise unexpected type +//! errors may occur at compile time. +//! +//! # Example +//! +//! ``` +//! #[macro_use] +//! extern crate bitflags; +//! +//! bitflags! { +//! struct Flags: u32 { +//! const FLAG_A = 0b00000001; +//! const FLAG_B = 0b00000010; +//! const FLAG_C = 0b00000100; +//! const FLAG_ABC = FLAG_A.bits +//! | FLAG_B.bits +//! | FLAG_C.bits; +//! } +//! } +//! +//! fn main() { +//! let e1 = FLAG_A | FLAG_C; +//! let e2 = FLAG_B | FLAG_C; +//! assert_eq!((e1 | e2), FLAG_ABC); // union +//! assert_eq!((e1 & e2), FLAG_C); // intersection +//! assert_eq!((e1 - e2), FLAG_A); // set difference +//! assert_eq!(!e2, FLAG_A); // set complement +//! } +//! ``` +//! +//! See [`example_generated::Flags`](./example_generated/struct.Flags.html) for documentation of code +//! generated by the above `bitflags!` expansion. +//! +//! The generated `struct`s can also be extended with type and trait +//! implementations: +//! +//! ``` +//! #[macro_use] +//! extern crate bitflags; +//! +//! use std::fmt; +//! +//! bitflags! { +//! struct Flags: u32 { +//! const FLAG_A = 0b00000001; +//! const FLAG_B = 0b00000010; +//! } +//! } +//! +//! impl Flags { +//! pub fn clear(&mut self) { +//! self.bits = 0; // The `bits` field can be accessed from within the +//! // same module where the `bitflags!` macro was invoked. +//! } +//! } +//! +//! impl fmt::Display for Flags { +//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +//! write!(f, "hi!") +//! } +//! } +//! +//! fn main() { +//! let mut flags = FLAG_A | FLAG_B; +//! flags.clear(); +//! assert!(flags.is_empty()); +//! assert_eq!(format!("{}", flags), "hi!"); +//! assert_eq!(format!("{:?}", FLAG_A | FLAG_B), "FLAG_A | FLAG_B"); +//! assert_eq!(format!("{:?}", FLAG_B), "FLAG_B"); +//! } +//! ``` +//! +//! # Visibility +//! +//! The generated struct and its associated flag constants are not exported +//! out of the current module by default. A definition can be exported out of +//! the current module by adding `pub` before `flags`: +//! +//! ```ignore +//! #[macro_use] +//! extern crate bitflags; +//! +//! mod example { +//! bitflags! { +//! pub struct Flags1: u32 { +//! const FLAG_A = 0b00000001; +//! } +//! } +//! bitflags! { +//! struct Flags2: u32 { +//! const FLAG_B = 0b00000010; +//! } +//! } +//! } +//! +//! fn main() { +//! let flag1 = example::FLAG_A; +//! let flag2 = example::FLAG_B; // error: const `FLAG_B` is private +//! } +//! ``` +//! +//! # Attributes +//! +//! Attributes can be attached to the generated `struct` by placing them +//! before the `flags` keyword. +//! +//! # Trait implementations +//! +//! The `Copy`, `Clone`, `PartialEq`, `Eq`, `PartialOrd`, `Ord` and `Hash` +//! traits automatically derived for the `struct` using the `derive` attribute. +//! Additional traits can be derived by providing an explicit `derive` +//! attribute on `flags`. +//! +//! The `Extend` and `FromIterator` traits are implemented for the `struct`, +//! too: `Extend` adds the union of the instances of the `struct` iterated over, +//! while `FromIterator` calculates the union. +//! +//! The `Binary`, `Debug`, `LowerExp`, `Octal` and `UpperExp` trait is also +//! implemented by displaying the bits value of the internal struct. +//! +//! ## Operators +//! +//! The following operator traits are implemented for the generated `struct`: +//! +//! - `BitOr` and `BitOrAssign`: union +//! - `BitAnd` and `BitAndAssign`: intersection +//! - `BitXor` and `BitXorAssign`: toggle +//! - `Sub` and `SubAssign`: set difference +//! - `Not`: set complement +//! +//! # Methods +//! +//! The following methods are defined for the generated `struct`: +//! +//! - `empty`: an empty set of flags +//! - `all`: the set of all flags +//! - `bits`: the raw value of the flags currently stored +//! - `from_bits`: convert from underlying bit representation, unless that +//! representation contains bits that do not correspond to a flag +//! - `from_bits_truncate`: convert from underlying bit representation, dropping +//! any bits that do not correspond to flags +//! - `is_empty`: `true` if no flags are currently stored +//! - `is_all`: `true` if all flags are currently set +//! - `intersects`: `true` if there are flags common to both `self` and `other` +//! - `contains`: `true` all of the flags in `other` are contained within `self` +//! - `insert`: inserts the specified flags in-place +//! - `remove`: removes the specified flags in-place +//! - `toggle`: the specified flags will be inserted if not present, and removed +//! if they are. +//! +//! ## Default +//! +//! The `Default` trait is not automatically implemented for the generated struct. +//! +//! If your default value is equal to `0` (which is the same value as calling `empty()` +//! on the generated struct), you can simply derive `Default`: +//! +//! ``` +//! #[macro_use] +//! extern crate bitflags; +//! +//! bitflags! { +//! // Results in default value with bits: 0 +//! #[derive(Default)] +//! struct Flags: u32 { +//! const FLAG_A = 0b00000001; +//! const FLAG_B = 0b00000010; +//! const FLAG_C = 0b00000100; +//! } +//! } +//! +//! fn main() { +//! let derived_default: Flags = Default::default(); +//! assert_eq!(derived_default.bits(), 0); +//! } +//! ``` +//! +//! If your default value is not equal to `0` you need to implement `Default` yourself: +//! +//! ``` +//! #[macro_use] +//! extern crate bitflags; +//! +//! bitflags! { +//! struct Flags: u32 { +//! const FLAG_A = 0b00000001; +//! const FLAG_B = 0b00000010; +//! const FLAG_C = 0b00000100; +//! } +//! } +//! +//! // explicit `Default` implementation +//! impl Default for Flags { +//! fn default() -> Flags { +//! FLAG_A | FLAG_C +//! } +//! } +//! +//! fn main() { +//! let implemented_default: Flags = Default::default(); +//! assert_eq!(implemented_default, (FLAG_A | FLAG_C)); +//! } +//! ``` #![no_std] +#![doc(html_root_url = "https://docs.rs/bitflags/0.9.1")] +// When compiled for the rustc compiler itself we want to make sure that this is +// an unstable crate. +#![cfg_attr(rustbuild, feature(staged_api))] +#![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))] + #[cfg(test)] #[macro_use] extern crate std; // Re-export libstd/libcore using an alias so that the macros can work in no_std // crates while remaining compatible with normal crates. -#[allow(private_in_public)] #[doc(hidden)] -pub use core as __core; +pub extern crate core as _core; -/// The `bitflags!` macro generates a `struct` that holds a set of C-style -/// bitmask flags. It is useful for creating typesafe wrappers for C APIs. +/// The macro used to generate the flag structure. /// -/// The flags should only be defined for integer types, otherwise unexpected -/// type errors may occur at compile time. +/// See the [crate level docs](../bitflags/index.html) for complete documentation. /// /// # Example /// -/// ```{.rust} +/// ``` /// #[macro_use] /// extern crate bitflags; /// /// bitflags! { -/// flags Flags: u32 { -/// const FLAG_A = 0b00000001, -/// const FLAG_B = 0b00000010, -/// const FLAG_C = 0b00000100, +/// struct Flags: u32 { +/// const FLAG_A = 0b00000001; +/// const FLAG_B = 0b00000010; +/// const FLAG_C = 0b00000100; /// const FLAG_ABC = FLAG_A.bits /// | FLAG_B.bits -/// | FLAG_C.bits, +/// | FLAG_C.bits; /// } /// } /// @@ -58,16 +267,16 @@ pub use core as __core; /// The generated `struct`s can also be extended with type and trait /// implementations: /// -/// ```{.rust} +/// ``` /// #[macro_use] /// extern crate bitflags; /// /// use std::fmt; /// /// bitflags! { -/// flags Flags: u32 { -/// const FLAG_A = 0b00000001, -/// const FLAG_B = 0b00000010, +/// struct Flags: u32 { +/// const FLAG_A = 0b00000001; +/// const FLAG_B = 0b00000010; /// } /// } /// @@ -93,91 +302,10 @@ pub use core as __core; /// assert_eq!(format!("{:?}", FLAG_B), "FLAG_B"); /// } /// ``` -/// -/// # Visibility -/// -/// The generated struct and its associated flag constants are not exported -/// out of the current module by default. A definition can be exported out of -/// the current module by adding `pub` before `flags`: -/// -/// ```{.rust},ignore -/// #[macro_use] -/// extern crate bitflags; -/// -/// mod example { -/// bitflags! { -/// pub flags Flags1: u32 { -/// const FLAG_A = 0b00000001, -/// } -/// } -/// bitflags! { -/// flags Flags2: u32 { -/// const FLAG_B = 0b00000010, -/// } -/// } -/// } -/// -/// fn main() { -/// let flag1 = example::FLAG_A; -/// let flag2 = example::FLAG_B; // error: const `FLAG_B` is private -/// } -/// ``` -/// -/// # Attributes -/// -/// Attributes can be attached to the generated `struct` by placing them -/// before the `flags` keyword. -/// -/// # Trait implementations -/// -/// The `Copy`, `Clone`, `PartialEq`, `Eq`, `PartialOrd`, `Ord` and `Hash` -/// traits automatically derived for the `struct` using the `derive` attribute. -/// Additional traits can be derived by providing an explicit `derive` -/// attribute on `flags`. -/// -/// The `Extend` and `FromIterator` traits are implemented for the `struct`, -/// too: `Extend` adds the union of the instances of the `struct` iterated over, -/// while `FromIterator` calculates the union. -/// -/// The `Debug` trait is also implemented by displaying the bits value of the -/// internal struct. -/// -/// ## Operators -/// -/// The following operator traits are implemented for the generated `struct`: -/// -/// - `BitOr` and `BitOrAssign`: union -/// - `BitAnd` and `BitAndAssign`: intersection -/// - `BitXor` and `BitXorAssign`: toggle -/// - `Sub` and `SubAssign`: set difference -/// - `Not`: set complement -/// -/// As long as the assignment operators are unstable rust feature they are only -/// available with the crate feature `assignment_ops` enabled. -/// -/// # Methods -/// -/// The following methods are defined for the generated `struct`: -/// -/// - `empty`: an empty set of flags -/// - `all`: the set of all flags -/// - `bits`: the raw value of the flags currently stored -/// - `from_bits`: convert from underlying bit representation, unless that -/// representation contains bits that do not correspond to a flag -/// - `from_bits_truncate`: convert from underlying bit representation, dropping -/// any bits that do not correspond to flags -/// - `is_empty`: `true` if no flags are currently stored -/// - `is_all`: `true` if all flags are currently set -/// - `intersects`: `true` if there are flags common to both `self` and `other` -/// - `contains`: `true` all of the flags in `other` are contained within `self` -/// - `insert`: inserts the specified flags in-place -/// - `remove`: removes the specified flags in-place -/// - `toggle`: the specified flags will be inserted if not present, and removed -/// if they are. #[macro_export] macro_rules! bitflags { - ($(#[$attr:meta])* pub flags $BitFlags:ident: $T:ty { - $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+ + ($(#[$attr:meta])* pub struct $BitFlags:ident: $T:ty { + $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr;)+ }) => { #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)] $(#[$attr])* @@ -187,14 +315,14 @@ macro_rules! bitflags { $($(#[$Flag_attr])* pub const $Flag: $BitFlags = $BitFlags { bits: $value };)+ - bitflags! { - @_impl flags $BitFlags: $T { - $($(#[$Flag_attr])* const $Flag = $value),+ + __impl_bitflags! { + struct $BitFlags: $T { + $($(#[$Flag_attr])* const $Flag = $value;)+ } } }; - ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty { - $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+ + ($(#[$attr:meta])* struct $BitFlags:ident: $T:ty { + $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr;)+ }) => { #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)] $(#[$attr])* @@ -204,69 +332,83 @@ macro_rules! bitflags { $($(#[$Flag_attr])* const $Flag: $BitFlags = $BitFlags { bits: $value };)+ - bitflags! { - @_impl flags $BitFlags: $T { - $($(#[$Flag_attr])* const $Flag = $value),+ + __impl_bitflags! { + struct $BitFlags: $T { + $($(#[$Flag_attr])* const $Flag = $value;)+ } } + }; - (@_impl flags $BitFlags:ident: $T:ty { - $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+ +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __impl_bitflags { + (struct $BitFlags:ident: $T:ty { + $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr;)+ }) => { - impl $crate::__core::fmt::Debug for $BitFlags { - fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result { + impl $crate::_core::fmt::Debug for $BitFlags { + fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { // This convoluted approach is to handle #[cfg]-based flag - // omission correctly. Some of the $Flag variants may not be - // defined in this module so we create an inner module which - // defines *all* flags to the value of 0. We then create a - // second inner module that defines all of the flags with #[cfg] - // to their real values. Afterwards the glob will import - // variants from the second inner module, shadowing all - // defined variants, leaving only the undefined ones with the - // bit value of 0. - #[allow(dead_code)] - #[allow(unused_assignments)] - mod dummy { - // We can't use the real $BitFlags struct because it may be - // private, which prevents us from using it to define - // public constants. - pub struct $BitFlags { - bits: u64, - } - mod real_flags { - use super::$BitFlags; - $($(#[$Flag_attr])* pub const $Flag: $BitFlags = $BitFlags { - bits: super::super::$Flag.bits as u64 - };)+ - } - // Now we define the "undefined" versions of the flags. - // This way, all the names exist, even if some are #[cfg]ed - // out. - $(const $Flag: $BitFlags = $BitFlags { bits: 0 };)+ - - #[inline] - pub fn fmt(self_: u64, - f: &mut $crate::__core::fmt::Formatter) - -> $crate::__core::fmt::Result { - // Now we import the real values for the flags. - // Only ones that are #[cfg]ed out will be 0. - use self::real_flags::*; - - let mut first = true; - $( - // $Flag.bits == 0 means that $Flag doesn't exist - if $Flag.bits != 0 && self_ & $Flag.bits as u64 == $Flag.bits as u64 { - if !first { - try!(f.write_str(" | ")); - } - first = false; - try!(f.write_str(stringify!($Flag))); - } - )+ - Ok(()) + // omission correctly. For example it needs to support: + // + // #[cfg(unix)] const A: Flag = /* ... */; + // #[cfg(windows)] const B: Flag = /* ... */; + + // Unconditionally define a check for every flag, even disabled + // ones. + #[allow(non_snake_case)] + trait __BitFlags { + $( + fn $Flag(&self) -> bool { false } + )+ + } + + // Conditionally override the check for just those flags that + // are not #[cfg]ed away. + impl __BitFlags for $BitFlags { + $( + $(#[$Flag_attr])* + fn $Flag(&self) -> bool { + self.bits & $Flag.bits == $Flag.bits + } + )+ + } + + let mut first = true; + $( + if <$BitFlags as __BitFlags>::$Flag(self) { + if !first { + try!(f.write_str(" | ")); + } + first = false; + try!(f.write_str(stringify!($Flag))); } + )+ + if first { + try!(f.write_str("(empty)")); } - dummy::fmt(self.bits as u64, f) + Ok(()) + } + } + impl $crate::_core::fmt::Binary for $BitFlags { + fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { + $crate::_core::fmt::Binary::fmt(&self.bits, f) + } + } + impl $crate::_core::fmt::Octal for $BitFlags { + fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { + $crate::_core::fmt::Octal::fmt(&self.bits, f) + } + } + impl $crate::_core::fmt::LowerHex for $BitFlags { + fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { + $crate::_core::fmt::LowerHex::fmt(&self.bits, f) + } + } + impl $crate::_core::fmt::UpperHex for $BitFlags { + fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { + $crate::_core::fmt::UpperHex::fmt(&self.bits, f) } } @@ -281,27 +423,20 @@ macro_rules! bitflags { /// Returns the set containing all flags. #[inline] pub fn all() -> $BitFlags { - // See above `dummy` module for why this approach is taken. - #[allow(dead_code)] - mod dummy { - pub struct $BitFlags { - bits: u64, - } - mod real_flags { - use super::$BitFlags; - $($(#[$Flag_attr])* pub const $Flag: $BitFlags = $BitFlags { - bits: super::super::$Flag.bits as u64 - };)+ - } - $(const $Flag: $BitFlags = $BitFlags { bits: 0 };)+ - - #[inline] - pub fn all() -> u64 { - use self::real_flags::*; - $($Flag.bits)|+ - } + // See `Debug::fmt` for why this approach is taken. + #[allow(non_snake_case)] + trait __BitFlags { + $( + fn $Flag() -> $T { 0 } + )+ + } + impl __BitFlags for $BitFlags { + $( + $(#[$Flag_attr])* + fn $Flag() -> $T { $Flag.bits } + )+ } - $BitFlags { bits: dummy::all() as $T } + $BitFlags { bits: $(<$BitFlags as __BitFlags>::$Flag())|+ } } /// Returns the raw value of the flags currently stored. @@ -313,11 +448,11 @@ macro_rules! bitflags { /// Convert from underlying bit representation, unless that /// representation contains bits that do not correspond to a flag. #[inline] - pub fn from_bits(bits: $T) -> $crate::__core::option::Option<$BitFlags> { + pub fn from_bits(bits: $T) -> $crate::_core::option::Option<$BitFlags> { if (bits & !$BitFlags::all().bits()) == 0 { - $crate::__core::option::Option::Some($BitFlags { bits: bits }) + $crate::_core::option::Option::Some($BitFlags { bits: bits }) } else { - $crate::__core::option::Option::None + $crate::_core::option::Option::None } } @@ -369,9 +504,19 @@ macro_rules! bitflags { pub fn toggle(&mut self, other: $BitFlags) { self.bits ^= other.bits; } + + /// Inserts or removes the specified flags depending on the passed value. + #[inline] + pub fn set(&mut self, other: $BitFlags, value: bool) { + if value { + self.insert(other); + } else { + self.remove(other); + } + } } - impl $crate::__core::ops::BitOr for $BitFlags { + impl $crate::_core::ops::BitOr for $BitFlags { type Output = $BitFlags; /// Returns the union of the two sets of flags. @@ -381,7 +526,7 @@ macro_rules! bitflags { } } - impl $crate::__core::ops::BitOrAssign for $BitFlags { + impl $crate::_core::ops::BitOrAssign for $BitFlags { /// Adds the set of flags. #[inline] @@ -390,7 +535,7 @@ macro_rules! bitflags { } } - impl $crate::__core::ops::BitXor for $BitFlags { + impl $crate::_core::ops::BitXor for $BitFlags { type Output = $BitFlags; /// Returns the left flags, but with all the right flags toggled. @@ -400,7 +545,7 @@ macro_rules! bitflags { } } - impl $crate::__core::ops::BitXorAssign for $BitFlags { + impl $crate::_core::ops::BitXorAssign for $BitFlags { /// Toggles the set of flags. #[inline] @@ -409,7 +554,7 @@ macro_rules! bitflags { } } - impl $crate::__core::ops::BitAnd for $BitFlags { + impl $crate::_core::ops::BitAnd for $BitFlags { type Output = $BitFlags; /// Returns the intersection between the two sets of flags. @@ -419,7 +564,7 @@ macro_rules! bitflags { } } - impl $crate::__core::ops::BitAndAssign for $BitFlags { + impl $crate::_core::ops::BitAndAssign for $BitFlags { /// Disables all flags disabled in the set. #[inline] @@ -428,7 +573,7 @@ macro_rules! bitflags { } } - impl $crate::__core::ops::Sub for $BitFlags { + impl $crate::_core::ops::Sub for $BitFlags { type Output = $BitFlags; /// Returns the set difference of the two sets of flags. @@ -438,7 +583,7 @@ macro_rules! bitflags { } } - impl $crate::__core::ops::SubAssign for $BitFlags { + impl $crate::_core::ops::SubAssign for $BitFlags { /// Disables all flags enabled in the set. #[inline] @@ -447,7 +592,7 @@ macro_rules! bitflags { } } - impl $crate::__core::ops::Not for $BitFlags { + impl $crate::_core::ops::Not for $BitFlags { type Output = $BitFlags; /// Returns the complement of this set of flags. @@ -457,82 +602,72 @@ macro_rules! bitflags { } } - impl $crate::__core::iter::Extend<$BitFlags> for $BitFlags { - fn extend>(&mut self, iterator: T) { + impl $crate::_core::iter::Extend<$BitFlags> for $BitFlags { + fn extend>(&mut self, iterator: T) { for item in iterator { self.insert(item) } } } - impl $crate::__core::iter::FromIterator<$BitFlags> for $BitFlags { - fn from_iter>(iterator: T) -> $BitFlags { + impl $crate::_core::iter::FromIterator<$BitFlags> for $BitFlags { + fn from_iter>(iterator: T) -> $BitFlags { let mut result = Self::empty(); result.extend(iterator); result } } }; - ($(#[$attr:meta])* pub flags $BitFlags:ident: $T:ty { - $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+, - }) => { - bitflags! { - $(#[$attr])* - pub flags $BitFlags: $T { - $($(#[$Flag_attr])* const $Flag = $value),+ - } - } - }; - ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty { - $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+, - }) => { - bitflags! { - $(#[$attr])* - flags $BitFlags: $T { - $($(#[$Flag_attr])* const $Flag = $value),+ - } - } - }; } +#[cfg(feature = "example_generated")] +pub mod example_generated; + #[cfg(test)] #[allow(non_upper_case_globals, dead_code)] mod tests { - use std::hash::{SipHasher, Hash, Hasher}; + use std::hash::{Hash, Hasher}; + use std::collections::hash_map::DefaultHasher; bitflags! { #[doc = "> The first principle is that you must not fool yourself — and"] #[doc = "> you are the easiest person to fool."] #[doc = "> "] #[doc = "> - Richard Feynman"] - flags Flags: u32 { - const FlagA = 0b00000001, + struct Flags: u32 { + const FlagA = 0b00000001; #[doc = " macros are way better at generating code than trans is"] - const FlagB = 0b00000010, - const FlagC = 0b00000100, + const FlagB = 0b00000010; + const FlagC = 0b00000100; #[doc = "* cmr bed"] #[doc = "* strcat table"] #[doc = " wait what?"] const FlagABC = FlagA.bits | FlagB.bits - | FlagC.bits, + | FlagC.bits; } } bitflags! { - flags _CfgFlags: u32 { + struct _CfgFlags: u32 { #[cfg(windows)] - const _CfgA = 0b01, + const _CfgA = 0b01; #[cfg(unix)] - const _CfgB = 0b01, + const _CfgB = 0b01; #[cfg(windows)] - const _CfgC = _CfgA.bits | 0b10, + const _CfgC = _CfgA.bits | 0b10; + } + } + + bitflags! { + struct AnotherSetOfFlags: i8 { + const AnotherFlag = -1_i8; } } bitflags! { - flags AnotherSetOfFlags: i8 { - const AnotherFlag = -1_i8, + struct LongFlags: u32 { + const LongFlagA = 0b1111111111111111; } } @@ -670,6 +805,15 @@ mod tests { assert_eq!(m4, AnotherSetOfFlags::empty()); } + #[test] + fn test_set() { + let mut e1 = FlagA | FlagC; + e1.set(FlagB, true); + e1.set(FlagC, false); + + assert_eq!(e1, FlagA | FlagB); + } + #[test] fn test_assignment_operators() { let mut m1 = Flags::empty(); @@ -745,7 +889,7 @@ mod tests { } fn hash(t: &T) -> u64 { - let mut s = SipHasher::new_with_keys(0, 0); + let mut s = DefaultHasher::new(); t.hash(&mut s); s.finish() } @@ -763,18 +907,43 @@ mod tests { #[test] fn test_debug() { assert_eq!(format!("{:?}", FlagA | FlagB), "FlagA | FlagB"); + assert_eq!(format!("{:?}", Flags::empty()), "(empty)"); assert_eq!(format!("{:?}", FlagABC), "FlagA | FlagB | FlagC | FlagABC"); } + #[test] + fn test_binary() { + assert_eq!(format!("{:b}", FlagABC), "111"); + assert_eq!(format!("{:#b}", FlagABC), "0b111"); + } + + #[test] + fn test_octal() { + assert_eq!(format!("{:o}", LongFlagA), "177777"); + assert_eq!(format!("{:#o}", LongFlagA), "0o177777"); + } + + #[test] + fn test_lowerhex() { + assert_eq!(format!("{:x}", LongFlagA), "ffff"); + assert_eq!(format!("{:#x}", LongFlagA), "0xffff"); + } + + #[test] + fn test_upperhex() { + assert_eq!(format!("{:X}", LongFlagA), "FFFF"); + assert_eq!(format!("{:#X}", LongFlagA), "0xFFFF"); + } + mod submodule { bitflags! { - pub flags PublicFlags: i8 { - const FlagX = 0, + pub struct PublicFlags: i8 { + const FlagX = 0; } } bitflags! { - flags PrivateFlags: i8 { - const FlagY = 0, + struct PrivateFlags: i8 { + const FlagY = 0; } } @@ -796,13 +965,26 @@ mod tests { bitflags! { /// baz - flags Flags: foo::Bar { - const A = 0b00000001, + struct Flags: foo::Bar { + const A = 0b00000001; #[cfg(foo)] - const B = 0b00000010, + const B = 0b00000010; #[cfg(foo)] - const C = 0b00000010, + const C = 0b00000010; + } + } + } + + #[test] + fn test_in_function() { + bitflags! { + struct Flags: u8 { + const A = 1; + #[cfg(any())] // false + const B = 2; } } + assert_eq!(Flags::all(), A); + assert_eq!(format!("{:?}", A), "A"); } } diff --git a/src/vendor/bitflags/tests/conflicting_trait_impls.rs b/src/vendor/bitflags/tests/conflicting_trait_impls.rs new file mode 100644 index 0000000000..4704dfaa3d --- /dev/null +++ b/src/vendor/bitflags/tests/conflicting_trait_impls.rs @@ -0,0 +1,20 @@ +#![allow(dead_code)] +#![no_std] + +#[macro_use] +extern crate bitflags; + +#[allow(unused_imports)] +use core::fmt::Display; + +bitflags! { + /// baz + struct Flags: u32 { + const A = 0b00000001; + } +} + +#[test] +fn main() { + +} diff --git a/src/vendor/bitflags-0.7.0/tests/external.rs b/src/vendor/bitflags/tests/external.rs similarity index 51% rename from src/vendor/bitflags-0.7.0/tests/external.rs rename to src/vendor/bitflags/tests/external.rs index 0f0c7f665f..fc1c346709 100644 --- a/src/vendor/bitflags-0.7.0/tests/external.rs +++ b/src/vendor/bitflags/tests/external.rs @@ -5,13 +5,13 @@ extern crate bitflags; bitflags! { /// baz - flags Flags: u32 { - const A = 0b00000001, + struct Flags: u32 { + const A = 0b00000001; #[doc = "bar"] - const B = 0b00000010, - const C = 0b00000100, + const B = 0b00000010; + const C = 0b00000100; #[doc = "foo"] - const ABC = A.bits | B.bits | C.bits, + const ABC = A.bits | B.bits | C.bits; } } diff --git a/src/vendor/bitflags-0.7.0/tests/external_no_std.rs b/src/vendor/bitflags/tests/external_no_std.rs similarity index 52% rename from src/vendor/bitflags-0.7.0/tests/external_no_std.rs rename to src/vendor/bitflags/tests/external_no_std.rs index 46526fd712..8b8c7067f6 100644 --- a/src/vendor/bitflags-0.7.0/tests/external_no_std.rs +++ b/src/vendor/bitflags/tests/external_no_std.rs @@ -6,13 +6,13 @@ extern crate bitflags; bitflags! { /// baz - flags Flags: u32 { - const A = 0b00000001, + struct Flags: u32 { + const A = 0b00000001; #[doc = "bar"] - const B = 0b00000010, - const C = 0b00000100, + const B = 0b00000010; + const C = 0b00000100; #[doc = "foo"] - const ABC = A.bits | B.bits | C.bits, + const ABC = A.bits | B.bits | C.bits; } } diff --git a/src/vendor/bitflags/tests/i128_bitflags.rs b/src/vendor/bitflags/tests/i128_bitflags.rs new file mode 100644 index 0000000000..acbb927821 --- /dev/null +++ b/src/vendor/bitflags/tests/i128_bitflags.rs @@ -0,0 +1,30 @@ +#![cfg(feature = "unstable_testing")] + +#![allow(dead_code, unused_imports)] +#![feature(i128_type)] + +#[macro_use] +extern crate bitflags; + +bitflags! { + /// baz + struct Flags128: u128 { + const A = 0x0000_0000_0000_0000_0000_0000_0000_0001; + const B = 0x0000_0000_0000_1000_0000_0000_0000_0000; + const C = 0x8000_0000_0000_0000_0000_0000_0000_0000; + const ABC = A.bits | B.bits | C.bits; + } +} + +#[test] +fn test_i128_bitflags() { + assert_eq!(ABC, A | B | C); + assert_eq!(A.bits, 0x0000_0000_0000_0000_0000_0000_0000_0001); + assert_eq!(B.bits, 0x0000_0000_0000_1000_0000_0000_0000_0000); + assert_eq!(C.bits, 0x8000_0000_0000_0000_0000_0000_0000_0000); + assert_eq!(ABC.bits, 0x8000_0000_0000_1000_0000_0000_0000_0001); + assert_eq!(format!("{:?}", A), "A"); + assert_eq!(format!("{:?}", B), "B"); + assert_eq!(format!("{:?}", C), "C"); + assert_eq!(format!("{:?}", ABC), "A | B | C | ABC"); +} diff --git a/src/vendor/cfg-if/.cargo-checksum.json b/src/vendor/cfg-if/.cargo-checksum.json index f19159795f..48d45d1973 100644 --- a/src/vendor/cfg-if/.cargo-checksum.json +++ b/src/vendor/cfg-if/.cargo-checksum.json @@ -1 +1 @@ -{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"f9b1ca6ae27d1c18215265024629a8960c31379f206d9ed20f64e0b2dcf79805",".travis.yml":"e4a302e9494e53483326b0307a2969e73fa7f3930199ad8b7be1015ee1827e03","Cargo.toml":"85c3d6ec135ebe7ba9681d76b08b4fb9ef16e70ad05fbbc5df5864567bbd2429","README.md":"3fa9368c60bc701dea294fbacae0469188c4be1de79f82e972bb9b321776cd52","src/lib.rs":"844d2f52dcc94a0118fab78163ff059342905e17177afbd14afcdb49e289050c","tests/xcrate.rs":"30dcb70fbb9c96fda2b7825592558279f534776f72e2a8a0a3e26df4dedb3caa"},"package":"de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"} \ No newline at end of file +{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"f9b1ca6ae27d1c18215265024629a8960c31379f206d9ed20f64e0b2dcf79805",".travis.yml":"50f67b20a376d437e0706d9bbb0343c677295529991370b2962f814c0b2efea3","Cargo.toml":"764b9ce160653e841430da3919ff968b957ff811f7da42c8483c8bfc2f06be25","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"3fa9368c60bc701dea294fbacae0469188c4be1de79f82e972bb9b321776cd52","src/lib.rs":"6915169e3ca05f28e1cb0e052379d74f2496400de1240b74c56e55c2674a6560","tests/xcrate.rs":"30dcb70fbb9c96fda2b7825592558279f534776f72e2a8a0a3e26df4dedb3caa"},"package":"d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"} \ No newline at end of file diff --git a/src/vendor/cfg-if/.travis.yml b/src/vendor/cfg-if/.travis.yml index c3e0bee3af..a52fad673d 100644 --- a/src/vendor/cfg-if/.travis.yml +++ b/src/vendor/cfg-if/.travis.yml @@ -1,25 +1,23 @@ language: rust rust: - - 1.0.0 + - stable - beta - nightly sudo: false +before_script: + - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH script: - cargo build --verbose - cargo test --verbose - rustdoc --test README.md -L target/debug -L target/debug/deps - - cargo doc -after_success: | - [ $TRAVIS_BRANCH = master ] && - [ $TRAVIS_PULL_REQUEST = false ] && - [ $TRAVIS_RUST_VERSION = nightly ] && - echo '' > target/doc/index.html && - pip install ghp-import --user $USER && - $HOME/.local/bin/ghp-import -n target/doc && - git push -qf https://${TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages + - cargo doc --no-deps +after_success: + - travis-cargo --only nightly doc-upload env: global: - secure: rPrap+rZmhWvNDXFP4auc31RA371E9grd5A7Zl0egZYbA+/OI9g4AZAD1Op4pgRX5HdiYtHAilvyKD0ITRrXdD9eoEOwx11y39XvcOOfJeYkP+SQaNXR9C2adxZ3oo7OFOz7ugqgISnHq37GHX8Yjir3cunlH5xvW5HKfrhMkTb8w4xO8wdo5PPx6dpeqcIkQpf5pAiOdeWAVzwbYFXqL4x32hmouumOidVCoYPPogWHjkvnOosKpagHSO1+eDZrQCyJYzBmb3infGqYvGdtST8rupu8DSD9mdQa1wcy8oLhJC6T/YDNBjh1Ab7/LgmI771fMQ3rZ2jWGI1GE/0Ht7GcysJi78k+avMMsbNTNZQEfcKZJU6HbQOWGuw1fkxNpGVn4M5MORH1GxTJMcqiNJCKbJJwv7fSpOG9fnsN+Rp+TYGma8+DjGLNSxrToIfjsKel+h43V1t9BNyK9sqssXzrPnJRSRZOixgWtHCsu7w7bEKZl2XJCESd65QiAOVXs6D7Y1Vrv4EKA47fO09VGYJCHlB5BlPJBVFXYwmoKKUs53/GzoLBjj9UI19p3EDVXvuyLmu2GtlIcTV5+YuHYDGFDfv12hYV2h4nMiZkZZ1lZdbojf24W+OATfzuZKqjbK9d5zwDtBzFgMd36gAnz8y3mQwUGqHhhMw+vV1r0N0= + secure: "TyMGH+sbPmKs9lKCziKShxWr3G6im0owEchVrbUChWnQIQv1WydXftFoEoUsVl6qZspjehWK1b1AsnIgCXK0HtEi4DnqLsxs0s36bOjfg5yHBT/pETTr6kcq7KAL4Be4GmI331k6gT1Oi0TPFp7Sg9xpiWsQqKIHA5Szk2wpFQ8=" + + notifications: email: on_success: never diff --git a/src/vendor/cfg-if/Cargo.toml b/src/vendor/cfg-if/Cargo.toml index b0e634aa9e..7afa063d1e 100644 --- a/src/vendor/cfg-if/Cargo.toml +++ b/src/vendor/cfg-if/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cfg-if" -version = "0.1.0" +version = "0.1.2" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" diff --git a/src/vendor/bitflags-0.7.0/LICENSE-APACHE b/src/vendor/cfg-if/LICENSE-APACHE similarity index 100% rename from src/vendor/bitflags-0.7.0/LICENSE-APACHE rename to src/vendor/cfg-if/LICENSE-APACHE diff --git a/src/vendor/toml-0.3.2/LICENSE-MIT b/src/vendor/cfg-if/LICENSE-MIT similarity index 100% rename from src/vendor/toml-0.3.2/LICENSE-MIT rename to src/vendor/cfg-if/LICENSE-MIT diff --git a/src/vendor/cfg-if/src/lib.rs b/src/vendor/cfg-if/src/lib.rs index 57fa291c49..563cda81f4 100644 --- a/src/vendor/cfg-if/src/lib.rs +++ b/src/vendor/cfg-if/src/lib.rs @@ -26,6 +26,8 @@ //! # fn main() {} //! ``` +#![no_std] + #![doc(html_root_url = "http://alexcrichton.com/cfg-if")] #![deny(missing_docs)] #![cfg_attr(test, deny(warnings))] @@ -42,6 +44,19 @@ macro_rules! cfg_if { $( ( ($($meta),*) ($($it)*) ), )* ( () ($($it2)*) ), } + }; + ( + if #[cfg($($i_met:meta),*)] { $($i_it:item)* } + $( + else if #[cfg($($e_met:meta),*)] { $($e_it:item)* } + )* + ) => { + __cfg_if_items! { + () ; + ( ($($i_met),*) ($($i_it)*) ), + $( ( ($($e_met),*) ($($e_it)*) ), )* + ( () () ), + } } } @@ -67,7 +82,7 @@ macro_rules! __cfg_if_apply { mod tests { cfg_if! { if #[cfg(test)] { - use std::option::Option as Option2; + use core::option::Option as Option2; fn works1() -> Option2 { Some(1) } } else { fn works1() -> Option { None } @@ -92,10 +107,27 @@ mod tests { } } + cfg_if! { + if #[cfg(test)] { + use core::option::Option as Option3; + fn works4() -> Option3 { Some(1) } + } + } + + cfg_if! { + if #[cfg(foo)] { + fn works5() -> bool { false } + } else if #[cfg(test)] { + fn works5() -> bool { true } + } + } + #[test] fn it_works() { assert!(works1().is_some()); assert!(works2()); assert!(works3()); + assert!(works4().is_some()); + assert!(works5()); } } diff --git a/src/vendor/clap/.appveyor.yml b/src/vendor/clap/.appveyor.yml new file mode 100644 index 0000000000..247a550d9f --- /dev/null +++ b/src/vendor/clap/.appveyor.yml @@ -0,0 +1,17 @@ +environment: + matrix: + - TARGET: x86_64-pc-windows-msvc + - TARGET: i686-pc-windows-msvc + - TARGET: x86_64-pc-windows-gnu + - TARGET: i686-pc-windows-gnu + RUST_BACKTRACE: full +install: + - curl -sSf -o rustup-init.exe https://win.rustup.rs/ + - rustup-init.exe -y --default-host %TARGET% + - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin + - rustc -vV + - cargo -vV +build: false +test_script: + - cargo build --verbose --features yaml + - cargo test --verbose --features yaml diff --git a/src/vendor/clap/.cargo-checksum.json b/src/vendor/clap/.cargo-checksum.json index 160505da4f..67692f6c6e 100644 --- a/src/vendor/clap/.cargo-checksum.json +++ b/src/vendor/clap/.cargo-checksum.json @@ -1 +1 @@ -{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".clog.toml":"2cb6bf3b74ca4ac47494e7c78327342a425e7832b8586ffa27c52041a26f1adf",".github/CONTRIBUTING.md":"86261d07a0e376e1ae86c9a7fab64f8b0ff517078879459e98c9cc560588d139",".github/ISSUE_TEMPLATE.md":"681afbd64b3603e3e82789ceb6841d851eaa7333caec5769173462bab1b5d82b",".gitignore":"57b1cc6deeaf68d35909201e4bb863c7dbec899ceaa17edde7b9fe64ece8c3e9",".travis.yml":"7f0c194b014c137dfc4c0fee0d34028572ec745e3e7a66d3d138cbb67e1edb3d","CHANGELOG.md":"17ff8a87a56d280abf36738ce6e1ffcb60dcd0464f77566efccf0391c3c31dfe","CONTRIBUTORS.md":"c22d68e41b80ecc22c4ca612d7fad27b7e671240a62da9f4e777740171bdd7ec","Cargo.toml":"dcc7b280354d400e319289ca78d3ecdf4c2bde879c2695f8747e6bf016d0a530","LICENSE-MIT":"6725d1437fc6c77301f2ff0e7d52914cf4f9509213e1078dc77d9356dbe6eac5","README.md":"d435f53baab48e726d65f6eb95b675acfe32fecda47d6158bee11600f7780316","appveyor.yml":"303c64c2cc84c24b3c9ac0b4cd66b98d6bb25dec7d030ed53e5cb6ab3f13ebd1","clap-test.rs":"6e06a0dda7a8dfd1d634fc22cea00e90259b524c9a1d4d5a37ca08bb930b4009","index.html":"36f9ce4465266f3af9a259444b01c4239200473cabfc848f789f75b322a3ea8f","justfile":"82c20f705bc096a391f4b7232dbf712a0d3f00f9a2229aaa674f035ad0d9650e","rustfmt.toml":"8fd2d63119df515fd5f44e530c709b19d66b09fbc2e22a640bf4b64c57e7d6b3","src/app/help.rs":"44b4acef869eb05da01c0946bf4eae85dd9d52c5aebf8b2dc6ce036dc19c6abc","src/app/macros.rs":"37f3e9384072adfad42003589f40ff4425db8785d4ab97e8933783b85131375b","src/app/meta.rs":"81414fb8bfb32fa809eb470f3f3deee6610bfe54205240095371708c3d037933","src/app/mod.rs":"fbf321cb4998dae437a9f58b7f6b5b2b7f1199cd617b0958bf17e12aad0a4aa5","src/app/parser.rs":"36761f46e032c7b58e344671b9a39c769a9d58a22b84cf7f276c5d91309fab56","src/app/settings.rs":"a677ea59465e0a85d7b8d61e58a2ec5fe6bb909ab6e6097cc673888224ce81d5","src/args/any_arg.rs":"0b2cc1b9942dd76120059c3f2be8581a72d6cd828bb7bab0781fb4468dc801ab","src/args/arg.rs":"f5fc1b5ccdabc21f228bf29b1cd3e449016900b65fe778885934dad29b6a77e4","src/args/arg_builder/base.rs":"e5e8b5e23f589b7cb99593e15b0e8954bf34905173f824722e0534911fd5bfed","src/args/arg_builder/flag.rs":"be5802a1f83388eac0cea54b6ef5f8f69fdf8169b329212f232dadac9c34effd","src/args/arg_builder/mod.rs":"7a32c8fd85b48f7b60e5f2c13dc70fa9100aa65cd933ba419300d28d682bf722","src/args/arg_builder/option.rs":"eb7fa02f866257546420d6444c12b8b47477378250d77d95d6798f493299313f","src/args/arg_builder/positional.rs":"d6250d5d2855f09870c00f4ffa13d063675be25d15c8c1090c952c7af1733f61","src/args/arg_builder/switched.rs":"43b4da391b51a475a8a9bd3a396f507c2ae21bbd5a5a923bb8b1fd6d7829f228","src/args/arg_builder/valued.rs":"4bf03b061224175d0082caf889a1558a51ee67d412e405b6cee6156277dcf4bb","src/args/arg_matcher.rs":"62ec288d0e0cc0faf21804a6395a92ae05546d9735db8a287d37cdde5c555a0a","src/args/arg_matches.rs":"5b948efdc025fc9c39c93a84fbda1c8916c400e3557ae09a422aa29091072414","src/args/group.rs":"9284416655e0def075a71a91bf69be7953266bf6624def990855ccbe240249ff","src/args/macros.rs":"fe2d75a2849df287de1425880f3bb7e65e835ef4d66328638157899929362e10","src/args/matched_arg.rs":"ce480cff445964707663886ebbdc7c7bc168ac079ea1dafe928305d387ca07f7","src/args/mod.rs":"e15fc06bd63c3ef09c13c38c801b70c3318350456a3171d0110816eb92e0a0e2","src/args/settings.rs":"f1cdaa80def5760c72efdfddb3c509fa6ebbd83defb746dfc8fbfd57bcd080e3","src/args/subcommand.rs":"e1ad9638c33785f1301675de1795b0a4f4b079452aa11f7526d263c2a1179432","src/completions/bash.rs":"82743850d5a59e522f775e3f1e90c47adebdc78fc0d6f12ba08fab633803fa18","src/completions/fish.rs":"698f39241ff62b094cc112c139b368b7dd6e0fc12b070a437a9670ea09262598","src/completions/macros.rs":"ebad5037e6e63401b1a54498e09d3bd93d1a3a06f045c2990902d47eb9a73774","src/completions/mod.rs":"3467ef4e92f7653ff6aa93bce581bfce122b04eed7a409ca3f3931858a52fb82","src/completions/powershell.rs":"f934f8f4f5ad4667bf166192ef644894320993bac896790de96bfb52f0f4df84","src/completions/shell.rs":"c7995ca229fd0d8671761da0aca0513c4f740165f02d06cd97aa0ae881c22cd4","src/completions/zsh.rs":"61a34aa2991a21d5479edeaf6bbdb38ec1e124403bbdadd52c6b3308071f16e2","src/errors.rs":"4da870f2002486b107b6b4b3dc8a5c81525b8416cef9aa1efb6bef495e431c09","src/fmt.rs":"b74adea43a9f0fc36f3aec5d0486c2581cae5de4315b86617351f71cc50056dd","src/lib.rs":"4c3aacccc5670320e9a3ed613906550e264187dfffc44a31a989f0c2d371e8f2","src/macros.rs":"2dfcd5b10d16485c70ff33138140858532ef48a6f3f29ef0ff9ecb664638222b","src/osstringext.rs":"a6648fcb1a23c4976fadfbcb88f81f8df2c107abce9b3137b2a5decc7113d0f9","src/strext.rs":"d4418d396069e9c05804f92c042ba7192a4244e46059e2edc98670b45cd2daee","src/suggestions.rs":"ca35c332646fe9d3f93c6263830eaef77c87522f71794bfc986f90fc34229dec","src/usage_parser.rs":"186d9b52f6a3cc167c7b41e7ffbb8642a46cb9aac1872ddf5ccff82922078bfc"},"package":"95b78f3fe0fc94c13c731714363260e04b557a637166f33a4570d3189d642374"} \ No newline at end of file +{"files":{".appveyor.yml":"38fb7e583271029caad727c9123a2b2679b7c59971de418f16dc5136dbebaeb5",".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".clog.toml":"f691701bd51b5f311931d0d8f05fa3d78c00dda8d60f3313e21011309c736ff1",".github/CONTRIBUTING.md":"f7eff737f3aa25294802fefb233e3758a64b248781dbbf3262532d693f340a87",".github/ISSUE_TEMPLATE.md":"681afbd64b3603e3e82789ceb6841d851eaa7333caec5769173462bab1b5d82b",".gitignore":"57b1cc6deeaf68d35909201e4bb863c7dbec899ceaa17edde7b9fe64ece8c3e9",".mention-bot":"51790ab49f43ed86a4a7c3d2e468aa5fa526ca5e2ac6af20432a2cb5b2fdbe84",".travis.yml":"2975b3159624d4ecc4dd29577f378e9d4fa27f1991bfd5042ac3c267fb2cdd38","CHANGELOG.md":"89936cd672f43681351e1b76622cc44d11c69f60440dd101f7b9db1cf2f184f7","CONTRIBUTORS.md":"5d7dbafaff6879bbfbb01b22cca299953ec163872d8d624bbf99e20851ca0165","Cargo.toml":"f12c622fae3f6582168616219b6e07e2ec99943e9515b76f97974e75227b9aa0","Cargo.toml.orig":"a4e07b1fb89cd8627eb54bd264aaa7cd3830ef6e7fa9916f787e3e54b7ab5651","LICENSE-MIT":"6725d1437fc6c77301f2ff0e7d52914cf4f9509213e1078dc77d9356dbe6eac5","README.md":"bce567fb1e3e57129f3d0f58f5a1e9e07dc7414731644a47939c50b76f9976bb","clap-test.rs":"995a9d41ef372a814616113f4a58c1e580043678e54527afc2ebee7e8e1d3ef5","index.html":"36f9ce4465266f3af9a259444b01c4239200473cabfc848f789f75b322a3ea8f","justfile":"811b2dec57aec46e570aeeb9945018cf87fe65f6d5b27cdb9ffca79d906910f6","rustfmt.toml":"8fd2d63119df515fd5f44e530c709b19d66b09fbc2e22a640bf4b64c57e7d6b3","src/app/help.rs":"515f3ec638e3df8323b44c906073c07657122ec1b34bdadbdc47661c5d97ad1d","src/app/macros.rs":"44610b6522cedbcb140670aac27c796379f562ce77fcf5e8d104b038aadf52ec","src/app/meta.rs":"a56d28bb466a8ba68155b3f2883e85228b4b74cf25658f62fc050e07cff2dc85","src/app/mod.rs":"d0e1843ae1f77c1da4179cebdd8fb1ea55803002fb1ae96087de3a8cdcedf6fc","src/app/parser.rs":"1bae4cecf4fc798efdc2ad8d237f17536dafd7524e2d9a366f30f72a8a275846","src/app/settings.rs":"c6b87d4da01891123edddee9e28b048cba0c19d8c1db34ad5ad3e85b657c6b97","src/app/usage.rs":"703cec975c53e7f01b14b4593de41c518910ab347bc4c54efe79367a704ffc4c","src/app/validator.rs":"bc2291f6231a63456acab9e7743d1f881f1d5dfc17955394fa856703a8e80086","src/args/any_arg.rs":"b082385eeff2505ced7b747bd44d20a3fb6fd9d4bd14be9e99870699c43ea072","src/args/arg.rs":"673de3f1957eccb1b116255bac9638fe24c0da54ccb358d958446c8ed54c9621","src/args/arg_builder/base.rs":"8b99a9ab811df3e0bdcfba8c0994042b0bcd06d8ddf794ab559baaf9a490ba59","src/args/arg_builder/flag.rs":"4007a950869789b1f4d5f953107aee228477e2d5fe82515d3b895286c65522c6","src/args/arg_builder/mod.rs":"7a32c8fd85b48f7b60e5f2c13dc70fa9100aa65cd933ba419300d28d682bf722","src/args/arg_builder/option.rs":"d5e5243e3a72d2c820c8fad4e1efc4b985881c6f60f3a72757b33a9054a87e99","src/args/arg_builder/positional.rs":"f103a22803d9fb7f7c8f37f705fe214fdaad46903439964fc13740ec6f647eb8","src/args/arg_builder/switched.rs":"61f5121b0ec746461215a47e1b7a4d699a37a3f181172820e0615f68d5f6f0ef","src/args/arg_builder/valued.rs":"19368a03e046d6b63451c3d04dff6e51d49f140ed45330f82879539c6d1b28dd","src/args/arg_matcher.rs":"27829739ae12ac7800a26109e751ce9f8c3d26e262d41de161a38baf5c421167","src/args/arg_matches.rs":"9d72a388053ef0c31fe2516df9ea791a4d0f6c0b5e9758eb61886f1ac8df89ab","src/args/group.rs":"7fe5e2f0dd24faf1765410a9336d85976875e964d7f246e1fa216c4808d88dde","src/args/macros.rs":"57f248e2694f9413cbbaf9087813ed4f27064f5f8e29eaf4ec41ec2b274ae806","src/args/matched_arg.rs":"1ed8d338869ecc3b5fa426ef4cf42f4c9c3b1dd538cdea1fe0489169345536f7","src/args/mod.rs":"c155cd989fa4ca1f8de6a79115afbf5086f092adcb854ff9698b9100f45fc323","src/args/settings.rs":"2753ff50046def9ccb7f601b3d9f565348da1ef0253af24ccee94616a2e5c470","src/args/subcommand.rs":"e1ad9638c33785f1301675de1795b0a4f4b079452aa11f7526d263c2a1179432","src/completions/bash.rs":"116c6830ee2b6310f299a69924f5b1e39b05ebec2b5f7b0ffe3b6938b7fa5514","src/completions/fish.rs":"63975f8beea9af6bef66c7dd7938bfa61c6f871995a74dbc1545daa9fbc1f2d0","src/completions/macros.rs":"ebad5037e6e63401b1a54498e09d3bd93d1a3a06f045c2990902d47eb9a73774","src/completions/mod.rs":"5d4a734df6a21e6c1e0831a2f7be50a45d2e7bdaf7475589ea78b978643229cd","src/completions/powershell.rs":"866409e5d0a9b2551d739f86c0e4faf86911e9e7c656fb74b38e6960844233b5","src/completions/shell.rs":"c7995ca229fd0d8671761da0aca0513c4f740165f02d06cd97aa0ae881c22cd4","src/completions/zsh.rs":"8ac4576e1cb3b1403dbb35ce146159aa8b29864e1d8201776200d999052b422d","src/errors.rs":"3c46a4d79d9304ffb152a190528ec9db0cb6c05799bb5211e6df9f7d7abab814","src/fmt.rs":"f205f784268572544ff7e84a89f416c898255404275d4ab1f8fea7e89695daa9","src/lib.rs":"87b3ee49c6389cdbaa23e705732bcc68e7235bb16ff469321c92a89258c21beb","src/macros.rs":"2317a90223c80d8688fea5334b09b783c8aca8894e6c22ec2fd400ce941d301b","src/osstringext.rs":"a87a5a0685dd8310f6329d5f8e8f54c0fac68eb75595a835aeb1c36208efd5f9","src/strext.rs":"d4418d396069e9c05804f92c042ba7192a4244e46059e2edc98670b45cd2daee","src/suggestions.rs":"ad1165a9896382a0f09f73c0f6bf468454c19da207f28c3973e02879f453ad68","src/usage_parser.rs":"a04143bba42a6506746091a3f898c38e2c7409bacefed21fa8194c90961ca390"},"package":"867a885995b4184be051b70a592d4d70e32d7a188db6e8dff626af286a962771"} \ No newline at end of file diff --git a/src/vendor/clap/.clog.toml b/src/vendor/clap/.clog.toml index 6c91769039..5a62fa4bad 100644 --- a/src/vendor/clap/.clog.toml +++ b/src/vendor/clap/.clog.toml @@ -8,4 +8,6 @@ Performance = ["perf"] Improvements = ["impr", "im", "imp"] Documentation = ["docs"] Deprecations = ["depr"] -Examples = ["examples"] \ No newline at end of file +Examples = ["examples"] +"New Settings" = ["setting", "settings"] +"API Additions" = ["add", "api"] diff --git a/src/vendor/clap/.github/CONTRIBUTING.md b/src/vendor/clap/.github/CONTRIBUTING.md index f8b8514fe5..b973a54b26 100644 --- a/src/vendor/clap/.github/CONTRIBUTING.md +++ b/src/vendor/clap/.github/CONTRIBUTING.md @@ -2,33 +2,6 @@ Contributions are always welcome! Please use the following guidelines when contributing to `clap` -1. Fork `clap` -2. Clone your fork (`git clone https://github.com/$YOUR_USERNAME/clap-rs && cd clap-rs`) -3. Create new branch (`git checkout -b new-branch`) -4. Make your changes, and commit (`git commit -am "your message"`) - * I use a [conventional](https://github.com/ajoslin/conventional-changelog/blob/a5505865ff3dd710cf757f50530e73ef0ca641da/conventions/angular.md) changelog format so I can update my changelog using [clog](https://github.com/clog-tool/clog-cli) - * In addition to the conventions defined above, I also use `imp`, `wip`, `examples`. - * Format your commit subject line using the following format: `TYPE(COMPONENT): MESSAGE` where `TYPE` is one of the following: - - `feat` - A new feature - - `imp` - An improvement to an existing feature - - `perf` - A performance improvement - - `docs` - Changes to documentation only - - `tests` - Changes to the testing framework or tests only - - `fix` - A bug fix - - `refactor` - Code functionality doesn't change, but underlying structure may - - `style` - Stylistic changes only, no functionality changes - - `wip` - A work in progress commit (Should typically be `git rebase`'ed away) - - `chore` - Catch all or things that have to do with the build system, etc - - `examples` - Changes to existing example, or a new example - * The `COMPONENT` is optional, and may be a single file, directory, or logical component. Can be omitted if commit applies globally -5. Run the tests (`cargo test --features "yaml unstable"`) -5. Run the lints (`cargo build --features lints`) (requires a nightly compiler) -6. `git rebase` into concise commits and remove `--fixup`s (`git rebase -i HEAD~NUM` where `NUM` is number of commits back) -7. Push your changes back to your fork (`git push origin $your-branch`) -8. Create a pull request! (You can also create the pull request first, and we'll merge when ready. This a good way to discuss proposed changes.) - -Another really great way to help is if you find an interesting, or helpful way in which to use `clap`. You can either add it to the [examples/](examples) directory, or file an issue and tell me. I'm all about giving credit where credit is due :) - ## Goals There are a few goals of `clap` that I'd like to maintain throughout contributions. @@ -43,3 +16,41 @@ There are a few goals of `clap` that I'd like to maintain throughout contributio * Try to be cognizant of memory usage - Once parsing is complete, the memory footprint of `clap` should be low since the main program is the star of the show * `panic!` on *developer* error, exit gracefully on *end-user* error + +### Commit Messages + +I use a [conventional](https://github.com/ajoslin/conventional-changelog/blob/a5505865ff3dd710cf757f50530e73ef0ca641da/conventions/angular.md) changelog format so I can update my changelog automatically using [clog](https://github.com/clog-tool/clog-cli) + + * Please format your commit subject line using the following format: `TYPE(COMPONENT): MESSAGE` where `TYPE` is one of the following: + - `api` - An addition to the API + - `setting` - A new `AppSettings` variant + - `feat` - A new feature of an existing API + - `imp` - An improvement to an existing feature/API + - `perf` - A performance improvement + - `docs` - Changes to documentation only + - `tests` - Changes to the testing framework or tests only + - `fix` - A bug fix + - `refactor` - Code functionality doesn't change, but underlying structure may + - `style` - Stylistic changes only, no functionality changes + - `wip` - A work in progress commit (Should typically be `git rebase`'ed away) + - `chore` - Catch all or things that have to do with the build system, etc + - `examples` - Changes to existing example, or a new example + * The `COMPONENT` is optional, and may be a single file, directory, or logical component. Parenthesis can be omitted if you are opting not to use the `COMPONENT`. + +### Tests and Documentation + +1. Create tests for your changes +2. **Ensure the tests are passing.** Run the tests (`cargo test --features "yaml unstable"`), alternatively `just run-tests` if you have `just` installed. +3. **Optional** Run the lints (`cargo build --features lints`) (requires a nightly compiler), alternatively `just lint` +4. Ensure your changes contain documentation if adding new APIs or features. + +### Preparing the PR + +1. `git rebase` into concise commits and remove `--fixup`s or `wip` commits (`git rebase -i HEAD~NUM` where `NUM` is number of commits back to start the rebase) +2. Push your changes back to your fork (`git push origin $your-branch`) +3. Create a pull request against `master`! (You can also create the pull request first, and we'll merge when ready. This a good way to discuss proposed changes.) + +### Other ways to contribute + +Another really great way to help is if you find an interesting, or helpful way in which to use `clap`. You can either add it to the [examples/](../examples) directory, or file an issue and tell me. I'm all about giving credit where credit is due :) + diff --git a/src/vendor/clap/.mention-bot b/src/vendor/clap/.mention-bot new file mode 100644 index 0000000000..f339f59cd0 --- /dev/null +++ b/src/vendor/clap/.mention-bot @@ -0,0 +1,9 @@ +{ + "findPotentialReviewers": false, + "alwaysNotifyForPaths": [ + { + "name": "kbknapp", + "files": ["**/*.rs", "**/*.md", "*"] + } + ] +} diff --git a/src/vendor/clap/.travis.yml b/src/vendor/clap/.travis.yml index 97d2e74042..6e74a6ae33 100644 --- a/src/vendor/clap/.travis.yml +++ b/src/vendor/clap/.travis.yml @@ -3,7 +3,7 @@ language: rust cache: cargo rust: - nightly - - nightly-2016-11-20 + - nightly-2017-01-25 - beta - stable - 1.11.0 diff --git a/src/vendor/clap/CHANGELOG.md b/src/vendor/clap/CHANGELOG.md index 7ea38c9ee7..c1015a0fb0 100644 --- a/src/vendor/clap/CHANGELOG.md +++ b/src/vendor/clap/CHANGELOG.md @@ -1,3 +1,361 @@ + +### v2.25.0 (2017-06-20) + + +#### Features + +* use textwrap crate for wrapping help texts ([b93870c1](https://github.com/kbknapp/clap-rs/commit/b93870c10ae3bd90d233c586a33e086803117285)) + +#### Improvements + +* **Suggestions:** suggests to use flag after subcommand when applicable ([2671ca72](https://github.com/kbknapp/clap-rs/commit/2671ca7260119d4311d21c4075466aafdd9da734)) +* Bumps bitflags crate to v0.9 + +#### Documentation + +* Change `who's` -> `whose` ([53c1ffe8](https://github.com/kbknapp/clap-rs/commit/53c1ffe87f38b05d8804a0f7832412a952845349)) + +#### Documentation + +* **App::template:** adds details about the necessity to use AppSettings::UnifiedHelpMessage when using {unified} tags in the help template ([cbea3d5a](https://github.com/kbknapp/clap-rs/commit/cbea3d5acf3271a7a734498c4d99c709941c331e), closes [#949](https://github.com/kbknapp/clap-rs/issues/949)) +* **Arg::allow_hyphen_values:** updates the docs to include warnings for allow_hyphen_values and multiple(true) used together ([f9b0d657](https://github.com/kbknapp/clap-rs/commit/f9b0d657835d3f517f313d70962177dc30acf4a7)) +* **README.md:** + * added a warning about using ~ deps ([821929b5](https://github.com/kbknapp/clap-rs/commit/821929b51bd60213955705900a436c9a64fcb79f), closes [#964](https://github.com/kbknapp/clap-rs/issues/964)) + * added a warning about using ~ deps ([667697b0](https://github.com/kbknapp/clap-rs/commit/667697b0018369b71da41d02d567ab57df0f4887)) +* **clap_app!:** adds using the @group specifier to the macro docs ([826048cb](https://github.com/kbknapp/clap-rs/commit/826048cb3cbc0280169303f1498ff0a2b7395883), closes [#932](https://github.com/kbknapp/clap-rs/issues/932)) + + + + +### v2.24.2 (2017-05-15) + + +#### Bug Fixes + +* adds a debug assertion to ensure all args added to groups actually exist ([14f6b8f3](https://github.com/kbknapp/clap-rs/commit/14f6b8f3a2f6df73aeeec9c54a54909b1acfc158), closes [#917](https://github.com/kbknapp/clap-rs/issues/917)) +* fixes a bug where args that allow values to start with a hyphen couldnt contain a double hyphen -- as a value ([ebf73a09](https://github.com/kbknapp/clap-rs/commit/ebf73a09db6f3c03c19cdd76b1ba6113930e1643), closes [#960](https://github.com/kbknapp/clap-rs/issues/960)) +* fixes a bug where positional argument help text is misaligned ([54c16836](https://github.com/kbknapp/clap-rs/commit/54c16836dea4651806a2cfad53146a83fa3abf21)) + +#### Documentation + +* **App::template:** adds details about the necessity to use AppSettings::UnifiedHelpMessage when using {unified} tags in the help template ([cf569438](https://github.com/kbknapp/clap-rs/commit/cf569438f309c199800bb8e46c9f140187de69d7), closes [#949](https://github.com/kbknapp/clap-rs/issues/949)) +* **Arg::allow_hyphen_values:** updates the docs to include warnings for allow_hyphen_values and multiple(true) used together ([ded5a2f1](https://github.com/kbknapp/clap-rs/commit/ded5a2f15474d4a5bd46a67b130ccb8b6781bd01)) +* **clap_app!:** adds using the @group specifier to the macro docs ([fe85fcb1](https://github.com/kbknapp/clap-rs/commit/fe85fcb1772b61f13b20b7ea5290e2437a76190c), closes [#932](https://github.com/kbknapp/clap-rs/issues/932)) + + + + +### v2.24.0 (2017-05-07) + + +#### Bug Fixes + +* fixes a bug where args with last(true) and required(true) set were not being printed in the usage string ([3ac533fe](https://github.com/kbknapp/clap-rs/commit/3ac533fedabf713943eedf006f830a5a486bbe80), closes [#944](https://github.com/kbknapp/clap-rs/issues/944)) +* fixes a bug that was printing the arg name, instead of value name when Arg::last(true) was used ([e1fe8ac3](https://github.com/kbknapp/clap-rs/commit/e1fe8ac3bc1f9cf4e36df0d881f8419755f1787b), closes [#940](https://github.com/kbknapp/clap-rs/issues/940)) +* fixes a bug where flags were parsed as flags AND positional values when specific combinations of settings were used ([20f83292](https://github.com/kbknapp/clap-rs/commit/20f83292d070038b8cee2a6b47e91f6b0a2f7871), closes [#946](https://github.com/kbknapp/clap-rs/issues/946)) + + + + +## v2.24.0 (2017-05-05) + + +#### Documentation + +* **README.md:** fix some typos ([fa34deac](https://github.com/kbknapp/clap-rs/commit/fa34deac079f334c3af97bb7fb151880ba8887f8)) + +#### API Additions + +* **Arg:** add `default_value_os` ([d5ef8955](https://github.com/kbknapp/clap-rs/commit/d5ef8955414b1587060f7218385256105b639c88)) +* **arg_matches.rs:** Added a Default implementation for Values and OsValues iterators. ([0a4384e3](https://github.com/kbknapp/clap-rs/commit/0a4384e350eed74c2a4dc8964c203f21ac64897f)) + + + +### v2.23.2 (2017-04-19) + + +#### Bug Fixes + +* **PowerShell Completions:** fixes a bug where powershells completions cant be used if no subcommands are defined ([a8bce558](https://github.com/kbknapp/clap-rs/commit/a8bce55837dc4e0fb187dc93180884a40ae09c6f), closes [#931](https://github.com/kbknapp/clap-rs/issues/931)) + +#### Improvements + +* bumps term_size to take advantage of better terminal dimension handling ([e05100b7](https://github.com/kbknapp/clap-rs/commit/e05100b73d74066a90876bf38f952adf5e8ee422)) +* **PowerShell Completions:** massively dedups subcommand names in the generate script to make smaller scripts that are still functionally equiv ([85b0e1cc](https://github.com/kbknapp/clap-rs/commit/85b0e1cc4b9755dda75a93d898d79bc38631552b)) + +#### Documentation + +* Fix a typo the minimum rust version required ([71dabba3](https://github.com/kbknapp/clap-rs/commit/71dabba3ea0a17c88b0e2199c9d99f0acbf3bc17)) + + +### v2.23.1 (2017-04-05) + + +#### Bug Fixes + +* fixes a missing newline character in the autogenerated help and version messages in some instances ([5ae9007d](https://github.com/kbknapp/clap-rs/commit/5ae9007d984ae94ae2752df51bcbaeb0ec89bc15)) + + + +## v2.23.0 (2017-04-05) + + +#### API Additions + +* `App::long_about` +* `App::long_version` +* `App::print_long_help` +* `App::write_long_help` +* `App::print_long_version` +* `App::write_long_version` +* `Arg::long_help` + +#### Features + +* allows distinguishing between short and long version messages (-V/short or --version/long) ([59272b06](https://github.com/kbknapp/clap-rs/commit/59272b06cc213289dc604dbc694cb95d383a5d68)) +* allows distinguishing between short and long help with subcommands in the same manner as args ([6b371891](https://github.com/kbknapp/clap-rs/commit/6b371891a1702173a849d1e95f9fecb168bf6fc4)) +* allows specifying a short help vs a long help (i.e. varying levels of detail depending on if -h or --help was used) ([ef1b24c3](https://github.com/kbknapp/clap-rs/commit/ef1b24c3a0dff2f58c5e2e90880fbc2b69df20ee)) +* **clap_app!:** adds support for arg names with hyphens similar to longs with hyphens ([f7a88779](https://github.com/kbknapp/clap-rs/commit/f7a8877978c8f90e6543d4f0d9600c086cf92cd7), closes [#869](https://github.com/kbknapp/clap-rs/issues/869)) + +#### Bug Fixes + +* fixes a bug that wasn't allowing help and version to be properly overridden ([8b2ceb83](https://github.com/kbknapp/clap-rs/commit/8b2ceb8368bcb70689fadf1c7f4b9549184926c1), closes [#922](https://github.com/kbknapp/clap-rs/issues/922)) + +#### Documentation + +* **clap_app!:** documents the `--("some-arg")` method for using args with hyphens inside them ([bc08ef3e](https://github.com/kbknapp/clap-rs/commit/bc08ef3e185393073d969d301989b6319c616c1f), closes [#919](https://github.com/kbknapp/clap-rs/issues/919)) + + + + +### v2.22.2 (2017-03-30) + + +#### Bug Fixes + +* **Custom Usage Strings:** fixes the usage string regression when using help templates ([0e4fd96d](https://github.com/kbknapp/clap-rs/commit/0e4fd96d74280d306d09e60ac44f938a82321769)) + + + + +### v2.22.1 (2017-03-24) + + +#### Bug Fixes + +* **usage:** fixes a big regression with custom usage strings ([2c41caba](https://github.com/kbknapp/clap-rs/commit/2c41caba3c7d723a2894e315d04da796b0e97759)) + + +## v2.22.0 (2017-03-23) + +#### API Additions + +* **App::name:** adds the ability to change the name of the App instance after creation ([d49e8292](https://github.com/kbknapp/clap-rs/commit/d49e8292b026b06e2b70447cd9f08299f4fcba76), closes [#908](https://github.com/kbknapp/clap-rs/issues/908)) +* **Arg::hide_default_value:** adds ability to hide the default value of an argument from the help string ([89e6ea86](https://github.com/kbknapp/clap-rs/commit/89e6ea861e16a1ad56757ca12f6b32d02253e44a), closes [#902](https://github.com/kbknapp/clap-rs/issues/902)) + + + +### v2.21.3 (2017-03-23) + +#### Bug Fixes + +* **yaml:** adds support for loading author info from yaml ([e04c390c](https://github.com/kbknapp/clap-rs/commit/e04c390c597a55fa27e724050342f16c42f1c5c9)) + + + +### v2.21.2 (2017-03-17) + + +#### Improvements + +* add fish subcommand help support ([f8f68cf8](https://github.com/kbknapp/clap-rs/commit/f8f68cf8251669aef4539a25a7c1166f0ac81ea6)) +* options that use `require_equals(true)` now display the equals sign in help messages, usage strings, and errors" ([c8eb0384](https://github.com/kbknapp/clap-rs/commit/c8eb0384d394d2900ccdc1593099c97808a3fa05), closes [#903](https://github.com/kbknapp/clap-rs/issues/903)) + + +#### Bug Fixes + +* setting the max term width now correctly propagates down through child subcommands + + + + +### v2.21.1 (2017-03-12) + + +#### Bug Fixes + +* **ArgRequiredElseHelp:** fixes the precedence of this error to prioritize over other error messages ([74b751ff](https://github.com/kbknapp/clap-rs/commit/74b751ff2e3631e337b7946347c1119829a41c53), closes [#895](https://github.com/kbknapp/clap-rs/issues/895)) +* **Positionals:** fixes some regression bugs resulting from old asserts in debug mode. ([9a3bc98e](https://github.com/kbknapp/clap-rs/commit/9a3bc98e9b55e7514b74b73374c5ac8b6e5e0508), closes [#896](https://github.com/kbknapp/clap-rs/issues/896)) + + + + +## v2.21.0 (2017-03-09) + +#### Performance + +* doesn't run `arg_post_processing` on multiple values anymore ([ec516182](https://github.com/kbknapp/clap-rs/commit/ec5161828729f6a53f0fccec8648f71697f01f78)) +* changes internal use of `VecMap` to `Vec` for matched values of `Arg`s ([22bf137a](https://github.com/kbknapp/clap-rs/commit/22bf137ac581684c6ed460d2c3c640c503d62621)) +* vastly reduces the amount of cloning when adding non-global args minus when they're added from `App::args` which is forced to clone ([8da0303b](https://github.com/kbknapp/clap-rs/commit/8da0303bc02db5fe047cfc0631a9da41d9dc60f7)) +* refactor to remove unneeded vectors and allocations and checks for significant performance increases ([0efa4119](https://github.com/kbknapp/clap-rs/commit/0efa4119632f134fc5b8b9695b007dd94b76735d)) + +#### Documentation + +* Fix examples link in CONTRIBUTING.md ([60cf875d](https://github.com/kbknapp/clap-rs/commit/60cf875d67a252e19bb85054be57696fac2c57a1)) + +#### Improvements + +* when `AppSettings::SubcommandsNegateReqs` and `ArgsNegateSubcommands` are used, a new more accurate double line usage string is shown ([50f02300](https://github.com/kbknapp/clap-rs/commit/50f02300d81788817acefef0697e157e01b6ca32), closes [#871](https://github.com/kbknapp/clap-rs/issues/871)) + +#### API Additions + +* **Arg::last:** adds the ability to mark a positional argument as 'last' which means it should be used with `--` syntax and can be accessed early ([6a7aea90](https://github.com/kbknapp/clap-rs/commit/6a7aea9043b83badd9ab038b4ecc4c787716147e), closes [#888](https://github.com/kbknapp/clap-rs/issues/888)) +* provides `default_value_os` and `default_value_if[s]_os` ([0f2a3782](https://github.com/kbknapp/clap-rs/commit/0f2a378219a6930748d178ba350fe5925be5dad5), closes [#849](https://github.com/kbknapp/clap-rs/issues/849)) +* provides `App::help_message` and `App::version_message` which allows one to override the auto-generated help/version flag associated help ([389c413](https://github.com/kbknapp/clap-rs/commit/389c413b7023dccab8c76aa00577ea1d048e7a99), closes [#889](https://github.com/kbknapp/clap-rs/issues/889)) + +#### New Settings + +* **InferSubcommands:** adds a setting to allow one to infer shortened subcommands or aliases (i.e. for subcommmand "test", "t", "te", or "tes" would be allowed assuming no other ambiguities) ([11602032](https://github.com/kbknapp/clap-rs/commit/11602032f6ff05881e3adf130356e37d5e66e8f9), closes [#863](https://github.com/kbknapp/clap-rs/issues/863)) + +#### Bug Fixes + +* doesn't print the argument sections in the help message if all args in that section are hidden ([ce5ee5f5](https://github.com/kbknapp/clap-rs/commit/ce5ee5f5a76f838104aeddd01c8ec956dd347f50)) +* doesn't include the various [ARGS] [FLAGS] or [OPTIONS] if the only ones available are hidden ([7b4000af](https://github.com/kbknapp/clap-rs/commit/7b4000af97637703645c5fb2ac8bb65bd546b95b), closes [#882](https://github.com/kbknapp/clap-rs/issues/882)) +* now correctly shows subcommand as required in the usage string when AppSettings::SubcommandRequiredElseHelp is used ([8f0884c1](https://github.com/kbknapp/clap-rs/commit/8f0884c1764983a49b45de52a1eddf8d721564d8)) +* fixes some memory leaks when an error is detected and clap exits ([8c2dd287](https://github.com/kbknapp/clap-rs/commit/8c2dd28718262ace4ae0db98563809548e02a86b)) +* fixes a trait that's marked private accidentlly, but should be crate internal public ([1ae21108](https://github.com/kbknapp/clap-rs/commit/1ae21108015cea87e5360402e1747025116c7878)) +* **Completions:** fixes a bug that tried to propogate global args multiple times when generating multiple completion scripts ([5e9b9cf4](https://github.com/kbknapp/clap-rs/commit/5e9b9cf4dd80fa66a624374fd04e6545635c1f94), closes [#846](https://github.com/kbknapp/clap-rs/issues/846)) + +#### Features + +* **Options:** adds the ability to require the equals syntax with options --opt=val ([f002693d](https://github.com/kbknapp/clap-rs/commit/f002693dec6a6959c4e9590cb7b7bfffd6d6e5bc), closes [#833](https://github.com/kbknapp/clap-rs/issues/833)) + + + + +### v2.20.5 (2017-02-18) + + +#### Bug Fixes + +* **clap_app!:** fixes a critical bug of a missing fragment specifier when using `!property` style tags. ([5635c1f94](https://github.com/kbknapp/clap-rs/commit/5e9b9cf4dd80fa66a624374fd04e6545635c1f94)) + + + +### v2.20.4 (2017-02-15) + + +#### Bug Fixes + +* **Completions:** fixes a bug that tried to propogate global args multiple times when generating multiple completion scripts ([5e9b9cf4](https://github.com/kbknapp/clap-rs/commit/5e9b9cf4dd80fa66a624374fd04e6545635c1f94), closes [#846](https://github.com/kbknapp/clap-rs/issues/846)) + +#### Documentation + +* Fix examples link in CONTRIBUTING.md ([60cf875d](https://github.com/kbknapp/clap-rs/commit/60cf875d67a252e19bb85054be57696fac2c57a1)) + + + +### v2.20.3 (2017-02-03) + + +#### Documentation + +* **Macros:** adds a warning about changing values in Cargo.toml not triggering a rebuild automatically ([112aea3e](https://github.com/kbknapp/clap-rs/commit/112aea3e42ae9e0c0a2d33ebad89496dbdd95e5d), closes [#838](https://github.com/kbknapp/clap-rs/issues/838)) + +#### Bug Fixes + +* fixes a println->debugln typo ([279aa62e](https://github.com/kbknapp/clap-rs/commit/279aa62eaf08f56ce090ba16b937bc763cbb45be)) +* fixes bash completions for commands that have an underscore in the name ([7f5cfa72](https://github.com/kbknapp/clap-rs/commit/7f5cfa724f0ac4e098f5fe466c903febddb2d994), closes [#581](https://github.com/kbknapp/clap-rs/issues/581)) +* fixes a bug where ZSH completions would panic if the binary name had an underscore in it ([891a2a00](https://github.com/kbknapp/clap-rs/commit/891a2a006f775e92c556dda48bb32fac9807c4fb), closes [#581](https://github.com/kbknapp/clap-rs/issues/581)) +* allow final word to be wrapped in wrap_help ([564c5f0f](https://github.com/kbknapp/clap-rs/commit/564c5f0f1730f4a2c1cdd128664f1a981c31dcd4), closes [#828](https://github.com/kbknapp/clap-rs/issues/828)) +* fixes a bug where global args weren't included in the generated completion scripts ([9a1e006e](https://github.com/kbknapp/clap-rs/commit/9a1e006eb75ad5a6057ebd119aa90f7e06c0ace8), closes [#841](https://github.com/kbknapp/clap-rs/issues/841)) + + + + +### v2.20.2 (2017-02-03) + +#### Bug Fixes + +* fixes a critical bug where subcommand settings were being propogated too far ([74648c94](https://github.com/kbknapp/clap-rs/commit/74648c94b893df542bfa5bb595e68c7bb8167e36), closes [#832](https://github.com/kbknapp/clap-rs/issues/832)) + + +#### Improvements + +* adds ArgGroup::multiple to the supported YAML fields for building ArgGroups from YAML ([d8590037](https://github.com/kbknapp/clap-rs/commit/d8590037ce07dafd8cd5b26928aa4a9fd3018288), closes [#840](https://github.com/kbknapp/clap-rs/issues/840)) + + +### v2.20.1 (2017-01-31) + +#### Bug Fixes + +* allow final word to be wrapped in wrap_help ([564c5f0f](https://github.com/kbknapp/clap-rs/commit/564c5f0f1730f4a2c1cdd128664f1a981c31dcd4), closes [#828](https://github.com/kbknapp/clap-rs/issues/828)) +* actually show character in debug output ([84d8c547](https://github.com/kbknapp/clap-rs/commit/84d8c5476de95b7f37d61888bc4f13688b712434)) +* include final character in line lenght ([aff4ba18](https://github.com/kbknapp/clap-rs/commit/aff4ba18da8147e1259b04b0bfbc1fcb5c78a3c0)) + +#### Improvements + +* updates libc and term_size deps for the libc version conflict ([6802ac4a](https://github.com/kbknapp/clap-rs/commit/6802ac4a59c142cda9ec55ca0c45ae5cb9a6ab55)) + +#### Documentation + +* fix link from app_from_crate! to crate_authors! (#822) ([5b29be9b](https://github.com/kbknapp/clap-rs/commit/5b29be9b073330ab1f7227cdd19fe4aab39d5dcb)) +* fix spelling of "guaranteed" ([4f30a65b](https://github.com/kbknapp/clap-rs/commit/4f30a65b9c03eb09607eb91a929a6396637dc105)) + + + +#### New Settings + +* **ArgsNegateSubcommands:** disables args being allowed between subcommands ([5e2af8c9](https://github.com/kbknapp/clap-rs/commit/5e2af8c96adb5ab75fa2d1536237ebcb41869494), closes [#793](https://github.com/kbknapp/clap-rs/issues/793)) +* **DontCollapseArgsInUsage:** disables the collapsing of positional args into `[ARGS]` in the usage string ([c2978afc](https://github.com/kbknapp/clap-rs/commit/c2978afc61fb46d5263ab3b2d87ecde1c9ce1553), closes [#769](https://github.com/kbknapp/clap-rs/issues/769)) +* **DisableHelpSubcommand:** disables building the `help` subcommand ([a10fc859](https://github.com/kbknapp/clap-rs/commit/a10fc859ee20159fbd9ff4337be59b76467a64f2)) +* **AllowMissingPositional:** allows one to implement `$ prog [optional] ` style CLIs where the second postional argument is required, but the first is optional ([1110fdc7](https://github.com/kbknapp/clap-rs/commit/1110fdc7a345c108820dc45783a9bf893fa4c214), closes [#636](https://github.com/kbknapp/clap-rs/issues/636)) +* **PropagateGlobalValuesDown:** automatically propagats global arg's values down through *used* subcommands ([985536c8](https://github.com/kbknapp/clap-rs/commit/985536c8ebcc09af98aac835f42a8072ad58c262), closes [#694](https://github.com/kbknapp/clap-rs/issues/694)) + +#### API Additions + +##### Arg + +* **Arg::value_terminator:** adds the ability to terminate multiple values with a given string or char ([be64ce0c](https://github.com/kbknapp/clap-rs/commit/be64ce0c373efc106384baca3f487ea99fe7b8cf), closes [#782](https://github.com/kbknapp/clap-rs/issues/782)) +* **Arg::default_value_if[s]:** adds new methods for *conditional* default values (such as a particular value from another argument was used) ([eb4010e7](https://github.com/kbknapp/clap-rs/commit/eb4010e7b21724447ef837db11ac441915728f22)) +* **Arg::requires_if[s]:** adds the ability to *conditionally* require additional args (such as if a particular value was used) ([198449d6](https://github.com/kbknapp/clap-rs/commit/198449d64393c265f0bc327aaeac23ec4bb97226)) +* **Arg::required_if[s]:** adds the ability for an arg to be *conditionally* required (i.e. "arg X is only required if arg Y was used with value Z") ([ee9cfddf](https://github.com/kbknapp/clap-rs/commit/ee9cfddf345a6b5ae2af42ba72aa5c89e2ca7f59)) +* **Arg::validator_os:** adds ability to validate values which may contain invalid UTF-8 ([47232498](https://github.com/kbknapp/clap-rs/commit/47232498a813db4f3366ccd3e9faf0bff56433a4)) + +##### Macros + +* **crate_description!:** Uses the `Cargo.toml` description field to fill in the `App::about` method at compile time ([4d9a82db](https://github.com/kbknapp/clap-rs/commit/4d9a82db8e875e9b64a9c2a5c6e22c25afc1279d), closes [#778](https://github.com/kbknapp/clap-rs/issues/778)) +* **crate_name!:** Uses the `Cargo.toml` name field to fill in the `App::new` method at compile time ([4d9a82db](https://github.com/kbknapp/clap-rs/commit/4d9a82db8e875e9b64a9c2a5c6e22c25afc1279d), closes [#778](https://github.com/kbknapp/clap-rs/issues/778)) +* **app_from_crate!:** Combines `crate_version!`, `crate_name!`, `crate_description!`, and `crate_authors!` into a single macro call to build a default `App` instance from the `Cargo.toml` fields ([4d9a82db](https://github.com/kbknapp/clap-rs/commit/4d9a82db8e875e9b64a9c2a5c6e22c25afc1279d), closes [#778](https://github.com/kbknapp/clap-rs/issues/778)) + + +#### Features + +* **no_cargo:** adds a `no_cargo` feature to disable Cargo-env-var-dependent macros for those *not* using `cargo` to build their crates (#786) ([6fdd2f9d](https://github.com/kbknapp/clap-rs/commit/6fdd2f9d693aaf1118fc61bd362273950703f43d)) + +#### Bug Fixes + +* **Options:** fixes a critical bug where options weren't forced to have a value ([5a5f2b1e](https://github.com/kbknapp/clap-rs/commit/5a5f2b1e9f598a0d0280ef3e98abbbba2bc41132), closes [#665](https://github.com/kbknapp/clap-rs/issues/665)) +* fixes a bug where calling the help of a subcommand wasn't ignoring required args of parent commands ([d3d34a2b](https://github.com/kbknapp/clap-rs/commit/d3d34a2b51ef31004055b0ab574f766d801c3adf), closes [#789](https://github.com/kbknapp/clap-rs/issues/789)) +* **Help Subcommand:** fixes a bug where the help subcommand couldn't be overriden ([d34ec3e0](https://github.com/kbknapp/clap-rs/commit/d34ec3e032d03e402d8e87af9b2942fe2819b2da), closes [#787](https://github.com/kbknapp/clap-rs/issues/787)) +* **Low Index Multiples:** fixes a bug which caused combinations of LowIndexMultiples and `Arg::allow_hyphen_values` to fail parsing ([26c670ca](https://github.com/kbknapp/clap-rs/commit/26c670ca16d2c80dc26d5c1ce83380ace6357318)) + +#### Improvements + +* **Default Values:** improves the error message when default values are involved ([1f33de54](https://github.com/kbknapp/clap-rs/commit/1f33de545036e7fd2f80faba251fca009bd519b8), closes [#774](https://github.com/kbknapp/clap-rs/issues/774)) +* **YAML:** adds conditional requirements and conditional default values to YAML ([9a4df327](https://github.com/kbknapp/clap-rs/commit/9a4df327893486adb5558ffefba790c634ccdc6e), closes [#764](https://github.com/kbknapp/clap-rs/issues/764)) +* Support `--("some-arg-name")` syntax for defining long arg names when using `clap_app!` macro ([f41ec962](https://github.com/kbknapp/clap-rs/commit/f41ec962c243a5ffff8b1be1ae2ad63970d3d1d4)) +* Support `("some app name")` syntax for defining app names when using `clap_app!` macro ([9895b671](https://github.com/kbknapp/clap-rs/commit/9895b671cff784f35cf56abcd8270f7c2ba09699), closes [#759](https://github.com/kbknapp/clap-rs/issues/759)) +* **Help Wrapping:** long app names (with spaces), authors, and descriptions are now wrapped appropriately ([ad4691b7](https://github.com/kbknapp/clap-rs/commit/ad4691b71a63e951ace346318238d8834e04ad8a), closes [#777](https://github.com/kbknapp/clap-rs/issues/777)) + + +#### Documentation + +* **Conditional Default Values:** fixes the failing doc tests of Arg::default_value_ifs ([4ef09101](https://github.com/kbknapp/clap-rs/commit/4ef091019c083b4db1a0c13f1c1e95ac363259f2)) +* **Conditional Requirements:** adds docs for Arg::requires_ifs ([7f296e29](https://github.com/kbknapp/clap-rs/commit/7f296e29db7d9036e76e5dbcc9c8b20dfe7b25bd)) +* **README.md:** fix some typos ([f22c21b4](https://github.com/kbknapp/clap-rs/commit/f22c21b422d5b287d1a1ac183a379ee02eebf54f)) +* **src/app/mod.rs:** fix some typos ([5c9b0d47](https://github.com/kbknapp/clap-rs/commit/5c9b0d47ca78dea285c5b9dec79063d24c3e451a)) + ### v2.19.3 (2016-12-28) diff --git a/src/vendor/clap/CONTRIBUTORS.md b/src/vendor/clap/CONTRIBUTORS.md index a7027f01e2..0a0d93f21e 100644 --- a/src/vendor/clap/CONTRIBUTORS.md +++ b/src/vendor/clap/CONTRIBUTORS.md @@ -1,48 +1,67 @@ -The following is a list of contributors in alphabetical order: +the following is a list of contributors: -[afiune](https://github.com/afiune) |[alexbool](https://github.com/alexbool) |[AluisioASG](https://github.com/AluisioASG) |[AluisioASG](https://github.com/AluisioASG) |[archer884](https://github.com/archer884) |[Arnavion](https://github.com/Arnavion) | +[kbknapp](https://github.com/kbknapp) |[homu](https://github.com/homu) |[Vinatorul](https://github.com/Vinatorul) |[tormol](https://github.com/tormol) |[sru](https://github.com/sru) |[nabijaczleweli](https://github.com/nabijaczleweli) | :---: |:---: |:---: |:---: |:---: |:---: | -[afiune](https://github.com/afiune) |[alexbool](https://github.com/alexbool) |[AluisioASG](https://github.com/AluisioASG) |[AluisioASG](https://github.com/AluisioASG) |[archer884](https://github.com/archer884) |[Arnavion](https://github.com/Arnavion) | +[kbknapp](https://github.com/kbknapp) |[homu](https://github.com/homu) |[Vinatorul](https://github.com/Vinatorul) |[tormol](https://github.com/tormol) |[sru](https://github.com/sru) |[nabijaczleweli](https://github.com/nabijaczleweli) | -[Bilalh](https://github.com/Bilalh) |[birkenfeld](https://github.com/birkenfeld) |[bradurani](https://github.com/bradurani) |[brennie](https://github.com/brennie) |[brianp](https://github.com/brianp) |[Byron](https://github.com/Byron) | +[Byron](https://github.com/Byron) |[hgrecco](https://github.com/hgrecco) |[james-darkfox](https://github.com/james-darkfox) |[rtaycher](https://github.com/rtaycher) |[glowing-chemist](https://github.com/glowing-chemist) |[Arnavion](https://github.com/Arnavion) | :---: |:---: |:---: |:---: |:---: |:---: | -[Bilalh](https://github.com/Bilalh) |[birkenfeld](https://github.com/birkenfeld) |[bradurani](https://github.com/bradurani) |[brennie](https://github.com/brennie) |[brianp](https://github.com/brianp) |[Byron](https://github.com/Byron) | +[Byron](https://github.com/Byron) |[hgrecco](https://github.com/hgrecco) |[james-darkfox](https://github.com/james-darkfox) |[rtaycher](https://github.com/rtaycher) |[glowing-chemist](https://github.com/glowing-chemist) |[Arnavion](https://github.com/Arnavion) | -[cstorey](https://github.com/cstorey) |[daboross](https://github.com/daboross) |[davidszotten](https://github.com/davidszotten) |[dguo](https://github.com/dguo) |[flying-sheep](https://github.com/flying-sheep) |[Geogi](https://github.com/Geogi) | +[mgeisler](https://github.com/mgeisler) |[afiune](https://github.com/afiune) |[crazymerlyn](https://github.com/crazymerlyn) |[SuperFluffy](https://github.com/SuperFluffy) |[untitaker](https://github.com/untitaker) |[japaric](https://github.com/japaric) | :---: |:---: |:---: |:---: |:---: |:---: | -[cstorey](https://github.com/cstorey) |[daboross](https://github.com/daboross) |[davidszotten](https://github.com/davidszotten) |[dguo](https://github.com/dguo) |[flying-sheep](https://github.com/flying-sheep) |[Geogi](https://github.com/Geogi) | +[mgeisler](https://github.com/mgeisler) |[afiune](https://github.com/afiune) |[crazymerlyn](https://github.com/crazymerlyn) |[SuperFluffy](https://github.com/SuperFluffy) |[untitaker](https://github.com/untitaker) |[japaric](https://github.com/japaric) | -[gohyda](https://github.com/gohyda) |[GrappigPanda](https://github.com/GrappigPanda) |[grossws](https://github.com/grossws) |[hexjelly](https://github.com/hexjelly) |[hgrecco](https://github.com/hgrecco) |[homu](https://github.com/homu) | +[matthiasbeyer](https://github.com/matthiasbeyer) |[SShrike](https://github.com/SShrike) |[gohyda](https://github.com/gohyda) |[jimmycuadra](https://github.com/jimmycuadra) |[Nemo157](https://github.com/Nemo157) |[tshepang](https://github.com/tshepang) | :---: |:---: |:---: |:---: |:---: |:---: | -[gohyda](https://github.com/gohyda) |[GrappigPanda](https://github.com/GrappigPanda) |[grossws](https://github.com/grossws) |[hexjelly](https://github.com/hexjelly) |[hgrecco](https://github.com/hgrecco) |[homu](https://github.com/homu) | +[matthiasbeyer](https://github.com/matthiasbeyer) |[SShrike](https://github.com/SShrike) |[gohyda](https://github.com/gohyda) |[jimmycuadra](https://github.com/jimmycuadra) |[Nemo157](https://github.com/Nemo157) |[tshepang](https://github.com/tshepang) | -[hoodie](https://github.com/hoodie) |[huonw](https://github.com/huonw) |[idmit](https://github.com/idmit) |[iliekturtles](https://github.com/iliekturtles) |[james-darkfox](https://github.com/james-darkfox) |[japaric](https://github.com/japaric) | +[porglezomp](https://github.com/porglezomp) |[wdv4758h](https://github.com/wdv4758h) |[frewsxcv](https://github.com/frewsxcv) |[hoodie](https://github.com/hoodie) |[huonw](https://github.com/huonw) |[GrappigPanda](https://github.com/GrappigPanda) | :---: |:---: |:---: |:---: |:---: |:---: | -[hoodie](https://github.com/hoodie) |[huonw](https://github.com/huonw) |[idmit](https://github.com/idmit) |[iliekturtles](https://github.com/iliekturtles) |[james-darkfox](https://github.com/james-darkfox) |[japaric](https://github.com/japaric) | +[porglezomp](https://github.com/porglezomp) |[wdv4758h](https://github.com/wdv4758h) |[frewsxcv](https://github.com/frewsxcv) |[hoodie](https://github.com/hoodie) |[huonw](https://github.com/huonw) |[GrappigPanda](https://github.com/GrappigPanda) | -[jespino](https://github.com/jespino) |[jimmycuadra](https://github.com/jimmycuadra) |[joshtriplett](https://github.com/joshtriplett) |[joshtriplett](https://github.com/joshtriplett) |[kbknapp](https://github.com/kbknapp) |[Keats](https://github.com/Keats) | +[ignatenkobrain](https://github.com/ignatenkobrain) |[cstorey](https://github.com/cstorey) |[musoke](https://github.com/musoke) |[nelsonjchen](https://github.com/nelsonjchen) |[pkgw](https://github.com/pkgw) |[Deedasmi](https://github.com/Deedasmi) | :---: |:---: |:---: |:---: |:---: |:---: | -[jespino](https://github.com/jespino) |[jimmycuadra](https://github.com/jimmycuadra) |[joshtriplett](https://github.com/joshtriplett) |[joshtriplett](https://github.com/joshtriplett) |[kbknapp](https://github.com/kbknapp) |[Keats](https://github.com/Keats) | +[ignatenkobrain](https://github.com/ignatenkobrain) |[cstorey](https://github.com/cstorey) |[musoke](https://github.com/musoke) |[nelsonjchen](https://github.com/nelsonjchen) |[pkgw](https://github.com/pkgw) |[Deedasmi](https://github.com/Deedasmi) | -[matthiasbeyer](https://github.com/matthiasbeyer) |[messense](https://github.com/messense) |[mvaude](https://github.com/mvaude) |[N-006](https://github.com/N-006) |[nabijaczleweli](https://github.com/nabijaczleweli) |[nelsonjchen](https://github.com/nelsonjchen) | +[N-006](https://github.com/N-006) |[Keats](https://github.com/Keats) |[starkat99](https://github.com/starkat99) |[alex-gulyas](https://github.com/alex-gulyas) |[cite-reader](https://github.com/cite-reader) |[alexbool](https://github.com/alexbool) | :---: |:---: |:---: |:---: |:---: |:---: | -[matthiasbeyer](https://github.com/matthiasbeyer) |[messense](https://github.com/messense) |[mvaude](https://github.com/mvaude) |[N-006](https://github.com/N-006) |[nabijaczleweli](https://github.com/nabijaczleweli) |[nelsonjchen](https://github.com/nelsonjchen) | +[N-006](https://github.com/N-006) |[Keats](https://github.com/Keats) |[starkat99](https://github.com/starkat99) |[alex-gulyas](https://github.com/alex-gulyas) |[cite-reader](https://github.com/cite-reader) |[alexbool](https://github.com/alexbool) | -[Nemo157](https://github.com/Nemo157) |[nicompte](https://github.com/nicompte) |[nvzqz](https://github.com/nvzqz) |[ogham](https://github.com/ogham) |[panicbit](https://github.com/panicbit) |[rnelson](https://github.com/rnelson) | +[AluisioASG](https://github.com/AluisioASG) |[BurntSushi](https://github.com/BurntSushi) |[nox](https://github.com/nox) |[pixelistik](https://github.com/pixelistik) |[brennie](https://github.com/brennie) |[ogham](https://github.com/ogham) | :---: |:---: |:---: |:---: |:---: |:---: | -[Nemo157](https://github.com/Nemo157) |[nicompte](https://github.com/nicompte) |[nvzqz](https://github.com/nvzqz) |[ogham](https://github.com/ogham) |[panicbit](https://github.com/panicbit) |[rnelson](https://github.com/rnelson) | +[AluisioASG](https://github.com/AluisioASG) |[BurntSushi](https://github.com/BurntSushi) |[nox](https://github.com/nox) |[pixelistik](https://github.com/pixelistik) |[brennie](https://github.com/brennie) |[ogham](https://github.com/ogham) | -[rtaycher](https://github.com/rtaycher) |[SirVer](https://github.com/SirVer) |[sru](https://github.com/sru) |[SShrike](https://github.com/SShrike) |[starkat99](https://github.com/starkat99) |[swatteau](https://github.com/swatteau) | +[Bilalh](https://github.com/Bilalh) |[dotdash](https://github.com/dotdash) |[bradurani](https://github.com/bradurani) |[Seeker14491](https://github.com/Seeker14491) |[brianp](https://github.com/brianp) |[casey](https://github.com/casey) | :---: |:---: |:---: |:---: |:---: |:---: | -[rtaycher](https://github.com/rtaycher) |[SirVer](https://github.com/SirVer) |[sru](https://github.com/sru) |[SShrike](https://github.com/SShrike) |[starkat99](https://github.com/starkat99) |[swatteau](https://github.com/swatteau) | +[Bilalh](https://github.com/Bilalh) |[dotdash](https://github.com/dotdash) |[bradurani](https://github.com/bradurani) |[Seeker14491](https://github.com/Seeker14491) |[brianp](https://github.com/brianp) |[casey](https://github.com/casey) | -[tanakh](https://github.com/tanakh) |[th4t](https://github.com/th4t) |[tormol](https://github.com/tormol) |[tshepang](https://github.com/tshepang) |[untitaker](https://github.com/untitaker) |[Vinatorul](https://github.com/Vinatorul) | +[volks73](https://github.com/volks73) |[daboross](https://github.com/daboross) |[mernen](https://github.com/mernen) |[dguo](https://github.com/dguo) |[davidszotten](https://github.com/davidszotten) |[eddyb](https://github.com/eddyb) | :---: |:---: |:---: |:---: |:---: |:---: | -[tanakh](https://github.com/tanakh) |[th4t](https://github.com/th4t) |[tormol](https://github.com/tormol) |[tshepang](https://github.com/tshepang) |[untitaker](https://github.com/untitaker) |[Vinatorul](https://github.com/Vinatorul) | +[volks73](https://github.com/volks73) |[daboross](https://github.com/daboross) |[mernen](https://github.com/mernen) |[dguo](https://github.com/dguo) |[davidszotten](https://github.com/davidszotten) |[eddyb](https://github.com/eddyb) | + +[birkenfeld](https://github.com/birkenfeld) |[tanakh](https://github.com/tanakh) |[SirVer](https://github.com/SirVer) |[idmit](https://github.com/idmit) |[archer884](https://github.com/archer884) |[shepmaster](https://github.com/shepmaster) | +:---: |:---: |:---: |:---: |:---: |:---: | +[birkenfeld](https://github.com/birkenfeld) |[tanakh](https://github.com/tanakh) |[SirVer](https://github.com/SirVer) |[idmit](https://github.com/idmit) |[archer884](https://github.com/archer884) |[shepmaster](https://github.com/shepmaster) | + +[jespino](https://github.com/jespino) |[jtdowney](https://github.com/jtdowney) |[andete](https://github.com/andete) |[joshtriplett](https://github.com/joshtriplett) |[malbarbo](https://github.com/malbarbo) |[iliekturtles](https://github.com/iliekturtles) | +:---: |:---: |:---: |:---: |:---: |:---: | +[jespino](https://github.com/jespino) |[jtdowney](https://github.com/jtdowney) |[andete](https://github.com/andete) |[joshtriplett](https://github.com/joshtriplett) |[malbarbo](https://github.com/malbarbo) |[iliekturtles](https://github.com/iliekturtles) | + +[nicompte](https://github.com/nicompte) |[NickeZ](https://github.com/NickeZ) |[nvzqz](https://github.com/nvzqz) |[Geogi](https://github.com/Geogi) |[flying-sheep](https://github.com/flying-sheep) |[peppsac](https://github.com/peppsac) | +:---: |:---: |:---: |:---: |:---: |:---: | +[nicompte](https://github.com/nicompte) |[NickeZ](https://github.com/NickeZ) |[nvzqz](https://github.com/nvzqz) |[Geogi](https://github.com/Geogi) |[flying-sheep](https://github.com/flying-sheep) |[peppsac](https://github.com/peppsac) | + +[hexjelly](https://github.com/hexjelly) |[rnelson](https://github.com/rnelson) |[swatteau](https://github.com/swatteau) |[tspiteri](https://github.com/tspiteri) |[vks](https://github.com/vks) |[th4t](https://github.com/th4t) | +:---: |:---: |:---: |:---: |:---: |:---: | +[hexjelly](https://github.com/hexjelly) |[rnelson](https://github.com/rnelson) |[swatteau](https://github.com/swatteau) |[tspiteri](https://github.com/tspiteri) |[vks](https://github.com/vks) |[th4t](https://github.com/th4t) | + +[mineo](https://github.com/mineo) |[grossws](https://github.com/grossws) |[messense](https://github.com/messense) |[mvaude](https://github.com/mvaude) |[panicbit](https://github.com/panicbit) |[mitsuhiko](https://github.com/mitsuhiko) | +:---: |:---: |:---: |:---: |:---: |:---: | +[mineo](https://github.com/mineo) |[grossws](https://github.com/grossws) |[messense](https://github.com/messense) |[mvaude](https://github.com/mvaude) |[panicbit](https://github.com/panicbit) |[mitsuhiko](https://github.com/mitsuhiko) | + -[vks](https://github.com/vks) |[volks73](https://github.com/volks73) |[wdv4758h](https://github.com/wdv4758h) | -:---: |:---: |:---: | -[vks](https://github.com/vks) |[volks73](https://github.com/volks73) |[wdv4758h](https://github.com/wdv4758h) | +This list was generated by [mgechev/github-contributors-list](https://github.com/mgechev/github-contributors-list) diff --git a/src/vendor/clap/Cargo.toml b/src/vendor/clap/Cargo.toml index 56bea2b394..07a55b2b0f 100644 --- a/src/vendor/clap/Cargo.toml +++ b/src/vendor/clap/Cargo.toml @@ -1,80 +1,117 @@ -[package] +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g. crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) +[package] name = "clap" -version = "2.19.3" +version = "2.25.0" authors = ["Kevin K. "] exclude = ["examples/*", "clap-test/*", "tests/*", "benches/*", "*.png", "clap-perf/*", "*.dot"] -repository = "https://github.com/kbknapp/clap-rs.git" -documentation = "https://docs.rs/clap/" +description = "A simple to use, efficient, and full featured Command Line Argument Parser\n" homepage = "https://clap.rs/" +documentation = "https://docs.rs/clap/" readme = "README.md" -license = "MIT" keywords = ["argument", "command", "arg", "parser", "parse"] -description = """ -A simple to use, efficient, and full featured Command Line Argument Parser -""" - -[dependencies] -bitflags = "~0.7" -vec_map = "~0.6" -unicode-width = "~0.1.3" -unicode-segmentation = "~0.1.2" -strsim = { version = "~0.5.1", optional = true } -ansi_term = { version = "~0.9.0", optional = true } -term_size = { version = "~0.2.0", optional = true } -libc = { version = "~0.2.9", optional = true } -yaml-rust = { version = "~0.3.2", optional = true } -clippy = { version = "~0.0.100", optional = true } - -[dev-dependencies] -regex = "~0.1.80" +categories = ["command-line-interface"] +license = "MIT" +repository = "https://github.com/kbknapp/clap-rs.git" +[profile.test] +opt-level = 1 +lto = false +codegen-units = 4 +debug = true +debug-assertions = true +rpath = false -[features] -default = ["suggestions", "color", "wrap_help"] -suggestions = ["strsim"] -color = ["ansi_term", "libc"] -wrap_help = ["libc", "term_size"] -yaml = ["yaml-rust"] -unstable = [] # for building with unstable clap features (doesn't require nightly Rust) (currently none) -nightly = [] # for building with unstable Rust features (currently none) -lints = ["clippy"] # Requires nightly Rust -debug = [] # Enables debug messages +[profile.doc] +opt-level = 0 +lto = false +codegen-units = 4 +debug = true +debug-assertions = true +rpath = false -[profile.release] +[profile.bench] opt-level = 3 -debug = false -rpath = false lto = true +debug = false debug-assertions = false -# codegen-units ignored with lto=true +rpath = false [profile.dev] opt-level = 0 -debug = true -rpath = false lto = false -debug-assertions = true codegen-units = 4 - -[profile.test] -opt-level = 1 debug = true -rpath = false -lto = false debug-assertions = true -codegen-units = 2 +rpath = false -[profile.bench] +[profile.release] opt-level = 3 -debug = false -rpath = false lto = true +debug = false debug-assertions = false - -[profile.doc] -opt-level = 0 -debug = true rpath = false -lto = false -debug-assertions = true -codegen-units = 4 +[dependencies.ansi_term] +version = "0.9.0" +optional = true + +[dependencies.term_size] +version = "0.3.0" +optional = true + +[dependencies.textwrap] +version = "0.6.0" + +[dependencies.yaml-rust] +version = "0.3.5" +optional = true + +[dependencies.unicode-width] +version = "0.1.4" + +[dependencies.atty] +version = "0.2.2" +optional = true + +[dependencies.vec_map] +version = "0.8" + +[dependencies.clippy] +version = "~0.0.131" +optional = true + +[dependencies.unicode-segmentation] +version = "~1.1.0" + +[dependencies.bitflags] +version = "0.9" + +[dependencies.strsim] +version = "0.6.0" +optional = true +[dev-dependencies.regex] +version = "0.2" + +[dev-dependencies.lazy_static] +version = "0.2" + +[features] +unstable = [] +default = ["suggestions", "color", "wrap_help"] +color = ["ansi_term", "atty"] +yaml = ["yaml-rust"] +no_cargo = [] +wrap_help = ["term_size"] +suggestions = ["strsim"] +nightly = [] +debug = [] +lints = ["clippy"] diff --git a/src/vendor/clap/Cargo.toml.orig b/src/vendor/clap/Cargo.toml.orig new file mode 100644 index 0000000000..60cc163312 --- /dev/null +++ b/src/vendor/clap/Cargo.toml.orig @@ -0,0 +1,84 @@ +[package] + +name = "clap" +version = "2.25.0" +authors = ["Kevin K. "] +exclude = ["examples/*", "clap-test/*", "tests/*", "benches/*", "*.png", "clap-perf/*", "*.dot"] +repository = "https://github.com/kbknapp/clap-rs.git" +documentation = "https://docs.rs/clap/" +homepage = "https://clap.rs/" +readme = "README.md" +license = "MIT" +keywords = ["argument", "command", "arg", "parser", "parse"] +categories = ["command-line-interface"] +description = """ +A simple to use, efficient, and full featured Command Line Argument Parser +""" + +[dependencies] +bitflags = "0.9" +vec_map = "0.8" +unicode-width = "0.1.4" +unicode-segmentation = "~1.1.0" # 1.2.0 requires Rust 1.13.0 +textwrap = "0.6.0" +strsim = { version = "0.6.0", optional = true } +ansi_term = { version = "0.9.0", optional = true } +term_size = { version = "0.3.0", optional = true } +yaml-rust = { version = "0.3.5", optional = true } +clippy = { version = "~0.0.131", optional = true } +atty = { version = "0.2.2", optional = true } + +[dev-dependencies] +regex = "0.2" +lazy_static = "0.2" + +[features] +default = ["suggestions", "color", "wrap_help"] +suggestions = ["strsim"] +color = ["ansi_term", "atty"] +wrap_help = ["term_size"] +yaml = ["yaml-rust"] +unstable = [] # for building with unstable clap features (doesn't require nightly Rust) (currently none) +nightly = [] # for building with unstable Rust features (currently none) +lints = ["clippy"] # Requires nightly Rust +debug = [] # Enables debug messages +no_cargo = [] # Enable if you're not using Cargo, disables Cargo-env-var-dependent macros + +[profile.release] +opt-level = 3 +debug = false +rpath = false +lto = true +debug-assertions = false +# codegen-units ignored with lto=true + +[profile.dev] +opt-level = 0 +debug = true +rpath = false +lto = false +debug-assertions = true +codegen-units = 4 + +[profile.test] +opt-level = 1 +debug = true +rpath = false +lto = false +debug-assertions = true +codegen-units = 4 + +[profile.bench] +opt-level = 3 +debug = false +rpath = false +lto = true +debug-assertions = false + +[profile.doc] +opt-level = 0 +debug = true +rpath = false +lto = false +debug-assertions = true +codegen-units = 4 diff --git a/src/vendor/clap/README.md b/src/vendor/clap/README.md index a80c75a04a..a433baf92e 100644 --- a/src/vendor/clap/README.md +++ b/src/vendor/clap/README.md @@ -45,93 +45,67 @@ Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc) ## What's New -Here's the highlights for v2.19.3 - -* Fixes a bug where calling the help of a subcommand wasn't ignoring required args of parent commands - -Here's the highlights from v2.0.0 to v2.19.2 - -* Fixes a bug by escaping square brackets in ZSH completions which were causing conflicts and errors. -* **Bash Completion:** allows bash completion to fall back to traidtional bash completion upon no matching completing function -* **Arg Setting**: Allows specifying an `AllowLeadingHyphen` style setting for values only for specific args, vice command wide -* **Validators:** improves the error messages for validators -* **Required Unless:** fixes a bug where having required_unless set doesn't work when conflicts are also set -* **ZSH Completions:** fixes an issue where zsh completions caused panics if there were no subcommands -* **Completions:** Adds completion support for Microsoft PowerShell! (Thanks to @Arnavion) -* Allows specifying the second to last positional argument as `multiple(true)` (i.e. things such as `mv ... `) -* Adds an `App::get_name` and `App::get_bin_name` -* Conflicting argument errors are now symetrical, meaning more consistent and better usage suggestions -* **Completions:** adds automatic ZSH completion script generation support! :tada: :tada: -* **AppSettings:** adds new setting `AppSettings::AllowNegativeNumbers` which functions like `AllowLeadingHyphen` except only allows undefined negative numbers to pass parsing. -* Stabilize `clap_app!` macro (i.e. no longer need to use `unstable` feature) -* Deprecate `App::with_defaults` -* One can now alias arguments either visibly (which appears in the help text) or invisibly just like subcommands! -* The `from_usage` parser now correctly handles non-ascii names / options and help! -* **Value Delimiters:** fixes the confusion around implicitly setting value delimiters. (The default is to *not* use a delimiter unless explicitly set) -* Changes the default value delimiter rules (i.e. the default is `use_delimiter(false)` *unless* a setting/method that implies multiple values was used) **[Bugfix that *may* "break" code]** - * If code breaks, simply add `Arg::use_delimiter(true)` to the affected args -* Adds ability to hide the possible values from the help text on a per argument basis, instead of command wide -* Allows for limiting detected terminal width (i.e. wrap at `x` length, unless the terminal width is *smaller*) -* `clap` now ignores hard newlines in help messages and properly re-aligns text, but still wraps if the term width is too small -* Adds support for the setting `Arg::require_delimiter` from YAML -* `clap` no longer requires one to use `{n}` inside help text to insert a newline that is properly aligned. One can now use the normal `\n`. -* `clap` now ignores hard newlines in help messages and properly re-aligns text, but still wraps if the term width is too small -* Errors can now have custom description -* Uses `term_size` instead of home-grown solution on Windows -* Adds the ability to wrap help text intelligently on Windows! -* Moves docs to [docs.rs!](https://docs.rs/clap/)! -* Automatically moves help text to the next line and wraps when term width is determined to be too small, or help text is too long -* Vastly improves *development* error messages when using YAML -* Adds a shorthand way to ignore help text wrapping and use source formatting (i.e. `App::set_term_width(0)`) -* **Help Subcommand:** fixes misleading usage string when using multi-level subcommmands such as `myprog help subcmd1 subcmd2` -* **YAML:** allows using lists or single values with certain arg declarations for increased ergonomics -* **Fish Shell Completions:** one can generate a basic fish completions script at compile time! -* Adds the ability to generate completions to an `io::Write` object -* Adds an `App::unset_setting` and `App::unset_settings` -* **Completions:** one can now [generate a bash completions](https://docs.rs/clap/2.9.0/clap/struct.App.html#method.gen_completions) script at compile time! These completions work with options using [possible values](https://docs.rs/clap/2.9.0/clap/struct.Arg.html#method.possible_values), [subcommand aliases](https://docs.rs/clap/2.9.0/clap/struct.App.html#method.aliases), and even multiple levels of subcommands -* **Arg:** adds new optional setting [`Arg::require_delimiter`](https://docs.rs/clap/2.8.0/clap/struct.Arg.html#method.require_delimiter) which requires val delimiter to parse multiple values -* The terminal sizing portion has been factored out into a separate crate, [term_size](https://crates.io/crates/term_size) -* Options using multiple values and delimiters no longer parse additional values after a trailing space (i.e. `prog -o 1,2 file.txt` parses as `1,2` for `-o` and `file.txt` for a positional arg) -* Using options using multiple values and with an `=` no longer parse args after the trailing space as values (i.e. `prog -o=1 file.txt` parses as `1` for `-o` and `file.txt` for a positional arg) -* **Usage Strings:** `[FLAGS]` and `[ARGS]` are no longer blindly added to usage strings, instead only when applicable -* `arg_enum!`: allows using more than one meta item, or things like `#[repr(C)]` with `arg_enum!`s -* `App::print_help`: now prints the same as would have been printed by `--help` or the like -* Prevents invoking ` help help` and displaying incorrect help message -* Subcommand help messages requested via ` help ` now correctly match ` --help` -* One can now specify groups which require AT LEAST one of the args -* Allows adding multiple ArgGroups per Arg -* **Global Settings:** One can now set an `AppSetting` which is propogated down through child subcommands -* **Terminal Wrapping:** Allows wrapping at specified term width (Even on Windows!) (can now set an absolute width to "smart" wrap at) -* **SubCommands/Aliases:** adds support for visible aliases for subcommands (i.e. aliases that are dipslayed in the help message) -* **Subcommands/Aliases:** when viewing the help of an alias, it now display help of the aliased subcommand -* Adds new setting to stop delimiting values with `--` or `AppSettings::TrailingVarArg` -* Subcommands now support aliases - think of them as hidden subcommands that dispatch to said subcommand automatically -* Fixed times when `ArgGroup`s are duplicated in usage strings -* **Before Help:** adds support for displaying info before help message -* **Required Unless:** adds support for allowing args that are required unless certain other args are present -* **New Help Template Engine!**: Now you have full control over the layout of your help message. Major thanks to @hgrecco -* **Pull crate Authors from Cargo.toml**: One can now use the `crate_authors!` macro to automatically pull the crate authors from their Cargo.toml file -* **Colored Help Messages**: Help messages can now be optionally colored (See the `AppSettings::ColoredHelp` setting). Screenshot below. -* **Help text auto wraps and aligns at for subcommands too!** - Long help strings of subcommands will now properly wrap and align to term width on Linux and OS X. This can be turned off as well. -* **Help text auto wraps and aligns at term width!** - Long help strings will now properly wrap and align to term width on Linux and OS X (and presumably Unix too). This can be turned off as well. -* **Can customize the order of opts, flags, and subcommands in help messages** - Instead of using the default alphabetical order, you can now re-arrange the order of your args and subcommands in help message. This helps to emphasize more popular or important options. -* **Can auto-derive the order from declaration order** - Have a bunch of args or subcommmands to re-order? You can now just derive the order from the declaration order! -* **Help subcommand now accepts other subcommands as arguments!** - Similar to other CLI precedents, the `help` subcommand can now accept other subcommands as arguments to display their help message. i.e. `$ myprog help mysubcmd` (*Note* these can even be nested heavily such as `$ myprog help subcmd1 subcmd2 subcmd3` etc.) -* **Default Values**: Args can now specify default values -* **Next Line Help**: Args can have help strings on the line following the argument (useful for long arguments, or those with many values). This can be set command-wide or for individual args - -Here's a gif of them in action! - -![zsh-comppletions](http://i.imgur.com/rwlMbAv.gif) - -An example of the help text wrapping at term width: - -![screenshot](http://i.imgur.com/PAJzJJG.png) - -An example of the optional colored help: - -![screenshot](http://i.imgur.com/7fs2h5j.png) - +Here's the highlights for v2.25.0 + +* use textwrap crate for wrapping help texts +* suggests to use flag after subcommand when applicable +* Bumps bitflags crate to v0.9 + +Here's the highlights for v2.21.0 to v2.24.2 + +* fixes a bug where args that allow values to start with a hyphen couldnt contain a double hyphen -- as a value +* fixes a bug where positional argument help text is misaligned +* **App::template docs:** adds details about the necessity to use AppSettings::UnifiedHelpMessage when using {unified} tags in the help template +* **Arg::allow_hyphen_values docs:** updates the docs to include warnings for allow_hyphen_values and multiple(true) used together +* **clap_app! docs:** adds using the @group specifier to the macro docs +* adds a debug assertion to ensure all args added to groups actually exist +* fixes a bug where args with last(true) and required(true) set were not being printed in the usage string +* fixes a bug that was printing the arg name, instead of value name when Arg::last(true) was used +* fixes a bug where flags were parsed as flags AND positional values when specific combinations of settings were used +* **README.md:** fix some typos +* **Arg:** add `default_value_os` +* **arg_matches.rs:** Added a Default implementation for Values and OsValues iterators. +* **PowerShell Completions:** + * fixes a bug where powershells completions cant be used if no subcommands are defined + * massively dedups subcommand names in the generate script to make smaller scripts that are still functionally equiv +* allows specifying a short help vs a long help (i.e. varying levels of detail depending on if -h or --help was used) +* **clap_app!:** adds support for arg names with hyphens similar to longs with hyphens +* fixes a bug that wasn't allowing help and version to be properly overridden + * This may break code that was relying on this bug! If you add a flag with a long of `help` manually *and* rely on the help message to be printed automatically your code could break. Please see the commit link in the full CHANGELOG.md +* `App::long_about` +* `App::long_version` +* `App::print_long_help` +* `App::write_long_help` +* `App::print_long_version` +* `App::write_long_version` +* `Arg::long_help` +* **clap_app!:** documents the `--("some-arg")` method for using args with hyphens inside them +* fixes the usage string regression when using help templates +* fixes a big regression with custom usage strings +* adds the ability to change the name of the App instance after creation +* adds ability to hide the default value of an argument from the help string +* fixes support for loading author info from yaml +* adds fish subcommand help support +* options that use `require_equals(true)` now display the equals sign in help messages, usage strings, and errors +* setting the max term width now correctly propagates down through child subcommands +* fixes the precedence of this error to prioritize over other error messages +* fixes some regression bugs resulting from old asserts in debug mode. +* adds the ability to mark a positional argument as 'last' which means it should be used with `--` syntax and can be accessed early to effectivly skip other positional args +* Some performance improvements by reducing the ammount of duplicate work, cloning, and allocations in all cases. +* Some massive performance gains when using many args (i.e. things like shell glob expansions) +* adds a setting to allow one to infer shortened subcommands or aliases (i.e. for subcommmand "test", "t", "te", or "tes" would be allowed assuming no other ambiguities) +* when `AppSettings::SubcommandsNegateReqs` and `ArgsNegateSubcommands` are used, a new more accurate double line usage string is shown +* provides `default_value_os` and `default_value_if[s]_os` +* provides `App::help_message` and `App::version_message` which allows one to override the auto-generated help/version flag associated help +* adds the ability to require the equals syntax with options `--opt=val` +* doesn't print the argument sections in the help message if all args in that section are hidden +* doesn't include the various `[ARGS]` `[FLAGS]` or `[OPTIONS]` if the only ones available are hidden +* now correctly shows subcommand as required in the usage string when AppSettings::SubcommandRequiredElseHelp is used +* fixes some "memory leaks" when an error is detected and clap exits +* fixes a trait that's marked private accidentlly, but should be crate internal public +* fixes a bug that tried to propogate global args multiple times when generating multiple completion scripts +* Fixes a critical bug in the `clap_app!` macro of a missing fragment specifier when using `!property` style tags. +* Fix examples link in CONTRIBUTING.md For full details, see [CHANGELOG.md](https://github.com/kbknapp/clap-rs/blob/master/CHANGELOG.md) @@ -501,8 +475,8 @@ Then run `cargo build` or `cargo update && cargo build` for your project. #### Features enabled by default * **"suggestions"**: Turns on the `Did you mean '--myoption'?` feature for when users make typos. (builds dependency `strsim`) -* **"color"**: Turns on colored error messages. This feature only works on non-Windows OSs. (builds dependency `ansi-term` and `libc`) -* **"wrap_help"**: Wraps the help at the actual terminal width when available, instead of 120 chracters. (builds dependency `term_size`, and `libc`) +* **"color"**: Turns on colored error messages. This feature only works on non-Windows OSs. (builds dependency `ansi-term`) +* **"wrap_help"**: Wraps the help at the actual terminal width when available, instead of 120 characters. (builds dependency `term_size`) To disable these, add this to your `Cargo.toml`: @@ -561,14 +535,14 @@ Please read [CONTRIBUTING.md](.github/CONTRIBUTING.md) before you start contribu ### Testing Code -To test with all features both enabled and disabled, you can run theese commands: +To test with all features both enabled and disabled, you can run these commands: ```sh $ cargo test --no-default-features $ cargo test --features "yaml unstable" ``` -Alternatively, if you have [`just`](https://github.com/casey/just) installed you can run the prebuilt recipies. *Not* using `just` is prfeclty fine as well, it simply bundles commands automatically. +Alternatively, if you have [`just`](https://github.com/casey/just) installed you can run the prebuilt recipes. *Not* using `just` is perfectly fine as well, it simply bundles commands automatically. For example, to test the code, as above simply run: @@ -638,7 +612,7 @@ Because `clap` takes SemVer and compatibility seriously, this is the official po `clap` will pin the minimum required version of Rust to the CI builds. Bumping the minimum version of Rust is considered a minor breaking change, meaning *at a minimum* the minor version of `clap` will be bumped. -In order to keep from being suprised of breaking changes, it is **highly** recommended to use the `~major.minor.patch` style in your `Cargo.toml` only if you wish to target a version of Rust that is *older* than current stable minus two releases: +In order to keep from being surprised of breaking changes, it is **highly** recommended to use the `~major.minor.patch` style in your `Cargo.toml` only if you wish to target a version of Rust that is *older* than current stable minus two releases: ```toml [dependencies] @@ -647,16 +621,38 @@ clap = "~2.19.0" This will cause *only* the patch version to be updated upon a `cargo update` call, and therefore cannot break due to new features, or bumped minimum versions of Rust. +#### Warning about '~' Dependencies + +Using `~` can cause issues in certain circumstances. + +From @alexcrichton: + +Right now Cargo's version resolution is pretty naive, it's just a brute-force search of the solution space, returning the first resolvable graph. This also means that it currently won't terminate until it proves there is not possible resolvable graph. This leads to situations where workspaces with multiple binaries, for example, have two different dependencies such as: + +```toml + +# In one Cargo.toml +[dependencies] +clap = "~2.19.0" + +# In another Cargo.toml +[dependencies] +clap = "2.22" + +``` + +This is inherently an unresolvable crate graph in Cargo right now. Cargo requires there's only one major version of a crate, and being in the same workspace these two crates must share a version. This is impossible in this location, though, as these version constraints cannot be met. + #### Minimum Version of Rust -`clap` will officially support current stable Rust, minus two releases, but may work with prior releases as well. For example, current stable Rust at the time of this writing is 1.13.0, meaning `clap` is garunteed to compile with 1.11.0 and beyond. -At the 1.14.0 release, `clap` will be garunteed to compile with 1.12.0 and beyond, etc. +`clap` will officially support current stable Rust, minus two releases, but may work with prior releases as well. For example, current stable Rust at the time of this writing is 1.13.0, meaning `clap` is guaranteed to compile with 1.11.0 and beyond. +At the 1.14.0 release, `clap` will be guaranteed to compile with 1.12.0 and beyond, etc. Upon bumping the minimum version of Rust (assuming it's within the stable-2 range), it *must* be clearly annotated in the `CHANGELOG.md` #### Breaking Changes -`clap` takes a similar policy to Rust and will bump the major veresion number upon breaking changes with only the following exceptions: +`clap` takes a similar policy to Rust and will bump the major version number upon breaking changes with only the following exceptions: * The breaking change is to fix a security concern * The breaking change is to be fixing a bug (i.e. relying on a bug as a feature) diff --git a/src/vendor/clap/appveyor.yml b/src/vendor/clap/appveyor.yml deleted file mode 100644 index a9ee3e859d..0000000000 --- a/src/vendor/clap/appveyor.yml +++ /dev/null @@ -1,12 +0,0 @@ -install: - - ps: Start-FileDownload 'https://static.rust-lang.org/dist/rust-nightly-i686-pc-windows-gnu.exe' - - rust-nightly-i686-pc-windows-gnu.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" - - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin - - rustc -V - - cargo -V - -build: false - -test_script: - - cargo build --features yaml - - cargo test --features yaml diff --git a/src/vendor/clap/clap-test.rs b/src/vendor/clap/clap-test.rs index 41f2172ee3..2f91b9e818 100644 --- a/src/vendor/clap/clap-test.rs +++ b/src/vendor/clap/clap-test.rs @@ -1,12 +1,47 @@ #[allow(unused_imports, dead_code)] mod test { use std::str; - use std::io::Write; + use std::io::{Cursor, Write}; use regex::Regex; use clap::{App, Arg, SubCommand, ArgGroup}; + fn compare(l: S, r: S2) -> bool + where S: AsRef, + S2: AsRef + { + let re = Regex::new("\x1b[^m]*m").unwrap(); + // Strip out any mismatching \r character on windows that might sneak in on either side + let ls = l.as_ref().trim().replace("\r", ""); + let rs = r.as_ref().trim().replace("\r", ""); + let left = re.replace_all(&*ls, ""); + let right = re.replace_all(&*rs, ""); + let b = left == right; + if !b { + println!(""); + println!("--> left"); + println!("{}", left); + println!("--> right"); + println!("{}", right); + println!("--") + } + b + } + + pub fn compare_output(l: App, args: &str, right: &str, stderr: bool) -> bool { + let mut buf = Cursor::new(Vec::with_capacity(50)); + let res = l.get_matches_from_safe(args.split(' ').collect::>()); + let err = res.unwrap_err(); + err.write_to(&mut buf).unwrap(); + let content = buf.into_inner(); + let left = String::from_utf8(content).unwrap(); + assert_eq!(stderr, err.use_stderr()); + compare(left, right) + } + + // Legacy tests from the pyhton script days + pub fn complex_app() -> App<'static, 'static> { let args = "-o --option=[opt]... 'tests options' [positional] 'tests positionals'"; @@ -35,152 +70,7 @@ mod test { .version("0.1") .author("Kevin K. ") .arg_from_usage("-o --option [scoption]... 'tests options'") + .arg_from_usage("-s --subcmdarg [subcmdarg] 'tests other args'") .arg_from_usage("[scpositional] 'tests positionals'")) } - - pub fn check_err_output(a: App, args: &str, out: &str, use_stderr: bool) { - let res = a.get_matches_from_safe(args.split(' ').collect::>()); - let re = Regex::new("\x1b[^m]*m").unwrap(); - - let mut w = vec![]; - let err = res.unwrap_err(); - err.write_to(&mut w).unwrap(); - let err_s = str::from_utf8(&w).unwrap(); - assert_eq!(re.replace_all(err_s, ""), out); - assert_eq!(use_stderr, err.use_stderr()); - } - - pub fn check_subcommand_help(mut a: App, cmd: &str, out: &str) { - // We call a get_matches method to cause --help and --version to be built - let _ = a.get_matches_from_safe_borrow(vec![""]); - let sc = a.p.subcommands.iter().filter(|s| s.p.meta.name == cmd).next().unwrap(); - - // Now we check the output of print_help() - let mut help = vec![]; - sc.write_help(&mut help).expect("failed to print help"); - assert_eq!(str::from_utf8(&help).unwrap(), out); - } - - pub fn check_help(mut a: App, out: &str) { - // We call a get_matches method to cause --help and --version to be built - let _ = a.get_matches_from_safe_borrow(vec![""]); - - // Now we check the output of print_help() - let mut help = vec![]; - a.write_help(&mut help).expect("failed to print help"); - assert_eq!(str::from_utf8(&help).unwrap(), out); - } - - pub fn check_version(mut a: App, out: &str) { - // We call a get_matches method to cause --help and --version to be built - let _ = a.get_matches_from_safe_borrow(vec![""]); - - // Now we check the output of print_version() - let mut ver = vec![]; - a.write_version(&mut ver).expect("failed to print help"); - assert_eq!(str::from_utf8(&ver).unwrap(), out); - } - - pub fn check_complex_output(args: &str, out: &str) { - let mut w = vec![]; - let matches = complex_app().get_matches_from(args.split(' ').collect::>()); - if matches.is_present("flag") { - writeln!(w, "flag present {} times", matches.occurrences_of("flag")).unwrap(); - } else { - writeln!(w, "flag NOT present").unwrap(); - } - - if matches.is_present("option") { - if let Some(v) = matches.value_of("option") { - writeln!(w, "option present {} times with value: {}",matches.occurrences_of("option"), v).unwrap(); - } - if let Some(ov) = matches.values_of("option") { - for o in ov { - writeln!(w, "An option: {}", o).unwrap(); - } - } - } else { - writeln!(w, "option NOT present").unwrap(); - } - - if let Some(p) = matches.value_of("positional") { - writeln!(w, "positional present with value: {}", p).unwrap(); - } else { - writeln!(w, "positional NOT present").unwrap(); - } - - if matches.is_present("flag2") { - writeln!(w, "flag2 present").unwrap(); - writeln!(w, "option2 present with value of: {}", matches.value_of("long-option-2").unwrap()).unwrap(); - writeln!(w, "positional2 present with value of: {}", matches.value_of("positional2").unwrap()).unwrap(); - } else { - writeln!(w, "flag2 NOT present").unwrap(); - writeln!(w, "option2 maybe present with value of: {}", matches.value_of("long-option-2").unwrap_or("Nothing")).unwrap(); - writeln!(w, "positional2 maybe present with value of: {}", matches.value_of("positional2").unwrap_or("Nothing")).unwrap(); - } - - let _ = match matches.value_of("Option3").unwrap_or("") { - "fast" => writeln!(w, "option3 present quickly"), - "slow" => writeln!(w, "option3 present slowly"), - _ => writeln!(w, "option3 NOT present") - }; - - let _ = match matches.value_of("positional3").unwrap_or("") { - "vi" => writeln!(w, "positional3 present in vi mode"), - "emacs" => writeln!(w, "positional3 present in emacs mode"), - _ => writeln!(w, "positional3 NOT present") - }; - - if matches.is_present("option") { - if let Some(v) = matches.value_of("option") { - writeln!(w, "option present {} times with value: {}",matches.occurrences_of("option"), v).unwrap(); - } - if let Some(ov) = matches.values_of("option") { - for o in ov { - writeln!(w, "An option: {}", o).unwrap(); - } - } - } else { - writeln!(w, "option NOT present").unwrap(); - } - - if let Some(p) = matches.value_of("positional") { - writeln!(w, "positional present with value: {}", p).unwrap(); - } else { - writeln!(w, "positional NOT present").unwrap(); - } - if matches.is_present("subcmd") { - writeln!(w, "subcmd present").unwrap(); - if let Some(matches) = matches.subcommand_matches("subcmd") { - if matches.is_present("flag") { - writeln!(w, "flag present {} times", matches.occurrences_of("flag")).unwrap(); - } else { - writeln!(w, "flag NOT present").unwrap(); - } - - if matches.is_present("option") { - if let Some(v) = matches.value_of("option") { - writeln!(w, "scoption present with value: {}", v).unwrap(); - } - if let Some(ov) = matches.values_of("option") { - for o in ov { - writeln!(w, "An scoption: {}", o).unwrap(); - } - } - } else { - writeln!(w, "scoption NOT present").unwrap(); - } - - if let Some(p) = matches.value_of("scpositional") { - writeln!(w, "scpositional present with value: {}", p).unwrap(); - } - } - } else { - writeln!(w, "subcmd NOT present").unwrap(); - } - - let res = str::from_utf8(&w).unwrap(); - assert_eq!(res, out); - } - } diff --git a/src/vendor/clap/justfile b/src/vendor/clap/justfile index d7eb63da6c..e9385c6bf9 100644 --- a/src/vendor/clap/justfile +++ b/src/vendor/clap/justfile @@ -2,10 +2,13 @@ echo 'Removing old CONTRIBUTORS.md' mv CONTRIBUTORS.md CONTRIBUTORS.md.bak echo 'Downloading a list of new contributors' - echo "The following is a list of contributors in alphabetical order:" > CONTRIBUTORS.md + echo "the following is a list of contributors:" > CONTRIBUTORS.md echo "" >> CONTRIBUTORS.md echo "" >> CONTRIBUTORS.md - githubcontrib --owner kbknapp --repo clap-rs --sha master --cols 6 --format md --showlogin true --sortBy login >> CONTRIBUTORS.md + githubcontrib --owner kbknapp --repo clap-rs --sha master --cols 6 --format md --showlogin true --sortBy contributions --sortOrder desc >> CONTRIBUTORS.md + echo "" >> CONTRIBUTORS.md + echo "" >> CONTRIBUTORS.md + echo "This list was generated by [mgechev/github-contributors-list](https://github.com/mgechev/github-contributors-list)" >> CONTRIBUTORS.md rm CONTRIBUTORS.md.bak run-test TEST: diff --git a/src/vendor/clap/src/app/help.rs b/src/vendor/clap/src/app/help.rs index 233e5b54ef..321a15823f 100644 --- a/src/vendor/clap/src/app/help.rs +++ b/src/vendor/clap/src/app/help.rs @@ -10,13 +10,14 @@ use app::{App, AppSettings}; use app::parser::Parser; use args::{AnyArg, ArgSettings, DispOrder}; use errors::{Error, Result as ClapResult}; -use fmt::{Format, Colorizer}; +use fmt::{Format, Colorizer, ColorizerOption}; +use app::usage; // Third Party use unicode_width::UnicodeWidthStr; #[cfg(feature = "wrap_help")] use term_size; -use unicode_segmentation::UnicodeSegmentation; +use textwrap; use vec_map::VecMap; #[cfg(not(feature = "wrap_help"))] @@ -76,20 +77,23 @@ pub struct Help<'a> { cizer: Colorizer, longest: usize, force_next_line: bool, + use_long: bool, } // Public Functions impl<'a> Help<'a> { /// Create a new `Help` instance. + #[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))] pub fn new(w: &'a mut Write, next_line_help: bool, hide_pv: bool, color: bool, cizer: Colorizer, term_w: Option, - max_w: Option) + max_w: Option, + use_long: bool) -> Self { - debugln!("fn=Help::new;"); + debugln!("Help::new;"); Help { writer: w, next_line_help: next_line_help, @@ -108,60 +112,62 @@ impl<'a> Help<'a> { cizer: cizer, longest: 0, force_next_line: false, + use_long: use_long, } } /// Reads help settings from an App /// and write its help to the wrapped stream. - pub fn write_app_help(w: &'a mut Write, app: &App) -> ClapResult<()> { - debugln!("fn=Help::write_app_help;"); - Self::write_parser_help(w, &app.p) + pub fn write_app_help(w: &'a mut Write, app: &App, use_long: bool) -> ClapResult<()> { + debugln!("Help::write_app_help;"); + Self::write_parser_help(w, &app.p, use_long) } /// Reads help settings from a Parser /// and write its help to the wrapped stream. - pub fn write_parser_help(w: &'a mut Write, parser: &Parser) -> ClapResult<()> { - debugln!("fn=Help::write_parser_help;"); - Self::_write_parser_help(w, parser, false) + pub fn write_parser_help(w: &'a mut Write, parser: &Parser, use_long: bool) -> ClapResult<()> { + debugln!("Help::write_parser_help;"); + Self::_write_parser_help(w, parser, false, use_long) } /// Reads help settings from a Parser /// and write its help to the wrapped stream which will be stderr. This method prevents /// formatting when required. pub fn write_parser_help_to_stderr(w: &'a mut Write, parser: &Parser) -> ClapResult<()> { - debugln!("fn=Help::write_parser_help;"); - Self::_write_parser_help(w, parser, true) + debugln!("Help::write_parser_help;"); + Self::_write_parser_help(w, parser, true, false) } #[doc(hidden)] - pub fn _write_parser_help(w: &'a mut Write, parser: &Parser, stderr: bool) -> ClapResult<()> { - debugln!("fn=Help::write_parser_help;"); + pub fn _write_parser_help(w: &'a mut Write, parser: &Parser, stderr: bool, use_long: bool) -> ClapResult<()> { + debugln!("Help::write_parser_help;"); let nlh = parser.is_set(AppSettings::NextLineHelp); let hide_v = parser.is_set(AppSettings::HidePossibleValuesInHelp); let color = parser.is_set(AppSettings::ColoredHelp); - let cizer = Colorizer { + let cizer = Colorizer::new(ColorizerOption { use_stderr: stderr, when: parser.color(), - }; + }); Self::new(w, nlh, hide_v, color, cizer, parser.meta.term_w, - parser.meta.max_w) - .write_help(parser) + parser.meta.max_w, + use_long) + .write_help(parser) } /// Writes the parser help to the wrapped stream. pub fn write_help(&mut self, parser: &Parser) -> ClapResult<()> { - debugln!("fn=Help::write_help;"); + debugln!("Help::write_help;"); if let Some(h) = parser.meta.help_str { try!(write!(self.writer, "{}", h).map_err(Error::from)); } else if let Some(tmpl) = parser.meta.template { - try!(self.write_templated_help(&parser, tmpl)); + try!(self.write_templated_help(parser, tmpl)); } else { - try!(self.write_default_help(&parser)); + try!(self.write_default_help(parser)); } Ok(()) } @@ -173,25 +179,25 @@ impl<'a> Help<'a> { fn write_args_unsorted<'b: 'd, 'c: 'd, 'd, I: 'd>(&mut self, args: I) -> io::Result<()> where I: Iterator> { + debugln!("Help::write_args_unsorted;"); // The shortest an arg can legally be is 2 (i.e. '-x') self.longest = 2; let mut arg_v = Vec::with_capacity(10); for arg in args.filter(|arg| { - !(arg.is_set(ArgSettings::Hidden)) || arg.is_set(ArgSettings::NextLineHelp) - }) { + !(arg.is_set(ArgSettings::Hidden)) || + arg.is_set(ArgSettings::NextLineHelp) + }) { if arg.longest_filter() { - self.longest = cmp::max(self.longest, arg.to_string().len()); - } - if !arg.is_set(ArgSettings::Hidden) { - arg_v.push(arg) + self.longest = cmp::max(self.longest, str_width(arg.to_string().as_str())); } + arg_v.push(arg) } let mut first = true; for arg in arg_v { if first { first = false; } else { - try!(self.writer.write(b"\n")); + try!(self.writer.write_all(b"\n")); } try!(self.write_arg(arg.as_base())); } @@ -202,7 +208,7 @@ impl<'a> Help<'a> { fn write_args<'b: 'd, 'c: 'd, 'd, I: 'd>(&mut self, args: I) -> io::Result<()> where I: Iterator> { - debugln!("fn=write_args;"); + debugln!("Help::write_args;"); // The shortest an arg can legally be is 2 (i.e. '-x') self.longest = 2; let mut ord_m = VecMap::new(); @@ -214,9 +220,9 @@ impl<'a> Help<'a> { !arg.is_set(ArgSettings::Hidden) || arg.is_set(ArgSettings::NextLineHelp) }) { if arg.longest_filter() { - debugln!("Longest...{}", self.longest); - self.longest = cmp::max(self.longest, arg.to_string().len()); - debugln!("New Longest...{}", self.longest); + debugln!("Help::write_args: Current Longest...{}", self.longest); + self.longest = cmp::max(self.longest, str_width(arg.to_string().as_str())); + debugln!("Help::write_args: New Longest...{}", self.longest); } let btm = ord_m.entry(arg.disp_ord()).or_insert(BTreeMap::new()); btm.insert(arg.name(), arg); @@ -227,7 +233,7 @@ impl<'a> Help<'a> { if first { first = false; } else { - try!(self.writer.write(b"\n")); + try!(self.writer.write_all(b"\n")); } try!(self.write_arg(arg.as_base())); } @@ -237,7 +243,7 @@ impl<'a> Help<'a> { /// Writes help for an argument to the wrapped stream. fn write_arg<'b, 'c>(&mut self, arg: &ArgWithDisplay<'b, 'c>) -> io::Result<()> { - debugln!("fn=write_arg;"); + debugln!("Help::write_arg;"); try!(self.short(arg)); try!(self.long(arg)); let spec_vals = try!(self.val(arg)); @@ -247,7 +253,7 @@ impl<'a> Help<'a> { /// Writes argument's short command to the wrapped stream. fn short<'b, 'c>(&mut self, arg: &ArgWithDisplay<'b, 'c>) -> io::Result<()> { - debugln!("fn=short;"); + debugln!("Help::short;"); try!(write!(self.writer, "{}", TAB)); if let Some(s) = arg.short() { color!(self, "-{}", s, good) @@ -260,7 +266,7 @@ impl<'a> Help<'a> { /// Writes argument's long command to the wrapped stream. fn long<'b, 'c>(&mut self, arg: &ArgWithDisplay<'b, 'c>) -> io::Result<()> { - debugln!("fn=long;"); + debugln!("Help::long;"); if !arg.has_switch() { return Ok(()); } @@ -271,7 +277,13 @@ impl<'a> Help<'a> { } try!(color!(self, "--{}", l, good)) } - try!(write!(self.writer, " ")); + + let sep = if arg.is_set(ArgSettings::RequireEquals) { + "=" + } else { + " " + }; + try!(write!(self.writer, "{}", sep)); } else if let Some(l) = arg.long() { if arg.short().is_some() { try!(write!(self.writer, ", ")); @@ -283,7 +295,7 @@ impl<'a> Help<'a> { /// Writes argument's possible values to the wrapped stream. fn val<'b, 'c>(&mut self, arg: &ArgWithDisplay<'b, 'c>) -> Result { - debugln!("fn=val;arg={}", arg); + debugln!("Help::val: arg={}", arg); if arg.takes_value() { if let Some(vec) = arg.val_names() { let mut it = vec.iter().peekable(); @@ -327,21 +339,21 @@ impl<'a> Help<'a> { (taken as f32 / self.term_w as f32) > 0.40 && h_w > (self.term_w - taken); - debug!("Has switch..."); + debug!("Help::val: Has switch..."); if arg.has_switch() { sdebugln!("Yes"); - debugln!("force_next_line...{:?}", self.force_next_line); - debugln!("nlh...{:?}", nlh); - debugln!("taken...{}", taken); - debugln!("help_width > (width - taken)...{} > ({} - {})", + debugln!("Help::val: force_next_line...{:?}", self.force_next_line); + debugln!("Help::val: nlh...{:?}", nlh); + debugln!("Help::val: taken...{}", taken); + debugln!("Help::val: help_width > (width - taken)...{} > ({} - {})", h_w, self.term_w, taken); - debugln!("longest...{}", self.longest); - debug!("next_line..."); + debugln!("Help::val: longest...{}", self.longest); + debug!("Help::val: next_line..."); if !(nlh || self.force_next_line) { sdebugln!("No"); - let self_len = arg.to_string().len(); + let self_len = str_width(arg.to_string().as_str()); // subtract ourself let mut spcs = self.longest - self_len; // Since we're writing spaces from the tab point we first need to know if we @@ -360,7 +372,7 @@ impl<'a> Help<'a> { } } else if !(nlh || self.force_next_line) { sdebugln!("No, and not next_line"); - write_nspaces!(self.writer, self.longest + 4 - (arg.to_string().len())); + write_nspaces!(self.writer, self.longest + 4 - (str_width(arg.to_string().as_str()))); } else { sdebugln!("No"); } @@ -368,60 +380,41 @@ impl<'a> Help<'a> { } fn write_before_after_help(&mut self, h: &str) -> io::Result<()> { - debugln!("fn=before_help;"); - let mut help = String::new(); + debugln!("Help::write_before_after_help;"); + let mut help = String::from(h); // determine if our help fits or needs to wrap - debugln!("Term width...{}", self.term_w); + debugln!("Help::write_before_after_help: Term width...{}", + self.term_w); let too_long = str_width(h) >= self.term_w; - debug!("Too long..."); + debug!("Help::write_before_after_help: Too long..."); if too_long || h.contains("{n}") { sdebugln!("Yes"); - help.push_str(h); - debugln!("help: {}", help); - debugln!("help width: {}", str_width(&*help)); + debugln!("Help::write_before_after_help: help: {}", help); + debugln!("Help::write_before_after_help: help width: {}", + str_width(&*help)); // Determine how many newlines we need to insert - debugln!("Usable space: {}", self.term_w); - let longest_w = { - let mut lw = 0; - for l in help.split(' ').map(|s| str_width(s)) { - if l > lw { - lw = l; - } - } - lw - }; - help = help.replace("{n}", "\n"); - wrap_help(&mut help, longest_w, self.term_w); + debugln!("Help::write_before_after_help: Usable space: {}", + self.term_w); + help = wrap_help(&help.replace("{n}", "\n"), self.term_w); } else { sdebugln!("No"); } - let help = if !help.is_empty() { - &*help - } else { - help.push_str(h); - &*help - }; - if help.contains('\n') { - if let Some(part) = help.lines().next() { - try!(write!(self.writer, "{}", part)); - } - for part in help.lines().skip(1) { - try!(write!(self.writer, "\n{}", part)); - } - } else { - try!(write!(self.writer, "{}", help)); - } + try!(write!(self.writer, "{}", help)); Ok(()) } /// Writes argument's help to the wrapped stream. fn help<'b, 'c>(&mut self, arg: &ArgWithDisplay<'b, 'c>, spec_vals: &str) -> io::Result<()> { - debugln!("fn=help;"); - let mut help = String::new(); - let h = arg.help().unwrap_or(""); - let nlh = self.next_line_help || arg.is_set(ArgSettings::NextLineHelp); - debugln!("Next Line...{:?}", nlh); + debugln!("Help::help;"); + let h = if self.use_long { + arg.long_help().unwrap_or_else(|| arg.help().unwrap_or("")) + } else { + arg.help().unwrap_or_else(|| arg.long_help().unwrap_or("")) + }; + let mut help = String::from(h) + spec_vals; + let nlh = self.next_line_help || arg.is_set(ArgSettings::NextLineHelp) || self.use_long; + debugln!("Help::help: Next Line...{:?}", nlh); let spcs = if nlh || self.force_next_line { 12 // "tab" * 3 @@ -436,77 +429,58 @@ impl<'a> Help<'a> { try!(write!(self.writer, "\n{}{}{}", TAB, TAB, TAB)); } - debug!("Too long..."); + debug!("Help::help: Too long..."); if too_long && spcs <= self.term_w || h.contains("{n}") { sdebugln!("Yes"); - help.push_str(h); - help.push_str(&*spec_vals); - debugln!("help...{}", help); - debugln!("help width...{}", str_width(&*help)); + debugln!("Help::help: help...{}", help); + debugln!("Help::help: help width...{}", str_width(&*help)); // Determine how many newlines we need to insert let avail_chars = self.term_w - spcs; - debugln!("Usable space...{}", avail_chars); - let longest_w = { - let mut lw = 0; - for l in help.split(' ').map(|s| str_width(s)) { - if l > lw { - lw = l; - } - } - lw - }; - help = help.replace("{n}", "\n"); - wrap_help(&mut help, longest_w, avail_chars); + debugln!("Help::help: Usable space...{}", avail_chars); + help = wrap_help(&help.replace("{n}", "\n"), avail_chars); } else { sdebugln!("No"); } - let help = if !help.is_empty() { - &*help - } else if spec_vals.is_empty() { - h - } else { - help.push_str(h); - help.push_str(&*spec_vals); - &*help - }; - if help.contains('\n') { - if let Some(part) = help.lines().next() { - try!(write!(self.writer, "{}", part)); - } - for part in help.lines().skip(1) { - try!(write!(self.writer, "\n")); - if nlh || self.force_next_line { - try!(write!(self.writer, "{}{}{}", TAB, TAB, TAB)); - } else if arg.has_switch() { - write_nspaces!(self.writer, self.longest + 12); - } else { - write_nspaces!(self.writer, self.longest + 8); - } - try!(write!(self.writer, "{}", part)); + if let Some(part) = help.lines().next() { + try!(write!(self.writer, "{}", part)); + } + for part in help.lines().skip(1) { + try!(write!(self.writer, "\n")); + if nlh || self.force_next_line { + try!(write!(self.writer, "{}{}{}", TAB, TAB, TAB)); + } else if arg.has_switch() { + write_nspaces!(self.writer, self.longest + 12); + } else { + write_nspaces!(self.writer, self.longest + 8); } - } else { - try!(write!(self.writer, "{}", help)); + try!(write!(self.writer, "{}", part)); + } + if !help.contains('\n') && (nlh || self.force_next_line) { + try!(write!(self.writer, "\n")); } Ok(()) } fn spec_vals(&self, a: &ArgWithDisplay) -> String { - debugln!("fn=spec_vals;a={}", a); + debugln!("Help::spec_vals: a={}", a); let mut spec_vals = vec![]; - if let Some(pv) = a.default_val() { - debugln!("Found default value...[{}]", pv); - spec_vals.push(format!(" [default: {}]", - if self.color { - self.cizer.good(pv) - } else { - Format::None(pv) - })); + if !a.is_set(ArgSettings::HideDefaultValue) { + if let Some(pv) = a.default_val() { + debugln!("Help::spec_vals: Found default value...[{:?}]", pv); + spec_vals.push(format!(" [default: {}]", + if self.color { + self.cizer.good(pv.to_string_lossy()) + } else { + Format::None(pv.to_string_lossy()) + })); + } } if let Some(ref aliases) = a.aliases() { - debugln!("Found aliases...{:?}", aliases); + debugln!("Help::spec_vals: Found aliases...{:?}", aliases); spec_vals.push(format!(" [aliases: {}]", if self.color { - aliases.iter() + aliases + .iter() .map(|v| format!("{}", self.cizer.good(v))) .collect::>() .join(", ") @@ -516,16 +490,16 @@ impl<'a> Help<'a> { } if !self.hide_pv && !a.is_set(ArgSettings::HidePossibleValues) { if let Some(pv) = a.possible_vals() { - debugln!("Found possible vals...{:?}", pv); + debugln!("Help::spec_vals: Found possible vals...{:?}", pv); spec_vals.push(if self.color { - format!(" [values: {}]", - pv.iter() - .map(|v| format!("{}", self.cizer.good(v))) - .collect::>() - .join(", ")) - } else { - format!(" [values: {}]", pv.join(", ")) - }); + format!(" [values: {}]", + pv.iter() + .map(|v| format!("{}", self.cizer.good(v))) + .collect::>() + .join(", ")) + } else { + format!(" [values: {}]", pv.join(", ")) + }); } } spec_vals.join(" ") @@ -538,10 +512,14 @@ impl<'a> Help<'a> { /// Writes help for all arguments (options, flags, args, subcommands) /// including titles of a Parser Object to the wrapped stream. #[cfg_attr(feature = "lints", allow(useless_let_if_seq))] + #[cfg_attr(feature = "cargo-clippy", allow(useless_let_if_seq))] pub fn write_all_args(&mut self, parser: &Parser) -> ClapResult<()> { - + debugln!("Help::write_all_args;"); let flags = parser.has_flags(); - let pos = parser.has_positionals(); + let pos = parser + .positionals() + .filter(|arg| !arg.is_set(ArgSettings::Hidden)) + .count() > 0; let opts = parser.has_opts(); let subcmds = parser.has_subcommands(); @@ -550,7 +528,8 @@ impl<'a> Help<'a> { let mut first = true; if unified_help && (flags || opts) { - let opts_flags = parser.flags() + let opts_flags = parser + .flags() .map(as_arg_trait) .chain(parser.opts().map(as_arg_trait)); try!(color!(self, "OPTIONS:\n", warning)); @@ -559,13 +538,12 @@ impl<'a> Help<'a> { } else { if flags { try!(color!(self, "FLAGS:\n", warning)); - try!(self.write_args(parser.flags() - .map(as_arg_trait))); + try!(self.write_args(parser.flags().map(as_arg_trait))); first = false; } if opts { if !first { - try!(self.writer.write(b"\n\n")); + try!(self.writer.write_all(b"\n\n")); } try!(color!(self, "OPTIONS:\n", warning)); try!(self.write_args(parser.opts().map(as_arg_trait))); @@ -575,7 +553,7 @@ impl<'a> Help<'a> { if pos { if !first { - try!(self.writer.write(b"\n\n")); + try!(self.writer.write_all(b"\n\n")); } try!(color!(self, "ARGS:\n", warning)); try!(self.write_args_unsorted(parser.positionals().map(as_arg_trait))); @@ -584,10 +562,10 @@ impl<'a> Help<'a> { if subcmds { if !first { - try!(self.writer.write(b"\n\n")); + try!(self.writer.write_all(b"\n\n")); } try!(color!(self, "SUBCOMMANDS:\n", warning)); - try!(self.write_subcommands(&parser)); + try!(self.write_subcommands(parser)); } Ok(()) @@ -595,13 +573,19 @@ impl<'a> Help<'a> { /// Writes help for subcommands of a Parser Object to the wrapped stream. fn write_subcommands(&mut self, parser: &Parser) -> io::Result<()> { - debugln!("fn=write_subcommands;"); + debugln!("Help::write_subcommands;"); // The shortest an arg can legally be is 2 (i.e. '-x') self.longest = 2; let mut ord_m = VecMap::new(); - for sc in parser.subcommands.iter().filter(|s| !s.p.is_set(AppSettings::Hidden)) { - let btm = ord_m.entry(sc.p.meta.disp_ord).or_insert(BTreeMap::new()); - self.longest = cmp::max(self.longest, sc.p.meta.name.len()); + for sc in parser + .subcommands + .iter() + .filter(|s| !s.p.is_set(AppSettings::Hidden)) { + let btm = ord_m + .entry(sc.p.meta.disp_ord) + .or_insert(BTreeMap::new()); + self.longest = cmp::max(self.longest, str_width(sc.p.meta.name.as_str())); + //self.longest = cmp::max(self.longest, sc.p.meta.name.len()); btm.insert(sc.p.meta.name.clone(), sc.clone()); } @@ -611,7 +595,7 @@ impl<'a> Help<'a> { if first { first = false; } else { - try!(self.writer.write(b"\n")); + try!(self.writer.write_all(b"\n")); } try!(self.write_arg(sc)); } @@ -621,50 +605,67 @@ impl<'a> Help<'a> { /// Writes version of a Parser Object to the wrapped stream. fn write_version(&mut self, parser: &Parser) -> io::Result<()> { - try!(write!(self.writer, "{}", parser.meta.version.unwrap_or("".into()))); + debugln!("Help::write_version;"); + try!(write!(self.writer, "{}", parser.meta.version.unwrap_or(""))); Ok(()) } /// Writes binary name of a Parser Object to the wrapped stream. fn write_bin_name(&mut self, parser: &Parser) -> io::Result<()> { + debugln!("Help::write_bin_name;"); + macro_rules! write_name { + () => {{ + let mut name = parser.meta.name.clone(); + name = name.replace("{n}", "\n"); + try!(color!(self, wrap_help(&name, self.term_w), good)); + }}; + } if let Some(bn) = parser.meta.bin_name.as_ref() { if bn.contains(' ') { // Incase we're dealing with subcommands i.e. git mv is translated to git-mv try!(color!(self, bn.replace(" ", "-"), good)) } else { - try!(color!(self, &parser.meta.name[..], good)) + write_name!(); } } else { - try!(color!(self, &parser.meta.name[..], good)) + write_name!(); } Ok(()) } /// Writes default help for a Parser Object to the wrapped stream. pub fn write_default_help(&mut self, parser: &Parser) -> ClapResult<()> { - debugln!("fn=write_default_help;"); + debugln!("Help::write_default_help;"); if let Some(h) = parser.meta.pre_help { try!(self.write_before_after_help(h)); - try!(self.writer.write(b"\n\n")); + try!(self.writer.write_all(b"\n\n")); } + macro_rules! write_thing { + ($thing:expr) => {{ + let mut owned_thing = $thing.to_owned(); + owned_thing = owned_thing.replace("{n}", "\n"); + try!(write!(self.writer, "{}\n", + wrap_help(&owned_thing, self.term_w))) + }}; + } // Print the version - try!(self.write_bin_name(&parser)); - try!(self.writer.write(b" ")); - try!(self.write_version(&parser)); - try!(self.writer.write(b"\n")); + try!(self.write_bin_name(parser)); + try!(self.writer.write_all(b" ")); + try!(self.write_version(parser)); + try!(self.writer.write_all(b"\n")); if let Some(author) = parser.meta.author { - try!(write!(self.writer, "{}\n", author)); + write_thing!(author) } if let Some(about) = parser.meta.about { - try!(write!(self.writer, "{}\n", about)); + write_thing!(about) } try!(color!(self, "\nUSAGE:", warning)); try!(write!(self.writer, "\n{}{}\n\n", TAB, - parser.create_usage_no_title(&[]))); + usage::create_usage_no_title(parser, &[]))); let flags = parser.has_flags(); let pos = parser.has_positionals(); @@ -672,12 +673,12 @@ impl<'a> Help<'a> { let subcmds = parser.has_subcommands(); if flags || opts || pos || subcmds { - try!(self.write_all_args(&parser)); + try!(self.write_all_args(parser)); } if let Some(h) = parser.meta.more_help { if flags || opts || pos || subcmds { - try!(self.writer.write(b"\n\n")); + try!(self.writer.write_all(b"\n\n")); } try!(self.write_before_after_help(h)); } @@ -700,6 +701,7 @@ enum CopyUntilResult { /// On success, the total number of bytes that were /// copied from reader to writer is returned. fn copy_until(r: &mut R, w: &mut W, delimiter_byte: u8) -> CopyUntilResult { + debugln!("copy_until;"); let mut count = 0; for wb in r.bytes() { @@ -726,14 +728,15 @@ fn copy_until(r: &mut R, w: &mut W, delimiter_byte: u8) -> Co /// Copies the contents of a reader into a writer until a {tag} is found, /// copying the tag content to a buffer and returning its size. /// In addition to errors, there are three possible outputs: -/// - None: The reader was consumed. -/// - Some(Ok(0)): No tag was captured but the reader still contains data. -/// - Some(Ok(length>0)): a tag with `length` was captured to the tag_buffer. +/// - `None`: The reader was consumed. +/// - `Some(Ok(0))`: No tag was captured but the reader still contains data. +/// - `Some(Ok(length>0))`: a tag with `length` was captured to the `tag_buffer`. fn copy_and_capture(r: &mut R, w: &mut W, tag_buffer: &mut Cursor>) -> Option> { use self::CopyUntilResult::*; + debugln!("copy_and_capture;"); // Find the opening byte. match copy_until(r, w, b'{') { @@ -812,7 +815,7 @@ impl<'a> Help<'a> { /// The template system is, on purpose, very simple. Therefore the tags have to writen /// in the lowercase and without spacing. fn write_templated_help(&mut self, parser: &Parser, template: &str) -> ClapResult<()> { - debugln!("fn=write_templated_help;"); + debugln!("Help::write_templated_help;"); let mut tmplr = Cursor::new(&template); let mut tag_buf = Cursor::new(vec![0u8; 15]); @@ -830,18 +833,18 @@ impl<'a> Help<'a> { _ => continue, }; - debugln!("iter;tag_buf={};", unsafe { + debugln!("Help::write_template_help:iter: tag_buf={};", unsafe { String::from_utf8_unchecked(tag_buf.get_ref()[0..tag_length] - .iter() - .map(|&i| i) - .collect::>()) + .iter() + .map(|&i| i) + .collect::>()) }); match &tag_buf.get_ref()[0..tag_length] { b"?" => { - try!(self.writer.write(b"Could not decode tag name")); + try!(self.writer.write_all(b"Could not decode tag name")); } b"bin" => { - try!(self.write_bin_name(&parser)); + try!(self.write_bin_name(parser)); } b"version" => { try!(write!(self.writer, @@ -859,31 +862,29 @@ impl<'a> Help<'a> { parser.meta.about.unwrap_or("unknown about"))); } b"usage" => { - try!(write!(self.writer, "{}", parser.create_usage_no_title(&[]))); + try!(write!(self.writer, "{}", usage::create_usage_no_title(parser, &[]))); } b"all-args" => { - try!(self.write_all_args(&parser)); + try!(self.write_all_args(parser)); } b"unified" => { - let opts_flags = parser.flags() + let opts_flags = parser + .flags() .map(as_arg_trait) .chain(parser.opts().map(as_arg_trait)); try!(self.write_args(opts_flags)); } b"flags" => { - try!(self.write_args(parser.flags() - .map(as_arg_trait))); + try!(self.write_args(parser.flags().map(as_arg_trait))); } b"options" => { - try!(self.write_args(parser.opts() - .map(as_arg_trait))); + try!(self.write_args(parser.opts().map(as_arg_trait))); } b"positionals" => { - try!(self.write_args(parser.positionals() - .map(as_arg_trait))); + try!(self.write_args(parser.positionals().map(as_arg_trait))); } b"subcommands" => { - try!(self.write_subcommands(&parser)); + try!(self.write_subcommands(parser)); } b"after-help" => { try!(write!(self.writer, @@ -897,52 +898,30 @@ impl<'a> Help<'a> { } // Unknown tag, write it back. r => { - try!(self.writer.write(b"{")); - try!(self.writer.write(r)); - try!(self.writer.write(b"}")); + try!(self.writer.write_all(b"{")); + try!(self.writer.write_all(r)); + try!(self.writer.write_all(b"}")); } } } } } -fn wrap_help(help: &mut String, longest_w: usize, avail_chars: usize) { - debugln!("fn=wrap_help;longest_w={},avail_chars={}", - longest_w, - avail_chars); - debug!("Enough space to wrap..."); - if longest_w < avail_chars { - sdebugln!("Yes"); - let mut prev_space = 0; - let mut j = 0; - for (idx, g) in (&*help.clone()).grapheme_indices(true) { - debugln!("iter;idx={},g={}", idx, g); - if g == "\n" { - debugln!("Newline found..."); - debugln!("Still space...{:?}", str_width(&help[j..idx]) < avail_chars); - if str_width(&help[j..idx]) < avail_chars { - j = idx; - continue; - } - } else if g != " " { - if idx != help.len() - 1 || str_width(&help[j..idx]) < avail_chars { - continue; - } - debugln!("Reached the end of the line and we're over..."); - } else if str_width(&help[j..idx]) < avail_chars { - debugln!("Space found with room..."); - prev_space = idx; - continue; - } - debugln!("Adding Newline..."); - j = prev_space; - debugln!("prev_space={},j={}", prev_space, j); - debugln!("removing: {}", j); - debugln!("char at {}: {}", j, &help[j..j]); - help.remove(j); - help.insert(j, '\n'); - } - } else { - sdebugln!("No"); +fn wrap_help(help: &str, avail_chars: usize) -> String { + let wrapper = textwrap::Wrapper::new(avail_chars).break_words(false); + help.lines() + .map(|line| wrapper.fill(line)) + .collect::>() + .join("\n") +} + +#[cfg(test)] +mod test { + use super::wrap_help; + + #[test] + fn wrap_help_last_word() { + let help = String::from("foo bar baz"); + assert_eq!(wrap_help(&help, 5), "foo\nbar\nbaz"); } } diff --git a/src/vendor/clap/src/app/macros.rs b/src/vendor/clap/src/app/macros.rs index fd98084529..719006da8b 100644 --- a/src/vendor/clap/src/app/macros.rs +++ b/src/vendor/clap/src/app/macros.rs @@ -1,21 +1,32 @@ macro_rules! remove_overriden { - (@remove $_self:ident, $v:ident, $a:ident.$ov:ident) => { - if let Some(ref ora) = $a.$ov() { - vec_remove_all!($_self.$v, ora); + (@remove_requires $rem_from:expr, $a:ident.$ov:ident) => { + if let Some(ora) = $a.$ov() { + for i in (0 .. $rem_from.len()).rev() { + let should_remove = ora.iter().any(|&(_, ref name)| name == &$rem_from[i]); + if should_remove { $rem_from.swap_remove(i); } + } + } + }; + (@remove $rem_from:expr, $a:ident.$ov:ident) => { + if let Some(ora) = $a.$ov() { + vec_remove_all!($rem_from, ora.iter()); } }; (@arg $_self:ident, $arg:ident) => { - remove_overriden!(@remove $_self, required, $arg.requires); - remove_overriden!(@remove $_self, blacklist, $arg.blacklist); - remove_overriden!(@remove $_self, overrides, $arg.overrides); + remove_overriden!(@remove_requires $_self.required, $arg.requires); + remove_overriden!(@remove $_self.blacklist, $arg.blacklist); + remove_overriden!(@remove $_self.overrides, $arg.overrides); }; ($_self:ident, $name:expr) => { - debugln!("macro=remove_overriden!;"); - if let Some(ref o) = $_self.opts.iter().filter(|o| o.b.name == *$name).next() { + debugln!("remove_overriden!;"); + if let Some(o) = $_self.opts.iter() .find(|o| o.b.name == *$name) { remove_overriden!(@arg $_self, o); - } else if let Some(ref f) = $_self.flags.iter().filter(|f| f.b.name == *$name).next() { + } else if let Some(f) = $_self.flags.iter() .find(|f| f.b.name == *$name) { remove_overriden!(@arg $_self, f); - } else if let Some(p) = $_self.positionals.values().filter(|p| p.b.name == *$name).next() { + } else { + let p = $_self.positionals.values() + .find(|p| p.b.name == *$name) + .expect(INTERNAL_ERROR_MSG); remove_overriden!(@arg $_self, p); } }; @@ -23,9 +34,9 @@ macro_rules! remove_overriden { macro_rules! arg_post_processing { ($me:ident, $arg:ident, $matcher:ident) => { - debugln!("macro=arg_post_processing!;"); + debugln!("arg_post_processing!;"); // Handle POSIX overrides - debug!("Is '{}' in overrides...", $arg.to_string()); + debug!("arg_post_processing!: Is '{}' in overrides...", $arg.to_string()); if $me.overrides.contains(&$arg.name()) { if let Some(ref name) = find_name_from!($me, &$arg.name(), overrides, $matcher) { sdebugln!("Yes by {}", name); @@ -35,23 +46,23 @@ macro_rules! arg_post_processing { } else { sdebugln!("No"); } // Add overrides - debug!("Does '{}' have overrides...", $arg.to_string()); + debug!("arg_post_processing!: Does '{}' have overrides...", $arg.to_string()); if let Some(or) = $arg.overrides() { sdebugln!("Yes"); $matcher.remove_all(or); for pa in or { remove_overriden!($me, pa); } $me.overrides.extend(or); - vec_remove_all!($me.required, or); + vec_remove_all!($me.required, or.iter()); } else { sdebugln!("No"); } // Handle conflicts - debug!("Does '{}' have conflicts...", $arg.to_string()); + debug!("arg_post_processing!: Does '{}' have conflicts...", $arg.to_string()); if let Some(bl) = $arg.blacklist() { sdebugln!("Yes"); - + for c in bl { // Inject two-way conflicts - debug!("Has '{}' already been matched...", c); + debug!("arg_post_processing!: Has '{}' already been matched...", c); if $matcher.contains(c) { sdebugln!("Yes"); // find who blacklisted us... @@ -61,21 +72,20 @@ macro_rules! arg_post_processing { } } - $me.blacklist.extend(bl); - vec_remove_all!($me.overrides, bl); - vec_remove_all!($me.required, bl); + $me.blacklist.extend_from_slice(bl); + vec_remove_all!($me.overrides, bl.iter()); + // vec_remove_all!($me.required, bl.iter()); } else { sdebugln!("No"); } // Add all required args which aren't already found in matcher to the master // list - debug!("Does '{}' have requirements...", $arg.to_string()); + debug!("arg_post_processing!: Does '{}' have requirements...", $arg.to_string()); if let Some(reqs) = $arg.requires() { - for n in reqs { - if $matcher.contains(&n) { - sdebugln!("\tYes '{}' but it's already met", n); - continue; - } else { sdebugln!("\tYes '{}'", n); } - + for n in reqs.iter() + .filter(|&&(val, _)| val.is_none()) + .filter(|&&(_, req)| !$matcher.contains(&req)) + .map(|&(_, name)| name) { + $me.required.push(n); } } else { sdebugln!("No"); } @@ -87,11 +97,11 @@ macro_rules! arg_post_processing { macro_rules! _handle_group_reqs{ ($me:ident, $arg:ident) => ({ use args::AnyArg; - debugln!("macro=_handle_group_reqs!;"); - for grp in $me.groups.values() { + debugln!("_handle_group_reqs!;"); + for grp in &$me.groups { let found = if grp.args.contains(&$arg.name()) { - vec_remove!($me.required, &$arg.name()); if let Some(ref reqs) = grp.requires { + debugln!("_handle_group_reqs!: Adding {:?} to the required list", reqs); $me.required.extend(reqs); } if let Some(ref bl) = grp.conflicts { @@ -101,31 +111,26 @@ macro_rules! _handle_group_reqs{ } else { false }; - debugln!("iter;grp={};found={:?}", grp.name, found); + debugln!("_handle_group_reqs!:iter: grp={}, found={:?}", grp.name, found); if found { - vec_remove_all!($me.required, &grp.args); - debugln!("Adding args from group to blacklist...{:?}", grp.args); + for i in (0 .. $me.required.len()).rev() { + let should_remove = grp.args.contains(&$me.required[i]); + if should_remove { $me.required.swap_remove(i); } + } + debugln!("_handle_group_reqs!:iter: Adding args from group to blacklist...{:?}", grp.args); if !grp.multiple { $me.blacklist.extend(&grp.args); - vec_remove!($me.blacklist, &$arg.name()); + debugln!("_handle_group_reqs!: removing {:?} from blacklist", $arg.name()); + for i in (0 .. $me.blacklist.len()).rev() { + let should_remove = $me.blacklist[i] == $arg.name(); + if should_remove { $me.blacklist.swap_remove(i); } + } } } } }) } -macro_rules! validate_multiples { - ($_self:ident, $a:ident, $m:ident) => { - debugln!("macro=validate_multiples!;"); - if $m.contains(&$a.b.name) && !$a.b.settings.is_set(ArgSettings::Multiple) { - // Not the first time, and we don't allow multiples - return Err(Error::unexpected_multiple_usage($a, - &*$_self.create_current_usage($m), - $_self.color())) - } - }; -} - macro_rules! parse_positional { ( $_self:ident, @@ -134,109 +139,27 @@ macro_rules! parse_positional { $pos_counter:ident, $matcher:ident ) => { - debugln!("macro=parse_positional!;"); - validate_multiples!($_self, $p, $matcher); + debugln!("parse_positional!;"); - if !$_self.trailing_vals && - ($_self.settings.is_set(AppSettings::TrailingVarArg) && + if !$_self.is_set(AS::TrailingValues) && + ($_self.is_set(AS::TrailingVarArg) && $pos_counter == $_self.positionals.len()) { - $_self.trailing_vals = true; + $_self.settings.set(AS::TrailingValues); } let _ = try!($_self.add_val_to_arg($p, &$arg_os, $matcher)); $matcher.inc_occurrence_of($p.b.name); let _ = $_self.groups_for_arg($p.b.name) .and_then(|vec| Some($matcher.inc_occurrences_of(&*vec))); - arg_post_processing!($_self, $p, $matcher); + if $_self.cache.map_or(true, |name| name != $p.b.name) { + arg_post_processing!($_self, $p, $matcher); + $_self.cache = Some($p.b.name); + } + + $_self.settings.set(AS::ValidArgFound); // Only increment the positional counter if it doesn't allow multiples if !$p.b.settings.is_set(ArgSettings::Multiple) { $pos_counter += 1; } }; } - -macro_rules! find_from { - ($_self:ident, $arg_name:expr, $from:ident, $matcher:expr) => {{ - let mut ret = None; - for k in $matcher.arg_names() { - if let Some(f) = find_by_name!($_self, &k, flags, iter) { - if let Some(ref v) = f.$from() { - if v.contains($arg_name) { - ret = Some(f.to_string()); - } - } - } - if let Some(o) = find_by_name!($_self, &k, opts, iter) { - if let Some(ref v) = o.$from() { - if v.contains(&$arg_name) { - ret = Some(o.to_string()); - } - } - } - if let Some(pos) = find_by_name!($_self, &k, positionals, values) { - if let Some(ref v) = pos.$from() { - if v.contains($arg_name) { - ret = Some(pos.b.name.to_owned()); - } - } - } - } - ret - }}; -} - -macro_rules! find_name_from { - ($_self:ident, $arg_name:expr, $from:ident, $matcher:expr) => {{ - let mut ret = None; - for k in $matcher.arg_names() { - if let Some(f) = find_by_name!($_self, &k, flags, iter) { - if let Some(ref v) = f.$from() { - if v.contains($arg_name) { - ret = Some(f.b.name); - } - } - } - if let Some(o) = find_by_name!($_self, &k, opts, iter) { - if let Some(ref v) = o.$from() { - if v.contains(&$arg_name) { - ret = Some(o.b.name); - } - } - } - if let Some(pos) = find_by_name!($_self, &k, positionals, values) { - if let Some(ref v) = pos.$from() { - if v.contains($arg_name) { - ret = Some(pos.b.name); - } - } - } - } - ret - }}; -} - -// Finds an arg by name -macro_rules! find_by_name { - ($_self:ident, $name:expr, $what:ident, $how:ident) => { - $_self.$what.$how().find(|o| &o.b.name == $name) - } -} - -// Finds an option including if it's aliasesed -macro_rules! find_by_long { - ($_self:ident, $long:expr, $what:ident) => { - $_self.$what - .iter() - .filter(|o| o.s.long.is_some()) - .find(|o| { - &&o.s.long.unwrap() == &$long || - (o.s.aliases.is_some() && - o.s - .aliases - .as_ref() - .unwrap() - .iter() - .any(|&(alias, _)| &&alias == &$long)) - }) - } -} diff --git a/src/vendor/clap/src/app/meta.rs b/src/vendor/clap/src/app/meta.rs index 33b2f355e0..6fbf412ce2 100644 --- a/src/vendor/clap/src/app/meta.rs +++ b/src/vendor/clap/src/app/meta.rs @@ -1,11 +1,14 @@ #[doc(hidden)] #[allow(missing_debug_implementations)] +#[derive(Default, Clone)] pub struct AppMeta<'b> { pub name: String, pub bin_name: Option, pub author: Option<&'b str>, pub version: Option<&'b str>, + pub long_version: Option<&'b str>, pub about: Option<&'b str>, + pub long_about: Option<&'b str>, pub more_help: Option<&'b str>, pub pre_help: Option<&'b str>, pub aliases: Option>, // (name, visible) @@ -18,51 +21,7 @@ pub struct AppMeta<'b> { pub template: Option<&'b str>, } -impl<'b> Default for AppMeta<'b> { - fn default() -> Self { - AppMeta { - name: String::new(), - author: None, - about: None, - more_help: None, - pre_help: None, - version: None, - usage_str: None, - usage: None, - bin_name: None, - help_str: None, - disp_ord: 999, - template: None, - aliases: None, - term_w: None, - max_w: None, - } - } -} - impl<'b> AppMeta<'b> { pub fn new() -> Self { Default::default() } - pub fn with_name(s: String) -> Self { AppMeta { name: s, ..Default::default() } } -} - -impl<'b> Clone for AppMeta<'b> { - fn clone(&self) -> Self { - AppMeta { - name: self.name.clone(), - author: self.author, - about: self.about, - more_help: self.more_help, - pre_help: self.pre_help, - version: self.version, - usage_str: self.usage_str, - usage: self.usage.clone(), - bin_name: self.bin_name.clone(), - help_str: self.help_str, - disp_ord: self.disp_ord, - template: self.template, - aliases: self.aliases.clone(), - term_w: self.term_w, - max_w: self.max_w, - } - } -} + pub fn with_name(s: String) -> Self { AppMeta { name: s, disp_ord: 999, ..Default::default() } } +} \ No newline at end of file diff --git a/src/vendor/clap/src/app/mod.rs b/src/vendor/clap/src/app/mod.rs index d1a690ffb9..03721386d5 100644 --- a/src/vendor/clap/src/app/mod.rs +++ b/src/vendor/clap/src/app/mod.rs @@ -4,11 +4,12 @@ mod macros; pub mod parser; mod meta; mod help; +mod validator; +mod usage; // Std -use std::borrow::Borrow; use std::env; -use std::ffi::OsString; +use std::ffi::{OsStr, OsString}; use std::fmt; use std::io::{self, BufRead, BufWriter, Write}; use std::path::Path; @@ -17,15 +18,14 @@ use std::rc::Rc; use std::result::Result as StdResult; // Third Party -use vec_map::VecMap; +use vec_map::{self, VecMap}; #[cfg(feature = "yaml")] use yaml_rust::Yaml; // Internal use app::help::Help; use app::parser::Parser; -use args::{ArgKind, AnyArg, Arg, ArgGroup, ArgMatcher, ArgMatches, ArgSettings}; -use errors::Error; +use args::{AnyArg, Arg, ArgGroup, ArgMatcher, ArgMatches, ArgSettings}; use errors::Result as ClapResult; pub use self::settings::AppSettings; use completions::Shell; @@ -51,7 +51,7 @@ use completions::Shell; /// .arg( /// Arg::with_name("in_file").index(1) /// ) -/// .after_help("Longer explaination to appear after the options when \ +/// .after_help("Longer explanation to appear after the options when \ /// displaying the help information from --help or -h") /// .get_matches(); /// @@ -104,12 +104,12 @@ impl<'a, 'b> App<'a, 'b> { #[deprecated(since="2.14.1", note="Can never work; use explicit App::author() and App::version() calls instead")] pub fn with_defaults>(n: S) -> Self { let mut a = App { p: Parser::with_name(n.into()) }; - a.p.meta.author = Some(crate_authors!()); - a.p.meta.version = Some(crate_version!()); + a.p.meta.author = Some("Kevin K. "); + a.p.meta.version = Some("2.19.2"); a } - /// Creates a new instace of [`App`] from a .yml (YAML) file. A full example of supported YAML + /// Creates a new instance of [`App`] from a .yml (YAML) file. A full example of supported YAML /// objects can be found in [`examples/17_yaml.rs`] and [`examples/17_yaml.yml`]. One great use /// for using YAML is when supporting multiple languages and dialects, as each language could /// be a distinct YAML file and determined at compiletime via `cargo` "features" in your @@ -177,7 +177,7 @@ impl<'a, 'b> App<'a, 'b> { } /// Overrides the system-determined binary name. This should only be used when absolutely - /// neccessary, such as when the binary name for your application is misleading, or perhaps + /// necessary, such as when the binary name for your application is misleading, or perhaps /// *not* how the user should invoke your program. /// /// **Pro-tip:** When building things such as third party `cargo` subcommands, this setting @@ -200,7 +200,13 @@ impl<'a, 'b> App<'a, 'b> { } /// Sets a string describing what the program does. This will be displayed when displaying help - /// information. + /// information with `-h`. + /// + /// **NOTE:** If only `about` is provided, and not [`App::long_about`] but the user requests + /// `--help` clap will still display the contents of `about` appropriately + /// + /// **NOTE:** Only [`App::about`] is used in completion script generation in order to be + /// concise /// /// # Examples /// @@ -210,11 +216,65 @@ impl<'a, 'b> App<'a, 'b> { /// .about("Does really amazing things to great people") /// # ; /// ``` + /// [`App::long_about`]: ./struct.App.html#method.long_about pub fn about>(mut self, about: S) -> Self { self.p.meta.about = Some(about.into()); self } + /// Sets a string describing what the program does. This will be displayed when displaying help + /// information. + /// + /// **NOTE:** If only `long_about` is provided, and not [`App::about`] but the user requests + /// `-h` clap will still display the contents of `long_about` appropriately + /// + /// **NOTE:** Only [`App::about`] is used in completion script generation in order to be + /// concise + /// + /// # Examples + /// + /// ```no_run + /// # use clap::{App, Arg}; + /// App::new("myprog") + /// .long_about( + /// "Does really amazing things to great people. Now let's talk a little + /// more in depth about how this subcommand really works. It may take about + /// a few lines of text, but that's ok!") + /// # ; + /// ``` + /// [`App::about`]: ./struct.App.html#method.about + pub fn long_about>(mut self, about: S) -> Self { + self.p.meta.long_about = Some(about.into()); + self + } + + /// Sets the program's name. This will be displayed when displaying help information. + /// + /// **Pro-top:** This function is particularly useful when configuring a program via + /// [`App::from_yaml`] in conjunction with the [`crate_name!`] macro to derive the program's + /// name from its `Cargo.toml`. + /// + /// # Examples + /// ```ignore + /// # #[macro_use] + /// # extern crate clap; + /// # use clap::App; + /// # fn main() { + /// let yml = load_yaml!("app.yml"); + /// let app = App::from_yaml(yml) + /// .name(crate_name!()); + /// + /// // continued logic goes here, such as `app.get_matches()` etc. + /// # } + /// ``` + /// + /// [`App::from_yaml`]: ./struct.App.html#method.from_yaml + /// [`crate_name!`]: ./macro.crate_name.html + pub fn name>(mut self, name: S) -> Self { + self.p.meta.name = name.into(); + self + } + /// Adds additional help information to be displayed in addition to auto-generated help. This /// information is displayed **after** the auto-generated help information. This is often used /// to describe how to use the arguments, or caveats to be noted. @@ -250,7 +310,10 @@ impl<'a, 'b> App<'a, 'b> { } /// Sets a string of the version number to be displayed when displaying version or help - /// information. + /// information with `-V`. + /// + /// **NOTE:** If only `version` is provided, and not [`App::long_version`] but the user + /// requests `--version` clap will still display the contents of `version` appropriately /// /// **Pro-tip:** Use `clap`s convenience macro [`crate_version!`] to automatically set your /// application's version to the same thing as your crate at compile time. See the [`examples/`] @@ -266,11 +329,43 @@ impl<'a, 'b> App<'a, 'b> { /// ``` /// [`crate_version!`]: ./macro.crate_version!.html /// [`examples/`]: https://github.com/kbknapp/clap-rs/tree/master/examples + /// [`App::long_version`]: ./struct.App.html#method.long_version pub fn version>(mut self, ver: S) -> Self { self.p.meta.version = Some(ver.into()); self } + /// Sets a string of the version number to be displayed when displaying version or help + /// information with `--version`. + /// + /// **NOTE:** If only `long_version` is provided, and not [`App::version`] but the user + /// requests `-V` clap will still display the contents of `long_version` appropriately + /// + /// **Pro-tip:** Use `clap`s convenience macro [`crate_version!`] to automatically set your + /// application's version to the same thing as your crate at compile time. See the [`examples/`] + /// directory for more information + /// + /// # Examples + /// + /// ```no_run + /// # use clap::{App, Arg}; + /// App::new("myprog") + /// .long_version( + /// "v0.1.24 + /// commit: abcdef89726d + /// revision: 123 + /// release: 2 + /// binary: myprog") + /// # ; + /// ``` + /// [`crate_version!`]: ./macro.crate_version!.html + /// [`examples/`]: https://github.com/kbknapp/clap-rs/tree/master/examples + /// [`App::version`]: ./struct.App.html#method.version + pub fn long_version>(mut self, ver: S) -> Self { + self.p.meta.long_version = Some(ver.into()); + self + } + /// Sets a custom usage string to override the auto-generated usage string. /// /// This will be displayed to the user when errors are found in argument parsing, or when you @@ -391,6 +486,44 @@ impl<'a, 'b> App<'a, 'b> { self } + /// Sets the help text for the auto-generated `help` argument. + /// + /// By default `clap` sets this to `"Prints help information"`, but if you're using a + /// different convention for your help messages and would prefer a different phrasing you can + /// override it. + /// + /// # Examples + /// + /// ```no_run + /// # use clap::{App, Arg}; + /// App::new("myprog") + /// .help_message("Print help information") // Perhaps you want imperative help messages + /// + /// # ; + /// ``` + pub fn help_message>(mut self, s: S) -> Self { + self.p.help_message = Some(s.into()); + self + } + + /// Sets the help text for the auto-generated `version` argument. + /// + /// By default `clap` sets this to `"Prints version information"`, but if you're using a + /// different convention for your help messages and would prefer a different phrasing then you + /// can change it. + /// + /// # Examples + /// ```no_run + /// # use clap::{App, Arg}; + /// App::new("myprog") + /// .version_message("Print version information") // Perhaps you want imperative help messages + /// # ; + /// ``` + pub fn version_message>(mut self, s: S) -> Self { + self.p.version_message = Some(s.into()); + self + } + /// Sets the help template to be used, overriding the default format. /// /// Tags arg given inside curly brackets. @@ -400,15 +533,19 @@ impl<'a, 'b> App<'a, 'b> { /// * `{bin}` - Binary name. /// * `{version}` - Version number. /// * `{author}` - Author information. + /// * `{about}` - General description (from [`App::about`]) /// * `{usage}` - Automatically generated or given usage string. /// * `{all-args}` - Help for all arguments (options, flags, positionals arguments, /// and subcommands) including titles. - /// * `{unified}` - Unified help for options and flags. + /// * `{unified}` - Unified help for options and flags. Note, you must *also* set + /// [`AppSettings::UnifiedHelpMessage`] to fully merge both options and + /// flags, otherwise the ordering is "best effort" /// * `{flags}` - Help for flags. /// * `{options}` - Help for options. /// * `{positionals}` - Help for positionals arguments. /// * `{subcommands}` - Help for subcommands. - /// * `{after-help}` - Help for flags. + /// * `{after-help}` - Help from [`App::after_help`] + /// * `{before-help}` - Help from [`App::before_help`] /// /// # Examples /// @@ -421,6 +558,10 @@ impl<'a, 'b> App<'a, 'b> { /// ``` /// **NOTE:**The template system is, on purpose, very simple. Therefore the tags have to writen /// in the lowercase and without spacing. + /// [`App::about`]: ./struct.App.html#method.about + /// [`App::after_help`]: ./struct.App.html#method.after_help + /// [`App::before_help`]: ./struct.App.html#method.before_help + /// [`AppSettings::UnifiedHelpMessage`]: ./enum.AppSettings.html#variant.UnifiedHelpMessage pub fn template>(mut self, s: S) -> Self { self.p.meta.template = Some(s.into()); self @@ -486,7 +627,7 @@ impl<'a, 'b> App<'a, 'b> { /// [`AppSettings`]: ./enum.AppSettings.html pub fn global_setting(mut self, setting: AppSettings) -> Self { self.p.set(setting); - self.p.g_settings.push(setting); + self.p.g_settings.set(setting); self } @@ -510,7 +651,7 @@ impl<'a, 'b> App<'a, 'b> { pub fn global_settings(mut self, settings: &[AppSettings]) -> Self { for s in settings { self.p.set(*s); - self.p.g_settings.push(*s) + self.p.g_settings.set(*s) } self } @@ -614,7 +755,7 @@ impl<'a, 'b> App<'a, 'b> { self } - /// Adds an [argument] to the list of valid possibilties. + /// Adds an [argument] to the list of valid possibilities. /// /// # Examples /// @@ -635,8 +776,8 @@ impl<'a, 'b> App<'a, 'b> { /// # ; /// ``` /// [argument]: ./struct.Arg.html - pub fn arg> + 'a>(mut self, a: A) -> Self { - self.p.add_arg(a.borrow()); + pub fn arg>>(mut self, a: A) -> Self { + self.p.add_arg(a.into()); self } @@ -656,7 +797,7 @@ impl<'a, 'b> App<'a, 'b> { /// [arguments]: ./struct.Arg.html pub fn args(mut self, args: &[Arg<'a, 'b>]) -> Self { for arg in args { - self.p.add_arg(arg); + self.p.add_arg_ref(arg); } self } @@ -679,7 +820,7 @@ impl<'a, 'b> App<'a, 'b> { /// [`Arg`]: ./struct.Arg.html /// [`Arg::from_usage`]: ./struct.Arg.html#method.from_usage pub fn arg_from_usage(mut self, usage: &'a str) -> Self { - self.p.add_arg(&Arg::from_usage(usage)); + self.p.add_arg(Arg::from_usage(usage)); self } @@ -711,7 +852,7 @@ impl<'a, 'b> App<'a, 'b> { if l.is_empty() { continue; } - self.p.add_arg(&Arg::from_usage(l)); + self.p.add_arg(Arg::from_usage(l)); } self } @@ -893,7 +1034,7 @@ impl<'a, 'b> App<'a, 'b> { self } - /// Adds a [`SubCommand`] to the list of valid possibilties. Subcommands are effectively + /// Adds a [`SubCommand`] to the list of valid possibilities. Subcommands are effectively /// sub-[`App`]s, because they can contain their own arguments, subcommands, version, usage, /// etc. They also function just like [`App`]s, in that they get their own auto generated help, /// version, and usage. @@ -915,7 +1056,7 @@ impl<'a, 'b> App<'a, 'b> { self } - /// Adds multiple subcommands to the list of valid possibilties by iterating over an + /// Adds multiple subcommands to the list of valid possibilities by iterating over an /// [`IntoIterator`] of [`SubCommand`]s /// /// # Examples @@ -992,7 +1133,11 @@ impl<'a, 'b> App<'a, 'b> { self } - /// Prints the full help message to [`io::stdout()`] using a [`BufWriter`] + /// Prints the full help message to [`io::stdout()`] using a [`BufWriter`] using the same + /// method as if someone ran `-h` to request the help message + /// + /// **NOTE:** clap has the ability to distinguish between "short" and "long" help messages + /// depending on if the user ran [`-h` (short)] or [`--help` (long)] /// /// # Examples /// @@ -1003,14 +1148,60 @@ impl<'a, 'b> App<'a, 'b> { /// ``` /// [`io::stdout()`]: https://doc.rust-lang.org/std/io/fn.stdout.html /// [`BufWriter`]: https://doc.rust-lang.org/std/io/struct.BufWriter.html + /// [`-h` (short)]: ./struct.Arg.html#method.help + /// [`--help` (long)]: ./struct.Arg.html#method.long_help pub fn print_help(&mut self) -> ClapResult<()> { + // If there are global arguments, or settings we need to propgate them down to subcommands + // before parsing incase we run into a subcommand + self.p.propogate_globals(); + self.p.propogate_settings(); + self.p.derive_display_order(); + self.p.create_help_and_version(); let out = io::stdout(); let mut buf_w = BufWriter::new(out.lock()); self.write_help(&mut buf_w) } - /// Writes the full help message to the user to a [`io::Write`] object + /// Prints the full help message to [`io::stdout()`] using a [`BufWriter`] using the same + /// method as if someone ran `-h` to request the help message + /// + /// **NOTE:** clap has the ability to distinguish between "short" and "long" help messages + /// depending on if the user ran [`-h` (short)] or [`--help` (long)] + /// + /// # Examples + /// + /// ```rust + /// # use clap::App; + /// let mut app = App::new("myprog"); + /// app.print_long_help(); + /// ``` + /// [`io::stdout()`]: https://doc.rust-lang.org/std/io/fn.stdout.html + /// [`BufWriter`]: https://doc.rust-lang.org/std/io/struct.BufWriter.html + /// [`-h` (short)]: ./struct.Arg.html#method.help + /// [`--help` (long)]: ./struct.Arg.html#method.long_help + pub fn print_long_help(&mut self) -> ClapResult<()> { + // If there are global arguments, or settings we need to propgate them down to subcommands + // before parsing incase we run into a subcommand + self.p.propogate_globals(); + self.p.propogate_settings(); + self.p.derive_display_order(); + + self.p.create_help_and_version(); + let out = io::stdout(); + let mut buf_w = BufWriter::new(out.lock()); + self.write_long_help(&mut buf_w) + } + + /// Writes the full help message to the user to a [`io::Write`] object in the same method as if + /// the user ran `-h` + /// + /// **NOTE:** clap has the ability to distinguish between "short" and "long" help messages + /// depending on if the user ran [`-h` (short)] or [`--help` (long)] + /// + /// **NOTE:** There is a known bug where this method does not write propogated global arguments + /// or autogenerated arguments (i.e. the default help/version args). Prefer + /// [`App::write_long_help`] instead if possibe! /// /// # Examples /// @@ -1022,11 +1213,52 @@ impl<'a, 'b> App<'a, 'b> { /// app.write_help(&mut out).expect("failed to write to stdout"); /// ``` /// [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html + /// [`-h` (short)]: ./struct.Arg.html#method.help + /// [`--help` (long)]: ./struct.Arg.html#method.long_help pub fn write_help(&self, w: &mut W) -> ClapResult<()> { - Help::write_app_help(w, self) + // PENDING ISSUE: 808 + // https://github.com/kbknapp/clap-rs/issues/808 + // If there are global arguments, or settings we need to propgate them down to subcommands + // before parsing incase we run into a subcommand + // self.p.propogate_globals(); + // self.p.propogate_settings(); + // self.p.derive_display_order(); + // self.p.create_help_and_version(); + + Help::write_app_help(w, self, false) } - /// Writes the version message to the user to a [`io::Write`] object + /// Writes the full help message to the user to a [`io::Write`] object in the same method as if + /// the user ran `--help` + /// + /// **NOTE:** clap has the ability to distinguish between "short" and "long" help messages + /// depending on if the user ran [`-h` (short)] or [`--help` (long)] + /// + /// # Examples + /// + /// ```rust + /// # use clap::App; + /// use std::io; + /// let mut app = App::new("myprog"); + /// let mut out = io::stdout(); + /// app.write_long_help(&mut out).expect("failed to write to stdout"); + /// ``` + /// [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html + /// [`-h` (short)]: ./struct.Arg.html#method.help + /// [`--help` (long)]: ./struct.Arg.html#method.long_help + pub fn write_long_help(&mut self, w: &mut W) -> ClapResult<()> { + self.p.propogate_globals(); + self.p.propogate_settings(); + self.p.derive_display_order(); + self.p.create_help_and_version(); + + Help::write_app_help(w, self, true) + } + + /// Writes the version message to the user to a [`io::Write`] object as if the user ran `-V`. + /// + /// **NOTE:** clap has the ability to distinguish between "short" and "long" version messages + /// depending on if the user ran [`-V` (short)] or [`--version` (long)] /// /// # Examples /// @@ -1038,10 +1270,32 @@ impl<'a, 'b> App<'a, 'b> { /// app.write_version(&mut out).expect("failed to write to stdout"); /// ``` /// [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html + /// [`-V` (short)]: ./struct.App.html#method.version + /// [`--version` (long)]: ./struct.App.html#method.long_version pub fn write_version(&self, w: &mut W) -> ClapResult<()> { - self.p.write_version(w).map_err(From::from) + self.p.write_version(w, false).map_err(From::from) } + /// Writes the version message to the user to a [`io::Write`] object + /// + /// **NOTE:** clap has the ability to distinguish between "short" and "long" version messages + /// depending on if the user ran [`-V` (short)] or [`--version` (long)] + /// + /// # Examples + /// + /// ```rust + /// # use clap::App; + /// use std::io; + /// let mut app = App::new("myprog"); + /// let mut out = io::stdout(); + /// app.write_long_version(&mut out).expect("failed to write to stdout"); + /// ``` + /// [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html + /// [`-V` (short)]: ./struct.App.html#method.version + /// [`--version` (long)]: ./struct.App.html#method.long_version + pub fn write_long_version(&self, w: &mut W) -> ClapResult<()> { + self.p.write_version(w, true).map_err(From::from) + } /// Generate a completions file for a specified shell at compile time. /// @@ -1052,9 +1306,9 @@ impl<'a, 'b> App<'a, 'b> { /// The following example generates a bash completion script via a `build.rs` script. In this /// simple example, we'll demo a very small application with only a single subcommand and two /// args. Real applications could be many multiple levels deep in subcommands, and have tens or - /// potentiall hundreds of arguments. + /// potentially hundreds of arguments. /// - /// First, it helps if we separate out our `App` definition into a seperate file. Whether you + /// First, it helps if we separate out our `App` definition into a separate file. Whether you /// do this as a function, or bare App definition is a matter of personal preference. /// /// ``` @@ -1098,7 +1352,7 @@ impl<'a, 'b> App<'a, 'b> { /// build = "build.rs" /// /// [build-dependencies] - /// clap = "2.9" + /// clap = "2.23" /// ``` /// /// Next, we place a `build.rs` in our project root. @@ -1248,7 +1502,21 @@ impl<'a, 'b> App<'a, 'b> { { self.get_matches_from_safe_borrow(itr).unwrap_or_else(|e| { // Otherwise, write to stderr and exit - self.maybe_wait_for_exit(e); + if e.use_stderr() { + wlnerr!("{}", e.message); + if self.p.is_set(AppSettings::WaitOnError) { + wlnerr!("\nPress [ENTER] / [RETURN] to continue..."); + let mut s = String::new(); + let i = io::stdin(); + i.lock().read_line(&mut s).unwrap(); + } + drop(self); + drop(e); + process::exit(1); + } + + drop(self); + e.exit() }) } @@ -1351,24 +1619,13 @@ impl<'a, 'b> App<'a, 'b> { return Err(e); } - Ok(matcher.into()) - } - - // Re-implements ClapError::exit except it checks if we should wait for input before exiting - // since ClapError doesn't have that info and the error message must be printed before exiting - fn maybe_wait_for_exit(&self, e: Error) -> ! { - if e.use_stderr() { - wlnerr!("{}", e.message); - if self.p.is_set(AppSettings::WaitOnError) { - wlnerr!("\nPress [ENTER] / [RETURN] to continue..."); - let mut s = String::new(); - let i = io::stdin(); - i.lock().read_line(&mut s).unwrap(); + if self.p.is_set(AppSettings::PropagateGlobalValuesDown) { + for a in &self.p.global_args { + matcher.propagate(a.b.name); } - process::exit(1); } - e.exit() + Ok(matcher.into()) } } @@ -1399,6 +1656,7 @@ impl<'a> From<&'a Yaml> for App<'a, 'a> { } yaml_str!(a, yaml, version); + yaml_str!(a, yaml, author); yaml_str!(a, yaml, bin_name); yaml_str!(a, yaml, about); yaml_str!(a, yaml, before_help); @@ -1408,6 +1666,8 @@ impl<'a> From<&'a Yaml> for App<'a, 'a> { yaml_str!(a, yaml, help); yaml_str!(a, yaml, help_short); yaml_str!(a, yaml, version_short); + yaml_str!(a, yaml, help_message); + yaml_str!(a, yaml, version_message); yaml_str!(a, yaml, alias); yaml_str!(a, yaml, visible_alias); @@ -1509,14 +1769,13 @@ impl<'n, 'e> AnyArg<'n, 'e> for App<'n, 'e> { fn name(&self) -> &'n str { unreachable!("App struct does not support AnyArg::name, this is a bug!") } - fn id(&self) -> usize { self.p.id } - fn kind(&self) -> ArgKind { ArgKind::Subcmd } fn overrides(&self) -> Option<&[&'e str]> { None } - fn requires(&self) -> Option<&[&'e str]> { None } + fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> { None } fn blacklist(&self) -> Option<&[&'e str]> { None } fn required_unless(&self) -> Option<&[&'e str]> { None } fn val_names(&self) -> Option<&VecMap<&'e str>> { None } fn is_set(&self, _: ArgSettings) -> bool { false } + fn val_terminator(&self) -> Option<&'e str> { None } fn set(&mut self, _: ArgSettings) { unreachable!("App struct does not support AnyArg::set, this is a bug!") } @@ -1525,13 +1784,18 @@ impl<'n, 'e> AnyArg<'n, 'e> for App<'n, 'e> { fn num_vals(&self) -> Option { None } fn possible_vals(&self) -> Option<&[&'e str]> { None } fn validator(&self) -> Option<&Rc StdResult<(), String>>> { None } + fn validator_os(&self) -> Option<&Rc StdResult<(), OsString>>> { None } fn min_vals(&self) -> Option { None } fn short(&self) -> Option { None } fn long(&self) -> Option<&'e str> { None } fn val_delim(&self) -> Option { None } fn takes_value(&self) -> bool { true } fn help(&self) -> Option<&'e str> { self.p.meta.about } - fn default_val(&self) -> Option<&'n str> { None } + fn long_help(&self) -> Option<&'e str> { self.p.meta.long_about } + fn default_val(&self) -> Option<&'e OsStr> { None } + fn default_vals_ifs(&self) -> Option, &'e OsStr)>> { + None + } fn longest_filter(&self) -> bool { true } fn aliases(&self) -> Option> { if let Some(ref aliases) = self.p.meta.aliases { diff --git a/src/vendor/clap/src/app/parser.rs b/src/vendor/clap/src/app/parser.rs index 62348c5058..272231a63e 100644 --- a/src/vendor/clap/src/app/parser.rs +++ b/src/vendor/clap/src/app/parser.rs @@ -1,5 +1,4 @@ // Std -use std::collections::{BTreeMap, HashMap, VecDeque}; use std::ffi::{OsStr, OsString}; use std::fmt::Display; use std::fs::File; @@ -20,98 +19,92 @@ use SubCommand; use app::App; use app::help::Help; use app::meta::AppMeta; -use app::settings::{AppFlags, AppSettings}; +use app::settings::AppFlags; use args::{AnyArg, ArgMatcher, Base, Switched, Arg, ArgGroup, FlagBuilder, OptBuilder, PosBuilder}; -use args::MatchedArg; use args::settings::ArgSettings; use completions::ComplGen; use errors::{Error, ErrorKind}; use errors::Result as ClapResult; -use fmt::{Format, ColorWhen}; +use fmt::ColorWhen; use osstringext::OsStrExt2; use completions::Shell; use suggestions; +use app::settings::AppSettings as AS; +use app::validator::Validator; +use app::usage; + +#[derive(Debug, PartialEq, Copy, Clone)] +#[doc(hidden)] +pub enum ParseResult<'a> { + Flag, + Opt(&'a str), + Pos(&'a str), + MaybeHyphenValue, + MaybeNegNum, + NotFound, + ValuesDone, +} #[allow(missing_debug_implementations)] #[doc(hidden)] +#[derive(Clone, Default)] pub struct Parser<'a, 'b> where 'a: 'b { - required: Vec<&'b str>, - pub short_list: Vec, - pub long_list: Vec<&'b str>, - blacklist: Vec<&'b str>, - // A list of possible flags + pub meta: AppMeta<'b>, + settings: AppFlags, + pub g_settings: AppFlags, pub flags: Vec>, - // A list of possible options pub opts: Vec>, - // A list of positional arguments pub positionals: VecMap>, - // A list of subcommands - #[doc(hidden)] pub subcommands: Vec>, - groups: HashMap<&'a str, ArgGroup<'a>>, - global_args: Vec>, - overrides: Vec<&'b str>, + pub groups: Vec>, + pub global_args: Vec>, + pub required: Vec<&'a str>, + pub r_ifs: Vec<(&'a str, &'b str, &'a str)>, + pub blacklist: Vec<&'b str>, + pub overrides: Vec<&'b str>, help_short: Option, version_short: Option, - settings: AppFlags, - pub g_settings: Vec, - pub meta: AppMeta<'b>, - trailing_vals: bool, - pub id: usize, - valid_neg_num: bool, -} - -impl<'a, 'b> Default for Parser<'a, 'b> { - fn default() -> Self { - Parser { - flags: vec![], - opts: vec![], - positionals: VecMap::new(), - subcommands: vec![], - help_short: None, - version_short: None, - required: vec![], - short_list: vec![], - long_list: vec![], - blacklist: vec![], - groups: HashMap::new(), - global_args: vec![], - overrides: vec![], - g_settings: vec![], - settings: AppFlags::new(), - meta: AppMeta::new(), - trailing_vals: false, - id: 0, - valid_neg_num: false, - } - } + cache: Option<&'a str>, + pub help_message: Option<&'a str>, + pub version_message: Option<&'a str>, } impl<'a, 'b> Parser<'a, 'b> where 'a: 'b { pub fn with_name(n: String) -> Self { - Parser { meta: AppMeta::with_name(n), ..Default::default() } + Parser { + meta: AppMeta::with_name(n), + ..Default::default() + } } pub fn help_short(&mut self, s: &str) { - self.help_short = s.trim_left_matches(|c| c == '-') + let c = s.trim_left_matches(|c| c == '-') .chars() - .nth(0); + .nth(0) + .unwrap_or('h'); + self.help_short = Some(c); } pub fn version_short(&mut self, s: &str) { - self.version_short = s.trim_left_matches(|c| c == '-') + let c = s.trim_left_matches(|c| c == '-') .chars() - .nth(0); + .nth(0) + .unwrap_or('V'); + self.version_short = Some(c); } pub fn gen_completions_to(&mut self, for_shell: Shell, buf: &mut W) { - - self.propogate_help_version(); - self.build_bin_names(); + if !self.is_set(AS::Propogated) { + self.propogate_help_version(); + self.build_bin_names(); + self.propogate_globals(); + self.propogate_settings(); + self.set(AS::Propogated); + } ComplGen::new(self).generate(for_shell, buf) } @@ -135,76 +128,213 @@ impl<'a, 'b> Parser<'a, 'b> self.gen_completions_to(for_shell, &mut file) } - // actually adds the arguments - pub fn add_arg(&mut self, a: &Arg<'a, 'b>) { - debug_assert!(!(self.flags.iter().any(|f| &f.b.name == &a.name) || - self.opts.iter().any(|o| o.b.name == a.name) || - self.positionals.values().any(|p| p.b.name == a.name)), - format!("Non-unique argument name: {} is already in use", a.name)); - if let Some(ref grps) = a.groups { - for g in grps { - let ag = self.groups.entry(g).or_insert_with(|| ArgGroup::with_name(g)); - ag.args.push(a.name); + #[inline] + fn app_debug_asserts(&mut self) -> bool { + assert!(self.verify_positionals()); + let should_err = self.groups + .iter() + .all(|g| { + g.args + .iter() + .all(|arg| { + (self.flags.iter().any(|f| &f.b.name == arg) || + self.opts.iter().any(|o| &o.b.name == arg) || + self.positionals.values().any(|p| &p.b.name == arg) || + self.groups.iter().any(|g| &g.name == arg)) + }) + }); + let g = self.groups + .iter() + .find(|g| { + g.args + .iter() + .any(|arg| { + !(self.flags.iter().any(|f| &f.b.name == arg) || + self.opts.iter().any(|o| &o.b.name == arg) || + self.positionals.values().any(|p| &p.b.name == arg) || + self.groups.iter().any(|g| &g.name == arg)) + }) + }); + assert!(should_err, + "The group '{}' contains the arg '{}' that doesn't actually exist.", + g.unwrap().name, + g.unwrap() + .args + .iter() + .find(|arg| { + !(self.flags.iter().any(|f| &&f.b.name == arg) || + self.opts.iter().any(|o| &&o.b.name == arg) || + self.positionals.values().any(|p| &&p.b.name == arg) || + self.groups.iter().any(|g| &&g.name == arg)) + }) + .unwrap()); + true + } + + #[inline] + fn debug_asserts(&self, a: &Arg) -> bool { + assert!(!arg_names!(self).any(|name| name == a.b.name), + format!("Non-unique argument name: {} is already in use", a.b.name)); + if let Some(l) = a.s.long { + assert!(!self.contains_long(l), + "Argument long must be unique\n\n\t--{} is already in use", + l); + } + if let Some(s) = a.s.short { + assert!(!self.contains_short(s), + "Argument short must be unique\n\n\t-{} is already in use", + s); + } + let i = if a.index.is_none() { + (self.positionals.len() + 1) + } else { + a.index.unwrap() as usize + }; + assert!(!self.positionals.contains_key(i), + "Argument \"{}\" has the same index as another positional \ + argument\n\n\tPerhaps try .multiple(true) to allow one positional argument \ + to take multiple values", + a.b.name); + assert!(!(a.is_set(ArgSettings::Required) && a.is_set(ArgSettings::Global)), + "Global arguments cannot be required.\n\n\t'{}' is marked as \ + global and required", + a.b.name); + if a.b.is_set(ArgSettings::Last) { + assert!(!self.positionals + .values() + .any(|p| p.b.is_set(ArgSettings::Last)), + "Only one positional argument may have last(true) set. Found two."); + assert!(a.s.long.is_none(), + "Flags or Options may not have last(true) set. {} has both a long and last(true) set.", + a.b.name); + assert!(a.s.short.is_none(), + "Flags or Options may not have last(true) set. {} has both a short and last(true) set.", + a.b.name); + } + true + } + + #[inline] + fn add_conditional_reqs(&mut self, a: &Arg<'a, 'b>) { + if let Some(ref r_ifs) = a.r_ifs { + for &(arg, val) in r_ifs { + self.r_ifs.push((arg, val, a.b.name)); } } - if let Some(s) = a.short { - debug_assert!(!self.short_list.contains(&s), - format!("Argument short must be unique\n\n\t-{} is already in use", - s)); - self.short_list.push(s); - } - if let Some(l) = a.long { - debug_assert!(!self.long_list.contains(&l), - format!("Argument long must be unique\n\n\t--{} is already in use", - l)); - self.long_list.push(l); - if l == "help" { - self.unset(AppSettings::NeedsLongHelp); - } else if l == "version" { - self.unset(AppSettings::NeedsLongVersion); + } + + #[inline] + fn add_arg_groups(&mut self, a: &Arg<'a, 'b>) { + if let Some(ref grps) = a.b.groups { + for g in grps { + let mut found = false; + if let Some(ref mut ag) = self.groups.iter_mut().find(|grp| &grp.name == g) { + ag.args.push(a.b.name); + found = true; + } + if !found { + let mut ag = ArgGroup::with_name(g); + ag.args.push(a.b.name); + self.groups.push(ag); + } } } + } + + #[inline] + fn add_reqs(&mut self, a: &Arg<'a, 'b>) { if a.is_set(ArgSettings::Required) { - self.required.push(a.name); + // If the arg is required, add all it's requirements to master required list + if let Some(ref areqs) = a.b.requires { + for name in areqs + .iter() + .filter(|&&(val, _)| val.is_none()) + .map(|&(_, name)| name) { + self.required.push(name); + } + } + self.required.push(a.b.name); + } + } + + #[inline] + fn implied_settings(&mut self, a: &Arg<'a, 'b>) { + if a.is_set(ArgSettings::Last) { + // if an arg has `Last` set, we need to imply DontCollapseArgsInUsage so that args + // in the usage string don't get confused or left out. + self.set(AS::DontCollapseArgsInUsage); + self.set(AS::ContainsLast); + } + if let Some(l) = a.s.long { + if l == "version" { + self.unset(AS::NeedsLongVersion); + } else if l == "help" { + self.unset(AS::NeedsLongHelp); + } } - if a.index.is_some() || (a.short.is_none() && a.long.is_none()) { + } + + // actually adds the arguments + pub fn add_arg(&mut self, a: Arg<'a, 'b>) { + // if it's global we have to clone anyways + if a.is_set(ArgSettings::Global) { + return self.add_arg_ref(&a); + } + debug_assert!(self.debug_asserts(&a)); + self.add_conditional_reqs(&a); + self.add_arg_groups(&a); + self.add_reqs(&a); + self.implied_settings(&a); + if a.index.is_some() || (a.s.short.is_none() && a.s.long.is_none()) { let i = if a.index.is_none() { (self.positionals.len() + 1) } else { a.index.unwrap() as usize }; - debug_assert!(!self.positionals.contains_key(i), - format!("Argument \"{}\" has the same index as another positional \ - argument\n\n\tPerhaps try .multiple(true) to allow one positional argument \ - to take multiple values", - a.name)); - let pb = PosBuilder::from_arg(a, i as u64, &mut self.required); + self.positionals + .insert(i, PosBuilder::from_arg(a, i as u64)); + } else if a.is_set(ArgSettings::TakesValue) { + let mut ob = OptBuilder::from(a); + ob.s.unified_ord = self.flags.len() + self.opts.len(); + self.opts.push(ob); + } else { + let mut fb = FlagBuilder::from(a); + fb.s.unified_ord = self.flags.len() + self.opts.len(); + self.flags.push(fb); + } + } + // actually adds the arguments but from a borrow (which means we have to do some clonine) + pub fn add_arg_ref(&mut self, a: &Arg<'a, 'b>) { + debug_assert!(self.debug_asserts(a)); + self.add_conditional_reqs(a); + self.add_arg_groups(a); + self.add_reqs(a); + self.implied_settings(a); + if a.index.is_some() || (a.s.short.is_none() && a.s.long.is_none()) { + let i = if a.index.is_none() { + (self.positionals.len() + 1) + } else { + a.index.unwrap() as usize + }; + let pb = PosBuilder::from_arg_ref(a, i as u64); self.positionals.insert(i, pb); } else if a.is_set(ArgSettings::TakesValue) { - let mut ob = OptBuilder::from_arg(a, &mut self.required); - let id = self.opts.len(); - ob.b.id = id; + let mut ob = OptBuilder::from(a); ob.s.unified_ord = self.flags.len() + self.opts.len(); - self.opts.insert(id, ob); + self.opts.push(ob); } else { let mut fb = FlagBuilder::from(a); - let id = self.flags.len(); - fb.b.id = id; fb.s.unified_ord = self.flags.len() + self.opts.len(); - self.flags.insert(id, fb); + self.flags.push(fb); } if a.is_set(ArgSettings::Global) { - debug_assert!(!a.is_set(ArgSettings::Required), - format!("Global arguments cannot be required.\n\n\t'{}' is marked as \ - global and required", - a.name)); self.global_args.push(a.into()); } } pub fn add_group(&mut self, group: ArgGroup<'a>) { if group.required { - self.required.push(group.name.into()); + self.required.push(group.name); if let Some(ref reqs) = group.requires { self.required.extend_from_slice(reqs); } @@ -212,56 +342,58 @@ impl<'a, 'b> Parser<'a, 'b> self.blacklist.extend_from_slice(bl); } } - let mut found = false; - if let Some(ref mut grp) = self.groups.get_mut(&group.name) { + if self.groups.iter().any(|g| g.name == group.name) { + let grp = self.groups + .iter_mut() + .find(|g| g.name == group.name) + .expect(INTERNAL_ERROR_MSG); grp.args.extend_from_slice(&group.args); grp.requires = group.requires.clone(); grp.conflicts = group.conflicts.clone(); grp.required = group.required; - found = true; - } - if !found { - self.groups.insert(group.name.into(), group); + } else { + self.groups.push(group); } } pub fn add_subcommand(&mut self, mut subcmd: App<'a, 'b>) { - debugln!("fn=Parser::add_subcommand;"); - debugln!("Term width...{:?}", self.meta.term_w); + debugln!("Parser::add_subcommand: term_w={:?}, name={}", + self.meta.term_w, + subcmd.p.meta.name); subcmd.p.meta.term_w = self.meta.term_w; - debug!("Is help..."); if subcmd.p.meta.name == "help" { - sdebugln!("Yes"); - self.settings.set(AppSettings::NeedsSubcommandHelp); - } else { - sdebugln!("No"); + self.unset(AS::NeedsSubcommandHelp); } self.subcommands.push(subcmd); } pub fn propogate_settings(&mut self) { + debugln!("Parser::propogate_settings: self={}, g_settings={:#?}", + self.meta.name, + self.g_settings); for sc in &mut self.subcommands { + debugln!("Parser::propogate_settings: sc={}, settings={:#?}, g_settings={:#?}", + sc.p.meta.name, + sc.p.settings, + sc.p.g_settings); // We have to create a new scope in order to tell rustc the borrow of `sc` is // done and to recursively call this method { - let vsc = self.settings.is_set(AppSettings::VersionlessSubcommands); - let gv = self.settings.is_set(AppSettings::GlobalVersion); - - debugln!("VersionlessSubcommands set...{:?}", vsc); - debugln!("GlobalVersion set...{:?}", gv); + let vsc = self.settings.is_set(AS::VersionlessSubcommands); + let gv = self.settings.is_set(AS::GlobalVersion); if vsc { - sc.p.settings.set(AppSettings::DisableVersion); + sc.p.set(AS::DisableVersion); } if gv && sc.p.meta.version.is_none() && self.meta.version.is_some() { - sc.p.set(AppSettings::GlobalVersion); + sc.p.set(AS::GlobalVersion); sc.p.meta.version = Some(self.meta.version.unwrap()); } - for s in &self.g_settings { - sc.p.set(*s); - sc.p.g_settings.push(*s); - } + sc.p.settings = sc.p.settings | self.g_settings; + sc.p.g_settings = sc.p.g_settings | self.g_settings; + sc.p.meta.term_w = self.meta.term_w; + sc.p.meta.max_w = self.meta.max_w; } sc.p.propogate_settings(); } @@ -269,24 +401,24 @@ impl<'a, 'b> Parser<'a, 'b> #[cfg_attr(feature = "lints", allow(needless_borrow))] pub fn derive_display_order(&mut self) { - if self.settings.is_set(AppSettings::DeriveDisplayOrder) { - let unified = self.settings.is_set(AppSettings::UnifiedHelpMessage); + if self.is_set(AS::DeriveDisplayOrder) { + let unified = self.is_set(AS::UnifiedHelpMessage); for (i, o) in self.opts - .iter_mut() - .enumerate() - .filter(|&(_, ref o)| o.s.disp_ord == 999) { + .iter_mut() + .enumerate() + .filter(|&(_, ref o)| o.s.disp_ord == 999) { o.s.disp_ord = if unified { o.s.unified_ord } else { i }; } for (i, f) in self.flags - .iter_mut() - .enumerate() - .filter(|&(_, ref f)| f.s.disp_ord == 999) { + .iter_mut() + .enumerate() + .filter(|&(_, ref f)| f.s.disp_ord == 999) { f.s.disp_ord = if unified { f.s.unified_ord } else { i }; } for (i, sc) in &mut self.subcommands - .iter_mut() - .enumerate() - .filter(|&(_, ref sc)| sc.p.meta.disp_ord == 999) { + .iter_mut() + .enumerate() + .filter(|&(_, ref sc)| sc.p.meta.disp_ord == 999) { sc.p.meta.disp_ord = i; } } @@ -297,187 +429,10 @@ impl<'a, 'b> Parser<'a, 'b> pub fn required(&self) -> Iter<&str> { self.required.iter() } - pub fn get_required_from(&self, - reqs: &[&'a str], - matcher: Option<&ArgMatcher<'a>>) - -> VecDeque { - let mut c_flags: Vec<&str> = vec![]; - let mut c_pos: Vec<&str> = vec![]; - let mut c_opt: Vec<&str> = vec![]; - let mut grps: Vec<&str> = vec![]; - for name in reqs { - if self.flags.iter().any(|f| &f.b.name == name) { - c_flags.push(name); - } else if self.opts.iter().any(|o| &o.b.name == name) { - c_opt.push(name); - } else if self.groups.contains_key(name) { - grps.push(name); - } else { - c_pos.push(name); - } - } - macro_rules! fill_vecs { - ($_self:ident { - $t1:ident => $v1:ident => $i1:ident, - $t2:ident => $v2:ident => $i2:ident, - $t3:ident => $v3:ident => $i3:ident, - $gv:ident, $tmp:ident - }) => { - for a in &$v1 { - if let Some(a) = self.$t1.$i1().filter(|arg| &arg.b.name == a).next() { - if let Some(ref rl) = a.b.requires { - for r in rl { - if !reqs.contains(r) { - if $_self.$t1.$i1().any(|t| &t.b.name == r) { - $tmp.push(*r); - } else if $_self.$t2.$i2().any(|t| &t.b.name == r) { - $v2.push(r); - } else if $_self.$t3.$i3().any(|t| &t.b.name == r) { - $v3.push(r); - } else if $_self.groups.contains_key(r) { - $gv.push(r); - } - } - } - } - } - } - $v1.extend(&$tmp); - }; - } - - let mut tmp = vec![]; - fill_vecs!(self { - flags => c_flags => iter, - opts => c_opt => iter, - positionals => c_pos => values, - grps, tmp - }); - tmp.clear(); - fill_vecs!(self { - opts => c_opt => iter, - flags => c_flags => iter, - positionals => c_pos => values, - grps, tmp - }); - tmp.clear(); - fill_vecs!(self { - positionals => c_pos => values, - opts => c_opt => iter, - flags => c_flags => iter, - grps, tmp - }); - let mut ret_val = VecDeque::new(); - c_pos.dedup(); - c_flags.dedup(); - c_opt.dedup(); - grps.dedup(); - let args_in_groups = grps.iter() - .flat_map(|g| self.arg_names_in_group(g)) - .collect::>(); - - let pmap = c_pos.into_iter() - .filter(|&p| matcher.is_none() || !matcher.as_ref().unwrap().contains(p)) - .filter_map(|p| self.positionals.values().find(|x| x.b.name == p)) - .filter(|p| !args_in_groups.contains(&p.b.name)) - .map(|p| (p.index, p)) - .collect::>();// sort by index - debugln!("args_in_groups={:?}", args_in_groups); - for &p in pmap.values() { - let s = p.to_string(); - if args_in_groups.is_empty() || !args_in_groups.contains(&&*s) { - ret_val.push_back(s); - } - } - macro_rules! write_arg { - ($i:expr, $m:ident, $v:ident, $r:ident, $aig:ident) => { - for f in $v { - if $m.is_some() && $m.as_ref().unwrap().contains(f) || $aig.contains(&f) { - continue; - } - $r.push_back($i.filter(|flg| &flg.b.name == &f).next().unwrap().to_string()); - } - } - } - write_arg!(self.flags.iter(), matcher, c_flags, ret_val, args_in_groups); - write_arg!(self.opts.iter(), matcher, c_opt, ret_val, args_in_groups); - let mut g_vec = vec![]; - for g in grps { - let g_string = self.args_in_group(g) - .join("|"); - g_vec.push(format!("<{}>", &g_string[..g_string.len()])); - } - g_vec.dedup(); - for g in g_vec { - ret_val.push_back(g); - } - - ret_val - } - - pub fn get_args_tag(&self) -> Option { - let mut count = 0; - 'outer: for p in self.positionals.values().filter(|p| !p.is_set(ArgSettings::Required)) { - if let Some(g_vec) = self.groups_for_arg(p.b.name) { - for grp_s in &g_vec { - debugln!("iter;grp_s={};", grp_s); - if let Some(grp) = self.groups.get(grp_s) { - debug!("Is group required..."); - if grp.required { - sdebugln!("Yes (continuing)"); - continue 'outer; - } else { - sdebugln!("No (breaking)"); - } - } - } - debugln!("Arg not required..."); - count += 1; - } else { - debugln!("Arg not required..."); - count += 1; - } - } - if count > 1 || self.positionals.len() > 1 { - return None; - } else if count == 1 { - let p = self.positionals.values().next().expect(INTERNAL_ERROR_MSG); - return Some(format!(" [{}]{}", p.name_no_brackets(), p.multiple_str())); - } - Some("".into()) - } - - pub fn needs_flags_tag(&self) -> bool { - debugln!("fn=needs_flags_tag;"); - 'outer: for f in self.flags.iter() { - debugln!("iter;f={};", f.b.name); - if let Some(l) = f.s.long { - if l == "help" || l == "version" { - continue; - } - } - if let Some(g_vec) = self.groups_for_arg(f.b.name) { - for grp_s in &g_vec { - debugln!("iter;grp_s={};", grp_s); - if let Some(grp) = self.groups.get(grp_s) { - debug!("Is group required..."); - if grp.required { - sdebugln!("Yes (continuing)"); - continue 'outer; - } else { - sdebugln!("No (breaking)"); - } - } - } - debugln!("Flag not required...(returning true)"); - return true; - } else { - debugln!("Flag not required...(returning true)"); - return true; - } - } - - false + #[cfg_attr(feature = "lints", allow(needless_borrow))] + #[inline] + pub fn has_args(&self) -> bool { + !(self.flags.is_empty() && self.opts.is_empty() && self.positionals.is_empty()) } #[inline] @@ -493,16 +448,50 @@ impl<'a, 'b> Parser<'a, 'b> pub fn has_subcommands(&self) -> bool { !self.subcommands.is_empty() } #[inline] - pub fn is_set(&self, s: AppSettings) -> bool { self.settings.is_set(s) } + pub fn has_visible_opts(&self) -> bool { + if self.opts.is_empty() { + return false; + } + self.opts.iter().any(|o| !o.is_set(ArgSettings::Hidden)) + } + + #[inline] + pub fn has_visible_flags(&self) -> bool { + if self.flags.is_empty() { + return false; + } + self.flags.iter().any(|f| !f.is_set(ArgSettings::Hidden)) + } + + #[inline] + pub fn has_visible_positionals(&self) -> bool { + if self.positionals.is_empty() { + return false; + } + self.positionals + .values() + .any(|p| !p.is_set(ArgSettings::Hidden)) + } + + #[inline] + pub fn has_visible_subcommands(&self) -> bool { + if self.subcommands.is_empty() { + return false; + } + self.subcommands.iter().any(|s| !s.p.is_set(AS::Hidden)) + } + + #[inline] + pub fn is_set(&self, s: AS) -> bool { self.settings.is_set(s) } #[inline] - pub fn set(&mut self, s: AppSettings) { self.settings.set(s) } + pub fn set(&mut self, s: AS) { self.settings.set(s) } #[inline] - pub fn unset(&mut self, s: AppSettings) { self.settings.unset(s) } + pub fn unset(&mut self, s: AS) { self.settings.unset(s) } #[cfg_attr(feature = "lints", allow(block_in_if_condition_stmt))] - pub fn verify_positionals(&mut self) { + pub fn verify_positionals(&mut self) -> bool { // Because you must wait until all arguments have been supplied, this is the first chance // to make assertions on positional argument indexes // @@ -510,66 +499,117 @@ impl<'a, 'b> Parser<'a, 'b> // positional arguments to verify there are no gaps (i.e. supplying an index of 1 and 3 // but no 2) if let Some((idx, p)) = self.positionals.iter().rev().next() { - debug_assert!(!(idx != self.positionals.len()), - format!("Found positional argument \"{}\" who's index is {} but there are \ - only {} positional arguments defined", - p.b.name, - idx, - self.positionals.len())); + assert!(!(idx != self.positionals.len()), + "Found positional argument \"{}\" whose index is {} but there \ + are only {} positional arguments defined", + p.b.name, + idx, + self.positionals.len()); } // Next we verify that only the highest index has a .multiple(true) (if any) if self.positionals - .values() - .any(|a| { - a.b.settings.is_set(ArgSettings::Multiple) && - (a.index as usize != self.positionals.len()) - }) { - debug_assert!(self.positionals.values() - .filter(|p| p.b.settings.is_set(ArgSettings::Multiple) - && p.v.num_vals.is_none()).map(|_| 1).sum::() <= 1, - "Only one positional argument with .multiple(true) set is allowed per command"); - - debug_assert!(self.positionals.values() - .rev() - .next() - .unwrap() - .is_set(ArgSettings::Required), - "When using a positional argument with .multiple(true) that is *not the last* \ - positional argument, the last positional argument (i.e the one with the highest \ - index) *must* have .required(true) set."); - - debug_assert!({ - let num = self.positionals.len() - 1; - self.positionals.get(num).unwrap().is_set(ArgSettings::Multiple) - }, - "Only the last positional argument, or second to last positional argument may be set to .multiple(true)"); - - self.set(AppSettings::LowIndexMultiplePositional); - } - - debug_assert!(self.positionals.values() - .filter(|p| p.b.settings.is_set(ArgSettings::Multiple) - && p.v.num_vals.is_none()) - .map(|_| 1) - .sum::() <= 1, - "Only one positional argument with .multiple(true) set is allowed per command"); - - // If it's required we also need to ensure all previous positionals are - // required too - let mut found = false; - for p in self.positionals.values().rev() { - if found { - debug_assert!(p.b.settings.is_set(ArgSettings::Required), - "Found positional argument which is not required with a lower index \ - than a required positional argument: {:?} index {}", - p.b.name, - p.index); - } else if p.b.settings.is_set(ArgSettings::Required) { - found = true; - continue; + .values() + .any(|a| { + a.b.is_set(ArgSettings::Multiple) && + (a.index as usize != self.positionals.len()) + }) { + let mut it = self.positionals.values().rev(); + let last = it.next().unwrap(); + let second_to_last = it.next().unwrap(); + // Either the final positional is required + // Or the second to last has a terminator or .last(true) set + let ok = last.is_set(ArgSettings::Required) || + (second_to_last.v.terminator.is_some() || + second_to_last.b.is_set(ArgSettings::Last)) || + last.is_set(ArgSettings::Last); + assert!(ok, + "When using a positional argument with .multiple(true) that is *not the \ + last* positional argument, the last positional argument (i.e the one \ + with the highest index) *must* have .required(true) or .last(true) set."); + let ok = second_to_last.is_set(ArgSettings::Multiple) || last.is_set(ArgSettings::Last); + assert!(ok, + "Only the last positional argument, or second to last positional \ + argument may be set to .multiple(true)"); + + let count = self.positionals + .values() + .filter(|p| p.b.settings.is_set(ArgSettings::Multiple) && p.v.num_vals.is_none()) + .count(); + let ok = count <= 1 || + (last.is_set(ArgSettings::Last) && last.is_set(ArgSettings::Multiple) && + second_to_last.is_set(ArgSettings::Multiple) && + count == 2); + assert!(ok, + "Only one positional argument with .multiple(true) set is allowed per \ + command, unless the second one also has .last(true) set"); + } + + + if self.is_set(AS::AllowMissingPositional) { + // Check that if a required positional argument is found, all positions with a lower + // index are also required. + let mut found = false; + let mut foundx2 = false; + for p in self.positionals.values().rev() { + if foundx2 && !p.b.settings.is_set(ArgSettings::Required) { + assert!(p.b.is_set(ArgSettings::Required), + "Found positional argument which is not required with a lower \ + index than a required positional argument by two or more: {:?} \ + index {}", + p.b.name, + p.index); + } else if p.b.is_set(ArgSettings::Required) && !p.b.is_set(ArgSettings::Last) { + // Args that .last(true) don't count since they can be required and have + // positionals with a lower index that aren't required + // Imagine: prog [opt1] -- + // Both of these are valid invocations: + // $ prog r1 -- r2 + // $ prog r1 o1 -- r2 + if found { + foundx2 = true; + continue; + } + found = true; + continue; + } else { + found = false; + } + } + } else { + // Check that if a required positional argument is found, all positions with a lower + // index are also required + let mut found = false; + for p in self.positionals.values().rev() { + if found { + assert!(p.b.is_set(ArgSettings::Required), + "Found positional argument which is not required with a lower \ + index than a required positional argument: {:?} index {}", + p.b.name, + p.index); + } else if p.b.is_set(ArgSettings::Required) && !p.b.is_set(ArgSettings::Last) { + // Args that .last(true) don't count since they can be required and have + // positionals with a lower index that aren't required + // Imagine: prog [opt1] -- + // Both of these are valid invocations: + // $ prog r1 -- r2 + // $ prog r1 o1 -- r2 + found = true; + continue; + } } } + if self.positionals + .values() + .any(|p| { + p.b.is_set(ArgSettings::Last) && p.b.is_set(ArgSettings::Required) + }) && self.has_subcommands() && + !self.is_set(AS::SubcommandsNegateReqs) { + panic!("Having a required positional argument with .last(true) set *and* child \ + subcommands without setting SubcommandsNegateReqs isn't compatible."); + } + + true } pub fn propogate_globals(&mut self) { @@ -578,7 +618,7 @@ impl<'a, 'b> Parser<'a, 'b> // done and to recursively call this method { for a in &self.global_args { - sc.p.add_arg(a); + sc.p.add_arg_ref(a); } } sc.p.propogate_globals(); @@ -586,29 +626,57 @@ impl<'a, 'b> Parser<'a, 'b> } // Checks if the arg matches a subcommand name, or any of it's aliases (if defined) - #[inline] - fn possible_subcommand(&self, arg_os: &OsStr) -> bool { - debugln!("fn=possible_subcommand"); - self.subcommands - .iter() - .any(|s| { - &s.p.meta.name[..] == &*arg_os || - (s.p.meta.aliases.is_some() && - s.p - .meta - .aliases - .as_ref() - .unwrap() - .iter() - .any(|&(a, _)| a == &*arg_os)) - }) + fn possible_subcommand(&self, arg_os: &OsStr) -> (bool, Option<&str>) { + debugln!("Parser::possible_subcommand: arg={:?}", arg_os); + fn starts(h: &str, n: &OsStr) -> bool { + #[cfg(not(target_os = "windows"))] + use std::os::unix::ffi::OsStrExt; + #[cfg(target_os = "windows")] + use osstringext::OsStrExt3; + + let n_bytes = n.as_bytes(); + let h_bytes = OsStr::new(h).as_bytes(); + + h_bytes.starts_with(n_bytes) + } + + if self.is_set(AS::ArgsNegateSubcommands) && self.is_set(AS::ValidArgFound) { + return (false, None); + } + if !self.is_set(AS::InferSubcommands) { + if let Some(sc) = find_subcmd!(self, arg_os) { + return (true, Some(&sc.p.meta.name)); + } + } else { + let v = self.subcommands + .iter() + .filter(|s| { + starts(&s.p.meta.name[..], &*arg_os) || + (s.p.meta.aliases.is_some() && + s.p + .meta + .aliases + .as_ref() + .unwrap() + .iter() + .filter(|&&(a, _)| starts(a, &*arg_os)) + .count() == 1) + }) + .map(|sc| &sc.p.meta.name) + .collect::>(); + + if v.len() == 1 { + return (true, Some(v[0])); + } + } + (false, None) } - fn parse_help_subcommand(&self, it: &mut I) -> ClapResult<()> + fn parse_help_subcommand(&self, it: &mut I) -> ClapResult> where I: Iterator, T: Into { - debugln!("fn=parse_help_subcommand;"); + debugln!("Parser::parse_help_subcommand;"); let cmds: Vec = it.map(|c| c.into()).collect(); let mut help_help = false; let mut bin_name = self.meta @@ -624,24 +692,21 @@ impl<'a, 'b> Parser<'a, 'b> help_help = true; } if let Some(c) = sc.subcommands - .iter() - .find(|s| &*s.p.meta.name == cmd) - .map(|sc| &sc.p) { + .iter() + .find(|s| &*s.p.meta.name == cmd) + .map(|sc| &sc.p) { sc = c; if i == cmds.len() - 1 { break; } } else if let Some(c) = sc.subcommands - .iter() - .find(|s| if let Some(ref als) = s.p - .meta - .aliases { - als.iter() - .any(|&(a, _)| &a == &&*cmd.to_string_lossy()) - } else { - false - }) - .map(|sc| &sc.p) { + .iter() + .find(|s| if let Some(ref als) = s.p.meta.aliases { + als.iter().any(|&(a, _)| a == &*cmd.to_string_lossy()) + } else { + false + }) + .map(|sc| &sc.p) { sc = c; if i == cmds.len() - 1 { break; @@ -654,9 +719,7 @@ impl<'a, 'b> Parser<'a, 'b> .unwrap_or(&self.meta.name), self.color())); } - bin_name = format!("{} {}", - bin_name, - &*sc.meta.name); + bin_name = format!("{} {}", bin_name, &*sc.meta.name); } sc.clone() }; @@ -665,27 +728,28 @@ impl<'a, 'b> Parser<'a, 'b> pb.b.help = Some("The subcommand whose help message to display"); pb.set(ArgSettings::Multiple); sc.positionals.insert(1, pb); - for s in self.g_settings.clone() { - sc.set(s); - } + sc.settings = sc.settings | self.g_settings; } else { sc.create_help_and_version(); } if sc.meta.bin_name != self.meta.bin_name { sc.meta.bin_name = Some(format!("{} {}", bin_name, sc.meta.name)); } - sc._help() + Err(sc._help(false)) } - #[inline] - fn check_is_new_arg(&mut self, arg_os: &OsStr, needs_val_of: Option<&'a str>) -> bool { - debugln!("fn=check_is_new_arg;nvo={:?}", needs_val_of); - let app_wide_settings = if self.is_set(AppSettings::AllowLeadingHyphen) { + // allow wrong self convention due to self.valid_neg_num = true and it's a private method + #[cfg_attr(feature = "lints", allow(wrong_self_convention))] + fn is_new_arg(&mut self, arg_os: &OsStr, needs_val_of: ParseResult<'a>) -> bool { + debugln!("Parser::is_new_arg: arg={:?}, Needs Val of={:?}", + arg_os, + needs_val_of); + let app_wide_settings = if self.is_set(AS::AllowLeadingHyphen) { true - } else if self.is_set(AppSettings::AllowNegativeNumbers) { + } else if self.is_set(AS::AllowNegativeNumbers) { let a = arg_os.to_string_lossy(); if a.parse::().is_ok() || a.parse::().is_ok() { - self.valid_neg_num = true; + self.set(AS::ValidNegNumFound); true } else { false @@ -693,44 +757,52 @@ impl<'a, 'b> Parser<'a, 'b> } else { false }; - let arg_allows_tac = if let Some(name) = needs_val_of { - if let Some(o) = find_by_name!(self, &name, opts, iter) { - !(o.is_set(ArgSettings::AllowLeadingHyphen) || app_wide_settings) - } else if let Some(p) = find_by_name!(self, &name, opts, iter) { - !(p.is_set(ArgSettings::AllowLeadingHyphen) || app_wide_settings) - } else { - true + let arg_allows_tac = match needs_val_of { + ParseResult::Opt(name) => { + let o = self.opts + .iter() + .find(|o| o.b.name == name) + .expect(INTERNAL_ERROR_MSG); + (o.is_set(ArgSettings::AllowLeadingHyphen) || app_wide_settings) } - } else { - true + ParseResult::Pos(name) => { + let p = self.positionals + .values() + .find(|p| p.b.name == name) + .expect(INTERNAL_ERROR_MSG); + (p.is_set(ArgSettings::AllowLeadingHyphen) || app_wide_settings) + } + _ => false, }; - debugln!("Does arg allow leading hyphen...{:?}", !arg_allows_tac); + debugln!("Parser::is_new_arg: Arg::allow_leading_hyphen({:?})", + arg_allows_tac); // Is this a new argument, or values from a previous option? - debug!("Starts new arg..."); let mut ret = if arg_os.starts_with(b"--") { - sdebugln!("--"); - if arg_os.len_() == 2 { + debugln!("Parser::is_new_arg: -- found"); + if arg_os.len_() == 2 && !arg_allows_tac { return true; // We have to return true so override everything else + } else if arg_allows_tac { + return false; } true } else if arg_os.starts_with(b"-") { - sdebugln!("-"); + debugln!("Parser::is_new_arg: - found"); // a singe '-' by itself is a value and typically means "stdin" on unix systems !(arg_os.len_() == 1) } else { - sdebugln!("Probable value"); + debugln!("Parser::is_new_arg: probably value"); false }; - ret = ret && arg_allows_tac; + ret = ret && !arg_allows_tac; - debugln!("Starts new arg...{:?}", ret); + debugln!("Parser::is_new_arg: starts_new_arg={:?}", ret); ret } // The actual parsing function - #[cfg_attr(feature = "lints", allow(while_let_on_iterator))] + #[cfg_attr(feature = "lints", allow(while_let_on_iterator, collapsible_if))] pub fn get_matches_with(&mut self, matcher: &mut ArgMatcher<'a>, it: &mut Peekable) @@ -738,54 +810,84 @@ impl<'a, 'b> Parser<'a, 'b> where I: Iterator, T: Into + Clone { - debugln!("fn=get_matches_with;"); + debugln!("Parser::get_matches_with;"); // Verify all positional assertions pass - self.verify_positionals(); + debug_assert!(self.app_debug_asserts()); + if self.positionals + .values() + .any(|a| { + a.b.is_set(ArgSettings::Multiple) && + (a.index as usize != self.positionals.len()) + }) && + self.positionals + .values() + .last() + .map_or(false, |p| !p.is_set(ArgSettings::Last)) { + self.settings.set(AS::LowIndexMultiplePositional); + } + let has_args = self.has_args(); // Next we create the `--help` and `--version` arguments and add them if // necessary self.create_help_and_version(); let mut subcmd_name: Option = None; - let mut needs_val_of: Option<&'a str> = None; + let mut needs_val_of: ParseResult<'a> = ParseResult::NotFound; let mut pos_counter = 1; while let Some(arg) = it.next() { let arg_os = arg.into(); - debugln!("Begin parsing '{:?}' ({:?})", arg_os, &*arg_os.as_bytes()); + debugln!("Parser::get_matches_with: Begin parsing '{:?}' ({:?})", + arg_os, + &*arg_os.as_bytes()); - self.valid_neg_num = false; + self.unset(AS::ValidNegNumFound); // Is this a new argument, or values from a previous option? - let starts_new_arg = self.check_is_new_arg(&arg_os, needs_val_of); + let starts_new_arg = self.is_new_arg(&arg_os, needs_val_of); + if arg_os.starts_with(b"--") && arg_os.len_() == 2 && starts_new_arg { + debugln!("Parser::get_matches_with: setting TrailingVals=true"); + self.set(AS::TrailingValues); + continue; + } // Has the user already passed '--'? Meaning only positional args follow - if !self.trailing_vals { + if !self.is_set(AS::TrailingValues) { // Does the arg match a subcommand name, or any of it's aliases (if defined) - let pos_sc = self.possible_subcommand(&arg_os); - - // If the arg doesn't start with a `-` (except numbers, or AllowLeadingHyphen) and - // isn't a subcommand - if !starts_new_arg && !pos_sc { - // Check to see if parsing a value from an option - if let Some(name) = needs_val_of { - // get the OptBuilder so we can check the settings - if let Some(arg) = find_by_name!(self, &name, opts, iter) { - needs_val_of = try!(self.add_val_to_arg(&*arg, &arg_os, matcher)); - // get the next value from the iterator - continue; + { + let (is_match, sc_name) = self.possible_subcommand(&arg_os); + debugln!("Parser::get_matches_with: possible_sc={:?}, sc={:?}", + is_match, + sc_name); + if is_match { + let sc_name = sc_name.expect(INTERNAL_ERROR_MSG); + if sc_name == "help" && self.is_set(AS::NeedsSubcommandHelp) { + try!(self.parse_help_subcommand(it)); } + subcmd_name = Some(sc_name.to_owned()); + break; } } - if arg_os.starts_with(b"--") { - if arg_os.len_() == 2 { - // The user has passed '--' which means only positional args follow no - // matter what they start with - self.trailing_vals = true; - continue; - } + if !starts_new_arg { + if let ParseResult::Opt(name) = needs_val_of { + // Check to see if parsing a value from a previous arg + let arg = self.opts + .iter() + .find(|o| o.b.name == name) + .expect(INTERNAL_ERROR_MSG); + // get the OptBuilder so we can check the settings + needs_val_of = try!(self.add_val_to_arg(arg, &arg_os, matcher)); + // get the next value from the iterator + continue; + } + } else if arg_os.starts_with(b"--") { needs_val_of = try!(self.parse_long_arg(matcher, &arg_os)); - if !(needs_val_of.is_none() && self.is_set(AppSettings::AllowLeadingHyphen)) { - continue; + debugln!("Parser:get_matches_with: After parse_long_arg {:?}", + needs_val_of); + match needs_val_of { + ParseResult::Flag | + ParseResult::Opt(..) | + ParseResult::ValuesDone => continue, + _ => (), } } else if arg_os.starts_with(b"-") && arg_os.len_() != 1 { // Try to parse short args like normal, if AllowLeadingHyphen or @@ -793,77 +895,103 @@ impl<'a, 'b> Parser<'a, 'b> // an error, and instead return Ok(None) needs_val_of = try!(self.parse_short_arg(matcher, &arg_os)); // If it's None, we then check if one of those two AppSettings was set - if needs_val_of.is_none() { - if self.is_set(AppSettings::AllowNegativeNumbers) { + debugln!("Parser:get_matches_with: After parse_short_arg {:?}", + needs_val_of); + match needs_val_of { + ParseResult::MaybeNegNum => { if !(arg_os.to_string_lossy().parse::().is_ok() || arg_os.to_string_lossy().parse::().is_ok()) { return Err(Error::unknown_argument(&*arg_os.to_string_lossy(), - "", - &*self.create_current_usage(matcher), - self.color())); + "", + &*usage::create_error_usage(self, matcher, None), + self.color())); } - } else if !self.is_set(AppSettings::AllowLeadingHyphen) { - continue; } - } else { - continue; + ParseResult::Opt(..) | + ParseResult::Flag | + ParseResult::ValuesDone => continue, + _ => (), } } - if pos_sc { - if &*arg_os == "help" && self.is_set(AppSettings::NeedsSubcommandHelp) { - try!(self.parse_help_subcommand(it)); + if !(self.is_set(AS::ArgsNegateSubcommands) && self.is_set(AS::ValidArgFound)) && + !self.is_set(AS::InferSubcommands) { + if let Some(cdate) = suggestions::did_you_mean(&*arg_os.to_string_lossy(), + sc_names!(self)) { + return Err(Error::invalid_subcommand(arg_os + .to_string_lossy() + .into_owned(), + cdate, + self.meta + .bin_name + .as_ref() + .unwrap_or(&self.meta.name), + &*usage::create_error_usage(self, + matcher, + None), + self.color())); } - subcmd_name = Some(arg_os.to_str().expect(INVALID_UTF8).to_owned()); - break; - } else if let Some(cdate) = - suggestions::did_you_mean(&*arg_os.to_string_lossy(), - self.subcommands - .iter() - .map(|s| &s.p.meta.name)) { - return Err(Error::invalid_subcommand(arg_os.to_string_lossy().into_owned(), - cdate, - self.meta - .bin_name - .as_ref() - .unwrap_or(&self.meta.name), - &*self.create_current_usage(matcher), - self.color())); } } - debugln!("Positional counter...{}", pos_counter); - debug!("Checking for low index multiples..."); - if self.is_set(AppSettings::LowIndexMultiplePositional) && - pos_counter == (self.positionals.len() - 1) { - sdebugln!("Found"); + let low_index_mults = self.is_set(AS::LowIndexMultiplePositional) && + pos_counter == (self.positionals.len() - 1); + let missing_pos = self.is_set(AS::AllowMissingPositional) && + pos_counter == (self.positionals.len() - 1); + debugln!("Parser::get_matches_with: Positional counter...{}", + pos_counter); + debugln!("Parser::get_matches_with: Low index multiples...{:?}", + low_index_mults); + if low_index_mults || missing_pos { if let Some(na) = it.peek() { let n = (*na).clone().into(); - if self.check_is_new_arg(&n, needs_val_of) || self.possible_subcommand(&n) || - suggestions::did_you_mean(&n.to_string_lossy(), - self.subcommands - .iter() - .map(|s| &s.p.meta.name)) - .is_some() { - debugln!("Bumping the positional counter..."); + needs_val_of = if needs_val_of != ParseResult::ValuesDone { + if let Some(p) = self.positionals.get(pos_counter) { + ParseResult::Pos(p.b.name) + } else { + ParseResult::ValuesDone + } + } else { + ParseResult::ValuesDone + }; + let sc_match = { + self.possible_subcommand(&n).0 + }; + if self.is_new_arg(&n, needs_val_of) || sc_match || + suggestions::did_you_mean(&n.to_string_lossy(), sc_names!(self)).is_some() { + debugln!("Parser::get_matches_with: Bumping the positional counter..."); pos_counter += 1; } } else { - debugln!("Bumping the positional counter..."); + debugln!("Parser::get_matches_with: Bumping the positional counter..."); pos_counter += 1; } - } else { - sdebugln!("None"); + } else if self.is_set(AS::ContainsLast) && self.is_set(AS::TrailingValues) { + // Came to -- and one postional has .last(true) set, so we go immediately + // to the last (highest index) positional + debugln!("Parser::get_matches_with: .last(true) and --, setting last pos"); + pos_counter = self.positionals.len(); } if let Some(p) = self.positionals.get(pos_counter) { + if p.is_set(ArgSettings::Last) && !self.is_set(AS::TrailingValues) { + return Err(Error::unknown_argument(&*arg_os.to_string_lossy(), + "", + &*usage::create_error_usage(self, + matcher, + None), + self.color())); + } parse_positional!(self, p, arg_os, pos_counter, matcher); - } else if self.settings.is_set(AppSettings::AllowExternalSubcommands) { + self.settings.set(AS::ValidArgFound); + } else if self.is_set(AS::AllowExternalSubcommands) { // Get external subcommand name let sc_name = match arg_os.to_str() { Some(s) => s.to_string(), None => { - if !self.settings.is_set(AppSettings::StrictUtf8) { - return Err(Error::invalid_utf8(&*self.create_current_usage(matcher), + if !self.is_set(AS::StrictUtf8) { + return Err(Error::invalid_utf8(&*usage::create_error_usage(self, + matcher, + None), self.color())); } arg_os.to_string_lossy().into_owned() @@ -874,115 +1002,86 @@ impl<'a, 'b> Parser<'a, 'b> let mut sc_m = ArgMatcher::new(); while let Some(v) = it.next() { let a = v.into(); - if a.to_str().is_none() && !self.settings.is_set(AppSettings::StrictUtf8) { - return Err(Error::invalid_utf8(&*self.create_current_usage(matcher), + if a.to_str().is_none() && !self.is_set(AS::StrictUtf8) { + return Err(Error::invalid_utf8(&*usage::create_error_usage(self, + matcher, + None), self.color())); } sc_m.add_val_to("", &a); } matcher.subcommand(SubCommand { - name: sc_name, - matches: sc_m.into(), - }); - } else if !(self.is_set(AppSettings::AllowLeadingHyphen) || - self.is_set(AppSettings::AllowNegativeNumbers)) { + name: sc_name, + matches: sc_m.into(), + }); + } else if !(self.is_set(AS::AllowLeadingHyphen) || + self.is_set(AS::AllowNegativeNumbers)) && + !self.is_set(AS::InferSubcommands) { return Err(Error::unknown_argument(&*arg_os.to_string_lossy(), "", - &*self.create_current_usage(matcher), + &*usage::create_error_usage(self, + matcher, + None), self.color())); + } else if !has_args || self.is_set(AS::InferSubcommands) && self.has_subcommands() { + if let Some(cdate) = suggestions::did_you_mean(&*arg_os.to_string_lossy(), + sc_names!(self)) { + return Err(Error::invalid_subcommand(arg_os.to_string_lossy().into_owned(), + cdate, + self.meta + .bin_name + .as_ref() + .unwrap_or(&self.meta.name), + &*usage::create_error_usage(self, + matcher, + None), + self.color())); + } else { + return Err(Error::unrecognized_subcommand(arg_os + .to_string_lossy() + .into_owned(), + self.meta + .bin_name + .as_ref() + .unwrap_or(&self.meta.name), + self.color())); + } } } if let Some(ref pos_sc_name) = subcmd_name { - // is this is a real subcommand, or an alias - if self.subcommands.iter().any(|sc| &sc.p.meta.name == pos_sc_name) { - - try!(self.parse_subcommand(&*pos_sc_name, matcher, it)); - } else { - let sc_name = &*self.subcommands - .iter() - .filter(|sc| sc.p.meta.aliases.is_some()) - .filter_map(|sc| if sc.p - .meta - .aliases - .as_ref() - .unwrap() - .iter() - .any(|&(a, _)| &a == &&*pos_sc_name) { - Some(sc.p.meta.name.clone()) - } else { - None - }) - .next() - .expect(INTERNAL_ERROR_MSG); - try!(self.parse_subcommand(sc_name, matcher, it)); + let sc_name = { + find_subcmd!(self, pos_sc_name) + .expect(INTERNAL_ERROR_MSG) + .p + .meta + .name + .clone() }; - } else if self.is_set(AppSettings::SubcommandRequired) { + try!(self.parse_subcommand(&*sc_name, matcher, it)); + } else if self.is_set(AS::SubcommandRequired) { let bn = self.meta.bin_name.as_ref().unwrap_or(&self.meta.name); return Err(Error::missing_subcommand(bn, - &self.create_current_usage(matcher), + &usage::create_error_usage(self, matcher, None), self.color())); - } else if self.is_set(AppSettings::SubcommandRequiredElseHelp) { + } else if self.is_set(AS::SubcommandRequiredElseHelp) { + debugln!("Parser::get_matches_with: SubcommandRequiredElseHelp=true"); let mut out = vec![]; try!(self.write_help_err(&mut out)); return Err(Error { - message: String::from_utf8_lossy(&*out).into_owned(), - kind: ErrorKind::MissingArgumentOrSubcommand, - info: None, - }); + message: String::from_utf8_lossy(&*out).into_owned(), + kind: ErrorKind::MissingArgumentOrSubcommand, + info: None, + }); } - self.validate(needs_val_of, subcmd_name, matcher) + Validator::new(self).validate(needs_val_of, subcmd_name, matcher) } - fn validate(&mut self, - needs_val_of: Option<&'a str>, - subcmd_name: Option, - matcher: &mut ArgMatcher<'a>) - -> ClapResult<()> { - let mut reqs_validated = false; - if let Some(a) = needs_val_of { - debugln!("needs_val_of={:?}", a); - let o = find_by_name!(self, &a, opts, iter).expect(INTERNAL_ERROR_MSG); - try!(self.validate_required(matcher)); - reqs_validated = true; - let should_err = if let Some(v) = matcher.0.args.get(&*o.b.name) { - v.vals.is_empty() && !(o.v.min_vals.is_some() && o.v.min_vals.unwrap() == 0) - } else { - true - }; - if should_err { - return Err(Error::empty_value(o, - &*self.create_current_usage(matcher), - self.color())); - } - } - - try!(self.add_defaults(matcher)); - try!(self.validate_blacklist(matcher)); - try!(self.validate_num_args(matcher)); - matcher.usage(self.create_usage(&[])); - - if !(self.settings.is_set(AppSettings::SubcommandsNegateReqs) && subcmd_name.is_some()) && - !reqs_validated { - try!(self.validate_required(matcher)); - } - if matcher.is_empty() && matcher.subcommand_name().is_none() && - self.is_set(AppSettings::ArgRequiredElseHelp) { - let mut out = vec![]; - try!(self.write_help_err(&mut out)); - return Err(Error { - message: String::from_utf8_lossy(&*out).into_owned(), - kind: ErrorKind::MissingArgumentOrSubcommand, - info: None, - }); - } - Ok(()) - } fn propogate_help_version(&mut self) { - debugln!("fn=propogate_help_version;"); + debugln!("Parser::propogate_help_version;"); self.create_help_and_version(); for sc in &mut self.subcommands { sc.p.propogate_help_version(); @@ -990,28 +1089,31 @@ impl<'a, 'b> Parser<'a, 'b> } fn build_bin_names(&mut self) { - debugln!("fn=build_bin_names;"); + debugln!("Parser::build_bin_names;"); for sc in &mut self.subcommands { - debug!("bin_name set..."); + debug!("Parser::build_bin_names:iter: bin_name set..."); if sc.p.meta.bin_name.is_none() { sdebugln!("No"); let bin_name = format!("{}{}{}", - self.meta - .bin_name - .as_ref() - .unwrap_or(&self.meta.name.clone()), - if self.meta.bin_name.is_some() { - " " - } else { - "" - }, - &*sc.p.meta.name); - debugln!("Setting bin_name of {} to {}", self.meta.name, bin_name); + self.meta + .bin_name + .as_ref() + .unwrap_or(&self.meta.name.clone()), + if self.meta.bin_name.is_some() { + " " + } else { + "" + }, + &*sc.p.meta.name); + debugln!("Parser::build_bin_names:iter: Setting bin_name of {} to {}", + self.meta.name, + bin_name); sc.p.meta.bin_name = Some(bin_name); } else { sdebugln!("yes ({:?})", sc.p.meta.bin_name); } - debugln!("Calling build_bin_names from...{}", sc.p.meta.name); + debugln!("Parser::build_bin_names:iter: Calling build_bin_names from...{}", + sc.p.meta.name); sc.p.build_bin_names(); } } @@ -1025,14 +1127,14 @@ impl<'a, 'b> Parser<'a, 'b> T: Into + Clone { use std::fmt::Write; - debugln!("fn=parse_subcommand;"); + debugln!("Parser::parse_subcommand;"); let mut mid_string = String::new(); - if !self.settings.is_set(AppSettings::SubcommandsNegateReqs) { + if !self.is_set(AS::SubcommandsNegateReqs) { let mut hs: Vec<&str> = self.required.iter().map(|n| &**n).collect(); for k in matcher.arg_names() { hs.push(k); } - let reqs = self.get_required_from(&hs, Some(matcher)); + let reqs = usage::get_required_usage_from(self, &hs, Some(matcher), None, false); for s in &reqs { write!(&mut mid_string, " {}", s).expect(INTERNAL_ERROR_MSG); @@ -1040,8 +1142,8 @@ impl<'a, 'b> Parser<'a, 'b> } mid_string.push_str(" "); if let Some(ref mut sc) = self.subcommands - .iter_mut() - .find(|s| &s.p.meta.name == &sc_name) { + .iter_mut() + .find(|s| s.p.meta.name == sc_name) { let mut sc_matcher = ArgMatcher::new(); // bin_name should be parent's bin_name + [] + the sc's name separated by // a space @@ -1053,41 +1155,41 @@ impl<'a, 'b> Parser<'a, 'b> "" }, &*sc.p.meta.name)); - sc.p.meta.bin_name = Some(format!("{}{}{}", - self.meta - .bin_name - .as_ref() - .unwrap_or(&String::new()), - if self.meta.bin_name.is_some() { - " " - } else { - "" - }, - &*sc.p.meta.name)); + sc.p.meta.bin_name = + Some(format!("{}{}{}", + self.meta.bin_name.as_ref().unwrap_or(&String::new()), + if self.meta.bin_name.is_some() { + " " + } else { + "" + }, + &*sc.p.meta.name)); + debugln!("Parser::parse_subcommand: About to parse sc={}", + sc.p.meta.name); + debugln!("Parser::parse_subcommand: sc settings={:#?}", sc.p.settings); try!(sc.p.get_matches_with(&mut sc_matcher, it)); matcher.subcommand(SubCommand { - name: sc.p.meta.name.clone(), - matches: sc_matcher.into(), - }); + name: sc.p.meta.name.clone(), + matches: sc_matcher.into(), + }); } Ok(()) } - - fn groups_for_arg(&self, name: &str) -> Option> { - debugln!("fn=groups_for_arg; name={}", name); + pub fn groups_for_arg(&self, name: &str) -> Option> { + debugln!("Parser::groups_for_arg: name={}", name); if self.groups.is_empty() { - debugln!("No groups defined"); + debugln!("Parser::groups_for_arg: No groups defined"); return None; } let mut res = vec![]; - debugln!("Searching through groups..."); - for (gn, grp) in &self.groups { + debugln!("Parser::groups_for_arg: Searching through groups..."); + for grp in &self.groups { for a in &grp.args { if a == &name { - sdebugln!("\tFound '{}'", gn); - res.push(*gn); + sdebugln!("\tFound '{}'", grp.name); + res.push(&*grp.name); } } } @@ -1098,21 +1200,23 @@ impl<'a, 'b> Parser<'a, 'b> Some(res) } - fn args_in_group(&self, group: &str) -> Vec { + pub fn args_in_group(&self, group: &str) -> Vec { let mut g_vec = vec![]; let mut args = vec![]; - for n in &self.groups[group].args { + for n in &self.groups + .iter() + .find(|g| g.name == group) + .expect(INTERNAL_ERROR_MSG) + .args { if let Some(f) = self.flags.iter().find(|f| &f.b.name == n) { args.push(f.to_string()); } else if let Some(f) = self.opts.iter().find(|o| &o.b.name == n) { args.push(f.to_string()); - } else if self.groups.contains_key(&**n) { - g_vec.push(*n); - } else if let Some(p) = self.positionals - .values() - .find(|p| &p.b.name == n) { + } else if let Some(p) = self.positionals.values().find(|p| &p.b.name == n) { args.push(p.b.name.to_owned()); + } else { + g_vec.push(*n); } } @@ -1123,39 +1227,38 @@ impl<'a, 'b> Parser<'a, 'b> args.iter().map(ToOwned::to_owned).collect() } - fn arg_names_in_group(&self, group: &str) -> Vec<&'a str> { + pub fn arg_names_in_group(&self, group: &str) -> Vec<&'a str> { let mut g_vec = vec![]; let mut args = vec![]; - for n in &self.groups[group].args { - if self.groups.contains_key(&*n) { + for n in &self.groups + .iter() + .find(|g| g.name == group) + .expect(INTERNAL_ERROR_MSG) + .args { + if self.groups.iter().any(|g| g.name == *n) { + args.extend(self.arg_names_in_group(n)); g_vec.push(*n); - } else { + } else if !args.contains(n) { args.push(*n); } } - for av in g_vec.iter().map(|g| self.arg_names_in_group(g)) { - args.extend(av); - } - args.dedup(); args.iter().map(|s| *s).collect() } pub fn create_help_and_version(&mut self) { - debugln!("fn=create_help_and_version;"); + debugln!("Parser::create_help_and_version;"); // name is "hclap_help" because flags are sorted by name - if self.is_set(AppSettings::NeedsLongHelp) { - debugln!("Building --help"); - if self.help_short.is_none() && !self.short_list.contains(&'h') { + if !self.contains_long("help") { + debugln!("Parser::create_help_and_version: Building --help"); + if self.help_short.is_none() && !self.contains_short('h') { self.help_short = Some('h'); } - let id = self.flags.len(); let arg = FlagBuilder { b: Base { name: "hclap_help", - help: Some("Prints help information"), - id: id, + help: self.help_message.or(Some("Prints help information")), ..Default::default() }, s: Switched { @@ -1164,25 +1267,18 @@ impl<'a, 'b> Parser<'a, 'b> ..Default::default() }, }; - if let Some(h) = self.help_short { - self.short_list.push(h); - } - self.long_list.push("help"); - self.flags.insert(id, arg); + self.flags.push(arg); } - if !self.settings.is_set(AppSettings::DisableVersion) && - self.is_set(AppSettings::NeedsLongVersion) { - debugln!("Building --version"); - if self.version_short.is_none() && !self.short_list.contains(&'V') { + if !self.is_set(AS::DisableVersion) && !self.contains_long("version") { + debugln!("Parser::create_help_and_version: Building --version"); + if self.version_short.is_none() && !self.contains_short('V') { self.version_short = Some('V'); } - let id = self.flags.len(); // name is "vclap_version" because flags are sorted by name let arg = FlagBuilder { b: Base { name: "vclap_version", - help: Some("Prints version information"), - id: id, + help: self.version_message.or(Some("Prints version information")), ..Default::default() }, s: Switched { @@ -1191,48 +1287,30 @@ impl<'a, 'b> Parser<'a, 'b> ..Default::default() }, }; - if let Some(v) = self.version_short { - self.short_list.push(v); - } - self.long_list.push("version"); - self.flags.insert(id, arg); + self.flags.push(arg); } - if !self.subcommands.is_empty() && self.is_set(AppSettings::NeedsSubcommandHelp) { - debugln!("Building help"); + if !self.subcommands.is_empty() && !self.is_set(AS::DisableHelpSubcommand) && + self.is_set(AS::NeedsSubcommandHelp) { + debugln!("Parser::create_help_and_version: Building help"); self.subcommands .push(App::new("help") - .about("Prints this message or the help of the given subcommand(s)")); + .about("Prints this message or the help of the given subcommand(s)")); } } // Retrieves the names of all args the user has supplied thus far, except required ones // because those will be listed in self.required - pub fn create_current_usage(&self, matcher: &'b ArgMatcher<'a>) -> String { - self.create_usage(&*matcher.arg_names() - .iter() - .filter(|n| { - if let Some(o) = find_by_name!(self, *n, opts, iter) { - !o.b.settings.is_set(ArgSettings::Required) - } else if let Some(p) = find_by_name!(self, *n, positionals, values) { - !p.b.settings.is_set(ArgSettings::Required) - } else { - true // flags can't be required, so they're always true - } - }) - .map(|&n| n) - .collect::>()) - } - fn check_for_help_and_version_str(&self, arg: &OsStr) -> ClapResult<()> { - debug!("Checking if --{} is help or version...", + debugln!("Parser::check_for_help_and_version_str;"); + debug!("Parser::check_for_help_and_version_str: Checking if --{} is help or version...", arg.to_str().unwrap()); - if arg == "help" && self.settings.is_set(AppSettings::NeedsLongHelp) { + if arg == "help" && self.is_set(AS::NeedsLongHelp) { sdebugln!("Help"); - try!(self._help()); + return Err(self._help(true)); } - if arg == "version" && self.settings.is_set(AppSettings::NeedsLongVersion) { + if arg == "version" && self.is_set(AS::NeedsLongVersion) { sdebugln!("Version"); - try!(self._version()); + return Err(self._version(true)); } sdebugln!("Neither"); @@ -1240,52 +1318,73 @@ impl<'a, 'b> Parser<'a, 'b> } fn check_for_help_and_version_char(&self, arg: char) -> ClapResult<()> { - debug!("Checking if -{} is help or version...", arg); + debugln!("Parser::check_for_help_and_version_char;"); + debug!("Parser::check_for_help_and_version_char: Checking if -{} is help or version...", + arg); if let Some(h) = self.help_short { - if arg == h && self.settings.is_set(AppSettings::NeedsLongHelp) { + if arg == h && self.is_set(AS::NeedsLongHelp) { sdebugln!("Help"); - try!(self._help()); + return Err(self._help(false)); } } if let Some(v) = self.version_short { - if arg == v && self.settings.is_set(AppSettings::NeedsLongVersion) { + if arg == v && self.is_set(AS::NeedsLongVersion) { sdebugln!("Version"); - try!(self._version()); + return Err(self._version(false)); } } sdebugln!("Neither"); Ok(()) } - fn _help(&self) -> ClapResult<()> { + #[cfg_attr(feature = "cargo-clippy", allow(let_and_return))] + fn use_long_help(&self) -> bool { + let ul = self.flags.iter().any(|f| f.b.long_help.is_some()) || + self.opts.iter().any(|o| o.b.long_help.is_some()) || + self.positionals.values().any(|p| p.b.long_help.is_some()) || + self.subcommands + .iter() + .any(|s| s.p.meta.long_about.is_some()); + debugln!("Parser::use_long_help: ret={:?}", ul); + ul + } + + fn _help(&self, mut use_long: bool) -> Error { + debugln!("Parser::_help: use_long={:?}", use_long); + use_long = use_long && self.use_long_help(); let mut buf = vec![]; - try!(Help::write_parser_help(&mut buf, self)); - Err(Error { - message: unsafe { String::from_utf8_unchecked(buf) }, - kind: ErrorKind::HelpDisplayed, - info: None, - }) + match Help::write_parser_help(&mut buf, self, use_long) { + Err(e) => e, + _ => Error { + message: unsafe { String::from_utf8_unchecked(buf) }, + kind: ErrorKind::HelpDisplayed, + info: None, + } + } } - fn _version(&self) -> ClapResult<()> { + fn _version(&self, use_long: bool) -> Error { + debugln!("Parser::_version: "); let out = io::stdout(); let mut buf_w = BufWriter::new(out.lock()); - try!(self.print_version(&mut buf_w)); - Err(Error { - message: String::new(), - kind: ErrorKind::VersionDisplayed, - info: None, - }) + match self.print_version(&mut buf_w, use_long) { + Err(e) => e, + _ => Error { + message: String::new(), + kind: ErrorKind::VersionDisplayed, + info: None, + } + } } fn parse_long_arg(&mut self, matcher: &mut ArgMatcher<'a>, full_arg: &OsStr) - -> ClapResult> { + -> ClapResult> { // maybe here lifetime should be 'a - debugln!("fn=parse_long_arg;"); + debugln!("Parser::parse_long_arg;"); let mut val = None; - debug!("Does it contain '='..."); + debug!("Parser::parse_long_arg: Does it contain '='..."); let arg = if full_arg.contains_byte(b'=') { let (p0, p1) = full_arg.trim_left_matches(b'-').split_at_byte(b'='); sdebugln!("Yes '{:?}'", p1); @@ -1296,14 +1395,21 @@ impl<'a, 'b> Parser<'a, 'b> full_arg.trim_left_matches(b'-') }; - if let Some(opt) = find_by_long!(self, &arg, opts) { - debugln!("Found valid opt '{}'", opt.to_string()); - let ret = try!(self.parse_opt(val, opt, matcher)); - arg_post_processing!(self, opt, matcher); + if let Some(opt) = find_opt_by_long!(@os self, arg) { + debugln!("Parser::parse_long_arg: Found valid opt '{}'", + opt.to_string()); + self.settings.set(AS::ValidArgFound); + let ret = try!(self.parse_opt(val, opt, val.is_some(), matcher)); + if self.cache.map_or(true, |name| name != opt.b.name) { + arg_post_processing!(self, opt, matcher); + self.cache = Some(opt.b.name); + } return Ok(ret); - } else if let Some(flag) = find_by_long!(self, &arg, flags) { - debugln!("Found valid flag '{}'", flag.to_string()); + } else if let Some(flag) = find_flag_by_long!(@os self, arg) { + debugln!("Parser::parse_long_arg: Found valid flag '{}'", + flag.to_string()); + self.settings.set(AS::ValidArgFound); // Only flags could be help or version, and we need to check the raw long // so this is the first point to check try!(self.check_for_help_and_version_str(arg)); @@ -1311,65 +1417,67 @@ impl<'a, 'b> Parser<'a, 'b> try!(self.parse_flag(flag, matcher)); // Handle conflicts, requirements, etc. + // if self.cache.map_or(true, |name| name != flag.b.name) { arg_post_processing!(self, flag, matcher); + // self.cache = Some(flag.b.name); + // } - return Ok(None); - } else if self.is_set(AppSettings::AllowLeadingHyphen) { - return Ok(None); - } else if self.valid_neg_num { - return Ok(None); + return Ok(ParseResult::Flag); + } else if self.is_set(AS::AllowLeadingHyphen) { + return Ok(ParseResult::MaybeHyphenValue); + } else if self.is_set(AS::ValidNegNumFound) { + return Ok(ParseResult::MaybeNegNum); } - debugln!("Didn't match anything"); - self.did_you_mean_error(arg.to_str().expect(INVALID_UTF8), matcher).map(|_| None) + debugln!("Parser::parse_long_arg: Didn't match anything"); + self.did_you_mean_error(arg.to_str().expect(INVALID_UTF8), matcher) + .map(|_| ParseResult::NotFound) } + #[cfg_attr(feature = "lints", allow(len_zero))] fn parse_short_arg(&mut self, matcher: &mut ArgMatcher<'a>, full_arg: &OsStr) - -> ClapResult> { - debugln!("fn=parse_short_arg;"); - // let mut utf8 = true; + -> ClapResult> { + debugln!("Parser::parse_short_arg: full_arg={:?}", full_arg); let arg_os = full_arg.trim_left_matches(b'-'); let arg = arg_os.to_string_lossy(); - // If AllowLeadingHyphen is set, we want to ensure `-val` gets parsed as `-val` and not `-v` `-a` `-l` assuming - // `v` `a` and `l` are all, or mostly, valid shorts. - if self.is_set(AppSettings::AllowLeadingHyphen) { - let mut good = true; - for c in arg.chars() { - good = self.short_list.contains(&c); - } - if !good { - return Ok(None); + // If AllowLeadingHyphen is set, we want to ensure `-val` gets parsed as `-val` and not + // `-v` `-a` `-l` assuming `v` `a` and `l` are all, or mostly, valid shorts. + if self.is_set(AS::AllowLeadingHyphen) { + if arg.chars().any(|c| !self.contains_short(c)) { + debugln!("Parser::parse_short_arg: LeadingHyphenAllowed yet -{} isn't valid", + arg); + return Ok(ParseResult::MaybeHyphenValue); } - } else if self.valid_neg_num { + } else if self.is_set(AS::ValidNegNumFound) { // TODO: Add docs about having AllowNegativeNumbers and `-2` as a valid short // May be better to move this to *after* not finding a valid flag/opt? - debugln!("Valid negative num..."); - return Ok(None); + debugln!("Parser::parse_short_arg: Valid negative num..."); + return Ok(ParseResult::MaybeNegNum); } + let mut ret = ParseResult::NotFound; for c in arg.chars() { - debugln!("iter;short={}", c); + debugln!("Parser::parse_short_arg:iter:{}", c); // Check for matching short options, and return the name if there is no trailing // concatenated value: -oval // Option: -o // Value: val - if let Some(opt) = self.opts - .iter() - .find(|&o| o.s.short.is_some() && o.s.short.unwrap() == c) { - debugln!("Found valid short opt -{} in '{}'", c, arg); + if let Some(opt) = find_opt_by_short!(self, c) { + debugln!("Parser::parse_short_arg:iter:{}: Found valid opt", c); + self.settings.set(AS::ValidArgFound); // Check for trailing concatenated value let p: Vec<_> = arg.splitn(2, c).collect(); - debugln!("arg: {:?}, arg_os: {:?}, full_arg: {:?}", - arg, - arg_os, - full_arg); - debugln!("p[0]: {:?}, p[1]: {:?}", p[0].as_bytes(), p[1].as_bytes()); + debugln!("Parser::parse_short_arg:iter:{}: p[0]={:?}, p[1]={:?}", + c, + p[0].as_bytes(), + p[1].as_bytes()); let i = p[0].as_bytes().len() + 1; let val = if p[1].as_bytes().len() > 0 { - debugln!("setting val: {:?} (bytes), {:?} (ascii)", + debugln!("Parser::parse_short_arg:iter:{}: val={:?} (bytes), val={:?} (ascii)", + c, arg_os.split_at(i).1.as_bytes(), arg_os.split_at(i).1); Some(arg_os.split_at(i).1) @@ -1378,115 +1486,141 @@ impl<'a, 'b> Parser<'a, 'b> }; // Default to "we're expecting a value later" - let ret = try!(self.parse_opt(val, opt, matcher)); + let ret = try!(self.parse_opt(val, opt, false, matcher)); - arg_post_processing!(self, opt, matcher); + if self.cache.map_or(true, |name| name != opt.b.name) { + arg_post_processing!(self, opt, matcher); + self.cache = Some(opt.b.name); + } return Ok(ret); - } else if let Some(flag) = self.flags - .iter() - .find(|&f| f.s.short.is_some() && f.s.short.unwrap() == c) { - debugln!("Found valid short flag -{}", c); + } else if let Some(flag) = find_flag_by_short!(self, c) { + debugln!("Parser::parse_short_arg:iter:{}: Found valid flag", c); + self.settings.set(AS::ValidArgFound); // Only flags can be help or version try!(self.check_for_help_and_version_char(c)); - try!(self.parse_flag(flag, matcher)); + ret = try!(self.parse_flag(flag, matcher)); + // Handle conflicts, requirements, overrides, etc. // Must be called here due to mutablilty - arg_post_processing!(self, flag, matcher); + if self.cache.map_or(true, |name| name != flag.b.name) { + arg_post_processing!(self, flag, matcher); + self.cache = Some(flag.b.name); + } } else { - let mut arg = String::new(); - arg.push('-'); - arg.push(c); + let arg = format!("-{}", c); return Err(Error::unknown_argument(&*arg, "", - &*self.create_current_usage(matcher), + &*usage::create_error_usage(self, + matcher, + None), self.color())); } } - Ok(None) + Ok(ret) } fn parse_opt(&self, val: Option<&OsStr>, opt: &OptBuilder<'a, 'b>, + had_eq: bool, matcher: &mut ArgMatcher<'a>) - -> ClapResult> { - debugln!("fn=parse_opt;"); - validate_multiples!(self, opt, matcher); + -> ClapResult> { + debugln!("Parser::parse_opt; opt={}, val={:?}", opt.b.name, val); + debugln!("Parser::parse_opt; opt.settings={:?}", opt.b.settings); let mut has_eq = false; - debug!("Checking for val..."); + debug!("Parser::parse_opt; Checking for val..."); if let Some(fv) = val { - has_eq = fv.starts_with(&[b'=']); + has_eq = fv.starts_with(&[b'=']) || had_eq; let v = fv.trim_left_matches(b'='); - if !opt.is_set(ArgSettings::EmptyValues) && v.len_() == 0 { + if !opt.is_set(ArgSettings::EmptyValues) && + (v.len_() == 0 || (opt.is_set(ArgSettings::RequireEquals) && !has_eq)) { sdebugln!("Found Empty - Error"); return Err(Error::empty_value(opt, - &*self.create_current_usage(matcher), + &*usage::create_error_usage(self, matcher, None), self.color())); } sdebugln!("Found - {:?}, len: {}", v, v.len_()); - debugln!("{:?} contains '='...{:?}", fv, fv.starts_with(&[b'='])); + debugln!("Parser::parse_opt: {:?} contains '='...{:?}", + fv, + fv.starts_with(&[b'='])); try!(self.add_val_to_arg(opt, v, matcher)); + } else if opt.is_set(ArgSettings::RequireEquals) && !opt.is_set(ArgSettings::EmptyValues) { + sdebugln!("None, but requires equals...Error"); + return Err(Error::empty_value(opt, + &*usage::create_error_usage(self, matcher, None), + self.color())); + } else { sdebugln!("None"); } matcher.inc_occurrence_of(opt.b.name); // Increment or create the group "args" - self.groups_for_arg(opt.b.name).and_then(|vec| Some(matcher.inc_occurrences_of(&*vec))); + self.groups_for_arg(opt.b.name) + .and_then(|vec| Some(matcher.inc_occurrences_of(&*vec))); if val.is_none() || !has_eq && (opt.is_set(ArgSettings::Multiple) && !opt.is_set(ArgSettings::RequireDelimiter) && matcher.needs_more_vals(opt)) { - debugln!("More arg vals required..."); - return Ok(Some(opt.b.name)); + debugln!("Parser::parse_opt: More arg vals required..."); + return Ok(ParseResult::Opt(opt.b.name)); } - debugln!("More arg vals not required..."); - Ok(None) + debugln!("Parser::parse_opt: More arg vals not required..."); + Ok(ParseResult::ValuesDone) } fn add_val_to_arg(&self, arg: &A, val: &OsStr, matcher: &mut ArgMatcher<'a>) - -> ClapResult> + -> ClapResult> where A: AnyArg<'a, 'b> + Display { - debugln!("fn=add_val_to_arg;"); - let mut ret = None; - if !(self.trailing_vals && self.is_set(AppSettings::DontDelimitTrailingValues)) { + debugln!("Parser::add_val_to_arg; arg={}, val={:?}", arg.name(), val); + debugln!("Parser::add_val_to_arg; trailing_vals={:?}, DontDelimTrailingVals={:?}", + self.is_set(AS::TrailingValues), + self.is_set(AS::DontDelimitTrailingValues)); + if !(self.is_set(AS::TrailingValues) && self.is_set(AS::DontDelimitTrailingValues)) { if let Some(delim) = arg.val_delim() { if val.is_empty_() { - ret = try!(self.add_single_val_to_arg(arg, val, matcher)); + Ok(try!(self.add_single_val_to_arg(arg, val, matcher))) } else { + let mut iret = ParseResult::ValuesDone; for v in val.split(delim as u32 as u8) { - ret = try!(self.add_single_val_to_arg(arg, v, matcher)); + iret = try!(self.add_single_val_to_arg(arg, v, matcher)); } // If there was a delimiter used, we're not looking for more values if val.contains_byte(delim as u32 as u8) || - arg.is_set(ArgSettings::RequireDelimiter) { - ret = None; - } + arg.is_set(ArgSettings::RequireDelimiter) { + iret = ParseResult::ValuesDone; + } + Ok(iret) } } else { - ret = try!(self.add_single_val_to_arg(arg, val, matcher)); + self.add_single_val_to_arg(arg, val, matcher) } } else { - ret = try!(self.add_single_val_to_arg(arg, val, matcher)); + self.add_single_val_to_arg(arg, val, matcher) } - Ok(ret) } fn add_single_val_to_arg(&self, arg: &A, v: &OsStr, matcher: &mut ArgMatcher<'a>) - -> ClapResult> + -> ClapResult> where A: AnyArg<'a, 'b> + Display { - debugln!("adding val: {:?}", v); + debugln!("Parser::add_single_val_to_arg;"); + debugln!("Parser::add_single_val_to_arg: adding val...{:?}", v); + if let Some(t) = arg.val_terminator() { + if t == v { + return Ok(ParseResult::ValuesDone); + } + } matcher.add_val_to(arg.name(), v); // Increment or create the group "args" @@ -1496,294 +1630,40 @@ impl<'a, 'b> Parser<'a, 'b> } } - // The validation must come AFTER inserting into 'matcher' or the usage string - // can't be built - self.validate_value(arg, v, matcher) - } - - fn validate_value(&self, - arg: &A, - val: &OsStr, - matcher: &ArgMatcher<'a>) - -> ClapResult> - where A: AnyArg<'a, 'b> + Display - { - debugln!("fn=validate_value; val={:?}", val); - if self.is_set(AppSettings::StrictUtf8) && val.to_str().is_none() { - return Err(Error::invalid_utf8(&*self.create_current_usage(matcher), self.color())); - } - if let Some(p_vals) = arg.possible_vals() { - let val_str = val.to_string_lossy(); - if !p_vals.contains(&&*val_str) { - return Err(Error::invalid_value(val_str, - p_vals, - arg, - &*self.create_current_usage(matcher), - self.color())); - } - } - if !arg.is_set(ArgSettings::EmptyValues) && val.is_empty_() && - matcher.contains(&*arg.name()) { - return Err(Error::empty_value(arg, &*self.create_current_usage(matcher), self.color())); - } - if let Some(vtor) = arg.validator() { - if let Err(e) = vtor(val.to_string_lossy().into_owned()) { - return Err(Error::value_validation(Some(arg), e, self.color())); - } - } if matcher.needs_more_vals(arg) { - return Ok(Some(arg.name())); + return Ok(ParseResult::Opt(arg.name())); } - Ok(None) + Ok(ParseResult::ValuesDone) } + fn parse_flag(&self, flag: &FlagBuilder<'a, 'b>, matcher: &mut ArgMatcher<'a>) - -> ClapResult<()> { - debugln!("fn=parse_flag;"); - validate_multiples!(self, flag, matcher); + -> ClapResult> { + debugln!("Parser::parse_flag;"); matcher.inc_occurrence_of(flag.b.name); // Increment or create the group "args" - self.groups_for_arg(flag.b.name).and_then(|vec| Some(matcher.inc_occurrences_of(&*vec))); - - Ok(()) - } - - fn validate_blacklist(&self, matcher: &mut ArgMatcher) -> ClapResult<()> { - debugln!("fn=validate_blacklist;blacklist={:?}", self.blacklist); - macro_rules! build_err { - ($me:ident, $name:expr, $matcher:ident) => ({ - debugln!("macro=build_err;name={}", $name); - let mut c_with = find_from!($me, $name, blacklist, &$matcher); - c_with = c_with.or( - $me.find_any_arg($name).map_or(None, |aa| aa.blacklist()) - .map_or(None, |bl| bl.iter().find(|arg| $matcher.contains(arg))) - .map_or(None, |an| $me.find_any_arg(an)) - .map_or(None, |aa| Some(format!("{}", aa))) - ); - debugln!("'{:?}' conflicts with '{}'", c_with, $name); - $matcher.remove($name); - let usg = $me.create_current_usage($matcher); - if let Some(f) = find_by_name!($me, $name, flags, iter) { - debugln!("It was a flag..."); - Error::argument_conflict(f, c_with, &*usg, self.color()) - } else if let Some(o) = find_by_name!($me, $name, opts, iter) { - debugln!("It was an option..."); - Error::argument_conflict(o, c_with, &*usg, self.color()) - } else { - match find_by_name!($me, $name, positionals, values) { - Some(p) => { - debugln!("It was a positional..."); - Error::argument_conflict(p, c_with, &*usg, self.color()) - }, - None => panic!(INTERNAL_ERROR_MSG) - } - } - }); - } - - for name in &self.blacklist { - debugln!("Checking blacklisted name: {}", name); - if self.groups.contains_key(name) { - debugln!("groups contains it..."); - for n in self.arg_names_in_group(name) { - debugln!("Checking arg '{}' in group...", n); - if matcher.contains(n) { - debugln!("matcher contains it..."); - return Err(build_err!(self, &n, matcher)); - } - } - } else if matcher.contains(name) { - debugln!("matcher contains it..."); - return Err(build_err!(self, name, matcher)); - } - } - Ok(()) - } + self.groups_for_arg(flag.b.name) + .and_then(|vec| Some(matcher.inc_occurrences_of(&*vec))); - fn validate_num_args(&self, matcher: &mut ArgMatcher) -> ClapResult<()> { - debugln!("fn=validate_num_args;"); - for (name, ma) in matcher.iter() { - debugln!("iter;name={}", name); - if let Some(opt) = find_by_name!(self, name, opts, iter) { - try!(self._validate_num_vals(opt, ma, matcher)); - } else if let Some(pos) = find_by_name!(self, name, positionals, values) { - try!(self._validate_num_vals(pos, ma, matcher)); - } - } - Ok(()) - } - - fn _validate_num_vals(&self, a: &A, ma: &MatchedArg, matcher: &ArgMatcher) -> ClapResult<()> - where A: AnyArg<'a, 'b> + Display - { - debugln!("fn=_validate_num_vals;"); - if let Some(num) = a.num_vals() { - debugln!("num_vals set: {}", num); - let should_err = if a.is_set(ArgSettings::Multiple) { - ((ma.vals.len() as u64) % num) != 0 - } else { - num != (ma.vals.len() as u64) - }; - if should_err { - debugln!("Sending error WrongNumberOfValues"); - return Err(Error::wrong_number_of_values(a, - num, - if a.is_set(ArgSettings::Multiple) { - (ma.vals.len() % num as usize) - } else { - ma.vals.len() - }, - if ma.vals.len() == 1 || - (a.is_set(ArgSettings::Multiple) && - (ma.vals.len() % num as usize) == - 1) { - "as" - } else { - "ere" - }, - &*self.create_current_usage(matcher), - self.color())); - } - } - if let Some(num) = a.max_vals() { - debugln!("max_vals set: {}", num); - if (ma.vals.len() as u64) > num { - debugln!("Sending error TooManyValues"); - return Err(Error::too_many_values(ma.vals - .get(ma.vals - .keys() - .last() - .expect(INTERNAL_ERROR_MSG)) - .expect(INTERNAL_ERROR_MSG) - .to_str() - .expect(INVALID_UTF8), - a, - &*self.create_current_usage(matcher), - self.color())); - } - } - if let Some(num) = a.min_vals() { - debugln!("min_vals set: {}", num); - if (ma.vals.len() as u64) < num { - debugln!("Sending error TooFewValues"); - return Err(Error::too_few_values(a, - num, - ma.vals.len(), - &*self.create_current_usage(matcher), - self.color())); - } - } - Ok(()) - } - - fn validate_required(&self, matcher: &ArgMatcher) -> ClapResult<()> { - debugln!("fn=validate_required;required={:?};", self.required); - 'outer: for name in &self.required { - debugln!("iter;name={}", name); - if matcher.contains(name) { - continue 'outer; - } - if let Some(grp) = self.groups.get(name) { - for arg in &grp.args { - if matcher.contains(arg) { - continue 'outer; - } - } - } - if self.groups.values().any(|g| g.args.contains(name)) { - continue 'outer; - } - if let Some(a) = find_by_name!(self, name, flags, iter) { - if self.is_missing_required_ok(a, matcher) { - continue 'outer; - } - } else if let Some(a) = find_by_name!(self, name, opts, iter) { - if self.is_missing_required_ok(a, matcher) { - continue 'outer; - } - } else if let Some(a) = find_by_name!(self, name, positionals, values) { - if self.is_missing_required_ok(a, matcher) { - continue 'outer; - } - } - let err = - if self.settings.is_set(AppSettings::ArgRequiredElseHelp) && matcher.is_empty() { - self._help().unwrap_err() - } else { - let mut reqs = self.required.iter().map(|&r| &*r).collect::>(); - reqs.retain(|n| !matcher.contains(n)); - reqs.dedup(); - Error::missing_required_argument( - &*self.get_required_from(&*reqs, Some(matcher)) - .iter() - .fold(String::new(), - |acc, s| acc + &format!("\n {}", Format::Error(s))[..]), - &*self.create_current_usage(matcher), - self.color()) - }; - return Err(err); - } - Ok(()) - } - - fn is_missing_required_ok(&self, a: &A, matcher: &ArgMatcher) -> bool - where A: AnyArg<'a, 'b> - { - debugln!("fn=is_missing_required_ok;a={}", a.name()); - if let Some(bl) = a.blacklist() { - debugln!("Conflicts found...{:?}", bl); - for n in bl.iter() { - debugln!("iter;conflict={}", n); - if matcher.contains(n) || - self.groups - .get(n) - .map_or(false, |g| g.args.iter().any(|an| matcher.contains(an))) { - return true; - } - } - } - if let Some(ru) = a.required_unless() { - debugln!("Required unless found...{:?}", ru); - let mut found_any = false; - for n in ru.iter() { - debugln!("iter;ru={}", n); - if matcher.contains(n) || - self.groups - .get(n) - .map_or(false, |g| g.args.iter().any(|an| matcher.contains(an))) { - if !a.is_set(ArgSettings::RequiredUnlessAll) { - debugln!("Doesn't require all...returning true"); - return true; - } - debugln!("Requires all...next"); - found_any = true; - } else if a.is_set(ArgSettings::RequiredUnlessAll) { - debugln!("Not in matcher, or group and requires all...returning false"); - return false; - } - } - return found_any; - } - false + Ok(ParseResult::Flag) } fn did_you_mean_error(&self, arg: &str, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> { - // Didn't match a flag or option...maybe it was a typo and close to one + + // Didn't match a flag or option let suffix = - suggestions::did_you_mean_suffix(arg, - self.long_list.iter(), - suggestions::DidYouMeanMessageStyle::LongFlag); + suggestions::did_you_mean_flag_suffix(arg, longs!(self), &self.subcommands); // Add the arg to the matches to build a proper usage string if let Some(name) = suffix.1 { - if let Some(opt) = find_by_long!(self, &name, opts) { + if let Some(opt) = find_opt_by_long!(self, name) { self.groups_for_arg(&*opt.b.name) .and_then(|grps| Some(matcher.inc_occurrences_of(&*grps))); matcher.insert(&*opt.b.name); - } else if let Some(flg) = find_by_long!(self, &name, flags) { + } else if let Some(flg) = find_flag_by_long!(self, name) { self.groups_for_arg(&*flg.b.name) .and_then(|grps| Some(matcher.inc_occurrences_of(&*grps))); matcher.insert(&*flg.b.name); @@ -1793,138 +1673,35 @@ impl<'a, 'b> Parser<'a, 'b> let used_arg = format!("--{}", arg); Err(Error::unknown_argument(&*used_arg, &*suffix.0, - &*self.create_current_usage(matcher), + &*usage::create_error_usage(self, matcher, None), self.color())) } - // Creates a usage string if one was not provided by the user manually. This happens just - // after all arguments were parsed, but before any subcommands have been parsed - // (so as to give subcommands their own usage recursively) - pub fn create_usage(&self, used: &[&str]) -> String { - debugln!("fn=create_usage;"); - let mut usage = String::with_capacity(75); - usage.push_str("USAGE:\n "); - usage.push_str(&self.create_usage_no_title(used)); - usage - } - - // Creates a usage string (*without title*) if one was not provided by the user - // manually. This happens just - // after all arguments were parsed, but before any subcommands have been parsed - // (so as to give subcommands their own usage recursively) - pub fn create_usage_no_title(&self, used: &[&str]) -> String { - debugln!("fn=create_usage_no_title;"); - let mut usage = String::with_capacity(75); - if let Some(u) = self.meta.usage_str { - usage.push_str(&*u); - } else if used.is_empty() { - usage.push_str(&*self.meta - .usage - .as_ref() - .unwrap_or(self.meta - .bin_name - .as_ref() - .unwrap_or(&self.meta.name))); - let mut reqs: Vec<&str> = self.required().map(|r| &**r).collect(); - reqs.dedup(); - let req_string = self.get_required_from(&reqs, None) - .iter() - .fold(String::new(), |a, s| a + &format!(" {}", s)[..]); - - let flags = self.needs_flags_tag(); - if flags && !self.is_set(AppSettings::UnifiedHelpMessage) { - usage.push_str(" [FLAGS]"); - } else if flags { - usage.push_str(" [OPTIONS]"); - } - if !self.is_set(AppSettings::UnifiedHelpMessage) && self.has_opts() && - self.opts.iter().any(|o| !o.b.settings.is_set(ArgSettings::Required)) { - usage.push_str(" [OPTIONS]"); - } - - usage.push_str(&req_string[..]); - - // places a '--' in the usage string if there are args and options - // supporting multiple values - if self.has_positionals() && - self.opts.iter().any(|o| o.b.settings.is_set(ArgSettings::Multiple)) && - self.positionals.values().any(|p| !p.b.settings.is_set(ArgSettings::Required)) && - !self.has_subcommands() { - usage.push_str(" [--]") - } - if self.has_positionals() && - self.positionals.values().any(|p| !p.b.settings.is_set(ArgSettings::Required)) { - if let Some(args_tag) = self.get_args_tag() { - usage.push_str(&*args_tag); - } else { - usage.push_str(" [ARGS]"); - } - } - - - if self.has_subcommands() && !self.is_set(AppSettings::SubcommandRequired) { - usage.push_str(" [SUBCOMMAND]"); - } else if self.is_set(AppSettings::SubcommandRequired) && self.has_subcommands() { - usage.push_str(" "); - } - } else { - self.smart_usage(&mut usage, used); - } - - usage.shrink_to_fit(); - usage - } - - // Creates a context aware usage string, or "smart usage" from currently used - // args, and requirements - fn smart_usage(&self, usage: &mut String, used: &[&str]) { - debugln!("fn=smart_usage;"); - let mut hs: Vec<&str> = self.required().map(|s| &**s).collect(); - hs.extend_from_slice(used); - - let r_string = self.get_required_from(&hs, None) - .iter() - .fold(String::new(), |acc, s| acc + &format!(" {}", s)[..]); - - usage.push_str(&self.meta - .usage - .as_ref() - .unwrap_or(self.meta - .bin_name - .as_ref() - .unwrap_or(&self.meta - .name))[..]); - usage.push_str(&*r_string); - if self.is_set(AppSettings::SubcommandRequired) { - usage.push_str(" "); - } - } - // Prints the version to the user and exits if quit=true - fn print_version(&self, w: &mut W) -> ClapResult<()> { - try!(self.write_version(w)); + fn print_version(&self, w: &mut W, use_long: bool) -> ClapResult<()> { + try!(self.write_version(w, use_long)); w.flush().map_err(Error::from) } - pub fn write_version(&self, w: &mut W) -> io::Result<()> { + pub fn write_version(&self, w: &mut W, use_long: bool) -> io::Result<()> { + let ver = if use_long { + self.meta + .long_version + .unwrap_or_else(|| self.meta.version.unwrap_or("")) + } else { + self.meta + .version + .unwrap_or_else(|| self.meta.long_version.unwrap_or("")) + }; if let Some(bn) = self.meta.bin_name.as_ref() { if bn.contains(' ') { // Incase we're dealing with subcommands i.e. git mv is translated to git-mv - write!(w, - "{} {}", - bn.replace(" ", "-"), - self.meta.version.unwrap_or("".into())) + write!(w, "{} {}", bn.replace(" ", "-"), ver) } else { - write!(w, - "{} {}", - &self.meta.name[..], - self.meta.version.unwrap_or("".into())) + write!(w, "{} {}", &self.meta.name[..], ver) } } else { - write!(w, - "{} {}", - &self.meta.name[..], - self.meta.version.unwrap_or("".into())) + write!(w, "{} {}", &self.meta.name[..], ver) } } @@ -1935,29 +1712,69 @@ impl<'a, 'b> Parser<'a, 'b> } pub fn write_help(&self, w: &mut W) -> ClapResult<()> { - Help::write_parser_help(w, self) + Help::write_parser_help(w, self, false) + } + + pub fn write_long_help(&self, w: &mut W) -> ClapResult<()> { + Help::write_parser_help(w, self, true) } pub fn write_help_err(&self, w: &mut W) -> ClapResult<()> { Help::write_parser_help_to_stderr(w, self) } - fn add_defaults(&mut self, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> { + pub fn add_defaults(&mut self, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> { macro_rules! add_val { + (@default $_self:ident, $a:ident, $m:ident) => { + if let Some(ref val) = $a.v.default_val { + if $m.get($a.b.name).is_none() { + try!($_self.add_val_to_arg($a, OsStr::new(val), $m)); + + if $_self.cache.map_or(true, |name| name != $a.name()) { + arg_post_processing!($_self, $a, $m); + $_self.cache = Some($a.name()); + } + } + } + }; ($_self:ident, $a:ident, $m:ident) => { - if $m.get($a.b.name).is_none() { - try!($_self.add_val_to_arg($a, OsStr::new($a.v.default_val - .as_ref() - .unwrap()), - $m)); - arg_post_processing!($_self, $a, $m); + if let Some(ref vm) = $a.v.default_vals_ifs { + let mut done = false; + if $m.get($a.b.name).is_none() { + for &(arg, val, default) in vm.values() { + let add = if let Some(a) = $m.get(arg) { + if let Some(v) = val { + a.vals.iter().any(|value| v == value) + } else { + true + } + } else { + false + }; + if add { + try!($_self.add_val_to_arg($a, OsStr::new(default), $m)); + if $_self.cache.map_or(true, |name| name != $a.name()) { + arg_post_processing!($_self, $a, $m); + $_self.cache = Some($a.name()); + } + done = true; + break; + } + } + } + + if done { + continue; // outer loop (outside macro) + } } + add_val!(@default $_self, $a, $m) }; } - for o in self.opts.iter().filter(|o| o.v.default_val.is_some()) { + + for o in &self.opts { add_val!(self, o, matcher); } - for p in self.positionals.values().filter(|p| p.v.default_val.is_some()) { + for p in self.positionals.values() { add_val!(self, p, matcher); } Ok(()) @@ -1974,12 +1791,12 @@ impl<'a, 'b> Parser<'a, 'b> // Should we color the output? None=determined by output location, true=yes, false=no #[doc(hidden)] pub fn color(&self) -> ColorWhen { - debugln!("fn=color;"); - debug!("Color setting..."); - if self.is_set(AppSettings::ColorNever) { + debugln!("Parser::color;"); + debug!("Parser::color: Color setting..."); + if self.is_set(AS::ColorNever) { sdebugln!("Never"); ColorWhen::Never - } else if self.is_set(AppSettings::ColorAlways) { + } else if self.is_set(AS::ColorAlways) { sdebugln!("Always"); ColorWhen::Always } else { @@ -1989,67 +1806,68 @@ impl<'a, 'b> Parser<'a, 'b> } pub fn find_any_arg(&self, name: &str) -> Option<&AnyArg> { - if let Some(f) = find_by_name!(self, &name, flags, iter) { + if let Some(f) = find_by_name!(self, name, flags, iter) { return Some(f); } - if let Some(o) = find_by_name!(self, &name, opts, iter) { + if let Some(o) = find_by_name!(self, name, opts, iter) { return Some(o); } - if let Some(p) = find_by_name!(self, &name, positionals, values) { + if let Some(p) = find_by_name!(self, name, positionals, values) { return Some(p); } None } - #[cfg_attr(feature = "lints", allow(explicit_iter_loop))] + /// Check is a given string matches the binary name for this parser + fn is_bin_name(&self, value: &str) -> bool { + self.meta.bin_name + .as_ref() + .and_then(|name| Some(value == name)) + .unwrap_or(false) + } + + /// Check is a given string is an alias for this parser + fn is_alias(&self, value: &str) -> bool { + self.meta.aliases + .as_ref() + .and_then(|aliases| { + for alias in aliases { + if alias.0 == value { + return Some(true); + } + } + Some(false) + }) + .unwrap_or(false) + } + + // Only used for completion scripts due to bin_name messiness + #[cfg_attr(feature = "lints", allow(block_in_if_condition_stmt))] pub fn find_subcommand(&'b self, sc: &str) -> Option<&'b App<'a, 'b>> { - debugln!("fn=find_subcommand;"); - debugln!("Looking for sc...{}", sc); - debugln!("Currently in Parser...{}", self.meta.bin_name.as_ref().unwrap()); - for s in self.subcommands.iter() { - if s.p.meta.bin_name.as_ref().unwrap_or(&String::new()) == sc || - (s.p.meta.aliases.is_some() && - s.p - .meta - .aliases - .as_ref() - .unwrap() - .iter() - .any(|&(s, _)| s == sc.split(' ').rev().next().expect(INTERNAL_ERROR_MSG))) { + debugln!("Parser::find_subcommand: sc={}", sc); + debugln!("Parser::find_subcommand: Currently in Parser...{}", + self.meta.bin_name.as_ref().unwrap()); + for s in &self.subcommands { + if s.p.is_bin_name(sc) { + return Some(s); + } + // XXX: why do we split here? + // isn't `sc` supposed to be single word already? + let last = sc.split(' ').rev().next().expect(INTERNAL_ERROR_MSG); + if s.p.is_alias(last) { return Some(s); } + if let Some(app) = s.p.find_subcommand(sc) { return Some(app); } } None } -} -impl<'a, 'b> Clone for Parser<'a, 'b> - where 'a: 'b -{ - fn clone(&self) -> Self { - Parser { - required: self.required.clone(), - short_list: self.short_list.clone(), - long_list: self.long_list.clone(), - blacklist: self.blacklist.clone(), - flags: self.flags.clone(), - opts: self.opts.clone(), - positionals: self.positionals.clone(), - subcommands: self.subcommands.clone(), - groups: self.groups.clone(), - global_args: self.global_args.clone(), - overrides: self.overrides.clone(), - help_short: self.help_short, - version_short: self.version_short, - settings: self.settings.clone(), - g_settings: self.g_settings.clone(), - meta: self.meta.clone(), - trailing_vals: self.trailing_vals, - id: self.id, - valid_neg_num: self.valid_neg_num, - } - } + #[inline] + fn contains_long(&self, l: &str) -> bool { longs!(self).any(|al| al == &l) } + + #[inline] + fn contains_short(&self, s: char) -> bool { shorts!(self).any(|arg_s| arg_s == &s) } } diff --git a/src/vendor/clap/src/app/settings.rs b/src/vendor/clap/src/app/settings.rs index 3405dbd853..c77fe3e536 100644 --- a/src/vendor/clap/src/app/settings.rs +++ b/src/vendor/clap/src/app/settings.rs @@ -1,47 +1,60 @@ // Std use std::ascii::AsciiExt; use std::str::FromStr; +use std::ops::BitOr; bitflags! { - flags Flags: u32 { - const SC_NEGATE_REQS = 0b00000000000000000000000000001, - const SC_REQUIRED = 0b00000000000000000000000000010, - const A_REQUIRED_ELSE_HELP = 0b00000000000000000000000000100, - const GLOBAL_VERSION = 0b00000000000000000000000001000, - const VERSIONLESS_SC = 0b00000000000000000000000010000, - const UNIFIED_HELP = 0b00000000000000000000000100000, - const WAIT_ON_ERROR = 0b00000000000000000000001000000, - const SC_REQUIRED_ELSE_HELP= 0b00000000000000000000010000000, - const NEEDS_LONG_HELP = 0b00000000000000000000100000000, - const NEEDS_LONG_VERSION = 0b00000000000000000001000000000, - const NEEDS_SC_HELP = 0b00000000000000000010000000000, - const DISABLE_VERSION = 0b00000000000000000100000000000, - const HIDDEN = 0b00000000000000001000000000000, - const TRAILING_VARARG = 0b00000000000000010000000000000, - const NO_BIN_NAME = 0b00000000000000100000000000000, - const ALLOW_UNK_SC = 0b00000000000001000000000000000, - const UTF8_STRICT = 0b00000000000010000000000000000, - const UTF8_NONE = 0b00000000000100000000000000000, - const LEADING_HYPHEN = 0b00000000001000000000000000000, - const NO_POS_VALUES = 0b00000000010000000000000000000, - const NEXT_LINE_HELP = 0b00000000100000000000000000000, - const DERIVE_DISP_ORDER = 0b00000001000000000000000000000, - const COLORED_HELP = 0b00000010000000000000000000000, - const COLOR_ALWAYS = 0b00000100000000000000000000000, - const COLOR_AUTO = 0b00001000000000000000000000000, - const COLOR_NEVER = 0b00010000000000000000000000000, - const DONT_DELIM_TRAIL = 0b00100000000000000000000000000, - const ALLOW_NEG_NUMS = 0b01000000000000000000000000000, - const LOW_INDEX_MUL_POS = 0b10000000000000000000000000000, + struct Flags: u64 { + const SC_NEGATE_REQS = 1; + const SC_REQUIRED = 1 << 1; + const A_REQUIRED_ELSE_HELP = 1 << 2; + const GLOBAL_VERSION = 1 << 3; + const VERSIONLESS_SC = 1 << 4; + const UNIFIED_HELP = 1 << 5; + const WAIT_ON_ERROR = 1 << 6; + const SC_REQUIRED_ELSE_HELP= 1 << 7; + const NEEDS_LONG_HELP = 1 << 8; + const NEEDS_LONG_VERSION = 1 << 9; + const NEEDS_SC_HELP = 1 << 10; + const DISABLE_VERSION = 1 << 11; + const HIDDEN = 1 << 12; + const TRAILING_VARARG = 1 << 13; + const NO_BIN_NAME = 1 << 14; + const ALLOW_UNK_SC = 1 << 15; + const UTF8_STRICT = 1 << 16; + const UTF8_NONE = 1 << 17; + const LEADING_HYPHEN = 1 << 18; + const NO_POS_VALUES = 1 << 19; + const NEXT_LINE_HELP = 1 << 20; + const DERIVE_DISP_ORDER = 1 << 21; + const COLORED_HELP = 1 << 22; + const COLOR_ALWAYS = 1 << 23; + const COLOR_AUTO = 1 << 24; + const COLOR_NEVER = 1 << 25; + const DONT_DELIM_TRAIL = 1 << 26; + const ALLOW_NEG_NUMS = 1 << 27; + const LOW_INDEX_MUL_POS = 1 << 28; + const DISABLE_HELP_SC = 1 << 29; + const DONT_COLLAPSE_ARGS = 1 << 30; + const ARGS_NEGATE_SCS = 1 << 31; + const PROPAGATE_VALS_DOWN = 1 << 32; + const ALLOW_MISSING_POS = 1 << 33; + const TRAILING_VALUES = 1 << 34; + const VALID_NEG_NUM_FOUND = 1 << 35; + const PROPOGATED = 1 << 36; + const VALID_ARG_FOUND = 1 << 37; + const INFER_SUBCOMMANDS = 1 << 38; + const CONTAINS_LAST = 1 << 39; } } #[doc(hidden)] -#[derive(Debug)] +#[derive(Debug, Copy, Clone, PartialEq)] pub struct AppFlags(Flags); -impl Clone for AppFlags { - fn clone(&self) -> Self { AppFlags(self.0) } +impl BitOr for AppFlags { + type Output = Self; + fn bitor(self, rhs: Self) -> Self { AppFlags(self.0 | rhs.0) } } impl Default for AppFlags { @@ -55,16 +68,20 @@ impl AppFlags { impl_settings! { AppSettings, ArgRequiredElseHelp => A_REQUIRED_ELSE_HELP, + ArgsNegateSubcommands => ARGS_NEGATE_SCS, AllowExternalSubcommands => ALLOW_UNK_SC, AllowInvalidUtf8 => UTF8_NONE, AllowLeadingHyphen => LEADING_HYPHEN, AllowNegativeNumbers => ALLOW_NEG_NUMS, + AllowMissingPositional => ALLOW_MISSING_POS, ColoredHelp => COLORED_HELP, ColorAlways => COLOR_ALWAYS, ColorAuto => COLOR_AUTO, ColorNever => COLOR_NEVER, DontDelimitTrailingValues => DONT_DELIM_TRAIL, + DontCollapseArgsInUsage => DONT_COLLAPSE_ARGS, DeriveDisplayOrder => DERIVE_DISP_ORDER, + DisableHelpSubcommand => DISABLE_HELP_SC, DisableVersion => DISABLE_VERSION, GlobalVersion => GLOBAL_VERSION, HidePossibleValuesInHelp => NO_POS_VALUES, @@ -74,6 +91,7 @@ impl AppFlags { NeedsLongVersion => NEEDS_LONG_VERSION, NeedsSubcommandHelp => NEEDS_SC_HELP, NoBinaryName => NO_BIN_NAME, + PropagateGlobalValuesDown=> PROPAGATE_VALS_DOWN, StrictUtf8 => UTF8_STRICT, SubcommandsNegateReqs => SC_NEGATE_REQS, SubcommandRequired => SC_REQUIRED, @@ -82,7 +100,13 @@ impl AppFlags { UnifiedHelpMessage => UNIFIED_HELP, NextLineHelp => NEXT_LINE_HELP, VersionlessSubcommands => VERSIONLESS_SC, - WaitOnError => WAIT_ON_ERROR + WaitOnError => WAIT_ON_ERROR, + TrailingValues => TRAILING_VALUES, + ValidNegNumFound => VALID_NEG_NUM_FOUND, + Propogated => PROPOGATED, + ValidArgFound => VALID_ARG_FOUND, + InferSubcommands => INFER_SUBCOMMANDS, + ContainsLast => CONTAINS_LAST } } @@ -138,11 +162,9 @@ pub enum AppSettings { /// Specifies that leading hyphens are allowed in argument *values*, such as negative numbers /// like `-10`. (which would otherwise be parsed as another flag or option) /// - /// **NOTE:** This can only be set application wide and not on a per argument basis. - /// /// **NOTE:** Use this setting with caution as it silences certain circumstances which would /// otherwise be an error (such as accidentally forgetting to specify a value for leading - /// option) + /// option). It is preferred to set this on a per argument basis, via [`Arg::allow_hyphen_values`] /// /// # Examples /// @@ -159,6 +181,7 @@ pub enum AppSettings { /// assert_eq!(m.value_of("neg"), Some("-20")); /// # ; /// ``` + /// [`Arg::allow_hyphen_values`]: ./struct.Arg.html#method.allow_hyphen_values AllowLeadingHyphen, /// Allows negative numbers to pass as values. This is similar to @@ -183,6 +206,39 @@ pub enum AppSettings { /// [`AllowLeadingHyphen`]: ./enum.AppSettings.html#variant.AllowLeadingHyphen AllowNegativeNumbers, + /// Allows one to implement a CLI where the second to last positional argument is optional, but + /// the final positional argument is required. Such as `$ prog [optional] ` where one + /// of the two following usages is allowed: + /// + /// * `$ prog [optional] ` + /// * `$ prog ` + /// + /// This would otherwise not be allowed. This is useful when `[optional]` has a default value. + /// + /// **Note:** In addition to using this setting, the second positional argument *must* be + /// [required] + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, Arg, AppSettings}; + /// // Assume there is an external subcommand named "subcmd" + /// let m = App::new("myprog") + /// .setting(AppSettings::AllowMissingPositional) + /// .arg(Arg::with_name("arg1") + /// .default_value("something")) + /// .arg(Arg::with_name("arg2") + /// .required(true)) + /// .get_matches_from(vec![ + /// "myprog", "other" + /// ]); + /// + /// assert_eq!(m.value_of("arg1"), Some("something")); + /// assert_eq!(m.value_of("arg2"), Some("other")); + /// ``` + /// [required]: ./struct.Arg.html#method.required + AllowMissingPositional, + /// Specifies that an unexpected positional argument, /// which would otherwise cause a [`ErrorKind::UnknownArgument`] error, /// should instead be treated as a [`SubCommand`] within the [`ArgMatches`] struct. @@ -219,11 +275,36 @@ pub enum AppSettings { /// [`ArgMatches`]: ./struct.ArgMatches.html AllowExternalSubcommands, + /// Specifies that use of a valid [argument] negates [subcomands] being used after. By default + /// `clap` allows arguments between subcommands such as + /// ` [cmd_args] [cmd2_args] [cmd3_args]`. This setting disables that + /// functionality and says that arguments can only follow the *final* subcommand. For instance + /// using this setting makes only the following invocations possible: + /// + /// * ` [cmd3_args]` + /// * ` [cmd2_args]` + /// * ` [cmd_args]` + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, AppSettings}; + /// App::new("myprog") + /// .setting(AppSettings::ArgsNegateSubcommands) + /// # ; + /// ``` + /// [subcommands]: ./struct.SubCommand.html + /// [argument]: ./struct.Arg.html + ArgsNegateSubcommands, + /// Specifies that the help text should be displayed (and then exit gracefully), /// if no arguments are present at runtime (i.e. an empty run such as, `$ myprog`. /// /// **NOTE:** [`SubCommand`]s count as arguments /// + /// **NOTE:** Setting [`Arg::default_value`] effectively disables this option as it will + /// ensure that some argument is always present. + /// /// # Examples /// /// ```rust @@ -233,6 +314,7 @@ pub enum AppSettings { /// # ; /// ``` /// [`SubCommand`]: ./struct.SubCommand.html + /// [`Arg::default_value`]: ./struct.Arg.html#method.default_value ArgRequiredElseHelp, /// Uses colorized help messages. @@ -309,6 +391,18 @@ pub enum AppSettings { /// ``` ColorNever, + /// Disables the automatic collapsing of positional args into `[ARGS]` inside the usage string + /// + /// # Examples + /// + /// ```no_run + /// # use clap::{App, Arg, SubCommand, AppSettings}; + /// App::new("myprog") + /// .setting(AppSettings::DontCollapseArgsInUsage) + /// .get_matches(); + /// ``` + DontCollapseArgsInUsage, + /// Disables the automatic delimiting of values when `--` or [`AppSettings::TrailingVarArg`] /// was used. /// @@ -328,6 +422,27 @@ pub enum AppSettings { /// [`Arg::use_delimiter(false)`]: ./struct.Arg.html#method.use_delimiter DontDelimitTrailingValues, + /// Disables the `help` subcommand + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, AppSettings, ErrorKind, SubCommand}; + /// let res = App::new("myprog") + /// .version("v1.1") + /// .setting(AppSettings::DisableHelpSubcommand) + /// // Normally, creating a subcommand causes a `help` subcommand to automaticaly + /// // be generated as well + /// .subcommand(SubCommand::with_name("test")) + /// .get_matches_from_safe(vec![ + /// "myprog", "help" + /// ]); + /// assert!(res.is_err()); + /// assert_eq!(res.unwrap_err().kind, ErrorKind::UnknownArgument); + /// ``` + /// [`SubCommand`]: ./struct.SubCommand.html + DisableHelpSubcommand, + /// Disables `-V` and `--version` [`App`] without affecting any of the [`SubCommand`]s /// (Defaults to `false`; application *does* have a version flag) /// @@ -413,6 +528,36 @@ pub enum AppSettings { /// This can be useful if there are many values, or they are explained elsewhere. HidePossibleValuesInHelp, + /// Tries to match unknown args to partial [`subcommands`] or their [aliases]. For example to + /// match a subcommand named `test`, one could use `t`, `te`, `tes`, and `test`. + /// + /// **NOTE:** The match *must not* be ambiguous at all in order to succeed. i.e. to match `te` + /// to `test` there could not also be a subcommand or alias `temp` because both start with `te` + /// + /// **CAUTION:** This setting can interfere with [positional/free arguments], take care when + /// designing CLIs which allow inferred subcommands and have potential positional/free + /// arguments whose values could start with the same characters as subcommands. If this is the + /// case, it's recommended to use settings such as [`AppSeettings::ArgsNegateSubcommands`] in + /// conjuction with this setting. + /// + /// # Examples + /// + /// ```no_run + /// # use clap::{App, Arg, SubCommand, AppSettings}; + /// let m = App::new("prog") + /// .setting(AppSettings::InferSubcommands) + /// .subcommand(SubCommand::with_name("test")) + /// .get_matches_from(vec![ + /// "prog", "te" + /// ]); + /// assert_eq!(m.subcommand_name(), Some("test")); + /// ``` + /// [`subcommands`]: ./struct.SubCommand.html + /// [positional/free arguments]: ./struct.Arg.html#method.index + /// [aliases]: ./struct.App.html#method.alias + /// [`AppSeettings::ArgsNegateSubcommands`]: ./enum.AppSettings.html#variant.ArgsNegateSubcommands + InferSubcommands, + /// Specifies that the parser should not assume the first argument passed is the binary name. /// This is normally the case when using a "daemon" style mode, or an interactive CLI where one /// one would not normally type the binary or program name for each command. @@ -443,6 +588,46 @@ pub enum AppSettings { /// ``` NextLineHelp, + /// Specifies that the parser should propagate global arg's values down through any *used* child + /// subcommands. Meaning, if a subcommand wasn't used, the values won't be propagated down to + /// said subcommand. + /// + /// **NOTE:** Values are only propagated *down* through futher child commands, not up + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, Arg, AppSettings, SubCommand}; + /// let m = App::new("myprog") + /// .setting(AppSettings::PropagateGlobalValuesDown) + /// .arg(Arg::from_usage("[cmd] 'command to run'") + /// .global(true)) + /// .subcommand(SubCommand::with_name("foo")) + /// .get_matches_from(vec!["myprog", "set", "foo"]); + /// + /// assert_eq!(m.value_of("cmd"), Some("set")); + /// + /// let sub_m = m.subcommand_matches("foo").unwrap(); + /// assert_eq!(sub_m.value_of("cmd"), Some("set")); + /// ``` + /// Now doing the same thing, but *not* using any subcommands will result in the value not being + /// propagated down. + /// + /// ```rust + /// # use clap::{App, Arg, AppSettings, SubCommand}; + /// let m = App::new("myprog") + /// .setting(AppSettings::PropagateGlobalValuesDown) + /// .arg(Arg::from_usage("[cmd] 'command to run'") + /// .global(true)) + /// .subcommand(SubCommand::with_name("foo")) + /// .get_matches_from(vec!["myprog", "set"]); + /// + /// assert_eq!(m.value_of("cmd"), Some("set")); + /// + /// assert!(m.subcommand_matches("foo").is_none()); + /// ``` + PropagateGlobalValuesDown, + /// Allows [`SubCommand`]s to override all requirements of the parent command. /// For example if you had a subcommand or top level application with a required argument /// that is only required as long as there is no subcommand present, @@ -663,6 +848,21 @@ pub enum AppSettings { #[doc(hidden)] LowIndexMultiplePositional, + + #[doc(hidden)] + TrailingValues, + + #[doc(hidden)] + ValidNegNumFound, + + #[doc(hidden)] + Propogated, + + #[doc(hidden)] + ValidArgFound, + + #[doc(hidden)] + ContainsLast, } impl FromStr for AppSettings { @@ -670,6 +870,7 @@ impl FromStr for AppSettings { fn from_str(s: &str) -> Result::Err> { match &*s.to_ascii_lowercase() { "argrequiredelsehelp" => Ok(AppSettings::ArgRequiredElseHelp), + "argsnegatesubcommands" => Ok(AppSettings::ArgsNegateSubcommands), "allowinvalidutf8" => Ok(AppSettings::AllowInvalidUtf8), "allowleadinghyphen" => Ok(AppSettings::AllowLeadingHyphen), "allowexternalsubcommands" => Ok(AppSettings::AllowExternalSubcommands), @@ -679,11 +880,14 @@ impl FromStr for AppSettings { "colornever" => Ok(AppSettings::ColorNever), "coloredhelp" => Ok(AppSettings::ColoredHelp), "derivedisplayorder" => Ok(AppSettings::DeriveDisplayOrder), + "dontcollapseargsinusage" => Ok(AppSettings::DontCollapseArgsInUsage), "dontdelimittrailingvalues" => Ok(AppSettings::DontDelimitTrailingValues), + "disablehelpsubcommand" => Ok(AppSettings::DisableHelpSubcommand), "disableversion" => Ok(AppSettings::DisableVersion), "globalversion" => Ok(AppSettings::GlobalVersion), "hidden" => Ok(AppSettings::Hidden), "hidepossiblevaluesinhelp" => Ok(AppSettings::HidePossibleValuesInHelp), + "infersubcommands" => Ok(AppSettings::InferSubcommands), "lowindexmultiplepositional" => Ok(AppSettings::LowIndexMultiplePositional), "nobinaryname" => Ok(AppSettings::NoBinaryName), "nextlinehelp" => Ok(AppSettings::NextLineHelp), @@ -695,6 +899,10 @@ impl FromStr for AppSettings { "unifiedhelpmessage" => Ok(AppSettings::UnifiedHelpMessage), "versionlesssubcommands" => Ok(AppSettings::VersionlessSubcommands), "waitonerror" => Ok(AppSettings::WaitOnError), + "validnegnumfound" => Ok(AppSettings::ValidNegNumFound), + "validargfound" => Ok(AppSettings::ValidArgFound), + "propogated" => Ok(AppSettings::Propogated), + "trailingvalues" => Ok(AppSettings::TrailingValues), _ => Err("unknown AppSetting, cannot convert from str".to_owned()), } } @@ -706,6 +914,8 @@ mod test { #[test] fn app_settings_fromstr() { + assert_eq!("argsnegatesubcommands".parse::().unwrap(), + AppSettings::ArgsNegateSubcommands); assert_eq!("argrequiredelsehelp".parse::().unwrap(), AppSettings::ArgRequiredElseHelp); assert_eq!("allowexternalsubcommands".parse::().unwrap(), @@ -724,8 +934,12 @@ mod test { AppSettings::ColorAlways); assert_eq!("colornever".parse::().unwrap(), AppSettings::ColorNever); + assert_eq!("disablehelpsubcommand".parse::().unwrap(), + AppSettings::DisableHelpSubcommand); assert_eq!("disableversion".parse::().unwrap(), AppSettings::DisableVersion); + assert_eq!("dontcollapseargsinusage".parse::().unwrap(), + AppSettings::DontCollapseArgsInUsage); assert_eq!("dontdelimittrailingvalues".parse::().unwrap(), AppSettings::DontDelimitTrailingValues); assert_eq!("derivedisplayorder".parse::().unwrap(), @@ -758,6 +972,16 @@ mod test { AppSettings::VersionlessSubcommands); assert_eq!("waitonerror".parse::().unwrap(), AppSettings::WaitOnError); + assert_eq!("validnegnumfound".parse::().unwrap(), + AppSettings::ValidNegNumFound); + assert_eq!("validargfound".parse::().unwrap(), + AppSettings::ValidArgFound); + assert_eq!("propogated".parse::().unwrap(), + AppSettings::Propogated); + assert_eq!("trailingvalues".parse::().unwrap(), + AppSettings::TrailingValues); + assert_eq!("infersubcommands".parse::().unwrap(), + AppSettings::InferSubcommands); assert!("hahahaha".parse::().is_err()); } } diff --git a/src/vendor/clap/src/app/usage.rs b/src/vendor/clap/src/app/usage.rs new file mode 100644 index 0000000000..39489dc75a --- /dev/null +++ b/src/vendor/clap/src/app/usage.rs @@ -0,0 +1,439 @@ +// std +use std::collections::{BTreeMap, VecDeque}; + +// Internal +use INTERNAL_ERROR_MSG; +use args::{AnyArg, ArgMatcher, PosBuilder}; +use args::settings::ArgSettings; +use app::settings::AppSettings as AS; +use app::parser::Parser; + +// Creates a usage string for display. This happens just after all arguments were parsed, but before +// any subcommands have been parsed (so as to give subcommands their own usage recursively) +pub fn create_usage_with_title(p: &Parser, used: &[&str]) -> String { + debugln!("usage::create_usage_with_title;"); + let mut usage = String::with_capacity(75); + usage.push_str("USAGE:\n "); + usage.push_str(&*create_usage_no_title(p, used)); + usage +} + +// Creates a usage string to be used in error message (i.e. one with currently used args) +pub fn create_error_usage<'a, 'b>(p: &Parser<'a, 'b>, + matcher: &'b ArgMatcher<'a>, + extra: Option<&str>) + -> String { + let mut args: Vec<_> = matcher.arg_names() + .iter() + .filter(|n| { + if let Some(o) = find_by_name!(p, **n, opts, iter) { + !o.b.is_set(ArgSettings::Required) && !o.b.is_set(ArgSettings::Hidden) + } else if let Some(p) = find_by_name!(p, **n, positionals, values) { + !p.b.is_set(ArgSettings::Required) && p.b.is_set(ArgSettings::Hidden) + } else { + true // flags can't be required, so they're always true + } + }) + .map(|&n| n) + .collect(); + if let Some(r) = extra { + args.push(r); + } + create_usage_with_title(p, &*args) +} + +// Creates a usage string (*without title*) if one was not provided by the user manually. +pub fn create_usage_no_title(p: &Parser, used: &[&str]) -> String { + debugln!("usage::create_usage_no_title;"); + if let Some(u) = p.meta.usage_str { + String::from(&*u) + } else if used.is_empty() { + create_help_usage(p, true) + } else { + create_smart_usage(p, used) + } +} + +// Creates a usage string for display in help messages (i.e. not for errors) +pub fn create_help_usage(p: &Parser, incl_reqs: bool) -> String { + let mut usage = String::with_capacity(75); + let name = p.meta + .usage + .as_ref() + .unwrap_or_else(|| { + p.meta + .bin_name + .as_ref() + .unwrap_or(&p.meta.name) + }); + usage.push_str(&*name); + let req_string = if incl_reqs { + let mut reqs: Vec<&str> = p.required().map(|r| &**r).collect(); + reqs.sort(); + reqs.dedup(); + get_required_usage_from(p, &reqs, None, None, false).iter().fold(String::new(), |a, s| { + a + &format!(" {}", s)[..] + }) + } else { + String::new() + }; + + let flags = needs_flags_tag(p); + if flags && !p.is_set(AS::UnifiedHelpMessage) { + usage.push_str(" [FLAGS]"); + } else if flags { + usage.push_str(" [OPTIONS]"); + } + if !p.is_set(AS::UnifiedHelpMessage) && + p.opts.iter().any(|o| !o.is_set(ArgSettings::Required) && !o.is_set(ArgSettings::Hidden)) { + usage.push_str(" [OPTIONS]"); + } + + usage.push_str(&req_string[..]); + + let has_last = p.positionals.values().any(|p| p.is_set(ArgSettings::Last)); + // places a '--' in the usage string if there are args and options + // supporting multiple values + if p.opts.iter().any(|o| o.is_set(ArgSettings::Multiple)) && + p.positionals.values().any(|p| !p.is_set(ArgSettings::Required)) && + !p.has_visible_subcommands() && !has_last { + usage.push_str(" [--]"); + } + let not_req_or_hidden = + |p: &PosBuilder| (!p.is_set(ArgSettings::Required) || p.is_set(ArgSettings::Last)) && !p.is_set(ArgSettings::Hidden); + if p.has_positionals() && p.positionals.values().any(not_req_or_hidden) { + if let Some(args_tag) = get_args_tag(p, incl_reqs) { + usage.push_str(&*args_tag); + } else { + usage.push_str(" [ARGS]"); + } + if has_last && incl_reqs { + let pos = p.positionals + .values() + .find(|p| p.b.is_set(ArgSettings::Last)) + .expect(INTERNAL_ERROR_MSG); + debugln!("usage::create_help_usage: '{}' has .last(true)", pos.name()); + let req = pos.is_set(ArgSettings::Required); + if req && p.positionals.values().any(|p| !p.is_set(ArgSettings::Required)) { + usage.push_str(" -- <"); + } else if req { + usage.push_str(" [--] <"); + } else { + usage.push_str(" [-- <"); + } + usage.push_str(&*pos.name_no_brackets()); + usage.push_str(">"); + usage.push_str(pos.multiple_str()); + if !req { + usage.push_str("]"); + } + } + } + + // incl_reqs is only false when this function is called recursively + if p.has_visible_subcommands() && incl_reqs { + if p.is_set(AS::SubcommandsNegateReqs) || p.is_set(AS::ArgsNegateSubcommands) { + if !p.is_set(AS::ArgsNegateSubcommands) { + usage.push_str("\n "); + usage.push_str(&*create_help_usage(p, false)); + usage.push_str(" "); + } else { + usage.push_str("\n "); + usage.push_str(&*name); + usage.push_str(" "); + } + } else if p.is_set(AS::SubcommandRequired) || p.is_set(AS::SubcommandRequiredElseHelp) { + usage.push_str(" "); + } else { + usage.push_str(" [SUBCOMMAND]"); + } + } + usage.shrink_to_fit(); + debugln!("usage::create_help_usage: usage={}", usage); + usage +} + +// Creates a context aware usage string, or "smart usage" from currently used +// args, and requirements +fn create_smart_usage(p: &Parser, used: &[&str]) -> String { + debugln!("usage::smart_usage;"); + let mut usage = String::with_capacity(75); + let mut hs: Vec<&str> = p.required().map(|s| &**s).collect(); + hs.extend_from_slice(used); + + let r_string = + get_required_usage_from(p, &hs, None, None, false).iter().fold(String::new(), |acc, s| { + acc + &format!(" {}", s)[..] + }); + + usage.push_str(&p.meta + .usage + .as_ref() + .unwrap_or_else(|| { + p.meta + .bin_name + .as_ref() + .unwrap_or(&p.meta.name) + }) + [..]); + usage.push_str(&*r_string); + if p.is_set(AS::SubcommandRequired) { + usage.push_str(" "); + } + usage.shrink_to_fit(); + usage +} + +// Gets the `[ARGS]` tag for the usage string +fn get_args_tag(p: &Parser, incl_reqs: bool) -> Option { + debugln!("usage::get_args_tag;"); + let mut count = 0; + 'outer: for pos in p.positionals + .values() + .filter(|pos| !pos.is_set(ArgSettings::Required)) + .filter(|pos| !pos.is_set(ArgSettings::Hidden)) + .filter(|pos| !pos.is_set(ArgSettings::Last)) { + debugln!("usage::get_args_tag:iter:{}:", pos.b.name); + if let Some(g_vec) = p.groups_for_arg(pos.b.name) { + for grp_s in &g_vec { + debugln!("usage::get_args_tag:iter:{}:iter:{};", pos.b.name, grp_s); + // if it's part of a required group we don't want to count it + if p.groups.iter().any(|g| g.required && (&g.name == grp_s)) { + continue 'outer; + } + } + } + count += 1; + debugln!("usage::get_args_tag:iter: {} Args not required or hidden", + count); + } + if !p.is_set(AS::DontCollapseArgsInUsage) && count > 1 { + debugln!("usage::get_args_tag:iter: More than one, returning [ARGS]"); + return None; // [ARGS] + } else if count == 1 && incl_reqs { + let pos = p.positionals + .values() + .find(|pos| { + !pos.is_set(ArgSettings::Required) && !pos.is_set(ArgSettings::Hidden) && + !pos.is_set(ArgSettings::Last) + }) + .expect(INTERNAL_ERROR_MSG); + debugln!("usage::get_args_tag:iter: Exactly one, returning '{}'", + pos.name()); + return Some(format!(" [{}]{}", pos.name_no_brackets(), pos.multiple_str())); + } else if p.is_set(AS::DontCollapseArgsInUsage) && !p.positionals.is_empty() && incl_reqs { + debugln!("usage::get_args_tag:iter: Don't collapse returning all"); + return Some(p.positionals + .values() + .filter(|pos| !pos.is_set(ArgSettings::Required)) + .filter(|pos| !pos.is_set(ArgSettings::Hidden)) + .filter(|pos| !pos.is_set(ArgSettings::Last)) + .map(|pos| { + format!(" [{}]{}", pos.name_no_brackets(), pos.multiple_str()) + }) + .collect::>() + .join("")); + } else if !incl_reqs { + debugln!("usage::get_args_tag:iter: incl_reqs=false, building secondary usage string"); + let highest_req_pos = p.positionals + .iter() + .filter_map(|(idx, pos)| if pos.b.is_set(ArgSettings::Required) && + !pos.b.is_set(ArgSettings::Last) { + Some(idx) + } else { + None + }) + .max() + .unwrap_or_else(|| p.positionals.len()); + return Some(p.positionals + .iter() + .filter_map(|(idx, pos)| if idx <= highest_req_pos { + Some(pos) + } else { + None + }) + .filter(|pos| !pos.is_set(ArgSettings::Required)) + .filter(|pos| !pos.is_set(ArgSettings::Hidden)) + .filter(|pos| !pos.is_set(ArgSettings::Last)) + .map(|pos| { + format!(" [{}]{}", pos.name_no_brackets(), pos.multiple_str()) + }) + .collect::>() + .join("")); + } + Some("".into()) +} + +// Determines if we need the `[FLAGS]` tag in the usage string +fn needs_flags_tag(p: &Parser) -> bool { + debugln!("usage::needs_flags_tag;"); + 'outer: for f in &p.flags { + debugln!("usage::needs_flags_tag:iter: f={};", f.b.name); + if let Some(l) = f.s.long { + if l == "help" || l == "version" { + // Don't print `[FLAGS]` just for help or version + continue; + } + } + if let Some(g_vec) = p.groups_for_arg(f.b.name) { + for grp_s in &g_vec { + debugln!("usage::needs_flags_tag:iter:iter: grp_s={};", grp_s); + if p.groups.iter().any(|g| &g.name == grp_s && g.required) { + debugln!("usage::needs_flags_tag:iter:iter: Group is required"); + continue 'outer; + } + } + } + if f.is_set(ArgSettings::Hidden) { + continue; + } + debugln!("usage::needs_flags_tag:iter: [FLAGS] required"); + return true; + } + + debugln!("usage::needs_flags_tag: [FLAGS] not required"); + false +} + +// Returns the required args in usage string form by fully unrolling all groups +pub fn get_required_usage_from<'a, 'b>(p: &Parser<'a, 'b>, + reqs: &[&'a str], + matcher: Option<&ArgMatcher<'a>>, + extra: Option<&str>, + incl_last: bool) + -> VecDeque { + debugln!("usage::get_required_usage_from: reqs={:?}, extra={:?}", + reqs, + extra); + let mut desc_reqs: Vec<&str> = vec![]; + desc_reqs.extend(extra); + let mut new_reqs: Vec<&str> = vec![]; + macro_rules! get_requires { + (@group $a: ident, $v:ident, $p:ident) => {{ + if let Some(rl) = p.groups.iter() + .filter(|g| g.requires.is_some()) + .find(|g| &g.name == $a) + .map(|g| g.requires.as_ref().unwrap()) { + for r in rl { + if !$p.contains(&r) { + debugln!("usage::get_required_usage_from:iter:{}: adding group req={:?}", + $a, r); + $v.push(r); + } + } + } + }}; + ($a:ident, $what:ident, $how:ident, $v:ident, $p:ident) => {{ + if let Some(rl) = p.$what.$how() + .filter(|a| a.b.requires.is_some()) + .find(|arg| &arg.b.name == $a) + .map(|a| a.b.requires.as_ref().unwrap()) { + for &(_, r) in rl.iter() { + if !$p.contains(&r) { + debugln!("usage::get_required_usage_from:iter:{}: adding arg req={:?}", + $a, r); + $v.push(r); + } + } + } + }}; + } + // initialize new_reqs + for a in reqs { + get_requires!(a, flags, iter, new_reqs, reqs); + get_requires!(a, opts, iter, new_reqs, reqs); + get_requires!(a, positionals, values, new_reqs, reqs); + get_requires!(@group a, new_reqs, reqs); + } + desc_reqs.extend_from_slice(&*new_reqs); + debugln!("usage::get_required_usage_from: after init desc_reqs={:?}", + desc_reqs); + loop { + let mut tmp = vec![]; + for a in &new_reqs { + get_requires!(a, flags, iter, tmp, desc_reqs); + get_requires!(a, opts, iter, tmp, desc_reqs); + get_requires!(a, positionals, values, tmp, desc_reqs); + get_requires!(@group a, tmp, desc_reqs); + } + if tmp.is_empty() { + debugln!("usage::get_required_usage_from: no more children"); + break; + } else { + debugln!("usage::get_required_usage_from: after iter tmp={:?}", tmp); + debugln!("usage::get_required_usage_from: after iter new_reqs={:?}", + new_reqs); + desc_reqs.extend_from_slice(&*new_reqs); + new_reqs.clear(); + new_reqs.extend_from_slice(&*tmp); + debugln!("usage::get_required_usage_from: after iter desc_reqs={:?}", + desc_reqs); + } + } + desc_reqs.extend_from_slice(reqs); + desc_reqs.sort(); + desc_reqs.dedup(); + debugln!("usage::get_required_usage_from: final desc_reqs={:?}", + desc_reqs); + let mut ret_val = VecDeque::new(); + let args_in_groups = p.groups + .iter() + .filter(|gn| desc_reqs.contains(&gn.name)) + .flat_map(|g| p.arg_names_in_group(g.name)) + .collect::>(); + + let pmap = if let Some(m) = matcher { + desc_reqs.iter() + .filter(|a| p.positionals.values().any(|p| &&p.b.name == a)) + .filter(|&pos| !m.contains(pos)) + .filter_map(|pos| p.positionals.values().find(|x| &x.b.name == pos)) + .filter(|&pos| incl_last || !pos.is_set(ArgSettings::Last)) + .filter(|pos| !args_in_groups.contains(&pos.b.name)) + .map(|pos| (pos.index, pos)) + .collect::>() // sort by index + } else { + desc_reqs.iter() + .filter(|a| p.positionals.values().any(|pos| &&pos.b.name == a)) + .filter_map(|pos| p.positionals.values().find(|x| &x.b.name == pos)) + .filter(|&pos| incl_last || !pos.is_set(ArgSettings::Last)) + .filter(|pos| !args_in_groups.contains(&pos.b.name)) + .map(|pos| (pos.index, pos)) + .collect::>() // sort by index + }; + debugln!("usage::get_required_usage_from: args_in_groups={:?}", + args_in_groups); + for &p in pmap.values() { + let s = p.to_string(); + if args_in_groups.is_empty() || !args_in_groups.contains(&&*s) { + ret_val.push_back(s); + } + } + for a in desc_reqs.iter() + .filter(|name| !p.positionals.values().any(|p| &&p.b.name == name)) + .filter(|name| !p.groups.iter().any(|g| &&g.name == name)) + .filter(|name| !args_in_groups.contains(name)) + .filter(|name| !(matcher.is_some() && matcher.as_ref().unwrap().contains(name))) { + debugln!("usage::get_required_usage_from:iter:{}:", a); + let arg = find_by_name!(p, *a, flags, iter) + .map(|f| f.to_string()) + .unwrap_or_else(|| { + find_by_name!(p, *a, opts, iter) + .map(|o| o.to_string()) + .expect(INTERNAL_ERROR_MSG) + }); + ret_val.push_back(arg); + } + let mut g_vec: Vec = vec![]; + for g in desc_reqs.iter().filter(|n| p.groups.iter().any(|g| &&g.name == n)) { + let g_string = p.args_in_group(g).join("|"); + let elem = format!("<{}>", &g_string[..g_string.len()]); + if !g_vec.contains(&elem) { + g_vec.push(elem); + } + } + for g in g_vec { + ret_val.push_back(g); + } + + ret_val +} diff --git a/src/vendor/clap/src/app/validator.rs b/src/vendor/clap/src/app/validator.rs new file mode 100644 index 0000000000..47d9064469 --- /dev/null +++ b/src/vendor/clap/src/app/validator.rs @@ -0,0 +1,456 @@ +// std +use std::fmt::Display; + +// Internal +use INTERNAL_ERROR_MSG; +use INVALID_UTF8; +use args::{AnyArg, ArgMatcher, MatchedArg}; +use args::settings::ArgSettings; +use errors::{Error, ErrorKind}; +use errors::Result as ClapResult; +use osstringext::OsStrExt2; +use app::settings::AppSettings as AS; +use app::parser::{Parser, ParseResult}; +use fmt::{Colorizer, ColorizerOption}; +use app::usage; + +pub struct Validator<'a, 'b, 'z>(&'z mut Parser<'a, 'b>) + where 'a: 'b, + 'b: 'z; + +impl<'a, 'b, 'z> Validator<'a, 'b, 'z> { + pub fn new(p: &'z mut Parser<'a, 'b>) -> Self { Validator(p) } + + pub fn validate(&mut self, + needs_val_of: ParseResult<'a>, + subcmd_name: Option, + matcher: &mut ArgMatcher<'a>) + -> ClapResult<()> { + debugln!("Validator::validate;"); + let mut reqs_validated = false; + try!(self.0.add_defaults(matcher)); + if let ParseResult::Opt(a) = needs_val_of { + debugln!("Validator::validate: needs_val_of={:?}", a); + let o = self.0 + .opts + .iter() + .find(|o| o.b.name == a) + .expect(INTERNAL_ERROR_MSG); + try!(self.validate_required(matcher)); + reqs_validated = true; + let should_err = if let Some(v) = matcher.0.args.get(&*o.b.name) { + v.vals.is_empty() && !(o.v.min_vals.is_some() && o.v.min_vals.unwrap() == 0) + } else { + true + }; + if should_err { + return Err(Error::empty_value(o, + &*usage::create_error_usage(self.0, matcher, None), + self.0.color())); + } + } + + if matcher.is_empty() && matcher.subcommand_name().is_none() && + self.0.is_set(AS::ArgRequiredElseHelp) { + let mut out = vec![]; + try!(self.0.write_help_err(&mut out)); + return Err(Error { + message: String::from_utf8_lossy(&*out).into_owned(), + kind: ErrorKind::MissingArgumentOrSubcommand, + info: None, + }); + } + try!(self.validate_blacklist(matcher)); + if !(self.0.is_set(AS::SubcommandsNegateReqs) && subcmd_name.is_some()) && !reqs_validated { + try!(self.validate_required(matcher)); + } + try!(self.validate_matched_args(matcher)); + matcher.usage(usage::create_usage_with_title(self.0, &[])); + + Ok(()) + } + + fn validate_values(&self, + arg: &A, + ma: &MatchedArg, + matcher: &ArgMatcher<'a>) + -> ClapResult<()> + where A: AnyArg<'a, 'b> + Display + { + debugln!("Validator::validate_values: arg={:?}", arg.name()); + for val in &ma.vals { + if self.0.is_set(AS::StrictUtf8) && val.to_str().is_none() { + debugln!("Validator::validate_values: invalid UTF-8 found in val {:?}", + val); + return Err(Error::invalid_utf8(&*usage::create_error_usage(self.0, matcher, None), + self.0.color())); + } + if let Some(p_vals) = arg.possible_vals() { + debugln!("Validator::validate_values: possible_vals={:?}", p_vals); + let val_str = val.to_string_lossy(); + if !p_vals.contains(&&*val_str) { + return Err(Error::invalid_value(val_str, + p_vals, + arg, + &*usage::create_error_usage(self.0, + matcher, + None), + self.0.color())); + } + } + if !arg.is_set(ArgSettings::EmptyValues) && val.is_empty_() && + matcher.contains(&*arg.name()) { + debugln!("Validator::validate_values: illegal empty val found"); + return Err(Error::empty_value(arg, + &*usage::create_error_usage(self.0, matcher, None), + self.0.color())); + } + if let Some(vtor) = arg.validator() { + debug!("Validator::validate_values: checking validator..."); + if let Err(e) = vtor(val.to_string_lossy().into_owned()) { + sdebugln!("error"); + return Err(Error::value_validation(Some(arg), e, self.0.color())); + } else { + sdebugln!("good"); + } + } + if let Some(vtor) = arg.validator_os() { + debug!("Validator::validate_values: checking validator_os..."); + if let Err(e) = vtor(val) { + sdebugln!("error"); + return Err(Error::value_validation(Some(arg), + (*e).to_string_lossy().to_string(), + self.0.color())); + } else { + sdebugln!("good"); + } + } + } + Ok(()) + } + + fn validate_blacklist(&self, matcher: &mut ArgMatcher) -> ClapResult<()> { + debugln!("Validator::validate_blacklist: blacklist={:?}", + self.0.blacklist); + macro_rules! build_err { + ($p:expr, $name:expr, $matcher:ident) => ({ + debugln!("build_err!: name={}", $name); + let mut c_with = find_from!($p, &$name, blacklist, &$matcher); + c_with = c_with.or( + $p.find_any_arg(&$name).map_or(None, |aa| aa.blacklist()) + .map_or(None, + |bl| bl.iter().find(|arg| $matcher.contains(arg))) + .map_or(None, |an| $p.find_any_arg(an)) + .map_or(None, |aa| Some(format!("{}", aa))) + ); + debugln!("build_err!: '{:?}' conflicts with '{}'", c_with, &$name); + $matcher.remove(&$name); + let usg = usage::create_error_usage($p, $matcher, None); + if let Some(f) = find_by_name!($p, $name, flags, iter) { + debugln!("build_err!: It was a flag..."); + Error::argument_conflict(f, c_with, &*usg, self.0.color()) + } else if let Some(o) = find_by_name!($p, $name, opts, iter) { + debugln!("build_err!: It was an option..."); + Error::argument_conflict(o, c_with, &*usg, self.0.color()) + } else { + match find_by_name!($p, $name, positionals, values) { + Some(p) => { + debugln!("build_err!: It was a positional..."); + Error::argument_conflict(p, c_with, &*usg, self.0.color()) + }, + None => panic!(INTERNAL_ERROR_MSG) + } + } + }); + } + + for name in &self.0.blacklist { + debugln!("Validator::validate_blacklist:iter: Checking blacklisted name: {}", + name); + if self.0.groups.iter().any(|g| &g.name == name) { + debugln!("Validator::validate_blacklist:iter: groups contains it..."); + for n in self.0.arg_names_in_group(name) { + debugln!("Validator::validate_blacklist:iter:iter: Checking arg '{}' in group...", + n); + if matcher.contains(n) { + debugln!("Validator::validate_blacklist:iter:iter: matcher contains it..."); + return Err(build_err!(self.0, n, matcher)); + } + } + } else if matcher.contains(name) { + debugln!("Validator::validate_blacklist:iter: matcher contains it..."); + return Err(build_err!(self.0, *name, matcher)); + } + } + Ok(()) + } + + fn validate_matched_args(&self, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> { + debugln!("Validator::validate_matched_args;"); + for (name, ma) in matcher.iter() { + debugln!("Validator::validate_matched_args:iter:{}: vals={:#?}", + name, + ma.vals); + if let Some(opt) = find_by_name!(self.0, *name, opts, iter) { + try!(self.validate_arg_num_vals(opt, ma, matcher)); + try!(self.validate_values(opt, ma, matcher)); + try!(self.validate_arg_requires(opt, ma, matcher)); + try!(self.validate_arg_num_occurs(opt, ma, matcher)); + } else if let Some(flag) = find_by_name!(self.0, *name, flags, iter) { + try!(self.validate_arg_requires(flag, ma, matcher)); + try!(self.validate_arg_num_occurs(flag, ma, matcher)); + } else if let Some(pos) = find_by_name!(self.0, *name, positionals, values) { + try!(self.validate_arg_num_vals(pos, ma, matcher)); + try!(self.validate_arg_num_occurs(pos, ma, matcher)); + try!(self.validate_values(pos, ma, matcher)); + try!(self.validate_arg_requires(pos, ma, matcher)); + } else { + let grp = self.0 + .groups + .iter() + .find(|g| &g.name == name) + .expect(INTERNAL_ERROR_MSG); + if let Some(ref g_reqs) = grp.requires { + if g_reqs.iter().any(|&n| !matcher.contains(n)) { + return self.missing_required_error(matcher, None); + } + } + } + } + Ok(()) + } + + fn validate_arg_num_occurs(&self, + a: &A, + ma: &MatchedArg, + matcher: &ArgMatcher) + -> ClapResult<()> + where A: AnyArg<'a, 'b> + Display + { + debugln!("Validator::validate_arg_num_occurs: a={};", a.name()); + if ma.occurs > 1 && !a.is_set(ArgSettings::Multiple) { + // Not the first time, and we don't allow multiples + return Err(Error::unexpected_multiple_usage(a, + &*usage::create_error_usage(self.0, + matcher, + None), + self.0.color())); + } + Ok(()) + } + + fn validate_arg_num_vals(&self, + a: &A, + ma: &MatchedArg, + matcher: &ArgMatcher) + -> ClapResult<()> + where A: AnyArg<'a, 'b> + Display + { + debugln!("Validator::validate_arg_num_vals;"); + if let Some(num) = a.num_vals() { + debugln!("Validator::validate_arg_num_vals: num_vals set...{}", num); + let should_err = if a.is_set(ArgSettings::Multiple) { + ((ma.vals.len() as u64) % num) != 0 + } else { + num != (ma.vals.len() as u64) + }; + if should_err { + debugln!("Validator::validate_arg_num_vals: Sending error WrongNumberOfValues"); + return Err(Error::wrong_number_of_values(a, + num, + if a.is_set(ArgSettings::Multiple) { + (ma.vals.len() % num as usize) + } else { + ma.vals.len() + }, + if ma.vals.len() == 1 || + (a.is_set(ArgSettings::Multiple) && + (ma.vals.len() % num as usize) == + 1) { + "as" + } else { + "ere" + }, + &*usage::create_error_usage(self.0, + matcher, + None), + self.0.color())); + } + } + if let Some(num) = a.max_vals() { + debugln!("Validator::validate_arg_num_vals: max_vals set...{}", num); + if (ma.vals.len() as u64) > num { + debugln!("Validator::validate_arg_num_vals: Sending error TooManyValues"); + return Err(Error::too_many_values(ma.vals + .iter() + .last() + .expect(INTERNAL_ERROR_MSG) + .to_str() + .expect(INVALID_UTF8), + a, + &*usage::create_error_usage(self.0, + matcher, + None), + self.0.color())); + } + } + if let Some(num) = a.min_vals() { + debugln!("Validator::validate_arg_num_vals: min_vals set: {}", num); + if (ma.vals.len() as u64) < num { + debugln!("Validator::validate_arg_num_vals: Sending error TooFewValues"); + return Err(Error::too_few_values(a, + num, + ma.vals.len(), + &*usage::create_error_usage(self.0, + matcher, + None), + self.0.color())); + } + } + // Issue 665 (https://github.com/kbknapp/clap-rs/issues/665) + if a.takes_value() && !a.is_set(ArgSettings::EmptyValues) && ma.vals.is_empty() { + return Err(Error::empty_value(a, + &*usage::create_error_usage(self.0, matcher, None), + self.0.color())); + } + Ok(()) + } + + fn validate_arg_requires(&self, + a: &A, + ma: &MatchedArg, + matcher: &ArgMatcher) + -> ClapResult<()> + where A: AnyArg<'a, 'b> + Display + { + debugln!("Validator::validate_arg_requires;"); + if let Some(a_reqs) = a.requires() { + for &(val, name) in a_reqs.iter().filter(|&&(val, _)| val.is_some()) { + let missing_req = + |v| v == val.expect(INTERNAL_ERROR_MSG) && !matcher.contains(name); + if ma.vals.iter().any(missing_req) { + return self.missing_required_error(matcher, None); + } + } + } + Ok(()) + } + + fn validate_required(&self, matcher: &ArgMatcher) -> ClapResult<()> { + debugln!("Validator::validate_required: required={:?};", + self.0.required); + 'outer: for name in &self.0.required { + debugln!("Validator::validate_required:iter:{}:", name); + if matcher.contains(name) { + continue 'outer; + } + if let Some(a) = find_by_name!(self.0, *name, flags, iter) { + if self.is_missing_required_ok(a, matcher) { + continue 'outer; + } + } else if let Some(a) = find_by_name!(self.0, *name, opts, iter) { + if self.is_missing_required_ok(a, matcher) { + continue 'outer; + } + } else if let Some(a) = find_by_name!(self.0, *name, positionals, values) { + if self.is_missing_required_ok(a, matcher) { + continue 'outer; + } + } + return self.missing_required_error(matcher, None); + } + + // Validate the conditionally required args + for &(a, v, r) in &self.0.r_ifs { + if let Some(ma) = matcher.get(a) { + if matcher.get(r).is_none() && ma.vals.iter().any(|val| val == v) { + return self.missing_required_error(matcher, Some(r)); + } + } + } + Ok(()) + } + + fn validate_conflicts(&self, a: &A, matcher: &ArgMatcher) -> Option + where A: AnyArg<'a, 'b> + { + debugln!("Validator::validate_conflicts: a={:?};", a.name()); + a.blacklist() + .map(|bl| { + bl.iter() + .any(|conf| { + matcher.contains(conf) || + self.0 + .groups + .iter() + .find(|g| &g.name == conf) + .map_or(false, |g| g.args.iter().any(|arg| matcher.contains(arg))) + }) + }) + } + + fn validate_required_unless(&self, a: &A, matcher: &ArgMatcher) -> Option + where A: AnyArg<'a, 'b> + { + debugln!("Validator::validate_required_unless: a={:?};", a.name()); + macro_rules! check { + ($how:ident, $_self:expr, $a:ident, $m:ident) => {{ + $a.required_unless().map(|ru| { + ru.iter().$how(|n| { + $m.contains(n) || { + if let Some(grp) = $_self.groups.iter().find(|g| &g.name == n) { + grp.args.iter().any(|arg| $m.contains(arg)) + } else { + false + } + } + }) + }) + }}; + } + if a.is_set(ArgSettings::RequiredUnlessAll) { + check!(all, self.0, a, matcher) + } else { + check!(any, self.0, a, matcher) + } + } + + fn missing_required_error(&self, matcher: &ArgMatcher, extra: Option<&str>) -> ClapResult<()> { + debugln!("Validator::missing_required_error: extra={:?}", extra); + let c = Colorizer::new(ColorizerOption { + use_stderr: true, + when: self.0.color(), + }); + let mut reqs = self.0 + .required + .iter() + .map(|&r| &*r) + .collect::>(); + if let Some(r) = extra { + reqs.push(r); + } + reqs.retain(|n| !matcher.contains(n)); + reqs.dedup(); + debugln!("Validator::missing_required_error: reqs={:#?}", reqs); + let req_args = + usage::get_required_usage_from(self.0, &reqs[..], Some(matcher), extra, true) + .iter() + .fold(String::new(), + |acc, s| acc + &format!("\n {}", c.error(s))[..]); + debugln!("Validator::missing_required_error: req_args={:#?}", + req_args); + Err(Error::missing_required_argument(&*req_args, + &*usage::create_error_usage(self.0, matcher, extra), + self.0.color())) + } + + #[inline] + fn is_missing_required_ok(&self, a: &A, matcher: &ArgMatcher) -> bool + where A: AnyArg<'a, 'b> + { + debugln!("Validator::is_missing_required_ok: a={}", a.name()); + self.validate_conflicts(a, matcher).unwrap_or(false) || + self.validate_required_unless(a, matcher) + .unwrap_or(false) + } +} diff --git a/src/vendor/clap/src/args/any_arg.rs b/src/vendor/clap/src/args/any_arg.rs index 7446ea7f46..5f8615fcad 100644 --- a/src/vendor/clap/src/args/any_arg.rs +++ b/src/vendor/clap/src/args/any_arg.rs @@ -1,21 +1,20 @@ // Std use std::rc::Rc; use std::fmt as std_fmt; +use std::ffi::{OsStr, OsString}; // Third Party -use vec_map::VecMap; +use vec_map::{self, VecMap}; // Internal use args::settings::ArgSettings; -use args::ArgKind; #[doc(hidden)] pub trait AnyArg<'n, 'e>: std_fmt::Display { fn name(&self) -> &'n str; - fn id(&self) -> usize; fn overrides(&self) -> Option<&[&'e str]>; fn aliases(&self) -> Option>; - fn requires(&self) -> Option<&[&'e str]>; + fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]>; fn blacklist(&self) -> Option<&[&'e str]>; fn required_unless(&self) -> Option<&[&'e str]>; fn is_set(&self, ArgSettings) -> bool; @@ -26,15 +25,18 @@ pub trait AnyArg<'n, 'e>: std_fmt::Display { fn num_vals(&self) -> Option; fn possible_vals(&self) -> Option<&[&'e str]>; fn validator(&self) -> Option<&Rc Result<(), String>>>; + fn validator_os(&self) -> Option<&Rc Result<(), OsString>>>; fn short(&self) -> Option; fn long(&self) -> Option<&'e str>; fn val_delim(&self) -> Option; fn takes_value(&self) -> bool; fn val_names(&self) -> Option<&VecMap<&'e str>>; fn help(&self) -> Option<&'e str>; - fn default_val(&self) -> Option<&'n str>; + fn long_help(&self) -> Option<&'e str>; + fn default_val(&self) -> Option<&'e OsStr>; + fn default_vals_ifs(&self) -> Option, &'e OsStr)>>; fn longest_filter(&self) -> bool; - fn kind(&self) -> ArgKind; + fn val_terminator(&self) -> Option<&'e str>; } pub trait DispOrder { diff --git a/src/vendor/clap/src/args/arg.rs b/src/vendor/clap/src/args/arg.rs index 7f21ad7c17..9e81911fab 100644 --- a/src/vendor/clap/src/args/arg.rs +++ b/src/vendor/clap/src/args/arg.rs @@ -1,13 +1,20 @@ #[cfg(feature = "yaml")] use std::collections::BTreeMap; use std::rc::Rc; +use std::ffi::{OsString, OsStr}; +#[cfg(target_os="windows")] +use osstringext::OsStrExt3; +#[cfg(not(target_os="windows"))] +use std::os::unix::ffi::OsStrExt; + #[cfg(feature = "yaml")] use yaml_rust::Yaml; use vec_map::VecMap; use usage_parser::UsageParser; -use args::settings::{ArgFlags, ArgSettings}; +use args::settings::ArgSettings; +use args::arg_builder::{Base, Valued, Switched}; /// The abstract representation of a command line argument. Used to set all the options and /// relationships that define a valid argument for the program. @@ -32,82 +39,22 @@ use args::settings::{ArgFlags, ArgSettings}; /// ``` /// [`Arg`]: ./struct.Arg.html #[allow(missing_debug_implementations)] +#[derive(Default, Clone)] pub struct Arg<'a, 'b> where 'a: 'b { #[doc(hidden)] - pub name: &'a str, - #[doc(hidden)] - pub short: Option, - #[doc(hidden)] - pub long: Option<&'b str>, + pub b: Base<'a, 'b>, #[doc(hidden)] - pub aliases: Option>, // (name, visible) + pub s: Switched<'b>, #[doc(hidden)] - pub help: Option<&'b str>, + pub v: Valued<'a, 'b>, #[doc(hidden)] pub index: Option, #[doc(hidden)] - pub blacklist: Option>, - #[doc(hidden)] - pub possible_vals: Option>, - #[doc(hidden)] - pub requires: Option>, - #[doc(hidden)] - pub groups: Option>, - #[doc(hidden)] - pub val_names: Option>, - #[doc(hidden)] - pub num_vals: Option, - #[doc(hidden)] - pub max_vals: Option, - #[doc(hidden)] - pub min_vals: Option, - #[doc(hidden)] - pub validator: Option Result<(), String>>>, - #[doc(hidden)] - pub overrides: Option>, - #[doc(hidden)] - pub settings: ArgFlags, - #[doc(hidden)] - pub val_delim: Option, - #[doc(hidden)] - pub default_val: Option<&'a str>, - #[doc(hidden)] - pub disp_ord: usize, - #[doc(hidden)] - pub r_unless: Option>, + pub r_ifs: Option>, } -impl<'a, 'b> Default for Arg<'a, 'b> { - fn default() -> Self { - Arg { - name: "".as_ref(), - short: None, - long: None, - aliases: None, - help: None, - index: None, - blacklist: None, - possible_vals: None, - requires: None, - groups: None, - val_names: None, - num_vals: None, - max_vals: None, - min_vals: None, - validator: None, - overrides: None, - settings: ArgFlags::new(), - val_delim: None, - default_val: None, - disp_ord: 999, - r_unless: None, - } - } -} - - impl<'a, 'b> Arg<'a, 'b> { /// Creates a new instance of [`Arg`] using a unique string name. The name will be used to get /// information about whether or not the argument was used at runtime, get values, set @@ -126,7 +73,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// ``` /// [`Arg::takes_value(true)`]: ./struct.Arg.html#method.takes_value /// [`Arg`]: ./struct.Arg.html - pub fn with_name(n: &'a str) -> Self { Arg { name: n, ..Default::default() } } + pub fn with_name(n: &'a str) -> Self { Arg { b: Base::new(n), ..Default::default() } } /// Creates a new instance of [`Arg`] from a .yml (YAML) file. /// @@ -156,7 +103,10 @@ impl<'a, 'b> Arg<'a, 'b> { "long" => yaml_to_str!(a, v, long), "aliases" => yaml_vec_or_str!(v, a, alias), "help" => yaml_to_str!(a, v, help), + "long_help" => yaml_to_str!(a, v, long_help), "required" => yaml_to_bool!(a, v, required), + "required_if" => yaml_tuple2!(a, v, required_if), + "required_ifs" => yaml_tuple2!(a, v, required_if), "takes_value" => yaml_to_bool!(a, v, takes_value), "index" => yaml_to_u64!(a, v, index), "global" => yaml_to_bool!(a, v, global), @@ -176,9 +126,13 @@ impl<'a, 'b> Arg<'a, 'b> { "required_unless" => yaml_to_str!(a, v, required_unless), "display_order" => yaml_to_usize!(a, v, display_order), "default_value" => yaml_to_str!(a, v, default_value), + "default_value_if" => yaml_tuple3!(a, v, default_value_if), + "default_value_ifs" => yaml_tuple3!(a, v, default_value_if), "value_names" => yaml_vec_or_str!(v, a, value_name), "groups" => yaml_vec_or_str!(v, a, group), "requires" => yaml_vec_or_str!(v, a, requires), + "requires_if" => yaml_tuple2!(a, v, requires_if), + "requires_ifs" => yaml_tuple2!(a, v, requires_if), "conflicts_with" => yaml_vec_or_str!(v, a, conflicts_with), "overrides_with" => yaml_vec_or_str!(v, a, overrides_with), "possible_values" => yaml_vec_or_str!(v, a, possible_value), @@ -320,7 +274,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// App::new("myprog") + /// App::new("prog") /// .args(&[ /// Arg::from_usage("--config 'a required file for the configuration and no short'"), /// Arg::from_usage("-d, --debug... 'turns on debugging information and allows multiples'"), @@ -361,18 +315,18 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("shorttest") + /// let m = App::new("prog") /// .arg(Arg::with_name("config") /// .short("c")) /// .get_matches_from(vec![ - /// "shorttest", "-c" + /// "prog", "-c" /// ]); /// /// assert!(m.is_present("config")); /// ``` /// [`short`]: ./struct.Arg.html#method.short pub fn short>(mut self, s: S) -> Self { - self.short = s.as_ref().trim_left_matches(|c| c == '-').chars().nth(0); + self.s.short = s.as_ref().trim_left_matches(|c| c == '-').chars().nth(0); self } @@ -402,17 +356,17 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("longtest") + /// let m = App::new("prog") /// .arg(Arg::with_name("cfg") /// .long("config")) /// .get_matches_from(vec![ - /// "longtest", "--config" + /// "prog", "--config" /// ]); /// /// assert!(m.is_present("cfg")); /// ``` pub fn long(mut self, l: &'b str) -> Self { - self.long = Some(l.trim_left_matches(|c| c == '-')); + self.s.long = Some(l.trim_left_matches(|c| c == '-')); self } @@ -425,21 +379,23 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("myprog") + /// let m = App::new("prog") /// .arg(Arg::with_name("test") /// .long("test") /// .alias("alias") /// .takes_value(true)) - /// .get_matches_from(vec!["myprog", "--alias", "cool"]); + /// .get_matches_from(vec![ + /// "prog", "--alias", "cool" + /// ]); /// assert!(m.is_present("test")); /// assert_eq!(m.value_of("test"), Some("cool")); /// ``` /// [`Arg`]: ./struct.Arg.html pub fn alias>(mut self, name: S) -> Self { - if let Some(ref mut als) = self.aliases { + if let Some(ref mut als) = self.s.aliases { als.push((name.into(), false)); } else { - self.aliases = Some(vec![(name.into(), false)]); + self.s.aliases = Some(vec![(name.into(), false)]); } self } @@ -453,23 +409,25 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("myprog") + /// let m = App::new("prog") /// .arg(Arg::with_name("test") /// .long("test") /// .aliases(&["do-stuff", "do-tests", "tests"]) /// .help("the file to add") /// .required(false)) - /// .get_matches_from(vec!["myprog", "--do-tests"]); + /// .get_matches_from(vec![ + /// "prog", "--do-tests" + /// ]); /// assert!(m.is_present("test")); /// ``` /// [`Arg`]: ./struct.Arg.html pub fn aliases(mut self, names: &[&'b str]) -> Self { - if let Some(ref mut als) = self.aliases { + if let Some(ref mut als) = self.s.aliases { for n in names { als.push((n, false)); } } else { - self.aliases = Some(names.iter().map(|n| (*n, false)).collect::>()); + self.s.aliases = Some(names.iter().map(|n| (*n, false)).collect::>()); } self } @@ -481,22 +439,24 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("myprog") + /// let m = App::new("prog") /// .arg(Arg::with_name("test") /// .visible_alias("something-awesome") /// .long("test") /// .takes_value(true)) - /// .get_matches_from(vec!["myprog", "--something-awesome", "coffee"]); + /// .get_matches_from(vec![ + /// "prog", "--something-awesome", "coffee" + /// ]); /// assert!(m.is_present("test")); /// assert_eq!(m.value_of("test"), Some("coffee")); /// ``` /// [`Arg`]: ./struct.Arg.html /// [`App::alias`]: ./struct.Arg.html#method.alias pub fn visible_alias>(mut self, name: S) -> Self { - if let Some(ref mut als) = self.aliases { + if let Some(ref mut als) = self.s.aliases { als.push((name.into(), true)); } else { - self.aliases = Some(vec![(name.into(), true)]); + self.s.aliases = Some(vec![(name.into(), true)]); } self } @@ -508,28 +468,36 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("myprog") + /// let m = App::new("prog") /// .arg(Arg::with_name("test") /// .long("test") /// .visible_aliases(&["something", "awesome", "cool"])) - /// .get_matches_from(vec!["myprog", "--awesome"]); + /// .get_matches_from(vec![ + /// "prog", "--awesome" + /// ]); /// assert!(m.is_present("test")); /// ``` /// [`Arg`]: ./struct.Arg.html /// [`App::aliases`]: ./struct.Arg.html#method.aliases pub fn visible_aliases(mut self, names: &[&'b str]) -> Self { - if let Some(ref mut als) = self.aliases { + if let Some(ref mut als) = self.s.aliases { for n in names { als.push((n, true)); } } else { - self.aliases = Some(names.iter().map(|n| (*n, true)).collect::>()); + self.s.aliases = Some(names.iter().map(|n| (*n, true)).collect::>()); } self } - /// Sets the help text of the argument that will be displayed to the user when they print the - /// usage/help information. + /// Sets the short help text of the argument that will be displayed to the user when they print + /// the help information with `-h`. Typically, this is a short (one line) description of the + /// arg. + /// + /// **NOTE:** If only `Arg::help` is provided, and not [`Arg::long_help`] but the user requests + /// `--help` clap will still display the contents of `help` appropriately + /// + /// **NOTE:** Only `Arg::help` is used in completion script generation in order to be concise /// /// # Examples /// @@ -549,12 +517,12 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("helptest") + /// let m = App::new("prog") /// .arg(Arg::with_name("cfg") /// .long("config") /// .help("Some help text describing the --config arg")) /// .get_matches_from(vec![ - /// "shorttest", "--help" + /// "prog", "--help" /// ]); /// ``` /// @@ -571,11 +539,163 @@ impl<'a, 'b> Arg<'a, 'b> { /// -h, --help Prints help information /// -V, --version Prints version information /// ``` + /// [`Arg::long_help`]: ./struct.Arg.html#method.long_help pub fn help(mut self, h: &'b str) -> Self { - self.help = Some(h); + self.b.help = Some(h); + self + } + + /// Sets the long help text of the argument that will be displayed to the user when they print + /// the help information with `--help`. Typically this a more detailed (multi-line) message + /// that describes the arg. + /// + /// **NOTE:** If only `long_help` is provided, and not [`Arg::help`] but the user requests `-h` + /// clap will still display the contents of `long_help` appropriately + /// + /// **NOTE:** Only [`Arg::help`] is used in completion script generation in order to be concise + /// + /// # Examples + /// + /// Any valid UTF-8 is allowed in the help text. The one exception is when one wishes to + /// include a newline in the help text and have the following text be properly aligned with all + /// the other help text. + /// + /// ```rust + /// # use clap::{App, Arg}; + /// Arg::with_name("config") + /// .long_help( + /// "The config file used by the myprog must be in JSON format + /// with only valid keys and may not contain other nonsense + /// that cannot be read by this program. Obviously I'm going on + /// and on, so I'll stop now.") + /// # ; + /// ``` + /// + /// Setting `help` displays a short message to the side of the argument when the user passes + /// `-h` or `--help` (by default). + /// + /// ```rust + /// # use clap::{App, Arg}; + /// let m = App::new("prog") + /// .arg(Arg::with_name("cfg") + /// .long("config") + /// .long_help( + /// "The config file used by the myprog must be in JSON format + /// with only valid keys and may not contain other nonsense + /// that cannot be read by this program. Obviously I'm going on + /// and on, so I'll stop now.")) + /// .get_matches_from(vec![ + /// "prog", "--help" + /// ]); + /// ``` + /// + /// The above example displays + /// + /// ```notrust + /// helptest + /// + /// USAGE: + /// helptest [FLAGS] + /// + /// FLAGS: + /// --config + /// The config file used by the myprog must be in JSON format + /// with only valid keys and may not contain other nonsense + /// that cannot be read by this program. Obviously I'm going on + /// and on, so I'll stop now. + /// + /// -h, --help + /// Prints help information + /// + /// -V, --version + /// Prints version information + /// ``` + /// [`Arg::help`]: ./struct.Arg.html#method.help + pub fn long_help(mut self, h: &'b str) -> Self { + self.b.long_help = Some(h); self } + /// Specifies that this arg is the last, or final, positional argument (i.e. has the highest + /// index) and is *only* able to be accessed via the `--` syntax (i.e. `$ prog args -- + /// last_arg`). Even, if no other arguments are left to parse, if the user omits the `--` syntax + /// they will receive an [`UnknownArgument`] error. Setting an argument to `.last(true)` also + /// allows one to access this arg early using the `--` syntax. Accessing an arg early, even with + /// the `--` syntax is otherwise not possible. + /// + /// **NOTE:** This will change the usage string to look like `$ prog [FLAGS] [-- ]` if + /// `ARG` is marked as `.last(true)`. + /// + /// **NOTE:** This setting will imply [`AppSettings::DontCollapseArgsInUsage`] because failing + /// to set this can make the usage string very confusing. + /// + /// **NOTE**: This setting only applies to positional arguments, and has no affect on FLAGS / + /// OPTIONS + /// + /// **CAUTION:** Setting an argument to `.last(true)` *and* having child subcommands is not + /// recommended with the exception of *also* using [`AppSettings::ArgsNegateSubcommands`] + /// (or [`AppSettings::SubcommandsNegateReqs`] if the argument marked `.last(true)` is also + /// marked [`.required(true)`]) + /// + /// # Examples + /// + /// ```rust + /// # use clap::Arg; + /// Arg::with_name("args") + /// .last(true) + /// # ; + /// ``` + /// + /// Setting [`Arg::last(true)`] ensures the arg has the highest [index] of all positional args + /// and requires that the `--` syntax be used to access it early. + /// + /// ```rust + /// # use clap::{App, Arg}; + /// let res = App::new("prog") + /// .arg(Arg::with_name("first")) + /// .arg(Arg::with_name("second")) + /// .arg(Arg::with_name("third").last(true)) + /// .get_matches_from_safe(vec![ + /// "prog", "one", "--", "three" + /// ]); + /// + /// assert!(res.is_ok()); + /// let m = res.unwrap(); + /// assert_eq!(m.value_of("third"), Some("three")); + /// assert!(m.value_of("second").is_none()); + /// ``` + /// + /// Even if the positional argument marked `.last(true)` is the only argument left to parse, + /// failing to use the `--` syntax results in an error. + /// + /// ```rust + /// # use clap::{App, Arg, ErrorKind}; + /// let res = App::new("prog") + /// .arg(Arg::with_name("first")) + /// .arg(Arg::with_name("second")) + /// .arg(Arg::with_name("third").last(true)) + /// .get_matches_from_safe(vec![ + /// "prog", "one", "two", "three" + /// ]); + /// + /// assert!(res.is_err()); + /// assert_eq!(res.unwrap_err().kind, ErrorKind::UnknownArgument); + /// ``` + /// [`Arg::last(true)`]: ./struct.Arg.html#method.last + /// [index]: ./struct.Arg.html#method.index + /// [`AppSettings::DontCollapseArgsInUsage`]: ./enum.AppSettings.html#variant.DontCollapseArgsInUsage + /// [`AppSettings::ArgsNegateSubcommands`]: ./enum.AppSettings.html#variant.ArgsNegateSubcommands + /// [`AppSettings::SubcommandsNegateReqs`]: ./enum.AppSettings.html#variant.SubcommandsNegateReqs + /// [`.required(true)`]: ./struct.Arg.html#method.required + /// [`UnknownArgument`]: ./enum.ErrorKind.html#variant.UnknownArgument + pub fn last(self, l: bool) -> Self { + if l { + self.set(ArgSettings::Last) + } else { + self.unset(ArgSettings::Last) + } + } + /// Sets whether or not the argument is required by default. Required by default means it is /// required, when no other conflicting rules have been evaluated. Conflicting rules take /// precedence over being required. **Default:** `false` @@ -598,13 +718,13 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let res = App::new("longtest") + /// let res = App::new("prog") /// .arg(Arg::with_name("cfg") /// .required(true) /// .takes_value(true) /// .long("config")) /// .get_matches_from_safe(vec![ - /// "shorttest", "--config", "file.conf" + /// "prog", "--config", "file.conf" /// ]); /// /// assert!(res.is_ok()); @@ -614,13 +734,13 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let res = App::new("longtest") + /// let res = App::new("prog") /// .arg(Arg::with_name("cfg") /// .required(true) /// .takes_value(true) /// .long("config")) /// .get_matches_from_safe(vec![ - /// "shorttest" + /// "prog" /// ]); /// /// assert!(res.is_err()); @@ -635,8 +755,76 @@ impl<'a, 'b> Arg<'a, 'b> { } } + /// Requires that options use the `--option=val` syntax (i.e. an equals between the option and + /// associated value) **Default:** `false` + /// + /// **NOTE:** This setting also removes the default of allowing empty values and implies + /// [`Arg::empty_values(false)`]. + /// + /// # Examples + /// + /// ```rust + /// # use clap::Arg; + /// Arg::with_name("config") + /// .long("config") + /// .takes_value(true) + /// .require_equals(true) + /// # ; + /// ``` + /// + /// Setting [`Arg::require_equals(true)`] requires that the option have an equals sign between + /// it and the associated value. + /// + /// ```rust + /// # use clap::{App, Arg}; + /// let res = App::new("prog") + /// .arg(Arg::with_name("cfg") + /// .require_equals(true) + /// .takes_value(true) + /// .long("config")) + /// .get_matches_from_safe(vec![ + /// "prog", "--config=file.conf" + /// ]); + /// + /// assert!(res.is_ok()); + /// ``` + /// + /// Setting [`Arg::require_equals(true)`] and *not* supplying the equals will cause an error + /// unless [`Arg::empty_values(true)`] is set. + /// + /// ```rust + /// # use clap::{App, Arg, ErrorKind}; + /// let res = App::new("prog") + /// .arg(Arg::with_name("cfg") + /// .require_equals(true) + /// .takes_value(true) + /// .long("config")) + /// .get_matches_from_safe(vec![ + /// "prog", "--config", "file.conf" + /// ]); + /// + /// assert!(res.is_err()); + /// assert_eq!(res.unwrap_err().kind, ErrorKind::EmptyValue); + /// ``` + /// [`Arg::require_equals(true)`]: ./struct.Arg.html#method.require_equals + /// [`Arg::empty_values(true)`]: ./struct.Arg.html#method.empty_values + /// [`Arg::empty_values(false)`]: ./struct.Arg.html#method.empty_values + pub fn require_equals(mut self, r: bool) -> Self { + if r { + self.unsetb(ArgSettings::EmptyValues); + self.set(ArgSettings::RequireEquals) + } else { + self.unset(ArgSettings::RequireEquals) + } + } + /// Allows values which start with a leading hyphen (`-`) /// + /// **WARNING**: Take caution when using this setting, combined with [`Arg::multiple(true)`] as + /// it this becomes ambigous `$ prog --arg -- -- val`. All three `--, --, val` will be values + /// when the user may have thought the second `--` would constitute the normal, "Only + /// positional args follow" idiom. To fix this, consider using [`Arg::number_of_values(1)`] + /// /// **WARNING**: When building your CLIs, consider the effects of allowing leading hyphens and /// the user passing in a value that matches a valid short. For example `prog -opt -F` where /// `-F` is supposed to be a value, yet `-F` is *also* a valid short for anther arg. Care should @@ -655,13 +843,13 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("pattest") + /// let m = App::new("prog") /// .arg(Arg::with_name("pat") /// .allow_hyphen_values(true) /// .takes_value(true) /// .long("pattern")) /// .get_matches_from(vec![ - /// "pattest", "--pattern", "-file" + /// "prog", "--pattern", "-file" /// ]); /// /// assert_eq!(m.value_of("pat"), Some("-file")); @@ -672,18 +860,20 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let res = App::new("pattest") + /// let res = App::new("prog") /// .arg(Arg::with_name("pat") /// .takes_value(true) /// .long("pattern")) /// .get_matches_from_safe(vec![ - /// "pattest", "--pattern", "-file" + /// "prog", "--pattern", "-file" /// ]); /// /// assert!(res.is_err()); /// assert_eq!(res.unwrap_err().kind, ErrorKind::UnknownArgument); /// ``` /// [`Arg::allow_hyphen_values(true)`]: ./struct.Arg.html#method.allow_hyphen_values + /// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple + /// [`Arg::number_of_values(1)`]: ./struct.Arg.html#method.number_of_values pub fn allow_hyphen_values(self, a: bool) -> Self { if a { self.set(ArgSettings::AllowLeadingHyphen) @@ -712,7 +902,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let res = App::new("unlesstest") + /// let res = App::new("prog") /// .arg(Arg::with_name("cfg") /// .required_unless("dbg") /// .takes_value(true) @@ -720,7 +910,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// .arg(Arg::with_name("dbg") /// .long("debug")) /// .get_matches_from_safe(vec![ - /// "unlesstest", "--debug" + /// "prog", "--debug" /// ]); /// /// assert!(res.is_ok()); @@ -730,7 +920,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let res = App::new("unlesstest") + /// let res = App::new("prog") /// .arg(Arg::with_name("cfg") /// .required_unless("dbg") /// .takes_value(true) @@ -738,7 +928,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// .arg(Arg::with_name("dbg") /// .long("debug")) /// .get_matches_from_safe(vec![ - /// "unlesstest" + /// "prog" /// ]); /// /// assert!(res.is_err()); @@ -748,10 +938,10 @@ impl<'a, 'b> Arg<'a, 'b> { /// [`Arg::required`]: ./struct.Arg.html#method.required /// [`Arg::required_unless(name)`]: ./struct.Arg.html#method.required_unless pub fn required_unless(mut self, name: &'a str) -> Self { - if let Some(ref mut vec) = self.r_unless { + if let Some(ref mut vec) = self.b.r_unless { vec.push(name); } else { - self.r_unless = Some(vec![name]); + self.b.r_unless = Some(vec![name]); } self.required(true) } @@ -778,7 +968,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let res = App::new("unlessall") + /// let res = App::new("prog") /// .arg(Arg::with_name("cfg") /// .required_unless_all(&["dbg", "infile"]) /// .takes_value(true) @@ -789,7 +979,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// .short("i") /// .takes_value(true)) /// .get_matches_from_safe(vec![ - /// "unlessall", "--debug", "-i", "file" + /// "prog", "--debug", "-i", "file" /// ]); /// /// assert!(res.is_ok()); @@ -800,7 +990,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let res = App::new("unlessall") + /// let res = App::new("prog") /// .arg(Arg::with_name("cfg") /// .required_unless_all(&["dbg", "infile"]) /// .takes_value(true) @@ -811,7 +1001,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// .short("i") /// .takes_value(true)) /// .get_matches_from_safe(vec![ - /// "unlessall" + /// "prog" /// ]); /// /// assert!(res.is_err()); @@ -820,12 +1010,12 @@ impl<'a, 'b> Arg<'a, 'b> { /// [`Arg::required_unless_one`]: ./struct.Arg.html#method.required_unless_one /// [`Arg::required_unless_all(names)`]: ./struct.Arg.html#method.required_unless_all pub fn required_unless_all(mut self, names: &[&'a str]) -> Self { - if let Some(ref mut vec) = self.r_unless { + if let Some(ref mut vec) = self.b.r_unless { for s in names { vec.push(s); } } else { - self.r_unless = Some(names.iter().map(|s| *s).collect::>()); + self.b.r_unless = Some(names.iter().map(|s| *s).collect::>()); } self.setb(ArgSettings::RequiredUnlessAll); self.required(true) @@ -853,7 +1043,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let res = App::new("unlessone") + /// let res = App::new("prog") /// .arg(Arg::with_name("cfg") /// .required_unless_one(&["dbg", "infile"]) /// .takes_value(true) @@ -864,7 +1054,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// .short("i") /// .takes_value(true)) /// .get_matches_from_safe(vec![ - /// "unlessone", "--debug" + /// "prog", "--debug" /// ]); /// /// assert!(res.is_ok()); @@ -875,7 +1065,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let res = App::new("unlessone") + /// let res = App::new("prog") /// .arg(Arg::with_name("cfg") /// .required_unless_one(&["dbg", "infile"]) /// .takes_value(true) @@ -886,7 +1076,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// .short("i") /// .takes_value(true)) /// .get_matches_from_safe(vec![ - /// "unlessone" + /// "prog" /// ]); /// /// assert!(res.is_err()); @@ -896,12 +1086,12 @@ impl<'a, 'b> Arg<'a, 'b> { /// [`Arg::required_unless_one(names)`]: ./struct.Arg.html#method.required_unless_one /// [`Arg::required_unless_all`]: ./struct.Arg.html#method.required_unless_all pub fn required_unless_one(mut self, names: &[&'a str]) -> Self { - if let Some(ref mut vec) = self.r_unless { + if let Some(ref mut vec) = self.b.r_unless { for s in names { vec.push(s); } } else { - self.r_unless = Some(names.iter().map(|s| *s).collect::>()); + self.b.r_unless = Some(names.iter().map(|s| *s).collect::>()); } self.required(true) } @@ -929,7 +1119,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let res = App::new("conflictions") + /// let res = App::new("prog") /// .arg(Arg::with_name("cfg") /// .takes_value(true) /// .conflicts_with("debug") @@ -937,17 +1127,17 @@ impl<'a, 'b> Arg<'a, 'b> { /// .arg(Arg::with_name("debug") /// .long("debug")) /// .get_matches_from_safe(vec![ - /// "conflictions", "--debug", "--config", "file.conf" + /// "prog", "--debug", "--config", "file.conf" /// ]); /// /// assert!(res.is_err()); /// assert_eq!(res.unwrap_err().kind, ErrorKind::ArgumentConflict); /// ``` pub fn conflicts_with(mut self, name: &'a str) -> Self { - if let Some(ref mut vec) = self.blacklist { + if let Some(ref mut vec) = self.b.blacklist { vec.push(name); } else { - self.blacklist = Some(vec![name]); + self.b.blacklist = Some(vec![name]); } self } @@ -976,7 +1166,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let res = App::new("conflictions") + /// let res = App::new("prog") /// .arg(Arg::with_name("cfg") /// .takes_value(true) /// .conflicts_with_all(&["debug", "input"]) @@ -986,7 +1176,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// .arg(Arg::with_name("input") /// .index(1)) /// .get_matches_from_safe(vec![ - /// "conflictions", "--config", "file.conf", "file.txt" + /// "prog", "--config", "file.conf", "file.txt" /// ]); /// /// assert!(res.is_err()); @@ -994,12 +1184,12 @@ impl<'a, 'b> Arg<'a, 'b> { /// ``` /// [`Arg::conflicts_with`]: ./struct.Arg.html#method.conflicts_with pub fn conflicts_with_all(mut self, names: &[&'a str]) -> Self { - if let Some(ref mut vec) = self.blacklist { + if let Some(ref mut vec) = self.b.blacklist { for s in names { vec.push(s); } } else { - self.blacklist = Some(names.iter().map(|s| *s).collect::>()); + self.b.blacklist = Some(names.iter().map(|s| *s).collect::>()); } self } @@ -1015,14 +1205,15 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("posix") + /// let m = App::new("prog") /// .arg(Arg::from_usage("-f, --flag 'some flag'") /// .conflicts_with("debug")) /// .arg(Arg::from_usage("-d, --debug 'other flag'")) /// .arg(Arg::from_usage("-c, --color 'third flag'") /// .overrides_with("flag")) - /// .get_matches_from(vec!["posix", "-f", "-d", "-c"]); - /// // ^~~~~~~~~~~~^~~~~ flag is overridden by color + /// .get_matches_from(vec![ + /// "prog", "-f", "-d", "-c"]); + /// // ^~~~~~~~~~~~^~~~~ flag is overridden by color /// /// assert!(m.is_present("color")); /// assert!(m.is_present("debug")); // even though flag conflicts with debug, it's as if flag @@ -1030,10 +1221,10 @@ impl<'a, 'b> Arg<'a, 'b> { /// assert!(!m.is_present("flag")); /// ``` pub fn overrides_with(mut self, name: &'a str) -> Self { - if let Some(ref mut vec) = self.overrides { + if let Some(ref mut vec) = self.b.overrides { vec.push(name.as_ref()); } else { - self.overrides = Some(vec![name.as_ref()]); + self.b.overrides = Some(vec![name.as_ref()]); } self } @@ -1049,14 +1240,15 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("posix") + /// let m = App::new("prog") /// .arg(Arg::from_usage("-f, --flag 'some flag'") /// .conflicts_with("color")) /// .arg(Arg::from_usage("-d, --debug 'other flag'")) /// .arg(Arg::from_usage("-c, --color 'third flag'") /// .overrides_with_all(&["flag", "debug"])) - /// .get_matches_from(vec!["posix", "-f", "-d", "-c"]); - /// // ^~~~~~^~~~~~~~~ flag and debug are overridden by color + /// .get_matches_from(vec![ + /// "prog", "-f", "-d", "-c"]); + /// // ^~~~~~^~~~~~~~~ flag and debug are overridden by color /// /// assert!(m.is_present("color")); // even though flag conflicts with color, it's as if flag /// // and debug were never used because they were overridden @@ -1064,64 +1256,361 @@ impl<'a, 'b> Arg<'a, 'b> { /// assert!(!m.is_present("debug")); /// assert!(!m.is_present("flag")); /// ``` - pub fn overrides_with_all(mut self, names: &[&'a str]) -> Self { - if let Some(ref mut vec) = self.overrides { - for s in names { - vec.push(s); - } + pub fn overrides_with_all(mut self, names: &[&'a str]) -> Self { + if let Some(ref mut vec) = self.b.overrides { + for s in names { + vec.push(s); + } + } else { + self.b.overrides = Some(names.iter().map(|s| *s).collect::>()); + } + self + } + + /// Sets an argument by name that is required when this one is present I.e. when + /// using this argument, the following argument *must* be present. + /// + /// **NOTE:** [Conflicting] rules and [override] rules take precedence over being required + /// + /// # Examples + /// + /// ```rust + /// # use clap::Arg; + /// Arg::with_name("config") + /// .requires("input") + /// # ; + /// ``` + /// + /// Setting [`Arg::requires(name)`] requires that the argument be used at runtime if the + /// defining argument is used. If the defining argument isn't used, the other argument isn't + /// required + /// + /// ```rust + /// # use clap::{App, Arg}; + /// let res = App::new("prog") + /// .arg(Arg::with_name("cfg") + /// .takes_value(true) + /// .requires("input") + /// .long("config")) + /// .arg(Arg::with_name("input") + /// .index(1)) + /// .get_matches_from_safe(vec![ + /// "prog" + /// ]); + /// + /// assert!(res.is_ok()); // We didn't use cfg, so input wasn't required + /// ``` + /// + /// Setting [`Arg::requires(name)`] and *not* supplying that argument is an error. + /// + /// ```rust + /// # use clap::{App, Arg, ErrorKind}; + /// let res = App::new("prog") + /// .arg(Arg::with_name("cfg") + /// .takes_value(true) + /// .requires("input") + /// .long("config")) + /// .arg(Arg::with_name("input") + /// .index(1)) + /// .get_matches_from_safe(vec![ + /// "prog", "--config", "file.conf" + /// ]); + /// + /// assert!(res.is_err()); + /// assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument); + /// ``` + /// [`Arg::requires(name)`]: ./struct.Arg.html#method.requires + /// [Conflicting]: ./struct.Arg.html#method.conflicts_with + /// [override]: ./struct.Arg.html#method.overrides_with + pub fn requires(mut self, name: &'a str) -> Self { + if let Some(ref mut vec) = self.b.requires { + vec.push((None, name)); + } else { + let mut vec = vec![]; + vec.push((None, name)); + self.b.requires = Some(vec); + } + self + } + + /// Allows a conditional requirement. The requirement will only become valid if this arg's value + /// equals `val`. + /// + /// **NOTE:** If using YAML the values should be laid out as follows + /// + /// ```yaml + /// requires_if: + /// - [val, arg] + /// ``` + /// + /// # Examples + /// + /// ```rust + /// # use clap::Arg; + /// Arg::with_name("config") + /// .requires_if("val", "arg") + /// # ; + /// ``` + /// + /// Setting [`Arg::requires_if(val, arg)`] requires that the `arg` be used at runtime if the + /// defining argument's value is equal to `val`. If the defining argument is anything other than + /// `val`, the other argument isn't required. + /// + /// ```rust + /// # use clap::{App, Arg}; + /// let res = App::new("prog") + /// .arg(Arg::with_name("cfg") + /// .takes_value(true) + /// .requires_if("my.cfg", "other") + /// .long("config")) + /// .arg(Arg::with_name("other")) + /// .get_matches_from_safe(vec![ + /// "prog", "--config", "some.cfg" + /// ]); + /// + /// assert!(res.is_ok()); // We didn't use --config=my.cfg, so other wasn't required + /// ``` + /// + /// Setting [`Arg::requires_if(val, arg)`] and setting the value to `val` but *not* supplying + /// `arg` is an error. + /// + /// ```rust + /// # use clap::{App, Arg, ErrorKind}; + /// let res = App::new("prog") + /// .arg(Arg::with_name("cfg") + /// .takes_value(true) + /// .requires_if("my.cfg", "input") + /// .long("config")) + /// .arg(Arg::with_name("input")) + /// .get_matches_from_safe(vec![ + /// "prog", "--config", "my.cfg" + /// ]); + /// + /// assert!(res.is_err()); + /// assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument); + /// ``` + /// [`Arg::requires(name)`]: ./struct.Arg.html#method.requires + /// [Conflicting]: ./struct.Arg.html#method.conflicts_with + /// [override]: ./struct.Arg.html#method.overrides_with + pub fn requires_if(mut self, val: &'b str, arg: &'a str) -> Self { + if let Some(ref mut vec) = self.b.requires { + vec.push((Some(val), arg)); + } else { + self.b.requires = Some(vec![(Some(val), arg)]); + } + self + } + + /// Allows multiple conditional requirements. The requirement will only become valid if this arg's value + /// equals `val`. + /// + /// **NOTE:** If using YAML the values should be laid out as follows + /// + /// ```yaml + /// requires_if: + /// - [val, arg] + /// - [val2, arg2] + /// ``` + /// + /// # Examples + /// + /// ```rust + /// # use clap::Arg; + /// Arg::with_name("config") + /// .requires_ifs(&[ + /// ("val", "arg"), + /// ("other_val", "arg2"), + /// ]) + /// # ; + /// ``` + /// + /// Setting [`Arg::requires_ifs(&["val", "arg"])`] requires that the `arg` be used at runtime if the + /// defining argument's value is equal to `val`. If the defining argument's value is anything other + /// than `val`, `arg` isn't required. + /// + /// ```rust + /// # use clap::{App, Arg, ErrorKind}; + /// let res = App::new("prog") + /// .arg(Arg::with_name("cfg") + /// .takes_value(true) + /// .requires_ifs(&[ + /// ("special.conf", "opt"), + /// ("other.conf", "other"), + /// ]) + /// .long("config")) + /// .arg(Arg::with_name("opt") + /// .long("option") + /// .takes_value(true)) + /// .arg(Arg::with_name("other")) + /// .get_matches_from_safe(vec![ + /// "prog", "--config", "special.conf" + /// ]); + /// + /// assert!(res.is_err()); // We used --config=special.conf so --option is required + /// assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument); + /// ``` + /// [`Arg::requires(name)`]: ./struct.Arg.html#method.requires + /// [Conflicting]: ./struct.Arg.html#method.conflicts_with + /// [override]: ./struct.Arg.html#method.overrides_with + pub fn requires_ifs(mut self, ifs: &[(&'b str, &'a str)]) -> Self { + if let Some(ref mut vec) = self.b.requires { + for &(val, arg) in ifs { + vec.push((Some(val), arg)); + } + } else { + let mut vec = vec![]; + for &(val, arg) in ifs { + vec.push((Some(val), arg)); + } + self.b.requires = Some(vec); + } + self + } + + /// Allows specifying that an argument is [required] conditionally. The requirement will only + /// become valid if the specified `arg`'s value equals `val`. + /// + /// **NOTE:** If using YAML the values should be laid out as follows + /// + /// ```yaml + /// required_if: + /// - [arg, val] + /// ``` + /// + /// # Examples + /// + /// ```rust + /// # use clap::Arg; + /// Arg::with_name("config") + /// .required_if("other_arg", "value") + /// # ; + /// ``` + /// + /// Setting [`Arg::required_if(arg, val)`] makes this arg required if the `arg` is used at + /// runtime and it's value is equal to `val`. If the `arg`'s value is anything other than `val`, + /// this argument isn't required. + /// + /// ```rust + /// # use clap::{App, Arg}; + /// let res = App::new("prog") + /// .arg(Arg::with_name("cfg") + /// .takes_value(true) + /// .required_if("other", "special") + /// .long("config")) + /// .arg(Arg::with_name("other") + /// .long("other") + /// .takes_value(true)) + /// .get_matches_from_safe(vec![ + /// "prog", "--other", "not-special" + /// ]); + /// + /// assert!(res.is_ok()); // We didn't use --other=special, so "cfg" wasn't required + /// ``` + /// + /// Setting [`Arg::required_if(arg, val)`] and having `arg` used with a vaue of `val` but *not* + /// using this arg is an error. + /// + /// ```rust + /// # use clap::{App, Arg, ErrorKind}; + /// let res = App::new("prog") + /// .arg(Arg::with_name("cfg") + /// .takes_value(true) + /// .required_if("other", "special") + /// .long("config")) + /// .arg(Arg::with_name("other") + /// .long("other") + /// .takes_value(true)) + /// .get_matches_from_safe(vec![ + /// "prog", "--other", "special" + /// ]); + /// + /// assert!(res.is_err()); + /// assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument); + /// ``` + /// [`Arg::requires(name)`]: ./struct.Arg.html#method.requires + /// [Conflicting]: ./struct.Arg.html#method.conflicts_with + /// [required]: ./struct.Arg.html#method.required + pub fn required_if(mut self, arg: &'a str, val: &'b str) -> Self { + if let Some(ref mut vec) = self.r_ifs { + vec.push((arg, val)); } else { - self.overrides = Some(names.iter().map(|s| *s).collect::>()); + self.r_ifs = Some(vec![(arg, val)]); } self } - /// Sets an argument by name that is required when this one is present I.e. when - /// using this argument, the following argument *must* be present. + /// Allows specifying that an argument is [required] based on multiple conditions. The + /// conditions are set up in a `(arg, val)` style tuple. The requirement will only become valid + /// if one of the specified `arg`'s value equals it's corresponding `val`. /// - /// **NOTE:** [Conflicting] rules and [override] rules take precedence over being required + /// **NOTE:** If using YAML the values should be laid out as follows + /// + /// ```yaml + /// required_if: + /// - [arg, val] + /// - [arg2, val2] + /// ``` /// /// # Examples /// /// ```rust /// # use clap::Arg; /// Arg::with_name("config") - /// .requires("input") + /// .required_ifs(&[ + /// ("extra", "val"), + /// ("option", "spec") + /// ]) /// # ; /// ``` /// - /// Setting [`Arg::requires(name)`] requires that the argument be used at runtime if the - /// defining argument is used. If the defining argument isn't used, the other argument isn't - /// required + /// Setting [`Arg::required_ifs(&[(arg, val)])`] makes this arg required if any of the `arg`s + /// are used at runtime and it's corresponding value is equal to `val`. If the `arg`'s value is + /// anything other than `val`, this argument isn't required. /// /// ```rust /// # use clap::{App, Arg}; - /// let res = App::new("reqtest") + /// let res = App::new("prog") /// .arg(Arg::with_name("cfg") + /// .required_ifs(&[ + /// ("extra", "val"), + /// ("option", "spec") + /// ]) /// .takes_value(true) - /// .requires("input") /// .long("config")) - /// .arg(Arg::with_name("input") - /// .index(1)) + /// .arg(Arg::with_name("extra") + /// .takes_value(true) + /// .long("extra")) + /// .arg(Arg::with_name("option") + /// .takes_value(true) + /// .long("option")) /// .get_matches_from_safe(vec![ - /// "reqtest" + /// "prog", "--option", "other" /// ]); /// - /// assert!(res.is_ok()); // We didn't use cfg, so input wasn't required + /// assert!(res.is_ok()); // We didn't use --option=spec, or --extra=val so "cfg" isn't required /// ``` /// - /// Setting [`Arg::requires(name)`] and *not* supplying that argument is an error. + /// Setting [`Arg::required_ifs(&[(arg, val)])`] and having any of the `arg`s used with it's + /// vaue of `val` but *not* using this arg is an error. /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let res = App::new("reqtest") + /// let res = App::new("prog") /// .arg(Arg::with_name("cfg") + /// .required_ifs(&[ + /// ("extra", "val"), + /// ("option", "spec") + /// ]) /// .takes_value(true) - /// .requires("input") /// .long("config")) - /// .arg(Arg::with_name("input") - /// .index(1)) + /// .arg(Arg::with_name("extra") + /// .takes_value(true) + /// .long("extra")) + /// .arg(Arg::with_name("option") + /// .takes_value(true) + /// .long("option")) /// .get_matches_from_safe(vec![ - /// "reqtest", "--config", "file.conf" + /// "prog", "--option", "spec" /// ]); /// /// assert!(res.is_err()); @@ -1129,12 +1618,18 @@ impl<'a, 'b> Arg<'a, 'b> { /// ``` /// [`Arg::requires(name)`]: ./struct.Arg.html#method.requires /// [Conflicting]: ./struct.Arg.html#method.conflicts_with - /// [override]: ./struct.Arg.html#method.overrides_with - pub fn requires(mut self, name: &'a str) -> Self { - if let Some(ref mut vec) = self.requires { - vec.push(name); + /// [required]: ./struct.Arg.html#method.required + pub fn required_ifs(mut self, ifs: &[(&'a str, &'b str)]) -> Self { + if let Some(ref mut vec) = self.r_ifs { + for r_if in ifs { + vec.push((r_if.0, r_if.1)); + } } else { - self.requires = Some(vec![name]); + let mut vec = vec![]; + for r_if in ifs { + vec.push((r_if.0, r_if.1)); + } + self.r_ifs = Some(vec); } self } @@ -1160,7 +1655,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let res = App::new("reqtest") + /// let res = App::new("prog") /// .arg(Arg::with_name("cfg") /// .takes_value(true) /// .requires("input") @@ -1170,7 +1665,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// .arg(Arg::with_name("output") /// .index(2)) /// .get_matches_from_safe(vec![ - /// "reqtest" + /// "prog" /// ]); /// /// assert!(res.is_ok()); // We didn't use cfg, so input and output weren't required @@ -1181,7 +1676,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let res = App::new("reqtest") + /// let res = App::new("prog") /// .arg(Arg::with_name("cfg") /// .takes_value(true) /// .requires_all(&["input", "output"]) @@ -1191,7 +1686,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// .arg(Arg::with_name("output") /// .index(2)) /// .get_matches_from_safe(vec![ - /// "reqtest", "--config", "file.conf", "in.txt" + /// "prog", "--config", "file.conf", "in.txt" /// ]); /// /// assert!(res.is_err()); @@ -1202,12 +1697,16 @@ impl<'a, 'b> Arg<'a, 'b> { /// [override]: ./struct.Arg.html#method.overrides_with /// [`Arg::requires_all(&[arg, arg2])`]: ./struct.Arg.html#method.requires_all pub fn requires_all(mut self, names: &[&'a str]) -> Self { - if let Some(ref mut vec) = self.requires { + if let Some(ref mut vec) = self.b.requires { for s in names { - vec.push(s); + vec.push((None, s)); } } else { - self.requires = Some(names.into_iter().map(|s| *s).collect::>()); + let mut vec = vec![]; + for s in names { + vec.push((None, *s)); + } + self.b.requires = Some(vec); } self } @@ -1236,11 +1735,13 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("posvals") + /// let m = App::new("prog") /// .arg(Arg::with_name("mode") /// .long("mode") /// .takes_value(true)) - /// .get_matches_from(vec!["posvals", "--mode", "fast"]); + /// .get_matches_from(vec![ + /// "prog", "--mode", "fast" + /// ]); /// /// assert!(m.is_present("mode")); /// assert_eq!(m.value_of("mode"), Some("fast")); @@ -1273,7 +1774,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("hide_posvals") + /// let m = App::new("prog") /// .arg(Arg::with_name("mode") /// .long("mode") /// .possible_values(&["fast", "slow"]) @@ -1292,6 +1793,40 @@ impl<'a, 'b> Arg<'a, 'b> { } } + /// Specifies if the default value of an argument should be displayed in the help text or + /// not. Defaults to `false` (i.e. show default value) + /// + /// This is useful when default behavior of an arg is explained elsewhere in the help text. + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, Arg}; + /// Arg::with_name("config") + /// .hide_default_value(true) + /// # ; + /// ``` + /// + /// ```rust + /// # use clap::{App, Arg}; + /// let m = App::new("connect") + /// .arg(Arg::with_name("host") + /// .long("host") + /// .default_value("localhost") + /// .hide_default_value(true)); + /// + /// ``` + /// + /// If we were to run the above program with `--help` the `[default: localhost]` portion of + /// the help text would be omitted. + pub fn hide_default_value(self, hide: bool) -> Self { + if hide { + self.set(ArgSettings::HideDefaultValue) + } else { + self.unset(ArgSettings::HideDefaultValue) + } + } + /// Specifies the index of a positional argument **starting at** 1. /// /// **NOTE:** The index refers to position according to **other positional argument**. It does @@ -1321,12 +1856,14 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("posvals") + /// let m = App::new("prog") /// .arg(Arg::with_name("mode") /// .index(1)) /// .arg(Arg::with_name("debug") /// .long("debug")) - /// .get_matches_from(vec!["posvals", "--debug", "fast"]); + /// .get_matches_from(vec![ + /// "prog", "--debug", "fast" + /// ]); /// /// assert!(m.is_present("mode")); /// assert_eq!(m.value_of("mode"), Some("fast")); // notice index(1) means "first positional" @@ -1378,11 +1915,13 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("mults") + /// let m = App::new("prog") /// .arg(Arg::with_name("verbose") /// .multiple(true) /// .short("v")) - /// .get_matches_from(vec!["mults", "-v", "-v", "-v"]); // note, -vvv would have same result + /// .get_matches_from(vec![ + /// "prog", "-v", "-v", "-v" // note, -vvv would have same result + /// ]); /// /// assert!(m.is_present("verbose")); /// assert_eq!(m.occurrences_of("verbose"), 3); @@ -1392,12 +1931,14 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("mults") + /// let m = App::new("prog") /// .arg(Arg::with_name("file") /// .multiple(true) /// .takes_value(true) /// .short("F")) - /// .get_matches_from(vec!["mults", "-F", "file1", "file2", "file3"]); + /// .get_matches_from(vec![ + /// "prog", "-F", "file1", "file2", "file3" + /// ]); /// /// assert!(m.is_present("file")); /// assert_eq!(m.occurrences_of("file"), 1); // notice only one occurrence @@ -1408,12 +1949,14 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("mults") + /// let m = App::new("prog") /// .arg(Arg::with_name("file") /// .multiple(true) /// .takes_value(true) /// .short("F")) - /// .get_matches_from(vec!["mults", "-F", "file1", "-F", "file2", "-F", "file3"]); + /// .get_matches_from(vec![ + /// "prog", "-F", "file1", "-F", "file2", "-F", "file3" + /// ]); /// let files: Vec<_> = m.values_of("file").unwrap().collect(); /// assert_eq!(files, ["file1", "file2", "file3"]); /// @@ -1427,14 +1970,16 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("mults") + /// let m = App::new("prog") /// .arg(Arg::with_name("file") /// .multiple(true) /// .takes_value(true) /// .short("F")) /// .arg(Arg::with_name("word") /// .index(1)) - /// .get_matches_from(vec!["mults", "-F", "file1", "file2", "file3", "word"]); + /// .get_matches_from(vec![ + /// "prog", "-F", "file1", "file2", "file3", "word" + /// ]); /// /// assert!(m.is_present("file")); /// let files: Vec<_> = m.values_of("file").unwrap().collect(); @@ -1450,7 +1995,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("mults") + /// let m = App::new("prog") /// .arg(Arg::with_name("file") /// .multiple(true) /// .takes_value(true) @@ -1458,7 +2003,9 @@ impl<'a, 'b> Arg<'a, 'b> { /// .short("F")) /// .arg(Arg::with_name("word") /// .index(1)) - /// .get_matches_from(vec!["mults", "-F", "file1", "-F", "file2", "-F", "file3", "word"]); + /// .get_matches_from(vec![ + /// "prog", "-F", "file1", "-F", "file2", "-F", "file3", "word" + /// ]); /// /// assert!(m.is_present("file")); /// let files: Vec<_> = m.values_of("file").unwrap().collect(); @@ -1472,7 +2019,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let res = App::new("mults") + /// let res = App::new("prog") /// .arg(Arg::with_name("file") /// .multiple(true) /// .takes_value(true) @@ -1480,7 +2027,9 @@ impl<'a, 'b> Arg<'a, 'b> { /// .short("F")) /// .arg(Arg::with_name("word") /// .index(1)) - /// .get_matches_from_safe(vec!["mults", "-F", "file1", "file2", "file3", "word"]); + /// .get_matches_from_safe(vec![ + /// "prog", "-F", "file1", "file2", "file3", "word" + /// ]); /// /// assert!(res.is_err()); /// assert_eq!(res.unwrap_err().kind, ErrorKind::UnknownArgument); @@ -1496,6 +2045,57 @@ impl<'a, 'b> Arg<'a, 'b> { } } + /// Specifies a value that *stops* parsing multiple values of a give argument. By default when + /// one sets [`multiple(true)`] on an argument, clap will continue parsing values for that + /// argument until it reaches another valid argument, or one of the other more specific settings + /// for multiple values is used (such as [`min_values`], [`max_values`] or + /// [`number_of_values`]). + /// + /// **NOTE:** This setting only applies to [options] and [positional arguments] + /// + /// **NOTE:** When the terminator is passed in on the command line, it is **not** stored as one + /// of the vaues + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, Arg}; + /// Arg::with_name("vals") + /// .takes_value(true) + /// .multiple(true) + /// .value_terminator(";") + /// # ; + /// ``` + /// The following example uses two arguments, a sequence of commands, and the location in which + /// to perform them + /// + /// ```rust + /// # use clap::{App, Arg}; + /// let m = App::new("prog") + /// .arg(Arg::with_name("cmds") + /// .multiple(true) + /// .allow_hyphen_values(true) + /// .value_terminator(";")) + /// .arg(Arg::with_name("location")) + /// .get_matches_from(vec![ + /// "prog", "find", "-type", "f", "-name", "special", ";", "/home/clap" + /// ]); + /// let cmds: Vec<_> = m.values_of("cmds").unwrap().collect(); + /// assert_eq!(&cmds, &["find", "-type", "f", "-name", "special"]); + /// assert_eq!(m.value_of("location"), Some("/home/clap")); + /// ``` + /// [options]: ./struct.Arg.html#method.takes_value + /// [positional arguments]: ./struct.Arg.html#method.index + /// [`multiple(true)`]: ./struct.Arg.html#method.multiple + /// [`min_values`]: ./struct.Arg.html#method.min_values + /// [`number_of_values`]: ./struct.Arg.html#method.number_of_values + /// [`max_values`]: ./struct.Arg.html#method.max_values + pub fn value_terminator(mut self, term: &'b str) -> Self { + self.setb(ArgSettings::TakesValue); + self.v.terminator = Some(term); + self + } + /// Specifies that an argument can be matched to all child [`SubCommand`]s. /// /// **NOTE:** Global arguments *only* propagate down, **not** up (to parent commands) @@ -1523,14 +2123,16 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg, SubCommand}; - /// let m = App::new("mults") + /// let m = App::new("prog") /// .arg(Arg::with_name("verb") /// .long("verbose") /// .short("v") /// .global(true)) /// .subcommand(SubCommand::with_name("test")) /// .subcommand(SubCommand::with_name("do-stuff")) - /// .get_matches_from(vec!["mults", "do-stuff", "--verbose"]); + /// .get_matches_from(vec![ + /// "prog", "do-stuff", "--verbose" + /// ]); /// /// assert_eq!(m.subcommand_name(), Some("do-stuff")); /// let sub_m = m.subcommand_matches("do-stuff").unwrap(); @@ -1570,12 +2172,14 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let res = App::new("evals") + /// let res = App::new("prog") /// .arg(Arg::with_name("cfg") /// .long("config") /// .short("v") /// .empty_values(false)) - /// .get_matches_from_safe(vec!["evals", "--config="]); + /// .get_matches_from_safe(vec![ + /// "prog", "--config=" + /// ]); /// /// assert!(res.is_err()); /// assert_eq!(res.unwrap_err().kind, ErrorKind::EmptyValue); @@ -1606,13 +2210,13 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("helptest") + /// let m = App::new("prog") /// .arg(Arg::with_name("cfg") /// .long("config") /// .hidden(true) /// .help("Some help text describing the --config arg")) /// .get_matches_from(vec![ - /// "shorttest", "--help" + /// "prog", "--help" /// ]); /// ``` /// @@ -1653,12 +2257,14 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("posvals") + /// let m = App::new("prog") /// .arg(Arg::with_name("mode") /// .long("mode") /// .takes_value(true) /// .possible_values(&["fast", "slow", "medium"])) - /// .get_matches_from(vec!["posvals", "--mode", "fast"]); + /// .get_matches_from(vec![ + /// "prog", "--mode", "fast" + /// ]); /// assert!(m.is_present("mode")); /// assert_eq!(m.value_of("mode"), Some("fast")); /// ``` @@ -1668,24 +2274,26 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let res = App::new("posvals") + /// let res = App::new("prog") /// .arg(Arg::with_name("mode") /// .long("mode") /// .takes_value(true) /// .possible_values(&["fast", "slow", "medium"])) - /// .get_matches_from_safe(vec!["myprog", "--mode", "wrong"]); + /// .get_matches_from_safe(vec![ + /// "prog", "--mode", "wrong" + /// ]); /// assert!(res.is_err()); /// assert_eq!(res.unwrap_err().kind, ErrorKind::InvalidValue); /// ``` /// [options]: ./struct.Arg.html#method.takes_value /// [positional arguments]: ./struct.Arg.html#method.index pub fn possible_values(mut self, names: &[&'b str]) -> Self { - if let Some(ref mut vec) = self.possible_vals { + if let Some(ref mut vec) = self.v.possible_vals { for s in names { vec.push(s); } } else { - self.possible_vals = Some(names.iter().map(|s| *s).collect::>()); + self.v.possible_vals = Some(names.iter().map(|s| *s).collect::>()); } self } @@ -1709,14 +2317,16 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("posvals") + /// let m = App::new("prog") /// .arg(Arg::with_name("mode") /// .long("mode") /// .takes_value(true) /// .possible_value("fast") /// .possible_value("slow") /// .possible_value("medium")) - /// .get_matches_from(vec!["posvals", "--mode", "fast"]); + /// .get_matches_from(vec![ + /// "prog", "--mode", "fast" + /// ]); /// assert!(m.is_present("mode")); /// assert_eq!(m.value_of("mode"), Some("fast")); /// ``` @@ -1726,24 +2336,26 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let res = App::new("posvals") + /// let res = App::new("prog") /// .arg(Arg::with_name("mode") /// .long("mode") /// .takes_value(true) /// .possible_value("fast") /// .possible_value("slow") /// .possible_value("medium")) - /// .get_matches_from_safe(vec!["myprog", "--mode", "wrong"]); + /// .get_matches_from_safe(vec![ + /// "prog", "--mode", "wrong" + /// ]); /// assert!(res.is_err()); /// assert_eq!(res.unwrap_err().kind, ErrorKind::InvalidValue); /// ``` /// [options]: ./struct.Arg.html#method.takes_value /// [positional arguments]: ./struct.Arg.html#method.index pub fn possible_value(mut self, name: &'b str) -> Self { - if let Some(ref mut vec) = self.possible_vals { + if let Some(ref mut vec) = self.v.possible_vals { vec.push(name); } else { - self.possible_vals = Some(vec![name]); + self.v.possible_vals = Some(vec![name]); } self } @@ -1765,22 +2377,24 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("groups") + /// let m = App::new("prog") /// .arg(Arg::with_name("debug") /// .long("debug") /// .group("mode")) /// .arg(Arg::with_name("verbose") /// .long("verbose") /// .group("mode")) - /// .get_matches_from(vec!["posvals", "--debug"]); + /// .get_matches_from(vec![ + /// "prog", "--debug" + /// ]); /// assert!(m.is_present("mode")); /// ``` /// [`ArgGroup`]: ./struct.ArgGroup.html pub fn group(mut self, name: &'a str) -> Self { - if let Some(ref mut vec) = self.requires { + if let Some(ref mut vec) = self.b.groups { vec.push(name); } else { - self.groups = Some(vec![name]); + self.b.groups = Some(vec![name]); } self } @@ -1802,25 +2416,27 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("groups") + /// let m = App::new("prog") /// .arg(Arg::with_name("debug") /// .long("debug") /// .groups(&["mode", "verbosity"])) /// .arg(Arg::with_name("verbose") /// .long("verbose") /// .groups(&["mode", "verbosity"])) - /// .get_matches_from(vec!["posvals", "--debug"]); + /// .get_matches_from(vec![ + /// "prog", "--debug" + /// ]); /// assert!(m.is_present("mode")); /// assert!(m.is_present("verbosity")); /// ``` /// [`ArgGroup`]: ./struct.ArgGroup.html pub fn groups(mut self, names: &[&'a str]) -> Self { - if let Some(ref mut vec) = self.groups { + if let Some(ref mut vec) = self.b.groups { for s in names { vec.push(s); } } else { - self.groups = Some(names.into_iter().map(|s| *s).collect::>()); + self.b.groups = Some(names.into_iter().map(|s| *s).collect::>()); } self } @@ -1848,12 +2464,14 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let res = App::new("numvals") + /// let res = App::new("prog") /// .arg(Arg::with_name("file") /// .takes_value(true) /// .number_of_values(2) /// .short("F")) - /// .get_matches_from_safe(vec!["mults", "-F", "file1"]); + /// .get_matches_from_safe(vec![ + /// "prog", "-F", "file1" + /// ]); /// /// assert!(res.is_err()); /// assert_eq!(res.unwrap_err().kind, ErrorKind::WrongNumberOfValues); @@ -1861,7 +2479,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple pub fn number_of_values(mut self, qty: u64) -> Self { self.setb(ArgSettings::TakesValue); - self.num_vals = Some(qty); + self.v.num_vals = Some(qty); self } @@ -1887,12 +2505,12 @@ impl<'a, 'b> Arg<'a, 'b> { /// if v.contains("@") { return Ok(()); } /// Err(String::from("The value did not contain the required @ sigil")) /// } - /// let res = App::new("validators") + /// let res = App::new("prog") /// .arg(Arg::with_name("file") /// .index(1) /// .validator(has_at)) /// .get_matches_from_safe(vec![ - /// "validators", "some@file" + /// "prog", "some@file" /// ]); /// assert!(res.is_ok()); /// assert_eq!(res.unwrap().value_of("file"), Some("some@file")); @@ -1904,7 +2522,44 @@ impl<'a, 'b> Arg<'a, 'b> { pub fn validator(mut self, f: F) -> Self where F: Fn(String) -> Result<(), String> + 'static { - self.validator = Some(Rc::new(f)); + self.v.validator = Some(Rc::new(f)); + self + } + + /// Works identically to Validator but is intended to be used with values that could + /// contain non UTF-8 formatted strings. + /// + /// # Examples + /// + #[cfg_attr(not(unix), doc=" ```ignore")] + #[cfg_attr( unix , doc=" ```rust")] + /// # use clap::{App, Arg}; + /// # use std::ffi::{OsStr, OsString}; + /// # use std::os::unix::ffi::OsStrExt; + /// fn has_ampersand(v: &OsStr) -> Result<(), OsString> { + /// if v.as_bytes().iter().any(|b| *b == b'&') { return Ok(()); } + /// Err(OsString::from("The value did not contain the required & sigil")) + /// } + /// let res = App::new("prog") + /// .arg(Arg::with_name("file") + /// .index(1) + /// .validator_os(has_ampersand)) + /// .get_matches_from_safe(vec![ + /// "prog", "Fish & chips" + /// ]); + /// assert!(res.is_ok()); + /// assert_eq!(res.unwrap().value_of("file"), Some("Fish & chips")); + /// ``` + /// [`String`]: https://doc.rust-lang.org/std/string/struct.String.html + /// [`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html + /// [`OsString`]: https://doc.rust-lang.org/std/ffi/struct.OsString.html + /// [`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html + /// [`Err(String)`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err + /// [`Rc`]: https://doc.rust-lang.org/std/rc/struct.Rc.html + pub fn validator_os(mut self, f: F) -> Self + where F: Fn(&OsStr) -> Result<(), OsString> + 'static + { + self.v.validator_os = Some(Rc::new(f)); self } @@ -1932,12 +2587,14 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let res = App::new("numvals") + /// let res = App::new("prog") /// .arg(Arg::with_name("file") /// .takes_value(true) /// .max_values(3) /// .short("F")) - /// .get_matches_from_safe(vec!["mults", "-F", "file1", "file2"]); + /// .get_matches_from_safe(vec![ + /// "prog", "-F", "file1", "file2" + /// ]); /// /// assert!(res.is_ok()); /// let m = res.unwrap(); @@ -1949,12 +2606,14 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let res = App::new("numvals") + /// let res = App::new("prog") /// .arg(Arg::with_name("file") /// .takes_value(true) /// .max_values(2) /// .short("F")) - /// .get_matches_from_safe(vec!["mults", "-F", "file1", "file2", "file3"]); + /// .get_matches_from_safe(vec![ + /// "prog", "-F", "file1", "file2", "file3" + /// ]); /// /// assert!(res.is_err()); /// assert_eq!(res.unwrap_err().kind, ErrorKind::TooManyValues); @@ -1962,7 +2621,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple pub fn max_values(mut self, qty: u64) -> Self { self.setb(ArgSettings::TakesValue); - self.max_vals = Some(qty); + self.v.max_vals = Some(qty); self } @@ -1991,12 +2650,14 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let res = App::new("numvals") + /// let res = App::new("prog") /// .arg(Arg::with_name("file") /// .takes_value(true) /// .min_values(2) /// .short("F")) - /// .get_matches_from_safe(vec!["mults", "-F", "file1", "file2", "file3"]); + /// .get_matches_from_safe(vec![ + /// "prog", "-F", "file1", "file2", "file3" + /// ]); /// /// assert!(res.is_ok()); /// let m = res.unwrap(); @@ -2008,19 +2669,21 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let res = App::new("numvals") + /// let res = App::new("prog") /// .arg(Arg::with_name("file") /// .takes_value(true) /// .min_values(2) /// .short("F")) - /// .get_matches_from_safe(vec!["mults", "-F", "file1"]); + /// .get_matches_from_safe(vec![ + /// "prog", "-F", "file1" + /// ]); /// /// assert!(res.is_err()); /// assert_eq!(res.unwrap_err().kind, ErrorKind::TooFewValues); /// ``` /// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple pub fn min_values(mut self, qty: u64) -> Self { - self.min_vals = Some(qty); + self.v.min_vals = Some(qty); self.set(ArgSettings::TakesValue) } @@ -2038,14 +2701,13 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let delims = App::new("delims") + /// let delims = App::new("prog") /// .arg(Arg::with_name("option") /// .long("option") /// .use_delimiter(true) /// .takes_value(true)) /// .get_matches_from(vec![ - /// "delims", - /// "--option=val1,val2,val3", + /// "prog", "--option=val1,val2,val3", /// ]); /// /// assert!(delims.is_present("option")); @@ -2057,14 +2719,13 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let nodelims = App::new("nodelims") + /// let nodelims = App::new("prog") /// .arg(Arg::with_name("option") /// .long("option") /// .use_delimiter(false) /// .takes_value(true)) /// .get_matches_from(vec![ - /// "nodelims", - /// "--option=val1,val2,val3", + /// "prog", "--option=val1,val2,val3", /// ]); /// /// assert!(nodelims.is_present("option")); @@ -2074,14 +2735,14 @@ impl<'a, 'b> Arg<'a, 'b> { /// [`Arg::value_delimiter`]: ./struct.Arg.html#method.value_delimiter pub fn use_delimiter(mut self, d: bool) -> Self { if d { - if self.val_delim.is_none() { - self.val_delim = Some(','); + if self.v.val_delim.is_none() { + self.v.val_delim = Some(','); } self.setb(ArgSettings::TakesValue); self.setb(ArgSettings::UseValueDelimiter); self.unset(ArgSettings::ValueDelimiterNotSet) } else { - self.val_delim = None; + self.v.val_delim = None; self.unsetb(ArgSettings::UseValueDelimiter); self.unset(ArgSettings::ValueDelimiterNotSet) } @@ -2106,15 +2767,14 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let delims = App::new("reqdelims") + /// let delims = App::new("prog") /// .arg(Arg::with_name("opt") /// .short("o") /// .takes_value(true) /// .multiple(true) /// .require_delimiter(true)) - /// // Simulate "$ reqdelims -o val1,val2,val3" /// .get_matches_from(vec![ - /// "reqdelims", "-o", "val1,val2,val3", + /// "prog", "-o", "val1,val2,val3", /// ]); /// /// assert!(delims.is_present("opt")); @@ -2124,15 +2784,14 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let res = App::new("reqdelims") + /// let res = App::new("prog") /// .arg(Arg::with_name("opt") /// .short("o") /// .takes_value(true) /// .multiple(true) /// .require_delimiter(true)) - /// // Simulate "$ reqdelims -o val1 val2 val3" /// .get_matches_from_safe(vec![ - /// "reqdelims", "-o", "val1", "val2", "val3", + /// "prog", "-o", "val1", "val2", "val3", /// ]); /// /// assert!(res.is_err()); @@ -2148,14 +2807,13 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let delims = App::new("reqdelims") + /// let delims = App::new("prog") /// .arg(Arg::with_name("opt") /// .short("o") /// .takes_value(true) /// .multiple(true)) - /// // Simulate "$ reqdelims -o val1 val2 val3" /// .get_matches_from(vec![ - /// "reqdelims", "-o", "val1", "val2", "val3", + /// "prog", "-o", "val1", "val2", "val3", /// ]); /// /// assert!(delims.is_present("opt")); @@ -2185,15 +2843,14 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let app = App::new("fake") + /// let m = App::new("prog") /// .arg(Arg::with_name("config") /// .short("c") /// .long("config") - /// .value_delimiter(";")); - /// - /// let m = app.get_matches_from(vec![ - /// "fake", "--config=val1;val2;val3" - /// ]); + /// .value_delimiter(";")) + /// .get_matches_from(vec![ + /// "prog", "--config=val1;val2;val3" + /// ]); /// /// assert_eq!(m.values_of("config").unwrap().collect::>(), ["val1", "val2", "val3"]) /// ``` @@ -2203,7 +2860,7 @@ impl<'a, 'b> Arg<'a, 'b> { self.unsetb(ArgSettings::ValueDelimiterNotSet); self.setb(ArgSettings::TakesValue); self.setb(ArgSettings::UseValueDelimiter); - self.val_delim = Some(d.chars() + self.v.val_delim = Some(d.chars() .nth(0) .expect("Failed to get value_delimiter from arg")); self @@ -2241,12 +2898,12 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let app = App::new("valnames") + /// let m = App::new("prog") /// .arg(Arg::with_name("io") /// .long("io-files") /// .value_names(&["INFILE", "OUTFILE"])) /// .get_matches_from(vec![ - /// "valnames", "--help" + /// "prog", "--help" /// ]); /// ``` /// Running the above program produces the following output @@ -2270,11 +2927,11 @@ impl<'a, 'b> Arg<'a, 'b> { /// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple pub fn value_names(mut self, names: &[&'b str]) -> Self { self.setb(ArgSettings::TakesValue); - if self.settings.is_set(ArgSettings::ValueDelimiterNotSet) { + if self.is_set(ArgSettings::ValueDelimiterNotSet) { self.unsetb(ArgSettings::ValueDelimiterNotSet); self.setb(ArgSettings::UseValueDelimiter); } - if let Some(ref mut vals) = self.val_names { + if let Some(ref mut vals) = self.v.val_names { let mut l = vals.len(); for s in names { vals.insert(l, s); @@ -2285,7 +2942,7 @@ impl<'a, 'b> Arg<'a, 'b> { for (i, n) in names.iter().enumerate() { vm.insert(i, *n); } - self.val_names = Some(vm); + self.v.val_names = Some(vm); } self } @@ -2310,12 +2967,12 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let app = App::new("valnames") + /// let m = App::new("prog") /// .arg(Arg::with_name("config") /// .long("config") /// .value_name("FILE")) /// .get_matches_from(vec![ - /// "valnames", "--help" + /// "prog", "--help" /// ]); /// ``` /// Running the above program produces the following output @@ -2338,13 +2995,13 @@ impl<'a, 'b> Arg<'a, 'b> { /// [`Arg::takes_value(true)`]: ./struct.Arg.html#method.takes_value pub fn value_name(mut self, name: &'b str) -> Self { self.setb(ArgSettings::TakesValue); - if let Some(ref mut vals) = self.val_names { + if let Some(ref mut vals) = self.v.val_names { let l = vals.len(); vals.insert(l, name); } else { let mut vm = VecMap::new(); vm.insert(0, name); - self.val_names = Some(vm); + self.v.val_names = Some(vm); } self } @@ -2359,20 +3016,31 @@ impl<'a, 'b> Arg<'a, 'b> { /// not, consider [`ArgMatches::occurrences_of`] which will return `0` if the argument was *not* /// used at runtmie. /// + /// **NOTE:** This setting is perfectly compatible with [`Arg::default_value_if`] but slightly + /// different. `Arg::default_value` *only* takes affect when the user has not provided this arg + /// at runtime. `Arg::default_value_if` however only takes affect when the user has not provided + /// a value at runtime **and** these other conditions are met as well. If you have set + /// `Arg::default_value` and `Arg::default_value_if`, and the user **did not** provide a this + /// arg at runtime, nor did were the conditions met for `Arg::default_value_if`, the + /// `Arg::default_value` will be applied. + /// /// **NOTE:** This implicitly sets [`Arg::takes_value(true)`]. /// + /// **NOTE:** This setting effectively disables `AppSettings::ArgRequiredElseHelp` if used in + /// conjuction as it ensures that some argument will always be present. + /// /// # Examples /// /// First we use the default value without providing any value at runtime. /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("defvals") + /// let m = App::new("prog") /// .arg(Arg::with_name("opt") /// .long("myopt") /// .default_value("myval")) /// .get_matches_from(vec![ - /// "defvals" + /// "prog" /// ]); /// /// assert_eq!(m.value_of("opt"), Some("myval")); @@ -2384,12 +3052,12 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("defvals") + /// let m = App::new("prog") /// .arg(Arg::with_name("opt") /// .long("myopt") /// .default_value("myval")) /// .get_matches_from(vec![ - /// "defvals", "--myopt=non_default" + /// "prog", "--myopt=non_default" /// ]); /// /// assert_eq!(m.value_of("opt"), Some("non_default")); @@ -2400,9 +3068,246 @@ impl<'a, 'b> Arg<'a, 'b> { /// [`ArgMatches::value_of`]: ./struct.ArgMatches.html#method.value_of /// [`Arg::takes_value(true)`]: ./struct.Arg.html#method.takes_value /// [`ArgMatches::is_present`]: ./struct.ArgMatches.html#method.is_present - pub fn default_value(mut self, val: &'a str) -> Self { + /// [`Arg::default_value_if`]: ./struct.Arg.html#method.default_value_if + pub fn default_value(self, val: &'a str) -> Self { + self.default_value_os(OsStr::from_bytes(val.as_bytes())) + } + + /// Provides a default value in the exact same manner as [`Arg::default_value`] + /// only using [`OsStr`]s instead. + /// [`Arg::default_value`]: ./struct.Arg.html#method.default_value + /// [`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html + pub fn default_value_os(mut self, val: &'a OsStr) -> Self { + self.setb(ArgSettings::TakesValue); + self.v.default_val = Some(val); + self + } + + /// Specifies the value of the argument if `arg` has been used at runtime. If `val` is set to + /// `None`, `arg` only needs to be present. If `val` is set to `"some-val"` then `arg` must be + /// present at runtime **and** have the value `val`. + /// + /// **NOTE:** This setting is perfectly compatible with [`Arg::default_value`] but slightly + /// different. `Arg::default_value` *only* takes affect when the user has not provided this arg + /// at runtime. This setting however only takes affect when the user has not provided a value at + /// runtime **and** these other conditions are met as well. If you have set `Arg::default_value` + /// and `Arg::default_value_if`, and the user **did not** provide a this arg at runtime, nor did + /// were the conditions met for `Arg::default_value_if`, the `Arg::default_value` will be + /// applied. + /// + /// **NOTE:** This implicitly sets [`Arg::takes_value(true)`]. + /// + /// **NOTE:** If using YAML the values should be laid out as follows (`None` can be represented + /// as `null` in YAML) + /// + /// ```yaml + /// default_value_if: + /// - [arg, val, default] + /// ``` + /// + /// # Examples + /// + /// First we use the default value only if another arg is present at runtime. + /// + /// ```rust + /// # use clap::{App, Arg}; + /// let m = App::new("prog") + /// .arg(Arg::with_name("flag") + /// .long("flag")) + /// .arg(Arg::with_name("other") + /// .long("other") + /// .default_value_if("flag", None, "default")) + /// .get_matches_from(vec![ + /// "prog", "--flag" + /// ]); + /// + /// assert_eq!(m.value_of("other"), Some("default")); + /// ``` + /// + /// Next we run the same test, but without providing `--flag`. + /// + /// ```rust + /// # use clap::{App, Arg}; + /// let m = App::new("prog") + /// .arg(Arg::with_name("flag") + /// .long("flag")) + /// .arg(Arg::with_name("other") + /// .long("other") + /// .default_value_if("flag", None, "default")) + /// .get_matches_from(vec![ + /// "prog" + /// ]); + /// + /// assert_eq!(m.value_of("other"), None); + /// ``` + /// + /// Now lets only use the default value if `--opt` contains the value `special`. + /// + /// ```rust + /// # use clap::{App, Arg}; + /// let m = App::new("prog") + /// .arg(Arg::with_name("opt") + /// .takes_value(true) + /// .long("opt")) + /// .arg(Arg::with_name("other") + /// .long("other") + /// .default_value_if("opt", Some("special"), "default")) + /// .get_matches_from(vec![ + /// "prog", "--opt", "special" + /// ]); + /// + /// assert_eq!(m.value_of("other"), Some("default")); + /// ``` + /// + /// We can run the same test and provide any value *other than* `special` and we won't get a + /// default value. + /// + /// ```rust + /// # use clap::{App, Arg}; + /// let m = App::new("prog") + /// .arg(Arg::with_name("opt") + /// .takes_value(true) + /// .long("opt")) + /// .arg(Arg::with_name("other") + /// .long("other") + /// .default_value_if("opt", Some("special"), "default")) + /// .get_matches_from(vec![ + /// "prog", "--opt", "hahaha" + /// ]); + /// + /// assert_eq!(m.value_of("other"), None); + /// ``` + /// [`Arg::takes_value(true)`]: ./struct.Arg.html#method.takes_value + /// [`Arg::default_value`]: ./struct.Arg.html#method.default_value + pub fn default_value_if(self, arg: &'a str, val: Option<&'b str>, default: &'b str) -> Self { + self.default_value_if_os(arg, + val.map(str::as_bytes).map(OsStr::from_bytes), + OsStr::from_bytes(default.as_bytes())) + } + + /// Provides a conditional default value in the exact same manner as [`Arg::default_value_if`] + /// only using [`OsStr`]s instead. + /// [`Arg::default_value_if`]: ./struct.Arg.html#method.default_value_if + /// [`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html + pub fn default_value_if_os(mut self, + arg: &'a str, + val: Option<&'b OsStr>, + default: &'b OsStr) + -> Self { self.setb(ArgSettings::TakesValue); - self.default_val = Some(val); + if let Some(ref mut vm) = self.v.default_vals_ifs { + let l = vm.len(); + vm.insert(l, (arg, val, default)); + } else { + let mut vm = VecMap::new(); + vm.insert(0, (arg, val, default)); + self.v.default_vals_ifs = Some(vm); + } + self + } + + /// Specifies multiple values and conditions in the same manner as [`Arg::default_value_if`]. + /// The method takes a slice of tuples in the `(arg, Option, default)` format. + /// + /// **NOTE**: The conditions are stored in order and evaluated in the same order. I.e. the first + /// if multiple conditions are true, the first one found will be applied and the ultimate value. + /// + /// **NOTE:** If using YAML the values should be laid out as follows + /// + /// ```yaml + /// default_value_if: + /// - [arg, val, default] + /// - [arg2, null, default2] + /// ``` + /// + /// # Examples + /// + /// First we use the default value only if another arg is present at runtime. + /// + /// ```rust + /// # use clap::{App, Arg}; + /// let m = App::new("prog") + /// .arg(Arg::with_name("flag") + /// .long("flag")) + /// .arg(Arg::with_name("opt") + /// .long("opt") + /// .takes_value(true)) + /// .arg(Arg::with_name("other") + /// .long("other") + /// .default_value_ifs(&[ + /// ("flag", None, "default"), + /// ("opt", Some("channal"), "chan"), + /// ])) + /// .get_matches_from(vec![ + /// "prog", "--opt", "channal" + /// ]); + /// + /// assert_eq!(m.value_of("other"), Some("chan")); + /// ``` + /// + /// Next we run the same test, but without providing `--flag`. + /// + /// ```rust + /// # use clap::{App, Arg}; + /// let m = App::new("prog") + /// .arg(Arg::with_name("flag") + /// .long("flag")) + /// .arg(Arg::with_name("other") + /// .long("other") + /// .default_value_ifs(&[ + /// ("flag", None, "default"), + /// ("opt", Some("channal"), "chan"), + /// ])) + /// .get_matches_from(vec![ + /// "prog" + /// ]); + /// + /// assert_eq!(m.value_of("other"), None); + /// ``` + /// + /// We can also see that these values are applied in order, and if more than one condition is + /// true, only the first evaluatd "wins" + /// + /// ```rust + /// # use clap::{App, Arg}; + /// let m = App::new("prog") + /// .arg(Arg::with_name("flag") + /// .long("flag")) + /// .arg(Arg::with_name("opt") + /// .long("opt") + /// .takes_value(true)) + /// .arg(Arg::with_name("other") + /// .long("other") + /// .default_value_ifs(&[ + /// ("flag", None, "default"), + /// ("opt", Some("channal"), "chan"), + /// ])) + /// .get_matches_from(vec![ + /// "prog", "--opt", "channal", "--flag" + /// ]); + /// + /// assert_eq!(m.value_of("other"), Some("default")); + /// ``` + /// [`Arg::takes_value(true)`]: ./struct.Arg.html#method.takes_value + /// [`Arg::default_value`]: ./struct.Arg.html#method.default_value + pub fn default_value_ifs(mut self, ifs: &[(&'a str, Option<&'b str>, &'b str)]) -> Self { + for &(arg, val, default) in ifs { + self = self.default_value_if_os(arg, + val.map(str::as_bytes).map(OsStr::from_bytes), + OsStr::from_bytes(default.as_bytes())); + } + self + } + + /// Provides multiple conditional default values in the exact same manner as + /// [`Arg::default_value_ifs`] only using [`OsStr`]s instead. + /// [`Arg::default_value_ifs`]: ./struct.Arg.html#method.default_value_ifs + /// [`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html + #[cfg_attr(feature = "lints", allow(explicit_counter_loop))] + pub fn default_value_ifs_os(mut self, ifs: &[(&'a str, Option<&'b OsStr>, &'b OsStr)]) -> Self { + for &(arg, val, default) in ifs { + self = self.default_value_if_os(arg, val, default); + } self } @@ -2417,7 +3322,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("nlh") + /// let m = App::new("prog") /// .arg(Arg::with_name("opt") /// .long("long-option-flag") /// .short("o") @@ -2428,7 +3333,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// on a line after the option") /// .next_line_help(true)) /// .get_matches_from(vec![ - /// "nlh", "--help" + /// "prog", "--help" /// ]); /// ``` /// @@ -2475,7 +3380,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// ```rust /// # use clap::{App, Arg}; - /// let m = App::new("cust-ord") + /// let m = App::new("prog") /// .arg(Arg::with_name("a") // Typically args are grouped alphabetically by name. /// // Args without a display_order have a value of 999 and are /// // displayed alphabetically with all other 999 valued args. @@ -2493,7 +3398,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// // alphabetically with this one...then 2 values, then 3, etc. /// .help("I should be first!")) /// .get_matches_from(vec![ - /// "cust-ord", "--help" + /// "prog", "--help" /// ]); /// ``` /// @@ -2516,13 +3421,13 @@ impl<'a, 'b> Arg<'a, 'b> { /// [positional arguments]: ./struct.Arg.html#method.index /// [index]: ./struct.Arg.html#method.index pub fn display_order(mut self, ord: usize) -> Self { - self.disp_ord = ord; + self.s.disp_ord = ord; self } /// Checks if one of the [`ArgSettings`] settings is set for the argument /// [`ArgSettings`]: ./enum.ArgSettings.html - pub fn is_set(&self, s: ArgSettings) -> bool { self.settings.is_set(s) } + pub fn is_set(&self, s: ArgSettings) -> bool { self.b.is_set(s) } /// Sets one of the [`ArgSettings`] settings for the argument /// [`ArgSettings`]: ./enum.ArgSettings.html @@ -2539,64 +3444,26 @@ impl<'a, 'b> Arg<'a, 'b> { } #[doc(hidden)] - pub fn setb(&mut self, s: ArgSettings) { self.settings.set(s); } + pub fn setb(&mut self, s: ArgSettings) { self.b.set(s); } #[doc(hidden)] - pub fn unsetb(&mut self, s: ArgSettings) { self.settings.unset(s); } + pub fn unsetb(&mut self, s: ArgSettings) { self.b.unset(s); } } impl<'a, 'b, 'z> From<&'z Arg<'a, 'b>> for Arg<'a, 'b> { fn from(a: &'z Arg<'a, 'b>) -> Self { Arg { - name: a.name, - short: a.short, - long: a.long, - aliases: a.aliases.clone(), - help: a.help, + b: a.b.clone(), + v: a.v.clone(), + s: a.s.clone(), index: a.index, - possible_vals: a.possible_vals.clone(), - blacklist: a.blacklist.clone(), - requires: a.requires.clone(), - num_vals: a.num_vals, - min_vals: a.min_vals, - max_vals: a.max_vals, - val_names: a.val_names.clone(), - groups: a.groups.clone(), - validator: a.validator.clone(), - overrides: a.overrides.clone(), - settings: a.settings, - val_delim: a.val_delim, - default_val: a.default_val, - disp_ord: a.disp_ord, - r_unless: a.r_unless.clone(), + r_ifs: a.r_ifs.clone(), } } } -impl<'a, 'b> Clone for Arg<'a, 'b> { - fn clone(&self) -> Self { - Arg { - name: self.name, - short: self.short, - long: self.long, - aliases: self.aliases.clone(), - help: self.help, - index: self.index, - possible_vals: self.possible_vals.clone(), - blacklist: self.blacklist.clone(), - requires: self.requires.clone(), - num_vals: self.num_vals, - min_vals: self.min_vals, - max_vals: self.max_vals, - val_names: self.val_names.clone(), - groups: self.groups.clone(), - validator: self.validator.clone(), - overrides: self.overrides.clone(), - settings: self.settings, - val_delim: self.val_delim, - default_val: self.default_val, - disp_ord: self.disp_ord, - r_unless: self.r_unless.clone(), - } +impl<'n, 'e> PartialEq for Arg<'n, 'e> { + fn eq(&self, other: &Arg<'n, 'e>) -> bool { + self.b == other.b } } diff --git a/src/vendor/clap/src/args/arg_builder/base.rs b/src/vendor/clap/src/args/arg_builder/base.rs index 3c6a8a92f7..5990bc0826 100644 --- a/src/vendor/clap/src/args/arg_builder/base.rs +++ b/src/vendor/clap/src/args/arg_builder/base.rs @@ -1,57 +1,35 @@ -use args::{ArgSettings, Arg, ArgFlags, ArgKind}; -#[derive(Debug, Clone)] +use args::{ArgSettings, Arg, ArgFlags}; + +#[derive(Debug, Clone, Default)] pub struct Base<'a, 'b> where 'a: 'b { pub name: &'a str, - pub id: usize, - pub kind: ArgKind, pub help: Option<&'b str>, + pub long_help: Option<&'b str>, pub blacklist: Option>, pub settings: ArgFlags, pub r_unless: Option>, pub overrides: Option>, pub groups: Option>, - pub requires: Option>, -} - -impl<'n, 'e> Default for Base<'n, 'e> { - fn default() -> Self { - Base { - name: "", - id: 0, - kind: ArgKind::Pos, - help: None, - blacklist: None, - settings: ArgFlags::new(), - r_unless: None, - overrides: None, - requires: None, - groups: None, - } - } + pub requires: Option, &'a str)>>, } impl<'n, 'e> Base<'n, 'e> { pub fn new(name: &'n str) -> Self { Base { name: name, ..Default::default() } } pub fn set(&mut self, s: ArgSettings) { self.settings.set(s); } + pub fn unset(&mut self, s: ArgSettings) { self.settings.unset(s); } + pub fn is_set(&self, s: ArgSettings) -> bool { self.settings.is_set(s) } } impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for Base<'n, 'e> { - fn from(a: &'z Arg<'n, 'e>) -> Self { - Base { - name: a.name, - help: a.help, - id: 0, - kind: ArgKind::Pos, - blacklist: a.blacklist.clone(), - settings: a.settings, - r_unless: a.r_unless.clone(), - overrides: a.overrides.clone(), - requires: a.requires.clone(), - groups: a.groups.clone(), - } - } + fn from(a: &'z Arg<'n, 'e>) -> Self { a.b.clone() } } + +impl<'n, 'e> PartialEq for Base<'n, 'e> { + fn eq(&self, other: &Base<'n, 'e>) -> bool { + self.name == other.name + } +} \ No newline at end of file diff --git a/src/vendor/clap/src/args/arg_builder/flag.rs b/src/vendor/clap/src/args/arg_builder/flag.rs index fcec7aadcc..e3e9dd0162 100644 --- a/src/vendor/clap/src/args/arg_builder/flag.rs +++ b/src/vendor/clap/src/args/arg_builder/flag.rs @@ -3,13 +3,15 @@ use std::convert::From; use std::fmt::{Display, Formatter, Result}; use std::rc::Rc; use std::result::Result as StdResult; +use std::ffi::{OsStr, OsString}; +use std::mem; // Third Party -use vec_map::VecMap; +use vec_map::{self, VecMap}; // Internal use Arg; -use args::{ArgSettings, ArgKind, Base, Switched, AnyArg, DispOrder}; +use args::{ArgSettings, Base, Switched, AnyArg, DispOrder}; #[derive(Default, Clone, Debug)] #[doc(hidden)] @@ -26,8 +28,6 @@ impl<'n, 'e> FlagBuilder<'n, 'e> { impl<'a, 'b, 'z> From<&'z Arg<'a, 'b>> for FlagBuilder<'a, 'b> { fn from(a: &'z Arg<'a, 'b>) -> Self { - // No need to check for index() or takes_value() as that is handled above - FlagBuilder { b: Base::from(a), s: Switched::from(a), @@ -35,6 +35,15 @@ impl<'a, 'b, 'z> From<&'z Arg<'a, 'b>> for FlagBuilder<'a, 'b> { } } +impl<'a, 'b> From> for FlagBuilder<'a, 'b> { + fn from(mut a: Arg<'a, 'b>) -> Self { + FlagBuilder { + b: mem::replace(&mut a.b, Base::default()), + s: mem::replace(&mut a.s, Switched::default()), + } + } +} + impl<'n, 'e> Display for FlagBuilder<'n, 'e> { fn fmt(&self, f: &mut Formatter) -> Result { if let Some(l) = self.s.long { @@ -49,10 +58,10 @@ impl<'n, 'e> Display for FlagBuilder<'n, 'e> { impl<'n, 'e> AnyArg<'n, 'e> for FlagBuilder<'n, 'e> { fn name(&self) -> &'n str { self.b.name } - fn id(&self) -> usize { self.b.id } - fn kind(&self) -> ArgKind { ArgKind::Flag } fn overrides(&self) -> Option<&[&'e str]> { self.b.overrides.as_ref().map(|o| &o[..]) } - fn requires(&self) -> Option<&[&'e str]> { self.b.requires.as_ref().map(|o| &o[..]) } + fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> { + self.b.requires.as_ref().map(|o| &o[..]) + } fn blacklist(&self) -> Option<&[&'e str]> { self.b.blacklist.as_ref().map(|o| &o[..]) } fn required_unless(&self) -> Option<&[&'e str]> { None } fn is_set(&self, s: ArgSettings) -> bool { self.b.settings.is_set(s) } @@ -64,12 +73,18 @@ impl<'n, 'e> AnyArg<'n, 'e> for FlagBuilder<'n, 'e> { fn num_vals(&self) -> Option { None } fn possible_vals(&self) -> Option<&[&'e str]> { None } fn validator(&self) -> Option<&Rc StdResult<(), String>>> { None } + fn validator_os(&self) -> Option<&Rc StdResult<(), OsString>>> { None } fn min_vals(&self) -> Option { None } fn short(&self) -> Option { self.s.short } fn long(&self) -> Option<&'e str> { self.s.long } fn val_delim(&self) -> Option { None } fn help(&self) -> Option<&'e str> { self.b.help } - fn default_val(&self) -> Option<&'n str> { None } + fn long_help(&self) -> Option<&'e str> { self.b.long_help } + fn val_terminator(&self) -> Option<&'e str> { None } + fn default_val(&self) -> Option<&'e OsStr> { None } + fn default_vals_ifs(&self) -> Option, &'e OsStr)>> { + None + } fn longest_filter(&self) -> bool { self.s.long.is_some() } fn aliases(&self) -> Option> { if let Some(ref aliases) = self.s.aliases { @@ -91,6 +106,12 @@ impl<'n, 'e> DispOrder for FlagBuilder<'n, 'e> { fn disp_ord(&self) -> usize { self.s.disp_ord } } +impl<'n, 'e> PartialEq for FlagBuilder<'n, 'e> { + fn eq(&self, other: &FlagBuilder<'n, 'e>) -> bool { + self.b == other.b + } +} + #[cfg(test)] mod test { use args::settings::ArgSettings; diff --git a/src/vendor/clap/src/args/arg_builder/option.rs b/src/vendor/clap/src/args/arg_builder/option.rs index 54c3f11f9e..6d77df046b 100644 --- a/src/vendor/clap/src/args/arg_builder/option.rs +++ b/src/vendor/clap/src/args/arg_builder/option.rs @@ -2,12 +2,14 @@ use std::fmt::{Display, Formatter, Result}; use std::rc::Rc; use std::result::Result as StdResult; +use std::ffi::{OsStr, OsString}; +use std::mem; // Third Party -use vec_map::VecMap; +use vec_map::{self, VecMap}; // Internal -use args::{ArgSettings, ArgKind, AnyArg, Base, Switched, Valued, Arg, DispOrder}; +use args::{ArgSettings, AnyArg, Base, Switched, Valued, Arg, DispOrder}; #[allow(missing_debug_implementations)] #[doc(hidden)] @@ -22,32 +24,42 @@ pub struct OptBuilder<'n, 'e> impl<'n, 'e> OptBuilder<'n, 'e> { pub fn new(name: &'n str) -> Self { OptBuilder { b: Base::new(name), ..Default::default() } } +} - pub fn from_arg(a: &Arg<'n, 'e>, reqs: &mut Vec<&'e str>) -> Self { - // No need to check for .index() as that is handled above - let ob = OptBuilder { +impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for OptBuilder<'n, 'e> { + fn from(a: &'z Arg<'n, 'e>) -> Self { + OptBuilder { b: Base::from(a), s: Switched::from(a), v: Valued::from(a), - }; - // If the arg is required, add all it's requirements to master required list - if a.is_set(ArgSettings::Required) { - if let Some(ref areqs) = a.requires { - reqs.extend_from_slice(areqs); - } } - ob + } +} + +impl<'n, 'e> From> for OptBuilder<'n, 'e> { + fn from(mut a: Arg<'n, 'e>) -> Self { + a.v.fill_in(); + OptBuilder { + b: mem::replace(&mut a.b, Base::default()), + s: mem::replace(&mut a.s, Switched::default()), + v: mem::replace(&mut a.v, Valued::default()), + } } } impl<'n, 'e> Display for OptBuilder<'n, 'e> { fn fmt(&self, f: &mut Formatter) -> Result { - debugln!("fn=fmt"); + debugln!("OptBuilder::fmt:{}", self.b.name); + let sep = if self.b.is_set(ArgSettings::RequireEquals) { + "=" + } else { + " " + }; // Write the name such --long or -l if let Some(l) = self.s.long { - try!(write!(f, "--{} ", l)); + try!(write!(f, "--{}{}", l, sep)); } else { - try!(write!(f, "-{} ", self.s.short.unwrap())); + try!(write!(f, "-{}{}", self.s.short.unwrap(), sep)); } // Write the values such as @@ -91,10 +103,10 @@ impl<'n, 'e> Display for OptBuilder<'n, 'e> { impl<'n, 'e> AnyArg<'n, 'e> for OptBuilder<'n, 'e> { fn name(&self) -> &'n str { self.b.name } - fn id(&self) -> usize { self.b.id } - fn kind(&self) -> ArgKind { ArgKind::Opt } fn overrides(&self) -> Option<&[&'e str]> { self.b.overrides.as_ref().map(|o| &o[..]) } - fn requires(&self) -> Option<&[&'e str]> { self.b.requires.as_ref().map(|o| &o[..]) } + fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> { + self.b.requires.as_ref().map(|o| &o[..]) + } fn blacklist(&self) -> Option<&[&'e str]> { self.b.blacklist.as_ref().map(|o| &o[..]) } fn required_unless(&self) -> Option<&[&'e str]> { self.b.r_unless.as_ref().map(|o| &o[..]) } fn val_names(&self) -> Option<&VecMap<&'e str>> { self.v.val_names.as_ref() } @@ -102,18 +114,26 @@ impl<'n, 'e> AnyArg<'n, 'e> for OptBuilder<'n, 'e> { fn has_switch(&self) -> bool { true } fn set(&mut self, s: ArgSettings) { self.b.settings.set(s) } fn max_vals(&self) -> Option { self.v.max_vals } + fn val_terminator(&self) -> Option<&'e str> { self.v.terminator } fn num_vals(&self) -> Option { self.v.num_vals } fn possible_vals(&self) -> Option<&[&'e str]> { self.v.possible_vals.as_ref().map(|o| &o[..]) } fn validator(&self) -> Option<&Rc StdResult<(), String>>> { self.v.validator.as_ref() } + fn validator_os(&self) -> Option<&Rc StdResult<(), OsString>>> { + self.v.validator_os.as_ref() + } fn min_vals(&self) -> Option { self.v.min_vals } fn short(&self) -> Option { self.s.short } fn long(&self) -> Option<&'e str> { self.s.long } fn val_delim(&self) -> Option { self.v.val_delim } fn takes_value(&self) -> bool { true } fn help(&self) -> Option<&'e str> { self.b.help } - fn default_val(&self) -> Option<&'n str> { self.v.default_val } + fn long_help(&self) -> Option<&'e str> { self.b.long_help } + fn default_val(&self) -> Option<&'e OsStr> { self.v.default_val } + fn default_vals_ifs(&self) -> Option, &'e OsStr)>> { + self.v.default_vals_ifs.as_ref().map(|vm| vm.values()) + } fn longest_filter(&self) -> bool { true } fn aliases(&self) -> Option> { if let Some(ref aliases) = self.s.aliases { @@ -135,6 +155,12 @@ impl<'n, 'e> DispOrder for OptBuilder<'n, 'e> { fn disp_ord(&self) -> usize { self.s.disp_ord } } +impl<'n, 'e> PartialEq for OptBuilder<'n, 'e> { + fn eq(&self, other: &OptBuilder<'n, 'e>) -> bool { + self.b == other.b + } +} + #[cfg(test)] mod test { use args::settings::ArgSettings; diff --git a/src/vendor/clap/src/args/arg_builder/positional.rs b/src/vendor/clap/src/args/arg_builder/positional.rs index ec5af27b5e..85442023c9 100644 --- a/src/vendor/clap/src/args/arg_builder/positional.rs +++ b/src/vendor/clap/src/args/arg_builder/positional.rs @@ -3,13 +3,16 @@ use std::borrow::Cow; use std::fmt::{Display, Formatter, Result}; use std::rc::Rc; use std::result::Result as StdResult; +use std::ffi::{OsStr, OsString}; +use std::mem; // Third Party -use vec_map::VecMap; +use vec_map::{self, VecMap}; // Internal use Arg; -use args::{ArgSettings, Base, Valued, ArgKind, AnyArg, DispOrder}; +use args::{ArgSettings, Base, Valued, AnyArg, DispOrder}; +use INTERNAL_ERROR_MSG; #[allow(missing_debug_implementations)] #[doc(hidden)] @@ -31,30 +34,37 @@ impl<'n, 'e> PosBuilder<'n, 'e> { } } - pub fn from_arg(a: &Arg<'n, 'e>, idx: u64, reqs: &mut Vec<&'e str>) -> Self { - // Create the Positional Argument Builder with each HashSet = None to only - // allocate - // those that require it + pub fn from_arg_ref(a: &Arg<'n, 'e>, idx: u64) -> Self { let mut pb = PosBuilder { b: Base::from(a), v: Valued::from(a), index: idx, }; - if a.max_vals.is_some() || a.min_vals.is_some() || - (a.num_vals.is_some() && a.num_vals.unwrap() > 1) { + if a.v.max_vals.is_some() || a.v.min_vals.is_some() || + (a.v.num_vals.is_some() && a.v.num_vals.unwrap() > 1) { pb.b.settings.set(ArgSettings::Multiple); } - // If the arg is required, add all it's requirements to master required list - if a.is_set(ArgSettings::Required) { - if let Some(ref areqs) = a.requires { - reqs.extend_from_slice(areqs); - } - } pb } + pub fn from_arg(mut a: Arg<'n, 'e>, idx: u64) -> Self { + if a.v.max_vals.is_some() || a.v.min_vals.is_some() || + (a.v.num_vals.is_some() && a.v.num_vals.unwrap() > 1) { + a.b.settings.set(ArgSettings::Multiple); + } + PosBuilder { + b: mem::replace(&mut a.b, Base::default()), + v: mem::replace(&mut a.v, Valued::default()), + index: idx, + } + } + pub fn multiple_str(&self) -> &str { - if self.b.settings.is_set(ArgSettings::Multiple) && self.v.val_names.is_none() { + let mult_vals = self.v + .val_names + .as_ref() + .map_or(true, |names| names.len() < 2); + if self.is_set(ArgSettings::Multiple) && mult_vals { "..." } else { "" @@ -62,12 +72,20 @@ impl<'n, 'e> PosBuilder<'n, 'e> { } pub fn name_no_brackets(&self) -> Cow { + debugln!("PosBuilder::name_no_brackets;"); if let Some(ref names) = self.v.val_names { - Cow::Owned(names.values() - .map(|n| format!("<{}>", n)) - .collect::>() - .join(" ")) + debugln!("PosBuilder:name_no_brackets: val_names={:#?}", names); + if names.len() > 1 { + Cow::Owned(names + .values() + .map(|n| format!("<{}>", n)) + .collect::>() + .join(" ")) + } else { + Cow::Borrowed(names.values().next().expect(INTERNAL_ERROR_MSG)) + } } else { + debugln!("PosBuilder:name_no_brackets: just name"); Cow::Borrowed(self.b.name) } } @@ -78,14 +96,15 @@ impl<'n, 'e> Display for PosBuilder<'n, 'e> { if let Some(ref names) = self.v.val_names { try!(write!(f, "{}", - names.values() + names + .values() .map(|n| format!("<{}>", n)) .collect::>() .join(" "))); } else { try!(write!(f, "<{}>", self.b.name)); } - if self.b.settings.is_set(ArgSettings::Multiple) && self.v.val_names.is_none() { + if self.b.settings.is_set(ArgSettings::Multiple) && (self.v.val_names.is_none() || self.v.val_names.as_ref().unwrap().len() == 1) { try!(write!(f, "...")); } @@ -95,10 +114,10 @@ impl<'n, 'e> Display for PosBuilder<'n, 'e> { impl<'n, 'e> AnyArg<'n, 'e> for PosBuilder<'n, 'e> { fn name(&self) -> &'n str { self.b.name } - fn id(&self) -> usize { self.b.id } - fn kind(&self) -> ArgKind { ArgKind::Pos } fn overrides(&self) -> Option<&[&'e str]> { self.b.overrides.as_ref().map(|o| &o[..]) } - fn requires(&self) -> Option<&[&'e str]> { self.b.requires.as_ref().map(|o| &o[..]) } + fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> { + self.b.requires.as_ref().map(|o| &o[..]) + } fn blacklist(&self) -> Option<&[&'e str]> { self.b.blacklist.as_ref().map(|o| &o[..]) } fn required_unless(&self) -> Option<&[&'e str]> { self.b.r_unless.as_ref().map(|o| &o[..]) } fn val_names(&self) -> Option<&VecMap<&'e str>> { self.v.val_names.as_ref() } @@ -106,18 +125,26 @@ impl<'n, 'e> AnyArg<'n, 'e> for PosBuilder<'n, 'e> { fn set(&mut self, s: ArgSettings) { self.b.settings.set(s) } fn has_switch(&self) -> bool { false } fn max_vals(&self) -> Option { self.v.max_vals } + fn val_terminator(&self) -> Option<&'e str> { self.v.terminator } fn num_vals(&self) -> Option { self.v.num_vals } fn possible_vals(&self) -> Option<&[&'e str]> { self.v.possible_vals.as_ref().map(|o| &o[..]) } fn validator(&self) -> Option<&Rc StdResult<(), String>>> { self.v.validator.as_ref() } + fn validator_os(&self) -> Option<&Rc StdResult<(), OsString>>> { + self.v.validator_os.as_ref() + } fn min_vals(&self) -> Option { self.v.min_vals } fn short(&self) -> Option { None } fn long(&self) -> Option<&'e str> { None } fn val_delim(&self) -> Option { self.v.val_delim } fn takes_value(&self) -> bool { true } fn help(&self) -> Option<&'e str> { self.b.help } - fn default_val(&self) -> Option<&'n str> { self.v.default_val } + fn long_help(&self) -> Option<&'e str> { self.b.long_help } + fn default_vals_ifs(&self) -> Option, &'e OsStr)>> { + self.v.default_vals_ifs.as_ref().map(|vm| vm.values()) + } + fn default_val(&self) -> Option<&'e OsStr> { self.v.default_val } fn longest_filter(&self) -> bool { true } fn aliases(&self) -> Option> { None } } @@ -126,6 +153,10 @@ impl<'n, 'e> DispOrder for PosBuilder<'n, 'e> { fn disp_ord(&self) -> usize { self.index as usize } } +impl<'n, 'e> PartialEq for PosBuilder<'n, 'e> { + fn eq(&self, other: &PosBuilder<'n, 'e>) -> bool { self.b == other.b } +} + #[cfg(test)] mod test { use args::settings::ArgSettings; diff --git a/src/vendor/clap/src/args/arg_builder/switched.rs b/src/vendor/clap/src/args/arg_builder/switched.rs index 33402e16b3..e42586c260 100644 --- a/src/vendor/clap/src/args/arg_builder/switched.rs +++ b/src/vendor/clap/src/args/arg_builder/switched.rs @@ -1,3 +1,4 @@ + use Arg; #[derive(Debug)] @@ -22,15 +23,7 @@ impl<'e> Default for Switched<'e> { } impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for Switched<'e> { - fn from(a: &'z Arg<'n, 'e>) -> Self { - Switched { - short: a.short, - long: a.long, - aliases: a.aliases.clone(), - disp_ord: a.disp_ord, - ..Default::default() - } - } + fn from(a: &'z Arg<'n, 'e>) -> Self { a.s.clone() } } impl<'e> Clone for Switched<'e> { diff --git a/src/vendor/clap/src/args/arg_builder/valued.rs b/src/vendor/clap/src/args/arg_builder/valued.rs index eba045020f..93d63cce0b 100644 --- a/src/vendor/clap/src/args/arg_builder/valued.rs +++ b/src/vendor/clap/src/args/arg_builder/valued.rs @@ -1,4 +1,5 @@ use std::rc::Rc; +use std::ffi::{OsStr, OsString}; use vec_map::VecMap; @@ -15,8 +16,11 @@ pub struct Valued<'a, 'b> pub max_vals: Option, pub min_vals: Option, pub validator: Option Result<(), String>>>, + pub validator_os: Option Result<(), OsString>>>, pub val_delim: Option, - pub default_val: Option<&'a str>, + pub default_val: Option<&'b OsStr>, + pub default_vals_ifs: Option, &'b OsStr)>>, + pub terminator: Option<&'b str>, } impl<'n, 'e> Default for Valued<'n, 'e> { @@ -28,30 +32,29 @@ impl<'n, 'e> Default for Valued<'n, 'e> { max_vals: None, val_names: None, validator: None, - val_delim: Some(','), + validator_os: None, + val_delim: None, default_val: None, + default_vals_ifs: None, + terminator: None, } } } -impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for Valued<'n, 'e> { - fn from(a: &'z Arg<'n, 'e>) -> Self { - let mut v = Valued { - possible_vals: a.possible_vals.clone(), - num_vals: a.num_vals, - min_vals: a.min_vals, - max_vals: a.max_vals, - val_names: a.val_names.clone(), - validator: a.validator.clone(), - val_delim: a.val_delim, - default_val: a.default_val, - }; - if let Some(ref vec) = a.val_names { +impl<'n, 'e> Valued<'n, 'e> { + pub fn fill_in(&mut self) { + if let Some(ref vec) = self.val_names { if vec.len() > 1 { - v.num_vals = Some(vec.len() as u64); + self.num_vals = Some(vec.len() as u64); } } - if let Some(ref vec) = a.val_names { + } +} + +impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for Valued<'n, 'e> { + fn from(a: &'z Arg<'n, 'e>) -> Self { + let mut v = a.v.clone(); + if let Some(ref vec) = a.v.val_names { if vec.len() > 1 { v.num_vals = Some(vec.len() as u64); } diff --git a/src/vendor/clap/src/args/arg_matcher.rs b/src/vendor/clap/src/args/arg_matcher.rs index d11044d46d..12e58fc13c 100644 --- a/src/vendor/clap/src/args/arg_matcher.rs +++ b/src/vendor/clap/src/args/arg_matcher.rs @@ -2,9 +2,7 @@ use std::collections::hash_map::{Entry, Iter}; use std::ffi::OsStr; use std::ops::Deref; - -// Third Party -use vec_map::VecMap; +use std::mem; // Internal use args::{ArgMatches, MatchedArg, SubCommand}; @@ -22,6 +20,34 @@ impl<'a> Default for ArgMatcher<'a> { impl<'a> ArgMatcher<'a> { pub fn new() -> Self { ArgMatcher::default() } + pub fn propagate(&mut self, arg: &'a str) { + debugln!("ArgMatcher::propagate: arg={}", arg); + let vals: Vec<_> = if let Some(ma) = self.get(arg) { + ma.vals.clone() + } else { + debugln!("ArgMatcher::propagate: arg wasn't used"); + return; + }; + if let Some(ref mut sc) = self.0.subcommand { + { + let sma = (*sc).matches.args.entry(arg).or_insert_with(|| { + let mut gma = MatchedArg::new(); + gma.occurs += 1; + gma.vals = vals.clone(); + gma + }); + if sma.vals.is_empty() { + sma.vals = vals.clone(); + } + } + let mut am = ArgMatcher(mem::replace(&mut sc.matches, ArgMatches::new())); + am.propagate(arg); + mem::swap(&mut am.0, &mut sc.matches); + } else { + debugln!("ArgMatcher::propagate: Subcommand wasn't used"); + } + } + pub fn get_mut(&mut self, arg: &str) -> Option<&mut MatchedArg> { self.0.args.get_mut(arg) } pub fn get(&self, arg: &str) -> Option<&MatchedArg> { self.0.args.get(arg) } @@ -53,17 +79,17 @@ impl<'a> ArgMatcher<'a> { pub fn iter(&self) -> Iter<&str, MatchedArg> { self.0.args.iter() } pub fn inc_occurrence_of(&mut self, arg: &'a str) { - debugln!("fn=inc_occurrence_of;"); + debugln!("ArgMatcher::inc_occurrence_of: arg={}", arg); if let Some(a) = self.get_mut(arg) { - debugln!("+1 to {}'s occurrences", arg); a.occurs += 1; return; } + debugln!("ArgMatcher::inc_occurrence_of: first instance"); self.insert(arg); } pub fn inc_occurrences_of(&mut self, args: &[&'a str]) { - debugln!("fn=inc_occurrences_of;"); + debugln!("ArgMatcher::inc_occurrences_of: args={:?}", args); for arg in args { self.inc_occurrence_of(arg); } @@ -72,29 +98,29 @@ impl<'a> ArgMatcher<'a> { pub fn add_val_to(&mut self, arg: &'a str, val: &OsStr) { let ma = self.entry(arg).or_insert(MatchedArg { occurs: 0, - vals: VecMap::new(), + vals: Vec::with_capacity(1), }); - let len = ma.vals.len() + 1; - ma.vals.insert(len, val.to_owned()); + // let len = ma.vals.len() + 1; + ma.vals.push(val.to_owned()); } pub fn needs_more_vals<'b, A>(&self, o: &A) -> bool where A: AnyArg<'a, 'b> { - debugln!("fn=needs_more_vals;"); + debugln!("ArgMatcher::needs_more_vals: o={}", o.name()); if let Some(ma) = self.get(o.name()) { if let Some(num) = o.num_vals() { - debugln!("num_vals...{}", num); + debugln!("ArgMatcher::needs_more_vals: num_vals...{}", num); return if o.is_set(ArgSettings::Multiple) { ((ma.vals.len() as u64) % num) != 0 } else { num != (ma.vals.len() as u64) }; } else if let Some(num) = o.max_vals() { - debugln!("max_vals...{}", num); + debugln!("ArgMatcher::needs_more_vals: max_vals...{}", num); return !((ma.vals.len() as u64) > num); } else if o.min_vals().is_some() { - debugln!("min_vals...true"); + debugln!("ArgMatcher::needs_more_vals: min_vals...true"); return true; } return o.is_set(ArgSettings::Multiple); diff --git a/src/vendor/clap/src/args/arg_matches.rs b/src/vendor/clap/src/args/arg_matches.rs index b20d490d7e..011b47d7b5 100644 --- a/src/vendor/clap/src/args/arg_matches.rs +++ b/src/vendor/clap/src/args/arg_matches.rs @@ -3,10 +3,7 @@ use std::borrow::Cow; use std::collections::HashMap; use std::ffi::{OsStr, OsString}; use std::iter::Map; -use std::slice; - -// Third Party -use vec_map; +use std::slice::Iter; // Internal use INVALID_UTF8; @@ -113,7 +110,7 @@ impl<'a> ArgMatches<'a> { /// [`panic!`]: https://doc.rust-lang.org/std/macro.panic!.html pub fn value_of>(&self, name: S) -> Option<&str> { if let Some(arg) = self.args.get(name.as_ref()) { - if let Some(v) = arg.vals.values().nth(0) { + if let Some(v) = arg.vals.get(0) { return Some(v.to_str().expect(INVALID_UTF8)); } } @@ -145,7 +142,7 @@ impl<'a> ArgMatches<'a> { /// [`Arg::values_of_lossy`]: ./struct.ArgMatches.html#method.values_of_lossy pub fn value_of_lossy>(&'a self, name: S) -> Option> { if let Some(arg) = self.args.get(name.as_ref()) { - if let Some(v) = arg.vals.values().nth(0) { + if let Some(v) = arg.vals.get(0) { return Some(v.to_string_lossy()); } } @@ -182,7 +179,7 @@ impl<'a> ArgMatches<'a> { pub fn value_of_os>(&self, name: S) -> Option<&OsStr> { self.args .get(name.as_ref()) - .map_or(None, |arg| arg.vals.values().nth(0).map(|v| v.as_os_str())) + .map_or(None, |arg| arg.vals.get(0).map(|v| v.as_os_str())) } /// Gets a [`Values`] struct which implements [`Iterator`] for values of a specific argument @@ -214,7 +211,7 @@ impl<'a> ArgMatches<'a> { if let Some(arg) = self.args.get(name.as_ref()) { fn to_str_slice(o: &OsString) -> &str { o.to_str().expect(INVALID_UTF8) } let to_str_slice: fn(&OsString) -> &str = to_str_slice; // coerce to fn pointer - return Some(Values { iter: arg.vals.values().map(to_str_slice) }); + return Some(Values { iter: arg.vals.iter().map(to_str_slice) }); } None } @@ -246,7 +243,7 @@ impl<'a> ArgMatches<'a> { pub fn values_of_lossy>(&'a self, name: S) -> Option> { if let Some(arg) = self.args.get(name.as_ref()) { return Some(arg.vals - .values() + .iter() .map(|v| v.to_string_lossy().into_owned()) .collect()); } @@ -288,7 +285,7 @@ impl<'a> ArgMatches<'a> { fn to_str_slice(o: &OsString) -> &OsStr { &*o } let to_str_slice: fn(&'a OsString) -> &'a OsStr = to_str_slice; // coerce to fn pointer if let Some(arg) = self.args.get(name.as_ref()) { - return Some(OsValues { iter: arg.vals.values().map(to_str_slice) }); + return Some(OsValues { iter: arg.vals.iter().map(to_str_slice) }); } None } @@ -554,7 +551,7 @@ impl<'a> ArgMatches<'a> { #[derive(Clone)] #[allow(missing_debug_implementations)] pub struct Values<'a> { - iter: Map, fn(&'a OsString) -> &'a str>, + iter: Map, fn(&'a OsString) -> &'a str>, } impl<'a> Iterator for Values<'a> { @@ -568,49 +565,22 @@ impl<'a> DoubleEndedIterator for Values<'a> { fn next_back(&mut self) -> Option<&'a str> { self.iter.next_back() } } -/// An iterator over the key-value pairs of a map. -#[derive(Clone)] -pub struct Iter<'a, V: 'a> { - front: usize, - back: usize, - iter: slice::Iter<'a, Option>, -} +impl<'a> ExactSizeIterator for Values<'a> {} -impl<'a, V> Iterator for Iter<'a, V> { - type Item = &'a V; - - #[inline] - fn next(&mut self) -> Option<&'a V> { - while self.front < self.back { - if let Some(elem) = self.iter.next() { - if let Some(x) = elem.as_ref() { - self.front += 1; - return Some(x); - } - } - self.front += 1; - } - None +/// Creates an empty iterator. +impl Default for Values<'static> { + fn default() -> Self { + static EMPTY: [OsString; 0] = []; + // This is never called because the iterator is empty: + fn to_str_slice(_: &OsString) -> &str { unreachable!() }; + Values { iter: EMPTY[..].iter().map(to_str_slice) } } - - #[inline] - fn size_hint(&self) -> (usize, Option) { (0, Some(self.back - self.front)) } } -impl<'a, V> DoubleEndedIterator for Iter<'a, V> { - #[inline] - fn next_back(&mut self) -> Option<&'a V> { - while self.front < self.back { - if let Some(elem) = self.iter.next_back() { - if let Some(x) = elem.as_ref() { - self.back -= 1; - return Some(x); - } - } - self.back -= 1; - } - None - } +#[test] +fn test_default_values() { + let mut values: Values = Values::default(); + assert_eq!(values.next(), None); } /// An iterator for getting multiple values out of an argument via the [`ArgMatches::values_of_os`] @@ -637,7 +607,7 @@ impl<'a, V> DoubleEndedIterator for Iter<'a, V> { #[derive(Clone)] #[allow(missing_debug_implementations)] pub struct OsValues<'a> { - iter: Map, fn(&'a OsString) -> &'a OsStr>, + iter: Map, fn(&'a OsString) -> &'a OsStr>, } impl<'a> Iterator for OsValues<'a> { @@ -650,3 +620,19 @@ impl<'a> Iterator for OsValues<'a> { impl<'a> DoubleEndedIterator for OsValues<'a> { fn next_back(&mut self) -> Option<&'a OsStr> { self.iter.next_back() } } + +/// Creates an empty iterator. +impl Default for OsValues<'static> { + fn default() -> Self { + static EMPTY: [OsString; 0] = []; + // This is never called because the iterator is empty: + fn to_str_slice(_: &OsString) -> &OsStr { unreachable!() }; + OsValues { iter: EMPTY[..].iter().map(to_str_slice) } + } +} + +#[test] +fn test_default_osvalues() { + let mut values: OsValues = OsValues::default(); + assert_eq!(values.next(), None); +} diff --git a/src/vendor/clap/src/args/group.rs b/src/vendor/clap/src/args/group.rs index 54f4afa4d5..1d555aba4c 100644 --- a/src/vendor/clap/src/args/group.rs +++ b/src/vendor/clap/src/args/group.rs @@ -10,8 +10,9 @@ use yaml_rust::Yaml; /// exclusion rules instead of having to list each argument individually, or when you want a rule /// to apply "any but not all" arguments. /// -/// For instance, you can make an entire `ArgGroup` required, this means that one (and *only* one, -/// if [`ArgGroup::multiple(true)`] is set) argument from that group must be present. +/// For instance, you can make an entire `ArgGroup` required. If [`ArgGroup::multiple(true)`] is +/// set, this means that at least one argument from that group must be present. If +/// [`ArgGroup::multiple(false)`] is set (the default), one and *only* one must be present. /// /// You can also do things such as name an entire `ArgGroup` as a [conflict] or [requirement] for /// another argument, meaning any of the arguments that belong to that group will cause a failure @@ -151,6 +152,7 @@ impl<'a> ArgGroup<'a> { /// assert!(m.is_present("flag")); /// ``` /// [argument]: ./struct.Arg.html + #[cfg_attr(feature = "lints", allow(should_assert_eq))] pub fn arg(mut self, n: &'a str) -> Self { assert!(self.name != n, "ArgGroup '{}' can not have same name as arg inside it", @@ -470,9 +472,10 @@ impl<'a> From<&'a BTreeMap> for ArgGroup<'a> { b }; - for (k, v) in group_settings.iter() { + for (k, v) in group_settings { a = match k.as_str().unwrap() { "required" => a.required(v.as_bool().unwrap()), + "multiple" => a.multiple(v.as_bool().unwrap()), "args" => yaml_vec_or_str!(v, a, arg), "arg" => { if let Some(ys) = v.as_str() { diff --git a/src/vendor/clap/src/args/macros.rs b/src/vendor/clap/src/args/macros.rs index 1a0ad6bbee..1de12f4ec2 100644 --- a/src/vendor/clap/src/args/macros.rs +++ b/src/vendor/clap/src/args/macros.rs @@ -1,4 +1,44 @@ +#[cfg(feature = "yaml")] +macro_rules! yaml_tuple2 { + ($a:ident, $v:ident, $c:ident) => {{ + if let Some(vec) = $v.as_vec() { + for ys in vec { + if let Some(tup) = ys.as_vec() { + debug_assert_eq!(2, tup.len()); + $a = $a.$c(yaml_str!(tup[0]), yaml_str!(tup[1])); + } else { + panic!("Failed to convert YAML value to vec"); + } + } + } else { + panic!("Failed to convert YAML value to vec"); + } + $a + } + }; +} + +#[cfg(feature = "yaml")] +macro_rules! yaml_tuple3 { + ($a:ident, $v:ident, $c:ident) => {{ + if let Some(vec) = $v.as_vec() { + for ys in vec { + if let Some(tup) = ys.as_vec() { + debug_assert_eq!(3, tup.len()); + $a = $a.$c(yaml_str!(tup[0]), yaml_opt_str!(tup[1]), yaml_str!(tup[2])); + } else { + panic!("Failed to convert YAML value to vec"); + } + } + } else { + panic!("Failed to convert YAML value to vec"); + } + $a + } + }; +} +#[cfg(feature = "yaml")] macro_rules! yaml_vec_or_str { ($v:ident, $a:ident, $c:ident) => {{ let maybe_vec = $v.as_vec(); @@ -22,24 +62,46 @@ macro_rules! yaml_vec_or_str { }; } +#[cfg(feature = "yaml")] +macro_rules! yaml_opt_str { + ($v:expr) => {{ + if $v.is_null() { + Some($v.as_str().unwrap_or_else(|| panic!("failed to convert YAML {:?} value to a string", $v))) + } else { + None + } + }}; +} + +#[cfg(feature = "yaml")] +macro_rules! yaml_str { + ($v:expr) => {{ + $v.as_str().unwrap_or_else(|| panic!("failed to convert YAML {:?} value to a string", $v)) + }}; +} + +#[cfg(feature = "yaml")] macro_rules! yaml_to_str { ($a:ident, $v:ident, $c:ident) => {{ - $a.$c($v.as_str().unwrap_or_else(|| panic!("failed to convert YAML {:?} value to a string", $v))) + $a.$c(yaml_str!($v)) }}; } +#[cfg(feature = "yaml")] macro_rules! yaml_to_bool { ($a:ident, $v:ident, $c:ident) => {{ $a.$c($v.as_bool().unwrap_or_else(|| panic!("failed to convert YAML {:?} value to a string", $v))) }}; } +#[cfg(feature = "yaml")] macro_rules! yaml_to_u64 { ($a:ident, $v:ident, $c:ident) => {{ $a.$c($v.as_i64().unwrap_or_else(|| panic!("failed to convert YAML {:?} value to a string", $v)) as u64) }}; } +#[cfg(feature = "yaml")] macro_rules! yaml_to_usize { ($a:ident, $v:ident, $c:ident) => {{ $a.$c($v.as_i64().unwrap_or_else(|| panic!("failed to convert YAML {:?} value to a string", $v)) as usize) diff --git a/src/vendor/clap/src/args/matched_arg.rs b/src/vendor/clap/src/args/matched_arg.rs index e852f26c52..9a73af9d59 100644 --- a/src/vendor/clap/src/args/matched_arg.rs +++ b/src/vendor/clap/src/args/matched_arg.rs @@ -1,23 +1,20 @@ // Std use std::ffi::OsString; -// Third Party -use vec_map::VecMap; - #[doc(hidden)] #[derive(Debug, Clone)] pub struct MatchedArg { #[doc(hidden)] pub occurs: u64, #[doc(hidden)] - pub vals: VecMap, + pub vals: Vec, } impl Default for MatchedArg { fn default() -> Self { MatchedArg { occurs: 1, - vals: VecMap::new(), + vals: Vec::with_capacity(1), } } } diff --git a/src/vendor/clap/src/args/mod.rs b/src/vendor/clap/src/args/mod.rs index 5acec4cead..5c87e1be91 100644 --- a/src/vendor/clap/src/args/mod.rs +++ b/src/vendor/clap/src/args/mod.rs @@ -19,13 +19,3 @@ mod arg_builder; mod matched_arg; mod group; pub mod settings; - -#[doc(hidden)] -#[derive(Copy, Clone, Debug)] -pub enum ArgKind { - Flag, - Opt, - Pos, - Subcmd, - Group, -} diff --git a/src/vendor/clap/src/args/settings.rs b/src/vendor/clap/src/args/settings.rs index bf4bb02527..c453e4a2ea 100644 --- a/src/vendor/clap/src/args/settings.rs +++ b/src/vendor/clap/src/args/settings.rs @@ -3,20 +3,23 @@ use std::ascii::AsciiExt; use std::str::FromStr; bitflags! { - flags Flags: u16 { - const REQUIRED = 0b0000000000001, - const MULTIPLE = 0b0000000000010, - const EMPTY_VALS = 0b0000000000100, - const GLOBAL = 0b0000000001000, - const HIDDEN = 0b0000000010000, - const TAKES_VAL = 0b0000000100000, - const USE_DELIM = 0b0000001000000, - const NEXT_LINE_HELP = 0b0000010000000, - const R_UNLESS_ALL = 0b0000100000000, - const REQ_DELIM = 0b0001000000000, - const DELIM_NOT_SET = 0b0010000000000, - const HIDE_POS_VALS = 0b0100000000000, - const ALLOW_TAC_VALS = 0b1000000000000, + struct Flags: u16 { + const REQUIRED = 1; + const MULTIPLE = 1 << 1; + const EMPTY_VALS = 1 << 2; + const GLOBAL = 1 << 3; + const HIDDEN = 1 << 4; + const TAKES_VAL = 1 << 5; + const USE_DELIM = 1 << 6; + const NEXT_LINE_HELP = 1 << 7; + const R_UNLESS_ALL = 1 << 8; + const REQ_DELIM = 1 << 9; + const DELIM_NOT_SET = 1 << 10; + const HIDE_POS_VALS = 1 << 11; + const ALLOW_TAC_VALS = 1 << 12; + const REQUIRE_EQUALS = 1 << 13; + const LAST = 1 << 14; + const HIDE_DEFAULT_VAL = 1 << 15; } } @@ -40,7 +43,10 @@ impl ArgFlags { RequireDelimiter => REQ_DELIM, ValueDelimiterNotSet => DELIM_NOT_SET, HidePossibleValues => HIDE_POS_VALS, - AllowLeadingHyphen => ALLOW_TAC_VALS + AllowLeadingHyphen => ALLOW_TAC_VALS, + RequireEquals => REQUIRE_EQUALS, + Last => LAST, + HideDefaultValue => HIDE_DEFAULT_VAL } } @@ -78,6 +84,13 @@ pub enum ArgSettings { HidePossibleValues, /// Allows vals that start with a '-' AllowLeadingHyphen, + /// Require options use `--option=val` syntax + RequireEquals, + /// Specifies that the arg is the last positional argument and may be accessed early via `--` + /// syntax + Last, + /// Hides the default value from the help string + HideDefaultValue, #[doc(hidden)] RequiredUnlessAll, #[doc(hidden)] @@ -101,6 +114,9 @@ impl FromStr for ArgSettings { "valuedelimiternotset" => Ok(ArgSettings::ValueDelimiterNotSet), "hidepossiblevalues" => Ok(ArgSettings::HidePossibleValues), "allowleadinghyphen" => Ok(ArgSettings::AllowLeadingHyphen), + "requireequals" => Ok(ArgSettings::RequireEquals), + "last" => Ok(ArgSettings::Last), + "hidedefaultvalue" => Ok(ArgSettings::HideDefaultValue), _ => Err("unknown ArgSetting, cannot convert from str".to_owned()), } } @@ -138,6 +154,12 @@ mod test { ArgSettings::UseValueDelimiter); assert_eq!("valuedelimiternotset".parse::().unwrap(), ArgSettings::ValueDelimiterNotSet); + assert_eq!("requireequals".parse::().unwrap(), + ArgSettings::RequireEquals); + assert_eq!("last".parse::().unwrap(), + ArgSettings::Last); + assert_eq!("hidedefaultvalue".parse::().unwrap(), + ArgSettings::HideDefaultValue); assert!("hahahaha".parse::().is_err()); } } diff --git a/src/vendor/clap/src/completions/bash.rs b/src/vendor/clap/src/completions/bash.rs index 8da517b279..a5333828af 100644 --- a/src/vendor/clap/src/completions/bash.rs +++ b/src/vendor/clap/src/completions/bash.rs @@ -70,22 +70,24 @@ complete -F _{name} -o bashdefault -o default {name} } fn all_subcommands(&self) -> String { + debugln!("BashGen::all_subcommands;"); let mut subcmds = String::new(); let scs = completions::all_subcommand_names(self.p); for sc in &scs { subcmds = format!("{} {name}) - cmd+=\"_{name}\" + cmd+=\"__{name}\" ;;", subcmds, - name = sc.replace("-", "_")); + name = sc.replace("-", "__")); } subcmds } fn subcommand_details(&self) -> String { + debugln!("BashGen::subcommand_details;"); let mut subcmd_dets = String::new(); let mut scs = completions::get_all_subcommand_paths(self.p, true); scs.sort(); @@ -109,9 +111,9 @@ complete -F _{name} -o bashdefault -o default {name} return 0 ;;", subcmd_dets, - subcmd = sc.replace("-", "_"), + subcmd = sc.replace("-", "__"), sc_opts = self.all_options_for_path(&*sc), - level = sc.split("_").map(|_| 1).fold(0, |acc, n| acc + n), + level = sc.split("__").map(|_| 1).fold(0, |acc, n| acc + n), opts_details = self.option_details_for_path(&*sc)); } @@ -119,24 +121,11 @@ complete -F _{name} -o bashdefault -o default {name} } fn option_details_for_path(&self, path: &str) -> String { + debugln!("BashGen::option_details_for_path: path={}", path); let mut p = self.p; - for sc in path.split('_').skip(1) { - debugln!("iter;sc={}", sc); - p = &p.subcommands - .iter() - .find(|s| { - s.p.meta.name == sc || - (s.p.meta.aliases.is_some() && - s.p - .meta - .aliases - .as_ref() - .unwrap() - .iter() - .any(|&(n, _)| n == sc)) - }) - .unwrap() - .p; + for sc in path.split("__").skip(1) { + debugln!("BashGen::option_details_for_path:iter: sc={}", sc); + p = &find_subcmd!(p, sc).unwrap().p; } let mut opts = String::new(); for o in p.opts() { @@ -165,6 +154,7 @@ complete -F _{name} -o bashdefault -o default {name} } fn vals_for(&self, o: &OptBuilder) -> String { + debugln!("BashGen::vals_for: o={}", o.b.name); use args::AnyArg; let mut ret = String::new(); let mut needs_quotes = true; @@ -206,31 +196,16 @@ complete -F _{name} -o bashdefault -o default {name} ret } fn all_options_for_path(&self, path: &str) -> String { + debugln!("BashGen::all_options_for_path: path={}", path); let mut p = self.p; - for sc in path.split('_').skip(1) { - debugln!("iter;sc={}", sc); - p = &p.subcommands - .iter() - .find(|s| { - s.p.meta.name == sc || - (s.p.meta.aliases.is_some() && - s.p - .meta - .aliases - .as_ref() - .unwrap() - .iter() - .any(|&(n, _)| n == sc)) - }) - .unwrap() - .p; + for sc in path.split("__").skip(1) { + debugln!("BashGen::all_options_for_path:iter: sc={}", sc); + p = &find_subcmd!(p, sc).unwrap().p; } - let mut opts = p.short_list.iter().fold(String::new(), |acc, s| format!("{} -{}", acc, s)); + let mut opts = shorts!(p).fold(String::new(), |acc, s| format!("{} -{}", acc, s)); opts = format!("{} {}", opts, - p.long_list - .iter() - .fold(String::new(), |acc, l| format!("{} --{}", acc, l))); + longs!(p).fold(String::new(), |acc, l| format!("{} --{}", acc, l))); opts = format!("{} {}", opts, p.positionals diff --git a/src/vendor/clap/src/completions/fish.rs b/src/vendor/clap/src/completions/fish.rs index ac4072948b..2e0f36ea44 100644 --- a/src/vendor/clap/src/completions/fish.rs +++ b/src/vendor/clap/src/completions/fish.rs @@ -41,6 +41,7 @@ end } fn gen_fish_inner(root_command: &str, comp_gen: &FishGen, parent_cmds: &str, buffer: &mut String) { + debugln!("FishGen::gen_fish_inner;"); // example : // // complete @@ -94,6 +95,9 @@ fn gen_fish_inner(root_command: &str, comp_gen: &FishGen, parent_cmds: &str, buf let mut template = basic_template.clone(); template.push_str(" -f"); template.push_str(format!(" -a \"{}\"", &subcommand.p.meta.name).as_str()); + if let Some(data) = subcommand.p.meta.about { + template.push_str(format!(" -d \"{}\"", &data).as_str()) + } buffer.push_str(template.as_str()); buffer.push_str("\n"); } diff --git a/src/vendor/clap/src/completions/mod.rs b/src/vendor/clap/src/completions/mod.rs index 34a676f6d1..6d067882bf 100644 --- a/src/vendor/clap/src/completions/mod.rs +++ b/src/vendor/clap/src/completions/mod.rs @@ -43,6 +43,7 @@ impl<'a, 'b> ComplGen<'a, 'b> { // Also note, aliases are treated as their own subcommands but duplicates of whatever they're // aliasing. pub fn all_subcommand_names(p: &Parser) -> Vec { + debugln!("all_subcommand_names;"); let mut subcmds: Vec<_> = subcommands_of(p).iter().map(|&(ref n, _)| n.clone()).collect(); for sc_v in p.subcommands.iter().map(|s| all_subcommand_names(&s.p)) { subcmds.extend(sc_v); @@ -59,6 +60,7 @@ pub fn all_subcommand_names(p: &Parser) -> Vec { // Also note, aliases are treated as their own subcommands but duplicates of whatever they're // aliasing. pub fn all_subcommands(p: &Parser) -> Vec<(String, String)> { + debugln!("all_subcommands;"); let mut subcmds: Vec<_> = subcommands_of(p); for sc_v in p.subcommands.iter().map(|s| all_subcommands(&s.p)) { subcmds.extend(sc_v); @@ -73,19 +75,18 @@ pub fn all_subcommands(p: &Parser) -> Vec<(String, String)> { // Also note, aliases are treated as their own subcommands but duplicates of whatever they're // aliasing. pub fn subcommands_of(p: &Parser) -> Vec<(String, String)> { - debugln!("fn=subcommands_of;name={};bin_name={}", + debugln!("subcommands_of: name={}, bin_name={}", p.meta.name, p.meta.bin_name.as_ref().unwrap()); let mut subcmds = vec![]; - debug!("Has subcommands..."); + debugln!("subcommands_of: Has subcommands...{:?}", p.has_subcommands()); if !p.has_subcommands() { - sdebugln!("No"); let mut ret = vec![(p.meta.name.clone(), p.meta.bin_name.as_ref().unwrap().clone())]; - debugln!("Looking for aliases..."); + debugln!("subcommands_of: Looking for aliases..."); if let Some(ref aliases) = p.meta.aliases { for &(n, _) in aliases { - debugln!("Found alias...{}", n); + debugln!("subcommands_of:iter:iter: Found alias...{}", n); let mut als_bin_name: Vec<_> = p.meta.bin_name.as_ref().unwrap().split(' ').collect(); als_bin_name.push(n); @@ -96,16 +97,15 @@ pub fn subcommands_of(p: &Parser) -> Vec<(String, String)> { } return ret; } - sdebugln!("Yes"); for sc in &p.subcommands { - debugln!("iter;name={};bin_name={}", + debugln!("subcommands_of:iter: name={}, bin_name={}", sc.p.meta.name, sc.p.meta.bin_name.as_ref().unwrap()); - debugln!("Looking for aliases..."); + debugln!("subcommands_of:iter: Looking for aliases..."); if let Some(ref aliases) = sc.p.meta.aliases { for &(n, _) in aliases { - debugln!("Found alias...{}", n); + debugln!("subcommands_of:iter:iter: Found alias...{}", n); let mut als_bin_name: Vec<_> = p.meta.bin_name.as_ref().unwrap().split(' ').collect(); als_bin_name.push(n); @@ -120,11 +120,12 @@ pub fn subcommands_of(p: &Parser) -> Vec<(String, String)> { } pub fn get_all_subcommand_paths(p: &Parser, first: bool) -> Vec { + debugln!("get_all_subcommand_paths;"); let mut subcmds = vec![]; if !p.has_subcommands() { if !first { let name = &*p.meta.name; - let path = p.meta.bin_name.as_ref().unwrap().clone().replace(" ", "_"); + let path = p.meta.bin_name.as_ref().unwrap().clone().replace(" ", "__"); let mut ret = vec![path.clone()]; if let Some(ref aliases) = p.meta.aliases { for &(n, _) in aliases { @@ -137,7 +138,7 @@ pub fn get_all_subcommand_paths(p: &Parser, first: bool) -> Vec { } for sc in &p.subcommands { let name = &*sc.p.meta.name; - let path = sc.p.meta.bin_name.as_ref().unwrap().clone().replace(" ", "_"); + let path = sc.p.meta.bin_name.as_ref().unwrap().clone().replace(" ", "__"); subcmds.push(path.clone()); if let Some(ref aliases) = sc.p.meta.aliases { for &(n, _) in aliases { diff --git a/src/vendor/clap/src/completions/powershell.rs b/src/vendor/clap/src/completions/powershell.rs index 373f2fb1fc..423dd450bf 100644 --- a/src/vendor/clap/src/completions/powershell.rs +++ b/src/vendor/clap/src/completions/powershell.rs @@ -4,6 +4,7 @@ use std::io::Write; // Internal use app::parser::Parser; +use INTERNAL_ERROR_MSG; pub struct PowerShellGen<'a, 'b> where 'a: 'b @@ -17,12 +18,10 @@ impl<'a, 'b> PowerShellGen<'a, 'b> { pub fn generate_to(&self, buf: &mut W) { let bin_name = self.p.meta.bin_name.as_ref().unwrap(); - let (subcommands_detection_cases, subcommands_cases) = generate_inner(self.p, ""); + let mut names = vec![]; + let (subcommands_detection_cases, subcommands_cases) = generate_inner(self.p, "", &mut names); - let mut bin_names = vec![ - bin_name.to_string(), - format!("./{0}", bin_name), - ]; + let mut bin_names = vec![bin_name.to_string(), format!("./{0}", bin_name)]; if cfg!(windows) { bin_names.push(format!("{0}.exe", bin_name)); bin_names.push(format!(r".\{0}", bin_name)); @@ -46,6 +45,9 @@ impl<'a, 'b> PowerShellGen<'a, 'b> { %{{ switch ($_.ToString()) {{ {subcommands_detection_cases} + default {{ + break + }} }} }} @@ -72,12 +74,16 @@ impl<'a, 'b> PowerShellGen<'a, 'b> { } } -fn generate_inner<'a, 'b>(p: &Parser<'a, 'b>, previous_command_name: &str) -> (String, String) { - let command_name = format!("{}_{}", previous_command_name, &p.meta.name); - - let mut subcommands_detection_cases = if previous_command_name == "" { - String::new() +fn generate_inner<'a, 'b, 'p>(p: &'p Parser<'a, 'b>, previous_command_name: &str, names: &mut Vec<&'p str>) -> (String, String) { + debugln!("PowerShellGen::generate_inner;"); + let command_name = if previous_command_name.is_empty() { + format!("{}_{}", previous_command_name, &p.meta.bin_name.as_ref().expect(INTERNAL_ERROR_MSG)) } else { + format!("{}_{}", previous_command_name, &p.meta.name) + }; + + let mut subcommands_detection_cases = if !names.contains(&&*p.meta.name) { + names.push(&*p.meta.name); format!(r" '{0}' {{ $command += '_{0}' @@ -85,16 +91,18 @@ fn generate_inner<'a, 'b>(p: &Parser<'a, 'b>, previous_command_name: &str) -> (S }} ", &p.meta.name) + } else { + String::new() }; let mut completions = String::new(); for subcommand in &p.subcommands { completions.push_str(&format!("'{}', ", &subcommand.p.meta.name)); } - for short in &p.short_list { + for short in shorts!(p) { completions.push_str(&format!("'-{}', ", short)); } - for long in &p.long_list { + for long in longs!(p) { completions.push_str(&format!("'--{}', ", long)); } @@ -108,7 +116,7 @@ fn generate_inner<'a, 'b>(p: &Parser<'a, 'b>, previous_command_name: &str) -> (S for subcommand in &p.subcommands { let (subcommand_subcommands_detection_cases, subcommand_subcommands_cases) = - generate_inner(&subcommand.p, &command_name); + generate_inner(&subcommand.p, &command_name, names); subcommands_detection_cases.push_str(&subcommand_subcommands_detection_cases); subcommands_cases.push_str(&subcommand_subcommands_cases); } diff --git a/src/vendor/clap/src/completions/zsh.rs b/src/vendor/clap/src/completions/zsh.rs index 1aa15e55b0..fa84342f8c 100644 --- a/src/vendor/clap/src/completions/zsh.rs +++ b/src/vendor/clap/src/completions/zsh.rs @@ -18,21 +18,21 @@ pub struct ZshGen<'a, 'b> impl<'a, 'b> ZshGen<'a, 'b> { pub fn new(p: &'b Parser<'a, 'b>) -> Self { - debugln!("fn=ZshGen::new;"); + debugln!("ZshGen::new;"); ZshGen { p: p } } pub fn generate_to(&self, buf: &mut W) { - debugln!("fn=generate_to;"); + debugln!("ZshGen::generate_to;"); w!(buf, format!("\ #compdef {name} _{name}() {{ - typeset -A opt_args - local ret=1 + typeset -A opt_args + local ret=1 - local context curcontext=\"$curcontext\" state line + local context curcontext=\"$curcontext\" state line {initial_args} {subcommands} }} @@ -76,7 +76,7 @@ _{name} \"$@\"", // _describe -t commands 'rustup commands' commands "$@" // fn subcommand_details(p: &Parser) -> String { - debugln!("fn=subcommand_details"); + debugln!("ZshGen::subcommand_details;"); // First we do ourself let mut ret = vec![format!("\ (( $+functions[_{bin_name_underscore}_commands] )) || @@ -86,7 +86,7 @@ _{bin_name_underscore}_commands() {{ ) _describe -t commands '{bin_name} commands' commands \"$@\" }}", - bin_name_underscore = p.meta.bin_name.as_ref().unwrap().replace(" ", "_"), + bin_name_underscore = p.meta.bin_name.as_ref().unwrap().replace(" ", "__"), bin_name = p.meta.bin_name.as_ref().unwrap(), subcommands_and_args = subcommands_and_args_of(p))]; @@ -95,7 +95,7 @@ _{bin_name_underscore}_commands() {{ all_subcommands.sort(); all_subcommands.dedup(); for &(_, ref bin_name) in &all_subcommands { - debugln!("iter;bin_name={}", bin_name); + debugln!("ZshGen::subcommand_details:iter: bin_name={}", bin_name); ret.push(format!("\ (( $+functions[_{bin_name_underscore}_commands] )) || _{bin_name_underscore}_commands() {{ @@ -104,7 +104,7 @@ _{bin_name_underscore}_commands() {{ ) _describe -t commands '{bin_name} commands' commands \"$@\" }}", - bin_name_underscore = bin_name.replace(" ", "_"), + bin_name_underscore = bin_name.replace(" ", "__"), bin_name = bin_name, subcommands_and_args = subcommands_and_args_of(parser_of(p, bin_name)))); } @@ -124,9 +124,10 @@ _{bin_name_underscore}_commands() {{ // 'show:Show the active and installed toolchains' // 'update:Update Rust toolchains' fn subcommands_and_args_of(p: &Parser) -> String { - debugln!("fn=subcommands_and_args_of;"); + debugln!("ZshGen::subcommands_and_args_of;"); let mut ret = vec![]; fn add_sc(sc: &App, n: &str, ret: &mut Vec) { + debugln!("ZshGen::add_sc;"); let s = format!("\"{name}:{help}\" \\", name = n, help = sc.p.meta.about.unwrap_or("").replace("[", "\\[").replace("]", "\\]")); @@ -137,7 +138,7 @@ fn subcommands_and_args_of(p: &Parser) -> String { // First the subcommands for sc in p.subcommands() { - debugln!("iter;subcommand={}", sc.p.meta.name); + debugln!("ZshGen::subcommands_and_args_of:iter: subcommand={}", sc.p.meta.name); add_sc(sc, &sc.p.meta.name, &mut ret); if let Some(ref v) = sc.p.meta.aliases { for alias in v.iter().filter(|&&(_, vis)| vis).map(|&(n, _)| n) { @@ -148,7 +149,7 @@ fn subcommands_and_args_of(p: &Parser) -> String { // Then the positional args for arg in p.positionals() { - debugln!("iter;arg={}", arg.b.name); + debugln!("ZshGen::subcommands_and_args_of:iter: arg={}", arg.b.name); let a = format!("\"{name}:{help}\" \\", name = arg.b.name.to_ascii_uppercase(), help = arg.b.help.unwrap_or("").replace("[", "\\[").replace("]", "\\]")); @@ -191,14 +192,11 @@ fn subcommands_and_args_of(p: &Parser) -> String { // [repeat] = From the same recursive calls, but for all subcommands // [subcommand_args] = The same as zsh::get_args_of fn get_subcommands_of(p: &Parser) -> String { - debugln!("fn=get_subcommands_of"); + debugln!("get_subcommands_of;"); - debug!("Has subcommands..."); + debugln!("get_subcommands_of: Has subcommands...{:?}", p.has_subcommands()); if !p.has_subcommands() { - sdebugln!("No"); return String::new(); - } else { - sdebugln!("Yes"); } let sc_names = completions::subcommands_of(p); @@ -233,7 +231,7 @@ esac", } fn parser_of<'a, 'b>(p: &'b Parser<'a, 'b>, sc: &str) -> &'b Parser<'a, 'b> { - debugln!("fn=parser_of;sc={}", sc); + debugln!("parser_of: sc={}", sc); if sc == p.meta.bin_name.as_ref().unwrap_or(&String::new()) { return p; } @@ -261,13 +259,13 @@ fn parser_of<'a, 'b>(p: &'b Parser<'a, 'b>, sc: &str) -> &'b Parser<'a, 'b> { // -s: Allow stacking of short args (i.e. -a -b -c => -abc) // -S: Do not complete anything after '--' and treat those as argument values fn get_args_of(p: &Parser) -> String { - debugln!("fn=get_args_of"); + debugln!("get_args_of;"); let mut ret = vec![String::from("_arguments -s -S -C \\")]; let opts = write_opts_of(p); let flags = write_flags_of(p); let sc_or_a = if p.has_subcommands() || p.has_positionals() { format!("\"1:: :_{name}_commands\" \\", - name = p.meta.bin_name.as_ref().unwrap().replace(" ", "_")) + name = p.meta.bin_name.as_ref().unwrap().replace(" ", "__")) } else { String::new() }; @@ -295,10 +293,10 @@ fn get_args_of(p: &Parser) -> String { } fn write_opts_of(p: &Parser) -> String { - debugln!("fn=write_opts_of;"); + debugln!("write_opts_of;"); let mut ret = vec![]; for o in p.opts() { - debugln!("iter;o={}", o.name()); + debugln!("write_opts_of:iter: o={}", o.name()); let help = o.help().unwrap_or("").replace("[", "\\[").replace("]", "\\]"); let mut conflicts = get_zsh_arg_conflicts!(p, o, INTERNAL_ERROR_MSG); conflicts = if conflicts.is_empty() { @@ -325,7 +323,7 @@ fn write_opts_of(p: &Parser) -> String { possible_values = pv, help = help); - debugln!("Wrote...{}", &*s); + debugln!("write_opts_of:iter: Wrote...{}", &*s); ret.push(s); } if let Some(long) = o.long() { @@ -336,7 +334,7 @@ fn write_opts_of(p: &Parser) -> String { possible_values = pv, help = help); - debugln!("Wrote...{}", &*l); + debugln!("write_opts_of:iter: Wrote...{}", &*l); ret.push(l); } } @@ -345,10 +343,10 @@ fn write_opts_of(p: &Parser) -> String { } fn write_flags_of(p: &Parser) -> String { - debugln!("fn=write_flags_of;"); + debugln!("write_flags_of;"); let mut ret = vec![]; for f in p.flags() { - debugln!("iter;f={}", f.name()); + debugln!("write_flags_of:iter: f={}", f.name()); let help = f.help().unwrap_or("").replace("[", "\\[").replace("]", "\\]"); let mut conflicts = get_zsh_arg_conflicts!(p, f, INTERNAL_ERROR_MSG); conflicts = if conflicts.is_empty() { @@ -369,7 +367,7 @@ fn write_flags_of(p: &Parser) -> String { arg = short, help = help); - debugln!("Wrote...{}", &*s); + debugln!("write_flags_of:iter: Wrote...{}", &*s); ret.push(s); } @@ -380,7 +378,7 @@ fn write_flags_of(p: &Parser) -> String { arg = long, help = help); - debugln!("Wrote...{}", &*l); + debugln!("write_flags_of:iter: Wrote...{}", &*l); ret.push(l); } } diff --git a/src/vendor/clap/src/errors.rs b/src/vendor/clap/src/errors.rs index 359b18ea89..bd1e7d55f8 100644 --- a/src/vendor/clap/src/errors.rs +++ b/src/vendor/clap/src/errors.rs @@ -9,7 +9,7 @@ use std::result::Result as StdResult; // Internal use args::{FlagBuilder, AnyArg}; -use fmt; +use fmt::{Colorizer, ColorizerOption, ColorWhen}; use suggestions; /// Short hand for [`Result`] type @@ -26,11 +26,11 @@ pub enum ErrorKind { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let result = App::new("myprog") + /// let result = App::new("prog") /// .arg(Arg::with_name("speed") /// .possible_value("fast") /// .possible_value("slow")) - /// .get_matches_from_safe(vec!["myprog", "other"]); + /// .get_matches_from_safe(vec!["prog", "other"]); /// assert!(result.is_err()); /// assert_eq!(result.unwrap_err().kind, ErrorKind::InvalidValue); /// ``` @@ -43,9 +43,9 @@ pub enum ErrorKind { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let result = App::new("myprog") + /// let result = App::new("prog") /// .arg(Arg::from_usage("--flag 'some flag'")) - /// .get_matches_from_safe(vec!["myprog", "--other"]); + /// .get_matches_from_safe(vec!["prog", "--other"]); /// assert!(result.is_err()); /// assert_eq!(result.unwrap_err().kind, ErrorKind::UnknownArgument); /// ``` @@ -61,13 +61,13 @@ pub enum ErrorKind { #[cfg_attr(not(feature="suggestions"), doc=" ```no_run")] #[cfg_attr( feature="suggestions" , doc=" ```")] /// # use clap::{App, Arg, ErrorKind, SubCommand}; - /// let result = App::new("myprog") + /// let result = App::new("prog") /// .subcommand(SubCommand::with_name("config") /// .about("Used for configuration") /// .arg(Arg::with_name("config_file") /// .help("The configuration file to use") /// .index(1))) - /// .get_matches_from_safe(vec!["myprog", "confi"]); + /// .get_matches_from_safe(vec!["prog", "confi"]); /// assert!(result.is_err()); /// assert_eq!(result.unwrap_err().kind, ErrorKind::InvalidSubcommand); /// ``` @@ -87,13 +87,13 @@ pub enum ErrorKind { /// /// ```rust /// # use clap::{App, Arg, ErrorKind, SubCommand}; - /// let result = App::new("myprog") + /// let result = App::new("prog") /// .subcommand(SubCommand::with_name("config") /// .about("Used for configuration") /// .arg(Arg::with_name("config_file") /// .help("The configuration file to use") /// .index(1))) - /// .get_matches_from_safe(vec!["myprog", "help", "nothing"]); + /// .get_matches_from_safe(vec!["prog", "help", "nothing"]); /// assert!(result.is_err()); /// assert_eq!(result.unwrap_err().kind, ErrorKind::UnrecognizedSubcommand); /// ``` @@ -109,11 +109,11 @@ pub enum ErrorKind { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let res = App::new("myprog") + /// let res = App::new("prog") /// .arg(Arg::with_name("color") /// .long("color") /// .empty_values(false)) - /// .get_matches_from_safe(vec!["myprog", "--color="]); + /// .get_matches_from_safe(vec!["prog", "--color="]); /// assert!(res.is_err()); /// assert_eq!(res.unwrap_err().kind, ErrorKind::EmptyValue); /// ``` @@ -133,10 +133,10 @@ pub enum ErrorKind { /// } /// } /// - /// let result = App::new("myprog") + /// let result = App::new("prog") /// .arg(Arg::with_name("num") /// .validator(is_numeric)) - /// .get_matches_from_safe(vec!["myprog", "NotANumber"]); + /// .get_matches_from_safe(vec!["prog", "NotANumber"]); /// assert!(result.is_err()); /// assert_eq!(result.unwrap_err().kind, ErrorKind::ValueValidation); /// ``` @@ -149,11 +149,11 @@ pub enum ErrorKind { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let result = App::new("myprog") + /// let result = App::new("prog") /// .arg(Arg::with_name("arg") /// .multiple(true) /// .max_values(2)) - /// .get_matches_from_safe(vec!["myprog", "too", "many", "values"]); + /// .get_matches_from_safe(vec!["prog", "too", "many", "values"]); /// assert!(result.is_err()); /// assert_eq!(result.unwrap_err().kind, ErrorKind::TooManyValues); /// ``` @@ -167,11 +167,11 @@ pub enum ErrorKind { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let result = App::new("myprog") + /// let result = App::new("prog") /// .arg(Arg::with_name("some_opt") /// .long("opt") /// .min_values(3)) - /// .get_matches_from_safe(vec!["myprog", "--opt", "too", "few"]); + /// .get_matches_from_safe(vec!["prog", "--opt", "too", "few"]); /// assert!(result.is_err()); /// assert_eq!(result.unwrap_err().kind, ErrorKind::TooFewValues); /// ``` @@ -186,12 +186,12 @@ pub enum ErrorKind { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let result = App::new("myprog") + /// let result = App::new("prog") /// .arg(Arg::with_name("some_opt") /// .long("opt") /// .takes_value(true) /// .number_of_values(2)) - /// .get_matches_from_safe(vec!["myprog", "--opt", "wrong"]); + /// .get_matches_from_safe(vec!["prog", "--opt", "wrong"]); /// assert!(result.is_err()); /// assert_eq!(result.unwrap_err().kind, ErrorKind::WrongNumberOfValues); /// ``` @@ -207,13 +207,13 @@ pub enum ErrorKind { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let result = App::new("myprog") + /// let result = App::new("prog") /// .arg(Arg::with_name("debug") /// .long("debug") /// .conflicts_with("color")) /// .arg(Arg::with_name("color") /// .long("color")) - /// .get_matches_from_safe(vec!["myprog", "--debug", "--color"]); + /// .get_matches_from_safe(vec!["prog", "--debug", "--color"]); /// assert!(result.is_err()); /// assert_eq!(result.unwrap_err().kind, ErrorKind::ArgumentConflict); /// ``` @@ -225,10 +225,10 @@ pub enum ErrorKind { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let result = App::new("myprog") + /// let result = App::new("prog") /// .arg(Arg::with_name("debug") /// .required(true)) - /// .get_matches_from_safe(vec!["myprog"]); + /// .get_matches_from_safe(vec!["prog"]); /// assert!(result.is_err()); /// assert_eq!(result.unwrap_err().kind, ErrorKind::MissingRequiredArgument); /// ``` @@ -241,7 +241,7 @@ pub enum ErrorKind { /// /// ```rust /// # use clap::{App, AppSettings, SubCommand, ErrorKind}; - /// let err = App::new("myprog") + /// let err = App::new("prog") /// .setting(AppSettings::SubcommandRequired) /// .subcommand(SubCommand::with_name("test")) /// .get_matches_from_safe(vec![ @@ -261,13 +261,13 @@ pub enum ErrorKind { /// /// ```rust /// # use clap::{App, Arg, AppSettings, ErrorKind, SubCommand}; - /// let result = App::new("myprog") + /// let result = App::new("prog") /// .setting(AppSettings::ArgRequiredElseHelp) /// .subcommand(SubCommand::with_name("config") /// .about("Used for configuration") /// .arg(Arg::with_name("config_file") /// .help("The configuration file to use"))) - /// .get_matches_from_safe(vec!["myprog"]); + /// .get_matches_from_safe(vec!["prog"]); /// assert!(result.is_err()); /// assert_eq!(result.unwrap_err().kind, ErrorKind::MissingArgumentOrSubcommand); /// ``` @@ -281,11 +281,11 @@ pub enum ErrorKind { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let result = App::new("myprog") + /// let result = App::new("prog") /// .arg(Arg::with_name("debug") /// .long("debug") /// .multiple(false)) - /// .get_matches_from_safe(vec!["myprog", "--debug", "--debug"]); + /// .get_matches_from_safe(vec!["prog", "--debug", "--debug"]); /// assert!(result.is_err()); /// assert_eq!(result.unwrap_err().kind, ErrorKind::UnexpectedMultipleUsage); /// ``` @@ -305,7 +305,7 @@ pub enum ErrorKind { /// # use clap::{App, Arg, ErrorKind, AppSettings}; /// # use std::os::unix::ffi::OsStringExt; /// # use std::ffi::OsString; - /// let result = App::new("myprog") + /// let result = App::new("prog") /// .setting(AppSettings::StrictUtf8) /// .arg(Arg::with_name("utf8") /// .short("u") @@ -329,8 +329,8 @@ pub enum ErrorKind { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let result = App::new("myprog") - /// .get_matches_from_safe(vec!["myprog", "--help"]); + /// let result = App::new("prog") + /// .get_matches_from_safe(vec!["prog", "--help"]); /// assert!(result.is_err()); /// assert_eq!(result.unwrap_err().kind, ErrorKind::HelpDisplayed); /// ``` @@ -343,8 +343,8 @@ pub enum ErrorKind { /// /// ```rust /// # use clap::{App, Arg, ErrorKind}; - /// let result = App::new("myprog") - /// .get_matches_from_safe(vec!["myprog", "--version"]); + /// let result = App::new("prog") + /// .get_matches_from_safe(vec!["prog", "--version"]); /// assert!(result.is_err()); /// assert_eq!(result.unwrap_err().kind, ErrorKind::VersionDisplayed); /// ``` @@ -408,17 +408,17 @@ impl Error { pub fn argument_conflict<'a, 'b, A, O, U>(arg: &A, other: Option, usage: U, - color: fmt::ColorWhen) + color: ColorWhen) -> Self where A: AnyArg<'a, 'b> + Display, O: Into, U: Display { let mut v = vec![arg.name().to_owned()]; - let c = fmt::Colorizer { + let c = Colorizer::new(ColorizerOption { use_stderr: true, when: color, - }; + }); Error { message: format!("{} The argument '{}' cannot be used with {}\n\n\ {}\n\n\ @@ -444,14 +444,14 @@ impl Error { } #[doc(hidden)] - pub fn empty_value<'a, 'b, A, U>(arg: &A, usage: U, color: fmt::ColorWhen) -> Self + pub fn empty_value<'a, 'b, A, U>(arg: &A, usage: U, color: ColorWhen) -> Self where A: AnyArg<'a, 'b> + Display, U: Display { - let c = fmt::Colorizer { + let c = Colorizer::new(ColorizerOption { use_stderr: true, when: color, - }; + }); Error { message: format!("{} The argument '{}' requires a value but none was supplied\ \n\n\ @@ -471,21 +471,21 @@ impl Error { good_vals: &[G], arg: &A, usage: U, - color: fmt::ColorWhen) + color: ColorWhen) -> Self where B: AsRef, G: AsRef + Display, A: AnyArg<'a, 'b> + Display, U: Display { - let c = fmt::Colorizer { + let c = Colorizer::new(ColorizerOption { use_stderr: true, when: color, - }; + }); let suffix = - suggestions::did_you_mean_suffix(bad_val.as_ref(), - good_vals.iter(), - suggestions::DidYouMeanMessageStyle::EnumValue); + suggestions::did_you_mean_value_suffix( + bad_val.as_ref(), + good_vals.iter()); let mut sorted = vec![]; for v in good_vals { @@ -517,7 +517,7 @@ impl Error { did_you_mean: D, name: N, usage: U, - color: fmt::ColorWhen) + color: ColorWhen) -> Self where S: Into, D: AsRef + Display, @@ -525,10 +525,10 @@ impl Error { U: Display { let s = subcmd.into(); - let c = fmt::Colorizer { + let c = Colorizer::new(ColorizerOption { use_stderr: true, when: color, - }; + }); Error { message: format!("{} The subcommand '{}' wasn't recognized\n\t\ Did you mean '{}'?\n\n\ @@ -550,15 +550,15 @@ impl Error { } #[doc(hidden)] - pub fn unrecognized_subcommand(subcmd: S, name: N, color: fmt::ColorWhen) -> Self + pub fn unrecognized_subcommand(subcmd: S, name: N, color: ColorWhen) -> Self where S: Into, N: Display { let s = subcmd.into(); - let c = fmt::Colorizer { + let c = Colorizer::new(ColorizerOption { use_stderr: true, when: color, - }; + }); Error { message: format!("{} The subcommand '{}' wasn't recognized\n\n\ {}\n\t\ @@ -575,14 +575,14 @@ impl Error { } #[doc(hidden)] - pub fn missing_required_argument(required: R, usage: U, color: fmt::ColorWhen) -> Self + pub fn missing_required_argument(required: R, usage: U, color: ColorWhen) -> Self where R: Display, U: Display { - let c = fmt::Colorizer { + let c = Colorizer::new(ColorizerOption { use_stderr: true, when: color, - }; + }); Error { message: format!("{} The following required arguments were not provided:{}\n\n\ {}\n\n\ @@ -597,14 +597,14 @@ impl Error { } #[doc(hidden)] - pub fn missing_subcommand(name: N, usage: U, color: fmt::ColorWhen) -> Self + pub fn missing_subcommand(name: N, usage: U, color: ColorWhen) -> Self where N: AsRef + Display, U: Display { - let c = fmt::Colorizer { + let c = Colorizer::new(ColorizerOption { use_stderr: true, when: color, - }; + }); Error { message: format!("{} '{}' requires a subcommand, but one was not provided\n\n\ {}\n\n\ @@ -620,13 +620,13 @@ impl Error { #[doc(hidden)] - pub fn invalid_utf8(usage: U, color: fmt::ColorWhen) -> Self + pub fn invalid_utf8(usage: U, color: ColorWhen) -> Self where U: Display { - let c = fmt::Colorizer { + let c = Colorizer::new(ColorizerOption { use_stderr: true, when: color, - }; + }); Error { message: format!("{} Invalid UTF-8 was detected in one or more arguments\n\n\ {}\n\n\ @@ -643,17 +643,17 @@ impl Error { pub fn too_many_values<'a, 'b, V, A, U>(val: V, arg: &A, usage: U, - color: fmt::ColorWhen) + color: ColorWhen) -> Self where V: AsRef + Display + ToOwned, A: AnyArg<'a, 'b> + Display, U: Display { let v = val.as_ref(); - let c = fmt::Colorizer { + let c = Colorizer::new(ColorizerOption { use_stderr: true, when: color, - }; + }); Error { message: format!("{} The value '{}' was provided to '{}', but it wasn't expecting \ any more values\n\n\ @@ -674,15 +674,15 @@ impl Error { min_vals: u64, curr_vals: usize, usage: U, - color: fmt::ColorWhen) + color: ColorWhen) -> Self where A: AnyArg<'a, 'b> + Display, U: Display { - let c = fmt::Colorizer { + let c = Colorizer::new(ColorizerOption { use_stderr: true, when: color, - }; + }); Error { message: format!("{} The argument '{}' requires at least {} values, but only {} w{} \ provided\n\n\ @@ -701,13 +701,13 @@ impl Error { } #[doc(hidden)] - pub fn value_validation<'a, 'b, A>(arg: Option<&A>, err: String, color: fmt::ColorWhen) -> Self + pub fn value_validation<'a, 'b, A>(arg: Option<&A>, err: String, color: ColorWhen) -> Self where A: AnyArg<'a, 'b> + Display { - let c = fmt::Colorizer { + let c = Colorizer::new(ColorizerOption { use_stderr: true, when: color, - }; + }); Error { message: format!("{} Invalid value{}: {}", c.error("error:"), @@ -725,7 +725,7 @@ impl Error { #[doc(hidden)] pub fn value_validation_auto(err: String) -> Self { let n: Option<&FlagBuilder> = None; - Error::value_validation(n, err, fmt::ColorWhen::Auto) + Error::value_validation(n, err, ColorWhen::Auto) } #[doc(hidden)] @@ -734,16 +734,16 @@ impl Error { curr_vals: usize, suffix: S, usage: U, - color: fmt::ColorWhen) + color: ColorWhen) -> Self where A: AnyArg<'a, 'b> + Display, S: Display, U: Display { - let c = fmt::Colorizer { + let c = Colorizer::new(ColorizerOption { use_stderr: true, when: color, - }; + }); Error { message: format!("{} The argument '{}' requires {} values, but {} w{} \ provided\n\n\ @@ -762,14 +762,14 @@ impl Error { } #[doc(hidden)] - pub fn unexpected_multiple_usage<'a, 'b, A, U>(arg: &A, usage: U, color: fmt::ColorWhen) -> Self + pub fn unexpected_multiple_usage<'a, 'b, A, U>(arg: &A, usage: U, color: ColorWhen) -> Self where A: AnyArg<'a, 'b> + Display, U: Display { - let c = fmt::Colorizer { + let c = Colorizer::new(ColorizerOption { use_stderr: true, when: color, - }; + }); Error { message: format!("{} The argument '{}' was provided more than once, but cannot \ be used multiple times\n\n\ @@ -788,16 +788,16 @@ impl Error { pub fn unknown_argument(arg: A, did_you_mean: &str, usage: U, - color: fmt::ColorWhen) + color: ColorWhen) -> Self where A: Into, U: Display { let a = arg.into(); - let c = fmt::Colorizer { + let c = Colorizer::new(ColorizerOption { use_stderr: true, when: color, - }; + }); Error { message: format!("{} Found argument '{}' which wasn't expected, or isn't valid in \ this context{}\n\ @@ -818,11 +818,11 @@ impl Error { } #[doc(hidden)] - pub fn io_error(e: &Error, color: fmt::ColorWhen) -> Self { - let c = fmt::Colorizer { + pub fn io_error(e: &Error, color: ColorWhen) -> Self { + let c = Colorizer::new(ColorizerOption { use_stderr: true, when: color, - }; + }); Error { message: format!("{} {}", c.error("error:"), e.description()), kind: ErrorKind::Io, @@ -835,10 +835,10 @@ impl Error { where A: Into { let a = arg.into(); - let c = fmt::Colorizer { + let c = Colorizer::new(ColorizerOption { use_stderr: true, - when: fmt::ColorWhen::Auto, - }; + when: ColorWhen::Auto, + }); Error { message: format!("{} The argument '{}' wasn't found", c.error("error:"), @@ -853,10 +853,10 @@ impl Error { /// This can be used in combination with `Error::exit` to exit your program /// with a custom error message. pub fn with_description(description: &str, kind: ErrorKind) -> Self { - let c = fmt::Colorizer { + let c = Colorizer::new(ColorizerOption { use_stderr: true, - when: fmt::ColorWhen::Auto, - }; + when: ColorWhen::Auto, + }); Error { message: format!("{} {}", c.error("error:"), description), kind: kind, diff --git a/src/vendor/clap/src/fmt.rs b/src/vendor/clap/src/fmt.rs index 5700943e6a..9fccd3f530 100644 --- a/src/vendor/clap/src/fmt.rs +++ b/src/vendor/clap/src/fmt.rs @@ -5,18 +5,9 @@ use ansi_term::ANSIString; use ansi_term::Colour::{Green, Red, Yellow}; #[cfg(feature = "color")] -use libc; +use atty; use std::fmt; - -#[cfg(all(feature = "color", not(target_os = "windows")))] -const STDERR: i32 = libc::STDERR_FILENO; -#[cfg(all(feature = "color", not(target_os = "windows")))] -const STDOUT: i32 = libc::STDOUT_FILENO; - -#[cfg(target_os = "windows")] -const STDERR: i32 = 0; -#[cfg(target_os = "windows")] -const STDOUT: i32 = 0; +use std::env; #[doc(hidden)] #[derive(Debug, Copy, Clone, PartialEq)] @@ -28,32 +19,38 @@ pub enum ColorWhen { #[cfg(feature = "color")] pub fn is_a_tty(stderr: bool) -> bool { - debugln!("fn=is_a_tty;"); - debugln!("Use stderr...{:?}", stderr); - let fd = if stderr { STDERR } else { STDOUT }; - unsafe { libc::isatty(fd) != 0 } + debugln!("is_a_tty: stderr={:?}", stderr); + let stream = if stderr { + atty::Stream::Stderr + } else { + atty::Stream::Stdout + }; + atty::is(stream) } #[cfg(not(feature = "color"))] pub fn is_a_tty(_: bool) -> bool { - debugln!("fn=is_a_tty;"); + debugln!("is_a_tty;"); false } +pub fn is_term_dumb() -> bool { env::var("TERM").ok() == Some(String::from("dumb")) } + #[doc(hidden)] -pub struct Colorizer { +pub struct ColorizerOption { pub use_stderr: bool, pub when: ColorWhen, } +#[doc(hidden)] +pub struct Colorizer { + when: ColorWhen, +} + macro_rules! color { ($_self:ident, $c:ident, $m:expr) => { match $_self.when { - ColorWhen::Auto => if is_a_tty($_self.use_stderr) { - Format::$c($m) - } else { - Format::None($m) - }, + ColorWhen::Auto => Format::$c($m), ColorWhen::Always => Format::$c($m), ColorWhen::Never => Format::None($m), } @@ -61,41 +58,53 @@ macro_rules! color { } impl Colorizer { + pub fn new(option: ColorizerOption) -> Colorizer { + let is_a_tty = is_a_tty(option.use_stderr); + let is_term_dumb = is_term_dumb(); + Colorizer { + when: if is_a_tty && !is_term_dumb { + option.when + } else { + ColorWhen::Never + }, + } + } + pub fn good(&self, msg: T) -> Format where T: fmt::Display + AsRef { - debugln!("fn=good;"); + debugln!("Colorizer::good;"); color!(self, Good, msg) } pub fn warning(&self, msg: T) -> Format where T: fmt::Display + AsRef { - debugln!("fn=warning;"); + debugln!("Colorizer::warning;"); color!(self, Warning, msg) } pub fn error(&self, msg: T) -> Format where T: fmt::Display + AsRef { - debugln!("fn=error;"); + debugln!("Colorizer::error;"); color!(self, Error, msg) } pub fn none(&self, msg: T) -> Format where T: fmt::Display + AsRef { - debugln!("fn=none;"); + debugln!("Colorizer::none;"); Format::None(msg) } } impl Default for Colorizer { fn default() -> Self { - Colorizer { + Colorizer::new(ColorizerOption { use_stderr: true, when: ColorWhen::Auto, - } + }) } } diff --git a/src/vendor/clap/src/lib.rs b/src/vendor/clap/src/lib.rs index d30e2a76a4..73e74f1127 100644 --- a/src/vendor/clap/src/lib.rs +++ b/src/vendor/clap/src/lib.rs @@ -274,6 +274,7 @@ //! ### BYOB (Build Your Own Binary) //! //! To test out `clap`'s default auto-generated help/version follow these steps: +//! //! * Create a new cargo project `$ cargo new fake --bin && cd fake` //! * Add `clap` to your `Cargo.toml` //! @@ -326,9 +327,9 @@ //! //! #### Features enabled by default //! -//! * **"suggestions"**: Turns on the `Did you mean '--myoption'?` feature for when users make typos. (builds dependency `strsim`) -//! * **"color"**: Turns on colored error messages. This feature only works on non-Windows OSs. (builds dependency `ansi-term` and `libc`) -//! * **"wrap_help"**: Wraps the help at the actual terminal width when available, instead of 120 chracters. (builds dependency `term_size`, and `libc`) +//! * `suggestions`: Turns on the `Did you mean '--myoption'?` feature for when users make typos. (builds dependency `strsim`) +//! * `color`: Turns on colored error messages. This feature only works on non-Windows OSs. (builds dependency `ansi-term` and `atty`) +//! * `wrap_help`: Wraps the help at the actual terminal width when available, instead of 120 chracters. (builds dependency `term_size`) //! //! To disable these, add this to your `Cargo.toml`: //! @@ -477,7 +478,7 @@ //! //! ### Compatibility Policy //! -//! Because `clap` takes SemVer and compatibility seriously, this is the official policy regarding +//! Because `clap` takes `SemVer` and compatibility seriously, this is the official policy regarding //! breaking changes and previous versions of Rust. //! //! `clap` will pin the minimum required version of Rust to the CI builds. Bumping the minimum @@ -498,8 +499,8 @@ //! //! `clap` will officially support current stable Rust, minus two releases, but may work with prior //! releases as well. For example, current stable Rust at the time of this writing is 1.13.0, -//! meaning `clap` is garunteed to compile with 1.11.0 and beyond. At the 1.14.0 release, `clap` -//! will be garunteed to compile with 2.12.0 and beyond, etc. +//! meaning `clap` is guaranteed to compile with 1.11.0 and beyond. At the 1.14.0 release, `clap` +//! will be guaranteed to compile with 1.12.0 and beyond, etc. //! //! Upon bumping the minimum version of Rust (assuming it's within the stable-2 range), it *must* be //! clearly annotated in the `CHANGELOG.md` @@ -526,6 +527,7 @@ #![cfg_attr(feature = "lints", deny(warnings))] #![cfg_attr(feature = "lints", allow(cyclomatic_complexity))] #![cfg_attr(feature = "lints", allow(doc_markdown))] +#![cfg_attr(feature = "lints", allow(explicit_iter_loop))] #[cfg(feature = "suggestions")] extern crate strsim; @@ -533,15 +535,16 @@ extern crate strsim; extern crate ansi_term; #[cfg(feature = "yaml")] extern crate yaml_rust; -#[cfg(any(feature = "wrap_help", feature = "color"))] -extern crate libc; extern crate unicode_width; #[macro_use] extern crate bitflags; extern crate vec_map; #[cfg(feature = "wrap_help")] extern crate term_size; +extern crate textwrap; extern crate unicode_segmentation; +#[cfg(feature = "color")] +extern crate atty; #[cfg(feature = "yaml")] pub use yaml_rust::YamlLoader; diff --git a/src/vendor/clap/src/macros.rs b/src/vendor/clap/src/macros.rs index 9478857cb0..ab89b88112 100644 --- a/src/vendor/clap/src/macros.rs +++ b/src/vendor/clap/src/macros.rs @@ -371,7 +371,7 @@ macro_rules! arg_enum { } /// Allows you to pull the version from your Cargo.toml at compile time as -/// MAJOR.MINOR.PATCH_PKGVERSION_PRE +/// `MAJOR.MINOR.PATCH_PKGVERSION_PRE` /// /// # Examples /// @@ -380,11 +380,12 @@ macro_rules! arg_enum { /// # extern crate clap; /// # use clap::App; /// # fn main() { -/// let m = App::new("app") -/// .version(crate_version!()) -/// .get_matches(); +/// let m = App::new("app") +/// .version(crate_version!()) +/// .get_matches(); /// # } /// ``` +#[cfg(not(feature="no_cargo"))] #[macro_export] macro_rules! crate_version { () => { @@ -393,9 +394,13 @@ macro_rules! crate_version { } /// Allows you to pull the authors for the app from your Cargo.toml at -/// compile time as -/// "author1 lastname. ", -/// "author2 lastname. " +/// compile time in the form: +/// `"author1 lastname :author2 lastname "` +/// +/// You can replace the colons with a custom separator by supplying a +/// replacement string, so, for example, +/// `crate_authors!(",\n")` would become +/// `"author1 lastname ,\nauthor2 lastname ,\nauthor3 lastname "` /// /// # Examples /// @@ -404,23 +409,206 @@ macro_rules! crate_version { /// # extern crate clap; /// # use clap::App; /// # fn main() { -/// let m = App::new("app") -/// .author(crate_authors!()) -/// .get_matches(); +/// let m = App::new("app") +/// .author(crate_authors!("\n")) +/// .get_matches(); /// # } /// ``` +#[cfg(not(feature="no_cargo"))] #[macro_export] macro_rules! crate_authors { + ($sep:expr) => {{ + use std::ops::Deref; + use std::sync::{ONCE_INIT, Once}; + + #[allow(missing_copy_implementations)] + #[allow(non_camel_case_types)] + #[allow(dead_code)] + struct CARGO_AUTHORS {__private_field: ()} + static CARGO_AUTHORS: CARGO_AUTHORS = CARGO_AUTHORS {__private_field: ()}; + + impl Deref for CARGO_AUTHORS { + type Target = String; + + #[allow(unsafe_code)] + fn deref<'a>(&'a self) -> &'a String { + unsafe { + static mut LAZY: (*const String, Once) = (0 as *const String, ONCE_INIT); + + LAZY.1.call_once(|| LAZY.0 = Box::into_raw(Box::new(env!("CARGO_PKG_AUTHORS").replace(':', $sep)))); + &*LAZY.0 + } + } + } + + &CARGO_AUTHORS[..] + }}; () => { env!("CARGO_PKG_AUTHORS") }; } +/// Allows you to pull the description from your Cargo.toml at compile time. +/// +/// # Examples +/// +/// ```no_run +/// # #[macro_use] +/// # extern crate clap; +/// # use clap::App; +/// # fn main() { +/// let m = App::new("app") +/// .about(crate_description!()) +/// .get_matches(); +/// # } +/// ``` +#[cfg(not(feature="no_cargo"))] +#[macro_export] +macro_rules! crate_description { + () => { + env!("CARGO_PKG_DESCRIPTION") + }; +} + +/// Allows you to pull the name from your Cargo.toml at compile time. +/// +/// # Examples +/// +/// ```no_run +/// # #[macro_use] +/// # extern crate clap; +/// # use clap::App; +/// # fn main() { +/// let m = App::new(crate_name!()) +/// .get_matches(); +/// # } +/// ``` +#[cfg(not(feature="no_cargo"))] +#[macro_export] +macro_rules! crate_name { + () => { + env!("CARGO_PKG_NAME") + }; +} + +/// Allows you to build the `App` instance from your Cargo.toml at compile time. +/// +/// Equivalent to using the `crate_*!` macros with their respective fields. +/// +/// Provided separator is for the [`crate_authors!`](macro.crate_authors.html) macro, +/// refer to the documentation therefor. +/// +/// **NOTE:** Changing the values in your `Cargo.toml` does not trigger a re-build automatically, +/// and therefore won't change the generated output until you recompile. +/// +/// **Pro Tip:** In some cases you can "trick" the compiler into triggering a rebuild when your +/// `Cargo.toml` is changed by including this in your `src/main.rs` file +/// `include_str!("../Cargo.toml");` +/// +/// # Examples +/// +/// ```no_run +/// # #[macro_use] +/// # extern crate clap; +/// # fn main() { +/// let m = app_from_crate!().get_matches(); +/// # } +/// ``` +#[cfg(not(feature="no_cargo"))] +#[macro_export] +macro_rules! app_from_crate { + () => { + $crate::App::new(crate_name!()) + .version(crate_version!()) + .author(crate_authors!()) + .about(crate_description!()) + }; + ($sep:expr) => { + $crate::App::new(crate_name!()) + .version(crate_version!()) + .author(crate_authors!($sep)) + .about(crate_description!()) + }; +} + /// Build `App`, `Arg`s, `SubCommand`s and `Group`s with Usage-string like input -/// but without the parsing. +/// but without the associated parsing runtime cost. +/// +/// `clap_app!` also supports several shorthand syntaxes. +/// +/// # Examples +/// +/// ```no_run +/// # #[macro_use] +/// # extern crate clap; +/// # fn main() { +/// let matches = clap_app!(myapp => +/// (version: "1.0") +/// (author: "Kevin K. ") +/// (about: "Does awesome things") +/// (@arg CONFIG: -c --config +takes_value "Sets a custom config file") +/// (@arg INPUT: +required "Sets the input file to use") +/// (@arg debug: -d ... "Sets the level of debugging information") +/// (@group difficulty => +/// (@arg hard: -h --hard "Sets hard mode") +/// (@arg normal: -n --normal "Sets normal mode") +/// (@arg easy: -e --easy "Sets easy mode") +/// ) +/// (@subcommand test => +/// (about: "controls testing features") +/// (version: "1.3") +/// (author: "Someone E. ") +/// (@arg verbose: -v --verbose "Print test information verbosely") +/// ) +/// ); +/// # } +/// ``` +/// # Shorthand Syntax for Args +/// +/// * A single hyphen followed by a character (such as `-c`) sets the [`Arg::short`] +/// * A double hyphen followed by a character or word (such as `--config`) sets [`Arg::long`] +/// * If one wishes to use a [`Arg::long`] with a hyphen inside (i.e. `--config-file`), you +/// must use `--("config-file")` due to limitations of the Rust macro system. +/// * Three dots (`...`) sets [`Arg::multiple(true)`] +/// * Angled brackets after either a short or long will set [`Arg::value_name`] and +/// `Arg::required(true)` such as `--config ` = `Arg::value_name("FILE")` and +/// `Arg::required(true) +/// * Square brackets after either a short or long will set [`Arg::value_name`] and +/// `Arg::required(false)` such as `--config [FILE]` = `Arg::value_name("FILE")` and +/// `Arg::required(false) +/// * There are short hand syntaxes for Arg methods that accept booleans +/// * A plus sign will set that method to `true` such as `+required` = `Arg::required(true)` +/// * An exclamation will set that method to `false` such as `!required` = `Arg::required(false)` +/// * A `#{min, max}` will set [`Arg::min_values(min)`] and [`Arg::max_values(max)`] +/// * An asterisk (`*`) will set `Arg::required(true)` +/// * Curly brackets around a `fn` will set [`Arg::validator`] as in `{fn}` = `Arg::validator(fn)` +/// * An Arg method that accepts a string followed by square brackets will set that method such as +/// `conflicts_with[FOO]` will set `Arg::conflicts_with("FOO")` (note the lack of quotes around +/// `FOO` in the macro) +/// * An Arg method that takes a string and can be set multiple times (such as +/// [`Arg::conflicts_with`]) followed by square brackets and a list of values separated by spaces +/// will set that method such as `conflicts_with[FOO BAR BAZ]` will set +/// `Arg::conflicts_with("FOO")`, `Arg::conflicts_with("BAR")`, and `Arg::conflicts_with("BAZ")` +/// (note the lack of quotes around the values in the macro) +/// +/// [`Arg::short`]: ./struct.Arg.html#method.short +/// [`Arg::long`]: ./struct.Arg.html#method.long +/// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple +/// [`Arg::value_name`]: ./struct.Arg.html#method.value_name +/// [`Arg::min_values(min)`]: ./struct.Arg.html#method.min_values +/// [`Arg::max_values(max)`]: ./struct.Arg.html#method.max_values +/// [`Arg::validator`]: ./struct.Arg.html#method.validator +/// [`Arg::conflicts_with`]: ./struct.Arg.html#method.conflicts_with #[macro_export] macro_rules! clap_app { (@app ($builder:expr)) => { $builder }; + (@app ($builder:expr) (@arg ($name:expr): $($tail:tt)*) $($tt:tt)*) => { + clap_app!{ @app + ($builder.arg( + clap_app!{ @arg ($crate::Arg::with_name($name)) (-) $($tail)* })) + $($tt)* + } + }; (@app ($builder:expr) (@arg $name:ident: $($tail:tt)*) $($tt:tt)*) => { clap_app!{ @app ($builder.arg( @@ -478,6 +666,9 @@ macro_rules! clap_app { // No more tokens to munch (@arg ($arg:expr) $modes:tt) => { $arg }; // Shorthand tokens influenced by the usage_string + (@arg ($arg:expr) $modes:tt --($long:expr) $($tail:tt)*) => { + clap_app!{ @arg ($arg.long($long)) $modes $($tail)* } + }; (@arg ($arg:expr) $modes:tt --$long:ident $($tail:tt)*) => { clap_app!{ @arg ($arg.long(stringify!($long))) $modes $($tail)* } }; @@ -507,10 +698,10 @@ macro_rules! clap_app { clap_app!{ @arg ($arg) $modes +required $($tail)* } }; // !foo -> .foo(false) - (@arg ($arg:expr) $modes:tt !$ident $($tail:tt)*) => { + (@arg ($arg:expr) $modes:tt !$ident:ident $($tail:tt)*) => { clap_app!{ @arg ($arg.$ident(false)) $modes $($tail)* } }; -// foo -> .foo(true) +// +foo -> .foo(true) (@arg ($arg:expr) $modes:tt +$ident:ident $($tail:tt)*) => { clap_app!{ @arg ($arg.$ident(true)) $modes $($tail)* } }; @@ -535,6 +726,10 @@ macro_rules! clap_app { clap_app!{ @app ($crate::SubCommand::with_name(stringify!($name))) $($tail)* } }; // Start the magic + (($name:expr) => $($tail:tt)*) => {{ + clap_app!{ @app ($crate::App::new($name)) $($tail)*} + }}; + ($name:ident => $($tail:tt)*) => {{ clap_app!{ @app ($crate::App::new(stringify!($name))) $($tail)*} }}; @@ -569,27 +764,21 @@ macro_rules! wlnerr( writeln!(&mut stderr(), $($arg)*).ok(); }) ); -macro_rules! werr( - ($($arg:tt)*) => ({ - use std::io::{Write, stderr}; - write!(&mut stderr(), $($arg)*).ok(); - }) -); #[cfg(feature = "debug")] #[cfg_attr(feature = "debug", macro_use)] mod debug_macros { macro_rules! debugln { - ($fmt:expr) => (println!(concat!("*DEBUG:clap: ", $fmt))); - ($fmt:expr, $($arg:tt)*) => (println!(concat!("*DEBUG:clap: ",$fmt), $($arg)*)); + ($fmt:expr) => (println!(concat!("DEBUG:clap:", $fmt))); + ($fmt:expr, $($arg:tt)*) => (println!(concat!("DEBUG:clap:",$fmt), $($arg)*)); } macro_rules! sdebugln { ($fmt:expr) => (println!($fmt)); ($fmt:expr, $($arg:tt)*) => (println!($fmt, $($arg)*)); } macro_rules! debug { - ($fmt:expr) => (print!(concat!("*DEBUG:clap: ", $fmt))); - ($fmt:expr, $($arg:tt)*) => (print!(concat!("*DEBUG:clap: ",$fmt), $($arg)*)); + ($fmt:expr) => (print!(concat!("DEBUG:clap:", $fmt))); + ($fmt:expr, $($arg:tt)*) => (print!(concat!("DEBUG:clap:",$fmt), $($arg)*)); } macro_rules! sdebug { ($fmt:expr) => (print!($fmt)); @@ -608,60 +797,234 @@ mod debug_macros { ($fmt:expr) => (); ($fmt:expr, $($arg:tt)*) => (); } - macro_rules! sdebug { - ($fmt:expr) => (); - ($fmt:expr, $($arg:tt)*) => (); - } macro_rules! debug { ($fmt:expr) => (); ($fmt:expr, $($arg:tt)*) => (); } } -// Helper/deduplication macro for printing the correct number of spaces in help messages -// used in: -// src/args/arg_builder/*.rs -// src/app/mod.rs -macro_rules! write_spaces { - ($num:expr, $w:ident) => ({ - debugln!("macro=write_spaces!;"); - for _ in 0..$num { - try!(write!($w, " ")); - } - }) -} - // Helper/deduplication macro for printing the correct number of spaces in help messages // used in: // src/args/arg_builder/*.rs // src/app/mod.rs macro_rules! write_nspaces { ($dst:expr, $num:expr) => ({ - debugln!("macro=write_spaces!;num={}", $num); + debugln!("write_spaces!: num={}", $num); for _ in 0..$num { - try!($dst.write(b" ")); + try!($dst.write_all(b" ")); } }) } // convenience macro for remove an item from a vec -macro_rules! vec_remove { +macro_rules! vec_remove_all { ($vec:expr, $to_rem:expr) => { - debugln!("macro=vec_remove!;to_rem={:?}", $to_rem); + debugln!("vec_remove_all! to_rem={:?}", $to_rem); for i in (0 .. $vec.len()).rev() { - let should_remove = &$vec[i] == $to_rem; + let should_remove = $to_rem.any(|name| name == &$vec[i]); if should_remove { $vec.swap_remove(i); } } }; } +macro_rules! find_from { + ($_self:expr, $arg_name:expr, $from:ident, $matcher:expr) => {{ + let mut ret = None; + for k in $matcher.arg_names() { + if let Some(f) = find_by_name!($_self, k, flags, iter) { + if let Some(ref v) = f.$from() { + if v.contains($arg_name) { + ret = Some(f.to_string()); + } + } + } + if let Some(o) = find_by_name!($_self, k, opts, iter) { + if let Some(ref v) = o.$from() { + if v.contains(&$arg_name) { + ret = Some(o.to_string()); + } + } + } + if let Some(pos) = find_by_name!($_self, k, positionals, values) { + if let Some(ref v) = pos.$from() { + if v.contains($arg_name) { + ret = Some(pos.b.name.to_owned()); + } + } + } + } + ret + }}; +} -// convenience macro for remove an item from a vec -macro_rules! vec_remove_all { - ($vec:expr, $to_rem:expr) => { - debugln!("macro=vec_remove_all!;to_rem={:?}", $to_rem); - for i in (0 .. $vec.len()).rev() { - let should_remove = $to_rem.contains(&$vec[i]); - if should_remove { $vec.swap_remove(i); } +macro_rules! find_name_from { + ($_self:expr, $arg_name:expr, $from:ident, $matcher:expr) => {{ + let mut ret = None; + for k in $matcher.arg_names() { + if let Some(f) = find_by_name!($_self, k, flags, iter) { + if let Some(ref v) = f.$from() { + if v.contains($arg_name) { + ret = Some(f.b.name); + } + } + } + if let Some(o) = find_by_name!($_self, k, opts, iter) { + if let Some(ref v) = o.$from() { + if v.contains(&$arg_name) { + ret = Some(o.b.name); + } + } + } + if let Some(pos) = find_by_name!($_self, k, positionals, values) { + if let Some(ref v) = pos.$from() { + if v.contains($arg_name) { + ret = Some(pos.b.name); + } + } + } } - }; + ret + }}; +} + +// Finds an arg by name +macro_rules! find_by_name { + ($p:expr, $name:expr, $what:ident, $how:ident) => { + $p.$what.$how().find(|o| o.b.name == $name) + } +} + +// Finds an option including if it's aliasesed +macro_rules! find_opt_by_long { + (@os $_self:ident, $long:expr) => {{ + _find_by_long!($_self, $long, opts) + }}; + ($_self:ident, $long:expr) => {{ + _find_by_long!($_self, $long, opts) + }}; +} + +macro_rules! find_flag_by_long { + (@os $_self:ident, $long:expr) => {{ + _find_by_long!($_self, $long, flags) + }}; + ($_self:ident, $long:expr) => {{ + _find_by_long!($_self, $long, flags) + }}; +} + +macro_rules! _find_by_long { + ($_self:ident, $long:expr, $what:ident) => {{ + $_self.$what + .iter() + .filter(|a| a.s.long.is_some()) + .find(|a| { + a.s.long.unwrap() == $long || + (a.s.aliases.is_some() && + a.s + .aliases + .as_ref() + .unwrap() + .iter() + .any(|&(alias, _)| alias == $long)) + }) + }} +} + +// Finds an option +macro_rules! find_opt_by_short { + ($_self:ident, $short:expr) => {{ + _find_by_short!($_self, $short, opts) + }} +} + +macro_rules! find_flag_by_short { + ($_self:ident, $short:expr) => {{ + _find_by_short!($_self, $short, flags) + }} +} + +macro_rules! _find_by_short { + ($_self:ident, $short:expr, $what:ident) => {{ + $_self.$what + .iter() + .filter(|a| a.s.short.is_some()) + .find(|a| a.s.short.unwrap() == $short) + }} +} + +macro_rules! find_subcmd { + ($_self:expr, $sc:expr) => {{ + $_self.subcommands + .iter() + .find(|s| { + &*s.p.meta.name == $sc || + (s.p.meta.aliases.is_some() && + s.p + .meta + .aliases + .as_ref() + .unwrap() + .iter() + .any(|&(n, _)| n == $sc)) + }) + }}; +} + +macro_rules! shorts { + ($_self:ident) => {{ + _shorts_longs!($_self, short) + }}; +} + + +macro_rules! longs { + ($_self:ident) => {{ + _shorts_longs!($_self, long) + }}; +} + +macro_rules! _shorts_longs { + ($_self:ident, $what:ident) => {{ + $_self.flags + .iter() + .filter(|f| f.s.$what.is_some()) + .map(|f| f.s.$what.as_ref().unwrap()) + .chain($_self.opts.iter() + .filter(|o| o.s.$what.is_some()) + .map(|o| o.s.$what.as_ref().unwrap())) + }}; +} + +macro_rules! arg_names { + ($_self:ident) => {{ + _names!(@args $_self) + }}; +} + +macro_rules! sc_names { + ($_self:ident) => {{ + _names!(@sc $_self) + }}; +} + +macro_rules! _names { + (@args $_self:ident) => {{ + $_self.flags + .iter() + .map(|f| &*f.b.name) + .chain($_self.opts.iter() + .map(|o| &*o.b.name) + .chain($_self.positionals.values() + .map(|p| &*p.b.name))) + }}; + (@sc $_self:ident) => {{ + $_self.subcommands + .iter() + .map(|s| &*s.p.meta.name) + .chain($_self.subcommands + .iter() + .filter(|s| s.p.meta.aliases.is_some()) + .flat_map(|s| s.p.meta.aliases.as_ref().unwrap().iter().map(|&(n, _)| n))) + + }} } diff --git a/src/vendor/clap/src/osstringext.rs b/src/vendor/clap/src/osstringext.rs index d9dfd33ff3..303cbcbef8 100644 --- a/src/vendor/clap/src/osstringext.rs +++ b/src/vendor/clap/src/osstringext.rs @@ -5,7 +5,7 @@ use std::ffi::OsStr; use std::os::unix::ffi::OsStrExt; #[cfg(target_os = "windows")] -trait OsStrExt3 { +pub trait OsStrExt3 { fn from_bytes(b: &[u8]) -> &Self; fn as_bytes(&self) -> &[u8]; } @@ -91,8 +91,7 @@ impl<'a> Iterator for OsSplit<'a> { type Item = &'a OsStr; fn next(&mut self) -> Option<&'a OsStr> { - debugln!("fn=OsSplit::next;"); - debugln!("OsSplit: {:?}", self); + debugln!("OsSplit::next: self={:?}", self); if self.pos == self.val.len() { return None; } diff --git a/src/vendor/clap/src/suggestions.rs b/src/vendor/clap/src/suggestions.rs index d11c664639..bf586def96 100644 --- a/src/vendor/clap/src/suggestions.rs +++ b/src/vendor/clap/src/suggestions.rs @@ -1,3 +1,4 @@ +use app::App; // Third Party #[cfg(feature = "suggestions")] use strsim; @@ -11,7 +12,7 @@ use fmt::Format; /// `Some("foo")`, whereas "blark" would yield `None`. #[cfg(feature = "suggestions")] #[cfg_attr(feature = "lints", allow(needless_lifetimes))] -pub fn did_you_mean<'a, T, I>(v: &str, possible_values: I) -> Option<&'a str> +pub fn did_you_mean<'a, T: ?Sized, I>(v: &str, possible_values: I) -> Option<&'a str> where T: AsRef + 'a, I: IntoIterator { @@ -31,7 +32,7 @@ pub fn did_you_mean<'a, T, I>(v: &str, possible_values: I) -> Option<&'a str> } #[cfg(not(feature = "suggestions"))] -pub fn did_you_mean<'a, T, I>(_: &str, _: I) -> Option<&'a str> +pub fn did_you_mean<'a, T: ?Sized, I>(_: &str, _: I) -> Option<&'a str> where T: AsRef + 'a, I: IntoIterator { @@ -40,39 +41,46 @@ pub fn did_you_mean<'a, T, I>(_: &str, _: I) -> Option<&'a str> /// Returns a suffix that can be empty, or is the standard 'did you mean' phrase #[cfg_attr(feature = "lints", allow(needless_lifetimes))] -pub fn did_you_mean_suffix<'z, T, I>(arg: &str, - values: I, - style: DidYouMeanMessageStyle) +pub fn did_you_mean_flag_suffix<'z, T, I>(arg: &str, longs: I, subcommands: &'z [App]) -> (String, Option<&'z str>) where T: AsRef + 'z, I: IntoIterator { - match did_you_mean(arg, values) { + match did_you_mean(arg, longs) { Some(candidate) => { - let mut suffix = "\n\tDid you mean ".to_owned(); - match style { - DidYouMeanMessageStyle::LongFlag => { - suffix.push_str(&Format::Good("--").to_string()) + let suffix = format!("\n\tDid you mean {}{}?", Format::Good("--"), Format::Good(candidate)); + return (suffix, Some(candidate)) + } + None => { + for subcommand in subcommands { + let opts = subcommand.p.flags.iter().filter_map(|f| f.s.long).chain( + subcommand.p.opts.iter().filter_map(|o| o.s.long)); + + if let Some(candidate) = did_you_mean(arg, opts) { + let suffix = format!( + "\n\tDid you mean to put '--{}' after the subcommand '{}'?", + Format::Good(arg), + Format::Good(candidate)); + return (suffix, Some(candidate)); } - DidYouMeanMessageStyle::EnumValue => suffix.push('\''), - } - suffix.push_str(&Format::Good(candidate).to_string()[..]); - if let DidYouMeanMessageStyle::EnumValue = style { - suffix.push('\''); } - suffix.push_str("?"); - (suffix, Some(candidate)) } - None => (String::new(), None), } + return (String::new(), None) } -/// A helper to determine message formatting -pub enum DidYouMeanMessageStyle { - /// Suggested value is a long flag - LongFlag, - /// Suggested value is one of various possible values - EnumValue, +/// Returns a suffix that can be empty, or is the standard 'did you mean' phrase +pub fn did_you_mean_value_suffix<'z, T, I>(arg: &str, values: I) -> (String, Option<&'z str>) + where T: AsRef + 'z, + I: IntoIterator +{ + match did_you_mean(arg, values) { + Some(candidate) => { + let suffix = format!("\n\tDid you mean '{}'?", Format::Good(candidate)); + (suffix, Some(candidate)) + } + None => (String::new(), None), + } } #[cfg(all(test, features = "suggestions"))] @@ -95,15 +103,13 @@ mod test { fn suffix_long() { let p_vals = ["test", "possible", "values"]; let suffix = "\n\tDid you mean \'--test\'?"; - assert_eq!(did_you_mean_suffix("tst", p_vals.iter(), DidYouMeanMessageStyle::LongFlag), - (suffix, Some("test"))); + assert_eq!(did_you_mean_flag_suffix("tst", p_vals.iter(), []), (suffix, Some("test"))); } #[test] fn suffix_enum() { let p_vals = ["test", "possible", "values"]; let suffix = "\n\tDid you mean \'test\'?"; - assert_eq!(did_you_mean_suffix("tst", p_vals.iter(), DidYouMeanMessageStyle::EnumValue), - (suffix, Some("test"))); + assert_eq!(did_you_mean_value_suffix("tst", p_vals.iter()), (suffix, Some("test"))); } } diff --git a/src/vendor/clap/src/usage_parser.rs b/src/vendor/clap/src/usage_parser.rs index e6cd12e0de..e890e333d8 100644 --- a/src/vendor/clap/src/usage_parser.rs +++ b/src/vendor/clap/src/usage_parser.rs @@ -29,7 +29,7 @@ pub struct UsageParser<'a> { impl<'a> UsageParser<'a> { fn new(usage: &'a str) -> Self { - debugln!("fn=new; usage={:?}", usage); + debugln!("UsageParser::new: usage={:?}", usage); UsageParser { usage: usage, pos: 0, @@ -40,15 +40,15 @@ impl<'a> UsageParser<'a> { } pub fn from_usage(usage: &'a str) -> Self { - debugln!("fn=from_usage;"); + debugln!("UsageParser::from_usage;"); UsageParser::new(usage) } pub fn parse(mut self) -> Arg<'a, 'a> { - debugln!("fn=parse;"); + debugln!("UsageParser::parse;"); let mut arg = Arg::default(); loop { - debugln!("iter; pos={};", self.pos); + debugln!("UsageParser::parse:iter: pos={};", self.pos); self.stop_at(token); if let Some(&c) = self.usage.as_bytes().get(self.pos) { match c { @@ -61,19 +61,19 @@ impl<'a> UsageParser<'a> { break; } } - debug_assert!(!arg.name.is_empty(), + debug_assert!(!arg.b.name.is_empty(), format!("No name found for Arg when parsing usage string: {}", self.usage)); - arg.num_vals = match arg.val_names { + arg.v.num_vals = match arg.v.val_names { Some(ref v) if v.len() >= 2 => Some(v.len() as u64), _ => None, }; - debugln!("vals: {:?}", arg.val_names); + debugln!("UsageParser::parse: vals...{:?}", arg.v.val_names); arg } fn name(&mut self, arg: &mut Arg<'a, 'a>) { - debugln!("fn=name;"); + debugln!("UsageParser::name;"); if *self.usage.as_bytes().get(self.pos).expect(INTERNAL_ERROR_MSG) == b'<' && !self.explicit_name_set { arg.setb(ArgSettings::Required); @@ -82,22 +82,22 @@ impl<'a> UsageParser<'a> { self.stop_at(name_end); let name = &self.usage[self.start..self.pos]; if self.prev == UsageToken::Unknown { - debugln!("setting name: {}", name); - arg.name = name; - if arg.long.is_none() && arg.short.is_none() { - debugln!("explicit name set..."); + debugln!("UsageParser::name: setting name...{}", name); + arg.b.name = name; + if arg.s.long.is_none() && arg.s.short.is_none() { + debugln!("UsageParser::name: explicit name set..."); self.explicit_name_set = true; self.prev = UsageToken::Name; } } else { - debugln!("setting val name: {}", name); - if let Some(ref mut v) = arg.val_names { + debugln!("UsageParser::name: setting val name...{}", name); + if let Some(ref mut v) = arg.v.val_names { let len = v.len(); v.insert(len, name); } else { let mut v = VecMap::new(); v.insert(0, name); - arg.val_names = Some(v); + arg.v.val_names = Some(v); arg.setb(ArgSettings::TakesValue); } self.prev = UsageToken::ValName; @@ -107,13 +107,13 @@ impl<'a> UsageParser<'a> { fn stop_at(&mut self, f: F) where F: Fn(u8) -> bool { - debugln!("fn=stop_at;"); + debugln!("UsageParser::stop_at;"); self.start = self.pos; self.pos += self.usage[self.start..].bytes().take_while(|&b| f(b)).count(); } fn short_or_long(&mut self, arg: &mut Arg<'a, 'a>) { - debugln!("fn=short_or_long;"); + debugln!("UsageParser::short_or_long;"); self.pos += 1; if *self.usage.as_bytes().get(self.pos).expect(INTERNAL_ERROR_MSG) == b'-' { self.pos += 1; @@ -124,36 +124,36 @@ impl<'a> UsageParser<'a> { } fn long(&mut self, arg: &mut Arg<'a, 'a>) { - debugln!("fn=long;"); + debugln!("UsageParser::long;"); self.stop_at(long_end); let name = &self.usage[self.start..self.pos]; if !self.explicit_name_set { - debugln!("setting name: {}", name); - arg.name = name; + debugln!("UsageParser::long: setting name...{}", name); + arg.b.name = name; } - debugln!("setting long: {}", name); - arg.long = Some(name); + debugln!("UsageParser::long: setting long...{}", name); + arg.s.long = Some(name); self.prev = UsageToken::Long; } fn short(&mut self, arg: &mut Arg<'a, 'a>) { - debugln!("fn=short;"); + debugln!("UsageParser::short;"); let start = &self.usage[self.pos..]; let short = start.chars().nth(0).expect(INTERNAL_ERROR_MSG); - debugln!("setting short: {}", short); - arg.short = Some(short); - if arg.name.is_empty() { + debugln!("UsageParser::short: setting short...{}", short); + arg.s.short = Some(short); + if arg.b.name.is_empty() { // --long takes precedence but doesn't set self.explicit_name_set let name = &start[..short.len_utf8()]; - debugln!("setting name: {}", name); - arg.name = name; + debugln!("UsageParser::short: setting name...{}", name); + arg.b.name = name; } self.prev = UsageToken::Short; } // "something..." fn multiple(&mut self, arg: &mut Arg) { - debugln!("fn=multiple;"); + debugln!("UsageParser::multiple;"); let mut dot_counter = 1; let start = self.pos; let mut bytes = self.usage[start..].bytes(); @@ -161,13 +161,13 @@ impl<'a> UsageParser<'a> { dot_counter += 1; self.pos += 1; if dot_counter == 3 { - debugln!("setting multiple"); + debugln!("UsageParser::multiple: setting multiple"); arg.setb(ArgSettings::Multiple); - if arg.settings.is_set(ArgSettings::TakesValue) { + if arg.is_set(ArgSettings::TakesValue) { arg.setb(ArgSettings::UseValueDelimiter); arg.unsetb(ArgSettings::ValueDelimiterNotSet); - if arg.val_delim.is_none() { - arg.val_delim = Some(','); + if arg.v.val_delim.is_none() { + arg.v.val_delim = Some(','); } } self.prev = UsageToken::Multiple; @@ -178,12 +178,12 @@ impl<'a> UsageParser<'a> { } fn help(&mut self, arg: &mut Arg<'a, 'a>) { - debugln!("fn=help;"); + debugln!("UsageParser::help;"); self.stop_at(help_start); self.start = self.pos + 1; self.pos = self.usage.len() - 1; - debugln!("setting help: {}", &self.usage[self.start..self.pos]); - arg.help = Some(&self.usage[self.start..self.pos]); + debugln!("UsageParser::help: setting help...{}", &self.usage[self.start..self.pos]); + arg.b.help = Some(&self.usage[self.start..self.pos]); self.pos += 1; // Move to next byte to keep from thinking ending ' is a start self.prev = UsageToken::Help; } @@ -211,989 +211,989 @@ mod test { #[test] fn create_flag_usage() { let a = Arg::from_usage("[flag] -f 'some help info'"); - assert_eq!(a.name, "flag"); - assert_eq!(a.short.unwrap(), 'f'); - assert!(a.long.is_none()); - assert_eq!(a.help.unwrap(), "some help info"); + assert_eq!(a.b.name, "flag"); + assert_eq!(a.s.short.unwrap(), 'f'); + assert!(a.s.long.is_none()); + assert_eq!(a.b.help.unwrap(), "some help info"); assert!(!a.is_set(ArgSettings::Multiple)); - assert!(a.val_names.is_none()); - assert!(a.num_vals.is_none()); + assert!(a.v.val_names.is_none()); + assert!(a.v.num_vals.is_none()); let b = Arg::from_usage("[flag] --flag 'some help info'"); - assert_eq!(b.name, "flag"); - assert_eq!(b.long.unwrap(), "flag"); - assert!(b.short.is_none()); - assert_eq!(b.help.unwrap(), "some help info"); + assert_eq!(b.b.name, "flag"); + assert_eq!(b.s.long.unwrap(), "flag"); + assert!(b.s.short.is_none()); + assert_eq!(b.b.help.unwrap(), "some help info"); assert!(!b.is_set(ArgSettings::Multiple)); - assert!(a.val_names.is_none()); - assert!(a.num_vals.is_none()); + assert!(a.v.val_names.is_none()); + assert!(a.v.num_vals.is_none()); let b = Arg::from_usage("--flag 'some help info'"); - assert_eq!(b.name, "flag"); - assert_eq!(b.long.unwrap(), "flag"); - assert!(b.short.is_none()); - assert_eq!(b.help.unwrap(), "some help info"); + assert_eq!(b.b.name, "flag"); + assert_eq!(b.s.long.unwrap(), "flag"); + assert!(b.s.short.is_none()); + assert_eq!(b.b.help.unwrap(), "some help info"); assert!(!b.is_set(ArgSettings::Multiple)); - assert!(b.val_names.is_none()); - assert!(b.num_vals.is_none()); + assert!(b.v.val_names.is_none()); + assert!(b.v.num_vals.is_none()); let c = Arg::from_usage("[flag] -f --flag 'some help info'"); - assert_eq!(c.name, "flag"); - assert_eq!(c.short.unwrap(), 'f'); - assert_eq!(c.long.unwrap(), "flag"); - assert_eq!(c.help.unwrap(), "some help info"); + assert_eq!(c.b.name, "flag"); + assert_eq!(c.s.short.unwrap(), 'f'); + assert_eq!(c.s.long.unwrap(), "flag"); + assert_eq!(c.b.help.unwrap(), "some help info"); assert!(!c.is_set(ArgSettings::Multiple)); - assert!(c.val_names.is_none()); - assert!(c.num_vals.is_none()); + assert!(c.v.val_names.is_none()); + assert!(c.v.num_vals.is_none()); let d = Arg::from_usage("[flag] -f... 'some help info'"); - assert_eq!(d.name, "flag"); - assert_eq!(d.short.unwrap(), 'f'); - assert!(d.long.is_none()); - assert_eq!(d.help.unwrap(), "some help info"); + assert_eq!(d.b.name, "flag"); + assert_eq!(d.s.short.unwrap(), 'f'); + assert!(d.s.long.is_none()); + assert_eq!(d.b.help.unwrap(), "some help info"); assert!(d.is_set(ArgSettings::Multiple)); - assert!(d.val_names.is_none()); - assert!(d.num_vals.is_none()); + assert!(d.v.val_names.is_none()); + assert!(d.v.num_vals.is_none()); let e = Arg::from_usage("[flag] -f --flag... 'some help info'"); - assert_eq!(e.name, "flag"); - assert_eq!(e.long.unwrap(), "flag"); - assert_eq!(e.short.unwrap(), 'f'); - assert_eq!(e.help.unwrap(), "some help info"); + assert_eq!(e.b.name, "flag"); + assert_eq!(e.s.long.unwrap(), "flag"); + assert_eq!(e.s.short.unwrap(), 'f'); + assert_eq!(e.b.help.unwrap(), "some help info"); assert!(e.is_set(ArgSettings::Multiple)); - assert!(e.val_names.is_none()); - assert!(e.num_vals.is_none()); + assert!(e.v.val_names.is_none()); + assert!(e.v.num_vals.is_none()); let e = Arg::from_usage("-f --flag... 'some help info'"); - assert_eq!(e.name, "flag"); - assert_eq!(e.long.unwrap(), "flag"); - assert_eq!(e.short.unwrap(), 'f'); - assert_eq!(e.help.unwrap(), "some help info"); + assert_eq!(e.b.name, "flag"); + assert_eq!(e.s.long.unwrap(), "flag"); + assert_eq!(e.s.short.unwrap(), 'f'); + assert_eq!(e.b.help.unwrap(), "some help info"); assert!(e.is_set(ArgSettings::Multiple)); - assert!(e.val_names.is_none()); - assert!(e.num_vals.is_none()); + assert!(e.v.val_names.is_none()); + assert!(e.v.num_vals.is_none()); let e = Arg::from_usage("--flags"); - assert_eq!(e.name, "flags"); - assert_eq!(e.long.unwrap(), "flags"); - assert!(e.val_names.is_none()); - assert!(e.num_vals.is_none()); + assert_eq!(e.b.name, "flags"); + assert_eq!(e.s.long.unwrap(), "flags"); + assert!(e.v.val_names.is_none()); + assert!(e.v.num_vals.is_none()); let e = Arg::from_usage("--flags..."); - assert_eq!(e.name, "flags"); - assert_eq!(e.long.unwrap(), "flags"); + assert_eq!(e.b.name, "flags"); + assert_eq!(e.s.long.unwrap(), "flags"); assert!(e.is_set(ArgSettings::Multiple)); - assert!(e.val_names.is_none()); - assert!(e.num_vals.is_none()); + assert!(e.v.val_names.is_none()); + assert!(e.v.num_vals.is_none()); let e = Arg::from_usage("[flags] -f"); - assert_eq!(e.name, "flags"); - assert_eq!(e.short.unwrap(), 'f'); - assert!(e.val_names.is_none()); - assert!(e.num_vals.is_none()); + assert_eq!(e.b.name, "flags"); + assert_eq!(e.s.short.unwrap(), 'f'); + assert!(e.v.val_names.is_none()); + assert!(e.v.num_vals.is_none()); let e = Arg::from_usage("[flags] -f..."); - assert_eq!(e.name, "flags"); - assert_eq!(e.short.unwrap(), 'f'); + assert_eq!(e.b.name, "flags"); + assert_eq!(e.s.short.unwrap(), 'f'); assert!(e.is_set(ArgSettings::Multiple)); - assert!(e.val_names.is_none()); - assert!(e.num_vals.is_none()); + assert!(e.v.val_names.is_none()); + assert!(e.v.num_vals.is_none()); let a = Arg::from_usage("-f 'some help info'"); - assert_eq!(a.name, "f"); - assert_eq!(a.short.unwrap(), 'f'); - assert!(a.long.is_none()); - assert_eq!(a.help.unwrap(), "some help info"); + assert_eq!(a.b.name, "f"); + assert_eq!(a.s.short.unwrap(), 'f'); + assert!(a.s.long.is_none()); + assert_eq!(a.b.help.unwrap(), "some help info"); assert!(!a.is_set(ArgSettings::Multiple)); - assert!(a.val_names.is_none()); - assert!(a.num_vals.is_none()); + assert!(a.v.val_names.is_none()); + assert!(a.v.num_vals.is_none()); let e = Arg::from_usage("-f"); - assert_eq!(e.name, "f"); - assert_eq!(e.short.unwrap(), 'f'); - assert!(e.val_names.is_none()); - assert!(e.num_vals.is_none()); + assert_eq!(e.b.name, "f"); + assert_eq!(e.s.short.unwrap(), 'f'); + assert!(e.v.val_names.is_none()); + assert!(e.v.num_vals.is_none()); let e = Arg::from_usage("-f..."); - assert_eq!(e.name, "f"); - assert_eq!(e.short.unwrap(), 'f'); + assert_eq!(e.b.name, "f"); + assert_eq!(e.s.short.unwrap(), 'f'); assert!(e.is_set(ArgSettings::Multiple)); - assert!(e.val_names.is_none()); - assert!(e.num_vals.is_none()); + assert!(e.v.val_names.is_none()); + assert!(e.v.num_vals.is_none()); } #[test] fn create_option_usage0() { // Short only let a = Arg::from_usage("[option] -o [opt] 'some help info'"); - assert_eq!(a.name, "option"); - assert_eq!(a.short.unwrap(), 'o'); - assert!(a.long.is_none()); - assert_eq!(a.help.unwrap(), "some help info"); + assert_eq!(a.b.name, "option"); + assert_eq!(a.s.short.unwrap(), 'o'); + assert!(a.s.long.is_none()); + assert_eq!(a.b.help.unwrap(), "some help info"); assert!(!a.is_set(ArgSettings::Multiple)); assert!(a.is_set(ArgSettings::TakesValue)); assert!(!a.is_set(ArgSettings::Required)); - assert_eq!(a.val_names.unwrap().values().collect::>(), [&"opt"]); - assert!(a.num_vals.is_none()); + assert_eq!(a.v.val_names.unwrap().values().collect::>(), [&"opt"]); + assert!(a.v.num_vals.is_none()); } #[test] fn create_option_usage1() { let b = Arg::from_usage("-o [opt] 'some help info'"); - assert_eq!(b.name, "o"); - assert_eq!(b.short.unwrap(), 'o'); - assert!(b.long.is_none()); - assert_eq!(b.help.unwrap(), "some help info"); + assert_eq!(b.b.name, "o"); + assert_eq!(b.s.short.unwrap(), 'o'); + assert!(b.s.long.is_none()); + assert_eq!(b.b.help.unwrap(), "some help info"); assert!(!b.is_set(ArgSettings::Multiple)); assert!(b.is_set(ArgSettings::TakesValue)); assert!(!b.is_set(ArgSettings::Required)); - assert_eq!(b.val_names.unwrap().values().collect::>(), [&"opt"]); - assert!(b.num_vals.is_none()); + assert_eq!(b.v.val_names.unwrap().values().collect::>(), [&"opt"]); + assert!(b.v.num_vals.is_none()); } #[test] fn create_option_usage2() { let c = Arg::from_usage("
{}
", text) - } else { - // we need to inject our own main - let (attrs, code) = partition_source(code); - format!("
# #![allow(unused_variables)]
+                if text.contains("fn main") || text.contains("quick_main!") {
+                    format!("
{}
", text) + } else { + // we need to inject our own main + let (attrs, code) = partition_source(code); + format!("
# #![allow(unused_variables)]
 {}#fn main() {{
-{}
-#}}
", classes, attrs, code) +\ + {} +#}}
", + classes, + attrs, + code) + } + } else { + // not language-rust, so no-op + format!("{}", text) } - } else { - // not language-rust, so no-op - format!("{}", text) - } - }).into_owned() + }) + .into_owned() } fn partition_source(s: &str) -> (String, String) { @@ -338,8 +377,7 @@ fn partition_source(s: &str) -> (String, String) { for line in s.lines() { let trimline = line.trim(); - let header = trimline.chars().all(|c| c.is_whitespace()) || - trimline.starts_with("#!["); + let header = trimline.chars().all(|c| c.is_whitespace()) || trimline.starts_with("#!["); if !header || after_header { after_header = true; after.push_str(line); @@ -351,4 +389,4 @@ fn partition_source(s: &str) -> (String, String) { } (before, after) -} \ No newline at end of file +} diff --git a/src/vendor/mdbook/src/renderer/html_handlebars/helpers/mod.rs b/src/vendor/mdbook/src/renderer/html_handlebars/helpers/mod.rs index 2fc287c244..f54eca8ed7 100644 --- a/src/vendor/mdbook/src/renderer/html_handlebars/helpers/mod.rs +++ b/src/vendor/mdbook/src/renderer/html_handlebars/helpers/mod.rs @@ -1,3 +1,3 @@ -pub mod navigation; -pub mod toc; -pub mod playpen; +pub mod navigation; +pub mod toc; +pub mod playpen; diff --git a/src/vendor/mdbook/src/renderer/html_handlebars/helpers/navigation.rs b/src/vendor/mdbook/src/renderer/html_handlebars/helpers/navigation.rs index 50dd7a4a2c..ca37efdbe3 100644 --- a/src/vendor/mdbook/src/renderer/html_handlebars/helpers/navigation.rs +++ b/src/vendor/mdbook/src/renderer/html_handlebars/helpers/navigation.rs @@ -14,9 +14,12 @@ pub fn previous(_h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<( // get value from context data // rc.get_path() is current json parent path, you should always use it like this // param is the key of value you want to display - let chapters = rc.context().navigate(rc.get_path(), &VecDeque::new(), "chapters").to_owned(); + let chapters = rc.context() + .navigate(rc.get_path(), &VecDeque::new(), "chapters") + .to_owned(); - let current = rc.context().navigate(rc.get_path(), &VecDeque::new(), "path") + let current = rc.context() + .navigate(rc.get_path(), &VecDeque::new(), "path") .to_string() .replace("\"", ""); @@ -84,7 +87,7 @@ pub fn previous(_h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<( match _h.template() { Some(t) => { *rc.context_mut() = updated_context; - try!(t.render(r, rc)); + t.render(r, rc)?; }, None => return Err(RenderError::new("Error with the handlebars template")), } @@ -115,9 +118,12 @@ pub fn next(_h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), R // get value from context data // rc.get_path() is current json parent path, you should always use it like this // param is the key of value you want to display - let chapters = rc.context().navigate(rc.get_path(), &VecDeque::new(), "chapters").to_owned(); + let chapters = rc.context() + .navigate(rc.get_path(), &VecDeque::new(), "chapters") + .to_owned(); - let current = rc.context().navigate(rc.get_path(), &VecDeque::new(), "path") + let current = rc.context() + .navigate(rc.get_path(), &VecDeque::new(), "path") .to_string() .replace("\"", ""); @@ -181,7 +187,7 @@ pub fn next(_h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), R match _h.template() { Some(t) => { *rc.context_mut() = updated_context; - try!(t.render(r, rc)); + t.render(r, rc)?; }, None => return Err(RenderError::new("Error with the handlebars template")), } diff --git a/src/vendor/mdbook/src/renderer/html_handlebars/helpers/playpen.rs b/src/vendor/mdbook/src/renderer/html_handlebars/helpers/playpen.rs index c71a70a081..5e49811f40 100644 --- a/src/vendor/mdbook/src/renderer/html_handlebars/helpers/playpen.rs +++ b/src/vendor/mdbook/src/renderer/html_handlebars/helpers/playpen.rs @@ -4,8 +4,9 @@ use std::io::Read; pub fn render_playpen(s: &str, path: &Path) -> String { - // When replacing one thing in a string by something with a different length, the indices - // after that will not correspond, we therefore have to store the difference to correct this + // When replacing one thing in a string by something with a different length, + // the indices after that will not correspond, + // we therefore have to store the difference to correct this let mut previous_end_index = 0; let mut replaced = String::new(); @@ -35,13 +36,13 @@ pub fn render_playpen(s: &str, path: &Path) -> String { continue; }; - let replacement = String::new() + "
" + &file_content +
-                          "
"; + let replacement = String::new() + "
" + &file_content + "
"; replaced.push_str(&s[previous_end_index..playpen.start_index]); replaced.push_str(&replacement); previous_end_index = playpen.end_index; - // println!("Playpen{{ {}, {}, {:?}, {} }}", playpen.start_index, playpen.end_index, playpen.rust_file, + // println!("Playpen{{ {}, {}, {:?}, {} }}", playpen.start_index, + // playpen.end_index, playpen.rust_file, // playpen.editable); } @@ -100,12 +101,12 @@ fn find_playpens(s: &str, base_path: &Path) -> Vec { .unwrap_or(false); playpens.push(Playpen { - start_index: i, - end_index: end_i, - rust_file: base_path.join(PathBuf::from(params[0])), - editable: editable, - escaped: escaped, - }) + start_index: i, + end_index: end_i, + rust_file: base_path.join(PathBuf::from(params[0])), + editable: editable, + escaped: escaped, + }) } playpens @@ -189,7 +190,11 @@ fn test_find_playpens_escaped_playpen() { println!("\nOUTPUT: {:?}\n", find_playpens(s, Path::new(""))); assert!(find_playpens(s, Path::new("")) == - vec![ - Playpen{start_index: 39, end_index: 68, rust_file: PathBuf::from("file.rs"), editable: true, escaped: true}, - ]); + vec![Playpen { + start_index: 39, + end_index: 68, + rust_file: PathBuf::from("file.rs"), + editable: true, + escaped: true, + }]); } diff --git a/src/vendor/mdbook/src/renderer/html_handlebars/helpers/toc.rs b/src/vendor/mdbook/src/renderer/html_handlebars/helpers/toc.rs index c7cc074a8e..bfc9513cf9 100644 --- a/src/vendor/mdbook/src/renderer/html_handlebars/helpers/toc.rs +++ b/src/vendor/mdbook/src/renderer/html_handlebars/helpers/toc.rs @@ -15,9 +15,14 @@ impl HelperDef for RenderToc { // get value from context data // rc.get_path() is current json parent path, you should always use it like this // param is the key of value you want to display - let chapters = rc.context().navigate(rc.get_path(), &VecDeque::new(), "chapters").to_owned(); - let current = rc.context().navigate(rc.get_path(), &VecDeque::new(), "path").to_string().replace("\"", ""); - try!(rc.writer.write_all("".as_bytes())?; + rc.writer.write_all("".as_bytes())?; current_level -= 1; } - try!(rc.writer.write_all("".as_bytes())); + rc.writer.write_all("".as_bytes())?; Ok(()) } } diff --git a/src/vendor/mdbook/src/renderer/html_handlebars/mod.rs b/src/vendor/mdbook/src/renderer/html_handlebars/mod.rs index f1df6d8dd9..3869fc6c87 100644 --- a/src/vendor/mdbook/src/renderer/html_handlebars/mod.rs +++ b/src/vendor/mdbook/src/renderer/html_handlebars/mod.rs @@ -1,4 +1,4 @@ -pub use self::hbs_renderer::HtmlHandlebars; - -mod hbs_renderer; -mod helpers; +pub use self::hbs_renderer::HtmlHandlebars; + +mod hbs_renderer; +mod helpers; diff --git a/src/vendor/mdbook/src/renderer/mod.rs b/src/vendor/mdbook/src/renderer/mod.rs index e76ffb486c..86f4a6a65e 100644 --- a/src/vendor/mdbook/src/renderer/mod.rs +++ b/src/vendor/mdbook/src/renderer/mod.rs @@ -1,9 +1,9 @@ -pub use self::html_handlebars::HtmlHandlebars; - -mod html_handlebars; - -use std::error::Error; - -pub trait Renderer { - fn render(&self, book: &::book::MDBook) -> Result<(), Box>; -} +pub use self::html_handlebars::HtmlHandlebars; + +mod html_handlebars; + +use std::error::Error; + +pub trait Renderer { + fn render(&self, book: &::book::MDBook) -> Result<(), Box>; +} diff --git a/src/vendor/mdbook/src/theme/book.js b/src/vendor/mdbook/src/theme/book.js index 52be9a9d06..424bac56c9 100644 --- a/src/vendor/mdbook/src/theme/book.js +++ b/src/vendor/mdbook/src/theme/book.js @@ -146,10 +146,10 @@ $( document ).ready(function() { for(var n = 0; n < lines.length; n++){ if($.trim(lines[n])[0] == hiding_character){ if(first_non_hidden_line){ - lines[n] = "" + "\n" + lines[n].replace(/(\s*)#/, "$1") + ""; + lines[n] = "" + "\n" + lines[n].replace(/(\s*)# ?/, "$1") + ""; } else { - lines[n] = "" + lines[n].replace(/(\s*)#/, "$1") + "\n" + ""; + lines[n] = "" + lines[n].replace(/(\s*)# ?/, "$1") + "\n" + ""; } lines_hidden = true; } diff --git a/src/vendor/mdbook/src/theme/index.hbs b/src/vendor/mdbook/src/theme/index.hbs index dec2927449..b3985fbca5 100644 --- a/src/vendor/mdbook/src/theme/index.hbs +++ b/src/vendor/mdbook/src/theme/index.hbs @@ -22,7 +22,7 @@ - + @@ -111,6 +111,19 @@ {{{livereload}}} + {{#if google_analytics}} + + {{/if}} + + diff --git a/src/vendor/mdbook/src/theme/mod.rs b/src/vendor/mdbook/src/theme/mod.rs index 130dd1157a..6082ff5179 100644 --- a/src/vendor/mdbook/src/theme/mod.rs +++ b/src/vendor/mdbook/src/theme/mod.rs @@ -19,11 +19,14 @@ pub static FONT_AWESOME_WOFF: &'static [u8] = include_bytes!("_FontAwesome/fonts pub static FONT_AWESOME_WOFF2: &'static [u8] = include_bytes!("_FontAwesome/fonts/fontawesome-webfont.woff2"); pub static FONT_AWESOME_OTF: &'static [u8] = include_bytes!("_FontAwesome/fonts/FontAwesome.otf"); -/// The `Theme` struct should be used instead of the static variables because the `new()` method -/// will look if the user has a theme directory in his source folder and use the users theme instead +/// The `Theme` struct should be used instead of the static variables because +/// the `new()` method +/// will look if the user has a theme directory in his source folder and use +/// the users theme instead /// of the default. /// -/// You should exceptionnaly use the static variables only if you need the default theme even if the +/// You should exceptionnaly use the static variables only if you need the +/// default theme even if the /// user has specified another theme. pub struct Theme { pub index: Vec, diff --git a/src/vendor/mdbook/src/theme/stylus/book.styl b/src/vendor/mdbook/src/theme/stylus/book.styl index c51497d012..da4aeb2674 100644 --- a/src/vendor/mdbook/src/theme/stylus/book.styl +++ b/src/vendor/mdbook/src/theme/stylus/book.styl @@ -1,10 +1,10 @@ -@import "nib" - -@import 'general' -@import 'sidebar' -@import 'page' -@import 'menu' -@import 'nav-icons' -@import 'theme-popup' -@import 'themes' -@import 'print' +@import "nib" + +@import 'general' +@import 'sidebar' +@import 'page' +@import 'menu' +@import 'nav-icons' +@import 'theme-popup' +@import 'themes' +@import 'print' diff --git a/src/vendor/mdbook/src/theme/stylus/menu.styl b/src/vendor/mdbook/src/theme/stylus/menu.styl index e3a8a20b0a..0b6828792f 100644 --- a/src/vendor/mdbook/src/theme/stylus/menu.styl +++ b/src/vendor/mdbook/src/theme/stylus/menu.styl @@ -1,39 +1,39 @@ -.menu-bar { - position: relative - height: 50px - - i { - position: relative - margin: 0 10px - z-index: 10 - line-height: 50px - - transition: color 0.5s - - &:hover { cursor: pointer } - } - - .left-buttons { float: left } - .right-buttons { float: right } -} - -.menu-title { - display: inline-block - font-weight: 200 - font-size: 20px - line-height: 50px - position: absolute - top: 0 - left: 0 - right: 0 - bottom: 0 - text-align: center - margin: 0 - - opacity: 0 - transition: opacity 0.5s ease-in-out -} - -.menu-bar:hover .menu-title { - opacity: 1 -} +.menu-bar { + position: relative + height: 50px + + i { + position: relative + margin: 0 10px + z-index: 10 + line-height: 50px + + transition: color 0.5s + + &:hover { cursor: pointer } + } + + .left-buttons { float: left } + .right-buttons { float: right } +} + +.menu-title { + display: inline-block + font-weight: 200 + font-size: 20px + line-height: 50px + position: absolute + top: 0 + left: 0 + right: 0 + bottom: 0 + text-align: center + margin: 0 + + opacity: 0 + transition: opacity 0.5s ease-in-out +} + +.menu-bar:hover .menu-title { + opacity: 1 +} diff --git a/src/vendor/mdbook/src/theme/stylus/nav-icons.styl b/src/vendor/mdbook/src/theme/stylus/nav-icons.styl index 211db6824c..42dfedc8dc 100644 --- a/src/vendor/mdbook/src/theme/stylus/nav-icons.styl +++ b/src/vendor/mdbook/src/theme/stylus/nav-icons.styl @@ -1,23 +1,23 @@ -.nav-chapters { - font-size: 2.5em - text-align: center - text-decoration: none - - position: absolute - top: 50px /* Height of menu-bar */ - bottom: 0 - margin: 0 - max-width: 150px - min-width: 90px - display: flex - justify-content: center - align-content: center - flex-direction: column - - transition: color 0.5s -} - -.mobile-nav-chapters { display: none } -.nav-chapters:hover { text-decoration: none } -.previous { left: 0 } -.next { right: 15px } +.nav-chapters { + font-size: 2.5em + text-align: center + text-decoration: none + + position: absolute + top: 50px /* Height of menu-bar */ + bottom: 0 + margin: 0 + max-width: 150px + min-width: 90px + display: flex + justify-content: center + align-content: center + flex-direction: column + + transition: color 0.5s +} + +.mobile-nav-chapters { display: none } +.nav-chapters:hover { text-decoration: none } +.previous { left: 0 } +.next { right: 15px } diff --git a/src/vendor/mdbook/src/theme/stylus/page.styl b/src/vendor/mdbook/src/theme/stylus/page.styl index 62bb6cf31e..21030bf359 100644 --- a/src/vendor/mdbook/src/theme/stylus/page.styl +++ b/src/vendor/mdbook/src/theme/stylus/page.styl @@ -1,55 +1,55 @@ -@require 'variables' - -.page-wrapper { - position: absolute - overflow-y: auto - left: $sidebar-width + 15px - right: 0 - top: 0 - bottom: 0 - box-sizing: border-box - -webkit-overflow-scrolling: touch - - min-height: 100% - - // Animation: slide away - transition: left 0.5s - - @media only screen and (max-width: 1060px) { - left: 15px; - padding-right: 15px; - } -} - -.sidebar-hidden .page-wrapper { - left: 15px -} - -.sidebar-visible .page-wrapper { - left: $sidebar-width + 15px -} - -.page { - position: absolute - top: 0 - right: 0 - left: 0 - bottom: 0 - - padding-right: 15px - overflow-y: auto -} - -.content { - margin-left: auto - margin-right:auto - max-width: 750px - padding-bottom: 50px - - a { - text-decoration: none; - &:hover { text-decoration: underline; } - } - - img { max-width: 100%; } -} +@require 'variables' + +.page-wrapper { + position: absolute + overflow-y: auto + left: $sidebar-width + 15px + right: 0 + top: 0 + bottom: 0 + box-sizing: border-box + -webkit-overflow-scrolling: touch + + min-height: 100% + + // Animation: slide away + transition: left 0.5s + + @media only screen and (max-width: 1060px) { + left: 15px; + padding-right: 15px; + } +} + +.sidebar-hidden .page-wrapper { + left: 15px +} + +.sidebar-visible .page-wrapper { + left: $sidebar-width + 15px +} + +.page { + position: absolute + top: 0 + right: 0 + left: 0 + bottom: 0 + + padding-right: 15px + overflow-y: auto +} + +.content { + margin-left: auto + margin-right:auto + max-width: 750px + padding-bottom: 50px + + a { + text-decoration: none; + &:hover { text-decoration: underline; } + } + + img { max-width: 100%; } +} diff --git a/src/vendor/mdbook/src/theme/stylus/print.styl b/src/vendor/mdbook/src/theme/stylus/print.styl index e2c8109968..f0907cd52c 100644 --- a/src/vendor/mdbook/src/theme/stylus/print.styl +++ b/src/vendor/mdbook/src/theme/stylus/print.styl @@ -1,52 +1,52 @@ -@media only print { - - #sidebar, - #menu-bar, - .nav-chapters, - .mobile-nav-chapters { - display: none - } - - #page-wrapper { - left: 0; - overflow-y: initial; - } - - #content { - max-width: none; - margin: 0; - padding: 0; - } - - .page { - overflow-y: initial; - } - - code { - background-color: #666666 - border-radius: 5px - - /* Force background to be printed in Chrome */ - -webkit-print-color-adjust: exact - } - - a, a:visited, a:active, a:hover { - color: #4183c4 - text-decoration: none - } - - h1, h2, h3, h4, h5, h6 { - page-break-inside: avoid - page-break-after: avoid - /*break-after: avoid*/ - } - - pre, code { - page-break-inside: avoid - white-space: pre-wrap /* CSS 3 */ - white-space: -moz-pre-wrap /* Mozilla, since 1999 */ - white-space: -pre-wrap /* Opera 4-6 */ - white-space: -o-pre-wrap /* Opera 7 */ - word-wrap: break-word /* Internet Explorer 5.5+ */ - } -} +@media only print { + + #sidebar, + #menu-bar, + .nav-chapters, + .mobile-nav-chapters { + display: none + } + + #page-wrapper { + left: 0; + overflow-y: initial; + } + + #content { + max-width: none; + margin: 0; + padding: 0; + } + + .page { + overflow-y: initial; + } + + code { + background-color: #666666 + border-radius: 5px + + /* Force background to be printed in Chrome */ + -webkit-print-color-adjust: exact + } + + a, a:visited, a:active, a:hover { + color: #4183c4 + text-decoration: none + } + + h1, h2, h3, h4, h5, h6 { + page-break-inside: avoid + page-break-after: avoid + /*break-after: avoid*/ + } + + pre, code { + page-break-inside: avoid + white-space: pre-wrap /* CSS 3 */ + white-space: -moz-pre-wrap /* Mozilla, since 1999 */ + white-space: -pre-wrap /* Opera 4-6 */ + white-space: -o-pre-wrap /* Opera 7 */ + word-wrap: break-word /* Internet Explorer 5.5+ */ + } +} diff --git a/src/vendor/mdbook/src/theme/stylus/sidebar.styl b/src/vendor/mdbook/src/theme/stylus/sidebar.styl index 58e7be8c91..261a63f81d 100644 --- a/src/vendor/mdbook/src/theme/stylus/sidebar.styl +++ b/src/vendor/mdbook/src/theme/stylus/sidebar.styl @@ -1,64 +1,64 @@ -@require 'variables' - -.sidebar { - position: absolute - left: 0 - top: 0 - bottom: 0 - width: $sidebar-width - overflow-y: auto - padding: 10px 10px - font-size: 0.875em - box-sizing: border-box - -webkit-overflow-scrolling: touch - - // Animation: slide away - transition: left 0.5s - - @media only screen and (max-width: 1060px) { - left: - $sidebar-width - } - - code { - line-height: 2em; - } -} - -.sidebar-hidden .sidebar { - left: - $sidebar-width -} - -.sidebar-visible .sidebar { - left: 0 -} - -.chapter { - list-style: none outside none - padding-left: 0 - line-height: 2.2em - - li a { - padding: 5px 0 - text-decoration: none - - &:hover { text-decoration: none } - } - - .spacer { - width: 100% - height: 3px - margin: 10px 0px - } -} - -.section { - list-style: none outside none - padding-left: 20px - line-height: 1.9em - - li { - text-overflow: ellipsis - overflow: hidden - white-space: nowrap - } -} +@require 'variables' + +.sidebar { + position: absolute + left: 0 + top: 0 + bottom: 0 + width: $sidebar-width + overflow-y: auto + padding: 10px 10px + font-size: 0.875em + box-sizing: border-box + -webkit-overflow-scrolling: touch + + // Animation: slide away + transition: left 0.5s + + @media only screen and (max-width: 1060px) { + left: - $sidebar-width + } + + code { + line-height: 2em; + } +} + +.sidebar-hidden .sidebar { + left: - $sidebar-width +} + +.sidebar-visible .sidebar { + left: 0 +} + +.chapter { + list-style: none outside none + padding-left: 0 + line-height: 2.2em + + li a { + padding: 5px 0 + text-decoration: none + + &:hover { text-decoration: none } + } + + .spacer { + width: 100% + height: 3px + margin: 10px 0px + } +} + +.section { + list-style: none outside none + padding-left: 20px + line-height: 1.9em + + li { + text-overflow: ellipsis + overflow: hidden + white-space: nowrap + } +} diff --git a/src/vendor/mdbook/src/theme/stylus/theme-popup.styl b/src/vendor/mdbook/src/theme/stylus/theme-popup.styl index dbd0d430d8..fadef8db84 100644 --- a/src/vendor/mdbook/src/theme/stylus/theme-popup.styl +++ b/src/vendor/mdbook/src/theme/stylus/theme-popup.styl @@ -1,56 +1,56 @@ -.theme-popup { - position: relative - left: 10px - - z-index: 1000; - - border-radius: 4px - font-size: 0.7em - - .theme { - margin: 0 - padding: 2px 10px - line-height: 25px - white-space: nowrap - - &:hover:first-child, - &:hover:last-child { - border-top-left-radius: inherit; - border-top-right-radius: inherit; - } - } - -} - -@media only screen and (max-width: 1250px) { - - .nav-chapters { - display: none - } - - .mobile-nav-chapters { - font-size: 2.5em - text-align: center - text-decoration: none - - max-width: 150px - min-width: 90px - - justify-content: center - align-content: center - - position: relative - display: inline-block - margin-bottom: 50px - - border-radius: 5px - } - - .next { - float: right - } - - .previous { - float: left - } -} +.theme-popup { + position: relative + left: 10px + + z-index: 1000; + + border-radius: 4px + font-size: 0.7em + + .theme { + margin: 0 + padding: 2px 10px + line-height: 25px + white-space: nowrap + + &:hover:first-child, + &:hover:last-child { + border-top-left-radius: inherit; + border-top-right-radius: inherit; + } + } + +} + +@media only screen and (max-width: 1250px) { + + .nav-chapters { + display: none + } + + .mobile-nav-chapters { + font-size: 2.5em + text-align: center + text-decoration: none + + max-width: 150px + min-width: 90px + + justify-content: center + align-content: center + + position: relative + display: inline-block + margin-bottom: 50px + + border-radius: 5px + } + + .next { + float: right + } + + .previous { + float: left + } +} diff --git a/src/vendor/mdbook/src/theme/stylus/variables.styl b/src/vendor/mdbook/src/theme/stylus/variables.styl index 66b89df61f..f24b3d1807 100644 --- a/src/vendor/mdbook/src/theme/stylus/variables.styl +++ b/src/vendor/mdbook/src/theme/stylus/variables.styl @@ -1 +1 @@ -$sidebar-width = 300px +$sidebar-width = 300px diff --git a/src/vendor/mdbook/src/theme/tomorrow-night.css b/src/vendor/mdbook/src/theme/tomorrow-night.css index 9788e0846b..851f218458 100644 --- a/src/vendor/mdbook/src/theme/tomorrow-night.css +++ b/src/vendor/mdbook/src/theme/tomorrow-night.css @@ -1,96 +1,96 @@ -/* Tomorrow Night Theme */ -/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ -/* Original theme - https://github.com/chriskempson/tomorrow-theme */ -/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ - -/* Tomorrow Comment */ -.hljs-comment { - color: #969896; -} - -/* Tomorrow Red */ -.hljs-variable, -.hljs-attribute, -.hljs-tag, -.hljs-regexp, -.ruby .hljs-constant, -.xml .hljs-tag .hljs-title, -.xml .hljs-pi, -.xml .hljs-doctype, -.html .hljs-doctype, -.css .hljs-id, -.css .hljs-class, -.css .hljs-pseudo { - color: #cc6666; -} - -/* Tomorrow Orange */ -.hljs-number, -.hljs-preprocessor, -.hljs-pragma, -.hljs-built_in, -.hljs-literal, -.hljs-params, -.hljs-constant { - color: #de935f; -} - -/* Tomorrow Yellow */ -.ruby .hljs-class .hljs-title, -.css .hljs-rule .hljs-attribute { - color: #f0c674; -} - -/* Tomorrow Green */ -.hljs-string, -.hljs-value, -.hljs-inheritance, -.hljs-header, -.hljs-name, -.ruby .hljs-symbol, -.xml .hljs-cdata { - color: #b5bd68; -} - -/* Tomorrow Aqua */ -.hljs-title, -.css .hljs-hexcolor { - color: #8abeb7; -} - -/* Tomorrow Blue */ -.hljs-function, -.python .hljs-decorator, -.python .hljs-title, -.ruby .hljs-function .hljs-title, -.ruby .hljs-title .hljs-keyword, -.perl .hljs-sub, -.javascript .hljs-title, -.coffeescript .hljs-title { - color: #81a2be; -} - -/* Tomorrow Purple */ -.hljs-keyword, -.javascript .hljs-function { - color: #b294bb; -} - -.hljs { - display: block; - overflow-x: auto; - background: #1d1f21; - color: #c5c8c6; - padding: 0.5em; - -webkit-text-size-adjust: none; -} - -.coffeescript .javascript, -.javascript .xml, -.tex .hljs-formula, -.xml .javascript, -.xml .vbscript, -.xml .css, -.xml .hljs-cdata { - opacity: 0.5; -} +/* Tomorrow Night Theme */ +/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ +/* Original theme - https://github.com/chriskempson/tomorrow-theme */ +/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ + +/* Tomorrow Comment */ +.hljs-comment { + color: #969896; +} + +/* Tomorrow Red */ +.hljs-variable, +.hljs-attribute, +.hljs-tag, +.hljs-regexp, +.ruby .hljs-constant, +.xml .hljs-tag .hljs-title, +.xml .hljs-pi, +.xml .hljs-doctype, +.html .hljs-doctype, +.css .hljs-id, +.css .hljs-class, +.css .hljs-pseudo { + color: #cc6666; +} + +/* Tomorrow Orange */ +.hljs-number, +.hljs-preprocessor, +.hljs-pragma, +.hljs-built_in, +.hljs-literal, +.hljs-params, +.hljs-constant { + color: #de935f; +} + +/* Tomorrow Yellow */ +.ruby .hljs-class .hljs-title, +.css .hljs-rule .hljs-attribute { + color: #f0c674; +} + +/* Tomorrow Green */ +.hljs-string, +.hljs-value, +.hljs-inheritance, +.hljs-header, +.hljs-name, +.ruby .hljs-symbol, +.xml .hljs-cdata { + color: #b5bd68; +} + +/* Tomorrow Aqua */ +.hljs-title, +.css .hljs-hexcolor { + color: #8abeb7; +} + +/* Tomorrow Blue */ +.hljs-function, +.python .hljs-decorator, +.python .hljs-title, +.ruby .hljs-function .hljs-title, +.ruby .hljs-title .hljs-keyword, +.perl .hljs-sub, +.javascript .hljs-title, +.coffeescript .hljs-title { + color: #81a2be; +} + +/* Tomorrow Purple */ +.hljs-keyword, +.javascript .hljs-function { + color: #b294bb; +} + +.hljs { + display: block; + overflow-x: auto; + background: #1d1f21; + color: #c5c8c6; + padding: 0.5em; + -webkit-text-size-adjust: none; +} + +.coffeescript .javascript, +.javascript .xml, +.tex .hljs-formula, +.xml .javascript, +.xml .vbscript, +.xml .css, +.xml .hljs-cdata { + opacity: 0.5; +} diff --git a/src/vendor/mdbook/src/utils/fs.rs b/src/vendor/mdbook/src/utils/fs.rs index d40e621b99..c2d7fe805c 100644 --- a/src/vendor/mdbook/src/utils/fs.rs +++ b/src/vendor/mdbook/src/utils/fs.rs @@ -24,10 +24,11 @@ pub fn file_to_string(path: &Path) -> Result> { Ok(content) } -/// Takes a path and returns a path containing just enough `../` to point to the root of the given path. +/// Takes a path and returns a path containing just enough `../` to point to +/// the root of the given path. /// -/// This is mostly interesting for a relative path to point back to the directory from where the -/// path starts. +/// This is mostly interesting for a relative path to point back to the +/// directory from where the path starts. /// /// ```ignore /// let mut path = Path::new("some/relative/path"); @@ -41,9 +42,10 @@ pub fn file_to_string(path: &Path) -> Result> { /// "../../" /// ``` /// -/// **note:** it's not very fool-proof, if you find a situation where it doesn't return the correct -/// path. Consider [submitting a new issue](https://github.com/azerupi/mdBook/issues) or a -/// [pull-request](https://github.com/azerupi/mdBook/pulls) to improve it. +/// **note:** it's not very fool-proof, if you find a situation where +/// it doesn't return the correct path. +/// Consider [submitting a new issue](https://github.com/azerupi/mdBook/issues) +/// or a [pull-request](https://github.com/azerupi/mdBook/pulls) to improve it. pub fn path_to_root(path: &Path) -> String { debug!("[fn]: path_to_root"); @@ -66,8 +68,9 @@ pub fn path_to_root(path: &Path) -> String { -/// This function creates a file and returns it. But before creating the file it checks every -/// directory in the path to see if it exists, and if it does not it will be created. +/// This function creates a file and returns it. But before creating the file +/// it checks every directory in the path to see if it exists, +/// and if it does not it will be created. pub fn create_file(path: &Path) -> io::Result { debug!("[fn]: create_file"); @@ -76,7 +79,7 @@ pub fn create_file(path: &Path) -> io::Result { if let Some(p) = path.parent() { debug!("Parent directory is: {:?}", p); - try!(fs::create_dir_all(p)); + fs::create_dir_all(p)?; } debug!("[*]: Create file: {:?}", path); @@ -86,13 +89,13 @@ pub fn create_file(path: &Path) -> io::Result { /// Removes all the content of a directory but not the directory itself pub fn remove_dir_content(dir: &Path) -> Result<(), Box> { - for item in try!(fs::read_dir(dir)) { + for item in fs::read_dir(dir)? { if let Ok(item) = item { let item = item.path(); if item.is_dir() { - try!(fs::remove_dir_all(item)); + fs::remove_dir_all(item)?; } else { - try!(fs::remove_file(item)); + fs::remove_file(item)?; } } } @@ -101,20 +104,21 @@ pub fn remove_dir_content(dir: &Path) -> Result<(), Box> { /// /// -/// Copies all files of a directory to another one except the files with the extensions given in the -/// `ext_blacklist` array +/// Copies all files of a directory to another one except the files +/// with the extensions given in the `ext_blacklist` array -pub fn copy_files_except_ext(from: &Path, to: &Path, recursive: bool, ext_blacklist: &[&str]) -> Result<(), Box> { +pub fn copy_files_except_ext(from: &Path, to: &Path, recursive: bool, ext_blacklist: &[&str]) + -> Result<(), Box> { debug!("[fn] copy_files_except_ext"); // Check that from and to are different if from == to { return Ok(()); } debug!("[*] Loop"); - for entry in try!(fs::read_dir(from)) { - let entry = try!(entry); + for entry in fs::read_dir(from)? { + let entry = entry?; debug!("[*] {:?}", entry.path()); - let metadata = try!(entry.metadata()); + let metadata = entry.metadata()?; // If the entry is a dir and the recursive option is enabled, call itself if metadata.is_dir() && recursive { @@ -125,13 +129,10 @@ pub fn copy_files_except_ext(from: &Path, to: &Path, recursive: bool, ext_blackl // check if output dir already exists if !to.join(entry.file_name()).exists() { - try!(fs::create_dir(&to.join(entry.file_name()))); + fs::create_dir(&to.join(entry.file_name()))?; } - try!(copy_files_except_ext(&from.join(entry.file_name()), - &to.join(entry.file_name()), - true, - ext_blacklist)); + copy_files_except_ext(&from.join(entry.file_name()), &to.join(entry.file_name()), true, ext_blacklist)?; } else if metadata.is_file() { // Check if it is in the blacklist @@ -141,13 +142,22 @@ pub fn copy_files_except_ext(from: &Path, to: &Path, recursive: bool, ext_blackl } } debug!("[*] creating path for file: {:?}", - &to.join(entry.path().file_name().expect("a file should have a file name..."))); + &to.join(entry + .path() + .file_name() + .expect("a file should have a file name..."))); info!("[*] Copying file: {:?}\n to {:?}", entry.path(), - &to.join(entry.path().file_name().expect("a file should have a file name..."))); - try!(fs::copy(entry.path(), - &to.join(entry.path().file_name().expect("a file should have a file name...")))); + &to.join(entry + .path() + .file_name() + .expect("a file should have a file name..."))); + fs::copy(entry.path(), + &to.join(entry + .path() + .file_name() + .expect("a file should have a file name...")))?; } } Ok(()) diff --git a/src/vendor/mdbook/src/utils/mod.rs b/src/vendor/mdbook/src/utils/mod.rs index ce98ee5081..ebb477ea34 100644 --- a/src/vendor/mdbook/src/utils/mod.rs +++ b/src/vendor/mdbook/src/utils/mod.rs @@ -1,20 +1,20 @@ -pub mod fs; - -use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - -/// -/// -/// Wrapper around the pulldown-cmark parser and renderer to render markdown - -pub fn render_markdown(text: &str) -> String { - let mut s = String::with_capacity(text.len() * 3 / 2); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(text, opts); - html::push_html(&mut s, p); - s -} +pub mod fs; + +use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; + + +/// +/// +/// Wrapper around the pulldown-cmark parser and renderer to render markdown + +pub fn render_markdown(text: &str) -> String { + let mut s = String::with_capacity(text.len() * 3 / 2); + + let mut opts = Options::empty(); + opts.insert(OPTION_ENABLE_TABLES); + opts.insert(OPTION_ENABLE_FOOTNOTES); + + let p = Parser::new_ext(text, opts); + html::push_html(&mut s, p); + s +} diff --git a/src/vendor/num-traits/.cargo-checksum.json b/src/vendor/num-traits/.cargo-checksum.json index 72a142d865..f4e87a0acb 100644 --- a/src/vendor/num-traits/.cargo-checksum.json +++ b/src/vendor/num-traits/.cargo-checksum.json @@ -1 +1 @@ -{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"c1f571e6884f2643c11053465800afe4056253687fd332e7a9c2d32fb30704ed","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","src/bounds.rs":"32f69f86640520478eff7978951a6d2dc0d51fe263782970185fb31ffcc4a9e1","src/cast.rs":"d76053ff336eadb80a18725c174226b4be147b876c6aa70d7aa81a16d85e9f25","src/float.rs":"1f9d571bd3946d1d93dc7f4f4ae344bfabf5fd871243145aad120e242599c2e4","src/identities.rs":"188c63de57997fb8468732251a3a8d7f665b8f61d512222c2553baefe1c827bb","src/int.rs":"b7b42dfa10423308f858216ac63fa52e26c49a7bc8900cd98de210992efc3f5f","src/lib.rs":"f99d825e652698d9b39b1e26132139542e12e968d87cf804d46e95ec0c21f14f","src/ops/checked.rs":"f02fd815b99edf079043d3621c1566e0ab3e755fe284d0b8fdf5d7ca56d546e7","src/ops/mod.rs":"668ea4d117bc1fdf7eaf0fe16692fa40dfbdfcbc7a2010237fe395ce0086e02e","src/ops/saturating.rs":"46821d815c90c16b2f6bec0b94b4d7ebdbddf3ea42edc0467de738c56abf6436","src/ops/wrapping.rs":"aa750486640063fad24175fd3b622eba2d4453d4de5a3d8bc93e1c3f50ced485","src/pow.rs":"73b611ad8d595ef917871ba859ff0c25efc2382220d30568e5fbb930bf6b4daa","src/sign.rs":"c08ad1647d393571cc73344b174b1764d7d7d5fb57170cc8f1d26e7ab9527e7c"},"package":"e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99"} \ No newline at end of file +{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"66a7dc4de5cbd1880cb7e5498317fd58c5bdca69fb3073c37f0a6604e0722387","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","src/bounds.rs":"3666fbdf8b347fa1daad3ee92e3ac4a10df99d26bc340b877d5bbba914b61782","src/cast.rs":"c44c11863751810ef40763ac3470facdf0c3f0d16db9474d3e566a8c78eafdaa","src/float.rs":"1f9d571bd3946d1d93dc7f4f4ae344bfabf5fd871243145aad120e242599c2e4","src/identities.rs":"c78281aa689c5f376a2cfbe1e81aefd54d634f410671ce1660a2c117b3ae6b04","src/int.rs":"b7b42dfa10423308f858216ac63fa52e26c49a7bc8900cd98de210992efc3f5f","src/lib.rs":"84c84706da4df88b87a0f5ed2e412dcfc644f9f849db2dc4302faa5d8b79379a","src/ops/checked.rs":"bc667779636f81c7eca138c6d57252a6bb6ca4cd1f0ff706a993067044d86f94","src/ops/mod.rs":"668ea4d117bc1fdf7eaf0fe16692fa40dfbdfcbc7a2010237fe395ce0086e02e","src/ops/saturating.rs":"46821d815c90c16b2f6bec0b94b4d7ebdbddf3ea42edc0467de738c56abf6436","src/ops/wrapping.rs":"a444c7eb3366f2ad4c3a9938f1158b1994b9da4bbf9097884b5e8e27a9b581dd","src/pow.rs":"73b611ad8d595ef917871ba859ff0c25efc2382220d30568e5fbb930bf6b4daa","src/sign.rs":"732736f44c3c410f43da98eb3c8887319d94ad2c4883d614a9c353659402b315"},"package":"1708c0628602a98b52fad936cf3edb9a107af06e52e49fdf0707e884456a6af6"} \ No newline at end of file diff --git a/src/vendor/num-traits/Cargo.toml b/src/vendor/num-traits/Cargo.toml index e0b996afc6..7fdf99d236 100644 --- a/src/vendor/num-traits/Cargo.toml +++ b/src/vendor/num-traits/Cargo.toml @@ -7,6 +7,6 @@ keywords = ["mathematics", "numerics"] license = "MIT/Apache-2.0" repository = "https://github.com/rust-num/num" name = "num-traits" -version = "0.1.37" +version = "0.1.39" [dependencies] diff --git a/src/vendor/num-traits/src/bounds.rs b/src/vendor/num-traits/src/bounds.rs index 966296c4ca..ea5c811a7d 100644 --- a/src/vendor/num-traits/src/bounds.rs +++ b/src/vendor/num-traits/src/bounds.rs @@ -1,6 +1,7 @@ use std::{usize, u8, u16, u32, u64}; use std::{isize, i8, i16, i32, i64}; use std::{f32, f64}; +use std::num::Wrapping; /// Numbers which have upper and lower bounds pub trait Bounded { @@ -35,6 +36,11 @@ bounded_impl!(i16, i16::MIN, i16::MAX); bounded_impl!(i32, i32::MIN, i32::MAX); bounded_impl!(i64, i64::MIN, i64::MAX); +impl Bounded for Wrapping { + fn min_value() -> Self { Wrapping(T::min_value()) } + fn max_value() -> Self { Wrapping(T::max_value()) } +} + bounded_impl!(f32, f32::MIN, f32::MAX); macro_rules! for_each_tuple_ { @@ -69,3 +75,25 @@ macro_rules! bounded_tuple { for_each_tuple!(bounded_tuple); bounded_impl!(f64, f64::MIN, f64::MAX); + + +macro_rules! test_wrapping_bounded { + ($($t:ty)+) => { + $( + assert_eq!(Wrapping::<$t>::min_value().0, <$t>::min_value()); + assert_eq!(Wrapping::<$t>::max_value().0, <$t>::max_value()); + )+ + }; +} + +#[test] +fn wrapping_bounded() { + test_wrapping_bounded!(usize u8 u16 u32 u64 isize i8 i16 i32 i64); +} + +#[test] +fn wrapping_is_bounded() { + fn require_bounded(_: &T) {} + require_bounded(&Wrapping(42_u32)); + require_bounded(&Wrapping(-42)); +} diff --git a/src/vendor/num-traits/src/cast.rs b/src/vendor/num-traits/src/cast.rs index 8ff03fd760..8949834a1e 100644 --- a/src/vendor/num-traits/src/cast.rs +++ b/src/vendor/num-traits/src/cast.rs @@ -1,4 +1,5 @@ use std::mem::size_of; +use std::num::Wrapping; use identities::Zero; use bounds::Bounded; @@ -385,6 +386,17 @@ impl_from_primitive!(u64, to_u64); impl_from_primitive!(f32, to_f32); impl_from_primitive!(f64, to_f64); + +impl ToPrimitive for Wrapping { + fn to_i64(&self) -> Option { self.0.to_i64() } + fn to_u64(&self) -> Option { self.0.to_u64() } +} +impl FromPrimitive for Wrapping { + fn from_u64(n: u64) -> Option { T::from_u64(n).map(Wrapping) } + fn from_i64(n: i64) -> Option { T::from_i64(n).map(Wrapping) } +} + + /// Cast from one machine scalar to another. /// /// # Examples @@ -434,6 +446,11 @@ impl_num_cast!(isize, to_isize); impl_num_cast!(f32, to_f32); impl_num_cast!(f64, to_f64); +impl NumCast for Wrapping { + fn from(n: U) -> Option { + T::from(n).map(Wrapping) + } +} #[test] fn to_primitive_float() { @@ -448,3 +465,47 @@ fn to_primitive_float() { assert_eq!((f64::NEG_INFINITY).to_f32(), Some(f32::NEG_INFINITY)); assert!((f64::NAN).to_f32().map_or(false, |f| f.is_nan())); } + +macro_rules! test_wrapping_to_primitive { + ($($t:ty)+) => { + $({ + let i: $t = 0; + let w = Wrapping(i); + assert_eq!(i.to_u8(), w.to_u8()); + assert_eq!(i.to_u16(), w.to_u16()); + assert_eq!(i.to_u32(), w.to_u32()); + assert_eq!(i.to_u64(), w.to_u64()); + assert_eq!(i.to_usize(), w.to_usize()); + assert_eq!(i.to_i8(), w.to_i8()); + assert_eq!(i.to_i16(), w.to_i16()); + assert_eq!(i.to_i32(), w.to_i32()); + assert_eq!(i.to_i64(), w.to_i64()); + assert_eq!(i.to_isize(), w.to_isize()); + assert_eq!(i.to_f32(), w.to_f32()); + assert_eq!(i.to_f64(), w.to_f64()); + })+ + }; +} + +#[test] +fn wrapping_to_primitive() { + test_wrapping_to_primitive!(usize u8 u16 u32 u64 isize i8 i16 i32 i64); +} + +#[test] +fn wrapping_is_toprimitive() { + fn require_toprimitive(_: &T) {} + require_toprimitive(&Wrapping(42)); +} + +#[test] +fn wrapping_is_fromprimitive() { + fn require_fromprimitive(_: &T) {} + require_fromprimitive(&Wrapping(42)); +} + +#[test] +fn wrapping_is_numcast() { + fn require_numcast(_: &T) {} + require_numcast(&Wrapping(42)); +} diff --git a/src/vendor/num-traits/src/identities.rs b/src/vendor/num-traits/src/identities.rs index 15f0c90c94..2f520e0878 100644 --- a/src/vendor/num-traits/src/identities.rs +++ b/src/vendor/num-traits/src/identities.rs @@ -1,4 +1,5 @@ use std::ops::{Add, Mul}; +use std::num::Wrapping; /// Defines an additive identity element for `Self`. pub trait Zero: Sized + Add { @@ -50,6 +51,16 @@ zero_impl!(i64, 0i64); zero_impl!(f32, 0.0f32); zero_impl!(f64, 0.0f64); +impl Zero for Wrapping where Wrapping: Add> { + fn is_zero(&self) -> bool { + self.0.is_zero() + } + fn zero() -> Self { + Wrapping(T::zero()) + } +} + + /// Defines a multiplicative identity element for `Self`. pub trait One: Sized + Mul { /// Returns the multiplicative identity element of `Self`, `1`. @@ -94,6 +105,11 @@ one_impl!(i64, 1i64); one_impl!(f32, 1.0f32); one_impl!(f64, 1.0f64); +impl One for Wrapping where Wrapping: Mul> { + fn one() -> Self { + Wrapping(T::one()) + } +} // Some helper functions provided for backwards compatibility. @@ -102,3 +118,31 @@ one_impl!(f64, 1.0f64); /// Returns the multiplicative identity, `1`. #[inline(always)] pub fn one() -> T { One::one() } + + +macro_rules! test_wrapping_identities { + ($($t:ty)+) => { + $( + assert_eq!(zero::<$t>(), zero::>().0); + assert_eq!(one::<$t>(), one::>().0); + assert_eq!((0 as $t).is_zero(), Wrapping(0 as $t).is_zero()); + assert_eq!((1 as $t).is_zero(), Wrapping(1 as $t).is_zero()); + )+ + }; +} + +#[test] +fn wrapping_identities() { + test_wrapping_identities!(isize i8 i16 i32 i64 usize u8 u16 u32 u64); +} + +#[test] +fn wrapping_is_zero() { + fn require_zero(_: &T) {} + require_zero(&Wrapping(42)); +} +#[test] +fn wrapping_is_one() { + fn require_one(_: &T) {} + require_one(&Wrapping(42)); +} diff --git a/src/vendor/num-traits/src/lib.rs b/src/vendor/num-traits/src/lib.rs index 4b4ed9cf40..41422c8d04 100644 --- a/src/vendor/num-traits/src/lib.rs +++ b/src/vendor/num-traits/src/lib.rs @@ -15,6 +15,8 @@ html_playground_url = "http://play.integer32.com/")] use std::ops::{Add, Sub, Mul, Div, Rem}; +use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; +use std::num::Wrapping; pub use bounds::Bounded; pub use float::{Float, FloatConst}; @@ -36,10 +38,9 @@ pub mod cast; pub mod int; pub mod pow; -/// The base trait for numeric types -pub trait Num: PartialEq + Zero + One - + Add + Sub - + Mul + Div + Rem +/// The base trait for numeric types, covering `0` and `1` values, +/// comparisons, basic numeric operations, and string conversion. +pub trait Num: PartialEq + Zero + One + NumOps { type FromStrRadixErr; @@ -59,6 +60,72 @@ pub trait Num: PartialEq + Zero + One fn from_str_radix(str: &str, radix: u32) -> Result; } +/// The trait for types implementing basic numeric operations +/// +/// This is automatically implemented for types which implement the operators. +pub trait NumOps + : Add + + Sub + + Mul + + Div + + Rem +{} + +impl NumOps for T +where T: Add + + Sub + + Mul + + Div + + Rem +{} + +/// The trait for `Num` types which also implement numeric operations taking +/// the second operand by reference. +/// +/// This is automatically implemented for types which implement the operators. +pub trait NumRef: Num + for<'r> NumOps<&'r Self> {} +impl NumRef for T where T: Num + for<'r> NumOps<&'r T> {} + +/// The trait for references which implement numeric operations, taking the +/// second operand either by value or by reference. +/// +/// This is automatically implemented for types which implement the operators. +pub trait RefNum: NumOps + for<'r> NumOps<&'r Base, Base> {} +impl RefNum for T where T: NumOps + for<'r> NumOps<&'r Base, Base> {} + +/// The trait for types implementing numeric assignment operators (like `+=`). +/// +/// This is automatically implemented for types which implement the operators. +pub trait NumAssignOps + : AddAssign + + SubAssign + + MulAssign + + DivAssign + + RemAssign +{} + +impl NumAssignOps for T +where T: AddAssign + + SubAssign + + MulAssign + + DivAssign + + RemAssign +{} + +/// The trait for `Num` types which also implement assignment operators. +/// +/// This is automatically implemented for types which implement the operators. +pub trait NumAssign: Num + NumAssignOps {} +impl NumAssign for T where T: Num + NumAssignOps {} + +/// The trait for `NumAssign` types which also implement assignment operations +/// taking the second operand by reference. +/// +/// This is automatically implemented for types which implement the operators. +pub trait NumAssignRef: NumAssign + for<'r> NumAssignOps<&'r Self> {} +impl NumAssignRef for T where T: NumAssign + for<'r> NumAssignOps<&'r T> {} + + macro_rules! int_trait_impl { ($name:ident for $($t:ty)*) => ($( impl $name for $t { @@ -74,6 +141,18 @@ macro_rules! int_trait_impl { } int_trait_impl!(Num for usize u8 u16 u32 u64 isize i8 i16 i32 i64); +impl Num for Wrapping + where Wrapping: + Add> + Sub> + + Mul> + Div> + Rem> +{ + type FromStrRadixErr = T::FromStrRadixErr; + fn from_str_radix(str: &str, radix: u32) -> Result { + T::from_str_radix(str, radix).map(Wrapping) + } +} + + #[derive(Debug)] pub enum FloatErrorKind { Empty, @@ -243,9 +322,9 @@ float_trait_impl!(Num for f32 f64); /// A value bounded by a minimum and a maximum /// -/// If input is less than min then this returns min. -/// If input is greater than max then this returns max. -/// Otherwise this returns input. +/// If input is less than min then this returns min. +/// If input is greater than max then this returns max. +/// Otherwise this returns input. #[inline] pub fn clamp(input: T, min: T, max: T) -> T { debug_assert!(min <= max, "min must be less than or equal to max"); @@ -281,3 +360,76 @@ fn from_str_radix_unwrap() { let f: f32 = Num::from_str_radix("0.0", 10).unwrap(); assert_eq!(f, 0.0); } + +macro_rules! test_wrapping_from_str_radix { + ($($t:ty)+) => { + $( + for &(s, r) in &[("42", 10), ("42", 2), ("-13.0", 10), ("foo", 10)] { + let w = Wrapping::<$t>::from_str_radix(s, r).map(|w| w.0); + assert_eq!(w, <$t as Num>::from_str_radix(s, r)); + } + )+ + }; +} +#[test] +fn wrapping_is_num() { + fn require_num(_: &T) {} + require_num(&Wrapping(42_u32)); + require_num(&Wrapping(-42)); +} +#[test] +fn wrapping_from_str_radix() { + test_wrapping_from_str_radix!(usize u8 u16 u32 u64 isize i8 i16 i32 i64); +} + +#[test] +fn check_num_ops() { + fn compute(x: T, y: T) -> T { + x * y / y % y + y - y + } + assert_eq!(compute(1, 2), 1) +} + +#[test] +fn check_numref_ops() { + fn compute(x: T, y: &T) -> T { + x * y / y % y + y - y + } + assert_eq!(compute(1, &2), 1) +} + +#[test] +fn check_refnum_ops() { + fn compute(x: &T, y: T) -> T + where for<'a> &'a T: RefNum + { + &(&(&(&(x * y) / y) % y) + y) - y + } + assert_eq!(compute(&1, 2), 1) +} + +#[test] +fn check_refref_ops() { + fn compute(x: &T, y: &T) -> T + where for<'a> &'a T: RefNum + { + &(&(&(&(x * y) / y) % y) + y) - y + } + assert_eq!(compute(&1, &2), 1) +} + +#[test] +fn check_numassign_ops() { + fn compute(mut x: T, y: T) -> T { + x *= y; + x /= y; + x %= y; + x += y; + x -= y; + x + } + assert_eq!(compute(1, 2), 1) +} + +// TODO test `NumAssignRef`, but even the standard numeric types don't +// implement this yet. (see rust pr41336) diff --git a/src/vendor/num-traits/src/ops/checked.rs b/src/vendor/num-traits/src/ops/checked.rs index b6bf0d6b0a..45e671685e 100644 --- a/src/vendor/num-traits/src/ops/checked.rs +++ b/src/vendor/num-traits/src/ops/checked.rs @@ -89,3 +89,4 @@ checked_impl!(CheckedDiv, checked_div, i16); checked_impl!(CheckedDiv, checked_div, i32); checked_impl!(CheckedDiv, checked_div, i64); checked_impl!(CheckedDiv, checked_div, isize); + diff --git a/src/vendor/num-traits/src/ops/wrapping.rs b/src/vendor/num-traits/src/ops/wrapping.rs index 40b266d979..f9890581b1 100644 --- a/src/vendor/num-traits/src/ops/wrapping.rs +++ b/src/vendor/num-traits/src/ops/wrapping.rs @@ -1,4 +1,5 @@ use std::ops::{Add, Sub, Mul}; +use std::num::Wrapping; macro_rules! wrapping_impl { ($trait_name:ident, $method:ident, $t:ty) => { @@ -76,6 +77,23 @@ wrapping_impl!(WrappingMul, wrapping_mul, i32); wrapping_impl!(WrappingMul, wrapping_mul, i64); wrapping_impl!(WrappingMul, wrapping_mul, isize); +// Well this is a bit funny, but all the more appropriate. +impl WrappingAdd for Wrapping where Wrapping: Add> { + fn wrapping_add(&self, v: &Self) -> Self { + Wrapping(self.0.wrapping_add(&v.0)) + } +} +impl WrappingSub for Wrapping where Wrapping: Sub> { + fn wrapping_sub(&self, v: &Self) -> Self { + Wrapping(self.0.wrapping_sub(&v.0)) + } +} +impl WrappingMul for Wrapping where Wrapping: Mul> { + fn wrapping_mul(&self, v: &Self) -> Self { + Wrapping(self.0.wrapping_mul(&v.0)) + } +} + #[test] fn test_wrapping_traits() { @@ -85,4 +103,25 @@ fn test_wrapping_traits() { assert_eq!(wrapping_add(255, 1), 0u8); assert_eq!(wrapping_sub(0, 1), 255u8); assert_eq!(wrapping_mul(255, 2), 254u8); + assert_eq!(wrapping_add(255, 1), (Wrapping(255u8) + Wrapping(1u8)).0); + assert_eq!(wrapping_sub(0, 1), (Wrapping(0u8) - Wrapping(1u8)).0); + assert_eq!(wrapping_mul(255, 2), (Wrapping(255u8) * Wrapping(2u8)).0); +} + +#[test] +fn wrapping_is_wrappingadd() { + fn require_wrappingadd(_: &T) {} + require_wrappingadd(&Wrapping(42)); +} + +#[test] +fn wrapping_is_wrappingsub() { + fn require_wrappingsub(_: &T) {} + require_wrappingsub(&Wrapping(42)); +} + +#[test] +fn wrapping_is_wrappingmul() { + fn require_wrappingmul(_: &T) {} + require_wrappingmul(&Wrapping(42)); } diff --git a/src/vendor/num-traits/src/sign.rs b/src/vendor/num-traits/src/sign.rs index c56ad25854..4b43c897ef 100644 --- a/src/vendor/num-traits/src/sign.rs +++ b/src/vendor/num-traits/src/sign.rs @@ -1,5 +1,6 @@ use std::ops::Neg; use std::{f32, f64}; +use std::num::Wrapping; use Num; @@ -73,6 +74,30 @@ macro_rules! signed_impl { signed_impl!(isize i8 i16 i32 i64); +impl Signed for Wrapping where Wrapping: Num + Neg> +{ + #[inline] + fn abs(&self) -> Self { + Wrapping(self.0.abs()) + } + + #[inline] + fn abs_sub(&self, other: &Self) -> Self { + Wrapping(self.0.abs_sub(&other.0)) + } + + #[inline] + fn signum(&self) -> Self { + Wrapping(self.0.signum()) + } + + #[inline] + fn is_positive(&self) -> bool { self.0.is_positive() } + + #[inline] + fn is_negative(&self) -> bool { self.0.is_negative() } +} + macro_rules! signed_float_impl { ($t:ty, $nan:expr, $inf:expr, $neg_inf:expr) => { impl Signed for $t { @@ -159,3 +184,21 @@ macro_rules! empty_trait_impl { } empty_trait_impl!(Unsigned for usize u8 u16 u32 u64); + +impl Unsigned for Wrapping where Wrapping: Num {} + +#[test] +fn unsigned_wrapping_is_unsigned() { + fn require_unsigned(_: &T) {} + require_unsigned(&Wrapping(42_u32)); +} +/* +// Commenting this out since it doesn't compile on Rust 1.8, +// because on this version Wrapping doesn't implement Neg and therefore can't +// implement Signed. +#[test] +fn signed_wrapping_is_signed() { + fn require_signed(_: &T) {} + require_signed(&Wrapping(-42)); +} +*/ diff --git a/src/vendor/num_cpus/.appveyor.yml b/src/vendor/num_cpus/.appveyor.yml new file mode 100644 index 0000000000..e75d59feb0 --- /dev/null +++ b/src/vendor/num_cpus/.appveyor.yml @@ -0,0 +1,16 @@ +environment: + matrix: + - TARGET: x86_64-pc-windows-msvc + - TARGET: i686-pc-windows-msvc + - TARGET: x86_64-pc-windows-gnu + - TARGET: i686-pc-windows-gnu +install: + - curl -sSf -o rustup-init.exe https://win.rustup.rs/ + - rustup-init.exe -y --default-host %TARGET% + - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin + - rustc -vV + - cargo -vV +build: false +test_script: + - cargo build --verbose + - cargo test --verbose diff --git a/src/vendor/num_cpus/.cargo-checksum.json b/src/vendor/num_cpus/.cargo-checksum.json index ef9bb34da4..41d8872a13 100644 --- a/src/vendor/num_cpus/.cargo-checksum.json +++ b/src/vendor/num_cpus/.cargo-checksum.json @@ -1 +1 @@ -{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"f9b1ca6ae27d1c18215265024629a8960c31379f206d9ed20f64e0b2dcf79805",".travis.yml":"979eec484d5ceb95a6553860cafa053694613fbafda322e6d159cfab261d99a0","Cargo.toml":"c5de4733fcac643bf2b8021fdaaca47b866aff3daebc8026b913eff08d21c623","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0593d22d122d4bfec6407115e3907546312976f75473417aaa4c57ecd2095ae6","README.md":"4427b594795a80d1955cf6111b580d37a857b06aa2e2fbe1242483b2208f1683","src/lib.rs":"87ea4d2864fb2c16edcdb1dd476220ed74647b5b76214c27e0ba457e82a10785"},"package":"ca313f1862c7ec3e0dfe8ace9fa91b1d9cb5c84ace3d00f5ec4216238e93c167"} \ No newline at end of file +{"files":{".appveyor.yml":"2f3f82a91e82a6c0b601048a5c9cd9b39fa78dfb7172ecfe7ff3d4d010af66d8",".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"f9b1ca6ae27d1c18215265024629a8960c31379f206d9ed20f64e0b2dcf79805",".travis.yml":"979eec484d5ceb95a6553860cafa053694613fbafda322e6d159cfab261d99a0","Cargo.toml":"64af5f893e89e09be28f21857fb4238ddc63cf12f012a6f59c1a404db3f96284","Cargo.toml.orig":"48a42b4b99acfab097debca9823f0a1b9de7e937cc60ed9c9e9d2ecd43edaa27","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0593d22d122d4bfec6407115e3907546312976f75473417aaa4c57ecd2095ae6","README.md":"4d586d8185ea43e6472db25ad748da265024869eabdcd62805c2bf3de06c4eb4","src/lib.rs":"295224974716d3ac2cd3d9f65764bae2ec92d94c01f939f62cf3b00974bb3e63"},"package":"aec53c34f2d0247c5ca5d32cca1478762f301740468ee9ee6dcb7a0dd7a0c584"} \ No newline at end of file diff --git a/src/vendor/num_cpus/Cargo.toml b/src/vendor/num_cpus/Cargo.toml index 3f9df98752..2f4034cec7 100644 --- a/src/vendor/num_cpus/Cargo.toml +++ b/src/vendor/num_cpus/Cargo.toml @@ -1,14 +1,24 @@ -[package] +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g. crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) +[package] name = "num_cpus" -version = "1.4.0" -description = "Get the number of CPUs on a machine." +version = "1.6.2" authors = ["Sean McArthur "] -license = "MIT/Apache-2.0" -repository = "https://github.com/seanmonstar/num_cpus" +description = "Get the number of CPUs on a machine." documentation = "https://docs.rs/num_cpus" keywords = ["cpu", "cpus", "cores"] categories = ["hardware-support"] - -[dependencies] -libc = "0.2" +license = "MIT/Apache-2.0" +repository = "https://github.com/seanmonstar/num_cpus" +[dependencies.libc] +version = "0.2.6" diff --git a/src/vendor/num_cpus/Cargo.toml.orig b/src/vendor/num_cpus/Cargo.toml.orig new file mode 100644 index 0000000000..1bd18e2b65 --- /dev/null +++ b/src/vendor/num_cpus/Cargo.toml.orig @@ -0,0 +1,14 @@ +[package] + +name = "num_cpus" +version = "1.6.2" +description = "Get the number of CPUs on a machine." +authors = ["Sean McArthur "] +license = "MIT/Apache-2.0" +repository = "https://github.com/seanmonstar/num_cpus" +documentation = "https://docs.rs/num_cpus" +keywords = ["cpu", "cpus", "cores"] +categories = ["hardware-support"] + +[dependencies] +libc = "0.2.6" diff --git a/src/vendor/num_cpus/README.md b/src/vendor/num_cpus/README.md index d98bee519d..a111b992ac 100644 --- a/src/vendor/num_cpus/README.md +++ b/src/vendor/num_cpus/README.md @@ -1,6 +1,10 @@ # num_cpus [![crates.io](http://meritbadge.herokuapp.com/num_cpus)](https://crates.io/crates/num_cpus) +[![Travis CI Status](https://travis-ci.org/seanmonstar/num_cpus.svg?branch=master)](https://travis-ci.org/seanmonstar/num_cpus) +[![AppVeyor status](https://ci.appveyor.com/api/projects/status/qn8t6grhko5jwno6?svg=true)](https://ci.appveyor.com/project/seanmonstar/num-cpus) + +[Documentation](https://docs.rs/num_cpus) Count the number of CPUs on the current machine. diff --git a/src/vendor/num_cpus/src/lib.rs b/src/vendor/num_cpus/src/lib.rs index 21b1ff72df..e53f9eba8c 100644 --- a/src/vendor/num_cpus/src/lib.rs +++ b/src/vendor/num_cpus/src/lib.rs @@ -1,4 +1,13 @@ -//! Replaces the deprecated functionality of std::os::num_cpus. +//! # num_cpus +//! +//! A crate with utilities to determine the number of CPUs available on the +//! current system. +//! +//! ## Example +//! +//! ``` +//! let cpus = num_cpus::get(); +//! ``` #![cfg_attr(test, deny(warnings))] #![deny(missing_docs)] #![allow(non_snake_case)] @@ -6,28 +15,116 @@ #[cfg(not(windows))] extern crate libc; -/// Returns the number of CPUs of the current machine. +/// Returns the number of available CPUs of the current system. +/// +/// # Note +/// +/// This will check sched affinity on Linux. #[inline] pub fn get() -> usize { get_num_cpus() } -/// Returns the number of physical cores of the current machine. -/// If not possible on the particular architecture returns same as get() which -/// is the logical CPUs. +/// Returns the number of physical cores of the current system. +/// +/// If not possible on the particular architecture, returns same as `get()` +/// which is the logical CPUs. #[inline] pub fn get_physical() -> usize { get_num_physical_cpus() } -#[cfg(not(target_os = "linux"))] +#[cfg(not(any(target_os = "linux", target_os = "windows")))] #[inline] fn get_num_physical_cpus() -> usize { // Not implemented, fallback get_num_cpus() } +#[cfg(target_os = "windows")] +fn get_num_physical_cpus() -> usize { + match get_num_physical_cpus_windows() { + Some(num) => num, + None => get_num_cpus() + } +} + +#[cfg(target_os = "windows")] +fn get_num_physical_cpus_windows() -> Option { + // Inspired by https://msdn.microsoft.com/en-us/library/ms683194 + + use std::ptr; + use std::mem; + + #[allow(non_upper_case_globals)] + const RelationProcessorCore: u32 = 0; + + #[repr(C)] + #[allow(non_camel_case_types)] + struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION { + mask: usize, + relationship: u32, + _unused: [u64; 2] + } + + extern "system" { + fn GetLogicalProcessorInformation( + info: *mut SYSTEM_LOGICAL_PROCESSOR_INFORMATION, + length: &mut u32 + ) -> u32; + } + + // First we need to determine how much space to reserve. + + // The required size of the buffer, in bytes. + let mut needed_size = 0; + + unsafe { + GetLogicalProcessorInformation(ptr::null_mut(), &mut needed_size); + } + + let struct_size = mem::size_of::() as u32; + + // Could be 0, or some other bogus size. + if needed_size == 0 || needed_size < struct_size || needed_size % struct_size != 0 { + return None; + } + + let count = needed_size / struct_size; + + // Allocate some memory where we will store the processor info. + let mut buf = Vec::with_capacity(count as usize); + + let result; + + unsafe { + result = GetLogicalProcessorInformation(buf.as_mut_ptr(), &mut needed_size); + } + + // Failed for any reason. + if result == 0 { + return None; + } + + let count = needed_size / struct_size; + + unsafe { + buf.set_len(count as usize); + } + + let phys_proc_count = buf.iter() + // Only interested in processor packages (physical processors.) + .filter(|proc_info| proc_info.relationship == RelationProcessorCore) + .count(); + + if phys_proc_count == 0 { + None + } else { + Some(phys_proc_count) + } +} + #[cfg(target_os = "linux")] fn get_num_physical_cpus() -> usize { use std::io::BufReader; @@ -146,36 +243,74 @@ fn get_num_cpus() -> usize { cpus as usize } -#[cfg( - any( - target_os = "linux", - target_os = "nacl", - target_os = "macos", - target_os = "ios", - target_os = "android", - target_os = "solaris", - target_os = "fuchsia", - ) +#[cfg(target_os = "linux")] +fn get_num_cpus() -> usize { + let mut set: libc::cpu_set_t = unsafe { std::mem::zeroed() }; + if unsafe { libc::sched_getaffinity(0, std::mem::size_of::(), &mut set) } == 0 { + let mut count: u32 = 0; + for i in 0..libc::CPU_SETSIZE as usize { + if unsafe { libc::CPU_ISSET(i, &set) } { + count += 1 + } + } + count as usize + } else { + let cpus = unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) }; + if cpus < 1 { + 1 + } else { + cpus as usize + } + } +} + +#[cfg(any( + target_os = "nacl", + target_os = "macos", + target_os = "ios", + target_os = "android", + target_os = "solaris", + target_os = "fuchsia") )] fn get_num_cpus() -> usize { - unsafe { - libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize + let cpus = unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) }; + if cpus < 1 { + 1 + } else { + cpus as usize } } + #[cfg(any(target_os = "emscripten", target_os = "redox", target_os = "haiku"))] fn get_num_cpus() -> usize { 1 } -#[test] -fn lower_bound() { - assert!(get() > 0); - assert!(get_physical() > 0); -} +#[cfg(test)] +mod tests { + fn env_var(name: &'static str) -> Option { + ::std::env::var(name).ok().map(|val| val.parse().unwrap()) + } + #[test] + fn test_get() { + let num = super::get(); + if let Some(n) = env_var("NUM_CPUS_TEST_GET") { + assert_eq!(num, n); + } else { + assert!(num > 0); + assert!(num < 236_451); + } + } -#[test] -fn upper_bound() { - assert!(get() < 236_451); - assert!(get_physical() < 236_451); + #[test] + fn test_get_physical() { + let num = super::get_physical(); + if let Some(n) = env_var("NUM_CPUS_TEST_GET_PHYSICAL") { + assert_eq!(num, n); + } else { + assert!(num > 0); + assert!(num < 236_451); + } + } } diff --git a/src/vendor/pulldown-cmark-0.0.8/.cargo-checksum.json b/src/vendor/pulldown-cmark-0.0.8/.cargo-checksum.json deleted file mode 100644 index a883018edc..0000000000 --- a/src/vendor/pulldown-cmark-0.0.8/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"c8abae1dde7fb754d895a22fd2ab3a1d55574904ad0b0b38202838a1885199a7","CONTRIBUTING.md":"8f3a78ee312b1d3010d7061cf08a92a54235452e9834d2b541b292ad8fe56611","Cargo.toml":"340080aa970b2448bdfa6009abe331623969a768499120276b750b820952e71d","LICENSE":"c4f10f55904bdb9f27d3fbf94c354926d6cfe8b982276e556238c258941b243b","README.md":"89295054ac267167e58828c6c14af30f0e2cd9736ccee204312e6ae1ef88aee9","specs/footnotes.txt":"3908656f568bb9edaf8c4b0cac17259488e1f1a689e71e460b1791019d6e2d38","specs/table.txt":"2277c624a0879b812ed8978c8ca6bc94217e3cc26b800833fa436da683e2d5d8","src/entities.rs":"146f254dc83a12a4df0343b40e3a8690fb1b5b5175a110123aced7fbaf360871","src/escape.rs":"47c69dcc2cd76882c29b167bbcb63e784a041feac5898735a437c85ade578cda","src/html.rs":"3ea94263896f76e20d45159375ba8270752d93f664127e456b1b88aac39f41ee","src/lib.rs":"372e880525718bc922286876cf7fe86396c91ac57ea13a422761b5c0912faf59","src/main.rs":"3be1775ac34c387b98d0c9e7f16c4802e13a539a3892572c245c92d51c6a9151","src/parse.rs":"38b91c6839c66aec3c4150ba7a4ea7d714f3f7ae1d1a893f43386a02fe8af726","src/passes.rs":"184a61180e14cff825bf69bb25e16d995efbce2ba8b14db98ca388ceeb2f620c","src/puncttable.rs":"6787a03f708e23851ef6e7ca636d15978c33ba3e8fcb6778a09762a8baa47870","src/scanners.rs":"4f739dab493be870d07dc66ab7c7b58e6136bd84f262d85af5300da0ea734702","src/utils.rs":"6400643f6b85d96b2e91166ab4701a007dba6ac40fa2b349a466d1a1b97bb843","tools/mk_entities.py":"a88f6a00413822644a00b146d39918d5a97e5092afdd30ce4ed0465b2ed4f315","tools/mk_puncttable.py":"5001dbf67e0009f2e23dbdfd50986564cdae977c611379c4b9d888366caa1d5e"},"package":"1058d7bb927ca067656537eec4e02c2b4b70eaaa129664c5b90c111e20326f41"} \ No newline at end of file diff --git a/src/vendor/pulldown-cmark-0.0.8/CONTRIBUTING.md b/src/vendor/pulldown-cmark-0.0.8/CONTRIBUTING.md deleted file mode 100644 index 1ba853922f..0000000000 --- a/src/vendor/pulldown-cmark-0.0.8/CONTRIBUTING.md +++ /dev/null @@ -1,24 +0,0 @@ -Want to contribute? Great! First, read this page (including the small print at the end). - -### Before you contribute -Before we can use your code, you must sign the -[Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual?csw=1) -(CLA), which you can do online. The CLA is necessary mainly because you own the -copyright to your changes, even after your contribution becomes part of our -codebase, so we need your permission to use and distribute your code. We also -need to be sure of various other things—for instance that you'll tell us if you -know that your code infringes on other people's patents. You don't have to sign -the CLA until after you've submitted your code for review and a member has -approved it, but you must do it before we can put your code into our codebase. -Before you start working on a larger contribution, you should get in touch with -us first through the issue tracker with your idea so that we can help out and -possibly guide you. Coordinating up front makes it much easier to avoid -frustration later on. - -### Code reviews -All submissions, including submissions by project members, require review. We -use Github pull requests for this purpose. - -### The small print -Contributions made by corporations are covered by a different agreement than -the one above, the Software Grant and Corporate Contributor License Agreement. diff --git a/src/vendor/pulldown-cmark-0.0.8/Cargo.toml b/src/vendor/pulldown-cmark-0.0.8/Cargo.toml deleted file mode 100644 index a7a200efdd..0000000000 --- a/src/vendor/pulldown-cmark-0.0.8/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "pulldown-cmark" -version = "0.0.8" -authors = [ "Raph Levien " ] -license = "MIT" -description = "A pull parser for CommonMark" -repository = "https://github.com/google/pulldown-cmark" - -[[bin]] -name = "pulldown-cmark" -doc = false - -[dependencies] -getopts = "0.2" -bitflags = "0.5" diff --git a/src/vendor/pulldown-cmark-0.0.8/README.md b/src/vendor/pulldown-cmark-0.0.8/README.md deleted file mode 100644 index 3ec499924a..0000000000 --- a/src/vendor/pulldown-cmark-0.0.8/README.md +++ /dev/null @@ -1,108 +0,0 @@ -# pulldown-cmark - -This library is a pull parser for [CommonMark](http://commonmark.org/), written -in [Rust](http://www.rust-lang.org/). It comes with a simple command-line tool, -useful for rendering to HTML, and is also designed to be easy to use from as -a library. - -It is designed to be: - -* Fast; a bare minimum of allocation and copying -* Safe; written in pure Rust with no unsafe blocks -* Versatile; in particular source-maps are supported -* Correct; the goal is 100% compliance with the [CommonMark spec](http://spec.commonmark.org/) - -## Why a pull parser? - -There are many parsers for Markdown and its variants, but to my knowledge none -use pull parsing. Pull parsing has become popular for XML, especially for -memory-conscious applications, because it uses dramatically less memory than -construcing a document tree, but is much easier to use than push parsers. Push -parsers are notoriously difficult to use, and also often error-prone because of -the need for user to delicately juggle state in a series of callbacks. - -In a clean design, the parsing and rendering stages are neatly separated, but -this is often sacrificed in the name of performance and expedience. Many Markdown -implementations mix parsing and rendering together, and even designs that try -to separate them (such as the popular [hoedown](https://github.com/hoedown/hoedown)), -make the assumption that the rendering process can be fully represented as a -serialized string. - -Pull parsing is in some sense the most versatile architecture. It's possible to -drive a push interface, also with minimal memory, and quite straightforward to -construct an AST. Another advantage is that source-map information (the mapping -between parsed blocks and offsets within the source text) is readily available; -you basically just call `get_offset()` as you consume events. - -While manipulating AST's is the most flexible way to transform documents, -operating on iterators is surprisingly easy, and quite efficient. Here, for -example, is the code to transform soft line breaks into hard breaks: - -```rust -let parser = parser.map(|event| match event { - Event::SoftBreak => Event::HardBreak, - _ => event -}); -``` - -Or expanding an abbreviation in text: - -```rust -let parser = parser.map(|event| match event { - Event::Str(text) => Event::Str(text.replace("abbr", "abbreviation")), - _ => event -}); -``` - -Another simple example is code to determine the max nesting level: - -```rust -let mut max_nesting = 0; -let mut level = 0; -for event in parser { - match event { - Event::Start(_) => { - level += 1; - max_nesting = std::cmp::max(max_nesting, level); - } - Event::End(_) => level -= 1, - _ => () - } -} -``` - -## Using Rust idiomatically - -A lot of the internal scanning code is written at a pretty low level (it -pretty much scans byte patterns for the bits of syntax), but the external -interface is designed to be idiomatic Rust. - -Pull parsers are at heart an iterator of events (start and end tags, text, -and other bits and pieces). The parser data structure implements the -Rust Iterator trait directly, and Event is an enum. Thus, you can use the -full power and expressivity of Rust's iterator infrastructure, including -for loops and `map` (as in the examples above), collecting the events into -a vector (for recording, playback, and manipulation), and more. - -Further, the Str event (representing text) is a copy-on-write string (note: -this isn't quite true yet). The vast majority of text fragments are just -slices of the source document. For these, copy-on-write gives a convenient -representation that requires no allocation or copying, but allocated -strings are available when they're needed. Thus, when rendering text to -HTML, most text is copied just once, from the source document to the -HTML buffer. - -## Authors - -The main author is Raph Levien. - -## Contributions - -We gladly accept contributions via GitHub pull requests, as long as the author -has signed the Google Contributor License. Please see CONTRIBUTIONS.md for -more details. - -### Disclaimer - -This is not an official Google product (experimental or otherwise), it -is just code that happens to be owned by Google. diff --git a/src/vendor/pulldown-cmark-0.0.8/specs/footnotes.txt b/src/vendor/pulldown-cmark-0.0.8/specs/footnotes.txt deleted file mode 100644 index 4f4f3ab670..0000000000 --- a/src/vendor/pulldown-cmark-0.0.8/specs/footnotes.txt +++ /dev/null @@ -1,154 +0,0 @@ -Run this with `cargo run -- -F -s specs/footnotes.txt`. - -This is how footnotes are basically used. - -. -Lorem ipsum.[^a] - -[^a]: Cool. -. -

Lorem ipsum.1

-
1 -

Cool.

-
-. - - -Footnotes can be used inside blockquotes: - -. -> This is the song that never ends.\ -> Yes it goes on and on my friends.[^lambchops] -> -> [^lambchops]: -. -
-

This is the song that never ends.
-Yes it goes on and on my friends.1

- -
-. - - -Footnotes can be complex block structures: - -. -Songs that simply loop are a popular way to annoy people. [^examples] - -[^examples]: - * [The song that never ends](https://www.youtube.com/watch?v=0U2zJOryHKQ) - * [I know a song that gets on everybody's nerves](https://www.youtube.com/watch?v=TehWI09qxls) - * [Ninety-nine bottles of beer on the wall](https://www.youtube.com/watch?v=qVjCag8XoHQ) -. -

Songs that simply loop are a popular way to annoy people. 1

- -. - - -Footnotes can even have multiple paragraphs. They also don't need to be referenced to show up. - -. -[^lorem]: If heaven ever wishes to grant me a boon, it will be a total effacing of the results of a mere chance which fixed my eye on a certain stray piece of shelf-paper. It was nothing on which I would naturally have stumbled in the course of my daily round, for it was an old number of an Australian journal, the Sydney Bulletin for April 18, 1925. It had escaped even the cutting bureau which had at the time of its issuance been avidly collecting material for my uncle's research. - -I had largely given over my inquiries into what Professor Angell called the "Cthulhu Cult", and was visiting a learned friend in Paterson, New Jersey; the curator of a local museum and a mineralogist of note. Examining one day the reserve specimens roughly set on the storage shelves in a rear room of the museum, my eye was caught by an odd picture in one of the old papers spread beneath the stones. It was the Sydney Bulletin I have mentioned, for my friend had wide affiliations in all conceivable foreign parts; and the picture was a half-tone cut of a hideous stone image almost identical with that which Legrasse had found in the swamp. -. -
1 -

If heaven ever wishes to grant me a boon, it will be a total effacing of the results of a mere chance which fixed my eye on a certain stray piece of shelf-paper. It was nothing on which I would naturally have stumbled in the course of my daily round, for it was an old number of an Australian journal, the Sydney Bulletin for April 18, 1925. It had escaped even the cutting bureau which had at the time of its issuance been avidly collecting material for my uncle's research.

-

I had largely given over my inquiries into what Professor Angell called the "Cthulhu Cult", and was visiting a learned friend in Paterson, New Jersey; the curator of a local museum and a mineralogist of note. Examining one day the reserve specimens roughly set on the storage shelves in a rear room of the museum, my eye was caught by an odd picture in one of the old papers spread beneath the stones. It was the Sydney Bulletin I have mentioned, for my friend had wide affiliations in all conceivable foreign parts; and the picture was a half-tone cut of a hideous stone image almost identical with that which Legrasse had found in the swamp.

-
-. - - -A footnote will end on a double line break. - -. -[^ipsum]: How much wood would a woodchuck chuck. - -If a woodchuck could chuck wood. - - -# Forms of entertainment that aren't childish -. -
1 -

How much wood would a woodchuck chuck.

-

If a woodchuck could chuck wood.

-
-

Forms of entertainment that aren't childish

-. - - -A footnote will also break if it's inside another container. - -. -> He's also really stupid. [^why] -> -> [^why]: Because your mamma! - -As such, we can guarantee that the non-childish forms of entertainment are probably more entertaining to adults, since, having had a whole childhood doing the childish ones, the non-childish ones are merely the ones that haven't gotten boring yet. -. -
-

He's also really stupid. 1

-
1 -

Because your mamma!

-
-
-

As such, we can guarantee that the non-childish forms of entertainment are probably more entertaining to adults, since, having had a whole childhood doing the childish ones, the non-childish ones are merely the ones that haven't gotten boring yet.

-. - - -As a special exception, footnotes cannot be nested directly inside each other. - -. -Nested footnotes are considered poor style. [^a] [^xkcd] - -[^a]: This does not mean that footnotes cannot reference each other. [^b] - -[^b]: This means that a footnote definition cannot be directly inside another footnote definition. - -> This means that a footnote cannot be directly inside another footnote's body. [^e] -> -> [^e]: They can, however, be inside anything else. - -[^xkcd]: [The other kind of nested footnote is, however, considered poor style.](https://xkcd.com/1208/) -. -

Nested footnotes are considered poor style. 1 2

-
1 -

This does not mean that footnotes cannot reference each other. 3

-
-
3 -

This means that a footnote definition cannot be directly inside another footnote definition.

-
-

This means that a footnote cannot be directly inside another footnote's body. 4

-
4 -

They can, however, be inside anything else.

-
-
-
- -. - -They do need one line between each other. - -. -[^Doh] Ray Me Fa So La Te Do! [^1] - -[^Doh]: I know. Wrong Doe. And it won't render right. -[^1]: Common for people practicing music. -. -

1 Ray Me Fa So La Te Do! 2

-
1 -

I know. Wrong Doe. And it won't render right. -2: Common for people practicing music.

-
-. - diff --git a/src/vendor/pulldown-cmark-0.0.8/specs/table.txt b/src/vendor/pulldown-cmark-0.0.8/specs/table.txt deleted file mode 100644 index 4c0e598cae..0000000000 --- a/src/vendor/pulldown-cmark-0.0.8/specs/table.txt +++ /dev/null @@ -1,215 +0,0 @@ -Run this with `cargo run -- -T -s specs/table.txt`. - -False match -=========== - -. -Test header ------------ -. -

Test header

-. - - -True match -========== - -. -Test|Table -----|----- -. - -
TestTable
-. - - -Actual rows in it -================= - -. -Test|Table -----|----- -Test row -Test|2 - -Test ending -. - - - -
TestTable
Test row
Test2
-

Test ending

-. - - -Test with quote -=============== - -. -> Test | Table -> ------|------ -> Row 1 | Every -> Row 2 | Day -> -> Paragraph -. -
- - - -
Test Table
Row 1 Every
Row 2 Day
-

Paragraph

-
-. - - -Test with list -============== - -. - 1. First entry - 2. Second entry - - Col 1|Col 2 - -|- - Row 1|Part 2 - Row 2|Part 2 -. -
    -
  1. -

    First entry

    -
  2. -
  3. -

    Second entry

    - - - -
    Col 1Col 2
    Row 1Part 2
    Row 2Part 2
    -
  4. -
-. - - -Test with border -================ - -. -|Col 1|Col 2| -|-----|-----| -|R1C1 |R1C2 | -|R2C1 |R2C2 | -. - - - -
Col 1Col 2
R1C1 R1C2
R2C1 R2C2
-. - - -Test with empty cells -===================== - -Empty cells should work. - -. -| Col 1 | Col 2 | -|-------|-------| -| | | -| | | -. - - - -
Col 1 Col 2
-. - -... and properly mix with filled cells. - -. -| Col 1 | Col 2 | -|-------|-------| -| x | | -| | x | -. - - - -
Col 1 Col 2
x
x
-. - - -Table with UTF-8 -================ - -Basic example. - -. -|Col 1|Col 2| -|-----|-----| -|✓ |✓ | -|✓ |✓ | -. - - - -
Col 1Col 2
✓ ✓
✓ ✓
-. - -More advanced example. - -. -| Target | std |rustc|cargo| notes | -|-------------------------------|-----|-----|-----|----------------------------| -| `x86_64-unknown-linux-musl` | ✓ | | | 64-bit Linux with MUSL | -| `arm-linux-androideabi` | ✓ | | | ARM Android | -| `arm-unknown-linux-gnueabi` | ✓ | ✓ | | ARM Linux (2.6.18+) | -| `arm-unknown-linux-gnueabihf` | ✓ | ✓ | | ARM Linux (2.6.18+) | -| `aarch64-unknown-linux-gnu` | ✓ | | | ARM64 Linux (2.6.18+) | -| `mips-unknown-linux-gnu` | ✓ | | | MIPS Linux (2.6.18+) | -| `mipsel-unknown-linux-gnu` | ✓ | | | MIPS (LE) Linux (2.6.18+) | -. - - - - - - - - -
Target std rustccargo notes
x86_64-unknown-linux-musl ✓ 64-bit Linux with MUSL
arm-linux-androideabi ✓ ARM Android
arm-unknown-linux-gnueabi ✓ ✓ ARM Linux (2.6.18+)
arm-unknown-linux-gnueabihf ✓ ✓ ARM Linux (2.6.18+)
aarch64-unknown-linux-gnu ✓ ARM64 Linux (2.6.18+)
mips-unknown-linux-gnu ✓ MIPS Linux (2.6.18+)
mipsel-unknown-linux-gnu ✓ MIPS (LE) Linux (2.6.18+)
-. - -Hiragana-containing pseudo-table. - -. -|-|-| -|ぃ|い| -. -

|-|-| -|ぃ|い|

-. - -Hiragana-containing actual table. - -. -|ぁ|ぃ| -|-|-| -|ぃ|ぃ| -. - - -
ぁぃ
ぃぃ
-. - -Test russian symbols. - -. -|Колонка 1|Колонка 2| -|---------|---------| -|Ячейка 1 |Ячейка 2 | -. - - -
Колонка 1Колонка 2
Ячейка 1 Ячейка 2
-. - diff --git a/src/vendor/pulldown-cmark-0.0.8/src/entities.rs b/src/vendor/pulldown-cmark-0.0.8/src/entities.rs deleted file mode 100644 index 8c5049461b..0000000000 --- a/src/vendor/pulldown-cmark-0.0.8/src/entities.rs +++ /dev/null @@ -1,4284 +0,0 @@ -// Copyright 2015 Google Inc. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -//! Expansions of HTML5 entities - -// Autogenerated by mk_entities.py - -const ENTITIES: [&'static str; 2125] = [ - "AElig", - "AMP", - "Aacute", - "Abreve", - "Acirc", - "Acy", - "Afr", - "Agrave", - "Alpha", - "Amacr", - "And", - "Aogon", - "Aopf", - "ApplyFunction", - "Aring", - "Ascr", - "Assign", - "Atilde", - "Auml", - "Backslash", - "Barv", - "Barwed", - "Bcy", - "Because", - "Bernoullis", - "Beta", - "Bfr", - "Bopf", - "Breve", - "Bscr", - "Bumpeq", - "CHcy", - "COPY", - "Cacute", - "Cap", - "CapitalDifferentialD", - "Cayleys", - "Ccaron", - "Ccedil", - "Ccirc", - "Cconint", - "Cdot", - "Cedilla", - "CenterDot", - "Cfr", - "Chi", - "CircleDot", - "CircleMinus", - "CirclePlus", - "CircleTimes", - "ClockwiseContourIntegral", - "CloseCurlyDoubleQuote", - "CloseCurlyQuote", - "Colon", - "Colone", - "Congruent", - "Conint", - "ContourIntegral", - "Copf", - "Coproduct", - "CounterClockwiseContourIntegral", - "Cross", - "Cscr", - "Cup", - "CupCap", - "DD", - "DDotrahd", - "DJcy", - "DScy", - "DZcy", - "Dagger", - "Darr", - "Dashv", - "Dcaron", - "Dcy", - "Del", - "Delta", - "Dfr", - "DiacriticalAcute", - "DiacriticalDot", - "DiacriticalDoubleAcute", - "DiacriticalGrave", - "DiacriticalTilde", - "Diamond", - "DifferentialD", - "Dopf", - "Dot", - "DotDot", - "DotEqual", - "DoubleContourIntegral", - "DoubleDot", - "DoubleDownArrow", - "DoubleLeftArrow", - "DoubleLeftRightArrow", - "DoubleLeftTee", - "DoubleLongLeftArrow", - "DoubleLongLeftRightArrow", - "DoubleLongRightArrow", - "DoubleRightArrow", - "DoubleRightTee", - "DoubleUpArrow", - "DoubleUpDownArrow", - "DoubleVerticalBar", - "DownArrow", - "DownArrowBar", - "DownArrowUpArrow", - "DownBreve", - "DownLeftRightVector", - "DownLeftTeeVector", - "DownLeftVector", - "DownLeftVectorBar", - "DownRightTeeVector", - "DownRightVector", - "DownRightVectorBar", - "DownTee", - "DownTeeArrow", - "Downarrow", - "Dscr", - "Dstrok", - "ENG", - "ETH", - "Eacute", - "Ecaron", - "Ecirc", - "Ecy", - "Edot", - "Efr", - "Egrave", - "Element", - "Emacr", - "EmptySmallSquare", - "EmptyVerySmallSquare", - "Eogon", - "Eopf", - "Epsilon", - "Equal", - "EqualTilde", - "Equilibrium", - "Escr", - "Esim", - "Eta", - "Euml", - "Exists", - "ExponentialE", - "Fcy", - "Ffr", - "FilledSmallSquare", - "FilledVerySmallSquare", - "Fopf", - "ForAll", - "Fouriertrf", - "Fscr", - "GJcy", - "GT", - "Gamma", - "Gammad", - "Gbreve", - "Gcedil", - "Gcirc", - "Gcy", - "Gdot", - "Gfr", - "Gg", - "Gopf", - "GreaterEqual", - "GreaterEqualLess", - "GreaterFullEqual", - "GreaterGreater", - "GreaterLess", - "GreaterSlantEqual", - "GreaterTilde", - "Gscr", - "Gt", - "HARDcy", - "Hacek", - "Hat", - "Hcirc", - "Hfr", - "HilbertSpace", - "Hopf", - "HorizontalLine", - "Hscr", - "Hstrok", - "HumpDownHump", - "HumpEqual", - "IEcy", - "IJlig", - "IOcy", - "Iacute", - "Icirc", - "Icy", - "Idot", - "Ifr", - "Igrave", - "Im", - "Imacr", - "ImaginaryI", - "Implies", - "Int", - "Integral", - "Intersection", - "InvisibleComma", - "InvisibleTimes", - "Iogon", - "Iopf", - "Iota", - "Iscr", - "Itilde", - "Iukcy", - "Iuml", - "Jcirc", - "Jcy", - "Jfr", - "Jopf", - "Jscr", - "Jsercy", - "Jukcy", - "KHcy", - "KJcy", - "Kappa", - "Kcedil", - "Kcy", - "Kfr", - "Kopf", - "Kscr", - "LJcy", - "LT", - "Lacute", - "Lambda", - "Lang", - "Laplacetrf", - "Larr", - "Lcaron", - "Lcedil", - "Lcy", - "LeftAngleBracket", - "LeftArrow", - "LeftArrowBar", - "LeftArrowRightArrow", - "LeftCeiling", - "LeftDoubleBracket", - "LeftDownTeeVector", - "LeftDownVector", - "LeftDownVectorBar", - "LeftFloor", - "LeftRightArrow", - "LeftRightVector", - "LeftTee", - "LeftTeeArrow", - "LeftTeeVector", - "LeftTriangle", - "LeftTriangleBar", - "LeftTriangleEqual", - "LeftUpDownVector", - "LeftUpTeeVector", - "LeftUpVector", - "LeftUpVectorBar", - "LeftVector", - "LeftVectorBar", - "Leftarrow", - "Leftrightarrow", - "LessEqualGreater", - "LessFullEqual", - "LessGreater", - "LessLess", - "LessSlantEqual", - "LessTilde", - "Lfr", - "Ll", - "Lleftarrow", - "Lmidot", - "LongLeftArrow", - "LongLeftRightArrow", - "LongRightArrow", - "Longleftarrow", - "Longleftrightarrow", - "Longrightarrow", - "Lopf", - "LowerLeftArrow", - "LowerRightArrow", - "Lscr", - "Lsh", - "Lstrok", - "Lt", - "Map", - "Mcy", - "MediumSpace", - "Mellintrf", - "Mfr", - "MinusPlus", - "Mopf", - "Mscr", - "Mu", - "NJcy", - "Nacute", - "Ncaron", - "Ncedil", - "Ncy", - "NegativeMediumSpace", - "NegativeThickSpace", - "NegativeThinSpace", - "NegativeVeryThinSpace", - "NestedGreaterGreater", - "NestedLessLess", - "NewLine", - "Nfr", - "NoBreak", - "NonBreakingSpace", - "Nopf", - "Not", - "NotCongruent", - "NotCupCap", - "NotDoubleVerticalBar", - "NotElement", - "NotEqual", - "NotEqualTilde", - "NotExists", - "NotGreater", - "NotGreaterEqual", - "NotGreaterFullEqual", - "NotGreaterGreater", - "NotGreaterLess", - "NotGreaterSlantEqual", - "NotGreaterTilde", - "NotHumpDownHump", - "NotHumpEqual", - "NotLeftTriangle", - "NotLeftTriangleBar", - "NotLeftTriangleEqual", - "NotLess", - "NotLessEqual", - "NotLessGreater", - "NotLessLess", - "NotLessSlantEqual", - "NotLessTilde", - "NotNestedGreaterGreater", - "NotNestedLessLess", - "NotPrecedes", - "NotPrecedesEqual", - "NotPrecedesSlantEqual", - "NotReverseElement", - "NotRightTriangle", - "NotRightTriangleBar", - "NotRightTriangleEqual", - "NotSquareSubset", - "NotSquareSubsetEqual", - "NotSquareSuperset", - "NotSquareSupersetEqual", - "NotSubset", - "NotSubsetEqual", - "NotSucceeds", - "NotSucceedsEqual", - "NotSucceedsSlantEqual", - "NotSucceedsTilde", - "NotSuperset", - "NotSupersetEqual", - "NotTilde", - "NotTildeEqual", - "NotTildeFullEqual", - "NotTildeTilde", - "NotVerticalBar", - "Nscr", - "Ntilde", - "Nu", - "OElig", - "Oacute", - "Ocirc", - "Ocy", - "Odblac", - "Ofr", - "Ograve", - "Omacr", - "Omega", - "Omicron", - "Oopf", - "OpenCurlyDoubleQuote", - "OpenCurlyQuote", - "Or", - "Oscr", - "Oslash", - "Otilde", - "Otimes", - "Ouml", - "OverBar", - "OverBrace", - "OverBracket", - "OverParenthesis", - "PartialD", - "Pcy", - "Pfr", - "Phi", - "Pi", - "PlusMinus", - "Poincareplane", - "Popf", - "Pr", - "Precedes", - "PrecedesEqual", - "PrecedesSlantEqual", - "PrecedesTilde", - "Prime", - "Product", - "Proportion", - "Proportional", - "Pscr", - "Psi", - "QUOT", - "Qfr", - "Qopf", - "Qscr", - "RBarr", - "REG", - "Racute", - "Rang", - "Rarr", - "Rarrtl", - "Rcaron", - "Rcedil", - "Rcy", - "Re", - "ReverseElement", - "ReverseEquilibrium", - "ReverseUpEquilibrium", - "Rfr", - "Rho", - "RightAngleBracket", - "RightArrow", - "RightArrowBar", - "RightArrowLeftArrow", - "RightCeiling", - "RightDoubleBracket", - "RightDownTeeVector", - "RightDownVector", - "RightDownVectorBar", - "RightFloor", - "RightTee", - "RightTeeArrow", - "RightTeeVector", - "RightTriangle", - "RightTriangleBar", - "RightTriangleEqual", - "RightUpDownVector", - "RightUpTeeVector", - "RightUpVector", - "RightUpVectorBar", - "RightVector", - "RightVectorBar", - "Rightarrow", - "Ropf", - "RoundImplies", - "Rrightarrow", - "Rscr", - "Rsh", - "RuleDelayed", - "SHCHcy", - "SHcy", - "SOFTcy", - "Sacute", - "Sc", - "Scaron", - "Scedil", - "Scirc", - "Scy", - "Sfr", - "ShortDownArrow", - "ShortLeftArrow", - "ShortRightArrow", - "ShortUpArrow", - "Sigma", - "SmallCircle", - "Sopf", - "Sqrt", - "Square", - "SquareIntersection", - "SquareSubset", - "SquareSubsetEqual", - "SquareSuperset", - "SquareSupersetEqual", - "SquareUnion", - "Sscr", - "Star", - "Sub", - "Subset", - "SubsetEqual", - "Succeeds", - "SucceedsEqual", - "SucceedsSlantEqual", - "SucceedsTilde", - "SuchThat", - "Sum", - "Sup", - "Superset", - "SupersetEqual", - "Supset", - "THORN", - "TRADE", - "TSHcy", - "TScy", - "Tab", - "Tau", - "Tcaron", - "Tcedil", - "Tcy", - "Tfr", - "Therefore", - "Theta", - "ThickSpace", - "ThinSpace", - "Tilde", - "TildeEqual", - "TildeFullEqual", - "TildeTilde", - "Topf", - "TripleDot", - "Tscr", - "Tstrok", - "Uacute", - "Uarr", - "Uarrocir", - "Ubrcy", - "Ubreve", - "Ucirc", - "Ucy", - "Udblac", - "Ufr", - "Ugrave", - "Umacr", - "UnderBar", - "UnderBrace", - "UnderBracket", - "UnderParenthesis", - "Union", - "UnionPlus", - "Uogon", - "Uopf", - "UpArrow", - "UpArrowBar", - "UpArrowDownArrow", - "UpDownArrow", - "UpEquilibrium", - "UpTee", - "UpTeeArrow", - "Uparrow", - "Updownarrow", - "UpperLeftArrow", - "UpperRightArrow", - "Upsi", - "Upsilon", - "Uring", - "Uscr", - "Utilde", - "Uuml", - "VDash", - "Vbar", - "Vcy", - "Vdash", - "Vdashl", - "Vee", - "Verbar", - "Vert", - "VerticalBar", - "VerticalLine", - "VerticalSeparator", - "VerticalTilde", - "VeryThinSpace", - "Vfr", - "Vopf", - "Vscr", - "Vvdash", - "Wcirc", - "Wedge", - "Wfr", - "Wopf", - "Wscr", - "Xfr", - "Xi", - "Xopf", - "Xscr", - "YAcy", - "YIcy", - "YUcy", - "Yacute", - "Ycirc", - "Ycy", - "Yfr", - "Yopf", - "Yscr", - "Yuml", - "ZHcy", - "Zacute", - "Zcaron", - "Zcy", - "Zdot", - "ZeroWidthSpace", - "Zeta", - "Zfr", - "Zopf", - "Zscr", - "aacute", - "abreve", - "ac", - "acE", - "acd", - "acirc", - "acute", - "acy", - "aelig", - "af", - "afr", - "agrave", - "alefsym", - "aleph", - "alpha", - "amacr", - "amalg", - "amp", - "and", - "andand", - "andd", - "andslope", - "andv", - "ang", - "ange", - "angle", - "angmsd", - "angmsdaa", - "angmsdab", - "angmsdac", - "angmsdad", - "angmsdae", - "angmsdaf", - "angmsdag", - "angmsdah", - "angrt", - "angrtvb", - "angrtvbd", - "angsph", - "angst", - "angzarr", - "aogon", - "aopf", - "ap", - "apE", - "apacir", - "ape", - "apid", - "apos", - "approx", - "approxeq", - "aring", - "ascr", - "ast", - "asymp", - "asympeq", - "atilde", - "auml", - "awconint", - "awint", - "bNot", - "backcong", - "backepsilon", - "backprime", - "backsim", - "backsimeq", - "barvee", - "barwed", - "barwedge", - "bbrk", - "bbrktbrk", - "bcong", - "bcy", - "bdquo", - "becaus", - "because", - "bemptyv", - "bepsi", - "bernou", - "beta", - "beth", - "between", - "bfr", - "bigcap", - "bigcirc", - "bigcup", - "bigodot", - "bigoplus", - "bigotimes", - "bigsqcup", - "bigstar", - "bigtriangledown", - "bigtriangleup", - "biguplus", - "bigvee", - "bigwedge", - "bkarow", - "blacklozenge", - "blacksquare", - "blacktriangle", - "blacktriangledown", - "blacktriangleleft", - "blacktriangleright", - "blank", - "blk12", - "blk14", - "blk34", - "block", - "bne", - "bnequiv", - "bnot", - "bopf", - "bot", - "bottom", - "bowtie", - "boxDL", - "boxDR", - "boxDl", - "boxDr", - "boxH", - "boxHD", - "boxHU", - "boxHd", - "boxHu", - "boxUL", - "boxUR", - "boxUl", - "boxUr", - "boxV", - "boxVH", - "boxVL", - "boxVR", - "boxVh", - "boxVl", - "boxVr", - "boxbox", - "boxdL", - "boxdR", - "boxdl", - "boxdr", - "boxh", - "boxhD", - "boxhU", - "boxhd", - "boxhu", - "boxminus", - "boxplus", - "boxtimes", - "boxuL", - "boxuR", - "boxul", - "boxur", - "boxv", - "boxvH", - "boxvL", - "boxvR", - "boxvh", - "boxvl", - "boxvr", - "bprime", - "breve", - "brvbar", - "bscr", - "bsemi", - "bsim", - "bsime", - "bsol", - "bsolb", - "bsolhsub", - "bull", - "bullet", - "bump", - "bumpE", - "bumpe", - "bumpeq", - "cacute", - "cap", - "capand", - "capbrcup", - "capcap", - "capcup", - "capdot", - "caps", - "caret", - "caron", - "ccaps", - "ccaron", - "ccedil", - "ccirc", - "ccups", - "ccupssm", - "cdot", - "cedil", - "cemptyv", - "cent", - "centerdot", - "cfr", - "chcy", - "check", - "checkmark", - "chi", - "cir", - "cirE", - "circ", - "circeq", - "circlearrowleft", - "circlearrowright", - "circledR", - "circledS", - "circledast", - "circledcirc", - "circleddash", - "cire", - "cirfnint", - "cirmid", - "cirscir", - "clubs", - "clubsuit", - "colon", - "colone", - "coloneq", - "comma", - "commat", - "comp", - "compfn", - "complement", - "complexes", - "cong", - "congdot", - "conint", - "copf", - "coprod", - "copy", - "copysr", - "crarr", - "cross", - "cscr", - "csub", - "csube", - "csup", - "csupe", - "ctdot", - "cudarrl", - "cudarrr", - "cuepr", - "cuesc", - "cularr", - "cularrp", - "cup", - "cupbrcap", - "cupcap", - "cupcup", - "cupdot", - "cupor", - "cups", - "curarr", - "curarrm", - "curlyeqprec", - "curlyeqsucc", - "curlyvee", - "curlywedge", - "curren", - "curvearrowleft", - "curvearrowright", - "cuvee", - "cuwed", - "cwconint", - "cwint", - "cylcty", - "dArr", - "dHar", - "dagger", - "daleth", - "darr", - "dash", - "dashv", - "dbkarow", - "dblac", - "dcaron", - "dcy", - "dd", - "ddagger", - "ddarr", - "ddotseq", - "deg", - "delta", - "demptyv", - "dfisht", - "dfr", - "dharl", - "dharr", - "diam", - "diamond", - "diamondsuit", - "diams", - "die", - "digamma", - "disin", - "div", - "divide", - "divideontimes", - "divonx", - "djcy", - "dlcorn", - "dlcrop", - "dollar", - "dopf", - "dot", - "doteq", - "doteqdot", - "dotminus", - "dotplus", - "dotsquare", - "doublebarwedge", - "downarrow", - "downdownarrows", - "downharpoonleft", - "downharpoonright", - "drbkarow", - "drcorn", - "drcrop", - "dscr", - "dscy", - "dsol", - "dstrok", - "dtdot", - "dtri", - "dtrif", - "duarr", - "duhar", - "dwangle", - "dzcy", - "dzigrarr", - "eDDot", - "eDot", - "eacute", - "easter", - "ecaron", - "ecir", - "ecirc", - "ecolon", - "ecy", - "edot", - "ee", - "efDot", - "efr", - "eg", - "egrave", - "egs", - "egsdot", - "el", - "elinters", - "ell", - "els", - "elsdot", - "emacr", - "empty", - "emptyset", - "emptyv", - "emsp", - "emsp13", - "emsp14", - "eng", - "ensp", - "eogon", - "eopf", - "epar", - "eparsl", - "eplus", - "epsi", - "epsilon", - "epsiv", - "eqcirc", - "eqcolon", - "eqsim", - "eqslantgtr", - "eqslantless", - "equals", - "equest", - "equiv", - "equivDD", - "eqvparsl", - "erDot", - "erarr", - "escr", - "esdot", - "esim", - "eta", - "eth", - "euml", - "euro", - "excl", - "exist", - "expectation", - "exponentiale", - "fallingdotseq", - "fcy", - "female", - "ffilig", - "fflig", - "ffllig", - "ffr", - "filig", - "fjlig", - "flat", - "fllig", - "fltns", - "fnof", - "fopf", - "forall", - "fork", - "forkv", - "fpartint", - "frac12", - "frac13", - "frac14", - "frac15", - "frac16", - "frac18", - "frac23", - "frac25", - "frac34", - "frac35", - "frac38", - "frac45", - "frac56", - "frac58", - "frac78", - "frasl", - "frown", - "fscr", - "gE", - "gEl", - "gacute", - "gamma", - "gammad", - "gap", - "gbreve", - "gcirc", - "gcy", - "gdot", - "ge", - "gel", - "geq", - "geqq", - "geqslant", - "ges", - "gescc", - "gesdot", - "gesdoto", - "gesdotol", - "gesl", - "gesles", - "gfr", - "gg", - "ggg", - "gimel", - "gjcy", - "gl", - "glE", - "gla", - "glj", - "gnE", - "gnap", - "gnapprox", - "gne", - "gneq", - "gneqq", - "gnsim", - "gopf", - "grave", - "gscr", - "gsim", - "gsime", - "gsiml", - "gt", - "gtcc", - "gtcir", - "gtdot", - "gtlPar", - "gtquest", - "gtrapprox", - "gtrarr", - "gtrdot", - "gtreqless", - "gtreqqless", - "gtrless", - "gtrsim", - "gvertneqq", - "gvnE", - "hArr", - "hairsp", - "half", - "hamilt", - "hardcy", - "harr", - "harrcir", - "harrw", - "hbar", - "hcirc", - "hearts", - "heartsuit", - "hellip", - "hercon", - "hfr", - "hksearow", - "hkswarow", - "hoarr", - "homtht", - "hookleftarrow", - "hookrightarrow", - "hopf", - "horbar", - "hscr", - "hslash", - "hstrok", - "hybull", - "hyphen", - "iacute", - "ic", - "icirc", - "icy", - "iecy", - "iexcl", - "iff", - "ifr", - "igrave", - "ii", - "iiiint", - "iiint", - "iinfin", - "iiota", - "ijlig", - "imacr", - "image", - "imagline", - "imagpart", - "imath", - "imof", - "imped", - "in", - "incare", - "infin", - "infintie", - "inodot", - "int", - "intcal", - "integers", - "intercal", - "intlarhk", - "intprod", - "iocy", - "iogon", - "iopf", - "iota", - "iprod", - "iquest", - "iscr", - "isin", - "isinE", - "isindot", - "isins", - "isinsv", - "isinv", - "it", - "itilde", - "iukcy", - "iuml", - "jcirc", - "jcy", - "jfr", - "jmath", - "jopf", - "jscr", - "jsercy", - "jukcy", - "kappa", - "kappav", - "kcedil", - "kcy", - "kfr", - "kgreen", - "khcy", - "kjcy", - "kopf", - "kscr", - "lAarr", - "lArr", - "lAtail", - "lBarr", - "lE", - "lEg", - "lHar", - "lacute", - "laemptyv", - "lagran", - "lambda", - "lang", - "langd", - "langle", - "lap", - "laquo", - "larr", - "larrb", - "larrbfs", - "larrfs", - "larrhk", - "larrlp", - "larrpl", - "larrsim", - "larrtl", - "lat", - "latail", - "late", - "lates", - "lbarr", - "lbbrk", - "lbrace", - "lbrack", - "lbrke", - "lbrksld", - "lbrkslu", - "lcaron", - "lcedil", - "lceil", - "lcub", - "lcy", - "ldca", - "ldquo", - "ldquor", - "ldrdhar", - "ldrushar", - "ldsh", - "le", - "leftarrow", - "leftarrowtail", - "leftharpoondown", - "leftharpoonup", - "leftleftarrows", - "leftrightarrow", - "leftrightarrows", - "leftrightharpoons", - "leftrightsquigarrow", - "leftthreetimes", - "leg", - "leq", - "leqq", - "leqslant", - "les", - "lescc", - "lesdot", - "lesdoto", - "lesdotor", - "lesg", - "lesges", - "lessapprox", - "lessdot", - "lesseqgtr", - "lesseqqgtr", - "lessgtr", - "lesssim", - "lfisht", - "lfloor", - "lfr", - "lg", - "lgE", - "lhard", - "lharu", - "lharul", - "lhblk", - "ljcy", - "ll", - "llarr", - "llcorner", - "llhard", - "lltri", - "lmidot", - "lmoust", - "lmoustache", - "lnE", - "lnap", - "lnapprox", - "lne", - "lneq", - "lneqq", - "lnsim", - "loang", - "loarr", - "lobrk", - "longleftarrow", - "longleftrightarrow", - "longmapsto", - "longrightarrow", - "looparrowleft", - "looparrowright", - "lopar", - "lopf", - "loplus", - "lotimes", - "lowast", - "lowbar", - "loz", - "lozenge", - "lozf", - "lpar", - "lparlt", - "lrarr", - "lrcorner", - "lrhar", - "lrhard", - "lrm", - "lrtri", - "lsaquo", - "lscr", - "lsh", - "lsim", - "lsime", - "lsimg", - "lsqb", - "lsquo", - "lsquor", - "lstrok", - "lt", - "ltcc", - "ltcir", - "ltdot", - "lthree", - "ltimes", - "ltlarr", - "ltquest", - "ltrPar", - "ltri", - "ltrie", - "ltrif", - "lurdshar", - "luruhar", - "lvertneqq", - "lvnE", - "mDDot", - "macr", - "male", - "malt", - "maltese", - "map", - "mapsto", - "mapstodown", - "mapstoleft", - "mapstoup", - "marker", - "mcomma", - "mcy", - "mdash", - "measuredangle", - "mfr", - "mho", - "micro", - "mid", - "midast", - "midcir", - "middot", - "minus", - "minusb", - "minusd", - "minusdu", - "mlcp", - "mldr", - "mnplus", - "models", - "mopf", - "mp", - "mscr", - "mstpos", - "mu", - "multimap", - "mumap", - "nGg", - "nGt", - "nGtv", - "nLeftarrow", - "nLeftrightarrow", - "nLl", - "nLt", - "nLtv", - "nRightarrow", - "nVDash", - "nVdash", - "nabla", - "nacute", - "nang", - "nap", - "napE", - "napid", - "napos", - "napprox", - "natur", - "natural", - "naturals", - "nbsp", - "nbump", - "nbumpe", - "ncap", - "ncaron", - "ncedil", - "ncong", - "ncongdot", - "ncup", - "ncy", - "ndash", - "ne", - "neArr", - "nearhk", - "nearr", - "nearrow", - "nedot", - "nequiv", - "nesear", - "nesim", - "nexist", - "nexists", - "nfr", - "ngE", - "nge", - "ngeq", - "ngeqq", - "ngeqslant", - "nges", - "ngsim", - "ngt", - "ngtr", - "nhArr", - "nharr", - "nhpar", - "ni", - "nis", - "nisd", - "niv", - "njcy", - "nlArr", - "nlE", - "nlarr", - "nldr", - "nle", - "nleftarrow", - "nleftrightarrow", - "nleq", - "nleqq", - "nleqslant", - "nles", - "nless", - "nlsim", - "nlt", - "nltri", - "nltrie", - "nmid", - "nopf", - "not", - "notin", - "notinE", - "notindot", - "notinva", - "notinvb", - "notinvc", - "notni", - "notniva", - "notnivb", - "notnivc", - "npar", - "nparallel", - "nparsl", - "npart", - "npolint", - "npr", - "nprcue", - "npre", - "nprec", - "npreceq", - "nrArr", - "nrarr", - "nrarrc", - "nrarrw", - "nrightarrow", - "nrtri", - "nrtrie", - "nsc", - "nsccue", - "nsce", - "nscr", - "nshortmid", - "nshortparallel", - "nsim", - "nsime", - "nsimeq", - "nsmid", - "nspar", - "nsqsube", - "nsqsupe", - "nsub", - "nsubE", - "nsube", - "nsubset", - "nsubseteq", - "nsubseteqq", - "nsucc", - "nsucceq", - "nsup", - "nsupE", - "nsupe", - "nsupset", - "nsupseteq", - "nsupseteqq", - "ntgl", - "ntilde", - "ntlg", - "ntriangleleft", - "ntrianglelefteq", - "ntriangleright", - "ntrianglerighteq", - "nu", - "num", - "numero", - "numsp", - "nvDash", - "nvHarr", - "nvap", - "nvdash", - "nvge", - "nvgt", - "nvinfin", - "nvlArr", - "nvle", - "nvlt", - "nvltrie", - "nvrArr", - "nvrtrie", - "nvsim", - "nwArr", - "nwarhk", - "nwarr", - "nwarrow", - "nwnear", - "oS", - "oacute", - "oast", - "ocir", - "ocirc", - "ocy", - "odash", - "odblac", - "odiv", - "odot", - "odsold", - "oelig", - "ofcir", - "ofr", - "ogon", - "ograve", - "ogt", - "ohbar", - "ohm", - "oint", - "olarr", - "olcir", - "olcross", - "oline", - "olt", - "omacr", - "omega", - "omicron", - "omid", - "ominus", - "oopf", - "opar", - "operp", - "oplus", - "or", - "orarr", - "ord", - "order", - "orderof", - "ordf", - "ordm", - "origof", - "oror", - "orslope", - "orv", - "oscr", - "oslash", - "osol", - "otilde", - "otimes", - "otimesas", - "ouml", - "ovbar", - "par", - "para", - "parallel", - "parsim", - "parsl", - "part", - "pcy", - "percnt", - "period", - "permil", - "perp", - "pertenk", - "pfr", - "phi", - "phiv", - "phmmat", - "phone", - "pi", - "pitchfork", - "piv", - "planck", - "planckh", - "plankv", - "plus", - "plusacir", - "plusb", - "pluscir", - "plusdo", - "plusdu", - "pluse", - "plusmn", - "plussim", - "plustwo", - "pm", - "pointint", - "popf", - "pound", - "pr", - "prE", - "prap", - "prcue", - "pre", - "prec", - "precapprox", - "preccurlyeq", - "preceq", - "precnapprox", - "precneqq", - "precnsim", - "precsim", - "prime", - "primes", - "prnE", - "prnap", - "prnsim", - "prod", - "profalar", - "profline", - "profsurf", - "prop", - "propto", - "prsim", - "prurel", - "pscr", - "psi", - "puncsp", - "qfr", - "qint", - "qopf", - "qprime", - "qscr", - "quaternions", - "quatint", - "quest", - "questeq", - "quot", - "rAarr", - "rArr", - "rAtail", - "rBarr", - "rHar", - "race", - "racute", - "radic", - "raemptyv", - "rang", - "rangd", - "range", - "rangle", - "raquo", - "rarr", - "rarrap", - "rarrb", - "rarrbfs", - "rarrc", - "rarrfs", - "rarrhk", - "rarrlp", - "rarrpl", - "rarrsim", - "rarrtl", - "rarrw", - "ratail", - "ratio", - "rationals", - "rbarr", - "rbbrk", - "rbrace", - "rbrack", - "rbrke", - "rbrksld", - "rbrkslu", - "rcaron", - "rcedil", - "rceil", - "rcub", - "rcy", - "rdca", - "rdldhar", - "rdquo", - "rdquor", - "rdsh", - "real", - "realine", - "realpart", - "reals", - "rect", - "reg", - "rfisht", - "rfloor", - "rfr", - "rhard", - "rharu", - "rharul", - "rho", - "rhov", - "rightarrow", - "rightarrowtail", - "rightharpoondown", - "rightharpoonup", - "rightleftarrows", - "rightleftharpoons", - "rightrightarrows", - "rightsquigarrow", - "rightthreetimes", - "ring", - "risingdotseq", - "rlarr", - "rlhar", - "rlm", - "rmoust", - "rmoustache", - "rnmid", - "roang", - "roarr", - "robrk", - "ropar", - "ropf", - "roplus", - "rotimes", - "rpar", - "rpargt", - "rppolint", - "rrarr", - "rsaquo", - "rscr", - "rsh", - "rsqb", - "rsquo", - "rsquor", - "rthree", - "rtimes", - "rtri", - "rtrie", - "rtrif", - "rtriltri", - "ruluhar", - "rx", - "sacute", - "sbquo", - "sc", - "scE", - "scap", - "scaron", - "sccue", - "sce", - "scedil", - "scirc", - "scnE", - "scnap", - "scnsim", - "scpolint", - "scsim", - "scy", - "sdot", - "sdotb", - "sdote", - "seArr", - "searhk", - "searr", - "searrow", - "sect", - "semi", - "seswar", - "setminus", - "setmn", - "sext", - "sfr", - "sfrown", - "sharp", - "shchcy", - "shcy", - "shortmid", - "shortparallel", - "shy", - "sigma", - "sigmaf", - "sigmav", - "sim", - "simdot", - "sime", - "simeq", - "simg", - "simgE", - "siml", - "simlE", - "simne", - "simplus", - "simrarr", - "slarr", - "smallsetminus", - "smashp", - "smeparsl", - "smid", - "smile", - "smt", - "smte", - "smtes", - "softcy", - "sol", - "solb", - "solbar", - "sopf", - "spades", - "spadesuit", - "spar", - "sqcap", - "sqcaps", - "sqcup", - "sqcups", - "sqsub", - "sqsube", - "sqsubset", - "sqsubseteq", - "sqsup", - "sqsupe", - "sqsupset", - "sqsupseteq", - "squ", - "square", - "squarf", - "squf", - "srarr", - "sscr", - "ssetmn", - "ssmile", - "sstarf", - "star", - "starf", - "straightepsilon", - "straightphi", - "strns", - "sub", - "subE", - "subdot", - "sube", - "subedot", - "submult", - "subnE", - "subne", - "subplus", - "subrarr", - "subset", - "subseteq", - "subseteqq", - "subsetneq", - "subsetneqq", - "subsim", - "subsub", - "subsup", - "succ", - "succapprox", - "succcurlyeq", - "succeq", - "succnapprox", - "succneqq", - "succnsim", - "succsim", - "sum", - "sung", - "sup", - "sup1", - "sup2", - "sup3", - "supE", - "supdot", - "supdsub", - "supe", - "supedot", - "suphsol", - "suphsub", - "suplarr", - "supmult", - "supnE", - "supne", - "supplus", - "supset", - "supseteq", - "supseteqq", - "supsetneq", - "supsetneqq", - "supsim", - "supsub", - "supsup", - "swArr", - "swarhk", - "swarr", - "swarrow", - "swnwar", - "szlig", - "target", - "tau", - "tbrk", - "tcaron", - "tcedil", - "tcy", - "tdot", - "telrec", - "tfr", - "there4", - "therefore", - "theta", - "thetasym", - "thetav", - "thickapprox", - "thicksim", - "thinsp", - "thkap", - "thksim", - "thorn", - "tilde", - "times", - "timesb", - "timesbar", - "timesd", - "tint", - "toea", - "top", - "topbot", - "topcir", - "topf", - "topfork", - "tosa", - "tprime", - "trade", - "triangle", - "triangledown", - "triangleleft", - "trianglelefteq", - "triangleq", - "triangleright", - "trianglerighteq", - "tridot", - "trie", - "triminus", - "triplus", - "trisb", - "tritime", - "trpezium", - "tscr", - "tscy", - "tshcy", - "tstrok", - "twixt", - "twoheadleftarrow", - "twoheadrightarrow", - "uArr", - "uHar", - "uacute", - "uarr", - "ubrcy", - "ubreve", - "ucirc", - "ucy", - "udarr", - "udblac", - "udhar", - "ufisht", - "ufr", - "ugrave", - "uharl", - "uharr", - "uhblk", - "ulcorn", - "ulcorner", - "ulcrop", - "ultri", - "umacr", - "uml", - "uogon", - "uopf", - "uparrow", - "updownarrow", - "upharpoonleft", - "upharpoonright", - "uplus", - "upsi", - "upsih", - "upsilon", - "upuparrows", - "urcorn", - "urcorner", - "urcrop", - "uring", - "urtri", - "uscr", - "utdot", - "utilde", - "utri", - "utrif", - "uuarr", - "uuml", - "uwangle", - "vArr", - "vBar", - "vBarv", - "vDash", - "vangrt", - "varepsilon", - "varkappa", - "varnothing", - "varphi", - "varpi", - "varpropto", - "varr", - "varrho", - "varsigma", - "varsubsetneq", - "varsubsetneqq", - "varsupsetneq", - "varsupsetneqq", - "vartheta", - "vartriangleleft", - "vartriangleright", - "vcy", - "vdash", - "vee", - "veebar", - "veeeq", - "vellip", - "verbar", - "vert", - "vfr", - "vltri", - "vnsub", - "vnsup", - "vopf", - "vprop", - "vrtri", - "vscr", - "vsubnE", - "vsubne", - "vsupnE", - "vsupne", - "vzigzag", - "wcirc", - "wedbar", - "wedge", - "wedgeq", - "weierp", - "wfr", - "wopf", - "wp", - "wr", - "wreath", - "wscr", - "xcap", - "xcirc", - "xcup", - "xdtri", - "xfr", - "xhArr", - "xharr", - "xi", - "xlArr", - "xlarr", - "xmap", - "xnis", - "xodot", - "xopf", - "xoplus", - "xotime", - "xrArr", - "xrarr", - "xscr", - "xsqcup", - "xuplus", - "xutri", - "xvee", - "xwedge", - "yacute", - "yacy", - "ycirc", - "ycy", - "yen", - "yfr", - "yicy", - "yopf", - "yscr", - "yucy", - "yuml", - "zacute", - "zcaron", - "zcy", - "zdot", - "zeetrf", - "zeta", - "zfr", - "zhcy", - "zigrarr", - "zopf", - "zscr", - "zwj", - "zwnj", - ]; - -const ENTITY_VALUES: [&'static str; 2125] = [ - "\u{00C6}", - "\u{0026}", - "\u{00C1}", - "\u{0102}", - "\u{00C2}", - "\u{0410}", - "\u{1D504}", - "\u{00C0}", - "\u{0391}", - "\u{0100}", - "\u{2A53}", - "\u{0104}", - "\u{1D538}", - "\u{2061}", - "\u{00C5}", - "\u{1D49C}", - "\u{2254}", - "\u{00C3}", - "\u{00C4}", - "\u{2216}", - "\u{2AE7}", - "\u{2306}", - "\u{0411}", - "\u{2235}", - "\u{212C}", - "\u{0392}", - "\u{1D505}", - "\u{1D539}", - "\u{02D8}", - "\u{212C}", - "\u{224E}", - "\u{0427}", - "\u{00A9}", - "\u{0106}", - "\u{22D2}", - "\u{2145}", - "\u{212D}", - "\u{010C}", - "\u{00C7}", - "\u{0108}", - "\u{2230}", - "\u{010A}", - "\u{00B8}", - "\u{00B7}", - "\u{212D}", - "\u{03A7}", - "\u{2299}", - "\u{2296}", - "\u{2295}", - "\u{2297}", - "\u{2232}", - "\u{201D}", - "\u{2019}", - "\u{2237}", - "\u{2A74}", - "\u{2261}", - "\u{222F}", - "\u{222E}", - "\u{2102}", - "\u{2210}", - "\u{2233}", - "\u{2A2F}", - "\u{1D49E}", - "\u{22D3}", - "\u{224D}", - "\u{2145}", - "\u{2911}", - "\u{0402}", - "\u{0405}", - "\u{040F}", - "\u{2021}", - "\u{21A1}", - "\u{2AE4}", - "\u{010E}", - "\u{0414}", - "\u{2207}", - "\u{0394}", - "\u{1D507}", - "\u{00B4}", - "\u{02D9}", - "\u{02DD}", - "\u{0060}", - "\u{02DC}", - "\u{22C4}", - "\u{2146}", - "\u{1D53B}", - "\u{00A8}", - "\u{20DC}", - "\u{2250}", - "\u{222F}", - "\u{00A8}", - "\u{21D3}", - "\u{21D0}", - "\u{21D4}", - "\u{2AE4}", - "\u{27F8}", - "\u{27FA}", - "\u{27F9}", - "\u{21D2}", - "\u{22A8}", - "\u{21D1}", - "\u{21D5}", - "\u{2225}", - "\u{2193}", - "\u{2913}", - "\u{21F5}", - "\u{0311}", - "\u{2950}", - "\u{295E}", - "\u{21BD}", - "\u{2956}", - "\u{295F}", - "\u{21C1}", - "\u{2957}", - "\u{22A4}", - "\u{21A7}", - "\u{21D3}", - "\u{1D49F}", - "\u{0110}", - "\u{014A}", - "\u{00D0}", - "\u{00C9}", - "\u{011A}", - "\u{00CA}", - "\u{042D}", - "\u{0116}", - "\u{1D508}", - "\u{00C8}", - "\u{2208}", - "\u{0112}", - "\u{25FB}", - "\u{25AB}", - "\u{0118}", - "\u{1D53C}", - "\u{0395}", - "\u{2A75}", - "\u{2242}", - "\u{21CC}", - "\u{2130}", - "\u{2A73}", - "\u{0397}", - "\u{00CB}", - "\u{2203}", - "\u{2147}", - "\u{0424}", - "\u{1D509}", - "\u{25FC}", - "\u{25AA}", - "\u{1D53D}", - "\u{2200}", - "\u{2131}", - "\u{2131}", - "\u{0403}", - "\u{003E}", - "\u{0393}", - "\u{03DC}", - "\u{011E}", - "\u{0122}", - "\u{011C}", - "\u{0413}", - "\u{0120}", - "\u{1D50A}", - "\u{22D9}", - "\u{1D53E}", - "\u{2265}", - "\u{22DB}", - "\u{2267}", - "\u{2AA2}", - "\u{2277}", - "\u{2A7E}", - "\u{2273}", - "\u{1D4A2}", - "\u{226B}", - "\u{042A}", - "\u{02C7}", - "\u{005E}", - "\u{0124}", - "\u{210C}", - "\u{210B}", - "\u{210D}", - "\u{2500}", - "\u{210B}", - "\u{0126}", - "\u{224E}", - "\u{224F}", - "\u{0415}", - "\u{0132}", - "\u{0401}", - "\u{00CD}", - "\u{00CE}", - "\u{0418}", - "\u{0130}", - "\u{2111}", - "\u{00CC}", - "\u{2111}", - "\u{012A}", - "\u{2148}", - "\u{21D2}", - "\u{222C}", - "\u{222B}", - "\u{22C2}", - "\u{2063}", - "\u{2062}", - "\u{012E}", - "\u{1D540}", - "\u{0399}", - "\u{2110}", - "\u{0128}", - "\u{0406}", - "\u{00CF}", - "\u{0134}", - "\u{0419}", - "\u{1D50D}", - "\u{1D541}", - "\u{1D4A5}", - "\u{0408}", - "\u{0404}", - "\u{0425}", - "\u{040C}", - "\u{039A}", - "\u{0136}", - "\u{041A}", - "\u{1D50E}", - "\u{1D542}", - "\u{1D4A6}", - "\u{0409}", - "\u{003C}", - "\u{0139}", - "\u{039B}", - "\u{27EA}", - "\u{2112}", - "\u{219E}", - "\u{013D}", - "\u{013B}", - "\u{041B}", - "\u{27E8}", - "\u{2190}", - "\u{21E4}", - "\u{21C6}", - "\u{2308}", - "\u{27E6}", - "\u{2961}", - "\u{21C3}", - "\u{2959}", - "\u{230A}", - "\u{2194}", - "\u{294E}", - "\u{22A3}", - "\u{21A4}", - "\u{295A}", - "\u{22B2}", - "\u{29CF}", - "\u{22B4}", - "\u{2951}", - "\u{2960}", - "\u{21BF}", - "\u{2958}", - "\u{21BC}", - "\u{2952}", - "\u{21D0}", - "\u{21D4}", - "\u{22DA}", - "\u{2266}", - "\u{2276}", - "\u{2AA1}", - "\u{2A7D}", - "\u{2272}", - "\u{1D50F}", - "\u{22D8}", - "\u{21DA}", - "\u{013F}", - "\u{27F5}", - "\u{27F7}", - "\u{27F6}", - "\u{27F8}", - "\u{27FA}", - "\u{27F9}", - "\u{1D543}", - "\u{2199}", - "\u{2198}", - "\u{2112}", - "\u{21B0}", - "\u{0141}", - "\u{226A}", - "\u{2905}", - "\u{041C}", - "\u{205F}", - "\u{2133}", - "\u{1D510}", - "\u{2213}", - "\u{1D544}", - "\u{2133}", - "\u{039C}", - "\u{040A}", - "\u{0143}", - "\u{0147}", - "\u{0145}", - "\u{041D}", - "\u{200B}", - "\u{200B}", - "\u{200B}", - "\u{200B}", - "\u{226B}", - "\u{226A}", - "\u{000A}", - "\u{1D511}", - "\u{2060}", - "\u{00A0}", - "\u{2115}", - "\u{2AEC}", - "\u{2262}", - "\u{226D}", - "\u{2226}", - "\u{2209}", - "\u{2260}", - "\u{2242}\u{0338}", - "\u{2204}", - "\u{226F}", - "\u{2271}", - "\u{2267}\u{0338}", - "\u{226B}\u{0338}", - "\u{2279}", - "\u{2A7E}\u{0338}", - "\u{2275}", - "\u{224E}\u{0338}", - "\u{224F}\u{0338}", - "\u{22EA}", - "\u{29CF}\u{0338}", - "\u{22EC}", - "\u{226E}", - "\u{2270}", - "\u{2278}", - "\u{226A}\u{0338}", - "\u{2A7D}\u{0338}", - "\u{2274}", - "\u{2AA2}\u{0338}", - "\u{2AA1}\u{0338}", - "\u{2280}", - "\u{2AAF}\u{0338}", - "\u{22E0}", - "\u{220C}", - "\u{22EB}", - "\u{29D0}\u{0338}", - "\u{22ED}", - "\u{228F}\u{0338}", - "\u{22E2}", - "\u{2290}\u{0338}", - "\u{22E3}", - "\u{2282}\u{20D2}", - "\u{2288}", - "\u{2281}", - "\u{2AB0}\u{0338}", - "\u{22E1}", - "\u{227F}\u{0338}", - "\u{2283}\u{20D2}", - "\u{2289}", - "\u{2241}", - "\u{2244}", - "\u{2247}", - "\u{2249}", - "\u{2224}", - "\u{1D4A9}", - "\u{00D1}", - "\u{039D}", - "\u{0152}", - "\u{00D3}", - "\u{00D4}", - "\u{041E}", - "\u{0150}", - "\u{1D512}", - "\u{00D2}", - "\u{014C}", - "\u{03A9}", - "\u{039F}", - "\u{1D546}", - "\u{201C}", - "\u{2018}", - "\u{2A54}", - "\u{1D4AA}", - "\u{00D8}", - "\u{00D5}", - "\u{2A37}", - "\u{00D6}", - "\u{203E}", - "\u{23DE}", - "\u{23B4}", - "\u{23DC}", - "\u{2202}", - "\u{041F}", - "\u{1D513}", - "\u{03A6}", - "\u{03A0}", - "\u{00B1}", - "\u{210C}", - "\u{2119}", - "\u{2ABB}", - "\u{227A}", - "\u{2AAF}", - "\u{227C}", - "\u{227E}", - "\u{2033}", - "\u{220F}", - "\u{2237}", - "\u{221D}", - "\u{1D4AB}", - "\u{03A8}", - "\u{0022}", - "\u{1D514}", - "\u{211A}", - "\u{1D4AC}", - "\u{2910}", - "\u{00AE}", - "\u{0154}", - "\u{27EB}", - "\u{21A0}", - "\u{2916}", - "\u{0158}", - "\u{0156}", - "\u{0420}", - "\u{211C}", - "\u{220B}", - "\u{21CB}", - "\u{296F}", - "\u{211C}", - "\u{03A1}", - "\u{27E9}", - "\u{2192}", - "\u{21E5}", - "\u{21C4}", - "\u{2309}", - "\u{27E7}", - "\u{295D}", - "\u{21C2}", - "\u{2955}", - "\u{230B}", - "\u{22A2}", - "\u{21A6}", - "\u{295B}", - "\u{22B3}", - "\u{29D0}", - "\u{22B5}", - "\u{294F}", - "\u{295C}", - "\u{21BE}", - "\u{2954}", - "\u{21C0}", - "\u{2953}", - "\u{21D2}", - "\u{211D}", - "\u{2970}", - "\u{21DB}", - "\u{211B}", - "\u{21B1}", - "\u{29F4}", - "\u{0429}", - "\u{0428}", - "\u{042C}", - "\u{015A}", - "\u{2ABC}", - "\u{0160}", - "\u{015E}", - "\u{015C}", - "\u{0421}", - "\u{1D516}", - "\u{2193}", - "\u{2190}", - "\u{2192}", - "\u{2191}", - "\u{03A3}", - "\u{2218}", - "\u{1D54A}", - "\u{221A}", - "\u{25A1}", - "\u{2293}", - "\u{228F}", - "\u{2291}", - "\u{2290}", - "\u{2292}", - "\u{2294}", - "\u{1D4AE}", - "\u{22C6}", - "\u{22D0}", - "\u{22D0}", - "\u{2286}", - "\u{227B}", - "\u{2AB0}", - "\u{227D}", - "\u{227F}", - "\u{220B}", - "\u{2211}", - "\u{22D1}", - "\u{2283}", - "\u{2287}", - "\u{22D1}", - "\u{00DE}", - "\u{2122}", - "\u{040B}", - "\u{0426}", - "\u{0009}", - "\u{03A4}", - "\u{0164}", - "\u{0162}", - "\u{0422}", - "\u{1D517}", - "\u{2234}", - "\u{0398}", - "\u{205F}\u{200A}", - "\u{2009}", - "\u{223C}", - "\u{2243}", - "\u{2245}", - "\u{2248}", - "\u{1D54B}", - "\u{20DB}", - "\u{1D4AF}", - "\u{0166}", - "\u{00DA}", - "\u{219F}", - "\u{2949}", - "\u{040E}", - "\u{016C}", - "\u{00DB}", - "\u{0423}", - "\u{0170}", - "\u{1D518}", - "\u{00D9}", - "\u{016A}", - "\u{005F}", - "\u{23DF}", - "\u{23B5}", - "\u{23DD}", - "\u{22C3}", - "\u{228E}", - "\u{0172}", - "\u{1D54C}", - "\u{2191}", - "\u{2912}", - "\u{21C5}", - "\u{2195}", - "\u{296E}", - "\u{22A5}", - "\u{21A5}", - "\u{21D1}", - "\u{21D5}", - "\u{2196}", - "\u{2197}", - "\u{03D2}", - "\u{03A5}", - "\u{016E}", - "\u{1D4B0}", - "\u{0168}", - "\u{00DC}", - "\u{22AB}", - "\u{2AEB}", - "\u{0412}", - "\u{22A9}", - "\u{2AE6}", - "\u{22C1}", - "\u{2016}", - "\u{2016}", - "\u{2223}", - "\u{007C}", - "\u{2758}", - "\u{2240}", - "\u{200A}", - "\u{1D519}", - "\u{1D54D}", - "\u{1D4B1}", - "\u{22AA}", - "\u{0174}", - "\u{22C0}", - "\u{1D51A}", - "\u{1D54E}", - "\u{1D4B2}", - "\u{1D51B}", - "\u{039E}", - "\u{1D54F}", - "\u{1D4B3}", - "\u{042F}", - "\u{0407}", - "\u{042E}", - "\u{00DD}", - "\u{0176}", - "\u{042B}", - "\u{1D51C}", - "\u{1D550}", - "\u{1D4B4}", - "\u{0178}", - "\u{0416}", - "\u{0179}", - "\u{017D}", - "\u{0417}", - "\u{017B}", - "\u{200B}", - "\u{0396}", - "\u{2128}", - "\u{2124}", - "\u{1D4B5}", - "\u{00E1}", - "\u{0103}", - "\u{223E}", - "\u{223E}\u{0333}", - "\u{223F}", - "\u{00E2}", - "\u{00B4}", - "\u{0430}", - "\u{00E6}", - "\u{2061}", - "\u{1D51E}", - "\u{00E0}", - "\u{2135}", - "\u{2135}", - "\u{03B1}", - "\u{0101}", - "\u{2A3F}", - "\u{0026}", - "\u{2227}", - "\u{2A55}", - "\u{2A5C}", - "\u{2A58}", - "\u{2A5A}", - "\u{2220}", - "\u{29A4}", - "\u{2220}", - "\u{2221}", - "\u{29A8}", - "\u{29A9}", - "\u{29AA}", - "\u{29AB}", - "\u{29AC}", - "\u{29AD}", - "\u{29AE}", - "\u{29AF}", - "\u{221F}", - "\u{22BE}", - "\u{299D}", - "\u{2222}", - "\u{00C5}", - "\u{237C}", - "\u{0105}", - "\u{1D552}", - "\u{2248}", - "\u{2A70}", - "\u{2A6F}", - "\u{224A}", - "\u{224B}", - "\u{0027}", - "\u{2248}", - "\u{224A}", - "\u{00E5}", - "\u{1D4B6}", - "\u{002A}", - "\u{2248}", - "\u{224D}", - "\u{00E3}", - "\u{00E4}", - "\u{2233}", - "\u{2A11}", - "\u{2AED}", - "\u{224C}", - "\u{03F6}", - "\u{2035}", - "\u{223D}", - "\u{22CD}", - "\u{22BD}", - "\u{2305}", - "\u{2305}", - "\u{23B5}", - "\u{23B6}", - "\u{224C}", - "\u{0431}", - "\u{201E}", - "\u{2235}", - "\u{2235}", - "\u{29B0}", - "\u{03F6}", - "\u{212C}", - "\u{03B2}", - "\u{2136}", - "\u{226C}", - "\u{1D51F}", - "\u{22C2}", - "\u{25EF}", - "\u{22C3}", - "\u{2A00}", - "\u{2A01}", - "\u{2A02}", - "\u{2A06}", - "\u{2605}", - "\u{25BD}", - "\u{25B3}", - "\u{2A04}", - "\u{22C1}", - "\u{22C0}", - "\u{290D}", - "\u{29EB}", - "\u{25AA}", - "\u{25B4}", - "\u{25BE}", - "\u{25C2}", - "\u{25B8}", - "\u{2423}", - "\u{2592}", - "\u{2591}", - "\u{2593}", - "\u{2588}", - "\u{003D}\u{20E5}", - "\u{2261}\u{20E5}", - "\u{2310}", - "\u{1D553}", - "\u{22A5}", - "\u{22A5}", - "\u{22C8}", - "\u{2557}", - "\u{2554}", - "\u{2556}", - "\u{2553}", - "\u{2550}", - "\u{2566}", - "\u{2569}", - "\u{2564}", - "\u{2567}", - "\u{255D}", - "\u{255A}", - "\u{255C}", - "\u{2559}", - "\u{2551}", - "\u{256C}", - "\u{2563}", - "\u{2560}", - "\u{256B}", - "\u{2562}", - "\u{255F}", - "\u{29C9}", - "\u{2555}", - "\u{2552}", - "\u{2510}", - "\u{250C}", - "\u{2500}", - "\u{2565}", - "\u{2568}", - "\u{252C}", - "\u{2534}", - "\u{229F}", - "\u{229E}", - "\u{22A0}", - "\u{255B}", - "\u{2558}", - "\u{2518}", - "\u{2514}", - "\u{2502}", - "\u{256A}", - "\u{2561}", - "\u{255E}", - "\u{253C}", - "\u{2524}", - "\u{251C}", - "\u{2035}", - "\u{02D8}", - "\u{00A6}", - "\u{1D4B7}", - "\u{204F}", - "\u{223D}", - "\u{22CD}", - "\u{005C}", - "\u{29C5}", - "\u{27C8}", - "\u{2022}", - "\u{2022}", - "\u{224E}", - "\u{2AAE}", - "\u{224F}", - "\u{224F}", - "\u{0107}", - "\u{2229}", - "\u{2A44}", - "\u{2A49}", - "\u{2A4B}", - "\u{2A47}", - "\u{2A40}", - "\u{2229}\u{FE00}", - "\u{2041}", - "\u{02C7}", - "\u{2A4D}", - "\u{010D}", - "\u{00E7}", - "\u{0109}", - "\u{2A4C}", - "\u{2A50}", - "\u{010B}", - "\u{00B8}", - "\u{29B2}", - "\u{00A2}", - "\u{00B7}", - "\u{1D520}", - "\u{0447}", - "\u{2713}", - "\u{2713}", - "\u{03C7}", - "\u{25CB}", - "\u{29C3}", - "\u{02C6}", - "\u{2257}", - "\u{21BA}", - "\u{21BB}", - "\u{00AE}", - "\u{24C8}", - "\u{229B}", - "\u{229A}", - "\u{229D}", - "\u{2257}", - "\u{2A10}", - "\u{2AEF}", - "\u{29C2}", - "\u{2663}", - "\u{2663}", - "\u{003A}", - "\u{2254}", - "\u{2254}", - "\u{002C}", - "\u{0040}", - "\u{2201}", - "\u{2218}", - "\u{2201}", - "\u{2102}", - "\u{2245}", - "\u{2A6D}", - "\u{222E}", - "\u{1D554}", - "\u{2210}", - "\u{00A9}", - "\u{2117}", - "\u{21B5}", - "\u{2717}", - "\u{1D4B8}", - "\u{2ACF}", - "\u{2AD1}", - "\u{2AD0}", - "\u{2AD2}", - "\u{22EF}", - "\u{2938}", - "\u{2935}", - "\u{22DE}", - "\u{22DF}", - "\u{21B6}", - "\u{293D}", - "\u{222A}", - "\u{2A48}", - "\u{2A46}", - "\u{2A4A}", - "\u{228D}", - "\u{2A45}", - "\u{222A}\u{FE00}", - "\u{21B7}", - "\u{293C}", - "\u{22DE}", - "\u{22DF}", - "\u{22CE}", - "\u{22CF}", - "\u{00A4}", - "\u{21B6}", - "\u{21B7}", - "\u{22CE}", - "\u{22CF}", - "\u{2232}", - "\u{2231}", - "\u{232D}", - "\u{21D3}", - "\u{2965}", - "\u{2020}", - "\u{2138}", - "\u{2193}", - "\u{2010}", - "\u{22A3}", - "\u{290F}", - "\u{02DD}", - "\u{010F}", - "\u{0434}", - "\u{2146}", - "\u{2021}", - "\u{21CA}", - "\u{2A77}", - "\u{00B0}", - "\u{03B4}", - "\u{29B1}", - "\u{297F}", - "\u{1D521}", - "\u{21C3}", - "\u{21C2}", - "\u{22C4}", - "\u{22C4}", - "\u{2666}", - "\u{2666}", - "\u{00A8}", - "\u{03DD}", - "\u{22F2}", - "\u{00F7}", - "\u{00F7}", - "\u{22C7}", - "\u{22C7}", - "\u{0452}", - "\u{231E}", - "\u{230D}", - "\u{0024}", - "\u{1D555}", - "\u{02D9}", - "\u{2250}", - "\u{2251}", - "\u{2238}", - "\u{2214}", - "\u{22A1}", - "\u{2306}", - "\u{2193}", - "\u{21CA}", - "\u{21C3}", - "\u{21C2}", - "\u{2910}", - "\u{231F}", - "\u{230C}", - "\u{1D4B9}", - "\u{0455}", - "\u{29F6}", - "\u{0111}", - "\u{22F1}", - "\u{25BF}", - "\u{25BE}", - "\u{21F5}", - "\u{296F}", - "\u{29A6}", - "\u{045F}", - "\u{27FF}", - "\u{2A77}", - "\u{2251}", - "\u{00E9}", - "\u{2A6E}", - "\u{011B}", - "\u{2256}", - "\u{00EA}", - "\u{2255}", - "\u{044D}", - "\u{0117}", - "\u{2147}", - "\u{2252}", - "\u{1D522}", - "\u{2A9A}", - "\u{00E8}", - "\u{2A96}", - "\u{2A98}", - "\u{2A99}", - "\u{23E7}", - "\u{2113}", - "\u{2A95}", - "\u{2A97}", - "\u{0113}", - "\u{2205}", - "\u{2205}", - "\u{2205}", - "\u{2003}", - "\u{2004}", - "\u{2005}", - "\u{014B}", - "\u{2002}", - "\u{0119}", - "\u{1D556}", - "\u{22D5}", - "\u{29E3}", - "\u{2A71}", - "\u{03B5}", - "\u{03B5}", - "\u{03F5}", - "\u{2256}", - "\u{2255}", - "\u{2242}", - "\u{2A96}", - "\u{2A95}", - "\u{003D}", - "\u{225F}", - "\u{2261}", - "\u{2A78}", - "\u{29E5}", - "\u{2253}", - "\u{2971}", - "\u{212F}", - "\u{2250}", - "\u{2242}", - "\u{03B7}", - "\u{00F0}", - "\u{00EB}", - "\u{20AC}", - "\u{0021}", - "\u{2203}", - "\u{2130}", - "\u{2147}", - "\u{2252}", - "\u{0444}", - "\u{2640}", - "\u{FB03}", - "\u{FB00}", - "\u{FB04}", - "\u{1D523}", - "\u{FB01}", - "\u{0066}\u{006A}", - "\u{266D}", - "\u{FB02}", - "\u{25B1}", - "\u{0192}", - "\u{1D557}", - "\u{2200}", - "\u{22D4}", - "\u{2AD9}", - "\u{2A0D}", - "\u{00BD}", - "\u{2153}", - "\u{00BC}", - "\u{2155}", - "\u{2159}", - "\u{215B}", - "\u{2154}", - "\u{2156}", - "\u{00BE}", - "\u{2157}", - "\u{215C}", - "\u{2158}", - "\u{215A}", - "\u{215D}", - "\u{215E}", - "\u{2044}", - "\u{2322}", - "\u{1D4BB}", - "\u{2267}", - "\u{2A8C}", - "\u{01F5}", - "\u{03B3}", - "\u{03DD}", - "\u{2A86}", - "\u{011F}", - "\u{011D}", - "\u{0433}", - "\u{0121}", - "\u{2265}", - "\u{22DB}", - "\u{2265}", - "\u{2267}", - "\u{2A7E}", - "\u{2A7E}", - "\u{2AA9}", - "\u{2A80}", - "\u{2A82}", - "\u{2A84}", - "\u{22DB}\u{FE00}", - "\u{2A94}", - "\u{1D524}", - "\u{226B}", - "\u{22D9}", - "\u{2137}", - "\u{0453}", - "\u{2277}", - "\u{2A92}", - "\u{2AA5}", - "\u{2AA4}", - "\u{2269}", - "\u{2A8A}", - "\u{2A8A}", - "\u{2A88}", - "\u{2A88}", - "\u{2269}", - "\u{22E7}", - "\u{1D558}", - "\u{0060}", - "\u{210A}", - "\u{2273}", - "\u{2A8E}", - "\u{2A90}", - "\u{003E}", - "\u{2AA7}", - "\u{2A7A}", - "\u{22D7}", - "\u{2995}", - "\u{2A7C}", - "\u{2A86}", - "\u{2978}", - "\u{22D7}", - "\u{22DB}", - "\u{2A8C}", - "\u{2277}", - "\u{2273}", - "\u{2269}\u{FE00}", - "\u{2269}\u{FE00}", - "\u{21D4}", - "\u{200A}", - "\u{00BD}", - "\u{210B}", - "\u{044A}", - "\u{2194}", - "\u{2948}", - "\u{21AD}", - "\u{210F}", - "\u{0125}", - "\u{2665}", - "\u{2665}", - "\u{2026}", - "\u{22B9}", - "\u{1D525}", - "\u{2925}", - "\u{2926}", - "\u{21FF}", - "\u{223B}", - "\u{21A9}", - "\u{21AA}", - "\u{1D559}", - "\u{2015}", - "\u{1D4BD}", - "\u{210F}", - "\u{0127}", - "\u{2043}", - "\u{2010}", - "\u{00ED}", - "\u{2063}", - "\u{00EE}", - "\u{0438}", - "\u{0435}", - "\u{00A1}", - "\u{21D4}", - "\u{1D526}", - "\u{00EC}", - "\u{2148}", - "\u{2A0C}", - "\u{222D}", - "\u{29DC}", - "\u{2129}", - "\u{0133}", - "\u{012B}", - "\u{2111}", - "\u{2110}", - "\u{2111}", - "\u{0131}", - "\u{22B7}", - "\u{01B5}", - "\u{2208}", - "\u{2105}", - "\u{221E}", - "\u{29DD}", - "\u{0131}", - "\u{222B}", - "\u{22BA}", - "\u{2124}", - "\u{22BA}", - "\u{2A17}", - "\u{2A3C}", - "\u{0451}", - "\u{012F}", - "\u{1D55A}", - "\u{03B9}", - "\u{2A3C}", - "\u{00BF}", - "\u{1D4BE}", - "\u{2208}", - "\u{22F9}", - "\u{22F5}", - "\u{22F4}", - "\u{22F3}", - "\u{2208}", - "\u{2062}", - "\u{0129}", - "\u{0456}", - "\u{00EF}", - "\u{0135}", - "\u{0439}", - "\u{1D527}", - "\u{0237}", - "\u{1D55B}", - "\u{1D4BF}", - "\u{0458}", - "\u{0454}", - "\u{03BA}", - "\u{03F0}", - "\u{0137}", - "\u{043A}", - "\u{1D528}", - "\u{0138}", - "\u{0445}", - "\u{045C}", - "\u{1D55C}", - "\u{1D4C0}", - "\u{21DA}", - "\u{21D0}", - "\u{291B}", - "\u{290E}", - "\u{2266}", - "\u{2A8B}", - "\u{2962}", - "\u{013A}", - "\u{29B4}", - "\u{2112}", - "\u{03BB}", - "\u{27E8}", - "\u{2991}", - "\u{27E8}", - "\u{2A85}", - "\u{00AB}", - "\u{2190}", - "\u{21E4}", - "\u{291F}", - "\u{291D}", - "\u{21A9}", - "\u{21AB}", - "\u{2939}", - "\u{2973}", - "\u{21A2}", - "\u{2AAB}", - "\u{2919}", - "\u{2AAD}", - "\u{2AAD}\u{FE00}", - "\u{290C}", - "\u{2772}", - "\u{007B}", - "\u{005B}", - "\u{298B}", - "\u{298F}", - "\u{298D}", - "\u{013E}", - "\u{013C}", - "\u{2308}", - "\u{007B}", - "\u{043B}", - "\u{2936}", - "\u{201C}", - "\u{201E}", - "\u{2967}", - "\u{294B}", - "\u{21B2}", - "\u{2264}", - "\u{2190}", - "\u{21A2}", - "\u{21BD}", - "\u{21BC}", - "\u{21C7}", - "\u{2194}", - "\u{21C6}", - "\u{21CB}", - "\u{21AD}", - "\u{22CB}", - "\u{22DA}", - "\u{2264}", - "\u{2266}", - "\u{2A7D}", - "\u{2A7D}", - "\u{2AA8}", - "\u{2A7F}", - "\u{2A81}", - "\u{2A83}", - "\u{22DA}\u{FE00}", - "\u{2A93}", - "\u{2A85}", - "\u{22D6}", - "\u{22DA}", - "\u{2A8B}", - "\u{2276}", - "\u{2272}", - "\u{297C}", - "\u{230A}", - "\u{1D529}", - "\u{2276}", - "\u{2A91}", - "\u{21BD}", - "\u{21BC}", - "\u{296A}", - "\u{2584}", - "\u{0459}", - "\u{226A}", - "\u{21C7}", - "\u{231E}", - "\u{296B}", - "\u{25FA}", - "\u{0140}", - "\u{23B0}", - "\u{23B0}", - "\u{2268}", - "\u{2A89}", - "\u{2A89}", - "\u{2A87}", - "\u{2A87}", - "\u{2268}", - "\u{22E6}", - "\u{27EC}", - "\u{21FD}", - "\u{27E6}", - "\u{27F5}", - "\u{27F7}", - "\u{27FC}", - "\u{27F6}", - "\u{21AB}", - "\u{21AC}", - "\u{2985}", - "\u{1D55D}", - "\u{2A2D}", - "\u{2A34}", - "\u{2217}", - "\u{005F}", - "\u{25CA}", - "\u{25CA}", - "\u{29EB}", - "\u{0028}", - "\u{2993}", - "\u{21C6}", - "\u{231F}", - "\u{21CB}", - "\u{296D}", - "\u{200E}", - "\u{22BF}", - "\u{2039}", - "\u{1D4C1}", - "\u{21B0}", - "\u{2272}", - "\u{2A8D}", - "\u{2A8F}", - "\u{005B}", - "\u{2018}", - "\u{201A}", - "\u{0142}", - "\u{003C}", - "\u{2AA6}", - "\u{2A79}", - "\u{22D6}", - "\u{22CB}", - "\u{22C9}", - "\u{2976}", - "\u{2A7B}", - "\u{2996}", - "\u{25C3}", - "\u{22B4}", - "\u{25C2}", - "\u{294A}", - "\u{2966}", - "\u{2268}\u{FE00}", - "\u{2268}\u{FE00}", - "\u{223A}", - "\u{00AF}", - "\u{2642}", - "\u{2720}", - "\u{2720}", - "\u{21A6}", - "\u{21A6}", - "\u{21A7}", - "\u{21A4}", - "\u{21A5}", - "\u{25AE}", - "\u{2A29}", - "\u{043C}", - "\u{2014}", - "\u{2221}", - "\u{1D52A}", - "\u{2127}", - "\u{00B5}", - "\u{2223}", - "\u{002A}", - "\u{2AF0}", - "\u{00B7}", - "\u{2212}", - "\u{229F}", - "\u{2238}", - "\u{2A2A}", - "\u{2ADB}", - "\u{2026}", - "\u{2213}", - "\u{22A7}", - "\u{1D55E}", - "\u{2213}", - "\u{1D4C2}", - "\u{223E}", - "\u{03BC}", - "\u{22B8}", - "\u{22B8}", - "\u{22D9}\u{0338}", - "\u{226B}\u{20D2}", - "\u{226B}\u{0338}", - "\u{21CD}", - "\u{21CE}", - "\u{22D8}\u{0338}", - "\u{226A}\u{20D2}", - "\u{226A}\u{0338}", - "\u{21CF}", - "\u{22AF}", - "\u{22AE}", - "\u{2207}", - "\u{0144}", - "\u{2220}\u{20D2}", - "\u{2249}", - "\u{2A70}\u{0338}", - "\u{224B}\u{0338}", - "\u{0149}", - "\u{2249}", - "\u{266E}", - "\u{266E}", - "\u{2115}", - "\u{00A0}", - "\u{224E}\u{0338}", - "\u{224F}\u{0338}", - "\u{2A43}", - "\u{0148}", - "\u{0146}", - "\u{2247}", - "\u{2A6D}\u{0338}", - "\u{2A42}", - "\u{043D}", - "\u{2013}", - "\u{2260}", - "\u{21D7}", - "\u{2924}", - "\u{2197}", - "\u{2197}", - "\u{2250}\u{0338}", - "\u{2262}", - "\u{2928}", - "\u{2242}\u{0338}", - "\u{2204}", - "\u{2204}", - "\u{1D52B}", - "\u{2267}\u{0338}", - "\u{2271}", - "\u{2271}", - "\u{2267}\u{0338}", - "\u{2A7E}\u{0338}", - "\u{2A7E}\u{0338}", - "\u{2275}", - "\u{226F}", - "\u{226F}", - "\u{21CE}", - "\u{21AE}", - "\u{2AF2}", - "\u{220B}", - "\u{22FC}", - "\u{22FA}", - "\u{220B}", - "\u{045A}", - "\u{21CD}", - "\u{2266}\u{0338}", - "\u{219A}", - "\u{2025}", - "\u{2270}", - "\u{219A}", - "\u{21AE}", - "\u{2270}", - "\u{2266}\u{0338}", - "\u{2A7D}\u{0338}", - "\u{2A7D}\u{0338}", - "\u{226E}", - "\u{2274}", - "\u{226E}", - "\u{22EA}", - "\u{22EC}", - "\u{2224}", - "\u{1D55F}", - "\u{00AC}", - "\u{2209}", - "\u{22F9}\u{0338}", - "\u{22F5}\u{0338}", - "\u{2209}", - "\u{22F7}", - "\u{22F6}", - "\u{220C}", - "\u{220C}", - "\u{22FE}", - "\u{22FD}", - "\u{2226}", - "\u{2226}", - "\u{2AFD}\u{20E5}", - "\u{2202}\u{0338}", - "\u{2A14}", - "\u{2280}", - "\u{22E0}", - "\u{2AAF}\u{0338}", - "\u{2280}", - "\u{2AAF}\u{0338}", - "\u{21CF}", - "\u{219B}", - "\u{2933}\u{0338}", - "\u{219D}\u{0338}", - "\u{219B}", - "\u{22EB}", - "\u{22ED}", - "\u{2281}", - "\u{22E1}", - "\u{2AB0}\u{0338}", - "\u{1D4C3}", - "\u{2224}", - "\u{2226}", - "\u{2241}", - "\u{2244}", - "\u{2244}", - "\u{2224}", - "\u{2226}", - "\u{22E2}", - "\u{22E3}", - "\u{2284}", - "\u{2AC5}\u{0338}", - "\u{2288}", - "\u{2282}\u{20D2}", - "\u{2288}", - "\u{2AC5}\u{0338}", - "\u{2281}", - "\u{2AB0}\u{0338}", - "\u{2285}", - "\u{2AC6}\u{0338}", - "\u{2289}", - "\u{2283}\u{20D2}", - "\u{2289}", - "\u{2AC6}\u{0338}", - "\u{2279}", - "\u{00F1}", - "\u{2278}", - "\u{22EA}", - "\u{22EC}", - "\u{22EB}", - "\u{22ED}", - "\u{03BD}", - "\u{0023}", - "\u{2116}", - "\u{2007}", - "\u{22AD}", - "\u{2904}", - "\u{224D}\u{20D2}", - "\u{22AC}", - "\u{2265}\u{20D2}", - "\u{003E}\u{20D2}", - "\u{29DE}", - "\u{2902}", - "\u{2264}\u{20D2}", - "\u{003C}\u{20D2}", - "\u{22B4}\u{20D2}", - "\u{2903}", - "\u{22B5}\u{20D2}", - "\u{223C}\u{20D2}", - "\u{21D6}", - "\u{2923}", - "\u{2196}", - "\u{2196}", - "\u{2927}", - "\u{24C8}", - "\u{00F3}", - "\u{229B}", - "\u{229A}", - "\u{00F4}", - "\u{043E}", - "\u{229D}", - "\u{0151}", - "\u{2A38}", - "\u{2299}", - "\u{29BC}", - "\u{0153}", - "\u{29BF}", - "\u{1D52C}", - "\u{02DB}", - "\u{00F2}", - "\u{29C1}", - "\u{29B5}", - "\u{03A9}", - "\u{222E}", - "\u{21BA}", - "\u{29BE}", - "\u{29BB}", - "\u{203E}", - "\u{29C0}", - "\u{014D}", - "\u{03C9}", - "\u{03BF}", - "\u{29B6}", - "\u{2296}", - "\u{1D560}", - "\u{29B7}", - "\u{29B9}", - "\u{2295}", - "\u{2228}", - "\u{21BB}", - "\u{2A5D}", - "\u{2134}", - "\u{2134}", - "\u{00AA}", - "\u{00BA}", - "\u{22B6}", - "\u{2A56}", - "\u{2A57}", - "\u{2A5B}", - "\u{2134}", - "\u{00F8}", - "\u{2298}", - "\u{00F5}", - "\u{2297}", - "\u{2A36}", - "\u{00F6}", - "\u{233D}", - "\u{2225}", - "\u{00B6}", - "\u{2225}", - "\u{2AF3}", - "\u{2AFD}", - "\u{2202}", - "\u{043F}", - "\u{0025}", - "\u{002E}", - "\u{2030}", - "\u{22A5}", - "\u{2031}", - "\u{1D52D}", - "\u{03C6}", - "\u{03D5}", - "\u{2133}", - "\u{260E}", - "\u{03C0}", - "\u{22D4}", - "\u{03D6}", - "\u{210F}", - "\u{210E}", - "\u{210F}", - "\u{002B}", - "\u{2A23}", - "\u{229E}", - "\u{2A22}", - "\u{2214}", - "\u{2A25}", - "\u{2A72}", - "\u{00B1}", - "\u{2A26}", - "\u{2A27}", - "\u{00B1}", - "\u{2A15}", - "\u{1D561}", - "\u{00A3}", - "\u{227A}", - "\u{2AB3}", - "\u{2AB7}", - "\u{227C}", - "\u{2AAF}", - "\u{227A}", - "\u{2AB7}", - "\u{227C}", - "\u{2AAF}", - "\u{2AB9}", - "\u{2AB5}", - "\u{22E8}", - "\u{227E}", - "\u{2032}", - "\u{2119}", - "\u{2AB5}", - "\u{2AB9}", - "\u{22E8}", - "\u{220F}", - "\u{232E}", - "\u{2312}", - "\u{2313}", - "\u{221D}", - "\u{221D}", - "\u{227E}", - "\u{22B0}", - "\u{1D4C5}", - "\u{03C8}", - "\u{2008}", - "\u{1D52E}", - "\u{2A0C}", - "\u{1D562}", - "\u{2057}", - "\u{1D4C6}", - "\u{210D}", - "\u{2A16}", - "\u{003F}", - "\u{225F}", - "\u{0022}", - "\u{21DB}", - "\u{21D2}", - "\u{291C}", - "\u{290F}", - "\u{2964}", - "\u{223D}\u{0331}", - "\u{0155}", - "\u{221A}", - "\u{29B3}", - "\u{27E9}", - "\u{2992}", - "\u{29A5}", - "\u{27E9}", - "\u{00BB}", - "\u{2192}", - "\u{2975}", - "\u{21E5}", - "\u{2920}", - "\u{2933}", - "\u{291E}", - "\u{21AA}", - "\u{21AC}", - "\u{2945}", - "\u{2974}", - "\u{21A3}", - "\u{219D}", - "\u{291A}", - "\u{2236}", - "\u{211A}", - "\u{290D}", - "\u{2773}", - "\u{007D}", - "\u{005D}", - "\u{298C}", - "\u{298E}", - "\u{2990}", - "\u{0159}", - "\u{0157}", - "\u{2309}", - "\u{007D}", - "\u{0440}", - "\u{2937}", - "\u{2969}", - "\u{201D}", - "\u{201D}", - "\u{21B3}", - "\u{211C}", - "\u{211B}", - "\u{211C}", - "\u{211D}", - "\u{25AD}", - "\u{00AE}", - "\u{297D}", - "\u{230B}", - "\u{1D52F}", - "\u{21C1}", - "\u{21C0}", - "\u{296C}", - "\u{03C1}", - "\u{03F1}", - "\u{2192}", - "\u{21A3}", - "\u{21C1}", - "\u{21C0}", - "\u{21C4}", - "\u{21CC}", - "\u{21C9}", - "\u{219D}", - "\u{22CC}", - "\u{02DA}", - "\u{2253}", - "\u{21C4}", - "\u{21CC}", - "\u{200F}", - "\u{23B1}", - "\u{23B1}", - "\u{2AEE}", - "\u{27ED}", - "\u{21FE}", - "\u{27E7}", - "\u{2986}", - "\u{1D563}", - "\u{2A2E}", - "\u{2A35}", - "\u{0029}", - "\u{2994}", - "\u{2A12}", - "\u{21C9}", - "\u{203A}", - "\u{1D4C7}", - "\u{21B1}", - "\u{005D}", - "\u{2019}", - "\u{2019}", - "\u{22CC}", - "\u{22CA}", - "\u{25B9}", - "\u{22B5}", - "\u{25B8}", - "\u{29CE}", - "\u{2968}", - "\u{211E}", - "\u{015B}", - "\u{201A}", - "\u{227B}", - "\u{2AB4}", - "\u{2AB8}", - "\u{0161}", - "\u{227D}", - "\u{2AB0}", - "\u{015F}", - "\u{015D}", - "\u{2AB6}", - "\u{2ABA}", - "\u{22E9}", - "\u{2A13}", - "\u{227F}", - "\u{0441}", - "\u{22C5}", - "\u{22A1}", - "\u{2A66}", - "\u{21D8}", - "\u{2925}", - "\u{2198}", - "\u{2198}", - "\u{00A7}", - "\u{003B}", - "\u{2929}", - "\u{2216}", - "\u{2216}", - "\u{2736}", - "\u{1D530}", - "\u{2322}", - "\u{266F}", - "\u{0449}", - "\u{0448}", - "\u{2223}", - "\u{2225}", - "\u{00AD}", - "\u{03C3}", - "\u{03C2}", - "\u{03C2}", - "\u{223C}", - "\u{2A6A}", - "\u{2243}", - "\u{2243}", - "\u{2A9E}", - "\u{2AA0}", - "\u{2A9D}", - "\u{2A9F}", - "\u{2246}", - "\u{2A24}", - "\u{2972}", - "\u{2190}", - "\u{2216}", - "\u{2A33}", - "\u{29E4}", - "\u{2223}", - "\u{2323}", - "\u{2AAA}", - "\u{2AAC}", - "\u{2AAC}\u{FE00}", - "\u{044C}", - "\u{002F}", - "\u{29C4}", - "\u{233F}", - "\u{1D564}", - "\u{2660}", - "\u{2660}", - "\u{2225}", - "\u{2293}", - "\u{2293}\u{FE00}", - "\u{2294}", - "\u{2294}\u{FE00}", - "\u{228F}", - "\u{2291}", - "\u{228F}", - "\u{2291}", - "\u{2290}", - "\u{2292}", - "\u{2290}", - "\u{2292}", - "\u{25A1}", - "\u{25A1}", - "\u{25AA}", - "\u{25AA}", - "\u{2192}", - "\u{1D4C8}", - "\u{2216}", - "\u{2323}", - "\u{22C6}", - "\u{2606}", - "\u{2605}", - "\u{03F5}", - "\u{03D5}", - "\u{00AF}", - "\u{2282}", - "\u{2AC5}", - "\u{2ABD}", - "\u{2286}", - "\u{2AC3}", - "\u{2AC1}", - "\u{2ACB}", - "\u{228A}", - "\u{2ABF}", - "\u{2979}", - "\u{2282}", - "\u{2286}", - "\u{2AC5}", - "\u{228A}", - "\u{2ACB}", - "\u{2AC7}", - "\u{2AD5}", - "\u{2AD3}", - "\u{227B}", - "\u{2AB8}", - "\u{227D}", - "\u{2AB0}", - "\u{2ABA}", - "\u{2AB6}", - "\u{22E9}", - "\u{227F}", - "\u{2211}", - "\u{266A}", - "\u{2283}", - "\u{00B9}", - "\u{00B2}", - "\u{00B3}", - "\u{2AC6}", - "\u{2ABE}", - "\u{2AD8}", - "\u{2287}", - "\u{2AC4}", - "\u{27C9}", - "\u{2AD7}", - "\u{297B}", - "\u{2AC2}", - "\u{2ACC}", - "\u{228B}", - "\u{2AC0}", - "\u{2283}", - "\u{2287}", - "\u{2AC6}", - "\u{228B}", - "\u{2ACC}", - "\u{2AC8}", - "\u{2AD4}", - "\u{2AD6}", - "\u{21D9}", - "\u{2926}", - "\u{2199}", - "\u{2199}", - "\u{292A}", - "\u{00DF}", - "\u{2316}", - "\u{03C4}", - "\u{23B4}", - "\u{0165}", - "\u{0163}", - "\u{0442}", - "\u{20DB}", - "\u{2315}", - "\u{1D531}", - "\u{2234}", - "\u{2234}", - "\u{03B8}", - "\u{03D1}", - "\u{03D1}", - "\u{2248}", - "\u{223C}", - "\u{2009}", - "\u{2248}", - "\u{223C}", - "\u{00FE}", - "\u{02DC}", - "\u{00D7}", - "\u{22A0}", - "\u{2A31}", - "\u{2A30}", - "\u{222D}", - "\u{2928}", - "\u{22A4}", - "\u{2336}", - "\u{2AF1}", - "\u{1D565}", - "\u{2ADA}", - "\u{2929}", - "\u{2034}", - "\u{2122}", - "\u{25B5}", - "\u{25BF}", - "\u{25C3}", - "\u{22B4}", - "\u{225C}", - "\u{25B9}", - "\u{22B5}", - "\u{25EC}", - "\u{225C}", - "\u{2A3A}", - "\u{2A39}", - "\u{29CD}", - "\u{2A3B}", - "\u{23E2}", - "\u{1D4C9}", - "\u{0446}", - "\u{045B}", - "\u{0167}", - "\u{226C}", - "\u{219E}", - "\u{21A0}", - "\u{21D1}", - "\u{2963}", - "\u{00FA}", - "\u{2191}", - "\u{045E}", - "\u{016D}", - "\u{00FB}", - "\u{0443}", - "\u{21C5}", - "\u{0171}", - "\u{296E}", - "\u{297E}", - "\u{1D532}", - "\u{00F9}", - "\u{21BF}", - "\u{21BE}", - "\u{2580}", - "\u{231C}", - "\u{231C}", - "\u{230F}", - "\u{25F8}", - "\u{016B}", - "\u{00A8}", - "\u{0173}", - "\u{1D566}", - "\u{2191}", - "\u{2195}", - "\u{21BF}", - "\u{21BE}", - "\u{228E}", - "\u{03C5}", - "\u{03D2}", - "\u{03C5}", - "\u{21C8}", - "\u{231D}", - "\u{231D}", - "\u{230E}", - "\u{016F}", - "\u{25F9}", - "\u{1D4CA}", - "\u{22F0}", - "\u{0169}", - "\u{25B5}", - "\u{25B4}", - "\u{21C8}", - "\u{00FC}", - "\u{29A7}", - "\u{21D5}", - "\u{2AE8}", - "\u{2AE9}", - "\u{22A8}", - "\u{299C}", - "\u{03F5}", - "\u{03F0}", - "\u{2205}", - "\u{03D5}", - "\u{03D6}", - "\u{221D}", - "\u{2195}", - "\u{03F1}", - "\u{03C2}", - "\u{228A}\u{FE00}", - "\u{2ACB}\u{FE00}", - "\u{228B}\u{FE00}", - "\u{2ACC}\u{FE00}", - "\u{03D1}", - "\u{22B2}", - "\u{22B3}", - "\u{0432}", - "\u{22A2}", - "\u{2228}", - "\u{22BB}", - "\u{225A}", - "\u{22EE}", - "\u{007C}", - "\u{007C}", - "\u{1D533}", - "\u{22B2}", - "\u{2282}\u{20D2}", - "\u{2283}\u{20D2}", - "\u{1D567}", - "\u{221D}", - "\u{22B3}", - "\u{1D4CB}", - "\u{2ACB}\u{FE00}", - "\u{228A}\u{FE00}", - "\u{2ACC}\u{FE00}", - "\u{228B}\u{FE00}", - "\u{299A}", - "\u{0175}", - "\u{2A5F}", - "\u{2227}", - "\u{2259}", - "\u{2118}", - "\u{1D534}", - "\u{1D568}", - "\u{2118}", - "\u{2240}", - "\u{2240}", - "\u{1D4CC}", - "\u{22C2}", - "\u{25EF}", - "\u{22C3}", - "\u{25BD}", - "\u{1D535}", - "\u{27FA}", - "\u{27F7}", - "\u{03BE}", - "\u{27F8}", - "\u{27F5}", - "\u{27FC}", - "\u{22FB}", - "\u{2A00}", - "\u{1D569}", - "\u{2A01}", - "\u{2A02}", - "\u{27F9}", - "\u{27F6}", - "\u{1D4CD}", - "\u{2A06}", - "\u{2A04}", - "\u{25B3}", - "\u{22C1}", - "\u{22C0}", - "\u{00FD}", - "\u{044F}", - "\u{0177}", - "\u{044B}", - "\u{00A5}", - "\u{1D536}", - "\u{0457}", - "\u{1D56A}", - "\u{1D4CE}", - "\u{044E}", - "\u{00FF}", - "\u{017A}", - "\u{017E}", - "\u{0437}", - "\u{017C}", - "\u{2128}", - "\u{03B6}", - "\u{1D537}", - "\u{0436}", - "\u{21DD}", - "\u{1D56B}", - "\u{1D4CF}", - "\u{200D}", - "\u{200C}", - ]; - -pub fn get_entity(name: &str) -> Option<&'static str> { - ENTITIES.binary_search(&name).ok().map(|i| ENTITY_VALUES[i]) -} - diff --git a/src/vendor/pulldown-cmark-0.0.8/src/escape.rs b/src/vendor/pulldown-cmark-0.0.8/src/escape.rs deleted file mode 100644 index fd0d901ce1..0000000000 --- a/src/vendor/pulldown-cmark-0.0.8/src/escape.rs +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2015 Google Inc. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -//! Utility functions for HTML escaping - -use std::str::from_utf8; - -static HREF_SAFE: [u8; 128] = [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, - ]; - -static HEX_CHARS: &'static [u8] = b"0123456789ABCDEF"; - -pub fn escape_href(ob: &mut String, s: &str) { - let mut mark = 0; - for i in 0..s.len() { - let c = s.as_bytes()[i]; - if c >= 0x80 || HREF_SAFE[c as usize] == 0 { - // character needing escape - - // write partial substring up to mark - if mark < i { - ob.push_str(&s[mark..i]); - } - match c { - b'&' => { - ob.push_str("&"); - }, - b'\'' => { - ob.push_str("'"); - }, - _ => { - let mut buf = [0u8; 3]; - buf[0] = b'%'; - buf[1] = HEX_CHARS[((c as usize) >> 4) & 0xF]; - buf[2] = HEX_CHARS[(c as usize) & 0xF]; - ob.push_str(from_utf8(&buf).unwrap()); - } - } - mark = i + 1; // all escaped characters are ASCII - } - } - ob.push_str(&s[mark..]); -} - -static HTML_ESCAPE_TABLE: [u8; 256] = [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 5, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]; - -static HTML_ESCAPES: [&'static str; 6] = [ - "", - """, - "&", - "/", - "<", - ">" - ]; - -pub fn escape_html(ob: &mut String, s: &str, secure: bool) { - let size = s.len(); - let bytes = s.as_bytes(); - let mut mark = 0; - let mut i = 0; - while i < size { - match bytes[i..].iter().position(|&c| HTML_ESCAPE_TABLE[c as usize] != 0) { - Some(pos) => { - i += pos; - } - None => break - } - let c = bytes[i]; - let escape = HTML_ESCAPE_TABLE[c as usize]; - if escape != 0 && (secure || c != b'/') { - ob.push_str(&s[mark..i]); - ob.push_str(HTML_ESCAPES[escape as usize]); - mark = i + 1; // all escaped characters are ASCII - } - i += 1; - } - ob.push_str(&s[mark..]); -} diff --git a/src/vendor/pulldown-cmark-0.0.8/src/html.rs b/src/vendor/pulldown-cmark-0.0.8/src/html.rs deleted file mode 100644 index cf46114502..0000000000 --- a/src/vendor/pulldown-cmark-0.0.8/src/html.rs +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright 2015 Google Inc. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -//! HTML renderer that takes an iterator of events as input. - -use std::borrow::Cow; -use std::collections::HashMap; -use std::fmt::Write; - -use parse::{Event, Tag}; -use parse::Event::{Start, End, Text, Html, InlineHtml, SoftBreak, HardBreak, FootnoteReference}; -use escape::{escape_html, escape_href}; - -struct Ctx<'b, I> { - iter: I, - buf: &'b mut String, -} - -impl<'a, 'b, I: Iterator>> Ctx<'b, I> { - fn fresh_line(&mut self) { - if !(self.buf.is_empty() || self.buf.ends_with('\n')) { - self.buf.push('\n'); - } - } - - pub fn run(&mut self) { - let mut numbers = HashMap::new(); - loop { - match self.iter.next() { - Some(event) => { - match event { - Start(tag) => self.start_tag(tag, &mut numbers), - End(tag) => self.end_tag(tag), - Text(text) => escape_html(self.buf, &text, false), - Html(html) => self.buf.push_str(&html), - InlineHtml(html) => self.buf.push_str(&html), - SoftBreak => self.buf.push('\n'), - HardBreak => self.buf.push_str("
\n"), - FootnoteReference(name) => { - let len = numbers.len() + 1; - self.buf.push_str(""); - let number = numbers.entry(name).or_insert(len); - self.buf.push_str(&*format!("{}", number)); - self.buf.push_str(""); - }, - } - } - None => break - } - } - } - - fn start_tag(&mut self, tag: Tag<'a>, numbers: &mut HashMap, usize>) { - match tag { - Tag::Paragraph => { - self.fresh_line(); - self.buf.push_str("

"); - } - Tag::Rule => { - self.fresh_line(); - self.buf.push_str("


\n") - } - Tag::Header(level) => { - self.fresh_line(); - self.buf.push_str("'); - } - Tag::Table(_) => { - self.buf.push_str(""); - } - Tag::TableHead => { - self.buf.push_str(""); - } - Tag::TableRow => { - self.buf.push_str(""); - } - Tag::TableCell => { - self.buf.push_str("
"); - } - Tag::BlockQuote => { - self.fresh_line(); - self.buf.push_str("
\n"); - } - Tag::CodeBlock(info) => { - self.fresh_line(); - let lang = info.split(' ').next().unwrap(); - if lang.is_empty() { - self.buf.push_str("
");
-                } else {
-                    self.buf.push_str("
");
-                }
-            }
-            Tag::List(Some(1)) => {
-                self.fresh_line();
-                self.buf.push_str("
    \n"); - } - Tag::List(Some(start)) => { - self.fresh_line(); - let _ = write!(self.buf, "
      \n", start); - } - Tag::List(None) => { - self.fresh_line(); - self.buf.push_str("
\n"); - } - Tag::TableHead => { - self.buf.push_str("\n"); - } - Tag::TableRow => { - self.buf.push_str("\n"); - } - Tag::TableCell => { - self.buf.push_str(""); - } - Tag::BlockQuote => self.buf.push_str("\n"), - Tag::CodeBlock(_) => self.buf.push_str("\n"), - Tag::List(Some(_)) => self.buf.push_str("\n"), - Tag::List(None) => self.buf.push_str("\n"), - Tag::Item => self.buf.push_str("\n"), - Tag::Emphasis => self.buf.push_str(""), - Tag::Strong => self.buf.push_str(""), - Tag::Code => self.buf.push_str(""), - Tag::Link(_, _) => self.buf.push_str(""), - Tag::Image(_, _) => (), // shouldn't happen, handled in start - Tag::FootnoteDefinition(_) => self.buf.push_str("\n"), - } - } - - // run raw text, consuming end tag - fn raw_text<'c>(&mut self, numbers: &'c mut HashMap, usize>) { - let mut nest = 0; - loop { - match self.iter.next() { - Some(event) => { - match event { - Start(_) => nest += 1, - End(_) => { - if nest == 0 { break; } - nest -= 1; - } - Text(text) => escape_html(self.buf, &text, false), - Html(_) => (), - InlineHtml(html) => escape_html(self.buf, &html, false), - SoftBreak | HardBreak => self.buf.push(' '), - FootnoteReference(name) => { - let len = numbers.len() + 1; - let number = numbers.entry(name).or_insert(len); - self.buf.push_str(&*format!("[{}]", number)); - } - } - } - None => break - } - } - } -} - -pub fn push_html<'a, I: Iterator>>(buf: &mut String, iter: I) { - let mut ctx = Ctx { - iter: iter, - buf: buf, - }; - ctx.run(); -} diff --git a/src/vendor/pulldown-cmark-0.0.8/src/lib.rs b/src/vendor/pulldown-cmark-0.0.8/src/lib.rs deleted file mode 100644 index 5ce4da9c2f..0000000000 --- a/src/vendor/pulldown-cmark-0.0.8/src/lib.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2015 Google Inc. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -//! Pull parser for commonmark. - -pub mod html; - -#[macro_use] -extern crate bitflags; - -mod passes; -mod parse; -mod scanners; -mod entities; -mod escape; -mod puncttable; -mod utils; - -pub use passes::Parser; -pub use parse::{Event, Tag, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; diff --git a/src/vendor/pulldown-cmark-0.0.8/src/main.rs b/src/vendor/pulldown-cmark-0.0.8/src/main.rs deleted file mode 100644 index 987f16cadc..0000000000 --- a/src/vendor/pulldown-cmark-0.0.8/src/main.rs +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright 2015 Google Inc. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -//! Command line tool to exercise pulldown-cmark. - -extern crate getopts; - -extern crate pulldown_cmark; - -use pulldown_cmark::Parser; -use pulldown_cmark::{Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; -use pulldown_cmark::html; - -use std::env; -use std::io; -use std::io::{Read, Write}; -use std::path::Path; -use std::fs::File; - -fn render_html(text: &str, opts: Options) -> String { - let mut s = String::with_capacity(text.len() * 3 / 2); - let p = Parser::new_ext(&text, opts); - html::push_html(&mut s, p); - s -} - -fn dry_run(text:&str, opts: Options) { - let p = Parser::new_ext(&text, opts); - /* - let events = p.collect::>(); - let count = events.len(); - */ - let count = p.count(); - println!("{} events", count); -} - -fn print_events(text: &str, opts: Options) { - let mut p = Parser::new_ext(&text, opts); - loop { - print!("{}: ", p.get_offset()); - if let Some(event) = p.next() { - println!("{:?}", event); - } else { - break; - } - } - println!("EOF"); -} - -fn read_file(filename: &str) -> String { - let path = Path::new(filename); - let mut file = match File::open(&path) { - Err(why) => panic!("couldn't open {}: {}", path.display(), why), - Ok(file) => file - }; - let mut s = String::new(); - match file.read_to_string(&mut s) { - Err(why) => panic!("couldn't open {}: {}", path.display(), why), - Ok(_) => s - } -} - -fn find_test_delim(text: &str) -> Option { - if text.starts_with(".\n") { Some(0) } - else { text.find("\n.\n").map(|pos| pos + 1) } -} - -fn run_spec(spec_text: &str, args: &[String], opts: Options) { - //println!("spec length={}, args={:?}", spec_text.len(), args); - let (first, last) = if args.is_empty() { - (None, None) - } else { - let mut iter = args[0].split(".."); - let first = iter.next().and_then(|s| s.parse().ok()); - let last = match iter.next() { - Some(s) => s.parse().ok(), - None => first - }; - (first, last) - }; - - let mut test_number = 1; - let mut tests_failed = 0; - let mut tests_run = 0; - let mut line_count = 0; - let mut tail = spec_text; - loop { - let rest = match find_test_delim(tail) { - Some(pos) => &tail[pos + 2 ..], - None => break - }; - let (source, rest) = match find_test_delim(rest) { - Some(pos) => (&rest[..pos], &rest[pos + 2 ..]), - None => break - }; - let (html, rest) = match find_test_delim(rest) { - Some(pos) => (&rest[.. pos], &rest[pos + 2 ..]), - None => break - }; - if first.map(|fst| fst <= test_number).unwrap_or(true) && - last.map(|lst| test_number <= lst).unwrap_or(true) { - if tests_run == 0 || line_count == 0 || (test_number % 10 == 0) { - if line_count > 30 { - println!(""); - line_count = 0; - } else if line_count > 0 { - print!(" "); - } - print!("[{}]", test_number); - } else if line_count > 0 && (test_number % 10) == 5 { - print!(" "); - } - let our_html = render_html(&source.replace("→", "\t").replace("\n", "\r\n"), opts); - if our_html == html { - print!("."); - } else { - if tests_failed == 0 { - print!("FAIL {}:\n---input---\n{}\n---wanted---\n{}\n---got---\n{}", - test_number, source, html, our_html); - } else { - print!("X"); - } - tests_failed += 1; - } - let _ = io::stdout().flush(); - tests_run += 1; - line_count += 1; - } - tail = rest; - test_number += 1; - } - println!("\n{}/{} tests passed", tests_run - tests_failed, tests_run) -} - -pub fn main() { - let args: Vec<_> = env::args().collect(); - let mut opts = getopts::Options::new(); - opts.optflag("d", "dry-run", "dry run, produce no output"); - opts.optflag("e", "events", "print event sequence instead of rendering"); - opts.optflag("T", "enable-tables", "enable GitHub-style tables"); - opts.optflag("F", "enable-footnotes", "enable Hoedown-style footnotes"); - opts.optopt("s", "spec", "run tests from spec file", "FILE"); - opts.optopt("b", "bench", "run benchmark", "FILE"); - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => panic!(f.to_string()) - }; - let mut opts = Options::empty(); - if matches.opt_present("enable-tables") { - opts.insert(OPTION_ENABLE_TABLES); - } - if matches.opt_present("enable-footnotes") { - opts.insert(OPTION_ENABLE_FOOTNOTES); - } - if let Some(filename) = matches.opt_str("spec") { - run_spec(&read_file(&filename), &matches.free, opts); - } else if let Some(filename) = matches.opt_str("bench") { - let inp = read_file(&filename); - for _ in 0..1000 { - let _ = render_html(&inp, opts); - } - } else { - let mut input = String::new(); - match io::stdin().read_to_string(&mut input) { - Err(why) => panic!("couldn't read from stdin: {}", why), - Ok(_) => () - } - if matches.opt_present("events") { - print_events(&input, opts); - } else if matches.opt_present("dry-run") { - dry_run(&input, opts); - } else { - print!("{}", render_html(&input, opts)); - } - } -} diff --git a/src/vendor/pulldown-cmark-0.0.8/src/parse.rs b/src/vendor/pulldown-cmark-0.0.8/src/parse.rs deleted file mode 100644 index 95b1ac8070..0000000000 --- a/src/vendor/pulldown-cmark-0.0.8/src/parse.rs +++ /dev/null @@ -1,1675 +0,0 @@ -// Copyright 2015 Google Inc. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -//! Raw parser, for doing a single pass over input. - -use scanners::*; -use utils; -use std::borrow::Cow; -use std::borrow::Cow::{Borrowed}; -use std::collections::{HashMap, HashSet}; -use std::cmp; - -#[derive(PartialEq, Debug)] -enum State { - StartBlock, - InContainers, - Inline, - TableHead(usize, usize), // limit, next - TableBody, - TableRow, - CodeLineStart, - Code, - InlineCode, - Literal, -} - -#[derive(Copy, Clone, Debug, PartialEq)] -enum Container { - BlockQuote, - List(usize, u8), - ListItem(usize), - FootnoteDefinition, -} - -pub struct RawParser<'a> { - text: &'a str, - off: usize, - - opts: Options, - active_tab: [u8; 256], - - state: State, - stack: Vec<(Tag<'a>, usize, usize)>, - leading_space: usize, - - containers: Vec, - last_line_was_empty: bool, - - // state for code fences - fence_char: u8, - fence_count: usize, - fence_indent: usize, - - // info, used in second pass - loose_lists: HashSet, // offset is at list marker - links: HashMap, Cow<'a, str>)>, -} - -pub struct ParseInfo<'a> { - pub loose_lists: HashSet, - pub links: HashMap, Cow<'a, str>)>, -} - -#[derive(Clone, Debug)] -pub enum Tag<'a> { - // block-level tags - Paragraph, - Rule, - Header(i32), - BlockQuote, - CodeBlock(Cow<'a, str>), - List(Option), // TODO: add delim and tight for ast (not needed for html) - Item, - FootnoteDefinition(Cow<'a, str>), - - // tables - Table(i32), - TableHead, - TableRow, - TableCell, - - // span-level tags - Emphasis, - Strong, - Code, - Link(Cow<'a, str>, Cow<'a, str>), - Image(Cow<'a, str>, Cow<'a, str>), -} - -#[derive(Debug)] -pub enum Event<'a> { - Start(Tag<'a>), - End(Tag<'a>), - Text(Cow<'a, str>), - Html(Cow<'a, str>), - InlineHtml(Cow<'a, str>), - FootnoteReference(Cow<'a, str>), - SoftBreak, - HardBreak, -} - -bitflags! { - pub flags Options: u32 { - const OPTION_FIRST_PASS = 1 << 0, - const OPTION_ENABLE_TABLES = 1 << 1, - const OPTION_ENABLE_FOOTNOTES = 1 << 2, - } -} - -const MAX_LINK_NEST: usize = 10; - -impl<'a> RawParser<'a> { - pub fn new_with_links(text: &'a str, opts: Options, - links: HashMap, Cow<'a, str>)>) -> RawParser<'a> { - let mut ret = RawParser { - text: text, - off: if text.starts_with("\u{FEFF}") { 3 } else { 0 }, - opts: opts, - active_tab: [0; 256], - state: State::StartBlock, - leading_space: 0, - stack: Vec::new(), - containers: Vec::new(), - last_line_was_empty: false, - - fence_char: 0, - fence_count: 0, - fence_indent: 0, - - // info, used in second pass - loose_lists: HashSet::new(), - links: links, - }; - ret.init_active(); - ret.skip_blank_lines(); - ret - } - - pub fn new(text: &'a str, opts: Options) -> RawParser<'a> { - RawParser::new_with_links(text, opts, HashMap::new()) - } - - // offset into text representing current parse position, hopefully - // useful for building source maps - pub fn get_offset(&self) -> usize { - self.off - } - - // extract info from parser on finish - pub fn get_info(self) -> ParseInfo<'a> { - ParseInfo { - loose_lists: self.loose_lists, - links: self.links, - } - } - - fn init_active(&mut self) { - if self.opts.contains(OPTION_FIRST_PASS) { - self.active_tab[b'\n' as usize] = 1 - } else { - for &c in b"\x00\t\n\r_\\&*[!`<" { - self.active_tab[c as usize] = 1; - } - } - } - - fn limit(&self) -> usize { - match self.stack.last() { - Some(&(_, limit, _)) => limit, - None => self.text.len() - } - } - - // if end is not known, limit should be text.len(), next should be 0 - fn start(&mut self, tag: Tag<'a>, limit: usize, next: usize) -> Event<'a> { - self.stack.push((tag.clone(), limit, next)); - Event::Start(tag) - } - - fn end(&mut self) -> Event<'a> { - let (tag, _, next) = self.stack.pop().unwrap(); - match tag { - // containers - Tag::BlockQuote | Tag::List(_) | Tag::Item | Tag::FootnoteDefinition(_) => { - let _ = self.containers.pop(); - } - - // block level tags - Tag::Paragraph | Tag::Header(_) | Tag::Rule | Tag::CodeBlock(_) | Tag::Table(_) => { - self.state = State::StartBlock; - // TODO: skip blank lines (for cleaner source maps) - } - - // tables - Tag::TableCell => self.state = State::TableRow, - Tag::TableRow | Tag::TableHead => self.state = State::TableBody, - - // inline - Tag::Code => self.state = State::Inline, - _ => (), - } - if next != 0 { self.off = next; } - - /* - if self.stack.is_empty() { - // TODO maybe: make block ends do this - self.state = State::StartBlock; - self.skip_blank_lines(); - } - */ - Event::End(tag) - } - - fn skip_leading_whitespace(&mut self) { - self.off += scan_whitespace_no_nl(&self.text[self.off .. self.limit()]); - } - - // TODO: this function doesn't respect containers - fn skip_blank_lines(&mut self) { - loop { - let ret = scan_blank_line(&self.text[self.off..]); - if ret == 0 { - break; - } - self.off += ret; - } - } - - // Scan markers and indentation for current container stack - // Return: bytes scanned, whether containers are complete, and remaining space - fn scan_containers(&self, text: &str) -> (usize, bool, usize) { - let (mut i, mut space) = scan_leading_space(text, 0); - for container in self.containers.iter() { - match *container { - Container::BlockQuote => { - if space <= 3 { - let n = scan_blockquote_start(&text[i..]); - if n > 0 { - let (n_sp, next_space) = scan_leading_space(text, i + n); - i += n + n_sp; - space = next_space; - } else { - return (i, false, space); - } - } else { - return (i, false, space); - } - } - Container::FootnoteDefinition => (), - Container::List(_, _) => (), - Container::ListItem(indent) => { - if space >= indent { - space -= indent; - } else if scan_eol(&text[i..]).1 { - space = 0; - } else { - return (i, false, 0); - } - } - } - } - (i, true, space) - } - - // scans empty lines with current container stack - // returns number of bytes scanned, number of empty lines - // note: EOF counts as a line ending for counting lines - fn scan_empty_lines(&self, text: &str) -> (usize, usize) { - let mut i = 0; - let mut lines = 0; - loop { - let (n, scanned, _) = self.scan_containers(&text[i..]); - if !scanned { - return (i, lines); - } - if i == text.len() { - return (i, lines + 1); - } - let n_blank = scan_eol(&text[i + n ..]).0; - if n_blank == 0 { - return (i, lines); - } - i += n + n_blank; - lines += 1; - } - } - - // scans whitespace, skipping past containers on newline - fn scan_whitespace_inline(&self, text: &str) -> usize { - let i = scan_whitespace_no_nl(text); - if let (n, true) = scan_eol(&text[i..]) { - let (n_containers, _, space) = self.scan_containers(&text[i + n ..]); - let j = i + n + n_containers; - if !self.is_inline_block_end(&text[j..], space) { - return j; - } - } - i - } - - fn at_list(&self, level: usize) -> Option { - let len = self.containers.len(); - if len >= level { - if let Container::List(offset, _) = self.containers[len - level] { - return Some(offset); - } - } - None - } - - fn start_block(&mut self) -> Option> { - let size = self.text.len(); - //println!("start_block {}", self.off); - while self.off < size { - //println!("start_block loop {} {}", self.off, self.last_line_was_empty); - if self.off >= self.limit() { - return Some(self.end()); - } - if self.state != State::InContainers { - let (n, scanned, space) = self.scan_containers(&self.text[self.off ..]); - if !scanned { - return Some(self.end()); - } - self.leading_space = space; - self.off += n; - self.state = State::InContainers; - } - - let (n, at_eol) = scan_eol(&self.text[self.off ..]); - if at_eol { - self.off += n; - self.state = State::StartBlock; - // two empty lines closes lists and footnotes - let (n, empty_lines) = self.scan_empty_lines(&self.text[self.off ..]); - //println!("{} empty lines (n = {})", empty_lines, n); - let mut closed = false; - if empty_lines >= 1 { - let mut close_tags: Vec<&mut (Tag<'a>, usize, usize)> = self.stack.iter_mut().skip_while(|tag| { - match tag.0 { - Tag::List(_) | Tag::FootnoteDefinition(_) => false, - _ => true, - } - }).collect(); - if close_tags.len() != 0 { - for tag in &mut close_tags { - tag.1 = self.off; // limit - tag.2 = self.off; // next - } - close_tags[0].2 = self.off + n; // next - closed = true; - } - } - if closed { - return Some(self.end()); - } - self.off += n; - if let Some(_) = self.at_list(2) { - self.last_line_was_empty = true; - } - continue; - } - - //println!("checking loose {} {:?}", self.last_line_was_empty, self.at_list(2)); - if self.last_line_was_empty { - if let Some(offset) = self.at_list(2) { - // list item contains two blocks separated by empty line - self.loose_lists.insert(offset); - } - } - - if self.leading_space >= 4 && !self.at_list(1).is_some() { - // see below - if let Some(&Container::List(_, _)) = self.containers.last() { - return Some(self.end()); - } - return Some(self.start_indented_code()); - } - - let tail = &self.text[self.off ..]; - - // must be before list item because ambiguous - let n = scan_hrule(tail); - if n != 0 { - self.last_line_was_empty = false; - // see below - if let Some(&Container::List(_, _)) = self.containers.last() { - return Some(self.end()); - } - self.off += n; - return Some(self.start_hrule()); - } - - let (n, c, start, indent) = scan_listitem(tail); - if n != 0 { - if self.last_line_was_empty { - if let Some(offset) = self.at_list(1) { - // two list items separated by empty line - self.loose_lists.insert(offset); - } - } - self.last_line_was_empty = false; - return Some(self.start_listitem(n, c, start, indent)); - } - - // not a list item, so if we're in a list, close it - if let Some(&Container::List(_, _)) = self.containers.last() { - return Some(self.end()); - } - self.last_line_was_empty = false; - - let c = tail.as_bytes()[0]; - match c { - b'#' => { - let (n, level) = scan_atx_header(tail); - if n != 0 { - self.off += n; - return Some(self.start_atx_header(level)); - } - } - b'`' | b'~' => { - let (n, ch) = scan_code_fence(tail); - if n != 0 { - return Some(self.start_code_fence(n, ch, n)); - } - } - b'>' => { - let n = scan_blockquote_start(tail); - if n != 0 { - self.off += n; - let (n, space) = scan_leading_space(self.text, self.off); - self.off += n; - self.leading_space = space; - self.containers.push(Container::BlockQuote); - return Some(self.start(Tag::BlockQuote, self.text.len(), 0)); - } - } - b'<' => { - if self.is_html_block(tail) { - return Some(self.do_html_block()); - } - } - b'[' => { - if self.opts.contains(OPTION_ENABLE_FOOTNOTES) { - if let Some((name, n)) = self.parse_footnote_definition(tail) { - if self.containers.last() == Some(&Container::FootnoteDefinition) { - return Some(self.end()); - } - self.off += n; - self.containers.push(Container::FootnoteDefinition); - return Some(self.start(Tag::FootnoteDefinition(Cow::Borrowed(name)), self.text.len(), 0)); - } - } - if self.try_link_reference_definition(tail) { - continue; - } - } - _ => () - } - return Some(self.start_paragraph()); - } - None - } - - // can start a paragraph, a setext header, or a table, as they start similarly - fn start_paragraph(&mut self) -> Event<'a> { - let mut i = self.off + scan_nextline(&self.text[self.off..]); - - if let (n, true, space) = self.scan_containers(&self.text[i..]) { - i += n; - if space <= 3 { - let (n, level) = scan_setext_header(&self.text[i..]); - if n != 0 { - let next = i + n; - while i > self.off && is_ascii_whitespace(self.text.as_bytes()[i - 1]) { - i -= 1; - } - self.state = State::Inline; - return self.start(Tag::Header(level), i, next); - } - if self.opts.contains(OPTION_ENABLE_TABLES) { - let (n, cols) = scan_table_head(&self.text[i..]); - if n != 0 { - let next = i + n; - while i > self.off && is_ascii_whitespace(self.text.as_bytes()[i - 1]) { - i -= 1; - } - self.state = State::TableHead(i, next); - return self.start(Tag::Table(cols), self.text.len(), 0); - } - } - } - } - - let size = self.text.len(); - self.state = State::Inline; - self.start(Tag::Paragraph, size, 0) - } - - fn start_table_head(&mut self) -> Event<'a> { - assert!(self.opts.contains(OPTION_ENABLE_TABLES)); - if let State::TableHead(limit, next) = self.state { - self.state = State::TableRow; - return self.start(Tag::TableHead, limit, next); - } else { - panic!(); - } - } - - fn start_table_body(&mut self) -> Event<'a> { - assert!(self.opts.contains(OPTION_ENABLE_TABLES)); - let (off, _) = match self.scan_containers(&self.text[self.off ..]) { - (n, true, space) => (self.off + n, space), - _ => { - return self.end(); - } - }; - let n = scan_blank_line(&self.text[off..]); - if n != 0 { - self.off = off + n; - return self.end(); - } - self.state = State::TableRow; - self.off = off; - return self.start(Tag::TableRow, self.text.len(), 0); - } - - fn start_hrule(&mut self) -> Event<'a> { - let limit = self.off; // body of hrule is empty - self.state = State::Inline; // handy state for producing correct end tag - self.start(Tag::Rule, limit, limit) - } - - fn start_atx_header(&mut self, level: i32) -> Event<'a> { - self.skip_leading_whitespace(); - let tail = &self.text[self.off..]; - let next = scan_nextline(tail); - let mut limit = next; - while limit > 0 && is_ascii_whitespace(tail.as_bytes()[limit - 1]) { - limit -= 1; - } - let mut end = limit; - while end > 0 && tail.as_bytes()[end - 1] == b'#' { - end -= 1; - } - if end == 0 { - limit = end; - } else if is_ascii_whitespace(tail.as_bytes()[end - 1]) { - limit = end - 1; - } - while limit > 0 && is_ascii_whitespace(tail.as_bytes()[limit - 1]) { - limit -= 1; - } - let limit = limit + self.off; - let next = next + self.off; - self.state = State::Inline; - self.start(Tag::Header(level), limit, next) - } - - fn start_indented_code(&mut self) -> Event<'a> { - self.fence_char = b'\0'; - self.fence_indent = 4; - let size = self.text.len(); - self.state = State::Code; - self.start(Tag::CodeBlock(Borrowed("")), size, 0) - } - - fn start_listitem(&mut self, n: usize, c: u8, start: usize, indent: usize) -> Event<'a> { - let indent = self.leading_space + indent; - match self.containers.last() { - Some(&Container::List(_, c2)) => { - if c != c2 { - // mismatched list type or delimeter - return self.end(); - } - self.off += n; - let n_blank = scan_blank_line(&self.text[self.off ..]); - if n_blank != 0 { - self.off += n_blank; - self.state = State::StartBlock; - } else { - // TODO: deal with tab - let (n, space) = scan_leading_space(self.text, self.off); - self.off += n; - self.leading_space = space; - } - self.containers.push(Container::ListItem(indent)); - self.start(Tag::Item, self.text.len(), 0) - } - _ => { - self.containers.push(Container::List(self.off, c)); - // arguably this should be done in the scanner, it should return option - let startopt = if c == b'.' || c == b')' { Some(start) } else { None }; - self.start(Tag::List(startopt), self.text.len(), 0) - } - } - } - - fn start_code_fence(&mut self, n: usize, ch: u8, count: usize) -> Event<'a> { - self.fence_char = ch; - self.fence_count = count; - self.fence_indent = self.leading_space; - let beg_info = self.off + n; - let next_line = beg_info + scan_nextline(&self.text[beg_info..]); - self.off = next_line; - let info = unescape(&self.text[beg_info..next_line].trim()); - let size = self.text.len(); - self.state = State::CodeLineStart; - self.start(Tag::CodeBlock(info), size, 0) - } - - fn next_code_line_start(&mut self) -> Event<'a> { - let (off, space) = match self.scan_containers(&self.text[self.off ..]) { - (n, true, space) => (self.off + n, space), - _ => { - return self.end(); - } - }; - - if self.fence_char == b'\0' { - let n = scan_blank_line(&self.text[off..]); - if n != 0 { - // TODO performance: this scanning is O(n^2) in the number of empty lines - let (n_empty, _lines) = self.scan_empty_lines(&self.text[off + n ..]); - let next = off + n + n_empty; - let (n_containers, scanned, nspace) = self.scan_containers(&self.text[next..]); - // TODO; handle space - if !scanned || self.is_code_block_end(next + n_containers, nspace) { - //println!("was end: {}", next + n_containers); - return self.end(); - } else { - self.off = off; - //println!("code line start space={}, off={}", space, off); - self.leading_space = space; - return self.next_code(); - } - } - } - - if self.is_code_block_end(off, space) { - let ret = self.end(); - if self.fence_char != b'\0' { - self.off = off + scan_nextline(&self.text[off..]); - } - ret - } else { - self.off = off; - self.state = State::Code; - self.leading_space = space; - self.next_code() - } - } - - fn next_code(&mut self) -> Event<'a> { - if self.leading_space > self.fence_indent { - // TODO: might try to combine spaces in text, for fewer events - let space = self.leading_space; - self.leading_space = 0; - return Event::Text(spaces(space - self.fence_indent)); - } - let bytes = self.text.as_bytes(); - let mut beg = self.off; - let mut i = beg; - loop { - match bytes[i..].iter().position(|&c| c < b' ') { - Some(j) => i += j, - None => { - i += bytes[i..].len(); - break; - } - } - match bytes[i] { - b'\n' => { - i += 1; - self.state = State::CodeLineStart; - break; - } - b'\t' => { - if i > beg { break; } - return self.char_tab(); - } - b'\r' => { - // just skip it (does not support '\r' only line break) - if i > beg { break; } - beg += 1; - } - _ => () - } - i += 1; - } - self.off = i; - Event::Text(Borrowed(&self.text[beg..i])) - } - - fn is_code_block_end(&self, loc: usize, space: usize) -> bool { - let tail = &self.text[loc..]; - if self.fence_char == b'\0' { - // indented code block - space < 4 - } else if space <= 3 { - let (n, c) = scan_code_fence(tail); - if c != self.fence_char || n < self.fence_count { - return false; - } - if n < tail.len() && scan_blank_line(&tail[n..]) == 0 { - // Closing code fences cannot have info strings - return false; - } - return true; - } else { - false - } - } - - // # HTML blocks - - fn scan_html_block_tag(&self, data: &'a str) -> (usize, &'a str) { - let mut i = scan_ch(data, b'<'); - if i == 0 { return (0, "") } - i += scan_ch(&data[i..], b'/'); - let n = scan_while(&data[i..], is_ascii_alphanumeric); - // TODO: scan attributes and > - (i + n, &data[i .. i + n]) - } - - fn is_html_block(&self, data: &str) -> bool { - let (n_tag, tag) = self.scan_html_block_tag(data); - (n_tag > 0 && is_html_tag(tag)) || - data.starts_with(" Event<'a> { - let size = self.text.len(); - let mut out = Borrowed(""); - let mut i = self.off; - let mut mark = i; - loop { - let n = scan_nextline(&self.text[i..]); - i += n; - if n >= 2 && self.text.as_bytes()[i - 2] == b'\r' { - if self.leading_space > 0 { - out = utils::cow_append(out, spaces(self.leading_space)); - self.leading_space = 0; - } - out = utils::cow_append(out, Borrowed(&self.text[mark .. i - 2])); - mark = i - 1; - } - let (n, scanned, space) = self.scan_containers(&self.text[i..]); - let n_blank = scan_blank_line(&self.text[i + n ..]); - if n != 0 || !scanned || i + n == size || n_blank != 0 { - if self.leading_space > 0 { - out = utils::cow_append(out, spaces(self.leading_space)); - } - self.leading_space = space; - out = utils::cow_append(out, Borrowed(&self.text[mark..i])); - mark = i + n; - } - if !scanned || i + n == size || n_blank != 0 { - self.off = i; // TODO: skip blank lines (cleaner source maps) - self.state = State::StartBlock; - return Event::Html(out) - } - } - } - - // # Link reference definitions - - fn try_link_reference_definition(&mut self, data: &'a str) -> bool { - let (n_link, text_beg, text_end, max_nest) = self.scan_link_label(data); - if n_link == 0 || max_nest > 1 { return false; } - let n_colon = scan_ch(&data[n_link ..], b':'); - if n_colon == 0 { return false; } - let mut i = n_link + n_colon; - i += self.scan_whitespace_inline(&data[i..]); - let linkdest = scan_link_dest(&data[i..]); - if linkdest.is_none() { return false; } - let (n_dest, raw_dest) = linkdest.unwrap(); - if n_dest == 0 { return false; } - i += n_dest; - i += scan_whitespace_no_nl(&data[i..]); - let n_nl = self.scan_whitespace_inline(&data[i..]); - let (n_title, title_beg, title_end) = self.scan_link_title(&data[i + n_nl ..]); - let title = if n_title == 0 { - Borrowed("") - } else { - let (title_beg, title_end) = (i + n_nl + title_beg, i + n_nl + title_end); - i += n_nl + n_title; - unescape(&data[title_beg..title_end]) - }; - i += scan_whitespace_no_nl(&data[i..]); - if let (n_eol, true) = scan_eol(&data[i..]) { - i += n_eol; - } else { - return false; - } - - let linktext = self.normalize_link_ref(&data[text_beg..text_end]); - if linktext.is_empty() { - return false; - } - if !self.links.contains_key(&linktext) { - let dest = unescape(raw_dest); - self.links.insert(linktext, (dest, title)); - } - self.state = State::StartBlock; - self.off += i; - true - } - - // normalize whitespace and case-fold - fn normalize_link_ref(&self, raw: &str) -> String { - let mut need_space = false; - let mut result = String::new(); - let mut i = 0; - while i < raw.len() { - let n = scan_nextline(&raw[i..]); - for c in raw[i.. i + n].chars() { - if c.is_whitespace() { - need_space = true; - } else { - if need_space && !result.is_empty() { - result.push(' '); - } - // TODO: Unicode case folding can differ from lowercase (ß) - result.extend(c.to_lowercase()); - need_space = false; - } - } - i += n; - if i == raw.len() { break; } - i += self.scan_containers(&raw[i..]).0; - need_space = true; - } - result - } - - // determine whether the line starting at loc ends the block - fn is_inline_block_end(&self, data: &str, space: usize) -> bool { - data.is_empty() || - scan_blank_line(data) != 0 || - space <= 3 && (scan_hrule(data) != 0 || - scan_atx_header(data).0 != 0 || - scan_code_fence(data).0 != 0 || - scan_blockquote_start(data) != 0 || - scan_listitem(data).0 != 0 || - self.is_html_block(data)) - } - - fn next_table_cell(&mut self) -> Event<'a> { - assert!(self.opts.contains(OPTION_ENABLE_TABLES)); - let bytes = self.text.as_bytes(); - let mut beg = self.off + scan_whitespace_no_nl(&self.text[self.off ..]); - let mut i = beg; - let limit = self.limit(); - if i < limit && bytes[i] == b'|' { - i += 1; - beg += 1; - self.off += 1; - } - if i >= limit { - self.off = limit; - return self.end(); - } - let mut n = 0; - while i < limit { - let c = bytes[i]; - if c == b'\\' && i + 1 < limit && bytes[i + 1] == b'|' { - i += 2; - continue; - } else if c == b'|' { - n = 0; - break; - } - n = if is_ascii_whitespace(bytes[i]) { scan_blank_line(&self.text[i..]) } else { 0 }; - if n != 0 { - if i > beg { - n = 0; - } - break; - } - i += 1; - } - if i > beg { - self.state = State::Inline; - self.start(Tag::TableCell, i, i + n) - } else { - self.off = i + n; - self.end() - } - } - - fn next_inline(&mut self) -> Event<'a> { - let bytes = self.text.as_bytes(); - let beg = self.off; - let mut i = beg; - let limit = self.limit(); - while i < limit { - match bytes[i..limit].iter().position(|&c| self.active_tab[c as usize] != 0) { - Some(pos) => i += pos, - None => { i = limit; break; } - } - let c = bytes[i]; - if c == b'\n' || c == b'\r' { - let n = scan_trailing_whitespace(&self.text[beg..i]); - let end = i - n; - if end > beg { - self.off = end; - return Event::Text(Borrowed(&self.text[beg..end])); - } - if c == b'\r' && i + 1 < limit && self.text.as_bytes()[i + 1] == b'\n' { - i += 1; - } - i += 1; - let next = i; - let (n_containers, _, space) = self.scan_containers(&self.text[i..limit]); - i += n_containers; - if self.is_inline_block_end(&self.text[i..limit], space) { - self.off = next; - return self.end(); - } - i += scan_whitespace_no_nl(&self.text[i..limit]); - self.off = i; - return if n >= 2 { Event::HardBreak } else { Event::SoftBreak }; - } - self.off = i; - if i > beg { - return Event::Text(Borrowed(&self.text[beg..i])); - } - if let Some(event) = self.active_char(c) { - return event; - } - i = self.off; // let handler advance offset even on None - i += 1; - } - if i > beg { - self.off = i; - Event::Text(Borrowed(&self.text[beg..i])) - } else { - self.end() - } - } - - fn active_char(&mut self, c: u8) -> Option> { - match c { - b'\x00' => Some(self.char_null()), - b'\t' => Some(self.char_tab()), - b'\\' => self.char_backslash(), - b'&' => self.char_entity(), - b'_' => self.char_emphasis(), - b'*' => self.char_emphasis(), - b'[' if self.opts.contains(OPTION_ENABLE_FOOTNOTES) => self.char_link_footnote(), - b'[' | b'!' => self.char_link(), - b'`' => self.char_backtick(), - b'<' => self.char_lt(), - _ => None - } - } - - fn char_null(&mut self) -> Event<'a> { - self.off += 1; - Event::Text(Borrowed(&"\u{fffd}")) - } - - // expand tab in content (used for code and inline) - // scan backward to find offset, counting unicode code points - fn char_tab(&mut self) -> Event<'a> { - let count = count_tab(&self.text.as_bytes()[.. self.off]); - self.off += 1; - Event::Text(Borrowed(&" "[..count])) - } - - fn char_backslash(&mut self) -> Option> { - let limit = self.limit(); - if self.off + 1 < limit { - if let (_, true) = scan_eol(&self.text[self.off + 1 .. limit]) { - let n_white = self.scan_whitespace_inline(&self.text[self.off + 1 .. limit]); - let space = 0; // TODO: figure this out - if !self.is_inline_block_end(&self.text[self.off + 1 + n_white .. limit], space) { - self.off += 1 + n_white; - return Some(Event::HardBreak); - } - } - let c = self.text.as_bytes()[self.off + 1]; - if is_ascii_punctuation(c) { - self.off += 2; - return Some(Event::Text(Borrowed(&self.text[self.off - 1 .. self.off]))); - } - } - None - } - - fn char_entity(&mut self) -> Option> { - match scan_entity(&self.text[self.off ..]) { - (n, Some(value)) => { - self.off += n; - Some(Event::Text(value)) - } - _ => None - } - } - - fn char_emphasis(&mut self) -> Option> { - // can see to left for flanking info, but not past limit - let limit = self.limit(); - let data = &self.text[..limit]; - - let c = data.as_bytes()[self.off]; - let (n, can_open, _can_close) = compute_open_close(data, self.off, c); - if !can_open { - return None; - } - let mut stack = vec![n]; // TODO performance: don't allocate - let mut i = self.off + n; - while i < limit { - let c2 = data.as_bytes()[i]; - if c2 == b'\n' && !is_escaped(data, i) { - let space = 0; // TODO: scan containers - if self.is_inline_block_end(&self.text[i + 1 .. limit], space) { - return None - } else { - i += 1; - } - } else if c2 == c && !is_escaped(data, i) { - let (mut n2, can_open, can_close) = compute_open_close(data, i, c); - if can_close { - loop { - let ntos = stack.pop().unwrap(); - if ntos > n2 { - stack.push(ntos - n2); - break; - } - if stack.is_empty() { - let npop = if ntos < n2 { ntos } else { n2 }; - if npop == 1 { - self.off += 1; - return Some(self.start(Tag::Emphasis, i, i + 1)); - } else { - self.off += 2; - let next = i + npop; - return Some(self.start(Tag::Strong, next - 2, next)); - } - } else { - i += ntos; - n2 -= ntos; - } - } - } else if can_open { - stack.push(n2); - } - i += n2; - } else if c2 == b'`' { - let (n, beg, _) = self.scan_inline_code(&self.text[i..limit]); - if n != 0 { - i += n; - } else { - i += beg; - } - } else if c2 == b'<' { - let n = self.scan_autolink_or_html(&self.text[i..limit]); - if n != 0 { - i += n; - } else { - i += 1; - } - } else if c2 == b'[' { - if self.opts.contains(OPTION_ENABLE_FOOTNOTES) { - if let Some((_, n)) = self.parse_footnote(&self.text[i..limit]) { - i += n; - continue; - } - } - if let Some((_, _, _, n)) = self.parse_link(&self.text[i..limit], false) { - i += n; - } else { - i += 1; - } - } else { - i += 1; - } - } - None - } - - // # Links - - // scans a link label, example [link] - // return value is: total bytes, start of text, end of text, max nesting - fn scan_link_label(&self, data: &str) -> (usize, usize, usize, usize) { - let mut i = scan_ch(data, b'['); - if i == 0 { return (0, 0, 0, 0); } - let text_beg = i; - let mut max_nest = 1; - let mut nest = 1; - loop { - if i >= data.len() { return (0, 0, 0, 0); } - match data.as_bytes()[i] { - b'\n' => { - let n = self.scan_whitespace_inline(&data[i..]); - if n == 0 { return (0, 0, 0, 0); } - i += n; - } - b'[' => { - nest += 1; - if nest == MAX_LINK_NEST { return (0, 0, 0, 0); } - max_nest = cmp::max(max_nest, nest); - i += 1; - } - b']' => { - nest -= 1; - if nest == 0 { - break; - } - i += 1; - } - b'\\' => i += 1, - b'<' => { - let n = self.scan_autolink_or_html(&data[i..]); - if n != 0 { - i += n; - } else { - i += 1; - } - } - b'`' => { - let (n, beg, _) = self.scan_inline_code(&data[i..]); - if n != 0 { - i += n; - } else { - i += beg; - } - } - _ => i += 1 - } - } - let text_end = i; - i += 1; // skip closing ] - (i, text_beg, text_end, max_nest) - } - - fn scan_link_title(&self, data: &str) -> (usize, usize, usize) { - let size = data.len(); - if size == 0 { return (0, 0, 0); } - let mut i = 0; - let titleclose = match data.as_bytes()[i] { - b'(' => b')', - b'\'' => b'\'', - b'\"' => b'\"', - _ => return (0, 0, 0) - }; - i += 1; - let title_beg = i; - while i < size { - match data.as_bytes()[i] { - x if x == titleclose => break, - b'\\' => i += 2, // may be > size - b'\n' => { - let n = self.scan_whitespace_inline(&data[i..]); - if n == 0 { return (0, 0, 0); } - i += n; - } - _ => i += 1 - } - } - if i >= size { return (0, 0, 0); } - let title_end = i; - i += 1; - (i, title_beg, title_end) - } - - fn char_link(&mut self) -> Option> { - self.parse_link(&self.text[self.off .. self.limit()], false).map(|(tag, beg, end, n)| { - let off = self.off; - self.off += beg; - self.start(tag, off + end, off + n) - }) - } - - // return: tag, begin, end, total size - fn parse_link(&self, data: &'a str, recur: bool) -> Option<(Tag<'a>, usize, usize, usize)> { - let size = data.len(); - - // scan link text - let i = scan_ch(data, b'!'); - let is_image = i == 1; - let (n, text_beg, text_end, max_nest) = self.scan_link_label(&data[i..]); - if n == 0 { return None; } - let (text_beg, text_end) = (text_beg + i, text_end + i); - if !is_image && !recur && max_nest > 1 && self.contains_link(&data[text_beg..text_end]) { - // disallow nested links in links (but ok in images) - return None; - } - let mut i = i + n; - - // scan dest - let (dest, title, beg, end, next) = if data[i..].starts_with("(") { - i += 1; - i += self.scan_whitespace_inline(&data[i..]); - if i >= size { return None; } - - let linkdest = scan_link_dest(&data[i..]); - if linkdest.is_none() { return None; } - let (n, raw_dest) = linkdest.unwrap(); - let dest = unescape(raw_dest); - i += n; - - i += self.scan_whitespace_inline(&data[i..]); - if i == size { return None; } - - // scan title - let (n_title, title_beg, title_end) = self.scan_link_title(&data[i..]); - let title = if n_title == 0 { - Borrowed("") - } else { - let (title_beg, title_end) = (i + title_beg, i + title_end); - i += n_title; - // TODO: not just unescape, remove containers from newlines - unescape(&data[title_beg..title_end]) - }; - i += self.scan_whitespace_inline(&data[i..]); - if i == size || data.as_bytes()[i] != b')' { return None; } - i += 1; - (dest, title, text_beg, text_end, i) - } else { - // try link reference - let j = i + self.scan_whitespace_inline(&data[i..]); - let (n_ref, ref_beg, ref_end, _) = self.scan_link_label(&data[j..]); - let (ref_beg, ref_end) = if n_ref == 0 || ref_beg == ref_end { - (text_beg, text_end) - } else { - (j + ref_beg, j + ref_end) - }; - if n_ref != 0 { - i = j + n_ref; - } - let reference = self.normalize_link_ref(&data[ref_beg..ref_end]); - let (dest, title) = match self.links.get(&reference) { - Some(&(ref dest, ref title)) => (dest.clone(), title.clone()), - None => return None - }; - (dest, title, text_beg, text_end, i) - }; - if is_image { - Some((Tag::Image(dest, title), beg, end, next)) - } else { - Some((Tag::Link(dest, title), beg, end, next)) - } - } - - // determine whether there's a link anywhere in the text - // TODO: code duplication with scan_link_label is unpleasant - fn contains_link(&self, data: &str) -> bool { - let mut i = 0; - while i < data.len() { - match data.as_bytes()[i] { - b'\n' => { - let n = self.scan_whitespace_inline(&data[i..]); - if n == 0 { return false; } - i += n; - continue; - } - b'!' => { - if scan_ch(&data[i + 1 ..], b'[') != 0 { - // ok to contain image, skip over opening bracket - i += 1; - } - } - b'[' => { - if self.opts.contains(OPTION_ENABLE_FOOTNOTES) && self.parse_footnote(&data[i..]).is_some() { - return false; - } - if self.parse_link(&data[i..], true).is_some() { return true; } - } - b'\\' => i += 1, - b'<' => { - let n = self.scan_autolink_or_html(&data[i..]); - if n != 0 { - i += n; - } else { - i += 1; - } - } - b'`' => { - let (n, beg, _) = self.scan_inline_code(&data[i..]); - if n != 0 { - i += n; - } else { - i += beg; - } - } - _ => () - } - i += 1; - } - false - } - - // # Footnotes - - fn parse_footnote_definition<'b>(&self, data: &'b str) -> Option<(&'b str, usize)> { - assert!(self.opts.contains(OPTION_ENABLE_FOOTNOTES)); - self.parse_footnote(data).and_then(|(name, len)| { - let n_colon = scan_ch(&data[len ..], b':'); - if n_colon == 0 { - None - } else { - let space = scan_whitespace_no_nl(&data[len + n_colon..]); - Some((name, len + n_colon + space)) - } - }) - } - - fn char_link_footnote(&mut self) -> Option> { - assert!(self.opts.contains(OPTION_ENABLE_FOOTNOTES)); - if let Some((name, end)) = self.parse_footnote(&self.text[self.off .. self.limit()]) { - self.off += end; - Some(Event::FootnoteReference(Cow::Borrowed(name))) - } else { - self.char_link() - } - } - - fn parse_footnote<'b>(&self, data: &'b str) -> Option<(&'b str, usize)> { - assert!(self.opts.contains(OPTION_ENABLE_FOOTNOTES)); - let (n_footnote, text_beg, text_end) = self.scan_footnote_label(data); - if n_footnote == 0 { return None; } - return Some((&data[text_beg..text_end], n_footnote)); - } - - fn scan_footnote_label(&self, data: &str) -> (usize, usize, usize) { - assert!(self.opts.contains(OPTION_ENABLE_FOOTNOTES)); - let mut i = scan_ch(data, b'['); - if i == 0 { return (0, 0, 0); } - if i >= data.len() || data.as_bytes()[i] != b'^' { return (0, 0, 0); } - i += 1; - let text_beg = i; - loop { - if i >= data.len() { return (0, 0, 0); } - match data.as_bytes()[i] { - b'\n' => { - let n = self.scan_whitespace_inline(&data[i..]); - if n == 0 { return (0, 0, 0); } - i += n; - continue; - } - b']' => break, - b'\\' => i += 1, - _ => () - } - i += 1; - } - let text_end = i; - i += 1; // skip closing ] - (i, text_beg, text_end) - } - - // # Autolinks and inline HTML - - fn char_lt(&mut self) -> Option> { - let tail = &self.text[self.off .. self.limit()]; - if let Some((n, link)) = scan_autolink(tail) { - let next = self.off + n; - self.off += 1; - self.state = State::Literal; - return Some(self.start(Tag::Link(link, Borrowed("")), next - 1, next)) - } - let n = self.scan_inline_html(tail); - if n != 0 { - return Some(self.inline_html_event(n)) - } - None - } - - fn scan_autolink_or_html(&self, data: &str) -> usize { - if let Some((n, _)) = scan_autolink(data) { - n - } else { - self.scan_inline_html(data) - } - } - - fn scan_inline_html(&self, data: &str) -> usize { - let n = self.scan_html_tag(data); - if n != 0 { return n; } - let n = self.scan_html_comment(data); - if n != 0 { return n; } - let n = self.scan_processing_instruction(data); - if n != 0 { return n; } - let n = self.scan_declaration(data); - if n != 0 { return n; } - let n = self.scan_cdata(data); - if n != 0 { return n; } - 0 - } - - fn scan_html_tag(&self, data: &str) -> usize { - let size = data.len(); - let mut i = 0; - if scan_ch(data, b'<') == 0 { return 0; } - i += 1; - let n_slash = scan_ch(&data[i..], b'/'); - i += n_slash; - if i == size || !is_ascii_alpha(data.as_bytes()[i]) { return 0; } - i += 1; - i += scan_while(&data[i..], is_ascii_alphanumeric); - if n_slash == 0 { - loop { - let n = self.scan_whitespace_inline(&data[i..]); - if n == 0 { break; } - i += n; - let n = scan_attribute_name(&data[i..]); - if n == 0 { break; } - i += n; - let n = self.scan_whitespace_inline(&data[i..]); - if scan_ch(&data[i + n ..], b'=') != 0 { - i += n + 1; - i += self.scan_whitespace_inline(&data[i..]); - let n_attr = self.scan_attribute_value(&data[i..]); - if n_attr == 0 { return 0; } - i += n_attr; - } - } - i += self.scan_whitespace_inline(&data[i..]); - i += scan_ch(&data[i..], b'/'); - } else { - i += self.scan_whitespace_inline(&data[i..]); - } - if scan_ch(&data[i..], b'>') == 0 { return 0; } - i += 1; - i - } - - fn scan_attribute_value(&self, data: &str) -> usize { - let size = data.len(); - if size == 0 { return 0; } - let open = data.as_bytes()[0]; - let quoted = open == b'\'' || open == b'"'; - let mut i = if quoted { 1 } else { 0 }; - while i < size { - let c = data.as_bytes()[i]; - match c { - b'\n' => { - if !quoted { break; } - let n = self.scan_whitespace_inline(&data[i..]); - if n == 0 { return 0; } - i += n; - } - b'\'' | b'"' | b'=' | b'<' | b'>' | b'`' | b'\t' ... b' ' => { - if !quoted || c == open { break; } - i += 1; - } - _ => i += 1 - } - } - if quoted { - if i == size || data.as_bytes()[i] != open { return 0; } - i += 1; - } - i - } - - fn scan_html_comment(&self, data: &str) -> usize { - if !data.starts_with("

"; - let thing = Json::String(raw.to_string()); - - assert_eq!(raw, thing.render()); - } - - struct Address { - city: String, - country: String, - } - - impl ToJson for Address { - fn to_json(&self) -> Json { - let mut m = BTreeMap::new(); - m.insert("city".to_string(), self.city.to_json()); - m.insert("country".to_string(), self.country.to_json()); - Json::Object(m) - } - } - - struct Person { - name: String, - age: i16, - addr: Address, - titles: Vec, - } - - impl ToJson for Person { - fn to_json(&self) -> Json { - let mut m = BTreeMap::new(); - m.insert("name".to_string(), self.name.to_json()); - m.insert("age".to_string(), self.age.to_json()); - m.insert("addr".to_string(), self.addr.to_json()); - m.insert("titles".to_string(), self.titles.to_json()); - Json::Object(m) - } - } - - #[test] - fn test_render() { - let v = "hello"; - let ctx = Context::wraps(&v.to_string()); - assert_eq!(ctx.navigate(".", &VecDeque::new(), "this").render(), - v.to_string()); - } #[test] fn test_key_name_with_this() { @@ -485,87 +351,4 @@ mod test { assert_eq!(ctx.navigate(".", &VecDeque::new(), "this_name").render(), "the_value".to_string()); } - - #[test] - fn test_navigation() { - let addr = Address { - city: "Beijing".to_string(), - country: "China".to_string(), - }; - - let person = Person { - name: "Ning Sun".to_string(), - age: 27, - addr: addr, - titles: vec!["programmer".to_string(), "cartographier".to_string()], - }; - - let ctx = Context::wraps(&person); - assert_eq!(ctx.navigate(".", &VecDeque::new(), "./name/../addr/country").render(), - "China".to_string()); - assert_eq!(ctx.navigate(".", &VecDeque::new(), "addr.[country]").render(), - "China".to_string()); - assert_eq!(ctx.navigate(".", &VecDeque::new(), "addr.[\"country\"]").render(), - "China".to_string()); - assert_eq!(ctx.navigate(".", &VecDeque::new(), "addr.['country']").render(), - "China".to_string()); - - let v = true; - let ctx2 = Context::wraps(&v); - assert_eq!(ctx2.navigate(".", &VecDeque::new(), "this").render(), - "true".to_string()); - - assert_eq!(ctx.navigate(".", &VecDeque::new(), "titles[0]").render(), - "programmer".to_string()); - assert_eq!(ctx.navigate(".", &VecDeque::new(), "titles.[0]").render(), - "programmer".to_string()); - - assert_eq!(ctx.navigate(".", &VecDeque::new(), "titles[0]/../../age").render(), - "27".to_string()); - assert_eq!(ctx.navigate(".", &VecDeque::new(), "this.titles[0]/../../age").render(), - "27".to_string()); - - } - - #[test] - fn test_this() { - let mut map_with_this = BTreeMap::new(); - map_with_this.insert("this".to_string(), "hello".to_json()); - map_with_this.insert("age".to_string(), 5usize.to_json()); - let ctx1 = Context::wraps(&map_with_this); - - let mut map_without_this = BTreeMap::new(); - map_without_this.insert("age".to_string(), 4usize.to_json()); - let ctx2 = Context::wraps(&map_without_this); - - assert_eq!(ctx1.navigate(".", &VecDeque::new(), "this").render(), - "hello".to_owned()); - assert_eq!(ctx2.navigate(".", &VecDeque::new(), "age").render(), - "4".to_owned()); - } - - #[test] - fn test_extend() { - let mut map = BTreeMap::new(); - map.insert("age".to_string(), 4usize.to_json()); - let ctx1 = Context::wraps(&map); - - let s = "hello".to_owned(); - let ctx2 = Context::wraps(&s); - - let mut hash = BTreeMap::new(); - hash.insert("tag".to_owned(), "h1".to_json()); - - let ctx_a1 = ctx1.extend(&hash); - assert_eq!(ctx_a1.navigate(".", &VecDeque::new(), "age").render(), - "4".to_owned()); - assert_eq!(ctx_a1.navigate(".", &VecDeque::new(), "tag").render(), - "h1".to_owned()); - - let ctx_a2 = ctx2.extend(&hash); - assert_eq!(ctx_a2.navigate(".", &VecDeque::new(), "this").render(), - "hello".to_owned()); - assert_eq!(ctx_a2.navigate(".", &VecDeque::new(), "tag").render(), - "h1".to_owned()); - } } diff --git a/src/vendor/handlebars/src/directives/inline.rs b/src/vendor/handlebars/src/directives/inline.rs index 525c1e68f0..afb798b9cf 100644 --- a/src/vendor/handlebars/src/directives/inline.rs +++ b/src/vendor/handlebars/src/directives/inline.rs @@ -5,18 +5,6 @@ use render::{RenderError, RenderContext, Directive}; #[derive(Clone, Copy)] pub struct InlineDirective; -#[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))] -fn get_name<'a>(d: &'a Directive) -> Result<&'a str, RenderError> { - d.param(0) - .ok_or_else(|| RenderError::new("Param required for directive \"inline\"")) - .and_then(|v| { - v.value() - .as_string() - .ok_or_else(|| RenderError::new("inline name must be string")) - }) -} - -#[cfg(feature = "serde_type")] fn get_name<'a>(d: &'a Directive) -> Result<&'a str, RenderError> { d.param(0) .ok_or_else(|| RenderError::new("Param required for directive \"inline\"")) diff --git a/src/vendor/handlebars/src/directives/mod.rs b/src/vendor/handlebars/src/directives/mod.rs index 1d5205cd7c..81e693fe56 100644 --- a/src/vendor/handlebars/src/directives/mod.rs +++ b/src/vendor/handlebars/src/directives/mod.rs @@ -14,16 +14,15 @@ pub use self::inline::INLINE_DIRECTIVE; /// /// In decorator, you can change some context data your are about to render. /// -/// ```ignore +/// ``` /// use handlebars::*; -/// use rustc_serialize::json::ToJson; /// /// fn update_data(_: &Decorator, _: &Handlebars, rc: &mut RenderContext) /// -> Result<(), RenderError> { /// // modify json object /// let mut ctx_ref = rc.context_mut(); /// if let Some(ref mut m) = ctx_ref.data_mut().as_object_mut() { -/// m.insert("hello".to_string(), "world".to_owned().to_json()); +/// m.insert("hello".to_string(), to_json(&"world".to_owned())); /// } /// Ok(()) /// } diff --git a/src/vendor/handlebars/src/grammar.rs b/src/vendor/handlebars/src/grammar.rs index 476814272b..8d67079494 100644 --- a/src/vendor/handlebars/src/grammar.rs +++ b/src/vendor/handlebars/src/grammar.rs @@ -111,7 +111,7 @@ impl_rdp! { path_ident = _{ ['a'..'z']|['A'..'Z']|['0'..'9']|["_"]|["@"]|["$"]|["<"]|[">"]|["-"]} path_id = { path_ident+ } path_num_id = { ['0'..'9']+ } - path_raw_id = { path_ident* } + path_raw_id = { (path_ident|["/"])* } path_sep = _{ ["/"] | ["."] } path_up = { [".."] } path_var = { path_id } @@ -233,7 +233,7 @@ impl_rdp! { path_ident = _{ ['a'..'z']|['A'..'Z']|['0'..'9']|["_"]|["@"]|["$"]|["<"]|[">"]|["-"]} path_id = { path_ident+ } path_num_id = { ['0'..'9']+ } - path_raw_id = { path_ident* } + path_raw_id = { (path_ident|["/"])* } path_sep = _{ ["/"] | ["."] } path_up = { [".."] } path_var = { path_id } @@ -482,7 +482,8 @@ fn test_path() { "a[\"bbc\"]/b/c/../d", "../a/b[0][1]", "./this[0][1]/this/../a", - "./this_name"]; + "./this_name", + "./goo[/bar]"]; for i in s.iter() { let mut rdp = Rdp::new(StringInput::new(i)); assert!(rdp.path()); diff --git a/src/vendor/handlebars/src/helpers/helper_each.rs b/src/vendor/handlebars/src/helpers/helper_each.rs index 5fbcac8d78..fe23074e18 100644 --- a/src/vendor/handlebars/src/helpers/helper_each.rs +++ b/src/vendor/handlebars/src/helpers/helper_each.rs @@ -1,8 +1,5 @@ use std::collections::BTreeMap; -#[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))] -use serialize::json::Json; -#[cfg(feature = "serde_type")] use serde_json::value::Value as Json; use helpers::HelperDef; @@ -131,9 +128,8 @@ mod test { use context::to_json; use std::collections::BTreeMap; - - #[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))] - use serialize::json::Json; + use std::str::FromStr; + use serde_json::value::Value as Json; #[test] fn test_each() { @@ -155,7 +151,6 @@ mod test { } #[test] - #[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))] fn test_each_with_parent() { let json_str = r#"{"a":{"a":99,"c":[{"d":100},{"d":200}]}}"#; @@ -176,7 +171,6 @@ mod test { } #[test] - #[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))] fn test_nested_each_with_parent() { let json_str = r#"{"a": [{"b": [{"d": 100}], "c": 200}]}"#; @@ -190,7 +184,6 @@ mod test { } #[test] - #[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))] fn test_nested_each() { let json_str = r#"{"a": [{"b": true}], "b": [[1, 2, 3],[4, 5]]}"#; diff --git a/src/vendor/handlebars/src/helpers/helper_if.rs b/src/vendor/handlebars/src/helpers/helper_if.rs index 0f767794c0..65e5d516ff 100644 --- a/src/vendor/handlebars/src/helpers/helper_if.rs +++ b/src/vendor/handlebars/src/helpers/helper_if.rs @@ -33,9 +33,8 @@ pub static UNLESS_HELPER: IfHelper = IfHelper { positive: false }; #[cfg(test)] mod test { use registry::Registry; - #[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))] - use serialize::json::Json; - #[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))] + use std::str::FromStr; + use serde_json::value::Value as Json; use helpers::WITH_HELPER; #[test] @@ -57,7 +56,6 @@ mod test { } #[test] - #[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))] fn test_if_context() { let json_str = r#"{"a":{"b":99,"c":{"d": true}}}"#; let data = Json::from_str(json_str).unwrap(); diff --git a/src/vendor/handlebars/src/helpers/helper_lookup.rs b/src/vendor/handlebars/src/helpers/helper_lookup.rs index a4feaad51a..64c5215cdb 100644 --- a/src/vendor/handlebars/src/helpers/helper_lookup.rs +++ b/src/vendor/handlebars/src/helpers/helper_lookup.rs @@ -1,6 +1,3 @@ -#[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))] -use serialize::json::Json; -#[cfg(feature = "serde_type")] use serde_json::value::Value as Json; use helpers::HelperDef; @@ -29,14 +26,6 @@ impl HelperDef for LookupHelper { .and_then(|u| v.get(u)) .unwrap_or(&null) } - #[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))] - &Json::Object(ref m) => { - index.value() - .as_string() - .and_then(|k| m.get(k)) - .unwrap_or(&null) - } - #[cfg(feature = "serde_type")] &Json::Object(ref m) => { index.value() .as_str() diff --git a/src/vendor/handlebars/src/helpers/helper_with.rs b/src/vendor/handlebars/src/helpers/helper_with.rs index ab06c3f731..c22ca913af 100644 --- a/src/vendor/handlebars/src/helpers/helper_with.rs +++ b/src/vendor/handlebars/src/helpers/helper_with.rs @@ -62,28 +62,17 @@ impl HelperDef for WithHelper { pub static WITH_HELPER: WithHelper = WithHelper; #[cfg(test)] -#[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))] mod test { use registry::Registry; use context::to_json; - use std::collections::BTreeMap; - use serialize::json::{Json, ToJson}; - + #[derive(Serialize)] struct Address { city: String, country: String, } - impl ToJson for Address { - fn to_json(&self) -> Json { - let mut m = BTreeMap::new(); - m.insert("city".to_string(), self.city.to_json()); - m.insert("country".to_string(), self.country.to_json()); - Json::Object(m) - } - } - + #[derive(Serialize)] struct Person { name: String, age: i16, @@ -91,17 +80,6 @@ mod test { titles: Vec, } - impl ToJson for Person { - fn to_json(&self) -> Json { - let mut m = BTreeMap::new(); - m.insert("name".to_string(), self.name.to_json()); - m.insert("age".to_string(), self.age.to_json()); - m.insert("addr".to_string(), self.addr.to_json()); - m.insert("titles".to_string(), self.titles.to_json()); - Json::Object(m) - } - } - #[test] fn test_with() { let addr = Address { diff --git a/src/vendor/handlebars/src/lib.rs b/src/vendor/handlebars/src/lib.rs index 0657fffe75..6fbfd2968b 100644 --- a/src/vendor/handlebars/src/lib.rs +++ b/src/vendor/handlebars/src/lib.rs @@ -20,8 +20,7 @@ //! //! // Prepare some data. //! // -//! // The data type should implements `rustc_serialize::json::ToJson` or -//! // `serde::Serialize` +//! // The data type should implements `serde::Serialize` //! let mut data = BTreeMap::new(); //! data.insert("world".to_string(), "世界!".to_string()); //! assert_eq!(handlebars.render("t1", &data).unwrap(), "hello 世界!"); @@ -92,12 +91,10 @@ //! #### Static typed //! //! As a static typed language, it's a little verbose to use handlebars. -//! You will have to make your data `ToJson`-able, so we can render -//! it. If you are on nightly channel, we have [a syntax -//! extension](https://github.com/sunng87/tojson_macros) to generate -//! default `ToJson` implementation for you. If you prefer -//! [serde](https://github.com/serde-rs/serde), you can enable `serde_type` feature -//! of handlebars-rust and add `#[Serialize]` for your types. +//! Handlebars templating language is designed against JSON data type. In rust, +//! we will convert user's structs, vectors or maps to JSON type in order to use +//! in template. You have to make sure your data implements the `Serialize` trait +//! from the [Serde](https://serde.rs) project. //! //! ## Usage //! @@ -143,32 +140,23 @@ //! //! ### Rendering Something //! -//! Since handlebars is originally based on JavaScript type system. It supports dynamic features like duck-typing, truthy/falsey values. But for a static language like Rust, this is a little difficult. As a solution, we are using the `serialize::json::Json` internally for data rendering. +//! Since handlebars is originally based on JavaScript type system. It supports dynamic features like duck-typing, truthy/falsey values. But for a static language like Rust, this is a little difficult. As a solution, we are using the `serde_json::value::Value` internally for data rendering. //! -//! That means, if you want to render something, you have to ensure the data type implements the `rustc_serialize::json::ToJson` trait (or serde's `Serialize`). Luckily, most rust internal types already have that trait. However, if you want to render your custom struct, you need to implement it manually, or use [tojson_macros](https://github.com/sunng87/tojson_macros) to generate default `ToJson` implementation. +//! That means, if you want to render something, you have to ensure the data type implements the `serde::Serialize` trait. Most rust internal types already have that trait. Use `#derive[Serialize]` for your types to generate default implementation. //! //! You can use default `render` function to render a template into `String`. From 0.9, there's `renderw` to render text into anything of `std::io::Write`. //! //! ```ignore -//! use rustc_serialize::json::{Json, ToJson}; //! use std::collections::BTreeMap; //! //! use handlebars::Handlebars; //! +//! #[derive(Serialize)] //! struct Person { //! name: String, //! age: i16, //! } //! -//! impl ToJson for Person { -//! fn to_json(&self) -> Json { -//! let mut m: BTreeMap = BTreeMap::new(); -//! m.insert("name".to_string(), self.name.to_json()); -//! m.insert("age".to_string(), self.age.to_json()); -//! m.to_json() -//! } -//! } -//! //! fn main() { //! let source = "Hello, {{name}}"; //! @@ -292,16 +280,17 @@ extern crate pest; #[macro_use] extern crate lazy_static; -extern crate regex; - #[cfg(test)] #[macro_use] extern crate maplit; +#[cfg(test)] +#[macro_use] +extern crate serde_derive; -#[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))] -extern crate rustc_serialize as serialize; - -#[cfg(feature = "serde_type")] +extern crate regex; +extern crate serde; +#[allow(unused_imports)] +#[macro_use] extern crate serde_json; pub use self::template::Template; diff --git a/src/vendor/handlebars/src/registry.rs b/src/vendor/handlebars/src/registry.rs index 81cef0b790..fb01843ea1 100644 --- a/src/vendor/handlebars/src/registry.rs +++ b/src/vendor/handlebars/src/registry.rs @@ -3,10 +3,7 @@ use std::io::prelude::*; use std::fs::File; use std::path::Path; -#[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))] -use serialize::json::ToJson; -#[cfg(feature = "serde_type")] -use serde_json::value::ToJson; +use serde::Serialize; use regex::{Regex, Captures}; @@ -231,11 +228,11 @@ impl Registry { /// Render a registered template with some data into a string /// /// * `name` is the template name you registred previously - /// * `ctx` is the data that implements `ToJson` of either rustc_serialize or serde_json + /// * `ctx` is the data that implements `serde::Serialize`` /// /// Returns rendered string or an struct with error information pub fn render(&self, name: &str, data: &T) -> Result - where T: ToJson + where T: Serialize { let mut writer = StringWriter::new(); { @@ -247,7 +244,7 @@ impl Registry { /// Render a registered template and write some data to the `std::io::Write` pub fn renderw(&self, name: &str, data: &T, writer: &mut Write) -> Result<(), RenderError> - where T: ToJson + where T: Serialize { self.get_template(&name.to_string()) .ok_or(RenderError::new(format!("Template not found: {}", name))) @@ -265,7 +262,7 @@ impl Registry { template_string: &str, data: &T) -> Result - where T: ToJson + where T: Serialize { let mut writer = StringWriter::new(); { @@ -280,7 +277,7 @@ impl Registry { data: &T, writer: &mut Write) -> Result<(), TemplateRenderError> - where T: ToJson + where T: Serialize { let tpl = try!(Template::compile(template_string)); let mut ctx = Context::wraps(data); @@ -295,7 +292,7 @@ impl Registry { data: &T, writer: &mut Write) -> Result<(), TemplateRenderError> - where T: ToJson + where T: Serialize { let mut tpl_str = String::new(); try!(template_source.read_to_string(&mut tpl_str).map_err(|e| { diff --git a/src/vendor/handlebars/src/render.rs b/src/vendor/handlebars/src/render.rs index ff83fcd95f..703513c262 100644 --- a/src/vendor/handlebars/src/render.rs +++ b/src/vendor/handlebars/src/render.rs @@ -5,10 +5,8 @@ use std::rc::Rc; use std::io::Write; use std::io::Error as IOError; -#[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))] -use serialize::json::{ToJson, Json}; -#[cfg(feature = "serde_type")] -use serde_json::value::{Value as Json, ToJson}; +use serde::Serialize; +use serde_json::value::{Value as Json}; use template::{Template, TemplateElement, Parameter, HelperTemplate, TemplateMapping, BlockParam, Directive as DirectiveTemplate}; @@ -212,7 +210,7 @@ impl<'a> RenderContext<'a> { } pub fn push_block_context(&mut self, ctx: &T) - where T: ToJson + where T: Serialize { self.block_context.push_front(Context::wraps(ctx)); } @@ -812,26 +810,25 @@ fn test_template() { } #[test] -#[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))] fn test_render_context_promotion_and_demotion() { - use serialize::json::ToJson; + use context::to_json; let mut sw = StringWriter::new(); let mut ctx = Context::null(); let mut hlps = HashMap::new(); let mut render_context = RenderContext::new(&mut ctx, &mut hlps, &mut sw); - render_context.set_local_var("@index".to_string(), 0usize.to_json()); + render_context.set_local_var("@index".to_string(), to_json(&0)); render_context.promote_local_vars(); assert_eq!(render_context.get_local_var(&"@../index".to_string()).unwrap(), - &0usize.to_json()); + &to_json(&0)); render_context.demote_local_vars(); assert_eq!(render_context.get_local_var(&"@index".to_string()).unwrap(), - &0usize.to_json()); + &to_json(&0)); } #[test] @@ -918,3 +915,16 @@ fn test_partial_failback_render() { let r = r.render("child", &true).expect("should work"); assert_eq!(r, "content"); } + +#[test] +fn test_key_with_slash() { + let mut r = Registry::new(); + + assert!(r.register_template_string("t", "{{#each .}}{{@key}}: {{this}}\n{{/each}}").is_ok()); + + let r = r.render("t", &json!({ + "/foo": "bar" + })).expect("should work"); + + assert_eq!(r, "/foo: bar\n"); +} diff --git a/src/vendor/handlebars/src/template.rs b/src/vendor/handlebars/src/template.rs index c81f641d27..4cd1da9742 100644 --- a/src/vendor/handlebars/src/template.rs +++ b/src/vendor/handlebars/src/template.rs @@ -4,11 +4,7 @@ use std::convert::From; use std::collections::{BTreeMap, VecDeque}; use pest::prelude::*; -#[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))] -use serialize::json::Json; -#[cfg(feature = "serde_type")] use serde_json::value::Value as Json; -#[cfg(feature = "serde_type")] use std::str::FromStr; use grammar::{Rdp, Rule}; diff --git a/src/vendor/jobserver/.appveyor.yml b/src/vendor/jobserver/.appveyor.yml new file mode 100644 index 0000000000..51ba2db343 --- /dev/null +++ b/src/vendor/jobserver/.appveyor.yml @@ -0,0 +1,18 @@ +environment: + matrix: + - TARGET: x86_64-pc-windows-msvc + MAKE: mingw32-make + +install: + # Install rust, x86_64-pc-windows-msvc host + - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe + - rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain nightly + - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin + - set PATH=C:\msys64\mingw64\bin;C:\msys64\usr\bin;%PATH% + - rustc -V + - cargo -V + +build: false + +test_script: + - cargo test diff --git a/src/vendor/jobserver/.cargo-checksum.json b/src/vendor/jobserver/.cargo-checksum.json new file mode 100644 index 0000000000..cdcf538031 --- /dev/null +++ b/src/vendor/jobserver/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".appveyor.yml":"f6cf18ef5dd546f75aee42523bab14ed619a3c6ac49fa403ce7a716ef125c52c",".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"1405b421de32d7744dd83162e9d640982ece71c6ccbd7ce2dc7df3d0b2c2c47d",".travis.yml":"31d3c1bfb1d3e6cb18b2360b923a02be52373f4a9232684648f07f9e27815b44","Cargo.toml":"ec0b1630fdaa99e55520513b365ffc7c566f73f7965882101f2c70972fe0bde6","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"f48c83086ae750b2ce48d36affc987d4da7023afc18f746c7ca070d3d0bc1121","src/lib.rs":"c7499f24ae4ba15ac02f3aa441d66ff0fa45f145d6e9fb46fbfa771df97c0359","tests/client-of-myself.rs":"9ba7aba16b276050d791931c9610eec6f33c713fa80d514fa9223a33372e6f71","tests/client.rs":"0f0eecdca8df9e46b5811c5fef33ceddbcf742b9386d970955facb503bc9c8ee","tests/helper.rs":"583e4013e2033bd6cba56219998a86651c3cc24429b2ca27f55152b75de75bdb","tests/make-as-a-client.rs":"844ce6be72c72291c7077e06646b39731f30b025afac1cbc32b2c13a32a3f327","tests/server.rs":"197c5366cb47925fb05598fdc466d4c7512058a66ac0fdbb16df517d8812954f"},"package":"443ae8bc0af6c106e6e8b77e04684faecc1a5ce94e058f4c2b0a037b0ea1b133"} \ No newline at end of file diff --git a/src/vendor/jobserver/.cargo-ok b/src/vendor/jobserver/.cargo-ok new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/vendor/jobserver/.gitignore b/src/vendor/jobserver/.gitignore new file mode 100644 index 0000000000..4308d82204 --- /dev/null +++ b/src/vendor/jobserver/.gitignore @@ -0,0 +1,3 @@ +target/ +**/*.rs.bk +Cargo.lock diff --git a/src/vendor/jobserver/.travis.yml b/src/vendor/jobserver/.travis.yml new file mode 100644 index 0000000000..5c8da36ab9 --- /dev/null +++ b/src/vendor/jobserver/.travis.yml @@ -0,0 +1,25 @@ +language: rust +rust: stable + +matrix: + include: + - os: osx + - rust: stable + - rust: beta + - rust: nightly + before_script: + - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH + after_success: + - travis-cargo doc-upload + +sudo: false +script: + - cargo test + - cargo doc --no-deps +env: + global: + secure: "u4sfTRgvuqtiwil/a5RMjNFKdUJl0fr8MM73c934I4nDuIPQ+v1ZIj/ehclHXED+vT3M5h0Ois+HWBn/626vVZCuCUBqeC96qB7K+tqJlzpxGgukF9Ps2q7nh14NBxsTQ3HBJbrxdi6qaozAaa3BLPh6pLCBBgfofsbaeikV6ogosI0ZeYDwwEA7dc7yVKWwuMDFnxeqEqkdC9SLc4dsSuFAYWs3w00EU6sukG7ISv1e5fluZtJgNxbMe5RUCa2/lsDtmrWpkHSagcfhbWqb5LZ0ZZE+v6/Z9ASlHEOt462p4ZnkTgVgRw9/QcV75KN/tHI4hrXOU55VkEBzZqlc1Fyr+xeIpghNel8HEnLpde8B+XbCxCzGORPntCjVjfIn++wxK7ce30hslBsT75UJPrTnsBPr5rPahX8i0K6R8Xc2i7qMd5p2NTDs51MWpnjNgAGFj/1WS7t638i+gkia9ficfNRXDlMCNDC8F24r5huB6G4EKWYyCLYdMZHNaKO1XCVMTeRh2EQpLILkT8BFVZN1ttGUZ1BhMsZ1U4pCgta7phRZkBiov7uomPHMUX+fn0rmh58Z2Rodbvdzdx4fVRCebBgqxh25We2ByWRyAHfEF0Cw91A8bs1u1ssdta8UXqrb9d6oKDPCDIO/v+mzd6KXN2d5bTExo0aLs8qMC3Q=" + +notifications: + email: + on_success: never diff --git a/src/vendor/jobserver/Cargo.toml b/src/vendor/jobserver/Cargo.toml new file mode 100644 index 0000000000..5341361b46 --- /dev/null +++ b/src/vendor/jobserver/Cargo.toml @@ -0,0 +1,47 @@ +[package] +name = "jobserver" +version = "0.1.6" +authors = ["Alex Crichton "] +license = "MIT/Apache-2.0" +repository = "https://github.com/alexcrichton/jobserver-rs" +homepage = "https://github.com/alexcrichton/jobserver-rs" +documentation = "https://docs.rs/jobserver" +description = """ +An implementation of the GNU make jobserver for Rust +""" + +[target.'cfg(unix)'.dependencies] +libc = "0.2" + +[target.'cfg(windows)'.dependencies] +rand = "0.3" + +[dev-dependencies] +futures = "0.1" +num_cpus = "1.0" +tempdir = "0.3" +tokio-core = "0.1" +tokio-process = "0.1" + +[[test]] +name = "client" +harness = false +path = "tests/client.rs" + +[[test]] +name = "server" +path = "tests/server.rs" + +[[test]] +name = "client-of-myself" +path = "tests/client-of-myself.rs" +harness = false + +[[test]] +name = "make-as-a-client" +path = "tests/make-as-a-client.rs" +harness = false + +[[test]] +name = "helper" +path = "tests/helper.rs" diff --git a/src/vendor/serde_json-0.9.10/LICENSE-APACHE b/src/vendor/jobserver/LICENSE-APACHE similarity index 100% rename from src/vendor/serde_json-0.9.10/LICENSE-APACHE rename to src/vendor/jobserver/LICENSE-APACHE diff --git a/src/vendor/jobserver/LICENSE-MIT b/src/vendor/jobserver/LICENSE-MIT new file mode 100644 index 0000000000..39e0ed6602 --- /dev/null +++ b/src/vendor/jobserver/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2014 Alex Crichton + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/src/vendor/jobserver/README.md b/src/vendor/jobserver/README.md new file mode 100644 index 0000000000..29858a761d --- /dev/null +++ b/src/vendor/jobserver/README.md @@ -0,0 +1,34 @@ +# jobserver-rs + +An implementation of the GNU make jobserver for Rust + +[![Build Status](https://travis-ci.org/alexcrichton/jobserver-rs.svg?branch=master)](https://travis-ci.org/alexcrichton/jobserver-rs) +[![Build status](https://ci.appveyor.com/api/projects/status/h5jc30hohp7ejd9c/branch/master?svg=true)](https://ci.appveyor.com/project/alexcrichton/jobserver-rs/branch/master) +[![Crates.io](https://img.shields.io/crates/v/jobserver.svg?maxAge=2592000)](https://crates.io/crates/jobserver) + +[Documentation](https://docs.rs/jobserver) + +## Usage + +First, add this to your `Cargo.toml`: + +```toml +[dependencies] +jobserver = "0.1" +``` + +Next, add this to your crate: + +```rust +extern crate jobserver; +``` + +# License + +`jobserver-rs` 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, and LICENSE-MIT for details. + + diff --git a/src/vendor/jobserver/src/lib.rs b/src/vendor/jobserver/src/lib.rs new file mode 100644 index 0000000000..fed717af98 --- /dev/null +++ b/src/vendor/jobserver/src/lib.rs @@ -0,0 +1,894 @@ +//! An implementation of the GNU make jobserver. +//! +//! This crate is an implementation, in Rust, of the GNU `make` jobserver for +//! CLI tools that are interoperating with make or otherwise require some form +//! of parallelism limiting across process boundaries. This was originally +//! written for usage in Cargo to both (a) work when `cargo` is invoked from +//! `make` (using `make`'s jobserver) and (b) work when `cargo` invokes build +//! scripts, exporting a jobserver implementation for `make` processes to +//! transitively use. +//! +//! The jobserver implementation can be found in [detail online][docs] but +//! basically boils down to a cross-process semaphore. On Unix this is +//! implemented with the `pipe` syscall and read/write ends of a pipe and on +//! Windows this is implemented literally with IPC semaphores. +//! +//! The jobserver protocol in `make` also dictates when tokens are acquire to +//! run child work, and clients using this crate should take care to implement +//! such details to ensure correct interoperation with `make` itself. +//! +//! ## Examples +//! +//! Connect to a jobserver that was set up by `make` or a different process: +//! +//! ```no_run +//! use jobserver::Client; +//! +//! // See API documentation for why this is `unsafe` +//! let client = match unsafe { Client::from_env() } { +//! Some(client) => client, +//! None => panic!("client not configured"), +//! }; +//! ``` +//! +//! Acquire and release token from a jobserver: +//! +//! ```no_run +//! use jobserver::Client; +//! +//! let client = unsafe { Client::from_env().unwrap() }; +//! let token = client.acquire().unwrap(); // blocks until it is available +//! drop(token); // releases the token when the work is done +//! ``` +//! +//! Create a new jobserver and configure a child process to have access: +//! +//! ``` +//! use std::process::Command; +//! use jobserver::Client; +//! +//! let client = Client::new(4).expect("failed to create jobserver"); +//! let mut cmd = Command::new("make"); +//! client.configure(&mut cmd); +//! ``` +//! +//! ## Caveats +//! +//! This crate makes no attempt to release tokens back to a jobserver on +//! abnormal exit of a process. If a process which acquires a token is killed +//! with ctrl-c or some similar signal then tokens will not be released and the +//! jobserver may be in a corrupt state. +//! +//! Note that this is typically ok as ctrl-c means that an entire build process +//! is being torn down, but it's worth being aware of at least! +//! +//! ## Windows caveats +//! +//! There appear to be two implementations of `make` on Windows. On MSYS2 one +//! typically comes as `mingw32-make` and the other as `make` itself. I'm not +//! personally too familiar with what's going on here, but for jobserver-related +//! information the `mingw32-make` implementation uses Windows semaphores +//! whereas the `make` program does not. The `make` program appears to use file +//! descriptors and I'm not really sure how it works, so this crate is not +//! compatible with `make` on Windows. It is, however, compatible with +//! `mingw32-make`. +//! +//! [docs]: http://make.mad-scientist.net/papers/jobserver-implementation/ + +#![deny(missing_docs, missing_debug_implementations)] +#![doc(html_root_url = "https://docs.rs/jobserver/0.1")] + +use std::env; +use std::io; +use std::process::Command; +use std::sync::Arc; +use std::sync::mpsc::{self, Sender}; + +/// A client of a jobserver +/// +/// This structure is the main type exposed by this library, and is where +/// interaction to a jobserver is configured through. Clients are either created +/// from scratch in which case the internal semphore is initialied on the spot, +/// or a client is created from the environment to connect to a jobserver +/// already created. +/// +/// Some usage examples can be found in the crate documentation for using a +/// client. +/// +/// Note that a `Client` implements the `Clone` trait, and all instances of a +/// `Client` refer to the same jobserver instance. +#[derive(Clone, Debug)] +pub struct Client { + inner: Arc, +} + +/// An acquired token from a jobserver. +/// +/// This token will be released back to the jobserver when it is dropped and +/// otherwise represents the ability to spawn off another thread of work. +#[derive(Debug)] +pub struct Acquired { + client: Arc, + data: imp::Acquired, +} + +impl Client { + /// Creates a new jobserver initialized with the given parallelism limit. + /// + /// A client to the jobserver created will be returned. This client will + /// allow at most `limit` tokens to be acquired from it in parallel. More + /// calls to `acquire` will cause the calling thread to block. + /// + /// Note that the created `Client` is not automatically inherited into + /// spawned child processes from this program. Manual usage of the + /// `configure` function is required for a child process to have access to a + /// job server. + /// + /// # Examples + /// + /// ``` + /// use jobserver::Client; + /// + /// let client = Client::new(4).expect("failed to create jobserver"); + /// ``` + /// + /// # Errors + /// + /// Returns an error if any I/O error happens when attempting to create the + /// jobserver client. + pub fn new(limit: usize) -> io::Result { + Ok(Client { + inner: Arc::new(imp::Client::new(limit)?), + }) + } + + /// Attempts to connect to the jobserver specified in this process's + /// environment. + /// + /// When the a `make` executable calls a child process it will configure the + /// environment of the child to ensure that it has handles to the jobserver + /// it's passing down. This function will attempt to look for these details + /// and connect to the jobserver. + /// + /// Note that the created `Client` is not automatically inherited into + /// spawned child processes from this program. Manual usage of the + /// `configure` function is required for a child process to have access to a + /// job server. + /// + /// # Return value + /// + /// If a jobserver was found in the environment and it looks correct then + /// `Some` of the connected client will be returned. If no jobserver was + /// found then `None` will be returned. + /// + /// Note that on Unix the `Client` returned **takes ownership of the file + /// descriptors specified in the environment**. Jobservers on Unix are + /// implemented with `pipe` file descriptors, and they're inherited from + /// parent processes. This `Client` returned takes ownership of the file + /// descriptors for this process and will close the file descriptors after + /// this value is dropped. + /// + /// Additionally on Unix this function will configure the file descriptors + /// with `CLOEXEC` so they're not automatically inherited by spawned + /// children. + /// + /// # Unsafety + /// + /// This function is `unsafe` to call on Unix specifically as it + /// transitively requires usage of the `from_raw_fd` function, which is + /// itself unsafe in some circumstances. + /// + /// It's recommended to call this function very early in the lifetime of a + /// program before any other file descriptors are opened. That way you can + /// make sure to take ownership properly of the file descriptors passed + /// down, if any. + /// + /// It's generally unsafe to call this function twice in a program if the + /// previous invocation returned `Some`. + /// + /// Note, though, that on Windows it should be safe to call this function + /// any number of times. + pub unsafe fn from_env() -> Option { + let var = match env::var("CARGO_MAKEFLAGS") + .or(env::var("MAKEFLAGS")) + .or(env::var("MFLAGS")) { + Ok(s) => s, + Err(_) => return None, + }; + let mut arg = "--jobserver-fds="; + let pos = match var.find(arg) { + Some(i) => i, + None => { + arg = "--jobserver-auth="; + match var.find(arg) { + Some(i) => i, + None => return None, + } + } + }; + + let s = var[pos + arg.len()..].split(' ').next().unwrap(); + imp::Client::open(s).map(|c| { + Client { inner: Arc::new(c) } + }) + } + + /// Acquires a token from this jobserver client. + /// + /// This function will block the calling thread until a new token can be + /// acquired from the jobserver. + /// + /// # Return value + /// + /// On successful acquisition of a token an instance of `Acquired` is + /// returned. This structure, when dropped, will release the token back to + /// the jobserver. It's recommended to avoid leaking this value. + /// + /// # Errors + /// + /// If an I/O error happens while acquiring a token then this function will + /// return immediately with the error. If an error is returned then a token + /// was not acquired. + pub fn acquire(&self) -> io::Result { + let data = try!(self.inner.acquire()); + Ok(Acquired { + client: self.inner.clone(), + data: data, + }) + } + + /// Configures a child process to have access to this client's jobserver as + /// well. + /// + /// This function is required to be called to ensure that a jobserver is + /// properly inherited to a child process. If this function is *not* called + /// then this `Client` will not be accessible in the child process. In other + /// words, if not called, then `Client::from_env` will return `None` in the + /// child process (or the equivalent of `Child::from_env` that `make` uses). + /// + /// ## Platform-specific behavior + /// + /// On Unix and Windows this will clobber the `CARGO_MAKEFLAGS` environment + /// variables for the child process, and on Unix this will also allow the + /// two file descriptors for this client to be inherited to the child. + pub fn configure(&self, cmd: &mut Command) { + let arg = self.inner.string_arg(); + // Older implementations of make use `--jobserver-fds` and newer + // implementations use `--jobserver-auth`, pass both to try to catch + // both implementations. + let value = format!("--jobserver-fds={0} --jobserver-auth={0}", arg); + cmd.env("CARGO_MAKEFLAGS", &value); + self.inner.configure(cmd); + } + + /// Converts this `Client` into a helper thread to deal with a blocking + /// `acquire` function a little more easily. + /// + /// The fact that the `acquire` function on `Client` blocks isn't always + /// the easiest to work with. Typically you're using a jobserver to + /// manage running other events in parallel! This means that you need to + /// either (a) wait for an existing job to finish or (b) wait for a + /// new token to become available. + /// + /// Unfortunately the blocking in `acquire` happens at the implementation + /// layer of jobservers. On Unix this requires a blocking call to `read` + /// and on Windows this requires one of the `WaitFor*` functions. Both + /// of these situations aren't the easiest to deal with: + /// + /// * On Unix there's basically only one way to wake up a `read` early, and + /// that's through a signal. This is what the `make` implementation + /// itself uses, relying on `SIGCHLD` to wake up a blocking acquisition + /// of a new job token. Unfortunately nonblocking I/O is not an option + /// here, so it means that "waiting for one of two events" means that + /// the latter event must generate a signal! This is not always the case + /// on unix for all jobservers. + /// + /// * On Windows you'd have to basically use the `WaitForMultipleObjects` + /// which means that you've got to canonicalize all your event sources + /// into a `HANDLE` which also isn't the easiest thing to do + /// unfortunately. + /// + /// This function essentially attempts to ease these limitations by + /// converting this `Client` into a helper thread spawned into this + /// process. The application can then request that the helper thread + /// acquires tokens and the provided closure will be invoked for each token + /// acquired. + /// + /// The intention is that this function can be used to translate the event + /// of a token acquisition into an arbitrary user-defined event. + /// + /// # Arguments + /// + /// This function will consume the `Client` provided to be transferred to + /// the helper thread that is spawned. Additionally a closure `f` is + /// provided to be invoked whenever a token is acquired. + /// + /// This closure is only invoked after calls to + /// `HelperThread::request_token` have been made and a token itself has + /// been acquired. If an error happens while acquiring the token then + /// an error will be yielded to the closure as well. + /// + /// # Return Value + /// + /// This function will return an instance of the `HelperThread` structure + /// which is used to manage the helper thread associated with this client. + /// Through the `HelperThread` you'll request that tokens are acquired. + /// When acquired, the closure provided here is invoked. + /// + /// When the `HelperThread` structure is returned it will be gracefully + /// torn down, and the calling thread will be blocked until the thread is + /// torn down (which should be prompt). + /// + /// # Errors + /// + /// This function may fail due to creation of the helper thread or + /// auxiliary I/O objects to manage the helper thread. In any of these + /// situations the error is propagated upwards. + /// + /// # Platform-specific behavior + /// + /// On Windows this function behaves pretty normally as expected, but on + /// Unix the implementation is... a little heinous. As mentioned above + /// we're forced into blocking I/O for token acquisition, namely a blocking + /// call to `read`. We must be able to unblock this, however, to tear down + /// the helper thread gracefully! + /// + /// Essentially what happens is that we'll send a signal to the helper + /// thread spawned and rely on `EINTR` being returned to wake up the helper + /// thread. This involves installing a global `SIGUSR1` handler that does + /// nothing along with sending signals to that thread. This may cause + /// odd behavior in some applications, so it's recommended to review and + /// test thoroughly before using this. + pub fn into_helper_thread(self, f: F) -> io::Result + where F: FnMut(io::Result) + Send + 'static, + { + let (tx, rx) = mpsc::channel(); + Ok(HelperThread { + inner: Some(imp::spawn_helper(self, rx, Box::new(f))?), + tx: Some(tx), + }) + } +} + +impl Drop for Acquired { + fn drop(&mut self) { + drop(self.client.release(&self.data)); + } +} + +/// Structure returned from `Client::into_helper_thread` to manage the lifetime +/// of the helper thread returned, see those associated docs for more info. +#[derive(Debug)] +pub struct HelperThread { + inner: Option, + tx: Option>, +} + +impl HelperThread { + /// Request that the helper thread acquires a token, eventually calling the + /// original closure with a token when it's available. + /// + /// For more information, see the docs on that function. + pub fn request_token(&self) { + self.tx.as_ref().unwrap().send(()).unwrap(); + } +} + +impl Drop for HelperThread { + fn drop(&mut self) { + drop(self.tx.take()); + self.inner.take().unwrap().join(); + } +} + +#[cfg(unix)] +mod imp { + extern crate libc; + + use std::fs::File; + use std::io::{self, Read, Write}; + use std::mem; + use std::os::unix::prelude::*; + use std::process::Command; + use std::ptr; + use std::sync::atomic::{AtomicBool, AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; + use std::sync::mpsc::{self, Receiver, RecvTimeoutError}; + use std::sync::{Arc, Once, ONCE_INIT}; + use std::thread::{JoinHandle, Builder}; + use std::time::Duration; + + use self::libc::c_int; + + #[derive(Debug)] + pub struct Client { + read: File, + write: File, + } + + #[derive(Debug)] + pub struct Acquired { + byte: u8, + } + + impl Client { + pub fn new(limit: usize) -> io::Result { + let client = unsafe { Client::mk()? }; + // I don't think the character written here matters, but I could be + // wrong! + for _ in 0..limit { + (&client.write).write(&[b'|'])?; + } + Ok(client) + } + + unsafe fn mk() -> io::Result { + let mut pipes = [0; 2]; + + // Attempt atomically-create-with-cloexec if we can + if cfg!(target_os = "linux") { + if let Some(pipe2) = pipe2() { + cvt(pipe2(pipes.as_mut_ptr(), libc::O_CLOEXEC))?; + return Ok(Client::from_fds(pipes[0], pipes[1])) + } + } + + cvt(libc::pipe(pipes.as_mut_ptr()))?; + drop(set_cloexec(pipes[0], true)); + drop(set_cloexec(pipes[1], true)); + Ok(Client::from_fds(pipes[0], pipes[1])) + } + + pub unsafe fn open(s: &str) -> Option { + let mut parts = s.splitn(2, ','); + let read = parts.next().unwrap(); + let write = match parts.next() { + Some(s) => s, + None => return None, + }; + + let read = match read.parse() { + Ok(n) => n, + Err(_) => return None, + }; + let write = match write.parse() { + Ok(n) => n, + Err(_) => return None, + }; + + // Ok so we've got two integers that look like file descriptors, but + // for extra sanity checking let's see if they actually look like + // instances of a pipe before we return the client. + // + // If we're called from `make` *without* the leading + on our rule + // then we'll have `MAKEFLAGS` env vars but won't actually have + // access to the file descriptors. + if is_pipe(read) && is_pipe(write) { + drop(set_cloexec(read, true)); + drop(set_cloexec(write, true)); + Some(Client::from_fds(read, write)) + } else { + None + } + } + + unsafe fn from_fds(read: c_int, write: c_int) -> Client { + Client { + read: File::from_raw_fd(read), + write: File::from_raw_fd(write), + } + } + + pub fn acquire(&self) -> io::Result { + let mut buf = [0]; + match (&self.read).read(&mut buf)? { + 1 => Ok(Acquired { byte: buf[0] }), + _ => Err(io::Error::new(io::ErrorKind::Other, + "early EOF on jobserver pipe")), + } + } + + pub fn release(&self, data: &Acquired) -> io::Result<()> { + match (&self.write).write(&[data.byte])? { + 1 => Ok(()), + _ => Err(io::Error::new(io::ErrorKind::Other, + "failed to write token back to jobserver")), + } + } + + pub fn string_arg(&self) -> String { + format!("{},{} -j", self.read.as_raw_fd(), self.write.as_raw_fd()) + } + + pub fn configure(&self, cmd: &mut Command) { + // Here we basically just want to say that in the child process + // we'll configure the read/write file descriptors to *not* be + // cloexec, so they're inherited across the exec and specified as + // integers through `string_arg` above. + let read = self.read.as_raw_fd(); + let write = self.write.as_raw_fd(); + cmd.before_exec(move || { + set_cloexec(read, false)?; + set_cloexec(write, false)?; + Ok(()) + }); + } + } + + #[derive(Debug)] + pub struct Helper { + thread: JoinHandle<()>, + quitting: Arc, + rx_done: Receiver<()>, + } + + pub fn spawn_helper(client: ::Client, + rx: Receiver<()>, + mut f: Box) + Send>) + -> io::Result + { + static USR1_INIT: Once = ONCE_INIT; + let mut err = None; + USR1_INIT.call_once(|| unsafe { + let mut new: libc::sigaction = mem::zeroed(); + new.sa_sigaction = sigusr1_handler as usize; + new.sa_flags = libc::SA_SIGINFO as _; + if libc::sigaction(libc::SIGUSR1, &new, ptr::null_mut()) != 0 { + err = Some(io::Error::last_os_error()); + } + }); + + if let Some(e) = err.take() { + return Err(e) + } + + let quitting = Arc::new(AtomicBool::new(false)); + let quitting2 = quitting.clone(); + let (tx_done, rx_done) = mpsc::channel(); + let thread = Builder::new().spawn(move || { + 'outer: + for () in rx { + loop { + let res = client.acquire(); + if let Err(ref e) = res { + if e.kind() == io::ErrorKind::Interrupted { + if quitting2.load(Ordering::SeqCst) { + break 'outer + } else { + continue + } + } + } + f(res); + break + } + } + tx_done.send(()).unwrap(); + })?; + + Ok(Helper { + thread: thread, + quitting: quitting, + rx_done: rx_done, + }) + } + + impl Helper { + pub fn join(self) { + self.quitting.store(true, Ordering::SeqCst); + let dur = Duration::from_millis(10); + let mut done = false; + for _ in 0..100 { + unsafe { + // Ignore the return value here of `pthread_kill`, + // apparently on OSX if you kill a dead thread it will + // return an error, but on other platforms it may not. In + // that sense we don't actually know if this will succeed or + // not! + libc::pthread_kill(self.thread.as_pthread_t(), libc::SIGUSR1); + match self.rx_done.recv_timeout(dur) { + Ok(()) | + Err(RecvTimeoutError::Disconnected) => { + done = true; + break + } + Err(RecvTimeoutError::Timeout) => {} + } + } + } + if !done { + panic!("failed to shut down worker thread"); + } + drop(self.thread.join()); + } + } + + #[allow(unused_assignments)] + fn is_pipe(fd: c_int) -> bool { + unsafe { + let mut stat = mem::zeroed(); + if libc::fstat(fd, &mut stat) == 0 { + // On android arm and i686 mode_t is u16 and st_mode is u32, + // this generates a type mismatch when S_IFIFO (declared as mode_t) + // is used in operations with st_mode, so we use this workaround + // to get the value of S_IFIFO with the same type of st_mode. + let mut s_ififo = stat.st_mode; + s_ififo = libc::S_IFIFO as _; + stat.st_mode & s_ififo == s_ififo + } else { + false + } + } + } + + fn set_cloexec(fd: c_int, set: bool) -> io::Result<()> { + unsafe { + let previous = cvt(libc::fcntl(fd, libc::F_GETFD))?; + let new = if set { + previous | libc::FD_CLOEXEC + } else { + previous & !libc::FD_CLOEXEC + }; + if new != previous { + cvt(libc::fcntl(fd, libc::F_SETFD, new))?; + } + Ok(()) + } + } + + fn cvt(t: c_int) -> io::Result { + if t == -1 { + Err(io::Error::last_os_error()) + } else { + Ok(t) + } + } + + unsafe fn pipe2() -> Option<&'static fn(*mut c_int, c_int) -> c_int> { + static PIPE2: AtomicUsize = ATOMIC_USIZE_INIT; + + if PIPE2.load(Ordering::SeqCst) == 0 { + let name = "pipe2\0"; + let n = match libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr() as *const _) as usize { + 0 => 1, + n => n, + }; + PIPE2.store(n, Ordering::SeqCst); + } + if PIPE2.load(Ordering::SeqCst) == 1 { + None + } else { + mem::transmute(&PIPE2) + } + } + + extern fn sigusr1_handler(_signum: c_int, + _info: *mut libc::siginfo_t, + _ptr: *mut libc::c_void) { + // nothing to do + } +} + +#[cfg(windows)] +mod imp { + extern crate rand; + + use std::ffi::CString; + use std::io; + use std::process::Command; + use std::ptr; + use std::sync::Arc; + use std::sync::mpsc::Receiver; + use std::thread::{Builder, JoinHandle}; + + #[derive(Debug)] + pub struct Client { + sem: Handle, + name: String, + } + + #[derive(Debug)] + pub struct Acquired; + + type BOOL = i32; + type DWORD = u32; + type HANDLE = *mut u8; + type LONG = i32; + + const ERROR_ALREADY_EXISTS: DWORD = 183; + const FALSE: BOOL = 0; + const INFINITE: DWORD = 0xffffffff; + const SEMAPHORE_MODIFY_STATE: DWORD = 0x2; + const SYNCHRONIZE: DWORD = 0x00100000; + const TRUE: BOOL = 1; + const WAIT_OBJECT_0: DWORD = 0; + + extern "system" { + fn CloseHandle(handle: HANDLE) -> BOOL; + fn SetEvent(hEvent: HANDLE) -> BOOL; + fn WaitForMultipleObjects(ncount: DWORD, + lpHandles: *const HANDLE, + bWaitAll: BOOL, + dwMilliseconds: DWORD) -> DWORD; + fn CreateEventA(lpEventAttributes: *mut u8, + bManualReset: BOOL, + bInitialState: BOOL, + lpName: *const i8) -> HANDLE; + fn ReleaseSemaphore(hSemaphore: HANDLE, + lReleaseCount: LONG, + lpPreviousCount: *mut LONG) -> BOOL; + fn CreateSemaphoreA(lpEventAttributes: *mut u8, + lInitialCount: LONG, + lMaximumCount: LONG, + lpName: *const i8) -> HANDLE; + fn OpenSemaphoreA(dwDesiredAccess: DWORD, + bInheritHandle: BOOL, + lpName: *const i8) -> HANDLE; + fn WaitForSingleObject(hHandle: HANDLE, + dwMilliseconds: DWORD) -> DWORD; + } + + impl Client { + pub fn new(limit: usize) -> io::Result { + // Try a bunch of random semaphore names until we get a unique one, + // but don't try for too long. + // + // Note that `limit == 0` is a valid argument above but Windows + // won't let us create a semaphore with 0 slots available to it. Get + // `limit == 0` working by creating a semaphore instead with one + // slot and then immediately acquire it (without ever releaseing it + // back). + for _ in 0..100 { + let mut name = format!("__rust_jobserver_semaphore_{}\0", + rand::random::()); + unsafe { + let create_limit = if limit == 0 {1} else {limit}; + let r = CreateSemaphoreA(ptr::null_mut(), + create_limit as LONG, + create_limit as LONG, + name.as_ptr() as *const _); + if r.is_null() { + return Err(io::Error::last_os_error()) + } + let handle = Handle(r); + + let err = io::Error::last_os_error(); + if err.raw_os_error() == Some(ERROR_ALREADY_EXISTS as i32) { + continue + } + name.pop(); // chop off the trailing nul + let client = Client { + sem: handle, + name: name, + }; + if create_limit != limit { + client.acquire()?; + } + return Ok(client) + } + } + + Err(io::Error::new(io::ErrorKind::Other, + "failed to find a unique name for a semaphore")) + } + + pub unsafe fn open(s: &str) -> Option { + let name = match CString::new(s) { + Ok(s) => s, + Err(_) => return None, + }; + + let sem = OpenSemaphoreA(SYNCHRONIZE | SEMAPHORE_MODIFY_STATE, + FALSE, + name.as_ptr()); + if sem.is_null() { + None + } else { + Some(Client { + sem: Handle(sem), + name: s.to_string(), + }) + } + } + + pub fn acquire(&self) -> io::Result { + unsafe { + let r = WaitForSingleObject(self.sem.0, INFINITE); + if r == WAIT_OBJECT_0 { + Ok(Acquired) + } else { + Err(io::Error::last_os_error()) + } + } + } + + pub fn release(&self, _data: &Acquired) -> io::Result<()> { + unsafe { + let r = ReleaseSemaphore(self.sem.0, 1, ptr::null_mut()); + if r != 0 { + Ok(()) + } else { + Err(io::Error::last_os_error()) + } + } + } + + pub fn string_arg(&self) -> String { + self.name.clone() + } + + pub fn configure(&self, _cmd: &mut Command) { + // nothing to do here, we gave the name of our semaphore to the + // child above + } + } + + #[derive(Debug)] + struct Handle(HANDLE); + // HANDLE is a raw ptr, but we're send/sync + unsafe impl Sync for Handle {} + unsafe impl Send for Handle {} + + impl Drop for Handle { + fn drop(&mut self) { + unsafe { + CloseHandle(self.0); + } + } + } + + #[derive(Debug)] + pub struct Helper { + event: Arc, + thread: JoinHandle<()>, + } + + pub fn spawn_helper(client: ::Client, + rx: Receiver<()>, + mut f: Box) + Send>) + -> io::Result + { + let event = unsafe { + let r = CreateEventA(ptr::null_mut(), TRUE, FALSE, ptr::null()); + if r.is_null() { + return Err(io::Error::last_os_error()) + } else { + Handle(r) + } + }; + let event = Arc::new(event); + let event2 = event.clone(); + let thread = Builder::new().spawn(move || { + let objects = [event2.0, client.inner.sem.0]; + for () in rx { + let r = unsafe { + WaitForMultipleObjects(2, objects.as_ptr(), FALSE, INFINITE) + }; + if r == WAIT_OBJECT_0 { + break + } + if r == WAIT_OBJECT_0 + 1 { + f(Ok(::Acquired { + client: client.inner.clone(), + data: Acquired, + })) + } else { + f(Err(io::Error::last_os_error())) + } + } + })?; + Ok(Helper { + thread: thread, + event: event, + }) + } + + impl Helper { + pub fn join(self) { + let r = unsafe { SetEvent(self.event.0) }; + if r == 0 { + panic!("failed to set event: {}", io::Error::last_os_error()); + } + drop(self.thread.join()); + } + } +} diff --git a/src/vendor/jobserver/tests/client-of-myself.rs b/src/vendor/jobserver/tests/client-of-myself.rs new file mode 100644 index 0000000000..1063689499 --- /dev/null +++ b/src/vendor/jobserver/tests/client-of-myself.rs @@ -0,0 +1,60 @@ +extern crate jobserver; + +use std::env; +use std::io::BufReader; +use std::io::prelude::*; +use std::process::{Command, Stdio}; +use std::sync::mpsc; +use std::thread; + +use jobserver::Client; + +macro_rules! t { + ($e:expr) => (match $e { + Ok(e) => e, + Err(e) => panic!("{} failed with {}", stringify!($e), e), + }) +} + +fn main() { + if env::var("I_AM_THE_CLIENT").is_ok() { + client(); + } else { + server(); + } +} + +fn server() { + let me = t!(env::current_exe()); + let client = t!(Client::new(1)); + let mut cmd = Command::new(me); + cmd.env("I_AM_THE_CLIENT", "1") + .stdout(Stdio::piped()); + client.configure(&mut cmd); + let acq = client.acquire().unwrap(); + let mut child = t!(cmd.spawn()); + let stdout = child.stdout.take().unwrap(); + let (tx, rx) = mpsc::channel(); + let t = thread::spawn(move || { + for line in BufReader::new(stdout).lines() { + tx.send(t!(line)).unwrap(); + } + }); + + for _ in 0..100 { + assert!(rx.try_recv().is_err()); + } + + drop(acq); + assert_eq!(rx.recv().unwrap(), "hello!"); + t.join().unwrap(); + assert!(rx.recv().is_err()); + client.acquire().unwrap(); +} + +fn client() { + let client = unsafe { Client::from_env().unwrap() }; + let acq = client.acquire().unwrap(); + println!("hello!"); + drop(acq); +} diff --git a/src/vendor/jobserver/tests/client.rs b/src/vendor/jobserver/tests/client.rs new file mode 100644 index 0000000000..4147191f73 --- /dev/null +++ b/src/vendor/jobserver/tests/client.rs @@ -0,0 +1,191 @@ +extern crate futures; +extern crate jobserver; +extern crate num_cpus; +extern crate tempdir; +extern crate tokio_core; +extern crate tokio_process; + +use std::env; +use std::fs::File; +use std::io::Write; +use std::process::Command; +use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::mpsc; +use std::thread; + +use futures::future::{self, Future}; +use futures::stream::{self, Stream}; +use jobserver::Client; +use tempdir::TempDir; +use tokio_core::reactor::Core; +use tokio_process::CommandExt; + +macro_rules! t { + ($e:expr) => (match $e { + Ok(e) => e, + Err(e) => panic!("{} failed with {}", stringify!($e), e), + }) +} + +struct Test { + name: &'static str, + f: &'static Fn(), + make_args: &'static [&'static str], + rule: &'static Fn(&str) -> String, +} + +const TESTS: &[Test] = &[ + Test { + name: "no j args", + make_args: &[], + rule: &|me| format!("{}", me), + f: &|| { + assert!(unsafe { Client::from_env().is_none() }); + }, + }, + Test { + name: "no j args with plus", + make_args: &[], + rule: &|me| format!("+{}", me), + f: &|| { + assert!(unsafe { Client::from_env().is_none() }); + }, + }, + Test { + name: "j args with plus", + make_args: &["-j2"], + rule: &|me| format!("+{}", me), + f: &|| { + assert!(unsafe { Client::from_env().is_some() }); + }, + }, + Test { + name: "acquire", + make_args: &["-j2"], + rule: &|me| format!("+{}", me), + f: &|| { + let c = unsafe { Client::from_env().unwrap() }; + drop(c.acquire().unwrap()); + drop(c.acquire().unwrap()); + }, + }, + Test { + name: "acquire3", + make_args: &["-j3"], + rule: &|me| format!("+{}", me), + f: &|| { + let c = unsafe { Client::from_env().unwrap() }; + let a = c.acquire().unwrap(); + let b = c.acquire().unwrap(); + drop((a, b)); + }, + }, + Test { + name: "acquire blocks", + make_args: &["-j2"], + rule: &|me| format!("+{}", me), + f: &|| { + let c = unsafe { Client::from_env().unwrap() }; + let a = c.acquire().unwrap(); + let hit = Arc::new(AtomicBool::new(false)); + let hit2 = hit.clone(); + let (tx, rx) = mpsc::channel(); + let t = thread::spawn(move || { + tx.send(()).unwrap(); + let _b = c.acquire().unwrap(); + hit2.store(true, Ordering::SeqCst); + }); + rx.recv().unwrap(); + assert!(!hit.load(Ordering::SeqCst)); + drop(a); + t.join().unwrap(); + assert!(hit.load(Ordering::SeqCst)); + }, + }, +]; + +fn main() { + if let Ok(test) = env::var("TEST_TO_RUN") { + return (TESTS.iter().find(|t| t.name == test).unwrap().f)() + } + + let me = t!(env::current_exe()); + let me = me.to_str().unwrap(); + let filter = env::args().skip(1).next(); + + let mut core = t!(Core::new()); + let ref handle = core.handle(); + + let futures = TESTS.iter().filter(|test| { + match filter { + Some(ref s) => test.name.contains(s), + None => true, + } + }).map(|test| { + let td = t!(TempDir::new("foo")); + let makefile = format!("\ +all: export TEST_TO_RUN={} +all: +\t{} +", test.name, (test.rule)(me)); + t!(t!(File::create(td.path().join("Makefile"))) + .write_all(makefile.as_bytes())); + let prog = env::var("MAKE").unwrap_or("make".to_string()); + let mut cmd = Command::new(prog); + cmd.args(test.make_args); + cmd.current_dir(td.path()); + future::lazy(move || { + cmd.output_async(&handle).map(move |e| { + drop(td); + (test, e) + }) + }) + }).collect::>(); + + println!("\nrunning {} tests\n", futures.len()); + + let stream = stream::iter(futures.into_iter().map(Ok)) + .buffer_unordered(num_cpus::get()); + + let mut failures = Vec::new(); + t!(core.run(stream.for_each(|(test, output)| { + if output.status.success() { + println!("test {} ... ok", test.name); + } else { + println!("test {} ... FAIL", test.name); + failures.push((test, output)); + } + Ok(()) + }))); + + if failures.len() == 0 { + println!("\ntest result: ok\n"); + return + } + + println!("\n----------- failures"); + + for (test, output) in failures { + println!("test {}", test.name); + let stdout = String::from_utf8_lossy(&output.stdout); + let stderr = String::from_utf8_lossy(&output.stderr); + + println!("\texit status: {}", output.status); + if !stdout.is_empty() { + println!("\tstdout ==="); + for line in stdout.lines() { + println!("\t\t{}", line); + } + } + + if !stderr.is_empty() { + println!("\tstderr ==="); + for line in stderr.lines() { + println!("\t\t{}", line); + } + } + } + + std::process::exit(4); +} diff --git a/src/vendor/jobserver/tests/helper.rs b/src/vendor/jobserver/tests/helper.rs new file mode 100644 index 0000000000..ed046ae59d --- /dev/null +++ b/src/vendor/jobserver/tests/helper.rs @@ -0,0 +1,44 @@ +extern crate jobserver; + +use std::sync::mpsc; + +use jobserver::Client; + +macro_rules! t { + ($e:expr) => (match $e { + Ok(e) => e, + Err(e) => panic!("{} failed with {}", stringify!($e), e), + }) +} + +#[test] +fn helper_smoke() { + let client = t!(Client::new(1)); + drop(client.clone().into_helper_thread(|_| ()).unwrap()); + drop(client.clone().into_helper_thread(|_| ()).unwrap()); + drop(client.clone().into_helper_thread(|_| ()).unwrap()); + drop(client.clone().into_helper_thread(|_| ()).unwrap()); + drop(client.clone().into_helper_thread(|_| ()).unwrap()); + drop(client.clone().into_helper_thread(|_| ()).unwrap()); +} + +#[test] +fn acquire() { + let (tx, rx) = mpsc::channel(); + let client = t!(Client::new(1)); + let helper = client.into_helper_thread(move |a| drop(tx.send(a))).unwrap(); + assert!(rx.try_recv().is_err()); + helper.request_token(); + rx.recv().unwrap().unwrap(); + helper.request_token(); + rx.recv().unwrap().unwrap(); + + helper.request_token(); + helper.request_token(); + rx.recv().unwrap().unwrap(); + rx.recv().unwrap().unwrap(); + + helper.request_token(); + helper.request_token(); + drop(helper); +} diff --git a/src/vendor/jobserver/tests/make-as-a-client.rs b/src/vendor/jobserver/tests/make-as-a-client.rs new file mode 100644 index 0000000000..d59b32d5cd --- /dev/null +++ b/src/vendor/jobserver/tests/make-as-a-client.rs @@ -0,0 +1,61 @@ +extern crate jobserver; +extern crate tempdir; + +use std::env; +use std::fs::File; +use std::io::prelude::*; +use std::net::{TcpStream, TcpListener}; +use std::process::Command; + +use jobserver::Client; +use tempdir::TempDir; + +macro_rules! t { + ($e:expr) => (match $e { + Ok(e) => e, + Err(e) => panic!("{} failed with {}", stringify!($e), e), + }) +} + +fn main() { + if let Ok(s) = env::var("TEST_ADDR") { + let mut contents = Vec::new(); + t!(t!(TcpStream::connect(&s)).read_to_end(&mut contents)); + return + } + + let c = t!(Client::new(1)); + let td = TempDir::new("foo").unwrap(); + + let prog = env::var("MAKE").unwrap_or("make".to_string()); + let mut cmd = Command::new(prog); + cmd.current_dir(td.path()); + + let me = t!(env::current_exe()); + let me = me.to_str().unwrap(); + t!(t!(File::create(td.path().join("Makefile"))).write_all(format!("\ +all: foo bar +foo: +\t{0} +bar: +\t{0} +", me).as_bytes())); + + // We're leaking one extra token to `make` sort of violating the makefile + // jobserver protocol. It has the desired effect though. + c.configure(&mut cmd); + + let listener = t!(TcpListener::bind("127.0.0.1:0")); + let addr = t!(listener.local_addr()); + cmd.env("TEST_ADDR", addr.to_string()); + let mut child = t!(cmd.spawn()); + + // We should get both connections as the two programs should be run + // concurrently. + let a = t!(listener.accept()); + let b = t!(listener.accept()); + drop((a, b)); + + assert!(t!(child.wait()).success()); +} + diff --git a/src/vendor/jobserver/tests/server.rs b/src/vendor/jobserver/tests/server.rs new file mode 100644 index 0000000000..94cd71c9c4 --- /dev/null +++ b/src/vendor/jobserver/tests/server.rs @@ -0,0 +1,145 @@ +extern crate jobserver; +extern crate tempdir; + +use std::env; +use std::fs::File; +use std::io::prelude::*; +use std::process::Command; +use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::mpsc; +use std::thread; + +use jobserver::Client; +use tempdir::TempDir; + +macro_rules! t { + ($e:expr) => (match $e { + Ok(e) => e, + Err(e) => panic!("{} failed with {}", stringify!($e), e), + }) +} + +#[test] +fn server_smoke() { + let c = t!(Client::new(1)); + drop(c.acquire().unwrap()); + drop(c.acquire().unwrap()); +} + +#[test] +fn server_multiple() { + let c = t!(Client::new(2)); + let a = c.acquire().unwrap(); + let b = c.acquire().unwrap(); + drop((a, b)); +} + +#[test] +fn server_blocks() { + let c = t!(Client::new(1)); + let a = c.acquire().unwrap(); + let hit = Arc::new(AtomicBool::new(false)); + let hit2 = hit.clone(); + let (tx, rx) = mpsc::channel(); + let t = thread::spawn(move || { + tx.send(()).unwrap(); + let _b = c.acquire().unwrap(); + hit2.store(true, Ordering::SeqCst); + }); + rx.recv().unwrap(); + assert!(!hit.load(Ordering::SeqCst)); + drop(a); + t.join().unwrap(); + assert!(hit.load(Ordering::SeqCst)); +} + +#[test] +fn make_as_a_single_thread_client() { + let c = t!(Client::new(1)); + let td = TempDir::new("foo").unwrap(); + + let prog = env::var("MAKE").unwrap_or("make".to_string()); + let mut cmd = Command::new(prog); + cmd.current_dir(td.path()); + + t!(t!(File::create(td.path().join("Makefile"))).write_all(b" +all: foo bar +foo: +\techo foo +bar: +\techo bar +")); + + // The jobserver protocol means that the `make` process itself "runs with a + // token", so we acquire our one token to drain the jobserver, and this + // should mean that `make` itself never has a second token available to it. + let _a = c.acquire(); + c.configure(&mut cmd); + let output = t!(cmd.output()); + println!("\n\t=== stderr\n\t\t{}", + String::from_utf8_lossy(&output.stderr).replace("\n", "\n\t\t")); + println!("\t=== stdout\n\t\t{}", + String::from_utf8_lossy(&output.stdout).replace("\n", "\n\t\t")); + + assert!(output.status.success()); + assert!(output.stderr.is_empty()); + + let stdout = String::from_utf8_lossy(&output.stdout).replace("\r\n", "\n"); + let a = "\ +echo foo +foo +echo bar +bar +"; + let b = "\ +echo bar +bar +echo foo +foo +"; + + assert!(stdout == a || stdout == b); +} + +#[test] +fn make_as_a_multi_thread_client() { + let c = t!(Client::new(1)); + let td = TempDir::new("foo").unwrap(); + + let prog = env::var("MAKE").unwrap_or("make".to_string()); + let mut cmd = Command::new(prog); + cmd.current_dir(td.path()); + + t!(t!(File::create(td.path().join("Makefile"))).write_all(b" +all: foo bar +foo: +\techo foo +bar: +\techo bar +")); + + // We're leaking one extra token to `make` sort of violating the makefile + // jobserver protocol. It has the desired effect though. + c.configure(&mut cmd); + let output = t!(cmd.output()); + println!("\n\t=== stderr\n\t\t{}", + String::from_utf8_lossy(&output.stderr).replace("\n", "\n\t\t")); + println!("\t=== stdout\n\t\t{}", + String::from_utf8_lossy(&output.stdout).replace("\n", "\n\t\t")); + + assert!(output.status.success()); +} + +#[test] +fn zero_client() { + let client = t!(Client::new(0)); + let (tx, rx) = mpsc::channel(); + let helper = client.into_helper_thread(move |a| drop(tx.send(a))).unwrap(); + helper.request_token(); + helper.request_token(); + + for _ in 0..1000 { + assert!(rx.try_recv().is_err()); + } +} diff --git a/src/vendor/libc/.cargo-checksum.json b/src/vendor/libc/.cargo-checksum.json index e0a2dd3fdc..24c3e8a615 100644 --- a/src/vendor/libc/.cargo-checksum.json +++ b/src/vendor/libc/.cargo-checksum.json @@ -1 +1 @@ -{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"7150ee9391a955b2ef7e0762fc61c0c1aab167620ca36d88d78062d93b8334ba",".travis.yml":"41a754a0d21cff3671a09503cae51bac20357bb0c9640ee5edba2208e573429c","Cargo.toml":"fc8266c859a18b4d550dd9c48a22700a5e002df0a85ad7d3caf58659d9cf9684","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"a2ffaf2a812cec7c243fd753891c7e2eada5b61d9846dd5318d7c99d4514c988","appveyor.yml":"483ae27670e061eb91f055699a9ad88255050b7b300f183b8580340407751bb4","ci/README.md":"be804f15e2128e5fd4b160cb0b13cff5f19e7d77b55ec5254aa6fd8731c84f0d","ci/android-accept-licenses.sh":"84ad00815f628005ed22c5d6cd14990ebc97812a7163bd275b2877904eddab53","ci/android-install-ndk.sh":"73c5f21438c024ce1b8c793184447ff9aecd83c87cbde8de580b782842b3563f","ci/android-install-sdk.sh":"891900fe4e4ceb04717b91a253753858270defc6d6401936d08c09801c1de178","ci/docker/aarch64-linux-android/Dockerfile":"68f375c6e0b3716f8c0b6ed217bc6c3631fa2b86c578b983a0bf60d0344efd74","ci/docker/aarch64-unknown-linux-gnu/Dockerfile":"62ca7317439f9c303990e897450a91cd467be05eb75dfc01456d417932ac8672","ci/docker/arm-linux-androideabi/Dockerfile":"1193bf048efbeb9be3c9fac0836dcf6ae07e12cdf09b36b386dd4cbd62abbffa","ci/docker/arm-unknown-linux-gnueabihf/Dockerfile":"e349f7caa463adbde8d6ec4d2b9f7720ed81c77f48d75bbfb78c89751f55c2dc","ci/docker/i686-linux-android/Dockerfile":"7c353aecdf0b21d8584392cc6ea31d455adad769034c3ea09191a1b26a2521e1","ci/docker/i686-unknown-linux-gnu/Dockerfile":"07e9df6ba91025cbec7ae81ade63f8cfb8a54c5e1e5a8f8def0617e17bd59db0","ci/docker/i686-unknown-linux-musl/Dockerfile":"fcaedc90fbb90375186b36b4324bff0a042aae70695be0f2b632e3cf7479eae6","ci/docker/mips-unknown-linux-gnu/Dockerfile":"860299d96ee50ebdbd788e65eb6ba1f561ef66107647bddffcb2567ac350896b","ci/docker/mips-unknown-linux-musl/Dockerfile":"711c43122fa34cee83a69944493213924b0ff1fccd78c7a141cb2b2127526484","ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile":"163776e0fd38f66df7415421202ac29efc7d345a628947434e573c3885594ab5","ci/docker/mipsel-unknown-linux-musl/Dockerfile":"aef213df08da03ab6a723c3e6e5594a0586251950d81482cf53179d8e64e95c7","ci/docker/powerpc-unknown-linux-gnu/Dockerfile":"08b846a338c2ee70100f4e80db812668dc58bfb536c44a95cd1cf004d965186b","ci/docker/powerpc64-unknown-linux-gnu/Dockerfile":"4da285ffd035d16f5da9e3701841eb86049c8cfa417fa81e53da4ef74152eac0","ci/docker/x86_64-linux-android/Dockerfile":"aecf2b18b70cebe04738f04eaafa7054fece5bc4dc6123786c130ad5446404cd","ci/docker/x86_64-rumprun-netbsd/Dockerfile":"44c3107fb30380785aaed6ff73fa334017a5bb4e3b5c7d4876154f09023a2b99","ci/docker/x86_64-unknown-freebsd/Dockerfile":"ef0f9f63065218728d2daafaa5ba71b17e4ccc23d72e859e0a7133fc64c0815e","ci/docker/x86_64-unknown-linux-gnu/Dockerfile":"67fabbc8c6ac02376cf9344251ad49ecdac396b71accb572fd1ae65225325bc0","ci/docker/x86_64-unknown-linux-musl/Dockerfile":"f71019fed5204b950843ef5e56144161fda7e27fad68ed0e8bc4353c388c7bcf","ci/docker/x86_64-unknown-openbsd/Dockerfile":"dfa5c23a6cff8c7a9a846668118c71a8406a360801fd3632fb12e8fbda6b7338","ci/dox.sh":"9ea240a4a607036235fd68c01b5d2a59f365768d103d3be774dcf34aa3ff563e","ci/ios/deploy_and_run_on_ios_simulator.rs":"3175066fd7f82390f6226d881e1a1dda9767ea2705656870e0d7774e2731800e","ci/landing-page-footer.html":"b70b3112c2147f5c967e7481061ef38bc2d79a28dd55a16fb916d9c9426da2c4","ci/landing-page-head.html":"ad69663fac7924f27d0209bc519d55838e86edfc4133713a6fd08caadac1b142","ci/run-docker.sh":"655712ba6127eb2efe2c641cf4cf1246f3e485096d72ec57b423e9d2bff6fb73","ci/run-qemu.sh":"bb859421170871ef23a8940c5e150efec0c01b95e32d2ce2d37b79a45d9d346c","ci/run.sh":"d2bac724d7541379577545d3b4be000acb6a4eea7c101bc8615b36a319217335","ci/style.rs":"60564abc1d5197ed1598426dd0d6ee9939a16d2875b03373538f58843bb616c4","src/dox.rs":"f732d3c0dcd6ace854ee32d8f898b96ac42204a799c6e386c4ba88f6e58673dc","src/lib.rs":"651696755aed40230cde8a505a2dfef61bea52d6349c9b9343497a5c7158ec92","src/macros.rs":"bd9802772b0e5c8b3c550d1c24307f06c0d1e4ce656b4ae1cf092142bbe5412c","src/redox.rs":"3dd158ba9fbbabe96ce2607e91dbf07b93b37c0427734118702dcb4901fe8964","src/unix/bsd/apple/b32.rs":"110ecff78da0e8d405d861447904da403d8b3f6da1f0f9dc9987633f3f04fe46","src/unix/bsd/apple/b64.rs":"2c51c1c063bfb5076ecf08fbc9371ce9473878d2e046c186eb9433955f6f8ba6","src/unix/bsd/apple/mod.rs":"4bc8b16112609cc0a72be6916c89bdca531fa02fc823bf34ad4ec2c4af9c576e","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"54b3b30c4cac35ced9197e7267f209b0f168de8a6899ab0cba290c5ae399f0e7","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"c7f46b9ae23fde5a9e245a28ed1380066e67f081323b4d253a18e9da3b97b860","src/unix/bsd/freebsdlike/freebsd/mod.rs":"ba1bd1487b41be91115a21e3968d15e4d877043ba4946cd11ed2be2ee66afc19","src/unix/bsd/freebsdlike/freebsd/x86.rs":"54311d3ebf2bb091ab22361e377e6ef9224aec2ecfe459fbfcedde4932db9c58","src/unix/bsd/freebsdlike/freebsd/x86_64.rs":"c7f46b9ae23fde5a9e245a28ed1380066e67f081323b4d253a18e9da3b97b860","src/unix/bsd/freebsdlike/mod.rs":"321c6b9157152e07045ad3d662e5a3a96c3ab0b0d50dc3585a32106147ee4a91","src/unix/bsd/mod.rs":"6c8511618608536d5026222c8e8f1c93af576a4bad7452bc1cd954d72c47615b","src/unix/bsd/netbsdlike/mod.rs":"50ca4e29f06669a0ebff72f2f24b2b08ff55478f580b1684e16a0cf6938a6a50","src/unix/bsd/netbsdlike/netbsd/mod.rs":"5b5c8d295a462ffca8dd65b826ead5d2d210e6a7a71a2909db600fa9aae36151","src/unix/bsd/netbsdlike/netbsd/other/b32/mod.rs":"bd251a102bed65d5cb3459275f6ec3310fe5803ff4c9651212115548f86256d0","src/unix/bsd/netbsdlike/netbsd/other/b64/mod.rs":"927eeccaf3269d299db4c2a55f8010807bf43dfa894aea6a783215f5d3560baa","src/unix/bsd/netbsdlike/netbsd/other/mod.rs":"4d9f7091af8e166943ac6f42ce85558909e5b6e61325039bff7adfbcf4b90212","src/unix/bsd/netbsdlike/openbsdlike/bitrig.rs":"f8cd05dacd3a3136c58da5a2fbe26f703767823b28e74fe8a2b57a7bd98d6d5c","src/unix/bsd/netbsdlike/openbsdlike/mod.rs":"2d4a17eb74ae5ced13fcd9bb1df283e5623a52754ec75b23cf7b76cb03d5f2a7","src/unix/bsd/netbsdlike/openbsdlike/openbsd.rs":"31686679c2df5f11437a338b9281fa0dd4f8d061dcd895d67619992171e115c9","src/unix/bsd/netbsdlike/openbsdlike/other/b32/mod.rs":"bd251a102bed65d5cb3459275f6ec3310fe5803ff4c9651212115548f86256d0","src/unix/bsd/netbsdlike/openbsdlike/other/b64/mod.rs":"927eeccaf3269d299db4c2a55f8010807bf43dfa894aea6a783215f5d3560baa","src/unix/bsd/netbsdlike/openbsdlike/other/mod.rs":"f5d8db6f54efd05520b31b764a6bacbf612e1aebce097d2d5bfaaef3b91f37b5","src/unix/haiku/b32.rs":"bd251a102bed65d5cb3459275f6ec3310fe5803ff4c9651212115548f86256d0","src/unix/haiku/b64.rs":"b422430c550c0ba833c9206d1350861e344e3a2eb33d7d58693efb35044be1cc","src/unix/haiku/mod.rs":"fe24d9863133ee2663b07ff872f4982ea36821c432fb569a9676436506c9a98a","src/unix/mod.rs":"63e28708e4791ae7f5d47d899b4060f141231c34a50d81e701c4ea987d1412c1","src/unix/notbsd/android/b32/arm.rs":"d63a234f3a2399bdef1fa13c6a209386cb5ddac04c90f2c6d42badc8235dc49d","src/unix/notbsd/android/b32/mod.rs":"c09b53e42b286a7ec56fb28d0a3e71ec42fecaec39b2015d1d4a3338b172c570","src/unix/notbsd/android/b32/x86.rs":"10e6879dcbf136f0e907337987a0609b357e27e0f24ccb907525fcad881c24c3","src/unix/notbsd/android/b64/aarch64.rs":"d0a25e73f8d02f8412fa9237e41d3f4993b45603a2a8f8d1690bc6624a190d42","src/unix/notbsd/android/b64/mod.rs":"567710245750e8d1e4c99e145b7079b59c1f67514616cbea14734202a8c79c0c","src/unix/notbsd/android/b64/x86_64.rs":"a2b048dad18c60ede035645bbfea2ba3dd75197c1ee0d54fb5fcab14d6c35194","src/unix/notbsd/android/mod.rs":"fd065159dd2a9cbb705d2013b407eb24714bc85c454fb60673e88a839b5427ad","src/unix/notbsd/linux/mips/mips32.rs":"b268f603f71d854614c20cea00431812def9b683d43e6254ae62a8f88a14f7c3","src/unix/notbsd/linux/mips/mips64.rs":"8bce84a47a6ad7fc95234fdd3513ddb8c78634f4ac18209c0276ab705c092ebe","src/unix/notbsd/linux/mips/mod.rs":"9c263551896f5a4403282a20f39f2113f02cb34d968dc65bd80dc73c65fbeb25","src/unix/notbsd/linux/mod.rs":"98b9e87bf4d4396c2195d19f95fa1f6129a92f2aa3783d328438cd35e90d6758","src/unix/notbsd/linux/musl/b32/arm.rs":"d43ba5c528926261b1ccd529ab55636254360a084ab84a7ec22a4eb5afddb8f8","src/unix/notbsd/linux/musl/b32/asmjs.rs":"085e410f990312de76f74cb9bbf9fcc27d686e94334143b34511f565d1b8bb91","src/unix/notbsd/linux/musl/b32/mips.rs":"941c88bc413ba2b87eb6a6cfe03355ee148b865f39598456965b3d04b3adbbe6","src/unix/notbsd/linux/musl/b32/mod.rs":"fc7e055edbe6fa170c2bda6b3415066c1871b3e60ebb70a6329d008f77100f0b","src/unix/notbsd/linux/musl/b32/x86.rs":"ffa5781b52a7d2774a34b1e3e2034a498b919fd96eb85e88098dba2e674a3797","src/unix/notbsd/linux/musl/b64/aarch64.rs":"4009c7eaf703472daef2a70bdac910d9fc395a33689ef2e8cf1c4e692445d3f0","src/unix/notbsd/linux/musl/b64/mod.rs":"d9b03a59a54a568b07ffa4380103a926cbb45dbfd87745edef79cd971ef31283","src/unix/notbsd/linux/musl/b64/powerpc64.rs":"dc28f5b7284235d6cf5519053cac59a1c16dc39223b71cca0871e4880755f852","src/unix/notbsd/linux/musl/b64/x86_64.rs":"43291acc0dfc92c2fec8ba6ce77ee9ca3c20bcdccec18e149f95ba911cee704b","src/unix/notbsd/linux/musl/mod.rs":"52391104b2e6e4f75be7c7625fb44b421514be19ad1fa3b04141b7d59bf93034","src/unix/notbsd/linux/other/b32/arm.rs":"d373022fd152341ec8f5d106937c7898dd68fb4c0346bd94a37526542a605e9a","src/unix/notbsd/linux/other/b32/mod.rs":"6122be151c5d85b9df6a3aaefc5cafd0657b371cafa9cb31ed9b1a394976af45","src/unix/notbsd/linux/other/b32/powerpc.rs":"cc85e75675abc37414fc7701dda7c3f6396e7b2d3c52eea7febdc41f7b033ea9","src/unix/notbsd/linux/other/b32/x86.rs":"1ec7dbfa52d59d3f79c46d5b6854e2dd3bd44dd0f020d4e32183eed4c00bbd52","src/unix/notbsd/linux/other/b64/aarch64.rs":"ce342b37a4a60c216625c8e177a50b3f328bdfd5c527e32e06c73f4aa5926829","src/unix/notbsd/linux/other/b64/mod.rs":"bee90e8d9217ee344d0e99fd483766a1b28e8b1ded930d44a0400a5e5224bb6a","src/unix/notbsd/linux/other/b64/powerpc64.rs":"fc7131f39a75a9e35d474d70b0bc829c52590dadf472ae5785972a94ffb95f12","src/unix/notbsd/linux/other/b64/sparc64.rs":"0ba7f399349bc586ebb73d0caef5c67f195c9e3a942eabfb2efd133b4cea9872","src/unix/notbsd/linux/other/b64/x86_64.rs":"a5e62a7e12891fb545d4b9a40c139c254ba392fd3b285a7f317668f8533c3e4f","src/unix/notbsd/linux/other/mod.rs":"808ea561c7e2a0f58bb1f7a6ecf00c5a3287925e1f6cdb634b44b754df193e55","src/unix/notbsd/linux/s390x.rs":"463f942d676a31d82913fc8ac23912770c2c683db3eb459c0c837cbbdb13610e","src/unix/notbsd/mod.rs":"5a4a2a7799c7b244c439a9599d8885c17dad0cf6179e8f31fb1de4e72f153b53","src/unix/solaris/mod.rs":"ba70c4ebd371f2580c1fb8f3f6cd32a391ec017e1eed9812137caa94e5149a03","src/windows.rs":"acccbd341e81206cb1dc66af41762c193ac0dd719d700b64f7e26c967ee7d670"},"package":"babb8281da88cba992fa1f4ddec7d63ed96280a1a53ec9b919fd37b53d71e502"} \ No newline at end of file +{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"7150ee9391a955b2ef7e0762fc61c0c1aab167620ca36d88d78062d93b8334ba",".travis.yml":"f84b6ca08671d85921dbcaa638410f11cc5cb54057cd52fb8a0e08c0025e118b","Cargo.toml":"a26e9c9ac774c38c66a191bc4115c977fbc03dc9bc41cf1a463daae1d6c6df2a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"8a9859c60f78d9075e22bc9f85b40e0b0216cccaeb7025c9f464cc33dcddaf5c","appveyor.yml":"483ae27670e061eb91f055699a9ad88255050b7b300f183b8580340407751bb4","ci/README.md":"be804f15e2128e5fd4b160cb0b13cff5f19e7d77b55ec5254aa6fd8731c84f0d","ci/android-accept-licenses.sh":"84ad00815f628005ed22c5d6cd14990ebc97812a7163bd275b2877904eddab53","ci/android-install-ndk.sh":"725db9025c5905849916bf7c910f98ff0e753484397c2a1f836d48a576d10890","ci/android-install-sdk.sh":"891900fe4e4ceb04717b91a253753858270defc6d6401936d08c09801c1de178","ci/android-sysimage.sh":"901415631752827454c827e8c51906ba4260612e4021eda98eb7fff771c7d0e8","ci/docker/aarch64-linux-android/Dockerfile":"68f375c6e0b3716f8c0b6ed217bc6c3631fa2b86c578b983a0bf60d0344efd74","ci/docker/aarch64-unknown-linux-gnu/Dockerfile":"62ca7317439f9c303990e897450a91cd467be05eb75dfc01456d417932ac8672","ci/docker/arm-linux-androideabi/Dockerfile":"1193bf048efbeb9be3c9fac0836dcf6ae07e12cdf09b36b386dd4cbd62abbffa","ci/docker/arm-unknown-linux-gnueabihf/Dockerfile":"e349f7caa463adbde8d6ec4d2b9f7720ed81c77f48d75bbfb78c89751f55c2dc","ci/docker/i686-linux-android/Dockerfile":"7c353aecdf0b21d8584392cc6ea31d455adad769034c3ea09191a1b26a2521e1","ci/docker/i686-unknown-linux-gnu/Dockerfile":"07e9df6ba91025cbec7ae81ade63f8cfb8a54c5e1e5a8f8def0617e17bd59db0","ci/docker/i686-unknown-linux-musl/Dockerfile":"8b420567a7de630f37dd85de9fd8cdedd1f864a320c229ad178fdc7cd8c701e2","ci/docker/mips-unknown-linux-gnu/Dockerfile":"860299d96ee50ebdbd788e65eb6ba1f561ef66107647bddffcb2567ac350896b","ci/docker/mips-unknown-linux-musl/Dockerfile":"711c43122fa34cee83a69944493213924b0ff1fccd78c7a141cb2b2127526484","ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile":"163776e0fd38f66df7415421202ac29efc7d345a628947434e573c3885594ab5","ci/docker/mipsel-unknown-linux-musl/Dockerfile":"aef213df08da03ab6a723c3e6e5594a0586251950d81482cf53179d8e64e95c7","ci/docker/powerpc-unknown-linux-gnu/Dockerfile":"08b846a338c2ee70100f4e80db812668dc58bfb536c44a95cd1cf004d965186b","ci/docker/powerpc64-unknown-linux-gnu/Dockerfile":"4da285ffd035d16f5da9e3701841eb86049c8cfa417fa81e53da4ef74152eac0","ci/docker/s390x-unknown-linux-gnu/Dockerfile":"3fed6984fb756717dad1282e243b51cb889d6d3800b13fb8c1c3d9479369ed4b","ci/docker/x86_64-linux-android/Dockerfile":"aeeaa540189ca712369c564c9a14cbace63217dadcfaf879a2cb40fbdeb08199","ci/docker/x86_64-rumprun-netbsd/Dockerfile":"44c3107fb30380785aaed6ff73fa334017a5bb4e3b5c7d4876154f09023a2b99","ci/docker/x86_64-unknown-freebsd/Dockerfile":"ef0f9f63065218728d2daafaa5ba71b17e4ccc23d72e859e0a7133fc64c0815e","ci/docker/x86_64-unknown-linux-gnu/Dockerfile":"67fabbc8c6ac02376cf9344251ad49ecdac396b71accb572fd1ae65225325bc0","ci/docker/x86_64-unknown-linux-musl/Dockerfile":"9c3f0e2590c5cd614d6a2c5877d5419f9182c094a7ffc869ae433e1a1cc21ddc","ci/docker/x86_64-unknown-openbsd/Dockerfile":"dfa5c23a6cff8c7a9a846668118c71a8406a360801fd3632fb12e8fbda6b7338","ci/dox.sh":"9ea240a4a607036235fd68c01b5d2a59f365768d103d3be774dcf34aa3ff563e","ci/ios/deploy_and_run_on_ios_simulator.rs":"3175066fd7f82390f6226d881e1a1dda9767ea2705656870e0d7774e2731800e","ci/landing-page-footer.html":"b70b3112c2147f5c967e7481061ef38bc2d79a28dd55a16fb916d9c9426da2c4","ci/landing-page-head.html":"ad69663fac7924f27d0209bc519d55838e86edfc4133713a6fd08caadac1b142","ci/run-docker.sh":"df10afe8674f6da8073ac41acd59f47309f5a96b7e9ec086ed15abb9cad87c34","ci/run-qemu.sh":"bb859421170871ef23a8940c5e150efec0c01b95e32d2ce2d37b79a45d9d346c","ci/run.sh":"856dbd724ef20dd8a47e31f2a60e27bff70869eb0f1cb00171b1650671ab4c68","ci/style.rs":"60564abc1d5197ed1598426dd0d6ee9939a16d2875b03373538f58843bb616c4","src/dox.rs":"bb9a85519e0d4a8d3bfb81301759b9b938435d79da9ce2918248fb2b0df19638","src/lib.rs":"651696755aed40230cde8a505a2dfef61bea52d6349c9b9343497a5c7158ec92","src/macros.rs":"bd9802772b0e5c8b3c550d1c24307f06c0d1e4ce656b4ae1cf092142bbe5412c","src/redox.rs":"3dd158ba9fbbabe96ce2607e91dbf07b93b37c0427734118702dcb4901fe8964","src/unix/bsd/apple/b32.rs":"9eb115aa9f247a984df65fef4268541dd6c823377e8ce33a63df806fa1e7c1a0","src/unix/bsd/apple/b64.rs":"587ea0da0873db39a0b8277f910c5a3ca22c6689a3591e939029da52bb8dcc96","src/unix/bsd/apple/mod.rs":"b725573b21f7a6ae0da79579c2ee3b695315f82eb6ce87994de15c463466f3de","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"3141ff09d78138d17f9a07e8d05685957570046dcd8d79531a62e9f21e4613ab","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"c7f46b9ae23fde5a9e245a28ed1380066e67f081323b4d253a18e9da3b97b860","src/unix/bsd/freebsdlike/freebsd/mod.rs":"e419d8cd4aa77a9dae7736660ba71522bfc02e8547e2a04f40d872c017806502","src/unix/bsd/freebsdlike/freebsd/x86.rs":"54311d3ebf2bb091ab22361e377e6ef9224aec2ecfe459fbfcedde4932db9c58","src/unix/bsd/freebsdlike/freebsd/x86_64.rs":"c7f46b9ae23fde5a9e245a28ed1380066e67f081323b4d253a18e9da3b97b860","src/unix/bsd/freebsdlike/mod.rs":"c6bea208420624421e9b0342ead4ce8d687e332b32f96307aab6259d2928c44b","src/unix/bsd/mod.rs":"4298c52b5452736666f8f732100070bc0e55e50f53535ea183b6a900df706fed","src/unix/bsd/netbsdlike/mod.rs":"ccac7555a04b12b65550728ac127baa89aa84e4b8f59063805cbc05abf551db3","src/unix/bsd/netbsdlike/netbsd/mod.rs":"33b88db7d08f0e3a89f53341a467c148e92a524a941dcad8f46a9a12ab3d6920","src/unix/bsd/netbsdlike/netbsd/other/b32/mod.rs":"bd251a102bed65d5cb3459275f6ec3310fe5803ff4c9651212115548f86256d0","src/unix/bsd/netbsdlike/netbsd/other/b64/mod.rs":"927eeccaf3269d299db4c2a55f8010807bf43dfa894aea6a783215f5d3560baa","src/unix/bsd/netbsdlike/netbsd/other/mod.rs":"4d9f7091af8e166943ac6f42ce85558909e5b6e61325039bff7adfbcf4b90212","src/unix/bsd/netbsdlike/openbsdlike/bitrig.rs":"f8cd05dacd3a3136c58da5a2fbe26f703767823b28e74fe8a2b57a7bd98d6d5c","src/unix/bsd/netbsdlike/openbsdlike/mod.rs":"a31b098fa02ed760bcecf1e4ca1cae1d0747f040c46413dd94c394268290d351","src/unix/bsd/netbsdlike/openbsdlike/openbsd.rs":"31686679c2df5f11437a338b9281fa0dd4f8d061dcd895d67619992171e115c9","src/unix/bsd/netbsdlike/openbsdlike/other/b32/mod.rs":"bd251a102bed65d5cb3459275f6ec3310fe5803ff4c9651212115548f86256d0","src/unix/bsd/netbsdlike/openbsdlike/other/b64/mod.rs":"927eeccaf3269d299db4c2a55f8010807bf43dfa894aea6a783215f5d3560baa","src/unix/bsd/netbsdlike/openbsdlike/other/mod.rs":"f5d8db6f54efd05520b31b764a6bacbf612e1aebce097d2d5bfaaef3b91f37b5","src/unix/haiku/b32.rs":"bd251a102bed65d5cb3459275f6ec3310fe5803ff4c9651212115548f86256d0","src/unix/haiku/b64.rs":"b422430c550c0ba833c9206d1350861e344e3a2eb33d7d58693efb35044be1cc","src/unix/haiku/mod.rs":"e367a2354a2860a5c88c65524e7d561fd55929f4d4c2ff6d94b0b60d194d94c1","src/unix/mod.rs":"8eab338c920cc930f9e4545b80f2d257bed8bdaec8488a8a6b47810273257690","src/unix/newlib/arm/mod.rs":"2b6dba2e697ab9b4f4bc4dd5f28057249e9b596d1cb395a9322ec87605c4a5c4","src/unix/newlib/mod.rs":"b334c39c4102b69150bfdfb124e4c61c243b011953eaceb78f3fa5c60dc7ca2a","src/unix/notbsd/android/b32/arm.rs":"d63a234f3a2399bdef1fa13c6a209386cb5ddac04c90f2c6d42badc8235dc49d","src/unix/notbsd/android/b32/mod.rs":"8b2614f91fda1ab840004a1051c5275fb60dc08424e8f0f1602f71b4867ef827","src/unix/notbsd/android/b32/x86.rs":"cd3fe1d0e7b638574ad6461bf2b8a759fac765ed5de211250879709f3f8fe11d","src/unix/notbsd/android/b64/aarch64.rs":"7801c1f90da1e6b3a94c3b603547209d6e0e025c2d3acf6599673b568aca17cb","src/unix/notbsd/android/b64/mod.rs":"172d704a50d6fb9f67683c7e66ff15b5c9f7b11e7064aa8bd129228ff074393f","src/unix/notbsd/android/b64/x86_64.rs":"e29853194f6a244da6d723d6be6b8962bae8d6a54bec42210e7701b7c1cea482","src/unix/notbsd/android/mod.rs":"f76d13d90b8db3debfa6059450e5ebb0260c1a1c568df7f590f59ab299e4ba0b","src/unix/notbsd/linux/mips/mips32.rs":"6bd310c9a971923b32f7bf64031c5ac91ae44e68d4153c5931c24d5e9d3fd990","src/unix/notbsd/linux/mips/mips64.rs":"2fd04b2a8f2075450fecbd5fe2a3ae1a40f456f7adcc7299d61ca4b96664bd6b","src/unix/notbsd/linux/mips/mod.rs":"7c9741e058e512f931d4e4a58cf591b22b1996ab88d793bc42656fc54219de88","src/unix/notbsd/linux/mod.rs":"164556418eb6363b5ce29343b6107b263051e82c5e07d8dcc5aa758c07b212d4","src/unix/notbsd/linux/musl/b32/arm.rs":"89e12a8617ab69630b8c8cc16173f7dc06cf9bf4123ba5bfe56cba730a5ff1d8","src/unix/notbsd/linux/musl/b32/asmjs.rs":"414c10c30e5cd72b9a8e0f3bfaf72d634e07c28efec32a864cc6fc9cfcf98fbc","src/unix/notbsd/linux/musl/b32/mips.rs":"3825e95fdda5d041bda90cbbebb2e0e8fb8d9b5b0a14cbb5f6df825576e2d37e","src/unix/notbsd/linux/musl/b32/mod.rs":"b18469ec638420d7dead9f660cf3a2de2f71c5e4bd761eda9a2b0d6ed406d9b3","src/unix/notbsd/linux/musl/b32/x86.rs":"e2016dc7bed44fb83e7bc5bf560b3fe950c06760ae2d06250ab62854f97a6d16","src/unix/notbsd/linux/musl/b64/aarch64.rs":"548565a3b0807accc22f32dcdbad2d8215b8f037adfdbedf8a62aaa8f021f770","src/unix/notbsd/linux/musl/b64/mod.rs":"f767de752471d6bf2a3695ab5e750c81d6945e144b053cb43b00ba9d0e7e5958","src/unix/notbsd/linux/musl/b64/powerpc64.rs":"f2bca7a3b274d6afd0b3b09e3c714704e4d9ff8d02856f960ff8f4e478902528","src/unix/notbsd/linux/musl/b64/x86_64.rs":"c683eb160b6f109de441fd6626270a5e452806096375952ab20d150359bf0587","src/unix/notbsd/linux/musl/mod.rs":"609a0353445b44b85c821cde5e598ccfe6eb744cd5d1e3076701901fa58798f0","src/unix/notbsd/linux/other/b32/arm.rs":"855fa4030c0ff457e548fb7e1cc49432d2fce1450883c159429baaf40c243ff5","src/unix/notbsd/linux/other/b32/mod.rs":"13be8d175fd5dfcf75e0d3f378ce2c0db3f7c308fd764bbbea17861af7cd8905","src/unix/notbsd/linux/other/b32/powerpc.rs":"ec98e87f96ca47d104cf6a3019386f8154882e675963e6bd755c2982d5e3d0db","src/unix/notbsd/linux/other/b32/x86.rs":"f6b3dee2ea946f762de5d88403a03877309164ed746a9251d39ffae915e0dfaf","src/unix/notbsd/linux/other/b64/aarch64.rs":"c7129e6491a238da3d42bd1bac38be55af218ddafa1fbb9d51758ac7f2eb9d7c","src/unix/notbsd/linux/other/b64/mod.rs":"34665e488736290b4b4c256304046531171859b8726c4a7d7886d8042f903ed9","src/unix/notbsd/linux/other/b64/powerpc64.rs":"e9963605e57ba66f0119e93f65a39f3cd58eb8868246196ed9b37656ad1b11d5","src/unix/notbsd/linux/other/b64/sparc64.rs":"367d3a198a03a8a150d533b7de15c65c8065cf990c14e86db11487960700e0b4","src/unix/notbsd/linux/other/b64/x86_64.rs":"d7a0a89ccb80f0a08c194930001f60a17d15f6dedf954107a9c50d989c57bdcd","src/unix/notbsd/linux/other/mod.rs":"5c15763e57ebbd2182154989622c5f259a6f6b9c75b69c23f2c179e20a4af82a","src/unix/notbsd/linux/s390x.rs":"d18f0f7ac6f4cf6ee776234310f01d84495abc56d0f96df7113a99f2ec71ff9b","src/unix/notbsd/mod.rs":"280057749a1677e6cc8ecf26eda18230b574c0ba2825fbe7be01869deea1da9b","src/unix/solaris/mod.rs":"71c2015789e17f5ad296e88983342bf7116ccf8f6cf04032d7abef8093561a64","src/unix/uclibc/mips/mips32.rs":"31b23e466cffb86116421ec9240b86e7419aacd84b0b1b04d23c7142c8717566","src/unix/uclibc/mips/mips64.rs":"e67eec1636a998b047d89a4cda1c99cb6bc3071db017762675179a68201c4438","src/unix/uclibc/mips/mod.rs":"74817a9b1ee3998d8e0b751a555d57225f70fd979c283c94ada344a162a8b856","src/unix/uclibc/mod.rs":"913508b913a41bfa5620574e3729097692a05c9af557c0ac48ca0fabba6b5121","src/unix/uclibc/x86_64/mod.rs":"8c7fe9de2f916d796af0f76ccf947de7c337bf480e65443343677546af13ec37","src/windows.rs":"6a79e13e727b8c7277ebcc65b390ad5494d70c65b6578cb468c5565a166048d0"},"package":"30885bcb161cf67054244d10d4a7f4835ffd58773bc72e07d35fecf472295503"} \ No newline at end of file diff --git a/src/vendor/libc/.travis.yml b/src/vendor/libc/.travis.yml index 22d86e033b..4a39797942 100644 --- a/src/vendor/libc/.travis.yml +++ b/src/vendor/libc/.travis.yml @@ -1,4 +1,5 @@ language: rust +rust: stable sudo: required dist: trusty services: @@ -22,105 +23,63 @@ env: matrix: include: # 1.0.0 compat - - os: linux - env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1 + - env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1 rust: 1.0.0 script: cargo build install: # build documentation - - os: linux - env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1 + - env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1 rust: nightly script: sh ci/dox.sh # stable compat - - os: linux - env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1 - rust: stable - - os: linux - env: TARGET=i686-unknown-linux-gnu - rust: stable + - env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1 + - env: TARGET=i686-unknown-linux-gnu - os: osx env: TARGET=x86_64-apple-darwin NO_ADD=1 - rust: stable - os: osx env: TARGET=i686-apple-darwin - rust: stable - - os: linux - env: TARGET=arm-linux-androideabi - rust: stable - - os: linux - env: TARGET=aarch64-linux-android - rust: stable - - os: linux - env: TARGET=i686-linux-android - rust: stable - - os: linux - env: TARGET=x86_64-unknown-linux-musl - rust: stable - - os: linux - env: TARGET=i686-unknown-linux-musl - rust: stable - - os: linux - env: TARGET=arm-unknown-linux-gnueabihf - rust: stable - - os: linux - env: TARGET=aarch64-unknown-linux-gnu - rust: stable + - env: TARGET=arm-linux-androideabi + - env: TARGET=aarch64-linux-android + - env: TARGET=i686-linux-android + - env: TARGET=x86_64-linux-android + - env: TARGET=x86_64-unknown-linux-musl + - env: TARGET=i686-unknown-linux-musl + - env: TARGET=arm-unknown-linux-gnueabihf + - env: TARGET=aarch64-unknown-linux-gnu - os: osx osx_image: xcode8.2 env: TARGET=i386-apple-ios - rust: stable - os: osx osx_image: xcode8.2 env: TARGET=x86_64-apple-ios - rust: stable - - os: linux - env: TARGET=x86_64-rumprun-netbsd - rust: stable - - os: linux - env: TARGET=powerpc-unknown-linux-gnu - rust: stable - - os: linux - env: TARGET=powerpc64-unknown-linux-gnu - rust: beta - - os: linux - env: TARGET=mips-unknown-linux-musl - rust: stable - - os: linux - env: TARGET=mipsel-unknown-linux-musl - rust: stable - - os: linux - env: TARGET=mips64-unknown-linux-gnuabi64 - rust: beta - - os: linux - env: TARGET=mips-unknown-linux-gnu - rust: beta + - env: TARGET=x86_64-rumprun-netbsd + - env: TARGET=powerpc-unknown-linux-gnu + - env: TARGET=powerpc64-unknown-linux-gnu + - env: TARGET=mips-unknown-linux-musl + - env: TARGET=mipsel-unknown-linux-musl + - env: TARGET=mips64-unknown-linux-gnuabi64 + - env: TARGET=mips-unknown-linux-gnu + - env: TARGET=s390x-unknown-linux-gnu # beta - - os: linux - env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1 + - env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1 rust: beta - os: osx env: TARGET=x86_64-apple-darwin NO_ADD=1 rust: beta # nightly - - os: linux - env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1 + - env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1 rust: nightly - os: osx env: TARGET=x86_64-apple-darwin NO_ADD=1 rust: nightly # QEMU based targets that compile in an emulator - - os: linux - env: TARGET=x86_64-unknown-freebsd - rust: stable - - os: linux - env: TARGET=x86_64-unknown-openbsd QEMU=openbsd.qcow2 - rust: stable + - env: TARGET=x86_64-unknown-freebsd + - env: TARGET=x86_64-unknown-openbsd QEMU=openbsd.qcow2 script: sh ci/run-docker.sh $TARGET install: diff --git a/src/vendor/libc/Cargo.toml b/src/vendor/libc/Cargo.toml index 2362eec9e1..4984e15ed2 100644 --- a/src/vendor/libc/Cargo.toml +++ b/src/vendor/libc/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libc" -version = "0.2.22" +version = "0.2.26" authors = ["The Rust Project Developers"] license = "MIT/Apache-2.0" readme = "README.md" diff --git a/src/vendor/libc/README.md b/src/vendor/libc/README.md index 83ae7b9352..67535d211e 100644 --- a/src/vendor/libc/README.md +++ b/src/vendor/libc/README.md @@ -98,6 +98,25 @@ We have two automated tests running on [Travis](https://travis-ci.org/rust-lang/ 2. Style checker - `rustc ci/style.rs && ./style src` +### Releasing your change to crates.io + +Now that you've done the amazing job of landing your new API or your new +platform in this crate, the next step is to get that sweet, sweet usage from +crates.io! The only next step is to bump the version of libc and then publish +it. If you'd like to get a release out ASAP you can follow these steps: + +1. Update the version number in `Cargo.toml`, you'll just be bumping the patch + version number. +2. Run `cargo update` to regenerate the lockfile to encode your version bump in + the lock file. You may pull in some other updated dependencies, that's ok. +3. Send a PR to this repository. It should [look like this][example], but it'd + also be nice to fill out the description with a small rationale for the + release (any rationale is ok though!) +4. Once merged the release will be tagged and published by one of the libc crate + maintainers. + +[example]: https://github.com/rust-lang/libc/pull/583 + ## Platforms and Documentation The following platforms are currently tested and have documentation available: diff --git a/src/vendor/libc/ci/android-install-ndk.sh b/src/vendor/libc/ci/android-install-ndk.sh index 75bcd20f2f..873f6c52c8 100644 --- a/src/vendor/libc/ci/android-install-ndk.sh +++ b/src/vendor/libc/ci/android-install-ndk.sh @@ -11,8 +11,8 @@ set -ex -curl -O https://dl.google.com/android/repository/android-ndk-r13b-linux-x86_64.zip -unzip -q android-ndk-r13b-linux-x86_64.zip +curl -O https://dl.google.com/android/repository/android-ndk-r15b-linux-x86_64.zip +unzip -q android-ndk-r15b-linux-x86_64.zip case "$1" in aarch64) @@ -28,9 +28,10 @@ case "$1" in ;; esac; -android-ndk-r13b/build/tools/make_standalone_toolchain.py \ +android-ndk-r15b/build/tools/make_standalone_toolchain.py \ + --unified-headers \ --install-dir /android/ndk-$1 \ --arch $arch \ --api 24 -rm -rf ./android-ndk-r13b-linux-x86_64.zip ./android-ndk-r13b +rm -rf ./android-ndk-r15b-linux-x86_64.zip ./android-ndk-r15b diff --git a/src/vendor/libc/ci/android-sysimage.sh b/src/vendor/libc/ci/android-sysimage.sh new file mode 100644 index 0000000000..9611dfeb0d --- /dev/null +++ b/src/vendor/libc/ci/android-sysimage.sh @@ -0,0 +1,52 @@ +# 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 + +URL=https://dl.google.com/android/repository/sys-img/android + +main() { + local arch=$1 + local name=$2 + local dest=/system + local td=$(mktemp -d) + + apt-get install --no-install-recommends e2tools + + pushd $td + curl -O $URL/$name + unzip -q $name + + local system=$(find . -name system.img) + mkdir -p $dest/{bin,lib,lib64} + + # Extract android linker and libraries to /system + # This allows android executables to be run directly (or with qemu) + if [ $arch = "x86_64" -o $arch = "arm64" ]; then + e2cp -p $system:/bin/linker64 $dest/bin/ + e2cp -p $system:/lib64/libdl.so $dest/lib64/ + e2cp -p $system:/lib64/libc.so $dest/lib64/ + e2cp -p $system:/lib64/libm.so $dest/lib64/ + else + e2cp -p $system:/bin/linker $dest/bin/ + e2cp -p $system:/lib/libdl.so $dest/lib/ + e2cp -p $system:/lib/libc.so $dest/lib/ + e2cp -p $system:/lib/libm.so $dest/lib/ + fi + + # clean up + apt-get purge --auto-remove -y e2tools + + popd + + rm -rf $td +} + +main "${@}" diff --git a/src/vendor/libc/ci/docker/i686-unknown-linux-musl/Dockerfile b/src/vendor/libc/ci/docker/i686-unknown-linux-musl/Dockerfile index bdc2272a35..31a87371af 100644 --- a/src/vendor/libc/ci/docker/i686-unknown-linux-musl/Dockerfile +++ b/src/vendor/libc/ci/docker/i686-unknown-linux-musl/Dockerfile @@ -18,6 +18,13 @@ RUN curl https://www.musl-libc.org/releases/musl-1.1.15.tar.gz | \ CC=gcc CFLAGS=-m32 ./configure --prefix=/musl-i686 --disable-shared --target=i686 && \ make CROSS_COMPILE= install -j4 && \ cd .. && \ - rm -rf musl-1.1.15 + rm -rf musl-1.1.15 && \ +# Install linux kernel headers sanitized for use with musl + curl -L https://github.com/sabotage-linux/kernel-headers/archive/v3.12.6-5.tar.gz | \ + tar xzf - && \ + cd kernel-headers-3.12.6-5 && \ + make ARCH=i386 prefix=/musl-i686 install -j4 && \ + cd .. && \ + rm -rf kernel-headers-3.12.6-5 ENV PATH=$PATH:/musl-i686/bin:/rust/bin \ CC_i686_unknown_linux_musl=musl-gcc diff --git a/src/vendor/libc/ci/docker/s390x-unknown-linux-gnu/Dockerfile b/src/vendor/libc/ci/docker/s390x-unknown-linux-gnu/Dockerfile new file mode 100644 index 0000000000..cbcfdf3592 --- /dev/null +++ b/src/vendor/libc/ci/docker/s390x-unknown-linux-gnu/Dockerfile @@ -0,0 +1,9 @@ +FROM ubuntu:17.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + gcc libc6-dev qemu-user ca-certificates \ + gcc-s390x-linux-gnu libc6-dev-s390x-cross + +ENV CARGO_TARGET_S390X_UNKNOWN_LINUX_GNU_LINKER=s390x-linux-gnu-gcc \ + CC_s390x_unknown_linux_gnu=s390x-linux-gnu-gcc \ + PATH=$PATH:/rust/bin diff --git a/src/vendor/libc/ci/docker/x86_64-linux-android/Dockerfile b/src/vendor/libc/ci/docker/x86_64-linux-android/Dockerfile index bf4793e060..0cfbc48209 100644 --- a/src/vendor/libc/ci/docker/x86_64-linux-android/Dockerfile +++ b/src/vendor/libc/ci/docker/x86_64-linux-android/Dockerfile @@ -1,32 +1,26 @@ FROM ubuntu:16.04 -RUN dpkg --add-architecture i386 && \ - apt-get update && \ +RUN apt-get update && \ apt-get install -y --no-install-recommends \ - file \ - curl \ ca-certificates \ - python \ - unzip \ - expect \ - openjdk-9-jre \ - libstdc++6:i386 \ - libpulse0 \ + curl \ gcc \ - libc6-dev + libc-dev \ + python \ + unzip WORKDIR /android/ -COPY android* /android/ - ENV ANDROID_ARCH=x86_64 -ENV PATH=$PATH:/android/ndk-$ANDROID_ARCH/bin:/android/sdk/tools:/android/sdk/platform-tools - +COPY android-install-ndk.sh /android/ RUN sh /android/android-install-ndk.sh $ANDROID_ARCH -RUN sh /android/android-install-sdk.sh $ANDROID_ARCH -RUN mv /root/.android /tmp -RUN chmod 777 -R /tmp/.android -RUN chmod 755 /android/sdk/tools/* /android/sdk/tools/qemu/linux-x86_64/* -ENV PATH=$PATH:/rust/bin \ +# We do not run x86_64-linux-android tests on an android emulator. +# See ci/android-sysimage.sh for informations about how tests are run. +COPY android-sysimage.sh /android/ +RUN bash /android/android-sysimage.sh x86_64 x86_64-24_r07.zip + +ENV PATH=$PATH:/rust/bin:/android/ndk-$ANDROID_ARCH/bin \ CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER=x86_64-linux-android-gcc \ + CC_x86_64_linux_android=x86_64-linux-android-gcc \ + CXX_x86_64_linux_android=x86_64-linux-android-g++ \ HOME=/tmp diff --git a/src/vendor/libc/ci/docker/x86_64-unknown-linux-musl/Dockerfile b/src/vendor/libc/ci/docker/x86_64-unknown-linux-musl/Dockerfile index 9c2499948a..38e2c2d70d 100644 --- a/src/vendor/libc/ci/docker/x86_64-unknown-linux-musl/Dockerfile +++ b/src/vendor/libc/ci/docker/x86_64-unknown-linux-musl/Dockerfile @@ -9,5 +9,12 @@ RUN curl https://www.musl-libc.org/releases/musl-1.1.15.tar.gz | \ ./configure --prefix=/musl-x86_64 && \ make install -j4 && \ cd .. && \ - rm -rf musl-1.1.15 + rm -rf musl-1.1.15 && \ +# Install linux kernel headers sanitized for use with musl + curl -L https://github.com/sabotage-linux/kernel-headers/archive/v3.12.6-5.tar.gz | \ + tar xzf - && \ + cd kernel-headers-3.12.6-5 && \ + make ARCH=x86_64 prefix=/musl-x86_64 install -j4 && \ + cd .. && \ + rm -rf kernel-headers-3.12.6-5 ENV PATH=$PATH:/musl-x86_64/bin:/rust/bin diff --git a/src/vendor/libc/ci/run-docker.sh b/src/vendor/libc/ci/run-docker.sh old mode 100644 new mode 100755 index e963078af8..deafa99226 --- a/src/vendor/libc/ci/run-docker.sh +++ b/src/vendor/libc/ci/run-docker.sh @@ -22,7 +22,6 @@ run() { --volume `pwd`/target:/checkout/target \ --env CARGO_TARGET_DIR=/checkout/target \ --workdir /checkout \ - --privileged \ libc \ ci/run.sh $1 } diff --git a/src/vendor/libc/ci/run.sh b/src/vendor/libc/ci/run.sh index 4b8825f8df..54e2129f8d 100755 --- a/src/vendor/libc/ci/run.sh +++ b/src/vendor/libc/ci/run.sh @@ -105,7 +105,10 @@ case "$TARGET" in esac case "$TARGET" in - arm-linux-androideabi | aarch64-linux-android | i686-linux-android | x86_64-linux-android) + # Android emulator for x86_64 does not work on travis (missing hardware + # acceleration). Tests are run on case *). See ci/android-sysimage.sh for + # informations about how tests are run. + arm-linux-androideabi | aarch64-linux-android | i686-linux-android) # set SHELL so android can detect a 64bits system, see # http://stackoverflow.com/a/41789144 # https://issues.jenkins-ci.org/browse/JENKINS-26930?focusedCommentId=230791&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-230791 @@ -165,6 +168,11 @@ case "$TARGET" in qemu-aarch64 -L /usr/aarch64-linux-gnu/ $CARGO_TARGET_DIR/$TARGET/debug/libc-test ;; + s390x-unknown-linux-gnu) + # TODO: in theory we should execute this, but qemu segfaults immediately :( + # qemu-s390x -L /usr/s390x-linux-gnu/ $CARGO_TARGET_DIR/$TARGET/debug/libc-test + ;; + *-rumprun-netbsd) rumprun-bake hw_virtio /tmp/libc-test.img $CARGO_TARGET_DIR/$TARGET/debug/libc-test qemu-system-x86_64 -nographic -vga none -m 64 \ diff --git a/src/vendor/libc/src/dox.rs b/src/vendor/libc/src/dox.rs index fbec3f2d4e..41aac385f4 100644 --- a/src/vendor/libc/src/dox.rs +++ b/src/vendor/libc/src/dox.rs @@ -26,6 +26,9 @@ mod imp { #[lang = "copy"] pub trait Copy {} + #[lang = "freeze"] + pub trait Freeze {} + #[lang = "sync"] pub trait Sync {} impl Sync for T {} diff --git a/src/vendor/libc/src/unix/bsd/apple/b32.rs b/src/vendor/libc/src/unix/bsd/apple/b32.rs index 8ca0254497..464939d747 100644 --- a/src/vendor/libc/src/unix/bsd/apple/b32.rs +++ b/src/vendor/libc/src/unix/bsd/apple/b32.rs @@ -14,6 +14,7 @@ pub const __PTHREAD_MUTEX_SIZE__: usize = 40; pub const __PTHREAD_COND_SIZE__: usize = 24; pub const __PTHREAD_CONDATTR_SIZE__: usize = 4; pub const __PTHREAD_RWLOCK_SIZE__: usize = 124; +pub const __PTHREAD_RWLOCKATTR_SIZE__: usize = 12; pub const TIOCTIMESTAMP: ::c_ulong = 0x40087459; pub const TIOCDCDTIMESTAMP: ::c_ulong = 0x40087458; diff --git a/src/vendor/libc/src/unix/bsd/apple/b64.rs b/src/vendor/libc/src/unix/bsd/apple/b64.rs index 3f83230805..aa25a0830a 100644 --- a/src/vendor/libc/src/unix/bsd/apple/b64.rs +++ b/src/vendor/libc/src/unix/bsd/apple/b64.rs @@ -14,6 +14,7 @@ pub const __PTHREAD_MUTEX_SIZE__: usize = 56; pub const __PTHREAD_COND_SIZE__: usize = 40; pub const __PTHREAD_CONDATTR_SIZE__: usize = 8; pub const __PTHREAD_RWLOCK_SIZE__: usize = 192; +pub const __PTHREAD_RWLOCKATTR_SIZE__: usize = 16; pub const TIOCTIMESTAMP: ::c_ulong = 0x40107459; pub const TIOCDCDTIMESTAMP: ::c_ulong = 0x40107458; diff --git a/src/vendor/libc/src/unix/bsd/apple/mod.rs b/src/vendor/libc/src/unix/bsd/apple/mod.rs index 6652bb8c09..3abf3cc43a 100644 --- a/src/vendor/libc/src/unix/bsd/apple/mod.rs +++ b/src/vendor/libc/src/unix/bsd/apple/mod.rs @@ -146,6 +146,11 @@ s! { __opaque: [u8; __PTHREAD_RWLOCK_SIZE__], } + pub struct pthread_rwlockattr_t { + __sig: ::c_long, + __opaque: [u8; __PTHREAD_RWLOCKATTR_SIZE__], + } + pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, @@ -448,14 +453,8 @@ pub const _PC_PIPE_BUF: ::c_int = 6; pub const _PC_CHOWN_RESTRICTED: ::c_int = 7; pub const _PC_NO_TRUNC: ::c_int = 8; pub const _PC_VDISABLE: ::c_int = 9; -pub const O_RDONLY: ::c_int = 0; -pub const O_WRONLY: ::c_int = 1; -pub const O_RDWR: ::c_int = 2; -pub const O_APPEND: ::c_int = 8; -pub const O_CREAT: ::c_int = 512; -pub const O_EXCL: ::c_int = 2048; -pub const O_NOCTTY: ::c_int = 131072; -pub const O_TRUNC: ::c_int = 1024; +pub const O_DSYNC: ::c_int = 0x400000; +pub const O_NOCTTY: ::c_int = 0x20000; pub const O_CLOEXEC: ::c_int = 0x1000000; pub const O_DIRECTORY: ::c_int = 0x100000; pub const S_IFIFO: mode_t = 4096; @@ -671,8 +670,6 @@ pub const AT_SYMLINK_NOFOLLOW: ::c_int = 0x0020; pub const AT_SYMLINK_FOLLOW: ::c_int = 0x0040; pub const AT_REMOVEDIR: ::c_int = 0x0080; -pub const O_ACCMODE: ::c_int = 3; - pub const TIOCMODG: ::c_ulong = 0x40047403; pub const TIOCMODS: ::c_ulong = 0x80047404; pub const TIOCM_LE: ::c_int = 0x1; @@ -812,6 +809,8 @@ pub const _SC_XOPEN_UNIX: ::c_int = 115; pub const _SC_XOPEN_VERSION: ::c_int = 116; pub const _SC_XOPEN_XCU_VERSION: ::c_int = 121; +pub const PTHREAD_PROCESS_PRIVATE: ::c_int = 2; +pub const PTHREAD_PROCESS_SHARED: ::c_int = 1; pub const PTHREAD_CREATE_JOINABLE: ::c_int = 1; pub const PTHREAD_CREATE_DETACHED: ::c_int = 2; pub const PTHREAD_STACK_MIN: ::size_t = 8192; @@ -1024,10 +1023,6 @@ pub const LOCK_EX: ::c_int = 2; pub const LOCK_NB: ::c_int = 4; pub const LOCK_UN: ::c_int = 8; -pub const O_DSYNC: ::c_int = 4194304; -pub const O_SYNC: ::c_int = 128; -pub const O_NONBLOCK: ::c_int = 4; - pub const MAP_COPY: ::c_int = 0x0002; pub const MAP_RENAME: ::c_int = 0x0020; pub const MAP_NORESERVE: ::c_int = 0x0040; @@ -1238,6 +1233,18 @@ pub const NOTE_TRACK: ::uint32_t = 0x00000001; pub const NOTE_TRACKERR: ::uint32_t = 0x00000002; pub const NOTE_CHILD: ::uint32_t = 0x00000004; +pub const OCRNL: ::c_int = 0x00000010; +pub const ONOCR: ::c_int = 0x00000020; +pub const ONLRET: ::c_int = 0x00000040; +pub const OFILL: ::c_int = 0x00000080; +pub const NLDLY: ::c_int = 0x00000300; +pub const TABDLY: ::c_int = 0x00000c04; +pub const CRDLY: ::c_int = 0x00003000; +pub const FFDLY: ::c_int = 0x00004000; +pub const BSDLY: ::c_int = 0x00008000; +pub const VTDLY: ::c_int = 0x00010000; +pub const OFDEL: ::c_int = 0x00020000; + pub const NL0: ::c_int = 0x00000000; pub const NL1: ::c_int = 0x00000100; pub const TAB0: ::c_int = 0x00000000; @@ -1516,6 +1523,13 @@ pub const P_ALL: idtype_t = 0; pub const P_PID: idtype_t = 1; pub const P_PGID: idtype_t = 2; +pub const XATTR_NOFOLLOW: ::c_int = 0x0001; +pub const XATTR_CREATE: ::c_int = 0x0002; +pub const XATTR_REPLACE: ::c_int = 0x0004; +pub const XATTR_NOSECURITY: ::c_int = 0x0008; +pub const XATTR_NODEFAULT: ::c_int = 0x0010; +pub const XATTR_SHOWCOMPRESSION: ::c_int = 0x0020; + f! { pub fn WSTOPSIG(status: ::c_int) -> ::c_int { status >> 8 @@ -1552,6 +1566,8 @@ extern { pub fn lio_listio(mode: ::c_int, aiocb_list: *const *mut aiocb, nitems: ::c_int, sevp: *mut sigevent) -> ::c_int; + pub fn dirfd(dirp: *mut ::DIR) -> ::c_int; + pub fn lutimes(file: *const ::c_char, times: *const ::timeval) -> ::c_int; pub fn getutxent() -> *mut utmpx; @@ -1606,6 +1622,10 @@ extern { pshared: ::c_int) -> ::c_int; pub fn pthread_mutexattr_getpshared(attr: *const pthread_mutexattr_t, pshared: *mut ::c_int) -> ::c_int; + pub fn pthread_rwlockattr_getpshared(attr: *const pthread_rwlockattr_t, + val: *mut ::c_int) -> ::c_int; + pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, + val: ::c_int) -> ::c_int; pub fn __error() -> *mut ::c_int; pub fn backtrace(buf: *mut *mut ::c_void, sz: ::c_int) -> ::c_int; @@ -1665,13 +1685,36 @@ extern { pub fn getpriority(which: ::c_int, who: ::id_t) -> ::c_int; pub fn setpriority(which: ::c_int, who: ::id_t, prio: ::c_int) -> ::c_int; + pub fn getxattr(path: *const ::c_char, name: *const ::c_char, + value: *mut ::c_void, size: ::size_t, position: u32, + flags: ::c_int) -> ::ssize_t; + pub fn fgetxattr(filedes: ::c_int, name: *const ::c_char, + value: *mut ::c_void, size: ::size_t, position: u32, + flags: ::c_int) -> ::ssize_t; + pub fn setxattr(path: *const ::c_char, name: *const ::c_char, + value: *const ::c_void, size: ::size_t, position: u32, + flags: ::c_int) -> ::c_int; + pub fn fsetxattr(filedes: ::c_int, name: *const ::c_char, + value: *const ::c_void, size: ::size_t, position: u32, + flags: ::c_int) -> ::c_int; + pub fn listxattr(path: *const ::c_char, list: *mut ::c_char, + size: ::size_t, flags: ::c_int) -> ::ssize_t; + pub fn flistxattr(filedes: ::c_int, list: *mut ::c_char, + size: ::size_t, flags: ::c_int) -> ::ssize_t; + pub fn removexattr(path: *const ::c_char, name: *const ::c_char, + flags: ::c_int) -> ::c_int; + pub fn fremovexattr(filedes: ::c_int, name: *const ::c_char, + flags: ::c_int) -> ::c_int; + pub fn initgroups(user: *const ::c_char, basegroup: ::c_int) -> ::c_int; #[cfg_attr(all(target_os = "macos", target_arch = "x86"), link_name = "waitid$UNIX2003")] pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t, options: ::c_int) -> ::c_int; - + pub fn brk(addr: *const ::c_void) -> *mut ::c_void; + pub fn sbrk(increment: ::c_int) -> *mut ::c_void; + pub fn settimeofday(tv: *const ::timeval, tz: *const ::timezone) -> ::c_int; } cfg_if! { diff --git a/src/vendor/libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs b/src/vendor/libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs index e60825a522..694c7f01b9 100644 --- a/src/vendor/libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs +++ b/src/vendor/libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs @@ -134,10 +134,11 @@ s! { } pub const RAND_MAX: ::c_int = 0x7fff_ffff; -pub const PTHREAD_STACK_MIN: ::size_t = 1024; +pub const PTHREAD_STACK_MIN: ::size_t = 16384; pub const SIGSTKSZ: ::size_t = 40960; pub const MADV_INVAL: ::c_int = 10; pub const O_CLOEXEC: ::c_int = 0x00020000; +pub const O_DIRECTORY: ::c_int = 0x08000000; pub const F_GETLK: ::c_int = 7; pub const F_SETLK: ::c_int = 8; pub const F_SETLKW: ::c_int = 9; @@ -404,6 +405,25 @@ pub const TIOCMODG: ::c_uint = 0x40047403; pub const TIOCMODS: ::c_ulong = 0x80047404; pub const TIOCREMOTE: ::c_ulong = 0x80047469; +// Constants used by "at" family of system calls. +pub const AT_FDCWD: ::c_int = 0xFFFAFDCD; // invalid file descriptor +pub const AT_SYMLINK_NOFOLLOW: ::c_int = 1; +pub const AT_REMOVEDIR: ::c_int = 2; +pub const AT_EACCESS: ::c_int = 4; +pub const AT_SYMLINK_FOLLOW: ::c_int = 8; + +pub const VCHECKPT: usize = 19; + +pub const _PC_2_SYMLINKS: ::c_int = 22; +pub const _PC_TIMESTAMP_RESOLUTION: ::c_int = 23; + +pub const _SC_V7_ILP32_OFF32: ::c_int = 122; +pub const _SC_V7_ILP32_OFFBIG: ::c_int = 123; +pub const _SC_V7_LP64_OFF64: ::c_int = 124; +pub const _SC_V7_LPBIG_OFFBIG: ::c_int = 125; +pub const _SC_THREAD_ROBUST_PRIO_INHERIT: ::c_int = 126; +pub const _SC_THREAD_ROBUST_PRIO_PROTECT: ::c_int = 127; + extern { pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; diff --git a/src/vendor/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs b/src/vendor/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs index fb113ded33..e570e38bd9 100644 --- a/src/vendor/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs +++ b/src/vendor/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs @@ -139,6 +139,9 @@ pub const SF_NODISKIO: ::c_int = 0x00000001; pub const SF_MNOWAIT: ::c_int = 0x00000002; pub const SF_SYNC: ::c_int = 0x00000004; pub const O_CLOEXEC: ::c_int = 0x00100000; +pub const O_DIRECTORY: ::c_int = 0x00020000; +pub const O_EXEC: ::c_int = 0x00040000; +pub const O_TTY_INIT: ::c_int = 0x00080000; pub const F_GETLK: ::c_int = 11; pub const F_SETLK: ::c_int = 12; pub const F_SETLKW: ::c_int = 13; @@ -508,6 +511,20 @@ pub const P_ALL: idtype_t = 7; pub const B460800: ::speed_t = 460800; pub const B921600: ::speed_t = 921600; +pub const AT_FDCWD: ::c_int = -100; +pub const AT_EACCESS: ::c_int = 0x100; +pub const AT_SYMLINK_NOFOLLOW: ::c_int = 0x200; +pub const AT_SYMLINK_FOLLOW: ::c_int = 0x400; +pub const AT_REMOVEDIR: ::c_int = 0x800; + +pub const TABDLY: ::tcflag_t = 0x00000004; +pub const TAB0: ::tcflag_t = 0x00000000; +pub const TAB3: ::tcflag_t = 0x00000004; + +pub const _PC_ACL_NFS4: ::c_int = 64; + +pub const _SC_CPUSET_SIZE: ::c_int = 122; + extern { pub fn __error() -> *mut ::c_int; @@ -559,6 +576,7 @@ extern { msgtyp: ::c_long, msgflg: ::c_int) -> ::c_int; pub fn msgsnd(msqid: ::c_int, msgp: *const ::c_void, msgsz: ::size_t, msgflg: ::c_int) -> ::c_int; + pub fn cfmakesane(termios: *mut ::termios); } cfg_if! { diff --git a/src/vendor/libc/src/unix/bsd/freebsdlike/mod.rs b/src/vendor/libc/src/unix/bsd/freebsdlike/mod.rs index 5cfa3b1143..7540d7992d 100644 --- a/src/vendor/libc/src/unix/bsd/freebsdlike/mod.rs +++ b/src/vendor/libc/src/unix/bsd/freebsdlike/mod.rs @@ -7,6 +7,7 @@ pub type pthread_mutexattr_t = *mut ::c_void; pub type pthread_cond_t = *mut ::c_void; pub type pthread_condattr_t = *mut ::c_void; pub type pthread_rwlock_t = *mut ::c_void; +pub type pthread_rwlockattr_t = *mut ::c_void; pub type pthread_key_t = ::c_int; pub type tcflag_t = ::c_uint; pub type speed_t = ::c_uint; @@ -272,15 +273,9 @@ pub const FILENAME_MAX: ::c_uint = 1024; pub const L_tmpnam: ::c_uint = 1024; pub const TMP_MAX: ::c_uint = 308915776; -pub const O_RDONLY: ::c_int = 0; -pub const O_WRONLY: ::c_int = 1; -pub const O_RDWR: ::c_int = 2; -pub const O_ACCMODE: ::c_int = 3; -pub const O_APPEND: ::c_int = 8; -pub const O_CREAT: ::c_int = 512; -pub const O_EXCL: ::c_int = 2048; pub const O_NOCTTY: ::c_int = 32768; -pub const O_TRUNC: ::c_int = 1024; +pub const O_DIRECT: ::c_int = 0x00010000; + pub const S_IFIFO: mode_t = 4096; pub const S_IFCHR: mode_t = 8192; pub const S_IFBLK: mode_t = 24576; @@ -452,11 +447,6 @@ pub const F_SETFD: ::c_int = 2; pub const F_GETFL: ::c_int = 3; pub const F_SETFL: ::c_int = 4; -pub const AT_EACCESS: ::c_int = 0x100; -pub const AT_SYMLINK_NOFOLLOW: ::c_int = 0x200; -pub const AT_SYMLINK_FOLLOW: ::c_int = 0x400; -pub const AT_REMOVEDIR: ::c_int = 0x800; - pub const SIGTRAP: ::c_int = 5; pub const GLOB_APPEND : ::c_int = 0x0001; @@ -477,36 +467,8 @@ pub const POSIX_MADV_SEQUENTIAL: ::c_int = 2; pub const POSIX_MADV_WILLNEED: ::c_int = 3; pub const POSIX_MADV_DONTNEED: ::c_int = 4; -pub const _SC_IOV_MAX: ::c_int = 56; -pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 70; -pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 71; -pub const _SC_LOGIN_NAME_MAX: ::c_int = 73; -pub const _SC_MQ_PRIO_MAX: ::c_int = 75; -pub const _SC_NPROCESSORS_ONLN: ::c_int = 58; -pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 82; -pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 83; -pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 85; -pub const _SC_THREAD_KEYS_MAX: ::c_int = 86; -pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 87; -pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 88; -pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 89; -pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 90; -pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 91; -pub const _SC_THREAD_STACK_MIN: ::c_int = 93; -pub const _SC_THREAD_THREADS_MAX: ::c_int = 94; -pub const _SC_THREADS: ::c_int = 96; -pub const _SC_TTY_NAME_MAX: ::c_int = 101; -pub const _SC_ATEXIT_MAX: ::c_int = 107; -pub const _SC_XOPEN_CRYPT: ::c_int = 108; -pub const _SC_XOPEN_ENH_I18N: ::c_int = 109; -pub const _SC_XOPEN_LEGACY: ::c_int = 110; -pub const _SC_XOPEN_REALTIME: ::c_int = 111; -pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 112; -pub const _SC_XOPEN_SHM: ::c_int = 113; -pub const _SC_XOPEN_UNIX: ::c_int = 115; -pub const _SC_XOPEN_VERSION: ::c_int = 116; -pub const _SC_XOPEN_XCU_VERSION: ::c_int = 117; - +pub const PTHREAD_PROCESS_PRIVATE: ::c_int = 0; +pub const PTHREAD_PROCESS_SHARED: ::c_int = 1; pub const PTHREAD_CREATE_JOINABLE: ::c_int = 0; pub const PTHREAD_CREATE_DETACHED: ::c_int = 1; @@ -687,9 +649,6 @@ pub const LOCK_EX: ::c_int = 2; pub const LOCK_NB: ::c_int = 4; pub const LOCK_UN: ::c_int = 8; -pub const O_SYNC: ::c_int = 128; -pub const O_NONBLOCK: ::c_int = 4; - pub const MAP_COPY: ::c_int = 0x0002; pub const MAP_RENAME: ::c_int = 0x0020; pub const MAP_NORESERVE: ::c_int = 0x0040; @@ -700,6 +659,32 @@ pub const MAP_NOCORE: ::c_int = 0x020000; pub const IPPROTO_RAW: ::c_int = 255; +pub const _PC_LINK_MAX: ::c_int = 1; +pub const _PC_MAX_CANON: ::c_int = 2; +pub const _PC_MAX_INPUT: ::c_int = 3; +pub const _PC_NAME_MAX: ::c_int = 4; +pub const _PC_PATH_MAX: ::c_int = 5; +pub const _PC_PIPE_BUF: ::c_int = 6; +pub const _PC_CHOWN_RESTRICTED: ::c_int = 7; +pub const _PC_NO_TRUNC: ::c_int = 8; +pub const _PC_VDISABLE: ::c_int = 9; +pub const _PC_ALLOC_SIZE_MIN: ::c_int = 10; +pub const _PC_FILESIZEBITS: ::c_int = 12; +pub const _PC_REC_INCR_XFER_SIZE: ::c_int = 14; +pub const _PC_REC_MAX_XFER_SIZE: ::c_int = 15; +pub const _PC_REC_MIN_XFER_SIZE: ::c_int = 16; +pub const _PC_REC_XFER_ALIGN: ::c_int = 17; +pub const _PC_SYMLINK_MAX: ::c_int = 18; +pub const _PC_MIN_HOLE_SIZE: ::c_int = 21; +pub const _PC_ASYNC_IO: ::c_int = 53; +pub const _PC_PRIO_IO: ::c_int = 54; +pub const _PC_SYNC_IO: ::c_int = 55; +pub const _PC_ACL_EXTENDED: ::c_int = 59; +pub const _PC_ACL_PATH_MAX: ::c_int = 60; +pub const _PC_CAP_PRESENT: ::c_int = 61; +pub const _PC_INF_PRESENT: ::c_int = 62; +pub const _PC_MAC_PRESENT: ::c_int = 63; + pub const _SC_ARG_MAX: ::c_int = 1; pub const _SC_CHILD_MAX: ::c_int = 2; pub const _SC_CLK_TCK: ::c_int = 3; @@ -753,7 +738,71 @@ pub const _SC_SEM_NSEMS_MAX: ::c_int = 49; pub const _SC_SEM_VALUE_MAX: ::c_int = 50; pub const _SC_SIGQUEUE_MAX: ::c_int = 51; pub const _SC_TIMER_MAX: ::c_int = 52; +pub const _SC_IOV_MAX: ::c_int = 56; +pub const _SC_NPROCESSORS_CONF: ::c_int = 57; +pub const _SC_2_PBS: ::c_int = 59; +pub const _SC_2_PBS_ACCOUNTING: ::c_int = 60; +pub const _SC_2_PBS_CHECKPOINT: ::c_int = 61; +pub const _SC_2_PBS_LOCATE: ::c_int = 62; +pub const _SC_2_PBS_MESSAGE: ::c_int = 63; +pub const _SC_2_PBS_TRACK: ::c_int = 64; +pub const _SC_ADVISORY_INFO: ::c_int = 65; +pub const _SC_BARRIERS: ::c_int = 66; +pub const _SC_CLOCK_SELECTION: ::c_int = 67; +pub const _SC_CPUTIME: ::c_int = 68; +pub const _SC_FILE_LOCKING: ::c_int = 69; +pub const _SC_NPROCESSORS_ONLN: ::c_int = 58; +pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 70; +pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 71; pub const _SC_HOST_NAME_MAX: ::c_int = 72; +pub const _SC_LOGIN_NAME_MAX: ::c_int = 73; +pub const _SC_MONOTONIC_CLOCK: ::c_int = 74; +pub const _SC_MQ_PRIO_MAX: ::c_int = 75; +pub const _SC_READER_WRITER_LOCKS: ::c_int = 76; +pub const _SC_REGEXP: ::c_int = 77; +pub const _SC_SHELL: ::c_int = 78; +pub const _SC_SPAWN: ::c_int = 79; +pub const _SC_SPIN_LOCKS: ::c_int = 80; +pub const _SC_SPORADIC_SERVER: ::c_int = 81; +pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 82; +pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 83; +pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 85; +pub const _SC_THREAD_KEYS_MAX: ::c_int = 86; +pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 87; +pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 88; +pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 89; +pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 90; +pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 91; +pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 92; +pub const _SC_THREAD_STACK_MIN: ::c_int = 93; +pub const _SC_THREAD_THREADS_MAX: ::c_int = 94; +pub const _SC_TIMEOUTS: ::c_int = 95; +pub const _SC_THREADS: ::c_int = 96; +pub const _SC_TRACE: ::c_int = 97; +pub const _SC_TRACE_EVENT_FILTER: ::c_int = 98; +pub const _SC_TRACE_INHERIT: ::c_int = 99; +pub const _SC_TRACE_LOG: ::c_int = 100; +pub const _SC_TTY_NAME_MAX: ::c_int = 101; +pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 102; +pub const _SC_V6_ILP32_OFF32: ::c_int = 103; +pub const _SC_V6_ILP32_OFFBIG: ::c_int = 104; +pub const _SC_V6_LP64_OFF64: ::c_int = 105; +pub const _SC_V6_LPBIG_OFFBIG: ::c_int = 106; +pub const _SC_ATEXIT_MAX: ::c_int = 107; +pub const _SC_XOPEN_CRYPT: ::c_int = 108; +pub const _SC_XOPEN_ENH_I18N: ::c_int = 109; +pub const _SC_XOPEN_LEGACY: ::c_int = 110; +pub const _SC_XOPEN_REALTIME: ::c_int = 111; +pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 112; +pub const _SC_XOPEN_SHM: ::c_int = 113; +pub const _SC_XOPEN_STREAMS: ::c_int = 114; +pub const _SC_XOPEN_UNIX: ::c_int = 115; +pub const _SC_XOPEN_VERSION: ::c_int = 116; +pub const _SC_XOPEN_XCU_VERSION: ::c_int = 117; +pub const _SC_IPV6: ::c_int = 118; +pub const _SC_RAW_SOCKETS: ::c_int = 119; +pub const _SC_SYMLOOP_MAX: ::c_int = 120; +pub const _SC_PHYS_PAGES: ::c_int = 121; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = 0 as *mut _; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = 0 as *mut _; @@ -875,6 +924,15 @@ pub const EXTB: speed_t = 38400; pub const SEM_FAILED: *mut sem_t = 0 as *mut sem_t; pub const CRTSCTS: ::tcflag_t = 0x00030000; +pub const CCTS_OFLOW: ::tcflag_t = 0x00010000; +pub const CRTS_IFLOW: ::tcflag_t = 0x00020000; +pub const CDTR_IFLOW: ::tcflag_t = 0x00040000; +pub const CDSR_OFLOW: ::tcflag_t = 0x00080000; +pub const CCAR_OFLOW: ::tcflag_t = 0x00100000; +pub const VERASE2: usize = 7; +pub const OCRNL: ::tcflag_t = 0x10; +pub const ONOCR: ::tcflag_t = 0x20; +pub const ONLRET: ::tcflag_t = 0x40; f! { pub fn WIFCONTINUED(status: ::c_int) -> bool { @@ -916,6 +974,7 @@ 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 dirfd(dirp: *mut ::DIR) -> ::c_int; pub fn getnameinfo(sa: *const ::sockaddr, salen: ::socklen_t, host: *mut ::c_char, @@ -1003,6 +1062,10 @@ extern { pshared: ::c_int) -> ::c_int; pub fn pthread_mutexattr_getpshared(attr: *const pthread_mutexattr_t, pshared: *mut ::c_int) -> ::c_int; + pub fn pthread_rwlockattr_getpshared(attr: *const pthread_rwlockattr_t, + val: *mut ::c_int) -> ::c_int; + pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, + val: ::c_int) -> ::c_int; pub fn getpriority(which: ::c_int, who: ::c_int) -> ::c_int; pub fn setpriority(which: ::c_int, who: ::c_int, prio: ::c_int) -> ::c_int; @@ -1026,6 +1089,7 @@ extern { nfds: ::nfds_t, timeout: *const ::timespec, sigmask: *const sigset_t) -> ::c_int; + pub fn settimeofday(tv: *const ::timeval, tz: *const ::timezone) -> ::c_int; } cfg_if! { diff --git a/src/vendor/libc/src/unix/bsd/mod.rs b/src/vendor/libc/src/unix/bsd/mod.rs index 69c71389ad..ec65f9ea92 100644 --- a/src/vendor/libc/src/unix/bsd/mod.rs +++ b/src/vendor/libc/src/unix/bsd/mod.rs @@ -187,10 +187,22 @@ pub const ST_RDONLY: ::c_ulong = 1; pub const NCCS: usize = 20; +pub const O_ACCMODE: ::c_int = 0x3; +pub const O_RDONLY: ::c_int = 0; +pub const O_WRONLY: ::c_int = 1; +pub const O_RDWR: ::c_int = 2; +pub const O_APPEND: ::c_int = 8; +pub const O_CREAT: ::c_int = 512; +pub const O_TRUNC: ::c_int = 1024; +pub const O_EXCL: ::c_int = 2048; pub const O_ASYNC: ::c_int = 0x40; -pub const O_FSYNC: ::c_int = 0x80; -pub const O_NDELAY: ::c_int = 0x4; +pub const O_SYNC: ::c_int = 0x80; +pub const O_NONBLOCK: ::c_int = 0x4; pub const O_NOFOLLOW: ::c_int = 0x100; +pub const O_SHLOCK: ::c_int = 0x10; +pub const O_EXLOCK: ::c_int = 0x20; +pub const O_FSYNC: ::c_int = O_SYNC; +pub const O_NDELAY: ::c_int = O_NONBLOCK; pub const F_GETOWN: ::c_int = 5; pub const F_SETOWN: ::c_int = 6; @@ -221,12 +233,15 @@ pub const VREPRINT: usize = 6; pub const VINTR: usize = 8; pub const VQUIT: usize = 9; pub const VSUSP: usize = 10; +pub const VDSUSP: usize = 11; pub const VSTART: usize = 12; pub const VSTOP: usize = 13; pub const VLNEXT: usize = 14; pub const VDISCARD: usize = 15; pub const VMIN: usize = 16; pub const VTIME: usize = 17; +pub const VSTATUS: usize = 18; +pub const _POSIX_VDISABLE: ::cc_t = 0xff; pub const IGNBRK: ::tcflag_t = 0x00000001; pub const BRKINT: ::tcflag_t = 0x00000002; pub const IGNPAR: ::tcflag_t = 0x00000004; @@ -244,6 +259,7 @@ pub const OPOST: ::tcflag_t = 0x1; pub const ONLCR: ::tcflag_t = 0x2; pub const OXTABS: ::tcflag_t = 0x4; pub const ONOEOT: ::tcflag_t = 0x8; +pub const CIGNORE: ::tcflag_t = 0x00000001; pub const CSIZE: ::tcflag_t = 0x00000300; pub const CS5: ::tcflag_t = 0x00000000; pub const CS6: ::tcflag_t = 0x00000100; @@ -264,18 +280,23 @@ pub const ECHOPRT: ::tcflag_t = 0x00000020; pub const ECHOCTL: ::tcflag_t = 0x00000040; pub const ISIG: ::tcflag_t = 0x00000080; pub const ICANON: ::tcflag_t = 0x00000100; +pub const ALTWERASE: ::tcflag_t = 0x00000200; pub const IEXTEN: ::tcflag_t = 0x00000400; pub const EXTPROC: ::tcflag_t = 0x00000800; pub const TOSTOP: ::tcflag_t = 0x00400000; pub const FLUSHO: ::tcflag_t = 0x00800000; +pub const NOKERNINFO: ::tcflag_t = 0x02000000; pub const PENDIN: ::tcflag_t = 0x20000000; pub const NOFLSH: ::tcflag_t = 0x80000000; +pub const MDMBUF: ::tcflag_t = 0x00100000; pub const WNOHANG: ::c_int = 0x00000001; pub const WUNTRACED: ::c_int = 0x00000002; pub const RTLD_NOW: ::c_int = 0x2; +pub const RTLD_NEXT: *mut ::c_void = -1isize as *mut ::c_void; pub const RTLD_DEFAULT: *mut ::c_void = -2isize as *mut ::c_void; +pub const RTLD_SELF: *mut ::c_void = -3isize as *mut ::c_void; pub const LOG_CRON: ::c_int = 9 << 3; pub const LOG_AUTHPRIV: ::c_int = 10 << 3; @@ -430,6 +451,8 @@ extern { link_name = "recvmsg$UNIX2003")] pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int) -> ::ssize_t; + + pub fn sync(); } cfg_if! { diff --git a/src/vendor/libc/src/unix/bsd/netbsdlike/mod.rs b/src/vendor/libc/src/unix/bsd/netbsdlike/mod.rs index 1471e6f384..55f58011ef 100644 --- a/src/vendor/libc/src/unix/bsd/netbsdlike/mod.rs +++ b/src/vendor/libc/src/unix/bsd/netbsdlike/mod.rs @@ -127,16 +127,7 @@ pub const BUFSIZ : ::c_uint = 1024; pub const FOPEN_MAX : ::c_uint = 20; pub const FILENAME_MAX : ::c_uint = 1024; pub const L_tmpnam : ::c_uint = 1024; -pub const O_RDONLY : ::c_int = 0; -pub const O_WRONLY : ::c_int = 1; -pub const O_RDWR : ::c_int = 2; -pub const O_ACCMODE : ::c_int = 3; -pub const O_APPEND : ::c_int = 8; -pub const O_CREAT : ::c_int = 512; -pub const O_EXCL : ::c_int = 2048; pub const O_NOCTTY : ::c_int = 32768; -pub const O_TRUNC : ::c_int = 1024; -pub const O_SYNC : ::c_int = 128; pub const S_IFIFO : mode_t = 4096; pub const S_IFCHR : mode_t = 8192; pub const S_IFBLK : mode_t = 24576; @@ -316,8 +307,6 @@ pub const POSIX_MADV_SEQUENTIAL : ::c_int = 2; pub const POSIX_MADV_WILLNEED : ::c_int = 3; pub const POSIX_MADV_DONTNEED : ::c_int = 4; -pub const _SC_XOPEN_SHM : ::c_int = 30; - pub const PTHREAD_CREATE_JOINABLE : ::c_int = 0; pub const PTHREAD_CREATE_DETACHED : ::c_int = 1; @@ -418,6 +407,7 @@ pub const PF_NATM: ::c_int = AF_NATM; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SOCK_RAW: ::c_int = 3; +pub const SOCK_RDM: ::c_int = 4; pub const SOCK_SEQPACKET: ::c_int = 5; pub const IPPROTO_ICMP: ::c_int = 1; pub const IPPROTO_ICMPV6: ::c_int = 58; @@ -478,8 +468,6 @@ pub const LOCK_EX: ::c_int = 2; pub const LOCK_NB: ::c_int = 4; pub const LOCK_UN: ::c_int = 8; -pub const O_NONBLOCK : ::c_int = 4; - pub const IPPROTO_RAW : ::c_int = 255; pub const _SC_ARG_MAX : ::c_int = 1; @@ -511,6 +499,7 @@ pub const _SC_TZNAME_MAX : ::c_int = 27; pub const _SC_PAGESIZE : ::c_int = 28; pub const _SC_PAGE_SIZE: ::c_int = _SC_PAGESIZE; pub const _SC_FSYNC : ::c_int = 29; +pub const _SC_XOPEN_SHM : ::c_int = 30; pub const Q_GETQUOTA: ::c_int = 0x300; pub const Q_SETQUOTA: ::c_int = 0x400; @@ -549,6 +538,23 @@ pub const EXTB: speed_t = 38400; pub const SEM_FAILED: *mut sem_t = 0 as *mut sem_t; +pub const CRTSCTS: ::tcflag_t = 0x00010000; +pub const CRTS_IFLOW: ::tcflag_t = CRTSCTS; +pub const CCTS_OFLOW: ::tcflag_t = CRTSCTS; +pub const OCRNL: ::tcflag_t = 0x10; + +pub const TIOCM_LE: ::c_int = 0o0001; +pub const TIOCM_DTR: ::c_int = 0o0002; +pub const TIOCM_RTS: ::c_int = 0o0004; +pub const TIOCM_ST: ::c_int = 0o0010; +pub const TIOCM_SR: ::c_int = 0o0020; +pub const TIOCM_CTS: ::c_int = 0o0040; +pub const TIOCM_CAR: ::c_int = 0o0100; +pub const TIOCM_RNG: ::c_int = 0o0200; +pub const TIOCM_DSR: ::c_int = 0o0400; +pub const TIOCM_CD: ::c_int = TIOCM_CAR; +pub const TIOCM_RI: ::c_int = TIOCM_RNG; + f! { pub fn WSTOPSIG(status: ::c_int) -> ::c_int { status >> 8 diff --git a/src/vendor/libc/src/unix/bsd/netbsdlike/netbsd/mod.rs b/src/vendor/libc/src/unix/bsd/netbsdlike/netbsd/mod.rs index ffe8d75cb8..79f2fce756 100644 --- a/src/vendor/libc/src/unix/bsd/netbsdlike/netbsd/mod.rs +++ b/src/vendor/libc/src/unix/bsd/netbsdlike/netbsd/mod.rs @@ -165,6 +165,11 @@ s! { ptma_private: *mut ::c_void, } + pub struct pthread_rwlockattr_t { + ptra_magic: ::c_uint, + ptra_private: *mut ::c_void, + } + pub struct pthread_cond_t { ptc_magic: ::c_uint, ptc_lock: ::c_uchar, @@ -270,9 +275,9 @@ pub const O_CLOEXEC: ::c_int = 0x400000; pub const O_ALT_IO: ::c_int = 0x40000; pub const O_NOSIGPIPE: ::c_int = 0x1000000; pub const O_SEARCH: ::c_int = 0x800000; -pub const O_EXLOCK: ::c_int = 0x20; -pub const O_SHLOCK: ::c_int = 0x10; pub const O_DIRECTORY: ::c_int = 0x200000; +pub const O_DIRECT : ::c_int = 0x00080000; +pub const O_RSYNC : ::c_int = 0x00020000; pub const MS_SYNC : ::c_int = 0x4; pub const MS_INVALIDATE : ::c_int = 0x2; @@ -349,42 +354,91 @@ pub const MAP_NORESERVE : ::c_int = 0x40; pub const MAP_HASSEMAPHORE : ::c_int = 0x200; pub const MAP_WIRED: ::c_int = 0x800; +pub const _PC_LINK_MAX : ::c_int = 1; +pub const _PC_MAX_CANON : ::c_int = 2; +pub const _PC_MAX_INPUT : ::c_int = 3; +pub const _PC_NAME_MAX : ::c_int = 4; +pub const _PC_PATH_MAX : ::c_int = 5; +pub const _PC_PIPE_BUF : ::c_int = 6; +pub const _PC_CHOWN_RESTRICTED : ::c_int = 7; +pub const _PC_NO_TRUNC : ::c_int = 8; +pub const _PC_VDISABLE : ::c_int = 9; +pub const _PC_SYNC_IO : ::c_int = 10; +pub const _PC_FILESIZEBITS : ::c_int = 11; +pub const _PC_SYMLINK_MAX : ::c_int = 12; +pub const _PC_2_SYMLINKS : ::c_int = 13; +pub const _PC_ACL_EXTENDED : ::c_int = 14; +pub const _PC_MIN_HOLE_SIZE : ::c_int = 15; + +pub const _SC_SYNCHRONIZED_IO : ::c_int = 31; pub const _SC_IOV_MAX : ::c_int = 32; +pub const _SC_MAPPED_FILES : ::c_int = 33; +pub const _SC_MEMLOCK : ::c_int = 34; +pub const _SC_MEMLOCK_RANGE : ::c_int = 35; +pub const _SC_MEMORY_PROTECTION : ::c_int = 36; +pub const _SC_LOGIN_NAME_MAX : ::c_int = 37; +pub const _SC_MONOTONIC_CLOCK : ::c_int = 38; +pub const _SC_CLK_TCK : ::c_int = 39; +pub const _SC_ATEXIT_MAX : ::c_int = 40; +pub const _SC_THREADS : ::c_int = 41; +pub const _SC_SEMAPHORES : ::c_int = 42; +pub const _SC_BARRIERS : ::c_int = 43; +pub const _SC_TIMERS : ::c_int = 44; +pub const _SC_SPIN_LOCKS : ::c_int = 45; +pub const _SC_READER_WRITER_LOCKS : ::c_int = 46; pub const _SC_GETGR_R_SIZE_MAX : ::c_int = 47; pub const _SC_GETPW_R_SIZE_MAX : ::c_int = 48; -pub const _SC_LOGIN_NAME_MAX : ::c_int = 37; +pub const _SC_CLOCK_SELECTION : ::c_int = 49; +pub const _SC_ASYNCHRONOUS_IO : ::c_int = 50; +pub const _SC_AIO_LISTIO_MAX : ::c_int = 51; +pub const _SC_AIO_MAX : ::c_int = 52; +pub const _SC_MESSAGE_PASSING : ::c_int = 53; +pub const _SC_MQ_OPEN_MAX : ::c_int = 54; pub const _SC_MQ_PRIO_MAX : ::c_int = 55; -pub const _SC_NPROCESSORS_ONLN : ::c_int = 1002; -pub const _SC_THREADS : ::c_int = 41; -pub const _SC_THREAD_ATTR_STACKADDR : ::c_int = 61; -pub const _SC_THREAD_ATTR_STACKSIZE : ::c_int = 62; +pub const _SC_PRIORITY_SCHEDULING : ::c_int = 56; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS : ::c_int = 57; pub const _SC_THREAD_KEYS_MAX : ::c_int = 58; +pub const _SC_THREAD_STACK_MIN : ::c_int = 59; +pub const _SC_THREAD_THREADS_MAX : ::c_int = 60; +pub const _SC_THREAD_ATTR_STACKADDR : ::c_int = 61; +pub const _SC_THREAD_ATTR_STACKSIZE : ::c_int = 62; +pub const _SC_THREAD_PRIORITY_SCHEDULING : ::c_int = 63; pub const _SC_THREAD_PRIO_INHERIT : ::c_int = 64; pub const _SC_THREAD_PRIO_PROTECT : ::c_int = 65; -pub const _SC_THREAD_PRIORITY_SCHEDULING : ::c_int = 63; pub const _SC_THREAD_PROCESS_SHARED : ::c_int = 66; pub const _SC_THREAD_SAFE_FUNCTIONS : ::c_int = 67; -pub const _SC_THREAD_STACK_MIN : ::c_int = 59; -pub const _SC_THREAD_THREADS_MAX : ::c_int = 60; pub const _SC_TTY_NAME_MAX : ::c_int = 68; -pub const _SC_ATEXIT_MAX : ::c_int = 40; -pub const _SC_CLK_TCK : ::c_int = 39; -pub const _SC_AIO_LISTIO_MAX : ::c_int = 51; -pub const _SC_AIO_MAX : ::c_int = 52; -pub const _SC_ASYNCHRONOUS_IO : ::c_int = 50; -pub const _SC_MAPPED_FILES : ::c_int = 33; -pub const _SC_MEMLOCK : ::c_int = 34; -pub const _SC_MEMLOCK_RANGE : ::c_int = 35; -pub const _SC_MEMORY_PROTECTION : ::c_int = 36; -pub const _SC_MESSAGE_PASSING : ::c_int = 53; -pub const _SC_MQ_OPEN_MAX : ::c_int = 54; -pub const _SC_PRIORITY_SCHEDULING : ::c_int = 56; -pub const _SC_SEMAPHORES : ::c_int = 42; -pub const _SC_SHARED_MEMORY_OBJECTS : ::c_int = 87; -pub const _SC_SYNCHRONIZED_IO : ::c_int = 31; -pub const _SC_TIMERS : ::c_int = 44; pub const _SC_HOST_NAME_MAX : ::c_int = 69; +pub const _SC_PASS_MAX : ::c_int = 70; +pub const _SC_REGEXP : ::c_int = 71; +pub const _SC_SHELL : ::c_int = 72; +pub const _SC_SYMLOOP_MAX : ::c_int = 73; +pub const _SC_V6_ILP32_OFF32 : ::c_int = 74; +pub const _SC_V6_ILP32_OFFBIG : ::c_int = 75; +pub const _SC_V6_LP64_OFF64 : ::c_int = 76; +pub const _SC_V6_LPBIG_OFFBIG : ::c_int = 77; +pub const _SC_2_PBS : ::c_int = 80; +pub const _SC_2_PBS_ACCOUNTING : ::c_int = 81; +pub const _SC_2_PBS_CHECKPOINT : ::c_int = 82; +pub const _SC_2_PBS_LOCATE : ::c_int = 83; +pub const _SC_2_PBS_MESSAGE : ::c_int = 84; +pub const _SC_2_PBS_TRACK : ::c_int = 85; +pub const _SC_SPAWN : ::c_int = 86; +pub const _SC_SHARED_MEMORY_OBJECTS : ::c_int = 87; +pub const _SC_TIMER_MAX : ::c_int = 88; +pub const _SC_SEM_NSEMS_MAX : ::c_int = 89; +pub const _SC_CPUTIME : ::c_int = 90; +pub const _SC_THREAD_CPUTIME : ::c_int = 91; +pub const _SC_DELAYTIMER_MAX : ::c_int = 92; +// These two variables will be supported in NetBSD 8.0 +// pub const _SC_SIGQUEUE_MAX : ::c_int = 93; +// pub const _SC_REALTIME_SIGNALS : ::c_int = 94; +pub const _SC_PHYS_PAGES : ::c_int = 121; +pub const _SC_NPROCESSORS_CONF : ::c_int = 1001; +pub const _SC_NPROCESSORS_ONLN : ::c_int = 1002; +pub const _SC_SCHED_RT_TS : ::c_int = 2001; +pub const _SC_SCHED_PRI_MIN : ::c_int = 2002; +pub const _SC_SCHED_PRI_MAX : ::c_int = 2003; pub const FD_SETSIZE: usize = 0x100; @@ -463,8 +517,6 @@ pub const NOTE_TRACK: ::uint32_t = 0x00000001; pub const NOTE_TRACKERR: ::uint32_t = 0x00000002; pub const NOTE_CHILD: ::uint32_t = 0x00000004; -pub const CRTSCTS: ::tcflag_t = 0x00010000; - pub const TMP_MAX : ::c_uint = 308915776; pub const NI_MAXHOST: ::socklen_t = 1025; @@ -644,6 +696,20 @@ pub const P_PGID: idtype_t = 4; pub const B460800: ::speed_t = 460800; pub const B921600: ::speed_t = 921600; +pub const ONOCR: ::tcflag_t = 0x20; +pub const ONLRET: ::tcflag_t = 0x40; +pub const CDTRCTS: ::tcflag_t = 0x00020000; +pub const CHWFLOW: ::tcflag_t = ::MDMBUF | ::CRTSCTS | ::CDTRCTS; + +// dirfd() is a macro on netbsd to access +// the first field of the struct where dirp points to: +// http://cvsweb.netbsd.org/bsdweb.cgi/src/include/dirent.h?rev=1.36 +f! { + pub fn dirfd(dirp: *mut ::DIR) -> ::c_int { + unsafe { *(dirp as *const ::c_int) } + } +} + extern { pub fn aio_read(aiocbp: *mut aiocb) -> ::c_int; pub fn aio_write(aiocbp: *mut aiocb) -> ::c_int; @@ -719,6 +785,8 @@ extern { pub fn newlocale(mask: ::c_int, locale: *const ::c_char, base: ::locale_t) -> ::locale_t; + #[link_name = "__settimeofday50"] + pub fn settimeofday(tv: *const ::timeval, tz: *const ::c_void) -> ::c_int; } mod other; diff --git a/src/vendor/libc/src/unix/bsd/netbsdlike/openbsdlike/mod.rs b/src/vendor/libc/src/unix/bsd/netbsdlike/openbsdlike/mod.rs index b0d8128c03..e3a5115d0b 100644 --- a/src/vendor/libc/src/unix/bsd/netbsdlike/openbsdlike/mod.rs +++ b/src/vendor/libc/src/unix/bsd/netbsdlike/openbsdlike/mod.rs @@ -1,3 +1,5 @@ +use unix::bsd::O_SYNC; + pub type clock_t = i64; pub type suseconds_t = ::c_long; pub type dev_t = i32; @@ -11,6 +13,7 @@ pub type pthread_mutexattr_t = *mut ::c_void; pub type pthread_cond_t = *mut ::c_void; pub type pthread_condattr_t = *mut ::c_void; pub type pthread_rwlock_t = *mut ::c_void; +pub type pthread_rwlockattr_t = *mut ::c_void; s! { pub struct dirent { @@ -140,6 +143,8 @@ pub const UT_LINESIZE: usize = 8; pub const UT_HOSTSIZE: usize = 256; pub const O_CLOEXEC: ::c_int = 0x10000; +pub const O_DIRECTORY: ::c_int = 0x20000; +pub const O_RSYNC: ::c_int = O_SYNC; pub const MS_SYNC : ::c_int = 0x0002; pub const MS_INVALIDATE : ::c_int = 0x0004; @@ -232,58 +237,128 @@ pub const RUSAGE_THREAD: ::c_int = 1; pub const MAP_COPY : ::c_int = 0x0002; pub const MAP_NOEXTEND : ::c_int = 0x0000; +pub const _PC_LINK_MAX : ::c_int = 1; +pub const _PC_MAX_CANON : ::c_int = 2; +pub const _PC_MAX_INPUT : ::c_int = 3; +pub const _PC_NAME_MAX : ::c_int = 4; +pub const _PC_PATH_MAX : ::c_int = 5; +pub const _PC_PIPE_BUF : ::c_int = 6; +pub const _PC_CHOWN_RESTRICTED : ::c_int = 7; +pub const _PC_NO_TRUNC : ::c_int = 8; +pub const _PC_VDISABLE : ::c_int = 9; +pub const _PC_2_SYMLINKS : ::c_int = 10; +pub const _PC_ALLOC_SIZE_MIN : ::c_int = 11; +pub const _PC_ASYNC_IO : ::c_int = 12; +pub const _PC_FILESIZEBITS : ::c_int = 13; +pub const _PC_PRIO_IO : ::c_int = 14; +pub const _PC_REC_INCR_XFER_SIZE : ::c_int = 15; +pub const _PC_REC_MAX_XFER_SIZE : ::c_int = 16; +pub const _PC_REC_MIN_XFER_SIZE : ::c_int = 17; +pub const _PC_REC_XFER_ALIGN : ::c_int = 18; +pub const _PC_SYMLINK_MAX : ::c_int = 19; +pub const _PC_SYNC_IO : ::c_int = 20; +pub const _PC_TIMESTAMP_RESOLUTION : ::c_int = 21; + pub const _SC_CLK_TCK : ::c_int = 3; -pub const _SC_IOV_MAX : ::c_int = 51; -pub const _SC_GETGR_R_SIZE_MAX : ::c_int = 100; -pub const _SC_GETPW_R_SIZE_MAX : ::c_int = 101; -pub const _SC_LOGIN_NAME_MAX : ::c_int = 102; -pub const _SC_MQ_PRIO_MAX : ::c_int = 59; -pub const _SC_NPROCESSORS_ONLN : ::c_int = 503; -pub const _SC_THREADS : ::c_int = 91; -pub const _SC_THREAD_ATTR_STACKADDR : ::c_int = 77; -pub const _SC_THREAD_ATTR_STACKSIZE : ::c_int = 78; -pub const _SC_THREAD_DESTRUCTOR_ITERATIONS : ::c_int = 80; -pub const _SC_THREAD_KEYS_MAX : ::c_int = 81; -pub const _SC_THREAD_PRIO_INHERIT : ::c_int = 82; -pub const _SC_THREAD_PRIO_PROTECT : ::c_int = 83; -pub const _SC_THREAD_PRIORITY_SCHEDULING : ::c_int = 84; -pub const _SC_THREAD_PROCESS_SHARED : ::c_int = 85; -pub const _SC_THREAD_SAFE_FUNCTIONS : ::c_int = 103; -pub const _SC_THREAD_STACK_MIN : ::c_int = 89; -pub const _SC_THREAD_THREADS_MAX : ::c_int = 90; -pub const _SC_TTY_NAME_MAX : ::c_int = 107; -pub const _SC_ATEXIT_MAX : ::c_int = 46; +pub const _SC_SEM_NSEMS_MAX : ::c_int = 31; +pub const _SC_SEM_VALUE_MAX : ::c_int = 32; +pub const _SC_HOST_NAME_MAX : ::c_int = 33; +pub const _SC_MONOTONIC_CLOCK : ::c_int = 34; +pub const _SC_2_PBS : ::c_int = 35; +pub const _SC_2_PBS_ACCOUNTING : ::c_int = 36; +pub const _SC_2_PBS_CHECKPOINT : ::c_int = 37; +pub const _SC_2_PBS_LOCATE : ::c_int = 38; +pub const _SC_2_PBS_MESSAGE : ::c_int = 39; +pub const _SC_2_PBS_TRACK : ::c_int = 40; +pub const _SC_ADVISORY_INFO : ::c_int = 41; pub const _SC_AIO_LISTIO_MAX : ::c_int = 42; pub const _SC_AIO_MAX : ::c_int = 43; +pub const _SC_AIO_PRIO_DELTA_MAX : ::c_int = 44; pub const _SC_ASYNCHRONOUS_IO : ::c_int = 45; +pub const _SC_ATEXIT_MAX : ::c_int = 46; +pub const _SC_BARRIERS : ::c_int = 47; +pub const _SC_CLOCK_SELECTION : ::c_int = 48; +pub const _SC_CPUTIME : ::c_int = 49; +pub const _SC_DELAYTIMER_MAX : ::c_int = 50; +pub const _SC_IOV_MAX : ::c_int = 51; +pub const _SC_IPV6 : ::c_int = 52; pub const _SC_MAPPED_FILES : ::c_int = 53; pub const _SC_MEMLOCK : ::c_int = 54; pub const _SC_MEMLOCK_RANGE : ::c_int = 55; pub const _SC_MEMORY_PROTECTION : ::c_int = 56; pub const _SC_MESSAGE_PASSING : ::c_int = 57; pub const _SC_MQ_OPEN_MAX : ::c_int = 58; +pub const _SC_MQ_PRIO_MAX : ::c_int = 59; +pub const _SC_PRIORITIZED_IO : ::c_int = 60; pub const _SC_PRIORITY_SCHEDULING : ::c_int = 61; +pub const _SC_RAW_SOCKETS : ::c_int = 62; +pub const _SC_READER_WRITER_LOCKS : ::c_int = 63; +pub const _SC_REALTIME_SIGNALS : ::c_int = 64; +pub const _SC_REGEXP : ::c_int = 65; +pub const _SC_RTSIG_MAX : ::c_int = 66; pub const _SC_SEMAPHORES : ::c_int = 67; pub const _SC_SHARED_MEMORY_OBJECTS : ::c_int = 68; +pub const _SC_SHELL : ::c_int = 69; +pub const _SC_SIGQUEUE_MAX : ::c_int = 70; +pub const _SC_SPAWN : ::c_int = 71; +pub const _SC_SPIN_LOCKS : ::c_int = 72; +pub const _SC_SPORADIC_SERVER : ::c_int = 73; +pub const _SC_SS_REPL_MAX : ::c_int = 74; pub const _SC_SYNCHRONIZED_IO : ::c_int = 75; +pub const _SC_SYMLOOP_MAX : ::c_int = 76; +pub const _SC_THREAD_ATTR_STACKADDR : ::c_int = 77; +pub const _SC_THREAD_ATTR_STACKSIZE : ::c_int = 78; +pub const _SC_THREAD_CPUTIME : ::c_int = 79; +pub const _SC_THREAD_DESTRUCTOR_ITERATIONS : ::c_int = 80; +pub const _SC_THREAD_KEYS_MAX : ::c_int = 81; +pub const _SC_THREAD_PRIO_INHERIT : ::c_int = 82; +pub const _SC_THREAD_PRIO_PROTECT : ::c_int = 83; +pub const _SC_THREAD_PRIORITY_SCHEDULING : ::c_int = 84; +pub const _SC_THREAD_PROCESS_SHARED : ::c_int = 85; +pub const _SC_THREAD_ROBUST_PRIO_INHERIT : ::c_int = 86; +pub const _SC_THREAD_ROBUST_PRIO_PROTECT : ::c_int = 87; +pub const _SC_THREAD_SPORADIC_SERVER : ::c_int = 88; +pub const _SC_THREAD_STACK_MIN : ::c_int = 89; +pub const _SC_THREAD_THREADS_MAX : ::c_int = 90; +pub const _SC_THREADS : ::c_int = 91; +pub const _SC_TIMEOUTS : ::c_int = 92; +pub const _SC_TIMER_MAX : ::c_int = 93; pub const _SC_TIMERS : ::c_int = 94; +pub const _SC_TRACE : ::c_int = 95; +pub const _SC_TRACE_EVENT_FILTER : ::c_int = 96; +pub const _SC_TRACE_EVENT_NAME_MAX : ::c_int = 97; +pub const _SC_TRACE_INHERIT : ::c_int = 98; +pub const _SC_TRACE_LOG : ::c_int = 99; +pub const _SC_GETGR_R_SIZE_MAX : ::c_int = 100; +pub const _SC_GETPW_R_SIZE_MAX : ::c_int = 101; +pub const _SC_LOGIN_NAME_MAX : ::c_int = 102; +pub const _SC_THREAD_SAFE_FUNCTIONS : ::c_int = 103; +pub const _SC_TRACE_NAME_MAX : ::c_int = 104; +pub const _SC_TRACE_SYS_MAX : ::c_int = 105; +pub const _SC_TRACE_USER_EVENT_MAX : ::c_int = 106; +pub const _SC_TTY_NAME_MAX : ::c_int = 107; +pub const _SC_TYPED_MEMORY_OBJECTS : ::c_int = 108; +pub const _SC_V6_ILP32_OFF32 : ::c_int = 109; +pub const _SC_V6_ILP32_OFFBIG : ::c_int = 110; +pub const _SC_V6_LP64_OFF64 : ::c_int = 111; +pub const _SC_V6_LPBIG_OFFBIG : ::c_int = 112; +pub const _SC_V7_ILP32_OFF32 : ::c_int = 113; +pub const _SC_V7_ILP32_OFFBIG : ::c_int = 114; +pub const _SC_V7_LP64_OFF64 : ::c_int = 115; +pub const _SC_V7_LPBIG_OFFBIG : ::c_int = 116; pub const _SC_XOPEN_CRYPT : ::c_int = 117; pub const _SC_XOPEN_ENH_I18N : ::c_int = 118; pub const _SC_XOPEN_LEGACY : ::c_int = 119; pub const _SC_XOPEN_REALTIME : ::c_int = 120; pub const _SC_XOPEN_REALTIME_THREADS : ::c_int = 121; +pub const _SC_XOPEN_STREAMS : ::c_int = 122; pub const _SC_XOPEN_UNIX : ::c_int = 123; +pub const _SC_XOPEN_UUCP : ::c_int = 124; pub const _SC_XOPEN_VERSION : ::c_int = 125; -pub const _SC_SEM_NSEMS_MAX : ::c_int = 31; -pub const _SC_SEM_VALUE_MAX : ::c_int = 32; -pub const _SC_AIO_PRIO_DELTA_MAX : ::c_int = 44; -pub const _SC_DELAYTIMER_MAX : ::c_int = 50; -pub const _SC_PRIORITIZED_IO : ::c_int = 60; -pub const _SC_REALTIME_SIGNALS : ::c_int = 64; -pub const _SC_RTSIG_MAX : ::c_int = 66; -pub const _SC_SIGQUEUE_MAX : ::c_int = 70; -pub const _SC_TIMER_MAX : ::c_int = 93; -pub const _SC_HOST_NAME_MAX : ::c_int = 33; +pub const _SC_PHYS_PAGES : ::c_int = 500; +pub const _SC_AVPHYS_PAGES : ::c_int = 501; +pub const _SC_NPROCESSORS_CONF : ::c_int = 502; +pub const _SC_NPROCESSORS_ONLN : ::c_int = 503; pub const FD_SETSIZE: usize = 1024; @@ -456,7 +531,13 @@ pub const KI_WMESGLEN: ::c_int = 8; pub const KI_MAXLOGNAME: ::c_int = 32; pub const KI_EMULNAMELEN: ::c_int = 8; +pub const CHWFLOW: ::tcflag_t = ::MDMBUF | ::CRTSCTS; +pub const OLCUC: ::tcflag_t = 0x20; +pub const ONOCR: ::tcflag_t = 0x40; +pub const ONLRET: ::tcflag_t = 0x80; + extern { + pub fn dirfd(dirp: *mut ::DIR) -> ::c_int; pub fn getnameinfo(sa: *const ::sockaddr, salen: ::socklen_t, host: *mut ::c_char, diff --git a/src/vendor/libc/src/unix/haiku/mod.rs b/src/vendor/libc/src/unix/haiku/mod.rs index 829c2258bf..b7dccc2e51 100644 --- a/src/vendor/libc/src/unix/haiku/mod.rs +++ b/src/vendor/libc/src/unix/haiku/mod.rs @@ -23,6 +23,7 @@ pub type useconds_t = u32; pub type socklen_t = u32; pub type pthread_t = ::uintptr_t; pub type pthread_mutexattr_t = ::uintptr_t; +pub type pthread_rwlockattr_t = ::uintptr_t; pub type sigset_t = u64; pub type fsblkcnt_t = i64; pub type fsfilcnt_t = i64; @@ -686,6 +687,60 @@ pub const P_ALL: idtype_t = 0; pub const P_PID: idtype_t = 1; pub const P_PGID: idtype_t = 2; +pub const VINTR: usize = 0; +pub const VQUIT: usize = 1; +pub const VERASE: usize = 2; +pub const VKILL: usize = 3; +pub const VEOF: usize = 4; +pub const VEOL: usize = 5; +pub const VMIN: usize = 4; +pub const VTIME: usize = 5; +pub const VEOL2: usize = 6; +pub const VSWTCH: usize = 7; +pub const VSTART: usize = 8; +pub const VSTOP: usize = 9; +pub const VSUSP: usize = 10; +pub const OLCUC: ::tcflag_t = 0o000002; +pub const OCRNL: ::tcflag_t = 0o000010; +pub const ONOCR: ::tcflag_t = 0o000020; +pub const ONLRET: ::tcflag_t = 0o000040; +pub const OFILL: ::tcflag_t = 0o000100; +pub const OFDEL: ::tcflag_t = 0o000200; +pub const NLDLY: ::tcflag_t = 0o000400; +pub const NL0: ::tcflag_t = 0o000000; +pub const NL1: ::tcflag_t = 0o000400; +pub const CRDLY: ::tcflag_t = 0o003000; +pub const CR0: ::tcflag_t = 0o000000; +pub const CR1: ::tcflag_t = 0o001000; +pub const CR2: ::tcflag_t = 0o002000; +pub const CR3: ::tcflag_t = 0o003000; +pub const TABDLY: ::tcflag_t = 0o014000; +pub const TAB0: ::tcflag_t = 0o000000; +pub const TAB1: ::tcflag_t = 0o004000; +pub const TAB2: ::tcflag_t = 0o010000; +pub const TAB3: ::tcflag_t = 0o014000; +pub const BSDLY: ::tcflag_t = 0o020000; +pub const BS0: ::tcflag_t = 0o000000; +pub const BS1: ::tcflag_t = 0o020000; +pub const FFDLY: ::tcflag_t = 0o100000; +pub const FF0: ::tcflag_t = 0o000000; +pub const FF1: ::tcflag_t = 0o100000; +pub const VTDLY: ::tcflag_t = 0o040000; +pub const VT0: ::tcflag_t = 0o000000; +pub const VT1: ::tcflag_t = 0o040000; + +pub const TCGB_CTS: ::c_int = 0x01; +pub const TCGB_DSR: ::c_int = 0x02; +pub const TCGB_RI: ::c_int = 0x04; +pub const TCGB_DCD: ::c_int = 0x08; +pub const TIOCM_CTS: ::c_int = TCGB_CTS; +pub const TIOCM_CD: ::c_int = TCGB_DCD; +pub const TIOCM_CAR: ::c_int = TIOCM_CD; +pub const TIOCM_RI: ::c_int = TCGB_RI; +pub const TIOCM_DSR: ::c_int = TCGB_dsR; +pub const TIOCM_DTR: ::c_int = 0x10; +pub const TIOCM_RTS: ::c_int = 0x20; + f! { pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () { let fd = fd as usize; @@ -749,6 +804,7 @@ extern { pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int; pub fn mprotect(addr: *const ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; + pub fn dirfd(dirp: *mut ::DIR) -> ::c_int; pub fn getnameinfo(sa: *const ::sockaddr, salen: ::socklen_t, host: *mut ::c_char, diff --git a/src/vendor/libc/src/unix/mod.rs b/src/vendor/libc/src/unix/mod.rs index 7ebf0d9e0b..2e6aae4bbd 100644 --- a/src/vendor/libc/src/unix/mod.rs +++ b/src/vendor/libc/src/unix/mod.rs @@ -124,6 +124,20 @@ s! { // Actually a union of an int and a void* pub sival_ptr: *mut ::c_void } + + // + pub struct itimerval { + pub it_interval: ::timeval, + pub it_value: ::timeval, + } + + // + pub struct tms { + pub tms_utime: ::clock_t, + pub tms_stime: ::clock_t, + pub tms_cutime: ::clock_t, + pub tms_cstime: ::clock_t, + } } pub const SIG_DFL: sighandler_t = 0 as sighandler_t; @@ -238,6 +252,10 @@ cfg_if! { #[link(name = "c")] #[link(name = "mxio")] extern {} + } else if #[cfg(target_env = "newlib")] { + #[link(name = "c")] + #[link(name = "m")] + extern {} } else { #[link(name = "c")] #[link(name = "m")] @@ -405,7 +423,9 @@ extern { pub fn lchown(path: *const c_char, uid: uid_t, gid: gid_t) -> ::c_int; #[cfg_attr(all(target_os = "macos", target_arch = "x86"), - link_name = "close$UNIX2003")] + link_name = "close$NOCANCEL$UNIX2003")] + #[cfg_attr(all(target_os = "macos", target_arch = "x86_64"), + link_name = "close$NOCANCEL")] 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; @@ -456,6 +476,7 @@ extern { pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::size_t) -> ::ssize_t; pub fn rmdir(path: *const c_char) -> ::c_int; + pub fn seteuid(uid: uid_t) -> ::c_int; pub fn setgid(gid: gid_t) -> ::c_int; pub fn setpgid(pid: pid_t, pgid: pid_t) -> ::c_int; pub fn setsid() -> pid_t; @@ -566,6 +587,8 @@ extern { #[cfg_attr(target_os = "netbsd", link_name = "__gettimeofday50")] pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int; + #[cfg_attr(target_os = "netbsd", link_name = "__times13")] + pub fn times(buf: *mut ::tms) -> ::clock_t; pub fn pthread_self() -> ::pthread_t; pub fn pthread_create(native: *mut ::pthread_t, @@ -628,6 +651,10 @@ extern { pub fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> ::c_int; pub fn pthread_condattr_init(attr: *mut pthread_condattr_t) -> ::c_int; pub fn pthread_condattr_destroy(attr: *mut pthread_condattr_t) -> ::c_int; + #[cfg_attr(all(target_os = "macos", target_arch = "x86"), + link_name = "pthread_rwlock_init$UNIX2003")] + pub fn pthread_rwlock_init(lock: *mut pthread_rwlock_t, + attr: *const pthread_rwlockattr_t) -> ::c_int; #[cfg_attr(all(target_os = "macos", target_arch = "x86"), link_name = "pthread_rwlock_destroy$UNIX2003")] pub fn pthread_rwlock_destroy(lock: *mut pthread_rwlock_t) -> ::c_int; @@ -646,6 +673,9 @@ extern { #[cfg_attr(all(target_os = "macos", target_arch = "x86"), link_name = "pthread_rwlock_unlock$UNIX2003")] pub fn pthread_rwlock_unlock(lock: *mut pthread_rwlock_t) -> ::c_int; + pub fn pthread_rwlockattr_init(attr: *mut pthread_rwlockattr_t) -> ::c_int; + pub fn pthread_rwlockattr_destroy(attr: *mut pthread_rwlockattr_t) + -> ::c_int; #[cfg_attr(all(target_os = "macos", target_arch = "x86"), link_name = "pthread_sigmask$UNIX2003")] pub fn pthread_sigmask(how: ::c_int, set: *const sigset_t, @@ -694,6 +724,14 @@ extern { res: *mut *mut addrinfo) -> ::c_int; pub fn freeaddrinfo(res: *mut addrinfo); pub fn gai_strerror(errcode: ::c_int) -> *const ::c_char; + #[cfg_attr(any( + all(target_os = "linux", not(target_env = "musl")), + target_os = "freebsd", + target_os = "dragonfly"), + link_name = "__res_init")] + #[cfg_attr(any(target_os = "macos", target_os = "ios"), + link_name = "res_9_init")] + pub fn res_init() -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__gmtime_r50")] pub fn gmtime_r(time_p: *const time_t, result: *mut tm) -> *mut tm; @@ -705,8 +743,10 @@ extern { pub fn mktime(tm: *mut tm) -> time_t; #[cfg_attr(target_os = "netbsd", link_name = "__time50")] pub fn time(time: *mut time_t) -> time_t; + #[cfg_attr(target_os = "netbsd", link_name = "__gmtime50")] + pub fn gmtime(time_p: *const time_t) -> *mut tm; #[cfg_attr(target_os = "netbsd", link_name = "__locatime50")] - pub fn localtime(time: *const time_t) -> *mut tm; + pub fn localtime(time_p: *const time_t) -> *mut tm; #[cfg_attr(target_os = "netbsd", link_name = "__mknod50")] pub fn mknod(pathname: *const ::c_char, mode: ::mode_t, @@ -785,6 +825,8 @@ extern { set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; + #[cfg_attr(target_os = "netbsd", link_name = "__sigpending14")] + pub fn sigpending(set: *mut sigset_t) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__timegm50")] pub fn timegm(tm: *mut ::tm) -> time_t; @@ -825,6 +867,7 @@ extern { termios: *const ::termios) -> ::c_int; pub fn tcflow(fd: ::c_int, action: ::c_int) -> ::c_int; pub fn tcflush(fd: ::c_int, action: ::c_int) -> ::c_int; + pub fn tcgetsid(fd: ::c_int) -> ::pid_t; pub fn tcsendbreak(fd: ::c_int, duration: ::c_int) -> ::c_int; pub fn mkstemp(template: *mut ::c_char) -> ::c_int; pub fn mkdtemp(template: *mut ::c_char) -> *mut ::c_char; @@ -846,10 +889,16 @@ extern { } cfg_if! { - if #[cfg(any(target_os = "linux", - target_os = "android", - target_os = "emscripten", - target_os = "fuchsia"))] { + if #[cfg(target_env = "uclibc")] { + mod uclibc; + pub use self::uclibc::*; + } else if #[cfg(target_env = "newlib")] { + mod newlib; + pub use self::newlib::*; + } else if #[cfg(any(target_os = "linux", + target_os = "android", + target_os = "emscripten", + target_os = "fuchsia"))] { mod notbsd; pub use self::notbsd::*; } else if #[cfg(any(target_os = "macos", diff --git a/src/vendor/libc/src/unix/newlib/arm/mod.rs b/src/vendor/libc/src/unix/newlib/arm/mod.rs new file mode 100644 index 0000000000..372a48c4b4 --- /dev/null +++ b/src/vendor/libc/src/unix/newlib/arm/mod.rs @@ -0,0 +1,5 @@ +pub type c_char = u8; +pub type wchar_t = u32; + +pub type c_long = i32; +pub type c_ulong = u32; diff --git a/src/vendor/libc/src/unix/newlib/mod.rs b/src/vendor/libc/src/unix/newlib/mod.rs new file mode 100644 index 0000000000..1929bb795f --- /dev/null +++ b/src/vendor/libc/src/unix/newlib/mod.rs @@ -0,0 +1,604 @@ +use dox::mem; + +pub type blkcnt_t = i32; +pub type blksize_t = i32; +pub type clock_t = i32; +pub type clockid_t = ::c_ulong; +pub type dev_t = u32; +pub type fsblkcnt_t = u64; +pub type fsfilcnt_t = u32; +pub type id_t = u32; +pub type ino_t = u32; +pub type key_t = ::c_int; +pub type loff_t = ::c_longlong; +pub type mode_t = ::c_uint; +pub type nfds_t = u32; +pub type nlink_t = ::c_ushort; +pub type off_t = i64; +pub type pthread_t = ::c_ulong; +pub type pthread_key_t = ::c_uint; +pub type rlim_t = u32; +pub type sa_family_t = u8; +pub type socklen_t = u32; +pub type speed_t = u32; +pub type suseconds_t = i32; +pub type tcflag_t = ::c_uint; +pub type time_t = i32; +pub type useconds_t = u32; + +s! { + pub struct sockaddr { + pub sa_family: sa_family_t, + pub sa_data: [::c_char; 14], + } + + pub struct sockaddr_in { + pub sin_family: sa_family_t, + pub sin_port: ::in_port_t, + pub sin_addr: ::in_addr, + pub sin_zero: [u8; 8], + } + + pub struct sockaddr_in6 { // Unverified + pub sin6_family: sa_family_t, + pub sin6_port: ::in_port_t, + pub sin6_flowinfo: u32, + pub sin6_addr: ::in6_addr, + pub sin6_scope_id: u32, + } + + pub struct sockaddr_storage { + pub ss_family: sa_family_t, + pub __ss_padding: [u8; 26], + } + + pub struct addrinfo { + pub ai_flags: ::c_int, + pub ai_family: ::c_int, + pub ai_socktype: ::c_int, + pub ai_protocol: ::c_int, + pub ai_addrlen: socklen_t, + pub ai_canonname: *mut ::c_char, + pub ai_addr: *mut sockaddr, + pub ai_next: *mut addrinfo, + } + + pub struct ip_mreq { + pub imr_multiaddr: in_addr, + pub imr_interface: in_addr, + } + + pub struct linger { + pub l_onoff: ::c_int, + pub l_linger: ::c_int, + } + + pub struct in_addr { + pub s_addr: ::in_addr_t, + } + + pub struct hostent { + pub h_name: *mut ::c_char, + pub h_aliases: *mut *mut ::c_char, + pub h_addrtype: ::c_int, + pub h_length: ::c_int, + pub h_addr_list: *mut *mut ::c_char, + pub h_addr: *mut ::c_char, + } + + pub struct pollfd { + pub fd: ::c_int, + pub events: ::c_int, + pub revents: ::c_int, + } + + pub struct lconv { + pub decimal_point: *mut ::c_char, + pub thousands_sep: *mut ::c_char, + pub grouping: *mut ::c_char, + pub int_curr_symbol: *mut ::c_char, + pub currency_symbol: *mut ::c_char, + pub mon_decimal_point: *mut ::c_char, + pub mon_thousands_sep: *mut ::c_char, + pub mon_grouping: *mut ::c_char, + pub positive_sign: *mut ::c_char, + pub negative_sign: *mut ::c_char, + pub int_frac_digits: ::c_char, + pub frac_digits: ::c_char, + pub p_cs_precedes: ::c_char, + pub p_sep_by_space: ::c_char, + pub n_cs_precedes: ::c_char, + pub n_sep_by_space: ::c_char, + pub p_sign_posn: ::c_char, + pub n_sign_posn: ::c_char, + pub int_n_cs_precedes: ::c_char, + pub int_n_sep_by_space: ::c_char, + pub int_n_sign_posn: ::c_char, + pub int_p_cs_precedes: ::c_char, + pub int_p_sep_by_space: ::c_char, + pub int_p_sign_posn: ::c_char, + } + + pub struct tm { + pub tm_sec: ::c_int, + pub tm_min: ::c_int, + pub tm_hour: ::c_int, + pub tm_mday: ::c_int, + pub tm_mon: ::c_int, + pub tm_year: ::c_int, + pub tm_wday: ::c_int, + pub tm_yday: ::c_int, + pub tm_isdst: ::c_int, + } + + pub struct stat { + pub st_dev: ::dev_t, + pub st_ino: ::ino_t, + pub st_mode: ::mode_t, + pub st_nlink: ::nlink_t, + pub st_uid: ::uid_t, + pub st_gid: ::gid_t, + pub st_rdev: dev_t, + pub st_size: off_t, + pub st_atime: time_t, + pub st_spare1: ::c_long, + pub st_mtime: time_t, + pub st_spare2: ::c_long, + pub st_ctime: time_t, + pub st_spare3: ::c_long, + pub st_blksize: blksize_t, + pub st_blocks: blkcnt_t, + pub st_spare4: [::c_long; 2usize], + } + + pub struct statvfs { + pub f_bsize: ::c_ulong, + pub f_frsize: ::c_ulong, + pub f_blocks: fsblkcnt_t, + pub f_bfree: fsblkcnt_t, + pub f_bavail: fsblkcnt_t, + pub f_files: fsfilcnt_t, + pub f_ffree: fsfilcnt_t, + pub f_favail: fsfilcnt_t, + pub f_fsid: ::c_ulong, + pub f_flag: ::c_ulong, + pub f_namemax: ::c_ulong, + } + + pub struct sigset_t { + __val: [::c_ulong; 16], + } + + pub struct sigaction { + pub sa_handler: extern fn(arg1: ::c_int), + pub sa_mask: sigset_t, + pub sa_flags: ::c_int, + } + + pub struct dirent { + pub d_ino: ino_t, + pub d_type: ::c_uchar, + pub d_name: [::c_char; 256usize], + } + + pub struct stack_t { + pub ss_sp: *mut ::c_void, + pub ss_flags: ::c_int, + pub ss_size: usize, + } + + pub struct fd_set { // Unverified + fds_bits: [::c_ulong; FD_SETSIZE / ULONG_SIZE], + } + + pub struct passwd { // Unverified + pub pw_name: *mut ::c_char, + pub pw_passwd: *mut ::c_char, + pub pw_uid: ::uid_t, + pub pw_gid: ::gid_t, + pub pw_gecos: *mut ::c_char, + pub pw_dir: *mut ::c_char, + pub pw_shell: *mut ::c_char, + } + + pub struct termios { // Unverified + pub c_iflag: ::tcflag_t, + pub c_oflag: ::tcflag_t, + pub c_cflag: ::tcflag_t, + pub c_lflag: ::tcflag_t, + pub c_line: ::cc_t, + pub c_cc: [::cc_t; ::NCCS], + } + + pub struct sem_t { // Unverified + __size: [::c_char; 16], + } + + pub struct Dl_info { // Unverified + pub dli_fname: *const ::c_char, + pub dli_fbase: *mut ::c_void, + pub dli_sname: *const ::c_char, + pub dli_saddr: *mut ::c_void, + } + + pub struct utsname { // Unverified + pub sysname: [::c_char; 65], + pub nodename: [::c_char; 65], + pub release: [::c_char; 65], + pub version: [::c_char; 65], + pub machine: [::c_char; 65], + pub domainname: [::c_char; 65] + } + + pub struct cpu_set_t { // Unverified + bits: [u32; 32], + } + + pub struct pthread_attr_t { // Unverified + __size: [u64; 7] + } + + pub struct pthread_mutex_t { // Unverified + #[cfg(any(target_arch = "mips", target_arch = "arm", + target_arch = "powerpc"))] + __align: [::c_long; 0], + #[cfg(not(any(target_arch = "mips", target_arch = "arm", + target_arch = "powerpc")))] + __align: [::c_longlong; 0], + size: [u8; __SIZEOF_PTHREAD_MUTEX_T], + } + + pub struct pthread_rwlock_t { // Unverified + #[cfg(any(target_arch = "mips", target_arch = "arm", + target_arch = "powerpc"))] + __align: [::c_long; 0], + #[cfg(not(any(target_arch = "mips", target_arch = "arm", + target_arch = "powerpc")))] + __align: [::c_longlong; 0], + size: [u8; __SIZEOF_PTHREAD_RWLOCK_T], + } + + pub struct pthread_mutexattr_t { // Unverified + #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64"))] + __align: [::c_int; 0], + #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64")))] + __align: [::c_long; 0], + size: [u8; __SIZEOF_PTHREAD_MUTEXATTR_T], + } + + pub struct pthread_rwlockattr_t { // Unverified + __lockkind: ::c_int, + __pshared: ::c_int, + } + + pub struct pthread_cond_t { // Unverified + __align: [::c_longlong; 0], + size: [u8; __SIZEOF_PTHREAD_COND_T], + } + + pub struct pthread_condattr_t { // Unverified + __align: [::c_int; 0], + size: [u8; __SIZEOF_PTHREAD_CONDATTR_T], + } + +} + +// unverified constants +pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { + __align: [], + size: [0; __SIZEOF_PTHREAD_MUTEX_T], +}; +pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { + __align: [], + size: [0; __SIZEOF_PTHREAD_COND_T], +}; +pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { + __align: [], + size: [0; __SIZEOF_PTHREAD_RWLOCK_T], +}; +pub const NCCS: usize = 32; +pub const __SIZEOF_PTHREAD_ATTR_T: usize = 56; +pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; +pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; +pub const __SIZEOF_PTHREAD_COND_T: usize = 48; +pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; +pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; +pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; +pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; +pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; +pub const __PTHREAD_MUTEX_HAVE_PREV: usize = 1; +pub const __PTHREAD_RWLOCK_INT_FLAGS_SHARED: usize = 1; +pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; +pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1; +pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2; +pub const FD_SETSIZE: usize = 1024; +// intentionally not public, only used for fd_set +const ULONG_SIZE: usize = 32; + +// Other constants +pub const EPERM: ::c_int = 1; +pub const ENOENT: ::c_int = 2; +pub const ESRCH: ::c_int = 3; +pub const EINTR: ::c_int = 4; +pub const EIO: ::c_int = 5; +pub const ENXIO: ::c_int = 6; +pub const E2BIG: ::c_int = 7; +pub const ENOEXEC: ::c_int = 8; +pub const EBADF: ::c_int = 9; +pub const ECHILD: ::c_int = 10; +pub const EAGAIN: ::c_int = 11; +pub const ENOMEM: ::c_int = 12; +pub const EACCES: ::c_int = 13; +pub const EFAULT: ::c_int = 14; +pub const EBUSY: ::c_int = 16; +pub const EEXIST: ::c_int = 17; +pub const EXDEV: ::c_int = 18; +pub const ENODEV: ::c_int = 19; +pub const ENOTDIR: ::c_int = 20; +pub const EISDIR: ::c_int = 21; +pub const EINVAL: ::c_int = 22; +pub const ENFILE: ::c_int = 23; +pub const EMFILE: ::c_int = 24; +pub const ENOTTY: ::c_int = 25; +pub const ETXTBSY: ::c_int = 26; +pub const EFBIG: ::c_int = 27; +pub const ENOSPC: ::c_int = 28; +pub const ESPIPE: ::c_int = 29; +pub const EROFS: ::c_int = 30; +pub const EMLINK: ::c_int = 31; +pub const EPIPE: ::c_int = 32; +pub const EDOM: ::c_int = 33; +pub const ERANGE: ::c_int = 34; +pub const ENOMSG: ::c_int = 35; +pub const EIDRM: ::c_int = 36; +pub const EDEADLK: ::c_int = 45; +pub const ENOLCK: ::c_int = 46; +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 ENOLINK: ::c_int = 67; +pub const EPROTO: ::c_int = 71; +pub const EMULTIHOP: ::c_int = 74; +pub const EBADMSG: ::c_int = 77; +pub const EFTYPE: ::c_int = 79; +pub const ENOSYS: ::c_int = 88; +pub const ENOTEMPTY: ::c_int = 90; +pub const ENAMETOOLONG: ::c_int = 91; +pub const ELOOP: ::c_int = 92; +pub const EOPNOTSUPP: ::c_int = 95; +pub const EPFNOSUPPORT: ::c_int = 96; +pub const ECONNRESET: ::c_int = 104; +pub const ENOBUFS: ::c_int = 105; +pub const EAFNOSUPPORT: ::c_int = 106; +pub const EPROTOTYPE: ::c_int = 107; +pub const ENOTSOCK: ::c_int = 108; +pub const ENOPROTOOPT: ::c_int = 109; +pub const ECONNREFUSED: ::c_int = 111; +pub const EADDRINUSE: ::c_int = 112; +pub const ECONNABORTED: ::c_int = 113; +pub const ENETUNREACH: ::c_int = 114; +pub const ENETDOWN: ::c_int = 115; +pub const ETIMEDOUT: ::c_int = 116; +pub const EHOSTDOWN: ::c_int = 117; +pub const EHOSTUNREACH: ::c_int = 118; +pub const EINPROGRESS: ::c_int = 119; +pub const EALREADY: ::c_int = 120; +pub const EDESTADDRREQ: ::c_int = 121; +pub const EMSGSIZE: ::c_int = 122; +pub const EPROTONOSUPPORT: ::c_int = 123; +pub const EADDRNOTAVAIL: ::c_int = 125; +pub const ENETRESET: ::c_int = 126; +pub const EISCONN: ::c_int = 127; +pub const ENOTCONN: ::c_int = 128; +pub const ETOOMANYREFS: ::c_int = 129; +pub const EDQUOT: ::c_int = 132; +pub const ESTALE: ::c_int = 133; +pub const ENOTSUP: ::c_int = 134; +pub const EILSEQ: ::c_int = 138; +pub const EOVERFLOW: ::c_int = 139; +pub const ECANCELED: ::c_int = 140; +pub const ENOTRECOVERABLE: ::c_int = 141; +pub const EOWNERDEAD: ::c_int = 142; +pub const EWOULDBLOCK: ::c_int = 11; + +pub const F_DUPFD: ::c_int = 0; +pub const F_GETFD: ::c_int = 1; +pub const F_SETFD: ::c_int = 2; +pub const F_GETFL: ::c_int = 3; +pub const F_SETFL: ::c_int = 4; +pub const F_GETOWN: ::c_int = 5; +pub const F_SETOWN: ::c_int = 6; +pub const F_GETLK: ::c_int = 7; +pub const F_SETLK: ::c_int = 8; +pub const F_SETLKW: ::c_int = 9; +pub const F_RGETLK: ::c_int = 10; +pub const F_RSETLK: ::c_int = 11; +pub const F_CNVT: ::c_int = 12; +pub const F_RSETLKW: ::c_int = 13; +pub const F_DUPFD_CLOEXEC: ::c_int = 14; + +pub const O_RDONLY: ::c_int = 0; +pub const O_WRONLY: ::c_int = 1; +pub const O_RDWR: ::c_int = 2; +pub const O_APPEND: ::c_int = 8; +pub const O_CREAT: ::c_int = 512; +pub const O_TRUNC: ::c_int = 1024; +pub const O_EXCL: ::c_int = 2048; +pub const O_SYNC: ::c_int = 8192; +pub const O_NONBLOCK: ::c_int = 16384; + +pub const O_ACCMODE: ::c_int = 3; +pub const O_CLOEXEC: ::c_int = 0x80000; + +pub const STDIN_FILENO: ::c_int = 0; +pub const STDOUT_FILENO: ::c_int = 1; +pub const STDERR_FILENO: ::c_int = 2; + +pub const SEEK_SET: ::c_int = 0; +pub const SEEK_CUR: ::c_int = 1; +pub const SEEK_END: ::c_int = 2; + +pub const FIONBIO: ::c_int = 1; + +pub const S_BLKSIZE: ::mode_t = 1024; +pub const S_IREAD: ::mode_t = 256; +pub const S_IWRITE: ::mode_t = 128; +pub const S_IEXEC: ::mode_t = 64; +pub const S_ENFMT: ::mode_t = 1024; +pub const S_IFMT: ::mode_t = 61440; +pub const S_IFDIR: ::mode_t = 16384; +pub const S_IFCHR: ::mode_t = 8192; +pub const S_IFBLK: ::mode_t = 24576; +pub const S_IFREG: ::mode_t = 32768; +pub const S_IFLNK: ::mode_t = 40960; +pub const S_IFSOCK: ::mode_t = 49152; +pub const S_IFIFO: ::mode_t = 4096; +pub const S_IRUSR: ::mode_t = 256; +pub const S_IWUSR: ::mode_t = 128; +pub const S_IXUSR: ::mode_t = 64; +pub const S_IRGRP: ::mode_t = 32; +pub const S_IWGRP: ::mode_t = 16; +pub const S_IXGRP: ::mode_t = 8; +pub const S_IROTH: ::mode_t = 4; +pub const S_IWOTH: ::mode_t = 2; +pub const S_IXOTH: ::mode_t = 1; + +pub const SOL_SOCKET: ::c_int = 65535; +pub const SOL_TCP: ::c_int = 6; + +pub const PF_UNSPEC: ::c_int = 0; +pub const PF_INET: ::c_int = 2; +pub const PF_INET6: ::c_int = 23; + +pub const AF_UNSPEC: ::c_int = 0; +pub const AF_INET: ::c_int = 2; +pub const AF_INET6: ::c_int = 23; + +pub const SOCK_STREAM: ::c_int = 1; +pub const SOCK_DGRAM: ::c_int = 2; + +pub const MSG_OOB: ::c_int = 1; +pub const MSG_PEEK: ::c_int = 2; +pub const MSG_DONTWAIT: ::c_int = 4; +pub const MSG_DONTROUTE: ::c_int = 0; +pub const MSG_WAITALL: ::c_int = 0; +pub const MSG_MORE: ::c_int = 0; +pub const MSG_NOSIGNAL: ::c_int = 0; + +pub const SHUT_RD: ::c_int = 0; +pub const SHUT_WR: ::c_int = 1; +pub const SHUT_RDWR: ::c_int = 2; + +pub const SO_REUSEADDR: ::c_int = 4; +pub const SO_LINGER: ::c_int = 128; +pub const SO_OOBINLINE: ::c_int = 256; +pub const SO_SNDBUF: ::c_int = 4097; +pub const SO_RCVBUF: ::c_int = 4098; +pub const SO_SNDLOWAT: ::c_int = 4099; +pub const SO_RCVLOWAT: ::c_int = 4100; +pub const SO_TYPE: ::c_int = 4104; +pub const SO_ERROR: ::c_int = 4105; + +pub const SOCK_CLOEXEC: ::c_int = O_CLOEXEC; + +pub const INADDR_LOOPBACK: ::c_int = 2130706433; +pub const INADDR_ANY: ::c_int = 0; +pub const INADDR_BROADCAST: ::c_int = 4294967295; +pub const INADDR_NONE: ::c_int = 4294967295; + +pub const INET_ADDRSTRLEN: ::c_int = 16; + +pub const IPPROTO_IP: ::c_int = 0; +pub const IPPROTO_UDP: ::c_int = 17; +pub const IPPROTO_TCP: ::c_int = 6; + +pub const TCP_NODELAY: ::c_int = 8193; +pub const TCP_MAXSEG: ::c_int = 8194; + +pub const IP_TOS: ::c_int = 7; +pub const IP_TTL: ::c_int = 8; +pub const IP_MULTICAST_LOOP: ::c_int = 9; +pub const IP_MULTICAST_TTL: ::c_int = 10; +pub const IP_ADD_MEMBERSHIP: ::c_int = 11; +pub const IP_DROP_MEMBERSHIP: ::c_int = 12; + +pub const HOST_NOT_FOUND: ::c_int = 1; +pub const NO_DATA: ::c_int = 2; +pub const NO_ADDRESS: ::c_int = 2; +pub const NO_RECOVERY: ::c_int = 3; +pub const TRY_AGAIN: ::c_int = 4; + +pub const AI_PASSIVE: ::c_int = 1; +pub const AI_CANONNAME: ::c_int = 2; +pub const AI_NUMERICHOST: ::c_int = 4; +pub const AI_NUMERICSERV: ::c_int = 0; +pub const AI_ADDRCONFIG: ::c_int = 0; + +pub const NI_MAXHOST: ::c_int = 1025; +pub const NI_MAXSERV: ::c_int = 32; +pub const NI_NOFQDN: ::c_int = 1; +pub const NI_NUMERICHOST: ::c_int = 2; +pub const NI_NAMEREQD: ::c_int = 4; +pub const NI_NUMERICSERV: ::c_int = 0; +pub const NI_DGRAM: ::c_int = 0; + +pub const EAI_FAMILY: ::c_int = -303; +pub const EAI_MEMORY: ::c_int = -304; +pub const EAI_NONAME: ::c_int = -305; +pub const EAI_SOCKTYPE: ::c_int = -307; + +f! { + pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () { + let bits = mem::size_of_val(&(*set).fds_bits[0]) * 8; + let fd = fd as usize; + (*set).fds_bits[fd / bits] &= !(1 << (fd % bits)); + return + } + + pub fn FD_ISSET(fd: ::c_int, set: *mut fd_set) -> bool { + let bits = mem::size_of_val(&(*set).fds_bits[0]) * 8; + let fd = fd as usize; + return ((*set).fds_bits[fd / bits] & (1 << (fd % bits))) != 0 + } + + pub fn FD_SET(fd: ::c_int, set: *mut fd_set) -> () { + let bits = mem::size_of_val(&(*set).fds_bits[0]) * 8; + let fd = fd as usize; + (*set).fds_bits[fd / bits] |= 1 << (fd % bits); + return + } + + pub fn FD_ZERO(set: *mut fd_set) -> () { + for slot in (*set).fds_bits.iter_mut() { + *slot = 0; + } + } +} + +extern { + pub fn bind(fd: ::c_int, addr: *const sockaddr, len: socklen_t) -> ::c_int; + pub fn closesocket(sockfd: ::c_int) -> ::c_int; + pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int; + pub fn recvfrom(fd: ::c_int, buf: *mut ::c_void, n: usize, flags: ::c_int, + addr: *mut sockaddr, addr_len: *mut socklen_t) -> isize; + pub fn getnameinfo(sa: *const sockaddr, salen: socklen_t, + host: *mut ::c_char, hostlen: socklen_t, + serv: *mut ::c_char, servlen: socklen_t, + flags: ::c_int) -> ::c_int; +} + +cfg_if! { + if #[cfg(target_arch = "arm")] { + mod arm; + pub use self::arm::*; + } else { + // Only tested on ARM so far. Other platforms might have different + // definitions for types and constants. + pub use target_arch_not_implemented; + } +} diff --git a/src/vendor/libc/src/unix/notbsd/android/b32/mod.rs b/src/vendor/libc/src/unix/notbsd/android/b32/mod.rs index 32f88e4987..f6b0f03d48 100644 --- a/src/vendor/libc/src/unix/notbsd/android/b32/mod.rs +++ b/src/vendor/libc/src/unix/notbsd/android/b32/mod.rs @@ -166,6 +166,9 @@ pub const UT_LINESIZE: usize = 8; pub const UT_NAMESIZE: usize = 8; pub const UT_HOSTSIZE: usize = 16; +pub const SIGSTKSZ: ::size_t = 8192; +pub const MINSIGSTKSZ: ::size_t = 2048; + extern { pub fn bind(socket: ::c_int, address: *const ::sockaddr, address_len: socklen_t) -> ::c_int; diff --git a/src/vendor/libc/src/unix/notbsd/android/b32/x86.rs b/src/vendor/libc/src/unix/notbsd/android/b32/x86.rs index c4b8197de5..bbf78e35b4 100644 --- a/src/vendor/libc/src/unix/notbsd/android/b32/x86.rs +++ b/src/vendor/libc/src/unix/notbsd/android/b32/x86.rs @@ -4,3 +4,5 @@ pub type wchar_t = i32; pub const O_DIRECT: ::c_int = 0x4000; pub const O_DIRECTORY: ::c_int = 0x10000; pub const O_NOFOLLOW: ::c_int = 0x20000; + +pub const MAP_32BIT: ::c_int = 0x40; diff --git a/src/vendor/libc/src/unix/notbsd/android/b64/aarch64.rs b/src/vendor/libc/src/unix/notbsd/android/b64/aarch64.rs index 89c505d06f..5771340250 100644 --- a/src/vendor/libc/src/unix/notbsd/android/b64/aarch64.rs +++ b/src/vendor/libc/src/unix/notbsd/android/b64/aarch64.rs @@ -54,3 +54,6 @@ pub const O_DIRECTORY: ::c_int = 0x4000; pub const O_NOFOLLOW: ::c_int = 0x8000; pub const SYS_gettid: ::c_long = 178; + +pub const SIGSTKSZ: ::size_t = 16384; +pub const MINSIGSTKSZ: ::size_t = 5120; diff --git a/src/vendor/libc/src/unix/notbsd/android/b64/mod.rs b/src/vendor/libc/src/unix/notbsd/android/b64/mod.rs index 57982a2225..98a2f39fbd 100644 --- a/src/vendor/libc/src/unix/notbsd/android/b64/mod.rs +++ b/src/vendor/libc/src/unix/notbsd/android/b64/mod.rs @@ -16,7 +16,7 @@ s! { pub sa_flags: ::c_uint, pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, - _restorer: *mut ::c_void, + pub sa_restorer: ::dox::Option, } pub struct rlimit64 { diff --git a/src/vendor/libc/src/unix/notbsd/android/b64/x86_64.rs b/src/vendor/libc/src/unix/notbsd/android/b64/x86_64.rs index 58d07e104d..0cbff0a3c5 100644 --- a/src/vendor/libc/src/unix/notbsd/android/b64/x86_64.rs +++ b/src/vendor/libc/src/unix/notbsd/android/b64/x86_64.rs @@ -48,3 +48,8 @@ pub const O_DIRECTORY: ::c_int = 0x10000; pub const O_NOFOLLOW: ::c_int = 0x20000; pub const SYS_gettid: ::c_long = 186; + +pub const SIGSTKSZ: ::size_t = 8192; +pub const MINSIGSTKSZ: ::size_t = 2048; + +pub const MAP_32BIT: ::c_int = 0x40; diff --git a/src/vendor/libc/src/unix/notbsd/android/mod.rs b/src/vendor/libc/src/unix/notbsd/android/mod.rs index 3eace010ad..4928d663cf 100644 --- a/src/vendor/libc/src/unix/notbsd/android/mod.rs +++ b/src/vendor/libc/src/unix/notbsd/android/mod.rs @@ -12,6 +12,7 @@ pub type nlink_t = u32; pub type useconds_t = u32; pub type pthread_t = ::c_long; pub type pthread_mutexattr_t = ::c_long; +pub type pthread_rwlockattr_t = ::c_long; pub type pthread_condattr_t = ::c_long; pub type fsfilcnt_t = ::c_ulong; pub type fsblkcnt_t = ::c_ulong; @@ -172,6 +173,9 @@ pub const SA_RESTART: ::c_int = 0x10000000; pub const SA_NOCLDSTOP: ::c_int = 0x00000001; pub const EPOLL_CLOEXEC: ::c_int = 0x80000; +pub const EPOLLONESHOT: ::c_int = 0x40000000; +pub const EPOLLRDHUP: ::c_int = 0x00002000; +pub const EPOLLWAKEUP: ::c_int = 0x20000000; pub const EFD_CLOEXEC: ::c_int = 0x80000; @@ -190,9 +194,19 @@ pub const _PC_MAX_INPUT: ::c_int = 3; pub const _PC_NAME_MAX: ::c_int = 4; pub const _PC_PATH_MAX: ::c_int = 5; pub const _PC_PIPE_BUF: ::c_int = 6; +pub const _PC_2_SYMLINKS: ::c_int = 7; +pub const _PC_ALLOC_SIZE_MIN: ::c_int = 8; +pub const _PC_REC_INCR_XFER_SIZE: ::c_int = 9; +pub const _PC_REC_MAX_XFER_SIZE: ::c_int = 10; +pub const _PC_REC_MIN_XFER_SIZE: ::c_int = 11; +pub const _PC_REC_XFER_ALIGN: ::c_int = 12; +pub const _PC_SYMLINK_MAX: ::c_int = 13; pub const _PC_CHOWN_RESTRICTED: ::c_int = 14; pub const _PC_NO_TRUNC: ::c_int = 15; pub const _PC_VDISABLE: ::c_int = 16; +pub const _PC_ASYNC_IO: ::c_int = 17; +pub const _PC_PRIO_IO: ::c_int = 18; +pub const _PC_SYNC_IO: ::c_int = 19; pub const FIONBIO: ::c_int = 0x5421; @@ -208,6 +222,7 @@ pub const _SC_EXPR_NEST_MAX: ::c_int = 8; pub const _SC_LINE_MAX: ::c_int = 9; pub const _SC_NGROUPS_MAX: ::c_int = 10; pub const _SC_OPEN_MAX: ::c_int = 11; +pub const _SC_PASS_MAX: ::c_int = 12; pub const _SC_2_C_BIND: ::c_int = 13; pub const _SC_2_C_DEV: ::c_int = 14; pub const _SC_2_C_VERSION: ::c_int = 15; @@ -237,7 +252,35 @@ pub const _SC_IOV_MAX: ::c_int = 38; pub const _SC_PAGESIZE: ::c_int = 39; pub const _SC_PAGE_SIZE: ::c_int = 40; pub const _SC_XOPEN_UNIX: ::c_int = 41; +pub const _SC_XBS5_ILP32_OFF32: ::c_int = 42; +pub const _SC_XBS5_ILP32_OFFBIG: ::c_int = 43; +pub const _SC_XBS5_LP64_OFF64: ::c_int = 44; +pub const _SC_XBS5_LPBIG_OFFBIG: ::c_int = 45; +pub const _SC_AIO_LISTIO_MAX: ::c_int = 46; +pub const _SC_AIO_MAX: ::c_int = 47; +pub const _SC_AIO_PRIO_DELTA_MAX: ::c_int = 48; +pub const _SC_DELAYTIMER_MAX: ::c_int = 49; +pub const _SC_MQ_OPEN_MAX: ::c_int = 50; pub const _SC_MQ_PRIO_MAX: ::c_int = 51; +pub const _SC_RTSIG_MAX: ::c_int = 52; +pub const _SC_SEM_NSEMS_MAX: ::c_int = 53; +pub const _SC_SEM_VALUE_MAX: ::c_int = 54; +pub const _SC_SIGQUEUE_MAX: ::c_int = 55; +pub const _SC_TIMER_MAX: ::c_int = 56; +pub const _SC_ASYNCHRONOUS_IO: ::c_int = 57; +pub const _SC_FSYNC: ::c_int = 58; +pub const _SC_MAPPED_FILES: ::c_int = 59; +pub const _SC_MEMLOCK: ::c_int = 60; +pub const _SC_MEMLOCK_RANGE: ::c_int = 61; +pub const _SC_MEMORY_PROTECTION: ::c_int = 62; +pub const _SC_MESSAGE_PASSING: ::c_int = 63; +pub const _SC_PRIORITIZED_IO: ::c_int = 64; +pub const _SC_PRIORITY_SCHEDULING: ::c_int = 65; +pub const _SC_REALTIME_SIGNALS: ::c_int = 66; +pub const _SC_SEMAPHORES: ::c_int = 67; +pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 68; +pub const _SC_SYNCHRONIZED_IO: ::c_int = 69; +pub const _SC_TIMERS: ::c_int = 70; pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 71; pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 72; pub const _SC_LOGIN_NAME_MAX: ::c_int = 73; @@ -253,7 +296,11 @@ pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 82; pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 83; pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 84; pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 85; +pub const _SC_NPROCESSORS_CONF: ::c_int = 96; pub const _SC_NPROCESSORS_ONLN: ::c_int = 97; +pub const _SC_PHYS_PAGES: ::c_int = 98; +pub const _SC_AVPHYS_PAGES: ::c_int = 99; +pub const _SC_MONOTONIC_CLOCK: ::c_int = 100; pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1; @@ -426,7 +473,7 @@ pub const SOL_NETROM: ::c_int = 259; pub const SOL_ROSE: ::c_int = 260; #[doc(hidden)] -pub const AF_MAX: ::c_int = 39; +pub const AF_MAX: ::c_int = 43; #[doc(hidden)] pub const PF_MAX: ::c_int = AF_MAX; @@ -439,13 +486,26 @@ 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_PRIORITY: ::c_int = 12; pub const SO_LINGER: ::c_int = 13; +pub const SO_BSDCOMPAT: ::c_int = 14; pub const SO_REUSEPORT: ::c_int = 15; +pub const SO_PASSCRED: ::c_int = 16; +pub const SO_PEERCRED: ::c_int = 17; pub const SO_RCVLOWAT: ::c_int = 18; pub const SO_SNDLOWAT: ::c_int = 19; pub const SO_RCVTIMEO: ::c_int = 20; pub const SO_SNDTIMEO: ::c_int = 21; +pub const SO_BINDTODEVICE: ::c_int = 25; +pub const SO_TIMESTAMP: ::c_int = 29; pub const SO_ACCEPTCONN: ::c_int = 30; +pub const SO_SNDBUFFORCE: ::c_int = 32; +pub const SO_MARK: ::c_int = 36; +pub const SO_PROTOCOL: ::c_int = 38; +pub const SO_DOMAIN: ::c_int = 39; +pub const SO_RXQ_OVFL: ::c_int = 40; +pub const SO_PEEK_OFF: ::c_int = 42; +pub const SO_BUSY_POLL: ::c_int = 46; pub const O_ACCMODE: ::c_int = 3; pub const O_APPEND: ::c_int = 1024; @@ -456,6 +516,7 @@ pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 0x101000; pub const O_ASYNC: ::c_int = 0x2000; pub const O_NDELAY: ::c_int = 0x800; +pub const O_DSYNC: ::c_int = 4096; pub const NI_MAXHOST: ::size_t = 1025; @@ -471,6 +532,7 @@ pub const VMIN: usize = 6; pub const IEXTEN: ::tcflag_t = 0x00008000; pub const TOSTOP: ::tcflag_t = 0x00000100; pub const FLUSHO: ::tcflag_t = 0x00001000; +pub const EXTPROC: ::tcflag_t = 0o200000; pub const ADFS_SUPER_MAGIC: ::c_long = 0x0000adf5; pub const AFFS_SUPER_MAGIC: ::c_long = 0x0000adff; @@ -583,8 +645,6 @@ pub const LINUX_REBOOT_CMD_KEXEC: ::c_int = 0x45584543; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; -pub const SIGSTKSZ: ::size_t = 8192; -pub const MINSIGSTKSZ: ::size_t = 2048; pub const CBAUD: ::tcflag_t = 0o0010017; pub const TAB1: ::c_int = 0x00000800; pub const TAB2: ::c_int = 0x00001000; @@ -625,6 +685,15 @@ pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; +pub const VSWTC: usize = 7; +pub const OLCUC: ::tcflag_t = 0o000002; +pub const NLDLY: ::tcflag_t = 0o000400; +pub const CRDLY: ::tcflag_t = 0o003000; +pub const TABDLY: ::tcflag_t = 0o014000; +pub const BSDLY: ::tcflag_t = 0o020000; +pub const FFDLY: ::tcflag_t = 0o100000; +pub const VTDLY: ::tcflag_t = 0o040000; +pub const XTABS: ::tcflag_t = 0o014000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; @@ -723,6 +792,22 @@ pub const NLA_TYPE_MASK: ::c_int = !(NLA_F_NESTED | NLA_F_NET_BYTEORDER); pub const SIGEV_THREAD_ID: ::c_int = 4; +pub const CMSPAR: ::tcflag_t = 0o10000000000; +pub const CIBAUD: ::tcflag_t = 0o02003600000; +pub const CBAUDEX: ::tcflag_t = 0o010000; + +pub const TIOCM_LE: ::c_int = 0x001; +pub const TIOCM_DTR: ::c_int = 0x002; +pub const TIOCM_RTS: ::c_int = 0x004; +pub const TIOCM_ST: ::c_int = 0x008; +pub const TIOCM_SR: ::c_int = 0x010; +pub const TIOCM_CTS: ::c_int = 0x020; +pub const TIOCM_CAR: ::c_int = 0x040; +pub const TIOCM_RNG: ::c_int = 0x080; +pub const TIOCM_DSR: ::c_int = 0x100; +pub const TIOCM_CD: ::c_int = TIOCM_CAR; +pub const TIOCM_RI: ::c_int = TIOCM_RNG; + f! { pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.__bits.iter_mut() { @@ -753,6 +838,17 @@ f! { pub fn CPU_EQUAL(set1: &cpu_set_t, set2: &cpu_set_t) -> bool { set1.__bits == set2.__bits } + pub fn major(dev: ::dev_t) -> ::c_int { + ((dev >> 8) & 0xfff) as ::c_int + } + pub fn minor(dev: ::dev_t) -> ::c_int { + ((dev & 0xff) | ((dev >> 12) & 0xfff00)) as ::c_int + } + pub fn makedev(ma: ::c_int, mi: ::c_int) -> ::dev_t { + let ma = ma as ::dev_t; + let mi = mi as ::dev_t; + ((ma & 0xfff) << 8) | (mi & 0xff) | ((mi & 0xfff00) << 12) + } } extern { diff --git a/src/vendor/libc/src/unix/notbsd/linux/mips/mips32.rs b/src/vendor/libc/src/unix/notbsd/linux/mips/mips32.rs index 22bb33b723..8bbaeb9c4b 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/mips/mips32.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/mips/mips32.rs @@ -10,9 +10,7 @@ pub type ino_t = u32; pub type blkcnt_t = i32; pub type blksize_t = i32; pub type nlink_t = u32; -pub type fsblkcnt_t = ::c_ulong; -pub type fsfilcnt_t = ::c_ulong; -pub type rlim_t = c_ulong; +pub type __u64 = ::c_ulonglong; s! { pub struct aiocb { @@ -86,7 +84,7 @@ s! { pub sa_flags: ::c_int, pub sa_sigaction: ::sighandler_t, pub sa_mask: sigset_t, - _restorer: *mut ::c_void, + pub sa_restorer: ::dox::Option, _resv: [::c_int; 1], } @@ -107,19 +105,6 @@ s! { pub _pad: [::c_int; 29], } - pub struct glob64_t { - pub gl_pathc: ::size_t, - pub gl_pathv: *mut *mut ::c_char, - pub gl_offs: ::size_t, - pub gl_flags: ::c_int, - - __unused1: *mut ::c_void, - __unused2: *mut ::c_void, - __unused3: *mut ::c_void, - __unused4: *mut ::c_void, - __unused5: *mut ::c_void, - } - pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, @@ -238,50 +223,14 @@ s! { pub mem_unit: ::c_uint, pub _f: [::c_char; 8], } - - // FIXME this is actually a union - pub struct sem_t { - #[cfg(target_pointer_width = "32")] - __size: [::c_char; 16], - #[cfg(target_pointer_width = "64")] - __size: [::c_char; 32], - __align: [::c_long; 0], - } } pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 24; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; +pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const RLIM_INFINITY: ::rlim_t = 0x7fffffff; pub const SYS_gettid: ::c_long = 4222; // Valid for O32 - -#[link(name = "util")] -extern { - pub fn sysctl(name: *mut ::c_int, - namelen: ::c_int, - oldp: *mut ::c_void, - oldlenp: *mut ::size_t, - newp: *mut ::c_void, - newlen: ::size_t) - -> ::c_int; - pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int; - pub fn backtrace(buf: *mut *mut ::c_void, - sz: ::c_int) -> ::c_int; - pub fn glob64(pattern: *const ::c_char, - flags: ::c_int, - errfunc: ::dox::Option ::c_int>, - pglob: *mut glob64_t) -> ::c_int; - pub fn globfree64(pglob: *mut glob64_t); - pub fn ptrace(request: ::c_uint, ...) -> ::c_long; - pub fn pthread_attr_getaffinity_np(attr: *const ::pthread_attr_t, - cpusetsize: ::size_t, - cpuset: *mut ::cpu_set_t) -> ::c_int; - pub fn pthread_attr_setaffinity_np(attr: *mut ::pthread_attr_t, - cpusetsize: ::size_t, - cpuset: *const ::cpu_set_t) -> ::c_int; -} diff --git a/src/vendor/libc/src/unix/notbsd/linux/mips/mips64.rs b/src/vendor/libc/src/unix/notbsd/linux/mips/mips64.rs index 947859998d..9091c566ab 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/mips/mips64.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/mips/mips64.rs @@ -3,15 +3,14 @@ pub type blksize_t = i64; pub type c_char = i8; pub type c_long = i64; pub type c_ulong = u64; -pub type fsblkcnt_t = ::c_ulong; -pub type fsfilcnt_t = ::c_ulong; pub type ino_t = u64; pub type nlink_t = u64; pub type off_t = i64; -pub type rlim_t = ::c_ulong; pub type suseconds_t = i64; pub type time_t = i64; pub type wchar_t = i32; +pub type clock_t = i64; +pub type __u64 = ::c_ulong; s! { pub struct aiocb { @@ -85,7 +84,7 @@ s! { pub sa_flags: ::c_int, pub sa_sigaction: ::sighandler_t, pub sa_mask: sigset_t, - _restorer: *mut ::c_void, + pub sa_restorer: ::dox::Option, } pub struct stack_t { @@ -186,6 +185,14 @@ s! { pub c_cc: [::cc_t; ::NCCS], } + pub struct flock { + pub l_type: ::c_short, + pub l_whence: ::c_short, + pub l_start: ::off_t, + pub l_len: ::off_t, + pub l_pid: ::pid_t, + } + pub struct sysinfo { pub uptime: ::c_long, pub loads: [::c_ulong; 3], @@ -202,24 +209,14 @@ s! { pub mem_unit: ::c_uint, pub _f: [::c_char; 0], } - - // FIXME this is actually a union - pub struct sem_t { - __size: [::c_char; 32], - __align: [::c_long; 0], - } } pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; +pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const RLIM_INFINITY: ::rlim_t = 0xffff_ffff_ffff_ffff; pub const SYS_gettid: ::c_long = 5178; // Valid for n64 - -#[link(name = "util")] -extern { - pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int; -} diff --git a/src/vendor/libc/src/unix/notbsd/linux/mips/mod.rs b/src/vendor/libc/src/unix/notbsd/linux/mips/mod.rs index 7b1c15e2fd..bb2b18d0dd 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/mips/mod.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/mips/mod.rs @@ -1,4 +1,31 @@ -pub const CLONE_NEWCGROUP: ::c_int = 0x02000000; +pub type fsblkcnt_t = ::c_ulong; +pub type fsfilcnt_t = ::c_ulong; +pub type rlim_t = c_ulong; +pub type __priority_which_t = ::c_uint; + +s! { + pub struct glob64_t { + pub gl_pathc: ::size_t, + pub gl_pathv: *mut *mut ::c_char, + pub gl_offs: ::size_t, + pub gl_flags: ::c_int, + + __unused1: *mut ::c_void, + __unused2: *mut ::c_void, + __unused3: *mut ::c_void, + __unused4: *mut ::c_void, + __unused5: *mut ::c_void, + } + + // FIXME this is actually a union + pub struct sem_t { + #[cfg(target_pointer_width = "32")] + __size: [::c_char; 16], + #[cfg(target_pointer_width = "64")] + __size: [::c_char; 32], + __align: [::c_long; 0], + } +} pub const SFD_CLOEXEC: ::c_int = 0x080000; @@ -38,7 +65,81 @@ pub const FOPEN_MAX: ::c_uint = 16; pub const POSIX_FADV_DONTNEED: ::c_int = 4; pub const POSIX_FADV_NOREUSE: ::c_int = 5; pub const POSIX_MADV_DONTNEED: ::c_int = 4; +pub const _SC_EQUIV_CLASS_MAX: ::c_int = 41; +pub const _SC_CHARCLASS_NAME_MAX: ::c_int = 45; +pub const _SC_PII: ::c_int = 53; +pub const _SC_PII_XTI: ::c_int = 54; +pub const _SC_PII_SOCKET: ::c_int = 55; +pub const _SC_PII_INTERNET: ::c_int = 56; +pub const _SC_PII_OSI: ::c_int = 57; +pub const _SC_POLL: ::c_int = 58; +pub const _SC_SELECT: ::c_int = 59; +pub const _SC_PII_INTERNET_STREAM: ::c_int = 61; +pub const _SC_PII_INTERNET_DGRAM: ::c_int = 62; +pub const _SC_PII_OSI_COTS: ::c_int = 63; +pub const _SC_PII_OSI_CLTS: ::c_int = 64; +pub const _SC_PII_OSI_M: ::c_int = 65; +pub const _SC_T_IOV_MAX: ::c_int = 66; pub const _SC_2_C_VERSION: ::c_int = 96; +pub const _SC_CHAR_BIT: ::c_int = 101; +pub const _SC_CHAR_MAX: ::c_int = 102; +pub const _SC_CHAR_MIN: ::c_int = 103; +pub const _SC_INT_MAX: ::c_int = 104; +pub const _SC_INT_MIN: ::c_int = 105; +pub const _SC_LONG_BIT: ::c_int = 106; +pub const _SC_WORD_BIT: ::c_int = 107; +pub const _SC_MB_LEN_MAX: ::c_int = 108; +pub const _SC_SSIZE_MAX: ::c_int = 110; +pub const _SC_SCHAR_MAX: ::c_int = 111; +pub const _SC_SCHAR_MIN: ::c_int = 112; +pub const _SC_SHRT_MAX: ::c_int = 113; +pub const _SC_SHRT_MIN: ::c_int = 114; +pub const _SC_UCHAR_MAX: ::c_int = 115; +pub const _SC_UINT_MAX: ::c_int = 116; +pub const _SC_ULONG_MAX: ::c_int = 117; +pub const _SC_USHRT_MAX: ::c_int = 118; +pub const _SC_NL_ARGMAX: ::c_int = 119; +pub const _SC_NL_LANGMAX: ::c_int = 120; +pub const _SC_NL_MSGMAX: ::c_int = 121; +pub const _SC_NL_NMAX: ::c_int = 122; +pub const _SC_NL_SETMAX: ::c_int = 123; +pub const _SC_NL_TEXTMAX: ::c_int = 124; +pub const _SC_BASE: ::c_int = 134; +pub const _SC_C_LANG_SUPPORT: ::c_int = 135; +pub const _SC_C_LANG_SUPPORT_R: ::c_int = 136; +pub const _SC_DEVICE_IO: ::c_int = 140; +pub const _SC_DEVICE_SPECIFIC: ::c_int = 141; +pub const _SC_DEVICE_SPECIFIC_R: ::c_int = 142; +pub const _SC_FD_MGMT: ::c_int = 143; +pub const _SC_FIFO: ::c_int = 144; +pub const _SC_PIPE: ::c_int = 145; +pub const _SC_FILE_ATTRIBUTES: ::c_int = 146; +pub const _SC_FILE_LOCKING: ::c_int = 147; +pub const _SC_FILE_SYSTEM: ::c_int = 148; +pub const _SC_MULTI_PROCESS: ::c_int = 150; +pub const _SC_SINGLE_PROCESS: ::c_int = 151; +pub const _SC_NETWORKING: ::c_int = 152; +pub const _SC_REGEX_VERSION: ::c_int = 156; +pub const _SC_SIGNALS: ::c_int = 158; +pub const _SC_SYSTEM_DATABASE: ::c_int = 162; +pub const _SC_SYSTEM_DATABASE_R: ::c_int = 163; +pub const _SC_USER_GROUPS: ::c_int = 166; +pub const _SC_USER_GROUPS_R: ::c_int = 167; +pub const _SC_LEVEL1_ICACHE_SIZE: ::c_int = 185; +pub const _SC_LEVEL1_ICACHE_ASSOC: ::c_int = 186; +pub const _SC_LEVEL1_ICACHE_LINESIZE: ::c_int = 187; +pub const _SC_LEVEL1_DCACHE_SIZE: ::c_int = 188; +pub const _SC_LEVEL1_DCACHE_ASSOC: ::c_int = 189; +pub const _SC_LEVEL1_DCACHE_LINESIZE: ::c_int = 190; +pub const _SC_LEVEL2_CACHE_SIZE: ::c_int = 191; +pub const _SC_LEVEL2_CACHE_ASSOC: ::c_int = 192; +pub const _SC_LEVEL2_CACHE_LINESIZE: ::c_int = 193; +pub const _SC_LEVEL3_CACHE_SIZE: ::c_int = 194; +pub const _SC_LEVEL3_CACHE_ASSOC: ::c_int = 195; +pub const _SC_LEVEL3_CACHE_LINESIZE: ::c_int = 196; +pub const _SC_LEVEL4_CACHE_SIZE: ::c_int = 197; +pub const _SC_LEVEL4_CACHE_ASSOC: ::c_int = 198; +pub const _SC_LEVEL4_CACHE_LINESIZE: ::c_int = 199; pub const O_ACCMODE: ::c_int = 3; pub const O_DIRECT: ::c_int = 0x8000; pub const O_DIRECTORY: ::c_int = 0x10000; @@ -461,6 +562,17 @@ pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; +pub const CIBAUD: ::tcflag_t = 0o02003600000; +pub const CBAUDEX: ::tcflag_t = 0o010000; +pub const VSWTC: usize = 7; +pub const OLCUC: ::tcflag_t = 0o000002; +pub const NLDLY: ::tcflag_t = 0o000400; +pub const CRDLY: ::tcflag_t = 0o003000; +pub const TABDLY: ::tcflag_t = 0o014000; +pub const BSDLY: ::tcflag_t = 0o020000; +pub const FFDLY: ::tcflag_t = 0o100000; +pub const VTDLY: ::tcflag_t = 0o040000; +pub const XTABS: ::tcflag_t = 0o014000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; @@ -496,6 +608,56 @@ pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; +pub const TIOCM_LE: ::c_int = 0x001; +pub const TIOCM_DTR: ::c_int = 0x002; +pub const TIOCM_RTS: ::c_int = 0x004; +pub const TIOCM_ST: ::c_int = 0x010; +pub const TIOCM_SR: ::c_int = 0x020; +pub const TIOCM_CTS: ::c_int = 0x040; +pub const TIOCM_CAR: ::c_int = 0x100; +pub const TIOCM_CD: ::c_int = TIOCM_CAR; +pub const TIOCM_RNG: ::c_int = 0x200; +pub const TIOCM_RI: ::c_int = TIOCM_RNG; +pub const TIOCM_DSR: ::c_int = 0x400; + +#[link(name = "util")] +extern { + pub fn sysctl(name: *mut ::c_int, + namelen: ::c_int, + oldp: *mut ::c_void, + oldlenp: *mut ::size_t, + newp: *mut ::c_void, + newlen: ::size_t) + -> ::c_int; + pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int; + pub fn backtrace(buf: *mut *mut ::c_void, + sz: ::c_int) -> ::c_int; + pub fn glob64(pattern: *const ::c_char, + flags: ::c_int, + errfunc: ::dox::Option ::c_int>, + pglob: *mut glob64_t) -> ::c_int; + pub fn globfree64(pglob: *mut glob64_t); + pub fn ptrace(request: ::c_uint, ...) -> ::c_long; + pub fn pthread_attr_getaffinity_np(attr: *const ::pthread_attr_t, + cpusetsize: ::size_t, + cpuset: *mut ::cpu_set_t) -> ::c_int; + pub fn pthread_attr_setaffinity_np(attr: *mut ::pthread_attr_t, + cpusetsize: ::size_t, + cpuset: *const ::cpu_set_t) -> ::c_int; + pub fn getpriority(which: ::__priority_which_t, who: ::id_t) -> ::c_int; + pub fn setpriority(which: ::__priority_which_t, who: ::id_t, + prio: ::c_int) -> ::c_int; + pub fn pthread_getaffinity_np(thread: ::pthread_t, + cpusetsize: ::size_t, + cpuset: *mut ::cpu_set_t) -> ::c_int; + pub fn pthread_setaffinity_np(thread: ::pthread_t, + cpusetsize: ::size_t, + cpuset: *const ::cpu_set_t) -> ::c_int; + pub fn sched_getcpu() -> ::c_int; +} + cfg_if! { if #[cfg(target_arch = "mips")] { mod mips32; diff --git a/src/vendor/libc/src/unix/notbsd/linux/mod.rs b/src/vendor/libc/src/unix/notbsd/linux/mod.rs index 9774f93f6d..7f4f885e2a 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/mod.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/mod.rs @@ -19,6 +19,12 @@ pub type nfds_t = ::c_ulong; pub type nl_item = ::c_int; pub type idtype_t = ::c_uint; +pub type __u8 = ::c_uchar; +pub type __u16 = ::c_ushort; +pub type __s16 = ::c_short; +pub type __u32 = ::c_uint; +pub type __s32 = ::c_int; + pub enum fpos64_t {} // TODO: fill this out with a struct s! { @@ -98,6 +104,14 @@ s! { size: [u8; __SIZEOF_PTHREAD_MUTEXATTR_T], } + pub struct pthread_rwlockattr_t { + #[cfg(any(target_env = "musl"))] + __align: [::c_int; 0], + #[cfg(not(any(target_env = "musl")))] + __align: [::c_long; 0], + size: [u8; __SIZEOF_PTHREAD_RWLOCKATTR_T], + } + pub struct pthread_cond_t { #[cfg(any(target_env = "musl"))] __align: [*const ::c_void; 0], @@ -220,6 +234,124 @@ s! { pub msgtql: ::c_int, pub msgseg: ::c_ushort, } + + pub struct mmsghdr { + pub msg_hdr: ::msghdr, + pub msg_len: ::c_uint, + } + + pub struct sembuf { + pub sem_num: ::c_ushort, + pub sem_op: ::c_short, + pub sem_flg: ::c_short, + } + + pub struct input_event { + pub time: ::timeval, + pub type_: ::__u16, + pub code: ::__u16, + pub value: ::__s32, + } + + pub struct input_id { + pub bustype: ::__u16, + pub vendor: ::__u16, + pub product: ::__u16, + pub version: ::__u16, + } + + pub struct input_absinfo { + pub value: ::__s32, + pub minimum: ::__s32, + pub maximum: ::__s32, + pub fuzz: ::__s32, + pub flat: ::__s32, + pub resolution: ::__s32, + } + + pub struct input_keymap_entry { + pub flags: ::__u8, + pub len: ::__u8, + pub index: ::__u16, + pub keycode: ::__u32, + pub scancode: [::__u8; 32], + } + + pub struct input_mask { + pub type_: ::__u32, + pub codes_size: ::__u32, + pub codes_ptr: ::__u64, + } + + pub struct ff_replay { + pub length: ::__u16, + pub delay: ::__u16, + } + + pub struct ff_trigger { + pub button: ::__u16, + pub interval: ::__u16, + } + + pub struct ff_envelope { + pub attack_length: ::__u16, + pub attack_level: ::__u16, + pub fade_length: ::__u16, + pub fade_level: ::__u16, + } + + pub struct ff_constant_effect { + pub level: ::__s16, + pub envelope: ff_envelope, + } + + pub struct ff_ramp_effect { + pub start_level: ::__s16, + pub end_level: ::__s16, + pub envelope: ff_envelope, + } + + pub struct ff_condition_effect { + pub right_saturation: ::__u16, + pub left_saturation: ::__u16, + + pub right_coeff: ::__s16, + pub left_coeff: ::__s16, + + pub deadband: ::__u16, + pub center: ::__s16, + } + + pub struct ff_periodic_effect { + pub waveform: ::__u16, + pub period: ::__u16, + pub magnitude: ::__s16, + pub offset: ::__s16, + pub phase: ::__u16, + + pub envelope: ff_envelope, + + pub custom_len: ::__u32, + pub custom_data: *mut ::__s16, + } + + pub struct ff_rumble_effect { + pub strong_magnitude: ::__u16, + pub weak_magnitude: ::__u16, + } + + pub struct ff_effect { + pub type_: ::__u16, + pub id: ::__s16, + pub direction: ::__u16, + pub trigger: ff_trigger, + pub replay: ff_replay, + // FIXME this is actually a union + #[cfg(target_pointer_width = "64")] + pub u: [u64; 4], + #[cfg(target_pointer_width = "32")] + pub u: [u32; 7], + } } pub const ABDAY_1: ::nl_item = 0x20000; @@ -304,6 +436,18 @@ pub const _PC_PIPE_BUF: ::c_int = 5; pub const _PC_CHOWN_RESTRICTED: ::c_int = 6; pub const _PC_NO_TRUNC: ::c_int = 7; pub const _PC_VDISABLE: ::c_int = 8; +pub const _PC_SYNC_IO: ::c_int = 9; +pub const _PC_ASYNC_IO: ::c_int = 10; +pub const _PC_PRIO_IO: ::c_int = 11; +pub const _PC_SOCK_MAXBUF: ::c_int = 12; +pub const _PC_FILESIZEBITS: ::c_int = 13; +pub const _PC_REC_INCR_XFER_SIZE: ::c_int = 14; +pub const _PC_REC_MAX_XFER_SIZE: ::c_int = 15; +pub const _PC_REC_MIN_XFER_SIZE: ::c_int = 16; +pub const _PC_REC_XFER_ALIGN: ::c_int = 17; +pub const _PC_ALLOC_SIZE_MIN: ::c_int = 18; +pub const _PC_SYMLINK_MAX: ::c_int = 19; +pub const _PC_2_SYMLINKS: ::c_int = 20; pub const _SC_ARG_MAX: ::c_int = 0; pub const _SC_CHILD_MAX: ::c_int = 1; @@ -357,6 +501,7 @@ pub const _SC_2_FORT_DEV: ::c_int = 49; pub const _SC_2_FORT_RUN: ::c_int = 50; pub const _SC_2_SW_DEV: ::c_int = 51; pub const _SC_2_LOCALEDEF: ::c_int = 52; +pub const _SC_UIO_MAXIOV: ::c_int = 60; pub const _SC_IOV_MAX: ::c_int = 60; pub const _SC_THREADS: ::c_int = 67; pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 68; @@ -373,8 +518,13 @@ pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 78; pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 79; pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 80; pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 81; +pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 82; +pub const _SC_NPROCESSORS_CONF: ::c_int = 83; pub const _SC_NPROCESSORS_ONLN: ::c_int = 84; +pub const _SC_PHYS_PAGES: ::c_int = 85; +pub const _SC_AVPHYS_PAGES: ::c_int = 86; pub const _SC_ATEXIT_MAX: ::c_int = 87; +pub const _SC_PASS_MAX: ::c_int = 88; pub const _SC_XOPEN_VERSION: ::c_int = 89; pub const _SC_XOPEN_XCU_VERSION: ::c_int = 90; pub const _SC_XOPEN_UNIX: ::c_int = 91; @@ -383,13 +533,63 @@ pub const _SC_XOPEN_ENH_I18N: ::c_int = 93; pub const _SC_XOPEN_SHM: ::c_int = 94; pub const _SC_2_CHAR_TERM: ::c_int = 95; pub const _SC_2_UPE: ::c_int = 97; +pub const _SC_XOPEN_XPG2: ::c_int = 98; +pub const _SC_XOPEN_XPG3: ::c_int = 99; +pub const _SC_XOPEN_XPG4: ::c_int = 100; +pub const _SC_NZERO: ::c_int = 109; pub const _SC_XBS5_ILP32_OFF32: ::c_int = 125; pub const _SC_XBS5_ILP32_OFFBIG: ::c_int = 126; +pub const _SC_XBS5_LP64_OFF64: ::c_int = 127; pub const _SC_XBS5_LPBIG_OFFBIG: ::c_int = 128; pub const _SC_XOPEN_LEGACY: ::c_int = 129; pub const _SC_XOPEN_REALTIME: ::c_int = 130; pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 131; +pub const _SC_ADVISORY_INFO: ::c_int = 132; +pub const _SC_BARRIERS: ::c_int = 133; +pub const _SC_CLOCK_SELECTION: ::c_int = 137; +pub const _SC_CPUTIME: ::c_int = 138; +pub const _SC_THREAD_CPUTIME: ::c_int = 139; +pub const _SC_MONOTONIC_CLOCK: ::c_int = 149; +pub const _SC_READER_WRITER_LOCKS: ::c_int = 153; +pub const _SC_SPIN_LOCKS: ::c_int = 154; +pub const _SC_REGEXP: ::c_int = 155; +pub const _SC_SHELL: ::c_int = 157; +pub const _SC_SPAWN: ::c_int = 159; +pub const _SC_SPORADIC_SERVER: ::c_int = 160; +pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 161; +pub const _SC_TIMEOUTS: ::c_int = 164; +pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 165; +pub const _SC_2_PBS: ::c_int = 168; +pub const _SC_2_PBS_ACCOUNTING: ::c_int = 169; +pub const _SC_2_PBS_LOCATE: ::c_int = 170; +pub const _SC_2_PBS_MESSAGE: ::c_int = 171; +pub const _SC_2_PBS_TRACK: ::c_int = 172; +pub const _SC_SYMLOOP_MAX: ::c_int = 173; +pub const _SC_STREAMS: ::c_int = 174; +pub const _SC_2_PBS_CHECKPOINT: ::c_int = 175; +pub const _SC_V6_ILP32_OFF32: ::c_int = 176; +pub const _SC_V6_ILP32_OFFBIG: ::c_int = 177; +pub const _SC_V6_LP64_OFF64: ::c_int = 178; +pub const _SC_V6_LPBIG_OFFBIG: ::c_int = 179; pub const _SC_HOST_NAME_MAX: ::c_int = 180; +pub const _SC_TRACE: ::c_int = 181; +pub const _SC_TRACE_EVENT_FILTER: ::c_int = 182; +pub const _SC_TRACE_INHERIT: ::c_int = 183; +pub const _SC_TRACE_LOG: ::c_int = 184; +pub const _SC_IPV6: ::c_int = 235; +pub const _SC_RAW_SOCKETS: ::c_int = 236; +pub const _SC_V7_ILP32_OFF32: ::c_int = 237; +pub const _SC_V7_ILP32_OFFBIG: ::c_int = 238; +pub const _SC_V7_LP64_OFF64: ::c_int = 239; +pub const _SC_V7_LPBIG_OFFBIG: ::c_int = 240; +pub const _SC_SS_REPL_MAX: ::c_int = 241; +pub const _SC_TRACE_EVENT_NAME_MAX: ::c_int = 242; +pub const _SC_TRACE_NAME_MAX: ::c_int = 243; +pub const _SC_TRACE_SYS_MAX: ::c_int = 244; +pub const _SC_TRACE_USER_EVENT_MAX: ::c_int = 245; +pub const _SC_XOPEN_STREAMS: ::c_int = 246; +pub const _SC_THREAD_ROBUST_PRIO_INHERIT: ::c_int = 247; +pub const _SC_THREAD_ROBUST_PRIO_PROTECT: ::c_int = 248; pub const RLIM_SAVED_MAX: ::rlim_t = RLIM_INFINITY; pub const RLIM_SAVED_CUR: ::rlim_t = RLIM_INFINITY; @@ -455,6 +655,8 @@ pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1; pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2; pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_NORMAL; +pub const PTHREAD_PROCESS_PRIVATE: ::c_int = 0; +pub const PTHREAD_PROCESS_SHARED: ::c_int = 1; pub const __SIZEOF_PTHREAD_COND_T: usize = 48; pub const SCHED_OTHER: ::c_int = 0; @@ -692,6 +894,20 @@ 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; +pub const ITIMER_REAL: ::c_int = 0; +pub const ITIMER_VIRTUAL: ::c_int = 1; +pub const ITIMER_PROF: ::c_int = 2; + +pub const XATTR_CREATE: ::c_int = 0x1; +pub const XATTR_REPLACE: ::c_int = 0x2; + +pub const _POSIX_VDISABLE: ::cc_t = 0; + +// On Linux, libc doesn't define this constant, libattr does instead. +// We still define it for Linux as it's defined by libc on other platforms, +// and it's mentioned in the man pages for getxattr and setxattr. +pub const ENOATTR: ::c_int = ::ENODATA; + f! { pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.bits.iter_mut() { @@ -722,6 +938,31 @@ f! { pub fn CPU_EQUAL(set1: &cpu_set_t, set2: &cpu_set_t) -> bool { set1.bits == set2.bits } + + pub fn major(dev: ::dev_t) -> ::c_uint { + let mut major = 0; + major |= (dev & 0x00000000000fff00) >> 8; + major |= (dev & 0xfffff00000000000) >> 32; + major as ::c_uint + } + + pub fn minor(dev: ::dev_t) -> ::c_uint { + let mut minor = 0; + minor |= (dev & 0xfffff00000000000) >> 0; + minor |= (dev & 0x00000ffffff00000) >> 12; + minor as ::c_uint + } + + pub fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t { + let major = major as ::dev_t; + let minor = minor as ::dev_t; + let mut dev = 0; + dev |= (major & 0x00000fff) << 8; + dev |= (major & 0xfffff000) << 32; + dev |= (minor & 0x000000ff) << 0; + dev |= (minor & 0xffffff00) << 12; + dev + } } extern { @@ -758,6 +999,11 @@ extern { cmd: ::c_int, buf: *mut ::shmid_ds) -> ::c_int; pub fn ftok(pathname: *const ::c_char, proj_id: ::c_int) -> ::key_t; + pub fn semget(key: ::key_t, nsems: ::c_int, semflag: ::c_int) -> ::c_int; + pub fn semop(semid: ::c_int, + sops: *mut ::sembuf, nsops: ::size_t) -> ::c_int; + pub fn semctl(semid: ::c_int, + semnum: ::c_int, cmd: ::c_int, ...) -> ::c_int; pub fn msgctl(msqid: ::c_int, cmd: ::c_int, buf: *mut msqid_ds) -> ::c_int; pub fn msgget(key: ::key_t, msgflg: ::c_int) -> ::c_int; pub fn msgrcv(msqid: ::c_int, msgp: *mut ::c_void, msgsz: ::size_t, @@ -846,7 +1092,6 @@ extern { timeout: ::c_int, sigmask: *const ::sigset_t) -> ::c_int; pub fn dup3(oldfd: ::c_int, newfd: ::c_int, flags: ::c_int) -> ::c_int; - pub fn sethostname(name: *const ::c_char, len: ::size_t) -> ::c_int; pub fn mkostemp(template: *mut ::c_char, flags: ::c_int) -> ::c_int; pub fn mkostemps(template: *mut ::c_char, suffixlen: ::c_int, @@ -856,15 +1101,6 @@ extern { timeout: *const ::timespec) -> ::c_int; pub fn sigwaitinfo(set: *const sigset_t, info: *mut siginfo_t) -> ::c_int; - pub fn openpty(amaster: *mut ::c_int, - aslave: *mut ::c_int, - name: *mut ::c_char, - termp: *const termios, - winp: *const ::winsize) -> ::c_int; - pub fn forkpty(amaster: *mut ::c_int, - name: *mut ::c_char, - termp: *const termios, - winp: *const ::winsize) -> ::pid_t; pub fn nl_langinfo_l(item: ::nl_item, locale: ::locale_t) -> *mut ::c_char; pub fn getnameinfo(sa: *const ::sockaddr, salen: ::socklen_t, @@ -873,6 +1109,8 @@ extern { serv: *mut ::c_char, sevlen: ::socklen_t, flags: ::c_int) -> ::c_int; + pub fn pthread_setschedprio(native: ::pthread_t, + priority: ::c_int) -> ::c_int; pub fn prlimit(pid: ::pid_t, resource: ::c_int, new_limit: *const ::rlimit, old_limit: *mut ::rlimit) -> ::c_int; pub fn prlimit64(pid: ::pid_t, @@ -895,8 +1133,6 @@ extern { pub fn reboot(how_to: ::c_int) -> ::c_int; pub fn setfsgid(gid: ::gid_t) -> ::c_int; pub fn setfsuid(uid: ::uid_t) -> ::c_int; - pub fn setresgid(rgid: ::gid_t, egid: ::gid_t, sgid: ::gid_t) -> ::c_int; - pub fn setresuid(ruid: ::uid_t, euid: ::uid_t, suid: ::uid_t) -> ::c_int; // Not available now on Android pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char, @@ -956,6 +1192,17 @@ extern { flags: ::c_int) -> ::ssize_t; pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int) -> ::ssize_t; + pub fn getdomainname(name: *mut ::c_char, len: ::size_t) -> ::c_int; + pub fn setdomainname(name: *const ::c_char, len: ::size_t) -> ::c_int; + pub fn vhangup() -> ::c_int; +} + +extern { + pub fn sendmmsg(sockfd: ::c_int, msgvec: *mut mmsghdr, vlen: ::c_uint, + flags: ::c_int) -> ::c_int; + pub fn recvmmsg(sockfd: ::c_int, msgvec: *mut mmsghdr, vlen: ::c_uint, + flags: ::c_int, timeout: *mut ::timespec) -> ::c_int; + pub fn sync(); } cfg_if! { diff --git a/src/vendor/libc/src/unix/notbsd/linux/musl/b32/arm.rs b/src/vendor/libc/src/unix/notbsd/linux/musl/b32/arm.rs index ce198aca92..b03ed62333 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/musl/b32/arm.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/musl/b32/arm.rs @@ -344,3 +344,15 @@ pub const SYS_perf_event_open: ::c_long = 364; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; + +pub const TIOCM_LE: ::c_int = 0x001; +pub const TIOCM_DTR: ::c_int = 0x002; +pub const TIOCM_RTS: ::c_int = 0x004; +pub const TIOCM_ST: ::c_int = 0x008; +pub const TIOCM_SR: ::c_int = 0x010; +pub const TIOCM_CTS: ::c_int = 0x020; +pub const TIOCM_CAR: ::c_int = 0x040; +pub const TIOCM_RNG: ::c_int = 0x080; +pub const TIOCM_DSR: ::c_int = 0x100; +pub const TIOCM_CD: ::c_int = TIOCM_CAR; +pub const TIOCM_RI: ::c_int = TIOCM_RNG; diff --git a/src/vendor/libc/src/unix/notbsd/linux/musl/b32/asmjs.rs b/src/vendor/libc/src/unix/notbsd/linux/musl/b32/asmjs.rs index e890a34585..70d73562d5 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/musl/b32/asmjs.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/musl/b32/asmjs.rs @@ -334,3 +334,15 @@ pub const SYS_gettid: ::c_long = 224; // Valid for arm (32-bit) and x86 (32-bit) pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; + +pub const TIOCM_LE: ::c_int = 0x001; +pub const TIOCM_DTR: ::c_int = 0x002; +pub const TIOCM_RTS: ::c_int = 0x004; +pub const TIOCM_ST: ::c_int = 0x008; +pub const TIOCM_SR: ::c_int = 0x010; +pub const TIOCM_CTS: ::c_int = 0x020; +pub const TIOCM_CAR: ::c_int = 0x040; +pub const TIOCM_RNG: ::c_int = 0x080; +pub const TIOCM_DSR: ::c_int = 0x100; +pub const TIOCM_CD: ::c_int = TIOCM_CAR; +pub const TIOCM_RI: ::c_int = TIOCM_RNG; diff --git a/src/vendor/libc/src/unix/notbsd/linux/musl/b32/mips.rs b/src/vendor/libc/src/unix/notbsd/linux/musl/b32/mips.rs index 23c1a267e6..dcfd0c379a 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/musl/b32/mips.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/musl/b32/mips.rs @@ -352,3 +352,15 @@ pub const SYS_perf_event_open: ::c_long = 4333; // Valid for O32 pub const POLLWRNORM: ::c_short = 0x4; pub const POLLWRBAND: ::c_short = 0x100; + +pub const TIOCM_LE: ::c_int = 0x001; +pub const TIOCM_DTR: ::c_int = 0x002; +pub const TIOCM_RTS: ::c_int = 0x004; +pub const TIOCM_ST: ::c_int = 0x010; +pub const TIOCM_SR: ::c_int = 0x020; +pub const TIOCM_CTS: ::c_int = 0x040; +pub const TIOCM_CAR: ::c_int = 0x100; +pub const TIOCM_CD: ::c_int = TIOCM_CAR; +pub const TIOCM_RNG: ::c_int = 0x200; +pub const TIOCM_RI: ::c_int = TIOCM_RNG; +pub const TIOCM_DSR: ::c_int = 0x400; diff --git a/src/vendor/libc/src/unix/notbsd/linux/musl/b32/mod.rs b/src/vendor/libc/src/unix/notbsd/linux/musl/b32/mod.rs index 61eb6dba17..f952105375 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/musl/b32/mod.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/musl/b32/mod.rs @@ -1,6 +1,7 @@ pub type c_long = i32; pub type c_ulong = u32; pub type nlink_t = u32; +pub type __u64 = ::c_ulonglong; s! { pub struct pthread_attr_t { diff --git a/src/vendor/libc/src/unix/notbsd/linux/musl/b32/x86.rs b/src/vendor/libc/src/unix/notbsd/linux/musl/b32/x86.rs index 9daeb58b99..a789917216 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/musl/b32/x86.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/musl/b32/x86.rs @@ -358,3 +358,15 @@ pub const SYS_perf_event_open: ::c_long = 336; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; + +pub const TIOCM_LE: ::c_int = 0x001; +pub const TIOCM_DTR: ::c_int = 0x002; +pub const TIOCM_RTS: ::c_int = 0x004; +pub const TIOCM_ST: ::c_int = 0x008; +pub const TIOCM_SR: ::c_int = 0x010; +pub const TIOCM_CTS: ::c_int = 0x020; +pub const TIOCM_CAR: ::c_int = 0x040; +pub const TIOCM_RNG: ::c_int = 0x080; +pub const TIOCM_DSR: ::c_int = 0x100; +pub const TIOCM_CD: ::c_int = TIOCM_CAR; +pub const TIOCM_RI: ::c_int = TIOCM_RNG; diff --git a/src/vendor/libc/src/unix/notbsd/linux/musl/b64/aarch64.rs b/src/vendor/libc/src/unix/notbsd/linux/musl/b64/aarch64.rs index 23f7dd35e5..003ee58c4d 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/musl/b64/aarch64.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/musl/b64/aarch64.rs @@ -1,3 +1,4 @@ pub type c_char = u8; +pub type __u64 = ::c_ulonglong; pub const SYS_perf_event_open: ::c_long = 241; diff --git a/src/vendor/libc/src/unix/notbsd/linux/musl/b64/mod.rs b/src/vendor/libc/src/unix/notbsd/linux/musl/b64/mod.rs index fab0b58fed..e35a0518b6 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/musl/b64/mod.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/musl/b64/mod.rs @@ -371,6 +371,18 @@ pub const TIOCCONS: ::c_int = 0x541D; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; +pub const TIOCM_LE: ::c_int = 0x001; +pub const TIOCM_DTR: ::c_int = 0x002; +pub const TIOCM_RTS: ::c_int = 0x004; +pub const TIOCM_ST: ::c_int = 0x008; +pub const TIOCM_SR: ::c_int = 0x010; +pub const TIOCM_CTS: ::c_int = 0x020; +pub const TIOCM_CAR: ::c_int = 0x040; +pub const TIOCM_RNG: ::c_int = 0x080; +pub const TIOCM_DSR: ::c_int = 0x100; +pub const TIOCM_CD: ::c_int = TIOCM_CAR; +pub const TIOCM_RI: ::c_int = TIOCM_RNG; + cfg_if! { if #[cfg(target_arch = "aarch64")] { mod aarch64; diff --git a/src/vendor/libc/src/unix/notbsd/linux/musl/b64/powerpc64.rs b/src/vendor/libc/src/unix/notbsd/linux/musl/b64/powerpc64.rs index 4b8ca10aab..e492107842 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/musl/b64/powerpc64.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/musl/b64/powerpc64.rs @@ -1,3 +1,4 @@ pub type c_char = u8; +pub type __u64 = ::c_ulong; pub const SYS_perf_event_open: ::c_long = 319; diff --git a/src/vendor/libc/src/unix/notbsd/linux/musl/b64/x86_64.rs b/src/vendor/libc/src/unix/notbsd/linux/musl/b64/x86_64.rs index 2cfd903ca8..c611950b30 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/musl/b64/x86_64.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/musl/b64/x86_64.rs @@ -1,4 +1,5 @@ pub type c_char = i8; +pub type __u64 = ::c_ulonglong; s! { pub struct mcontext_t { diff --git a/src/vendor/libc/src/unix/notbsd/linux/musl/mod.rs b/src/vendor/libc/src/unix/notbsd/linux/musl/mod.rs index a0d947bc42..c7841721fb 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/musl/mod.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/musl/mod.rs @@ -35,7 +35,7 @@ s! { pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, pub sa_flags: ::c_int, - _restorer: *mut ::c_void, + pub sa_restorer: ::dox::Option, } pub struct ipc_perm { @@ -87,8 +87,6 @@ s! { } } -pub const CLONE_NEWCGROUP: ::c_int = 0x02000000; - pub const SFD_CLOEXEC: ::c_int = 0x080000; pub const NCCS: usize = 32; @@ -160,6 +158,7 @@ pub const FALLOC_FL_PUNCH_HOLE: ::c_int = 0x02; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; +pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const CPU_SETSIZE: ::c_int = 128; @@ -280,6 +279,18 @@ pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; +pub const CMSPAR: ::tcflag_t = 0o10000000000; +pub const CIBAUD: ::tcflag_t = 0o02003600000; +pub const CBAUDEX: ::tcflag_t = 0o010000; +pub const VSWTC: usize = 7; +pub const OLCUC: ::tcflag_t = 0o000002; +pub const NLDLY: ::tcflag_t = 0o000400; +pub const CRDLY: ::tcflag_t = 0o003000; +pub const TABDLY: ::tcflag_t = 0o014000; +pub const BSDLY: ::tcflag_t = 0o020000; +pub const FFDLY: ::tcflag_t = 0o100000; +pub const VTDLY: ::tcflag_t = 0o040000; +pub const XTABS: ::tcflag_t = 0o014000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; @@ -315,6 +326,13 @@ pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; +pub const SO_BINDTODEVICE: ::c_int = 25; +pub const SO_TIMESTAMP: ::c_int = 29; +pub const SO_MARK: ::c_int = 36; +pub const SO_RXQ_OVFL: ::c_int = 40; +pub const SO_PEEK_OFF: ::c_int = 42; +pub const SO_BUSY_POLL: ::c_int = 46; + extern { pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int; pub fn ptrace(request: ::c_int, ...) -> ::c_long; diff --git a/src/vendor/libc/src/unix/notbsd/linux/other/b32/arm.rs b/src/vendor/libc/src/unix/notbsd/linux/other/b32/arm.rs index ee6d67403a..b78b10f3c1 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/other/b32/arm.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/other/b32/arm.rs @@ -81,11 +81,13 @@ pub const MAP_NORESERVE: ::c_int = 0x04000; pub const EDEADLOCK: ::c_int = 35; +pub const SO_PASSCRED: ::c_int = 16; pub const SO_PEERCRED: ::c_int = 17; pub const SO_RCVLOWAT: ::c_int = 18; pub const SO_SNDLOWAT: ::c_int = 19; pub const SO_RCVTIMEO: ::c_int = 20; pub const SO_SNDTIMEO: ::c_int = 21; +pub const SO_SNDBUFFORCE: ::c_int = 32; pub const FIOCLEX: ::c_ulong = 0x5451; pub const FIONBIO: ::c_ulong = 0x5421; @@ -141,6 +143,17 @@ pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; +pub const CIBAUD: ::tcflag_t = 0o02003600000; +pub const CBAUDEX: ::tcflag_t = 0o010000; +pub const VSWTC: usize = 7; +pub const OLCUC: ::tcflag_t = 0o000002; +pub const NLDLY: ::tcflag_t = 0o000400; +pub const CRDLY: ::tcflag_t = 0o003000; +pub const TABDLY: ::tcflag_t = 0o014000; +pub const BSDLY: ::tcflag_t = 0o020000; +pub const FFDLY: ::tcflag_t = 0o100000; +pub const VTDLY: ::tcflag_t = 0o040000; +pub const XTABS: ::tcflag_t = 0o014000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; diff --git a/src/vendor/libc/src/unix/notbsd/linux/other/b32/mod.rs b/src/vendor/libc/src/unix/notbsd/linux/other/b32/mod.rs index 0f936c7e24..d03457bdd0 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/other/b32/mod.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/other/b32/mod.rs @@ -12,6 +12,7 @@ pub type __fsword_t = i32; pub type blksize_t = i32; pub type nlink_t = u32; +pub type __u64 = ::c_ulonglong; s! { pub struct stat { @@ -171,9 +172,19 @@ 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_PRIORITY: ::c_int = 12; pub const SO_LINGER: ::c_int = 13; +pub const SO_BSDCOMPAT: ::c_int = 14; pub const SO_REUSEPORT: ::c_int = 15; +pub const SO_BINDTODEVICE: ::c_int = 25; +pub const SO_TIMESTAMP: ::c_int = 29; pub const SO_ACCEPTCONN: ::c_int = 30; +pub const SO_MARK: ::c_int = 36; +pub const SO_PROTOCOL: ::c_int = 38; +pub const SO_DOMAIN: ::c_int = 39; +pub const SO_RXQ_OVFL: ::c_int = 40; +pub const SO_PEEK_OFF: ::c_int = 42; +pub const SO_BUSY_POLL: ::c_int = 46; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000004; @@ -224,7 +235,6 @@ 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; @@ -262,6 +272,7 @@ pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 24; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; +pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const PTRACE_GETFPREGS: ::c_uint = 14; pub const PTRACE_SETFPREGS: ::c_uint = 15; diff --git a/src/vendor/libc/src/unix/notbsd/linux/other/b32/powerpc.rs b/src/vendor/libc/src/unix/notbsd/linux/other/b32/powerpc.rs index 035bfe19cd..1be28461d2 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/other/b32/powerpc.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/other/b32/powerpc.rs @@ -84,8 +84,6 @@ pub const EDEADLOCK: ::c_int = 58; pub const SO_SNDBUFFORCE: ::c_int = 32; pub const SO_RCVBUFFORCE: ::c_int = 33; pub const SO_NO_CHECK: ::c_int = 11; -pub const SO_PRIORITY: ::c_int = 12; -pub const SO_BSDCOMPAT: ::c_int = 14; pub const SO_RCVLOWAT: ::c_int = 16; pub const SO_SNDLOWAT: ::c_int = 17; pub const SO_RCVTIMEO: ::c_int = 18; @@ -144,6 +142,15 @@ pub const ISIG: ::tcflag_t = 0x80; pub const ICANON: ::tcflag_t = 0x100; pub const PENDIN: ::tcflag_t = 0x20000000; pub const NOFLSH: ::tcflag_t = 0x80000000; +pub const VSWTC: usize = 9; +pub const OLCUC: ::tcflag_t = 0o000004; +pub const NLDLY: ::tcflag_t = 0o001400; +pub const CRDLY: ::tcflag_t = 0o030000; +pub const TABDLY: ::tcflag_t = 0o006000; +pub const BSDLY: ::tcflag_t = 0o100000; +pub const FFDLY: ::tcflag_t = 0o040000; +pub const VTDLY: ::tcflag_t = 0o200000; +pub const XTABS: ::tcflag_t = 0o006000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; diff --git a/src/vendor/libc/src/unix/notbsd/linux/other/b32/x86.rs b/src/vendor/libc/src/unix/notbsd/linux/other/b32/x86.rs index 263e1406b7..00041bf0dd 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/other/b32/x86.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/other/b32/x86.rs @@ -20,6 +20,71 @@ s! { pub status: ::c_ulong, } + pub struct user_fpregs_struct { + pub cwd: ::c_long, + pub swd: ::c_long, + pub twd: ::c_long, + pub fip: ::c_long, + pub fcs: ::c_long, + pub foo: ::c_long, + pub fos: ::c_long, + pub st_space: [::c_long; 20], + } + + pub struct user_fpxregs_struct { + pub cwd: ::c_ushort, + pub swd: ::c_ushort, + pub twd: ::c_ushort, + pub fop: ::c_ushort, + pub fip: ::c_long, + pub fcs: ::c_long, + pub foo: ::c_long, + pub fos: ::c_long, + pub mxcsr: ::c_long, + __reserved: ::c_long, + pub st_space: [::c_long; 32], + pub xmm_space: [::c_long; 32], + padding: [::c_long; 56], + } + + pub struct user_regs_struct { + pub ebx: ::c_long, + pub ecx: ::c_long, + pub edx: ::c_long, + pub esi: ::c_long, + pub edi: ::c_long, + pub ebp: ::c_long, + pub eax: ::c_long, + pub xds: ::c_long, + pub xes: ::c_long, + pub xfs: ::c_long, + pub xgs: ::c_long, + pub orig_eax: ::c_long, + pub eip: ::c_long, + pub xcs: ::c_long, + pub eflags: ::c_long, + pub esp: ::c_long, + pub xss: ::c_long, + } + + pub struct user { + pub regs: user_regs_struct, + pub u_fpvalid: ::c_int, + pub i387: user_fpregs_struct, + pub u_tsize: ::c_ulong, + pub u_dsize: ::c_ulong, + pub u_ssize: ::c_ulong, + pub start_code: ::c_ulong, + pub start_stack: ::c_ulong, + pub signal: ::c_long, + __reserved: ::c_int, + pub u_ar0: *mut user_regs_struct, + pub u_fpstate: *mut user_fpregs_struct, + pub magic: ::c_ulong, + pub u_comm: [c_char; 32], + pub u_debugreg: [::c_int; 8], + } + pub struct mcontext_t { pub gregs: [greg_t; 19], pub fpregs: *mut _libc_fpstate, @@ -119,8 +184,6 @@ pub const EDEADLOCK: ::c_int = 35; pub const SO_SNDBUFFORCE: ::c_int = 32; pub const SO_RCVBUFFORCE: ::c_int = 33; pub const SO_NO_CHECK: ::c_int = 11; -pub const SO_PRIORITY: ::c_int = 12; -pub const SO_BSDCOMPAT: ::c_int = 14; pub const SO_PASSCRED: ::c_int = 16; pub const SO_PEERCRED: ::c_int = 17; pub const SO_RCVLOWAT: ::c_int = 18; @@ -182,6 +245,17 @@ pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; +pub const CIBAUD: ::tcflag_t = 0o02003600000; +pub const CBAUDEX: ::tcflag_t = 0o010000; +pub const VSWTC: usize = 7; +pub const OLCUC: ::tcflag_t = 0o000002; +pub const NLDLY: ::tcflag_t = 0o000400; +pub const CRDLY: ::tcflag_t = 0o003000; +pub const TABDLY: ::tcflag_t = 0o014000; +pub const BSDLY: ::tcflag_t = 0o020000; +pub const FFDLY: ::tcflag_t = 0o100000; +pub const VTDLY: ::tcflag_t = 0o040000; +pub const XTABS: ::tcflag_t = 0o014000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; diff --git a/src/vendor/libc/src/unix/notbsd/linux/other/b64/aarch64.rs b/src/vendor/libc/src/unix/notbsd/linux/other/b64/aarch64.rs index 77cee3d217..692cae4122 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/other/b64/aarch64.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/other/b64/aarch64.rs @@ -5,6 +5,7 @@ pub type wchar_t = u32; pub type nlink_t = u32; pub type blksize_t = i32; pub type suseconds_t = i64; +pub type __u64 = ::c_ulonglong; s! { pub struct stat { @@ -287,8 +288,6 @@ 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; @@ -385,6 +384,17 @@ pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; +pub const CIBAUD: ::tcflag_t = 0o02003600000; +pub const CBAUDEX: ::tcflag_t = 0o010000; +pub const VSWTC: usize = 7; +pub const OLCUC: ::tcflag_t = 0o000002; +pub const NLDLY: ::tcflag_t = 0o000400; +pub const CRDLY: ::tcflag_t = 0o003000; +pub const TABDLY: ::tcflag_t = 0o014000; +pub const BSDLY: ::tcflag_t = 0o020000; +pub const FFDLY: ::tcflag_t = 0o100000; +pub const VTDLY: ::tcflag_t = 0o040000; +pub const XTABS: ::tcflag_t = 0o014000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; diff --git a/src/vendor/libc/src/unix/notbsd/linux/other/b64/mod.rs b/src/vendor/libc/src/unix/notbsd/linux/other/b64/mod.rs index 2fcec73a89..1e306dad2b 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/other/b64/mod.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/other/b64/mod.rs @@ -47,6 +47,7 @@ s! { } pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; +pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; cfg_if! { if #[cfg(target_arch = "aarch64")] { diff --git a/src/vendor/libc/src/unix/notbsd/linux/other/b64/powerpc64.rs b/src/vendor/libc/src/unix/notbsd/linux/other/b64/powerpc64.rs index 8c19b0713d..aad7763638 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/other/b64/powerpc64.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/other/b64/powerpc64.rs @@ -5,6 +5,7 @@ pub type wchar_t = i32; pub type nlink_t = u64; pub type blksize_t = i64; pub type suseconds_t = i64; +pub type __u64 = ::c_ulong; s! { pub struct stat { @@ -285,8 +286,6 @@ 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; @@ -383,6 +382,15 @@ pub const ISIG: ::tcflag_t = 0x80; pub const ICANON: ::tcflag_t = 0x100; pub const PENDIN: ::tcflag_t = 0x20000000; pub const NOFLSH: ::tcflag_t = 0x80000000; +pub const VSWTC: usize = 9; +pub const OLCUC: ::tcflag_t = 0o000004; +pub const NLDLY: ::tcflag_t = 0o001400; +pub const CRDLY: ::tcflag_t = 0o030000; +pub const TABDLY: ::tcflag_t = 0o006000; +pub const BSDLY: ::tcflag_t = 0o100000; +pub const FFDLY: ::tcflag_t = 0o040000; +pub const VTDLY: ::tcflag_t = 0o200000; +pub const XTABS: ::tcflag_t = 0o006000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; diff --git a/src/vendor/libc/src/unix/notbsd/linux/other/b64/sparc64.rs b/src/vendor/libc/src/unix/notbsd/linux/other/b64/sparc64.rs index 12598e0522..c9c4b4cdcb 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/other/b64/sparc64.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/other/b64/sparc64.rs @@ -5,6 +5,7 @@ pub type wchar_t = i32; pub type nlink_t = u32; pub type blksize_t = i64; pub type suseconds_t = i32; +pub type __u64 = ::c_ulonglong; s! { pub struct stat { @@ -182,12 +183,19 @@ pub const ERFKILL: ::c_int = 134; pub const SOL_SOCKET: ::c_int = 0xffff; pub const SO_REUSEADDR: ::c_int = 4; +pub const SO_BINDTODEVICE: ::c_int = 0x000d; +pub const SO_TIMESTAMP: ::c_int = 0x001d; +pub const SO_MARK: ::c_int = 0x0022; +pub const SO_RXQ_OVFL: ::c_int = 0x0024; +pub const SO_PEEK_OFF: ::c_int = 0x0026; +pub const SO_BUSY_POLL: ::c_int = 0x0030; 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_DOMAIN: ::c_int = 0x1029; pub const SO_KEEPALIVE: ::c_int = 8; pub const SO_OOBINLINE: ::c_int = 0x100; pub const SO_LINGER: ::c_int = 128; @@ -342,6 +350,17 @@ 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 CIBAUD: ::tcflag_t = 0o02003600000; +pub const CBAUDEX: ::tcflag_t = 0x00001000; +pub const VSWTC: usize = 7; +pub const OLCUC: ::tcflag_t = 0o000002; +pub const NLDLY: ::tcflag_t = 0o000400; +pub const CRDLY: ::tcflag_t = 0o003000; +pub const TABDLY: ::tcflag_t = 0o014000; +pub const BSDLY: ::tcflag_t = 0o020000; +pub const FFDLY: ::tcflag_t = 0o100000; +pub const VTDLY: ::tcflag_t = 0o040000; +pub const XTABS: ::tcflag_t = 0o014000; pub const VEOL: usize = 5; pub const VEOL2: usize = 6; diff --git a/src/vendor/libc/src/unix/notbsd/linux/other/b64/x86_64.rs b/src/vendor/libc/src/unix/notbsd/linux/other/b64/x86_64.rs index b39ccb3916..51df5a0496 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/other/b64/x86_64.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/other/b64/x86_64.rs @@ -6,6 +6,7 @@ pub type nlink_t = u64; pub type blksize_t = i64; pub type greg_t = i64; pub type suseconds_t = i64; +pub type __u64 = ::c_ulonglong; s! { pub struct stat { @@ -78,6 +79,68 @@ s! { __private: [u64; 12], } + pub struct user_fpregs_struct { + pub cwd: ::c_ushort, + pub swd: ::c_ushort, + pub ftw: ::c_ushort, + pub fop: ::c_ushort, + pub rip: ::c_ulonglong, + pub rdp: ::c_ulonglong, + pub mxcsr: ::c_uint, + pub mxcr_mask: ::c_uint, + pub st_space: [::c_uint; 32], + pub xmm_space: [::c_uint; 64], + padding: [::c_uint; 24], + } + + pub struct user_regs_struct { + pub r15: ::c_ulonglong, + pub r14: ::c_ulonglong, + pub r13: ::c_ulonglong, + pub r12: ::c_ulonglong, + pub rbp: ::c_ulonglong, + pub rbx: ::c_ulonglong, + pub r11: ::c_ulonglong, + pub r10: ::c_ulonglong, + pub r9: ::c_ulonglong, + pub r8: ::c_ulonglong, + pub rax: ::c_ulonglong, + pub rcx: ::c_ulonglong, + pub rdx: ::c_ulonglong, + pub rsi: ::c_ulonglong, + pub rdi: ::c_ulonglong, + pub orig_rax: ::c_ulonglong, + pub rip: ::c_ulonglong, + pub cs: ::c_ulonglong, + pub eflags: ::c_ulonglong, + pub rsp: ::c_ulonglong, + pub ss: ::c_ulonglong, + pub fs_base: ::c_ulonglong, + pub gs_base: ::c_ulonglong, + pub ds: ::c_ulonglong, + pub es: ::c_ulonglong, + pub fs: ::c_ulonglong, + pub gs: ::c_ulonglong, + } + + pub struct user { + pub regs: user_regs_struct, + pub u_fpvalid: ::c_int, + pub i387: user_fpregs_struct, + pub u_tsize: ::c_ulonglong, + pub u_dsize: ::c_ulonglong, + pub u_ssize: ::c_ulonglong, + pub start_code: ::c_ulonglong, + pub start_stack: ::c_ulonglong, + pub signal: ::c_longlong, + __reserved: ::c_int, + pub u_ar0: *mut user_regs_struct, + pub u_fpstate: *mut user_fpregs_struct, + pub magic: ::c_ulonglong, + pub u_comm: [::c_char; 32], + pub u_debugreg: [::c_ulonglong; 8], + } + pub struct mcontext_t { pub gregs: [greg_t; 23], pub fpregs: *mut _libc_fpstate, @@ -326,8 +389,6 @@ 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; @@ -443,6 +504,17 @@ pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; +pub const CIBAUD: ::tcflag_t = 0o02003600000; +pub const CBAUDEX: ::tcflag_t = 0o010000; +pub const VSWTC: usize = 7; +pub const OLCUC: ::tcflag_t = 0o000002; +pub const NLDLY: ::tcflag_t = 0o000400; +pub const CRDLY: ::tcflag_t = 0o003000; +pub const TABDLY: ::tcflag_t = 0o014000; +pub const BSDLY: ::tcflag_t = 0o020000; +pub const FFDLY: ::tcflag_t = 0o100000; +pub const VTDLY: ::tcflag_t = 0o040000; +pub const XTABS: ::tcflag_t = 0o014000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; @@ -512,4 +584,7 @@ extern { argc: ::c_int, ...); pub fn swapcontext(uocp: *mut ucontext_t, ucp: *const ucontext_t) -> ::c_int; + pub fn iopl(level: ::c_int) -> ::c_int; + pub fn ioperm(from: ::c_ulong, num: ::c_ulong, + turn_on: ::c_int) -> ::c_int; } diff --git a/src/vendor/libc/src/unix/notbsd/linux/other/mod.rs b/src/vendor/libc/src/unix/notbsd/linux/other/mod.rs index 13a5c68d6f..6dc59c78fa 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/other/mod.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/other/mod.rs @@ -70,7 +70,7 @@ s! { #[cfg(target_arch = "sparc64")] __reserved0: ::c_int, pub sa_flags: ::c_int, - _restorer: *mut ::c_void, + pub sa_restorer: ::dox::Option, } pub struct stack_t { @@ -281,7 +281,81 @@ pub const FOPEN_MAX: ::c_uint = 16; pub const POSIX_FADV_DONTNEED: ::c_int = 4; pub const POSIX_FADV_NOREUSE: ::c_int = 5; pub const POSIX_MADV_DONTNEED: ::c_int = 4; +pub const _SC_EQUIV_CLASS_MAX: ::c_int = 41; +pub const _SC_CHARCLASS_NAME_MAX: ::c_int = 45; +pub const _SC_PII: ::c_int = 53; +pub const _SC_PII_XTI: ::c_int = 54; +pub const _SC_PII_SOCKET: ::c_int = 55; +pub const _SC_PII_INTERNET: ::c_int = 56; +pub const _SC_PII_OSI: ::c_int = 57; +pub const _SC_POLL: ::c_int = 58; +pub const _SC_SELECT: ::c_int = 59; +pub const _SC_PII_INTERNET_STREAM: ::c_int = 61; +pub const _SC_PII_INTERNET_DGRAM: ::c_int = 62; +pub const _SC_PII_OSI_COTS: ::c_int = 63; +pub const _SC_PII_OSI_CLTS: ::c_int = 64; +pub const _SC_PII_OSI_M: ::c_int = 65; +pub const _SC_T_IOV_MAX: ::c_int = 66; pub const _SC_2_C_VERSION: ::c_int = 96; +pub const _SC_CHAR_BIT: ::c_int = 101; +pub const _SC_CHAR_MAX: ::c_int = 102; +pub const _SC_CHAR_MIN: ::c_int = 103; +pub const _SC_INT_MAX: ::c_int = 104; +pub const _SC_INT_MIN: ::c_int = 105; +pub const _SC_LONG_BIT: ::c_int = 106; +pub const _SC_WORD_BIT: ::c_int = 107; +pub const _SC_MB_LEN_MAX: ::c_int = 108; +pub const _SC_SSIZE_MAX: ::c_int = 110; +pub const _SC_SCHAR_MAX: ::c_int = 111; +pub const _SC_SCHAR_MIN: ::c_int = 112; +pub const _SC_SHRT_MAX: ::c_int = 113; +pub const _SC_SHRT_MIN: ::c_int = 114; +pub const _SC_UCHAR_MAX: ::c_int = 115; +pub const _SC_UINT_MAX: ::c_int = 116; +pub const _SC_ULONG_MAX: ::c_int = 117; +pub const _SC_USHRT_MAX: ::c_int = 118; +pub const _SC_NL_ARGMAX: ::c_int = 119; +pub const _SC_NL_LANGMAX: ::c_int = 120; +pub const _SC_NL_MSGMAX: ::c_int = 121; +pub const _SC_NL_NMAX: ::c_int = 122; +pub const _SC_NL_SETMAX: ::c_int = 123; +pub const _SC_NL_TEXTMAX: ::c_int = 124; +pub const _SC_BASE: ::c_int = 134; +pub const _SC_C_LANG_SUPPORT: ::c_int = 135; +pub const _SC_C_LANG_SUPPORT_R: ::c_int = 136; +pub const _SC_DEVICE_IO: ::c_int = 140; +pub const _SC_DEVICE_SPECIFIC: ::c_int = 141; +pub const _SC_DEVICE_SPECIFIC_R: ::c_int = 142; +pub const _SC_FD_MGMT: ::c_int = 143; +pub const _SC_FIFO: ::c_int = 144; +pub const _SC_PIPE: ::c_int = 145; +pub const _SC_FILE_ATTRIBUTES: ::c_int = 146; +pub const _SC_FILE_LOCKING: ::c_int = 147; +pub const _SC_FILE_SYSTEM: ::c_int = 148; +pub const _SC_MULTI_PROCESS: ::c_int = 150; +pub const _SC_SINGLE_PROCESS: ::c_int = 151; +pub const _SC_NETWORKING: ::c_int = 152; +pub const _SC_REGEX_VERSION: ::c_int = 156; +pub const _SC_SIGNALS: ::c_int = 158; +pub const _SC_SYSTEM_DATABASE: ::c_int = 162; +pub const _SC_SYSTEM_DATABASE_R: ::c_int = 163; +pub const _SC_USER_GROUPS: ::c_int = 166; +pub const _SC_USER_GROUPS_R: ::c_int = 167; +pub const _SC_LEVEL1_ICACHE_SIZE: ::c_int = 185; +pub const _SC_LEVEL1_ICACHE_ASSOC: ::c_int = 186; +pub const _SC_LEVEL1_ICACHE_LINESIZE: ::c_int = 187; +pub const _SC_LEVEL1_DCACHE_SIZE: ::c_int = 188; +pub const _SC_LEVEL1_DCACHE_ASSOC: ::c_int = 189; +pub const _SC_LEVEL1_DCACHE_LINESIZE: ::c_int = 190; +pub const _SC_LEVEL2_CACHE_SIZE: ::c_int = 191; +pub const _SC_LEVEL2_CACHE_ASSOC: ::c_int = 192; +pub const _SC_LEVEL2_CACHE_LINESIZE: ::c_int = 193; +pub const _SC_LEVEL3_CACHE_SIZE: ::c_int = 194; +pub const _SC_LEVEL3_CACHE_ASSOC: ::c_int = 195; +pub const _SC_LEVEL3_CACHE_LINESIZE: ::c_int = 196; +pub const _SC_LEVEL4_CACHE_SIZE: ::c_int = 197; +pub const _SC_LEVEL4_CACHE_ASSOC: ::c_int = 198; +pub const _SC_LEVEL4_CACHE_LINESIZE: ::c_int = 199; pub const O_ACCMODE: ::c_int = 3; pub const ST_RELATIME: ::c_ulong = 4096; pub const NI_MAXHOST: ::socklen_t = 1025; @@ -443,6 +517,20 @@ pub const NLA_F_NESTED: ::c_int = 1 << 15; pub const NLA_F_NET_BYTEORDER: ::c_int = 1 << 14; pub const NLA_TYPE_MASK: ::c_int = !(NLA_F_NESTED | NLA_F_NET_BYTEORDER); +pub const CMSPAR: ::tcflag_t = 0o10000000000; + +pub const TIOCM_LE: ::c_int = 0x001; +pub const TIOCM_DTR: ::c_int = 0x002; +pub const TIOCM_RTS: ::c_int = 0x004; +pub const TIOCM_ST: ::c_int = 0x008; +pub const TIOCM_SR: ::c_int = 0x010; +pub const TIOCM_CTS: ::c_int = 0x020; +pub const TIOCM_CAR: ::c_int = 0x040; +pub const TIOCM_RNG: ::c_int = 0x080; +pub const TIOCM_DSR: ::c_int = 0x100; +pub const TIOCM_CD: ::c_int = TIOCM_CAR; +pub const TIOCM_RI: ::c_int = TIOCM_RNG; + cfg_if! { if #[cfg(any(target_arch = "arm", target_arch = "x86", target_arch = "x86_64"))] { @@ -500,6 +588,10 @@ extern { pub fn pthread_setaffinity_np(thread: ::pthread_t, cpusetsize: ::size_t, cpuset: *const ::cpu_set_t) -> ::c_int; + pub fn pthread_rwlockattr_getkind_np(attr: *const ::pthread_rwlockattr_t, + val: *mut ::c_int) -> ::c_int; + pub fn pthread_rwlockattr_setkind_np(attr: *mut ::pthread_rwlockattr_t, + val: ::c_int) -> ::c_int; pub fn sched_getcpu() -> ::c_int; } diff --git a/src/vendor/libc/src/unix/notbsd/linux/s390x.rs b/src/vendor/libc/src/unix/notbsd/linux/s390x.rs index f9f7416797..fb95a07af2 100644 --- a/src/vendor/libc/src/unix/notbsd/linux/s390x.rs +++ b/src/vendor/libc/src/unix/notbsd/linux/s390x.rs @@ -16,6 +16,7 @@ pub type greg_t = u64; pub type clock_t = i64; pub type __fsword_t = ::c_long; pub type __priority_which_t = ::c_uint; +pub type __u64 = u64; s! { pub struct aiocb { @@ -86,7 +87,7 @@ s! { pub sa_sigaction: ::sighandler_t, __glibc_reserved0: ::c_int, pub sa_flags: ::c_int, - _restorer: *mut ::c_void, + pub sa_restorer: ::dox::Option, pub sa_mask: sigset_t, } @@ -273,8 +274,6 @@ s! { } } -pub const CLONE_NEWCGROUP: ::c_int = 0x02000000; - pub const SFD_CLOEXEC: ::c_int = 0x080000; pub const NCCS: usize = 32; @@ -314,6 +313,7 @@ pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; +pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; @@ -349,6 +349,14 @@ pub const SO_ERROR: ::c_int = 4; pub const SO_RCVTIMEO: ::c_int = 20; pub const SO_REUSEADDR: ::c_int = 2; pub const SO_SNDTIMEO: ::c_int = 21; +pub const SO_BINDTODEVICE: ::c_int = 25; +pub const SO_TIMESTAMP: ::c_int = 29; +pub const SO_MARK: ::c_int = 36; +pub const SO_PROTOCOL: ::c_int = 38; +pub const SO_DOMAIN: ::c_int = 39; +pub const SO_RXQ_OVFL: ::c_int = 40; +pub const SO_PEEK_OFF: ::c_int = 42; +pub const SO_BUSY_POLL: ::c_int = 46; pub const RLIMIT_RSS: ::c_int = 5; pub const RLIMIT_NOFILE: ::c_int = 7; @@ -537,7 +545,81 @@ pub const BUFSIZ: ::c_uint = 8192; pub const TMP_MAX: ::c_uint = 238328; pub const FOPEN_MAX: ::c_uint = 16; pub const POSIX_MADV_DONTNEED: ::c_int = 4; +pub const _SC_EQUIV_CLASS_MAX: ::c_int = 41; +pub const _SC_CHARCLASS_NAME_MAX: ::c_int = 45; +pub const _SC_PII: ::c_int = 53; +pub const _SC_PII_XTI: ::c_int = 54; +pub const _SC_PII_SOCKET: ::c_int = 55; +pub const _SC_PII_INTERNET: ::c_int = 56; +pub const _SC_PII_OSI: ::c_int = 57; +pub const _SC_POLL: ::c_int = 58; +pub const _SC_SELECT: ::c_int = 59; +pub const _SC_PII_INTERNET_STREAM: ::c_int = 61; +pub const _SC_PII_INTERNET_DGRAM: ::c_int = 62; +pub const _SC_PII_OSI_COTS: ::c_int = 63; +pub const _SC_PII_OSI_CLTS: ::c_int = 64; +pub const _SC_PII_OSI_M: ::c_int = 65; +pub const _SC_T_IOV_MAX: ::c_int = 66; pub const _SC_2_C_VERSION: ::c_int = 96; +pub const _SC_CHAR_BIT: ::c_int = 101; +pub const _SC_CHAR_MAX: ::c_int = 102; +pub const _SC_CHAR_MIN: ::c_int = 103; +pub const _SC_INT_MAX: ::c_int = 104; +pub const _SC_INT_MIN: ::c_int = 105; +pub const _SC_LONG_BIT: ::c_int = 106; +pub const _SC_WORD_BIT: ::c_int = 107; +pub const _SC_MB_LEN_MAX: ::c_int = 108; +pub const _SC_SSIZE_MAX: ::c_int = 110; +pub const _SC_SCHAR_MAX: ::c_int = 111; +pub const _SC_SCHAR_MIN: ::c_int = 112; +pub const _SC_SHRT_MAX: ::c_int = 113; +pub const _SC_SHRT_MIN: ::c_int = 114; +pub const _SC_UCHAR_MAX: ::c_int = 115; +pub const _SC_UINT_MAX: ::c_int = 116; +pub const _SC_ULONG_MAX: ::c_int = 117; +pub const _SC_USHRT_MAX: ::c_int = 118; +pub const _SC_NL_ARGMAX: ::c_int = 119; +pub const _SC_NL_LANGMAX: ::c_int = 120; +pub const _SC_NL_MSGMAX: ::c_int = 121; +pub const _SC_NL_NMAX: ::c_int = 122; +pub const _SC_NL_SETMAX: ::c_int = 123; +pub const _SC_NL_TEXTMAX: ::c_int = 124; +pub const _SC_BASE: ::c_int = 134; +pub const _SC_C_LANG_SUPPORT: ::c_int = 135; +pub const _SC_C_LANG_SUPPORT_R: ::c_int = 136; +pub const _SC_DEVICE_IO: ::c_int = 140; +pub const _SC_DEVICE_SPECIFIC: ::c_int = 141; +pub const _SC_DEVICE_SPECIFIC_R: ::c_int = 142; +pub const _SC_FD_MGMT: ::c_int = 143; +pub const _SC_FIFO: ::c_int = 144; +pub const _SC_PIPE: ::c_int = 145; +pub const _SC_FILE_ATTRIBUTES: ::c_int = 146; +pub const _SC_FILE_LOCKING: ::c_int = 147; +pub const _SC_FILE_SYSTEM: ::c_int = 148; +pub const _SC_MULTI_PROCESS: ::c_int = 150; +pub const _SC_SINGLE_PROCESS: ::c_int = 151; +pub const _SC_NETWORKING: ::c_int = 152; +pub const _SC_REGEX_VERSION: ::c_int = 156; +pub const _SC_SIGNALS: ::c_int = 158; +pub const _SC_SYSTEM_DATABASE: ::c_int = 162; +pub const _SC_SYSTEM_DATABASE_R: ::c_int = 163; +pub const _SC_USER_GROUPS: ::c_int = 166; +pub const _SC_USER_GROUPS_R: ::c_int = 167; +pub const _SC_LEVEL1_ICACHE_SIZE: ::c_int = 185; +pub const _SC_LEVEL1_ICACHE_ASSOC: ::c_int = 186; +pub const _SC_LEVEL1_ICACHE_LINESIZE: ::c_int = 187; +pub const _SC_LEVEL1_DCACHE_SIZE: ::c_int = 188; +pub const _SC_LEVEL1_DCACHE_ASSOC: ::c_int = 189; +pub const _SC_LEVEL1_DCACHE_LINESIZE: ::c_int = 190; +pub const _SC_LEVEL2_CACHE_SIZE: ::c_int = 191; +pub const _SC_LEVEL2_CACHE_ASSOC: ::c_int = 192; +pub const _SC_LEVEL2_CACHE_LINESIZE: ::c_int = 193; +pub const _SC_LEVEL3_CACHE_SIZE: ::c_int = 194; +pub const _SC_LEVEL3_CACHE_ASSOC: ::c_int = 195; +pub const _SC_LEVEL3_CACHE_LINESIZE: ::c_int = 196; +pub const _SC_LEVEL4_CACHE_SIZE: ::c_int = 197; +pub const _SC_LEVEL4_CACHE_ASSOC: ::c_int = 198; +pub const _SC_LEVEL4_CACHE_LINESIZE: ::c_int = 199; pub const O_ASYNC: ::c_int = 0x2000; pub const O_NDELAY: ::c_int = 0x800; pub const ST_RELATIME: ::c_ulong = 4096; @@ -692,6 +774,38 @@ pub const LINUX_REBOOT_CMD_KEXEC: ::c_int = 0x45584543; pub const SYS_gettid: ::c_long = 236; pub const SYS_perf_event_open: ::c_long = 331; +pub const CMSPAR: ::tcflag_t = 0o10000000000; +pub const VSWTC: usize = 7; +pub const OLCUC: ::tcflag_t = 0o000002; +pub const NLDLY: ::tcflag_t = 0o000400; +pub const CRDLY: ::tcflag_t = 0o003000; +pub const CR1: ::tcflag_t = 0x00000200; +pub const CR2: ::tcflag_t = 0x00000400; +pub const CR3: ::tcflag_t = 0x00000600; +pub const TABDLY: ::tcflag_t = 0o014000; +pub const TAB1: ::tcflag_t = 0x00000800; +pub const TAB2: ::tcflag_t = 0x00001000; +pub const TAB3: ::tcflag_t = 0x00001800; +pub const BSDLY: ::tcflag_t = 0o020000; +pub const BS1: ::tcflag_t = 0x00002000; +pub const FFDLY: ::tcflag_t = 0o100000; +pub const FF1: ::tcflag_t = 0x00008000; +pub const VTDLY: ::tcflag_t = 0o040000; +pub const VT1: ::tcflag_t = 0x00004000; +pub const XTABS: ::tcflag_t = 0o014000; + +pub const TIOCM_LE: ::c_int = 0x001; +pub const TIOCM_DTR: ::c_int = 0x002; +pub const TIOCM_RTS: ::c_int = 0x004; +pub const TIOCM_ST: ::c_int = 0x008; +pub const TIOCM_SR: ::c_int = 0x010; +pub const TIOCM_CTS: ::c_int = 0x020; +pub const TIOCM_CAR: ::c_int = 0x040; +pub const TIOCM_RNG: ::c_int = 0x080; +pub const TIOCM_DSR: ::c_int = 0x100; +pub const TIOCM_CD: ::c_int = TIOCM_CAR; +pub const TIOCM_RI: ::c_int = TIOCM_RNG; + #[link(name = "util")] extern { pub fn sysctl(name: *mut ::c_int, diff --git a/src/vendor/libc/src/unix/notbsd/mod.rs b/src/vendor/libc/src/unix/notbsd/mod.rs index b20d043d7a..1a9b7cba6e 100644 --- a/src/vendor/libc/src/unix/notbsd/mod.rs +++ b/src/vendor/libc/src/unix/notbsd/mod.rs @@ -680,6 +680,11 @@ pub const OPOST: ::tcflag_t = 0x1; pub const CS5: ::tcflag_t = 0x00000000; pub const CRTSCTS: ::tcflag_t = 0x80000000; pub const ECHO: ::tcflag_t = 0x00000008; +pub const OCRNL: ::tcflag_t = 0o000010; +pub const ONOCR: ::tcflag_t = 0o000020; +pub const ONLRET: ::tcflag_t = 0o000040; +pub const OFILL: ::tcflag_t = 0o000100; +pub const OFDEL: ::tcflag_t = 0o000200; pub const CLONE_VM: ::c_int = 0x100; pub const CLONE_FS: ::c_int = 0x200; @@ -703,6 +708,7 @@ pub const CLONE_NEWUSER: ::c_int = 0x10000000; pub const CLONE_NEWPID: ::c_int = 0x20000000; pub const CLONE_NEWNET: ::c_int = 0x40000000; pub const CLONE_IO: ::c_int = 0x80000000; +pub const CLONE_NEWCGROUP: ::c_int = 0x02000000; pub const WNOHANG: ::c_int = 0x00000001; pub const WUNTRACED: ::c_int = 0x00000002; @@ -835,6 +841,9 @@ extern { rqtp: *const ::timespec, rmtp: *mut ::timespec) -> ::c_int; pub fn clock_settime(clk_id: clockid_t, tp: *const ::timespec) -> ::c_int; + pub fn dirfd(dirp: *mut ::DIR) -> ::c_int; + pub fn settimeofday(tv: *const ::timeval, tz: *const ::timezone) -> ::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; @@ -853,6 +862,9 @@ extern { pub fn sched_getscheduler(pid: ::pid_t) -> ::c_int; pub fn sched_get_priority_max(policy: ::c_int) -> ::c_int; pub fn sched_get_priority_min(policy: ::c_int) -> ::c_int; + pub fn sched_setparam(pid: ::pid_t, param: *const sched_param) -> ::c_int; + pub fn sched_getparam(pid: ::pid_t, param: *mut sched_param) -> ::c_int; + pub fn sched_rr_get_interval(pid: ::pid_t, tp: *mut ::timespec) -> ::c_int; pub fn epoll_create(size: ::c_int) -> ::c_int; pub fn epoll_create1(flags: ::c_int) -> ::c_int; pub fn epoll_ctl(epfd: ::c_int, @@ -957,6 +969,12 @@ extern { pshared: ::c_int) -> ::c_int; pub fn pthread_condattr_getpshared(attr: *const pthread_condattr_t, pshared: *mut ::c_int) -> ::c_int; + pub fn pthread_getschedparam(native: ::pthread_t, + policy: *mut ::c_int, + param: *mut ::sched_param) -> ::c_int; + pub fn pthread_setschedparam(native: ::pthread_t, + policy: ::c_int, + param: *const ::sched_param) -> ::c_int; pub fn sched_getaffinity(pid: ::pid_t, cpusetsize: ::size_t, cpuset: *mut cpu_set_t) -> ::c_int; @@ -975,12 +993,44 @@ extern { pshared: ::c_int) -> ::c_int; pub fn pthread_mutexattr_getpshared(attr: *const pthread_mutexattr_t, pshared: *mut ::c_int) -> ::c_int; + pub fn pthread_rwlockattr_getpshared(attr: *const pthread_rwlockattr_t, + val: *mut ::c_int) -> ::c_int; + pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, + val: ::c_int) -> ::c_int; pub fn ptsname_r(fd: ::c_int, buf: *mut ::c_char, buflen: ::size_t) -> ::c_int; pub fn clearenv() -> ::c_int; pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t, options: ::c_int) -> ::c_int; + pub fn sigsuspend(mask: *const ::sigset_t) -> ::c_int; + pub fn setreuid(ruid: ::uid_t, euid: ::uid_t) -> ::c_int; + pub fn setregid(rgid: ::gid_t, egid: ::gid_t) -> ::c_int; + pub fn getresuid(ruid: *mut ::uid_t, euid: *mut ::uid_t, + suid: *mut ::uid_t) -> ::c_int; + pub fn getresgid(rgid: *mut ::gid_t, egid: *mut ::gid_t, + sgid: *mut ::gid_t) -> ::c_int; + pub fn personality(persona: ::c_ulong) -> ::c_int; + pub fn swapon(path: *const ::c_char, swapflags: ::c_int) -> ::c_int; + pub fn swapoff(puath: *const ::c_char) -> ::c_int; + pub fn acct(filename: *const ::c_char) -> ::c_int; + pub fn brk(addr: *mut ::c_void) -> ::c_int; + pub fn sbrk(increment: ::intptr_t) -> *mut ::c_void; + pub fn vfork() -> ::pid_t; + pub fn sethostname(name: *const ::c_char, len: ::size_t) -> ::c_int; + pub fn setresgid(rgid: ::gid_t, egid: ::gid_t, sgid: ::gid_t) -> ::c_int; + pub fn setresuid(ruid: ::uid_t, euid: ::uid_t, suid: ::uid_t) -> ::c_int; + pub fn wait4(pid: ::pid_t, status: *mut ::c_int, options: ::c_int, + rusage: *mut ::rusage) -> ::pid_t; + pub fn openpty(amaster: *mut ::c_int, + aslave: *mut ::c_int, + name: *mut ::c_char, + termp: *const termios, + winp: *const ::winsize) -> ::c_int; + pub fn forkpty(amaster: *mut ::c_int, + name: *mut ::c_char, + termp: *const termios, + winp: *const ::winsize) -> ::pid_t; } cfg_if! { diff --git a/src/vendor/libc/src/unix/solaris/mod.rs b/src/vendor/libc/src/unix/solaris/mod.rs index 757d5817ed..51d034e0f4 100644 --- a/src/vendor/libc/src/unix/solaris/mod.rs +++ b/src/vendor/libc/src/unix/solaris/mod.rs @@ -169,6 +169,10 @@ s! { __pthread_rwlock_writercv: ::pthread_cond_t } + pub struct pthread_rwlockattr_t { + __pthread_rwlockattrp: *mut ::c_void, + } + pub struct dirent { pub d_ino: ::ino_t, pub d_off: ::off_t, @@ -766,39 +770,10 @@ pub const POSIX_MADV_SEQUENTIAL: ::c_int = 2; pub const POSIX_MADV_WILLNEED: ::c_int = 3; pub const POSIX_MADV_DONTNEED: ::c_int = 4; -pub const _SC_IOV_MAX: ::c_int = 77; -pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 569; -pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 570; -pub const _SC_LOGIN_NAME_MAX: ::c_int = 571; -pub const _SC_MQ_PRIO_MAX: ::c_int = 30; -pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 577; -pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 578; -pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 568; -pub const _SC_THREAD_KEYS_MAX: ::c_int = 572; -pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 580; -pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 581; -pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 579; -pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 582; -pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 583; -pub const _SC_THREAD_STACK_MIN: ::c_int = 573; -pub const _SC_THREAD_THREADS_MAX: ::c_int = 574; -pub const _SC_THREADS: ::c_int = 576; -pub const _SC_TTY_NAME_MAX: ::c_int = 575; -pub const _SC_ATEXIT_MAX: ::c_int = 76; -pub const _SC_XOPEN_CRYPT: ::c_int = 62; -pub const _SC_XOPEN_ENH_I18N: ::c_int = 63; -pub const _SC_XOPEN_LEGACY: ::c_int = 717; -pub const _SC_XOPEN_REALTIME: ::c_int = 718; -pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 719; -pub const _SC_XOPEN_SHM: ::c_int = 64; -pub const _SC_XOPEN_UNIX: ::c_int = 78; -pub const _SC_XOPEN_VERSION: ::c_int = 12; -pub const _SC_XOPEN_XCU_VERSION: ::c_int = 67; - pub const PTHREAD_CREATE_JOINABLE: ::c_int = 0; pub const PTHREAD_CREATE_DETACHED: ::c_int = 0x40; pub const PTHREAD_PROCESS_SHARED: ::c_int = 1; -pub const PTHREAD_PROCESS_PRIVATE: u16 = 0; +pub const PTHREAD_PROCESS_PRIVATE: ::c_int = 0; pub const PTHREAD_STACK_MIN: ::size_t = 4096; pub const SIGSTKSZ: ::size_t = 8192; @@ -905,6 +880,37 @@ pub const O_NONBLOCK: ::c_int = 128; pub const IPPROTO_RAW: ::c_int = 255; +pub const _PC_LINK_MAX: ::c_int = 1; +pub const _PC_MAX_CANON: ::c_int = 2; +pub const _PC_MAX_INPUT: ::c_int = 3; +pub const _PC_NAME_MAX: ::c_int = 4; +pub const _PC_PATH_MAX: ::c_int = 5; +pub const _PC_PIPE_BUF: ::c_int = 6; +pub const _PC_NO_TRUNC: ::c_int = 7; +pub const _PC_VDISABLE: ::c_int = 8; +pub const _PC_CHOWN_RESTRICTED: ::c_int = 9; +pub const _PC_ASYNC_IO: ::c_int = 10; +pub const _PC_PRIO_IO: ::c_int = 11; +pub const _PC_SYNC_IO: ::c_int = 12; +pub const _PC_ALLOC_SIZE_MIN: ::c_int = 13; +pub const _PC_REC_INCR_XFER_SIZE: ::c_int = 14; +pub const _PC_REC_MAX_XFER_SIZE: ::c_int = 15; +pub const _PC_REC_MIN_XFER_SIZE: ::c_int = 16; +pub const _PC_REC_XFER_ALIGN: ::c_int = 17; +pub const _PC_SYMLINK_MAX: ::c_int = 18; +pub const _PC_2_SYMLINKS: ::c_int = 19; +pub const _PC_ACL_ENABLED: ::c_int = 20; +pub const _PC_MIN_HOLE_SIZE: ::c_int = 21; +pub const _PC_CASE_BEHAVIOR: ::c_int = 22; +pub const _PC_SATTR_ENABLED: ::c_int = 23; +pub const _PC_SATTR_EXISTS: ::c_int = 24; +pub const _PC_ACCESS_FILTERING: ::c_int = 25; +pub const _PC_TIMESTAMP_RESOLUTION: ::c_int = 26; +pub const _PC_FILESIZEBITS: ::c_int = 67; +pub const _PC_XATTR_ENABLED: ::c_int = 100; +pub const _PC_LAST: ::c_int = 101; +pub const _PC_XATTR_EXISTS: ::c_int = 101; + pub const _SC_ARG_MAX: ::c_int = 1; pub const _SC_CHILD_MAX: ::c_int = 2; pub const _SC_CLK_TCK: ::c_int = 3; @@ -913,52 +919,148 @@ pub const _SC_OPEN_MAX: ::c_int = 5; pub const _SC_JOB_CONTROL: ::c_int = 6; pub const _SC_SAVED_IDS: ::c_int = 7; pub const _SC_VERSION: ::c_int = 8; +pub const _SC_PASS_MAX: ::c_int = 9; +pub const _SC_LOGNAME_MAX: ::c_int = 10; pub const _SC_PAGESIZE: ::c_int = 11; pub const _SC_PAGE_SIZE: ::c_int = _SC_PAGESIZE; +pub const _SC_XOPEN_VERSION: ::c_int = 12; +pub const _SC_NPROCESSORS_CONF: ::c_int = 14; pub const _SC_NPROCESSORS_ONLN: ::c_int = 15; pub const _SC_STREAM_MAX: ::c_int = 16; pub const _SC_TZNAME_MAX: ::c_int = 17; pub const _SC_AIO_LISTIO_MAX: ::c_int = 18; pub const _SC_AIO_MAX: ::c_int = 19; -pub const _SC_BC_BASE_MAX: ::c_int = 54; -pub const _SC_BC_DIM_MAX: ::c_int = 55; -pub const _SC_BC_SCALE_MAX: ::c_int = 56; -pub const _SC_BC_STRING_MAX: ::c_int = 57; -pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 58; -pub const _SC_EXPR_NEST_MAX: ::c_int = 59; -pub const _SC_LINE_MAX: ::c_int = 60; -pub const _SC_RE_DUP_MAX: ::c_int = 61; -pub const _SC_2_VERSION: ::c_int = 53; -pub const _SC_2_C_BIND: ::c_int = 45; -pub const _SC_2_C_DEV: ::c_int = 46; -pub const _SC_2_CHAR_TERM: ::c_int = 66; -pub const _SC_2_FORT_DEV: ::c_int = 48; -pub const _SC_2_FORT_RUN: ::c_int = 49; -pub const _SC_2_LOCALEDEF: ::c_int = 50; -pub const _SC_2_SW_DEV: ::c_int = 51; -pub const _SC_2_UPE: ::c_int = 52; +pub const _SC_AIO_PRIO_DELTA_MAX: ::c_int = 20; pub const _SC_ASYNCHRONOUS_IO: ::c_int = 21; +pub const _SC_DELAYTIMER_MAX: ::c_int = 22; +pub const _SC_FSYNC: ::c_int = 23; pub const _SC_MAPPED_FILES: ::c_int = 24; pub const _SC_MEMLOCK: ::c_int = 25; pub const _SC_MEMLOCK_RANGE: ::c_int = 26; pub const _SC_MEMORY_PROTECTION: ::c_int = 27; pub const _SC_MESSAGE_PASSING: ::c_int = 28; +pub const _SC_MQ_OPEN_MAX: ::c_int = 29; +pub const _SC_MQ_PRIO_MAX: ::c_int = 30; pub const _SC_PRIORITIZED_IO: ::c_int = 31; pub const _SC_PRIORITY_SCHEDULING: ::c_int = 32; pub const _SC_REALTIME_SIGNALS: ::c_int = 33; -pub const _SC_SEMAPHORES: ::c_int = 35; -pub const _SC_FSYNC: ::c_int = 23; -pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 38; -pub const _SC_SYNCHRONIZED_IO: ::c_int = 42; -pub const _SC_TIMERS: ::c_int = 43; -pub const _SC_AIO_PRIO_DELTA_MAX: ::c_int = 20; -pub const _SC_DELAYTIMER_MAX: ::c_int = 22; -pub const _SC_MQ_OPEN_MAX: ::c_int = 29; pub const _SC_RTSIG_MAX: ::c_int = 34; +pub const _SC_SEMAPHORES: ::c_int = 35; pub const _SC_SEM_NSEMS_MAX: ::c_int = 36; pub const _SC_SEM_VALUE_MAX: ::c_int = 37; +pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 38; pub const _SC_SIGQUEUE_MAX: ::c_int = 39; +pub const _SC_SIGRT_MIN: ::c_int = 40; +pub const _SC_SIGRT_MAX: ::c_int = 41; +pub const _SC_SYNCHRONIZED_IO: ::c_int = 42; +pub const _SC_TIMERS: ::c_int = 43; pub const _SC_TIMER_MAX: ::c_int = 44; +pub const _SC_2_C_BIND: ::c_int = 45; +pub const _SC_2_C_DEV: ::c_int = 46; +pub const _SC_2_C_VERSION: ::c_int = 47; +pub const _SC_2_FORT_DEV: ::c_int = 48; +pub const _SC_2_FORT_RUN: ::c_int = 49; +pub const _SC_2_LOCALEDEF: ::c_int = 50; +pub const _SC_2_SW_DEV: ::c_int = 51; +pub const _SC_2_UPE: ::c_int = 52; +pub const _SC_2_VERSION: ::c_int = 53; +pub const _SC_BC_BASE_MAX: ::c_int = 54; +pub const _SC_BC_DIM_MAX: ::c_int = 55; +pub const _SC_BC_SCALE_MAX: ::c_int = 56; +pub const _SC_BC_STRING_MAX: ::c_int = 57; +pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 58; +pub const _SC_EXPR_NEST_MAX: ::c_int = 59; +pub const _SC_LINE_MAX: ::c_int = 60; +pub const _SC_RE_DUP_MAX: ::c_int = 61; +pub const _SC_XOPEN_CRYPT: ::c_int = 62; +pub const _SC_XOPEN_ENH_I18N: ::c_int = 63; +pub const _SC_XOPEN_SHM: ::c_int = 64; +pub const _SC_2_CHAR_TERM: ::c_int = 66; +pub const _SC_XOPEN_XCU_VERSION: ::c_int = 67; +pub const _SC_ATEXIT_MAX: ::c_int = 76; +pub const _SC_IOV_MAX: ::c_int = 77; +pub const _SC_XOPEN_UNIX: ::c_int = 78; +pub const _SC_T_IOV_MAX: ::c_int = 79; +pub const _SC_PHYS_PAGES: ::c_int = 500; +pub const _SC_AVPHYS_PAGES: ::c_int = 501; +pub const _SC_COHER_BLKSZ: ::c_int = 503; +pub const _SC_SPLIT_CACHE: ::c_int = 504; +pub const _SC_ICACHE_SZ: ::c_int = 505; +pub const _SC_DCACHE_SZ: ::c_int = 506; +pub const _SC_ICACHE_LINESZ: ::c_int = 507; +pub const _SC_DCACHE_LINESZ: ::c_int = 508; +pub const _SC_ICACHE_BLKSZ: ::c_int = 509; +pub const _SC_DCACHE_BLKSZ: ::c_int = 510; +pub const _SC_DCACHE_TBLKSZ: ::c_int = 511; +pub const _SC_ICACHE_ASSOC: ::c_int = 512; +pub const _SC_DCACHE_ASSOC: ::c_int = 513; +pub const _SC_MAXPID: ::c_int = 514; +pub const _SC_STACK_PROT: ::c_int = 515; +pub const _SC_NPROCESSORS_MAX: ::c_int = 516; +pub const _SC_CPUID_MAX: ::c_int = 517; +pub const _SC_EPHID_MAX: ::c_int = 518; +pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 568; +pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 569; +pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 570; +pub const _SC_LOGIN_NAME_MAX: ::c_int = 571; +pub const _SC_THREAD_KEYS_MAX: ::c_int = 572; +pub const _SC_THREAD_STACK_MIN: ::c_int = 573; +pub const _SC_THREAD_THREADS_MAX: ::c_int = 574; +pub const _SC_TTY_NAME_MAX: ::c_int = 575; +pub const _SC_THREADS: ::c_int = 576; +pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 577; +pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 578; +pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 579; +pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 580; +pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 581; +pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 582; +pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 583; +pub const _SC_XOPEN_LEGACY: ::c_int = 717; +pub const _SC_XOPEN_REALTIME: ::c_int = 718; +pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 719; +pub const _SC_XBS5_ILP32_OFF32: ::c_int = 720; +pub const _SC_XBS5_ILP32_OFFBIG: ::c_int = 721; +pub const _SC_XBS5_LP64_OFF64: ::c_int = 722; +pub const _SC_XBS5_LPBIG_OFFBIG: ::c_int = 723; +pub const _SC_2_PBS: ::c_int = 724; +pub const _SC_2_PBS_ACCOUNTING: ::c_int = 725; +pub const _SC_2_PBS_CHECKPOINT: ::c_int = 726; +pub const _SC_2_PBS_LOCATE: ::c_int = 728; +pub const _SC_2_PBS_MESSAGE: ::c_int = 729; +pub const _SC_2_PBS_TRACK: ::c_int = 730; +pub const _SC_ADVISORY_INFO: ::c_int = 731; +pub const _SC_BARRIERS: ::c_int = 732; +pub const _SC_CLOCK_SELECTION: ::c_int = 733; +pub const _SC_CPUTIME: ::c_int = 734; +pub const _SC_HOST_NAME_MAX: ::c_int = 735; +pub const _SC_MONOTONIC_CLOCK: ::c_int = 736; +pub const _SC_READER_WRITER_LOCKS: ::c_int = 737; +pub const _SC_REGEXP: ::c_int = 738; +pub const _SC_SHELL: ::c_int = 739; +pub const _SC_SPAWN: ::c_int = 740; +pub const _SC_SPIN_LOCKS: ::c_int = 741; +pub const _SC_SPORADIC_SERVER: ::c_int = 742; +pub const _SC_SS_REPL_MAX: ::c_int = 743; +pub const _SC_SYMLOOP_MAX: ::c_int = 744; +pub const _SC_THREAD_CPUTIME: ::c_int = 745; +pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 746; +pub const _SC_TIMEOUTS: ::c_int = 747; +pub const _SC_TRACE: ::c_int = 748; +pub const _SC_TRACE_EVENT_FILTER: ::c_int = 749; +pub const _SC_TRACE_EVENT_NAME_MAX: ::c_int = 750; +pub const _SC_TRACE_INHERIT: ::c_int = 751; +pub const _SC_TRACE_LOG: ::c_int = 752; +pub const _SC_TRACE_NAME_MAX: ::c_int = 753; +pub const _SC_TRACE_SYS_MAX: ::c_int = 754; +pub const _SC_TRACE_USER_EVENT_MAX: ::c_int = 755; +pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 756; +pub const _SC_V6_ILP32_OFF32: ::c_int = 757; +pub const _SC_V6_ILP32_OFFBIG: ::c_int = 758; +pub const _SC_V6_LP64_OFF64: ::c_int = 759; +pub const _SC_V6_LPBIG_OFFBIG: ::c_int = 760; +pub const _SC_XOPEN_STREAMS: ::c_int = 761; +pub const _SC_IPV6: ::c_int = 762; +pub const _SC_RAW_SOCKETS: ::c_int = 763; pub const _MUTEX_MAGIC: u16 = 0x4d58; // MX pub const _COND_MAGIC: u16 = 0x4356; // CV diff --git a/src/vendor/libc/src/unix/uclibc/mips/mips32.rs b/src/vendor/libc/src/unix/uclibc/mips/mips32.rs new file mode 100644 index 0000000000..a81e884e0b --- /dev/null +++ b/src/vendor/libc/src/unix/uclibc/mips/mips32.rs @@ -0,0 +1,269 @@ +pub type c_char = i8; +pub type c_long = i32; +pub type c_ulong = u32; +pub type clock_t = i32; +pub type time_t = i32; +pub type suseconds_t = i32; +pub type wchar_t = i32; +pub type off_t = i32; +pub type ino_t = u32; +pub type blkcnt_t = i32; +pub type blksize_t = i32; +pub type nlink_t = u32; +pub type fsblkcnt_t = ::c_ulong; +pub type fsfilcnt_t = ::c_ulong; +pub type rlim_t = c_ulong; + +s! { + pub struct stat { + pub st_dev: ::dev_t, + st_pad1: [::c_long; 2], + pub st_ino: ::ino_t, + pub st_mode: ::mode_t, + pub st_nlink: ::nlink_t, + pub st_uid: ::uid_t, + pub st_gid: ::gid_t, + pub st_rdev: ::dev_t, + pub st_pad2: [::c_long; 1], + pub st_size: ::off_t, + st_pad3: ::c_long, + pub st_atime: ::time_t, + pub st_atime_nsec: ::c_long, + pub st_mtime: ::time_t, + pub st_mtime_nsec: ::c_long, + pub st_ctime: ::time_t, + pub st_ctime_nsec: ::c_long, + pub st_blksize: ::blksize_t, + pub st_blocks: ::blkcnt_t, + st_pad5: [::c_long; 14], + } + + pub struct stat64 { + pub st_dev: ::dev_t, + st_pad1: [::c_long; 2], + 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, + st_pad2: [::c_long; 2], + pub st_size: ::off64_t, + pub st_atime: ::time_t, + pub st_atime_nsec: ::c_long, + pub st_mtime: ::time_t, + pub st_mtime_nsec: ::c_long, + pub st_ctime: ::time_t, + pub st_ctime_nsec: ::c_long, + pub st_blksize: ::blksize_t, + st_pad3: ::c_long, + pub st_blocks: ::blkcnt64_t, + st_pad5: [::c_long; 14], + } + + pub struct pthread_attr_t { + __size: [u32; 9] + } + + pub struct sigaction { + pub sa_flags: ::c_uint, + pub sa_sigaction: ::sighandler_t, + pub sa_mask: sigset_t, + _restorer: *mut ::c_void, + } + + pub struct stack_t { + pub ss_sp: *mut ::c_void, + pub ss_size: ::size_t, + pub ss_flags: ::c_int, + } + + pub struct sigset_t { + __val: [::c_ulong; 4], + } + + pub struct siginfo_t { + pub si_signo: ::c_int, + pub si_code: ::c_int, + pub si_errno: ::c_int, + pub _pad: [::c_int; 29], + } + + pub struct glob64_t { + pub gl_pathc: ::size_t, + pub gl_pathv: *mut *mut ::c_char, + pub gl_offs: ::size_t, + pub gl_flags: ::c_int, + + __unused1: *mut ::c_void, + __unused2: *mut ::c_void, + __unused3: *mut ::c_void, + __unused4: *mut ::c_void, + __unused5: *mut ::c_void, + } + + 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: ::c_uint, + pub __seq: ::c_ushort, + __pad1: ::c_ushort, + __unused1: ::c_ulong, + __unused2: ::c_ulong + } + + pub struct shmid_ds { + pub shm_perm: ::ipc_perm, + pub shm_segsz: ::size_t, + pub shm_atime: ::time_t, + pub shm_dtime: ::time_t, + pub shm_ctime: ::time_t, + pub shm_cpid: ::pid_t, + pub shm_lpid: ::pid_t, + pub shm_nattch: ::shmatt_t, + __unused4: ::c_ulong, + __unused5: ::c_ulong + } + + pub struct msqid_ds { + pub msg_perm: ::ipc_perm, + #[cfg(target_endian = "big")] + __glibc_reserved1: ::c_ulong, + pub msg_stime: ::time_t, + #[cfg(target_endian = "little")] + __glibc_reserved1: ::c_ulong, + #[cfg(target_endian = "big")] + __glibc_reserved2: ::c_ulong, + pub msg_rtime: ::time_t, + #[cfg(target_endian = "little")] + __glibc_reserved2: ::c_ulong, + #[cfg(target_endian = "big")] + __glibc_reserved3: ::c_ulong, + pub msg_ctime: ::time_t, + #[cfg(target_endian = "little")] + __glibc_reserved3: ::c_ulong, + __msg_cbytes: ::c_ulong, + pub msg_qnum: ::msgqnum_t, + pub msg_qbytes: ::msglen_t, + pub msg_lspid: ::pid_t, + pub msg_lrpid: ::pid_t, + __glibc_reserved4: ::c_ulong, + __glibc_reserved5: ::c_ulong, + } + + pub struct statfs { + pub f_type: ::c_long, + pub f_bsize: ::c_long, + pub f_frsize: ::c_long, + pub f_blocks: ::fsblkcnt_t, + pub f_bfree: ::fsblkcnt_t, + pub f_files: ::fsblkcnt_t, + pub f_ffree: ::fsblkcnt_t, + pub f_bavail: ::fsblkcnt_t, + pub f_fsid: ::fsid_t, + + pub f_namelen: ::c_long, + f_spare: [::c_long; 6], + } + + pub struct msghdr { + pub msg_name: *mut ::c_void, + pub msg_namelen: ::socklen_t, + pub msg_iov: *mut ::iovec, + pub msg_iovlen: ::c_int, + pub msg_control: *mut ::c_void, + pub msg_controllen: ::size_t, + 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, + pub c_cflag: ::tcflag_t, + pub c_lflag: ::tcflag_t, + pub c_line: ::cc_t, + pub c_cc: [::cc_t; ::NCCS], + } + + pub struct flock { + pub l_type: ::c_short, + pub l_whence: ::c_short, + pub l_start: ::off_t, + pub l_len: ::off_t, + pub l_sysid: ::c_long, + pub l_pid: ::pid_t, + pad: [::c_long; 4], + } + + pub struct sysinfo { + pub uptime: ::c_long, + pub loads: [::c_ulong; 3], + pub totalram: ::c_ulong, + pub freeram: ::c_ulong, + pub sharedram: ::c_ulong, + pub bufferram: ::c_ulong, + pub totalswap: ::c_ulong, + pub freeswap: ::c_ulong, + pub procs: ::c_ushort, + pub pad: ::c_ushort, + pub totalhigh: ::c_ulong, + pub freehigh: ::c_ulong, + pub mem_unit: ::c_uint, + pub _f: [::c_char; 8], + } + + // FIXME this is actually a union + pub struct sem_t { + #[cfg(target_pointer_width = "32")] + __size: [::c_char; 16], + #[cfg(target_pointer_width = "64")] + __size: [::c_char; 32], + __align: [::c_long; 0], + } +} + +pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; +pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 24; +pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32; +pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; + +pub const RLIM_INFINITY: ::rlim_t = 0x7fffffff; + +pub const SYS_gettid: ::c_long = 4222; // Valid for O32 + +#[link(name = "util")] +extern { + pub fn sysctl(name: *mut ::c_int, + namelen: ::c_int, + oldp: *mut ::c_void, + oldlenp: *mut ::size_t, + newp: *mut ::c_void, + newlen: ::size_t) + -> ::c_int; + pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int; + pub fn backtrace(buf: *mut *mut ::c_void, + sz: ::c_int) -> ::c_int; + pub fn glob64(pattern: *const ::c_char, + flags: ::c_int, + errfunc: ::dox::Option ::c_int>, + pglob: *mut glob64_t) -> ::c_int; + pub fn globfree64(pglob: *mut glob64_t); + pub fn ptrace(request: ::c_uint, ...) -> ::c_long; + pub fn pthread_attr_getaffinity_np(attr: *const ::pthread_attr_t, + cpusetsize: ::size_t, + cpuset: *mut ::cpu_set_t) -> ::c_int; + pub fn pthread_attr_setaffinity_np(attr: *mut ::pthread_attr_t, + cpusetsize: ::size_t, + cpuset: *const ::cpu_set_t) -> ::c_int; +} diff --git a/src/vendor/libc/src/unix/uclibc/mips/mips64.rs b/src/vendor/libc/src/unix/uclibc/mips/mips64.rs new file mode 100644 index 0000000000..79bac1fa8a --- /dev/null +++ b/src/vendor/libc/src/unix/uclibc/mips/mips64.rs @@ -0,0 +1,209 @@ +pub type blkcnt_t = i64; +pub type blksize_t = i64; +pub type c_char = i8; +pub type c_long = i64; +pub type c_ulong = u64; +pub type fsblkcnt_t = ::c_ulong; +pub type fsfilcnt_t = ::c_ulong; +pub type ino_t = u64; +pub type nlink_t = u64; +pub type off_t = i64; +pub type rlim_t = ::c_ulong; +pub type suseconds_t = i64; +pub type time_t = i64; +pub type wchar_t = i32; + +s! { + pub struct stat { + pub st_dev: ::c_ulong, + st_pad1: [::c_long; 2], + 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: ::c_ulong, + st_pad2: [::c_ulong; 1], + pub st_size: ::off_t, + st_pad3: ::c_long, + pub st_atime: ::time_t, + pub st_atime_nsec: ::c_long, + pub st_mtime: ::time_t, + pub st_mtime_nsec: ::c_long, + pub st_ctime: ::time_t, + pub st_ctime_nsec: ::c_long, + pub st_blksize: ::blksize_t, + st_pad4: ::c_long, + pub st_blocks: ::blkcnt_t, + st_pad5: [::c_long; 7], + } + + pub struct stat64 { + pub st_dev: ::c_ulong, + st_pad1: [::c_long; 2], + 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: ::c_ulong, + st_pad2: [::c_long; 2], + pub st_size: ::off64_t, + pub st_atime: ::time_t, + pub st_atime_nsec: ::c_long, + pub st_mtime: ::time_t, + pub st_mtime_nsec: ::c_long, + pub st_ctime: ::time_t, + pub st_ctime_nsec: ::c_long, + pub st_blksize: ::blksize_t, + st_pad3: ::c_long, + pub st_blocks: ::blkcnt64_t, + st_pad5: [::c_long; 7], + } + + pub struct pthread_attr_t { + __size: [::c_ulong; 7] + } + + pub struct sigaction { + pub sa_flags: ::c_int, + pub sa_sigaction: ::sighandler_t, + pub sa_mask: sigset_t, + _restorer: *mut ::c_void, + } + + pub struct stack_t { + pub ss_sp: *mut ::c_void, + pub ss_size: ::size_t, + pub ss_flags: ::c_int, + } + + pub struct sigset_t { + __size: [::c_ulong; 16], + } + + pub struct siginfo_t { + pub si_signo: ::c_int, + pub si_code: ::c_int, + pub si_errno: ::c_int, + _pad: ::c_int, + _pad2: [::c_long; 14], + } + + 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: ::c_uint, + pub __seq: ::c_ushort, + __pad1: ::c_ushort, + __unused1: ::c_ulong, + __unused2: ::c_ulong + } + + pub struct shmid_ds { + pub shm_perm: ::ipc_perm, + pub shm_segsz: ::size_t, + pub shm_atime: ::time_t, + pub shm_dtime: ::time_t, + pub shm_ctime: ::time_t, + pub shm_cpid: ::pid_t, + pub shm_lpid: ::pid_t, + pub shm_nattch: ::shmatt_t, + __unused4: ::c_ulong, + __unused5: ::c_ulong + } + + pub struct msqid_ds { + pub msg_perm: ::ipc_perm, + pub msg_stime: ::time_t, + pub msg_rtime: ::time_t, + pub msg_ctime: ::time_t, + __msg_cbytes: ::c_ulong, + pub msg_qnum: ::msgqnum_t, + pub msg_qbytes: ::msglen_t, + pub msg_lspid: ::pid_t, + pub msg_lrpid: ::pid_t, + __glibc_reserved4: ::c_ulong, + __glibc_reserved5: ::c_ulong, + } + + pub struct statfs { + pub f_type: ::c_long, + pub f_bsize: ::c_long, + pub f_frsize: ::c_long, + pub f_blocks: ::fsblkcnt_t, + pub f_bfree: ::fsblkcnt_t, + pub f_files: ::fsblkcnt_t, + pub f_ffree: ::fsblkcnt_t, + pub f_bavail: ::fsblkcnt_t, + pub f_fsid: ::fsid_t, + + pub f_namelen: ::c_long, + f_spare: [::c_long; 6], + } + + pub struct msghdr { + pub msg_name: *mut ::c_void, + pub msg_namelen: ::socklen_t, + pub msg_iov: *mut ::iovec, + pub msg_iovlen: ::size_t, + pub msg_control: *mut ::c_void, + pub msg_controllen: ::size_t, + 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, + pub c_cflag: ::tcflag_t, + pub c_lflag: ::tcflag_t, + pub c_line: ::cc_t, + pub c_cc: [::cc_t; ::NCCS], + } + + pub struct sysinfo { + pub uptime: ::c_long, + pub loads: [::c_ulong; 3], + pub totalram: ::c_ulong, + pub freeram: ::c_ulong, + pub sharedram: ::c_ulong, + pub bufferram: ::c_ulong, + pub totalswap: ::c_ulong, + pub freeswap: ::c_ulong, + pub procs: ::c_ushort, + pub pad: ::c_ushort, + pub totalhigh: ::c_ulong, + pub freehigh: ::c_ulong, + pub mem_unit: ::c_uint, + pub _f: [::c_char; 0], + } + + // FIXME this is actually a union + pub struct sem_t { + __size: [::c_char; 32], + __align: [::c_long; 0], + } +} + +pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; +pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; +pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; +pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; + +pub const RLIM_INFINITY: ::rlim_t = 0xffff_ffff_ffff_ffff; + +pub const SYS_gettid: ::c_long = 5178; // Valid for n64 + +#[link(name = "util")] +extern { + pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int; +} diff --git a/src/vendor/libc/src/unix/uclibc/mips/mod.rs b/src/vendor/libc/src/unix/uclibc/mips/mod.rs new file mode 100644 index 0000000000..cc3ddf254d --- /dev/null +++ b/src/vendor/libc/src/unix/uclibc/mips/mod.rs @@ -0,0 +1,476 @@ +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 = 4096; +pub const TMP_MAX: ::c_uint = 238328; +pub const FOPEN_MAX: ::c_uint = 16; +pub const POSIX_FADV_DONTNEED: ::c_int = 4; +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_DIRECT: ::c_int = 0x8000; +pub const O_DIRECTORY: ::c_int = 0x10000; +pub const O_NOFOLLOW: ::c_int = 0x20000; +pub const ST_RELATIME: ::c_ulong = 4096; +pub const NI_MAXHOST: ::socklen_t = 1025; + +pub const RLIMIT_NOFILE: ::c_int = 5; +pub const RLIMIT_AS: ::c_int = 6; +pub const RLIMIT_RSS: ::c_int = 7; +pub const RLIMIT_NPROC: ::c_int = 8; +pub const RLIMIT_MEMLOCK: ::c_int = 9; +pub const RLIMIT_NLIMITS: ::c_int = 15; + +pub const O_APPEND: ::c_int = 8; +pub const O_CREAT: ::c_int = 256; +pub const O_EXCL: ::c_int = 1024; +pub const O_NOCTTY: ::c_int = 2048; +pub const O_NONBLOCK: ::c_int = 128; +pub const O_SYNC: ::c_int = 0x10; +pub const O_RSYNC: ::c_int = 0x10; +pub const O_DSYNC: ::c_int = 0x10; +pub const O_FSYNC: ::c_int = 0x10; +pub const O_ASYNC: ::c_int = 0x1000; +pub const O_NDELAY: ::c_int = 0x80; + +pub const SOCK_NONBLOCK: ::c_int = 128; + +pub const EDEADLK: ::c_int = 45; +pub const ENAMETOOLONG: ::c_int = 78; +pub const ENOLCK: ::c_int = 46; +pub const ENOSYS: ::c_int = 89; +pub const ENOTEMPTY: ::c_int = 93; +pub const ELOOP: ::c_int = 90; +pub const ENOMSG: ::c_int = 35; +pub const EIDRM: ::c_int = 36; +pub const ECHRNG: ::c_int = 37; +pub const EL2NSYNC: ::c_int = 38; +pub const EL3HLT: ::c_int = 39; +pub const EL3RST: ::c_int = 40; +pub const ELNRNG: ::c_int = 41; +pub const EUNATCH: ::c_int = 42; +pub const ENOCSI: ::c_int = 43; +pub const EL2HLT: ::c_int = 44; +pub const EBADE: ::c_int = 50; +pub const EBADR: ::c_int = 51; +pub const EXFULL: ::c_int = 52; +pub const ENOANO: ::c_int = 53; +pub const EBADRQC: ::c_int = 54; +pub const EBADSLT: ::c_int = 55; +pub const EDEADLOCK: ::c_int = 56; +pub const EMULTIHOP: ::c_int = 74; +pub const EOVERFLOW: ::c_int = 79; +pub const ENOTUNIQ: ::c_int = 80; +pub const EBADFD: ::c_int = 81; +pub const EBADMSG: ::c_int = 77; +pub const EREMCHG: ::c_int = 82; +pub const ELIBACC: ::c_int = 83; +pub const ELIBBAD: ::c_int = 84; +pub const ELIBSCN: ::c_int = 85; +pub const ELIBMAX: ::c_int = 86; +pub const ELIBEXEC: ::c_int = 87; +pub const EILSEQ: ::c_int = 88; +pub const ERESTART: ::c_int = 91; +pub const ESTRPIPE: ::c_int = 92; +pub const EUSERS: ::c_int = 94; +pub const ENOTSOCK: ::c_int = 95; +pub const EDESTADDRREQ: ::c_int = 96; +pub const EMSGSIZE: ::c_int = 97; +pub const EPROTOTYPE: ::c_int = 98; +pub const ENOPROTOOPT: ::c_int = 99; +pub const EPROTONOSUPPORT: ::c_int = 120; +pub const ESOCKTNOSUPPORT: ::c_int = 121; +pub const EOPNOTSUPP: ::c_int = 122; +pub const ENOTSUP: ::c_int = EOPNOTSUPP; +pub const EPFNOSUPPORT: ::c_int = 123; +pub const EAFNOSUPPORT: ::c_int = 124; +pub const EADDRINUSE: ::c_int = 125; +pub const EADDRNOTAVAIL: ::c_int = 126; +pub const ENETDOWN: ::c_int = 127; +pub const ENETUNREACH: ::c_int = 128; +pub const ENETRESET: ::c_int = 129; +pub const ECONNABORTED: ::c_int = 130; +pub const ECONNRESET: ::c_int = 131; +pub const ENOBUFS: ::c_int = 132; +pub const EISCONN: ::c_int = 133; +pub const ENOTCONN: ::c_int = 134; +pub const ESHUTDOWN: ::c_int = 143; +pub const ETOOMANYREFS: ::c_int = 144; +pub const ETIMEDOUT: ::c_int = 145; +pub const ECONNREFUSED: ::c_int = 146; +pub const EHOSTDOWN: ::c_int = 147; +pub const EHOSTUNREACH: ::c_int = 148; +pub const EALREADY: ::c_int = 149; +pub const EINPROGRESS: ::c_int = 150; +pub const ESTALE: ::c_int = 151; +pub const EUCLEAN: ::c_int = 135; +pub const ENOTNAM: ::c_int = 137; +pub const ENAVAIL: ::c_int = 138; +pub const EISNAM: ::c_int = 139; +pub const EREMOTEIO: ::c_int = 140; +pub const EDQUOT: ::c_int = 1133; +pub const ENOMEDIUM: ::c_int = 159; +pub const EMEDIUMTYPE: ::c_int = 160; +pub const ECANCELED: ::c_int = 158; +pub const ENOKEY: ::c_int = 161; +pub const EKEYEXPIRED: ::c_int = 162; +pub const EKEYREVOKED: ::c_int = 163; +pub const EKEYREJECTED: ::c_int = 164; +pub const EOWNERDEAD: ::c_int = 165; +pub const ENOTRECOVERABLE: ::c_int = 166; +pub const ERFKILL: ::c_int = 167; + +pub const MAP_NORESERVE: ::c_int = 0x400; +pub const MAP_ANON: ::c_int = 0x800; +pub const MAP_ANONYMOUS: ::c_int = 0x800; +pub const MAP_GROWSDOWN: ::c_int = 0x1000; +pub const MAP_DENYWRITE: ::c_int = 0x2000; +pub const MAP_EXECUTABLE: ::c_int = 0x4000; +pub const MAP_LOCKED: ::c_int = 0x8000; +pub const MAP_POPULATE: ::c_int = 0x10000; +pub const MAP_NONBLOCK: ::c_int = 0x20000; +pub const MAP_STACK: ::c_int = 0x40000; + +pub const SOCK_STREAM: ::c_int = 2; +pub const SOCK_DGRAM: ::c_int = 1; +pub const SOCK_SEQPACKET: ::c_int = 5; + +pub const SOL_SOCKET: ::c_int = 0xffff; + +pub const SO_REUSEADDR: ::c_int = 0x0004; +pub const SO_KEEPALIVE: ::c_int = 0x0008; +pub const SO_DONTROUTE: ::c_int = 0x0010; +pub const SO_BROADCAST: ::c_int = 0x0020; +pub const SO_LINGER: ::c_int = 0x0080; +pub const SO_OOBINLINE: ::c_int = 0x0100; +pub const SO_REUSEPORT: ::c_int = 0x0200; +pub const SO_TYPE: ::c_int = 0x1008; +pub const SO_STYLE: ::c_int = SO_TYPE; +pub const SO_ERROR: ::c_int = 0x1007; +pub const SO_SNDBUF: ::c_int = 0x1001; +pub const SO_RCVBUF: ::c_int = 0x1002; +pub const SO_SNDLOWAT: ::c_int = 0x1003; +pub const SO_RCVLOWAT: ::c_int = 0x1004; +pub const SO_SNDTIMEO: ::c_int = 0x1005; +pub const SO_RCVTIMEO: ::c_int = 0x1006; +pub const SO_ACCEPTCONN: ::c_int = 0x1009; +pub const SO_PROTOCOL: ::c_int = 0x1028; +pub const SO_DOMAIN: ::c_int = 0x1029; +pub const SO_NO_CHECK: ::c_int = 11; +pub const SO_PRIORITY: ::c_int = 12; +pub const SO_BSDCOMPAT: ::c_int = 14; +pub const SO_PASSCRED: ::c_int = 17; +pub const SO_PEERCRED: ::c_int = 18; +pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22; +pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23; +pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24; +pub const SO_BINDTODEVICE: ::c_int = 25; +pub const SO_ATTACH_FILTER: ::c_int = 26; +pub const SO_DETACH_FILTER: ::c_int = 27; +pub const SO_GET_FILTER: ::c_int = SO_ATTACH_FILTER; +pub const SO_PEERNAME: ::c_int = 28; +pub const SO_TIMESTAMP: ::c_int = 29; +pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP; +pub const SO_PEERSEC: ::c_int = 30; +pub const SO_SNDBUFFORCE: ::c_int = 31; +pub const SO_RCVBUFFORCE: ::c_int = 33; +pub const SO_PASSSEC: ::c_int = 34; +pub const SO_TIMESTAMPNS: ::c_int = 35; +pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS; +pub const SO_MARK: ::c_int = 36; +pub const SO_TIMESTAMPING: ::c_int = 37; +pub const SCM_TIMESTAMPING: ::c_int = SO_TIMESTAMPING; +pub const SO_RXQ_OVFL: ::c_int = 40; +pub const SO_WIFI_STATUS: ::c_int = 41; +pub const SCM_WIFI_STATUS: ::c_int = SO_WIFI_STATUS; +pub const SO_PEEK_OFF: ::c_int = 42; +pub const SO_NOFCS: ::c_int = 43; +pub const SO_LOCK_FILTER: ::c_int = 44; +pub const SO_SELECT_ERR_QUEUE: ::c_int = 45; +pub const SO_BUSY_POLL: ::c_int = 46; +pub const SO_MAX_PACING_RATE: ::c_int = 47; +pub const SO_BPF_EXTENSIONS: ::c_int = 48; + +pub const FIOCLEX: ::c_ulong = 0x6601; +pub const FIONBIO: ::c_ulong = 0x667e; + +pub const SA_ONSTACK: ::c_int = 0x08000000; +pub const SA_SIGINFO: ::c_int = 0x00000008; +pub const SA_NOCLDWAIT: ::c_int = 0x00010000; + +pub const SIGCHLD: ::c_int = 18; +pub const SIGBUS: ::c_int = 10; +pub const SIGTTIN: ::c_int = 26; +pub const SIGTTOU: ::c_int = 27; +pub const SIGXCPU: ::c_int = 30; +pub const SIGXFSZ: ::c_int = 31; +pub const SIGVTALRM: ::c_int = 28; +pub const SIGPROF: ::c_int = 29; +pub const SIGWINCH: ::c_int = 20; +pub const SIGUSR1: ::c_int = 16; +pub const SIGUSR2: ::c_int = 17; +pub const SIGCONT: ::c_int = 25; +pub const SIGSTOP: ::c_int = 23; +pub const SIGTSTP: ::c_int = 24; +pub const SIGURG: ::c_int = 21; +pub const SIGIO: ::c_int = 22; +pub const SIGSYS: ::c_int = 12; +pub const SIGPOLL: ::c_int = 22; +pub const SIGPWR: ::c_int = 19; +pub const SIG_SETMASK: ::c_int = 3; +pub const SIG_BLOCK: ::c_int = 0x1; +pub const SIG_UNBLOCK: ::c_int = 0x2; + +pub const POLLRDNORM: ::c_short = 0x040; +pub const POLLWRNORM: ::c_short = 0x004; +pub const POLLRDBAND: ::c_short = 0x080; +pub const POLLWRBAND: ::c_short = 0x100; + +pub const PTHREAD_STACK_MIN: ::size_t = 16384; + +pub const ADFS_SUPER_MAGIC: ::c_long = 0x0000adf5; +pub const AFFS_SUPER_MAGIC: ::c_long = 0x0000adff; +pub const CODA_SUPER_MAGIC: ::c_long = 0x73757245; +pub const CRAMFS_MAGIC: ::c_long = 0x28cd3d45; +pub const EFS_SUPER_MAGIC: ::c_long = 0x00414a53; +pub const EXT2_SUPER_MAGIC: ::c_long = 0x0000ef53; +pub const EXT3_SUPER_MAGIC: ::c_long = 0x0000ef53; +pub const EXT4_SUPER_MAGIC: ::c_long = 0x0000ef53; +pub const HPFS_SUPER_MAGIC: ::c_long = 0xf995e849; +pub const HUGETLBFS_MAGIC: ::c_long = 0x958458f6; +pub const ISOFS_SUPER_MAGIC: ::c_long = 0x00009660; +pub const JFFS2_SUPER_MAGIC: ::c_long = 0x000072b6; +pub const MINIX_SUPER_MAGIC: ::c_long = 0x0000137f; +pub const MINIX_SUPER_MAGIC2: ::c_long = 0x0000138f; +pub const MINIX2_SUPER_MAGIC: ::c_long = 0x00002468; +pub const MINIX2_SUPER_MAGIC2: ::c_long = 0x00002478; +pub const MSDOS_SUPER_MAGIC: ::c_long = 0x00004d44; +pub const NCP_SUPER_MAGIC: ::c_long = 0x0000564c; +pub const NFS_SUPER_MAGIC: ::c_long = 0x00006969; +pub const OPENPROM_SUPER_MAGIC: ::c_long = 0x00009fa1; +pub const PROC_SUPER_MAGIC: ::c_long = 0x00009fa0; +pub const QNX4_SUPER_MAGIC: ::c_long = 0x0000002f; +pub const REISERFS_SUPER_MAGIC: ::c_long = 0x52654973; +pub const SMB_SUPER_MAGIC: ::c_long = 0x0000517b; +pub const TMPFS_MAGIC: ::c_long = 0x01021994; +pub const USBDEVICE_SUPER_MAGIC: ::c_long = 0x00009fa2; + +pub const VEOF: usize = 16; +pub const VEOL: usize = 17; +pub const VEOL2: usize = 6; +pub const VMIN: usize = 4; +pub const IEXTEN: ::tcflag_t = 0x00000100; +pub const TOSTOP: ::tcflag_t = 0x00008000; +pub const FLUSHO: ::tcflag_t = 0x00002000; +pub const IUTF8: ::tcflag_t = 0x00004000; +pub const TCSANOW: ::c_int = 0x540e; +pub const TCSADRAIN: ::c_int = 0x540f; +pub const TCSAFLUSH: ::c_int = 0x5410; + +pub const CPU_SETSIZE: ::c_int = 0x400; + +pub const PTRACE_TRACEME: ::c_uint = 0; +pub const PTRACE_PEEKTEXT: ::c_uint = 1; +pub const PTRACE_PEEKDATA: ::c_uint = 2; +pub const PTRACE_PEEKUSER: ::c_uint = 3; +pub const PTRACE_POKETEXT: ::c_uint = 4; +pub const PTRACE_POKEDATA: ::c_uint = 5; +pub const PTRACE_POKEUSER: ::c_uint = 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; +pub const PTRACE_GETSIGINFO: ::c_uint = 0x4202; +pub const PTRACE_SETSIGINFO: ::c_uint = 0x4203; +pub const PTRACE_GETFPREGS: ::c_uint = 14; +pub const PTRACE_SETFPREGS: ::c_uint = 15; +pub const PTRACE_GETFPXREGS: ::c_uint = 18; +pub const PTRACE_SETFPXREGS: ::c_uint = 19; +pub const PTRACE_GETREGS: ::c_uint = 12; +pub const PTRACE_SETREGS: ::c_uint = 13; + +pub const EFD_NONBLOCK: ::c_int = 0x80; + +pub const F_GETLK: ::c_int = 14; +pub const F_GETOWN: ::c_int = 23; +pub const F_SETOWN: ::c_int = 24; +pub const F_SETLK: ::c_int = 6; +pub const F_SETLKW: ::c_int = 7; + +pub const SFD_NONBLOCK: ::c_int = 0x80; + +pub const TCGETS: ::c_ulong = 0x540d; +pub const TCSETS: ::c_ulong = 0x540e; +pub const TCSETSW: ::c_ulong = 0x540f; +pub const TCSETSF: ::c_ulong = 0x5410; +pub const TCGETA: ::c_ulong = 0x5401; +pub const TCSETA: ::c_ulong = 0x5402; +pub const TCSETAW: ::c_ulong = 0x5403; +pub const TCSETAF: ::c_ulong = 0x5404; +pub const TCSBRK: ::c_ulong = 0x5405; +pub const TCXONC: ::c_ulong = 0x5406; +pub const TCFLSH: ::c_ulong = 0x5407; +pub const TIOCGSOFTCAR: ::c_ulong = 0x5481; +pub const TIOCSSOFTCAR: ::c_ulong = 0x5482; +pub const TIOCINQ: ::c_ulong = 0x467f; +pub const TIOCLINUX: ::c_ulong = 0x5483; +pub const TIOCGSERIAL: ::c_ulong = 0x5484; +pub const TIOCEXCL: ::c_ulong = 0x740d; +pub const TIOCNXCL: ::c_ulong = 0x740e; +pub const TIOCSCTTY: ::c_ulong = 0x5480; +pub const TIOCGPGRP: ::c_ulong = 0x40047477; +pub const TIOCSPGRP: ::c_ulong = 0x80047476; +pub const TIOCOUTQ: ::c_ulong = 0x7472; +pub const TIOCSTI: ::c_ulong = 0x5472; +pub const TIOCGWINSZ: ::c_ulong = 0x40087468; +pub const TIOCSWINSZ: ::c_ulong = 0x80087467; +pub const TIOCMGET: ::c_ulong = 0x741d; +pub const TIOCMBIS: ::c_ulong = 0x741b; +pub const TIOCMBIC: ::c_ulong = 0x741c; +pub const TIOCMSET: ::c_ulong = 0x741a; +pub const FIONREAD: ::c_ulong = 0x467f; +pub const TIOCCONS: ::c_ulong = 0x80047478; + +pub const RTLD_DEEPBIND: ::c_int = 0x10; +pub const RTLD_GLOBAL: ::c_int = 0x4; +pub const RTLD_NOLOAD: ::c_int = 0x8; + +pub const LINUX_REBOOT_MAGIC1: ::c_int = 0xfee1dead; +pub const LINUX_REBOOT_MAGIC2: ::c_int = 672274793; +pub const LINUX_REBOOT_MAGIC2A: ::c_int = 85072278; +pub const LINUX_REBOOT_MAGIC2B: ::c_int = 369367448; +pub const LINUX_REBOOT_MAGIC2C: ::c_int = 537993216; + +pub const LINUX_REBOOT_CMD_RESTART: ::c_int = 0x01234567; +pub const LINUX_REBOOT_CMD_HALT: ::c_int = 0xCDEF0123; +pub const LINUX_REBOOT_CMD_CAD_ON: ::c_int = 0x89ABCDEF; +pub const LINUX_REBOOT_CMD_CAD_OFF: ::c_int = 0x00000000; +pub const LINUX_REBOOT_CMD_POWER_OFF: ::c_int = 0x4321FEDC; +pub const LINUX_REBOOT_CMD_RESTART2: ::c_int = 0xA1B2C3D4; +pub const LINUX_REBOOT_CMD_SW_SUSPEND: ::c_int = 0xD000FCE2; +pub const LINUX_REBOOT_CMD_KEXEC: ::c_int = 0x45584543; + +pub const MCL_CURRENT: ::c_int = 0x0001; +pub const MCL_FUTURE: ::c_int = 0x0002; + +pub const SIGSTKSZ: ::size_t = 8192; +pub const CBAUD: ::tcflag_t = 0o0010017; +pub const TAB1: ::c_int = 0x00000800; +pub const TAB2: ::c_int = 0x00001000; +pub const TAB3: ::c_int = 0x00001800; +pub const CR1: ::c_int = 0x00000200; +pub const CR2: ::c_int = 0x00000400; +pub const CR3: ::c_int = 0x00000600; +pub const FF1: ::c_int = 0x00008000; +pub const BS1: ::c_int = 0x00002000; +pub const VT1: ::c_int = 0x00004000; +pub const VWERASE: usize = 14; +pub const VREPRINT: usize = 12; +pub const VSUSP: usize = 10; +pub const VSTART: usize = 8; +pub const VSTOP: usize = 9; +pub const VDISCARD: usize = 13; +pub const VTIME: usize = 5; +pub const IXON: ::tcflag_t = 0x00000400; +pub const IXOFF: ::tcflag_t = 0x00001000; +pub const ONLCR: ::tcflag_t = 0x4; +pub const CSIZE: ::tcflag_t = 0x00000030; +pub const CS6: ::tcflag_t = 0x00000010; +pub const CS7: ::tcflag_t = 0x00000020; +pub const CS8: ::tcflag_t = 0x00000030; +pub const CSTOPB: ::tcflag_t = 0x00000040; +pub const CREAD: ::tcflag_t = 0x00000080; +pub const PARENB: ::tcflag_t = 0x00000100; +pub const PARODD: ::tcflag_t = 0x00000200; +pub const HUPCL: ::tcflag_t = 0x00000400; +pub const CLOCAL: ::tcflag_t = 0x00000800; +pub const ECHOKE: ::tcflag_t = 0x00000800; +pub const ECHOE: ::tcflag_t = 0x00000010; +pub const ECHOK: ::tcflag_t = 0x00000020; +pub const ECHONL: ::tcflag_t = 0x00000040; +pub const ECHOPRT: ::tcflag_t = 0x00000400; +pub const ECHOCTL: ::tcflag_t = 0x00000200; +pub const ISIG: ::tcflag_t = 0x00000001; +pub const ICANON: ::tcflag_t = 0x00000002; +pub const PENDIN: ::tcflag_t = 0x00004000; +pub const NOFLSH: ::tcflag_t = 0x00000080; + +pub const B0: ::speed_t = 0o000000; +pub const B50: ::speed_t = 0o000001; +pub const B75: ::speed_t = 0o000002; +pub const B110: ::speed_t = 0o000003; +pub const B134: ::speed_t = 0o000004; +pub const B150: ::speed_t = 0o000005; +pub const B200: ::speed_t = 0o000006; +pub const B300: ::speed_t = 0o000007; +pub const B600: ::speed_t = 0o000010; +pub const B1200: ::speed_t = 0o000011; +pub const B1800: ::speed_t = 0o000012; +pub const B2400: ::speed_t = 0o000013; +pub const B4800: ::speed_t = 0o000014; +pub const B9600: ::speed_t = 0o000015; +pub const B19200: ::speed_t = 0o000016; +pub const B38400: ::speed_t = 0o000017; +pub const EXTA: ::speed_t = B19200; +pub const EXTB: ::speed_t = B38400; +pub const B57600: ::speed_t = 0o010001; +pub const B115200: ::speed_t = 0o010002; +pub const B230400: ::speed_t = 0o010003; +pub const B460800: ::speed_t = 0o010004; +pub const B500000: ::speed_t = 0o010005; +pub const B576000: ::speed_t = 0o010006; +pub const B921600: ::speed_t = 0o010007; +pub const B1000000: ::speed_t = 0o010010; +pub const B1152000: ::speed_t = 0o010011; +pub const B1500000: ::speed_t = 0o010012; +pub const B2000000: ::speed_t = 0o010013; +pub const B2500000: ::speed_t = 0o010014; +pub const B3000000: ::speed_t = 0o010015; +pub const B3500000: ::speed_t = 0o010016; +pub const B4000000: ::speed_t = 0o010017; + +cfg_if! { + if #[cfg(target_arch = "mips")] { + mod mips32; + pub use self::mips32::*; + } else if #[cfg(target_arch = "mips64")] { + mod mips64; + pub use self::mips64::*; + } else { + // Unknown target_arch + } +} diff --git a/src/vendor/libc/src/unix/uclibc/mod.rs b/src/vendor/libc/src/unix/uclibc/mod.rs new file mode 100644 index 0000000000..01960361b9 --- /dev/null +++ b/src/vendor/libc/src/unix/uclibc/mod.rs @@ -0,0 +1,1782 @@ +use dox::{mem, Option}; + +pub type sa_family_t = u16; +pub type pthread_key_t = ::c_uint; +pub type speed_t = ::c_uint; +pub type tcflag_t = ::c_uint; +pub type loff_t = ::c_longlong; +pub type clockid_t = ::c_int; +pub type key_t = ::c_int; +pub type id_t = ::c_uint; +pub type useconds_t = u32; +pub type dev_t = u64; +pub type socklen_t = u32; +pub type pthread_t = ::c_ulong; +pub type mode_t = u32; +pub type ino64_t = u64; +pub type off64_t = i64; +pub type blkcnt64_t = i64; +pub type rlim64_t = u64; +pub type shmatt_t = ::c_ulong; +pub type mqd_t = ::c_int; +pub type msgqnum_t = ::c_ulong; +pub type msglen_t = ::c_ulong; +pub type nfds_t = ::c_ulong; +pub type nl_item = ::c_int; +pub type idtype_t = ::c_uint; + +pub enum fpos64_t {} // TODO: fill this out with a struct + +pub enum timezone {} + +s! { + pub struct sockaddr { + pub sa_family: sa_family_t, + pub sa_data: [::c_char; 14], + } + + pub struct sockaddr_in { + pub sin_family: sa_family_t, + pub sin_port: ::in_port_t, + pub sin_addr: ::in_addr, + pub sin_zero: [u8; 8], + } + + pub struct sockaddr_in6 { + pub sin6_family: sa_family_t, + pub sin6_port: ::in_port_t, + pub sin6_flowinfo: u32, + pub sin6_addr: ::in6_addr, + pub sin6_scope_id: u32, + } + + pub struct sockaddr_un { + pub sun_family: sa_family_t, + pub sun_path: [::c_char; 108] + } + + pub struct sockaddr_storage { + pub ss_family: sa_family_t, + __ss_align: ::size_t, + #[cfg(target_pointer_width = "32")] + __ss_pad2: [u8; 128 - 2 * 4], + #[cfg(target_pointer_width = "64")] + __ss_pad2: [u8; 128 - 2 * 8], + } + + pub struct addrinfo { + pub ai_flags: ::c_int, + pub ai_family: ::c_int, + pub ai_socktype: ::c_int, + pub ai_protocol: ::c_int, + pub ai_addrlen: socklen_t, + + pub ai_addr: *mut ::sockaddr, + + pub ai_canonname: *mut c_char, + + pub ai_next: *mut addrinfo, + } + + pub struct sockaddr_nl { + pub nl_family: ::sa_family_t, + nl_pad: ::c_ushort, + pub nl_pid: u32, + pub nl_groups: u32 + } + + pub struct sockaddr_ll { + pub sll_family: ::c_ushort, + pub sll_protocol: ::c_ushort, + pub sll_ifindex: ::c_int, + pub sll_hatype: ::c_ushort, + pub sll_pkttype: ::c_uchar, + pub sll_halen: ::c_uchar, + pub sll_addr: [::c_uchar; 8] + } + + pub struct fd_set { + fds_bits: [::c_ulong; FD_SETSIZE / ULONG_SIZE], + } + + pub struct tm { + pub tm_sec: ::c_int, + pub tm_min: ::c_int, + pub tm_hour: ::c_int, + pub tm_mday: ::c_int, + pub tm_mon: ::c_int, + pub tm_year: ::c_int, + pub tm_wday: ::c_int, + pub tm_yday: ::c_int, + pub tm_isdst: ::c_int, + pub tm_gmtoff: ::c_long, + pub tm_zone: *const ::c_char, + } + + pub struct sched_param { + pub sched_priority: ::c_int, + } + + pub struct Dl_info { + pub dli_fname: *const ::c_char, + pub dli_fbase: *mut ::c_void, + pub dli_sname: *const ::c_char, + pub dli_saddr: *mut ::c_void, + } + + #[cfg_attr(any(all(target_arch = "x86", + target_arch = "x86_64")), + repr(packed))] + pub struct epoll_event { + pub events: ::uint32_t, + pub u64: ::uint64_t, + } + + pub struct utsname { + pub sysname: [::c_char; 65], + pub nodename: [::c_char; 65], + pub release: [::c_char; 65], + pub version: [::c_char; 65], + pub machine: [::c_char; 65], + pub domainname: [::c_char; 65] + } + + pub struct lconv { + pub decimal_point: *mut ::c_char, + pub thousands_sep: *mut ::c_char, + pub grouping: *mut ::c_char, + pub int_curr_symbol: *mut ::c_char, + pub currency_symbol: *mut ::c_char, + pub mon_decimal_point: *mut ::c_char, + pub mon_thousands_sep: *mut ::c_char, + pub mon_grouping: *mut ::c_char, + pub positive_sign: *mut ::c_char, + pub negative_sign: *mut ::c_char, + pub int_frac_digits: ::c_char, + pub frac_digits: ::c_char, + pub p_cs_precedes: ::c_char, + pub p_sep_by_space: ::c_char, + pub n_cs_precedes: ::c_char, + pub n_sep_by_space: ::c_char, + pub p_sign_posn: ::c_char, + pub n_sign_posn: ::c_char, + pub int_p_cs_precedes: ::c_char, + pub int_p_sep_by_space: ::c_char, + pub int_n_cs_precedes: ::c_char, + pub int_n_sep_by_space: ::c_char, + pub int_p_sign_posn: ::c_char, + pub int_n_sign_posn: ::c_char, + } + + pub struct sigevent { + pub sigev_value: ::sigval, + pub sigev_signo: ::c_int, + pub sigev_notify: ::c_int, + // Actually a union. We only expose sigev_notify_thread_id because it's + // the most useful member + pub sigev_notify_thread_id: ::c_int, + #[cfg(target_pointer_width = "64")] + __unused1: [::c_int; 11], + #[cfg(target_pointer_width = "32")] + __unused1: [::c_int; 12] + } + + pub struct dirent { + pub d_ino: ::ino_t, + pub d_off: ::off_t, + pub d_reclen: ::c_ushort, + pub d_type: ::c_uchar, + pub d_name: [::c_char; 256], + } + + pub struct dirent64 { + pub d_ino: ::ino64_t, + pub d_off: ::off64_t, + pub d_reclen: ::c_ushort, + pub d_type: ::c_uchar, + pub d_name: [::c_char; 256], + } + + pub struct rlimit64 { + pub rlim_cur: rlim64_t, + pub rlim_max: rlim64_t, + } + + pub struct glob_t { + pub gl_pathc: ::size_t, + pub gl_pathv: *mut *mut c_char, + pub gl_offs: ::size_t, + pub gl_flags: ::c_int, + + __unused1: *mut ::c_void, + __unused2: *mut ::c_void, + __unused3: *mut ::c_void, + __unused4: *mut ::c_void, + __unused5: *mut ::c_void, + } + + pub struct ifaddrs { + pub ifa_next: *mut ifaddrs, + pub ifa_name: *mut c_char, + pub ifa_flags: ::c_uint, + pub ifa_addr: *mut ::sockaddr, + pub ifa_netmask: *mut ::sockaddr, + pub ifa_ifu: *mut ::sockaddr, // FIXME This should be a union + pub ifa_data: *mut ::c_void + } + + pub struct pthread_mutex_t { + #[cfg(any(target_arch = "mips", target_arch = "arm", + target_arch = "powerpc"))] + __align: [::c_long; 0], + #[cfg(not(any(target_arch = "mips", target_arch = "arm", + target_arch = "powerpc")))] + __align: [::c_longlong; 0], + size: [u8; __SIZEOF_PTHREAD_MUTEX_T], + } + + pub struct pthread_rwlock_t { + #[cfg(any(target_arch = "mips", target_arch = "arm", + target_arch = "powerpc"))] + __align: [::c_long; 0], + #[cfg(not(any(target_arch = "mips", target_arch = "arm", + target_arch = "powerpc")))] + __align: [::c_longlong; 0], + size: [u8; __SIZEOF_PTHREAD_RWLOCK_T], + } + + pub struct pthread_mutexattr_t { + #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64"))] + __align: [::c_int; 0], + #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64")))] + __align: [::c_long; 0], + size: [u8; __SIZEOF_PTHREAD_MUTEXATTR_T], + } + + pub struct pthread_rwlockattr_t { + __lockkind: ::c_int, + __pshared: ::c_int, + } + + pub struct pthread_cond_t { + __align: [::c_longlong; 0], + size: [u8; __SIZEOF_PTHREAD_COND_T], + } + + pub struct pthread_condattr_t { + __align: [::c_int; 0], + size: [u8; __SIZEOF_PTHREAD_CONDATTR_T], + } + + pub struct passwd { + pub pw_name: *mut ::c_char, + pub pw_passwd: *mut ::c_char, + pub pw_uid: ::uid_t, + pub pw_gid: ::gid_t, + pub pw_gecos: *mut ::c_char, + pub pw_dir: *mut ::c_char, + pub pw_shell: *mut ::c_char, + } + + pub struct spwd { + pub sp_namp: *mut ::c_char, + pub sp_pwdp: *mut ::c_char, + pub sp_lstchg: ::c_long, + pub sp_min: ::c_long, + pub sp_max: ::c_long, + pub sp_warn: ::c_long, + pub sp_inact: ::c_long, + pub sp_expire: ::c_long, + pub sp_flag: ::c_ulong, + } + + pub struct statvfs { + pub f_bsize: ::c_ulong, + pub f_frsize: ::c_ulong, + pub f_blocks: ::fsblkcnt_t, + pub f_bfree: ::fsblkcnt_t, + pub f_bavail: ::fsblkcnt_t, + pub f_files: ::fsfilcnt_t, + pub f_ffree: ::fsfilcnt_t, + pub f_favail: ::fsfilcnt_t, + #[cfg(target_endian = "little")] + pub f_fsid: ::c_ulong, + #[cfg(target_pointer_width = "32")] + __f_unused: ::c_int, + #[cfg(target_endian = "big")] + pub f_fsid: ::c_ulong, + pub f_flag: ::c_ulong, + pub f_namemax: ::c_ulong, + __f_spare: [::c_int; 6], + } + + pub struct dqblk { + pub dqb_bhardlimit: ::uint32_t, + pub dqb_bsoftlimit: ::uint32_t, + pub dqb_curblocks: ::uint32_t, + pub dqb_ihardlimit: ::uint32_t, + pub dqb_isoftlimit: ::uint32_t, + pub dqb_curinodes: ::uint32_t, + pub dqb_btime: ::time_t, + pub dqb_itime: ::time_t, + } + + pub struct signalfd_siginfo { + pub ssi_signo: ::uint32_t, + pub ssi_errno: ::int32_t, + pub ssi_code: ::int32_t, + pub ssi_pid: ::uint32_t, + pub ssi_uid: ::uint32_t, + pub ssi_fd: ::int32_t, + pub ssi_tid: ::uint32_t, + pub ssi_band: ::uint32_t, + pub ssi_overrun: ::uint32_t, + pub ssi_trapno: ::uint32_t, + pub ssi_status: ::int32_t, + pub ssi_int: ::int32_t, + pub ssi_ptr: ::uint64_t, + pub ssi_utime: ::uint64_t, + pub ssi_stime: ::uint64_t, + pub ssi_addr: ::uint64_t, + _pad: [::uint8_t; 48], + } + + pub struct fsid_t { + __val: [::c_int; 2], + } + + pub struct mq_attr { + pub mq_flags: ::c_long, + pub mq_maxmsg: ::c_long, + pub mq_msgsize: ::c_long, + pub mq_curmsgs: ::c_long, + pad: [::c_long; 4] + } + + pub struct cpu_set_t { + #[cfg(target_pointer_width = "32")] + bits: [u32; 32], + #[cfg(target_pointer_width = "64")] + bits: [u64; 16], + } + + pub struct if_nameindex { + pub if_index: ::c_uint, + pub if_name: *mut ::c_char, + } + + // System V IPC + pub struct msginfo { + pub msgpool: ::c_int, + pub msgmap: ::c_int, + pub msgmax: ::c_int, + pub msgmnb: ::c_int, + pub msgmni: ::c_int, + pub msgssz: ::c_int, + pub msgtql: ::c_int, + pub msgseg: ::c_ushort, + } +} + +// intentionally not public, only used for fd_set +cfg_if! { + if #[cfg(target_pointer_width = "32")] { + const ULONG_SIZE: usize = 32; + } else if #[cfg(target_pointer_width = "64")] { + const ULONG_SIZE: usize = 64; + } else { + // Unknown target_pointer_width + } +} + +pub const EXIT_FAILURE: ::c_int = 1; +pub const EXIT_SUCCESS: ::c_int = 0; +pub const RAND_MAX: ::c_int = 2147483647; +pub const EOF: ::c_int = -1; +pub const SEEK_SET: ::c_int = 0; +pub const SEEK_CUR: ::c_int = 1; +pub const SEEK_END: ::c_int = 2; +pub const _IOFBF: ::c_int = 0; +pub const _IONBF: ::c_int = 2; +pub const _IOLBF: ::c_int = 1; + +pub const F_DUPFD: ::c_int = 0; +pub const F_GETFD: ::c_int = 1; +pub const F_SETFD: ::c_int = 2; +pub const F_GETFL: ::c_int = 3; +pub const F_SETFL: ::c_int = 4; + +// Linux-specific fcntls +pub const F_SETLEASE: ::c_int = 1024; +pub const F_GETLEASE: ::c_int = 1025; +pub const F_NOTIFY: ::c_int = 1026; +pub const F_DUPFD_CLOEXEC: ::c_int = 1030; + +// TODO(#235): Include file sealing fcntls once we have a way to verify them. + +pub const SIGTRAP: ::c_int = 5; + +pub const PTHREAD_CREATE_JOINABLE: ::c_int = 0; +pub const PTHREAD_CREATE_DETACHED: ::c_int = 1; + +pub const CLOCK_REALTIME: clockid_t = 0; +pub const CLOCK_MONOTONIC: clockid_t = 1; +pub const CLOCK_PROCESS_CPUTIME_ID: clockid_t = 2; +pub const CLOCK_THREAD_CPUTIME_ID: clockid_t = 3; +// TODO(#247) Someday our Travis shall have glibc 2.21 (released in Sep +// 2014.) See also musl/mod.rs +// pub const CLOCK_SGI_CYCLE: clockid_t = 10; +// pub const CLOCK_TAI: clockid_t = 11; +pub const TIMER_ABSTIME: ::c_int = 1; + +pub const RLIMIT_CPU: ::c_int = 0; +pub const RLIMIT_FSIZE: ::c_int = 1; +pub const RLIMIT_DATA: ::c_int = 2; +pub const RLIMIT_STACK: ::c_int = 3; +pub const RLIMIT_CORE: ::c_int = 4; +pub const RLIMIT_LOCKS: ::c_int = 10; +pub const RLIMIT_SIGPENDING: ::c_int = 11; +pub const RLIMIT_MSGQUEUE: ::c_int = 12; +pub const RLIMIT_NICE: ::c_int = 13; +pub const RLIMIT_RTPRIO: ::c_int = 14; + +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 SOCK_CLOEXEC: ::c_int = O_CLOEXEC; + +pub const S_IFIFO: ::mode_t = 4096; +pub const S_IFCHR: ::mode_t = 8192; +pub const S_IFBLK: ::mode_t = 24576; +pub const S_IFDIR: ::mode_t = 16384; +pub const S_IFREG: ::mode_t = 32768; +pub const S_IFLNK: ::mode_t = 40960; +pub const S_IFSOCK: ::mode_t = 49152; +pub const S_IFMT: ::mode_t = 61440; +pub const S_IRWXU: ::mode_t = 448; +pub const S_IXUSR: ::mode_t = 64; +pub const S_IWUSR: ::mode_t = 128; +pub const S_IRUSR: ::mode_t = 256; +pub const S_IRWXG: ::mode_t = 56; +pub const S_IXGRP: ::mode_t = 8; +pub const S_IWGRP: ::mode_t = 16; +pub const S_IRGRP: ::mode_t = 32; +pub const S_IRWXO: ::mode_t = 7; +pub const S_IXOTH: ::mode_t = 1; +pub const S_IWOTH: ::mode_t = 2; +pub const S_IROTH: ::mode_t = 4; +pub const F_OK: ::c_int = 0; +pub const R_OK: ::c_int = 4; +pub const W_OK: ::c_int = 2; +pub const X_OK: ::c_int = 1; +pub const STDIN_FILENO: ::c_int = 0; +pub const STDOUT_FILENO: ::c_int = 1; +pub const STDERR_FILENO: ::c_int = 2; +pub const SIGHUP: ::c_int = 1; +pub const SIGINT: ::c_int = 2; +pub const SIGQUIT: ::c_int = 3; +pub const SIGILL: ::c_int = 4; +pub const SIGABRT: ::c_int = 6; +pub const SIGFPE: ::c_int = 8; +pub const SIGKILL: ::c_int = 9; +pub const SIGSEGV: ::c_int = 11; +pub const SIGPIPE: ::c_int = 13; +pub const SIGALRM: ::c_int = 14; +pub const SIGTERM: ::c_int = 15; + +pub const PROT_NONE: ::c_int = 0; +pub const PROT_READ: ::c_int = 1; +pub const PROT_WRITE: ::c_int = 2; +pub const PROT_EXEC: ::c_int = 4; + +pub const LC_CTYPE: ::c_int = 0; +pub const LC_NUMERIC: ::c_int = 1; +pub const LC_MONETARY: ::c_int = 2; +pub const LC_TIME: ::c_int = 3; +pub const LC_COLLATE: ::c_int = 4; +pub const LC_MESSAGES: ::c_int = 5; +pub const LC_ALL: ::c_int = 6; +pub const LC_CTYPE_MASK: ::c_int = (1 << LC_CTYPE); +pub const LC_NUMERIC_MASK: ::c_int = (1 << LC_NUMERIC); +pub const LC_TIME_MASK: ::c_int = (1 << LC_TIME); +pub const LC_COLLATE_MASK: ::c_int = (1 << LC_COLLATE); +pub const LC_MONETARY_MASK: ::c_int = (1 << LC_MONETARY); +pub const LC_MESSAGES_MASK: ::c_int = (1 << LC_MESSAGES); +// LC_ALL_MASK defined per platform + +pub const MAP_FILE: ::c_int = 0x0000; +pub const MAP_SHARED: ::c_int = 0x0001; +pub const MAP_PRIVATE: ::c_int = 0x0002; +pub const MAP_FIXED: ::c_int = 0x0010; + +pub const MAP_FAILED: *mut ::c_void = !0 as *mut ::c_void; + +// MS_ flags for msync(2) +pub const MS_ASYNC: ::c_int = 0x0001; +pub const MS_INVALIDATE: ::c_int = 0x0002; +pub const MS_SYNC: ::c_int = 0x0004; + +// MS_ flags for mount(2) +pub const MS_RDONLY: ::c_ulong = 0x01; +pub const MS_NOSUID: ::c_ulong = 0x02; +pub const MS_NODEV: ::c_ulong = 0x04; +pub const MS_NOEXEC: ::c_ulong = 0x08; +pub const MS_SYNCHRONOUS: ::c_ulong = 0x10; +pub const MS_REMOUNT: ::c_ulong = 0x20; +pub const MS_MANDLOCK: ::c_ulong = 0x40; +pub const MS_NOATIME: ::c_ulong = 0x0400; +pub const MS_NODIRATIME: ::c_ulong = 0x0800; +pub const MS_BIND: ::c_ulong = 0x1000; +pub const MS_NOUSER: ::c_ulong = 0x80000000; +pub const MS_MGC_VAL: ::c_ulong = 0xc0ed0000; +pub const MS_MGC_MSK: ::c_ulong = 0xffff0000; +pub const MS_RMT_MASK: ::c_ulong = 0x800051; + +pub const EPERM: ::c_int = 1; +pub const ENOENT: ::c_int = 2; +pub const ESRCH: ::c_int = 3; +pub const EINTR: ::c_int = 4; +pub const EIO: ::c_int = 5; +pub const ENXIO: ::c_int = 6; +pub const E2BIG: ::c_int = 7; +pub const ENOEXEC: ::c_int = 8; +pub const EBADF: ::c_int = 9; +pub const ECHILD: ::c_int = 10; +pub const EAGAIN: ::c_int = 11; +pub const ENOMEM: ::c_int = 12; +pub const EACCES: ::c_int = 13; +pub const EFAULT: ::c_int = 14; +pub const ENOTBLK: ::c_int = 15; +pub const EBUSY: ::c_int = 16; +pub const EEXIST: ::c_int = 17; +pub const EXDEV: ::c_int = 18; +pub const ENODEV: ::c_int = 19; +pub const ENOTDIR: ::c_int = 20; +pub const EISDIR: ::c_int = 21; +pub const EINVAL: ::c_int = 22; +pub const ENFILE: ::c_int = 23; +pub const EMFILE: ::c_int = 24; +pub const ENOTTY: ::c_int = 25; +pub const ETXTBSY: ::c_int = 26; +pub const EFBIG: ::c_int = 27; +pub const ENOSPC: ::c_int = 28; +pub const ESPIPE: ::c_int = 29; +pub const EROFS: ::c_int = 30; +pub const EMLINK: ::c_int = 31; +pub const EPIPE: ::c_int = 32; +pub const EDOM: ::c_int = 33; +pub const ERANGE: ::c_int = 34; +pub const EWOULDBLOCK: ::c_int = EAGAIN; + +pub const SCM_RIGHTS: ::c_int = 0x01; +pub const SCM_CREDENTIALS: ::c_int = 0x02; + +pub const IPPROTO_RAW: ::c_int = 255; + +pub const PROT_GROWSDOWN: ::c_int = 0x1000000; +pub const PROT_GROWSUP: ::c_int = 0x2000000; + +pub const MAP_TYPE: ::c_int = 0x000f; + +pub const MADV_NORMAL: ::c_int = 0; +pub const MADV_RANDOM: ::c_int = 1; +pub const MADV_SEQUENTIAL: ::c_int = 2; +pub const MADV_WILLNEED: ::c_int = 3; +pub const MADV_DONTNEED: ::c_int = 4; +pub const MADV_REMOVE: ::c_int = 9; +pub const MADV_DONTFORK: ::c_int = 10; +pub const MADV_DOFORK: ::c_int = 11; +pub const MADV_MERGEABLE: ::c_int = 12; +pub const MADV_UNMERGEABLE: ::c_int = 13; +pub const MADV_HWPOISON: ::c_int = 100; + +pub const IFF_UP: ::c_int = 0x1; +pub const IFF_BROADCAST: ::c_int = 0x2; +pub const IFF_DEBUG: ::c_int = 0x4; +pub const IFF_LOOPBACK: ::c_int = 0x8; +pub const IFF_POINTOPOINT: ::c_int = 0x10; +pub const IFF_NOTRAILERS: ::c_int = 0x20; +pub const IFF_RUNNING: ::c_int = 0x40; +pub const IFF_NOARP: ::c_int = 0x80; +pub const IFF_PROMISC: ::c_int = 0x100; +pub const IFF_ALLMULTI: ::c_int = 0x200; +pub const IFF_MASTER: ::c_int = 0x400; +pub const IFF_SLAVE: ::c_int = 0x800; +pub const IFF_MULTICAST: ::c_int = 0x1000; +pub const IFF_PORTSEL: ::c_int = 0x2000; +pub const IFF_AUTOMEDIA: ::c_int = 0x4000; +pub const IFF_DYNAMIC: ::c_int = 0x8000; + +pub const SOL_IP: ::c_int = 0; +pub const SOL_TCP: ::c_int = 6; +pub const SOL_IPV6: ::c_int = 41; +pub const SOL_ICMPV6: ::c_int = 58; +pub const SOL_RAW: ::c_int = 255; +pub const SOL_DECNET: ::c_int = 261; +pub const SOL_X25: ::c_int = 262; +pub const SOL_PACKET: ::c_int = 263; +pub const SOL_ATM: ::c_int = 264; +pub const SOL_AAL: ::c_int = 265; +pub const SOL_IRDA: ::c_int = 266; + +pub const AF_UNSPEC: ::c_int = 0; +pub const AF_UNIX: ::c_int = 1; +pub const AF_LOCAL: ::c_int = 1; +pub const AF_INET: ::c_int = 2; +pub const AF_AX25: ::c_int = 3; +pub const AF_IPX: ::c_int = 4; +pub const AF_APPLETALK: ::c_int = 5; +pub const AF_NETROM: ::c_int = 6; +pub const AF_BRIDGE: ::c_int = 7; +pub const AF_ATMPVC: ::c_int = 8; +pub const AF_X25: ::c_int = 9; +pub const AF_INET6: ::c_int = 10; +pub const AF_ROSE: ::c_int = 11; +pub const AF_DECnet: ::c_int = 12; +pub const AF_NETBEUI: ::c_int = 13; +pub const AF_SECURITY: ::c_int = 14; +pub const AF_KEY: ::c_int = 15; +pub const AF_NETLINK: ::c_int = 16; +pub const AF_ROUTE: ::c_int = AF_NETLINK; +pub const AF_PACKET: ::c_int = 17; +pub const AF_ASH: ::c_int = 18; +pub const AF_ECONET: ::c_int = 19; +pub const AF_ATMSVC: ::c_int = 20; +pub const AF_SNA: ::c_int = 22; +pub const AF_IRDA: ::c_int = 23; +pub const AF_PPPOX: ::c_int = 24; +pub const AF_WANPIPE: ::c_int = 25; +pub const AF_LLC: ::c_int = 26; +pub const AF_CAN: ::c_int = 29; +pub const AF_TIPC: ::c_int = 30; +pub const AF_BLUETOOTH: ::c_int = 31; +pub const AF_IUCV: ::c_int = 32; +pub const AF_RXRPC: ::c_int = 33; +pub const AF_ISDN: ::c_int = 34; +pub const AF_PHONET: ::c_int = 35; +pub const AF_IEEE802154: ::c_int = 36; +pub const AF_CAIF: ::c_int = 37; +pub const AF_ALG: ::c_int = 38; + +pub const PF_UNSPEC: ::c_int = AF_UNSPEC; +pub const PF_UNIX: ::c_int = AF_UNIX; +pub const PF_LOCAL: ::c_int = AF_LOCAL; +pub const PF_INET: ::c_int = AF_INET; +pub const PF_AX25: ::c_int = AF_AX25; +pub const PF_IPX: ::c_int = AF_IPX; +pub const PF_APPLETALK: ::c_int = AF_APPLETALK; +pub const PF_NETROM: ::c_int = AF_NETROM; +pub const PF_BRIDGE: ::c_int = AF_BRIDGE; +pub const PF_ATMPVC: ::c_int = AF_ATMPVC; +pub const PF_X25: ::c_int = AF_X25; +pub const PF_INET6: ::c_int = AF_INET6; +pub const PF_ROSE: ::c_int = AF_ROSE; +pub const PF_DECnet: ::c_int = AF_DECnet; +pub const PF_NETBEUI: ::c_int = AF_NETBEUI; +pub const PF_SECURITY: ::c_int = AF_SECURITY; +pub const PF_KEY: ::c_int = AF_KEY; +pub const PF_NETLINK: ::c_int = AF_NETLINK; +pub const PF_ROUTE: ::c_int = AF_ROUTE; +pub const PF_PACKET: ::c_int = AF_PACKET; +pub const PF_ASH: ::c_int = AF_ASH; +pub const PF_ECONET: ::c_int = AF_ECONET; +pub const PF_ATMSVC: ::c_int = AF_ATMSVC; +pub const PF_SNA: ::c_int = AF_SNA; +pub const PF_IRDA: ::c_int = AF_IRDA; +pub const PF_PPPOX: ::c_int = AF_PPPOX; +pub const PF_WANPIPE: ::c_int = AF_WANPIPE; +pub const PF_LLC: ::c_int = AF_LLC; +pub const PF_CAN: ::c_int = AF_CAN; +pub const PF_TIPC: ::c_int = AF_TIPC; +pub const PF_BLUETOOTH: ::c_int = AF_BLUETOOTH; +pub const PF_IUCV: ::c_int = AF_IUCV; +pub const PF_RXRPC: ::c_int = AF_RXRPC; +pub const PF_ISDN: ::c_int = AF_ISDN; +pub const PF_PHONET: ::c_int = AF_PHONET; +pub const PF_IEEE802154: ::c_int = AF_IEEE802154; +pub const PF_CAIF: ::c_int = AF_CAIF; +pub const PF_ALG: ::c_int = AF_ALG; + +pub const SOMAXCONN: ::c_int = 128; + +pub const MSG_OOB: ::c_int = 1; +pub const MSG_PEEK: ::c_int = 2; +pub const MSG_DONTROUTE: ::c_int = 4; +pub const MSG_CTRUNC: ::c_int = 8; +pub const MSG_TRUNC: ::c_int = 0x20; +pub const MSG_DONTWAIT: ::c_int = 0x40; +pub const MSG_EOR: ::c_int = 0x80; +pub const MSG_WAITALL: ::c_int = 0x100; +pub const MSG_FIN: ::c_int = 0x200; +pub const MSG_SYN: ::c_int = 0x400; +pub const MSG_CONFIRM: ::c_int = 0x800; +pub const MSG_RST: ::c_int = 0x1000; +pub const MSG_ERRQUEUE: ::c_int = 0x2000; +pub const MSG_NOSIGNAL: ::c_int = 0x4000; +pub const MSG_MORE: ::c_int = 0x8000; +pub const MSG_WAITFORONE: ::c_int = 0x10000; +pub const MSG_CMSG_CLOEXEC: ::c_int = 0x40000000; + +pub const SOCK_RAW: ::c_int = 3; +pub const IPPROTO_ICMP: ::c_int = 1; +pub const IPPROTO_ICMPV6: ::c_int = 58; +pub const IPPROTO_TCP: ::c_int = 6; +pub const IPPROTO_IP: ::c_int = 0; +pub const IPPROTO_IPV6: ::c_int = 41; +pub const IP_MULTICAST_TTL: ::c_int = 33; +pub const IP_MULTICAST_LOOP: ::c_int = 34; +pub const IP_TTL: ::c_int = 2; +pub const IP_HDRINCL: ::c_int = 3; +pub const IP_ADD_MEMBERSHIP: ::c_int = 35; +pub const IP_DROP_MEMBERSHIP: ::c_int = 36; + +pub const TCP_NODELAY: ::c_int = 1; +pub const TCP_MAXSEG: ::c_int = 2; +pub const TCP_CORK: ::c_int = 3; +pub const TCP_KEEPIDLE: ::c_int = 4; +pub const TCP_KEEPINTVL: ::c_int = 5; +pub const TCP_KEEPCNT: ::c_int = 6; +pub const TCP_SYNCNT: ::c_int = 7; +pub const TCP_LINGER2: ::c_int = 8; +pub const TCP_DEFER_ACCEPT: ::c_int = 9; +pub const TCP_WINDOW_CLAMP: ::c_int = 10; +pub const TCP_INFO: ::c_int = 11; +pub const TCP_QUICKACK: ::c_int = 12; +pub const TCP_CONGESTION: ::c_int = 13; + +pub const IPV6_MULTICAST_LOOP: ::c_int = 19; +pub const IPV6_V6ONLY: ::c_int = 26; + +pub const SO_DEBUG: ::c_int = 1; + +pub const SHUT_RD: ::c_int = 0; +pub const SHUT_WR: ::c_int = 1; +pub const SHUT_RDWR: ::c_int = 2; + +pub const LOCK_SH: ::c_int = 1; +pub const LOCK_EX: ::c_int = 2; +pub const LOCK_NB: ::c_int = 4; +pub const LOCK_UN: ::c_int = 8; + +pub const SS_ONSTACK: ::c_int = 1; +pub const SS_DISABLE: ::c_int = 2; + +pub const PATH_MAX: ::c_int = 4096; + +pub const FD_SETSIZE: usize = 1024; + +pub const EPOLLIN: ::c_int = 0x1; +pub const EPOLLPRI: ::c_int = 0x2; +pub const EPOLLOUT: ::c_int = 0x4; +pub const EPOLLRDNORM: ::c_int = 0x40; +pub const EPOLLRDBAND: ::c_int = 0x80; +pub const EPOLLWRNORM: ::c_int = 0x100; +pub const EPOLLWRBAND: ::c_int = 0x200; +pub const EPOLLMSG: ::c_int = 0x400; +pub const EPOLLERR: ::c_int = 0x8; +pub const EPOLLHUP: ::c_int = 0x10; +pub const EPOLLET: ::c_int = 0x80000000; + +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 MNT_DETACH: ::c_int = 0x2; +pub const MNT_EXPIRE: ::c_int = 0x4; + +pub const MNT_FORCE: ::c_int = 0x1; + +pub const Q_SYNC: ::c_int = 0x600; +pub const Q_QUOTAON: ::c_int = 0x100; +pub const Q_QUOTAOFF: ::c_int = 0x200; +pub const Q_GETQUOTA: ::c_int = 0x300; +pub const Q_SETQUOTA: ::c_int = 0x400; + +pub const TCIOFF: ::c_int = 2; +pub const TCION: ::c_int = 3; +pub const TCOOFF: ::c_int = 0; +pub const TCOON: ::c_int = 1; +pub const TCIFLUSH: ::c_int = 0; +pub const TCOFLUSH: ::c_int = 1; +pub const TCIOFLUSH: ::c_int = 2; +pub const NL0: ::c_int = 0x00000000; +pub const NL1: ::c_int = 0x00000100; +pub const TAB0: ::c_int = 0x00000000; +pub const CR0: ::c_int = 0x00000000; +pub const FF0: ::c_int = 0x00000000; +pub const BS0: ::c_int = 0x00000000; +pub const VT0: ::c_int = 0x00000000; +pub const VERASE: usize = 2; +pub const VKILL: usize = 3; +pub const VINTR: usize = 0; +pub const VQUIT: usize = 1; +pub const VLNEXT: usize = 15; +pub const IGNBRK: ::tcflag_t = 0x00000001; +pub const BRKINT: ::tcflag_t = 0x00000002; +pub const IGNPAR: ::tcflag_t = 0x00000004; +pub const PARMRK: ::tcflag_t = 0x00000008; +pub const INPCK: ::tcflag_t = 0x00000010; +pub const ISTRIP: ::tcflag_t = 0x00000020; +pub const INLCR: ::tcflag_t = 0x00000040; +pub const IGNCR: ::tcflag_t = 0x00000080; +pub const ICRNL: ::tcflag_t = 0x00000100; +pub const IXANY: ::tcflag_t = 0x00000800; +pub const IMAXBEL: ::tcflag_t = 0x00002000; +pub const OPOST: ::tcflag_t = 0x1; +pub const CS5: ::tcflag_t = 0x00000000; +pub const CRTSCTS: ::tcflag_t = 0x80000000; +pub const ECHO: ::tcflag_t = 0x00000008; + +pub const CLONE_VM: ::c_int = 0x100; +pub const CLONE_FS: ::c_int = 0x200; +pub const CLONE_FILES: ::c_int = 0x400; +pub const CLONE_SIGHAND: ::c_int = 0x800; +pub const CLONE_PTRACE: ::c_int = 0x2000; +pub const CLONE_VFORK: ::c_int = 0x4000; +pub const CLONE_PARENT: ::c_int = 0x8000; +pub const CLONE_THREAD: ::c_int = 0x10000; +pub const CLONE_NEWNS: ::c_int = 0x20000; +pub const CLONE_SYSVSEM: ::c_int = 0x40000; +pub const CLONE_SETTLS: ::c_int = 0x80000; +pub const CLONE_PARENT_SETTID: ::c_int = 0x100000; +pub const CLONE_CHILD_CLEARTID: ::c_int = 0x200000; +pub const CLONE_DETACHED: ::c_int = 0x400000; +pub const CLONE_UNTRACED: ::c_int = 0x800000; +pub const CLONE_CHILD_SETTID: ::c_int = 0x01000000; +pub const CLONE_NEWUTS: ::c_int = 0x04000000; +pub const CLONE_NEWIPC: ::c_int = 0x08000000; +pub const CLONE_NEWUSER: ::c_int = 0x10000000; +pub const CLONE_NEWPID: ::c_int = 0x20000000; +pub const CLONE_NEWNET: ::c_int = 0x40000000; +pub const CLONE_IO: ::c_int = 0x80000000; + +pub const WNOHANG: ::c_int = 0x00000001; +pub const WUNTRACED: ::c_int = 0x00000002; +pub const WSTOPPED: ::c_int = WUNTRACED; +pub const WEXITED: ::c_int = 0x00000004; +pub const WCONTINUED: ::c_int = 0x00000008; +pub const WNOWAIT: ::c_int = 0x01000000; + +pub const __WNOTHREAD: ::c_int = 0x20000000; +pub const __WALL: ::c_int = 0x40000000; +pub const __WCLONE: ::c_int = 0x80000000; + +pub const SPLICE_F_MOVE: ::c_uint = 0x01; +pub const SPLICE_F_NONBLOCK: ::c_uint = 0x02; +pub const SPLICE_F_MORE: ::c_uint = 0x04; +pub const SPLICE_F_GIFT: ::c_uint = 0x08; + +pub const RTLD_LOCAL: ::c_int = 0; + +pub const POSIX_FADV_NORMAL: ::c_int = 0; +pub const POSIX_FADV_RANDOM: ::c_int = 1; +pub const POSIX_FADV_SEQUENTIAL: ::c_int = 2; +pub const POSIX_FADV_WILLNEED: ::c_int = 3; + +pub const AT_FDCWD: ::c_int = -100; +pub const AT_SYMLINK_NOFOLLOW: ::c_int = 0x100; +pub const AT_REMOVEDIR: ::c_int = 0x200; +pub const AT_SYMLINK_FOLLOW: ::c_int = 0x400; + +pub const LOG_CRON: ::c_int = 9 << 3; +pub const LOG_AUTHPRIV: ::c_int = 10 << 3; +pub const LOG_FTP: ::c_int = 11 << 3; +pub const LOG_PERROR: ::c_int = 0x20; + +pub const PIPE_BUF: usize = 4096; + +pub const SI_LOAD_SHIFT: ::c_uint = 16; + +pub const SIGEV_SIGNAL: ::c_int = 0; +pub const SIGEV_NONE: ::c_int = 1; +pub const SIGEV_THREAD: ::c_int = 2; + +pub const P_ALL: idtype_t = 0; +pub const P_PID: idtype_t = 1; +pub const P_PGID: idtype_t = 2; + +pub const UTIME_OMIT: c_long = 1073741822; +pub const UTIME_NOW: c_long = 1073741823; + +pub const L_tmpnam: ::c_uint = 20; +pub const _PC_LINK_MAX: ::c_int = 0; +pub const _PC_MAX_CANON: ::c_int = 1; +pub const _PC_MAX_INPUT: ::c_int = 2; +pub const _PC_NAME_MAX: ::c_int = 3; +pub const _PC_PATH_MAX: ::c_int = 4; +pub const _PC_PIPE_BUF: ::c_int = 5; +pub const _PC_CHOWN_RESTRICTED: ::c_int = 6; +pub const _PC_NO_TRUNC: ::c_int = 7; +pub const _PC_VDISABLE: ::c_int = 8; + +pub const _SC_ARG_MAX: ::c_int = 0; +pub const _SC_CHILD_MAX: ::c_int = 1; +pub const _SC_CLK_TCK: ::c_int = 2; +pub const _SC_NGROUPS_MAX: ::c_int = 3; +pub const _SC_OPEN_MAX: ::c_int = 4; +pub const _SC_STREAM_MAX: ::c_int = 5; +pub const _SC_TZNAME_MAX: ::c_int = 6; +pub const _SC_JOB_CONTROL: ::c_int = 7; +pub const _SC_SAVED_IDS: ::c_int = 8; +pub const _SC_REALTIME_SIGNALS: ::c_int = 9; +pub const _SC_PRIORITY_SCHEDULING: ::c_int = 10; +pub const _SC_TIMERS: ::c_int = 11; +pub const _SC_ASYNCHRONOUS_IO: ::c_int = 12; +pub const _SC_PRIORITIZED_IO: ::c_int = 13; +pub const _SC_SYNCHRONIZED_IO: ::c_int = 14; +pub const _SC_FSYNC: ::c_int = 15; +pub const _SC_MAPPED_FILES: ::c_int = 16; +pub const _SC_MEMLOCK: ::c_int = 17; +pub const _SC_MEMLOCK_RANGE: ::c_int = 18; +pub const _SC_MEMORY_PROTECTION: ::c_int = 19; +pub const _SC_MESSAGE_PASSING: ::c_int = 20; +pub const _SC_SEMAPHORES: ::c_int = 21; +pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 22; +pub const _SC_AIO_LISTIO_MAX: ::c_int = 23; +pub const _SC_AIO_MAX: ::c_int = 24; +pub const _SC_AIO_PRIO_DELTA_MAX: ::c_int = 25; +pub const _SC_DELAYTIMER_MAX: ::c_int = 26; +pub const _SC_MQ_OPEN_MAX: ::c_int = 27; +pub const _SC_MQ_PRIO_MAX: ::c_int = 28; +pub const _SC_VERSION: ::c_int = 29; +pub const _SC_PAGESIZE: ::c_int = 30; +pub const _SC_PAGE_SIZE: ::c_int = _SC_PAGESIZE; +pub const _SC_RTSIG_MAX: ::c_int = 31; +pub const _SC_SEM_NSEMS_MAX: ::c_int = 32; +pub const _SC_SEM_VALUE_MAX: ::c_int = 33; +pub const _SC_SIGQUEUE_MAX: ::c_int = 34; +pub const _SC_TIMER_MAX: ::c_int = 35; +pub const _SC_BC_BASE_MAX: ::c_int = 36; +pub const _SC_BC_DIM_MAX: ::c_int = 37; +pub const _SC_BC_SCALE_MAX: ::c_int = 38; +pub const _SC_BC_STRING_MAX: ::c_int = 39; +pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 40; +pub const _SC_EXPR_NEST_MAX: ::c_int = 42; +pub const _SC_LINE_MAX: ::c_int = 43; +pub const _SC_RE_DUP_MAX: ::c_int = 44; +pub const _SC_2_VERSION: ::c_int = 46; +pub const _SC_2_C_BIND: ::c_int = 47; +pub const _SC_2_C_DEV: ::c_int = 48; +pub const _SC_2_FORT_DEV: ::c_int = 49; +pub const _SC_2_FORT_RUN: ::c_int = 50; +pub const _SC_2_SW_DEV: ::c_int = 51; +pub const _SC_2_LOCALEDEF: ::c_int = 52; +pub const _SC_IOV_MAX: ::c_int = 60; +pub const _SC_THREADS: ::c_int = 67; +pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 68; +pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 69; +pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 70; +pub const _SC_LOGIN_NAME_MAX: ::c_int = 71; +pub const _SC_TTY_NAME_MAX: ::c_int = 72; +pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 73; +pub const _SC_THREAD_KEYS_MAX: ::c_int = 74; +pub const _SC_THREAD_STACK_MIN: ::c_int = 75; +pub const _SC_THREAD_THREADS_MAX: ::c_int = 76; +pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 77; +pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 78; +pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 79; +pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 80; +pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 81; +pub const _SC_NPROCESSORS_ONLN: ::c_int = 84; +pub const _SC_ATEXIT_MAX: ::c_int = 87; +pub const _SC_XOPEN_VERSION: ::c_int = 89; +pub const _SC_XOPEN_XCU_VERSION: ::c_int = 90; +pub const _SC_XOPEN_UNIX: ::c_int = 91; +pub const _SC_XOPEN_CRYPT: ::c_int = 92; +pub const _SC_XOPEN_ENH_I18N: ::c_int = 93; +pub const _SC_XOPEN_SHM: ::c_int = 94; +pub const _SC_2_CHAR_TERM: ::c_int = 95; +pub const _SC_2_UPE: ::c_int = 97; +pub const _SC_XBS5_ILP32_OFF32: ::c_int = 125; +pub const _SC_XBS5_ILP32_OFFBIG: ::c_int = 126; +pub const _SC_XBS5_LPBIG_OFFBIG: ::c_int = 128; +pub const _SC_XOPEN_LEGACY: ::c_int = 129; +pub const _SC_XOPEN_REALTIME: ::c_int = 130; +pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 131; +pub const _SC_HOST_NAME_MAX: ::c_int = 180; + +pub const RLIM_SAVED_MAX: ::rlim_t = RLIM_INFINITY; +pub const RLIM_SAVED_CUR: ::rlim_t = RLIM_INFINITY; + +pub const GLOB_ERR: ::c_int = 1 << 0; +pub const GLOB_MARK: ::c_int = 1 << 1; +pub const GLOB_NOSORT: ::c_int = 1 << 2; +pub const GLOB_DOOFFS: ::c_int = 1 << 3; +pub const GLOB_NOCHECK: ::c_int = 1 << 4; +pub const GLOB_APPEND: ::c_int = 1 << 5; +pub const GLOB_NOESCAPE: ::c_int = 1 << 6; + +pub const GLOB_NOSPACE: ::c_int = 1; +pub const GLOB_ABORTED: ::c_int = 2; +pub const GLOB_NOMATCH: ::c_int = 3; + +pub const POSIX_MADV_NORMAL: ::c_int = 0; +pub const POSIX_MADV_RANDOM: ::c_int = 1; +pub const POSIX_MADV_SEQUENTIAL: ::c_int = 2; +pub const POSIX_MADV_WILLNEED: ::c_int = 3; + +pub const S_IEXEC: mode_t = 64; +pub const S_IWRITE: mode_t = 128; +pub const S_IREAD: mode_t = 256; + +pub const F_LOCK: ::c_int = 1; +pub const F_TEST: ::c_int = 3; +pub const F_TLOCK: ::c_int = 2; +pub const F_ULOCK: ::c_int = 0; + +pub const ST_RDONLY: ::c_ulong = 1; +pub const ST_NOSUID: ::c_ulong = 2; +pub const ST_NODEV: ::c_ulong = 4; +pub const ST_NOEXEC: ::c_ulong = 8; +pub const ST_SYNCHRONOUS: ::c_ulong = 16; +pub const ST_MANDLOCK: ::c_ulong = 64; +pub const ST_WRITE: ::c_ulong = 128; +pub const ST_APPEND: ::c_ulong = 256; +pub const ST_IMMUTABLE: ::c_ulong = 512; +pub const ST_NOATIME: ::c_ulong = 1024; +pub const ST_NODIRATIME: ::c_ulong = 2048; + +pub const RTLD_NEXT: *mut ::c_void = -1i64 as *mut ::c_void; +pub const RTLD_DEFAULT: *mut ::c_void = 0i64 as *mut ::c_void; +pub const RTLD_NODELETE: ::c_int = 0x1000; +pub const RTLD_NOW: ::c_int = 0x2; + +pub const TCP_MD5SIG: ::c_int = 14; + +pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { + __align: [], + size: [0; __SIZEOF_PTHREAD_MUTEX_T], +}; +pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { + __align: [], + size: [0; __SIZEOF_PTHREAD_COND_T], +}; +pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { + __align: [], + size: [0; __SIZEOF_PTHREAD_RWLOCK_T], +}; +pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; +pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1; +pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2; +pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_NORMAL; +pub const __SIZEOF_PTHREAD_COND_T: usize = 48; + +pub const SCHED_OTHER: ::c_int = 0; +pub const SCHED_FIFO: ::c_int = 1; +pub const SCHED_RR: ::c_int = 2; +pub const SCHED_BATCH: ::c_int = 3; +pub const SCHED_IDLE: ::c_int = 5; + +// System V IPC +pub const IPC_PRIVATE: ::key_t = 0; + +pub const IPC_CREAT: ::c_int = 0o1000; +pub const IPC_EXCL: ::c_int = 0o2000; +pub const IPC_NOWAIT: ::c_int = 0o4000; + +pub const IPC_RMID: ::c_int = 0; +pub const IPC_SET: ::c_int = 1; +pub const IPC_STAT: ::c_int = 2; +pub const IPC_INFO: ::c_int = 3; +pub const MSG_STAT: ::c_int = 11; +pub const MSG_INFO: ::c_int = 12; + +pub const MSG_NOERROR: ::c_int = 0o10000; +pub const MSG_EXCEPT: ::c_int = 0o20000; + +pub const SHM_R: ::c_int = 0o400; +pub const SHM_W: ::c_int = 0o200; + +pub const SHM_RDONLY: ::c_int = 0o10000; +pub const SHM_RND: ::c_int = 0o20000; +pub const SHM_REMAP: ::c_int = 0o40000; + +pub const SHM_LOCK: ::c_int = 11; +pub const SHM_UNLOCK: ::c_int = 12; + +pub const SHM_HUGETLB: ::c_int = 0o4000; +pub const SHM_NORESERVE: ::c_int = 0o10000; + +pub const EPOLLRDHUP: ::c_int = 0x2000; +pub const EPOLLONESHOT: ::c_int = 0x40000000; + +pub const QFMT_VFS_OLD: ::c_int = 1; +pub const QFMT_VFS_V0: ::c_int = 2; + +pub const EFD_SEMAPHORE: ::c_int = 0x1; + +pub const LOG_NFACILITIES: ::c_int = 24; + +pub const SEM_FAILED: *mut ::sem_t = 0 as *mut sem_t; + +pub const RB_AUTOBOOT: ::c_int = 0x01234567u32 as i32; +pub const RB_HALT_SYSTEM: ::c_int = 0xcdef0123u32 as i32; +pub const RB_ENABLE_CAD: ::c_int = 0x89abcdefu32 as i32; +pub const RB_DISABLE_CAD: ::c_int = 0x00000000u32 as i32; +pub const RB_POWER_OFF: ::c_int = 0x4321fedcu32 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; + +pub const EAI_SYSTEM: ::c_int = -11; + +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 ABDAY_1: ::nl_item = 0x300; +pub const ABDAY_2: ::nl_item = 0x301; +pub const ABDAY_3: ::nl_item = 0x302; +pub const ABDAY_4: ::nl_item = 0x303; +pub const ABDAY_5: ::nl_item = 0x304; +pub const ABDAY_6: ::nl_item = 0x305; +pub const ABDAY_7: ::nl_item = 0x306; + +pub const DAY_1: ::nl_item = 0x307; +pub const DAY_2: ::nl_item = 0x308; +pub const DAY_3: ::nl_item = 0x309; +pub const DAY_4: ::nl_item = 0x30A; +pub const DAY_5: ::nl_item = 0x30B; +pub const DAY_6: ::nl_item = 0x30C; +pub const DAY_7: ::nl_item = 0x30D; + +pub const ABMON_1: ::nl_item = 0x30E; +pub const ABMON_2: ::nl_item = 0x30F; +pub const ABMON_3: ::nl_item = 0x310; +pub const ABMON_4: ::nl_item = 0x311; +pub const ABMON_5: ::nl_item = 0x312; +pub const ABMON_6: ::nl_item = 0x313; +pub const ABMON_7: ::nl_item = 0x314; +pub const ABMON_8: ::nl_item = 0x315; +pub const ABMON_9: ::nl_item = 0x316; +pub const ABMON_10: ::nl_item = 0x317; +pub const ABMON_11: ::nl_item = 0x318; +pub const ABMON_12: ::nl_item = 0x319; + +pub const MON_1: ::nl_item = 0x31A; +pub const MON_2: ::nl_item = 0x31B; +pub const MON_3: ::nl_item = 0x31C; +pub const MON_4: ::nl_item = 0x31D; +pub const MON_5: ::nl_item = 0x31E; +pub const MON_6: ::nl_item = 0x31F; +pub const MON_7: ::nl_item = 0x320; +pub const MON_8: ::nl_item = 0x321; +pub const MON_9: ::nl_item = 0x322; +pub const MON_10: ::nl_item = 0x323; +pub const MON_11: ::nl_item = 0x324; +pub const MON_12: ::nl_item = 0x325; + +pub const AM_STR: ::nl_item = 0x326; +pub const PM_STR: ::nl_item = 0x327; + +pub const D_T_FMT: ::nl_item = 0x328; +pub const D_FMT: ::nl_item = 0x329; +pub const T_FMT: ::nl_item = 0x32A; +pub const T_FMT_AMPM: ::nl_item = 0x32B; + +pub const ERA: ::nl_item = 0x32C; +pub const ERA_D_FMT: ::nl_item = 0x32E; +pub const ALT_DIGITS: ::nl_item = 0x32F; +pub const ERA_D_T_FMT: ::nl_item = 0x330; +pub const ERA_T_FMT: ::nl_item = 0x331; + +pub const CODESET: ::nl_item = 10; + +pub const CRNCYSTR: ::nl_item = 0x215; + +pub const RADIXCHAR: ::nl_item = 0x100; +pub const THOUSEP: ::nl_item = 0x101; + +pub const NOEXPR: ::nl_item = 0x501; +pub const YESSTR: ::nl_item = 0x502; +pub const NOSTR: ::nl_item = 0x503; + +pub const FILENAME_MAX: ::c_uint = 4095; + +pub const AF_MAX: ::c_int = 39; + +f! { + pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () { + let fd = fd as usize; + let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; + (*set).fds_bits[fd / size] &= !(1 << (fd % size)); + return + } + + pub fn FD_ISSET(fd: ::c_int, set: *mut fd_set) -> bool { + let fd = fd as usize; + let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; + return ((*set).fds_bits[fd / size] & (1 << (fd % size))) != 0 + } + + pub fn FD_SET(fd: ::c_int, set: *mut fd_set) -> () { + let fd = fd as usize; + let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; + (*set).fds_bits[fd / size] |= 1 << (fd % size); + return + } + + pub fn FD_ZERO(set: *mut fd_set) -> () { + for slot in (*set).fds_bits.iter_mut() { + *slot = 0; + } + } + + pub fn WIFSTOPPED(status: ::c_int) -> bool { + (status & 0xff) == 0x7f + } + + pub fn WSTOPSIG(status: ::c_int) -> ::c_int { + (status >> 8) & 0xff + } + + pub fn WIFCONTINUED(status: ::c_int) -> bool { + status == 0xffff + } + + pub fn WIFSIGNALED(status: ::c_int) -> bool { + ((status & 0x7f) + 1) as i8 >= 2 + } + + pub fn WTERMSIG(status: ::c_int) -> ::c_int { + status & 0x7f + } + + pub fn WIFEXITED(status: ::c_int) -> bool { + (status & 0x7f) == 0 + } + + pub fn WEXITSTATUS(status: ::c_int) -> ::c_int { + (status >> 8) & 0xff + } + + pub fn WCOREDUMP(status: ::c_int) -> bool { + (status & 0x80) != 0 + } + + pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { + for slot in cpuset.bits.iter_mut() { + *slot = 0; + } + } + + pub fn CPU_SET(cpu: usize, cpuset: &mut cpu_set_t) -> () { + let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc + let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); + cpuset.bits[idx] |= 1 << offset; + () + } + + pub fn CPU_CLR(cpu: usize, cpuset: &mut cpu_set_t) -> () { + let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc + let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); + cpuset.bits[idx] &= !(1 << offset); + () + } + + pub fn CPU_ISSET(cpu: usize, cpuset: &cpu_set_t) -> bool { + let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]); + let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); + 0 != (cpuset.bits[idx] & (1 << offset)) + } + + pub fn CPU_EQUAL(set1: &cpu_set_t, set2: &cpu_set_t) -> bool { + set1.bits == set2.bits + } +} + +extern { + pub fn getpwnam_r(name: *const ::c_char, + pwd: *mut passwd, + buf: *mut ::c_char, + buflen: ::size_t, + result: *mut *mut passwd) -> ::c_int; + pub fn getpwuid_r(uid: ::uid_t, + pwd: *mut passwd, + buf: *mut ::c_char, + buflen: ::size_t, + result: *mut *mut passwd) -> ::c_int; + pub fn fdatasync(fd: ::c_int) -> ::c_int; + pub fn mincore(addr: *mut ::c_void, len: ::size_t, + vec: *mut ::c_uchar) -> ::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_nanosleep(clk_id: clockid_t, + 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; + 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, + stackaddr: *mut *mut ::c_void, + stacksize: *mut ::size_t) -> ::c_int; + 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; + pub fn sched_getscheduler(pid: ::pid_t) -> ::c_int; + pub fn sched_get_priority_max(policy: ::c_int) -> ::c_int; + pub fn sched_get_priority_min(policy: ::c_int) -> ::c_int; + pub fn epoll_create(size: ::c_int) -> ::c_int; + pub fn epoll_create1(flags: ::c_int) -> ::c_int; + pub fn epoll_ctl(epfd: ::c_int, + op: ::c_int, + fd: ::c_int, + event: *mut epoll_event) -> ::c_int; + pub fn epoll_wait(epfd: ::c_int, + events: *mut epoll_event, + maxevents: ::c_int, + timeout: ::c_int) -> ::c_int; + pub fn pipe2(fds: *mut ::c_int, flags: ::c_int) -> ::c_int; + pub fn mount(src: *const ::c_char, + target: *const ::c_char, + fstype: *const ::c_char, + flags: ::c_ulong, + data: *const ::c_void) -> ::c_int; + pub fn umount(target: *const ::c_char) -> ::c_int; + pub fn umount2(target: *const ::c_char, flags: ::c_int) -> ::c_int; + pub fn clone(cb: extern fn(*mut ::c_void) -> ::c_int, + child_stack: *mut ::c_void, + flags: ::c_int, + arg: *mut ::c_void, ...) -> ::c_int; + pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int; + pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int; + pub fn memrchr(cx: *const ::c_void, + c: ::c_int, + n: ::size_t) -> *mut ::c_void; + pub fn syscall(num: ::c_long, ...) -> ::c_long; + pub fn sendfile(out_fd: ::c_int, + in_fd: ::c_int, + offset: *mut off_t, + count: ::size_t) -> ::ssize_t; + pub fn splice(fd_in: ::c_int, + off_in: *mut ::loff_t, + fd_out: ::c_int, + off_out: *mut ::loff_t, + len: ::size_t, + flags: ::c_uint) -> ::ssize_t; + pub fn tee(fd_in: ::c_int, + fd_out: ::c_int, + len: ::size_t, + flags: ::c_uint) -> ::ssize_t; + pub fn vmsplice(fd: ::c_int, + iov: *const ::iovec, + nr_segs: ::size_t, + flags: ::c_uint) -> ::ssize_t; + + pub fn posix_fadvise(fd: ::c_int, offset: ::off_t, len: ::off_t, + advise: ::c_int) -> ::c_int; + pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int; + pub fn utimensat(dirfd: ::c_int, path: *const ::c_char, + times: *const ::timespec, flag: ::c_int) -> ::c_int; + pub fn duplocale(base: ::locale_t) -> ::locale_t; + pub fn freelocale(loc: ::locale_t); + pub fn newlocale(mask: ::c_int, + locale: *const ::c_char, + base: ::locale_t) -> ::locale_t; + pub fn uselocale(loc: ::locale_t) -> ::locale_t; + pub fn creat64(path: *const c_char, mode: mode_t) -> ::c_int; + pub fn fstat64(fildes: ::c_int, buf: *mut stat64) -> ::c_int; + pub fn ftruncate64(fd: ::c_int, length: off64_t) -> ::c_int; + pub fn getrlimit64(resource: ::c_int, rlim: *mut rlimit64) -> ::c_int; + pub fn lseek64(fd: ::c_int, offset: off64_t, whence: ::c_int) -> off64_t; + pub fn lstat64(path: *const c_char, buf: *mut stat64) -> ::c_int; + pub fn mmap64(addr: *mut ::c_void, + len: ::size_t, + prot: ::c_int, + flags: ::c_int, + fd: ::c_int, + offset: off64_t) + -> *mut ::c_void; + pub fn open64(path: *const c_char, oflag: ::c_int, ...) -> ::c_int; + pub fn openat64(fd: ::c_int, + path: *const c_char, + oflag: ::c_int, ...) -> ::c_int; + pub fn pread64(fd: ::c_int, buf: *mut ::c_void, count: ::size_t, + offset: off64_t) -> ::ssize_t; + pub fn pwrite64(fd: ::c_int, buf: *const ::c_void, count: ::size_t, + offset: off64_t) -> ::ssize_t; + pub fn readdir64(dirp: *mut ::DIR) -> *mut ::dirent64; + pub fn readdir64_r(dirp: *mut ::DIR, entry: *mut ::dirent64, + result: *mut *mut ::dirent64) -> ::c_int; + pub fn setrlimit64(resource: ::c_int, rlim: *const rlimit64) -> ::c_int; + pub fn stat64(path: *const c_char, buf: *mut stat64) -> ::c_int; + pub fn truncate64(path: *const c_char, length: off64_t) -> ::c_int; + pub fn eventfd(init: ::c_uint, flags: ::c_int) -> ::c_int; + + pub fn fdopendir(fd: ::c_int) -> *mut ::DIR; + + pub fn mknodat(dirfd: ::c_int, pathname: *const ::c_char, + mode: ::mode_t, dev: dev_t) -> ::c_int; + pub fn ppoll(fds: *mut ::pollfd, + nfds: nfds_t, + timeout: *const ::timespec, + sigmask: *const sigset_t) -> ::c_int; + pub fn pthread_condattr_getclock(attr: *const pthread_condattr_t, + clock_id: *mut clockid_t) -> ::c_int; + pub fn pthread_condattr_setclock(attr: *mut pthread_condattr_t, + clock_id: clockid_t) -> ::c_int; + pub fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, + pshared: ::c_int) -> ::c_int; + pub fn pthread_condattr_getpshared(attr: *const pthread_condattr_t, + pshared: *mut ::c_int) -> ::c_int; + pub fn sched_getaffinity(pid: ::pid_t, + cpusetsize: ::size_t, + cpuset: *mut cpu_set_t) -> ::c_int; + pub fn sched_setaffinity(pid: ::pid_t, + cpusetsize: ::size_t, + cpuset: *const cpu_set_t) -> ::c_int; + pub fn unshare(flags: ::c_int) -> ::c_int; + pub fn sem_timedwait(sem: *mut sem_t, + abstime: *const ::timespec) -> ::c_int; + pub fn accept4(fd: ::c_int, addr: *mut ::sockaddr, len: *mut ::socklen_t, + flg: ::c_int) -> ::c_int; + pub fn pthread_mutex_timedlock(lock: *mut pthread_mutex_t, + abstime: *const ::timespec) -> ::c_int; + pub fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, + pshared: ::c_int) -> ::c_int; + pub fn pthread_mutexattr_getpshared(attr: *const pthread_mutexattr_t, + pshared: *mut ::c_int) -> ::c_int; + pub fn pthread_rwlockattr_getkind_np(attr: *const pthread_rwlockattr_t, + val: *mut ::c_int) -> ::c_int; + pub fn pthread_rwlockattr_setkind_np(attr: *mut pthread_rwlockattr_t, + val: ::c_int) -> ::c_int; + pub fn pthread_rwlockattr_getpshared(attr: *const pthread_rwlockattr_t, + val: *mut ::c_int) -> ::c_int; + pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, + val: ::c_int) -> ::c_int; + pub fn ptsname_r(fd: ::c_int, + buf: *mut ::c_char, + buflen: ::size_t) -> ::c_int; + pub fn clearenv() -> ::c_int; + pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t, + options: ::c_int) -> ::c_int; + + pub fn lutimes(file: *const ::c_char, times: *const ::timeval) -> ::c_int; + + pub fn setpwent(); + pub fn getpwent() -> *mut passwd; + pub fn setspent(); + pub fn endspent(); + pub fn getspent() -> *mut spwd; + pub fn getspnam(__name: *const ::c_char) -> *mut spwd; + + pub fn shm_open(name: *const c_char, oflag: ::c_int, + mode: mode_t) -> ::c_int; + + // System V IPC + pub fn shmget(key: ::key_t, size: ::size_t, shmflg: ::c_int) -> ::c_int; + pub fn shmat(shmid: ::c_int, + shmaddr: *const ::c_void, + shmflg: ::c_int) -> *mut ::c_void; + pub fn shmdt(shmaddr: *const ::c_void) -> ::c_int; + pub fn shmctl(shmid: ::c_int, + cmd: ::c_int, + buf: *mut ::shmid_ds) -> ::c_int; + pub fn ftok(pathname: *const ::c_char, proj_id: ::c_int) -> ::key_t; + pub fn msgctl(msqid: ::c_int, cmd: ::c_int, buf: *mut msqid_ds) -> ::c_int; + pub fn msgget(key: ::key_t, msgflg: ::c_int) -> ::c_int; + pub fn msgrcv(msqid: ::c_int, msgp: *mut ::c_void, msgsz: ::size_t, + msgtyp: ::c_long, msgflg: ::c_int) -> ::ssize_t; + pub fn msgsnd(msqid: ::c_int, msgp: *const ::c_void, msgsz: ::size_t, + msgflg: ::c_int) -> ::c_int; + + pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) + -> ::c_int; + pub fn __errno_location() -> *mut ::c_int; + + pub fn fopen64(filename: *const c_char, + mode: *const c_char) -> *mut ::FILE; + pub fn freopen64(filename: *const c_char, mode: *const c_char, + file: *mut ::FILE) -> *mut ::FILE; + pub fn tmpfile64() -> *mut ::FILE; + pub fn fgetpos64(stream: *mut ::FILE, ptr: *mut fpos64_t) -> ::c_int; + pub fn fsetpos64(stream: *mut ::FILE, ptr: *const fpos64_t) -> ::c_int; + pub fn fseeko64(stream: *mut ::FILE, + offset: ::off64_t, + whence: ::c_int) -> ::c_int; + pub fn ftello64(stream: *mut ::FILE) -> ::off64_t; + pub fn readahead(fd: ::c_int, offset: ::off64_t, + count: ::size_t) -> ::ssize_t; + pub fn getxattr(path: *const c_char, name: *const c_char, + value: *mut ::c_void, size: ::size_t) -> ::ssize_t; + pub fn lgetxattr(path: *const c_char, name: *const c_char, + value: *mut ::c_void, size: ::size_t) -> ::ssize_t; + pub fn fgetxattr(filedes: ::c_int, name: *const c_char, + value: *mut ::c_void, size: ::size_t) -> ::ssize_t; + pub fn setxattr(path: *const c_char, name: *const c_char, + value: *const ::c_void, size: ::size_t, + flags: ::c_int) -> ::c_int; + pub fn lsetxattr(path: *const c_char, name: *const c_char, + value: *const ::c_void, size: ::size_t, + flags: ::c_int) -> ::c_int; + pub fn fsetxattr(filedes: ::c_int, name: *const c_char, + value: *const ::c_void, size: ::size_t, + flags: ::c_int) -> ::c_int; + pub fn listxattr(path: *const c_char, list: *mut c_char, + size: ::size_t) -> ::ssize_t; + pub fn llistxattr(path: *const c_char, list: *mut c_char, + size: ::size_t) -> ::ssize_t; + pub fn flistxattr(filedes: ::c_int, list: *mut c_char, + size: ::size_t) -> ::ssize_t; + pub fn removexattr(path: *const c_char, name: *const c_char) -> ::c_int; + pub fn lremovexattr(path: *const c_char, name: *const c_char) -> ::c_int; + pub fn fremovexattr(filedes: ::c_int, name: *const c_char) -> ::c_int; + pub fn signalfd(fd: ::c_int, + mask: *const ::sigset_t, + flags: ::c_int) -> ::c_int; + pub fn quotactl(cmd: ::c_int, + special: *const ::c_char, + id: ::c_int, + data: *mut ::c_char) -> ::c_int; + pub fn mq_open(name: *const ::c_char, oflag: ::c_int, ...) -> ::mqd_t; + pub fn mq_close(mqd: ::mqd_t) -> ::c_int; + pub fn mq_unlink(name: *const ::c_char) -> ::c_int; + pub fn mq_receive(mqd: ::mqd_t, + msg_ptr: *mut ::c_char, + msg_len: ::size_t, + msq_prio: *mut ::c_uint) -> ::ssize_t; + pub fn mq_send(mqd: ::mqd_t, + msg_ptr: *const ::c_char, + msg_len: ::size_t, + msq_prio: ::c_uint) -> ::c_int; + pub fn mq_getattr(mqd: ::mqd_t, attr: *mut ::mq_attr) -> ::c_int; + pub fn mq_setattr(mqd: ::mqd_t, + newattr: *const ::mq_attr, + oldattr: *mut ::mq_attr) -> ::c_int; + pub fn epoll_pwait(epfd: ::c_int, + events: *mut ::epoll_event, + maxevents: ::c_int, + timeout: ::c_int, + sigmask: *const ::sigset_t) -> ::c_int; + pub fn sethostname(name: *const ::c_char, len: ::size_t) -> ::c_int; + pub fn sigtimedwait(set: *const sigset_t, + info: *mut siginfo_t, + timeout: *const ::timespec) -> ::c_int; + pub fn sigwaitinfo(set: *const sigset_t, + info: *mut siginfo_t) -> ::c_int; + pub fn nl_langinfo_l(item: ::nl_item, locale: ::locale_t) -> *mut ::c_char; + pub fn prlimit(pid: ::pid_t, resource: ::c_int, new_limit: *const ::rlimit, + old_limit: *mut ::rlimit) -> ::c_int; + pub fn prlimit64(pid: ::pid_t, + resource: ::c_int, + new_limit: *const ::rlimit64, + old_limit: *mut ::rlimit64) -> ::c_int; + pub fn reboot(how_to: ::c_int) -> ::c_int; + pub fn setfsgid(gid: ::gid_t) -> ::c_int; + pub fn setfsuid(uid: ::uid_t) -> ::c_int; + pub fn setresgid(rgid: ::gid_t, egid: ::gid_t, sgid: ::gid_t) -> ::c_int; + pub fn setresuid(ruid: ::uid_t, euid: ::uid_t, suid: ::uid_t) -> ::c_int; + + // Not available now on Android + pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char, + mode: ::mode_t) -> ::c_int; + pub fn if_nameindex() -> *mut if_nameindex; + pub fn if_freenameindex(ptr: *mut if_nameindex); + pub fn sync_file_range(fd: ::c_int, offset: ::off64_t, + 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; + + pub fn glob(pattern: *const c_char, + flags: ::c_int, + errfunc: Option ::c_int>, + pglob: *mut ::glob_t) -> ::c_int; + pub fn globfree(pglob: *mut ::glob_t); + + pub fn shm_unlink(name: *const ::c_char) -> ::c_int; + + pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long); + + pub fn telldir(dirp: *mut ::DIR) -> ::c_long; + pub fn madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) + -> ::c_int; + + pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int; + + pub fn recvfrom(socket: ::c_int, buf: *mut ::c_void, len: ::size_t, + flags: ::c_int, addr: *mut ::sockaddr, + addrlen: *mut ::socklen_t) -> ::ssize_t; + pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char; + + pub fn bind(socket: ::c_int, address: *const ::sockaddr, + address_len: ::socklen_t) -> ::c_int; + + pub fn writev(fd: ::c_int, + iov: *const ::iovec, + iovcnt: ::c_int) -> ::ssize_t; + pub fn readv(fd: ::c_int, + iov: *const ::iovec, + iovcnt: ::c_int) -> ::ssize_t; + + pub fn sendmsg(fd: ::c_int, + msg: *const ::msghdr, + flags: ::c_int) -> ::ssize_t; + pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int) + -> ::ssize_t; +} + +cfg_if! { + if #[cfg(target_arch = "mips")] { + mod mips; + pub use self::mips::*; + } else if #[cfg(target_arch = "x86_64")] { + mod x86_64; + pub use self::x86_64::*; + } else { + pub use unsupported_target; + } +} + diff --git a/src/vendor/libc/src/unix/uclibc/x86_64/mod.rs b/src/vendor/libc/src/unix/uclibc/x86_64/mod.rs new file mode 100644 index 0000000000..603efb10fc --- /dev/null +++ b/src/vendor/libc/src/unix/uclibc/x86_64/mod.rs @@ -0,0 +1,361 @@ +//! Definitions for l4re-uclibc on 64bit systems + +pub type blkcnt_t = i64; +pub type blksize_t = i64; +pub type clock_t = i64; +pub type c_char = u8; +pub type c_long = i64; +pub type c_ulong = u64; +pub type fsblkcnt_t = ::c_ulong; +pub type fsfilcnt_t = ::c_ulong; +pub type fsword_t = ::c_long; +pub type ino_t = ::c_ulong; +pub type nlink_t = ::c_uint; +pub type off_t = ::c_long; +pub type rlim_t = c_ulong; +pub type rlim64_t = u64; +pub type suseconds_t = ::c_long; +pub type time_t = ::c_int; +pub type wchar_t = ::c_int; + +// ToDo, used? +//pub type d_ino = ::c_ulong; +pub type nfds_t = ::c_ulong; + +s! { + 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: ::c_ushort, // read / write + __pad1: ::c_ushort, + pub __seq: ::c_ushort, + __pad2: ::c_ushort, + __unused1: ::c_ulong, + __unused2: ::c_ulong + } + + pub struct siginfo_t { + si_signo: ::c_int, // signal number + si_errno: ::c_int, // if not zero: error value of signal, see errno.h + si_code: ::c_int, // signal code + pub _pad: [::c_int; 28], // unported union + _align: [usize; 0], + } + + pub struct shmid_ds { + pub shm_perm: ::ipc_perm, + pub shm_segsz: ::size_t, // segment size in bytes + pub shm_atime: ::time_t, // time of last shmat() + pub shm_dtime: ::time_t, + pub shm_ctime: ::time_t, + pub shm_cpid: ::pid_t, + pub shm_lpid: ::pid_t, + pub shm_nattch: ::shmatt_t, + __unused1: ::c_ulong, + __unused2: ::c_ulong + } + + pub struct msqid_ds { + pub msg_perm: ::ipc_perm, + pub msg_stime: ::time_t, + pub msg_rtime: ::time_t, + pub msg_ctime: ::time_t, + __msg_cbytes: ::c_ulong, + pub msg_qnum: ::msgqnum_t, + pub msg_qbytes: ::msglen_t, + pub msg_lspid: ::pid_t, + pub msg_lrpid: ::pid_t, + __ignored1: ::c_ulong, + __ignored2: ::c_ulong, + } + + pub struct sockaddr { + pub sa_family: ::sa_family_t, + pub sa_data: [::c_char; 14], + } + + pub struct sockaddr_in { + pub sin_family: ::sa_family_t, + pub sin_port: ::in_port_t, + pub sin_addr: ::in_addr, + pub sin_zero: [u8; 8], + } + + pub struct sockaddr_in6 { + pub sin6_family: ::sa_family_t, + pub sin6_port: ::in_port_t, + pub sin6_flowinfo: u32, + pub sin6_addr: ::in6_addr, + pub sin6_scope_id: u32, + } + + // ------------------------------------------------------------ + // definitions below are *unverified* and might **break** the software +// pub struct in_addr { +// pub s_addr: in_addr_t, +// } +// +// pub struct in6_addr { +// pub s6_addr: [u8; 16], +// __align: [u32; 0], +// } + + pub struct stat { // ToDo + pub st_dev: ::c_ulong, + st_pad1: [::c_long; 2], + 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: u64, + pub st_pad2: [u64; 1], + pub st_size: off_t, + st_pad3: ::c_long, + pub st_atime: ::time_t, + pub st_atime_nsec: ::c_long, + pub st_mtime: ::time_t, + pub st_mtime_nsec: ::c_long, + pub st_ctime: ::time_t, + pub st_ctime_nsec: ::c_long, + pub st_blksize: ::blksize_t, + st_pad4: ::c_long, + pub st_blocks: ::blkcnt_t, + st_pad5: [::c_long; 7], + } + + pub struct statvfs { // ToDo: broken + pub f_bsize: ::c_ulong, + pub f_frsize: ::c_ulong, + pub f_blocks: ::fsblkcnt_t, + pub f_bfree: ::fsblkcnt_t, + pub f_bavail: ::fsblkcnt_t, + pub f_files: ::fsfilcnt_t, + pub f_ffree: ::fsfilcnt_t, + pub f_favail: ::fsfilcnt_t, + #[cfg(target_endian = "little")] + pub f_fsid: ::c_ulong, + #[cfg(target_pointer_width = "32")] + __f_unused: ::c_int, + #[cfg(target_endian = "big")] + pub f_fsid: ::c_ulong, + pub f_flag: ::c_ulong, + pub f_namemax: ::c_ulong, + __f_spare: [::c_int; 6], + } + + pub struct dirent { // Todo + pub d_ino: ::ino64_t, + pub d_off: ::off64_t, + d_reclen: u16, + pub d_type: u8, + pub d_name: [i8; 256], + } + + pub struct dirent64 { // + pub d_ino: ::ino64_t, + pub d_off: ::off64_t, + pub d_reclen: u16, + pub d_type: u8, + pub d_name: [i8; 256], + } + + pub struct pthread_attr_t { // ToDo + __size: [u64; 7] + } + + pub struct sigaction { // TODO!! + 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, + } + + pub struct stack_t { // ToDo + pub ss_sp: *mut ::c_void, + pub ss_flags: ::c_int, + pub ss_size: ::size_t + } + + pub struct statfs { // ToDo + pub f_type: fsword_t, + pub f_bsize: fsword_t, + pub f_blocks: ::fsblkcnt_t, + pub f_bfree: ::fsblkcnt_t, + pub f_bavail: ::fsblkcnt_t, + pub f_files: ::fsfilcnt_t, + pub f_ffree: ::fsfilcnt_t, + pub f_fsid: ::fsid_t, + pub f_namelen: fsword_t, + pub f_frsize: fsword_t, + f_spare: [fsword_t; 5], + } + + pub struct msghdr { // ToDo + pub msg_name: *mut ::c_void, + pub msg_namelen: ::socklen_t, + pub msg_iov: *mut ::iovec, + pub msg_iovlen: ::size_t, + pub msg_control: *mut ::c_void, + pub msg_controllen: ::size_t, + pub msg_flags: ::c_int, + } + + pub struct termios { // ToDo + pub c_iflag: ::tcflag_t, + pub c_oflag: ::tcflag_t, + pub c_cflag: ::tcflag_t, + pub c_lflag: ::tcflag_t, + pub c_line: ::cc_t, + pub c_cc: [::cc_t; ::NCCS], + } + + pub struct sem_t { // ToDo + #[cfg(target_pointer_width = "32")] + __size: [::c_char; 16], + #[cfg(target_pointer_width = "64")] + __size: [::c_char; 32], + __align: [::c_long; 0], + } + + pub struct pthread_mutex_t { // ToDo + #[cfg(any(target_arch = "mips", target_arch = "arm", + target_arch = "powerpc"))] + __align: [::c_long; 0], + #[cfg(not(any(target_arch = "mips", target_arch = "arm", + target_arch = "powerpc")))] + __align: [::c_longlong; 0], + size: [u8; __SIZEOF_PTHREAD_MUTEX_T], + } + + pub struct pthread_mutexattr_t { // ToDo + #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64"))] + __align: [::c_int; 0], + #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64")))] + __align: [::c_long; 0], + size: [u8; __SIZEOF_PTHREAD_MUTEXATTR_T], + } + + pub struct pthread_cond_t { // ToDo + __align: [::c_longlong; 0], + size: [u8; __SIZEOF_PTHREAD_COND_T], + } + + pub struct pthread_condattr_t { // ToDo + __align: [::c_int; 0], + size: [u8; __SIZEOF_PTHREAD_CONDATTR_T], + } + + pub struct pthread_rwlock_t { // ToDo + #[cfg(any(target_arch = "mips", target_arch = "arm", + target_arch = "powerpc"))] + __align: [::c_long; 0], + #[cfg(not(any(target_arch = "mips", target_arch = "arm", + target_arch = "powerpc")))] + __align: [::c_longlong; 0], + size: [u8; __SIZEOF_PTHREAD_RWLOCK_T], + } + + pub struct sigset_t { // ToDo + __val: [::c_ulong; 16], + } + + pub struct sysinfo { // ToDo + pub uptime: ::c_long, + pub loads: [::c_ulong; 3], + pub totalram: ::c_ulong, + pub freeram: ::c_ulong, + pub sharedram: ::c_ulong, + pub bufferram: ::c_ulong, + pub totalswap: ::c_ulong, + pub freeswap: ::c_ulong, + pub procs: ::c_ushort, + pub pad: ::c_ushort, + pub totalhigh: ::c_ulong, + pub freehigh: ::c_ulong, + pub mem_unit: ::c_uint, + pub _f: [::c_char; 0], + } + + pub struct glob_t { // ToDo + pub gl_pathc: ::size_t, + pub gl_pathv: *mut *mut c_char, + pub gl_offs: ::size_t, + pub gl_flags: ::c_int, + __unused1: *mut ::c_void, + __unused2: *mut ::c_void, + __unused3: *mut ::c_void, + __unused4: *mut ::c_void, + __unused5: *mut ::c_void, + } + + pub struct stat64 { // ToDo + pub st_dev: ::dev_t, + pub st_ino: ::ino64_t, + pub st_nlink: ::nlink_t, + pub st_mode: ::mode_t, + pub st_uid: ::uid_t, + pub st_gid: ::gid_t, + __pad0: ::c_int, + pub st_rdev: ::dev_t, + pub st_size: ::off_t, + pub st_blksize: ::blksize_t, + pub st_blocks: ::blkcnt64_t, + pub st_atime: ::time_t, + pub st_atime_nsec: ::c_long, + pub st_mtime: ::time_t, + pub st_mtime_nsec: ::c_long, + pub st_ctime: ::time_t, + pub st_ctime_nsec: ::c_long, + __reserved: [::c_long; 3], + } + + pub struct rlimit64 { // ToDo + pub rlim_cur: rlim64_t, + pub rlim_max: rlim64_t, + } + + pub struct cpu_set_t { // ToDo + #[cfg(target_pointer_width = "32")] + bits: [u32; 32], + #[cfg(target_pointer_width = "64")] + bits: [u64; 16], + } + + pub struct timespec { // ToDo + tv_sec: time_t, // seconds + tv_nsec: ::c_ulong, // nanoseconds + } + + pub struct fsid_t { // ToDo + __val: [::c_int; 2], + } +} + +// constants +pub const O_CLOEXEC: ::c_int = 0x80000; +pub const O_DIRECTORY: ::c_int = 0200000; +pub const NCCS: usize = 32; +pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; +pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; +pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; +pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1; +pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2; +pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_NORMAL; +pub const RLIM_INFINITY: u64 = 0xffffffffffffffff; +pub const __SIZEOF_PTHREAD_COND_T: usize = 48; +pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; +pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; + +extern { + pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void; +} diff --git a/src/vendor/libc/src/windows.rs b/src/vendor/libc/src/windows.rs index 6c8332a62e..385b66758c 100644 --- a/src/vendor/libc/src/windows.rs +++ b/src/vendor/libc/src/windows.rs @@ -43,6 +43,18 @@ s! { pub modtime: time64_t, } + pub struct tm { + tm_sec: ::c_int, + tm_min: ::c_int, + tm_hour: ::c_int, + tm_mday: ::c_int, + tm_mon: ::c_int, + tm_year: ::c_int, + tm_wday: ::c_int, + tm_yday: ::c_int, + tm_isdst: ::c_int, + } + pub struct timeval { pub tv_sec: c_long, pub tv_usec: c_long, diff --git a/src/vendor/log/.cargo-checksum.json b/src/vendor/log/.cargo-checksum.json index cd8b7d9c52..542f06e5ae 100644 --- a/src/vendor/log/.cargo-checksum.json +++ b/src/vendor/log/.cargo-checksum.json @@ -1 +1 @@ -{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"12cc0f91b51fedf41ae1670d1624ee1d78a284bdb101645b60a06a12de16c069",".travis.yml":"985cf95c79f32c65766927fd6ef5079f8c14f235ddb4213e6410d90a86a95811","Cargo.toml":"b539d6f30b4775e17454d3bf8a0976faad71b779d3dc63c160aaeb98c836fccb","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"7c831cff45cfd33333cc246815dccb25bfa0b981053656e707828fe3f25151da","appveyor.yml":"c61473b8c780ad2626282ce2b2ba0ef278082b6afe151a62ff419f33eaf90221","src/lib.rs":"daba1222c7b4a71b701d45c061fa0198378fa9e08da722587a03397586b0e28d","src/macros.rs":"9068d69d32e989ac273ce73659125d31cf4a166076eefdad74dfbdf9506cf9c4","tests/filters.rs":"cc61ed41a6cd77e5aef91cc8c76216b492d8de34f00635254f3835a3d964ce22"},"package":"5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad"} \ No newline at end of file +{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"12cc0f91b51fedf41ae1670d1624ee1d78a284bdb101645b60a06a12de16c069",".travis.yml":"985cf95c79f32c65766927fd6ef5079f8c14f235ddb4213e6410d90a86a95811","Cargo.toml":"0a4a756f7ef47f5dfa221a173b21f9ec496b448aafcd9bde08d9d16935b55007","Cargo.toml.orig":"511fe1dec6d79cbadb22c9f61c9153627bb57b2cfc975e1d558574a409659d6e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"aa8356455efcc3d49f66e7fa394eac292c9158164dff074e32c699b64891cb4b","appveyor.yml":"c61473b8c780ad2626282ce2b2ba0ef278082b6afe151a62ff419f33eaf90221","src/lib.rs":"75b44acfc9627b821cd725649db07693a43b2e44b2fac19b79354c6d950c4038","src/macros.rs":"3953610da3ee2dc393262b753f2406d1864a1cbd74d2bd20d279e09aabfe7131","tests/filters.rs":"cc61ed41a6cd77e5aef91cc8c76216b492d8de34f00635254f3835a3d964ce22"},"package":"880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"} \ No newline at end of file diff --git a/src/vendor/log/Cargo.toml b/src/vendor/log/Cargo.toml index 7f4645379e..8ab7f22e5a 100644 --- a/src/vendor/log/Cargo.toml +++ b/src/vendor/log/Cargo.toml @@ -1,37 +1,49 @@ -[package] +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g. crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) +[package] name = "log" -version = "0.3.7" +version = "0.3.8" authors = ["The Rust Project Developers"] -license = "MIT/Apache-2.0" -readme = "README.md" -repository = "https://github.com/rust-lang/log" -documentation = "https://doc.rust-lang.org/log" +description = "A lightweight logging facade for Rust\n" homepage = "https://github.com/rust-lang/log" -description = """ -A lightweight logging facade for Rust -""" +documentation = "https://docs.rs/log" +readme = "README.md" categories = ["development-tools::debugging"] +license = "MIT/Apache-2.0" +repository = "https://github.com/rust-lang/log" [[test]] name = "filters" harness = false [features] -max_level_off = [] -max_level_error = [] -max_level_warn = [] -max_level_info = [] +max_level_info = [] +nightly = [] +max_level_warn = [] +release_max_level_debug = [] +release_max_level_info = [] +release_max_level_off = [] +release_max_level_error = [] max_level_debug = [] +release_max_level_warn = [] +use_std = [] +max_level_off = [] max_level_trace = [] - -release_max_level_off = [] -release_max_level_error = [] -release_max_level_warn = [] -release_max_level_info = [] -release_max_level_debug = [] release_max_level_trace = [] - -nightly = [] -use_std = [] +max_level_error = [] default = ["use_std"] +[badges.appveyor] +repository = "alexcrichton/log" + +[badges.travis-ci] +repository = "rust-lang-nursery/log" diff --git a/src/vendor/log/Cargo.toml.orig b/src/vendor/log/Cargo.toml.orig new file mode 100644 index 0000000000..66638c65ef --- /dev/null +++ b/src/vendor/log/Cargo.toml.orig @@ -0,0 +1,41 @@ +[package] + +name = "log" +version = "0.3.8" +authors = ["The Rust Project Developers"] +license = "MIT/Apache-2.0" +readme = "README.md" +repository = "https://github.com/rust-lang/log" +documentation = "https://docs.rs/log" +homepage = "https://github.com/rust-lang/log" +description = """ +A lightweight logging facade for Rust +""" +categories = ["development-tools::debugging"] + +[[test]] +name = "filters" +harness = false + +[features] +max_level_off = [] +max_level_error = [] +max_level_warn = [] +max_level_info = [] +max_level_debug = [] +max_level_trace = [] + +release_max_level_off = [] +release_max_level_error = [] +release_max_level_warn = [] +release_max_level_info = [] +release_max_level_debug = [] +release_max_level_trace = [] + +nightly = [] +use_std = [] +default = ["use_std"] + +[badges] +travis-ci = { repository = "rust-lang-nursery/log" } +appveyor = { repository = "alexcrichton/log" } diff --git a/src/vendor/log/README.md b/src/vendor/log/README.md index 0e9dc58ae7..1ff4a89ba7 100644 --- a/src/vendor/log/README.md +++ b/src/vendor/log/README.md @@ -158,3 +158,20 @@ test tests::it_adds_one ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured ``` + +## Configuring log target + +By default, `env_logger` logs to stderr. If you want to log to stdout instead, +you can use the `LogBuilder` to change the log target: + +```rust +use std::env; +use env_logger::{LogBuilder, LogTarget}; + +let mut builder = LogBuilder::new(); +builder.target(LogTarget::Stdout); +if env::var("RUST_LOG").is_ok() { + builder.parse(&env::var("RUST_LOG").unwrap()); +} +builder.init().unwrap(); +``` diff --git a/src/vendor/log/src/lib.rs b/src/vendor/log/src/lib.rs index 6c222baef1..04a410e146 100644 --- a/src/vendor/log/src/lib.rs +++ b/src/vendor/log/src/lib.rs @@ -10,7 +10,7 @@ //! A lightweight logging facade. //! -//! A logging facade provides a single logging API that abstracts over the +//! The `log` crate provides a single logging API that abstracts over the //! actual logging implementation. Libraries can use the logging API provided //! by this crate, and the consumer of those libraries can choose the logging //! framework that is most suitable for its use case. @@ -19,11 +19,10 @@ //! implementation that ignores all log messages. The overhead in this case //! is very small - just an integer load, comparison and jump. //! -//! A log request consists of a target, a level, and a body. A target is a -//! string which defaults to the module path of the location of the log -//! request, though that default may be overridden. Logger implementations -//! typically use the target to filter requests based on some user -//! configuration. +//! A log request consists of a _target_, a _level_, and a _body_. A target is a +//! string which defaults to the module path of the location of the log request, +//! though that default may be overridden. Logger implementations typically use +//! the target to filter requests based on some user configuration. //! //! # Use //! @@ -79,21 +78,25 @@ //! ```rust,ignore //! #[macro_use] //! extern crate log; -//! extern crate my_logger; +//! extern crate env_logger; //! //! fn main() { -//! my_logger::init(); -//! +//! // Select env_logger, one possible logger implementation +//! // (see https://doc.rust-lang.org/log/env_logger/index.html) +//! env_logger::init().unwrap(); +//! //! info!("starting up"); -//! +//! error!("error: {}", 404); +//! //! // ... //! } //! ``` //! //! # Logger implementations //! -//! Loggers implement the `Log` trait. Here's a very basic example that simply -//! logs all messages at the `Error`, `Warn` or `Info` levels to stdout: +//! Loggers implement the [`Log`] trait. Here's a very basic example that simply +//! logs all messages at the [`Error`][level_link], [`Warn`][level_link] or +//! [`Info`][level_link] levels to stdout: //! //! ```rust //! extern crate log; @@ -117,15 +120,16 @@ //! # fn main() {} //! ``` //! -//! Loggers are installed by calling the `set_logger` function. It takes a -//! closure which is provided a `MaxLogLevel` token and returns a `Log` trait -//! object. The `MaxLogLevel` token controls the global maximum log level. The -//! logging facade uses this as an optimization to improve performance of log -//! messages at levels that are disabled. In the case of our example logger, -//! we'll want to set the maximum log level to `Info`, since we ignore any -//! `Debug` or `Trace` level log messages. A logging framework should provide a -//! function that wraps a call to `set_logger`, handling initialization of the -//! logger: +//! Loggers are installed by calling the [`set_logger`] function. It takes a +//! closure which is provided a [`MaxLogLevelFilter`] token and returns a +//! [`Log`] trait object. The [`MaxLogLevelFilter`] token controls the global +//! maximum log level. The logging facade uses this as an optimization to +//! improve performance of log messages at levels that are disabled. In the +//! case of our example logger, we'll want to set the maximum log level to +//! [`Info`][level_link], since we ignore any [`Debug`][level_link] or +//! [`Trace`][level_link] level log messages. A logging framework should +//! provide a function that wraps a call to [`set_logger`], handling +//! initialization of the logger: //! //! ```rust //! # extern crate log; @@ -150,8 +154,8 @@ //! To use the `log` crate without depending on `libstd`, you need to specify //! `default-features = false` when specifying the dependency in `Cargo.toml`. //! This makes no difference to libraries using `log` since the logging API -//! remains the same. However executables will need to use the `set_logger_raw` -//! function to initialize a logger and the `shutdown_logger_raw` function to +//! remains the same. However executables will need to use the [`set_logger_raw`] +//! function to initialize a logger and the [`shutdown_logger_raw`] function to //! shut down the global logger before exiting: //! //! ```rust @@ -183,11 +187,19 @@ //! }) //! } //! ``` +//! +//! [`Log`]: trait.Log.html +//! [level_link]: enum.LogLevel.html +//! [`set_logger`]: fn.set_logger.html +//! [`MaxLogLevelFilter`]: struct.MaxLogLevelFilter.html +//! [`set_logger_raw`]: fn.set_logger_raw.html +//! [`shutdown_logger_raw`]: fn.shutdown_logger_raw.html #![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/log/")] #![warn(missing_docs)] +#![deny(missing_debug_implementations)] #![cfg_attr(feature = "nightly", feature(panic_handler))] #![cfg_attr(not(feature = "use_std"), no_std)] @@ -244,11 +256,14 @@ static MAX_LOG_LEVEL_FILTER: AtomicUsize = ATOMIC_USIZE_INIT; static LOG_LEVEL_NAMES: [&'static str; 6] = ["OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"]; -/// An enum representing the available verbosity levels of the logging framework +/// An enum representing the available verbosity levels of the logging framework. /// -/// A `LogLevel` may be compared directly to a `LogLevelFilter`. +/// Typical usage includes: checking if a certain `LogLevel` is enabled with +/// [`log_enabled!`](macro.log_enabled.html), specifying the `LogLevel` of +/// [`log!`](macro.log.html), and comparing a `LogLevel` directly to a +/// [`LogLevelFilter`](enum.LogLevelFilter.html). #[repr(usize)] -#[derive(Copy, Eq, Debug)] +#[derive(Copy, Eq, Debug, Hash)] pub enum LogLevel { /// The "error" level. /// @@ -386,9 +401,13 @@ impl LogLevel { /// An enum representing the available verbosity level filters of the logging /// framework. /// -/// A `LogLevelFilter` may be compared directly to a `LogLevel`. +/// A `LogLevelFilter` may be compared directly to a [`LogLevel`](enum.LogLevel.html). +/// Use this type to [`get()`](struct.MaxLogLevelFilter.html#method.get) and +/// [`set()`](struct.MaxLogLevelFilter.html#method.set) the +/// [`MaxLogLevelFilter`](struct.MaxLogLevelFilter.html), or to match with the getter +/// [`max_log_level()`](fn.max_log_level.html). #[repr(usize)] -#[derive(Copy, Eq, Debug)] +#[derive(Copy, Eq, Debug, Hash)] pub enum LogLevelFilter { /// A level lower than all log levels. Off, @@ -490,7 +509,12 @@ impl LogLevelFilter { } } -/// The "payload" of a log message. +/// The "payload" of a log message. This structure is primarily used as a +/// parameter in the [`log`] method of the [`Log`] trait. +/// +/// [`log`]: trait.Log.html#tymethod.log +/// [`Log`]: trait.Log.html +#[derive(Debug)] pub struct LogRecord<'a> { metadata: LogMetadata<'a>, location: &'a LogLocation, @@ -525,6 +549,7 @@ impl<'a> LogRecord<'a> { } /// Metadata about a log message. +#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] pub struct LogMetadata<'a> { level: LogLevel, target: &'a str, @@ -576,7 +601,7 @@ impl Log for NopLogger { /// The fields of this struct are public so that they may be initialized by the /// `log!` macro. They are subject to change at any time and should never be /// accessed directly. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct LogLocation { #[doc(hidden)] pub __module_path: &'static str, diff --git a/src/vendor/log/src/macros.rs b/src/vendor/log/src/macros.rs index 7037f9ac0d..f9a7788d2e 100644 --- a/src/vendor/log/src/macros.rs +++ b/src/vendor/log/src/macros.rs @@ -14,6 +14,23 @@ /// /// The `max_level_*` features can be used to statically disable logging at /// various levels. +/// +/// # Examples +/// +/// ```rust +/// # #[macro_use] +/// # extern crate log; +/// use log::LogLevel; +/// +/// # fn main() { +/// let data = (42, "Forty-two"); +/// let private_data = "private"; +/// +/// log!(LogLevel::Error, "Received errors: {}, {}", data.0, data.1); +/// log!(target: "app_events", LogLevel::Warn, "App warning: {}, {}, {}", +/// data.0, data.1, private_data); +/// # } +/// ``` #[macro_export] macro_rules! log { (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ @@ -33,6 +50,19 @@ macro_rules! log { /// Logs a message at the error level. /// /// Logging at this level is disabled if the `max_level_off` feature is present. +/// +/// # Examples +/// +/// ```rust +/// # #[macro_use] +/// # extern crate log; +/// # fn main() { +/// let (err_info, port) = ("No connection", 22); +/// +/// error!("Error: {} on port {}", err_info, port); +/// error!(target: "app_events", "App Error: {}, Port: {}", err_info, 22); +/// # } +/// ``` #[macro_export] macro_rules! error { (target: $target:expr, $($arg:tt)*) => ( @@ -51,6 +81,19 @@ macro_rules! error { /// When building in release mode (i.e., without the `debug_assertions` option), /// logging at this level is also disabled if any of the following features are /// present: `release_max_level_off` or `max_level_error`. +/// +/// # Examples +/// +/// ```rust +/// # #[macro_use] +/// # extern crate log; +/// # fn main() { +/// let warn_description = "Invalid Input"; +/// +/// warn!("Warning! {}!", warn_description); +/// warn!(target: "input_events", "App received warning: {}", warn_description); +/// # } +/// ``` #[macro_export] macro_rules! warn { (target: $target:expr, $($arg:tt)*) => ( @@ -70,6 +113,21 @@ macro_rules! warn { /// logging at this level is also disabled if any of the following features are /// present: `release_max_level_off`, `release_max_level_error`, or /// `release_max_level_warn`. +/// +/// # Examples +/// +/// ```rust +/// # #[macro_use] +/// # extern crate log; +/// # fn main() { +/// # struct Connection { port: u32, speed: f32 } +/// let conn_info = Connection { port: 40, speed: 3.20 }; +/// +/// info!("Connected to port {} at {} Mb/s", conn_info.port, conn_info.speed); +/// info!(target: "connection_events", "Successfull connection, port: {}, speed: {}", +/// conn_info.port, conn_info.speed); +/// # } +/// ``` #[macro_export] macro_rules! info { (target: $target:expr, $($arg:tt)*) => ( @@ -90,6 +148,20 @@ macro_rules! info { /// logging at this level is also disabled if any of the following features are /// present: `release_max_level_off`, `release_max_level_error`, /// `release_max_level_warn`, or `release_max_level_info`. +/// +/// # Examples +/// +/// ```rust +/// # #[macro_use] +/// # extern crate log; +/// # fn main() { +/// # struct Position { x: f32, y: f32 } +/// let pos = Position { x: 3.234, y: -1.223 }; +/// +/// debug!("New position: x: {}, y: {}", pos.x, pos.y); +/// debug!(target: "app_events", "New position: x: {}, y: {}", pos.x, pos.y); +/// # } +/// ``` #[macro_export] macro_rules! debug { (target: $target:expr, $($arg:tt)*) => ( @@ -111,6 +183,22 @@ macro_rules! debug { /// present: `release_max_level_off`, `release_max_level_error`, /// `release_max_level_warn`, `release_max_level_info`, or /// `release_max_level_debug`. +/// +/// # Examples +/// +/// ```rust +/// # #[macro_use] +/// # extern crate log; +/// # fn main() { +/// # struct Position { x: f32, y: f32 } +/// let pos = Position { x: 3.234, y: -1.223 }; +/// +/// trace!("Position is: x: {}, y: {}", pos.x, pos.y); +/// trace!(target: "app_events", "x is {} and y is {}", +/// if pos.x >= 0.0 { "positive" } else { "negative" }, +/// if pos.y >= 0.0 { "positive" } else { "negative" }); +/// # } +/// ``` #[macro_export] macro_rules! trace { (target: $target:expr, $($arg:tt)*) => ( diff --git a/src/vendor/lzma-sys/.cargo-checksum.json b/src/vendor/lzma-sys/.cargo-checksum.json index e734625565..b5fda6eeb8 100644 --- a/src/vendor/lzma-sys/.cargo-checksum.json +++ b/src/vendor/lzma-sys/.cargo-checksum.json @@ -1 +1 @@ -{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"150af06c35bbf9baf852c819d2e50763008ff6dc75c6b83d370d7945f81da0d1","build.rs":"10dc958a5e21f776fc7d791a7fa808f5dc6f10e458b23a813d4740a199718b92","src/lib.rs":"599f2b0cea899a4b28be5ae2c02093babbd6fd6bfa5d49428b97da110ada7b7a","xz-5.2.3/ABOUT-NLS":"e97b73baef31710d510598584f5c0f5018cb0847770defa1347966909b7c1f5d","xz-5.2.3/AUTHORS":"72d7a7ee8a4eaca5d0b53f20609eff95d5e6f9e155ecce98127414b8215b0b15","xz-5.2.3/COPYING":"c4f8e14fafe458d84808a4cd8b69f94673ebe2bf8fc992291629a69ac12218f8","xz-5.2.3/COPYING.GPLv2":"8177f97513213526df2cf6184d8ff986c675afb514d4e68a404010521b880643","xz-5.2.3/COPYING.GPLv3":"8ceb4b9ee5adedde47b31e975c1d90c73ad27b6b165a1dcd80c7c545eb65b903","xz-5.2.3/COPYING.LGPLv2.1":"dc626520dcd53a22f727af3ee42c770e56c97a64fe3adb063799d8ab032fe551","xz-5.2.3/ChangeLog":"e2cb2743a1e4297114f7a96cf6b9fe3168735be0cbb45111ac171aa81ce65204","xz-5.2.3/Doxyfile.in":"31160d92de7aa43a525a8978a95be0a30c0dd8fbc9d2115b2a5baf75e9f7aeda","xz-5.2.3/INSTALL":"2efb9b0f3e5002d4dd08b5686a45b28fb9f33759b378a5cac239ea1d35aa8636","xz-5.2.3/INSTALL.generic":"fd9db1c52e12eebd099a1fce89a5603048f4250329ba445bfb2fe8cdca04d3a6","xz-5.2.3/Makefile.am":"fca284f001e4eebdf1aee98e88b719a42ca7fddf2af874b971efd1b2629ce8ae","xz-5.2.3/Makefile.in":"20d3639e564b5cbaa6c0109ef49db75e9a927ed28cf4a2232843f0f99155a24e","xz-5.2.3/NEWS":"64598d59470537de94b5a2a145ce8e819ce70e0d0315aad624b094e130bc2040","xz-5.2.3/PACKAGERS":"8ab0db1c1bf19383b6fd4e7f3fc1a627f7e4d44119fb019469644131df99c0e2","xz-5.2.3/README":"a6058088674fa61559c97ebd82dcbcba9ae64441767f0ae07b89fd7a3232ee09","xz-5.2.3/THANKS":"396f2938a389fc7b554de6c46990ad673fd7bdd2ac0bcdac144b6dbcb59a59b8","xz-5.2.3/TODO":"2ce425810436c5299aa5e4a8b0186c0de15a496697b518481f606abb421e80a9","xz-5.2.3/aclocal.m4":"233acad8d0d2add0f938800317ce360acb63c9e9de3539aca65e927eb0513935","xz-5.2.3/autogen.sh":"46e696c66b31605de388dc55fef5419105622bda81276ae77db0e6523ec4f225","xz-5.2.3/build-aux/compile":"41856428226c049fa0ea4ca7a574c28416de2769b55ed7feea4ab5e60283af16","xz-5.2.3/build-aux/config.guess":"b7eab9b8a73dc6e0421366bca6921cd2621dab6c3909d6e3bebf863011442d15","xz-5.2.3/build-aux/config.rpath":"c8b4c017079da9dfb3086a0583e60ffe736184d89005dc5973f0bb0fd17c04bb","xz-5.2.3/build-aux/config.sub":"82745ce935695e7984a053c155a64b9ad16ece3a07d931cc90ab3fb28b7221af","xz-5.2.3/build-aux/depcomp":"786149ab4493e86b837077ebaecab65ef6230ae8a619b17fa5c1695564a427e9","xz-5.2.3/build-aux/install-sh":"d7c113e5484fce8b48f9a34a7a91e385ec279247d415b0b7d749bd56ad8ee8a2","xz-5.2.3/build-aux/ltmain.sh":"34ffaa53e9becccce1cee4f149a3b1cbba3c4cda06ab7dfaf1ae905ea4b2c0e3","xz-5.2.3/build-aux/manconv.sh":"3441e64f658e9edb0afa8a0446c2f643ba661187c0576527a5a62124619c0b8c","xz-5.2.3/build-aux/missing":"b1a337b731bbb58846d31ca2f5143c293a455fa41b481e236e89a9016d96b034","xz-5.2.3/build-aux/version.sh":"39bba40cf83ee58a901c351244ce717b0ef6f9d76e1896f2867065814d49246a","xz-5.2.3/config.h.in":"8c94c4f88de4a3722d993d31abe667d1b4aef5dd01adbe20208d79cbbfbe84be","xz-5.2.3/configure":"dccab7a59ce8ce9c6cf3f3e27d598a89f0f3d2c79b9a96b227220fd4bf3e5ab5","xz-5.2.3/configure.ac":"4b538a19f3b1f5e88e5ecae33e58fdfbb8a6842bfad37287904eb615b36a18e7","xz-5.2.3/debug/Makefile.am":"2505f6da25ac274d02330fbafd3901aeb955fae4f74a908e700073e0d409d630","xz-5.2.3/debug/Makefile.in":"ce98eadfc05ec111b810d46451c6c8f5c493236c74d510178d2c2375763e6ac8","xz-5.2.3/debug/README":"8d5b8e3b842551bc0cb2ce02537325ce75c0816697bb2b7dfdc9962bdb669451","xz-5.2.3/debug/crc32.c":"35cfdb89ef7b99b81b44655ad4eff661354af3215ed9fcef3187001f5eef672f","xz-5.2.3/debug/full_flush.c":"1b82ef164c550bf514d58221f0f6aed7fb9a73062f32c5dace74ddf67f23b932","xz-5.2.3/debug/hex2bin.c":"e06c050a93c5260bafb58b744fa3a4bd20e8d9050256b53d35620a3129f38c89","xz-5.2.3/debug/known_sizes.c":"8ea1b581c3319966fdb725421d4672497c4381336ab130adcf567a59b23af417","xz-5.2.3/debug/memusage.c":"c1b7b773267998b46cbc07e2d70c977590e2027bbc1994fa5d2804fd9a5221ec","xz-5.2.3/debug/repeat.c":"384cfa0c8ec7af687cb8d63aaf4cb2f275273a7ce3607c0bcba10592218cf434","xz-5.2.3/debug/sync_flush.c":"7a2c4b73220e5730a6b353f699a495ece1514917186f5755e2e65ba69769bf5a","xz-5.2.3/debug/translation.bash":"98949da3fe3eb46173321dba78a4643a504e8ab922358eccfb70c9a4470dcd6f","xz-5.2.3/doc/examples/00_README.txt":"f0ddaa731c89d6028f55281229e56b89f32b8c477aba4f52367488f0f42651be","xz-5.2.3/doc/examples/01_compress_easy.c":"183bea5347ddd735ea9ebdb39fe21d0c91b191c8b16157480e1ca0623c72372d","xz-5.2.3/doc/examples/02_decompress.c":"f2181b5c5acaa1d4438bb94f8e0338efc6678ddaf222928f731c07a682ce6bfa","xz-5.2.3/doc/examples/03_compress_custom.c":"914afd1e3494d9942ef752123f9743fa9427d5a82ca3e593794b9a4d9e390f42","xz-5.2.3/doc/examples/04_compress_easy_mt.c":"80a5d7e1acd455ffb55bd1ca26f767789171293a231e6645ca991b83b954988c","xz-5.2.3/doc/examples/Makefile":"067ac8dbf5a9cab8c2a12b3fadda34c93656308f150a8a195bfcdb071ca043a7","xz-5.2.3/doc/examples_old/xz_pipe_comp.c":"fce7eefb9149c5f5a43869e07a4a576c1f2af4ca0aae6872bd7ca50ed8c85522","xz-5.2.3/doc/examples_old/xz_pipe_decomp.c":"5d157c3c397fffc3b0489e49ef1d396fcfe6153f134ec5ea44ef0acc7fe474aa","xz-5.2.3/doc/faq.txt":"37636bca2e8c28bccdb440feb4dd306a717991049506a3cf463944f09235a3ce","xz-5.2.3/doc/history.txt":"9d6a0a72822734a0afb1816e07f0a7edab03339119bed4f393c1c7eec884eab6","xz-5.2.3/doc/lzma-file-format.txt":"0e961a7244cca641aa33619e9c9f0d795f9cc95657245f5d157e5bad05d3df66","xz-5.2.3/doc/man/txt/lzmainfo.txt":"3582617c79cacc571b4a87744243ad330b2f4c353ec4b6897d8052e2798c5ea8","xz-5.2.3/doc/man/txt/xz.txt":"4fd6872c77efde39d6a445df65a14346fe2e6e2c0ca3ccc47992cb6a98a5317c","xz-5.2.3/doc/man/txt/xzdec.txt":"805d933db332ff3603b83aafb432830a66632cc5cdbbe11ea62ee44f132583d8","xz-5.2.3/doc/man/txt/xzdiff.txt":"99cd14e76276f4790d4763a539965058003ff50275476b43bdaf10e43afad0a1","xz-5.2.3/doc/man/txt/xzgrep.txt":"67ec945751a59ada72524df5589817df2885c66a1f89bc85265ce041f9e35a4f","xz-5.2.3/doc/man/txt/xzless.txt":"1a2ac240c60f2873d7d7c9af95850eaf46dcc736684106a1164d8854977c85c6","xz-5.2.3/doc/man/txt/xzmore.txt":"d28e996e884205e68c99e2f35b6bef518bc5b4f54cc26bfeb402e79f76934e4f","xz-5.2.3/doc/xz-file-format.txt":"fada567e0ebd8b910d2c3210d13e74f3fcc8475d64e29e35db0fc05e3c6820f5","xz-5.2.3/dos/INSTALL.txt":"8a29c9ffc4cd0cf26b8913af62033980d4edca85b8c3c532c238ab1c7ece4a45","xz-5.2.3/dos/Makefile":"ffb97657224a5dec72179919f8341ef3d3b6ce8433ac8d47fa9608c5c35331c1","xz-5.2.3/dos/README.txt":"afa9abc814a28d75917b17a95fe049d331f6db4b4df78a95bd03eaf080571251","xz-5.2.3/dos/config.h":"27897319d3528c9a714882218617f7b54ac647e6f59a7e5f115433c9665f9348","xz-5.2.3/extra/7z2lzma/7z2lzma.bash":"568c344d12f6465e307caa3828203cc3c63666577c4f2f82b708f24af72734c1","xz-5.2.3/extra/scanlzma/scanlzma.c":"48203b9ecae7b2d56f1d6382b1cc6305d4eb74466ae713aa24280245cede1e2b","xz-5.2.3/lib/Makefile.am":"6a620762de0091fa6a335d0a0faafdaaa5998bb26f46889c21c8e42659ed5354","xz-5.2.3/lib/Makefile.in":"184be9ea3460b0bbc445e0f2f7b1a93dd1e522503ca4e84363216489838593c3","xz-5.2.3/lib/getopt.c":"bf9113fd84a7414cbc807e1578c18d5ef8a12ea46ac64239623caab659c21f34","xz-5.2.3/lib/getopt.in.h":"bebcc6657cbd7dec9d6a70ec31c697d334d4d9b9ef8010c16823c075b3425189","xz-5.2.3/lib/getopt1.c":"2d49657d2b4dbc38aa2f31f3e2fd7c5a4594c2caba09132f4842312ee64e5726","xz-5.2.3/lib/getopt_int.h":"2dc491c9544667a9916a23bd2c872325ced525cc58b9d9ada4742f7e9588bed7","xz-5.2.3/m4/ax_check_capsicum.m4":"764ba27e847d425386ff872a4bd68a19eb7f494dc4db139803fe4b6ae33b6d06","xz-5.2.3/m4/ax_pthread.m4":"894dc48a681069315e8bc61f0d236dc5061c9b43bde42cc9f857ed8c1dd71164","xz-5.2.3/m4/getopt.m4":"07b0c232c8cb06c1a6c168ac605e992c31717a20c64b2eef4ec361070e6eed05","xz-5.2.3/m4/gettext.m4":"6c279c958f980621dfeb725cb79173dbe93534aef2a4377a6fafa666c3c0b677","xz-5.2.3/m4/iconv.m4":"5b6ecb913051efa159e785930a59c79498a820694704883af324abef3796d360","xz-5.2.3/m4/intlmacosx.m4":"d0e24c3c982ca2c8c00aaf7d0a27502c83a299660b00829b02159dd8b1917f95","xz-5.2.3/m4/lib-ld.m4":"b9625b301655214df17e9b7e9fac9292707dc10b9df572cdee4a90d7a83af8b3","xz-5.2.3/m4/lib-link.m4":"998a5c2d2ca268a2dc7a22f2b6c8791ab26318ba66c77cf0df1dd2122d071976","xz-5.2.3/m4/lib-prefix.m4":"b23f4661e2c6081496bc34586caaee8afdc0935ac77aa9b8d8497d14028315d9","xz-5.2.3/m4/libtool.m4":"94ebc155f41e96e5cb8762a2661e0d39426274e1b2b930bfb6d99c680a041c58","xz-5.2.3/m4/ltoptions.m4":"e77ebba8361b36f14b4d0927173a034b98c5d05049697a9ded84d85eb99a7990","xz-5.2.3/m4/ltsugar.m4":"5a6735cda60e0ba0d1b706c0ef648f5d096298da46daefd9cdecdb6a0f4584d3","xz-5.2.3/m4/ltversion.m4":"a27b754709de61575197bf5a980696c98ae49da3f92f0de8ee7f42dd543b7465","xz-5.2.3/m4/lt~obsolete.m4":"26fa3285c35dd6ab00ed1e466ba92a17e4655e01897731ec18a587a4cf5e4f8d","xz-5.2.3/m4/nls.m4":"6d231fb983fcb7c8f833b7c32eeea00a578b46837ab774fd417603a857c67a38","xz-5.2.3/m4/po.m4":"a511e6e80ced17c4c5b6ff7c9dac277275d3ec1544f19d5bb951671b45756031","xz-5.2.3/m4/posix-shell.m4":"edc32356d26f677c308a8f5877058260a88a258f2a1d8e3ff36dcbe95e25775d","xz-5.2.3/m4/progtest.m4":"2b63243f5e160602a1411eed30a4abd66ce29a5d4c8664711465059362ef7353","xz-5.2.3/m4/tuklib_common.m4":"7f72e262bec40c2243ba26e3a72764dda20be0f8c3a4dc4e9bd7a68b494b6aa5","xz-5.2.3/m4/tuklib_cpucores.m4":"26c32f6b37bf0e8e0913c483b4ec1c32b17d780279dcc5dbd5eff76f85018178","xz-5.2.3/m4/tuklib_integer.m4":"f1a326f55f067aa5cd2c64acd50e80ef8a5fca426ca531c6d9a4d9bb11b23f04","xz-5.2.3/m4/tuklib_mbstr.m4":"c5d8e37d8e1384073944765bca4291cb787c427f53e87022fd5274704c084a4c","xz-5.2.3/m4/tuklib_physmem.m4":"f8ae3f46ec22f5c9d13a1c7eb267225ba7f5c453eb8163ee2745b8b48a133443","xz-5.2.3/m4/tuklib_progname.m4":"e3dd84887a1bd2f944656355f3b0e933fb01807ae0f4040fa3eb661fe635a281","xz-5.2.3/m4/visibility.m4":"56c24c3697d4e0b8206c551a3425a99fd2648d2739acf39c2acc7869e79daee5","xz-5.2.3/macosx/build.sh":"4792ea057807ff46309db27bfe29d5edfcc61269f3b0a0172043a904f08d63c8","xz-5.2.3/po/LINGUAS":"b6ecc012505449bd71f13c32ae8a1d350f01ad81c6ef91cc993f38dbbf98d6c7","xz-5.2.3/po/Makefile.in.in":"fda41c837ebf2de985752fb56650a4eb9c4da7b49144f44d06503204bdbc7841","xz-5.2.3/po/Makevars":"656fa2fed4882e2656ae4398d1f4ed1cf818822f4f8f31cf1b9247850f20817c","xz-5.2.3/po/POTFILES.in":"6730d37ff01e4fe53f12c899963209b2d6658d2bed4d9cd551de6b2922a77366","xz-5.2.3/po/Rules-quot":"8604411891fa5b5456904b41d22f0efe5158c457c75c5ab2fd58b1b9e7c97185","xz-5.2.3/po/boldquot.sed":"33234736a58f1610c73e1c8c08faf1b2ef1397d878dd7d2cbd888ca0f2da4ffc","xz-5.2.3/po/cs.gmo":"7dbe95f7ef4750d6af43e6a4847bfecbf8dae704f23b9e5e04113d67824297af","xz-5.2.3/po/cs.po":"ef25a51220691216215c4664b72b1b7bd207e55a5fef30f09ce3d399e7fd6dd6","xz-5.2.3/po/de.gmo":"b6c0a678137ee109adb4d50ad1ff89b8e822851c4d00728c0923e6b69aa7dd83","xz-5.2.3/po/de.po":"bccef85a99191454f4538e9095b8978868c29e6099f8e65961f3c8c0dcbec014","xz-5.2.3/po/en@boldquot.header":"3b0b89aa6625c051e69cce1e341f973f62ca94aff62cbb36b4a452ce67eb261c","xz-5.2.3/po/en@quot.header":"90e35325bf9b6b9562bd0882128ea4650b65c9389b35edf9ff534dc3a48e8bed","xz-5.2.3/po/fr.gmo":"c2cdc620605c7f701d8f26047a12e81ea1ad4ce8732368c185af8b169f1f317d","xz-5.2.3/po/fr.po":"4cb8414564bbd5b507e2d9c80ac797ff2bd792fb2e084ce8cc25f97f4f31c35c","xz-5.2.3/po/insert-header.sin":"73e650aeccc3ef0a7c2e1bbab934b0882b61f19569e96e4615d069dc50b6becd","xz-5.2.3/po/it.gmo":"d544c91a781767172e52728bbbe19312d5c86752dfd2311c76c7acb1737d5d1b","xz-5.2.3/po/it.po":"9ecfea52b080b969e7bd7cd4effbec243b97f1d1f31f3c04531fdb97b1cb2cc2","xz-5.2.3/po/pl.gmo":"73a73536bed63173995b36ab496f2ad48b189677d77062cf8644d114dd7c4dc3","xz-5.2.3/po/pl.po":"ff96c3afd0b1def3e01e0480379b4dd83c5782c699097c201f0915b45d8f3a80","xz-5.2.3/po/quot.sed":"d19ab2cc69000c1206f1b8460952857f05d154158da8b89273ac2900a5c80ec0","xz-5.2.3/po/remove-potcdate.sin":"9a36cf3e93b6374521c81fa4f302350d3c04b95573f5570717284107689188e6","xz-5.2.3/po/stamp-po":"2cd8ec3de6a07e1fd39676100db57ba62372e820c19812fee55899f65746e192","xz-5.2.3/po/vi.gmo":"9826f269d7bb218978d3d898b0d958f3c6a45e0a7e6e31f7fc0dca315227a5cf","xz-5.2.3/po/vi.po":"fc0e4051e5b5689ee753d688cc8f774c6bc49f040df99079d44e965979720e46","xz-5.2.3/po/xz.pot":"40787ca0234ab808a5e7323f901f623aa980ce589907553c17c7e430f313d918","xz-5.2.3/src/Makefile.am":"2ac2419e71b07af9c7f281e04139092154c23f33b234609e6f38631861e57b7c","xz-5.2.3/src/Makefile.in":"6568340e13bda8435f7cf29925d85269887e8279ea585e902f98e0f11c521cab","xz-5.2.3/src/common/common_w32res.rc":"a930b1c7dc6499541aa104f9d10d36892467ee1f7c9c73da6ecfc4a98cb4aa1b","xz-5.2.3/src/common/mythread.h":"8d0c6391f2b758c3a6f87f16b5f875a0bfeea52131250574b7d57c1903d96b61","xz-5.2.3/src/common/sysdefs.h":"eee95743275635246e07fb66e6100765cae3bd5cedaead921ad6cac2e316377f","xz-5.2.3/src/common/tuklib_common.h":"1f07791b997b9feb81d4b1b56b537114e84030fef7db3cd904215c60fd0cc285","xz-5.2.3/src/common/tuklib_config.h":"9a60f2a72efab8a1b3dc44d428b8058c3e5cce9f100a6c1a08c7621dec268273","xz-5.2.3/src/common/tuklib_cpucores.c":"3ae85bdd2036a5b68ef010388df231ac70f6a15d935cb211af29301800fcf266","xz-5.2.3/src/common/tuklib_cpucores.h":"e2e7a1ad1304be23b2c068608d5c353e0e20b3f5b1d15ef4c080b0bdaa02d136","xz-5.2.3/src/common/tuklib_exit.c":"5257ba4143203933508e29ca37feb8d13dbb31d58812898be7039e35b4beae95","xz-5.2.3/src/common/tuklib_exit.h":"f8a93da1333db3b5f44ffc837a8c2f487880c02974bf9eb5c645407e8ecc0e23","xz-5.2.3/src/common/tuklib_gettext.h":"b2538271af8a1f51bef13b68e793ee69f2d6983892d860b92a535b4aa90b1612","xz-5.2.3/src/common/tuklib_integer.h":"878367b9762dc466c75864e15b7eff9070781383aadf1e34f8a3e7d5541d102f","xz-5.2.3/src/common/tuklib_mbstr.h":"e209e406810cae18efde147f24e8b66d3645243e90f2ac0aa5f9ef2b0b453f6b","xz-5.2.3/src/common/tuklib_mbstr_fw.c":"6e0d0870b845d6e8d61dd1718cd571db3db0495c7e2fb293b51d0f1bfd8fd341","xz-5.2.3/src/common/tuklib_mbstr_width.c":"497103f332d1eb4b420ff11e71649923c224e3167698ff7e4f9845839e4cc7ea","xz-5.2.3/src/common/tuklib_open_stdxxx.c":"674baaa486dec81a7394c51e5bb0a723f505f9df9626d2587c2c8bc15072e697","xz-5.2.3/src/common/tuklib_open_stdxxx.h":"eda1984d58364eec9949aa49fd110d62b1d3685f7addc6fe4c3f1284bc8dd614","xz-5.2.3/src/common/tuklib_physmem.c":"2da27bdaf9703705d749dc4a2b79f58b49ceccb1b7e34f388a1afb69cd722d4a","xz-5.2.3/src/common/tuklib_physmem.h":"dda058f02fcbf14d326acdbddd704c9b1823b3bbd3028fef120b70c5a20a1c02","xz-5.2.3/src/common/tuklib_progname.c":"3956e35bc0002e479aef535d4c565286c244ce17bd925ad693d6794412df37f9","xz-5.2.3/src/common/tuklib_progname.h":"9343b38f50a61f695b44ca41d4ad7d363e571eeb72b57729e5e779c3fb943abf","xz-5.2.3/src/liblzma/Makefile.am":"86ad0878521666a2ada15a86d7d48bbbdfcb087391cf5e98984667d7ac0c472a","xz-5.2.3/src/liblzma/Makefile.in":"57038a0970171d30ddfc8642372ba76c4df92e901783f85f608a66f6e987d3b2","xz-5.2.3/src/liblzma/api/Makefile.am":"400d830936568f09d5b670fa57a91aebe7c4d59a217dbce0a1f1ef248bafece1","xz-5.2.3/src/liblzma/api/Makefile.in":"97104f1b333752acdd457f0caa9f8954144c6b23843f40ff16bf0fbf8f79dd62","xz-5.2.3/src/liblzma/api/lzma.h":"42b6e2029bb2457a0c1a70913d07dedb08daaee613fbae5d0c9675b257afb91a","xz-5.2.3/src/liblzma/api/lzma/base.h":"387707f60d1d54f4b8ff51d1be1a10244c360b89a7dfade58f4dea23d3555949","xz-5.2.3/src/liblzma/api/lzma/bcj.h":"485ee1ac185747b6e5324094aa462af194ba3a22a0206314e25f70423045e43d","xz-5.2.3/src/liblzma/api/lzma/block.h":"fbaa28d605010a58b00b6b6ff4a5c41a89ee9eb2adcf5d54fc5b011a397414e7","xz-5.2.3/src/liblzma/api/lzma/check.h":"79ef75b06fe389ccbc47ebeea1bb704157a58fe9710ddfbac8a62035359f9ae1","xz-5.2.3/src/liblzma/api/lzma/container.h":"41f2fde869a55c5da0c8d48348aa90cf114a4f7676f92e3386dd000949ac9aba","xz-5.2.3/src/liblzma/api/lzma/delta.h":"db9db049ab07363921bf19320174afbab16a1b4d401f797a5b2232dcb89b9d64","xz-5.2.3/src/liblzma/api/lzma/filter.h":"99142d7f19743625dc952c1b453229d4fdddd7c5d612bd596f947d7487485f65","xz-5.2.3/src/liblzma/api/lzma/hardware.h":"b5b2574c9cb7fb98450d7bd3baf656c38aad6b6fda9ccd5796d1e0fcf41892ac","xz-5.2.3/src/liblzma/api/lzma/index.h":"d8feec69646325a13d9475d292727a110dfe3e72b31412f70617642dd6a553d2","xz-5.2.3/src/liblzma/api/lzma/index_hash.h":"0840c2ae8dedc05a7ffe1597ead131532a8dc03521728d1d38e55da0fa769831","xz-5.2.3/src/liblzma/api/lzma/lzma12.h":"9722b770c5bd05f701fd77b195cdb27c02d0eeffc13b10b28e6312093555c699","xz-5.2.3/src/liblzma/api/lzma/stream_flags.h":"beba70fa9d83dc6a7fcfae9b1f8d07b3b5acbbdc789f008e63da4206e2434acc","xz-5.2.3/src/liblzma/api/lzma/version.h":"ecde4959e6bf10e7907b0b1361cc6d30b950260fd69a24e2d1c1f9ae11e2dd47","xz-5.2.3/src/liblzma/api/lzma/vli.h":"408347fd3b2b2c2b1e50f81963bf393a8b817dd1c066e1ba7e99705ea3d543f3","xz-5.2.3/src/liblzma/check/Makefile.inc":"200fa89c39ac280abea3fb0026e10880de9eaf526e50a5a9531e079d8b050afb","xz-5.2.3/src/liblzma/check/check.c":"bea09bd4b782dcf36b674fb5e2583e4fb11023ff3fec4d2824e5a912e5c96ce6","xz-5.2.3/src/liblzma/check/check.h":"27ccc14df0db6970deb58b9fc261c417e4e24b422f07db353d549b2ac88a69b1","xz-5.2.3/src/liblzma/check/crc32_fast.c":"558b5c05ec91cc37e197b4eacbf0fc58559ec26428db37dbc8f4b6f9c7031b0c","xz-5.2.3/src/liblzma/check/crc32_small.c":"52a70d7be7e0f29bb065117e31d86d8d6db387ff3fb13c43d3e790e511cff2a6","xz-5.2.3/src/liblzma/check/crc32_table.c":"58c9cabd23f44deb929d52ee62195a556bc2a3de3d8328a2b9e513e07282d6eb","xz-5.2.3/src/liblzma/check/crc32_table_be.h":"d6f2bbb39f07fbc0c166bcec1a11f4680c1d20553f5a12a29bc991bbd3d4213e","xz-5.2.3/src/liblzma/check/crc32_table_le.h":"95fdd8507304a2c07cca6beee871d752a91dfb5a0c6ec290648e582bf562017d","xz-5.2.3/src/liblzma/check/crc32_tablegen.c":"baeaadb54ee5faf389210c8de880adc44830b8ce12cf32537c59a8a5b498476b","xz-5.2.3/src/liblzma/check/crc32_x86.S":"6caa295858c8327bc0eb35eec0de725a934065f0b463bac0f254edb381b47f78","xz-5.2.3/src/liblzma/check/crc64_fast.c":"c05b26e1196d02ebc333b8fa3012e71cb2aef4e890abfc2189be5fe59634f2f4","xz-5.2.3/src/liblzma/check/crc64_small.c":"3f6007032a8e75cbc57f1134ebadc929f4eff9cf34fed85e960eed79c06a91bb","xz-5.2.3/src/liblzma/check/crc64_table.c":"76492c3de7dfa3a8578fe5ad41b69500c2af235728432e8ee19a26dd6e40f480","xz-5.2.3/src/liblzma/check/crc64_table_be.h":"8927164685123fb0f931195973b95c096c32c063aa82815b98609fb3c34f951b","xz-5.2.3/src/liblzma/check/crc64_table_le.h":"dfef9fef2c5b973ad585aa971729dff570f1bf390db12b022f565a411fdf9e04","xz-5.2.3/src/liblzma/check/crc64_tablegen.c":"af64bc13735080958a6f9dbab3a24b267dac0bc8f91c4c92149ce76287e08550","xz-5.2.3/src/liblzma/check/crc64_x86.S":"d10b289ab8b7cffa6193c903531fc08a91853d50b61ff601c7892e966ab252f6","xz-5.2.3/src/liblzma/check/crc_macros.h":"e89523a8599be0521986e678c9b7da701199eea43e6d81d448c87f07ed4db9cd","xz-5.2.3/src/liblzma/check/sha256.c":"c143c38c74222bd1f0ea0e5abd67dbd49c47b1828d59b82bf43786dc56393ec9","xz-5.2.3/src/liblzma/common/Makefile.inc":"89b90642d5ff3b0e9983b43789b94401f0fe85b6adccf7b17ecf39e71a34b81b","xz-5.2.3/src/liblzma/common/alone_decoder.c":"667c357ede5b35df0eac618aa1cd773a9ea7aa059575ece7344a65597a025df1","xz-5.2.3/src/liblzma/common/alone_decoder.h":"95b4f8e6567076af9651291f98dd145e213e388a8a4ff4ca3dcc5fd361a6f54e","xz-5.2.3/src/liblzma/common/alone_encoder.c":"ad037edc0e35cb9a1d7cae10ba737f933d797333ad8cb5f99c5dd06b0f0cc553","xz-5.2.3/src/liblzma/common/auto_decoder.c":"9777c34025c7422b1e68d32cadcf848f950412f1fa7062f5cf8a4a1af9a224ea","xz-5.2.3/src/liblzma/common/block_buffer_decoder.c":"13b954917929088d5205ebef3bf14d0823ef6233deda0ff26f8c0d8e7371f637","xz-5.2.3/src/liblzma/common/block_buffer_encoder.c":"4d4a0fe031353e53baab66056cbfb9d7c5bd323a0546e4a368252e14195d9b2e","xz-5.2.3/src/liblzma/common/block_buffer_encoder.h":"92954e63e2bab41d09acf2cd39ea988639a573724b08acf52192e28895cb9b8c","xz-5.2.3/src/liblzma/common/block_decoder.c":"e82ef1b890c9ab629f7d4387fda44b0261a9db875405f362c266cf502bb90ba3","xz-5.2.3/src/liblzma/common/block_decoder.h":"d067e66c89f066dbe698efae7415143347a44e2d3629bab61bb217b3e3ab49a2","xz-5.2.3/src/liblzma/common/block_encoder.c":"b05ca89a7923d9cc61aee04027e47700302cf81c3b9d983e4c6075efec959510","xz-5.2.3/src/liblzma/common/block_encoder.h":"2595cc5c2f67a57a574356cbec5d5d1b90ca6c6e9f431a4364067acd5d3e6632","xz-5.2.3/src/liblzma/common/block_header_decoder.c":"ad9164dec9c21c906ecd141e94fd72a536b4dfaf943a3887024a03657f285cba","xz-5.2.3/src/liblzma/common/block_header_encoder.c":"2546ccb656272a34d7e68fda5d233aeda816d82f5c90420756d5a7068b57e47b","xz-5.2.3/src/liblzma/common/block_util.c":"59d9cf65e20849202f2c2f7fa9f7569239f2c86687fa45cd309863a90f643eae","xz-5.2.3/src/liblzma/common/common.c":"fc1b0a0b3c20ad29ab22a42f95f80b537a0011c64ca970b872bc743253f9e3b8","xz-5.2.3/src/liblzma/common/common.h":"a3f7e30eddf1e2913399fb2ac90af32099d387cb691c363d12c09b68138611eb","xz-5.2.3/src/liblzma/common/easy_buffer_encoder.c":"3d66fc8b3788e815a2167460f312fe45725d1bba6a3c23e5977a1727eaa33964","xz-5.2.3/src/liblzma/common/easy_decoder_memusage.c":"f2daa4675f914f503f28df798ba5c2c5fbbc0a94b08cc305e9c6645569cb8c7d","xz-5.2.3/src/liblzma/common/easy_encoder.c":"331416f038afe091a920e629db9f3f3b594fae05705354e0ba1e8ae5fc4a6ca6","xz-5.2.3/src/liblzma/common/easy_encoder_memusage.c":"ac313566ecc7062a84014457be28bf046b29be2bf9a036c8b6fb49c57b3182d1","xz-5.2.3/src/liblzma/common/easy_preset.c":"65ea57b839e0ec864fb26f38ba66a8a0d2070dec63a821b1a1665273ed0b2738","xz-5.2.3/src/liblzma/common/easy_preset.h":"0e0bcf762c76499d86a6bfb7ae11ecf5be4d50efe8339096e69a605f2fac1b32","xz-5.2.3/src/liblzma/common/filter_buffer_decoder.c":"5fe3edd0cc5641463840775aba4ced9027da9e91ae50edd8eadf14a3bc1fb94e","xz-5.2.3/src/liblzma/common/filter_buffer_encoder.c":"eddc23cd0e0fcb0e4cd5b66c2878d580adf9bc1b6dfa1818e77c4488b9853203","xz-5.2.3/src/liblzma/common/filter_common.c":"39e17b0e805300649115a22123ac6cf40b21132726c9591b5deac5d6c1a3a2e4","xz-5.2.3/src/liblzma/common/filter_common.h":"f8808dfc406763d32b2cfc7f3a0685e1b7fe45ffde3436cd83a789f1bc493445","xz-5.2.3/src/liblzma/common/filter_decoder.c":"23e163711327e49d82f0e3677ea3579233a050acc1dd835b06c8da496e2c3709","xz-5.2.3/src/liblzma/common/filter_decoder.h":"2a45547e1fcc2b122a317bd19195ff99cf4f1cd3427f63aca4879682a1d25e3e","xz-5.2.3/src/liblzma/common/filter_encoder.c":"384b83831d1f1fa75fef39281dd7a1f5325a7c4c23f06d24f149e8b4dd75f3e0","xz-5.2.3/src/liblzma/common/filter_encoder.h":"2b6a90f9054d6b34dc0e42846bfaf7fa816a04ca531421b19fc6118ae2c83617","xz-5.2.3/src/liblzma/common/filter_flags_decoder.c":"fe9cd544195e038010a31ba5f5b3f9f5e1d412f1ee315d231f87948df6df2124","xz-5.2.3/src/liblzma/common/filter_flags_encoder.c":"75d3325b9ec18cd7cb7ec3464fe2b5b23e919cbfade9df48bc3303eaacb1c121","xz-5.2.3/src/liblzma/common/hardware_cputhreads.c":"f017cc4bec6f5e922e58c58d240b5432a0375874c221e09d95a3af0be30c224f","xz-5.2.3/src/liblzma/common/hardware_physmem.c":"9c24bf5d1c12ca6e459380d0ef3c357760f81037ca04f98a2af4425a746aa4e4","xz-5.2.3/src/liblzma/common/index.c":"7aca4e0de549feecb00bf4c4fde58ace144d90f7a11cb01be70155ae388188ef","xz-5.2.3/src/liblzma/common/index.h":"57f38ebcb497405b4efd510579678a891873143c65c7d6a6bbc8e3764e4c62d6","xz-5.2.3/src/liblzma/common/index_decoder.c":"288df67313244bb1bfc3319dd5d4e01572ec024c180a38ec4f11532604d646b8","xz-5.2.3/src/liblzma/common/index_encoder.c":"07bb53b6d65e0fa43b683def95623f2330000461f32552dfc55fdb7cf0bcf070","xz-5.2.3/src/liblzma/common/index_encoder.h":"d90e2aa654e0c78a3cc43f3bd2628fa2d208e76c0c9b1d1449e53830fda03bf7","xz-5.2.3/src/liblzma/common/index_hash.c":"154f56d958ed4d2a1ed335103b141ae0adedbbdffad11751a2d000fdf95a51d8","xz-5.2.3/src/liblzma/common/memcmplen.h":"99afe1d736a3b2a464c7dbb6d2eeccc45bcd46c7248a024cb3e7015f596c41d6","xz-5.2.3/src/liblzma/common/outqueue.c":"78b30911bd1b7cfde10f3c59e8827850539f5411cfbdeaf3f830c0a34863ed73","xz-5.2.3/src/liblzma/common/outqueue.h":"9355e10fbd2d9fbf9413ec2d0925729907599063a2a8980abd6cbc6288d38f4a","xz-5.2.3/src/liblzma/common/stream_buffer_decoder.c":"ac2e5511d2833f9a00c3199e2eab458d560800c34ebc6ec9cc78a2cf7da5df4a","xz-5.2.3/src/liblzma/common/stream_buffer_encoder.c":"1908b3c0078e9624cdfe72df4935c638a01064a4992d8c18ee96b1cf86edc75b","xz-5.2.3/src/liblzma/common/stream_decoder.c":"057905ea920ebaa3165c881a2c292ed6b6422f2340850e347aceb8f7dc58dbed","xz-5.2.3/src/liblzma/common/stream_decoder.h":"1d8b599273cfc339d14bc03fb6d729d03f1045c3237ad34d607e0eb9ff96dab9","xz-5.2.3/src/liblzma/common/stream_encoder.c":"724f757f11b55c7a5a8e53973340b7af02a8f7adf0753e80759b90c36b15ad14","xz-5.2.3/src/liblzma/common/stream_encoder_mt.c":"6fbad07969c2f759bc2e96313907ec88b31789abb7bab0baad7cd5a6cd2e5344","xz-5.2.3/src/liblzma/common/stream_flags_common.c":"c23cc834a730ca0141f6569ed8717c2285a0b6c4dc63930f4d8ae2cdcbd853db","xz-5.2.3/src/liblzma/common/stream_flags_common.h":"e0287a3d2bfb9abb974f4ee4ce67cf67b6adf1015bed7e9ccf92b7d8715aa878","xz-5.2.3/src/liblzma/common/stream_flags_decoder.c":"06abe4767eec770545f3983bb688772c41df6d66b6280fdc95343710be5cde3b","xz-5.2.3/src/liblzma/common/stream_flags_encoder.c":"be639e1905a5fa082dd88fa498a01bdd0a3d3df202665fc66396fa398ee15c26","xz-5.2.3/src/liblzma/common/vli_decoder.c":"2a1ac4d19c16d861e0221494c5fd05512db40c43859f427accaa3a6be520d754","xz-5.2.3/src/liblzma/common/vli_encoder.c":"a29a42274cb4e997b20e7ff4ad17d8f464cfc402ff7ea23a020279059e86e971","xz-5.2.3/src/liblzma/common/vli_size.c":"84970cb87f840b317f1218fba9068d30013f8dd2f42e4bfac163d894229e9259","xz-5.2.3/src/liblzma/delta/Makefile.inc":"1b0bdbef291dab04b95250d16814351ce5bf2cdf768e7d50ec86397fc9a0a8a0","xz-5.2.3/src/liblzma/delta/delta_common.c":"d1de035aa8485f85c8b288eec876b743357fd5fbed0c14267443307ae9e6337f","xz-5.2.3/src/liblzma/delta/delta_common.h":"ab0687c451cad4e5a831686f579ae51579cb5c35826db73688871ab1ebd3bb2a","xz-5.2.3/src/liblzma/delta/delta_decoder.c":"9f084a005848e0004fb919cbadec17c749db5e254895c0735c5146833ae34ee6","xz-5.2.3/src/liblzma/delta/delta_decoder.h":"a5cff12597923e2481e8fb2988b67fa4659a407199824eba2f0206bda47d7268","xz-5.2.3/src/liblzma/delta/delta_encoder.c":"eace1e85192db49ebe7ec89d633a99a65e416920f863e401e62697401335544d","xz-5.2.3/src/liblzma/delta/delta_encoder.h":"2bcd0e2fb30f4b5ce3e5acb6df5eeb1c95024fbff8b52e2586dd226243a3f228","xz-5.2.3/src/liblzma/delta/delta_private.h":"fd00f847e99b88a031182a3b5d52f4f8957aedadd10a96c1e7012edbe4a135d9","xz-5.2.3/src/liblzma/liblzma.map":"fbfee8d61ad96f89910e35e3915fb21d1c5ff584e2d9e1d2b6b62349bb9864d1","xz-5.2.3/src/liblzma/liblzma.pc.in":"2ea84ce8be346e75f8e8410dcaf871f95fae6fcb0aec5da854c2c6e09dfff05d","xz-5.2.3/src/liblzma/liblzma_w32res.rc":"62c5e352a64d5add147f5412ba3223ca9c24b766184fcfa6b885697a4110058e","xz-5.2.3/src/liblzma/lz/Makefile.inc":"d616835619909528c789e9204119154dc21626ba133db74b22906e6aaff797a8","xz-5.2.3/src/liblzma/lz/lz_decoder.c":"53911777644cc11fc544a5b324bbbb377b12a6230cb3ff6506d0193f60b08c91","xz-5.2.3/src/liblzma/lz/lz_decoder.h":"d2b8d43803f39c846fe0c685740e26366a8d4579f8d5687f0ed719cbf125d0c7","xz-5.2.3/src/liblzma/lz/lz_encoder.c":"7eff05d3d25136db679cb72b3c90fe2e3090cd6d791e6c24d6bb57782a71d3e0","xz-5.2.3/src/liblzma/lz/lz_encoder.h":"64ff40bdc990a3921b6d3678627d8bd26e4032e42a8a9559e370c369d633a53a","xz-5.2.3/src/liblzma/lz/lz_encoder_hash.h":"a31a243ca234f2f5e310132079ff3ea47b163ae5b07b211cbbb63614f97505ca","xz-5.2.3/src/liblzma/lz/lz_encoder_hash_table.h":"494d503e26cf1fd2cc08ebfc7bc9f96a2c56e8e9bfba6f86eef63e4add744f2f","xz-5.2.3/src/liblzma/lz/lz_encoder_mf.c":"7d9b636342b7f3a8d49d73265cd7a12290fb576d5e02b284eeb5ab07dc57fe2a","xz-5.2.3/src/liblzma/lzma/Makefile.inc":"8ab29479e093b48af89e8c4cf6acf0a1660423570b83f2dc55757ae55677863a","xz-5.2.3/src/liblzma/lzma/fastpos.h":"790a02cb3105c9332927604a976e78f2f39c3b046bfbf456e430faf32dacffea","xz-5.2.3/src/liblzma/lzma/fastpos_table.c":"d2fba7f634dd93ba6d1a12e26a8292e96a9c71090c94364e47b43e4d8ee642ab","xz-5.2.3/src/liblzma/lzma/fastpos_tablegen.c":"62fd65638f54438d110ca917e52fe35a5286674a7781ef6360a4a5b1e1a07c6e","xz-5.2.3/src/liblzma/lzma/lzma2_decoder.c":"5c22fa4550da1b492626b55c4dd6b43c4bf551ada1cca8e078b3b78ddf1c9d25","xz-5.2.3/src/liblzma/lzma/lzma2_decoder.h":"ce79b5baa8062e63078114778a920203ad9c35e351f281999682b60106f3ad2d","xz-5.2.3/src/liblzma/lzma/lzma2_encoder.c":"65c815a5f2ae106a04fadbd301d8bd1dedc52aef6815fac84a97933866640c4a","xz-5.2.3/src/liblzma/lzma/lzma2_encoder.h":"8558aedaed67c0b2282ee69f97aa9f95a8d19562475b0cbe93c9539cc2098b3f","xz-5.2.3/src/liblzma/lzma/lzma_common.h":"05905ac386202b25cda9f3961bb07ec80acff3855c7fc12ebe7cdf78e9aced67","xz-5.2.3/src/liblzma/lzma/lzma_decoder.c":"b4665d674cdf1d86e8afd9a798c57490a443ecefd936936bc5ad9f94cc3268e1","xz-5.2.3/src/liblzma/lzma/lzma_decoder.h":"6b455583a68834f3e31aa81d6620b27fd44885bde72decf4ef52a05c4c66e19f","xz-5.2.3/src/liblzma/lzma/lzma_encoder.c":"0e68917175ad12f297093d15ed9ab247fafa63dc6844e4a1a12b4677e42ca478","xz-5.2.3/src/liblzma/lzma/lzma_encoder.h":"2ca6d3683107f4575c227e1d2a525db81c691a5b7ebc1140bc381484ca4e58d2","xz-5.2.3/src/liblzma/lzma/lzma_encoder_optimum_fast.c":"985b0b9ba50af0605cfe4028e177315dc156a64653dc0318344552ddcb9e3087","xz-5.2.3/src/liblzma/lzma/lzma_encoder_optimum_normal.c":"8b4e7b94bd033b8e7322465fc42b972623c258ef13cce224aa6be8de90d2ce37","xz-5.2.3/src/liblzma/lzma/lzma_encoder_presets.c":"d3ad6260bafdc8d12319f6548231a332f6509f61ce35222e83bd8ed33065242f","xz-5.2.3/src/liblzma/lzma/lzma_encoder_private.h":"6cf7eb3b817ae62c1cb4f8c27fc7dc1d8ba80cc9ccff2ce37c3ca498d67873d6","xz-5.2.3/src/liblzma/rangecoder/Makefile.inc":"fb835be542437407ec1b1409a069d0a14b5550b06e4188e3b0cba8abadfd4790","xz-5.2.3/src/liblzma/rangecoder/price.h":"d11cf3ae775f7809c909e3a60c5b9d3f2d3f1a8ff90b6320a236d955cf3dd15f","xz-5.2.3/src/liblzma/rangecoder/price_table.c":"916cf099a79c5c68505c090fbf8a2e76a61c2cea83c6f158271eae0e657fe9ca","xz-5.2.3/src/liblzma/rangecoder/price_tablegen.c":"de6b7374b7c208faf7782232229886f5d944dbb98ad7d30a423c37036feab56d","xz-5.2.3/src/liblzma/rangecoder/range_common.h":"a68e29f8c979874966df0f2145705f22decd34ffd5e1034efeeef8126430f757","xz-5.2.3/src/liblzma/rangecoder/range_decoder.h":"e8063a1782bd85f9a7f94f5b5e1114622cb30c842c09fd2c657793d0edfae8c2","xz-5.2.3/src/liblzma/rangecoder/range_encoder.h":"6a43ce6dfb706662419b2246e1c21e6e90e8f5ba2e1e0a8a049533ea4df7bda3","xz-5.2.3/src/liblzma/simple/Makefile.inc":"5f33830fe8750481867dd7986d02894beb4e86b1bbf716e227f0132a0615819a","xz-5.2.3/src/liblzma/simple/arm.c":"d7fc50ce8d8afcebd08dea8e2531500c49f398c7ef8b7c7c8ebdf69efc311597","xz-5.2.3/src/liblzma/simple/armthumb.c":"fd7184a80b0d53f9d42bf3122f642a17881947419c0eab306b5d67f11cbac337","xz-5.2.3/src/liblzma/simple/ia64.c":"44f58579861358d8e0fdb3363aaf96b42c0d9aa54baf174f271ab22e26d41958","xz-5.2.3/src/liblzma/simple/powerpc.c":"7354365dd381dce8303c448ef993d2e059f3da36554ea08bfba0aad5b1548e37","xz-5.2.3/src/liblzma/simple/simple_coder.c":"8136e3b24fcb81b75a88e56516b95dfaab8c5eb29a5a693879dd075e55be381b","xz-5.2.3/src/liblzma/simple/simple_coder.h":"c8301307e370fcb40feba74c55c62ba50c4f29fe1242c822de09665a75512a3b","xz-5.2.3/src/liblzma/simple/simple_decoder.c":"51d678b89325e48e8af2d7cc3061569f17e5de36af6e49016b4e4b36d9c13a8f","xz-5.2.3/src/liblzma/simple/simple_decoder.h":"22c1d4850a392672ea50b72c8e60c5891dc3c9429715124408eef4c649f4a6e0","xz-5.2.3/src/liblzma/simple/simple_encoder.c":"10146da95bf969a8eb0a6f45a87bdbbe55a1dfd198253513d3d89d35b3d4013a","xz-5.2.3/src/liblzma/simple/simple_encoder.h":"bf61a79557c59ecb60489e07ff3fd4cb2e0eb226670e3b3ed3ed86f9aa4b34e9","xz-5.2.3/src/liblzma/simple/simple_private.h":"89d35ed2633465ecfd589d1a69442083eb80f0e1027725968411258a86204938","xz-5.2.3/src/liblzma/simple/sparc.c":"8bd89686c31c4700541f236239612e4bc91bb1346c2efd7074e032e98da6845d","xz-5.2.3/src/liblzma/simple/x86.c":"e4ea15a021d2dda07bd4c04d07ca15fce29348aff46756ccee5799037bde0a1b","xz-5.2.3/src/liblzma/validate_map.sh":"c34a6f22905dbbc4900e3945f2484ac8c97900bf68f3015f91e177731120d38a","xz-5.2.3/src/lzmainfo/Makefile.am":"517291d4ea68eff886e257c9a921f0fd0021a6883e6ace36f03f12037758f89f","xz-5.2.3/src/lzmainfo/Makefile.in":"c99a3cfddaf721f802585f4e362fa1c50c5c6cf9ac07fcb8d131720974e7e3cf","xz-5.2.3/src/lzmainfo/lzmainfo.1":"0963a1fe3e0539f036aaa9adf5bb179df10f2abe5f7f470c87340a5619e5f500","xz-5.2.3/src/lzmainfo/lzmainfo.c":"9b59add935c2329b84555bdacd7e6926bb35197e8e860a8fcf1757c320856532","xz-5.2.3/src/lzmainfo/lzmainfo_w32res.rc":"04a960119a80ae00c04a63c500626a321fee38281778b415555d289bb6a40727","xz-5.2.3/src/scripts/Makefile.am":"ff195ed243d7256172024a6c8dc4cf11c316ceee0e17a6da4d52778366ffe18a","xz-5.2.3/src/scripts/Makefile.in":"19df2d15a7ddb4bbd8471eca7ec2d42ee63a232b417430e03c554dcc43bc8325","xz-5.2.3/src/scripts/xzdiff.1":"fea4e489a64a2be64121e36041b993021839fbfe59d49a8b1b737c93fec3d29f","xz-5.2.3/src/scripts/xzdiff.in":"4aae54d26eb113c6ec1a9790dc097947e51a0ec9fed156090e344257d6b2baec","xz-5.2.3/src/scripts/xzgrep.1":"d838d6e694c2c9bc89a5b118e96ee6976c74319bf3e1d469c9d6d66674e34a7d","xz-5.2.3/src/scripts/xzgrep.in":"bd12900e67c80ae7abd3c46731ccadc02bd06b935d08bf69130ee5540ce77d68","xz-5.2.3/src/scripts/xzless.1":"2db6570b6f62b6f0d46fecfc18ead93000abaec97399514b31e18edb7ab2fecb","xz-5.2.3/src/scripts/xzless.in":"2d29b72f79de105bd29499edc3548b677cce24381d56e78c881e3f3daae15d76","xz-5.2.3/src/scripts/xzmore.1":"551a2a7f6e2e5626b0cee4580a0107d81410afd742da25001c846b4fa7645b07","xz-5.2.3/src/scripts/xzmore.in":"2f0f5b355285ef326258767797716c3c7885332e6dcf593573019906d0644b8d","xz-5.2.3/src/xz/Makefile.am":"864d6d9a5eb22553bb719a5a7678ea5cd480e171a3a49e66328816353d9f64f1","xz-5.2.3/src/xz/Makefile.in":"542a1bf45dd9daf2167ef4396f2167e5ad31fbcc89b3140e141d06799bf984fc","xz-5.2.3/src/xz/args.c":"8f650cfd30ce5bf6547691996c6eacee577a2dd9898d6101567b87122d3ef26f","xz-5.2.3/src/xz/args.h":"46521467728df4959f0a76fc3ca8a72619c288a2cd3c7db99d794a0b553055fb","xz-5.2.3/src/xz/coder.c":"10b36cfb0899b030663e5509a0c3662c7f7f5535a29f6e097437f91682f7a420","xz-5.2.3/src/xz/coder.h":"8aa2c13ffe794fb78504cb782ad57b85a314c7652091fbd3d798730d0205fcb8","xz-5.2.3/src/xz/file_io.c":"ba1454e57a295179e44dc1f7f51ad5fccc8a86470e9d49dcb2f2e381fb5f0569","xz-5.2.3/src/xz/file_io.h":"32138c65942b5be8160d61108077a63c1329a4acadf4a5496129988b1d4aa9d8","xz-5.2.3/src/xz/hardware.c":"50b5e99cf6f74e0856d3f02674c18f83fc22b0d1d8fec09c729d2e28259fbf4f","xz-5.2.3/src/xz/hardware.h":"38ac7e3e3acd28f09ad18f7200a39949ef7a373b61be5094b00525fbefb51a54","xz-5.2.3/src/xz/list.c":"ec6d7132cd4f6f34bbef76d2ba006924cf22832f9c5c0f45fba40c9641cd30cd","xz-5.2.3/src/xz/list.h":"63d7517c23adb530850dd4e4f92783f78bd52ff46b2746ef4ebffaaa8c4bef71","xz-5.2.3/src/xz/main.c":"610b2858d223b494f242d5dd413aa92fc3179249b16807b43c76c0c03c474f29","xz-5.2.3/src/xz/main.h":"e2737b49acdeafedb35619a862bccbc886d918a3d2d8cb633d06914955584fd4","xz-5.2.3/src/xz/message.c":"2e6f12174e15a61fc2602a58601169258ac244f6beb225c67bbe79e4f92d28a0","xz-5.2.3/src/xz/message.h":"409ca162b16c6755b84055020a4202c4a95fd48fb147e80b2cac9a7736af48e2","xz-5.2.3/src/xz/mytime.c":"08404f52436ae4ad0842c7787c5b4e1471c3fc3162b125be2b6e6c66eb45e10c","xz-5.2.3/src/xz/mytime.h":"d45be8e58683ccc34415a0b7b3fc32e6b32fa41ed661cbd345d4a152aff4ea11","xz-5.2.3/src/xz/options.c":"f0953f0e4faca6dd26ac0eb81261e345ec9302c7b54eaab576478e1e6ff08e94","xz-5.2.3/src/xz/options.h":"44de29c2eb5a7252ffc8b91ff6dd9e209a3fffc7d9cfb5119a2270f136895abf","xz-5.2.3/src/xz/private.h":"b0804ba5a06f9bb3fb9433c67237fc3c36fd9a04b6f444bbc4536b1dddb39a87","xz-5.2.3/src/xz/signals.c":"3a5f9dd993637bf9062593dc558417ecb1ae2c026d075ad1bbe9695ab8ef924f","xz-5.2.3/src/xz/signals.h":"38f6cec8dd2dd1fe0d927e13046f77a9295fe1404f5eaaf0de672f6202821073","xz-5.2.3/src/xz/suffix.c":"82bbdcb43e38090979cce401cb98709ec54a2bf88705ee98b81abee203ef2d9a","xz-5.2.3/src/xz/suffix.h":"37bdffa95beef1a1eaa1dfb764fcc450372ceff44a866bb60ab80453fb7bf9cb","xz-5.2.3/src/xz/util.c":"94107291a967a0e85088e1b7118e66793a456df0258c23e81b553f7f2d4cacff","xz-5.2.3/src/xz/util.h":"0ed0546122bc9b7422b64252a33ef061f39f48ebec55bbfa0d6374e5775c0826","xz-5.2.3/src/xz/xz.1":"2eb973fc64bc58b40c70a6887cfa2c95f64f076d309409cea7c6f94b89f0cf9a","xz-5.2.3/src/xz/xz_w32res.rc":"d42a35bcf8e872e875972fb90f3971acfd570a45c07d258759cc9b3e8a1d7424","xz-5.2.3/src/xzdec/Makefile.am":"f0709c759d911ad2450e185a4997e550a5fb9990805f3be7d70d1675644a65fd","xz-5.2.3/src/xzdec/Makefile.in":"fbfeda69f242dc2cfa2808bc94be1b9bb9e5de9dec268dfc01519761c2a582b8","xz-5.2.3/src/xzdec/lzmadec_w32res.rc":"87c6554af463075e3109964769108a54af237eeb1b427a75dfd8b92e0335bee0","xz-5.2.3/src/xzdec/xzdec.1":"d47d7c95f22cf49554b8d361f4a4e3bf95474a88849ca64a00c1e884defe3201","xz-5.2.3/src/xzdec/xzdec.c":"42f2ebb08bd9a8260076f053d4b8ea7fb7eed9d838bc72142e0b9e051708aaca","xz-5.2.3/src/xzdec/xzdec_w32res.rc":"356ce543f7143a6572da3bdaf473acd686d8765a672a929b7dc79c5f21c15428","xz-5.2.3/tests/Makefile.am":"3e726b207ec54a8bd4e3e4ad0e4b4e9cdb973172d2409b81de2cc54acb1715dc","xz-5.2.3/tests/Makefile.in":"a34be569447c4dc2c0340572dafa558bf91232b528386c58116d058f9a67479b","xz-5.2.3/tests/bcj_test.c":"6984161ceebc2f94ba41047b85ddd083f64266f354d79f128c57882378aadb61","xz-5.2.3/tests/compress_prepared_bcj_sparc":"898511c9fbfd1ff3ad474638283a82a0bc0ca11fcb47e7a7e1f8b0758d999ee2","xz-5.2.3/tests/compress_prepared_bcj_x86":"dee7bc599bfc07147a302f44d1e994140bc812029baa4394d703e73e29117113","xz-5.2.3/tests/create_compress_files.c":"fd8c8370869c27a8923b770996094c81a4f6166e87639e2cab99a10bf719b7db","xz-5.2.3/tests/files/README":"ca69ae71c4dd4a8211694ce9efc081cc895433691716007330ef3898d78a06fb","xz-5.2.3/tests/files/bad-0-backward_size.xz":"894d4b6d4ea8657893e9ab1c48162438605537e6ff974ee8ee61903b8eaec55a","xz-5.2.3/tests/files/bad-0-empty-truncated.xz":"9de843e125667ecf9b804469889bcea152758585c0e335a7dc15ed243ce83a50","xz-5.2.3/tests/files/bad-0-footer_magic.xz":"b7d60be0dd400c8d8b2a04094d297f4bbf563fd33041cf27ef6e9be74f7df829","xz-5.2.3/tests/files/bad-0-header_magic.xz":"3adb42fba230b3c09d2277adb7f3ba347f26c1831d4e9514d3068bd3bca9d2a4","xz-5.2.3/tests/files/bad-0-nonempty_index.xz":"ece3915eacdc4edc296f593b3cb2617cdd888315eada28dcb366a3fda131590a","xz-5.2.3/tests/files/bad-0cat-alone.xz":"14bbcda4f97f6d3583f36c6a4946d0d0dfb847653175d432ee275d5738d6d9b7","xz-5.2.3/tests/files/bad-0cat-header_magic.xz":"bd3f4dfeae3f4ec3e778809e013859b6b291d18e067c8e9557cc0d4c1009f22e","xz-5.2.3/tests/files/bad-0catpad-empty.xz":"56317222b2ef4743fb18b457c3760094937dacc9fdf18d645c181e5be4b327c6","xz-5.2.3/tests/files/bad-0pad-empty.xz":"a5995e19c63bdb9d327d514c8e8c9d2971b4cfdbc755ffcb11aee30b8a9787b1","xz-5.2.3/tests/files/bad-1-block_header-1.xz":"c8bc15e7bfb1056d358cbe5f9b6ae86489e277e353f275a79a1c212a09cc56af","xz-5.2.3/tests/files/bad-1-block_header-2.xz":"3b0de551b66e8ee65abfaed399e1638de2955aebc882b9585e12d5f93eb21146","xz-5.2.3/tests/files/bad-1-block_header-3.xz":"2a05eb3e61e10b862f09ddaf030ee5a04ca4c875b2dac251ef0529a8ddbb61f3","xz-5.2.3/tests/files/bad-1-block_header-4.xz":"8ac58b8fade15875213c116bec05ec78fc659d3cda69116d3aa4dc71557b2d1c","xz-5.2.3/tests/files/bad-1-block_header-5.xz":"a76c17d193405f180c3b84c9047ccaf1b4f0483242dda58e7c5070313898f3e9","xz-5.2.3/tests/files/bad-1-block_header-6.xz":"f7cc702ce7a2523e9718816b4a5983b05fa8acbb07341df2a5234ce1828731cb","xz-5.2.3/tests/files/bad-1-check-crc32.xz":"4f2de28e30a05d979c7b2db4ba4f4126e92563e3f591bef1508b0926dcf17fa8","xz-5.2.3/tests/files/bad-1-check-crc64.xz":"d7218954fd4bd69eb77b545d8b2428ac35a984ff3bb015846b65d88b325ca219","xz-5.2.3/tests/files/bad-1-check-sha256.xz":"f106a808e57ca48fa4a64b1913042c526c1d777f9eb1622a0857ce18ee34aba3","xz-5.2.3/tests/files/bad-1-lzma2-1.xz":"b99d620ac64188c4af54e88c79404f153642bed63442a31b642942804f1e1785","xz-5.2.3/tests/files/bad-1-lzma2-2.xz":"91517a1280b5e52ddaa5a327e7c7f5a045d22db94cdc8a2f79781135f461de12","xz-5.2.3/tests/files/bad-1-lzma2-3.xz":"e063697abf2d7cbb7271eaffb064484095abbc2397268cbe11897dca8af52427","xz-5.2.3/tests/files/bad-1-lzma2-4.xz":"8777af9f9c9e3ddca331d0671a7753a219ef01f3b87708bc5129cc619e63c6e6","xz-5.2.3/tests/files/bad-1-lzma2-5.xz":"2e2759a097712c49a3e93446276cd56ecb748315c0cdec1d8603d8740c0a1494","xz-5.2.3/tests/files/bad-1-lzma2-6.xz":"646cb3043b6aac6da1540af308a78e6504c7708af54d5815f224f27a58f00919","xz-5.2.3/tests/files/bad-1-lzma2-7.xz":"ddd7b265fe96595408d72a6664ac3693de097c0d887a9419c5aff3a7fee83d5e","xz-5.2.3/tests/files/bad-1-lzma2-8.xz":"85c49abc062cddf535f41347edb368f702c442241ede7276c4d99b0051f19b0e","xz-5.2.3/tests/files/bad-1-stream_flags-1.xz":"c65babcb94c3c175f2d8686391d2d0113fbc434fc8dca009e3f5d1ddf7c83d61","xz-5.2.3/tests/files/bad-1-stream_flags-2.xz":"35ece04169f64180ba2b4fff03f80a3048ba11b3ef4e16a0ce8d9b5c32ce5e9c","xz-5.2.3/tests/files/bad-1-stream_flags-3.xz":"c59b030817cec49b51d1f1b8e9f06ff2535de25e2c4c07a3f45c197d0e3db949","xz-5.2.3/tests/files/bad-1-vli-1.xz":"dde033a0281c2326178e23ace66268dddac8f5d7d2e585ce865c6f3b4e7ed7da","xz-5.2.3/tests/files/bad-1-vli-2.xz":"9eddf417be15f3f7170fdcdadd753c0fe35d22d13377f271319f0c16889b0e4d","xz-5.2.3/tests/files/bad-2-compressed_data_padding.xz":"9cfe1c1e950111e4563d773790073637c3f76d42d586f10e77469844a0c84dd2","xz-5.2.3/tests/files/bad-2-index-1.xz":"ff6b77b8ce16cdb0b6d455c8045029fa6baec1877798a7e7ed7431b9cec83bca","xz-5.2.3/tests/files/bad-2-index-2.xz":"fa394dea8bedb64ad388a8d44ab324cc0aefe9d5b6d7a78b4dfd610ef78263d0","xz-5.2.3/tests/files/bad-2-index-3.xz":"62f82cabb391bb98ba87162ad04376e2d839741b56eff0750e93cea822b767c8","xz-5.2.3/tests/files/bad-2-index-4.xz":"102877780afb8155832afd630e426d2e1456f4da62360e4091bec3524d599cec","xz-5.2.3/tests/files/bad-2-index-5.xz":"72ac8e7907c092126bfcc999474e44aa17d29feeeabacc50819a0b5a737afdb3","xz-5.2.3/tests/files/good-0-empty.xz":"14c80c40f5b247deead9e9d1d31b8b4f5f0b4f4425e6eb12291fd3e505fc8414","xz-5.2.3/tests/files/good-0cat-empty.xz":"65de7e01eff8cf2f9a287153971467b1c11811213b64a38bdf673bad240436ff","xz-5.2.3/tests/files/good-0catpad-empty.xz":"019ad3e542d5f5797c6d98148f72725930a057fec6abd9a426ce889302a9fbfe","xz-5.2.3/tests/files/good-0pad-empty.xz":"6b97fc3c4f6f4a9115377b3dce52caf4e726458ed9dfd68b60f94ccdff3c5f8c","xz-5.2.3/tests/files/good-1-3delta-lzma2.xz":"00058b3c84d5e2718c298dd8689730ae79c46995943d242897537e9da3d1b04f","xz-5.2.3/tests/files/good-1-block_header-1.xz":"b94444ef9b5918e4b6c9bcd83080884b61c0c5072588f66c03f244faec475f12","xz-5.2.3/tests/files/good-1-block_header-2.xz":"96d4c234920acdd9b61ca904b2c38a402706131a5136ec04d98592f755e52664","xz-5.2.3/tests/files/good-1-block_header-3.xz":"2bb7072476150fdf06cbe83465f443f7928ee011538296f5713e22856b808fb8","xz-5.2.3/tests/files/good-1-check-crc32.xz":"eaa0f7d82fb273920c5247fa4928e695830ce40631945c6dda3cdf3f14d65cec","xz-5.2.3/tests/files/good-1-check-crc64.xz":"a0b759464fa8d02f0a3da4d19cebdd1d7d86b19728b599f7f946f58e687a22c1","xz-5.2.3/tests/files/good-1-check-none.xz":"cf3bece11d937fceb9c7599bfeffb067d140441d806823ace927a24e4410c16d","xz-5.2.3/tests/files/good-1-check-sha256.xz":"dda8bb24f50e39e750a5ad3697960083450a21ae054b2dff30699d542894826c","xz-5.2.3/tests/files/good-1-delta-lzma2.tiff.xz":"c9005e580f3e74b2cb8d817120f68cc2177840cda75f48d679551a7f3e323413","xz-5.2.3/tests/files/good-1-lzma2-1.xz":"d0e6089fe87776cb754b08012cc05b922e2d04f8a5484baf2d946cceebc24546","xz-5.2.3/tests/files/good-1-lzma2-2.xz":"8d8d4708327aa13930373d80ce3b996ccf0f1ff67d3cdd3d494aa6360fa53537","xz-5.2.3/tests/files/good-1-lzma2-3.xz":"2c286d6b18f24301f25a1c501a2c74c2036c94e0ab85d2289991f7fca2acb3ad","xz-5.2.3/tests/files/good-1-lzma2-4.xz":"ee91a262eaac56d93ffe9b3d582bcfdc1d92a8edb3a5555d52adc4c21f5347f1","xz-5.2.3/tests/files/good-1-lzma2-5.xz":"a59afee16f97700f89a3cc81740058a0e64fc9e06d176450b44aff3d70716c4f","xz-5.2.3/tests/files/good-1-sparc-lzma2.xz":"8ec92e5fcfe27c5bc320880bcca89bfa8a4aa789a5527a087f5a49492c31af5b","xz-5.2.3/tests/files/good-1-x86-lzma2.xz":"43ca5c4310f28554fcb2912db1098a779c1e91251802d4adbf23bb5634333389","xz-5.2.3/tests/files/good-2-lzma2.xz":"c096d08c0effa829b9c1cb92242b80e26be3a206f7a503d73b552da205b64d6d","xz-5.2.3/tests/files/unsupported-block_header.xz":"acf4e10b6f8e885ca80cf27c36187cafd974af46b42f70a761d969f5c0edbcaf","xz-5.2.3/tests/files/unsupported-check.xz":"c781077a53fcb200131fc6aaa3eaed6140f71f8cea5bcf9aae6898c5df4371bd","xz-5.2.3/tests/files/unsupported-filter_flags-1.xz":"adb9d23d6645ffa0a4dfd377cb8fb6a01a2622edc1c8bf1ed1ddc91b45b6d5f1","xz-5.2.3/tests/files/unsupported-filter_flags-2.xz":"e7cd859ba5efd8e238fd4bb44724ee3ee27fa2c993cc8794330e97867d137eff","xz-5.2.3/tests/files/unsupported-filter_flags-3.xz":"03b202ddc097d5918b808c2de99b37fbf1d138274998911bff2d514d1a04f109","xz-5.2.3/tests/test_bcj_exact_size.c":"c1f3674f454b860ae633c72739a5104f945b971aa92c63c18df9e94414b39e60","xz-5.2.3/tests/test_block_header.c":"78e08591a1fcf3a653ad6a806889c715b1d60e2141ad17b793c184251239399e","xz-5.2.3/tests/test_check.c":"c10d97f8bd21ea418b1ef0bec72e169a842f4d0342eb3f536e645b314eb9bdce","xz-5.2.3/tests/test_compress.sh":"b57f43cfcfdc920ce7210fa49a41d49f633b43f4efaffe0c0d01dd7d1d1489ee","xz-5.2.3/tests/test_files.sh":"b6778cb21bc6f4ca5c96e498ab376d1f00d79969c8df8be70498eff4232eeb6c","xz-5.2.3/tests/test_filter_flags.c":"a254c53ea6744b0238530af02bd45a917bffa8f952d02f01c3f5535667556462","xz-5.2.3/tests/test_index.c":"4289a811c1feb96c0294a4fc541022a87926f4b6c90a0d89f5bb8101427660be","xz-5.2.3/tests/test_scripts.sh":"c0b184719746b4569b91232e59d37f39e8641806d261ba31ffa6b041c9ed4055","xz-5.2.3/tests/test_stream_flags.c":"951cdcc3832f89900e839b79e6990b179630e19bd9847b13d2e75538cb66e482","xz-5.2.3/tests/tests.h":"103dd2b5c336c41d170db088002a9f99d326ae20206b0a7455a7171636bc8c59","xz-5.2.3/tests/xzgrep_expected_output":"260f99403d67f8c7a6dfeb736072c781d3f1cd6a410190e91abeb13864d3dba0","xz-5.2.3/windows/INSTALL-MSVC.txt":"c2136963b02c118dbfb4eb3ccc7953e996cbfb9b1a049ca975f980aabd0b2bf4","xz-5.2.3/windows/INSTALL-MinGW.txt":"8df1b40b122f8a041d1c5883883a381eb13ee870a6a856be4a6817139ea7dded","xz-5.2.3/windows/README-Windows.txt":"bb0f480c1be63ea699c785590bd840cd6fcbe750ed584cf260430d72183b72fe","xz-5.2.3/windows/build.bash":"bb08c5fc109952609bef97e3ddb1e8d05ef8d9371f0d84c6aeaf0426b8152cdf","xz-5.2.3/windows/config.h":"0b7421307adb8ef20f1c02224f1524b091df625b12fce2bf011335b8e8e06430","xz-5.2.3/windows/liblzma.vcxproj":"dcb0fd2b6e17c1ab4b97f183623e6efd33546ad066e022cbeb6e7684038fc42b","xz-5.2.3/windows/liblzma_dll.vcxproj":"1ddf32f8df200eeb7f180f9454ef836fc0a019484ecde5bbd478465f3003986a","xz-5.2.3/windows/xz_win.sln":"c33105e2b70986217893c5a7c250907580a78da057527101dc55588b1a0afb28"},"package":"fedff6a5cbb24494ec6ee4784e9ac5c187161fede04c7767d49bf87544013afa"} \ No newline at end of file +{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"5a7624f6789228bcea0ebb290ca957028bc266a985c2ba50b6912b361775f0c5","build.rs":"8e3b311b5fbb074c38c2aa338bd2de498a553a075d529e8f6d5855030eeeaf1e","src/lib.rs":"599f2b0cea899a4b28be5ae2c02093babbd6fd6bfa5d49428b97da110ada7b7a","xz-5.2.3/ABOUT-NLS":"e97b73baef31710d510598584f5c0f5018cb0847770defa1347966909b7c1f5d","xz-5.2.3/AUTHORS":"72d7a7ee8a4eaca5d0b53f20609eff95d5e6f9e155ecce98127414b8215b0b15","xz-5.2.3/COPYING":"c4f8e14fafe458d84808a4cd8b69f94673ebe2bf8fc992291629a69ac12218f8","xz-5.2.3/COPYING.GPLv2":"8177f97513213526df2cf6184d8ff986c675afb514d4e68a404010521b880643","xz-5.2.3/COPYING.GPLv3":"8ceb4b9ee5adedde47b31e975c1d90c73ad27b6b165a1dcd80c7c545eb65b903","xz-5.2.3/COPYING.LGPLv2.1":"dc626520dcd53a22f727af3ee42c770e56c97a64fe3adb063799d8ab032fe551","xz-5.2.3/ChangeLog":"e2cb2743a1e4297114f7a96cf6b9fe3168735be0cbb45111ac171aa81ce65204","xz-5.2.3/Doxyfile.in":"31160d92de7aa43a525a8978a95be0a30c0dd8fbc9d2115b2a5baf75e9f7aeda","xz-5.2.3/INSTALL":"2efb9b0f3e5002d4dd08b5686a45b28fb9f33759b378a5cac239ea1d35aa8636","xz-5.2.3/INSTALL.generic":"fd9db1c52e12eebd099a1fce89a5603048f4250329ba445bfb2fe8cdca04d3a6","xz-5.2.3/Makefile.am":"fca284f001e4eebdf1aee98e88b719a42ca7fddf2af874b971efd1b2629ce8ae","xz-5.2.3/Makefile.in":"20d3639e564b5cbaa6c0109ef49db75e9a927ed28cf4a2232843f0f99155a24e","xz-5.2.3/NEWS":"64598d59470537de94b5a2a145ce8e819ce70e0d0315aad624b094e130bc2040","xz-5.2.3/PACKAGERS":"8ab0db1c1bf19383b6fd4e7f3fc1a627f7e4d44119fb019469644131df99c0e2","xz-5.2.3/README":"a6058088674fa61559c97ebd82dcbcba9ae64441767f0ae07b89fd7a3232ee09","xz-5.2.3/THANKS":"396f2938a389fc7b554de6c46990ad673fd7bdd2ac0bcdac144b6dbcb59a59b8","xz-5.2.3/TODO":"2ce425810436c5299aa5e4a8b0186c0de15a496697b518481f606abb421e80a9","xz-5.2.3/aclocal.m4":"233acad8d0d2add0f938800317ce360acb63c9e9de3539aca65e927eb0513935","xz-5.2.3/autogen.sh":"46e696c66b31605de388dc55fef5419105622bda81276ae77db0e6523ec4f225","xz-5.2.3/build-aux/compile":"41856428226c049fa0ea4ca7a574c28416de2769b55ed7feea4ab5e60283af16","xz-5.2.3/build-aux/config.guess":"b7eab9b8a73dc6e0421366bca6921cd2621dab6c3909d6e3bebf863011442d15","xz-5.2.3/build-aux/config.rpath":"c8b4c017079da9dfb3086a0583e60ffe736184d89005dc5973f0bb0fd17c04bb","xz-5.2.3/build-aux/config.sub":"82745ce935695e7984a053c155a64b9ad16ece3a07d931cc90ab3fb28b7221af","xz-5.2.3/build-aux/depcomp":"786149ab4493e86b837077ebaecab65ef6230ae8a619b17fa5c1695564a427e9","xz-5.2.3/build-aux/install-sh":"d7c113e5484fce8b48f9a34a7a91e385ec279247d415b0b7d749bd56ad8ee8a2","xz-5.2.3/build-aux/ltmain.sh":"34ffaa53e9becccce1cee4f149a3b1cbba3c4cda06ab7dfaf1ae905ea4b2c0e3","xz-5.2.3/build-aux/manconv.sh":"3441e64f658e9edb0afa8a0446c2f643ba661187c0576527a5a62124619c0b8c","xz-5.2.3/build-aux/missing":"b1a337b731bbb58846d31ca2f5143c293a455fa41b481e236e89a9016d96b034","xz-5.2.3/build-aux/version.sh":"39bba40cf83ee58a901c351244ce717b0ef6f9d76e1896f2867065814d49246a","xz-5.2.3/config.h.in":"8c94c4f88de4a3722d993d31abe667d1b4aef5dd01adbe20208d79cbbfbe84be","xz-5.2.3/configure":"dccab7a59ce8ce9c6cf3f3e27d598a89f0f3d2c79b9a96b227220fd4bf3e5ab5","xz-5.2.3/configure.ac":"4b538a19f3b1f5e88e5ecae33e58fdfbb8a6842bfad37287904eb615b36a18e7","xz-5.2.3/debug/Makefile.am":"2505f6da25ac274d02330fbafd3901aeb955fae4f74a908e700073e0d409d630","xz-5.2.3/debug/Makefile.in":"ce98eadfc05ec111b810d46451c6c8f5c493236c74d510178d2c2375763e6ac8","xz-5.2.3/debug/README":"8d5b8e3b842551bc0cb2ce02537325ce75c0816697bb2b7dfdc9962bdb669451","xz-5.2.3/debug/crc32.c":"35cfdb89ef7b99b81b44655ad4eff661354af3215ed9fcef3187001f5eef672f","xz-5.2.3/debug/full_flush.c":"1b82ef164c550bf514d58221f0f6aed7fb9a73062f32c5dace74ddf67f23b932","xz-5.2.3/debug/hex2bin.c":"e06c050a93c5260bafb58b744fa3a4bd20e8d9050256b53d35620a3129f38c89","xz-5.2.3/debug/known_sizes.c":"8ea1b581c3319966fdb725421d4672497c4381336ab130adcf567a59b23af417","xz-5.2.3/debug/memusage.c":"c1b7b773267998b46cbc07e2d70c977590e2027bbc1994fa5d2804fd9a5221ec","xz-5.2.3/debug/repeat.c":"384cfa0c8ec7af687cb8d63aaf4cb2f275273a7ce3607c0bcba10592218cf434","xz-5.2.3/debug/sync_flush.c":"7a2c4b73220e5730a6b353f699a495ece1514917186f5755e2e65ba69769bf5a","xz-5.2.3/debug/translation.bash":"98949da3fe3eb46173321dba78a4643a504e8ab922358eccfb70c9a4470dcd6f","xz-5.2.3/doc/examples/00_README.txt":"f0ddaa731c89d6028f55281229e56b89f32b8c477aba4f52367488f0f42651be","xz-5.2.3/doc/examples/01_compress_easy.c":"183bea5347ddd735ea9ebdb39fe21d0c91b191c8b16157480e1ca0623c72372d","xz-5.2.3/doc/examples/02_decompress.c":"f2181b5c5acaa1d4438bb94f8e0338efc6678ddaf222928f731c07a682ce6bfa","xz-5.2.3/doc/examples/03_compress_custom.c":"914afd1e3494d9942ef752123f9743fa9427d5a82ca3e593794b9a4d9e390f42","xz-5.2.3/doc/examples/04_compress_easy_mt.c":"80a5d7e1acd455ffb55bd1ca26f767789171293a231e6645ca991b83b954988c","xz-5.2.3/doc/examples/Makefile":"067ac8dbf5a9cab8c2a12b3fadda34c93656308f150a8a195bfcdb071ca043a7","xz-5.2.3/doc/examples_old/xz_pipe_comp.c":"fce7eefb9149c5f5a43869e07a4a576c1f2af4ca0aae6872bd7ca50ed8c85522","xz-5.2.3/doc/examples_old/xz_pipe_decomp.c":"5d157c3c397fffc3b0489e49ef1d396fcfe6153f134ec5ea44ef0acc7fe474aa","xz-5.2.3/doc/faq.txt":"37636bca2e8c28bccdb440feb4dd306a717991049506a3cf463944f09235a3ce","xz-5.2.3/doc/history.txt":"9d6a0a72822734a0afb1816e07f0a7edab03339119bed4f393c1c7eec884eab6","xz-5.2.3/doc/lzma-file-format.txt":"0e961a7244cca641aa33619e9c9f0d795f9cc95657245f5d157e5bad05d3df66","xz-5.2.3/doc/man/txt/lzmainfo.txt":"3582617c79cacc571b4a87744243ad330b2f4c353ec4b6897d8052e2798c5ea8","xz-5.2.3/doc/man/txt/xz.txt":"4fd6872c77efde39d6a445df65a14346fe2e6e2c0ca3ccc47992cb6a98a5317c","xz-5.2.3/doc/man/txt/xzdec.txt":"805d933db332ff3603b83aafb432830a66632cc5cdbbe11ea62ee44f132583d8","xz-5.2.3/doc/man/txt/xzdiff.txt":"99cd14e76276f4790d4763a539965058003ff50275476b43bdaf10e43afad0a1","xz-5.2.3/doc/man/txt/xzgrep.txt":"67ec945751a59ada72524df5589817df2885c66a1f89bc85265ce041f9e35a4f","xz-5.2.3/doc/man/txt/xzless.txt":"1a2ac240c60f2873d7d7c9af95850eaf46dcc736684106a1164d8854977c85c6","xz-5.2.3/doc/man/txt/xzmore.txt":"d28e996e884205e68c99e2f35b6bef518bc5b4f54cc26bfeb402e79f76934e4f","xz-5.2.3/doc/xz-file-format.txt":"fada567e0ebd8b910d2c3210d13e74f3fcc8475d64e29e35db0fc05e3c6820f5","xz-5.2.3/dos/INSTALL.txt":"8a29c9ffc4cd0cf26b8913af62033980d4edca85b8c3c532c238ab1c7ece4a45","xz-5.2.3/dos/Makefile":"ffb97657224a5dec72179919f8341ef3d3b6ce8433ac8d47fa9608c5c35331c1","xz-5.2.3/dos/README.txt":"afa9abc814a28d75917b17a95fe049d331f6db4b4df78a95bd03eaf080571251","xz-5.2.3/dos/config.h":"27897319d3528c9a714882218617f7b54ac647e6f59a7e5f115433c9665f9348","xz-5.2.3/extra/7z2lzma/7z2lzma.bash":"568c344d12f6465e307caa3828203cc3c63666577c4f2f82b708f24af72734c1","xz-5.2.3/extra/scanlzma/scanlzma.c":"48203b9ecae7b2d56f1d6382b1cc6305d4eb74466ae713aa24280245cede1e2b","xz-5.2.3/lib/Makefile.am":"6a620762de0091fa6a335d0a0faafdaaa5998bb26f46889c21c8e42659ed5354","xz-5.2.3/lib/Makefile.in":"184be9ea3460b0bbc445e0f2f7b1a93dd1e522503ca4e84363216489838593c3","xz-5.2.3/lib/getopt.c":"bf9113fd84a7414cbc807e1578c18d5ef8a12ea46ac64239623caab659c21f34","xz-5.2.3/lib/getopt.in.h":"bebcc6657cbd7dec9d6a70ec31c697d334d4d9b9ef8010c16823c075b3425189","xz-5.2.3/lib/getopt1.c":"2d49657d2b4dbc38aa2f31f3e2fd7c5a4594c2caba09132f4842312ee64e5726","xz-5.2.3/lib/getopt_int.h":"2dc491c9544667a9916a23bd2c872325ced525cc58b9d9ada4742f7e9588bed7","xz-5.2.3/m4/ax_check_capsicum.m4":"764ba27e847d425386ff872a4bd68a19eb7f494dc4db139803fe4b6ae33b6d06","xz-5.2.3/m4/ax_pthread.m4":"894dc48a681069315e8bc61f0d236dc5061c9b43bde42cc9f857ed8c1dd71164","xz-5.2.3/m4/getopt.m4":"07b0c232c8cb06c1a6c168ac605e992c31717a20c64b2eef4ec361070e6eed05","xz-5.2.3/m4/gettext.m4":"6c279c958f980621dfeb725cb79173dbe93534aef2a4377a6fafa666c3c0b677","xz-5.2.3/m4/iconv.m4":"5b6ecb913051efa159e785930a59c79498a820694704883af324abef3796d360","xz-5.2.3/m4/intlmacosx.m4":"d0e24c3c982ca2c8c00aaf7d0a27502c83a299660b00829b02159dd8b1917f95","xz-5.2.3/m4/lib-ld.m4":"b9625b301655214df17e9b7e9fac9292707dc10b9df572cdee4a90d7a83af8b3","xz-5.2.3/m4/lib-link.m4":"998a5c2d2ca268a2dc7a22f2b6c8791ab26318ba66c77cf0df1dd2122d071976","xz-5.2.3/m4/lib-prefix.m4":"b23f4661e2c6081496bc34586caaee8afdc0935ac77aa9b8d8497d14028315d9","xz-5.2.3/m4/libtool.m4":"94ebc155f41e96e5cb8762a2661e0d39426274e1b2b930bfb6d99c680a041c58","xz-5.2.3/m4/ltoptions.m4":"e77ebba8361b36f14b4d0927173a034b98c5d05049697a9ded84d85eb99a7990","xz-5.2.3/m4/ltsugar.m4":"5a6735cda60e0ba0d1b706c0ef648f5d096298da46daefd9cdecdb6a0f4584d3","xz-5.2.3/m4/ltversion.m4":"a27b754709de61575197bf5a980696c98ae49da3f92f0de8ee7f42dd543b7465","xz-5.2.3/m4/lt~obsolete.m4":"26fa3285c35dd6ab00ed1e466ba92a17e4655e01897731ec18a587a4cf5e4f8d","xz-5.2.3/m4/nls.m4":"6d231fb983fcb7c8f833b7c32eeea00a578b46837ab774fd417603a857c67a38","xz-5.2.3/m4/po.m4":"a511e6e80ced17c4c5b6ff7c9dac277275d3ec1544f19d5bb951671b45756031","xz-5.2.3/m4/posix-shell.m4":"edc32356d26f677c308a8f5877058260a88a258f2a1d8e3ff36dcbe95e25775d","xz-5.2.3/m4/progtest.m4":"2b63243f5e160602a1411eed30a4abd66ce29a5d4c8664711465059362ef7353","xz-5.2.3/m4/tuklib_common.m4":"7f72e262bec40c2243ba26e3a72764dda20be0f8c3a4dc4e9bd7a68b494b6aa5","xz-5.2.3/m4/tuklib_cpucores.m4":"26c32f6b37bf0e8e0913c483b4ec1c32b17d780279dcc5dbd5eff76f85018178","xz-5.2.3/m4/tuklib_integer.m4":"f1a326f55f067aa5cd2c64acd50e80ef8a5fca426ca531c6d9a4d9bb11b23f04","xz-5.2.3/m4/tuklib_mbstr.m4":"c5d8e37d8e1384073944765bca4291cb787c427f53e87022fd5274704c084a4c","xz-5.2.3/m4/tuklib_physmem.m4":"f8ae3f46ec22f5c9d13a1c7eb267225ba7f5c453eb8163ee2745b8b48a133443","xz-5.2.3/m4/tuklib_progname.m4":"e3dd84887a1bd2f944656355f3b0e933fb01807ae0f4040fa3eb661fe635a281","xz-5.2.3/m4/visibility.m4":"56c24c3697d4e0b8206c551a3425a99fd2648d2739acf39c2acc7869e79daee5","xz-5.2.3/macosx/build.sh":"4792ea057807ff46309db27bfe29d5edfcc61269f3b0a0172043a904f08d63c8","xz-5.2.3/po/LINGUAS":"b6ecc012505449bd71f13c32ae8a1d350f01ad81c6ef91cc993f38dbbf98d6c7","xz-5.2.3/po/Makefile.in.in":"fda41c837ebf2de985752fb56650a4eb9c4da7b49144f44d06503204bdbc7841","xz-5.2.3/po/Makevars":"656fa2fed4882e2656ae4398d1f4ed1cf818822f4f8f31cf1b9247850f20817c","xz-5.2.3/po/POTFILES.in":"6730d37ff01e4fe53f12c899963209b2d6658d2bed4d9cd551de6b2922a77366","xz-5.2.3/po/Rules-quot":"8604411891fa5b5456904b41d22f0efe5158c457c75c5ab2fd58b1b9e7c97185","xz-5.2.3/po/boldquot.sed":"33234736a58f1610c73e1c8c08faf1b2ef1397d878dd7d2cbd888ca0f2da4ffc","xz-5.2.3/po/cs.gmo":"7dbe95f7ef4750d6af43e6a4847bfecbf8dae704f23b9e5e04113d67824297af","xz-5.2.3/po/cs.po":"ef25a51220691216215c4664b72b1b7bd207e55a5fef30f09ce3d399e7fd6dd6","xz-5.2.3/po/de.gmo":"b6c0a678137ee109adb4d50ad1ff89b8e822851c4d00728c0923e6b69aa7dd83","xz-5.2.3/po/de.po":"bccef85a99191454f4538e9095b8978868c29e6099f8e65961f3c8c0dcbec014","xz-5.2.3/po/en@boldquot.header":"3b0b89aa6625c051e69cce1e341f973f62ca94aff62cbb36b4a452ce67eb261c","xz-5.2.3/po/en@quot.header":"90e35325bf9b6b9562bd0882128ea4650b65c9389b35edf9ff534dc3a48e8bed","xz-5.2.3/po/fr.gmo":"c2cdc620605c7f701d8f26047a12e81ea1ad4ce8732368c185af8b169f1f317d","xz-5.2.3/po/fr.po":"4cb8414564bbd5b507e2d9c80ac797ff2bd792fb2e084ce8cc25f97f4f31c35c","xz-5.2.3/po/insert-header.sin":"73e650aeccc3ef0a7c2e1bbab934b0882b61f19569e96e4615d069dc50b6becd","xz-5.2.3/po/it.gmo":"d544c91a781767172e52728bbbe19312d5c86752dfd2311c76c7acb1737d5d1b","xz-5.2.3/po/it.po":"9ecfea52b080b969e7bd7cd4effbec243b97f1d1f31f3c04531fdb97b1cb2cc2","xz-5.2.3/po/pl.gmo":"73a73536bed63173995b36ab496f2ad48b189677d77062cf8644d114dd7c4dc3","xz-5.2.3/po/pl.po":"ff96c3afd0b1def3e01e0480379b4dd83c5782c699097c201f0915b45d8f3a80","xz-5.2.3/po/quot.sed":"d19ab2cc69000c1206f1b8460952857f05d154158da8b89273ac2900a5c80ec0","xz-5.2.3/po/remove-potcdate.sin":"9a36cf3e93b6374521c81fa4f302350d3c04b95573f5570717284107689188e6","xz-5.2.3/po/stamp-po":"2cd8ec3de6a07e1fd39676100db57ba62372e820c19812fee55899f65746e192","xz-5.2.3/po/vi.gmo":"9826f269d7bb218978d3d898b0d958f3c6a45e0a7e6e31f7fc0dca315227a5cf","xz-5.2.3/po/vi.po":"fc0e4051e5b5689ee753d688cc8f774c6bc49f040df99079d44e965979720e46","xz-5.2.3/po/xz.pot":"40787ca0234ab808a5e7323f901f623aa980ce589907553c17c7e430f313d918","xz-5.2.3/src/Makefile.am":"2ac2419e71b07af9c7f281e04139092154c23f33b234609e6f38631861e57b7c","xz-5.2.3/src/Makefile.in":"6568340e13bda8435f7cf29925d85269887e8279ea585e902f98e0f11c521cab","xz-5.2.3/src/common/common_w32res.rc":"a930b1c7dc6499541aa104f9d10d36892467ee1f7c9c73da6ecfc4a98cb4aa1b","xz-5.2.3/src/common/mythread.h":"8d0c6391f2b758c3a6f87f16b5f875a0bfeea52131250574b7d57c1903d96b61","xz-5.2.3/src/common/sysdefs.h":"eee95743275635246e07fb66e6100765cae3bd5cedaead921ad6cac2e316377f","xz-5.2.3/src/common/tuklib_common.h":"1f07791b997b9feb81d4b1b56b537114e84030fef7db3cd904215c60fd0cc285","xz-5.2.3/src/common/tuklib_config.h":"9a60f2a72efab8a1b3dc44d428b8058c3e5cce9f100a6c1a08c7621dec268273","xz-5.2.3/src/common/tuklib_cpucores.c":"3ae85bdd2036a5b68ef010388df231ac70f6a15d935cb211af29301800fcf266","xz-5.2.3/src/common/tuklib_cpucores.h":"e2e7a1ad1304be23b2c068608d5c353e0e20b3f5b1d15ef4c080b0bdaa02d136","xz-5.2.3/src/common/tuklib_exit.c":"5257ba4143203933508e29ca37feb8d13dbb31d58812898be7039e35b4beae95","xz-5.2.3/src/common/tuklib_exit.h":"f8a93da1333db3b5f44ffc837a8c2f487880c02974bf9eb5c645407e8ecc0e23","xz-5.2.3/src/common/tuklib_gettext.h":"b2538271af8a1f51bef13b68e793ee69f2d6983892d860b92a535b4aa90b1612","xz-5.2.3/src/common/tuklib_integer.h":"878367b9762dc466c75864e15b7eff9070781383aadf1e34f8a3e7d5541d102f","xz-5.2.3/src/common/tuklib_mbstr.h":"e209e406810cae18efde147f24e8b66d3645243e90f2ac0aa5f9ef2b0b453f6b","xz-5.2.3/src/common/tuklib_mbstr_fw.c":"6e0d0870b845d6e8d61dd1718cd571db3db0495c7e2fb293b51d0f1bfd8fd341","xz-5.2.3/src/common/tuklib_mbstr_width.c":"497103f332d1eb4b420ff11e71649923c224e3167698ff7e4f9845839e4cc7ea","xz-5.2.3/src/common/tuklib_open_stdxxx.c":"674baaa486dec81a7394c51e5bb0a723f505f9df9626d2587c2c8bc15072e697","xz-5.2.3/src/common/tuklib_open_stdxxx.h":"eda1984d58364eec9949aa49fd110d62b1d3685f7addc6fe4c3f1284bc8dd614","xz-5.2.3/src/common/tuklib_physmem.c":"2da27bdaf9703705d749dc4a2b79f58b49ceccb1b7e34f388a1afb69cd722d4a","xz-5.2.3/src/common/tuklib_physmem.h":"dda058f02fcbf14d326acdbddd704c9b1823b3bbd3028fef120b70c5a20a1c02","xz-5.2.3/src/common/tuklib_progname.c":"3956e35bc0002e479aef535d4c565286c244ce17bd925ad693d6794412df37f9","xz-5.2.3/src/common/tuklib_progname.h":"9343b38f50a61f695b44ca41d4ad7d363e571eeb72b57729e5e779c3fb943abf","xz-5.2.3/src/liblzma/Makefile.am":"86ad0878521666a2ada15a86d7d48bbbdfcb087391cf5e98984667d7ac0c472a","xz-5.2.3/src/liblzma/Makefile.in":"57038a0970171d30ddfc8642372ba76c4df92e901783f85f608a66f6e987d3b2","xz-5.2.3/src/liblzma/api/Makefile.am":"400d830936568f09d5b670fa57a91aebe7c4d59a217dbce0a1f1ef248bafece1","xz-5.2.3/src/liblzma/api/Makefile.in":"97104f1b333752acdd457f0caa9f8954144c6b23843f40ff16bf0fbf8f79dd62","xz-5.2.3/src/liblzma/api/lzma.h":"42b6e2029bb2457a0c1a70913d07dedb08daaee613fbae5d0c9675b257afb91a","xz-5.2.3/src/liblzma/api/lzma/base.h":"387707f60d1d54f4b8ff51d1be1a10244c360b89a7dfade58f4dea23d3555949","xz-5.2.3/src/liblzma/api/lzma/bcj.h":"485ee1ac185747b6e5324094aa462af194ba3a22a0206314e25f70423045e43d","xz-5.2.3/src/liblzma/api/lzma/block.h":"fbaa28d605010a58b00b6b6ff4a5c41a89ee9eb2adcf5d54fc5b011a397414e7","xz-5.2.3/src/liblzma/api/lzma/check.h":"79ef75b06fe389ccbc47ebeea1bb704157a58fe9710ddfbac8a62035359f9ae1","xz-5.2.3/src/liblzma/api/lzma/container.h":"41f2fde869a55c5da0c8d48348aa90cf114a4f7676f92e3386dd000949ac9aba","xz-5.2.3/src/liblzma/api/lzma/delta.h":"db9db049ab07363921bf19320174afbab16a1b4d401f797a5b2232dcb89b9d64","xz-5.2.3/src/liblzma/api/lzma/filter.h":"99142d7f19743625dc952c1b453229d4fdddd7c5d612bd596f947d7487485f65","xz-5.2.3/src/liblzma/api/lzma/hardware.h":"b5b2574c9cb7fb98450d7bd3baf656c38aad6b6fda9ccd5796d1e0fcf41892ac","xz-5.2.3/src/liblzma/api/lzma/index.h":"d8feec69646325a13d9475d292727a110dfe3e72b31412f70617642dd6a553d2","xz-5.2.3/src/liblzma/api/lzma/index_hash.h":"0840c2ae8dedc05a7ffe1597ead131532a8dc03521728d1d38e55da0fa769831","xz-5.2.3/src/liblzma/api/lzma/lzma12.h":"9722b770c5bd05f701fd77b195cdb27c02d0eeffc13b10b28e6312093555c699","xz-5.2.3/src/liblzma/api/lzma/stream_flags.h":"beba70fa9d83dc6a7fcfae9b1f8d07b3b5acbbdc789f008e63da4206e2434acc","xz-5.2.3/src/liblzma/api/lzma/version.h":"ecde4959e6bf10e7907b0b1361cc6d30b950260fd69a24e2d1c1f9ae11e2dd47","xz-5.2.3/src/liblzma/api/lzma/vli.h":"408347fd3b2b2c2b1e50f81963bf393a8b817dd1c066e1ba7e99705ea3d543f3","xz-5.2.3/src/liblzma/check/Makefile.inc":"200fa89c39ac280abea3fb0026e10880de9eaf526e50a5a9531e079d8b050afb","xz-5.2.3/src/liblzma/check/check.c":"bea09bd4b782dcf36b674fb5e2583e4fb11023ff3fec4d2824e5a912e5c96ce6","xz-5.2.3/src/liblzma/check/check.h":"27ccc14df0db6970deb58b9fc261c417e4e24b422f07db353d549b2ac88a69b1","xz-5.2.3/src/liblzma/check/crc32_fast.c":"558b5c05ec91cc37e197b4eacbf0fc58559ec26428db37dbc8f4b6f9c7031b0c","xz-5.2.3/src/liblzma/check/crc32_small.c":"52a70d7be7e0f29bb065117e31d86d8d6db387ff3fb13c43d3e790e511cff2a6","xz-5.2.3/src/liblzma/check/crc32_table.c":"58c9cabd23f44deb929d52ee62195a556bc2a3de3d8328a2b9e513e07282d6eb","xz-5.2.3/src/liblzma/check/crc32_table_be.h":"d6f2bbb39f07fbc0c166bcec1a11f4680c1d20553f5a12a29bc991bbd3d4213e","xz-5.2.3/src/liblzma/check/crc32_table_le.h":"95fdd8507304a2c07cca6beee871d752a91dfb5a0c6ec290648e582bf562017d","xz-5.2.3/src/liblzma/check/crc32_tablegen.c":"baeaadb54ee5faf389210c8de880adc44830b8ce12cf32537c59a8a5b498476b","xz-5.2.3/src/liblzma/check/crc32_x86.S":"6caa295858c8327bc0eb35eec0de725a934065f0b463bac0f254edb381b47f78","xz-5.2.3/src/liblzma/check/crc64_fast.c":"c05b26e1196d02ebc333b8fa3012e71cb2aef4e890abfc2189be5fe59634f2f4","xz-5.2.3/src/liblzma/check/crc64_small.c":"3f6007032a8e75cbc57f1134ebadc929f4eff9cf34fed85e960eed79c06a91bb","xz-5.2.3/src/liblzma/check/crc64_table.c":"76492c3de7dfa3a8578fe5ad41b69500c2af235728432e8ee19a26dd6e40f480","xz-5.2.3/src/liblzma/check/crc64_table_be.h":"8927164685123fb0f931195973b95c096c32c063aa82815b98609fb3c34f951b","xz-5.2.3/src/liblzma/check/crc64_table_le.h":"dfef9fef2c5b973ad585aa971729dff570f1bf390db12b022f565a411fdf9e04","xz-5.2.3/src/liblzma/check/crc64_tablegen.c":"af64bc13735080958a6f9dbab3a24b267dac0bc8f91c4c92149ce76287e08550","xz-5.2.3/src/liblzma/check/crc64_x86.S":"d10b289ab8b7cffa6193c903531fc08a91853d50b61ff601c7892e966ab252f6","xz-5.2.3/src/liblzma/check/crc_macros.h":"e89523a8599be0521986e678c9b7da701199eea43e6d81d448c87f07ed4db9cd","xz-5.2.3/src/liblzma/check/sha256.c":"c143c38c74222bd1f0ea0e5abd67dbd49c47b1828d59b82bf43786dc56393ec9","xz-5.2.3/src/liblzma/common/Makefile.inc":"89b90642d5ff3b0e9983b43789b94401f0fe85b6adccf7b17ecf39e71a34b81b","xz-5.2.3/src/liblzma/common/alone_decoder.c":"667c357ede5b35df0eac618aa1cd773a9ea7aa059575ece7344a65597a025df1","xz-5.2.3/src/liblzma/common/alone_decoder.h":"95b4f8e6567076af9651291f98dd145e213e388a8a4ff4ca3dcc5fd361a6f54e","xz-5.2.3/src/liblzma/common/alone_encoder.c":"ad037edc0e35cb9a1d7cae10ba737f933d797333ad8cb5f99c5dd06b0f0cc553","xz-5.2.3/src/liblzma/common/auto_decoder.c":"9777c34025c7422b1e68d32cadcf848f950412f1fa7062f5cf8a4a1af9a224ea","xz-5.2.3/src/liblzma/common/block_buffer_decoder.c":"13b954917929088d5205ebef3bf14d0823ef6233deda0ff26f8c0d8e7371f637","xz-5.2.3/src/liblzma/common/block_buffer_encoder.c":"4d4a0fe031353e53baab66056cbfb9d7c5bd323a0546e4a368252e14195d9b2e","xz-5.2.3/src/liblzma/common/block_buffer_encoder.h":"92954e63e2bab41d09acf2cd39ea988639a573724b08acf52192e28895cb9b8c","xz-5.2.3/src/liblzma/common/block_decoder.c":"e82ef1b890c9ab629f7d4387fda44b0261a9db875405f362c266cf502bb90ba3","xz-5.2.3/src/liblzma/common/block_decoder.h":"d067e66c89f066dbe698efae7415143347a44e2d3629bab61bb217b3e3ab49a2","xz-5.2.3/src/liblzma/common/block_encoder.c":"b05ca89a7923d9cc61aee04027e47700302cf81c3b9d983e4c6075efec959510","xz-5.2.3/src/liblzma/common/block_encoder.h":"2595cc5c2f67a57a574356cbec5d5d1b90ca6c6e9f431a4364067acd5d3e6632","xz-5.2.3/src/liblzma/common/block_header_decoder.c":"ad9164dec9c21c906ecd141e94fd72a536b4dfaf943a3887024a03657f285cba","xz-5.2.3/src/liblzma/common/block_header_encoder.c":"2546ccb656272a34d7e68fda5d233aeda816d82f5c90420756d5a7068b57e47b","xz-5.2.3/src/liblzma/common/block_util.c":"59d9cf65e20849202f2c2f7fa9f7569239f2c86687fa45cd309863a90f643eae","xz-5.2.3/src/liblzma/common/common.c":"fc1b0a0b3c20ad29ab22a42f95f80b537a0011c64ca970b872bc743253f9e3b8","xz-5.2.3/src/liblzma/common/common.h":"a3f7e30eddf1e2913399fb2ac90af32099d387cb691c363d12c09b68138611eb","xz-5.2.3/src/liblzma/common/easy_buffer_encoder.c":"3d66fc8b3788e815a2167460f312fe45725d1bba6a3c23e5977a1727eaa33964","xz-5.2.3/src/liblzma/common/easy_decoder_memusage.c":"f2daa4675f914f503f28df798ba5c2c5fbbc0a94b08cc305e9c6645569cb8c7d","xz-5.2.3/src/liblzma/common/easy_encoder.c":"331416f038afe091a920e629db9f3f3b594fae05705354e0ba1e8ae5fc4a6ca6","xz-5.2.3/src/liblzma/common/easy_encoder_memusage.c":"ac313566ecc7062a84014457be28bf046b29be2bf9a036c8b6fb49c57b3182d1","xz-5.2.3/src/liblzma/common/easy_preset.c":"65ea57b839e0ec864fb26f38ba66a8a0d2070dec63a821b1a1665273ed0b2738","xz-5.2.3/src/liblzma/common/easy_preset.h":"0e0bcf762c76499d86a6bfb7ae11ecf5be4d50efe8339096e69a605f2fac1b32","xz-5.2.3/src/liblzma/common/filter_buffer_decoder.c":"5fe3edd0cc5641463840775aba4ced9027da9e91ae50edd8eadf14a3bc1fb94e","xz-5.2.3/src/liblzma/common/filter_buffer_encoder.c":"eddc23cd0e0fcb0e4cd5b66c2878d580adf9bc1b6dfa1818e77c4488b9853203","xz-5.2.3/src/liblzma/common/filter_common.c":"39e17b0e805300649115a22123ac6cf40b21132726c9591b5deac5d6c1a3a2e4","xz-5.2.3/src/liblzma/common/filter_common.h":"f8808dfc406763d32b2cfc7f3a0685e1b7fe45ffde3436cd83a789f1bc493445","xz-5.2.3/src/liblzma/common/filter_decoder.c":"23e163711327e49d82f0e3677ea3579233a050acc1dd835b06c8da496e2c3709","xz-5.2.3/src/liblzma/common/filter_decoder.h":"2a45547e1fcc2b122a317bd19195ff99cf4f1cd3427f63aca4879682a1d25e3e","xz-5.2.3/src/liblzma/common/filter_encoder.c":"384b83831d1f1fa75fef39281dd7a1f5325a7c4c23f06d24f149e8b4dd75f3e0","xz-5.2.3/src/liblzma/common/filter_encoder.h":"2b6a90f9054d6b34dc0e42846bfaf7fa816a04ca531421b19fc6118ae2c83617","xz-5.2.3/src/liblzma/common/filter_flags_decoder.c":"fe9cd544195e038010a31ba5f5b3f9f5e1d412f1ee315d231f87948df6df2124","xz-5.2.3/src/liblzma/common/filter_flags_encoder.c":"75d3325b9ec18cd7cb7ec3464fe2b5b23e919cbfade9df48bc3303eaacb1c121","xz-5.2.3/src/liblzma/common/hardware_cputhreads.c":"f017cc4bec6f5e922e58c58d240b5432a0375874c221e09d95a3af0be30c224f","xz-5.2.3/src/liblzma/common/hardware_physmem.c":"9c24bf5d1c12ca6e459380d0ef3c357760f81037ca04f98a2af4425a746aa4e4","xz-5.2.3/src/liblzma/common/index.c":"7aca4e0de549feecb00bf4c4fde58ace144d90f7a11cb01be70155ae388188ef","xz-5.2.3/src/liblzma/common/index.h":"57f38ebcb497405b4efd510579678a891873143c65c7d6a6bbc8e3764e4c62d6","xz-5.2.3/src/liblzma/common/index_decoder.c":"288df67313244bb1bfc3319dd5d4e01572ec024c180a38ec4f11532604d646b8","xz-5.2.3/src/liblzma/common/index_encoder.c":"07bb53b6d65e0fa43b683def95623f2330000461f32552dfc55fdb7cf0bcf070","xz-5.2.3/src/liblzma/common/index_encoder.h":"d90e2aa654e0c78a3cc43f3bd2628fa2d208e76c0c9b1d1449e53830fda03bf7","xz-5.2.3/src/liblzma/common/index_hash.c":"154f56d958ed4d2a1ed335103b141ae0adedbbdffad11751a2d000fdf95a51d8","xz-5.2.3/src/liblzma/common/memcmplen.h":"99afe1d736a3b2a464c7dbb6d2eeccc45bcd46c7248a024cb3e7015f596c41d6","xz-5.2.3/src/liblzma/common/outqueue.c":"78b30911bd1b7cfde10f3c59e8827850539f5411cfbdeaf3f830c0a34863ed73","xz-5.2.3/src/liblzma/common/outqueue.h":"9355e10fbd2d9fbf9413ec2d0925729907599063a2a8980abd6cbc6288d38f4a","xz-5.2.3/src/liblzma/common/stream_buffer_decoder.c":"ac2e5511d2833f9a00c3199e2eab458d560800c34ebc6ec9cc78a2cf7da5df4a","xz-5.2.3/src/liblzma/common/stream_buffer_encoder.c":"1908b3c0078e9624cdfe72df4935c638a01064a4992d8c18ee96b1cf86edc75b","xz-5.2.3/src/liblzma/common/stream_decoder.c":"057905ea920ebaa3165c881a2c292ed6b6422f2340850e347aceb8f7dc58dbed","xz-5.2.3/src/liblzma/common/stream_decoder.h":"1d8b599273cfc339d14bc03fb6d729d03f1045c3237ad34d607e0eb9ff96dab9","xz-5.2.3/src/liblzma/common/stream_encoder.c":"724f757f11b55c7a5a8e53973340b7af02a8f7adf0753e80759b90c36b15ad14","xz-5.2.3/src/liblzma/common/stream_encoder_mt.c":"6fbad07969c2f759bc2e96313907ec88b31789abb7bab0baad7cd5a6cd2e5344","xz-5.2.3/src/liblzma/common/stream_flags_common.c":"c23cc834a730ca0141f6569ed8717c2285a0b6c4dc63930f4d8ae2cdcbd853db","xz-5.2.3/src/liblzma/common/stream_flags_common.h":"e0287a3d2bfb9abb974f4ee4ce67cf67b6adf1015bed7e9ccf92b7d8715aa878","xz-5.2.3/src/liblzma/common/stream_flags_decoder.c":"06abe4767eec770545f3983bb688772c41df6d66b6280fdc95343710be5cde3b","xz-5.2.3/src/liblzma/common/stream_flags_encoder.c":"be639e1905a5fa082dd88fa498a01bdd0a3d3df202665fc66396fa398ee15c26","xz-5.2.3/src/liblzma/common/vli_decoder.c":"2a1ac4d19c16d861e0221494c5fd05512db40c43859f427accaa3a6be520d754","xz-5.2.3/src/liblzma/common/vli_encoder.c":"a29a42274cb4e997b20e7ff4ad17d8f464cfc402ff7ea23a020279059e86e971","xz-5.2.3/src/liblzma/common/vli_size.c":"84970cb87f840b317f1218fba9068d30013f8dd2f42e4bfac163d894229e9259","xz-5.2.3/src/liblzma/delta/Makefile.inc":"1b0bdbef291dab04b95250d16814351ce5bf2cdf768e7d50ec86397fc9a0a8a0","xz-5.2.3/src/liblzma/delta/delta_common.c":"d1de035aa8485f85c8b288eec876b743357fd5fbed0c14267443307ae9e6337f","xz-5.2.3/src/liblzma/delta/delta_common.h":"ab0687c451cad4e5a831686f579ae51579cb5c35826db73688871ab1ebd3bb2a","xz-5.2.3/src/liblzma/delta/delta_decoder.c":"9f084a005848e0004fb919cbadec17c749db5e254895c0735c5146833ae34ee6","xz-5.2.3/src/liblzma/delta/delta_decoder.h":"a5cff12597923e2481e8fb2988b67fa4659a407199824eba2f0206bda47d7268","xz-5.2.3/src/liblzma/delta/delta_encoder.c":"eace1e85192db49ebe7ec89d633a99a65e416920f863e401e62697401335544d","xz-5.2.3/src/liblzma/delta/delta_encoder.h":"2bcd0e2fb30f4b5ce3e5acb6df5eeb1c95024fbff8b52e2586dd226243a3f228","xz-5.2.3/src/liblzma/delta/delta_private.h":"fd00f847e99b88a031182a3b5d52f4f8957aedadd10a96c1e7012edbe4a135d9","xz-5.2.3/src/liblzma/liblzma.map":"fbfee8d61ad96f89910e35e3915fb21d1c5ff584e2d9e1d2b6b62349bb9864d1","xz-5.2.3/src/liblzma/liblzma.pc.in":"2ea84ce8be346e75f8e8410dcaf871f95fae6fcb0aec5da854c2c6e09dfff05d","xz-5.2.3/src/liblzma/liblzma_w32res.rc":"62c5e352a64d5add147f5412ba3223ca9c24b766184fcfa6b885697a4110058e","xz-5.2.3/src/liblzma/lz/Makefile.inc":"d616835619909528c789e9204119154dc21626ba133db74b22906e6aaff797a8","xz-5.2.3/src/liblzma/lz/lz_decoder.c":"53911777644cc11fc544a5b324bbbb377b12a6230cb3ff6506d0193f60b08c91","xz-5.2.3/src/liblzma/lz/lz_decoder.h":"d2b8d43803f39c846fe0c685740e26366a8d4579f8d5687f0ed719cbf125d0c7","xz-5.2.3/src/liblzma/lz/lz_encoder.c":"7eff05d3d25136db679cb72b3c90fe2e3090cd6d791e6c24d6bb57782a71d3e0","xz-5.2.3/src/liblzma/lz/lz_encoder.h":"64ff40bdc990a3921b6d3678627d8bd26e4032e42a8a9559e370c369d633a53a","xz-5.2.3/src/liblzma/lz/lz_encoder_hash.h":"a31a243ca234f2f5e310132079ff3ea47b163ae5b07b211cbbb63614f97505ca","xz-5.2.3/src/liblzma/lz/lz_encoder_hash_table.h":"494d503e26cf1fd2cc08ebfc7bc9f96a2c56e8e9bfba6f86eef63e4add744f2f","xz-5.2.3/src/liblzma/lz/lz_encoder_mf.c":"7d9b636342b7f3a8d49d73265cd7a12290fb576d5e02b284eeb5ab07dc57fe2a","xz-5.2.3/src/liblzma/lzma/Makefile.inc":"8ab29479e093b48af89e8c4cf6acf0a1660423570b83f2dc55757ae55677863a","xz-5.2.3/src/liblzma/lzma/fastpos.h":"790a02cb3105c9332927604a976e78f2f39c3b046bfbf456e430faf32dacffea","xz-5.2.3/src/liblzma/lzma/fastpos_table.c":"d2fba7f634dd93ba6d1a12e26a8292e96a9c71090c94364e47b43e4d8ee642ab","xz-5.2.3/src/liblzma/lzma/fastpos_tablegen.c":"62fd65638f54438d110ca917e52fe35a5286674a7781ef6360a4a5b1e1a07c6e","xz-5.2.3/src/liblzma/lzma/lzma2_decoder.c":"5c22fa4550da1b492626b55c4dd6b43c4bf551ada1cca8e078b3b78ddf1c9d25","xz-5.2.3/src/liblzma/lzma/lzma2_decoder.h":"ce79b5baa8062e63078114778a920203ad9c35e351f281999682b60106f3ad2d","xz-5.2.3/src/liblzma/lzma/lzma2_encoder.c":"65c815a5f2ae106a04fadbd301d8bd1dedc52aef6815fac84a97933866640c4a","xz-5.2.3/src/liblzma/lzma/lzma2_encoder.h":"8558aedaed67c0b2282ee69f97aa9f95a8d19562475b0cbe93c9539cc2098b3f","xz-5.2.3/src/liblzma/lzma/lzma_common.h":"05905ac386202b25cda9f3961bb07ec80acff3855c7fc12ebe7cdf78e9aced67","xz-5.2.3/src/liblzma/lzma/lzma_decoder.c":"b4665d674cdf1d86e8afd9a798c57490a443ecefd936936bc5ad9f94cc3268e1","xz-5.2.3/src/liblzma/lzma/lzma_decoder.h":"6b455583a68834f3e31aa81d6620b27fd44885bde72decf4ef52a05c4c66e19f","xz-5.2.3/src/liblzma/lzma/lzma_encoder.c":"0e68917175ad12f297093d15ed9ab247fafa63dc6844e4a1a12b4677e42ca478","xz-5.2.3/src/liblzma/lzma/lzma_encoder.h":"2ca6d3683107f4575c227e1d2a525db81c691a5b7ebc1140bc381484ca4e58d2","xz-5.2.3/src/liblzma/lzma/lzma_encoder_optimum_fast.c":"985b0b9ba50af0605cfe4028e177315dc156a64653dc0318344552ddcb9e3087","xz-5.2.3/src/liblzma/lzma/lzma_encoder_optimum_normal.c":"8b4e7b94bd033b8e7322465fc42b972623c258ef13cce224aa6be8de90d2ce37","xz-5.2.3/src/liblzma/lzma/lzma_encoder_presets.c":"d3ad6260bafdc8d12319f6548231a332f6509f61ce35222e83bd8ed33065242f","xz-5.2.3/src/liblzma/lzma/lzma_encoder_private.h":"6cf7eb3b817ae62c1cb4f8c27fc7dc1d8ba80cc9ccff2ce37c3ca498d67873d6","xz-5.2.3/src/liblzma/rangecoder/Makefile.inc":"fb835be542437407ec1b1409a069d0a14b5550b06e4188e3b0cba8abadfd4790","xz-5.2.3/src/liblzma/rangecoder/price.h":"d11cf3ae775f7809c909e3a60c5b9d3f2d3f1a8ff90b6320a236d955cf3dd15f","xz-5.2.3/src/liblzma/rangecoder/price_table.c":"916cf099a79c5c68505c090fbf8a2e76a61c2cea83c6f158271eae0e657fe9ca","xz-5.2.3/src/liblzma/rangecoder/price_tablegen.c":"de6b7374b7c208faf7782232229886f5d944dbb98ad7d30a423c37036feab56d","xz-5.2.3/src/liblzma/rangecoder/range_common.h":"a68e29f8c979874966df0f2145705f22decd34ffd5e1034efeeef8126430f757","xz-5.2.3/src/liblzma/rangecoder/range_decoder.h":"e8063a1782bd85f9a7f94f5b5e1114622cb30c842c09fd2c657793d0edfae8c2","xz-5.2.3/src/liblzma/rangecoder/range_encoder.h":"6a43ce6dfb706662419b2246e1c21e6e90e8f5ba2e1e0a8a049533ea4df7bda3","xz-5.2.3/src/liblzma/simple/Makefile.inc":"5f33830fe8750481867dd7986d02894beb4e86b1bbf716e227f0132a0615819a","xz-5.2.3/src/liblzma/simple/arm.c":"d7fc50ce8d8afcebd08dea8e2531500c49f398c7ef8b7c7c8ebdf69efc311597","xz-5.2.3/src/liblzma/simple/armthumb.c":"fd7184a80b0d53f9d42bf3122f642a17881947419c0eab306b5d67f11cbac337","xz-5.2.3/src/liblzma/simple/ia64.c":"44f58579861358d8e0fdb3363aaf96b42c0d9aa54baf174f271ab22e26d41958","xz-5.2.3/src/liblzma/simple/powerpc.c":"7354365dd381dce8303c448ef993d2e059f3da36554ea08bfba0aad5b1548e37","xz-5.2.3/src/liblzma/simple/simple_coder.c":"8136e3b24fcb81b75a88e56516b95dfaab8c5eb29a5a693879dd075e55be381b","xz-5.2.3/src/liblzma/simple/simple_coder.h":"c8301307e370fcb40feba74c55c62ba50c4f29fe1242c822de09665a75512a3b","xz-5.2.3/src/liblzma/simple/simple_decoder.c":"51d678b89325e48e8af2d7cc3061569f17e5de36af6e49016b4e4b36d9c13a8f","xz-5.2.3/src/liblzma/simple/simple_decoder.h":"22c1d4850a392672ea50b72c8e60c5891dc3c9429715124408eef4c649f4a6e0","xz-5.2.3/src/liblzma/simple/simple_encoder.c":"10146da95bf969a8eb0a6f45a87bdbbe55a1dfd198253513d3d89d35b3d4013a","xz-5.2.3/src/liblzma/simple/simple_encoder.h":"bf61a79557c59ecb60489e07ff3fd4cb2e0eb226670e3b3ed3ed86f9aa4b34e9","xz-5.2.3/src/liblzma/simple/simple_private.h":"89d35ed2633465ecfd589d1a69442083eb80f0e1027725968411258a86204938","xz-5.2.3/src/liblzma/simple/sparc.c":"8bd89686c31c4700541f236239612e4bc91bb1346c2efd7074e032e98da6845d","xz-5.2.3/src/liblzma/simple/x86.c":"e4ea15a021d2dda07bd4c04d07ca15fce29348aff46756ccee5799037bde0a1b","xz-5.2.3/src/liblzma/validate_map.sh":"c34a6f22905dbbc4900e3945f2484ac8c97900bf68f3015f91e177731120d38a","xz-5.2.3/src/lzmainfo/Makefile.am":"517291d4ea68eff886e257c9a921f0fd0021a6883e6ace36f03f12037758f89f","xz-5.2.3/src/lzmainfo/Makefile.in":"c99a3cfddaf721f802585f4e362fa1c50c5c6cf9ac07fcb8d131720974e7e3cf","xz-5.2.3/src/lzmainfo/lzmainfo.1":"0963a1fe3e0539f036aaa9adf5bb179df10f2abe5f7f470c87340a5619e5f500","xz-5.2.3/src/lzmainfo/lzmainfo.c":"9b59add935c2329b84555bdacd7e6926bb35197e8e860a8fcf1757c320856532","xz-5.2.3/src/lzmainfo/lzmainfo_w32res.rc":"04a960119a80ae00c04a63c500626a321fee38281778b415555d289bb6a40727","xz-5.2.3/src/scripts/Makefile.am":"ff195ed243d7256172024a6c8dc4cf11c316ceee0e17a6da4d52778366ffe18a","xz-5.2.3/src/scripts/Makefile.in":"19df2d15a7ddb4bbd8471eca7ec2d42ee63a232b417430e03c554dcc43bc8325","xz-5.2.3/src/scripts/xzdiff.1":"fea4e489a64a2be64121e36041b993021839fbfe59d49a8b1b737c93fec3d29f","xz-5.2.3/src/scripts/xzdiff.in":"4aae54d26eb113c6ec1a9790dc097947e51a0ec9fed156090e344257d6b2baec","xz-5.2.3/src/scripts/xzgrep.1":"d838d6e694c2c9bc89a5b118e96ee6976c74319bf3e1d469c9d6d66674e34a7d","xz-5.2.3/src/scripts/xzgrep.in":"bd12900e67c80ae7abd3c46731ccadc02bd06b935d08bf69130ee5540ce77d68","xz-5.2.3/src/scripts/xzless.1":"2db6570b6f62b6f0d46fecfc18ead93000abaec97399514b31e18edb7ab2fecb","xz-5.2.3/src/scripts/xzless.in":"2d29b72f79de105bd29499edc3548b677cce24381d56e78c881e3f3daae15d76","xz-5.2.3/src/scripts/xzmore.1":"551a2a7f6e2e5626b0cee4580a0107d81410afd742da25001c846b4fa7645b07","xz-5.2.3/src/scripts/xzmore.in":"2f0f5b355285ef326258767797716c3c7885332e6dcf593573019906d0644b8d","xz-5.2.3/src/xz/Makefile.am":"864d6d9a5eb22553bb719a5a7678ea5cd480e171a3a49e66328816353d9f64f1","xz-5.2.3/src/xz/Makefile.in":"542a1bf45dd9daf2167ef4396f2167e5ad31fbcc89b3140e141d06799bf984fc","xz-5.2.3/src/xz/args.c":"8f650cfd30ce5bf6547691996c6eacee577a2dd9898d6101567b87122d3ef26f","xz-5.2.3/src/xz/args.h":"46521467728df4959f0a76fc3ca8a72619c288a2cd3c7db99d794a0b553055fb","xz-5.2.3/src/xz/coder.c":"10b36cfb0899b030663e5509a0c3662c7f7f5535a29f6e097437f91682f7a420","xz-5.2.3/src/xz/coder.h":"8aa2c13ffe794fb78504cb782ad57b85a314c7652091fbd3d798730d0205fcb8","xz-5.2.3/src/xz/file_io.c":"ba1454e57a295179e44dc1f7f51ad5fccc8a86470e9d49dcb2f2e381fb5f0569","xz-5.2.3/src/xz/file_io.h":"32138c65942b5be8160d61108077a63c1329a4acadf4a5496129988b1d4aa9d8","xz-5.2.3/src/xz/hardware.c":"50b5e99cf6f74e0856d3f02674c18f83fc22b0d1d8fec09c729d2e28259fbf4f","xz-5.2.3/src/xz/hardware.h":"38ac7e3e3acd28f09ad18f7200a39949ef7a373b61be5094b00525fbefb51a54","xz-5.2.3/src/xz/list.c":"ec6d7132cd4f6f34bbef76d2ba006924cf22832f9c5c0f45fba40c9641cd30cd","xz-5.2.3/src/xz/list.h":"63d7517c23adb530850dd4e4f92783f78bd52ff46b2746ef4ebffaaa8c4bef71","xz-5.2.3/src/xz/main.c":"610b2858d223b494f242d5dd413aa92fc3179249b16807b43c76c0c03c474f29","xz-5.2.3/src/xz/main.h":"e2737b49acdeafedb35619a862bccbc886d918a3d2d8cb633d06914955584fd4","xz-5.2.3/src/xz/message.c":"2e6f12174e15a61fc2602a58601169258ac244f6beb225c67bbe79e4f92d28a0","xz-5.2.3/src/xz/message.h":"409ca162b16c6755b84055020a4202c4a95fd48fb147e80b2cac9a7736af48e2","xz-5.2.3/src/xz/mytime.c":"08404f52436ae4ad0842c7787c5b4e1471c3fc3162b125be2b6e6c66eb45e10c","xz-5.2.3/src/xz/mytime.h":"d45be8e58683ccc34415a0b7b3fc32e6b32fa41ed661cbd345d4a152aff4ea11","xz-5.2.3/src/xz/options.c":"f0953f0e4faca6dd26ac0eb81261e345ec9302c7b54eaab576478e1e6ff08e94","xz-5.2.3/src/xz/options.h":"44de29c2eb5a7252ffc8b91ff6dd9e209a3fffc7d9cfb5119a2270f136895abf","xz-5.2.3/src/xz/private.h":"b0804ba5a06f9bb3fb9433c67237fc3c36fd9a04b6f444bbc4536b1dddb39a87","xz-5.2.3/src/xz/signals.c":"3a5f9dd993637bf9062593dc558417ecb1ae2c026d075ad1bbe9695ab8ef924f","xz-5.2.3/src/xz/signals.h":"38f6cec8dd2dd1fe0d927e13046f77a9295fe1404f5eaaf0de672f6202821073","xz-5.2.3/src/xz/suffix.c":"82bbdcb43e38090979cce401cb98709ec54a2bf88705ee98b81abee203ef2d9a","xz-5.2.3/src/xz/suffix.h":"37bdffa95beef1a1eaa1dfb764fcc450372ceff44a866bb60ab80453fb7bf9cb","xz-5.2.3/src/xz/util.c":"94107291a967a0e85088e1b7118e66793a456df0258c23e81b553f7f2d4cacff","xz-5.2.3/src/xz/util.h":"0ed0546122bc9b7422b64252a33ef061f39f48ebec55bbfa0d6374e5775c0826","xz-5.2.3/src/xz/xz.1":"2eb973fc64bc58b40c70a6887cfa2c95f64f076d309409cea7c6f94b89f0cf9a","xz-5.2.3/src/xz/xz_w32res.rc":"d42a35bcf8e872e875972fb90f3971acfd570a45c07d258759cc9b3e8a1d7424","xz-5.2.3/src/xzdec/Makefile.am":"f0709c759d911ad2450e185a4997e550a5fb9990805f3be7d70d1675644a65fd","xz-5.2.3/src/xzdec/Makefile.in":"fbfeda69f242dc2cfa2808bc94be1b9bb9e5de9dec268dfc01519761c2a582b8","xz-5.2.3/src/xzdec/lzmadec_w32res.rc":"87c6554af463075e3109964769108a54af237eeb1b427a75dfd8b92e0335bee0","xz-5.2.3/src/xzdec/xzdec.1":"d47d7c95f22cf49554b8d361f4a4e3bf95474a88849ca64a00c1e884defe3201","xz-5.2.3/src/xzdec/xzdec.c":"42f2ebb08bd9a8260076f053d4b8ea7fb7eed9d838bc72142e0b9e051708aaca","xz-5.2.3/src/xzdec/xzdec_w32res.rc":"356ce543f7143a6572da3bdaf473acd686d8765a672a929b7dc79c5f21c15428","xz-5.2.3/tests/Makefile.am":"3e726b207ec54a8bd4e3e4ad0e4b4e9cdb973172d2409b81de2cc54acb1715dc","xz-5.2.3/tests/Makefile.in":"a34be569447c4dc2c0340572dafa558bf91232b528386c58116d058f9a67479b","xz-5.2.3/tests/bcj_test.c":"6984161ceebc2f94ba41047b85ddd083f64266f354d79f128c57882378aadb61","xz-5.2.3/tests/compress_prepared_bcj_sparc":"898511c9fbfd1ff3ad474638283a82a0bc0ca11fcb47e7a7e1f8b0758d999ee2","xz-5.2.3/tests/compress_prepared_bcj_x86":"dee7bc599bfc07147a302f44d1e994140bc812029baa4394d703e73e29117113","xz-5.2.3/tests/create_compress_files.c":"fd8c8370869c27a8923b770996094c81a4f6166e87639e2cab99a10bf719b7db","xz-5.2.3/tests/files/README":"ca69ae71c4dd4a8211694ce9efc081cc895433691716007330ef3898d78a06fb","xz-5.2.3/tests/files/bad-0-backward_size.xz":"894d4b6d4ea8657893e9ab1c48162438605537e6ff974ee8ee61903b8eaec55a","xz-5.2.3/tests/files/bad-0-empty-truncated.xz":"9de843e125667ecf9b804469889bcea152758585c0e335a7dc15ed243ce83a50","xz-5.2.3/tests/files/bad-0-footer_magic.xz":"b7d60be0dd400c8d8b2a04094d297f4bbf563fd33041cf27ef6e9be74f7df829","xz-5.2.3/tests/files/bad-0-header_magic.xz":"3adb42fba230b3c09d2277adb7f3ba347f26c1831d4e9514d3068bd3bca9d2a4","xz-5.2.3/tests/files/bad-0-nonempty_index.xz":"ece3915eacdc4edc296f593b3cb2617cdd888315eada28dcb366a3fda131590a","xz-5.2.3/tests/files/bad-0cat-alone.xz":"14bbcda4f97f6d3583f36c6a4946d0d0dfb847653175d432ee275d5738d6d9b7","xz-5.2.3/tests/files/bad-0cat-header_magic.xz":"bd3f4dfeae3f4ec3e778809e013859b6b291d18e067c8e9557cc0d4c1009f22e","xz-5.2.3/tests/files/bad-0catpad-empty.xz":"56317222b2ef4743fb18b457c3760094937dacc9fdf18d645c181e5be4b327c6","xz-5.2.3/tests/files/bad-0pad-empty.xz":"a5995e19c63bdb9d327d514c8e8c9d2971b4cfdbc755ffcb11aee30b8a9787b1","xz-5.2.3/tests/files/bad-1-block_header-1.xz":"c8bc15e7bfb1056d358cbe5f9b6ae86489e277e353f275a79a1c212a09cc56af","xz-5.2.3/tests/files/bad-1-block_header-2.xz":"3b0de551b66e8ee65abfaed399e1638de2955aebc882b9585e12d5f93eb21146","xz-5.2.3/tests/files/bad-1-block_header-3.xz":"2a05eb3e61e10b862f09ddaf030ee5a04ca4c875b2dac251ef0529a8ddbb61f3","xz-5.2.3/tests/files/bad-1-block_header-4.xz":"8ac58b8fade15875213c116bec05ec78fc659d3cda69116d3aa4dc71557b2d1c","xz-5.2.3/tests/files/bad-1-block_header-5.xz":"a76c17d193405f180c3b84c9047ccaf1b4f0483242dda58e7c5070313898f3e9","xz-5.2.3/tests/files/bad-1-block_header-6.xz":"f7cc702ce7a2523e9718816b4a5983b05fa8acbb07341df2a5234ce1828731cb","xz-5.2.3/tests/files/bad-1-check-crc32.xz":"4f2de28e30a05d979c7b2db4ba4f4126e92563e3f591bef1508b0926dcf17fa8","xz-5.2.3/tests/files/bad-1-check-crc64.xz":"d7218954fd4bd69eb77b545d8b2428ac35a984ff3bb015846b65d88b325ca219","xz-5.2.3/tests/files/bad-1-check-sha256.xz":"f106a808e57ca48fa4a64b1913042c526c1d777f9eb1622a0857ce18ee34aba3","xz-5.2.3/tests/files/bad-1-lzma2-1.xz":"b99d620ac64188c4af54e88c79404f153642bed63442a31b642942804f1e1785","xz-5.2.3/tests/files/bad-1-lzma2-2.xz":"91517a1280b5e52ddaa5a327e7c7f5a045d22db94cdc8a2f79781135f461de12","xz-5.2.3/tests/files/bad-1-lzma2-3.xz":"e063697abf2d7cbb7271eaffb064484095abbc2397268cbe11897dca8af52427","xz-5.2.3/tests/files/bad-1-lzma2-4.xz":"8777af9f9c9e3ddca331d0671a7753a219ef01f3b87708bc5129cc619e63c6e6","xz-5.2.3/tests/files/bad-1-lzma2-5.xz":"2e2759a097712c49a3e93446276cd56ecb748315c0cdec1d8603d8740c0a1494","xz-5.2.3/tests/files/bad-1-lzma2-6.xz":"646cb3043b6aac6da1540af308a78e6504c7708af54d5815f224f27a58f00919","xz-5.2.3/tests/files/bad-1-lzma2-7.xz":"ddd7b265fe96595408d72a6664ac3693de097c0d887a9419c5aff3a7fee83d5e","xz-5.2.3/tests/files/bad-1-lzma2-8.xz":"85c49abc062cddf535f41347edb368f702c442241ede7276c4d99b0051f19b0e","xz-5.2.3/tests/files/bad-1-stream_flags-1.xz":"c65babcb94c3c175f2d8686391d2d0113fbc434fc8dca009e3f5d1ddf7c83d61","xz-5.2.3/tests/files/bad-1-stream_flags-2.xz":"35ece04169f64180ba2b4fff03f80a3048ba11b3ef4e16a0ce8d9b5c32ce5e9c","xz-5.2.3/tests/files/bad-1-stream_flags-3.xz":"c59b030817cec49b51d1f1b8e9f06ff2535de25e2c4c07a3f45c197d0e3db949","xz-5.2.3/tests/files/bad-1-vli-1.xz":"dde033a0281c2326178e23ace66268dddac8f5d7d2e585ce865c6f3b4e7ed7da","xz-5.2.3/tests/files/bad-1-vli-2.xz":"9eddf417be15f3f7170fdcdadd753c0fe35d22d13377f271319f0c16889b0e4d","xz-5.2.3/tests/files/bad-2-compressed_data_padding.xz":"9cfe1c1e950111e4563d773790073637c3f76d42d586f10e77469844a0c84dd2","xz-5.2.3/tests/files/bad-2-index-1.xz":"ff6b77b8ce16cdb0b6d455c8045029fa6baec1877798a7e7ed7431b9cec83bca","xz-5.2.3/tests/files/bad-2-index-2.xz":"fa394dea8bedb64ad388a8d44ab324cc0aefe9d5b6d7a78b4dfd610ef78263d0","xz-5.2.3/tests/files/bad-2-index-3.xz":"62f82cabb391bb98ba87162ad04376e2d839741b56eff0750e93cea822b767c8","xz-5.2.3/tests/files/bad-2-index-4.xz":"102877780afb8155832afd630e426d2e1456f4da62360e4091bec3524d599cec","xz-5.2.3/tests/files/bad-2-index-5.xz":"72ac8e7907c092126bfcc999474e44aa17d29feeeabacc50819a0b5a737afdb3","xz-5.2.3/tests/files/good-0-empty.xz":"14c80c40f5b247deead9e9d1d31b8b4f5f0b4f4425e6eb12291fd3e505fc8414","xz-5.2.3/tests/files/good-0cat-empty.xz":"65de7e01eff8cf2f9a287153971467b1c11811213b64a38bdf673bad240436ff","xz-5.2.3/tests/files/good-0catpad-empty.xz":"019ad3e542d5f5797c6d98148f72725930a057fec6abd9a426ce889302a9fbfe","xz-5.2.3/tests/files/good-0pad-empty.xz":"6b97fc3c4f6f4a9115377b3dce52caf4e726458ed9dfd68b60f94ccdff3c5f8c","xz-5.2.3/tests/files/good-1-3delta-lzma2.xz":"00058b3c84d5e2718c298dd8689730ae79c46995943d242897537e9da3d1b04f","xz-5.2.3/tests/files/good-1-block_header-1.xz":"b94444ef9b5918e4b6c9bcd83080884b61c0c5072588f66c03f244faec475f12","xz-5.2.3/tests/files/good-1-block_header-2.xz":"96d4c234920acdd9b61ca904b2c38a402706131a5136ec04d98592f755e52664","xz-5.2.3/tests/files/good-1-block_header-3.xz":"2bb7072476150fdf06cbe83465f443f7928ee011538296f5713e22856b808fb8","xz-5.2.3/tests/files/good-1-check-crc32.xz":"eaa0f7d82fb273920c5247fa4928e695830ce40631945c6dda3cdf3f14d65cec","xz-5.2.3/tests/files/good-1-check-crc64.xz":"a0b759464fa8d02f0a3da4d19cebdd1d7d86b19728b599f7f946f58e687a22c1","xz-5.2.3/tests/files/good-1-check-none.xz":"cf3bece11d937fceb9c7599bfeffb067d140441d806823ace927a24e4410c16d","xz-5.2.3/tests/files/good-1-check-sha256.xz":"dda8bb24f50e39e750a5ad3697960083450a21ae054b2dff30699d542894826c","xz-5.2.3/tests/files/good-1-delta-lzma2.tiff.xz":"c9005e580f3e74b2cb8d817120f68cc2177840cda75f48d679551a7f3e323413","xz-5.2.3/tests/files/good-1-lzma2-1.xz":"d0e6089fe87776cb754b08012cc05b922e2d04f8a5484baf2d946cceebc24546","xz-5.2.3/tests/files/good-1-lzma2-2.xz":"8d8d4708327aa13930373d80ce3b996ccf0f1ff67d3cdd3d494aa6360fa53537","xz-5.2.3/tests/files/good-1-lzma2-3.xz":"2c286d6b18f24301f25a1c501a2c74c2036c94e0ab85d2289991f7fca2acb3ad","xz-5.2.3/tests/files/good-1-lzma2-4.xz":"ee91a262eaac56d93ffe9b3d582bcfdc1d92a8edb3a5555d52adc4c21f5347f1","xz-5.2.3/tests/files/good-1-lzma2-5.xz":"a59afee16f97700f89a3cc81740058a0e64fc9e06d176450b44aff3d70716c4f","xz-5.2.3/tests/files/good-1-sparc-lzma2.xz":"8ec92e5fcfe27c5bc320880bcca89bfa8a4aa789a5527a087f5a49492c31af5b","xz-5.2.3/tests/files/good-1-x86-lzma2.xz":"43ca5c4310f28554fcb2912db1098a779c1e91251802d4adbf23bb5634333389","xz-5.2.3/tests/files/good-2-lzma2.xz":"c096d08c0effa829b9c1cb92242b80e26be3a206f7a503d73b552da205b64d6d","xz-5.2.3/tests/files/unsupported-block_header.xz":"acf4e10b6f8e885ca80cf27c36187cafd974af46b42f70a761d969f5c0edbcaf","xz-5.2.3/tests/files/unsupported-check.xz":"c781077a53fcb200131fc6aaa3eaed6140f71f8cea5bcf9aae6898c5df4371bd","xz-5.2.3/tests/files/unsupported-filter_flags-1.xz":"adb9d23d6645ffa0a4dfd377cb8fb6a01a2622edc1c8bf1ed1ddc91b45b6d5f1","xz-5.2.3/tests/files/unsupported-filter_flags-2.xz":"e7cd859ba5efd8e238fd4bb44724ee3ee27fa2c993cc8794330e97867d137eff","xz-5.2.3/tests/files/unsupported-filter_flags-3.xz":"03b202ddc097d5918b808c2de99b37fbf1d138274998911bff2d514d1a04f109","xz-5.2.3/tests/test_bcj_exact_size.c":"c1f3674f454b860ae633c72739a5104f945b971aa92c63c18df9e94414b39e60","xz-5.2.3/tests/test_block_header.c":"78e08591a1fcf3a653ad6a806889c715b1d60e2141ad17b793c184251239399e","xz-5.2.3/tests/test_check.c":"c10d97f8bd21ea418b1ef0bec72e169a842f4d0342eb3f536e645b314eb9bdce","xz-5.2.3/tests/test_compress.sh":"b57f43cfcfdc920ce7210fa49a41d49f633b43f4efaffe0c0d01dd7d1d1489ee","xz-5.2.3/tests/test_files.sh":"b6778cb21bc6f4ca5c96e498ab376d1f00d79969c8df8be70498eff4232eeb6c","xz-5.2.3/tests/test_filter_flags.c":"a254c53ea6744b0238530af02bd45a917bffa8f952d02f01c3f5535667556462","xz-5.2.3/tests/test_index.c":"4289a811c1feb96c0294a4fc541022a87926f4b6c90a0d89f5bb8101427660be","xz-5.2.3/tests/test_scripts.sh":"c0b184719746b4569b91232e59d37f39e8641806d261ba31ffa6b041c9ed4055","xz-5.2.3/tests/test_stream_flags.c":"951cdcc3832f89900e839b79e6990b179630e19bd9847b13d2e75538cb66e482","xz-5.2.3/tests/tests.h":"103dd2b5c336c41d170db088002a9f99d326ae20206b0a7455a7171636bc8c59","xz-5.2.3/tests/xzgrep_expected_output":"260f99403d67f8c7a6dfeb736072c781d3f1cd6a410190e91abeb13864d3dba0","xz-5.2.3/windows/INSTALL-MSVC.txt":"c2136963b02c118dbfb4eb3ccc7953e996cbfb9b1a049ca975f980aabd0b2bf4","xz-5.2.3/windows/INSTALL-MinGW.txt":"8df1b40b122f8a041d1c5883883a381eb13ee870a6a856be4a6817139ea7dded","xz-5.2.3/windows/README-Windows.txt":"bb0f480c1be63ea699c785590bd840cd6fcbe750ed584cf260430d72183b72fe","xz-5.2.3/windows/build.bash":"bb08c5fc109952609bef97e3ddb1e8d05ef8d9371f0d84c6aeaf0426b8152cdf","xz-5.2.3/windows/config.h":"0b7421307adb8ef20f1c02224f1524b091df625b12fce2bf011335b8e8e06430","xz-5.2.3/windows/liblzma.vcxproj":"dcb0fd2b6e17c1ab4b97f183623e6efd33546ad066e022cbeb6e7684038fc42b","xz-5.2.3/windows/liblzma_dll.vcxproj":"1ddf32f8df200eeb7f180f9454ef836fc0a019484ecde5bbd478465f3003986a","xz-5.2.3/windows/xz_win.sln":"c33105e2b70986217893c5a7c250907580a78da057527101dc55588b1a0afb28"},"package":"013fa6506eb7d26040c46dab9ecb7ccb4e2896b5bf24a9d65932501ea9f67af8"} \ No newline at end of file diff --git a/src/vendor/lzma-sys/Cargo.toml b/src/vendor/lzma-sys/Cargo.toml index 26e1d5c714..1a3e457941 100644 --- a/src/vendor/lzma-sys/Cargo.toml +++ b/src/vendor/lzma-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lzma-sys" -version = "0.1.4" +version = "0.1.7" authors = ["Alex Crichton "] build = "build.rs" links = "lzma" diff --git a/src/vendor/lzma-sys/build.rs b/src/vendor/lzma-sys/build.rs index c7019a5e82..b1e642eaf9 100644 --- a/src/vendor/lzma-sys/build.rs +++ b/src/vendor/lzma-sys/build.rs @@ -29,8 +29,6 @@ fn main() { .unwrap_or(String::new()); if target.contains("msvc") { println!("cargo:rustc-link-lib=static=liblzma"); - let mut msbuild = gcc::windows_registry::find(&target, "msbuild") - .expect("needs msbuild installed"); let build = dst.join("build"); let _ = fs::remove_dir_all(&build); let _ = fs::remove_dir_all(dst.join("lib")); @@ -43,9 +41,20 @@ fn main() { "Release" }; - run(msbuild.current_dir(build.join("windows")) - .arg("liblzma.vcxproj") - .arg(&format!("/p:Configuration={}", profile))); + let mut build_succeeded = false; + for platform_toolset in &["v141", "v140", "v120", "v110"] { + let mut msbuild = gcc::windows_registry::find(&target, "msbuild") + .expect("needs msbuild installed"); + if try_run(msbuild.current_dir(build.join("windows")) + .arg("liblzma.vcxproj") + .arg(&format!("/p:Configuration={}", profile)) + .arg(&format!("/p:PlatformToolset={}", platform_toolset))) { + build_succeeded = true; + break; + } + } + assert!(build_succeeded); + t!(fs::create_dir(dst.join("lib"))); t!(fs::create_dir(dst.join("include"))); let platform = if target.contains("x86_64") {"X64"} else {"Win32"}; @@ -124,20 +133,36 @@ fn main() { } run(&mut cmd); - run(Command::new("make") + run(make() .arg(&format!("-j{}", env::var("NUM_JOBS").unwrap())) .current_dir(&dst.join("build"))); // Unset DESTDIR or liblzma.a ends up in it and cargo can't find it env::remove_var("DESTDIR"); - run(Command::new("make") + run(make() .arg("install") .current_dir(&dst.join("build/src/liblzma"))); } } -fn run(cmd: &mut Command) { +fn make() -> Command { + let mut cmd = Command::new("make"); + + // We're using the MSYS make which doesn't work with the mingw32-make-style + // MAKEFLAGS, so remove that from the env if present. + if cfg!(windows) { + cmd.env_remove("MAKEFLAGS").env_remove("MFLAGS"); + } + + return cmd +} + +fn try_run(cmd: &mut Command) -> bool { println!("running: {:?}", cmd); - assert!(t!(cmd.status()).success()); + t!(cmd.status()).success() +} + +fn run(cmd: &mut Command) { + assert!(try_run(cmd)); } fn cp_r(src: &Path, dst: &Path) { diff --git a/src/vendor/mdbook/.cargo-checksum.json b/src/vendor/mdbook/.cargo-checksum.json index 7525edc13a..3ab7747959 100644 --- a/src/vendor/mdbook/.cargo-checksum.json +++ b/src/vendor/mdbook/.cargo-checksum.json @@ -1 +1 @@ -{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"7fc53e58ea4fc231547669915c3aa5c935160fad031fec21dea2bb3b16a15b2a",".travis.yml":"d731d3f863b67b45fff35ac820cd8e59fbf9bd2f31945eb95a81efd663d02d6f","Cargo.toml":"4b8e1b67da1a09bdc4487e2dee85203e9ef1aa139eca5cb0d8426bd611c4f250","LICENSE":"af175b9d96ee93c21a036152e1b905b0b95304d4ae8c2c921c7609100ba8df7e","README.md":"83aecab607b1ee604474919ff6cb5656cbdfe5fb19434ba9e376e8c0ea31a4ef","appveyor.yml":"a668f162445352248c2959a4a2cdbc841a65e720315ed63465a5e2a496da8fc3","build.rs":"a4a6cae4865610b7f072d49d6a207aa347b224f1599a1f8040319238794d78ab","ci/before_deploy.sh":"315c72bd54e3a06523cd4b578fba03aa77ffa719585e355f6af53d83b6186ef3","ci/install.sh":"0bd60e5dd47a8abe15fcb8a24321b3d41eeab2c831e7b6c0a698a8e14243362e","ci/script.sh":"200d93a045f609cddf76e300b972d39482611d562b47c6db6cee43574023c319","deploy.sh":"a1ac4451da71df79d33bfebe8cdf551a6108a458c3e05b6f0cd88e834e16f207","rustfmt.toml":"6b70725f7f74ddf6156780fb848f1bbad19002a5ebd613cdd2eed886e8a7bc08","src/bin/mdbook.rs":"6bf068173d3c56af9dcf07a8e2f525474ad45d8e2dcfd854a2502f658ae899f0","src/book/bookconfig.rs":"5f7ce7990b040fb72473a79985498eb03c8c6a583b925b29045a9edbe64c4467","src/book/bookconfig_test.rs":"1cfc10c752e17ac4fde86ab5f98a5bf27b30d2a1a6de29f4b3dd2e9abd48a893","src/book/bookitem.rs":"6b7e0c1ac396a5ec7c173de5b598db64aa877237a703d2d13d28848987462d5b","src/book/mod.rs":"c78de3cb014501a7cc009becc4116fcddd4c1842c1e6cd3a3e0a5a8ba059e851","src/lib.rs":"1d6d728909373153ede38ccfe0425113a8a05b1d53477cedbc1535327b3b7938","src/parse/mod.rs":"7f84c961253464c84da440a0c6970607e5f80fffcf85ea417ac7e5f16b85ff26","src/parse/summary.rs":"92ab07cc076ab4d455538c347ec93c6a875a9485481f780d91ae20735916c973","src/renderer/html_handlebars/hbs_renderer.rs":"d2f9c345f32042840e6cb38903434fed160ae30977289c89c06e8499b429b2f5","src/renderer/html_handlebars/helpers/mod.rs":"7e7a9af12ddb4f06b6672b13b8b82dc698c7f95716830f2338f73715589c51ea","src/renderer/html_handlebars/helpers/navigation.rs":"5a7fe4e223fbd096ca32ba9112b202716ff45ba15f8962328c62438ea198bdd3","src/renderer/html_handlebars/helpers/playpen.rs":"096b3821703235c5ce7abfee0541f87790842cd98624a13788720ec4b51fb780","src/renderer/html_handlebars/helpers/toc.rs":"da6d2554d5dea053a692d73f3946dceb372815383336ab767c0b4bbee5c59c8b","src/renderer/html_handlebars/mod.rs":"b59451bbd082b10ead4a1b4ef27496a64381e609ced7dcfd0e4fd15ecb03e996","src/renderer/mod.rs":"5d01bb20dbdac8cdd01cbd4b3ad2baac34521cacd4e19163eec001cb753801c3","src/theme/_FontAwesome/css/font-awesome.min.css":"936ffccdc35bc55221e669d0e76034af76ba8c080c1b1149144dbbd3b5311829","src/theme/_FontAwesome/fonts/FontAwesome.otf":"7961070f76a33c1307de19ce2a93dc2b26d6747fa759aee5045118644c758acc","src/theme/_FontAwesome/fonts/fontawesome-webfont.eot":"d4f5a99224154f2a808e42a441ddc9248ffe78b7a4083684ce159270b30b912a","src/theme/_FontAwesome/fonts/fontawesome-webfont.svg":"7414288c272f6cc10304aa18e89bf24fb30f40afd644623f425c2c3d71fbe06a","src/theme/_FontAwesome/fonts/fontawesome-webfont.ttf":"1b7f3de49d68b01f415574ebb82e6110a1d09cda2071ad8451bdb5124131a292","src/theme/_FontAwesome/fonts/fontawesome-webfont.woff":"a7c7e4930090e038a280fd61d88f0dc03dad4aeaedbd8c9be3dd9aa4c3b6f8d1","src/theme/_FontAwesome/fonts/fontawesome-webfont.woff2":"3c4a1bb7ce3234407184f0d80cc4dec075e4ad616b44dcc5778e1cfb1bc24019","src/theme/book.css":"faa68e7fb58e00934baedf9bb60a4187f2568cf1b10736d9c9592adfd5c249f0","src/theme/book.js":"461df0f6998eb8c585362e4bfc84c2b29f46948025ba7f6221f88104c94ce527","src/theme/favicon.png":"8114d1fc74f4b5621ad9afde7746ed9cf7e420be317a6e29023d2298d58aa15b","src/theme/highlight.css":"e5c723e9ac733f76838f992e66b73c470865a42eeb07a4db71f4dca7628c3ac5","src/theme/highlight.js":"37ace44c6a45f7b68004c7264ccf29a1bafa2a8f737cf48525914b3e9984bdf8","src/theme/index.hbs":"5e83292c4522aca17ff47c28648709314dcd9912fa391e44a11e9e2e817d042f","src/theme/jquery-2.1.4.min.js":"f16ab224bb962910558715c82f58c10c3ed20f153ddfaa199029f141b5b0255c","src/theme/mod.rs":"4f8d40c66f1dadf94a714ed9b7e5821c2078837c6b4d20ee22e9945125466c3c","src/theme/stylus/book.styl":"22bec9f79e1a49904824cbcb007c06ab46a5ecabb9058e0165d62972dfa0b8e0","src/theme/stylus/general.styl":"50c86eaeee69f3b15aca150aeb39fd370dd66831db2935344ec88d6e783c29d7","src/theme/stylus/menu.styl":"c4990d4852275b6cac8201ef03ce7fb3c657a4f0630dfcbaab8f62af2b8f9446","src/theme/stylus/nav-icons.styl":"aae03f9a9927c5e3b17504227c18c2e1542581dccb10fcaa65f3b348a326bf47","src/theme/stylus/page.styl":"624960299de334cf1ff3075ed23742c441199e6811984a0f1f7a8f6246b2cc5e","src/theme/stylus/print.styl":"89a714a5c376f01a211f1f5b79ae1e2ef241dbee150d09563e6d0cd2e6b6c424","src/theme/stylus/sidebar.styl":"7a7a501f1d824375532b6f3e97e53980e176bccfae6b542fff73c660ac543c68","src/theme/stylus/theme-popup.styl":"c9f1c75c5e7e2ddef8f7fdf50749d29b3819a0410378bf1424f6cdac5f3bda1e","src/theme/stylus/themes/base.styl":"cf4ba427c9fea01ca17db9af457e60ee9936d2cff1439278d549d8b200979687","src/theme/stylus/themes/coal.styl":"151ccd7de802ac319787b2a7f0e13286dcfb203f730e7324b156760167b486e9","src/theme/stylus/themes/index.styl":"4afadc7eb2fdd29408cd8ec0f2d37948a98040994a7142b3d114ae61214e6d21","src/theme/stylus/themes/light.styl":"7cf535638cdca25c94b87613facbd52036d10222144f838e8410a4e9ffd3f8e1","src/theme/stylus/themes/navy.styl":"065dad59ccee44d075805e60a07987d6d80d72051f496ec89341b1d3096c429c","src/theme/stylus/themes/rust.styl":"6aeb5a69df72824edbcf8ae963dc48b5766311eb0d03b4ecc6e9f0f32a8b0783","src/theme/stylus/variables.styl":"cd8cf21678e86104d21a2a84dae192f1b8b1ed39a912363428ae958052376aa0","src/theme/tomorrow-night.css":"c914fd853acc9b53301a97948476de8a8ffd3e40f5bbd4f5d62ff42819558b82","src/utils/fs.rs":"a383300135a988e3db0b8f7198c00cf538ce2439d233f554aa50edd2a7bcea5a","src/utils/mod.rs":"a7e7271c6528b3a8dbcf6c5eb76446bf9b5f9e5acf90a8e52ed2219b8fc61eff"},"package":"f1e2e9d848514dcfad4195788d0d42ae5153a477c191d75d5b84fab10f222fbd"} \ No newline at end of file +{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"7612c630f7ceaf8827018e5b963438fde7229dbc1d3ab93ae3a523e8897dea58",".travis.yml":"c4658664271137ad2f4e531a4a13b5f58dc5a0f81eaffce307922c70853df81d","CONTRIBUTING.md":"83683758174127303ae6cd2aa24b93bd31fc7bd607c7acedf44af6a948cb809c","Cargo.toml":"c819700e31df6202095da79558b571d35843c75fa9c7ac6ef79252e21abb9b22","LICENSE":"daccd6f5b8e0fd07c0992116280fcddc77c2a612c4ebeb64d8b114ed9da1a10b","README.md":"648acfe8e107c6a1352e2bf23d4740dbe827f9c2d313b3e9bf19b8d82679bca5","appveyor.yml":"e3709a665d17a8d34956e228a5399cdafb75a64be270a16b8ec36b1f7680d254","build.rs":"0d5b680a9c6edc683110ea15162e7d0c2c9697e1f371236a605cbffccff90f83","ci/before_deploy.sh":"234420ac249ed2bdc7a74d470fe2f1b898ac1e165a931a659cb23792ac399d84","ci/install.sh":"0edce34ea7a51a664b43d8397173cf484119145b7a89d913805b8635d45c92ca","ci/script.sh":"9bad90afed9fb44c2e0b0078b5d2b03f29669e3432e92e731b329420f9ceb7a3","deploy.sh":"8333f8b912eb9dc5bda56973896769a2af642ab27a477f7a4957967bec820818","rustfmt.toml":"2dde0ea1340c0bc964a44c813e6337ce11816cc7df37f059a67271fd256a012b","src/bin/mdbook.rs":"b5b530ed37d290b36288bc7a591dcd11b2854331fcc15b51baca7119b04d105c","src/book/bookconfig.rs":"eca6d3a425691b45bf40012b5ac0ee2d9bf46d1a6fc83db914a38071078e6204","src/book/bookconfig_test.rs":"02494a3ab97ff0a4a1ae2d5e00fc32d190746297f323cdc0348f0650d08c9ffd","src/book/bookitem.rs":"34bbf455b608069f3794706875ca3bbc2e6891d6a88a86e7eef41771306b5cc0","src/book/mod.rs":"f031fbbdc517de701ccb209bc4b943f723d8c7f34eff5fb2305ba9187dddee34","src/lib.rs":"57491c3b9696ee8262dcaa3e61c738d67bde42e5770411c6d39e3fbb88b560a8","src/parse/mod.rs":"8d17800a04d1b77a0fbf6b27c52a4adb0755a6d004819ebacdf5adf94f231fc4","src/parse/summary.rs":"48e270e1efdf95e337d30aa9da05a2a14c98110bbd5229305222f0bca9f0362b","src/renderer/html_handlebars/hbs_renderer.rs":"80abc4dbe4a78fd394525cd3dc5b19a884d83a489178d8eb788ce538759fa2fa","src/renderer/html_handlebars/helpers/mod.rs":"243447b1957ece344721546933bb6643c2b084270bf0133f8b8233842936c612","src/renderer/html_handlebars/helpers/navigation.rs":"850c217ac9dda2b756082f131ab39c9698b6840926f8bb2d0cf6f6edc733fe57","src/renderer/html_handlebars/helpers/playpen.rs":"6104cdfb0ac480f600b7b3169338e319146358412c35887d3a20d8846950370b","src/renderer/html_handlebars/helpers/toc.rs":"34f4c91f6e5aa46d91aa3c6009f5594dde57fc2e83d9b73190dda601c1a227a4","src/renderer/html_handlebars/mod.rs":"fd11f3b70867696c710a077af4030c3ff21f0b36a412d62b5628528376f1f3c2","src/renderer/mod.rs":"c530f762a3eb8c65e70372769f857b92d2eb6b355a717a3d09d1203ac87316b4","src/theme/_FontAwesome/css/font-awesome.min.css":"936ffccdc35bc55221e669d0e76034af76ba8c080c1b1149144dbbd3b5311829","src/theme/_FontAwesome/fonts/FontAwesome.otf":"7961070f76a33c1307de19ce2a93dc2b26d6747fa759aee5045118644c758acc","src/theme/_FontAwesome/fonts/fontawesome-webfont.eot":"d4f5a99224154f2a808e42a441ddc9248ffe78b7a4083684ce159270b30b912a","src/theme/_FontAwesome/fonts/fontawesome-webfont.svg":"7414288c272f6cc10304aa18e89bf24fb30f40afd644623f425c2c3d71fbe06a","src/theme/_FontAwesome/fonts/fontawesome-webfont.ttf":"1b7f3de49d68b01f415574ebb82e6110a1d09cda2071ad8451bdb5124131a292","src/theme/_FontAwesome/fonts/fontawesome-webfont.woff":"a7c7e4930090e038a280fd61d88f0dc03dad4aeaedbd8c9be3dd9aa4c3b6f8d1","src/theme/_FontAwesome/fonts/fontawesome-webfont.woff2":"3c4a1bb7ce3234407184f0d80cc4dec075e4ad616b44dcc5778e1cfb1bc24019","src/theme/book.css":"faa68e7fb58e00934baedf9bb60a4187f2568cf1b10736d9c9592adfd5c249f0","src/theme/book.js":"53218c727e49fafc09c86f38da2f082d78ce513a04bb6030a12809297ecc4efc","src/theme/favicon.png":"8114d1fc74f4b5621ad9afde7746ed9cf7e420be317a6e29023d2298d58aa15b","src/theme/highlight.css":"a8e0cdb65ed7959c997b047be0cc3809bdabb64c093c870ddff001a45fd34831","src/theme/highlight.js":"350fc176452dcb8b6ad142004119e0df3679684f54691efbf57ed9803781d058","src/theme/index.hbs":"3b67ceb2594c7fb2b9d5dbd5b5c26f59bffa2f85e1f1b29fd1466a2d32f10a6b","src/theme/jquery-2.1.4.min.js":"de4b3c3d1dc2506b6693f0f98884e1dc074cda9d66cab39b7b48a115fdfc4c0f","src/theme/mod.rs":"ede7877bc03583293d5b2e0649b5664ca10bf570395f86e999b24e5f8517d70b","src/theme/stylus/book.styl":"7424e30554a62ddde341d055a2c576ff8b36b5ad2de30af9799bf79e76748b74","src/theme/stylus/general.styl":"50c86eaeee69f3b15aca150aeb39fd370dd66831db2935344ec88d6e783c29d7","src/theme/stylus/menu.styl":"5699bc3eee208af30c7ca1a4518c347b2f043a58d0e1307cb08ab15995557fd5","src/theme/stylus/nav-icons.styl":"ce371f2eeaf0d50a6d94ce1407578908753fb4010bba30d9b0dcabfc7b3b779e","src/theme/stylus/page.styl":"a8a1718e2e4fb3d48e4d527e5400e954ab7b6a1ae87f1b6b40b28a11b6926e73","src/theme/stylus/print.styl":"54efe6860611698dc520f82b05e9e17f4cdbc913822b17f1c44e0808ecf163eb","src/theme/stylus/sidebar.styl":"648c3c3b2fa0541321a646f7742a5222f655db39e4f20ef43a9ba3dcdbdb293f","src/theme/stylus/theme-popup.styl":"8c801836bc8d91c68e933dbc3b94eaac132a3fc04fd87b85550dc1f628765447","src/theme/stylus/themes/base.styl":"cf4ba427c9fea01ca17db9af457e60ee9936d2cff1439278d549d8b200979687","src/theme/stylus/themes/coal.styl":"151ccd7de802ac319787b2a7f0e13286dcfb203f730e7324b156760167b486e9","src/theme/stylus/themes/index.styl":"4afadc7eb2fdd29408cd8ec0f2d37948a98040994a7142b3d114ae61214e6d21","src/theme/stylus/themes/light.styl":"7cf535638cdca25c94b87613facbd52036d10222144f838e8410a4e9ffd3f8e1","src/theme/stylus/themes/navy.styl":"065dad59ccee44d075805e60a07987d6d80d72051f496ec89341b1d3096c429c","src/theme/stylus/themes/rust.styl":"6aeb5a69df72824edbcf8ae963dc48b5766311eb0d03b4ecc6e9f0f32a8b0783","src/theme/stylus/variables.styl":"15f1215c0336336966a2db1a741860f2cb400d9816eaad9a1b24aba494c78f29","src/theme/tomorrow-night.css":"c50d01aea634fb78b058fa95bfa93e8338a5595a6e1cf9c34822f82a0176e418","src/utils/fs.rs":"3adf29a22f7127171db476959677e734a837d5f08a1542bbd502fa84d3149bc2","src/utils/mod.rs":"3a8e2c6084faa7423511e473619119d71515d6410bd78be59cef9e5584ac7cfe"},"package":"22911d86cde6f80fa9f0fb2a68bbbde85d97af4fe0ce267141c83a4187d28700"} \ No newline at end of file diff --git a/src/vendor/mdbook/.gitignore b/src/vendor/mdbook/.gitignore index fbe2812f57..0f3c9d607a 100644 --- a/src/vendor/mdbook/.gitignore +++ b/src/vendor/mdbook/.gitignore @@ -1,5 +1,5 @@ -Cargo.lock -target - -book-test -book-example/book +Cargo.lock +target + +book-test +book-example/book diff --git a/src/vendor/mdbook/.travis.yml b/src/vendor/mdbook/.travis.yml index dc6e19dcba..e1d21a08bd 100644 --- a/src/vendor/mdbook/.travis.yml +++ b/src/vendor/mdbook/.travis.yml @@ -57,15 +57,6 @@ matrix: - os: linux env: TARGET=x86_64-unknown-linux-musl CHANNEL=nightly - # Musl builds fail due to a bug in Rust (https://github.com/azerupi/mdBook/issues/158) - allow_failures: - - os: linux - env: TARGET=x86_64-unknown-linux-musl CHANNEL=stable - - os: linux - env: TARGET=x86_64-unknown-linux-musl CHANNEL=beta - - os: linux - env: TARGET=x86_64-unknown-linux-musl CHANNEL=nightly - install: - export PATH="$PATH:$HOME/.cargo/bin" - bash ci/install.sh diff --git a/src/vendor/mdbook/CONTRIBUTING.md b/src/vendor/mdbook/CONTRIBUTING.md new file mode 100644 index 0000000000..015ff53dae --- /dev/null +++ b/src/vendor/mdbook/CONTRIBUTING.md @@ -0,0 +1,84 @@ +# Contributing + +Welcome stranger! + +If you have come here to learn how to contribute to mdBook, we have some tips for you! + +First of all, don't hesitate to ask questions! +Use the [issue tracker](https://github.com/azerupi/mdBook/issues), no question is too simple. +If we don't respond in a couple of days, ping us @azerupi, @steveklabnik, @frewsxcv it might just be that we forgot. :wink: + +### Issues to work on + +Any issue is up for the grabbing, but if you are starting out, you might be interested in the +[E-Easy issues](https://github.com/azerupi/mdBook/issues?q=is%3Aopen+is%3Aissue+label%3AE-Easy). +Those are issues that are considered more straightforward for beginners to Rust or the codebase itself. +These issues can be a good launching pad for more involved issues. Easy tasks for a first time contribution +include documentation improvements, new tests, examples, updating dependencies, etc. + +If you come from a web development background, you might be interested in issues related to web technologies tagged +[A-JavaScript](https://github.com/azerupi/mdBook/issues?q=is%3Aopen+is%3Aissue+label%3AA-JavaScript), +[A-Style](https://github.com/azerupi/mdBook/issues?q=is%3Aopen+is%3Aissue+label%3AA-Style), +[A-HTML](https://github.com/azerupi/mdBook/issues?q=is%3Aopen+is%3Aissue+label%3AA-HTML) or +[A-Mobile](https://github.com/azerupi/mdBook/issues?q=is%3Aopen+is%3Aissue+label%3AA-Mobile). + +When you decide you want to work on a specific issue, ping us on that issue so that we can assign it to you. +Again, do not hesitate to ask questions. We will gladly mentor anyone that want to tackle an issue. + +Issues on the issue tracker are categorized with the following labels: + +- **A**-prefixed labels state which area of the project an issue relates to. +- **E**-prefixed labels show an estimate of the experience necessary to fix the issue. +- **M**-prefixed labels are meta-issues used for questions, discussions, or tracking issues +- **S**-prefixed labels show the status of the issue +- **T**-prefixed labels show the type of issue + +### Building mdBook + +mdBook builds on stable Rust, if you want to build mdBook from source, here are the steps to follow: + +1. Navigate to the directory of your choice +0. Clone this repository with git. + + ``` + git clone https://github.com/azerupi/mdBook.git + ``` +0. Navigate into the newly created `mdBook` directory +0. Run `cargo build` + +The resulting binary can be found in `mdBook/target/debug/` under the name `mdBook` or `mdBook.exe`. + + +### Making changes to the style + +mdBook doesn't use CSS directly but uses [Stylus](http://stylus-lang.com/), a CSS-preprocessor which compiles to CSS. + +When you want to change the style, it is important to not change the CSS directly because any manual modification to +the CSS files will be overwritten when compiling the stylus files. Instead, you should make your changes directly in the +[stylus files](https://github.com/azerupi/mdBook/tree/master/src/theme/stylus) and regenerate the CSS. + +For this to work, you first need [Node and NPM](https://nodejs.org/en/) installed on your machine. +Then run the following inside of the mdBook directory: + +``` +npm install +``` + +When that finished, you can simply regenerate the CSS files by building mdBook with the following command: + +``` +cargo build --features=regenerate-css +``` + +This should automatically call the appropriate stylus command to recompile the files to CSS and include them in the project. + +### Making a pull-request + +When you feel comfortable that your changes could be integrated into mdBook, you can create a pull-request on GitHub. +One of the core maintainers will then approve the changes or request some changes before it gets merged. + +If you want to make your pull-request even better, you might want to run [Clippy](https://github.com/Manishearth/rust-clippy) +and [rustfmt](https://github.com/rust-lang-nursery/rustfmt) on the code first. +This is not a requirement though and will never block a pull-request from being merged. + +That's it, happy contributions! :tada: :tada: :tada: diff --git a/src/vendor/mdbook/Cargo.toml b/src/vendor/mdbook/Cargo.toml index a0b29ee906..8342326caa 100644 --- a/src/vendor/mdbook/Cargo.toml +++ b/src/vendor/mdbook/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mdbook" -version = "0.0.21" +version = "0.0.22" authors = ["Mathieu David "] description = "create books from markdown files (like Gitbook)" documentation = "http://azerupi.github.io/mdBook/index.html" @@ -15,14 +15,14 @@ exclude = [ ] [dependencies] -clap = "2.19.2" -handlebars = { version = "0.25.0", features = ["serde_type"] } -serde = "0.9" -serde_json = "0.9" -pulldown-cmark = "0.0.8" +clap = "2.24" +handlebars = "0.26" +serde = "1.0" +serde_json = "1.0" +pulldown-cmark = "0.0.14" log = "0.3" env_logger = "0.4.0" -toml = { version = "0.3", features = ["serde"] } +toml = { version = "0.4", features = ["serde"] } open = "1.1" regex = "0.2.1" @@ -34,7 +34,7 @@ crossbeam = { version = "0.2.8", optional = true } # Serve feature iron = { version = "0.5", optional = true } staticfile = { version = "0.4", optional = true } -ws = { version = "0.6", optional = true} +ws = { version = "0.7", optional = true} # Tests [dev-dependencies] diff --git a/src/vendor/mdbook/LICENSE b/src/vendor/mdbook/LICENSE index be2cc4dfb6..b5952f7d4e 100644 --- a/src/vendor/mdbook/LICENSE +++ b/src/vendor/mdbook/LICENSE @@ -1,362 +1,362 @@ -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. "Contributor" - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. "Contributor Version" - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the terms of - a Secondary License. - -1.6. "Executable Form" - - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - - means a work that combines Covered Software with other material, in a - separate file or files, that is not Covered Software. - -1.8. "License" - - means this document. - -1.9. "Licensable" - - means having the right to grant, to the maximum extent possible, whether - at the time of the initial grant or subsequently, any and all of the - rights conveyed by this License. - -1.10. "Modifications" - - means any of the following: - - a. any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. "Patent Claims" of a Contributor - - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the License, - by the making, using, selling, offering for sale, having made, import, - or transfer of either its Contributions or its Contributor Version. - -1.12. "Secondary License" - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. "Source Code Form" - - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, "control" means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution - become effective for each Contribution on the date the Contributor first - distributes such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under - this License. No additional rights or licenses will be implied from the - distribution or licensing of Covered Software under this License. - Notwithstanding Section 2.1(b) above, no patent license is granted by a - Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of - its Contributions. - - This License does not grant any rights in the trademarks, service marks, - or logos of any Contributor (except as may be necessary to comply with - the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this - License (see Section 10.2) or under the terms of a Secondary License (if - permitted under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its - Contributions are its original creation(s) or it has sufficient rights to - grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under - applicable copyright doctrines of fair use, fair dealing, or other - equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under - the terms of this License. You must inform recipients that the Source - Code Form of the Covered Software is governed by the terms of this - License, and how they can obtain a copy of this License. You may not - attempt to alter or restrict the recipients' rights in the Source Code - Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter the - recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for - the Covered Software. If the Larger Work is a combination of Covered - Software with a work governed by one or more Secondary Licenses, and the - Covered Software is not Incompatible With Secondary Licenses, this - License permits You to additionally distribute such Covered Software - under the terms of such Secondary License(s), so that the recipient of - the Larger Work may, at their option, further distribute the Covered - Software under the terms of either this License or such Secondary - License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices - (including copyright notices, patent notices, disclaimers of warranty, or - limitations of liability) contained within the Source Code Form of the - Covered Software, except that You may alter any license notices to the - extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on - behalf of any Contributor. You must make it absolutely clear that any - such warranty, support, indemnity, or liability obligation is offered by - You alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, - judicial order, or regulation then You must: (a) comply with the terms of - this License to the maximum extent possible; and (b) describe the - limitations and the code they affect. Such description must be placed in a - text file included with all distributions of the Covered Software under - this License. Except to the extent prohibited by statute or regulation, - such description must be sufficiently detailed for a recipient of ordinary - skill to be able to understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing - basis, if such Contributor fails to notify You of the non-compliance by - some reasonable means prior to 60 days after You have come back into - compliance. Moreover, Your grants from a particular Contributor are - reinstated on an ongoing basis if such Contributor notifies You of the - non-compliance by some reasonable means, this is the first time You have - received notice of non-compliance with this License from such - Contributor, and You become compliant prior to 30 days after Your receipt - of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, - counter-claims, and cross-claims) alleging that a Contributor Version - directly or indirectly infringes any patent, then the rights granted to - You by any and all Contributors for the Covered Software under Section - 2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an "as is" basis, - without warranty of any kind, either expressed, implied, or statutory, - including, without limitation, warranties that the Covered Software is free - of defects, merchantable, fit for a particular purpose or non-infringing. - The entire risk as to the quality and performance of the Covered Software - is with You. Should any Covered Software prove defective in any respect, - You (not any Contributor) assume the cost of any necessary servicing, - repair, or correction. This disclaimer of warranty constitutes an essential - part of this License. No use of any Covered Software is authorized under - this License except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from - such party's negligence to the extent applicable law prohibits such - limitation. Some jurisdictions do not allow the exclusion or limitation of - incidental or consequential damages, so this exclusion and limitation may - not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts - of a jurisdiction where the defendant maintains its principal place of - business and such litigation shall be governed by laws of that - jurisdiction, without reference to its conflict-of-law provisions. Nothing - in this Section shall prevent a party's ability to bring cross-claims or - counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. Any law or regulation which provides that - the language of a contract shall be construed against the drafter shall not - be used to construe this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version - of the License under which You originally received the Covered Software, - or under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a - modified version of this License if you rename the license and remove - any references to the name of the license steward (except to note that - such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary - Licenses If You choose to distribute Source Code Form that is - Incompatible With Secondary Licenses under the terms of this version of - the License, the notice described in Exhibit B of this License must be - attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, -then You may include the notice in a location (such as a LICENSE file in a -relevant directory) where a recipient would be likely to look for such a -notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice - - This Source Code Form is "Incompatible - With Secondary Licenses", as defined by - the Mozilla Public License, v. 2.0. +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. "Contributor" + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. "Contributor Version" + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the terms of + a Secondary License. + +1.6. "Executable Form" + + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + + means a work that combines Covered Software with other material, in a + separate file or files, that is not Covered Software. + +1.8. "License" + + means this document. + +1.9. "Licensable" + + means having the right to grant, to the maximum extent possible, whether + at the time of the initial grant or subsequently, any and all of the + rights conveyed by this License. + +1.10. "Modifications" + + means any of the following: + + a. any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. "Patent Claims" of a Contributor + + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the License, + by the making, using, selling, offering for sale, having made, import, + or transfer of either its Contributions or its Contributor Version. + +1.12. "Secondary License" + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. "Source Code Form" + + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, "control" means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution + become effective for each Contribution on the date the Contributor first + distributes such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under + this License. No additional rights or licenses will be implied from the + distribution or licensing of Covered Software under this License. + Notwithstanding Section 2.1(b) above, no patent license is granted by a + Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of + its Contributions. + + This License does not grant any rights in the trademarks, service marks, + or logos of any Contributor (except as may be necessary to comply with + the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this + License (see Section 10.2) or under the terms of a Secondary License (if + permitted under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its + Contributions are its original creation(s) or it has sufficient rights to + grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under + applicable copyright doctrines of fair use, fair dealing, or other + equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under + the terms of this License. You must inform recipients that the Source + Code Form of the Covered Software is governed by the terms of this + License, and how they can obtain a copy of this License. You may not + attempt to alter or restrict the recipients' rights in the Source Code + Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter the + recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for + the Covered Software. If the Larger Work is a combination of Covered + Software with a work governed by one or more Secondary Licenses, and the + Covered Software is not Incompatible With Secondary Licenses, this + License permits You to additionally distribute such Covered Software + under the terms of such Secondary License(s), so that the recipient of + the Larger Work may, at their option, further distribute the Covered + Software under the terms of either this License or such Secondary + License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices + (including copyright notices, patent notices, disclaimers of warranty, or + limitations of liability) contained within the Source Code Form of the + Covered Software, except that You may alter any license notices to the + extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on + behalf of any Contributor. You must make it absolutely clear that any + such warranty, support, indemnity, or liability obligation is offered by + You alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, + judicial order, or regulation then You must: (a) comply with the terms of + this License to the maximum extent possible; and (b) describe the + limitations and the code they affect. Such description must be placed in a + text file included with all distributions of the Covered Software under + this License. Except to the extent prohibited by statute or regulation, + such description must be sufficiently detailed for a recipient of ordinary + skill to be able to understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing + basis, if such Contributor fails to notify You of the non-compliance by + some reasonable means prior to 60 days after You have come back into + compliance. Moreover, Your grants from a particular Contributor are + reinstated on an ongoing basis if such Contributor notifies You of the + non-compliance by some reasonable means, this is the first time You have + received notice of non-compliance with this License from such + Contributor, and You become compliant prior to 30 days after Your receipt + of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, + counter-claims, and cross-claims) alleging that a Contributor Version + directly or indirectly infringes any patent, then the rights granted to + You by any and all Contributors for the Covered Software under Section + 2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an "as is" basis, + without warranty of any kind, either expressed, implied, or statutory, + including, without limitation, warranties that the Covered Software is free + of defects, merchantable, fit for a particular purpose or non-infringing. + The entire risk as to the quality and performance of the Covered Software + is with You. Should any Covered Software prove defective in any respect, + You (not any Contributor) assume the cost of any necessary servicing, + repair, or correction. This disclaimer of warranty constitutes an essential + part of this License. No use of any Covered Software is authorized under + this License except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from + such party's negligence to the extent applicable law prohibits such + limitation. Some jurisdictions do not allow the exclusion or limitation of + incidental or consequential damages, so this exclusion and limitation may + not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts + of a jurisdiction where the defendant maintains its principal place of + business and such litigation shall be governed by laws of that + jurisdiction, without reference to its conflict-of-law provisions. Nothing + in this Section shall prevent a party's ability to bring cross-claims or + counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. Any law or regulation which provides that + the language of a contract shall be construed against the drafter shall not + be used to construe this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version + of the License under which You originally received the Covered Software, + or under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a + modified version of this License if you rename the license and remove + any references to the name of the license steward (except to note that + such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary + Licenses If You choose to distribute Source Code Form that is + Incompatible With Secondary Licenses under the terms of this version of + the License, the notice described in Exhibit B of this License must be + attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, +then You may include the notice in a location (such as a LICENSE file in a +relevant directory) where a recipient would be likely to look for such a +notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice + + This Source Code Form is "Incompatible + With Secondary Licenses", as defined by + the Mozilla Public License, v. 2.0. diff --git a/src/vendor/mdbook/README.md b/src/vendor/mdbook/README.md index 55e18f483a..679e4c66a1 100644 --- a/src/vendor/mdbook/README.md +++ b/src/vendor/mdbook/README.md @@ -23,9 +23,6 @@ mdBook is a utility to create modern online books from Markdown files. -**This project is still evolving.** -See [#90](https://github.com/azerupi/mdBook/issues/90) - ## What does it look like? @@ -114,13 +111,11 @@ See the [Documentation](http://azerupi.github.io/mdBook/lib/lib.html) and the [A Contributions are highly appreciated and encouraged! Don't hesitate to participate to discussions in the issues, propose new features and ask for help. -If you are not very confident with Rust, **I will be glad to mentor as best as I can if you decide to tackle an issue or new feature.** - -People who are not familiar with the code can look at [issues that are tagged **easy**](https://github.com/azerupi/mdBook/labels/Easy). A lot of issues are also related to web development, so people that are not comfortable with Rust can also participate! :wink: +If you are just starting out with Rust, there are a series of issus that are tagged [E-Easy](https://github.com/azerupi/mdBook/issues?q=is%3Aopen+is%3Aissue+label%3AE-Easy) and **we will gladly mentor you** so that you can successfully go through the process of fixing a bug or adding a new feature! Let us know if you need any help. -You can pick any issue you want to work on. Usually it's a good idea to ask if someone is already working on it and if not to claim the issue. +For more info about contributing, check out our [contribution guide](CONTRIBUTING.md) who helps you go through the build and contribution process! ## License -All the code is released under the ***Mozilla Public License v2.0***, for more information take a look at the [LICENSE](LICENSE) file. +All the code in this repository is released under the ***Mozilla Public License v2.0***, for more information take a look at the [LICENSE](LICENSE) file. diff --git a/src/vendor/mdbook/appveyor.yml b/src/vendor/mdbook/appveyor.yml index 87da24ce2a..6de34ec5ed 100644 --- a/src/vendor/mdbook/appveyor.yml +++ b/src/vendor/mdbook/appveyor.yml @@ -1,60 +1,60 @@ -environment: - global: - PROJECT_NAME: mdBook - matrix: - # Stable channel - - TARGET: i686-pc-windows-msvc - RUST_CHANNEL: stable - - TARGET: x86_64-pc-windows-msvc - RUST_CHANNEL: stable - # Beta channel - - TARGET: i686-pc-windows-msvc - RUST_CHANNEL: beta - - TARGET: x86_64-pc-windows-msvc - RUST_CHANNEL: beta - # Nightly channel - - TARGET: i686-pc-windows-msvc - RUST_CHANNEL: nightly - - TARGET: x86_64-pc-windows-msvc - RUST_CHANNEL: nightly - -# Install Rust and Cargo -install: - - ps: Start-FileDownload "https://static.rust-lang.org/dist/channel-rust-stable" - - ps: $env:RUST_VERSION = Get-Content channel-rust-stable | select -first 1 | %{$_.split('-')[1]} - - if NOT "%RUST_CHANNEL%" == "stable" set RUST_VERSION=%RUST_CHANNEL% - - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-${env:RUST_VERSION}-${env:TARGET}.exe" - - rust-%RUST_VERSION%-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" - - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin - - rustc -V - - cargo -V - -build: false - -# Equivalent to Travis' `script` phase -test_script: - - cargo build --verbose - - cargo test --verbose - -before_deploy: - # Generate artifacts for release - - cargo build --release - - mkdir staging - - copy target\release\mdbook.exe staging - - cd staging - - 7z a ../%PROJECT_NAME%-%APPVEYOR_REPO_TAG_NAME%-%TARGET%.zip * - - appveyor PushArtifact ../%PROJECT_NAME%-%APPVEYOR_REPO_TAG_NAME%-%TARGET%.zip - -deploy: - description: 'Windows release' - artifact: /.*\.zip/ - auth_token: - secure: QQhjKVyz7mpjlyGhlXytbFQQfKFQWTahHkD+B0NzIUoEVqO7ZLWjnoWasvLqW4nE - provider: GitHub - on: - RUST_CHANNEL: stable - appveyor_repo_tag: true - -branches: - only: - - master +environment: + global: + PROJECT_NAME: mdBook + matrix: + # Stable channel + - TARGET: i686-pc-windows-msvc + RUST_CHANNEL: stable + - TARGET: x86_64-pc-windows-msvc + RUST_CHANNEL: stable + # Beta channel + - TARGET: i686-pc-windows-msvc + RUST_CHANNEL: beta + - TARGET: x86_64-pc-windows-msvc + RUST_CHANNEL: beta + # Nightly channel + - TARGET: i686-pc-windows-msvc + RUST_CHANNEL: nightly + - TARGET: x86_64-pc-windows-msvc + RUST_CHANNEL: nightly + +# Install Rust and Cargo +install: + - ps: Start-FileDownload "https://static.rust-lang.org/dist/channel-rust-stable" + - ps: $env:RUST_VERSION = Get-Content channel-rust-stable | select -first 1 | %{$_.split('-')[1]} + - if NOT "%RUST_CHANNEL%" == "stable" set RUST_VERSION=%RUST_CHANNEL% + - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-${env:RUST_VERSION}-${env:TARGET}.exe" + - rust-%RUST_VERSION%-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" + - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin + - rustc -V + - cargo -V + +build: false + +# Equivalent to Travis' `script` phase +test_script: + - cargo build --verbose + - cargo test --verbose + +before_deploy: + # Generate artifacts for release + - cargo build --release + - mkdir staging + - copy target\release\mdbook.exe staging + - cd staging + - 7z a ../%PROJECT_NAME%-%APPVEYOR_REPO_TAG_NAME%-%TARGET%.zip * + - appveyor PushArtifact ../%PROJECT_NAME%-%APPVEYOR_REPO_TAG_NAME%-%TARGET%.zip + +deploy: + description: 'Windows release' + artifact: /.*\.zip/ + auth_token: + secure: QQhjKVyz7mpjlyGhlXytbFQQfKFQWTahHkD+B0NzIUoEVqO7ZLWjnoWasvLqW4nE + provider: GitHub + on: + RUST_CHANNEL: stable + appveyor_repo_tag: true + +branches: + only: + - master diff --git a/src/vendor/mdbook/build.rs b/src/vendor/mdbook/build.rs index d3177444da..25884ef3d3 100644 --- a/src/vendor/mdbook/build.rs +++ b/src/vendor/mdbook/build.rs @@ -20,7 +20,8 @@ fn main() { .arg(format!("{}", theme_dir.to_str().unwrap())) .arg("--use") .arg("nib") - .status().unwrap() + .status() + .unwrap() .success() { panic!("Stylus encoutered an error"); } diff --git a/src/vendor/mdbook/ci/before_deploy.sh b/src/vendor/mdbook/ci/before_deploy.sh index 9fa9ab1b4c..ce1eacdbc8 100644 --- a/src/vendor/mdbook/ci/before_deploy.sh +++ b/src/vendor/mdbook/ci/before_deploy.sh @@ -1,32 +1,32 @@ -# `before_deploy` phase: here we package the build artifacts - -set -ex - -mktempd() { - echo $(mktemp -d 2>/dev/null || mktemp -d -t tmp) -} - -mk_artifacts() { - cargo build --target $TARGET --release -} - -mk_tarball() { - local td=$(mktempd) - local out_dir=$(pwd) - - cp target/$TARGET/release/mdbook $td - - pushd $td - - tar czf $out_dir/${PROJECT_NAME}-${TRAVIS_TAG}-${TARGET}.tar.gz * - - popd $td - rm -r $td -} - -main() { - mk_artifacts - mk_tarball -} - -main +# `before_deploy` phase: here we package the build artifacts + +set -ex + +mktempd() { + echo $(mktemp -d 2>/dev/null || mktemp -d -t tmp) +} + +mk_artifacts() { + cargo build --target $TARGET --release +} + +mk_tarball() { + local td=$(mktempd) + local out_dir=$(pwd) + + cp target/$TARGET/release/mdbook $td + + pushd $td + + tar czf $out_dir/${PROJECT_NAME}-${TRAVIS_TAG}-${TARGET}.tar.gz * + + popd $td + rm -r $td +} + +main() { + mk_artifacts + mk_tarball +} + +main diff --git a/src/vendor/mdbook/ci/install.sh b/src/vendor/mdbook/ci/install.sh index 1b51cec785..a86833d8dc 100644 --- a/src/vendor/mdbook/ci/install.sh +++ b/src/vendor/mdbook/ci/install.sh @@ -1,58 +1,58 @@ -# `install` phase: install stuff needed for the `script` phase - -set -ex - -case "$TRAVIS_OS_NAME" in - linux) - host=x86_64-unknown-linux-gnu - ;; - osx) - host=x86_64-apple-darwin - ;; -esac - -mktempd() { - echo $(mktemp -d 2>/dev/null || mktemp -d -t tmp) -} - -install_rustup() { - local td=$(mktempd) - - pushd $td - curl -O https://static.rust-lang.org/rustup/dist/$host/rustup-setup - chmod +x rustup-setup - ./rustup-setup -y - popd - - rm -r $td - - rustup default $CHANNEL - rustc -V - cargo -V -} - -install_standard_crates() { - if [ "$host" != "$TARGET" ]; then - if [ ! "$CHANNEL" = "stable" ]; then - rustup target add $TARGET - else - local version=$(rustc -V | cut -d' ' -f2) - local tarball=rust-std-${version}-${TARGET} - - local td=$(mktempd) - curl -s https://static.rust-lang.org/dist/${tarball}.tar.gz | \ - tar --strip-components 1 -C $td -xz - - $td/install.sh --prefix=$(rustc --print sysroot) - - rm -r $td - fi - fi -} - -main() { - install_rustup - install_standard_crates -} - -main +# `install` phase: install stuff needed for the `script` phase + +set -ex + +case "$TRAVIS_OS_NAME" in + linux) + host=x86_64-unknown-linux-gnu + ;; + osx) + host=x86_64-apple-darwin + ;; +esac + +mktempd() { + echo $(mktemp -d 2>/dev/null || mktemp -d -t tmp) +} + +install_rustup() { + local td=$(mktempd) + + pushd $td + curl -O https://static.rust-lang.org/rustup/dist/$host/rustup-setup + chmod +x rustup-setup + ./rustup-setup -y + popd + + rm -r $td + + rustup default $CHANNEL + rustc -V + cargo -V +} + +install_standard_crates() { + if [ "$host" != "$TARGET" ]; then + if [ ! "$CHANNEL" = "stable" ]; then + rustup target add $TARGET + else + local version=$(rustc -V | cut -d' ' -f2) + local tarball=rust-std-${version}-${TARGET} + + local td=$(mktempd) + curl -s https://static.rust-lang.org/dist/${tarball}.tar.gz | \ + tar --strip-components 1 -C $td -xz + + $td/install.sh --prefix=$(rustc --print sysroot) + + rm -r $td + fi + fi +} + +main() { + install_rustup + install_standard_crates +} + +main diff --git a/src/vendor/mdbook/ci/script.sh b/src/vendor/mdbook/ci/script.sh index 9504ae8fae..771130ce52 100644 --- a/src/vendor/mdbook/ci/script.sh +++ b/src/vendor/mdbook/ci/script.sh @@ -1,45 +1,45 @@ -# `script` phase: you usually build, test and generate docs in this phase - -set -ex - -# NOTE Workaround for rust-lang/rust#31907 - disable doc tests when cross compiling -# This has been fixed in the nightly channel but it would take a while to reach the other channels -disable_cross_doctests() { - local host - case "$TRAVIS_OS_NAME" in - linux) - host=x86_64-unknown-linux-gnu - ;; - osx) - host=x86_64-apple-darwin - ;; - esac - - if [ "$host" != "$TARGET" ] && [ "$CHANNEL" != "nightly" ]; then - if [ "$TRAVIS_OS_NAME" = "osx" ]; then - brew install gnu-sed --default-names - fi - - find src -name '*.rs' -type f | xargs sed -i -e 's:\(//.\s*```\):\1 ignore,:g' - fi -} - -run_test_suite() { - # Extra test without default features to avoid bitrot. We only test on a single target (but with - # all the channels) to avoid significantly increasing the build times - if [ $TARGET = x86_64-unknown-linux-gnu ]; then - cargo build --target $TARGET --no-default-features --verbose - cargo test --target $TARGET --no-default-features --verbose - cargo clean - fi - - cargo build --target $TARGET --verbose - cargo test --target $TARGET --verbose -} - -main() { - disable_cross_doctests - run_test_suite -} - -main +# `script` phase: you usually build, test and generate docs in this phase + +set -ex + +# NOTE Workaround for rust-lang/rust#31907 - disable doc tests when cross compiling +# This has been fixed in the nightly channel but it would take a while to reach the other channels +disable_cross_doctests() { + local host + case "$TRAVIS_OS_NAME" in + linux) + host=x86_64-unknown-linux-gnu + ;; + osx) + host=x86_64-apple-darwin + ;; + esac + + if [ "$host" != "$TARGET" ] && [ "$CHANNEL" != "nightly" ]; then + if [ "$TRAVIS_OS_NAME" = "osx" ]; then + brew install gnu-sed --default-names + fi + + find src -name '*.rs' -type f | xargs sed -i -e 's:\(//.\s*```\):\1 ignore,:g' + fi +} + +run_test_suite() { + # Extra test without default features to avoid bitrot. We only test on a single target (but with + # all the channels) to avoid significantly increasing the build times + if [ $TARGET = x86_64-unknown-linux-gnu ]; then + cargo build --target $TARGET --no-default-features --verbose + cargo test --target $TARGET --no-default-features --verbose + cargo clean + fi + + cargo build --target $TARGET --verbose + cargo test --target $TARGET --verbose +} + +main() { + disable_cross_doctests + run_test_suite +} + +main diff --git a/src/vendor/mdbook/deploy.sh b/src/vendor/mdbook/deploy.sh index 84c5fb36d4..5162951feb 100644 --- a/src/vendor/mdbook/deploy.sh +++ b/src/vendor/mdbook/deploy.sh @@ -1,42 +1,42 @@ -#!/bin/bash - -# Exit on error or variable unset -set -o errexit -o nounset - -NC='\033[39m' -CYAN='\033[36m' -GREEN='\033[32m' - -rev=$(git rev-parse --short HEAD) - -echo -e "${CYAN}Running cargo doc${NC}" -# Run cargo doc -cargo doc - -echo -e "${CYAN}Running mdbook build${NC}" -# Run mdbook to generate the book -target/"$TARGET"/debug/mdbook build book-example/ - -echo -e "${CYAN}Copying book to target/doc${NC}" -# Copy files from rendered book to doc root -cp -R book-example/book/* target/doc/ - -cd target/doc - -echo -e "${CYAN}Initializing Git${NC}" -git init -git config user.name "Mathieu David" -git config user.email "mathieudavid@mathieudavid.org" - -git remote add upstream "https://$GH_TOKEN@github.com/azerupi/mdBook.git" -git fetch upstream -git reset upstream/gh-pages - -touch . - -echo -e "${CYAN}Pushing changes to gh-pages${NC}" -git add -A . -git commit -m "rebuild pages at ${rev}" -git push -q upstream HEAD:gh-pages - -echo -e "${GREEN}Deployement done${NC}" +#!/bin/bash + +# Exit on error or variable unset +set -o errexit -o nounset + +NC='\033[39m' +CYAN='\033[36m' +GREEN='\033[32m' + +rev=$(git rev-parse --short HEAD) + +echo -e "${CYAN}Running cargo doc${NC}" +# Run cargo doc +cargo doc + +echo -e "${CYAN}Running mdbook build${NC}" +# Run mdbook to generate the book +target/"$TARGET"/debug/mdbook build book-example/ + +echo -e "${CYAN}Copying book to target/doc${NC}" +# Copy files from rendered book to doc root +cp -R book-example/book/* target/doc/ + +cd target/doc + +echo -e "${CYAN}Initializing Git${NC}" +git init +git config user.name "Mathieu David" +git config user.email "mathieudavid@mathieudavid.org" + +git remote add upstream "https://$GH_TOKEN@github.com/azerupi/mdBook.git" +git fetch upstream +git reset upstream/gh-pages + +touch . + +echo -e "${CYAN}Pushing changes to gh-pages${NC}" +git add -A . +git commit -m "rebuild pages at ${rev}" +git push -q upstream HEAD:gh-pages + +echo -e "${GREEN}Deployement done${NC}" diff --git a/src/vendor/mdbook/rustfmt.toml b/src/vendor/mdbook/rustfmt.toml index 78db360bdd..5ac9fa5632 100644 --- a/src/vendor/mdbook/rustfmt.toml +++ b/src/vendor/mdbook/rustfmt.toml @@ -10,6 +10,7 @@ enum_trailing_comma = true match_block_trailing_comma = true struct_trailing_comma = "Always" wrap_comments = true +use_try_shorthand = true report_todo = "Always" report_fixme = "Always" diff --git a/src/vendor/mdbook/src/bin/mdbook.rs b/src/vendor/mdbook/src/bin/mdbook.rs index 3af3ada4ad..0b931457cf 100644 --- a/src/vendor/mdbook/src/bin/mdbook.rs +++ b/src/vendor/mdbook/src/bin/mdbook.rs @@ -121,7 +121,7 @@ fn init(args: &ArgMatches) -> Result<(), Box> { let mut book = MDBook::new(&book_dir); // Call the function that does the initialization - try!(book.init()); + book.init()?; // If flag `--theme` is present, copy theme to src if args.is_present("theme") { @@ -142,7 +142,7 @@ fn init(args: &ArgMatches) -> Result<(), Box> { } // Call the function that copies the theme - try!(book.copy_theme()); + book.copy_theme()?; println!("\nTheme copied."); } @@ -172,14 +172,14 @@ fn build(args: &ArgMatches) -> Result<(), Box> { let mut book = match args.value_of("dest-dir") { Some(dest_dir) => book.set_dest(Path::new(dest_dir)), - None => book + None => book, }; if args.is_present("no-create") { book.create_missing = false; } - try!(book.build()); + book.build()?; if args.is_present("open") { open(book.get_dest().join("index.html")); @@ -197,11 +197,11 @@ fn watch(args: &ArgMatches) -> Result<(), Box> { let mut book = match args.value_of("dest-dir") { Some(dest_dir) => book.set_dest(Path::new(dest_dir)), - None => book + None => book, }; if args.is_present("open") { - try!(book.build()); + book.build()?; open(book.get_dest().join("index.html")); } @@ -227,7 +227,7 @@ fn serve(args: &ArgMatches) -> Result<(), Box> { let mut book = match args.value_of("dest-dir") { Some(dest_dir) => book.set_dest(Path::new(dest_dir)), - None => book + None => book, }; let port = args.value_of("port").unwrap_or("3000"); @@ -253,25 +253,22 @@ fn serve(args: &ArgMatches) -> Result<(), Box> { socket.close(); }} - "#, public_address, ws_port, RELOAD_COMMAND).to_owned()); + "#, + public_address, + ws_port, + RELOAD_COMMAND)); - try!(book.build()); + book.build()?; let staticfile = staticfile::Static::new(book.get_dest()); let iron = iron::Iron::new(staticfile); let _iron = iron.http(&*address).unwrap(); - let ws_server = ws::WebSocket::new(|_| { - |_| { - Ok(()) - } - }).unwrap(); + let ws_server = ws::WebSocket::new(|_| |_| Ok(())).unwrap(); let broadcaster = ws_server.broadcaster(); - std::thread::spawn(move || { - ws_server.listen(&*ws_address).unwrap(); - }); + std::thread::spawn(move || { ws_server.listen(&*ws_address).unwrap(); }); println!("\nServing on {}", address); @@ -296,7 +293,7 @@ fn test(args: &ArgMatches) -> Result<(), Box> { let book_dir = get_book_dir(args); let mut book = MDBook::new(&book_dir).read_config(); - try!(book.test()); + book.test()?; Ok(()) } @@ -339,7 +336,7 @@ fn trigger_on_change(book: &mut MDBook, closure: F) -> () Err(e) => { println!("Error while trying to watch the files:\n\n\t{:?}", e); ::std::process::exit(0); - } + }, }; // Add the source directory to the watcher @@ -350,10 +347,14 @@ fn trigger_on_change(book: &mut MDBook, closure: F) -> () // Add the book.{json,toml} file to the watcher if it exists, because it's not // located in the source directory - if watcher.watch(book.get_root().join("book.json"), NonRecursive).is_err() { + if watcher + .watch(book.get_root().join("book.json"), NonRecursive) + .is_err() { // do nothing if book.json is not found } - if watcher.watch(book.get_root().join("book.toml"), NonRecursive).is_err() { + if watcher + .watch(book.get_root().join("book.toml"), NonRecursive) + .is_err() { // do nothing if book.toml is not found } @@ -361,16 +362,18 @@ fn trigger_on_change(book: &mut MDBook, closure: F) -> () loop { match rx.recv() { - Ok(event) => match event { - NoticeWrite(path) | - NoticeRemove(path) | - Create(path) | - Write(path) | - Remove(path) | - Rename(_, path) => { - closure(&path, book); + Ok(event) => { + match event { + NoticeWrite(path) | + NoticeRemove(path) | + Create(path) | + Write(path) | + Remove(path) | + Rename(_, path) => { + closure(&path, book); + }, + _ => {}, } - _ => {} }, Err(e) => { println!("An error occured: {:?}", e); diff --git a/src/vendor/mdbook/src/book/bookconfig.rs b/src/vendor/mdbook/src/book/bookconfig.rs index 53544eb07f..ac1f06054e 100644 --- a/src/vendor/mdbook/src/book/bookconfig.rs +++ b/src/vendor/mdbook/src/book/bookconfig.rs @@ -21,6 +21,7 @@ pub struct BookConfig { pub indent_spaces: i32, multilingual: bool, + pub google_analytics: Option, } impl BookConfig { @@ -37,6 +38,7 @@ impl BookConfig { indent_spaces: 4, // indentation used for SUMMARY.md multilingual: false, + google_analytics: None, } } @@ -51,7 +53,7 @@ impl BookConfig { Err(_) => { error!("[*]: Failed to open {:?}", &path); exit(2); - } + }, }; if f.read_to_string(&mut data).is_err() { error!("[*]: Failed to read {:?}", &path); @@ -83,11 +85,11 @@ impl BookConfig { pub fn parse_from_toml_string(&mut self, data: &str) -> &mut Self { let config = match toml::from_str(data) { - Ok(x) => {x}, + Ok(x) => x, Err(e) => { error!("[*]: Toml parse errors in book.toml: {:?}", e); exit(2); - } + }, }; self.parse_from_btreemap(&config); @@ -95,7 +97,8 @@ impl BookConfig { self } - /// Parses the string to JSON and converts it to BTreeMap. + /// Parses the string to JSON and converts it + /// to BTreeMap. pub fn parse_from_json_string(&mut self, data: &str) -> &mut Self { let c: serde_json::Value = match serde_json::from_str(data) { @@ -103,7 +106,7 @@ impl BookConfig { Err(e) => { error!("[*]: JSON parse errors in book.json: {:?}", e); exit(2); - } + }, }; let config = json_object_to_btreemap(c.as_object().unwrap()); @@ -154,6 +157,11 @@ impl BookConfig { self.set_theme_path(&theme_path); } + // Google analytics code + if let Some(id) = config.get("google_analytics_id") { + self.google_analytics = Some(id.to_string().replace("\"", "")); + } + self } @@ -198,10 +206,7 @@ pub fn json_object_to_btreemap(json: &serde_json::Map let mut config: BTreeMap = BTreeMap::new(); for (key, value) in json.iter() { - config.insert( - String::from_str(key).unwrap(), - json_value_to_toml_value(value.to_owned()) - ); + config.insert(String::from_str(key).unwrap(), json_value_to_toml_value(value.to_owned())); } config @@ -216,10 +221,10 @@ pub fn json_value_to_toml_value(json: serde_json::Value) -> toml::Value { serde_json::Value::Number(x) => toml::Value::Float(x.as_f64().unwrap()), serde_json::Value::String(x) => toml::Value::String(x), serde_json::Value::Array(x) => { - toml::Value::Array(x.iter().map(|v| json_value_to_toml_value(v.to_owned())).collect()) - }, - serde_json::Value::Object(x) => { - toml::Value::Table(json_object_to_btreemap(&x)) + toml::Value::Array(x.iter() + .map(|v| json_value_to_toml_value(v.to_owned())) + .collect()) }, + serde_json::Value::Object(x) => toml::Value::Table(json_object_to_btreemap(&x)), } } diff --git a/src/vendor/mdbook/src/book/bookconfig_test.rs b/src/vendor/mdbook/src/book/bookconfig_test.rs index 61cfa6a985..b3a24385e7 100644 --- a/src/vendor/mdbook/src/book/bookconfig_test.rs +++ b/src/vendor/mdbook/src/book/bookconfig_test.rs @@ -347,3 +347,25 @@ fn it_parses_json_arrays_to_toml() { assert_eq!(format!("{:#?}", result), expected); } + +#[test] +fn it_fetches_google_analytics_from_toml() { + let text = r#" +title = "mdBook Documentation" +description = "Create book from markdown files. Like Gitbook but implemented in Rust" +author = "Mathieu David" +google_analytics_id = "123456" +"#; + + let mut config = BookConfig::new(Path::new(".")); + + config.parse_from_toml_string(&text.to_string()); + + let mut expected = BookConfig::new(Path::new(".")); + expected.title = "mdBook Documentation".to_string(); + expected.author = "Mathieu David".to_string(); + expected.description = "Create book from markdown files. Like Gitbook but implemented in Rust".to_string(); + expected.google_analytics = Some("123456".to_string()); + + assert_eq!(format!("{:#?}", config), format!("{:#?}", expected)); +} diff --git a/src/vendor/mdbook/src/book/bookitem.rs b/src/vendor/mdbook/src/book/bookitem.rs index 51773371d1..e3e4022596 100644 --- a/src/vendor/mdbook/src/book/bookitem.rs +++ b/src/vendor/mdbook/src/book/bookitem.rs @@ -37,10 +37,12 @@ impl Chapter { impl Serialize for Chapter { - fn serialize(&self, serializer: S) -> Result where S: Serializer { - let mut struct_ = try!(serializer.serialize_struct("Chapter", 2)); - try!(struct_.serialize_field("name", &self.name)); - try!(struct_.serialize_field("path", &self.path)); + fn serialize(&self, serializer: S) -> Result + where S: Serializer + { + let mut struct_ = serializer.serialize_struct("Chapter", 2)?; + struct_.serialize_field("name", &self.name)?; + struct_.serialize_field("path", &self.path)?; struct_.end() } } @@ -66,7 +68,8 @@ impl<'a> Iterator for BookItems<'a> { let cur = &self.items[self.current_index]; match *cur { - BookItem::Chapter(_, ref ch) | BookItem::Affix(ref ch) => { + BookItem::Chapter(_, ref ch) | + BookItem::Affix(ref ch) => { self.stack.push((self.items, self.current_index)); self.items = &ch.sub_items[..]; self.current_index = 0; diff --git a/src/vendor/mdbook/src/book/mod.rs b/src/vendor/mdbook/src/book/mod.rs index 85d20a7918..0a0e1099a7 100644 --- a/src/vendor/mdbook/src/book/mod.rs +++ b/src/vendor/mdbook/src/book/mod.rs @@ -36,6 +36,8 @@ pub struct MDBook { /// Should `mdbook build` create files referenced from SUMMARY.md if they /// don't exist pub create_missing: bool, + + pub google_analytics: Option, } impl MDBook { @@ -52,8 +54,10 @@ impl MDBook { /// # } /// ``` /// - /// In this example, `root_dir` will be the root directory of our book and is specified in function - /// of the current working directory by using a relative path instead of an absolute path. + /// In this example, `root_dir` will be the root directory of our book + /// and is specified in function of the current working directory + /// by using a relative path instead of an + /// absolute path. /// /// Default directory paths: /// @@ -61,7 +65,8 @@ impl MDBook { /// - output: `root/book` /// - theme: `root/theme` /// - /// They can both be changed by using [`set_src()`](#method.set_src) and [`set_dest()`](#method.set_dest) + /// They can both be changed by using [`set_src()`](#method.set_src) and + /// [`set_dest()`](#method.set_dest) pub fn new(root: &Path) -> MDBook { @@ -84,10 +89,12 @@ impl MDBook { livereload: None, create_missing: true, + google_analytics: None, } } - /// Returns a flat depth-first iterator over the elements of the book, it returns an [BookItem enum](bookitem.html): + /// Returns a flat depth-first iterator over the elements of the book, + /// it returns an [BookItem enum](bookitem.html): /// `(section: String, bookitem: &BookItem)` /// /// ```no_run @@ -123,7 +130,8 @@ impl MDBook { } } - /// `init()` creates some boilerplate files and directories to get you started with your book. + /// `init()` creates some boilerplate files and directories + /// to get you started with your book. /// /// ```text /// book-test/ @@ -133,7 +141,8 @@ impl MDBook { /// └── SUMMARY.md /// ``` /// - /// It uses the paths given as source and output directories and adds a `SUMMARY.md` and a + /// It uses the paths given as source and output directories + /// and adds a `SUMMARY.md` and a /// `chapter_1.md` to the source directory. pub fn init(&mut self) -> Result<(), Box> { @@ -149,12 +158,12 @@ impl MDBook { if !self.dest.exists() { debug!("[*]: {:?} does not exist, trying to create directory", self.dest); - try!(fs::create_dir_all(&self.dest)); + fs::create_dir_all(&self.dest)?; } if !self.src.exists() { debug!("[*]: {:?} does not exist, trying to create directory", self.src); - try!(fs::create_dir_all(&self.src)); + fs::create_dir_all(&self.src)?; } let summary = self.src.join("SUMMARY.md"); @@ -164,18 +173,18 @@ impl MDBook { // Summary does not exist, create it debug!("[*]: {:?} does not exist, trying to create SUMMARY.md", self.src.join("SUMMARY.md")); - let mut f = try!(File::create(&self.src.join("SUMMARY.md"))); + let mut f = File::create(&self.src.join("SUMMARY.md"))?; debug!("[*]: Writing to SUMMARY.md"); - try!(writeln!(f, "# Summary")); - try!(writeln!(f, "")); - try!(writeln!(f, "- [Chapter 1](./chapter_1.md)")); + writeln!(f, "# Summary")?; + writeln!(f, "")?; + writeln!(f, "- [Chapter 1](./chapter_1.md)")?; } } // parse SUMMARY.md, and create the missing item related file - try!(self.parse_summary()); + self.parse_summary()?; debug!("[*]: constructing paths for missing files"); for item in self.iter() { @@ -190,16 +199,15 @@ impl MDBook { if !path.exists() { if !self.create_missing { - return Err(format!( - "'{}' referenced from SUMMARY.md does not exist.", - path.to_string_lossy()).into()); + return Err(format!("'{}' referenced from SUMMARY.md does not exist.", path.to_string_lossy()) + .into()); } debug!("[*]: {:?} does not exist, trying to create file", path); - try!(::std::fs::create_dir_all(path.parent().unwrap())); - let mut f = try!(File::create(path)); + ::std::fs::create_dir_all(path.parent().unwrap())?; + let mut f = File::create(path)?; // debug!("[*]: Writing to {:?}", path); - try!(writeln!(f, "# {}", ch.name)); + writeln!(f, "# {}", ch.name)?; } } } @@ -214,17 +222,19 @@ impl MDBook { if !gitignore.exists() { // Gitignore does not exist, create it - // Because of `src/book/mdbook.rs#L37-L39`, `dest` will always start with `root`. If it - // is not, `strip_prefix` will return an Error. + // Because of `src/book/mdbook.rs#L37-L39`, + // `dest` will always start with `root`. + // If it is not, `strip_prefix` will return an Error. if !self.get_dest().starts_with(&self.root) { return; } let relative = self.get_dest() - .strip_prefix(&self.root) - .expect("Destination is not relative to root."); - let relative = relative.to_str() - .expect("Path could not be yielded into a string slice."); + .strip_prefix(&self.root) + .expect("Destination is not relative to root."); + let relative = relative + .to_str() + .expect("Path could not be yielded into a string slice."); debug!("[*]: {:?} does not exist, trying to create .gitignore", gitignore); @@ -236,20 +246,21 @@ impl MDBook { } } - /// The `build()` method is the one where everything happens. First it parses `SUMMARY.md` to - /// construct the book's structure in the form of a `Vec` and then calls `render()` + /// The `build()` method is the one where everything happens. + /// First it parses `SUMMARY.md` to construct the book's structure + /// in the form of a `Vec` and then calls `render()` /// method of the current renderer. /// /// It is the renderer who generates all the output files. pub fn build(&mut self) -> Result<(), Box> { debug!("[fn]: build"); - try!(self.init()); + self.init()?; // Clean output directory - try!(utils::fs::remove_dir_content(&self.dest)); + utils::fs::remove_dir_content(&self.dest)?; - try!(self.renderer.render(&self)); + self.renderer.render(&self)?; Ok(()) } @@ -266,55 +277,54 @@ impl MDBook { if !theme_dir.exists() { debug!("[*]: {:?} does not exist, trying to create directory", theme_dir); - try!(fs::create_dir(&theme_dir)); + fs::create_dir(&theme_dir)?; } // index.hbs - let mut index = try!(File::create(&theme_dir.join("index.hbs"))); - try!(index.write_all(theme::INDEX)); + let mut index = File::create(&theme_dir.join("index.hbs"))?; + index.write_all(theme::INDEX)?; // book.css - let mut css = try!(File::create(&theme_dir.join("book.css"))); - try!(css.write_all(theme::CSS)); + let mut css = File::create(&theme_dir.join("book.css"))?; + css.write_all(theme::CSS)?; // favicon.png - let mut favicon = try!(File::create(&theme_dir.join("favicon.png"))); - try!(favicon.write_all(theme::FAVICON)); + let mut favicon = File::create(&theme_dir.join("favicon.png"))?; + favicon.write_all(theme::FAVICON)?; // book.js - let mut js = try!(File::create(&theme_dir.join("book.js"))); - try!(js.write_all(theme::JS)); + let mut js = File::create(&theme_dir.join("book.js"))?; + js.write_all(theme::JS)?; // highlight.css - let mut highlight_css = try!(File::create(&theme_dir.join("highlight.css"))); - try!(highlight_css.write_all(theme::HIGHLIGHT_CSS)); + let mut highlight_css = File::create(&theme_dir.join("highlight.css"))?; + highlight_css.write_all(theme::HIGHLIGHT_CSS)?; // highlight.js - let mut highlight_js = try!(File::create(&theme_dir.join("highlight.js"))); - try!(highlight_js.write_all(theme::HIGHLIGHT_JS)); + let mut highlight_js = File::create(&theme_dir.join("highlight.js"))?; + highlight_js.write_all(theme::HIGHLIGHT_JS)?; Ok(()) } pub fn write_file>(&self, filename: P, content: &[u8]) -> Result<(), Box> { let path = self.get_dest().join(filename); - try!(utils::fs::create_file(&path).and_then(|mut file| { - file.write_all(content) - }).map_err(|e| { - io::Error::new(io::ErrorKind::Other, format!("Could not create {}: {}", path.display(), e)) - })); + utils::fs::create_file(&path) + .and_then(|mut file| file.write_all(content)) + .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("Could not create {}: {}", path.display(), e)))?; Ok(()) } - /// Parses the `book.json` file (if it exists) to extract the configuration parameters. + /// Parses the `book.json` file (if it exists) to extract + /// the configuration parameters. /// The `book.json` file should be in the root directory of the book. /// The root directory is the one specified when creating a new `MDBook` pub fn read_config(mut self) -> Self { let config = BookConfig::new(&self.root) - .read_config(&self.root) - .to_owned(); + .read_config(&self.root) + .to_owned(); self.title = config.title; self.description = config.description; @@ -327,8 +337,10 @@ impl MDBook { self } - /// You can change the default renderer to another one by using this method. The only requirement - /// is for your renderer to implement the [Renderer trait](../../renderer/renderer/trait.Renderer.html) + /// You can change the default renderer to another one + /// by using this method. The only requirement + /// is for your renderer to implement the + /// [Renderer trait](../../renderer/renderer/trait.Renderer.html) /// /// ```no_run /// extern crate mdbook; @@ -340,12 +352,14 @@ impl MDBook { /// let mut book = MDBook::new(Path::new("mybook")) /// .set_renderer(Box::new(HtmlHandlebars::new())); /// - /// // In this example we replace the default renderer by the default renderer... - /// // Don't forget to put your renderer in a Box + /// // In this example we replace the default renderer + /// // by the default renderer... + /// // Don't forget to put your renderer in a Box /// } /// ``` /// - /// **note:** Don't forget to put your renderer in a `Box` before passing it to `set_renderer()` + /// **note:** Don't forget to put your renderer in a `Box` + /// before passing it to `set_renderer()` pub fn set_renderer(mut self, renderer: Box) -> Self { self.renderer = renderer; @@ -354,7 +368,7 @@ impl MDBook { pub fn test(&mut self) -> Result<(), Box> { // read in the chapters - try!(self.parse_summary()); + self.parse_summary()?; for item in self.iter() { if let BookItem::Chapter(_, ref ch) = *item { @@ -364,17 +378,15 @@ impl MDBook { println!("[*]: Testing file: {:?}", path); - let output_result = Command::new("rustdoc") - .arg(&path) - .arg("--test") - .output(); - let output = try!(output_result); + let output_result = Command::new("rustdoc").arg(&path).arg("--test").output(); + let output = output_result?; if !output.status.success() { - return Err(Box::new(io::Error::new(ErrorKind::Other, format!( - "{}\n{}", - String::from_utf8_lossy(&output.stdout), - String::from_utf8_lossy(&output.stderr)))) as Box); + return Err(Box::new(io::Error::new(ErrorKind::Other, + format!("{}\n{}", + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr)))) as + Box); } } } @@ -477,7 +489,7 @@ impl MDBook { // Construct book fn parse_summary(&mut self) -> Result<(), Box> { // When append becomes stable, use self.content.append() ... - self.content = try!(parse::construct_bookitems(&self.src.join("SUMMARY.md"))); + self.content = parse::construct_bookitems(&self.src.join("SUMMARY.md"))?; Ok(()) } } diff --git a/src/vendor/mdbook/src/lib.rs b/src/vendor/mdbook/src/lib.rs index 49c56facf8..303bb23bb6 100644 --- a/src/vendor/mdbook/src/lib.rs +++ b/src/vendor/mdbook/src/lib.rs @@ -76,7 +76,8 @@ extern crate handlebars; extern crate pulldown_cmark; extern crate regex; -#[macro_use] extern crate log; +#[macro_use] +extern crate log; pub mod book; mod parse; pub mod renderer; diff --git a/src/vendor/mdbook/src/parse/mod.rs b/src/vendor/mdbook/src/parse/mod.rs index c8c8aab7d4..3f5b01a1ef 100644 --- a/src/vendor/mdbook/src/parse/mod.rs +++ b/src/vendor/mdbook/src/parse/mod.rs @@ -1,3 +1,3 @@ -pub use self::summary::construct_bookitems; - -pub mod summary; +pub use self::summary::construct_bookitems; + +pub mod summary; diff --git a/src/vendor/mdbook/src/parse/summary.rs b/src/vendor/mdbook/src/parse/summary.rs index 3d96635538..cc8452d441 100644 --- a/src/vendor/mdbook/src/parse/summary.rs +++ b/src/vendor/mdbook/src/parse/summary.rs @@ -6,10 +6,10 @@ use book::bookitem::{BookItem, Chapter}; pub fn construct_bookitems(path: &PathBuf) -> Result> { debug!("[fn]: construct_bookitems"); let mut summary = String::new(); - try!(try!(File::open(path)).read_to_string(&mut summary)); + File::open(path)?.read_to_string(&mut summary)?; debug!("[*]: Parse SUMMARY.md"); - let top_items = try!(parse_level(&mut summary.split('\n').collect(), 0, vec![0])); + let top_items = parse_level(&mut summary.split('\n').collect(), 0, vec![0])?; debug!("[*]: Done parsing SUMMARY.md"); Ok(top_items) } @@ -22,9 +22,10 @@ fn parse_level(summary: &mut Vec<&str>, current_level: i32, mut section: Vec, current_level: i32, mut section: Vec, current_level: i32, mut section: Vec 0 => { + BookItem::Affix(_) | + BookItem::Spacer if level > 0 => { return Err(Error::new(ErrorKind::Other, "Your summary.md is messed up\n\n \ @@ -98,7 +102,9 @@ fn parse_level(summary: &mut Vec<&str>, current_level: i32, mut section: Vec parsed_item, diff --git a/src/vendor/mdbook/src/renderer/html_handlebars/hbs_renderer.rs b/src/vendor/mdbook/src/renderer/html_handlebars/hbs_renderer.rs index 4fac6869cc..cb4520000d 100644 --- a/src/vendor/mdbook/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/vendor/mdbook/src/renderer/html_handlebars/hbs_renderer.rs @@ -37,7 +37,8 @@ impl Renderer for HtmlHandlebars { // Register template debug!("[*]: Register handlebars template"); - try!(handlebars.register_template_string("index", try!(String::from_utf8(theme.index)))); + handlebars + .register_template_string("index", String::from_utf8(theme.index)?)?; // Register helpers debug!("[*]: Register handlebars helpers"); @@ -45,7 +46,7 @@ impl Renderer for HtmlHandlebars { handlebars.register_helper("previous", Box::new(helpers::navigation::previous)); handlebars.register_helper("next", Box::new(helpers::navigation::next)); - let mut data = try!(make_data(book)); + let mut data = make_data(book)?; // Print version let mut print_content: String = String::new(); @@ -69,11 +70,11 @@ impl Renderer for HtmlHandlebars { let path = book.get_src().join(&ch.path); debug!("[*]: Opening file: {:?}", path); - let mut f = try!(File::open(&path)); + let mut f = File::open(&path)?; let mut content: String = String::new(); debug!("[*]: Reading file"); - try!(f.read_to_string(&mut content)); + f.read_to_string(&mut content)?; // Parse for playpen links if let Some(p) = path.parent() { @@ -85,8 +86,10 @@ impl Renderer for HtmlHandlebars { print_content.push_str(&content); // Update the context with data for this file - let path = ch.path.to_str().ok_or_else(|| - io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))?; + let path = + ch.path + .to_str() + .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))?; data.insert("path".to_owned(), json!(path)); data.insert("content".to_owned(), json!(content)); data.insert("chapter_title".to_owned(), json!(ch.name)); @@ -94,7 +97,7 @@ impl Renderer for HtmlHandlebars { // Render the handlebars template with the data debug!("[*]: Render template"); - let rendered = try!(handlebars.render("index", &data)); + let rendered = handlebars.render("index", &data)?; let filename = Path::new(&ch.path).with_extension("html"); @@ -106,24 +109,26 @@ impl Renderer for HtmlHandlebars { // Write to file info!("[*] Creating {:?} ✓", filename.display()); - try!(book.write_file(filename, &rendered.into_bytes())); + book.write_file(filename, &rendered.into_bytes())?; // Create an index.html from the first element in SUMMARY.md if index { debug!("[*]: index.html"); let mut content = String::new(); - let _source = try!(File::open(book.get_dest().join(&ch.path.with_extension("html")))) + let _source = File::open(book.get_dest().join(&ch.path.with_extension("html")))? .read_to_string(&mut content); - // This could cause a problem when someone displays code containing + // This could cause a problem when someone displays + // code containing // on the front page, however this case should be very very rare... - content = content.lines() + content = content + .lines() .filter(|line| !line.contains(" Result data.insert("livereload".to_owned(), json!(livereload)); } + // Add google analytics tag + if let Some(ref ga) = book.google_analytics { + data.insert("google_analytics".to_owned(), json!(ga)); + } + let mut chapters = vec![]; for item in book.iter() { @@ -202,15 +212,17 @@ fn make_data(book: &MDBook) -> Result match *item { BookItem::Affix(ref ch) => { chapter.insert("name".to_owned(), json!(ch.name)); - let path = ch.path.to_str().ok_or_else(|| - io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))?; + let path = ch.path + .to_str() + .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))?; chapter.insert("path".to_owned(), json!(path)); }, BookItem::Chapter(ref s, ref ch) => { chapter.insert("section".to_owned(), json!(s)); chapter.insert("name".to_owned(), json!(ch.name)); - let path = ch.path.to_str().ok_or_else(|| - io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))?; + let path = ch.path + .to_str() + .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))?; chapter.insert("path".to_owned(), json!(path)); }, BookItem::Spacer => { @@ -232,42 +244,55 @@ fn build_header_links(html: String, filename: &str) -> String { let regex = Regex::new(r"(.*?)").unwrap(); let mut id_counter = HashMap::new(); - regex.replace_all(&html, |caps: &Captures| { - let level = &caps[1]; - let text = &caps[2]; - let mut id = text.to_string(); - let repl_sub = vec!["", "", "", "", - "", "", - "<", ">", "&", "'", """]; - for sub in repl_sub { - id = id.replace(sub, ""); - } - let id = id.chars().filter_map(|c| { - if c.is_alphanumeric() || c == '-' || c == '_' { - if c.is_ascii() { - Some(c.to_ascii_lowercase()) - } else { - Some(c) - } - } else if c.is_whitespace() && c.is_ascii() { - Some('-') - } else { - None + regex + .replace_all(&html, |caps: &Captures| { + let level = &caps[1]; + let text = &caps[2]; + let mut id = text.to_string(); + let repl_sub = vec!["", + "", + "", + "", + "", + "", + "<", + ">", + "&", + "'", + """]; + for sub in repl_sub { + id = id.replace(sub, ""); } - }).collect::(); - - let id_count = *id_counter.get(&id).unwrap_or(&0); - id_counter.insert(id.clone(), id_count + 1); - - let id = if id_count > 0 { - format!("{}-{}", id, id_count) - } else { - id - }; - - format!("{text}", - level=level, id=id, text=text, filename=filename) - }).into_owned() + let id = id.chars() + .filter_map(|c| if c.is_alphanumeric() || c == '-' || c == '_' { + if c.is_ascii() { + Some(c.to_ascii_lowercase()) + } else { + Some(c) + } + } else if c.is_whitespace() && c.is_ascii() { + Some('-') + } else { + None + }) + .collect::(); + + let id_count = *id_counter.get(&id).unwrap_or(&0); + id_counter.insert(id.clone(), id_count + 1); + + let id = if id_count > 0 { + format!("{}-{}", id, id_count) + } else { + id + }; + + format!("{text}", + level = level, + id = id, + text = text, + filename = filename) + }) + .into_owned() } // anchors to the same page (href="#anchor") do not work because of @@ -275,18 +300,24 @@ fn build_header_links(html: String, filename: &str) -> String { // that in a very inelegant way fn fix_anchor_links(html: String, filename: &str) -> String { let regex = Regex::new(r##"]+)href="#([^"]+)"([^>]*)>"##).unwrap(); - regex.replace_all(&html, |caps: &Captures| { - let before = &caps[1]; - let anchor = &caps[2]; - let after = &caps[3]; - - format!("", - before=before, filename=filename, anchor=anchor, after=after) - }).into_owned() + regex + .replace_all(&html, |caps: &Captures| { + let before = &caps[1]; + let anchor = &caps[2]; + let after = &caps[3]; + + format!("", + before = before, + filename = filename, + anchor = anchor, + after = after) + }) + .into_owned() } -// The rust book uses annotations for rustdoc to test code snippets, like the following: +// The rust book uses annotations for rustdoc to test code snippets, +// like the following: // ```rust,should_panic // fn main() { // // Code here @@ -295,40 +326,48 @@ fn fix_anchor_links(html: String, filename: &str) -> String { // This function replaces all commas by spaces in the code block classes fn fix_code_blocks(html: String) -> String { let regex = Regex::new(r##"]+)class="([^"]+)"([^>]*)>"##).unwrap(); - regex.replace_all(&html, |caps: &Captures| { - let before = &caps[1]; - let classes = &caps[2].replace(",", " "); - let after = &caps[3]; - - format!("", before=before, classes=classes, after=after) - }).into_owned() + regex + .replace_all(&html, |caps: &Captures| { + let before = &caps[1]; + let classes = &caps[2].replace(",", " "); + let after = &caps[3]; + + format!("", before = before, classes = classes, after = after) + }) + .into_owned() } fn add_playpen_pre(html: String) -> String { let regex = Regex::new(r##"((?s)]?class="([^"]+)".*?>(.*?))"##).unwrap(); - regex.replace_all(&html, |caps: &Captures| { - let text = &caps[1]; - let classes = &caps[2]; - let code = &caps[3]; + regex + .replace_all(&html, |caps: &Captures| { + let text = &caps[1]; + let classes = &caps[2]; + let code = &caps[3]; - if classes.contains("language-rust") && !classes.contains("ignore") { - // wrap the contents in an external pre block + if classes.contains("language-rust") && !classes.contains("ignore") { + // wrap the contents in an external pre block - if text.contains("fn main") { - format!("