From: kennytm Date: Wed, 14 Feb 2018 08:14:29 +0000 (+0800) Subject: Rollup merge of #47846 - roblabla:bugfix-ocaml, r=kennytm X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=2be44ceaa207f6a29f2c10399b524e8700ec173d;hp=3c01dea03e1b4ffbcb665a68bcf228c02497ecdc;p=rust.git Rollup merge of #47846 - roblabla:bugfix-ocaml, r=kennytm Work around LLVM OCAML binding installation failure Hello, I have OCaml installed on my machine, and compiling rust systematically fails when LLVM attempts installing the OCaml bindings in `/usr/lib/ocaml`, which is write-protected. Here are the logs: https://gist.github.com/roblabla/3f147914c5df627c9d97ab311ba133ad Some digging around the issue reveals: - The code that finds if OCaml is installed, and sets the bindings to be compiled/installed: https://github.com/llvm-mirror/llvm/blob/b24a45d2e9f4fc10c3f9e16172104910b38637f2/cmake/config-ix.cmake#L612 - https://github.com/llvm-mirror/llvm/blob/b24a45d2e9f4fc10c3f9e16172104910b38637f2/bindings/ocaml/llvm/CMakeLists.txt Some code that does the installation. The problem seems to be that `LLVM_OCAML_INSTALL_PATH` is set to `OCAML_STDLIB_PATH` by default, which is in `/usr/lib/ocaml`, instead of the prefix. This PR "fixes" the issue by setting `LLVM_OCAML_INSTALL_PATH` to `usr/lib/ocaml`. I haven't found a way to make LLVM not build OCaml, which would probably be a superior fix. --- diff --git a/RELEASES.md b/RELEASES.md index 45c389d72af..d6f95f52075 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,117 @@ +Version 1.24.0 (2018-02-15) +========================== + +Language +-------- +- [External `sysv64` ffi is now available.][46528] + eg. `extern "sysv64" fn foo () {}` + +Compiler +-------- +- [rustc now uses 16 codegen units by default for release builds.][46910] + For the fastest builds, utilize `codegen-units=1`. +- [Added `armv4t-unknown-linux-gnueabi` target.][47018] +- [Add `aarch64-unknown-openbsd` support][46760] + +Libraries +--------- +- [`str::find::` now uses memchr.][46735] This should lead to a 10x + improvement in performance in the majority of cases. +- [`OsStr`'s `Debug` implementation is now lossless and consistent + with Windows.][46798] +- [`time::{SystemTime, Instant}` now implement `Hash`.][46828] +- [impl `From` for `AtomicBool`][46293] +- [impl `From<{CString, &CStr}>` for `{Arc, Rc}`][45990] +- [impl `From<{OsString, &OsStr}>` for `{Arc, Rc}`][45990] +- [impl `From<{PathBuf, &Path}>` for `{Arc, Rc}`][45990] +- [float::from_bits now just uses transmute.][46012] This provides + some optimisations from LLVM. +- [Copied `AsciiExt` methods onto `char`][46077] +- [Remove `T: Sized` requirement on `ptr::is_null()`][46094] +- [impl `From` for `{TryRecvError, RecvTimeoutError}`][45506] +- [Optimised `f32::{min, max}` to generate more efficent x86 assembly][47080] +- [`[u8]::contains` now uses memchr which provides a 3x speed improvement][46713] + +Stabilized APIs +--------------- +- [`RefCell::replace`] +- [`RefCell::swap`] +- [`atomic::spin_loop_hint`] + +The following functions can now be used in a constant expression. +eg. `let buffer: [u8; size_of::()];`, `static COUNTER: AtomicUsize = AtomicUsize::new(1);` + +- [`AtomicBool::new`][46287] +- [`AtomicUsize::new`][46287] +- [`AtomicIsize::new`][46287] +- [`AtomicPtr::new`][46287] +- [`Cell::new`][46287] +- [`{integer}::min_value`][46287] +- [`{integer}::max_value`][46287] +- [`mem::size_of`][46287] +- [`mem::align_of`][46287] +- [`ptr::null`][46287] +- [`ptr::null_mut`][46287] +- [`RefCell::new`][46287] +- [`UnsafeCell::new`][46287] + +Cargo +----- +- [Added a `workspace.default-members` config that + overrides implied `--all` in virtual workspaces.][cargo/4743] +- [Enable incremental by default on development builds.][cargo/4817] Also added + configuration keys to `Cargo.toml` and `.cargo/config` to disable on a + per-project or global basis respectively. + +Misc +---- + +Compatibility Notes +------------------- +- [Floating point types `Debug` impl now always prints a decimal point.][46831] +- [`Ipv6Addr` now rejects superfluous `::`'s in IPv6 addresses][46671] This is + in accordance with IETF RFC 4291 §2.2. +- [Unwinding will no longer go past FFI boundaries, and will instead abort.][46833] +- [`Formatter::flags` method is now deprecated.][46284] The `sign_plus`, + `sign_minus`, `alternate`, and `sign_aware_zero_pad` should be used instead. +- [Leading zeros in tuple struct members is now an error][47084] +- [`column!()` macro is one-based instead of zero-based][46977] +- [`fmt::Arguments` can no longer be shared across threads][45198] +- [Access to `#[repr(packed)]` struct fields is now unsafe][44884] + +[44884]: https://github.com/rust-lang/rust/pull/44884 +[45198]: https://github.com/rust-lang/rust/pull/45198 +[45506]: https://github.com/rust-lang/rust/pull/45506 +[45904]: https://github.com/rust-lang/rust/pull/45904 +[45990]: https://github.com/rust-lang/rust/pull/45990 +[46012]: https://github.com/rust-lang/rust/pull/46012 +[46077]: https://github.com/rust-lang/rust/pull/46077 +[46094]: https://github.com/rust-lang/rust/pull/46094 +[46284]: https://github.com/rust-lang/rust/pull/46284 +[46287]: https://github.com/rust-lang/rust/pull/46287 +[46293]: https://github.com/rust-lang/rust/pull/46293 +[46528]: https://github.com/rust-lang/rust/pull/46528 +[46671]: https://github.com/rust-lang/rust/pull/46671 +[46713]: https://github.com/rust-lang/rust/pull/46713 +[46735]: https://github.com/rust-lang/rust/pull/46735 +[46749]: https://github.com/rust-lang/rust/pull/46749 +[46760]: https://github.com/rust-lang/rust/pull/46760 +[46798]: https://github.com/rust-lang/rust/pull/46798 +[46828]: https://github.com/rust-lang/rust/pull/46828 +[46831]: https://github.com/rust-lang/rust/pull/46831 +[46833]: https://github.com/rust-lang/rust/pull/46833 +[46910]: https://github.com/rust-lang/rust/pull/46910 +[46977]: https://github.com/rust-lang/rust/pull/46977 +[47018]: https://github.com/rust-lang/rust/pull/47018 +[47080]: https://github.com/rust-lang/rust/pull/47080 +[47084]: https://github.com/rust-lang/rust/pull/47084 +[cargo/4743]: https://github.com/rust-lang/cargo/pull/4743 +[cargo/4817]: https://github.com/rust-lang/cargo/pull/4817 +[`RefCell::replace`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.replace +[`RefCell::swap`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.swap +[`atomic::spin_loop_hint`]: https://doc.rust-lang.org/std/sync/atomic/fn.spin_loop_hint.html + + Version 1.23.0 (2018-01-04) ========================== diff --git a/config.toml.example b/config.toml.example index 1d60d8c9494..f153562a538 100644 --- a/config.toml.example +++ b/config.toml.example @@ -151,6 +151,10 @@ # default. #extended = false +# Installs choosen set of extended tools if enables. By default builds all. +# If choosen tool failed to build the installation fails. +#tools = ["cargo", "rls", "rustfmt", "analysis", "src"] + # Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose #verbose = 0 @@ -235,6 +239,11 @@ # compiler. #codegen-units = 1 +# Whether to enable ThinLTO (and increase the codegen units to either a default +# or the configured value). On by default. If we want the fastest possible +# compiler, we should disable this. +#thinlto = true + # Whether or not debug assertions are enabled for the compiler and standard # library. Also enables compilation of debug! and trace! logging macros. #debug-assertions = false @@ -290,7 +299,7 @@ # Flag indicating whether git info will be retrieved from .git automatically. # Having the git information can cause a lot of rebuilds during development. -# Note: If this attribute is not explicity set (e.g. if left commented out) it +# Note: If this attribute is not explicitly set (e.g. if left commented out) it # will default to true if channel = "dev", but will default to false otherwise. #ignore-git = true @@ -312,6 +321,11 @@ # bootstrap) #codegen-backends = ["llvm"] +# Flag indicating whether `libstd` calls an imported function to handle basic IO +# when targeting WebAssembly. Enable this to debug tests for the `wasm32-unknown-unknown` +# target, as without this option the test output will not be captured. +#wasm-syscall = false + # ============================================================================= # Options for specific targets # @@ -339,7 +353,7 @@ #linker = "cc" # Path to the `llvm-config` binary of the installation of a custom LLVM to link -# against. Note that if this is specifed we don't compile LLVM at all for this +# against. Note that if this is specified we don't compile LLVM at all for this # target. #llvm-config = "../path/to/llvm/root/bin/llvm-config" diff --git a/src/Cargo.lock b/src/Cargo.lock index d26098903ee..6b722db53ed 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -133,6 +133,7 @@ dependencies = [ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -291,14 +292,14 @@ dependencies = [ [[package]] name = "clippy" -version = "0.0.174" +version = "0.0.186" dependencies = [ "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy-mini-macro-test 0.1.0", - "clippy_lints 0.0.174", - "compiletest_rs 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy-mini-macro-test 0.2.0", + "clippy_lints 0.0.186", + "compiletest_rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", @@ -306,15 +307,15 @@ dependencies = [ [[package]] name = "clippy-mini-macro-test" -version = "0.1.0" +version = "0.2.0" [[package]] name = "clippy_lints" -version = "0.0.174" +version = "0.0.186" dependencies = [ "if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -386,7 +387,7 @@ dependencies = [ [[package]] name = "compiletest_rs" -version = "0.3.3" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -928,6 +929,11 @@ dependencies = [ "xz2 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "is-match" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "itertools" version = "0.6.5" @@ -936,6 +942,14 @@ dependencies = [ "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "itertools" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "itoa" version = "0.3.4" @@ -1129,23 +1143,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "mdbook" -version = "0.0.28" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "handlebars 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "toml-query 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1190,7 +1209,7 @@ version = "0.1.0" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "compiletest_rs 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "compiletest_rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1618,7 +1637,7 @@ version = "0.1.0" [[package]] name = "rls" -version = "0.124.0" +version = "0.125.0" dependencies = [ "cargo 0.26.0", "env_logger 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1635,7 +1654,7 @@ dependencies = [ "rls-rustc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt-nightly 0.3.6", + "rustfmt-nightly 0.3.8", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1666,6 +1685,15 @@ dependencies = [ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rls-data" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rls-rustc" version = "0.2.1" @@ -1695,7 +1723,7 @@ name = "rustbook" version = "0.1.0" dependencies = [ "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)", - "mdbook 0.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "mdbook 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1723,7 +1751,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "12.0.0" +version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1732,57 +1760,57 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "12.0.0" +version = "29.0.0" 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)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "12.0.0" +version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (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 = "rustc-ap-serialize" -version = "12.0.0" +version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-syntax" -version = "12.0.0" +version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "12.0.0" +version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2103,7 +2131,7 @@ name = "rustc_save_analysis" version = "0.0.0" dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-data 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-data 0.15.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)", @@ -2198,6 +2226,10 @@ dependencies = [ "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustdoc-themes" +version = "0.1.0" + [[package]] name = "rustdoc-tool" version = "0.0.0" @@ -2207,7 +2239,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "0.3.6" +version = "0.3.8" dependencies = [ "cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2219,8 +2251,8 @@ dependencies = [ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2379,6 +2411,11 @@ name = "shell-escape" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "shlex" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "siphasher" version = "0.2.2" @@ -2702,6 +2739,18 @@ dependencies = [ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "toml-query" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "unicode-bidi" version = "0.3.4" @@ -2941,7 +2990,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd" "checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007" "checksum commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2" -"checksum compiletest_rs 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "562bafeec9aef1e3e08f1c5b0c542220bb80ff2894e5373a1f9d17c346412c66" +"checksum compiletest_rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6c5aafb5d4a77c6b5fa384fe93c7a9a3561bd88c4b8b8e45187cf5e779b1badc" "checksum core-foundation 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8047f547cd6856d45b1cdd75ef8d2f21f3d0e4bf1dab0a0041b0ae9a5dda9c0e" "checksum core-foundation-sys 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "152195421a2e6497a8179195672e9d4ee8e45ed8c465b626f1606d27a08ebcd5" "checksum crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bd66663db5a988098a89599d4857919b3acf7f61402e61365acfd3919857b9be" @@ -2992,7 +3041,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" "checksum if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "61bb90bdd39e3af69b0172dfc6130f6cd6332bf040fbb9bdd4401d37adbd48b8" "checksum ignore 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bb2f0238094bd1b41800fb6eb9b16fdd5e9832ed6053ed91409f0cd5bf28dcfd" +"checksum is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7e5b386aef33a1c677be65237cb9d32c3f3ef56bd035949710c4bb13083eb053" "checksum itertools 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3f2be4da1690a039e9ae5fd575f706a63ad5a2120f161b1d653c9da3930dd21" +"checksum itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b07332223953b5051bceb67e8c4700aa65291535568e1f12408c43c4a42c0394" "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" "checksum jobserver 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "565f6106bd87b394398f813bea4e5ecad6d6b0f6aa077592d088f882a506481d" "checksum json 0.11.12 (registry+https://github.com/rust-lang/crates.io-index)" = "39ebf0fac977ee3a4a3242b6446004ff64514889e3e2730bbd4f764a67a2e483" @@ -3014,7 +3065,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" "checksum markup5ever 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "047150a0e03b57e638fc45af33a0b63a0362305d5b9f92ecef81df472a4cceb0" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" -"checksum mdbook 0.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "1ee8ba20c002000546681dc78d7f7e91fd35832058b1e2fdd492ca842bb6e9be" +"checksum mdbook 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fef236caad7ba3b5b3944df946f19ab3e190bca53c111dd00fe05fa8d879f2fd" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" @@ -3065,15 +3116,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e" "checksum rls-analysis 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "38841e3c5271715a574ac220d9b408b59ed9e2626909c3bc54b5853b4eaadb7b" "checksum rls-data 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8024f1feaca72d0aa4ae1e2a8d454a31b9a33ed02f8d0e9c8559bf53c267ec3c" +"checksum rls-data 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bea04462e94b5512a78499837eecb7db182ff082144cd1b4bc32ef5d43de6510" "checksum rls-rustc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "85cfb9dde19e313da3e47738008f8a472e470cc42d910b71595a9238494701f2" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" "checksum rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ffd34691a510938bb67fe0444fb363103c73ffb31c121d1e16bc92d8945ea8ff" -"checksum rustc-ap-rustc_cratesio_shim 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1a51c10af5abd5d698b7e3487e869e6d15f6feb04cbedb5c792e2824f9d845e" -"checksum rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1aa227490501072780d57f74b1164d361833ff8e172f817da0da2cdf2e4280cc" -"checksum rustc-ap-rustc_errors 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21ff6c6e13ac4fc04b7d4d398828b024c4b6577045cb3175b33d35fea35ff6d0" -"checksum rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b4e7f51e298675c2bf830f7265621a8936fb09e63b825b58144cbaac969e604" -"checksum rustc-ap-syntax 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8bf5639869ba2f7fa581939cd217cb71a85506b82ad0ea520614fb0dceb2386c" -"checksum rustc-ap-syntax_pos 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1c020cdb7379e1c733ae0a311ae47c748337ba584d2dd7b7f53baaae78de6f8b" +"checksum rustc-ap-rustc_cratesio_shim 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ad5e562044ea78a6764dd75ae8afe4b21fde49f4548024b5fdf6345c21fb524" +"checksum rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c0d65325492aba7db72899e3edbab34d39af98c42ab7c7e450c9a288ffe4ad" +"checksum rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87d4ab2e06a671b5b5c5b0359dac346f164c99d059dce6a22feb08f2f56bd182" +"checksum rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e0745fa445ff41c4b6699936cf35ce3ca49502377dd7b3929c829594772c3a7b" +"checksum rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82efedabe30f393161e11214a9130edfa01ad476372d1c6f3fec1f8d30488c9d" +"checksum rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db9de2e927e280c75b8efab9c5f591ad31082d5d2c4c562c68fdba2ee77286b0" "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" @@ -3094,6 +3146,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9db7266c7d63a4c4b7fe8719656ccdd51acf1bed6124b174f933b009fb10bcb" "checksum shared_child 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "099b38928dbe4a0a01fcd8c233183072f14a7d126a34bed05880869be66e14cc" "checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8" +"checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" "checksum smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4f8266519bc1d17d0b5b16f6c21295625d562841c708f6376f49028a43e9c11e" "checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9" @@ -3122,6 +3175,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098" "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4" "checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e" +"checksum toml-query 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6854664bfc6df0360c695480836ee90e2d0c965f06db291d10be9344792d43e8" "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.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" diff --git a/src/Cargo.toml b/src/Cargo.toml index c22ba7a37c8..c03301852cd 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -22,6 +22,7 @@ members = [ "tools/rls", "tools/rustfmt", "tools/miri", + "tools/rustdoc-themes", # FIXME(https://github.com/rust-lang/cargo/issues/4089): move these to exclude "tools/rls/test_data/bin_lib", "tools/rls/test_data/borrow_error", diff --git a/src/binaryen b/src/binaryen index 1c9bf65aa0e..17841e155ed 160000 --- a/src/binaryen +++ b/src/binaryen @@ -1 +1 @@ -Subproject commit 1c9bf65aa0e371b84755a8ddd6e79497fac57171 +Subproject commit 17841e155edf858c8ea7802dd5f5ecbef54b989f diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index bbbbf0e1915..2d478341317 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -41,3 +41,4 @@ serde_derive = "1.0.8" serde_json = "1.0.2" toml = "0.4" lazy_static = "0.2" +time = "0.1" diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 79058984b13..74dd4a6fa01 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -258,7 +258,7 @@ macro_rules! describe { test::HostCompiletest, test::Crate, test::CrateLibrustc, test::Rustdoc, test::Linkcheck, test::Cargotest, test::Cargo, test::Rls, test::Docs, test::ErrorIndex, test::Distcheck, test::Rustfmt, test::Miri, test::Clippy, - test::RustdocJS), + test::RustdocJS, test::RustdocTheme), Kind::Bench => describe!(test::Crate, test::CrateLibrustc), Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook, doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon, @@ -377,6 +377,11 @@ fn run(self, builder: &Builder) -> Interned { self.ensure(Libdir { compiler, target }) } + pub fn sysroot_codegen_backends(&self, compiler: Compiler) -> PathBuf { + self.sysroot_libdir(compiler, compiler.host) + .with_file_name("codegen-backends") + } + /// Returns the compiler's libdir where it stores the dynamic libraries that /// it itself links against. /// @@ -469,6 +474,18 @@ pub fn cargo(&self, stage = compiler.stage; } + let mut extra_args = env::var(&format!("RUSTFLAGS_STAGE_{}", stage)).unwrap_or_default(); + if stage != 0 { + let s = env::var("RUSTFLAGS_STAGE_NOT_0").unwrap_or_default(); + extra_args.push_str(" "); + extra_args.push_str(&s); + } + + if !extra_args.is_empty() { + cargo.env("RUSTFLAGS", + format!("{} {}", env::var("RUSTFLAGS").unwrap_or_default(), extra_args)); + } + // Customize the compiler we're running. Specify the compiler to cargo // as our shim and then pass it some various options used to configure // how the actual compiler itself is called. @@ -492,10 +509,6 @@ pub fn cargo(&self, }) .env("TEST_MIRI", self.config.test_miri.to_string()) .env("RUSTC_ERROR_METADATA_DST", self.extended_error_dir()); - if let Some(n) = self.config.rust_codegen_units { - cargo.env("RUSTC_CODEGEN_UNITS", n.to_string()); - } - if let Some(host_linker) = self.build.linker(compiler.host) { cargo.env("RUSTC_HOST_LINKER", host_linker); @@ -557,7 +570,7 @@ pub fn cargo(&self, // build scripts in that situation. // // If LLVM support is disabled we need to use the snapshot compiler to compile - // build scripts, as the new compiler doesnt support executables. + // build scripts, as the new compiler doesn't support executables. if mode == Mode::Libstd || !self.build.config.llvm_enabled { cargo.env("RUSTC_SNAPSHOT", &self.initial_rustc) .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir()); @@ -587,9 +600,25 @@ pub fn cargo(&self, // // FIXME: the guard against msvc shouldn't need to be here if !target.contains("msvc") { - let cc = self.cc(target); - cargo.env(format!("CC_{}", target), cc) - .env("CC", cc); + let ccache = self.config.ccache.as_ref(); + let ccacheify = |s: &Path| { + let ccache = match ccache { + Some(ref s) => s, + None => return s.display().to_string(), + }; + // FIXME: the cc-rs crate only recognizes the literal strings + // `ccache` and `sccache` when doing caching compilations, so we + // mirror that here. It should probably be fixed upstream to + // accept a new env var or otherwise work with custom ccache + // vars. + match &ccache[..] { + "ccache" | "sccache" => format!("{} {}", ccache, s.display()), + _ => s.display().to_string(), + } + }; + let cc = ccacheify(&self.cc(target)); + cargo.env(format!("CC_{}", target), &cc) + .env("CC", &cc); let cflags = self.cflags(target).join(" "); cargo.env(format!("CFLAGS_{}", target), cflags.clone()) @@ -604,8 +633,9 @@ pub fn cargo(&self, } if let Ok(cxx) = self.cxx(target) { - cargo.env(format!("CXX_{}", target), cxx) - .env("CXX", cxx) + let cxx = ccacheify(&cxx); + cargo.env(format!("CXX_{}", target), &cxx) + .env("CXX", &cxx) .env(format!("CXXFLAGS_{}", target), cflags.clone()) .env("CXXFLAGS", cflags); } @@ -662,6 +692,13 @@ pub fn cargo(&self, if self.is_very_verbose() { cargo.arg("-v"); } + + // This must be kept before the thinlto check, as we set codegen units + // to 1 forcibly there. + if let Some(n) = self.config.rust_codegen_units { + cargo.env("RUSTC_CODEGEN_UNITS", n.to_string()); + } + if self.config.rust_optimize { // FIXME: cargo bench does not accept `--release` if cmd != "bench" { @@ -669,11 +706,17 @@ pub fn cargo(&self, } if self.config.rust_codegen_units.is_none() && - self.build.is_rust_llvm(compiler.host) - { + self.build.is_rust_llvm(compiler.host) && + self.config.rust_thinlto { cargo.env("RUSTC_THINLTO", "1"); + } else if self.config.rust_codegen_units.is_none() { + // Generally, if ThinLTO has been disabled for some reason, we + // want to set the codegen units to 1. However, we shouldn't do + // this if the option was specifically set by the user. + cargo.env("RUSTC_CODEGEN_UNITS", "1"); } } + if self.config.locked_deps { cargo.arg("--locked"); } diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index e6871764b2c..ede403491d7 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -160,4 +160,3 @@ pub fn libtest_stamp(build: &Build, compiler: Compiler, target: Interned pub fn librustc_stamp(build: &Build, compiler: Compiler, target: Interned) -> PathBuf { build.cargo_out(compiler, Mode::Librustc, target).join(".librustc-check.stamp") } - diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index fa289bbd76a..1d5e11c5d6d 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -724,8 +724,7 @@ fn copy_codegen_backends_to_sysroot(builder: &Builder, // // Here we're looking for the output dylib of the `CodegenBackend` step and // we're copying that into the `codegen-backends` folder. - let libdir = builder.sysroot_libdir(target_compiler, target); - let dst = libdir.join("codegen-backends"); + let dst = builder.sysroot_codegen_backends(target_compiler); t!(fs::create_dir_all(&dst)); for backend in builder.config.rust_codegen_backends.iter() { diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index dbeb27cbfb7..4f4fd14ae8c 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -13,7 +13,7 @@ //! This module implements parsing `config.toml` configuration files to tweak //! how the build runs. -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::env; use std::fs::File; use std::io::prelude::*; @@ -52,6 +52,7 @@ pub struct Config { pub target_config: HashMap, Target>, pub full_bootstrap: bool, pub extended: bool, + pub tools: Option>, pub sanitizers: bool, pub profiler: bool, pub ignore_git: bool, @@ -81,6 +82,7 @@ pub struct Config { // rust codegen options pub rust_optimize: bool, pub rust_codegen_units: Option, + pub rust_thinlto: bool, pub rust_debug_assertions: bool, pub rust_debuginfo: bool, pub rust_debuginfo_lines: bool, @@ -107,6 +109,7 @@ pub struct Config { pub debug_jemalloc: bool, pub use_jemalloc: bool, pub backtrace: bool, // support for RUST_BACKTRACE + pub wasm_syscall: bool, // misc pub low_priority: bool, @@ -189,6 +192,7 @@ struct Build { python: Option, full_bootstrap: Option, extended: Option, + tools: Option>, verbose: Option, sanitizers: Option, profiler: Option, @@ -260,6 +264,7 @@ fn default() -> StringOrBool { struct Rust { optimize: Option, codegen_units: Option, + thinlto: Option, debug_assertions: Option, debuginfo: Option, debuginfo_lines: Option, @@ -282,6 +287,7 @@ struct Rust { test_miri: Option, save_toolstates: Option, codegen_backends: Option>, + wasm_syscall: Option, } /// TOML representation of how each build target is configured. @@ -391,6 +397,7 @@ pub fn parse(args: &[String]) -> Config { set(&mut config.vendor, build.vendor); set(&mut config.full_bootstrap, build.full_bootstrap); set(&mut config.extended, build.extended); + config.tools = build.tools; set(&mut config.verbose, build.verbose); set(&mut config.sanitizers, build.sanitizers); set(&mut config.profiler, build.profiler); @@ -410,6 +417,7 @@ pub fn parse(args: &[String]) -> Config { // Store off these values as options because if they're not provided // we'll infer default values for them later + let mut thinlto = None; let mut llvm_assertions = None; let mut debuginfo_lines = None; let mut debuginfo_only_std = None; @@ -453,6 +461,7 @@ pub fn parse(args: &[String]) -> Config { optimize = rust.optimize; ignore_git = rust.ignore_git; debug_jemalloc = rust.debug_jemalloc; + thinlto = rust.thinlto; set(&mut config.rust_optimize_tests, rust.optimize_tests); set(&mut config.rust_debuginfo_tests, rust.debuginfo_tests); set(&mut config.codegen_tests, rust.codegen_tests); @@ -463,6 +472,7 @@ pub fn parse(args: &[String]) -> Config { set(&mut config.rust_dist_src, rust.dist_src); set(&mut config.quiet_tests, rust.quiet_tests); set(&mut config.test_miri, rust.test_miri); + set(&mut config.wasm_syscall, rust.wasm_syscall); config.rustc_parallel_queries = rust.experimental_parallel_queries.unwrap_or(false); config.rustc_default_linker = rust.default_linker.clone(); config.musl_root = rust.musl_root.clone().map(PathBuf::from); @@ -536,6 +546,7 @@ pub fn parse(args: &[String]) -> Config { "stable" | "beta" | "nightly" => true, _ => false, }; + config.rust_thinlto = thinlto.unwrap_or(true); config.rust_debuginfo_lines = debuginfo_lines.unwrap_or(default); config.rust_debuginfo_only_std = debuginfo_only_std.unwrap_or(default); diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index bc6f666d001..99a3ee4e4c3 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -70,6 +70,7 @@ o("emscripten", None, "compile the emscripten backend as well as LLVM") # Optimization and debugging options. These may be overridden by the release # channel, etc. o("optimize", "rust.optimize", "build optimized rust code") +o("thinlto", "rust.thinlto", "build Rust with ThinLTO enabled") o("optimize-llvm", "llvm.optimize", "build optimized LLVM") o("llvm-assertions", "llvm.assertions", "build LLVM with assertions") o("debug-assertions", "rust.debug-assertions", "build with debugging assertions") @@ -143,6 +144,7 @@ o("jemalloc", "rust.use-jemalloc", "build liballoc with jemalloc") o("full-bootstrap", "build.full-bootstrap", "build three compilers instead of two") o("extended", "build.extended", "build an extended rust tool set") +v("tools", "build.tools", "List of extended tools will be installed") v("build", "build.build", "GNUs ./configure syntax LLVM build triple") v("host", None, "GNUs ./configure syntax LLVM host triples") v("target", None, "GNUs ./configure syntax LLVM target triples") diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 4127239dc49..460fb016f16 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -31,8 +31,10 @@ use util::{cp_r, libdir, is_dylib, cp_filtered, copy, replace_in_file}; use builder::{Builder, RunConfig, ShouldRun, Step}; use compile; +use native; use tool::{self, Tool}; use cache::{INTERNER, Interned}; +use time; pub fn pkgname(build: &Build, component: &str) -> String { if component == "cargo" { @@ -435,11 +437,9 @@ fn prepare_image(builder: &Builder, compiler: Compiler, image: &Path) { } // Copy over the codegen backends - let backends_src = builder.sysroot_libdir(compiler, host) - .join("codegen-backends"); - let backends_dst = image.join("lib/rustlib") - .join(&*host) - .join("lib/codegen-backends"); + let backends_src = builder.sysroot_codegen_backends(compiler); + let backends_rel = backends_src.strip_prefix(&src).unwrap(); + let backends_dst = image.join(&backends_rel); t!(fs::create_dir_all(&backends_dst)); cp_r(&backends_src, &backends_dst); @@ -447,8 +447,7 @@ fn prepare_image(builder: &Builder, compiler: Compiler, image: &Path) { t!(fs::create_dir_all(image.join("share/man/man1"))); let man_src = build.src.join("src/doc/man"); let man_dst = image.join("share/man/man1"); - let date_output = output(Command::new("date").arg("+%B %Y")); - let month_year = date_output.trim(); + let month_year = t!(time::strftime("%B %Y", &time::now())); // don't use our `bootstrap::util::{copy, cp_r}`, because those try // to hardlink, and we don't want to edit the source templates for entry_result in t!(fs::read_dir(man_src)) { @@ -458,7 +457,7 @@ fn prepare_image(builder: &Builder, compiler: Compiler, image: &Path) { t!(fs::copy(&page_src, &page_dst)); // template in month/year and version number replace_in_file(&page_dst, - &[("", month_year), + &[("", &month_year), ("", channel::CFG_RELEASE_NUM)]); } @@ -900,6 +899,12 @@ fn run(self, builder: &Builder) -> PathBuf { .arg("--vers").arg(CARGO_VENDOR_VERSION) .arg("cargo-vendor") .env("RUSTC", &build.initial_rustc); + if let Some(dir) = build.openssl_install_dir(build.config.build) { + builder.ensure(native::Openssl { + target: build.config.build, + }); + cmd.env("OPENSSL_DIR", dir); + } build.run(&mut cmd); } diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 743f32ece99..20f7d379a69 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -22,6 +22,7 @@ use builder::{Builder, RunConfig, ShouldRun, Step}; use cache::Interned; +use config::Config; pub fn install_docs(builder: &Builder, stage: u32, host: Interned) { install_sh(builder, "docs", "rust-docs", stage, Some(host)); @@ -144,6 +145,19 @@ pub struct $name { pub host: Interned, } + impl $name { + #[allow(dead_code)] + fn should_build(config: &Config) -> bool { + config.extended && config.tools.as_ref() + .map_or(true, |t| t.contains($path)) + } + + #[allow(dead_code)] + fn should_install(builder: &Builder) -> bool { + builder.config.tools.as_ref().map_or(false, |t| t.contains($path)) + } + } + impl Step for $name { type Output = (); const DEFAULT: bool = true; @@ -185,32 +199,34 @@ fn run($sel, $builder: &Builder) { install_std(builder, self.stage, *target); } }; - Cargo, "cargo", _config.extended, only_hosts: true, { + Cargo, "cargo", Self::should_build(_config), only_hosts: true, { builder.ensure(dist::Cargo { stage: self.stage, target: self.target }); install_cargo(builder, self.stage, self.target); }; - Rls, "rls", _config.extended, only_hosts: true, { - if builder.ensure(dist::Rls { stage: self.stage, target: self.target }).is_some() { + Rls, "rls", Self::should_build(_config), only_hosts: true, { + if builder.ensure(dist::Rls { stage: self.stage, target: self.target }).is_some() || + Self::should_install(builder) { install_rls(builder, self.stage, self.target); } else { println!("skipping Install RLS stage{} ({})", self.stage, self.target); } }; - Rustfmt, "rustfmt", _config.extended, only_hosts: true, { - if builder.ensure(dist::Rustfmt { stage: self.stage, target: self.target }).is_some() { + Rustfmt, "rustfmt", Self::should_build(_config), only_hosts: true, { + if builder.ensure(dist::Rustfmt { stage: self.stage, target: self.target }).is_some() || + Self::should_install(builder) { install_rustfmt(builder, self.stage, self.target); } else { println!("skipping Install Rustfmt stage{} ({})", self.stage, self.target); } }; - Analysis, "analysis", _config.extended, only_hosts: false, { + Analysis, "analysis", Self::should_build(_config), only_hosts: false, { builder.ensure(dist::Analysis { compiler: builder.compiler(self.stage, self.host), target: self.target }); install_analysis(builder, self.stage, self.target); }; - Src, "src", _config.extended, only_hosts: true, { + Src, "src", Self::should_build(_config) , only_hosts: true, { builder.ensure(dist::Src); install_src(builder, self.stage); }, ONLY_BUILD; diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index aae0a4f056f..83c270865c0 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -130,6 +130,7 @@ extern crate getopts; extern crate num_cpus; extern crate toml; +extern crate time; #[cfg(unix)] extern crate libc; @@ -423,6 +424,9 @@ fn std_features(&self) -> String { if self.config.profiler { features.push_str(" profiler"); } + if self.config.wasm_syscall { + features.push_str(" wasm_syscall"); + } features } @@ -662,7 +666,7 @@ fn cxx(&self, target: Interned) -> Result<&Path, String> { } } - /// Returns the path to the linker for the given target if it needs to be overriden. + /// Returns the path to the linker for the given target if it needs to be overridden. fn linker(&self, target: Interned) -> Option<&Path> { if let Some(linker) = self.config.target_config.get(&target) .and_then(|c| c.linker.as_ref()) { diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 108b0159dce..5a4791833fe 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -194,7 +194,7 @@ fn run(self, builder: &Builder) -> PathBuf { } // http://llvm.org/docs/HowToCrossCompileLLVM.html - if target != build.build { + if target != build.build && !emscripten { builder.ensure(Llvm { target: build.build, emscripten: false, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index a316b0f7ef9..f6b95f0bf97 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -113,7 +113,7 @@ fn run(self, builder: &Builder) { let _time = util::timeit(); try_run(build, builder.tool_cmd(Tool::Linkchecker) - .arg(build.out.join(host).join("doc"))); + .arg(build.out.join(host).join("doc"))); } fn should_run(run: ShouldRun) -> ShouldRun { @@ -424,6 +424,47 @@ fn path_for_cargo(builder: &Builder, compiler: Compiler) -> OsString { env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("") } +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct RustdocTheme { + pub compiler: Compiler, +} + +impl Step for RustdocTheme { + type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/tools/rustdoc-themes") + } + + fn make_run(run: RunConfig) { + let compiler = run.builder.compiler(run.builder.top_stage, run.host); + + run.builder.ensure(RustdocTheme { + compiler: compiler, + }); + } + + fn run(self, builder: &Builder) { + let rustdoc = builder.rustdoc(self.compiler.host); + let mut cmd = builder.tool_cmd(Tool::RustdocTheme); + cmd.arg(rustdoc.to_str().unwrap()) + .arg(builder.src.join("src/librustdoc/html/static/themes").to_str().unwrap()) + .env("RUSTC_STAGE", self.compiler.stage.to_string()) + .env("RUSTC_SYSROOT", builder.sysroot(self.compiler)) + .env("RUSTDOC_LIBDIR", builder.sysroot_libdir(self.compiler, self.compiler.host)) + .env("CFG_RELEASE_CHANNEL", &builder.build.config.channel) + .env("RUSTDOC_REAL", builder.rustdoc(self.compiler.host)) + .env("RUSTDOC_CRATE_VERSION", builder.build.rust_version()) + .env("RUSTC_BOOTSTRAP", "1"); + if let Some(linker) = builder.build.linker(self.compiler.host) { + cmd.env("RUSTC_TARGET_LINKER", linker); + } + try_run(builder.build, &mut cmd); + } +} + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct RustdocJS { pub host: Interned, @@ -610,7 +651,6 @@ fn run(self, builder: &Builder) { mode: "incremental", suite: "incremental-fulldeps", }, - Test { path: "src/test/run-make", mode: "run-make", suite: "run-make" }, Test { path: "src/test/rustdoc", mode: "rustdoc", suite: "rustdoc" }, Test { path: "src/test/pretty", mode: "pretty", suite: "pretty" }, @@ -619,6 +659,7 @@ fn run(self, builder: &Builder) { Test { path: "src/test/run-pass-valgrind/pretty", mode: "pretty", suite: "run-pass-valgrind" }, Test { path: "src/test/run-pass-fulldeps/pretty", mode: "pretty", suite: "run-pass-fulldeps" }, Test { path: "src/test/run-fail-fulldeps/pretty", mode: "pretty", suite: "run-fail-fulldeps" }, + Test { path: "src/test/run-make", mode: "run-make", suite: "run-make" }, ]; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -861,7 +902,7 @@ fn run(self, builder: &Builder) { } } if suite == "run-make" && !build.config.llvm_enabled { - println!("Ignoring run-make test suite as they generally dont work without LLVM"); + println!("Ignoring run-make test suite as they generally don't work without LLVM"); return; } @@ -1286,6 +1327,14 @@ fn run(self, builder: &Builder) { cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target)), build.config.nodejs.as_ref().expect("nodejs not configured")); } else if target.starts_with("wasm32") { + // Warn about running tests without the `wasm_syscall` feature enabled. + // The javascript shim implements the syscall interface so that test + // output can be correctly reported. + if !build.config.wasm_syscall { + println!("Libstd was built without `wasm_syscall` feature enabled: \ + test output may not be visible."); + } + // On the wasm32-unknown-unknown target we're using LTO which is // incompatible with `-C prefer-dynamic`, so disable that here cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index ea055cb5d1b..9036eb044b5 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -260,6 +260,7 @@ fn run(self, builder: &Builder) -> PathBuf { BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::Libstd; RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::Libstd; RustInstaller, "src/tools/rust-installer", "fabricate", Mode::Libstd; + RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes", Mode::Libstd; ); #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] diff --git a/src/ci/docker/dist-i686-freebsd/Dockerfile b/src/ci/docker/dist-i686-freebsd/Dockerfile index 686afc97289..673fa4c0c4b 100644 --- a/src/ci/docker/dist-i686-freebsd/Dockerfile +++ b/src/ci/docker/dist-i686-freebsd/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:16.04 +FROM ubuntu:18.04 RUN apt-get update && apt-get install -y --no-install-recommends \ clang \ diff --git a/src/ci/docker/dist-i686-linux/Dockerfile b/src/ci/docker/dist-i686-linux/Dockerfile index 0fd6af6e10d..5e405aa72e8 100644 --- a/src/ci/docker/dist-i686-linux/Dockerfile +++ b/src/ci/docker/dist-i686-linux/Dockerfile @@ -86,7 +86,8 @@ ENV RUST_CONFIGURE_ARGS \ --enable-extended \ --enable-sanitizers \ --enable-profiler \ - --enable-emscripten + --enable-emscripten \ + --build=i686-unknown-linux-gnu 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-netbsd/build-netbsd-toolchain.sh b/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh index 5b4314d57e6..e730dd86087 100755 --- a/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh +++ b/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh @@ -54,7 +54,7 @@ cd usr/src # The options, in order, do the following # * this is an unprivileged build # * output to a predictable location -# * disable various uneeded stuff +# * disable various unneeded stuff MKUNPRIVED=yes TOOLDIR=/x-tools/x86_64-unknown-netbsd \ MKSHARE=no MKDOC=no MKHTML=no MKINFO=no MKKMOD=no MKLINT=no MKMAN=no MKNLS=no MKPROFILE=no \ hide_output ./build.sh -j10 -m amd64 tools diff --git a/src/ci/docker/x86_64-gnu-tools/checktools.sh b/src/ci/docker/x86_64-gnu-tools/checktools.sh index b9268fe62ed..61bb5a84d21 100755 --- a/src/ci/docker/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/x86_64-gnu-tools/checktools.sh @@ -32,7 +32,7 @@ cat "$TOOLSTATE_FILE" # If this PR is intended to update one of these tools, do not let the build pass # when they do not test-pass. -for TOOL in rls rustfmt miri clippy; do +for TOOL in rls rustfmt clippy; do echo "Verifying status of $TOOL..." if echo "$CHANGED_FILES" | grep -q "^M[[:blank:]]src/tools/$TOOL$"; then echo "This PR updated 'src/tools/$TOOL', verifying if status is 'test-pass'..." diff --git a/src/ci/run.sh b/src/ci/run.sh index dab385c0964..02480c6937d 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -46,6 +46,7 @@ export RUST_RELEASE_CHANNEL=nightly if [ "$DEPLOY$DEPLOY_ALT" != "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=$RUST_RELEASE_CHANNEL" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp" + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-thinlto" if [ "$NO_LLVM_ASSERTIONS" = "1" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-llvm-assertions" diff --git a/src/dlmalloc b/src/dlmalloc index d3812c3acca..9b2dcac06c3 160000 --- a/src/dlmalloc +++ b/src/dlmalloc @@ -1 +1 @@ -Subproject commit d3812c3accaee7ad23068ed4fc089cc05c7a538f +Subproject commit 9b2dcac06c3e23235f8997b3c5f2325a6d3382df diff --git a/src/doc/book b/src/doc/book index 194eb8d5f17..ec5660820de 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 194eb8d5f1753fb5f4501011cebdc1b585712474 +Subproject commit ec5660820dea91df470dab0b9eb26ef798f20889 diff --git a/src/doc/nomicon b/src/doc/nomicon index fec3182d0b0..ad5ddd62c09 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit fec3182d0b0a3cf8122e192b3270064a5b19be5b +Subproject commit ad5ddd62c098d5b424151beda574ae7df2154df1 diff --git a/src/doc/reference b/src/doc/reference index 1d791b55b23..254df654a9b 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 1d791b55b23ec5389fbd5b3cee80db3f8bbdd162 +Subproject commit 254df654a9b75abf6ca08806535dbe1fad41be3f diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 4ebb8169dfe..919980be7df 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 4ebb8169dfe569b3dcbeab560607800bb717978a +Subproject commit 919980be7df4ea7d45a9dca8efc34da89bcf7d6b diff --git a/src/doc/unstable-book/src/language-features/generators.md b/src/doc/unstable-book/src/language-features/generators.md index 7a559a7bec8..e8e2132dca2 100644 --- a/src/doc/unstable-book/src/language-features/generators.md +++ b/src/doc/unstable-book/src/language-features/generators.md @@ -139,11 +139,11 @@ closure-like semantics. Namely: types and such. * Traits like `Send` and `Sync` are automatically implemented for a `Generator` - depending on the captured variables of the environment. Unlike closures though + depending on the captured variables of the environment. Unlike closures, generators also depend on variables live across suspension points. This means that although the ambient environment may be `Send` or `Sync`, the generator itself may not be due to internal variables live across `yield` points being - not-`Send` or not-`Sync`. Note, though, that generators, like closures, do + not-`Send` or not-`Sync`. Note that generators, like closures, do not implement traits like `Copy` or `Clone` automatically. * Whenever a generator is dropped it will drop all captured environment @@ -155,7 +155,7 @@ lifted at a future date, the design is ongoing! ### Generators as state machines -In the compiler generators are currently compiled as state machines. Each +In the compiler, generators are currently compiled as state machines. Each `yield` expression will correspond to a different state that stores all live variables over that suspension point. Resumption of a generator will dispatch on the current state and then execute internally until a `yield` is reached, at 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 0137a052a62..c5167418614 100644 --- a/src/doc/unstable-book/src/language-features/lang-items.md +++ b/src/doc/unstable-book/src/language-features/lang-items.md @@ -37,28 +37,23 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { p } -#[lang = "exchange_free"] -unsafe fn deallocate(ptr: *mut u8, _size: usize, _align: usize) { - libc::free(ptr as *mut libc::c_void) -} - #[lang = "box_free"] unsafe fn box_free(ptr: *mut T) { - deallocate(ptr as *mut u8, ::core::mem::size_of_val(&*ptr), ::core::mem::align_of_val(&*ptr)); + libc::free(ptr as *mut libc::c_void) } #[start] -fn main(argc: isize, argv: *const *const u8) -> isize { - let x = box 1; +fn main(_argc: isize, _argv: *const *const u8) -> isize { + let _x = box 1; 0 } #[lang = "eh_personality"] extern fn rust_eh_personality() {} #[lang = "panic_fmt"] extern fn rust_begin_panic() -> ! { unsafe { intrinsics::abort() } } -# #[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {} -# #[no_mangle] pub extern fn rust_eh_register_frames () {} -# #[no_mangle] pub extern fn rust_eh_unregister_frames () {} +#[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {} +#[no_mangle] pub extern fn rust_eh_register_frames () {} +#[no_mangle] pub extern fn rust_eh_unregister_frames () {} ``` Note the use of `abort`: the `exchange_malloc` lang item is assumed to @@ -80,7 +75,7 @@ Other features provided by lang items include: Lang items are loaded lazily by the compiler; e.g. if one never uses `Box` then there is no need to define functions for `exchange_malloc` -and `exchange_free`. `rustc` will emit an error when an item is needed +and `box_free`. `rustc` will emit an error when an item is needed but not found in the current crate or any that it depends on. Most lang items are defined by `libcore`, but if you're trying to build @@ -318,4 +313,4 @@ the source code. - `phantom_data`: `libcore/marker.rs` - `freeze`: `libcore/marker.rs` - `debug_trait`: `libcore/fmt/mod.rs` - - `non_zero`: `libcore/nonzero.rs` \ No newline at end of file + - `non_zero`: `libcore/nonzero.rs` diff --git a/src/doc/unstable-book/src/language-features/macro-at-most-once-rep.md b/src/doc/unstable-book/src/language-features/macro-at-most-once-rep.md new file mode 100644 index 00000000000..dbaf91b6e78 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/macro-at-most-once-rep.md @@ -0,0 +1,17 @@ +# `macro_at_most_once_rep` + +The tracking issue for this feature is: TODO(mark-i-m) + +With this feature gate enabled, one can use `?` as a Kleene operator meaning "0 +or 1 repetitions" in a macro definition. Previously only `+` and `*` were allowed. + +For example: +```rust +macro_rules! foo { + (something $(,)?) // `?` indicates `,` is "optional"... + => {} +} +``` + +------------------------ + diff --git a/src/doc/unstable-book/src/language-features/match-beginning-vert.md b/src/doc/unstable-book/src/language-features/match-beginning-vert.md deleted file mode 100644 index f0a51af7fd1..00000000000 --- a/src/doc/unstable-book/src/language-features/match-beginning-vert.md +++ /dev/null @@ -1,23 +0,0 @@ -# `match_beginning_vert` - -The tracking issue for this feature is [#44101]. - -With this feature enabled, you are allowed to add a '|' to the beginning of a -match arm: - -```rust -#![feature(match_beginning_vert)] - -enum Foo { A, B, C } - -fn main() { - let x = Foo::A; - match x { - | Foo::A - | Foo::B => println!("AB"), - | Foo::C => println!("C"), - } -} -``` - -[#44101]: https://github.com/rust-lang/rust/issues/44101 \ No newline at end of file diff --git a/src/doc/unstable-book/src/language-features/use-nested-groups.md b/src/doc/unstable-book/src/language-features/use-nested-groups.md deleted file mode 100644 index 47b635bad73..00000000000 --- a/src/doc/unstable-book/src/language-features/use-nested-groups.md +++ /dev/null @@ -1,90 +0,0 @@ -# `use_nested_groups` - -The tracking issue for this feature is: [#44494] - -[#44494]: https://github.com/rust-lang/rust/issues/44494 - ------------------------- - -The `use_nested_groups` feature allows you to import multiple items from a -complex module tree easily, by nesting different imports in the same -declaration. For example: - -```rust -#![feature(use_nested_groups)] -# #![allow(unused_imports, dead_code)] -# -# mod foo { -# pub mod bar { -# pub type Foo = (); -# } -# pub mod baz { -# pub mod quux { -# pub type Bar = (); -# } -# } -# } - -use foo::{ - bar::{self, Foo}, - baz::{*, quux::Bar}, -}; -# -# fn main() {} -``` - -## Snippet for the book's new features appendix - -When stabilizing, add this to -`src/doc/book/second-edition/src/appendix-07-newest-features.md`: - -### Nested groups in `use` declarations - -If you have a complex module tree with many different submodules and you need -to import a few items from each one, it might be useful to group all the -imports in the same declaration to keep your code clean and avoid repeating the -base modules' name. - -The `use` declaration supports nesting to help you in those cases, both with -simple imports and glob ones. For example this snippets imports `bar`, `Foo`, -all the items in `baz` and `Bar`: - -```rust -# #![feature(use_nested_groups)] -# #![allow(unused_imports, dead_code)] -# -# mod foo { -# pub mod bar { -# pub type Foo = (); -# } -# pub mod baz { -# pub mod quux { -# pub type Bar = (); -# } -# } -# } -# -use foo::{ - bar::{self, Foo}, - baz::{*, quux::Bar}, -}; -# -# fn main() {} -``` - -## Updated reference - -When stabilizing, replace the shortcut list in -`src/doc/reference/src/items/use-declarations.md` with this updated one: - -* Simultaneously binding a list of paths with a common prefix, using the - glob-like brace syntax `use a::b::{c, d, e::f, g::h::i};` -* Simultaneously binding a list of paths with a common prefix and their common - parent module, using the `self` keyword, such as `use a::b::{self, c, d::e};` -* Rebinding the target name as a new local name, using the syntax `use p::q::r - as x;`. This can also be used with the last two features: - `use a::b::{self as ab, c as abc}`. -* Binding all paths matching a given prefix, using the asterisk wildcard syntax - `use a::b::*;`. -* Nesting groups of the previous features multiple times, such as - `use a::b::{self as ab, c d::{*, e::f}};` diff --git a/src/etc/installer/msi/rust.wxs b/src/etc/installer/msi/rust.wxs index d95b096d732..a471ccc6f5b 100644 --- a/src/etc/installer/msi/rust.wxs +++ b/src/etc/installer/msi/rust.wxs @@ -18,7 +18,7 @@ - + @@ -129,7 +129,7 @@ - + diff --git a/src/etc/platform-intrinsics/generator.py b/src/etc/platform-intrinsics/generator.py index e9cf71c32fe..d9f78978a25 100644 --- a/src/etc/platform-intrinsics/generator.py +++ b/src/etc/platform-intrinsics/generator.py @@ -591,7 +591,7 @@ def parse_args(): The X86 architecture is specified as multiple files (for the different instruction sets that x86 supports). To generate the compiler definitions one needs to pass the script a "platform information file" - (with the -i flag) next to the files of the different intruction sets. + (with the -i flag) next to the files of the different instruction sets. For example, to generate the X86 compiler-definitions for SSE4.2, just: python generator.py --format compiler-defs -i x86/info.json sse42.json diff --git a/src/etc/test-float-parse/runtests.py b/src/etc/test-float-parse/runtests.py index d520c9bd5c3..e9f5bba2312 100644 --- a/src/etc/test-float-parse/runtests.py +++ b/src/etc/test-float-parse/runtests.py @@ -41,7 +41,7 @@ Instead, we take the input and compute the true value with bignum arithmetic (as a fraction, using the ``fractions`` module). Given an input string and the corresponding float computed via Rust, simply -decode the float into f * 2^k (for intergers f, k) and the ULP. +decode the float into f * 2^k (for integers f, k) and the ULP. We can now easily compute the error and check if it is within 0.5 ULP as it should be. Zero and infinites are handled similarly: diff --git a/src/etc/wasm32-shim.js b/src/etc/wasm32-shim.js index d55083e0f8e..69647f37eec 100644 --- a/src/etc/wasm32-shim.js +++ b/src/etc/wasm32-shim.js @@ -28,14 +28,76 @@ let m = new WebAssembly.Module(buffer); let memory = null; +function viewstruct(data, fields) { + return new Uint32Array(memory.buffer).subarray(data/4, data/4 + fields); +} + function copystr(a, b) { - if (memory === null) { - return null - } - let view = new Uint8Array(memory.buffer).slice(a, a + b); + let view = new Uint8Array(memory.buffer).subarray(a, a + b); return String.fromCharCode.apply(null, view); } +function syscall_write([fd, ptr, len]) { + let s = copystr(ptr, len); + switch (fd) { + case 1: process.stdout.write(s); break; + case 2: process.stderr.write(s); break; + } +} + +function syscall_exit([code]) { + process.exit(code); +} + +function syscall_args(params) { + let [ptr, len] = params; + + // Calculate total required buffer size + let totalLen = -1; + for (let i = 2; i < process.argv.length; ++i) { + totalLen += Buffer.byteLength(process.argv[i]) + 1; + } + if (totalLen < 0) { totalLen = 0; } + params[2] = totalLen; + + // If buffer is large enough, copy data + if (len >= totalLen) { + let view = new Uint8Array(memory.buffer); + for (let i = 2; i < process.argv.length; ++i) { + let value = process.argv[i]; + Buffer.from(value).copy(view, ptr); + ptr += Buffer.byteLength(process.argv[i]) + 1; + } + } +} + +function syscall_getenv(params) { + let [keyPtr, keyLen, valuePtr, valueLen] = params; + + let key = copystr(keyPtr, keyLen); + let value = process.env[key]; + + if (value == null) { + params[4] = 0xFFFFFFFF; + } else { + let view = new Uint8Array(memory.buffer); + let totalLen = Buffer.byteLength(value); + params[4] = totalLen; + if (valueLen >= totalLen) { + Buffer.from(value).copy(view, valuePtr); + } + } +} + +function syscall_time(params) { + let t = Date.now(); + let secs = Math.floor(t / 1000); + let millis = t % 1000; + params[1] = Math.floor(secs / 0x100000000); + params[2] = secs % 0x100000000; + params[3] = Math.floor(millis * 1000000); +} + let imports = {}; imports.env = { // These are generated by LLVM itself for various intrinsic calls. Hopefully @@ -48,68 +110,25 @@ imports.env = { log10: Math.log10, log10f: Math.log10, - // These are called in src/libstd/sys/wasm/stdio.rs and are used when - // debugging is enabled. - rust_wasm_write_stdout: function(a, b) { - let s = copystr(a, b); - if (s !== null) { - process.stdout.write(s); - } - }, - rust_wasm_write_stderr: function(a, b) { - let s = copystr(a, b); - if (s !== null) { - process.stderr.write(s); - } - }, - - // These are called in src/libstd/sys/wasm/args.rs and are used when - // debugging is enabled. - rust_wasm_args_count: function() { - if (memory === null) - return 0; - return process.argv.length - 2; - }, - rust_wasm_args_arg_size: function(i) { - return Buffer.byteLength(process.argv[i + 2]); - }, - rust_wasm_args_arg_fill: function(idx, ptr) { - let arg = process.argv[idx + 2]; - let view = new Uint8Array(memory.buffer); - Buffer.from(arg).copy(view, ptr); - }, - - // These are called in src/libstd/sys/wasm/os.rs and are used when - // debugging is enabled. - rust_wasm_getenv_len: function(a, b) { - let key = copystr(a, b); - if (key === null) { - return -1; + rust_wasm_syscall: function(index, data) { + switch (index) { + case 1: syscall_write(viewstruct(data, 3)); return true; + case 2: syscall_exit(viewstruct(data, 1)); return true; + case 3: syscall_args(viewstruct(data, 3)); return true; + case 4: syscall_getenv(viewstruct(data, 5)); return true; + case 6: syscall_time(viewstruct(data, 4)); return true; + default: + console.log("Unsupported syscall: " + index); + return false; } - if (!(key in process.env)) { - return -1; - } - return Buffer.byteLength(process.env[key]); - }, - rust_wasm_getenv_data: function(a, b, ptr) { - let key = copystr(a, b); - let value = process.env[key]; - let view = new Uint8Array(memory.buffer); - Buffer.from(value).copy(view, ptr); - }, -}; - -let module_imports = WebAssembly.Module.imports(m); - -for (var i = 0; i < module_imports.length; i++) { - let imp = module_imports[i]; - if (imp.module != 'env') { - continue } - if (imp.name == 'memory' && imp.kind == 'memory') { - memory = new WebAssembly.Memory({initial: 20}); - imports.env.memory = memory; - } -} +}; let instance = new WebAssembly.Instance(m, imports); +memory = instance.exports.memory; +try { + instance.exports.main(); +} catch (e) { + console.error(e); + process.exit(101); +} diff --git a/src/liballoc/btree/map.rs b/src/liballoc/btree/map.rs index b114dc640fb..b320bed5432 100644 --- a/src/liballoc/btree/map.rs +++ b/src/liballoc/btree/map.rs @@ -1748,6 +1748,11 @@ impl<'a, K: Ord, Q: ?Sized, V> Index<&'a Q> for BTreeMap { type Output = V; + /// Returns a reference to the value corresponding to the supplied key. + /// + /// # Panics + /// + /// Panics if the key is not present in the `BTreeMap`. #[inline] fn index(&self, key: &Q) -> &V { self.get(key).expect("no entry found for key") diff --git a/src/libbacktrace/ltmain.sh b/src/libbacktrace/ltmain.sh index eff9e62be8a..fd23815fc61 100644 --- a/src/libbacktrace/ltmain.sh +++ b/src/libbacktrace/ltmain.sh @@ -487,7 +487,7 @@ func_mkdir_p () # While some portion of DIR does not yet exist... while test ! -d "$my_directory_path"; do # ...make a list in topmost first order. Use a colon delimited - # list incase some portion of path contains whitespace. + # list in case some portion of path contains whitespace. my_dir_list="$my_directory_path:$my_dir_list" # If the last portion added has no slash in it, the list is done diff --git a/src/libbacktrace/macho.c b/src/libbacktrace/macho.c index 9af14e724b4..ba7f94c079f 100644 --- a/src/libbacktrace/macho.c +++ b/src/libbacktrace/macho.c @@ -327,7 +327,7 @@ macho_get_commands (struct backtrace_state *state, int descriptor, goto end; file_header_view_valid = 1; - // The endianess of the slice may be different than the fat image + // The endianness of the slice may be different than the fat image switch (*(uint32_t *) file_header_view.data) { case MH_MAGIC: diff --git a/src/libcompiler_builtins b/src/libcompiler_builtins index 0a95675bab8..345447948f7 160000 --- a/src/libcompiler_builtins +++ b/src/libcompiler_builtins @@ -1 +1 @@ -Subproject commit 0a95675bab808c49f86208bacc89c5d9c53ac43f +Subproject commit 345447948f7a51eca970fa036cefd613d54a4f79 diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 338e5c7fd95..566bfe2a3fb 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -367,9 +367,36 @@ impl TypeId { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(stage0)] pub fn of() -> TypeId { TypeId { t: unsafe { intrinsics::type_id::() }, } } + + /// Returns the `TypeId` of the type this generic function has been + /// instantiated with. + /// + /// # Examples + /// + /// ``` + /// use std::any::{Any, TypeId}; + /// + /// fn is_string(_s: &T) -> bool { + /// TypeId::of::() == TypeId::of::() + /// } + /// + /// fn main() { + /// assert_eq!(is_string(&0), false); + /// assert_eq!(is_string(&"cookie monster".to_string()), true); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature="const_type_id")] + #[cfg(not(stage0))] + pub const fn of() -> TypeId { + TypeId { + t: unsafe { intrinsics::type_id::() }, + } + } } diff --git a/src/libcore/char.rs b/src/libcore/char.rs index e8b81db0706..7215bd2a476 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -211,7 +211,7 @@ fn from(i: u8) -> Self { /// An error which can be returned when parsing a char. #[stable(feature = "char_from_str", since = "1.20.0")] -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct ParseCharError { kind: CharErrorKind, } diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index e815d72d366..d3a83dc795c 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -141,9 +141,9 @@ pub trait AsRef { /// /// # Generic Implementations /// -/// - `AsMut` auto-dereferences if the inner type is a reference or a mutable -/// reference (e.g.: `foo.as_ref()` will work the same if `foo` has type -/// `&mut Foo` or `&&mut Foo`) +/// - `AsMut` auto-dereferences if the inner type is a mutable reference +/// (e.g.: `foo.as_mut()` will work the same if `foo` has type `&mut Foo` +/// or `&mut &mut Foo`) /// /// # Examples /// diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 65aacb23bd7..8ad5a9861a0 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -530,9 +530,12 @@ fn fmt(&self, fmt: &mut Formatter) -> Result { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "`{Self}` cannot be formatted using `:?`; if it is \ - defined in your crate, add `#[derive(Debug)]` or \ - manually implement it"] +#[rustc_on_unimplemented( + on(crate_local, label="`{Self}` cannot be formatted using `:?`; \ + add `#[derive(Debug)]` or manually implement `{Debug}`"), + message="`{Self}` doesn't implement `{Debug}`", + label="`{Self}` cannot be formatted using `:?` because it doesn't implement `{Debug}`", +)] #[lang = "debug_trait"] pub trait Debug { /// Formats the value using the given formatter. @@ -593,9 +596,11 @@ pub trait Debug { /// /// println!("The origin is: {}", origin); /// ``` -#[rustc_on_unimplemented = "`{Self}` cannot be formatted with the default \ - formatter; try using `:?` instead if you are using \ - a format string"] +#[rustc_on_unimplemented( + message="`{Self}` doesn't implement `{Display}`", + label="`{Self}` cannot be formatted with the default formatter; \ + try using `:?` instead if you are using a format string", +)] #[stable(feature = "rust1", since = "1.0.0")] pub trait Display { /// Formats the value using the given formatter. @@ -1586,6 +1591,7 @@ fn fmt(&self, _: &mut Formatter) -> Result { #[stable(feature = "rust1", since = "1.0.0")] impl Debug for bool { + #[inline] fn fmt(&self, f: &mut Formatter) -> Result { Display::fmt(self, f) } @@ -1748,6 +1754,7 @@ fn fmt(&self, f: &mut Formatter) -> Result { #[stable(feature = "rust1", since = "1.0.0")] impl Debug for () { + #[inline] fn fmt(&self, f: &mut Formatter) -> Result { f.pad("()") } diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index ee989854a37..2992e7cf8db 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -157,6 +157,7 @@ macro_rules! debug { ($T:ident) => { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for $T { + #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, f) } diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index a611dc02469..a05d67a304f 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -992,7 +992,7 @@ /// 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 `tmp` + /// // y and t now point to the same thing, but we need to completely forget `t` /// // because it's no longer relevant. /// mem::forget(t); /// } diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 35cd7441c66..33adb3f49dd 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -28,8 +28,13 @@ fn _assert_is_object_safe(_: &Iterator) {} /// [module-level documentation]: index.html /// [impl]: index.html#implementing-iterator #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling \ - `.iter()` or a similar method"] +#[rustc_on_unimplemented( + on( + _Self="&str", + label="`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`" + ), + label="`{Self}` is not an iterator; maybe try calling `.iter()` or a similar method" +)] #[doc(spotlight)] pub trait Iterator { /// The type of the elements being iterated over. @@ -1426,6 +1431,10 @@ fn try_fold(&mut self, init: B, mut f: F) -> R where /// Folding is useful whenever you have a collection of something, and want /// to produce a single value from it. /// + /// Note: `fold()`, and similar methods that traverse the entire iterator, + /// may not terminate for infinite iterators, even on traits for which a + /// result is determinable in finite time. + /// /// # Examples /// /// Basic usage: diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 06c29b47bf9..29b62c901f3 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -298,7 +298,21 @@ //! //! This will print the numbers `0` through `4`, each on their own line. //! +//! Bear in mind that methods on infinite iterators, even those for which a +//! result can be determined mathematically in finite time, may not terminate. +//! Specifically, methods such as [`min`], which in the general case require +//! traversing every element in the iterator, are likely not to return +//! successfully for any infinite iterators. +//! +//! ```no_run +//! let ones = std::iter::repeat(1); +//! let least = ones.min().unwrap(); // Oh no! An infinite loop! +//! // `ones.min()` causes an infinite loop, so we won't reach this point! +//! println!("The smallest number one is {}.", least); +//! ``` +//! //! [`take`]: trait.Iterator.html#method.take +//! [`min`]: trait.Iterator.html#method.min #![stable(feature = "rust1", since = "1.0.0")] @@ -307,6 +321,7 @@ use iter_private::TrustedRandomAccess; use ops::Try; use usize; +use intrinsics; #[stable(feature = "rust1", since = "1.0.0")] pub use self::iterator::Iterator; @@ -694,6 +709,49 @@ fn size_hint(&self) -> (usize, Option) { (f(inner_hint.0), inner_hint.1.map(f)) } } + + #[inline] + fn nth(&mut self, mut n: usize) -> Option { + if self.first_take { + self.first_take = false; + let first = self.iter.next(); + if n == 0 { + return first; + } + n -= 1; + } + // n and self.step are indices, we need to add 1 to get the amount of elements + // When calling `.nth`, we need to subtract 1 again to convert back to an index + // step + 1 can't overflow because `.step_by` sets `self.step` to `step - 1` + let mut step = self.step + 1; + // n + 1 could overflow + // thus, if n is usize::MAX, instead of adding one, we call .nth(step) + if n == usize::MAX { + self.iter.nth(step - 1); + } else { + n += 1; + } + + // overflow handling + loop { + let mul = n.checked_mul(step); + if unsafe { intrinsics::likely(mul.is_some()) } { + return self.iter.nth(mul.unwrap() - 1); + } + let div_n = usize::MAX / n; + let div_step = usize::MAX / step; + let nth_n = div_n * n; + let nth_step = div_step * step; + let nth = if nth_n > nth_step { + step -= div_n; + nth_n + } else { + n -= div_step; + nth_step + }; + self.iter.nth(nth - 1); + } + } } // StepBy can only make the iterator shorter, so the len will still fit. @@ -2278,6 +2336,9 @@ impl ExactSizeIterator for Take where I: ExactSizeIterator {} #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for Take where I: FusedIterator {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Take {} + /// An iterator to maintain state while iterating another iterator. /// /// This `struct` is created by the [`scan`] method on [`Iterator`]. See its diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 66a76a24df4..65b38c94dda 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -10,7 +10,7 @@ use convert::TryFrom; use mem; -use ops::{self, Add, Sub}; +use ops::{self, Add, Sub, Try}; use usize; use super::{FusedIterator, TrustedLen}; @@ -325,25 +325,26 @@ fn nth(&mut self, n: usize) -> Option { #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for ops::RangeFrom {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for ops::RangeFrom {} + #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] impl Iterator for ops::RangeInclusive { type Item = A; #[inline] fn next(&mut self) -> Option { - use cmp::Ordering::*; - - match self.start.partial_cmp(&self.end) { - Some(Less) => { + if self.start <= self.end { + if self.start < self.end { let n = self.start.add_one(); Some(mem::replace(&mut self.start, n)) - }, - Some(Equal) => { + } else { let last = self.start.replace_one(); self.end.replace_zero(); Some(last) - }, - _ => None, + } + } else { + None } } @@ -397,26 +398,68 @@ fn min(mut self) -> Option { fn max(mut self) -> Option { self.next_back() } + + #[inline] + fn try_fold(&mut self, init: B, mut f: F) -> R where + Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try + { + let mut accum = init; + if self.start <= self.end { + loop { + let (x, done) = + if self.start < self.end { + let n = self.start.add_one(); + (mem::replace(&mut self.start, n), false) + } else { + self.end.replace_zero(); + (self.start.replace_one(), true) + }; + accum = f(accum, x)?; + if done { break } + } + } + Try::from_ok(accum) + } } #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] impl DoubleEndedIterator for ops::RangeInclusive { #[inline] fn next_back(&mut self) -> Option { - use cmp::Ordering::*; - - match self.start.partial_cmp(&self.end) { - Some(Less) => { + if self.start <= self.end { + if self.start < self.end { let n = self.end.sub_one(); Some(mem::replace(&mut self.end, n)) - }, - Some(Equal) => { + } else { let last = self.end.replace_zero(); self.start.replace_one(); Some(last) - }, - _ => None, + } + } else { + None + } + } + + #[inline] + fn try_rfold(&mut self, init: B, mut f: F) -> R where + Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try + { + let mut accum = init; + if self.start <= self.end { + loop { + let (x, done) = + if self.start < self.end { + let n = self.end.sub_one(); + (mem::replace(&mut self.end, n), false) + } else { + self.start.replace_one(); + (self.end.replace_zero(), true) + }; + accum = f(accum, x)?; + if done { break } + } } + Try::from_ok(accum) } } diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs index b405f35d5e4..b05a893e661 100644 --- a/src/libcore/iter/sources.rs +++ b/src/libcore/iter/sources.rs @@ -44,6 +44,9 @@ fn next_back(&mut self) -> Option { Some(self.element.clone()) } #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for Repeat {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Repeat {} + /// Creates a new iterator that endlessly repeats a single element. /// /// The `repeat()` function repeats a single value over and over and over and diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 11e668d228c..be4889f2487 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -970,9 +970,11 @@ impl<'a, I: FusedIterator + ?Sized> FusedIterator for &'a mut I {} /// The iterator reports a size hint where it is either exact /// (lower bound is equal to upper bound), or the upper bound is [`None`]. /// The upper bound must only be [`None`] if the actual iterator length is -/// larger than [`usize::MAX`]. +/// larger than [`usize::MAX`]. In that case, the lower bound must be +/// [`usize::MAX`], resulting in a [`.size_hint`] of `(usize::MAX, None)`. /// -/// The iterator must produce exactly the number of elements it reported. +/// The iterator must produce exactly the number of elements it reported +/// or diverge before reaching the end. /// /// # Safety /// diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index d5190b65863..59a296c2a76 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -91,6 +91,7 @@ #![feature(untagged_unions)] #![feature(unwind_attributes)] #![feature(doc_spotlight)] +#![feature(rustc_const_unstable)] #[prelude_import] #[allow(unused)] @@ -168,6 +169,7 @@ pub mod str; pub mod hash; pub mod fmt; +pub mod time; // note: does not need to be public mod char_private; diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index f00128a8147..cc5cf6523a9 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -327,7 +327,7 @@ macro_rules! debug_assert_ne { /// } /// } /// -/// // The prefered method of quick returning Errors +/// // The preferred method of quick returning Errors /// fn write_to_file_question() -> Result<(), MyError> { /// let mut file = File::create("my_best_friends.txt")?; /// file.write_all(b"This is a list of my best friends.")?; diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 93f6a0214d7..21a0beccbf6 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -189,6 +189,7 @@ pub fn forget(t: T) { /// Type | size_of::\() /// ---- | --------------- /// () | 0 +/// bool | 1 /// u8 | 1 /// u16 | 2 /// u32 | 4 diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 207df84d080..3586fa5442f 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -239,7 +239,9 @@ fn powi(self, n: i32) -> f32 { /// Converts to degrees, assuming the number is in radians. #[inline] fn to_degrees(self) -> f32 { - self * (180.0f32 / consts::PI) + // Use a constant for better precision. + const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32; + self * PIS_IN_180 } /// Converts to radians, assuming the number is in degrees. diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 9206132e8b4..64c0d508b38 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -237,6 +237,9 @@ fn powi(self, n: i32) -> f64 { /// Converts to degrees, assuming the number is in radians. #[inline] fn to_degrees(self) -> f64 { + // The division here is correctly rounded with respect to the true + // value of 180/π. (This differs from f32, where a constant must be + // used to ensure a correctly rounded result.) self * (180.0f64 / consts::PI) } diff --git a/src/libcore/ops/arith.rs b/src/libcore/ops/arith.rs index 8b3d662a6db..88db019b02f 100644 --- a/src/libcore/ops/arith.rs +++ b/src/libcore/ops/arith.rs @@ -75,7 +75,18 @@ /// ``` #[lang = "add"] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} + {RHS}`"] +#[rustc_on_unimplemented( + on( + all(_Self="{integer}", RHS="{float}"), + message="cannot add a float to an integer", + ), + on( + all(_Self="{float}", RHS="{integer}"), + message="cannot add an integer to a float", + ), + message="cannot add `{RHS}` to `{Self}`", + label="no implementation for `{Self} + {RHS}`", +)] pub trait Add { /// The resulting type after applying the `+` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -170,7 +181,8 @@ fn add(self, other: $t) -> $t { self + other } /// ``` #[lang = "sub"] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} - {RHS}`"] +#[rustc_on_unimplemented(message="cannot subtract `{RHS}` from `{Self}`", + label="no implementation for `{Self} - {RHS}`")] pub trait Sub { /// The resulting type after applying the `-` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -287,7 +299,8 @@ fn sub(self, other: $t) -> $t { self - other } /// ``` #[lang = "mul"] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} * {RHS}`"] +#[rustc_on_unimplemented(message="cannot multiply `{RHS}` to `{Self}`", + label="no implementation for `{Self} * {RHS}`")] pub trait Mul { /// The resulting type after applying the `*` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -408,7 +421,8 @@ fn mul(self, other: $t) -> $t { self * other } /// ``` #[lang = "div"] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} / {RHS}`"] +#[rustc_on_unimplemented(message="cannot divide `{Self}` by `{RHS}`", + label="no implementation for `{Self} / {RHS}`")] pub trait Div { /// The resulting type after applying the `/` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -490,7 +504,8 @@ fn div(self, other: $t) -> $t { self / other } /// ``` #[lang = "rem"] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} % {RHS}`"] +#[rustc_on_unimplemented(message="cannot mod `{Self}` by `{RHS}`", + label="no implementation for `{Self} % {RHS}`")] pub trait Rem { /// The resulting type after applying the `%` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -647,7 +662,8 @@ macro_rules! neg_impl_unsigned { /// ``` #[lang = "add_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} += {Rhs}`"] +#[rustc_on_unimplemented(message="cannot add-assign `{Rhs}` to `{Self}`", + label="no implementation for `{Self} += {Rhs}`")] pub trait AddAssign { /// Performs the `+=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] @@ -700,7 +716,8 @@ fn add_assign(&mut self, other: $t) { *self += other } /// ``` #[lang = "sub_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} -= {Rhs}`"] +#[rustc_on_unimplemented(message="cannot subtract-assign `{Rhs}` from `{Self}`", + label="no implementation for `{Self} -= {Rhs}`")] pub trait SubAssign { /// Performs the `-=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] @@ -744,7 +761,8 @@ fn sub_assign(&mut self, other: $t) { *self -= other } /// ``` #[lang = "mul_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} *= {Rhs}`"] +#[rustc_on_unimplemented(message="cannot multiply-assign `{Rhs}` to `{Self}`", + label="no implementation for `{Self} *= {Rhs}`")] pub trait MulAssign { /// Performs the `*=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] @@ -788,7 +806,8 @@ fn mul_assign(&mut self, other: $t) { *self *= other } /// ``` #[lang = "div_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} /= {Rhs}`"] +#[rustc_on_unimplemented(message="cannot divide-assign `{Self}` by `{Rhs}`", + label="no implementation for `{Self} /= {Rhs}`")] pub trait DivAssign { /// Performs the `/=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] @@ -835,7 +854,8 @@ fn div_assign(&mut self, other: $t) { *self /= other } /// ``` #[lang = "rem_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} %= {Rhs}`"] +#[rustc_on_unimplemented(message="cannot mod-assign `{Self}` by `{Rhs}``", + label="no implementation for `{Self} %= {Rhs}`")] pub trait RemAssign { /// Performs the `%=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] diff --git a/src/libcore/ops/bit.rs b/src/libcore/ops/bit.rs index 7ac5fc4debf..a0ecd6cf75c 100644 --- a/src/libcore/ops/bit.rs +++ b/src/libcore/ops/bit.rs @@ -120,7 +120,8 @@ fn not(self) -> $t { !self } /// ``` #[lang = "bitand"] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} & {RHS}`"] +#[rustc_on_unimplemented(message="no implementation for `{Self} & {RHS}`", + label="no implementation for `{Self} & {RHS}`")] pub trait BitAnd { /// The resulting type after applying the `&` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -201,7 +202,8 @@ fn bitand(self, rhs: $t) -> $t { self & rhs } /// ``` #[lang = "bitor"] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} | {RHS}`"] +#[rustc_on_unimplemented(message="no implementation for `{Self} | {RHS}`", + label="no implementation for `{Self} | {RHS}`")] pub trait BitOr { /// The resulting type after applying the `|` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -285,7 +287,8 @@ fn bitor(self, rhs: $t) -> $t { self | rhs } /// ``` #[lang = "bitxor"] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} ^ {RHS}`"] +#[rustc_on_unimplemented(message="no implementation for `{Self} ^ {RHS}`", + label="no implementation for `{Self} ^ {RHS}`")] pub trait BitXor { /// The resulting type after applying the `^` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -365,7 +368,8 @@ fn bitxor(self, other: $t) -> $t { self ^ other } /// ``` #[lang = "shl"] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} << {RHS}`"] +#[rustc_on_unimplemented(message="no implementation for `{Self} << {RHS}`", + label="no implementation for `{Self} << {RHS}`")] pub trait Shl { /// The resulting type after applying the `<<` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -466,7 +470,8 @@ macro_rules! shl_impl_all { /// ``` #[lang = "shr"] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} >> {RHS}`"] +#[rustc_on_unimplemented(message="no implementation for `{Self} >> {RHS}`", + label="no implementation for `{Self} >> {RHS}`")] pub trait Shr { /// The resulting type after applying the `>>` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -579,7 +584,8 @@ macro_rules! shr_impl_all { /// ``` #[lang = "bitand_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} &= {Rhs}`"] +#[rustc_on_unimplemented(message="no implementation for `{Self} &= {Rhs}`", + label="no implementation for `{Self} &= {Rhs}`")] pub trait BitAndAssign { /// Performs the `&=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] @@ -626,7 +632,8 @@ fn bitand_assign(&mut self, other: $t) { *self &= other } /// ``` #[lang = "bitor_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} |= {Rhs}`"] +#[rustc_on_unimplemented(message="no implementation for `{Self} |= {Rhs}`", + label="no implementation for `{Self} |= {Rhs}`")] pub trait BitOrAssign { /// Performs the `|=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] @@ -673,7 +680,8 @@ fn bitor_assign(&mut self, other: $t) { *self |= other } /// ``` #[lang = "bitxor_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} ^= {Rhs}`"] +#[rustc_on_unimplemented(message="no implementation for `{Self} ^= {Rhs}`", + label="no implementation for `{Self} ^= {Rhs}`")] pub trait BitXorAssign { /// Performs the `^=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] @@ -718,7 +726,8 @@ fn bitxor_assign(&mut self, other: $t) { *self ^= other } /// ``` #[lang = "shl_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} <<= {Rhs}`"] +#[rustc_on_unimplemented(message="no implementation for `{Self} <<= {Rhs}`", + label="no implementation for `{Self} <<= {Rhs}`")] pub trait ShlAssign { /// Performs the `<<=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] @@ -784,7 +793,8 @@ macro_rules! shl_assign_impl_all { /// ``` #[lang = "shr_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} >>= {Rhs}`"] +#[rustc_on_unimplemented(message="no implementation for `{Self} >>= {Rhs}`", + label="no implementation for `{Self} >>= {Rhs}`")] pub trait ShrAssign { /// Performs the `>>=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index fab5832d905..3d84e910fe6 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2461,7 +2461,7 @@ fn from(p: NonNull) -> Self { } /// Previous name of `NonNull`. -#[rustc_deprecated(since = "1.24", reason = "renamed to `NonNull`")] +#[rustc_deprecated(since = "1.25.0", reason = "renamed to `NonNull`")] #[unstable(feature = "shared", issue = "27730")] pub type Shared = NonNull; @@ -2482,26 +2482,19 @@ fn from(p: NonNull) -> Self { /// Usually this won't be necessary; covariance is correct for most safe abstractions, /// such as Box, Rc, Arc, Vec, and LinkedList. This is the case because they /// provide a public API that follows the normal shared XOR mutable rules of Rust. -#[stable(feature = "nonnull", since = "1.24.0")] +#[stable(feature = "nonnull", since = "1.25.0")] pub struct NonNull { pointer: NonZero<*const T>, } -#[stable(feature = "nonnull", since = "1.24.0")] -impl fmt::Debug for NonNull { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Pointer::fmt(&self.as_ptr(), f) - } -} - /// `NonNull` pointers are not `Send` because the data they reference may be aliased. // NB: This impl is unnecessary, but should provide better error messages. -#[stable(feature = "nonnull", since = "1.24.0")] +#[stable(feature = "nonnull", since = "1.25.0")] impl !Send for NonNull { } /// `NonNull` pointers are not `Sync` because the data they reference may be aliased. // NB: This impl is unnecessary, but should provide better error messages. -#[stable(feature = "nonnull", since = "1.24.0")] +#[stable(feature = "nonnull", since = "1.25.0")] impl !Sync for NonNull { } impl NonNull { @@ -2509,7 +2502,7 @@ impl NonNull { /// /// This is useful for initializing types which lazily allocate, like /// `Vec::new` does. - #[stable(feature = "nonnull", since = "1.24.0")] + #[stable(feature = "nonnull", since = "1.25.0")] pub fn dangling() -> Self { unsafe { let ptr = mem::align_of::() as *mut T; @@ -2524,19 +2517,19 @@ impl NonNull { /// # Safety /// /// `ptr` must be non-null. - #[stable(feature = "nonnull", since = "1.24.0")] + #[stable(feature = "nonnull", since = "1.25.0")] pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { NonNull { pointer: NonZero::new_unchecked(ptr) } } /// Creates a new `NonNull` if `ptr` is non-null. - #[stable(feature = "nonnull", since = "1.24.0")] + #[stable(feature = "nonnull", since = "1.25.0")] pub fn new(ptr: *mut T) -> Option { NonZero::new(ptr as *const T).map(|nz| NonNull { pointer: nz }) } /// Acquires the underlying `*mut` pointer. - #[stable(feature = "nonnull", since = "1.24.0")] + #[stable(feature = "nonnull", since = "1.25.0")] pub fn as_ptr(self) -> *mut T { self.pointer.get() as *mut T } @@ -2546,7 +2539,7 @@ pub fn as_ptr(self) -> *mut T { /// The resulting lifetime is bound to self so this behaves "as if" /// it were actually an instance of T that is getting borrowed. If a longer /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`. - #[stable(feature = "nonnull", since = "1.24.0")] + #[stable(feature = "nonnull", since = "1.25.0")] pub unsafe fn as_ref(&self) -> &T { &*self.as_ptr() } @@ -2556,47 +2549,93 @@ pub unsafe fn as_ref(&self) -> &T { /// The resulting lifetime is bound to self so this behaves "as if" /// it were actually an instance of T that is getting borrowed. If a longer /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`. - #[stable(feature = "nonnull", since = "1.24.0")] + #[stable(feature = "nonnull", since = "1.25.0")] pub unsafe fn as_mut(&mut self) -> &mut T { &mut *self.as_ptr() } + + /// Cast to a pointer of another type + #[unstable(feature = "nonnull_cast", issue = "47653")] + pub fn cast(self) -> NonNull { + unsafe { + NonNull::new_unchecked(self.as_ptr() as *mut U) + } + } } -#[stable(feature = "nonnull", since = "1.24.0")] +#[stable(feature = "nonnull", since = "1.25.0")] impl Clone for NonNull { fn clone(&self) -> Self { *self } } -#[stable(feature = "nonnull", since = "1.24.0")] +#[stable(feature = "nonnull", since = "1.25.0")] impl Copy for NonNull { } -#[stable(feature = "nonnull", since = "1.24.0")] +#[stable(feature = "nonnull", since = "1.25.0")] impl CoerceUnsized> for NonNull where T: Unsize { } -#[stable(feature = "nonnull", since = "1.24.0")] +#[stable(feature = "nonnull", since = "1.25.0")] +impl fmt::Debug for NonNull { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Pointer::fmt(&self.as_ptr(), f) + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] impl fmt::Pointer for NonNull { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Pointer::fmt(&self.as_ptr(), f) } } -#[stable(feature = "nonnull", since = "1.24.0")] +#[stable(feature = "nonnull", since = "1.25.0")] +impl Eq for NonNull {} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl PartialEq for NonNull { + fn eq(&self, other: &Self) -> bool { + self.as_ptr() == other.as_ptr() + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl Ord for NonNull { + fn cmp(&self, other: &Self) -> Ordering { + self.as_ptr().cmp(&other.as_ptr()) + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl PartialOrd for NonNull { + fn partial_cmp(&self, other: &Self) -> Option { + self.as_ptr().partial_cmp(&other.as_ptr()) + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl hash::Hash for NonNull { + fn hash(&self, state: &mut H) { + self.as_ptr().hash(state) + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] impl From> for NonNull { fn from(unique: Unique) -> Self { NonNull { pointer: unique.pointer } } } -#[stable(feature = "nonnull", since = "1.24.0")] +#[stable(feature = "nonnull", since = "1.25.0")] impl<'a, T: ?Sized> From<&'a mut T> for NonNull { fn from(reference: &'a mut T) -> Self { NonNull { pointer: NonZero::from(reference) } } } -#[stable(feature = "nonnull", since = "1.24.0")] +#[stable(feature = "nonnull", since = "1.25.0")] impl<'a, T: ?Sized> From<&'a T> for NonNull { fn from(reference: &'a T) -> Self { NonNull { pointer: NonZero::from(reference) } diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 8b47143f63c..f22862ae701 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -945,6 +945,7 @@ macro_rules! atomic_int { $stable_debug:meta, $stable_access:meta, $stable_from:meta, + $stable_nand:meta, $s_int_type:expr, $int_ref:expr, $int_type:ident $atomic_type:ident $atomic_init:ident) => { /// An integer type which can be safely shared between threads. @@ -1325,6 +1326,29 @@ pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { unsafe { atomic_and(self.v.get(), val, order) } } + /// Bitwise "nand" with the current value. + /// + /// Performs a bitwise "nand" operation on the current value and the argument `val`, and + /// sets the new value to the result. + /// + /// Returns the previous value. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_nand)] + /// + /// use std::sync::atomic::{AtomicIsize, Ordering}; + /// + /// let foo = AtomicIsize::new(0xf731); + /// assert_eq!(foo.fetch_nand(0x137f, Ordering::SeqCst), 0xf731); + /// assert_eq!(foo.load(Ordering::SeqCst), !(0xf731 & 0x137f)); + #[inline] + #[$stable_nand] + pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type { + unsafe { atomic_nand(self.v.get(), val, order) } + } + /// Bitwise "or" with the current value. /// /// Performs a bitwise "or" operation on the current value and the argument `val`, and @@ -1377,6 +1401,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "atomic_nand", issue = "13226"), "i8", "../../../std/primitive.i8.html", i8 AtomicI8 ATOMIC_I8_INIT } @@ -1387,6 +1412,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "atomic_nand", issue = "13226"), "u8", "../../../std/primitive.u8.html", u8 AtomicU8 ATOMIC_U8_INIT } @@ -1397,6 +1423,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "atomic_nand", issue = "13226"), "i16", "../../../std/primitive.i16.html", i16 AtomicI16 ATOMIC_I16_INIT } @@ -1407,6 +1434,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "atomic_nand", issue = "13226"), "u16", "../../../std/primitive.u16.html", u16 AtomicU16 ATOMIC_U16_INIT } @@ -1417,6 +1445,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "atomic_nand", issue = "13226"), "i32", "../../../std/primitive.i32.html", i32 AtomicI32 ATOMIC_I32_INIT } @@ -1427,6 +1456,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "atomic_nand", issue = "13226"), "u32", "../../../std/primitive.u32.html", u32 AtomicU32 ATOMIC_U32_INIT } @@ -1437,6 +1467,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "atomic_nand", issue = "13226"), "i64", "../../../std/primitive.i64.html", i64 AtomicI64 ATOMIC_I64_INIT } @@ -1447,6 +1478,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "atomic_nand", issue = "13226"), "u64", "../../../std/primitive.u64.html", u64 AtomicU64 ATOMIC_U64_INIT } @@ -1457,6 +1489,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { stable(feature = "atomic_debug", since = "1.3.0"), stable(feature = "atomic_access", since = "1.15.0"), stable(feature = "atomic_from", since = "1.23.0"), + unstable(feature = "atomic_nand", issue = "13226"), "isize", "../../../std/primitive.isize.html", isize AtomicIsize ATOMIC_ISIZE_INIT } @@ -1467,6 +1500,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { stable(feature = "atomic_debug", since = "1.3.0"), stable(feature = "atomic_access", since = "1.15.0"), stable(feature = "atomic_from", since = "1.23.0"), + unstable(feature = "atomic_nand", issue = "13226"), "usize", "../../../std/primitive.usize.html", usize AtomicUsize ATOMIC_USIZE_INIT } @@ -1609,6 +1643,18 @@ unsafe fn atomic_and(dst: *mut T, val: T, order: Ordering) -> T { } } +#[inline] +unsafe fn atomic_nand(dst: *mut T, val: T, order: Ordering) -> T { + match order { + Acquire => intrinsics::atomic_nand_acq(dst, val), + Release => intrinsics::atomic_nand_rel(dst, val), + AcqRel => intrinsics::atomic_nand_acqrel(dst, val), + Relaxed => intrinsics::atomic_nand_relaxed(dst, val), + SeqCst => intrinsics::atomic_nand(dst, val), + __Nonexhaustive => panic!("invalid memory ordering"), + } +} + #[inline] unsafe fn atomic_or(dst: *mut T, val: T, order: Ordering) -> T { match order { diff --git a/src/libcore/tests/atomic.rs b/src/libcore/tests/atomic.rs index 9babe24a985..f634fabe503 100644 --- a/src/libcore/tests/atomic.rs +++ b/src/libcore/tests/atomic.rs @@ -48,6 +48,13 @@ fn uint_and() { assert_eq!(x.load(SeqCst), 0xf731 & 0x137f); } +#[test] +fn uint_nand() { + let x = AtomicUsize::new(0xf731); + assert_eq!(x.fetch_nand(0x137f, SeqCst), 0xf731); + assert_eq!(x.load(SeqCst), !(0xf731 & 0x137f)); +} + #[test] fn uint_or() { let x = AtomicUsize::new(0xf731); @@ -69,6 +76,13 @@ fn int_and() { assert_eq!(x.load(SeqCst), 0xf731 & 0x137f); } +#[test] +fn int_nand() { + let x = AtomicIsize::new(0xf731); + assert_eq!(x.fetch_nand(0x137f, SeqCst), 0xf731); + assert_eq!(x.load(SeqCst), !(0xf731 & 0x137f)); +} + #[test] fn int_or() { let x = AtomicIsize::new(0xf731); diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 8997cf9c6bf..b2a5243d5e6 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -161,6 +161,68 @@ fn test_iterator_step_by() { assert_eq!(it.next(), None); } +#[test] +fn test_iterator_step_by_nth() { + let mut it = (0..16).step_by(5); + assert_eq!(it.nth(0), Some(0)); + assert_eq!(it.nth(0), Some(5)); + assert_eq!(it.nth(0), Some(10)); + assert_eq!(it.nth(0), Some(15)); + assert_eq!(it.nth(0), None); + + let it = (0..18).step_by(5); + assert_eq!(it.clone().nth(0), Some(0)); + assert_eq!(it.clone().nth(1), Some(5)); + assert_eq!(it.clone().nth(2), Some(10)); + assert_eq!(it.clone().nth(3), Some(15)); + assert_eq!(it.clone().nth(4), None); + assert_eq!(it.clone().nth(42), None); +} + +#[test] +fn test_iterator_step_by_nth_overflow() { + #[cfg(target_pointer_width = "8")] + type Bigger = u16; + #[cfg(target_pointer_width = "16")] + type Bigger = u32; + #[cfg(target_pointer_width = "32")] + type Bigger = u64; + #[cfg(target_pointer_width = "64")] + type Bigger = u128; + + #[derive(Clone)] + struct Test(Bigger); + impl<'a> Iterator for &'a mut Test { + type Item = i32; + fn next(&mut self) -> Option { Some(21) } + fn nth(&mut self, n: usize) -> Option { + self.0 += n as Bigger + 1; + Some(42) + } + } + + let mut it = Test(0); + let root = usize::MAX >> (::std::mem::size_of::() * 8 / 2); + let n = root + 20; + (&mut it).step_by(n).nth(n); + assert_eq!(it.0, n as Bigger * n as Bigger); + + // large step + let mut it = Test(0); + (&mut it).step_by(usize::MAX).nth(5); + assert_eq!(it.0, (usize::MAX as Bigger) * 5); + + // n + 1 overflows + let mut it = Test(0); + (&mut it).step_by(2).nth(usize::MAX); + assert_eq!(it.0, (usize::MAX as Bigger) * 2); + + // n + 1 overflows + let mut it = Test(0); + (&mut it).step_by(1).nth(usize::MAX); + assert_eq!(it.0, (usize::MAX as Bigger) * 1); +} + #[test] #[should_panic] fn test_iterator_step_by_zero() { @@ -1270,6 +1332,18 @@ fn test_range_inclusive_exhaustion() { assert_eq!(r.next_back(), Some(10)); assert_eq!(r, 1..=0); + let mut r = 10..=12; + assert_eq!(r.next(), Some(10)); + assert_eq!(r.next(), Some(11)); + assert_eq!(r.next(), Some(12)); + assert_eq!(r, 1..=0); + + let mut r = 10..=12; + assert_eq!(r.next_back(), Some(12)); + assert_eq!(r.next_back(), Some(11)); + 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); @@ -1278,6 +1352,13 @@ fn test_range_inclusive_exhaustion() { assert_eq!(r.nth(5), None); assert_eq!(r, 1..=0); + let mut r = 100..=10; + assert_eq!(r.next(), None); + assert_eq!(r, 100..=10); + + let mut r = 100..=10; + assert_eq!(r.next_back(), None); + assert_eq!(r, 100..=10); } #[test] @@ -1309,6 +1390,29 @@ fn test_range_from_nth() { assert_eq!(r, 16..); assert_eq!(r.nth(10), Some(26)); assert_eq!(r, 27..); + + assert_eq!((0..).size_hint(), (usize::MAX, None)); +} + +fn is_trusted_len(_: I) {} + +#[test] +fn test_range_from_take() { + let mut it = (0..).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); + is_trusted_len((0..).take(3)); + assert_eq!((0..).take(3).size_hint(), (3, Some(3))); + assert_eq!((0..).take(0).size_hint(), (0, Some(0))); + assert_eq!((0..).take(usize::MAX).size_hint(), (usize::MAX, Some(usize::MAX))); +} + +#[test] +fn test_range_from_take_collect() { + let v: Vec<_> = (0..).take(3).collect(); + assert_eq!(v, vec![0, 1, 2]); } #[test] @@ -1397,12 +1501,52 @@ fn test_range_inclusive_min() { assert_eq!(r.min(), None); } +#[test] +fn test_range_inclusive_folds() { + assert_eq!((1..=10).sum::(), 55); + assert_eq!((1..=10).rev().sum::(), 55); + + let mut it = 40..=50; + assert_eq!(it.try_fold(0, i8::checked_add), None); + assert_eq!(it, 44..=50); + assert_eq!(it.try_rfold(0, i8::checked_add), None); + assert_eq!(it, 44..=47); + + let mut it = 10..=20; + assert_eq!(it.try_fold(0, |a,b| Some(a+b)), Some(165)); + assert_eq!(it, 1..=0); + + let mut it = 10..=20; + assert_eq!(it.try_rfold(0, |a,b| Some(a+b)), Some(165)); + assert_eq!(it, 1..=0); +} + #[test] fn test_repeat() { let mut it = repeat(42); assert_eq!(it.next(), Some(42)); assert_eq!(it.next(), Some(42)); assert_eq!(it.next(), Some(42)); + assert_eq!(repeat(42).size_hint(), (usize::MAX, None)); +} + +#[test] +fn test_repeat_take() { + let mut it = repeat(42).take(3); + assert_eq!(it.next(), Some(42)); + assert_eq!(it.next(), Some(42)); + assert_eq!(it.next(), Some(42)); + assert_eq!(it.next(), None); + is_trusted_len(repeat(42).take(3)); + assert_eq!(repeat(42).take(3).size_hint(), (3, Some(3))); + assert_eq!(repeat(42).take(0).size_hint(), (0, Some(0))); + assert_eq!(repeat(42).take(usize::MAX).size_hint(), (usize::MAX, Some(usize::MAX))); +} + +#[test] +fn test_repeat_take_collect() { + let v: Vec<_> = repeat(42).take(3).collect(); + assert_eq!(v, vec![42, 42, 42]); } #[test] diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 1c32452f846..9e90313bc0e 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -42,6 +42,7 @@ #![feature(try_from)] #![feature(try_trait)] #![feature(exact_chunks)] +#![feature(atomic_nand)] extern crate core; extern crate test; diff --git a/src/libcore/time.rs b/src/libcore/time.rs new file mode 100644 index 00000000000..1a0208d2f25 --- /dev/null +++ b/src/libcore/time.rs @@ -0,0 +1,603 @@ +// 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. +#![stable(feature = "duration_core", since = "1.24.0")] + +//! Temporal quantification. +//! +//! Example: +//! +//! ``` +//! use std::time::Duration; +//! +//! let five_seconds = Duration::new(5, 0); +//! // both declarations are equivalent +//! assert_eq!(Duration::new(5, 0), Duration::from_secs(5)); +//! ``` + +use iter::Sum; +use ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign}; + +const NANOS_PER_SEC: u32 = 1_000_000_000; +const NANOS_PER_MILLI: u32 = 1_000_000; +const NANOS_PER_MICRO: u32 = 1_000; +const MILLIS_PER_SEC: u64 = 1_000; +const MICROS_PER_SEC: u64 = 1_000_000; + +/// A `Duration` type to represent a span of time, typically used for system +/// timeouts. +/// +/// Each `Duration` is composed of a whole number of seconds and a fractional part +/// represented in nanoseconds. If the underlying system does not support +/// nanosecond-level precision, APIs binding a system timeout will typically round up +/// the number of nanoseconds. +/// +/// `Duration`s implement many common traits, including [`Add`], [`Sub`], and other +/// [`ops`] traits. +/// +/// [`Add`]: ../../std/ops/trait.Add.html +/// [`Sub`]: ../../std/ops/trait.Sub.html +/// [`ops`]: ../../std/ops/index.html +/// +/// # Examples +/// +/// ``` +/// use std::time::Duration; +/// +/// let five_seconds = Duration::new(5, 0); +/// let five_seconds_and_five_nanos = five_seconds + Duration::new(0, 5); +/// +/// assert_eq!(five_seconds_and_five_nanos.as_secs(), 5); +/// assert_eq!(five_seconds_and_five_nanos.subsec_nanos(), 5); +/// +/// let ten_millis = Duration::from_millis(10); +/// ``` +#[stable(feature = "duration_core", since = "1.24.0")] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Default)] +pub struct Duration { + secs: u64, + nanos: u32, // Always 0 <= nanos < NANOS_PER_SEC +} + +impl Duration { + /// Creates a new `Duration` from the specified number of whole seconds and + /// additional nanoseconds. + /// + /// If the number of nanoseconds is greater than 1 billion (the number of + /// nanoseconds in a second), then it will carry over into the seconds provided. + /// + /// # Panics + /// + /// This constructor will panic if the carry from the nanoseconds overflows + /// the seconds counter. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let five_seconds = Duration::new(5, 0); + /// ``` + #[stable(feature = "duration", since = "1.3.0")] + #[inline] + pub fn new(secs: u64, nanos: u32) -> Duration { + let secs = secs.checked_add((nanos / NANOS_PER_SEC) as u64) + .expect("overflow in Duration::new"); + let nanos = nanos % NANOS_PER_SEC; + Duration { secs: secs, nanos: nanos } + } + + /// Creates a new `Duration` from the specified number of whole seconds. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let duration = Duration::from_secs(5); + /// + /// assert_eq!(5, duration.as_secs()); + /// assert_eq!(0, duration.subsec_nanos()); + /// ``` + #[stable(feature = "duration", since = "1.3.0")] + #[inline] + pub const fn from_secs(secs: u64) -> Duration { + Duration { secs: secs, nanos: 0 } + } + + /// Creates a new `Duration` from the specified number of milliseconds. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let duration = Duration::from_millis(2569); + /// + /// assert_eq!(2, duration.as_secs()); + /// assert_eq!(569_000_000, duration.subsec_nanos()); + /// ``` + #[stable(feature = "duration", since = "1.3.0")] + #[inline] + pub const fn from_millis(millis: u64) -> Duration { + Duration { + secs: millis / MILLIS_PER_SEC, + nanos: ((millis % MILLIS_PER_SEC) as u32) * NANOS_PER_MILLI, + } + } + + /// Creates a new `Duration` from the specified number of microseconds. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_from_micros)] + /// use std::time::Duration; + /// + /// let duration = Duration::from_micros(1_000_002); + /// + /// assert_eq!(1, duration.as_secs()); + /// assert_eq!(2000, duration.subsec_nanos()); + /// ``` + #[unstable(feature = "duration_from_micros", issue = "44400")] + #[inline] + pub const fn from_micros(micros: u64) -> Duration { + Duration { + secs: micros / MICROS_PER_SEC, + nanos: ((micros % MICROS_PER_SEC) as u32) * NANOS_PER_MICRO, + } + } + + /// Creates a new `Duration` from the specified number of nanoseconds. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_extras)] + /// use std::time::Duration; + /// + /// let duration = Duration::from_nanos(1_000_000_123); + /// + /// assert_eq!(1, duration.as_secs()); + /// assert_eq!(123, duration.subsec_nanos()); + /// ``` + #[unstable(feature = "duration_extras", issue = "46507")] + #[inline] + pub const fn from_nanos(nanos: u64) -> Duration { + Duration { + secs: nanos / (NANOS_PER_SEC as u64), + nanos: (nanos % (NANOS_PER_SEC as u64)) as u32, + } + } + + /// Returns the number of _whole_ seconds contained by this `Duration`. + /// + /// The returned value does not include the fractional (nanosecond) part of the + /// duration, which can be obtained using [`subsec_nanos`]. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let duration = Duration::new(5, 730023852); + /// assert_eq!(duration.as_secs(), 5); + /// ``` + /// + /// To determine the total number of seconds represented by the `Duration`, + /// use `as_secs` in combination with [`subsec_nanos`]: + /// + /// ``` + /// use std::time::Duration; + /// + /// let duration = Duration::new(5, 730023852); + /// + /// assert_eq!(5.730023852, + /// duration.as_secs() as f64 + /// + duration.subsec_nanos() as f64 * 1e-9); + /// ``` + /// + /// [`subsec_nanos`]: #method.subsec_nanos + #[stable(feature = "duration", since = "1.3.0")] + #[inline] + pub fn as_secs(&self) -> u64 { self.secs } + + /// Returns the fractional part of this `Duration`, in milliseconds. + /// + /// This method does **not** return the length of the duration when + /// represented by milliseconds. The returned number always represents a + /// fractional portion of a second (i.e. it is less than one thousand). + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_extras)] + /// use std::time::Duration; + /// + /// let duration = Duration::from_millis(5432); + /// assert_eq!(duration.as_secs(), 5); + /// assert_eq!(duration.subsec_millis(), 432); + /// ``` + #[unstable(feature = "duration_extras", issue = "46507")] + #[inline] + pub fn subsec_millis(&self) -> u32 { self.nanos / NANOS_PER_MILLI } + + /// Returns the fractional part of this `Duration`, in microseconds. + /// + /// This method does **not** return the length of the duration when + /// represented by microseconds. The returned number always represents a + /// fractional portion of a second (i.e. it is less than one million). + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_extras, duration_from_micros)] + /// use std::time::Duration; + /// + /// let duration = Duration::from_micros(1_234_567); + /// assert_eq!(duration.as_secs(), 1); + /// assert_eq!(duration.subsec_micros(), 234_567); + /// ``` + #[unstable(feature = "duration_extras", issue = "46507")] + #[inline] + pub fn subsec_micros(&self) -> u32 { self.nanos / NANOS_PER_MICRO } + + /// Returns the fractional part of this `Duration`, in nanoseconds. + /// + /// This method does **not** return the length of the duration when + /// represented by nanoseconds. The returned number always represents a + /// fractional portion of a second (i.e. it is less than one billion). + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let duration = Duration::from_millis(5010); + /// assert_eq!(duration.as_secs(), 5); + /// assert_eq!(duration.subsec_nanos(), 10_000_000); + /// ``` + #[stable(feature = "duration", since = "1.3.0")] + #[inline] + pub fn subsec_nanos(&self) -> u32 { self.nanos } + + /// Checked `Duration` addition. Computes `self + other`, returning [`None`] + /// if overflow occurred. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::time::Duration; + /// + /// assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), Some(Duration::new(0, 1))); + /// assert_eq!(Duration::new(1, 0).checked_add(Duration::new(std::u64::MAX, 0)), None); + /// ``` + #[stable(feature = "duration_checked_ops", since = "1.16.0")] + #[inline] + pub fn checked_add(self, rhs: Duration) -> Option { + if let Some(mut secs) = self.secs.checked_add(rhs.secs) { + let mut nanos = self.nanos + rhs.nanos; + if nanos >= NANOS_PER_SEC { + nanos -= NANOS_PER_SEC; + if let Some(new_secs) = secs.checked_add(1) { + secs = new_secs; + } else { + return None; + } + } + debug_assert!(nanos < NANOS_PER_SEC); + Some(Duration { + secs, + nanos, + }) + } else { + None + } + } + + /// Checked `Duration` subtraction. Computes `self - other`, returning [`None`] + /// if the result would be negative or if overflow occurred. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::time::Duration; + /// + /// assert_eq!(Duration::new(0, 1).checked_sub(Duration::new(0, 0)), Some(Duration::new(0, 1))); + /// assert_eq!(Duration::new(0, 0).checked_sub(Duration::new(0, 1)), None); + /// ``` + #[stable(feature = "duration_checked_ops", since = "1.16.0")] + #[inline] + pub fn checked_sub(self, rhs: Duration) -> Option { + if let Some(mut secs) = self.secs.checked_sub(rhs.secs) { + let nanos = if self.nanos >= rhs.nanos { + self.nanos - rhs.nanos + } else { + if let Some(sub_secs) = secs.checked_sub(1) { + secs = sub_secs; + self.nanos + NANOS_PER_SEC - rhs.nanos + } else { + return None; + } + }; + debug_assert!(nanos < NANOS_PER_SEC); + Some(Duration { secs: secs, nanos: nanos }) + } else { + None + } + } + + /// Checked `Duration` multiplication. Computes `self * other`, returning + /// [`None`] if overflow occurred. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::time::Duration; + /// + /// assert_eq!(Duration::new(0, 500_000_001).checked_mul(2), Some(Duration::new(1, 2))); + /// assert_eq!(Duration::new(std::u64::MAX - 1, 0).checked_mul(2), None); + /// ``` + #[stable(feature = "duration_checked_ops", since = "1.16.0")] + #[inline] + pub fn checked_mul(self, rhs: u32) -> Option { + // Multiply nanoseconds as u64, because it cannot overflow that way. + let total_nanos = self.nanos as u64 * rhs as u64; + let extra_secs = total_nanos / (NANOS_PER_SEC as u64); + let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32; + if let Some(secs) = self.secs + .checked_mul(rhs as u64) + .and_then(|s| s.checked_add(extra_secs)) { + debug_assert!(nanos < NANOS_PER_SEC); + Some(Duration { + secs, + nanos, + }) + } else { + None + } + } + + /// Checked `Duration` division. Computes `self / other`, returning [`None`] + /// if `other == 0`. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::time::Duration; + /// + /// assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0))); + /// assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000))); + /// assert_eq!(Duration::new(2, 0).checked_div(0), None); + /// ``` + #[stable(feature = "duration_checked_ops", since = "1.16.0")] + #[inline] + pub fn checked_div(self, rhs: u32) -> Option { + if rhs != 0 { + let secs = self.secs / (rhs as u64); + let carry = self.secs - secs * (rhs as u64); + let extra_nanos = carry * (NANOS_PER_SEC as u64) / (rhs as u64); + let nanos = self.nanos / rhs + (extra_nanos as u32); + debug_assert!(nanos < NANOS_PER_SEC); + Some(Duration { secs: secs, nanos: nanos }) + } else { + None + } + } +} + +#[stable(feature = "duration", since = "1.3.0")] +impl Add for Duration { + type Output = Duration; + + fn add(self, rhs: Duration) -> Duration { + self.checked_add(rhs).expect("overflow when adding durations") + } +} + +#[stable(feature = "time_augmented_assignment", since = "1.9.0")] +impl AddAssign for Duration { + fn add_assign(&mut self, rhs: Duration) { + *self = *self + rhs; + } +} + +#[stable(feature = "duration", since = "1.3.0")] +impl Sub for Duration { + type Output = Duration; + + fn sub(self, rhs: Duration) -> Duration { + self.checked_sub(rhs).expect("overflow when subtracting durations") + } +} + +#[stable(feature = "time_augmented_assignment", since = "1.9.0")] +impl SubAssign for Duration { + fn sub_assign(&mut self, rhs: Duration) { + *self = *self - rhs; + } +} + +#[stable(feature = "duration", since = "1.3.0")] +impl Mul for Duration { + type Output = Duration; + + fn mul(self, rhs: u32) -> Duration { + self.checked_mul(rhs).expect("overflow when multiplying duration by scalar") + } +} + +#[stable(feature = "time_augmented_assignment", since = "1.9.0")] +impl MulAssign for Duration { + fn mul_assign(&mut self, rhs: u32) { + *self = *self * rhs; + } +} + +#[stable(feature = "duration", since = "1.3.0")] +impl Div for Duration { + type Output = Duration; + + fn div(self, rhs: u32) -> Duration { + self.checked_div(rhs).expect("divide by zero error when dividing duration by scalar") + } +} + +#[stable(feature = "time_augmented_assignment", since = "1.9.0")] +impl DivAssign for Duration { + fn div_assign(&mut self, rhs: u32) { + *self = *self / rhs; + } +} + +#[stable(feature = "duration_sum", since = "1.16.0")] +impl Sum for Duration { + fn sum>(iter: I) -> Duration { + iter.fold(Duration::new(0, 0), |a, b| a + b) + } +} + +#[stable(feature = "duration_sum", since = "1.16.0")] +impl<'a> Sum<&'a Duration> for Duration { + fn sum>(iter: I) -> Duration { + iter.fold(Duration::new(0, 0), |a, b| a + *b) + } +} + +#[cfg(test)] +mod tests { + use super::Duration; + + #[test] + fn creation() { + assert!(Duration::from_secs(1) != Duration::from_secs(0)); + assert_eq!(Duration::from_secs(1) + Duration::from_secs(2), + Duration::from_secs(3)); + assert_eq!(Duration::from_millis(10) + Duration::from_secs(4), + Duration::new(4, 10 * 1_000_000)); + assert_eq!(Duration::from_millis(4000), Duration::new(4, 0)); + } + + #[test] + fn secs() { + assert_eq!(Duration::new(0, 0).as_secs(), 0); + assert_eq!(Duration::from_secs(1).as_secs(), 1); + assert_eq!(Duration::from_millis(999).as_secs(), 0); + assert_eq!(Duration::from_millis(1001).as_secs(), 1); + } + + #[test] + fn nanos() { + assert_eq!(Duration::new(0, 0).subsec_nanos(), 0); + assert_eq!(Duration::new(0, 5).subsec_nanos(), 5); + assert_eq!(Duration::new(0, 1_000_000_001).subsec_nanos(), 1); + assert_eq!(Duration::from_secs(1).subsec_nanos(), 0); + assert_eq!(Duration::from_millis(999).subsec_nanos(), 999 * 1_000_000); + assert_eq!(Duration::from_millis(1001).subsec_nanos(), 1 * 1_000_000); + } + + #[test] + fn add() { + assert_eq!(Duration::new(0, 0) + Duration::new(0, 1), + Duration::new(0, 1)); + assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001), + Duration::new(1, 1)); + } + + #[test] + fn checked_add() { + assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), + Some(Duration::new(0, 1))); + assert_eq!(Duration::new(0, 500_000_000).checked_add(Duration::new(0, 500_000_001)), + Some(Duration::new(1, 1))); + assert_eq!(Duration::new(1, 0).checked_add(Duration::new(::u64::MAX, 0)), None); + } + + #[test] + fn sub() { + assert_eq!(Duration::new(0, 1) - Duration::new(0, 0), + Duration::new(0, 1)); + assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000), + Duration::new(0, 1)); + assert_eq!(Duration::new(1, 0) - Duration::new(0, 1), + Duration::new(0, 999_999_999)); + } + + #[test] + fn checked_sub() { + let zero = Duration::new(0, 0); + let one_nano = Duration::new(0, 1); + let one_sec = Duration::new(1, 0); + assert_eq!(one_nano.checked_sub(zero), Some(Duration::new(0, 1))); + assert_eq!(one_sec.checked_sub(one_nano), + Some(Duration::new(0, 999_999_999))); + assert_eq!(zero.checked_sub(one_nano), None); + assert_eq!(zero.checked_sub(one_sec), None); + } + + #[test] #[should_panic] + fn sub_bad1() { + Duration::new(0, 0) - Duration::new(0, 1); + } + + #[test] #[should_panic] + fn sub_bad2() { + Duration::new(0, 0) - Duration::new(1, 0); + } + + #[test] + fn mul() { + assert_eq!(Duration::new(0, 1) * 2, Duration::new(0, 2)); + assert_eq!(Duration::new(1, 1) * 3, Duration::new(3, 3)); + assert_eq!(Duration::new(0, 500_000_001) * 4, Duration::new(2, 4)); + assert_eq!(Duration::new(0, 500_000_001) * 4000, + Duration::new(2000, 4000)); + } + + #[test] + fn checked_mul() { + assert_eq!(Duration::new(0, 1).checked_mul(2), Some(Duration::new(0, 2))); + assert_eq!(Duration::new(1, 1).checked_mul(3), Some(Duration::new(3, 3))); + assert_eq!(Duration::new(0, 500_000_001).checked_mul(4), Some(Duration::new(2, 4))); + assert_eq!(Duration::new(0, 500_000_001).checked_mul(4000), + Some(Duration::new(2000, 4000))); + assert_eq!(Duration::new(::u64::MAX - 1, 0).checked_mul(2), None); + } + + #[test] + fn div() { + assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0)); + assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333)); + assert_eq!(Duration::new(99, 999_999_000) / 100, + Duration::new(0, 999_999_990)); + } + + #[test] + fn checked_div() { + assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0))); + assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000))); + assert_eq!(Duration::new(2, 0).checked_div(0), None); + } +} diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 44cdb5e8a36..71519ab21fe 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -73,7 +73,7 @@ pub struct FormatSpec<'a> { /// Enum describing where an argument for a format can be located. #[derive(Copy, Clone, PartialEq)] pub enum Position<'a> { - /// The arugment is implied to be located at an index + /// The argument is implied to be located at an index ArgumentImplicitlyIs(usize), /// The argument is located at a specific index given in the format ArgumentIs(usize), diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index c3bd6a2bc18..5f768ef4399 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -27,10 +27,12 @@ #![feature(libc)] #![feature(panic_runtime)] #![feature(staged_api)] +#![feature(rustc_attrs)] // Rust's "try" function, but if we're aborting on panics we just call the // function as there's nothing else we need to do here. #[no_mangle] +#[rustc_std_internal_symbol] pub unsafe extern fn __rust_maybe_catch_panic(f: fn(*mut u8), data: *mut u8, _data_ptr: *mut usize, @@ -50,6 +52,7 @@ // will kill us with an illegal instruction, which will do a good enough job for // now hopefully. #[no_mangle] +#[rustc_std_internal_symbol] pub unsafe extern fn __rust_start_panic(_data: usize, _vtable: usize) -> u32 { abort(); diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index b9e816baac0..6768e0ade43 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -685,7 +685,7 @@ fn joint(first: char, rest: Token, is_joint: bool, span: &mut syntax_pos::Span, }) } - DotEq => unreachable!(), + DotEq => joint!('.', Eq), OpenDelim(..) | CloseDelim(..) => unreachable!(), Whitespace | Comment | Shebang(..) | Eof => unreachable!(), }; diff --git a/src/librustc/README.md b/src/librustc/README.md index ddf71a06d60..722456a76ce 100644 --- a/src/librustc/README.md +++ b/src/librustc/README.md @@ -176,6 +176,7 @@ pointers for understanding them better. - `'gcx` -- the lifetime of the global arena (see `librustc/ty`). - generics -- the set of generic type parameters defined on a type or item - ICE -- internal compiler error. When the compiler crashes. +- ICH -- incremental compilation hash. - infcx -- the inference context (see `librustc/infer`) - MIR -- the **Mid-level IR** that is created after type-checking for use by borrowck and trans. Defined in the `src/librustc/mir/` module, but much of the code that manipulates it is diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 1de9091b5df..4034055d041 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -639,6 +639,9 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool { [] TargetFeaturesEnabled(DefId), [] InstanceDefSizeEstimate { instance_def: InstanceDef<'tcx> }, + + [] GetSymbolExportLevel(DefId), + ); trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug { diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 8bd89b834d6..4c256556191 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -256,6 +256,28 @@ trait Foo { } ``` +### The trait cannot contain associated constants + +Just like static functions, associated constants aren't stored on the method +table. If the trait or any subtrait contain an associated constant, they cannot +be made into an object. + +```compile_fail,E0038 +trait Foo { + const X: i32; +} + +impl Foo {} +``` + +A simple workaround is to use a helper method instead: + +``` +trait Foo { + fn x(&self) -> i32; +} +``` + ### The trait cannot use `Self` as a type parameter in the supertrait listing This is similar to the second sub-error, but subtler. It happens in situations diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 97cf9b01410..b804cf7bf5a 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -965,8 +965,8 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { walk_list!(visitor, visit_expr, subexpressions); } ExprCall(ref callee_expression, ref arguments) => { + visitor.visit_expr(callee_expression); walk_list!(visitor, visit_expr, arguments); - visitor.visit_expr(callee_expression) } ExprMethodCall(ref segment, _, ref arguments) => { visitor.visit_path_segment(expression.span, segment); diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index f46b590d2dc..67b4cfb6fa7 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -20,7 +20,6 @@ impl_stable_hash_for!(struct mir::GeneratorLayout<'tcx> { fields }); impl_stable_hash_for!(struct mir::SourceInfo { span, scope }); impl_stable_hash_for!(enum mir::Mutability { Mut, Not }); -impl_stable_hash_for!(enum mir::BorrowKind { Shared, Unique, Mut }); impl_stable_hash_for!(enum mir::LocalKind { Var, Temp, Arg, ReturnPointer }); impl_stable_hash_for!(struct mir::LocalDecl<'tcx> { mutability, @@ -36,6 +35,25 @@ impl_stable_hash_for!(struct mir::UnsafetyViolation { source_info, description, kind }); impl_stable_hash_for!(struct mir::UnsafetyCheckResult { violations, unsafe_blocks }); +impl<'gcx> HashStable> +for mir::BorrowKind { + #[inline] + fn hash_stable(&self, + hcx: &mut StableHashingContext<'gcx>, + hasher: &mut StableHasher) { + mem::discriminant(self).hash_stable(hcx, hasher); + + match *self { + mir::BorrowKind::Shared | + mir::BorrowKind::Unique => {} + mir::BorrowKind::Mut { allow_two_phase_borrow } => { + allow_two_phase_borrow.hash_stable(hcx, hasher); + } + } + } +} + + impl<'gcx> HashStable> for mir::UnsafetyViolationKind { #[inline] @@ -201,6 +219,10 @@ fn hash_stable(&self, target.hash_stable(hcx, hasher); } } + mir::TerminatorKind::FalseUnwind { ref real_target, ref unwind } => { + real_target.hash_stable(hcx, hasher); + unwind.hash_stable(hcx, hasher); + } } } } diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 107779ec3fa..d1e431597e7 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -163,6 +163,20 @@ fn hash_stable(&self, impl_stable_hash_for!(struct ty::adjustment::OverloadedDeref<'tcx> { region, mutbl }); impl_stable_hash_for!(struct ty::UpvarBorrow<'tcx> { kind, region }); +impl<'gcx> HashStable> for ty::adjustment::AutoBorrowMutability { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'gcx>, + hasher: &mut StableHasher) { + mem::discriminant(self).hash_stable(hcx, hasher); + match *self { + ty::adjustment::AutoBorrowMutability::Mutable { ref allow_two_phase_borrow } => { + allow_two_phase_borrow.hash_stable(hcx, hasher); + } + ty::adjustment::AutoBorrowMutability::Immutable => {} + } + } +} + impl_stable_hash_for!(struct ty::UpvarId { var_id, closure_expr_id }); impl_stable_hash_for!(enum ty::BorrowKind { diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index b10e7425957..03fc40b2e39 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -175,25 +175,6 @@ fn explain_span<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ty::ReEarlyBound(_) | ty::ReFree(_) => { let scope = region.free_region_binding_scope(self); - let prefix = match *region { - ty::ReEarlyBound(ref br) => { - format!("the lifetime {} as defined on", br.name) - } - ty::ReFree(ref fr) => { - match fr.bound_region { - ty::BrAnon(idx) => { - format!("the anonymous lifetime #{} defined on", idx + 1) - } - ty::BrFresh(_) => "an anonymous lifetime defined on".to_owned(), - _ => { - format!("the lifetime {} as defined on", - fr.bound_region) - } - } - } - _ => bug!() - }; - let node = self.hir.as_local_node_id(scope) .unwrap_or(DUMMY_NODE_ID); let unknown; @@ -218,7 +199,26 @@ fn explain_span<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, &unknown } }; - let (msg, opt_span) = explain_span(self, tag, self.hir.span(node)); + let (prefix, span) = match *region { + ty::ReEarlyBound(ref br) => { + (format!("the lifetime {} as defined on", br.name), + self.sess.codemap().def_span(self.hir.span(node))) + } + ty::ReFree(ref fr) => { + match fr.bound_region { + ty::BrAnon(idx) => { + (format!("the anonymous lifetime #{} defined on", idx + 1), + self.hir.span(node)) + } + ty::BrFresh(_) => ("an anonymous lifetime defined on".to_owned(), + self.hir.span(node)), + _ => (format!("the lifetime {} as defined on", fr.bound_region), + self.sess.codemap().def_span(self.hir.span(node))), + } + } + _ => bug!() + }; + let (msg, opt_span) = explain_span(self, tag, span); (format!("{} {}", prefix, msg), opt_span) } @@ -807,7 +807,7 @@ pub fn note_type_err(&self, } }; - let span = cause.span; + let span = cause.span(&self.tcx); diag.span_label(span, terr.to_string()); if let Some((sp, msg)) = secondary_span { @@ -842,7 +842,7 @@ pub fn note_type_err(&self, "did you mean `{}(/* fields */)`?", self.tcx.item_path_str(def_id) ); - diag.span_label(cause.span, message); + diag.span_label(span, message); } } } @@ -870,7 +870,7 @@ pub fn report_and_explain_type_error(&self, trace, terr); - let span = trace.cause.span; + let span = trace.cause.span(&self.tcx); let failure_code = trace.cause.as_failure_code(terr); let mut diag = match failure_code { FailureCode::Error0317(failure_str) => { @@ -1076,6 +1076,31 @@ fn report_sub_sup_conflict(&self, sup_region, "..."); + match (&sup_origin, &sub_origin) { + (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) => { + if let (Some((sup_expected, sup_found)), + Some((sub_expected, sub_found))) = (self.values_str(&sup_trace.values), + self.values_str(&sub_trace.values)) { + if sub_expected == sup_expected && sub_found == sup_found { + self.tcx.note_and_explain_region( + region_scope_tree, + &mut err, + "...but the lifetime must also be valid for ", + sub_region, + "...", + ); + err.note(&format!("...so that the {}:\nexpected {}\n found {}", + sup_trace.cause.as_requirement_str(), + sup_expected.content(), + sup_found.content())); + err.emit(); + return; + } + } + } + _ => {} + } + self.note_region_origin(&mut err, &sup_origin); self.tcx.note_and_explain_region(region_scope_tree, &mut err, diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs index e46613b3e4d..02ec9fe74c1 100644 --- a/src/librustc/infer/error_reporting/note.rs +++ b/src/librustc/infer/error_reporting/note.rs @@ -23,12 +23,10 @@ pub(super) fn note_region_origin(&self, if let Some((expected, found)) = self.values_str(&trace.values) { let expected = expected.content(); let found = found.content(); - // FIXME: do we want a "the" here? - err.span_note(trace.cause.span, - &format!("...so that {} (expected {}, found {})", - trace.cause.as_requirement_str(), - expected, - found)); + err.note(&format!("...so that the {}:\nexpected {}\n found {}", + trace.cause.as_requirement_str(), + expected, + found)); } else { // FIXME: this really should be handled at some earlier stage. Our // handling of region checking when type errors are present is diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index d727dfb0c4b..a7a26195059 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -58,6 +58,7 @@ #![feature(macro_vis_matcher)] #![feature(match_default_bindings)] #![feature(never_type)] +#![feature(non_exhaustive)] #![feature(nonzero)] #![feature(quote)] #![feature(refcell_replace_swap)] @@ -66,6 +67,7 @@ #![feature(specialization)] #![feature(unboxed_closures)] #![feature(underscore_lifetimes)] +#![feature(universal_impl_trait)] #![feature(trace_macros)] #![feature(catch_expr)] #![feature(test)] diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 143d2c2ea28..0577800f3f4 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -246,6 +246,12 @@ "raw pointer to an inference variable" } +declare_lint! { + pub ELIDED_LIFETIME_IN_PATH, + Allow, + "hidden lifetime parameters are deprecated, try `Foo<'_>`" +} + /// Does nothing as a lint pass, but registers some `Lint`s /// which are used by other parts of the compiler. #[derive(Copy, Clone)] @@ -291,7 +297,9 @@ fn get_lints(&self) -> LintArray { UNUSED_MUT, COERCE_NEVER, SINGLE_USE_LIFETIME, - TYVAR_BEHIND_RAW_POINTER + TYVAR_BEHIND_RAW_POINTER, + ELIDED_LIFETIME_IN_PATH + ) } } diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 5336c1944e8..ed937046e5e 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -631,7 +631,7 @@ impl<'a, 'tcx> LayoutOf> for &'a LateContext<'a, 'tcx> { type TyLayout = Result, LayoutError<'tcx>>; fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout { - (self.tcx, self.param_env.reveal_all()).layout_of(ty) + self.tcx.layout_of(self.param_env.and(ty)) } } @@ -1042,11 +1042,20 @@ pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) { // Put the lint store levels and passes back in the session. cx.lint_sess.restore(&sess.lint_store); - // Emit all buffered lints from early on in the session now that we've - // calculated the lint levels for all AST nodes. - for (_id, lints) in cx.buffered.map { - for early_lint in lints { - span_bug!(early_lint.span, "failed to process buffered lint here"); + // All of the buffered lints should have been emitted at this point. + // If not, that means that we somehow buffered a lint for a node id + // that was not lint-checked (perhaps it doesn't exist?). This is a bug. + // + // Rustdoc runs everybody-loops before the early lints and removes + // function bodies, so it's totally possible for linted + // node ids to not exist (e.g. macros defined within functions for the + // unused_macro lint) anymore. So we only run this check + // when we're not in rustdoc mode. (see issue #47639) + if !sess.opts.actually_rustdoc { + for (_id, lints) in cx.buffered.map { + for early_lint in lints { + span_bug!(early_lint.span, "failed to process buffered lint here"); + } } } } diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index 31e054ec1cb..8b4b9aaeac8 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -175,6 +175,10 @@ fn configure_main(this: &mut EntryContext) { err.emit(); this.session.abort_if_errors(); } else { + if this.session.teach(&err.get_code().unwrap()) { + err.note("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/"); + } err.emit(); } } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index c69005101c6..7db75a51668 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -760,7 +760,7 @@ fn walk_autoref(&mut self, expr.span, cmt_base, r, - ty::BorrowKind::from_mutbl(m), + ty::BorrowKind::from_mutbl(m.into()), AutoRef); } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index d4fa03b5085..10497c95e27 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -109,7 +109,7 @@ use hir::def::*; use ty::{self, TyCtxt}; use lint; -use util::nodemap::NodeMap; +use util::nodemap::{NodeMap, NodeSet}; use std::{fmt, usize}; use std::io::prelude::*; @@ -244,7 +244,8 @@ struct CaptureInfo { #[derive(Copy, Clone, Debug)] struct LocalInfo { id: NodeId, - name: ast::Name + name: ast::Name, + is_shorthand: bool, } #[derive(Copy, Clone, Debug)] @@ -333,6 +334,13 @@ fn variable_name(&self, var: Variable) -> String { } } + fn variable_is_shorthand(&self, var: Variable) -> bool { + match self.var_kinds[var.get()] { + Local(LocalInfo { is_shorthand, .. }) => is_shorthand, + Arg(..) | CleanExit => false + } + } + fn set_captures(&mut self, node_id: NodeId, cs: Vec) { self.capture_info_map.insert(node_id, Rc::new(cs)); } @@ -384,8 +392,9 @@ fn visit_local<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, local: &'tcx hir::Local) { let name = path1.node; ir.add_live_node_for_node(p_id, VarDefNode(sp)); ir.add_variable(Local(LocalInfo { - id: p_id, - name, + id: p_id, + name, + is_shorthand: false, })); }); intravisit::walk_local(ir, local); @@ -393,6 +402,22 @@ fn visit_local<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, local: &'tcx hir::Local) { fn visit_arm<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, arm: &'tcx hir::Arm) { for pat in &arm.pats { + // for struct patterns, take note of which fields used shorthand (`x` + // rather than `x: x`) + // + // FIXME: according to the rust-lang-nursery/rustc-guide book and + // librustc/README.md, `NodeId`s are to be phased out in favor of + // `HirId`s; however, we need to match the signature of `each_binding`, + // which uses `NodeIds`. + let mut shorthand_field_ids = NodeSet(); + if let hir::PatKind::Struct(_, ref fields, _) = pat.node { + for field in fields { + if field.node.is_shorthand { + shorthand_field_ids.insert(field.node.pat.id); + } + } + } + pat.each_binding(|bm, p_id, sp, path1| { debug!("adding local variable {} from match with bm {:?}", p_id, bm); @@ -400,7 +425,8 @@ 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, + is_shorthand: shorthand_field_ids.contains(&p_id) })); }) } @@ -1034,10 +1060,10 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode) } hir::ExprAssign(ref l, ref r) => { - // see comment on lvalues in - // propagate_through_lvalue_components() - let succ = self.write_lvalue(&l, succ, ACC_WRITE); - let succ = self.propagate_through_lvalue_components(&l, succ); + // see comment on places in + // propagate_through_place_components() + let succ = self.write_place(&l, succ, ACC_WRITE); + let succ = self.propagate_through_place_components(&l, succ); self.propagate_through_expr(&r, succ) } @@ -1047,11 +1073,11 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode) let succ = self.propagate_through_expr(&l, succ); self.propagate_through_expr(&r, succ) } else { - // see comment on lvalues in - // propagate_through_lvalue_components() - let succ = self.write_lvalue(&l, succ, ACC_WRITE|ACC_READ); + // see comment on places in + // propagate_through_place_components() + let succ = self.write_place(&l, succ, ACC_WRITE|ACC_READ); let succ = self.propagate_through_expr(&r, succ); - self.propagate_through_lvalue_components(&l, succ) + self.propagate_through_place_components(&l, succ) } } @@ -1121,14 +1147,14 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode) hir::ExprInlineAsm(ref ia, ref outputs, ref inputs) => { let succ = ia.outputs.iter().zip(outputs).rev().fold(succ, |succ, (o, output)| { - // see comment on lvalues - // in propagate_through_lvalue_components() + // see comment on places + // in propagate_through_place_components() if o.is_indirect { self.propagate_through_expr(output, succ) } else { let acc = if o.is_rw { ACC_WRITE|ACC_READ } else { ACC_WRITE }; - let succ = self.write_lvalue(output, succ, acc); - self.propagate_through_lvalue_components(output, succ) + let succ = self.write_place(output, succ, acc); + self.propagate_through_place_components(output, succ) } }); @@ -1146,11 +1172,11 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode) } } - fn propagate_through_lvalue_components(&mut self, + fn propagate_through_place_components(&mut self, expr: &Expr, succ: LiveNode) -> LiveNode { - // # Lvalues + // # Places // // In general, the full flow graph structure for an // assignment/move/etc can be handled in one of two ways, @@ -1160,7 +1186,7 @@ fn propagate_through_lvalue_components(&mut self, // // The two kinds of graphs are: // - // Tracked lvalue Untracked lvalue + // Tracked place Untracked place // ----------------------++----------------------- // || // | || | @@ -1168,7 +1194,7 @@ fn propagate_through_lvalue_components(&mut self, // (rvalue) || (rvalue) // | || | // v || v - // (write of lvalue) || (lvalue components) + // (write of place) || (place components) // | || | // v || v // (succ) || (succ) @@ -1177,25 +1203,25 @@ fn propagate_through_lvalue_components(&mut self, // // I will cover the two cases in turn: // - // # Tracked lvalues + // # Tracked places // - // A tracked lvalue is a local variable/argument `x`. In + // A tracked place is a local variable/argument `x`. In // these cases, the link_node where the write occurs is linked - // to node id of `x`. The `write_lvalue()` routine generates + // to node id of `x`. The `write_place()` routine generates // the contents of this node. There are no subcomponents to // consider. // - // # Non-tracked lvalues + // # Non-tracked places // - // These are lvalues like `x[5]` or `x.f`. In that case, we + // These are places like `x[5]` or `x.f`. In that case, we // basically ignore the value which is written to but generate // reads for the components---`x` in these two examples. The // components reads are generated by - // `propagate_through_lvalue_components()` (this fn). + // `propagate_through_place_components()` (this fn). // - // # Illegal lvalues + // # Illegal places // - // It is still possible to observe assignments to non-lvalues; + // It is still possible to observe assignments to non-places; // these errors are detected in the later pass borrowck. We // just ignore such cases and treat them as reads. @@ -1207,17 +1233,17 @@ fn propagate_through_lvalue_components(&mut self, } } - // see comment on propagate_through_lvalue() - fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: u32) + // see comment on propagate_through_place() + fn write_place(&mut self, expr: &Expr, succ: LiveNode, acc: u32) -> LiveNode { match expr.node { hir::ExprPath(hir::QPath::Resolved(_, ref path)) => { self.access_path(expr.id, path, succ, acc) } - // We do not track other lvalues, so just propagate through + // We do not track other places, so just propagate through // to their subcomponents. Also, it may happen that - // non-lvalues occur here, because those are detected in the + // non-places occur here, because those are detected in the // later pass borrowck. _ => succ } @@ -1363,14 +1389,14 @@ fn check_arm<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, arm: &'tcx hir::Arm) { fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) { match expr.node { hir::ExprAssign(ref l, _) => { - this.check_lvalue(&l); + this.check_place(&l); intravisit::walk_expr(this, expr); } hir::ExprAssignOp(_, ref l, _) => { if !this.tables.is_method_call(expr) { - this.check_lvalue(&l); + this.check_place(&l); } intravisit::walk_expr(this, expr); @@ -1381,10 +1407,10 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) { this.visit_expr(input); } - // Output operands must be lvalues + // Output operands must be places for (o, output) in ia.outputs.iter().zip(outputs) { if !o.is_indirect { - this.check_lvalue(output); + this.check_place(output); } this.visit_expr(output); } @@ -1409,7 +1435,7 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) { } impl<'a, 'tcx> Liveness<'a, 'tcx> { - fn check_lvalue(&mut self, expr: &'tcx Expr) { + fn check_place(&mut self, expr: &'tcx Expr) { match expr.node { hir::ExprPath(hir::QPath::Resolved(_, ref path)) => { if let Def::Local(nid) = path.def { @@ -1423,7 +1449,7 @@ fn check_lvalue(&mut self, expr: &'tcx Expr) { } } _ => { - // For other kinds of lvalues, no checks are required, + // For other kinds of places, no checks are required, // and any embedded expressions are actually rvalues intravisit::walk_expr(self, expr); } @@ -1483,17 +1509,26 @@ fn warn_about_unused(&self, self.assigned_on_exit(ln, var).is_some() }; + let suggest_underscore_msg = format!("consider using `_{}` instead", + name); if is_assigned { - self.ir.tcx.lint_node_note(lint::builtin::UNUSED_VARIABLES, id, sp, - &format!("variable `{}` is assigned to, but never used", - name), - &format!("to avoid this warning, consider using `_{}` instead", - name)); + self.ir.tcx + .lint_node_note(lint::builtin::UNUSED_VARIABLES, id, sp, + &format!("variable `{}` is assigned to, but never used", + name), + &suggest_underscore_msg); } else if name != "self" { - self.ir.tcx.lint_node_note(lint::builtin::UNUSED_VARIABLES, id, sp, - &format!("unused variable: `{}`", name), - &format!("to avoid this warning, consider using `_{}` instead", - name)); + let msg = format!("unused variable: `{}`", name); + let mut err = self.ir.tcx + .struct_span_lint_node(lint::builtin::UNUSED_VARIABLES, id, sp, &msg); + if self.ir.variable_is_shorthand(var) { + err.span_suggestion(sp, "try ignoring the field", + format!("{}: _", name)); + } else { + err.span_suggestion_short(sp, &suggest_underscore_msg, + format!("_{}", name)); + } + err.emit() } } true diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index a8955723e3a..45b595adfe7 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -26,8 +26,8 @@ //! | E.comp // access to an interior component //! //! Imagine a routine ToAddr(Expr) that evaluates an expression and returns an -//! address where the result is to be found. If Expr is an lvalue, then this -//! is the address of the lvalue. If Expr is an rvalue, this is the address of +//! address where the result is to be found. If Expr is a place, then this +//! is the address of the place. If Expr is an rvalue, this is the address of //! some temporary spot in memory where the result is stored. //! //! Now, cat_expr() classifies the expression Expr and the address A=ToAddr(Expr) @@ -182,7 +182,7 @@ pub struct cmt_<'tcx> { pub id: ast::NodeId, // id of expr/pat producing this value pub span: Span, // span of same expr/pat pub cat: Categorization<'tcx>, // categorization of expr - pub mutbl: MutabilityCategory, // mutability of expr as lvalue + pub mutbl: MutabilityCategory, // mutability of expr as place pub ty: Ty<'tcx>, // type of the expr (*see WARNING above*) pub note: Note, // Note about the provenance of this cmt } @@ -517,7 +517,7 @@ fn pat_ty(&self, pat: &hir::Pat) -> McResult> { // a bind-by-ref means that the base_ty will be the type of the ident itself, // but what we want here is the type of the underlying value being borrowed. // So peel off one-level, turning the &T into T. - match base_ty.builtin_deref(false, ty::NoPreference) { + match base_ty.builtin_deref(false) { Some(t) => t.ty, None => { debug!("By-ref binding of non-derefable type {:?}", base_ty); @@ -603,7 +603,7 @@ pub fn cat_expr_unadjusted(&self, expr: &hir::Expr) -> McResult> { match expr.node { hir::ExprUnary(hir::UnDeref, ref e_base) => { if self.tables.is_method_call(expr) { - self.cat_overloaded_lvalue(expr, e_base, false) + self.cat_overloaded_place(expr, e_base, false) } else { let base_cmt = self.cat_expr(&e_base)?; self.cat_deref(expr, base_cmt, false) @@ -631,7 +631,7 @@ pub fn cat_expr_unadjusted(&self, expr: &hir::Expr) -> McResult> { // The call to index() returns a `&T` value, which // is an rvalue. That is what we will be // dereferencing. - self.cat_overloaded_lvalue(expr, base, true) + self.cat_overloaded_place(expr, base, true) } else { let base_cmt = self.cat_expr(&base)?; self.cat_index(expr, base_cmt, expr_ty, InteriorOffsetKind::Index) @@ -983,27 +983,27 @@ pub fn cat_tup_field(&self, ret } - fn cat_overloaded_lvalue(&self, + fn cat_overloaded_place(&self, expr: &hir::Expr, base: &hir::Expr, implicit: bool) -> McResult> { - debug!("cat_overloaded_lvalue: implicit={}", implicit); + debug!("cat_overloaded_place: implicit={}", implicit); // Reconstruct the output assuming it's a reference with the // same region and mutability as the receiver. This holds for // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`. - let lvalue_ty = self.expr_ty(expr)?; + let place_ty = self.expr_ty(expr)?; let base_ty = self.expr_ty_adjusted(base)?; let (region, mutbl) = match base_ty.sty { ty::TyRef(region, mt) => (region, mt.mutbl), _ => { - span_bug!(expr.span, "cat_overloaded_lvalue: base is not a reference") + span_bug!(expr.span, "cat_overloaded_place: base is not a reference") } }; let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut { - ty: lvalue_ty, + ty: place_ty, mutbl, }); @@ -1019,7 +1019,7 @@ pub fn cat_deref(&self, debug!("cat_deref: base_cmt={:?}", base_cmt); let base_cmt_ty = base_cmt.ty; - let deref_ty = match base_cmt_ty.builtin_deref(true, ty::NoPreference) { + let deref_ty = match base_cmt_ty.builtin_deref(true) { Some(mt) => mt.ty, None => { debug!("Explicit deref of non-derefable type: {:?}", @@ -1386,7 +1386,7 @@ pub fn guarantor(&self) -> cmt<'tcx> { } } - /// Returns `FreelyAliasable(_)` if this lvalue represents a freely aliasable pointer type. + /// Returns `FreelyAliasable(_)` if this place represents a freely aliasable pointer type. pub fn freely_aliasable(&self) -> Aliasability { // Maybe non-obvious: copied upvars can only be considered // non-aliasable in once closures, since any other kind can be @@ -1453,7 +1453,7 @@ pub fn descriptive_string(&self, tcx: TyCtxt) -> String { "static item".to_string() } Categorization::Rvalue(..) => { - "non-lvalue".to_string() + "non-place".to_string() } Categorization::Local(vid) => { if tcx.hir.is_argument(vid) { diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 66b3adb83c1..e5619f469e7 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -467,9 +467,13 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { } fn visit_pat(&mut self, pat: &'tcx Pat) { + intravisit::walk_pat(self, pat); + self.expr_and_pat_count += 1; - intravisit::walk_pat(self, pat); + if pat.id == self.id { + self.result = Some(self.expr_and_pat_count); + } } fn visit_expr(&mut self, expr: &'tcx Expr) { @@ -814,7 +818,8 @@ pub fn free_scope<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, fr: &ty::FreeReg /// Checks whether the given scope contains a `yield`. If so, /// returns `Some((span, expr_count))` with the span of a yield we found and - /// the number of expressions appearing before the `yield` in the body. + /// the number of expressions and patterns appearing before the `yield` in the body + 1. + /// If there a are multiple yields in a scope, the one with the highest number is returned. pub fn yield_in_scope(&self, scope: Scope) -> Option<(Span, usize)> { self.yield_in_scope.get(&scope).cloned() } @@ -1112,7 +1117,7 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, // I mean that creating a binding into a ref-counted or managed value // would still count.) // - // 3. `ET`, which matches both rvalues like `foo()` as well as lvalues + // 3. `ET`, which matches both rvalues like `foo()` as well as places // based on rvalues like `foo().x[2].y`. // // A subexpression `` that appears in a let initializer @@ -1283,7 +1288,7 @@ fn record_rvalue_scope_if_borrow_expr<'a, 'tcx>( /// | (ET) /// | /// - /// Note: ET is intended to match "rvalues or lvalues based on rvalues". + /// Note: ET is intended to match "rvalues or places based on rvalues". fn record_rvalue_scope<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: &hir::Expr, blk_scope: Option) { diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 944d7705163..59460141166 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -737,7 +737,7 @@ fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) { if lifetime_ref.is_elided() { - self.resolve_elided_lifetimes(slice::from_ref(lifetime_ref)); + self.resolve_elided_lifetimes(slice::from_ref(lifetime_ref), false); return; } if lifetime_ref.is_static() { @@ -1444,7 +1444,7 @@ fn visit_segment_parameters( } if params.lifetimes.iter().all(|l| l.is_elided()) { - self.resolve_elided_lifetimes(¶ms.lifetimes); + self.resolve_elided_lifetimes(¶ms.lifetimes, true); } else { for l in ¶ms.lifetimes { self.visit_lifetime(l); @@ -1803,14 +1803,24 @@ fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) { } } - fn resolve_elided_lifetimes(&mut self, lifetime_refs: &'tcx [hir::Lifetime]) { + fn resolve_elided_lifetimes(&mut self, lifetime_refs: &'tcx [hir::Lifetime], deprecated: bool) { if lifetime_refs.is_empty() { return; } let span = lifetime_refs[0].span; + let id = lifetime_refs[0].id; let mut late_depth = 0; let mut scope = self.scope; + if deprecated { + self.tcx + .struct_span_lint_node( + lint::builtin::ELIDED_LIFETIME_IN_PATH, + id, + span, + &format!("hidden lifetime parameters are deprecated, try `Foo<'_>`")) + .emit(); + } let error = loop { match *scope { // Do not assign any resolution, it will be inferred. diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 3aa94b34699..439be667861 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -413,7 +413,20 @@ pub enum BorrowKind { Unique, /// Data is mutable and not aliasable. - Mut, + Mut { + /// True if this borrow arose from method-call auto-ref + /// (i.e. `adjustment::Adjust::Borrow`) + allow_two_phase_borrow: bool + } +} + +impl BorrowKind { + pub fn allows_two_phase_borrow(&self) -> bool { + match *self { + BorrowKind::Shared | BorrowKind::Unique => false, + BorrowKind::Mut { allow_two_phase_borrow } => allow_two_phase_borrow, + } + } } /////////////////////////////////////////////////////////////////////////// @@ -733,13 +746,13 @@ pub enum TerminatorKind<'tcx> { }, /// Drop the Place and assign the new value over it. This ensures - /// that the assignment to LV occurs *even if* the destructor for + /// that the assignment to `P` occurs *even if* the destructor for /// place unwinds. Its semantics are best explained by by the /// elaboration: /// /// ``` /// BB0 { - /// DropAndReplace(LV <- RV, goto BB1, unwind BB2) + /// DropAndReplace(P <- V, goto BB1, unwind BB2) /// } /// ``` /// @@ -747,15 +760,15 @@ pub enum TerminatorKind<'tcx> { /// /// ``` /// BB0 { - /// Drop(LV, goto BB1, unwind BB2) + /// Drop(P, goto BB1, unwind BB2) /// } /// BB1 { - /// // LV is now unitialized - /// LV <- RV + /// // P is now unitialized + /// P <- V /// } /// BB2 { - /// // LV is now unitialized -- its dtor panicked - /// LV <- RV + /// // P is now unitialized -- its dtor panicked + /// P <- V /// } /// ``` DropAndReplace { @@ -803,9 +816,28 @@ pub enum TerminatorKind<'tcx> { /// Indicates the end of the dropping of a generator GeneratorDrop, + /// A block where control flow only ever takes one real path, but borrowck + /// needs to be more conservative. FalseEdges { + /// The target normal control flow will take real_target: BasicBlock, - imaginary_targets: Vec + /// The list of blocks control flow could conceptually take, but won't + /// in practice + imaginary_targets: Vec, + }, + /// A terminator for blocks that only take one path in reality, but where we + /// reserve the right to unwind in borrowck, even if it won't happen in practice. + /// This can arise in infinite loops with no function calls for example. + FalseUnwind { + /// The target normal control flow will take + real_target: BasicBlock, + /// The imaginary cleanup block link. This particular path will never be taken + /// in practice, but in order to avoid fragility we want to always + /// consider it in borrowck. We don't want to accept programs which + /// pass borrowck only when panic=abort or some assertions are disabled + /// due to release vs. debug mode builds. This needs to be an Option because + /// of the remove_noop_landing_pads and no_landing_pads passes + unwind: Option, }, } @@ -865,6 +897,8 @@ pub fn successors(&self) -> Cow<[BasicBlock]> { s.extend_from_slice(imaginary_targets); s.into_cow() } + FalseUnwind { real_target: t, unwind: Some(u) } => vec![t, u].into_cow(), + FalseUnwind { real_target: ref t, unwind: None } => slice::from_ref(t).into_cow(), } } @@ -897,6 +931,8 @@ pub fn successors_mut(&mut self) -> Vec<&mut BasicBlock> { s.extend(imaginary_targets.iter_mut()); s } + FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => vec![t, u], + FalseUnwind { ref mut real_target, unwind: None } => vec![real_target], } } @@ -916,7 +952,8 @@ pub fn unwind_mut(&mut self) -> Option<&mut Option> { TerminatorKind::Call { cleanup: ref mut unwind, .. } | TerminatorKind::Assert { cleanup: ref mut unwind, .. } | TerminatorKind::DropAndReplace { ref mut unwind, .. } | - TerminatorKind::Drop { ref mut unwind, .. } => { + TerminatorKind::Drop { ref mut unwind, .. } | + TerminatorKind::FalseUnwind { ref mut unwind, .. } => { Some(unwind) } } @@ -1045,7 +1082,8 @@ pub fn fmt_head(&self, fmt: &mut W) -> fmt::Result { write!(fmt, ")") }, - FalseEdges { .. } => write!(fmt, "falseEdges") + FalseEdges { .. } => write!(fmt, "falseEdges"), + FalseUnwind { .. } => write!(fmt, "falseUnwind"), } } @@ -1087,6 +1125,8 @@ pub fn fmt_successor_labels(&self) -> Vec> { l.resize(imaginary_targets.len() + 1, "imaginary".into()); l } + FalseUnwind { unwind: Some(_), .. } => vec!["real".into(), "cleanup".into()], + FalseUnwind { unwind: None, .. } => vec!["real".into()], } } } @@ -1515,8 +1555,8 @@ pub enum AggregateKind<'tcx> { Array(Ty<'tcx>), Tuple, - /// The second field is variant number (discriminant), it's equal - /// to 0 for struct and union expressions. The fourth field is + /// The second field is the variant index. It's equal to 0 for struct + /// and union expressions. The fourth field is /// active field number and is present only for union expressions /// -- e.g. for a union expression `SomeUnion { c: .. }`, the /// active field index would identity the field `c` @@ -1611,7 +1651,7 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { Ref(region, borrow_kind, ref place) => { let kind_str = match borrow_kind { BorrowKind::Shared => "", - BorrowKind::Mut | BorrowKind::Unique => "mut ", + BorrowKind::Mut { .. } | BorrowKind::Unique => "mut ", }; // When printing regions, add trailing space if necessary. @@ -1825,7 +1865,7 @@ pub struct Location { /// the location is within this block pub block: BasicBlock, - /// the location is the start of the this statement; or, if `statement_index` + /// the location is the start of the statement; or, if `statement_index` /// == num-statements, then the start of the terminator. pub statement_index: usize, } @@ -2189,7 +2229,8 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) Return => Return, Unreachable => Unreachable, FalseEdges { real_target, ref imaginary_targets } => - FalseEdges { real_target, imaginary_targets: imaginary_targets.clone() } + FalseEdges { real_target, imaginary_targets: imaginary_targets.clone() }, + FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind }, }; Terminator { source_info: self.source_info, @@ -2231,7 +2272,8 @@ fn super_visit_with>(&self, visitor: &mut V) -> bool { Return | GeneratorDrop | Unreachable | - FalseEdges { .. } => false + FalseEdges { .. } | + FalseUnwind { .. } => false } } } diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 23f360d5c39..bbfb9c89b3f 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -52,7 +52,7 @@ pub fn projection_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, match *elem { ProjectionElem::Deref => { let ty = self.to_ty(tcx) - .builtin_deref(true, ty::LvaluePreference::NoPreference) + .builtin_deref(true) .unwrap_or_else(|| { bug!("deref projection of non-dereferencable ty {:?}", self) }) @@ -182,9 +182,8 @@ pub fn ty<'a, 'gcx, D>(&self, local_decls: &D, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> T if let ty::TyAdt(adt_def, _) = ty.sty { adt_def.repr.discr_type().to_ty(tcx) } else { - // Undefined behaviour, bug for now; may want to return something for - // the `discriminant` intrinsic later. - bug!("Rvalue::Discriminant on Place of type {:?}", ty); + // This can only be `0`, for now, so `u8` will suffice. + tcx.types.u8 } } Rvalue::NullaryOp(NullOp::Box, t) => tcx.mk_box(t), @@ -264,7 +263,7 @@ pub fn ty<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, impl BorrowKind { pub fn to_mutbl_lossy(self) -> hir::Mutability { match self { - BorrowKind::Mut => hir::MutMutable, + BorrowKind::Mut { .. } => hir::MutMutable, BorrowKind::Shared => hir::MutImmutable, // We have no type corresponding to a unique imm borrow, so diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 57ed41f2f06..0b6f1275bdb 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -495,15 +495,21 @@ fn super_terminator_kind(&mut self, self.visit_operand(value, source_location); self.visit_branch(block, resume); drop.map(|t| self.visit_branch(block, t)); - } - TerminatorKind::FalseEdges { real_target, ref imaginary_targets } => { + TerminatorKind::FalseEdges { real_target, ref imaginary_targets} => { self.visit_branch(block, real_target); for target in imaginary_targets { self.visit_branch(block, *target); } } + + TerminatorKind::FalseUnwind { real_target, unwind } => { + self.visit_branch(block, real_target); + if let Some(unwind) = unwind { + self.visit_branch(block, unwind); + } + } } } @@ -951,9 +957,10 @@ pub fn is_storage_dead_marker(&self) -> bool { pub fn is_mutating_use(&self) -> bool { match *self { PlaceContext::Store | PlaceContext::AsmOutput | PlaceContext::Call | - PlaceContext::Borrow { kind: BorrowKind::Mut, .. } | + PlaceContext::Borrow { kind: BorrowKind::Mut { .. }, .. } | PlaceContext::Projection(Mutability::Mut) | PlaceContext::Drop => true, + PlaceContext::Inspect | PlaceContext::Borrow { kind: BorrowKind::Shared, .. } | PlaceContext::Borrow { kind: BorrowKind::Unique, .. } | @@ -971,7 +978,8 @@ pub fn is_nonmutating_use(&self) -> bool { PlaceContext::Borrow { kind: BorrowKind::Unique, .. } | PlaceContext::Projection(Mutability::Not) | PlaceContext::Copy | PlaceContext::Move => true, - PlaceContext::Borrow { kind: BorrowKind::Mut, .. } | PlaceContext::Store | + + PlaceContext::Borrow { kind: BorrowKind::Mut { .. }, .. } | PlaceContext::Store | PlaceContext::AsmOutput | PlaceContext::Call | PlaceContext::Projection(Mutability::Mut) | PlaceContext::Drop | PlaceContext::StorageLive | PlaceContext::StorageDead | diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index b9546143a05..1f40c2db453 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -112,6 +112,31 @@ pub enum OutputType { DepInfo, } +/// The epoch of the compiler (RFC 2052) +#[derive(Clone, Copy, Hash, PartialOrd, Ord, Eq, PartialEq)] +#[non_exhaustive] +pub enum Epoch { + // epochs must be kept in order, newest to oldest + + /// The 2015 epoch + Epoch2015, + /// The 2018 epoch + Epoch2018, + + // when adding new epochs, be sure to update: + // + // - the list in the `parse_epoch` static + // - the match in the `parse_epoch` function + // - add a `rust_####()` function to the session + // - update the enum in Cargo's sources as well + // + // When -Zepoch becomes --epoch, there will + // also be a check for the epoch being nightly-only + // somewhere. That will need to be updated + // whenever we're stabilizing/introducing a new epoch + // as well as changing the default Cargo template. +} + impl_stable_hash_for!(enum self::OutputType { Bitcode, Assembly, @@ -548,25 +573,6 @@ pub fn with_extension(&self, extension: &str) -> PathBuf { pub fn filestem(&self) -> String { format!("{}{}", self.out_filestem, self.extra) } - - pub fn contains_path(&self, input_path: &PathBuf) -> bool { - let input_path = input_path.canonicalize().ok(); - if input_path.is_none() { - return false - } - match self.single_output_file { - Some(ref output_path) => output_path.canonicalize().ok() == input_path, - None => { - for k in self.outputs.keys() { - let output_path = self.path(k.to_owned()); - if output_path.canonicalize().ok() == input_path { - return true; - } - } - false - } - } - } } pub fn host_triple() -> &'static str { @@ -802,11 +808,13 @@ mod $mod_desc { Some("`string` or `string=string`"); pub const parse_lto: Option<&'static str> = Some("one of `thin`, `fat`, or omitted"); + pub const parse_epoch: Option<&'static str> = + Some("one of: `2015`, `2018`"); } #[allow(dead_code)] mod $mod_set { - use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto}; + use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto, Epoch}; use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel}; use std::path::PathBuf; @@ -1010,6 +1018,15 @@ fn parse_lto(slot: &mut Lto, v: Option<&str>) -> bool { }; true } + + fn parse_epoch(slot: &mut Epoch, v: Option<&str>) -> bool { + match v { + Some("2015") => *slot = Epoch::Epoch2015, + Some("2018") => *slot = Epoch::Epoch2018, + _ => return false, + } + true + } } ) } @@ -1104,6 +1121,8 @@ fn parse_lto(slot: &mut Lto, v: Option<&str>) -> bool { "select which borrowck is used (`ast`, `mir`, or `compare`)"), two_phase_borrows: bool = (false, parse_bool, [UNTRACKED], "use two-phase reserved/active distinction for `&mut` borrows in MIR borrowck"), + two_phase_beyond_autoref: bool = (false, parse_bool, [UNTRACKED], + "when using two-phase-borrows, allow two phases even for non-autoref `&mut` borrows"), time_passes: bool = (false, parse_bool, [UNTRACKED], "measure time of each rustc pass"), count_llvm_insns: bool = (false, parse_bool, @@ -1288,6 +1307,8 @@ fn parse_lto(slot: &mut Lto, v: Option<&str>) -> bool { dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED], "in dep-info output, omit targets for tracking dependencies of the dep-info files \ themselves"), + approximate_suggestions: bool = (false, parse_bool, [UNTRACKED], + "include machine-applicability of suggestions in JSON output"), unpretty: Option = (None, parse_unpretty, [UNTRACKED], "Present the input source, unstable (and less-pretty) variants; valid types are any of the types for `--pretty`, as well as: @@ -1295,6 +1316,12 @@ fn parse_lto(slot: &mut Lto, v: Option<&str>) -> bool { `everybody_loops` (all function bodies replaced with `loop {}`), `hir` (the HIR), `hir,identified`, or `hir,typed` (HIR with types for each node)."), + epoch: Epoch = (Epoch::Epoch2015, parse_epoch, [TRACKED], + "The epoch to build Rust with. Newer epochs may include features + that require breaking changes. The default epoch is 2015 (the first + epoch). Crates compiled with different epochs can be linked together."), + run_dsymutil: Option = (None, parse_opt_bool, [TRACKED], + "run `dsymutil` and delete intermediate object files"), } pub fn default_lib_output() -> CrateType { @@ -2086,7 +2113,7 @@ mod dep_tracking { use std::path::PathBuf; use std::collections::hash_map::DefaultHasher; use super::{Passes, CrateType, OptLevel, DebugInfoLevel, Lto, - OutputTypes, Externs, ErrorOutputType, Sanitizer}; + OutputTypes, Externs, ErrorOutputType, Sanitizer, Epoch}; use syntax::feature_gate::UnstableFeatures; use rustc_back::{PanicStrategy, RelroLevel}; @@ -2148,6 +2175,7 @@ fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) { impl_dep_tracking_hash_via_hash!(cstore::NativeLibraryKind); impl_dep_tracking_hash_via_hash!(Sanitizer); impl_dep_tracking_hash_via_hash!(Option); + impl_dep_tracking_hash_via_hash!(Epoch); impl_dep_tracking_hash_for_sortable_vec_of!(String); impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf); diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 2765239d5e6..9d7a9acc3d5 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -19,7 +19,7 @@ use middle::allocator::AllocatorKind; use middle::dependency_format; use session::search_paths::PathKind; -use session::config::{BorrowckMode, DebugInfoLevel, OutputType}; +use session::config::{BorrowckMode, DebugInfoLevel, OutputType, Epoch}; use ty::tls; use util::nodemap::{FxHashMap, FxHashSet}; use util::common::{duration_to_secs_str, ErrorReported}; @@ -864,6 +864,11 @@ pub fn codegen_units(&self) -> usize { pub fn teach(&self, code: &DiagnosticId) -> bool { self.opts.debugging_opts.teach && !self.parse_sess.span_diagnostic.code_emitted(code) } + + /// Are we allowed to use features from the Rust 2018 epoch? + pub fn rust_2018(&self) -> bool { + self.opts.debugging_opts.epoch >= Epoch::Epoch2018 + } } pub fn build_session(sopts: config::Options, @@ -904,22 +909,27 @@ pub fn build_session_with_codemap(sopts: config::Options, let emitter: Box = match (sopts.error_format, emitter_dest) { (config::ErrorOutputType::HumanReadable(color_config), None) => { - Box::new(EmitterWriter::stderr(color_config, Some(codemap.clone()), false)) + Box::new(EmitterWriter::stderr(color_config, + Some(codemap.clone()), + false, + sopts.debugging_opts.teach)) } (config::ErrorOutputType::HumanReadable(_), Some(dst)) => { - Box::new(EmitterWriter::new(dst, Some(codemap.clone()), false)) + Box::new(EmitterWriter::new(dst, Some(codemap.clone()), false, false)) } (config::ErrorOutputType::Json(pretty), None) => { - Box::new(JsonEmitter::stderr(Some(registry), codemap.clone(), pretty)) + Box::new(JsonEmitter::stderr(Some(registry), codemap.clone(), + pretty, sopts.debugging_opts.approximate_suggestions)) } (config::ErrorOutputType::Json(pretty), Some(dst)) => { - Box::new(JsonEmitter::new(dst, Some(registry), codemap.clone(), pretty)) + Box::new(JsonEmitter::new(dst, Some(registry), codemap.clone(), + pretty, sopts.debugging_opts.approximate_suggestions)) } (config::ErrorOutputType::Short(color_config), None) => { - Box::new(EmitterWriter::stderr(color_config, Some(codemap.clone()), true)) + Box::new(EmitterWriter::stderr(color_config, Some(codemap.clone()), true, false)) } (config::ErrorOutputType::Short(_), Some(dst)) => { - Box::new(EmitterWriter::new(dst, Some(codemap.clone()), true)) + Box::new(EmitterWriter::new(dst, Some(codemap.clone()), true, false)) } }; @@ -1095,11 +1105,11 @@ pub enum IncrCompSession { pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! { let emitter: Box = match output { config::ErrorOutputType::HumanReadable(color_config) => { - Box::new(EmitterWriter::stderr(color_config, None, false)) + Box::new(EmitterWriter::stderr(color_config, None, false, false)) } config::ErrorOutputType::Json(pretty) => Box::new(JsonEmitter::basic(pretty)), config::ErrorOutputType::Short(color_config) => { - Box::new(EmitterWriter::stderr(color_config, None, true)) + Box::new(EmitterWriter::stderr(color_config, None, true, false)) } }; let handler = errors::Handler::with_emitter(true, false, emitter); @@ -1110,11 +1120,11 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! { pub fn early_warn(output: config::ErrorOutputType, msg: &str) { let emitter: Box = match output { config::ErrorOutputType::HumanReadable(color_config) => { - Box::new(EmitterWriter::stderr(color_config, None, false)) + Box::new(EmitterWriter::stderr(color_config, None, false, false)) } config::ErrorOutputType::Json(pretty) => Box::new(JsonEmitter::basic(pretty)), config::ErrorOutputType::Short(color_config) => { - Box::new(EmitterWriter::stderr(color_config, None, true)) + Box::new(EmitterWriter::stderr(color_config, None, true, false)) } }; let handler = errors::Handler::with_emitter(true, false, emitter); diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index ae68e3fe8d0..9de18612d81 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -19,7 +19,7 @@ use ty::fold::TypeFoldable; use ty::subst::Subst; -use infer::{InferCtxt, InferOk}; +use infer::{InferOk}; /// Whether we do the orphan check relative to this crate or /// to some remote crate. @@ -40,13 +40,20 @@ pub struct OverlapResult<'tcx> { pub intercrate_ambiguity_causes: Vec, } -/// If there are types that satisfy both impls, returns a suitably-freshened -/// `ImplHeader` with those types substituted -pub fn overlapping_impls<'cx, 'gcx, 'tcx>(infcx: &InferCtxt<'cx, 'gcx, 'tcx>, - impl1_def_id: DefId, - impl2_def_id: DefId, - intercrate_mode: IntercrateMode) - -> Option> +/// If there are types that satisfy both impls, invokes `on_overlap` +/// with a suitably-freshened `ImplHeader` with those types +/// substituted. Otherwise, invokes `no_overlap`. +pub fn overlapping_impls<'gcx, F1, F2, R>( + tcx: TyCtxt<'_, 'gcx, 'gcx>, + impl1_def_id: DefId, + impl2_def_id: DefId, + intercrate_mode: IntercrateMode, + on_overlap: F1, + no_overlap: F2, +) -> R +where + F1: FnOnce(OverlapResult<'_>) -> R, + F2: FnOnce() -> R, { debug!("impl_can_satisfy(\ impl1_def_id={:?}, \ @@ -56,8 +63,23 @@ pub fn overlapping_impls<'cx, 'gcx, 'tcx>(infcx: &InferCtxt<'cx, 'gcx, 'tcx>, impl2_def_id, intercrate_mode); - let selcx = &mut SelectionContext::intercrate(infcx, intercrate_mode); - overlap(selcx, impl1_def_id, impl2_def_id) + let overlaps = tcx.infer_ctxt().enter(|infcx| { + let selcx = &mut SelectionContext::intercrate(&infcx, intercrate_mode); + overlap(selcx, impl1_def_id, impl2_def_id).is_some() + }); + + if !overlaps { + return no_overlap(); + } + + // In the case where we detect an error, run the check again, but + // this time tracking intercrate ambuiguity causes for better + // diagnostics. (These take time and can lead to false errors.) + tcx.infer_ctxt().enter(|infcx| { + let selcx = &mut SelectionContext::intercrate(&infcx, intercrate_mode); + selcx.enable_tracking_intercrate_ambiguity_causes(); + on_overlap(overlap(selcx, impl1_def_id, impl2_def_id).unwrap()) + }) } fn with_fresh_ty_vars<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, @@ -135,10 +157,10 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, return None } - Some(OverlapResult { - impl_header: selcx.infcx().resolve_type_vars_if_possible(&a_impl_header), - intercrate_ambiguity_causes: selcx.intercrate_ambiguity_causes().to_vec(), - }) + let impl_header = selcx.infcx().resolve_type_vars_if_possible(&a_impl_header); + let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes(); + debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes); + Some(OverlapResult { impl_header, intercrate_ambiguity_causes }) } pub fn trait_ref_is_knowable<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 42200a3a447..214d8ec325f 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -348,7 +348,7 @@ fn on_unimplemented_note( if direct { // this is a "direct", user-specified, rather than derived, // obligation. - flags.push(("direct", None)); + flags.push(("direct".to_string(), None)); } if let ObligationCauseCode::ItemObligation(item) = obligation.cause.code { @@ -359,21 +359,37 @@ fn on_unimplemented_note( // Currently I'm leaving it for what I need for `try`. if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) { method = self.tcx.item_name(item); - flags.push(("from_method", None)); - flags.push(("from_method", Some(&*method))); + flags.push(("from_method".to_string(), None)); + flags.push(("from_method".to_string(), Some(method.to_string()))); } } if let Some(k) = obligation.cause.span.compiler_desugaring_kind() { desugaring = k.as_symbol().as_str(); - flags.push(("from_desugaring", None)); - flags.push(("from_desugaring", Some(&*desugaring))); + flags.push(("from_desugaring".to_string(), None)); + flags.push(("from_desugaring".to_string(), Some(desugaring.to_string()))); + } + let generics = self.tcx.generics_of(def_id); + let self_ty = trait_ref.self_ty(); + let self_ty_str = self_ty.to_string(); + flags.push(("_Self".to_string(), Some(self_ty_str.clone()))); + + for param in generics.types.iter() { + let name = param.name.as_str().to_string(); + let ty = trait_ref.substs.type_for_def(param); + let ty_str = ty.to_string(); + flags.push((name.clone(), + Some(ty_str.clone()))); + } + + if let Some(true) = self_ty.ty_to_def_id().map(|def_id| def_id.is_local()) { + flags.push(("crate_local".to_string(), None)); } if let Ok(Some(command)) = OnUnimplementedDirective::of_item( self.tcx, trait_ref.def_id, def_id ) { - command.evaluate(self.tcx, trait_ref, &flags) + command.evaluate(self.tcx, trait_ref, &flags[..]) } else { OnUnimplementedNote::empty() } @@ -549,7 +565,7 @@ pub fn report_selection_error(&self, .map(|t| (format!(" in `{}`", t), format!("within `{}`, ", t))) .unwrap_or((String::new(), String::new())); - let OnUnimplementedNote { message, label } + let OnUnimplementedNote { message, label, note } = self.on_unimplemented_note(trait_ref, obligation); let have_alt_message = message.is_some() || label.is_some(); @@ -578,6 +594,10 @@ pub fn report_selection_error(&self, trait_ref, trait_ref.self_ty())); } + if let Some(ref s) = note { + // If it has a custom "#[rustc_on_unimplemented]" note, let's display it + err.note(s.as_str()); + } self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err); @@ -744,8 +764,10 @@ pub fn report_selection_error(&self, } else { let (closure_span, found) = found_did .and_then(|did| self.tcx.hir.get_if_local(did)) - .map(|node| self.get_fn_like_arguments(node)) - .unwrap_or((found_span.unwrap(), found)); + .map(|node| { + let (found_span, found) = self.get_fn_like_arguments(node); + (Some(found_span), found) + }).unwrap_or((found_span, found)); self.report_arg_count_mismatch(span, closure_span, @@ -831,6 +853,11 @@ fn get_fn_like_arguments(&self, node: hir::map::Node) -> (Span, Vec) { span, node: hir::ImplItemKind::Method(hir::MethodSig { ref decl, .. }, _), .. + }) | + hir::map::NodeTraitItem(&hir::TraitItem { + span, + node: hir::TraitItemKind::Method(hir::MethodSig { ref decl, .. }, _), + .. }) => { (self.tcx.sess.codemap().def_span(span), decl.inputs.iter() .map(|arg| match arg.clone().into_inner().node { @@ -850,7 +877,7 @@ fn get_fn_like_arguments(&self, node: hir::map::Node) -> (Span, Vec) { fn report_arg_count_mismatch( &self, span: Span, - found_span: Span, + found_span: Option, expected_args: Vec, found_args: Vec, is_closure: bool, @@ -888,48 +915,51 @@ fn report_arg_count_mismatch( ); err.span_label(span, format!( "expected {} that takes {}", kind, expected_str)); - err.span_label(found_span, format!("takes {}", found_str)); - - if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] { - if fields.len() == expected_args.len() { - let sugg = fields.iter() - .map(|(name, _)| name.to_owned()) - .collect::>().join(", "); - err.span_suggestion(found_span, - "change the closure to take multiple arguments instead of \ - a single tuple", - format!("|{}|", sugg)); + + if let Some(found_span) = found_span { + err.span_label(found_span, format!("takes {}", found_str)); + + if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] { + if fields.len() == expected_args.len() { + let sugg = fields.iter() + .map(|(name, _)| name.to_owned()) + .collect::>().join(", "); + err.span_suggestion(found_span, + "change the closure to take multiple arguments instead of \ + a single tuple", + format!("|{}|", sugg)); + } } - } - if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] { - if fields.len() == found_args.len() && is_closure { - let sugg = format!( - "|({}){}|", - found_args.iter() - .map(|arg| match arg { - ArgKind::Arg(name, _) => name.to_owned(), - _ => "_".to_owned(), - }) - .collect::>() - .join(", "), - // add type annotations if available - if found_args.iter().any(|arg| match arg { - ArgKind::Arg(_, ty) => ty != "_", - _ => false, - }) { - format!(": ({})", - fields.iter() - .map(|(_, ty)| ty.to_owned()) - .collect::>() - .join(", ")) - } else { - "".to_owned() - }, - ); - err.span_suggestion(found_span, - "change the closure to accept a tuple instead of individual \ - arguments", - sugg); + if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] { + if fields.len() == found_args.len() && is_closure { + let sugg = format!( + "|({}){}|", + found_args.iter() + .map(|arg| match arg { + ArgKind::Arg(name, _) => name.to_owned(), + _ => "_".to_owned(), + }) + .collect::>() + .join(", "), + // add type annotations if available + if found_args.iter().any(|arg| match arg { + ArgKind::Arg(_, ty) => ty != "_", + _ => false, + }) { + format!(": ({})", + fields.iter() + .map(|(_, ty)| ty.to_owned()) + .collect::>() + .join(", ")) + } else { + "".to_owned() + }, + ); + err.span_suggestion(found_span, + "change the closure to accept a tuple instead of \ + individual arguments", + sugg); + } } } @@ -1194,13 +1224,15 @@ fn note_obligation_cause(&self, { self.note_obligation_cause_code(err, &obligation.predicate, - &obligation.cause.code); + &obligation.cause.code, + &mut vec![]); } fn note_obligation_cause_code(&self, err: &mut DiagnosticBuilder, predicate: &T, - cause_code: &ObligationCauseCode<'tcx>) + cause_code: &ObligationCauseCode<'tcx>, + obligated_types: &mut Vec<&ty::TyS<'tcx>>) where T: fmt::Display { let tcx = self.tcx; @@ -1261,6 +1293,10 @@ fn note_obligation_cause_code(&self, err.note("the return type of a function must have a \ statically known size"); } + ObligationCauseCode::SizedYieldType => { + err.note("the yield type of a generator must have a \ + statically known size"); + } ObligationCauseCode::AssignmentLhsSized => { err.note("the left-hand-side of an assignment must have a statically known size"); } @@ -1292,12 +1328,17 @@ fn note_obligation_cause_code(&self, } ObligationCauseCode::BuiltinDerivedObligation(ref data) => { let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref); - err.note(&format!("required because it appears within the type `{}`", - parent_trait_ref.0.self_ty())); + let ty = parent_trait_ref.0.self_ty(); + err.note(&format!("required because it appears within the type `{}`", ty)); + obligated_types.push(ty); + let parent_predicate = parent_trait_ref.to_predicate(); - self.note_obligation_cause_code(err, - &parent_predicate, - &data.parent_code); + if !self.is_recursive_obligation(obligated_types, &data.parent_code) { + self.note_obligation_cause_code(err, + &parent_predicate, + &data.parent_code, + obligated_types); + } } ObligationCauseCode::ImplDerivedObligation(ref data) => { let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref); @@ -1307,8 +1348,9 @@ fn note_obligation_cause_code(&self, parent_trait_ref.0.self_ty())); let parent_predicate = parent_trait_ref.to_predicate(); self.note_obligation_cause_code(err, - &parent_predicate, - &data.parent_code); + &parent_predicate, + &data.parent_code, + obligated_types); } ObligationCauseCode::CompareImplMethodObligation { .. } => { err.note( @@ -1327,6 +1369,20 @@ fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder) { err.help(&format!("consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate", suggested_limit)); } + + fn is_recursive_obligation(&self, + obligated_types: &mut Vec<&ty::TyS<'tcx>>, + cause_code: &ObligationCauseCode<'tcx>) -> bool { + if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code { + let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref); + for obligated_type in obligated_types { + if obligated_type == &parent_trait_ref.0.self_ty() { + return true; + } + } + } + return false; + } } enum ArgKind { diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index fd47e09aad7..80819a86b7c 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -100,6 +100,19 @@ pub struct ObligationCause<'tcx> { pub code: ObligationCauseCode<'tcx> } +impl<'tcx> ObligationCause<'tcx> { + pub fn span<'a, 'gcx>(&self, tcx: &TyCtxt<'a, 'gcx, 'tcx>) -> Span { + match self.code { + ObligationCauseCode::CompareImplMethodObligation { .. } | + ObligationCauseCode::MainFunctionType | + ObligationCauseCode::StartFunctionType => { + tcx.sess.codemap().def_span(self.span) + } + _ => self.span, + } + } +} + #[derive(Clone, Debug, PartialEq, Eq)] pub enum ObligationCauseCode<'tcx> { /// Not well classified or should be obvious from span. @@ -138,6 +151,8 @@ pub enum ObligationCauseCode<'tcx> { VariableType(ast::NodeId), /// Return type must be Sized SizedReturnType, + /// Yield type must be Sized + SizedYieldType, /// [T,..n] --> T must be Copy RepeatVec, diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index 757b078086d..8c2c1cfa454 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -29,16 +29,18 @@ pub struct OnUnimplementedDirective { pub subcommands: Vec, pub message: Option, pub label: Option, + pub note: Option, } pub struct OnUnimplementedNote { pub message: Option, pub label: Option, + pub note: Option, } impl OnUnimplementedNote { pub fn empty() -> Self { - OnUnimplementedNote { message: None, label: None } + OnUnimplementedNote { message: None, label: None, note: None } } } @@ -89,6 +91,7 @@ pub fn parse(tcx: TyCtxt<'a, 'gcx, 'tcx>, let mut message = None; let mut label = None; + let mut note = None; let mut subcommands = vec![]; for item in item_iter { if item.check_name("message") && message.is_none() { @@ -103,8 +106,14 @@ pub fn parse(tcx: TyCtxt<'a, 'gcx, 'tcx>, tcx, trait_def_id, label_.as_str(), span)?); continue; } + } else if item.check_name("note") && note.is_none() { + if let Some(note_) = item.value_str() { + note = Some(OnUnimplementedFormatString::try_parse( + tcx, trait_def_id, note_.as_str(), span)?); + continue; + } } else if item.check_name("on") && is_root && - message.is_none() && label.is_none() + message.is_none() && label.is_none() && note.is_none() { if let Some(items) = item.meta_item_list() { if let Ok(subcommand) = @@ -128,7 +137,7 @@ pub fn parse(tcx: TyCtxt<'a, 'gcx, 'tcx>, if errored { Err(ErrorReported) } else { - Ok(OnUnimplementedDirective { condition, message, label, subcommands }) + Ok(OnUnimplementedDirective { condition, message, label, subcommands, note }) } } @@ -154,7 +163,8 @@ pub fn of_item(tcx: TyCtxt<'a, 'gcx, 'tcx>, message: None, subcommands: vec![], label: Some(OnUnimplementedFormatString::try_parse( - tcx, trait_def_id, value.as_str(), attr.span)?) + tcx, trait_def_id, value.as_str(), attr.span)?), + note: None, })) } else { return Err(parse_error(tcx, attr.span, @@ -169,20 +179,20 @@ pub fn of_item(tcx: TyCtxt<'a, 'gcx, 'tcx>, pub fn evaluate(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, trait_ref: ty::TraitRef<'tcx>, - options: &[(&str, Option<&str>)]) + options: &[(String, Option)]) -> OnUnimplementedNote { let mut message = None; let mut label = None; - info!("evaluate({:?}, trait_ref={:?}, options={:?})", - self, trait_ref, options); + let mut note = None; + info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options); for command in self.subcommands.iter().chain(Some(self)).rev() { if let Some(ref condition) = command.condition { if !attr::eval_condition(condition, &tcx.sess.parse_sess, &mut |c| { - options.contains(&(&c.name().as_str(), - match c.value_str().map(|s| s.as_str()) { - Some(ref s) => Some(s), + options.contains(&(c.name().as_str().to_string(), + match c.value_str().map(|s| s.as_str().to_string()) { + Some(s) => Some(s), None => None })) }) { @@ -198,11 +208,16 @@ pub fn evaluate(&self, if let Some(ref label_) = command.label { label = Some(label_.clone()); } + + if let Some(ref note_) = command.note { + note = Some(note_.clone()); + } } OnUnimplementedNote { label: label.map(|l| l.format(tcx, trait_ref)), - message: message.map(|m| m.format(tcx, trait_ref)) + message: message.map(|m| m.format(tcx, trait_ref)), + note: note.map(|n| n.format(tcx, trait_ref)), } } } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 55cbc890e1e..4ed25646d43 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -92,10 +92,10 @@ pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> { inferred_obligations: SnapshotVec>, - intercrate_ambiguity_causes: Vec, + intercrate_ambiguity_causes: Option>, } -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum IntercrateAmbiguityCause { DownstreamCrate { trait_desc: String, @@ -423,7 +423,7 @@ pub fn new(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>) -> SelectionContext<'cx, 'gcx freshener: infcx.freshener(), intercrate: None, inferred_obligations: SnapshotVec::new(), - intercrate_ambiguity_causes: Vec::new(), + intercrate_ambiguity_causes: None, } } @@ -435,10 +435,30 @@ pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, freshener: infcx.freshener(), intercrate: Some(mode), inferred_obligations: SnapshotVec::new(), - intercrate_ambiguity_causes: Vec::new(), + intercrate_ambiguity_causes: None, } } + /// Enables tracking of intercrate ambiguity causes. These are + /// used in coherence to give improved diagnostics. We don't do + /// this until we detect a coherence error because it can lead to + /// false overflow results (#47139) and because it costs + /// computation time. + pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) { + assert!(self.intercrate.is_some()); + assert!(self.intercrate_ambiguity_causes.is_none()); + self.intercrate_ambiguity_causes = Some(vec![]); + debug!("selcx: enable_tracking_intercrate_ambiguity_causes"); + } + + /// Gets the intercrate ambiguity causes collected since tracking + /// was enabled and disables tracking at the same time. If + /// tracking is not enabled, just returns an empty vector. + pub fn take_intercrate_ambiguity_causes(&mut self) -> Vec { + assert!(self.intercrate.is_some()); + self.intercrate_ambiguity_causes.take().unwrap_or(vec![]) + } + pub fn infcx(&self) -> &'cx InferCtxt<'cx, 'gcx, 'tcx> { self.infcx } @@ -451,10 +471,6 @@ pub fn closure_typer(&self) -> &'cx InferCtxt<'cx, 'gcx, 'tcx> { self.infcx } - pub fn intercrate_ambiguity_causes(&self) -> &[IntercrateAmbiguityCause] { - &self.intercrate_ambiguity_causes - } - /// Wraps the inference context's in_snapshot s.t. snapshot handling is only from the selection /// context's self. fn in_snapshot(&mut self, f: F) -> R @@ -828,19 +844,23 @@ fn evaluate_stack<'o>(&mut self, debug!("evaluate_stack({:?}) --> unbound argument, intercrate --> ambiguous", stack.fresh_trait_ref); // Heuristics: show the diagnostics when there are no candidates in crate. - if let Ok(candidate_set) = self.assemble_candidates(stack) { - if !candidate_set.ambiguous && candidate_set.vec.is_empty() { - let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; - let self_ty = trait_ref.self_ty(); - let cause = IntercrateAmbiguityCause::DownstreamCrate { - trait_desc: trait_ref.to_string(), - self_desc: if self_ty.has_concrete_skeleton() { - Some(self_ty.to_string()) - } else { - None - }, - }; - self.intercrate_ambiguity_causes.push(cause); + if self.intercrate_ambiguity_causes.is_some() { + debug!("evaluate_stack: intercrate_ambiguity_causes is some"); + if let Ok(candidate_set) = self.assemble_candidates(stack) { + if !candidate_set.ambiguous && candidate_set.vec.is_empty() { + let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; + let self_ty = trait_ref.self_ty(); + let cause = IntercrateAmbiguityCause::DownstreamCrate { + trait_desc: trait_ref.to_string(), + self_desc: if self_ty.has_concrete_skeleton() { + Some(self_ty.to_string()) + } else { + None + }, + }; + debug!("evaluate_stack: pushing cause = {:?}", cause); + self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause); + } } } return EvaluatedToAmbig; @@ -1092,25 +1112,29 @@ fn candidate_from_obligation_no_cache<'o>(&mut self, None => {} Some(conflict) => { debug!("coherence stage: not knowable"); - // Heuristics: show the diagnostics when there are no candidates in crate. - let candidate_set = self.assemble_candidates(stack)?; - if !candidate_set.ambiguous && candidate_set.vec.iter().all(|c| { - !self.evaluate_candidate(stack, &c).may_apply() - }) { - let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; - let self_ty = trait_ref.self_ty(); - let trait_desc = trait_ref.to_string(); - let self_desc = if self_ty.has_concrete_skeleton() { - Some(self_ty.to_string()) - } else { - None - }; - let cause = if let Conflict::Upstream = conflict { - IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_desc, self_desc } - } else { - IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc } - }; - self.intercrate_ambiguity_causes.push(cause); + if self.intercrate_ambiguity_causes.is_some() { + debug!("evaluate_stack: intercrate_ambiguity_causes is some"); + // Heuristics: show the diagnostics when there are no candidates in crate. + let candidate_set = self.assemble_candidates(stack)?; + if !candidate_set.ambiguous && candidate_set.vec.iter().all(|c| { + !self.evaluate_candidate(stack, &c).may_apply() + }) { + let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; + let self_ty = trait_ref.self_ty(); + let trait_desc = trait_ref.to_string(); + let self_desc = if self_ty.has_concrete_skeleton() { + Some(self_ty.to_string()) + } else { + None + }; + let cause = if let Conflict::Upstream = conflict { + IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_desc, self_desc } + } else { + IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc } + }; + debug!("evaluate_stack: pushing cause = {:?}", cause); + self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause); + } } return Ok(None); } diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index 834389e5d00..a10169e13e6 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -133,12 +133,12 @@ fn insert(&mut self, }; let tcx = tcx.global_tcx(); - let (le, ge) = tcx.infer_ctxt().enter(|infcx| { - let overlap = traits::overlapping_impls(&infcx, - possible_sibling, - impl_def_id, - traits::IntercrateMode::Issue43355); - if let Some(overlap) = overlap { + let (le, ge) = traits::overlapping_impls( + tcx, + possible_sibling, + impl_def_id, + traits::IntercrateMode::Issue43355, + |overlap| { if tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) { return Ok((false, false)); } @@ -151,10 +151,9 @@ fn insert(&mut self, } else { Ok((le, ge)) } - } else { - Ok((false, false)) - } - })?; + }, + || Ok((false, false)), + )?; if le && !ge { debug!("descending as child of TraitRef {:?}", @@ -171,16 +170,14 @@ fn insert(&mut self, return Ok(Inserted::Replaced(possible_sibling)); } else { if !tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) { - tcx.infer_ctxt().enter(|infcx| { - if let Some(overlap) = traits::overlapping_impls( - &infcx, - possible_sibling, - impl_def_id, - traits::IntercrateMode::Fixed) - { - last_lint = Some(overlap_error(overlap)); - } - }); + traits::overlapping_impls( + tcx, + possible_sibling, + impl_def_id, + traits::IntercrateMode::Fixed, + |overlap| last_lint = Some(overlap_error(overlap)), + || (), + ); } // no overlap (error bailed already via ?) diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index e1e2798ecb5..1eb14a22278 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -209,6 +209,7 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option Some(super::VariableType(id)), super::ReturnType(id) => Some(super::ReturnType(id)), super::SizedReturnType => Some(super::SizedReturnType), + super::SizedYieldType => Some(super::SizedYieldType), super::RepeatVec => Some(super::RepeatVec), super::FieldSized(item) => Some(super::FieldSized(item)), super::ConstSized => Some(super::ConstSized), @@ -526,6 +527,7 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) super::VariableType(_) | super::ReturnType(_) | super::SizedReturnType | + super::SizedYieldType | super::ReturnNoExpression | super::RepeatVec | super::FieldSized(_) | @@ -574,6 +576,7 @@ fn super_visit_with>(&self, visitor: &mut V) -> bool { super::VariableType(_) | super::ReturnType(_) | super::SizedReturnType | + super::SizedYieldType | super::ReturnNoExpression | super::RepeatVec | super::FieldSized(_) | diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs index 6df6bb9df23..7579d95a8fe 100644 --- a/src/librustc/ty/adjustment.rs +++ b/src/librustc/ty/adjustment.rs @@ -77,7 +77,7 @@ pub enum Adjust<'tcx> { /// Go from a mut raw pointer to a const raw pointer. MutToConstPointer, - /// Dereference once, producing an lvalue. + /// Dereference once, producing a place. Deref(Option>), /// Take the address and produce either a `&` or `*` pointer. @@ -119,10 +119,25 @@ pub fn method_call(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, source: Ty<'tcx>) } } +#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)] +pub enum AutoBorrowMutability { + Mutable { allow_two_phase_borrow: bool }, + Immutable, +} + +impl From for hir::Mutability { + fn from(m: AutoBorrowMutability) -> Self { + match m { + AutoBorrowMutability::Mutable { .. } => hir::MutMutable, + AutoBorrowMutability::Immutable => hir::MutImmutable, + } + } +} + #[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)] pub enum AutoBorrow<'tcx> { /// Convert from T to &T. - Ref(ty::Region<'tcx>, hir::Mutability), + Ref(ty::Region<'tcx>, AutoBorrowMutability), /// Convert from T to *T. RawPtr(hir::Mutability), diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 69d07eafdca..63b91ff1101 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -895,7 +895,8 @@ fn layout_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } tcx.layout_depth.set(depth+1); - let layout = LayoutDetails::compute_uncached(tcx, param_env, ty); + let cx = LayoutCx { tcx, param_env }; + let layout = cx.layout_raw_uncached(ty); tcx.layout_depth.set(depth); layout @@ -908,13 +909,18 @@ pub fn provide(providers: &mut ty::maps::Providers) { }; } -impl<'a, 'tcx> LayoutDetails { - fn compute_uncached(tcx: TyCtxt<'a, 'tcx, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - ty: Ty<'tcx>) - -> Result<&'tcx Self, LayoutError<'tcx>> { - let cx = (tcx, param_env); - let dl = cx.data_layout(); +#[derive(Copy, Clone)] +pub struct LayoutCx<'tcx, C> { + pub tcx: C, + pub param_env: ty::ParamEnv<'tcx> +} + +impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { + fn layout_raw_uncached(self, ty: Ty<'tcx>) + -> Result<&'tcx LayoutDetails, LayoutError<'tcx>> { + let tcx = self.tcx; + let param_env = self.param_env; + let dl = self.data_layout(); let scalar_unit = |value: Primitive| { let bits = value.size(dl).bits(); assert!(bits <= 128); @@ -924,7 +930,7 @@ fn compute_uncached(tcx: TyCtxt<'a, 'tcx, 'tcx>, } }; let scalar = |value: Primitive| { - tcx.intern_layout(LayoutDetails::scalar(cx, scalar_unit(value))) + tcx.intern_layout(LayoutDetails::scalar(self, scalar_unit(value))) }; let scalar_pair = |a: Scalar, b: Scalar| { let align = a.value.align(dl).max(b.value.align(dl)).max(dl.aggregate_align); @@ -1158,13 +1164,13 @@ enum StructKind { Ok(match ty.sty { // Basic scalars. ty::TyBool => { - tcx.intern_layout(LayoutDetails::scalar(cx, Scalar { + tcx.intern_layout(LayoutDetails::scalar(self, Scalar { value: Int(I8, false), valid_range: 0..=1 })) } ty::TyChar => { - tcx.intern_layout(LayoutDetails::scalar(cx, Scalar { + tcx.intern_layout(LayoutDetails::scalar(self, Scalar { value: Int(I32, false), valid_range: 0..=0x10FFFF })) @@ -1180,7 +1186,7 @@ enum StructKind { ty::TyFnPtr(_) => { let mut ptr = scalar_unit(Pointer); ptr.valid_range.start = 1; - tcx.intern_layout(LayoutDetails::scalar(cx, ptr)) + tcx.intern_layout(LayoutDetails::scalar(self, ptr)) } // The never type. @@ -1198,13 +1204,13 @@ enum StructKind { let pointee = tcx.normalize_associated_type_in_env(&pointee, param_env); if pointee.is_sized(tcx, param_env, DUMMY_SP) { - return Ok(tcx.intern_layout(LayoutDetails::scalar(cx, data_ptr))); + return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr))); } let unsized_part = tcx.struct_tail(pointee); let metadata = match unsized_part.sty { ty::TyForeign(..) => { - return Ok(tcx.intern_layout(LayoutDetails::scalar(cx, data_ptr))); + return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr))); } ty::TySlice(_) | ty::TyStr => { scalar_unit(Int(dl.ptr_sized_integer(), false)) @@ -1230,7 +1236,7 @@ enum StructKind { } } - let element = cx.layout_of(element)?; + let element = self.layout_of(element)?; let count = count.val.to_const_int().unwrap().to_u64().unwrap(); let size = element.size.checked_mul(count, dl) .ok_or(LayoutError::SizeOverflow(ty))?; @@ -1247,7 +1253,7 @@ enum StructKind { }) } ty::TySlice(element) => { - let element = cx.layout_of(element)?; + let element = self.layout_of(element)?; tcx.intern_layout(LayoutDetails { variants: Variants::Single { index: 0 }, fields: FieldPlacement::Array { @@ -1289,14 +1295,14 @@ enum StructKind { // Tuples, generators and closures. ty::TyGenerator(def_id, ref substs, _) => { let tys = substs.field_tys(def_id, tcx); - univariant(&tys.map(|ty| cx.layout_of(ty)).collect::, _>>()?, + univariant(&tys.map(|ty| self.layout_of(ty)).collect::, _>>()?, &ReprOptions::default(), StructKind::AlwaysSized)? } ty::TyClosure(def_id, ref substs) => { let tys = substs.upvar_tys(def_id, tcx); - univariant(&tys.map(|ty| cx.layout_of(ty)).collect::, _>>()?, + univariant(&tys.map(|ty| self.layout_of(ty)).collect::, _>>()?, &ReprOptions::default(), StructKind::AlwaysSized)? } @@ -1308,13 +1314,13 @@ enum StructKind { StructKind::MaybeUnsized }; - univariant(&tys.iter().map(|ty| cx.layout_of(ty)).collect::, _>>()?, + univariant(&tys.iter().map(|ty| self.layout_of(ty)).collect::, _>>()?, &ReprOptions::default(), kind)? } // SIMD vector types. ty::TyAdt(def, ..) if def.repr.simd() => { - let element = cx.layout_of(ty.simd_type(tcx))?; + let element = self.layout_of(ty.simd_type(tcx))?; let count = ty.simd_size(tcx) as u64; assert!(count > 0); let scalar = match element.abi { @@ -1350,7 +1356,7 @@ enum StructKind { // Cache the field layouts. let variants = def.variants.iter().map(|v| { v.fields.iter().map(|field| { - cx.layout_of(field.ty(tcx, substs)) + self.layout_of(field.ty(tcx, substs)) }).collect::, _>>() }).collect::, _>>()?; @@ -1430,7 +1436,7 @@ enum StructKind { let mut st = univariant_uninterned(&variants[v], &def.repr, kind)?; st.variants = Variants::Single { index: v }; // Exclude 0 from the range of a newtype ABI NonZero. - if Some(def.did) == cx.tcx().lang_items().non_zero() { + if Some(def.did) == self.tcx.lang_items().non_zero() { match st.abi { Abi::Scalar(ref mut scalar) | Abi::ScalarPair(ref mut scalar, _) => { @@ -1482,7 +1488,7 @@ enum StructKind { let count = (niche_variants.end - niche_variants.start + 1) as u128; for (field_index, field) in variants[i].iter().enumerate() { let (offset, niche, niche_start) = - match field.find_niche(cx, count)? { + match field.find_niche(self, count)? { Some(niche) => niche, None => continue }; @@ -1687,56 +1693,49 @@ enum StructKind { /// This is invoked by the `layout_raw` query to record the final /// layout of each type. #[inline] - fn record_layout_for_printing(tcx: TyCtxt<'a, 'tcx, 'tcx>, - ty: Ty<'tcx>, - param_env: ty::ParamEnv<'tcx>, - layout: TyLayout<'tcx>) { + fn record_layout_for_printing(self, layout: TyLayout<'tcx>) { // If we are running with `-Zprint-type-sizes`, record layouts for // dumping later. Ignore layouts that are done with non-empty // environments or non-monomorphic layouts, as the user only wants // to see the stuff resulting from the final trans session. if - !tcx.sess.opts.debugging_opts.print_type_sizes || - ty.has_param_types() || - ty.has_self_ty() || - !param_env.caller_bounds.is_empty() + !self.tcx.sess.opts.debugging_opts.print_type_sizes || + layout.ty.has_param_types() || + layout.ty.has_self_ty() || + !self.param_env.caller_bounds.is_empty() { return; } - Self::record_layout_for_printing_outlined(tcx, ty, param_env, layout) + self.record_layout_for_printing_outlined(layout) } - fn record_layout_for_printing_outlined(tcx: TyCtxt<'a, 'tcx, 'tcx>, - ty: Ty<'tcx>, - param_env: ty::ParamEnv<'tcx>, - layout: TyLayout<'tcx>) { - let cx = (tcx, param_env); + fn record_layout_for_printing_outlined(self, layout: TyLayout<'tcx>) { // (delay format until we actually need it) let record = |kind, opt_discr_size, variants| { - let type_desc = format!("{:?}", ty); - tcx.sess.code_stats.borrow_mut().record_type_size(kind, - type_desc, - layout.align, - layout.size, - opt_discr_size, - variants); + let type_desc = format!("{:?}", layout.ty); + self.tcx.sess.code_stats.borrow_mut().record_type_size(kind, + type_desc, + layout.align, + layout.size, + opt_discr_size, + variants); }; - let adt_def = match ty.sty { + let adt_def = match layout.ty.sty { ty::TyAdt(ref adt_def, _) => { - debug!("print-type-size t: `{:?}` process adt", ty); + debug!("print-type-size t: `{:?}` process adt", layout.ty); adt_def } ty::TyClosure(..) => { - debug!("print-type-size t: `{:?}` record closure", ty); + debug!("print-type-size t: `{:?}` record closure", layout.ty); record(DataTypeKind::Closure, None, vec![]); return; } _ => { - debug!("print-type-size t: `{:?}` skip non-nominal", ty); + debug!("print-type-size t: `{:?}` skip non-nominal", layout.ty); return; } }; @@ -1748,7 +1747,7 @@ fn record_layout_for_printing_outlined(tcx: TyCtxt<'a, 'tcx, 'tcx>, layout: TyLayout<'tcx>| { let mut min_size = Size::from_bytes(0); let field_info: Vec<_> = flds.iter().enumerate().map(|(i, &name)| { - match layout.field(cx, i) { + match layout.field(self, i) { Err(err) => { bug!("no layout found for field {}: `{:?}`", name, err); } @@ -1808,18 +1807,18 @@ fn record_layout_for_printing_outlined(tcx: TyCtxt<'a, 'tcx, 'tcx>, Variants::NicheFilling { .. } | Variants::Tagged { .. } => { debug!("print-type-size `{:#?}` adt general variants def {}", - ty, adt_def.variants.len()); + layout.ty, adt_def.variants.len()); let variant_infos: Vec<_> = adt_def.variants.iter().enumerate().map(|(i, variant_def)| { let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect(); build_variant_info(Some(variant_def.name), &fields, - layout.for_variant(cx, i)) + layout.for_variant(self, i)) }) .collect(); record(adt_kind.into(), match layout.variants { - Variants::Tagged { ref discr, .. } => Some(discr.value.size(tcx)), + Variants::Tagged { ref discr, .. } => Some(discr.value.size(self)), _ => None }, variant_infos); } @@ -1855,7 +1854,7 @@ pub fn compute(ty: Ty<'tcx>, assert!(!ty.has_infer_types()); // First try computing a static layout. - let err = match (tcx, param_env).layout_of(ty) { + let err = match tcx.layout_of(param_env.and(ty)) { Ok(layout) => { return Ok(SizeSkeleton::Known(layout.size)); } @@ -2001,15 +2000,15 @@ fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'gcx> { } } -impl<'a, 'gcx, 'tcx, T: Copy> HasDataLayout for (TyCtxt<'a, 'gcx, 'tcx>, T) { +impl<'tcx, T: HasDataLayout> HasDataLayout for LayoutCx<'tcx, T> { fn data_layout(&self) -> &TargetDataLayout { - self.0.data_layout() + self.tcx.data_layout() } } -impl<'a, 'gcx, 'tcx, T: Copy> HasTyCtxt<'gcx> for (TyCtxt<'a, 'gcx, 'tcx>, T) { +impl<'gcx, 'tcx, T: HasTyCtxt<'gcx>> HasTyCtxt<'gcx> for LayoutCx<'tcx, T> { fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'gcx> { - self.0.tcx() + self.tcx.tcx() } } @@ -2042,17 +2041,15 @@ pub trait LayoutOf { fn layout_of(self, ty: T) -> Self::TyLayout; } -impl<'a, 'tcx> LayoutOf> for (TyCtxt<'a, 'tcx, 'tcx>, ty::ParamEnv<'tcx>) { +impl<'a, 'tcx> LayoutOf> for LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { type TyLayout = Result, LayoutError<'tcx>>; /// Computes the layout of a type. Note that this implicitly /// executes in "reveal all" mode. - #[inline] fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout { - let (tcx, param_env) = self; - - let ty = tcx.normalize_associated_type_in_env(&ty, param_env.reveal_all()); - let details = tcx.layout_raw(param_env.reveal_all().and(ty))?; + let param_env = self.param_env.reveal_all(); + let ty = self.tcx.normalize_associated_type_in_env(&ty, param_env); + let details = self.tcx.layout_raw(param_env.and(ty))?; let layout = TyLayout { ty, details @@ -2064,24 +2061,21 @@ fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout { // completed, to avoid problems around recursive structures // and the like. (Admitedly, I wasn't able to reproduce a problem // here, but it seems like the right thing to do. -nmatsakis) - LayoutDetails::record_layout_for_printing(tcx, ty, param_env, layout); + self.record_layout_for_printing(layout); Ok(layout) } } -impl<'a, 'tcx> LayoutOf> for (ty::maps::TyCtxtAt<'a, 'tcx, 'tcx>, - ty::ParamEnv<'tcx>) { +impl<'a, 'tcx> LayoutOf> for LayoutCx<'tcx, ty::maps::TyCtxtAt<'a, 'tcx, 'tcx>> { type TyLayout = Result, LayoutError<'tcx>>; /// Computes the layout of a type. Note that this implicitly /// executes in "reveal all" mode. - #[inline] fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout { - let (tcx_at, param_env) = self; - - let ty = tcx_at.tcx.normalize_associated_type_in_env(&ty, param_env.reveal_all()); - let details = tcx_at.layout_raw(param_env.reveal_all().and(ty))?; + let param_env = self.param_env.reveal_all(); + let ty = self.tcx.normalize_associated_type_in_env(&ty, param_env.reveal_all()); + let details = self.tcx.layout_raw(param_env.reveal_all().and(ty))?; let layout = TyLayout { ty, details @@ -2093,12 +2087,45 @@ fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout { // completed, to avoid problems around recursive structures // and the like. (Admitedly, I wasn't able to reproduce a problem // here, but it seems like the right thing to do. -nmatsakis) - LayoutDetails::record_layout_for_printing(tcx_at.tcx, ty, param_env, layout); + let cx = LayoutCx { + tcx: *self.tcx, + param_env: self.param_env + }; + cx.record_layout_for_printing(layout); Ok(layout) } } +// Helper (inherent) `layout_of` methods to avoid pushing `LayoutCx` to users. +impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { + /// Computes the layout of a type. Note that this implicitly + /// executes in "reveal all" mode. + #[inline] + pub fn layout_of(self, param_env_and_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) + -> Result, LayoutError<'tcx>> { + let cx = LayoutCx { + tcx: self, + param_env: param_env_and_ty.param_env + }; + cx.layout_of(param_env_and_ty.value) + } +} + +impl<'a, 'tcx> ty::maps::TyCtxtAt<'a, 'tcx, 'tcx> { + /// Computes the layout of a type. Note that this implicitly + /// executes in "reveal all" mode. + #[inline] + pub fn layout_of(self, param_env_and_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) + -> Result, LayoutError<'tcx>> { + let cx = LayoutCx { + tcx: self, + param_env: param_env_and_ty.param_env + }; + cx.layout_of(param_env_and_ty.value) + } +} + impl<'a, 'tcx> TyLayout<'tcx> { pub fn for_variant(&self, cx: C, variant_index: usize) -> Self where C: LayoutOf> + HasTyCtxt<'tcx>, diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 6c79f6a62fa..85fca68187f 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -343,6 +343,7 @@ -> (Arc, Arc>>>), [] fn export_name: ExportName(DefId) -> Option, [] fn contains_extern_indicator: ContainsExternIndicator(DefId) -> bool, + [] fn symbol_export_level: GetSymbolExportLevel(DefId) -> SymbolExportLevel, [] fn is_translated_function: IsTranslatedFunction(DefId) -> bool, [] fn codegen_unit: CodegenUnit(InternedString) -> Arc>, [] fn compile_codegen_unit: CompileCodegenUnit(InternedString) -> Stats, diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index c9eebc3d2a0..0ab6ee1a54a 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -921,6 +921,8 @@ macro_rules! force { DepKind::TargetFeaturesWhitelist => { force!(target_features_whitelist, LOCAL_CRATE); } DepKind::TargetFeaturesEnabled => { force!(target_features_enabled, def_id!()); } + + DepKind::GetSymbolExportLevel => { force!(symbol_export_level, def_id!()); } } true diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 63df1179af2..f52f2ea0f9f 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -12,7 +12,6 @@ pub use self::AssociatedItemContainer::*; pub use self::BorrowKind::*; pub use self::IntVarValue::*; -pub use self::LvaluePreference::*; pub use self::fold::TypeFoldable; use hir::{map as hir_map, FreevarMap, TraitMap}; @@ -2099,21 +2098,6 @@ pub fn maybe_walk(&'tcx self, mut f: F) } } -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum LvaluePreference { - PreferMutLvalue, - NoPreference -} - -impl LvaluePreference { - pub fn from_mutbl(m: hir::Mutability) -> Self { - match m { - hir::MutMutable => PreferMutLvalue, - hir::MutImmutable => NoPreference, - } - } -} - impl BorrowKind { pub fn from_mutbl(m: hir::Mutability) -> BorrowKind { match m { @@ -2193,60 +2177,6 @@ pub fn expr_span(self, id: NodeId) -> Span { } } - pub fn expr_is_lval(self, expr: &hir::Expr) -> bool { - match expr.node { - hir::ExprPath(hir::QPath::Resolved(_, ref path)) => { - match path.def { - Def::Local(..) | Def::Upvar(..) | Def::Static(..) | Def::Err => true, - _ => false, - } - } - - hir::ExprType(ref e, _) => { - self.expr_is_lval(e) - } - - hir::ExprUnary(hir::UnDeref, _) | - hir::ExprField(..) | - hir::ExprTupField(..) | - hir::ExprIndex(..) => { - true - } - - // Partially qualified paths in expressions can only legally - // refer to associated items which are always rvalues. - hir::ExprPath(hir::QPath::TypeRelative(..)) | - - hir::ExprCall(..) | - hir::ExprMethodCall(..) | - hir::ExprStruct(..) | - hir::ExprTup(..) | - hir::ExprIf(..) | - hir::ExprMatch(..) | - hir::ExprClosure(..) | - hir::ExprBlock(..) | - hir::ExprRepeat(..) | - hir::ExprArray(..) | - hir::ExprBreak(..) | - hir::ExprAgain(..) | - hir::ExprRet(..) | - hir::ExprWhile(..) | - hir::ExprLoop(..) | - hir::ExprAssign(..) | - hir::ExprInlineAsm(..) | - hir::ExprAssignOp(..) | - hir::ExprLit(_) | - hir::ExprUnary(..) | - hir::ExprBox(..) | - hir::ExprAddrOf(..) | - hir::ExprBinary(..) | - hir::ExprYield(..) | - hir::ExprCast(..) => { - false - } - } - } - pub fn provided_trait_methods(self, id: DefId) -> Vec { self.associated_items(id) .filter(|item| item.kind == AssociatedKind::Method && item.defaultness.has_value()) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index db7e4fe45ef..1593b452cdf 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -390,14 +390,21 @@ impl Iterator> + 'a state.map(move |d| d.ty.subst(tcx, self.substs)) } + /// This is the types of the fields of a generate which + /// is available before the generator transformation. + /// It includes the upvars and the state discriminant which is u32. + pub fn pre_transforms_tys(self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> + impl Iterator> + 'a + { + self.upvar_tys(def_id, tcx).chain(iter::once(tcx.types.u32)) + } + /// This is the types of all the fields stored in a generator. /// It includes the upvars, state types and the state discriminant which is u32. pub fn field_tys(self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> impl Iterator> + 'a { - let upvars = self.upvar_tys(def_id, tcx); - let state = self.state_tys(def_id, tcx); - upvars.chain(iter::once(tcx.types.u32)).chain(state) + self.pre_transforms_tys(def_id, tcx).chain(self.state_tys(def_id, tcx)) } } @@ -1514,18 +1521,12 @@ pub fn has_concrete_skeleton(&self) -> bool { /// /// The parameter `explicit` indicates if this is an *explicit* dereference. /// Some types---notably unsafe ptrs---can only be dereferenced explicitly. - pub fn builtin_deref(&self, explicit: bool, pref: ty::LvaluePreference) - -> Option> - { + pub fn builtin_deref(&self, explicit: bool) -> Option> { match self.sty { TyAdt(def, _) if def.is_box() => { Some(TypeAndMut { ty: self.boxed_ty(), - mutbl: if pref == ty::PreferMutLvalue { - hir::MutMutable - } else { - hir::MutImmutable - }, + mutbl: hir::MutImmutable, }) }, TyRef(_, mt) => Some(mt), diff --git a/src/librustc/util/nodemap.rs b/src/librustc/util/nodemap.rs index 674f67d5cd2..f98a8f834df 100644 --- a/src/librustc/util/nodemap.rs +++ b/src/librustc/util/nodemap.rs @@ -13,7 +13,7 @@ #![allow(non_snake_case)] use hir::def_id::DefId; -use hir::ItemLocalId; +use hir::{HirId, ItemLocalId}; use syntax::ast; pub use rustc_data_structures::fx::FxHashMap; @@ -21,10 +21,12 @@ pub type NodeMap = FxHashMap; pub type DefIdMap = FxHashMap; +pub type HirIdMap = FxHashMap; pub type ItemLocalMap = FxHashMap; pub type NodeSet = FxHashSet; pub type DefIdSet = FxHashSet; +pub type HirIdSet = FxHashSet; pub type ItemLocalSet = FxHashSet; pub fn NodeMap() -> NodeMap { FxHashMap() } diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 3c8a676dcc2..2872c59157d 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -468,6 +468,10 @@ pub struct TargetOptions { /// The codegen backend to use for this target, typically "llvm" pub codegen_backend: String, + + /// The default visibility for symbols in this target should be "hidden" + /// rather than "default" + pub default_hidden_visibility: bool, } impl Default for TargetOptions { @@ -538,6 +542,7 @@ fn default() -> TargetOptions { no_builtins: false, i128_lowering: false, codegen_backend: "llvm".to_string(), + default_hidden_visibility: false, } } } @@ -785,6 +790,7 @@ macro_rules! key { key!(singlethread, bool); key!(no_builtins, bool); key!(codegen_backend); + key!(default_hidden_visibility, 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()) { @@ -982,6 +988,7 @@ macro_rules! target_option_val { target_option_val!(singlethread); target_option_val!(no_builtins); target_option_val!(codegen_backend); + target_option_val!(default_hidden_visibility); if default.abi_blacklist != self.options.abi_blacklist { d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter() diff --git a/src/librustc_back/target/msp430_none_elf.rs b/src/librustc_back/target/msp430_none_elf.rs index 509a7cf5e03..966df897f01 100644 --- a/src/librustc_back/target/msp430_none_elf.rs +++ b/src/librustc_back/target/msp430_none_elf.rs @@ -53,6 +53,12 @@ pub fn target() -> TargetResult { // don't want to invoke that many gcc instances. default_codegen_units: Some(1), + // Since MSP430 doesn't meaningfully support faulting on illegal + // instructions, LLVM generates a call to abort() function instead + // of a trap instruction. Such calls are 4 bytes long, and that is + // too much overhead for such small target. + trap_unreachable: false, + .. Default::default( ) } }) diff --git a/src/librustc_back/target/wasm32_unknown_unknown.rs b/src/librustc_back/target/wasm32_unknown_unknown.rs index 7e1011ab8af..242860e5c6e 100644 --- a/src/librustc_back/target/wasm32_unknown_unknown.rs +++ b/src/librustc_back/target/wasm32_unknown_unknown.rs @@ -83,6 +83,9 @@ pub fn target() -> Result { // performing LTO with compiler-builtins. no_builtins: true, + // no dynamic linking, no need for default visibility! + default_hidden_visibility: true, + .. Default::default() }; Ok(Target { diff --git a/src/librustc_binaryen/BinaryenWrapper.cpp b/src/librustc_binaryen/BinaryenWrapper.cpp index d1095a7819d..55f11665f6d 100644 --- a/src/librustc_binaryen/BinaryenWrapper.cpp +++ b/src/librustc_binaryen/BinaryenWrapper.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include "s2wasm.h" @@ -24,6 +25,7 @@ using namespace wasm; struct BinaryenRustModule { BufferWithRandomAccess buffer; + std::string sourceMapJSON; }; struct BinaryenRustModuleOptions { @@ -36,6 +38,7 @@ struct BinaryenRustModuleOptions { bool ignoreUnknownSymbols; bool debugInfo; std::string startFunction; + std::string sourceMapUrl; BinaryenRustModuleOptions() : globalBase(0), @@ -46,7 +49,8 @@ struct BinaryenRustModuleOptions { importMemory(false), ignoreUnknownSymbols(false), debugInfo(false), - startFunction("") + startFunction(""), + sourceMapUrl("") {} }; @@ -73,6 +77,12 @@ BinaryenRustModuleOptionsSetStart(BinaryenRustModuleOptions *options, options->startFunction = start; } +extern "C" void +BinaryenRustModuleOptionsSetSourceMapUrl(BinaryenRustModuleOptions *options, + char *sourceMapUrl) { + options->sourceMapUrl = sourceMapUrl; +} + extern "C" void BinaryenRustModuleOptionsSetStackAllocation(BinaryenRustModuleOptions *options, uint64_t stack) { @@ -106,12 +116,20 @@ BinaryenRustModuleCreate(const BinaryenRustModuleOptions *options, { WasmBinaryWriter writer(&linker.getOutput().wasm, ret->buffer, options->debug); writer.setNamesSection(options->debugInfo); - // FIXME: support source maps? - // writer.setSourceMap(sourceMapStream.get(), sourceMapUrl); + + std::unique_ptr sourceMapStream = nullptr; + { + sourceMapStream = make_unique(); + writer.setSourceMap(sourceMapStream.get(), options->sourceMapUrl); + } // FIXME: support symbol maps? // writer.setSymbolMap(symbolMap); writer.write(); + + if (sourceMapStream) { + ret->sourceMapJSON = sourceMapStream->str(); + } } return ret.release(); } @@ -126,6 +144,16 @@ BinaryenRustModuleLen(const BinaryenRustModule *M) { return M->buffer.size(); } +extern "C" const char* +BinaryenRustModuleSourceMapPtr(const BinaryenRustModule *M) { + return M->sourceMapJSON.data(); +} + +extern "C" size_t +BinaryenRustModuleSourceMapLen(const BinaryenRustModule *M) { + return M->sourceMapJSON.length(); +} + extern "C" void BinaryenRustModuleFree(BinaryenRustModule *M) { delete M; diff --git a/src/librustc_binaryen/lib.rs b/src/librustc_binaryen/lib.rs index 6c7feb6a7a9..36174e11ba0 100644 --- a/src/librustc_binaryen/lib.rs +++ b/src/librustc_binaryen/lib.rs @@ -51,6 +51,15 @@ pub fn data(&self) -> &[u8] { slice::from_raw_parts(ptr, len) } } + + /// Returns the data of the source map JSON. + pub fn source_map(&self) -> &[u8] { + unsafe { + let ptr = BinaryenRustModuleSourceMapPtr(self.ptr); + let len = BinaryenRustModuleSourceMapLen(self.ptr); + slice::from_raw_parts(ptr, len) + } + } } impl Drop for Module { @@ -94,6 +103,15 @@ pub fn start(&mut self, func: &str) -> &mut Self { self } + /// Configures a `sourceMappingURL` custom section value for the module. + pub fn source_map_url(&mut self, url: &str) -> &mut Self { + let url = CString::new(url).unwrap(); + unsafe { + BinaryenRustModuleOptionsSetSourceMapUrl(self.ptr, url.as_ptr()); + } + self + } + /// Configures how much stack is initially allocated for the module. 1MB is /// probably good enough for now. pub fn stack(&mut self, amt: u64) -> &mut Self { @@ -130,6 +148,8 @@ fn BinaryenRustModuleCreate(opts: *const BinaryenRustModuleOptions, -> *mut BinaryenRustModule; fn BinaryenRustModulePtr(module: *const BinaryenRustModule) -> *const u8; fn BinaryenRustModuleLen(module: *const BinaryenRustModule) -> usize; + fn BinaryenRustModuleSourceMapPtr(module: *const BinaryenRustModule) -> *const u8; + fn BinaryenRustModuleSourceMapLen(module: *const BinaryenRustModule) -> usize; fn BinaryenRustModuleFree(module: *mut BinaryenRustModule); fn BinaryenRustModuleOptionsCreate() @@ -138,6 +158,8 @@ fn BinaryenRustModuleOptionsSetDebugInfo(module: *mut BinaryenRustModuleOptions, debuginfo: bool); fn BinaryenRustModuleOptionsSetStart(module: *mut BinaryenRustModuleOptions, start: *const libc::c_char); + fn BinaryenRustModuleOptionsSetSourceMapUrl(module: *mut BinaryenRustModuleOptions, + sourceMapUrl: *const libc::c_char); fn BinaryenRustModuleOptionsSetStackAllocation( module: *mut BinaryenRustModuleOptions, stack: u64, diff --git a/src/librustc_borrowck/borrowck/README.md b/src/librustc_borrowck/borrowck/README.md index b877c5a9cbc..da2b1ef0b1c 100644 --- a/src/librustc_borrowck/borrowck/README.md +++ b/src/librustc_borrowck/borrowck/README.md @@ -43,14 +43,14 @@ it is safe with respect to the in-scope loans. # Formal model Throughout the docs we'll consider a simple subset of Rust in which -you can only borrow from lvalues, defined like so: +you can only borrow from places, defined like so: ```text -LV = x | LV.f | *LV +P = x | P.f | *P ``` -Here `x` represents some variable, `LV.f` is a field reference, -and `*LV` is a pointer dereference. There is no auto-deref or other +Here `x` represents some variable, `P.f` is a field reference, +and `*P` is a pointer dereference. There is no auto-deref or other niceties. This means that if you have a type like: ```rust @@ -58,7 +58,7 @@ struct S { f: i32 } ``` and a variable `a: Box`, then the rust expression `a.f` would correspond -to an `LV` of `(*a).f`. +to an `P` of `(*a).f`. Here is the formal grammar for the types we'll consider: @@ -99,7 +99,7 @@ this sort of thing. #### Loans and restrictions The way the borrow checker works is that it analyzes each borrow -expression (in our simple model, that's stuff like `&LV`, though in +expression (in our simple model, that's stuff like `&P`, though in real life there are a few other cases to consider). For each borrow expression, it computes a `Loan`, which is a data structure that records (1) the value being borrowed, (2) the mutability and scope of @@ -108,29 +108,29 @@ struct defined in `middle::borrowck`. Formally, we define `LOAN` as follows: ```text -LOAN = (LV, LT, MQ, RESTRICTION*) -RESTRICTION = (LV, ACTION*) +LOAN = (P, LT, MQ, RESTRICTION*) +RESTRICTION = (P, ACTION*) ACTION = MUTATE | CLAIM | FREEZE ``` -Here the `LOAN` tuple defines the lvalue `LV` being borrowed; the +Here the `LOAN` tuple defines the place `P` being borrowed; the lifetime `LT` of that borrow; the mutability `MQ` of the borrow; and a list of restrictions. The restrictions indicate actions which, if taken, could invalidate the loan and lead to type safety violations. -Each `RESTRICTION` is a pair of a restrictive lvalue `LV` (which will +Each `RESTRICTION` is a pair of a restrictive place `P` (which will either be the path that was borrowed or some prefix of the path that was borrowed) and a set of restricted actions. There are three kinds -of actions that may be restricted for the path `LV`: +of actions that may be restricted for the path `P`: -- `MUTATE` means that `LV` cannot be assigned to; -- `CLAIM` means that the `LV` cannot be borrowed mutably; -- `FREEZE` means that the `LV` cannot be borrowed immutably; +- `MUTATE` means that `P` cannot be assigned to; +- `CLAIM` means that the `P` cannot be borrowed mutably; +- `FREEZE` means that the `P` cannot be borrowed immutably; -Finally, it is never possible to move from an lvalue that appears in a -restriction. This implies that the "empty restriction" `(LV, [])`, +Finally, it is never possible to move from a place that appears in a +restriction. This implies that the "empty restriction" `(P, [])`, which contains an empty set of actions, still has a purpose---it -prevents moves from `LV`. I chose not to make `MOVE` a fourth kind of +prevents moves from `P`. I chose not to make `MOVE` a fourth kind of action because that would imply that sometimes moves are permitted from restricted values, which is not the case. @@ -239,22 +239,22 @@ live. (This is done via restrictions, read on.) We start with the `gather_loans` pass, which walks the AST looking for borrows. For each borrow, there are three bits of information: the -lvalue `LV` being borrowed and the mutability `MQ` and lifetime `LT` +place `P` being borrowed and the mutability `MQ` and lifetime `LT` of the resulting pointer. Given those, `gather_loans` applies four validity tests: -1. `MUTABILITY(LV, MQ)`: The mutability of the reference is -compatible with the mutability of `LV` (i.e., not borrowing immutable +1. `MUTABILITY(P, MQ)`: The mutability of the reference is +compatible with the mutability of `P` (i.e., not borrowing immutable data as mutable). -2. `ALIASABLE(LV, MQ)`: The aliasability of the reference is -compatible with the aliasability of `LV`. The goal is to prevent +2. `ALIASABLE(P, MQ)`: The aliasability of the reference is +compatible with the aliasability of `P`. The goal is to prevent `&mut` borrows of aliasability data. -3. `LIFETIME(LV, LT, MQ)`: The lifetime of the borrow does not exceed +3. `LIFETIME(P, LT, MQ)`: The lifetime of the borrow does not exceed the lifetime of the value being borrowed. -4. `RESTRICTIONS(LV, LT, ACTIONS) = RS`: This pass checks and computes the +4. `RESTRICTIONS(P, LT, ACTIONS) = RS`: This pass checks and computes the restrictions to maintain memory safety. These are the restrictions that will go into the final loan. We'll discuss in more detail below. @@ -263,7 +263,7 @@ that will go into the final loan. We'll discuss in more detail below. Checking mutability is fairly straightforward. We just want to prevent immutable data from being borrowed as mutable. Note that it is ok to borrow mutable data as immutable, since that is simply a freeze. The judgement -`MUTABILITY(LV, MQ)` means the mutability of `LV` is compatible with a borrow +`MUTABILITY(P, MQ)` means the mutability of `P` is compatible with a borrow of mutability `MQ`. The Rust code corresponding to this predicate is the function `check_mutability` in `middle::borrowck::gather_loans`. @@ -288,15 +288,15 @@ MUTABILITY(X, imm) // M-Var-Imm Fields and boxes inherit their mutability from their base expressions, so both of their rules basically -delegate the check to the base expression `LV`: +delegate the check to the base expression `P`: ```text -MUTABILITY(LV.f, MQ) // M-Field - MUTABILITY(LV, MQ) +MUTABILITY(P.f, MQ) // M-Field + MUTABILITY(P, MQ) -MUTABILITY(*LV, MQ) // M-Deref-Unique - TYPE(LV) = Box - MUTABILITY(LV, MQ) +MUTABILITY(*P, MQ) // M-Deref-Unique + TYPE(P) = Box + MUTABILITY(P, MQ) ``` ### Checking mutability of immutable pointer types @@ -305,8 +305,8 @@ Immutable pointer types like `&T` can only be borrowed if MQ is immutable: ```text -MUTABILITY(*LV, imm) // M-Deref-Borrowed-Imm - TYPE(LV) = &Ty +MUTABILITY(*P, imm) // M-Deref-Borrowed-Imm + TYPE(P) = &Ty ``` ### Checking mutability of mutable pointer types @@ -314,15 +314,15 @@ MUTABILITY(*LV, imm) // M-Deref-Borrowed-Imm `&mut T` can be frozen, so it is acceptable to borrow it as either imm or mut: ```text -MUTABILITY(*LV, MQ) // M-Deref-Borrowed-Mut - TYPE(LV) = &mut Ty +MUTABILITY(*P, MQ) // M-Deref-Borrowed-Mut + TYPE(P) = &mut Ty ``` ## Checking aliasability The goal of the aliasability check is to ensure that we never permit `&mut` -borrows of aliasable data. The judgement `ALIASABLE(LV, MQ)` means the -aliasability of `LV` is compatible with a borrow of mutability `MQ`. The Rust +borrows of aliasable data. The judgement `ALIASABLE(P, MQ)` means the +aliasability of `P` is compatible with a borrow of mutability `MQ`. The Rust code corresponding to this predicate is the function `check_aliasability()` in `middle::borrowck::gather_loans`. @@ -340,11 +340,11 @@ the stack frame. Owned content is aliasable if it is found in an aliasable location: ```text -ALIASABLE(LV.f, MQ) // M-Field - ALIASABLE(LV, MQ) +ALIASABLE(P.f, MQ) // M-Field + ALIASABLE(P, MQ) -ALIASABLE(*LV, MQ) // M-Deref-Unique - ALIASABLE(LV, MQ) +ALIASABLE(*P, MQ) // M-Deref-Unique + ALIASABLE(P, MQ) ``` ### Checking aliasability of immutable pointer types @@ -353,8 +353,8 @@ Immutable pointer types like `&T` are aliasable, and hence can only be borrowed immutably: ```text -ALIASABLE(*LV, imm) // M-Deref-Borrowed-Imm - TYPE(LV) = &Ty +ALIASABLE(*P, imm) // M-Deref-Borrowed-Imm + TYPE(P) = &Ty ``` ### Checking aliasability of mutable pointer types @@ -362,16 +362,16 @@ ALIASABLE(*LV, imm) // M-Deref-Borrowed-Imm `&mut T` can be frozen, so it is acceptable to borrow it as either imm or mut: ```text -ALIASABLE(*LV, MQ) // M-Deref-Borrowed-Mut - TYPE(LV) = &mut Ty +ALIASABLE(*P, MQ) // M-Deref-Borrowed-Mut + TYPE(P) = &mut Ty ``` ## Checking lifetime These rules aim to ensure that no data is borrowed for a scope that exceeds its lifetime. These two computations wind up being intimately related. -Formally, we define a predicate `LIFETIME(LV, LT, MQ)`, which states that -"the lvalue `LV` can be safely borrowed for the lifetime `LT` with mutability +Formally, we define a predicate `LIFETIME(P, LT, MQ)`, which states that +"the place `P` can be safely borrowed for the lifetime `LT` with mutability `MQ`". The Rust code corresponding to this predicate is the module `middle::borrowck::gather_loans::lifetime`. @@ -391,12 +391,12 @@ The lifetime of a field or box is the same as the lifetime of its owner: ```text -LIFETIME(LV.f, LT, MQ) // L-Field - LIFETIME(LV, LT, MQ) +LIFETIME(P.f, LT, MQ) // L-Field + LIFETIME(P, LT, MQ) -LIFETIME(*LV, LT, MQ) // L-Deref-Send - TYPE(LV) = Box - LIFETIME(LV, LT, MQ) +LIFETIME(*P, LT, MQ) // L-Deref-Send + TYPE(P) = Box + LIFETIME(P, LT, MQ) ``` ### Checking lifetime for derefs of references @@ -408,8 +408,8 @@ of the borrow is shorter than the lifetime `LT'` of the pointer itself: ```text -LIFETIME(*LV, LT, MQ) // L-Deref-Borrowed - TYPE(LV) = <' Ty OR <' mut Ty +LIFETIME(*P, LT, MQ) // L-Deref-Borrowed + TYPE(P) = <' Ty OR <' mut Ty LT <= LT' ``` @@ -417,17 +417,17 @@ LIFETIME(*LV, LT, MQ) // L-Deref-Borrowed The final rules govern the computation of *restrictions*, meaning that we compute the set of actions that will be illegal for the life of the -loan. The predicate is written `RESTRICTIONS(LV, LT, ACTIONS) = +loan. The predicate is written `RESTRICTIONS(P, LT, ACTIONS) = RESTRICTION*`, which can be read "in order to prevent `ACTIONS` from -occurring on `LV`, the restrictions `RESTRICTION*` must be respected +occurring on `P`, the restrictions `RESTRICTION*` must be respected for the lifetime of the loan". Note that there is an initial set of restrictions: these restrictions are computed based on the kind of borrow: ```text -&mut LV => RESTRICTIONS(LV, LT, MUTATE|CLAIM|FREEZE) -&LV => RESTRICTIONS(LV, LT, MUTATE|CLAIM) +&mut P => RESTRICTIONS(P, LT, MUTATE|CLAIM|FREEZE) +&P => RESTRICTIONS(P, LT, MUTATE|CLAIM) ``` The reasoning here is that a mutable borrow must be the only writer, @@ -451,8 +451,8 @@ Restricting a field is the same as restricting the owner of that field: ```text -RESTRICTIONS(LV.f, LT, ACTIONS) = RS, (LV.f, ACTIONS) // R-Field - RESTRICTIONS(LV, LT, ACTIONS) = RS +RESTRICTIONS(P.f, LT, ACTIONS) = RS, (P.f, ACTIONS) // R-Field + RESTRICTIONS(P, LT, ACTIONS) = RS ``` The reasoning here is as follows. If the field must not be mutated, @@ -467,16 +467,16 @@ origin of inherited mutability. Because the mutability of owned referents is inherited, restricting an owned referent is similar to restricting a field, in that it implies restrictions on the pointer. However, boxes have an important -twist: if the owner `LV` is mutated, that causes the owned referent -`*LV` to be freed! So whenever an owned referent `*LV` is borrowed, we -must prevent the box `LV` from being mutated, which means +twist: if the owner `P` is mutated, that causes the owned referent +`*P` to be freed! So whenever an owned referent `*P` is borrowed, we +must prevent the box `P` from being mutated, which means that we always add `MUTATE` and `CLAIM` to the restriction set imposed -on `LV`: +on `P`: ```text -RESTRICTIONS(*LV, LT, ACTIONS) = RS, (*LV, ACTIONS) // R-Deref-Send-Pointer - TYPE(LV) = Box - RESTRICTIONS(LV, LT, ACTIONS|MUTATE|CLAIM) = RS +RESTRICTIONS(*P, LT, ACTIONS) = RS, (*P, ACTIONS) // R-Deref-Send-Pointer + TYPE(P) = Box + RESTRICTIONS(P, LT, ACTIONS|MUTATE|CLAIM) = RS ``` ### Restrictions for loans of immutable borrowed referents @@ -484,15 +484,15 @@ RESTRICTIONS(*LV, LT, ACTIONS) = RS, (*LV, ACTIONS) // R-Deref-Send-Pointer Immutable borrowed referents are freely aliasable, meaning that the compiler does not prevent you from copying the pointer. This implies that issuing restrictions is useless. We might prevent the -user from acting on `*LV` itself, but there could be another path -`*LV1` that refers to the exact same memory, and we would not be +user from acting on `*P` itself, but there could be another path +`*P1` that refers to the exact same memory, and we would not be restricting that path. Therefore, the rule for `&Ty` pointers always returns an empty set of restrictions, and it only permits restricting `MUTATE` and `CLAIM` actions: ```text -RESTRICTIONS(*LV, LT, ACTIONS) = [] // R-Deref-Imm-Borrowed - TYPE(LV) = <' Ty +RESTRICTIONS(*P, LT, ACTIONS) = [] // R-Deref-Imm-Borrowed + TYPE(P) = <' Ty LT <= LT' // (1) ACTIONS subset of [MUTATE, CLAIM] ``` @@ -546,7 +546,7 @@ This function is legal. The reason for this is that the inner pointer (`*point : &'b Point`) is enough to guarantee the memory is immutable and valid for the lifetime `'b`. This is reflected in `RESTRICTIONS()` by the fact that we do not recurse (i.e., we impose -no restrictions on `LV`, which in this particular case is the pointer +no restrictions on `P`, which in this particular case is the pointer `point : &'a &'b Point`). #### Why both `LIFETIME()` and `RESTRICTIONS()`? @@ -612,10 +612,10 @@ while the new claimant is live. The rule for mutable borrowed pointers is as follows: ```text -RESTRICTIONS(*LV, LT, ACTIONS) = RS, (*LV, ACTIONS) // R-Deref-Mut-Borrowed - TYPE(LV) = <' mut Ty +RESTRICTIONS(*P, LT, ACTIONS) = RS, (*P, ACTIONS) // R-Deref-Mut-Borrowed + TYPE(P) = <' mut Ty LT <= LT' // (1) - RESTRICTIONS(LV, LT, ACTIONS) = RS // (2) + RESTRICTIONS(P, LT, ACTIONS) = RS // (2) ``` Let's examine the two numbered clauses: @@ -670,7 +670,7 @@ fn foo(t0: &mut i32) { Remember that `&mut` pointers are linear, and hence `let t1 = t0` is a move of `t0` -- or would be, if it were legal. Instead, we get an -error, because clause (2) imposes restrictions on `LV` (`t0`, here), +error, because clause (2) imposes restrictions on `P` (`t0`, here), and any restrictions on a path make it impossible to move from that path. @@ -906,7 +906,7 @@ results of a dataflow computation. The `MovePath` tree tracks every path that is moved or assigned to. These paths have the same form as the `LoanPath` data structure, which -in turn is the "real world version of the lvalues `LV` that we +in turn is the "real world version of the places `P` that we introduced earlier. The difference between a `MovePath` and a `LoanPath` is that move paths are: @@ -1132,7 +1132,7 @@ is implied by the relevant moves. While writing up these docs, I encountered some rules I believe to be stricter than necessary: -- I think restricting the `&mut` LV against moves and `ALIAS` is sufficient, +- I think restricting the `&mut` P against moves and `ALIAS` is sufficient, `MUTATE` and `CLAIM` are overkill. `MUTATE` was necessary when swap was a built-in operator, but as it is not, it is implied by `CLAIM`, and `CLAIM` is implied by `ALIAS`. The only net effect of this is an diff --git a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs index 66aaafb77f7..97fa94b5e5c 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs @@ -104,7 +104,7 @@ fn check_scope(&self, max_scope: ty::Region<'tcx>) -> R { fn scope(&self, cmt: &mc::cmt<'tcx>) -> ty::Region<'tcx> { //! Returns the maximal region scope for the which the - //! lvalue `cmt` is guaranteed to be valid without any + //! place `cmt` is guaranteed to be valid without any //! rooting etc, and presuming `cmt` is not mutated. match cmt.cat { diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index b35e8c6b419..738c0d82ee1 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -170,7 +170,7 @@ fn build_borrowck_dataflow_data<'a, 'c, 'tcx, F>(this: &mut BorrowckCtxt<'a, 'tc if !force_analysis && move_data.is_empty() && all_loans.is_empty() { // large arrays of data inserted as constants can take a lot of // time and memory to borrow-check - see issue #36799. However, - // they don't have lvalues, so no borrow-check is actually needed. + // they don't have places, so no borrow-check is actually needed. // Recognize that case and skip borrow-checking. debug!("skipping loan propagation for {:?} because of no loans", body_id); return None; @@ -384,9 +384,9 @@ fn cleaned(self) -> InteriorKind { } // This can be: -// - a pointer dereference (`*LV` in README.md) +// - a pointer dereference (`*P` in README.md) // - a field reference, with an optional definition of the containing -// enum variant (`LV.f` in README.md) +// enum variant (`P.f` in README.md) // `DefId` is present when the field is part of struct that is in // a variant of an enum. For instance in: // `enum E { X { foo: u32 }, Y { foo: u32 }}` @@ -1068,22 +1068,12 @@ pub fn report_aliasability_violation(&self, }; match cause { - mc::AliasableStatic => { - // This happens when we have an `&mut` or assignment to a - // static. We should have already reported a mutability - // violation first, but may have continued compiling. - self.tcx.sess.delay_span_bug( - span, - &format!("aliasability violation for static `{}`", prefix) - ); - return; - } mc::AliasableStaticMut => { // This path cannot occur. `static mut X` is not checked // for aliasability violations. span_bug!(span, "aliasability violation for static mut `{}`", prefix) } - mc::AliasableBorrowed => {} + mc::AliasableStatic | mc::AliasableBorrowed => {} }; let blame = cmt.immutability_blame(); let mut err = match blame { diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs index 98de394ae39..a90dcd1072f 100644 --- a/src/librustc_borrowck/borrowck/move_data.rs +++ b/src/librustc_borrowck/borrowck/move_data.rs @@ -153,7 +153,7 @@ pub struct Assignment { /// span of node where assignment occurs pub span: Span, - /// id for l-value expression on lhs of assignment + /// id for place expression on lhs of assignment pub assignee_id: hir::ItemLocalId, } diff --git a/src/librustc_borrowck/borrowck/unused.rs b/src/librustc_borrowck/borrowck/unused.rs index ddee122d0a6..7bcd8a18545 100644 --- a/src/librustc_borrowck/borrowck/unused.rs +++ b/src/librustc_borrowck/borrowck/unused.rs @@ -77,7 +77,7 @@ fn check_unused_mut_pat(&self, pats: &[P]) { continue } - let mut_span = tcx.sess.codemap().span_until_char(ids[0].2, ' '); + let mut_span = tcx.sess.codemap().span_until_non_whitespace(ids[0].2); // Ok, every name wasn't used mutably, so issue a warning that this // didn't need to be mutable. diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index fd171b89924..ae53ed0e114 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -127,13 +127,16 @@ fn visit_body(&mut self, body: &'tcx hir::Body) { } } + impl<'a, 'tcx> PatternContext<'a, 'tcx> { fn report_inlining_errors(&self, pat_span: Span) { for error in &self.errors { match *error { PatternError::StaticInPattern(span) => { - span_err!(self.tcx.sess, span, E0158, - "statics cannot be referenced in patterns"); + self.span_e0158(span, "statics cannot be referenced in patterns") + } + PatternError::AssociatedConstInPattern(span) => { + self.span_e0158(span, "associated consts cannot be referenced in patterns") } PatternError::ConstEval(ref err) => { err.report(self.tcx, pat_span, "pattern"); @@ -141,6 +144,10 @@ fn report_inlining_errors(&self, pat_span: Span) { } } } + + fn span_e0158(&self, span: Span, text: &str) { + span_err!(self.tcx.sess, span, E0158, "{}", text) + } } impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 418bd4b5eff..8e4ec93c14b 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -17,7 +17,6 @@ use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def_id::DefId; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::layout::LayoutOf; use rustc::ty::util::IntTypeExt; use rustc::ty::subst::{Substs, Subst}; use rustc::util::common::ErrorReported; @@ -313,7 +312,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, if tcx.fn_sig(def_id).abi() == Abi::RustIntrinsic { let layout_of = |ty: Ty<'tcx>| { let ty = tcx.erase_regions(&ty); - (tcx.at(e.span), cx.param_env).layout_of(ty).map_err(|err| { + tcx.at(e.span).layout_of(cx.param_env.and(ty)).map_err(|err| { ConstEvalErr { span: e.span, kind: LayoutError(err) } }) }; @@ -328,6 +327,10 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, return Ok(mk_const(Integral(Usize(ConstUsize::new(align, tcx.sess.target.usize_ty).unwrap())))); } + "type_id" => { + let type_id = tcx.type_id_hash(substs.type_at(0)); + return Ok(mk_const(Integral(U64(type_id)))); + } _ => signal!(e, TypeckError) } } diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index 3577feaf90c..bdb1001124d 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -27,6 +27,7 @@ #[derive(Clone, Debug)] pub enum PatternError<'tcx> { + AssociatedConstInPattern(Span), StaticInPattern(Span), ConstEval(ConstEvalErr<'tcx>), } @@ -133,7 +134,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { BindingMode::ByValue => mutability == Mutability::Mut, BindingMode::ByRef(_, bk) => { write!(f, "ref ")?; - bk == BorrowKind::Mut + match bk { BorrowKind::Mut { .. } => true, _ => false } } }; if is_mut { @@ -428,7 +429,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> { (Mutability::Not, BindingMode::ByValue), ty::BindByReference(hir::MutMutable) => (Mutability::Not, BindingMode::ByRef( - region.unwrap(), BorrowKind::Mut)), + region.unwrap(), BorrowKind::Mut { allow_two_phase_borrow: false })), ty::BindByReference(hir::MutImmutable) => (Mutability::Not, BindingMode::ByRef( region.unwrap(), BorrowKind::Shared)), @@ -635,6 +636,10 @@ fn lower_path(&mut self, -> Pattern<'tcx> { let ty = self.tables.node_id_to_type(id); let def = self.tables.qpath_def(qpath, id); + let is_associated_const = match def { + Def::AssociatedConst(_) => true, + _ => false, + }; let kind = match def { Def::Const(def_id) | Def::AssociatedConst(def_id) => { let substs = self.tables.node_substs(id); @@ -656,7 +661,11 @@ fn lower_path(&mut self, return pat; } None => { - self.errors.push(PatternError::StaticInPattern(span)); + self.errors.push(if is_associated_const { + PatternError::AssociatedConstInPattern(span) + } else { + PatternError::StaticInPattern(span) + }); PatternKind::Wild } } diff --git a/src/librustc_data_structures/bitvec.rs b/src/librustc_data_structures/bitvec.rs index 94edaa746f9..80cdb0e4417 100644 --- a/src/librustc_data_structures/bitvec.rs +++ b/src/librustc_data_structures/bitvec.rs @@ -51,6 +51,17 @@ pub fn insert(&mut self, bit: usize) -> bool { new_value != value } + /// Returns true if the bit has changed. + #[inline] + pub fn remove(&mut self, bit: usize) -> bool { + let (word, mask) = word_mask(bit); + let data = &mut self.data[word]; + let value = *data; + let new_value = value & !mask; + *data = new_value; + new_value != value + } + #[inline] pub fn insert_all(&mut self, all: &BitVector) -> bool { assert!(self.data.len() == all.data.len()); diff --git a/src/librustc_data_structures/blake2b.rs b/src/librustc_data_structures/blake2b.rs deleted file mode 100644 index 6b8bf8df0d3..00000000000 --- a/src/librustc_data_structures/blake2b.rs +++ /dev/null @@ -1,363 +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. - - -// An implementation of the Blake2b cryptographic hash function. -// The implementation closely follows: https://tools.ietf.org/html/rfc7693 -// -// "BLAKE2 is a cryptographic hash function faster than MD5, SHA-1, SHA-2, and -// SHA-3, yet is at least as secure as the latest standard SHA-3." -// according to their own website :) -// -// Indeed this implementation is two to three times as fast as our SHA-256 -// implementation. If you have the luxury of being able to use crates from -// crates.io, you can go there and find still faster implementations. - -use std::mem; -use std::slice; - -#[repr(C)] -struct Blake2bCtx { - b: [u8; 128], - h: [u64; 8], - t: [u64; 2], - c: usize, - outlen: u16, - finalized: bool, - - #[cfg(debug_assertions)] - fnv_hash: u64, -} - -#[cfg(debug_assertions)] -impl ::std::fmt::Debug for Blake2bCtx { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(fmt, "{:x}", self.fnv_hash) - } -} - -#[cfg(not(debug_assertions))] -impl ::std::fmt::Debug for Blake2bCtx { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(fmt, "Enable debug_assertions() for more info.") - } -} - -#[inline(always)] -fn b2b_g(v: &mut [u64; 16], - a: usize, - b: usize, - c: usize, - d: usize, - x: u64, - y: u64) -{ - v[a] = v[a].wrapping_add(v[b]).wrapping_add(x); - v[d] = (v[d] ^ v[a]).rotate_right(32); - v[c] = v[c].wrapping_add(v[d]); - v[b] = (v[b] ^ v[c]).rotate_right(24); - v[a] = v[a].wrapping_add(v[b]).wrapping_add(y); - v[d] = (v[d] ^ v[a]).rotate_right(16); - v[c] = v[c].wrapping_add(v[d]); - v[b] = (v[b] ^ v[c]).rotate_right(63); -} - -// Initialization vector -const BLAKE2B_IV: [u64; 8] = [ - 0x6A09E667F3BCC908, 0xBB67AE8584CAA73B, - 0x3C6EF372FE94F82B, 0xA54FF53A5F1D36F1, - 0x510E527FADE682D1, 0x9B05688C2B3E6C1F, - 0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179 -]; - -fn blake2b_compress(ctx: &mut Blake2bCtx, last: bool) { - - const SIGMA: [[usize; 16]; 12] = [ - [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], - [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 ], - [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 ], - [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 ], - [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 ], - [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 ], - [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 ], - [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 ], - [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 ], - [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 ], - [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], - [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 ] - ]; - - let mut v: [u64; 16] = [ - ctx.h[0], - ctx.h[1], - ctx.h[2], - ctx.h[3], - ctx.h[4], - ctx.h[5], - ctx.h[6], - ctx.h[7], - - BLAKE2B_IV[0], - BLAKE2B_IV[1], - BLAKE2B_IV[2], - BLAKE2B_IV[3], - BLAKE2B_IV[4], - BLAKE2B_IV[5], - BLAKE2B_IV[6], - BLAKE2B_IV[7], - ]; - - v[12] ^= ctx.t[0]; // low 64 bits of offset - v[13] ^= ctx.t[1]; // high 64 bits - if last { - v[14] = !v[14]; - } - - { - // Re-interpret the input buffer in the state as an array - // of little-endian u64s, converting them to machine - // endianness. It's OK to modify the buffer in place - // since this is the last time this data will be accessed - // before it's overwritten. - - let m: &mut [u64; 16] = unsafe { - let b: &mut [u8; 128] = &mut ctx.b; - ::std::mem::transmute(b) - }; - - if cfg!(target_endian = "big") { - for word in &mut m[..] { - *word = u64::from_le(*word); - } - } - - for i in 0 .. 12 { - b2b_g(&mut v, 0, 4, 8, 12, m[SIGMA[i][ 0]], m[SIGMA[i][ 1]]); - b2b_g(&mut v, 1, 5, 9, 13, m[SIGMA[i][ 2]], m[SIGMA[i][ 3]]); - b2b_g(&mut v, 2, 6, 10, 14, m[SIGMA[i][ 4]], m[SIGMA[i][ 5]]); - b2b_g(&mut v, 3, 7, 11, 15, m[SIGMA[i][ 6]], m[SIGMA[i][ 7]]); - b2b_g(&mut v, 0, 5, 10, 15, m[SIGMA[i][ 8]], m[SIGMA[i][ 9]]); - b2b_g(&mut v, 1, 6, 11, 12, m[SIGMA[i][10]], m[SIGMA[i][11]]); - b2b_g(&mut v, 2, 7, 8, 13, m[SIGMA[i][12]], m[SIGMA[i][13]]); - b2b_g(&mut v, 3, 4, 9, 14, m[SIGMA[i][14]], m[SIGMA[i][15]]); - } - } - - for i in 0 .. 8 { - ctx.h[i] ^= v[i] ^ v[i + 8]; - } -} - -fn blake2b_new(outlen: usize, key: &[u8]) -> Blake2bCtx { - assert!(outlen > 0 && outlen <= 64 && key.len() <= 64); - - let mut ctx = Blake2bCtx { - b: [0; 128], - h: BLAKE2B_IV, - t: [0; 2], - c: 0, - outlen: outlen as u16, - finalized: false, - - #[cfg(debug_assertions)] - fnv_hash: 0xcbf29ce484222325, - }; - - ctx.h[0] ^= 0x01010000 ^ ((key.len() << 8) as u64) ^ (outlen as u64); - - if key.len() > 0 { - blake2b_update(&mut ctx, key); - ctx.c = ctx.b.len(); - } - - ctx -} - -fn blake2b_update(ctx: &mut Blake2bCtx, mut data: &[u8]) { - assert!(!ctx.finalized, "Blake2bCtx already finalized"); - - let mut bytes_to_copy = data.len(); - let mut space_in_buffer = ctx.b.len() - ctx.c; - - while bytes_to_copy > space_in_buffer { - checked_mem_copy(data, &mut ctx.b[ctx.c .. ], space_in_buffer); - - ctx.t[0] = ctx.t[0].wrapping_add(ctx.b.len() as u64); - if ctx.t[0] < (ctx.b.len() as u64) { - ctx.t[1] += 1; - } - blake2b_compress(ctx, false); - ctx.c = 0; - - data = &data[space_in_buffer .. ]; - bytes_to_copy -= space_in_buffer; - space_in_buffer = ctx.b.len(); - } - - if bytes_to_copy > 0 { - checked_mem_copy(data, &mut ctx.b[ctx.c .. ], bytes_to_copy); - ctx.c += bytes_to_copy; - } - - #[cfg(debug_assertions)] - { - // compute additional FNV hash for simpler to read debug output - const MAGIC_PRIME: u64 = 0x00000100000001b3; - - for &byte in data { - ctx.fnv_hash = (ctx.fnv_hash ^ byte as u64).wrapping_mul(MAGIC_PRIME); - } - } -} - -fn blake2b_final(ctx: &mut Blake2bCtx) -{ - assert!(!ctx.finalized, "Blake2bCtx already finalized"); - - ctx.t[0] = ctx.t[0].wrapping_add(ctx.c as u64); - if ctx.t[0] < ctx.c as u64 { - ctx.t[1] += 1; - } - - while ctx.c < 128 { - ctx.b[ctx.c] = 0; - ctx.c += 1; - } - - blake2b_compress(ctx, true); - - // Modify our buffer to little-endian format as it will be read - // as a byte array. It's OK to modify the buffer in place since - // this is the last time this data will be accessed. - if cfg!(target_endian = "big") { - for word in &mut ctx.h { - *word = word.to_le(); - } - } - - ctx.finalized = true; -} - -#[inline(always)] -fn checked_mem_copy(from: &[T1], to: &mut [T2], byte_count: usize) { - let from_size = from.len() * mem::size_of::(); - let to_size = to.len() * mem::size_of::(); - assert!(from_size >= byte_count); - assert!(to_size >= byte_count); - let from_byte_ptr = from.as_ptr() as * const u8; - let to_byte_ptr = to.as_mut_ptr() as * mut u8; - unsafe { - ::std::ptr::copy_nonoverlapping(from_byte_ptr, to_byte_ptr, byte_count); - } -} - -pub fn blake2b(out: &mut [u8], key: &[u8], data: &[u8]) -{ - let mut ctx = blake2b_new(out.len(), key); - blake2b_update(&mut ctx, data); - blake2b_final(&mut ctx); - checked_mem_copy(&ctx.h, out, ctx.outlen as usize); -} - -pub struct Blake2bHasher(Blake2bCtx); - -impl ::std::hash::Hasher for Blake2bHasher { - fn write(&mut self, bytes: &[u8]) { - blake2b_update(&mut self.0, bytes); - } - - fn finish(&self) -> u64 { - assert!(self.0.outlen == 8, - "Hasher initialized with incompatible output length"); - u64::from_le(self.0.h[0]) - } -} - -impl Blake2bHasher { - pub fn new(outlen: usize, key: &[u8]) -> Blake2bHasher { - Blake2bHasher(blake2b_new(outlen, key)) - } - - pub fn finalize(&mut self) -> &[u8] { - if !self.0.finalized { - blake2b_final(&mut self.0); - } - debug_assert!(mem::size_of_val(&self.0.h) >= self.0.outlen as usize); - let raw_ptr = (&self.0.h[..]).as_ptr() as * const u8; - unsafe { - slice::from_raw_parts(raw_ptr, self.0.outlen as usize) - } - } -} - -impl ::std::fmt::Debug for Blake2bHasher { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { - write!(fmt, "{:?}", self.0) - } -} - -#[cfg(test)] -fn selftest_seq(out: &mut [u8], seed: u32) -{ - let mut a: u32 = 0xDEAD4BADu32.wrapping_mul(seed); - let mut b: u32 = 1; - - for i in 0 .. out.len() { - let t: u32 = a.wrapping_add(b); - a = b; - b = t; - out[i] = ((t >> 24) & 0xFF) as u8; - } -} - -#[test] -fn blake2b_selftest() -{ - use std::hash::Hasher; - - // grand hash of hash results - const BLAKE2B_RES: [u8; 32] = [ - 0xC2, 0x3A, 0x78, 0x00, 0xD9, 0x81, 0x23, 0xBD, - 0x10, 0xF5, 0x06, 0xC6, 0x1E, 0x29, 0xDA, 0x56, - 0x03, 0xD7, 0x63, 0xB8, 0xBB, 0xAD, 0x2E, 0x73, - 0x7F, 0x5E, 0x76, 0x5A, 0x7B, 0xCC, 0xD4, 0x75 - ]; - - // parameter sets - const B2B_MD_LEN: [usize; 4] = [20, 32, 48, 64]; - const B2B_IN_LEN: [usize; 6] = [0, 3, 128, 129, 255, 1024]; - - let mut data = [0u8; 1024]; - let mut md = [0u8; 64]; - let mut key = [0u8; 64]; - - let mut hasher = Blake2bHasher::new(32, &[]); - - for i in 0 .. 4 { - let outlen = B2B_MD_LEN[i]; - for j in 0 .. 6 { - let inlen = B2B_IN_LEN[j]; - - selftest_seq(&mut data[.. inlen], inlen as u32); // unkeyed hash - blake2b(&mut md[.. outlen], &[], &data[.. inlen]); - hasher.write(&md[.. outlen]); // hash the hash - - selftest_seq(&mut key[0 .. outlen], outlen as u32); // keyed hash - blake2b(&mut md[.. outlen], &key[.. outlen], &data[.. inlen]); - hasher.write(&md[.. outlen]); // hash the hash - } - } - - // compute and compare the hash of hashes - let md = hasher.finalize(); - for i in 0 .. 32 { - assert_eq!(md[i], BLAKE2B_RES[i]); - } -} diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index a35ef2f7ce7..33d760d0a14 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -57,7 +57,6 @@ pub mod base_n; pub mod bitslice; pub mod bitvec; -pub mod blake2b; pub mod graph; pub mod indexed_set; pub mod indexed_vec; @@ -70,7 +69,6 @@ pub mod unify; pub mod fx; pub mod tuple_slice; -pub mod veccell; pub mod control_flow_graph; pub mod flock; pub mod sync; diff --git a/src/librustc_data_structures/veccell/mod.rs b/src/librustc_data_structures/veccell/mod.rs deleted file mode 100644 index 054eee8829a..00000000000 --- a/src/librustc_data_structures/veccell/mod.rs +++ /dev/null @@ -1,47 +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::cell::UnsafeCell; -use std::mem; - -pub struct VecCell { - data: UnsafeCell>, -} - -impl VecCell { - pub fn with_capacity(capacity: usize) -> VecCell { - VecCell { data: UnsafeCell::new(Vec::with_capacity(capacity)) } - } - - #[inline] - pub fn push(&self, data: T) -> usize { - // The logic here, and in `swap` below, is that the `push` - // method on the vector will not recursively access this - // `VecCell`. Therefore, we can temporarily obtain mutable - // access, secure in the knowledge that even if aliases exist - // -- indeed, even if aliases are reachable from within the - // vector -- they will not be used for the duration of this - // particular fn call. (Note that we also are relying on the - // fact that `VecCell` is not `Sync`.) - unsafe { - let v = self.data.get(); - (*v).push(data); - (*v).len() - } - } - - pub fn swap(&self, mut data: Vec) -> Vec { - unsafe { - let v = self.data.get(); - mem::swap(&mut *v, &mut data); - } - data - } -} diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index e97d83ed1ee..f344624666a 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -121,23 +121,8 @@ macro_rules! controller_entry_point { }; let outputs = build_output_filenames(input, outdir, output, &krate.attrs, sess); - - // Ensure the source file isn't accidentally overwritten during compilation. - match *input_path { - Some(ref input_path) => { - if outputs.contains_path(input_path) && sess.opts.will_create_output_file() { - sess.err(&format!( - "the input file \"{}\" would be overwritten by the generated executable", - input_path.display())); - return Err(CompileIncomplete::Stopped); - } - }, - None => {} - } - let crate_name = ::rustc_trans_utils::link::find_crate_name(Some(sess), &krate.attrs, input); - let ExpansionResult { expanded_crate, defs, analysis, resolutions, mut hir_forest } = { phase_2_configure_and_expand( sess, @@ -157,12 +142,41 @@ macro_rules! controller_entry_point { )? }; - write_out_deps(sess, &outputs, &crate_name); + let output_paths = generated_output_paths(sess, &outputs, output.is_some(), &crate_name); + + // Ensure the source file isn't accidentally overwritten during compilation. + if let Some(ref input_path) = *input_path { + if sess.opts.will_create_output_file() { + if output_contains_path(&output_paths, input_path) { + sess.err(&format!( + "the input file \"{}\" would be overwritten by the generated \ + executable", + input_path.display())); + return Err(CompileIncomplete::Stopped); + } + if let Some(dir_path) = output_conflicts_with_dir(&output_paths) { + sess.err(&format!( + "the generated executable for the input file \"{}\" conflicts with the \ + existing directory \"{}\"", + input_path.display(), dir_path.display())); + return Err(CompileIncomplete::Stopped); + } + } + } + + write_out_deps(sess, &outputs, &output_paths); if sess.opts.output_types.contains_key(&OutputType::DepInfo) && sess.opts.output_types.keys().count() == 1 { return Ok(()) } + if let &Some(ref dir) = outdir { + if fs::create_dir_all(dir).is_err() { + sess.err("failed to find or create the directory specified by --out-dir"); + return Err(CompileIncomplete::Stopped); + } + } + let arenas = AllArenas::new(); // Construct the HIR map @@ -1101,16 +1115,22 @@ fn escape_dep_filename(filename: &FileName) -> String { filename.to_string().replace(" ", "\\ ") } -fn write_out_deps(sess: &Session, outputs: &OutputFilenames, crate_name: &str) { +// Returns all the paths that correspond to generated files. +fn generated_output_paths(sess: &Session, + outputs: &OutputFilenames, + exact_name: bool, + crate_name: &str) -> Vec { let mut out_filenames = Vec::new(); for output_type in sess.opts.output_types.keys() { let file = outputs.path(*output_type); match *output_type { - OutputType::Exe => { - for output in sess.crate_types.borrow().iter() { + // If the filename has been overridden using `-o`, it will not be modified + // by appending `.rlib`, `.exe`, etc., so we can skip this transformation. + OutputType::Exe if !exact_name => { + for crate_type in sess.crate_types.borrow().iter() { let p = ::rustc_trans_utils::link::filename_for_input( sess, - *output, + *crate_type, crate_name, outputs ); @@ -1125,7 +1145,46 @@ fn write_out_deps(sess: &Session, outputs: &OutputFilenames, crate_name: &str) { } } } + out_filenames +} +// Runs `f` on every output file path and returns the first non-None result, or None if `f` +// returns None for every file path. +fn check_output(output_paths: &Vec, f: F) -> Option + where F: Fn(&PathBuf) -> Option { + for output_path in output_paths { + if let Some(result) = f(output_path) { + return Some(result); + } + } + None +} + +pub fn output_contains_path(output_paths: &Vec, input_path: &PathBuf) -> bool { + let input_path = input_path.canonicalize().ok(); + if input_path.is_none() { + return false + } + let check = |output_path: &PathBuf| { + if output_path.canonicalize().ok() == input_path { + Some(()) + } else { None } + }; + check_output(output_paths, check).is_some() +} + +pub fn output_conflicts_with_dir(output_paths: &Vec) -> Option { + let check = |output_path: &PathBuf| { + if output_path.is_dir() { + Some(output_path.clone()) + } else { None } + }; + check_output(output_paths, check) +} + +fn write_out_deps(sess: &Session, + outputs: &OutputFilenames, + out_filenames: &Vec) { // Write out dependency rules to the dep-info file if requested if !sess.opts.output_types.contains_key(&OutputType::DepInfo) { return; @@ -1144,7 +1203,7 @@ fn write_out_deps(sess: &Session, outputs: &OutputFilenames, crate_name: &str) { .map(|fmap| escape_dep_filename(&fmap.name)) .collect(); let mut file = fs::File::create(&deps_filename)?; - for path in &out_filenames { + for path in out_filenames { write!(file, "{}: {}\n\n", path.display(), files.join(" "))?; } @@ -1327,7 +1386,10 @@ pub fn build_output_filenames(input: &Input, Some(out_file.clone()) }; if *odir != None { - sess.warn("ignoring --out-dir flag due to -o flag."); + sess.warn("ignoring --out-dir flag due to -o flag"); + } + if !sess.opts.cg.extra_filename.is_empty() { + sess.warn("ignoring -C extra-filename flag due to -o flag"); } let cur_dir = Path::new(""); diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 6118ee94c84..05dcaf73135 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -167,7 +167,8 @@ pub fn run(run_compiler: F) -> isize let emitter = errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, None, - true); + true, + false); let handler = errors::Handler::with_emitter(true, false, Box::new(emitter)); handler.emit(&MultiSpan::new(), "aborting due to previous error(s)", @@ -289,7 +290,7 @@ fn get_trans_sysroot(backend_name: &str) -> fn() -> Box { let sysroot = sysroot_candidates.iter() .map(|sysroot| { let libdir = filesearch::relative_target_lib_path(&sysroot, &target); - sysroot.join(&libdir).join("codegen-backends") + sysroot.join(libdir).with_file_name("codegen-backends") }) .filter(|f| { info!("codegen backend candidate: {}", f.display()); @@ -456,10 +457,13 @@ macro_rules! do_or_return {($expr: expr, $sess: expr) => { None); let (odir, ofile) = make_output(&matches); - let (input, input_file_path) = match make_input(&matches.free) { - Some((input, input_file_path)) => callbacks.some_input(input, input_file_path), + let (input, input_file_path, input_err) = match make_input(&matches.free) { + Some((input, input_file_path, input_err)) => { + let (input, input_file_path) = callbacks.some_input(input, input_file_path); + (input, input_file_path, input_err) + }, None => match callbacks.no_input(&matches, &sopts, &cfg, &odir, &ofile, &descriptions) { - Some((input, input_file_path)) => (input, input_file_path), + Some((input, input_file_path)) => (input, input_file_path, None), None => return (Ok(()), None), }, }; @@ -470,6 +474,13 @@ macro_rules! do_or_return {($expr: expr, $sess: expr) => { sopts, input_file_path.clone(), descriptions, codemap, emitter_dest, ); + if let Some(err) = input_err { + // Immediately stop compilation if there was an issue reading + // the input (for example if the input stream is not UTF-8). + sess.err(&format!("{}", err)); + return (Err(CompileIncomplete::Stopped), Some(sess)); + } + let trans = get_trans(&sess); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); @@ -512,17 +523,22 @@ fn make_output(matches: &getopts::Matches) -> (Option, Option) } // Extract input (string or file and optional path) from matches. -fn make_input(free_matches: &[String]) -> Option<(Input, Option)> { +fn make_input(free_matches: &[String]) -> Option<(Input, Option, Option)> { if free_matches.len() == 1 { let ifile = &free_matches[0]; if ifile == "-" { let mut src = String::new(); - io::stdin().read_to_string(&mut src).unwrap(); + let err = if io::stdin().read_to_string(&mut src).is_err() { + Some(io::Error::new(io::ErrorKind::InvalidData, + "couldn't read from stdin, as it did not contain valid UTF-8")) + } else { + None + }; Some((Input::Str { name: FileName::Anon, input: src }, - None)) + None, err)) } else { Some((Input::File(PathBuf::from(ifile)), - Some(PathBuf::from(ifile)))) + Some(PathBuf::from(ifile)), None)) } } else { None @@ -1434,6 +1450,7 @@ pub fn monitor(f: F) { let emitter = Box::new(errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, None, + false, false)); let handler = errors::Handler::with_emitter(true, false, emitter); diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 2e654fe9929..40e4efb397d 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -222,6 +222,7 @@ pub fn span_suggestion_short(&mut self, sp: Span, msg: &str, suggestion: String) }], msg: msg.to_owned(), show_code_when_inline: false, + approximate: false, }); self } @@ -252,6 +253,7 @@ pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &m }], msg: msg.to_owned(), show_code_when_inline: true, + approximate: false, }); self } @@ -267,6 +269,41 @@ pub fn span_suggestions(&mut self, sp: Span, msg: &str, suggestions: Vec }).collect(), msg: msg.to_owned(), show_code_when_inline: true, + approximate: false, + }); + self + } + + /// This is a suggestion that may contain mistakes or fillers and should + /// be read and understood by a human. + pub fn span_approximate_suggestion(&mut self, sp: Span, msg: &str, + suggestion: String) -> &mut Self { + self.suggestions.push(CodeSuggestion { + substitutions: vec![Substitution { + parts: vec![SubstitutionPart { + snippet: suggestion, + span: sp, + }], + }], + msg: msg.to_owned(), + show_code_when_inline: true, + approximate: true, + }); + self + } + + pub fn span_approximate_suggestions(&mut self, sp: Span, msg: &str, + suggestions: Vec) -> &mut Self { + self.suggestions.push(CodeSuggestion { + substitutions: suggestions.into_iter().map(|snippet| Substitution { + parts: vec![SubstitutionPart { + snippet, + span: sp, + }], + }).collect(), + msg: msg.to_owned(), + show_code_when_inline: true, + approximate: true, }); self } diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 61674ada6fa..2536fc648c7 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -186,6 +186,16 @@ pub fn span_label>(&mut self, span: Span, label: T) -> &mut Self msg: &str, suggestions: Vec) -> &mut Self); + forward!(pub fn span_approximate_suggestion(&mut self, + sp: Span, + msg: &str, + suggestion: String) + -> &mut Self); + forward!(pub fn span_approximate_suggestions(&mut self, + sp: Span, + msg: &str, + suggestions: Vec) + -> &mut Self); forward!(pub fn set_span>(&mut self, sp: S) -> &mut Self); forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self); diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 8a4fd24a29b..a49284eb55a 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -106,6 +106,7 @@ pub struct EmitterWriter { dst: Destination, cm: Option>, short_message: bool, + teach: bool, } struct FileWithAnnotatedLines { @@ -117,32 +118,37 @@ struct FileWithAnnotatedLines { impl EmitterWriter { pub fn stderr(color_config: ColorConfig, code_map: Option>, - short_message: bool) + short_message: bool, + teach: bool) -> EmitterWriter { if color_config.use_color() { let dst = Destination::from_stderr(); EmitterWriter { dst, cm: code_map, - short_message: short_message, + short_message, + teach, } } else { EmitterWriter { dst: Raw(Box::new(io::stderr())), cm: code_map, - short_message: short_message, + short_message, + teach, } } } pub fn new(dst: Box, code_map: Option>, - short_message: bool) + short_message: bool, + teach: bool) -> EmitterWriter { EmitterWriter { dst: Raw(dst), cm: code_map, - short_message: short_message, + short_message, + teach, } } @@ -284,6 +290,10 @@ fn render_source_line(&self, line: &Line, width_offset: usize, code_offset: usize) -> Vec<(usize, Style)> { + if line.line_index == 0 { + return Vec::new(); + } + let source_string = match file.get_line(line.line_index - 1) { Some(s) => s, None => return Vec::new(), @@ -551,7 +561,14 @@ fn render_source_line(&self, code_offset + annotation.start_col, style); } - _ => (), + _ if self.teach => { + buffer.set_style_range(line_offset, + code_offset + annotation.start_col, + code_offset + annotation.end_col, + style, + annotation.is_primary); + } + _ => {} } } @@ -1014,8 +1031,21 @@ fn emit_message_default(&mut self, // Then, the secondary file indicator buffer.prepend(buffer_msg_line_offset + 1, "::: ", Style::LineNumber); + let loc = if let Some(first_line) = annotated_file.lines.first() { + let col = if let Some(first_annotation) = first_line.annotations.first() { + format!(":{}", first_annotation.start_col + 1) + } else { + "".to_string() + }; + format!("{}:{}{}", + annotated_file.file.name, + cm.doctest_offset_line(first_line.line_index), + col) + } else { + annotated_file.file.name.to_string() + }; buffer.append(buffer_msg_line_offset + 1, - &annotated_file.file.name.to_string(), + &loc, Style::LineAndColumn); for _ in 0..max_line_num_len { buffer.prepend(buffer_msg_line_offset + 1, " ", Style::NoStyle); diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 3d50c95d3f4..236698ed2d4 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -83,6 +83,12 @@ pub struct CodeSuggestion { pub substitutions: Vec, pub msg: String, pub show_code_when_inline: bool, + /// Whether or not the suggestion is approximate + /// + /// Sometimes we may show suggestions with placeholders, + /// which are useful for users but not useful for + /// tools like rustfix + pub approximate: bool, } #[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)] @@ -297,7 +303,7 @@ pub fn with_tty_emitter_and_flags(color_config: ColorConfig, cm: Option>, flags: HandlerFlags) -> Handler { - let emitter = Box::new(EmitterWriter::stderr(color_config, cm, false)); + let emitter = Box::new(EmitterWriter::stderr(color_config, cm, false, false)); Handler::with_emitter_and_flags(emitter, flags) } diff --git a/src/librustc_errors/snippet.rs b/src/librustc_errors/snippet.rs index c2f4701999e..7d416f13ffc 100644 --- a/src/librustc_errors/snippet.rs +++ b/src/librustc_errors/snippet.rs @@ -10,31 +10,8 @@ // Code for annotating snippets. -use syntax_pos::{Span, FileMap}; -use CodeMapper; -use std::rc::Rc; use Level; -#[derive(Clone)] -pub struct SnippetData { - codemap: Rc, - files: Vec, -} - -#[derive(Clone)] -pub struct FileInfo { - file: Rc, - - /// The "primary file", if any, gets a `-->` marker instead of - /// `>>>`, and has a line-number/column printed and not just a - /// filename. It appears first in the listing. It is known to - /// contain at least one primary span, though primary spans (which - /// are designated with `^^^`) may also occur in other files. - primary_span: Option, - - lines: Vec, -} - #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)] pub struct Line { pub line_index: usize, diff --git a/src/librustc_errors/styled_buffer.rs b/src/librustc_errors/styled_buffer.rs index 2c33f805203..2c736ec22c3 100644 --- a/src/librustc_errors/styled_buffer.rs +++ b/src/librustc_errors/styled_buffer.rs @@ -144,4 +144,25 @@ pub fn append(&mut self, line: usize, string: &str, style: Style) { pub fn num_lines(&self) -> usize { self.text.len() } + + pub fn set_style_range(&mut self, + line: usize, + col_start: usize, + col_end: usize, + style: Style, + overwrite: bool) { + for col in col_start..col_end { + self.set_style(line, col, style, overwrite); + } + } + + pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) { + if let Some(ref mut line) = self.styles.get_mut(line) { + if let Some(s) = line.get_mut(col) { + if *s == Style::NoStyle || *s == Style::Quotation || overwrite { + *s = style; + } + } + } + } } diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index e0999db6e3e..e7e4119b999 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -437,8 +437,8 @@ fn check_type_for_ffi(&self, // repr(transparent) types are allowed to have arbitrary ZSTs, not just // PhantomData -- skip checking all ZST fields if def.repr.transparent() { - let is_zst = (cx, cx.param_env(field.did)) - .layout_of(field_ty) + let is_zst = cx + .layout_of(cx.param_env(field.did).and(field_ty)) .map(|layout| layout.is_zst()) .unwrap_or(false); if is_zst { diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index ef6475f9ee4..439533fae49 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -302,19 +302,38 @@ fn check_expr(&mut self, cx: &EarlyContext, e: &ast::Expr) { Assign(_, ref value) => (value, "assigned value", false), AssignOp(.., ref value) => (value, "assigned value", false), InPlace(_, ref value) => (value, "emplacement value", false), - Call(_, ref args) => { - for arg in args { - self.check_unused_parens_core(cx, arg, "function argument", false) + // either function/method call, or something this lint doesn't care about + ref call_or_other => { + let args_to_check; + let call_kind; + match *call_or_other { + Call(_, ref args) => { + call_kind = "function"; + args_to_check = &args[..]; + }, + MethodCall(_, ref args) => { + call_kind = "method"; + // first "argument" is self (which sometimes needs parens) + args_to_check = &args[1..]; + } + // actual catch-all arm + _ => { return; } } - return; - }, - MethodCall(_, ref args) => { - for arg in &args[1..] { // first "argument" is self (which sometimes needs parens) - self.check_unused_parens_core(cx, arg, "method argument", false) + // Don't lint if this is a nested macro expansion: otherwise, the lint could + // trigger in situations that macro authors shouldn't have to care about, e.g., + // when a parenthesized token tree matched in one macro expansion is matched as + // an expression in another and used as a fn/method argument (Issue #47775) + if e.span.ctxt().outer().expn_info() + .map_or(false, |info| info.call_site.ctxt().outer() + .expn_info().is_some()) { + return; + } + let msg = format!("{} argument", call_kind); + for arg in args_to_check { + self.check_unused_parens_core(cx, arg, &msg, false); } return; } - _ => return, }; self.check_unused_parens_core(cx, &value, msg, struct_lit_needs_parens); } @@ -418,8 +437,10 @@ fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { for adj in cx.tables.expr_adjustments(e) { if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(_, m)) = adj.kind { let msg = match m { - hir::MutImmutable => "unnecessary allocation, use & instead", - hir::MutMutable => "unnecessary allocation, use &mut instead" + adjustment::AutoBorrowMutability::Immutable => + "unnecessary allocation, use & instead", + adjustment::AutoBorrowMutability::Mutable { .. }=> + "unnecessary allocation, use &mut instead" }; cx.span_lint(UNUSED_ALLOCATION, e.span, msg); } diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 7bd3b6e39f0..34551e8e76f 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -256,8 +256,8 @@ pub(super) fn report_conflicting_borrow( "immutable", "mutable", ) { - (BorrowKind::Shared, lft, _, BorrowKind::Mut, _, rgt) | - (BorrowKind::Mut, _, lft, BorrowKind::Shared, rgt, _) => self.tcx + (BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt) | + (BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => self.tcx .cannot_reborrow_already_borrowed( span, &desc_place, @@ -271,7 +271,7 @@ pub(super) fn report_conflicting_borrow( Origin::Mir, ), - (BorrowKind::Mut, _, _, BorrowKind::Mut, _, _) => self.tcx + (BorrowKind::Mut { .. }, _, _, BorrowKind::Mut { .. }, _, _) => self.tcx .cannot_mutably_borrow_multiply( span, &desc_place, @@ -314,7 +314,7 @@ pub(super) fn report_conflicting_borrow( Origin::Mir, ), - (BorrowKind::Mut, _, lft, BorrowKind::Unique, _, _) => self.tcx + (BorrowKind::Mut { .. }, _, lft, BorrowKind::Unique, _, _) => self.tcx .cannot_reborrow_already_uniquely_borrowed( span, &desc_place, @@ -362,33 +362,20 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough( let scope_tree = borrows.0.scope_tree(); let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All).last().unwrap(); - match root_place { - &Place::Local(local) => { - if let Some(_) = self.storage_dead_or_drop_error_reported_l.replace(local) { - debug!("report_does_not_live_long_enough({:?}): ", - (borrow, drop_span)); - return - } - } - &Place::Static(ref statik) => { - if let Some(_) = self.storage_dead_or_drop_error_reported_s - .replace(statik.def_id) - { - debug!("report_does_not_live_long_enough({:?}): ", - (borrow, drop_span)); - return - } - }, - &Place::Projection(_) => - unreachable!("root_place is an unreachable???") - }; - let borrow_span = self.mir.source_info(borrow.location).span; let proper_span = match *root_place { Place::Local(local) => self.mir.local_decls[local].source_info.span, _ => drop_span, }; + if self.access_place_error_reported.contains(&(root_place.clone(), borrow_span)) { + debug!("suppressing access_place error when borrow doesn't live long enough for {:?}", + borrow_span); + return; + } + + self.access_place_error_reported.insert((root_place.clone(), borrow_span)); + match (borrow.region, &self.describe_place(&borrow.borrowed_place)) { (RegionKind::ReScope(_), Some(name)) => { self.report_scoped_local_value_does_not_live_long_enough( @@ -746,12 +733,12 @@ fn describe_field_from_ty(&self, ty: &ty::Ty, field: Field) -> String { self.describe_field_from_ty(&tnm.ty, field) } ty::TyArray(ty, _) | ty::TySlice(ty) => self.describe_field_from_ty(&ty, field), - ty::TyClosure(closure_def_id, _) => { + ty::TyClosure(def_id, _) | ty::TyGenerator(def_id, _, _) => { // Convert the def-id into a node-id. node-ids are only valid for // the local code in the current crate, so this returns an `Option` in case // the closure comes from another crate. But in that case we wouldn't // be borrowck'ing it, so we can just unwrap: - let node_id = self.tcx.hir.as_local_node_id(closure_def_id).unwrap(); + let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); let freevar = self.tcx.with_freevars(node_id, |fv| fv[field.index()]); self.tcx.hir.name(freevar.var_id()).to_string() diff --git a/src/librustc_mir/borrow_check/flows.rs b/src/librustc_mir/borrow_check/flows.rs index 61d6c14d627..ba966c9d4e3 100644 --- a/src/librustc_mir/borrow_check/flows.rs +++ b/src/librustc_mir/borrow_check/flows.rs @@ -15,8 +15,8 @@ use rustc::mir::{BasicBlock, Location}; -use dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; -use dataflow::{EverInitializedLvals, MovingOutStatements}; +use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; +use dataflow::{EverInitializedPlaces, MovingOutStatements}; use dataflow::{ActiveBorrows, FlowAtLocation, FlowsAtLocation}; use dataflow::move_paths::HasMoveData; use std::fmt; @@ -24,19 +24,19 @@ // (forced to be `pub` due to its use as an associated type below.) pub(crate) struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> { pub borrows: FlowAtLocation>, - pub inits: FlowAtLocation>, - pub uninits: FlowAtLocation>, + pub inits: FlowAtLocation>, + pub uninits: FlowAtLocation>, pub move_outs: FlowAtLocation>, - pub ever_inits: FlowAtLocation>, + pub ever_inits: FlowAtLocation>, } impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> { pub fn new( borrows: FlowAtLocation>, - inits: FlowAtLocation>, - uninits: FlowAtLocation>, + inits: FlowAtLocation>, + uninits: FlowAtLocation>, move_outs: FlowAtLocation>, - ever_inits: FlowAtLocation>, + ever_inits: FlowAtLocation>, ) -> Self { Flows { borrows, diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index f6923651663..c4df7349391 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -17,7 +17,7 @@ use rustc::infer::InferCtxt; use rustc::ty::{self, ParamEnv, TyCtxt}; use rustc::ty::maps::Providers; -use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Local, Location, Place}; +use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Location, Place}; use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue}; use rustc::mir::{Field, Statement, StatementKind, Terminator, TerminatorKind}; use rustc::mir::ClosureRegionRequirements; @@ -35,8 +35,8 @@ use dataflow::FlowAtLocation; use dataflow::MoveDataParamEnv; use dataflow::{DataflowAnalysis, DataflowResultsConsumer}; -use dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; -use dataflow::{EverInitializedLvals, MovingOutStatements}; +use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; +use dataflow::{EverInitializedPlaces, MovingOutStatements}; use dataflow::{BorrowData, Borrows, ReserveOrActivateIndex}; use dataflow::{ActiveBorrows, Reservations}; use dataflow::indexes::BorrowIndex; @@ -160,7 +160,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( id, &attributes, &dead_unwinds, - MaybeInitializedLvals::new(tcx, mir, &mdpe), + MaybeInitializedPlaces::new(tcx, mir, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), )); let flow_uninits = FlowAtLocation::new(do_dataflow( @@ -169,7 +169,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( id, &attributes, &dead_unwinds, - MaybeUninitializedLvals::new(tcx, mir, &mdpe), + MaybeUninitializedPlaces::new(tcx, mir, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), )); let flow_move_outs = FlowAtLocation::new(do_dataflow( @@ -187,7 +187,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( id, &attributes, &dead_unwinds, - EverInitializedLvals::new(tcx, mir, &mdpe), + EverInitializedPlaces::new(tcx, mir, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().inits[i]), )); @@ -228,8 +228,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => false, hir::BodyOwnerKind::Fn => true, }, - storage_dead_or_drop_error_reported_l: FxHashSet(), - storage_dead_or_drop_error_reported_s: FxHashSet(), + access_place_error_reported: FxHashSet(), reservation_error_reported: FxHashSet(), nonlexical_regioncx: opt_regioncx.clone(), }; @@ -294,12 +293,12 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> { /// I'm not sure this is the right approach - @eddyb could you try and /// figure this out? locals_are_invalidated_at_exit: bool, - /// This field keeps track of when storage dead or drop errors are reported - /// in order to stop duplicate error reporting and identify the conditions required - /// for a "temporary value dropped here while still borrowed" error. See #45360. - storage_dead_or_drop_error_reported_l: FxHashSet, - /// Same as the above, but for statics (thread-locals) - storage_dead_or_drop_error_reported_s: FxHashSet, + /// This field keeps track of when borrow errors are reported in the access_place function + /// so that there is no duplicate reporting. This field cannot also be used for the conflicting + /// borrow errors that is handled by the `reservation_error_reported` field as the inclusion + /// of the `Span` type (while required to mute some errors) stops the muting of the reservation + /// errors. + access_place_error_reported: FxHashSet<(Place<'tcx>, Span)>, /// This field keeps track of when borrow conflict errors are reported /// for reservations, so that we don't report seemingly duplicate /// errors for corresponding activations @@ -348,6 +347,13 @@ fn visit_statement_entry( match stmt.kind { StatementKind::Assign(ref lhs, ref rhs) => { + self.consume_rvalue( + ContextKind::AssignRhs.new(location), + (rhs, span), + location, + flow_state, + ); + self.mutate_place( ContextKind::AssignLhs.new(location), (lhs, span), @@ -355,13 +361,6 @@ fn visit_statement_entry( JustWrite, flow_state, ); - - self.consume_rvalue( - ContextKind::AssignRhs.new(location), - (rhs, span), - location, - flow_state, - ); } StatementKind::SetDiscriminant { ref place, @@ -576,7 +575,8 @@ fn visit_terminator_entry( TerminatorKind::Goto { target: _ } | TerminatorKind::Abort | TerminatorKind::Unreachable - | TerminatorKind::FalseEdges { .. } => { + | TerminatorKind::FalseEdges { real_target: _, imaginary_targets: _ } + | TerminatorKind::FalseUnwind { real_target: _, unwind: _ } => { // no data used, thus irrelevant to borrowck } } @@ -607,7 +607,7 @@ enum ArtificialField { #[derive(Copy, Clone, PartialEq, Eq, Debug)] enum ShallowOrDeep { /// From the RFC: "A *shallow* access means that the immediate - /// fields reached at LV are accessed, but references or pointers + /// fields reached at P are accessed, but references or pointers /// found within are not dereferenced. Right now, the only access /// that is shallow is an assignment like `x = ...;`, which would /// be a *shallow write* of `x`." @@ -708,6 +708,15 @@ fn as_verb_in_past_tense(self) -> &'static str { } impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { + /// Returns true if the borrow represented by `kind` is + /// allowed to be split into separate Reservation and + /// Activation phases. + fn allow_two_phase_borrow(&self, kind: BorrowKind) -> bool { + self.tcx.sess.two_phase_borrows() && + (kind.allows_two_phase_borrow() || + self.tcx.sess.opts.debugging_opts.two_phase_beyond_autoref) + } + /// Checks an access to the given place to see if it is allowed. Examines the set of borrows /// that are in scope, as well as which paths have been initialized, to ensure that (a) the /// place is initialized and (b) it is not borrowed in some way that would prevent this @@ -726,12 +735,8 @@ fn access_place( if let Activation(_, borrow_index) = rw { if self.reservation_error_reported.contains(&place_span.0) { - debug!( - "skipping access_place for activation of invalid reservation \ - place: {:?} borrow_index: {:?}", - place_span.0, - borrow_index - ); + debug!("skipping access_place for activation of invalid reservation \ + place: {:?} borrow_index: {:?}", place_span.0, borrow_index); return AccessErrorsReported { mutability_error: false, conflict_error: true, @@ -739,11 +744,26 @@ fn access_place( } } + if self.access_place_error_reported.contains(&(place_span.0.clone(), place_span.1)) { + debug!("access_place: suppressing error place_span=`{:?}` kind=`{:?}`", + place_span, kind); + return AccessErrorsReported { + mutability_error: false, + conflict_error: true, + }; + } + let mutability_error = self.check_access_permissions(place_span, rw, is_local_mutation_allowed); let conflict_error = self.check_access_for_conflict(context, place_span, sd, rw, flow_state); + if conflict_error || mutability_error { + debug!("access_place: logging error place_span=`{:?}` kind=`{:?}`", + place_span, kind); + self.access_place_error_reported.insert((place_span.0.clone(), place_span.1)); + } + AccessErrorsReported { mutability_error, conflict_error, @@ -787,9 +807,9 @@ fn check_access_for_conflict( Control::Continue } - (Read(kind), BorrowKind::Unique) | (Read(kind), BorrowKind::Mut) => { + (Read(kind), BorrowKind::Unique) | (Read(kind), BorrowKind::Mut { .. }) => { // Reading from mere reservations of mutable-borrows is OK. - if this.tcx.sess.two_phase_borrows() && index.is_reservation() + if this.allow_two_phase_borrow(borrow.kind) && index.is_reservation() { return Control::Continue; } @@ -818,7 +838,7 @@ fn check_access_for_conflict( } (Reservation(kind), BorrowKind::Unique) - | (Reservation(kind), BorrowKind::Mut) + | (Reservation(kind), BorrowKind::Mut { .. }) | (Activation(kind, _), _) | (Write(kind), _) => { match rw { @@ -829,15 +849,15 @@ fn check_access_for_conflict( place_span.0 ); this.reservation_error_reported.insert(place_span.0.clone()); - } + }, Activation(_, activating) => { debug!( "observing check_place for activation of \ borrow_index: {:?}", activating ); - } - Read(..) | Write(..) => {} + }, + Read(..) | Write(..) => {}, } match kind { @@ -935,9 +955,9 @@ fn consume_rvalue( Rvalue::Ref(_ /*rgn*/, bk, ref place) => { let access_kind = match bk { BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))), - BorrowKind::Unique | BorrowKind::Mut => { + BorrowKind::Unique | BorrowKind::Mut { .. } => { let wk = WriteKind::MutableBorrow(bk); - if self.tcx.sess.two_phase_borrows() { + if self.allow_two_phase_borrow(bk) { (Deep, Reservation(wk)) } else { (Deep, Write(wk)) @@ -1186,7 +1206,7 @@ fn check_activations( // mutable borrow before we check it. match borrow.kind { BorrowKind::Shared => return, - BorrowKind::Unique | BorrowKind::Mut => {} + BorrowKind::Unique | BorrowKind::Mut { .. } => {} } self.access_place( @@ -1457,8 +1477,8 @@ fn check_access_permissions( span_bug!(span, "&unique borrow for {:?} should not fail", place); } } - Reservation(WriteKind::MutableBorrow(BorrowKind::Mut)) - | Write(WriteKind::MutableBorrow(BorrowKind::Mut)) => if let Err(place_err) = + Reservation(WriteKind::MutableBorrow(BorrowKind::Mut { .. })) + | Write(WriteKind::MutableBorrow(BorrowKind::Mut { .. })) => if let Err(place_err) = self.is_mutable(place, is_local_mutation_allowed) { error_reported = true; @@ -1522,7 +1542,7 @@ fn check_access_permissions( Activation(..) => {} // permission checks are done at Reservation point. Read(ReadKind::Borrow(BorrowKind::Unique)) - | Read(ReadKind::Borrow(BorrowKind::Mut)) + | Read(ReadKind::Borrow(BorrowKind::Mut { .. })) | Read(ReadKind::Borrow(BorrowKind::Shared)) | Read(ReadKind::Copy) => {} // Access authorized } diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index f96e107efa3..66ca74b0139 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -19,7 +19,7 @@ use transform::MirSource; use util::liveness::{LivenessResults, LocalSet}; use dataflow::FlowAtLocation; -use dataflow::MaybeInitializedLvals; +use dataflow::MaybeInitializedPlaces; use dataflow::move_paths::MoveData; use util as mir_util; @@ -71,7 +71,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( universal_regions: UniversalRegions<'tcx>, mir: &Mir<'tcx>, param_env: ty::ParamEnv<'gcx>, - flow_inits: &mut FlowAtLocation>, + flow_inits: &mut FlowAtLocation>, move_data: &MoveData<'tcx>, ) -> ( RegionInferenceContext<'tcx>, diff --git a/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs b/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs index e8a23acd798..d213f376d2b 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs @@ -45,10 +45,11 @@ pub(crate) fn annotate(&self, err: &mut DiagnosticBuilder<'_>) { &substs[..] )); } - DefiningTy::Const(ty) => { + DefiningTy::Const(def_id, substs) => { err.note(&format!( - "defining type: {:?}", - ty + "defining constant type: {:?} with substs {:#?}", + def_id, + &substs[..] )); } } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index 9a2f98d4622..9a338947f47 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::collections::HashMap; + use super::universal_regions::UniversalRegions; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; @@ -22,6 +24,7 @@ use rustc::traits::ObligationCause; use rustc::ty::{self, RegionVid, Ty, TypeFoldable}; use rustc::util::common::ErrorReported; +use rustc_data_structures::bitvec::BitVector; use rustc_data_structures::indexed_vec::IndexVec; use rustc_errors::DiagnosticBuilder; use std::fmt; @@ -452,8 +455,6 @@ pub(super) fn solve<'gcx>( /// satisfied. Note that some values may grow **too** large to be /// feasible, but we check this later. fn propagate_constraints(&mut self, mir: &Mir<'tcx>) { - let mut changed = true; - debug!("propagate_constraints()"); debug!("propagate_constraints: constraints={:#?}", { let mut constraints: Vec<_> = self.constraints.iter().collect(); @@ -465,37 +466,65 @@ fn propagate_constraints(&mut self, mir: &Mir<'tcx>) { // constraints we have accumulated. let mut inferred_values = self.liveness_constraints.clone(); - while changed { - changed = false; - debug!("propagate_constraints: --------------------"); - for constraint in &self.constraints { - debug!("propagate_constraints: constraint={:?}", constraint); - - // Grow the value as needed to accommodate the - // outlives constraint. - let Ok(made_changes) = self.dfs( - mir, - CopyFromSourceToTarget { - source_region: constraint.sub, - target_region: constraint.sup, - inferred_values: &mut inferred_values, - constraint_point: constraint.point, - constraint_span: constraint.span, - }, - ); + let dependency_map = self.build_dependency_map(); + + // Constraints that may need to be repropagated (initially all): + let mut dirty_list: Vec<_> = (0..self.constraints.len()).collect(); + + // Set to 0 for each constraint that is on the dirty list: + let mut clean_bit_vec = BitVector::new(dirty_list.len()); + + debug!("propagate_constraints: --------------------"); + while let Some(constraint_idx) = dirty_list.pop() { + clean_bit_vec.insert(constraint_idx); + + let constraint = &self.constraints[constraint_idx]; + debug!("propagate_constraints: constraint={:?}", constraint); - if made_changes { - debug!("propagate_constraints: sub={:?}", constraint.sub); - debug!("propagate_constraints: sup={:?}", constraint.sup); - changed = true; + // Grow the value as needed to accommodate the + // outlives constraint. + let Ok(made_changes) = self.dfs( + mir, + CopyFromSourceToTarget { + source_region: constraint.sub, + target_region: constraint.sup, + inferred_values: &mut inferred_values, + constraint_point: constraint.point, + constraint_span: constraint.span, + }, + ); + + if made_changes { + debug!("propagate_constraints: sub={:?}", constraint.sub); + debug!("propagate_constraints: sup={:?}", constraint.sup); + + for &dep_idx in dependency_map.get(&constraint.sup).unwrap_or(&vec![]) { + if clean_bit_vec.remove(dep_idx) { + dirty_list.push(dep_idx); + } } } + debug!("\n"); } self.inferred_values = Some(inferred_values); } + /// Builds up a map from each region variable X to a vector with the + /// indices of constraints that need to be re-evaluated when X changes. + /// These are constraints like Y: X @ P -- so if X changed, we may + /// need to grow Y. + fn build_dependency_map(&self) -> HashMap> { + let mut map = HashMap::new(); + + for (idx, constraint) in self.constraints.iter().enumerate() { + map.entry(constraint.sub).or_insert(Vec::new()).push(idx); + } + + map + } + /// Once regions have been propagated, this method is used to see /// whether the "type tests" produced by typeck were satisfied; /// type tests encode type-outlives relationships like `T: diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs index 8a0578ae4d4..a50b9993747 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs @@ -10,12 +10,15 @@ use dataflow::{FlowAtLocation, FlowsAtLocation}; use borrow_check::nll::region_infer::Cause; -use dataflow::MaybeInitializedLvals; +use dataflow::MaybeInitializedPlaces; use dataflow::move_paths::{HasMoveData, MoveData}; use rustc::mir::{BasicBlock, Location, Mir}; use rustc::mir::Local; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; +use rustc::traits; +use rustc::infer::InferOk; use rustc::util::common::ErrorReported; +use borrow_check::nll::type_check::AtLocation; use rustc_data_structures::fx::FxHashSet; use syntax::codemap::DUMMY_SP; use util::liveness::LivenessResults; @@ -34,7 +37,7 @@ pub(super) fn generate<'gcx, 'tcx>( cx: &mut TypeChecker<'_, 'gcx, 'tcx>, mir: &Mir<'tcx>, liveness: &LivenessResults, - flow_inits: &mut FlowAtLocation>, + flow_inits: &mut FlowAtLocation>, move_data: &MoveData<'tcx>, ) { let tcx = cx.tcx(); @@ -63,7 +66,7 @@ struct TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx> tcx: TyCtxt<'typeck, 'gcx, 'tcx>, mir: &'gen Mir<'tcx>, liveness: &'gen LivenessResults, - flow_inits: &'gen mut FlowAtLocation>, + flow_inits: &'gen mut FlowAtLocation>, move_data: &'gen MoveData<'tcx>, } @@ -184,48 +187,86 @@ fn add_drop_live_constraint( location ); - let tcx = self.cx.infcx.tcx; - let mut types = vec![(dropped_ty, 0)]; - let mut known = FxHashSet(); - while let Some((ty, depth)) = types.pop() { - let span = DUMMY_SP; // FIXME - let result = match tcx.dtorck_constraint_for_ty(span, dropped_ty, depth, ty) { - Ok(result) => result, - Err(ErrorReported) => { - continue; - } - }; - - let ty::DtorckConstraint { - outlives, - dtorck_types, - } = result; - - // All things in the `outlives` array may be touched by - // the destructor and must be live at this point. - for outlive in outlives { - let cause = Cause::DropVar(dropped_local, location); - self.push_type_live_constraint(outlive, location, cause); - } + // If we end visiting the same type twice (usually due to a cycle involving + // associated types), we need to ensure that its region types match up with the type + // we added to the 'known' map the first time around. For this reason, we need + // our infcx to hold onto its calculated region constraints after each call + // to dtorck_constraint_for_ty. Otherwise, normalizing the corresponding associated + // type will end up instantiating the type with a new set of inference variables + // Since this new type will never be in 'known', we end up looping forever. + // + // For this reason, we avoid calling TypeChecker.normalize, instead doing all normalization + // ourselves in one large 'fully_perform_op' callback. + let (type_constraints, kind_constraints) = self.cx.fully_perform_op(location.at_self(), + |cx| { + + let tcx = cx.infcx.tcx; + let mut selcx = traits::SelectionContext::new(cx.infcx); + let cause = cx.misc(cx.last_span); + + let mut types = vec![(dropped_ty, 0)]; + let mut final_obligations = Vec::new(); + let mut type_constraints = Vec::new(); + let mut kind_constraints = Vec::new(); - // However, there may also be some types that - // `dtorck_constraint_for_ty` could not resolve (e.g., - // associated types and parameters). We need to normalize - // associated types here and possibly recursively process. - for ty in dtorck_types { - let ty = self.cx.normalize(&ty, location); - let ty = self.cx.infcx.resolve_type_and_region_vars_if_possible(&ty); - match ty.sty { - ty::TyParam(..) | ty::TyProjection(..) | ty::TyAnon(..) => { - let cause = Cause::DropVar(dropped_local, location); - self.push_type_live_constraint(ty, location, cause); + let mut known = FxHashSet(); + + while let Some((ty, depth)) = types.pop() { + let span = DUMMY_SP; // FIXME + let result = match tcx.dtorck_constraint_for_ty(span, dropped_ty, depth, ty) { + Ok(result) => result, + Err(ErrorReported) => { + continue; } + }; + + let ty::DtorckConstraint { + outlives, + dtorck_types, + } = result; + + // All things in the `outlives` array may be touched by + // the destructor and must be live at this point. + for outlive in outlives { + let cause = Cause::DropVar(dropped_local, location); + kind_constraints.push((outlive, location, cause)); + } - _ => if known.insert(ty) { - types.push((ty, depth + 1)); - }, + // However, there may also be some types that + // `dtorck_constraint_for_ty` could not resolve (e.g., + // associated types and parameters). We need to normalize + // associated types here and possibly recursively process. + for ty in dtorck_types { + let traits::Normalized { value: ty, obligations } = + traits::normalize(&mut selcx, cx.param_env, cause.clone(), &ty); + + final_obligations.extend(obligations); + + let ty = cx.infcx.resolve_type_and_region_vars_if_possible(&ty); + match ty.sty { + ty::TyParam(..) | ty::TyProjection(..) | ty::TyAnon(..) => { + let cause = Cause::DropVar(dropped_local, location); + type_constraints.push((ty, location, cause)); + } + + _ => if known.insert(ty) { + types.push((ty, depth + 1)); + }, + } } } + + Ok(InferOk { + value: (type_constraints, kind_constraints), obligations: final_obligations + }) + }).unwrap(); + + for (ty, location, cause) in type_constraints { + self.push_type_live_constraint(ty, location, cause); + } + + for (kind, location, cause) in kind_constraints { + self.push_type_live_constraint(kind, location, cause); } } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 9dcd4435580..7ca8d0bdd50 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -15,7 +15,7 @@ use borrow_check::nll::region_infer::ClosureRegionRequirementsExt; use borrow_check::nll::universal_regions::UniversalRegions; use dataflow::FlowAtLocation; -use dataflow::MaybeInitializedLvals; +use dataflow::MaybeInitializedPlaces; use dataflow::move_paths::MoveData; use rustc::hir::def_id::DefId; use rustc::infer::{InferCtxt, InferOk, InferResult, LateBoundRegionConversionTime, UnitResult}; @@ -100,7 +100,7 @@ pub(crate) fn type_check<'gcx, 'tcx>( mir_def_id: DefId, universal_regions: &UniversalRegions<'tcx>, liveness: &LivenessResults, - flow_inits: &mut FlowAtLocation>, + flow_inits: &mut FlowAtLocation>, move_data: &MoveData<'tcx>, ) -> MirTypeckRegionConstraints<'tcx> { let body_id = infcx.tcx.hir.as_local_node_id(mir_def_id).unwrap(); @@ -374,13 +374,20 @@ fn sanitize_place( } }; if let PlaceContext::Copy = context { - let ty = place_ty.to_ty(self.tcx()); - if self.cx - .infcx - .type_moves_by_default(self.cx.param_env, ty, DUMMY_SP) - { - span_mirbug!(self, place, "attempted copy of non-Copy type ({:?})", ty); - } + let tcx = self.tcx(); + let trait_ref = ty::TraitRef { + def_id: tcx.lang_items().copy_trait().unwrap(), + substs: tcx.mk_substs_trait(place_ty.to_ty(tcx), &[]), + }; + + // In order to have a Copy operand, the type T of the value must be Copy. Note that we + // prove that T: Copy, rather than using the type_moves_by_default test. This is + // important because type_moves_by_default ignores the resulting region obligations and + // assumes they pass. This can result in bounds from Copy impls being unsoundly ignored + // (e.g., #29149). Note that we decide to use Copy before knowing whether the bounds + // fully apply: in effect, the rule is that if a value of some type could implement + // Copy, then it must. + self.cx.prove_trait_ref(trait_ref, location); } place_ty } @@ -397,7 +404,7 @@ fn sanitize_projection( let base_ty = base.to_ty(tcx); match *pi { ProjectionElem::Deref => { - let deref_ty = base_ty.builtin_deref(true, ty::LvaluePreference::NoPreference); + let deref_ty = base_ty.builtin_deref(true); PlaceTy::Ty { ty: deref_ty.map(|t| t.ty).unwrap_or_else(|| { span_mirbug_and_err!(self, place, "deref of non-pointer {:?}", base_ty) @@ -533,15 +540,17 @@ fn field_ty( } } ty::TyGenerator(def_id, substs, _) => { - // Try upvars first. `field_tys` requires final optimized MIR. - if let Some(ty) = substs.upvar_tys(def_id, tcx).nth(field.index()) { + // Try pre-transform fields first (upvars and current state) + if let Some(ty) = substs.pre_transforms_tys(def_id, tcx).nth(field.index()) { return Ok(ty); } + // Then try `field_tys` which contains all the fields, but it + // requires the final optimized MIR. return match substs.field_tys(def_id, tcx).nth(field.index()) { Some(ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { - field_count: substs.field_tys(def_id, tcx).count() + 1, + field_count: substs.field_tys(def_id, tcx).count(), }), }; } @@ -787,7 +796,8 @@ fn check_terminator( | TerminatorKind::GeneratorDrop | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } - | TerminatorKind::FalseEdges { .. } => { + | TerminatorKind::FalseEdges { .. } + | TerminatorKind::FalseUnwind { .. } => { // no checks needed for these } @@ -1143,6 +1153,18 @@ fn check_iscleanup(&mut self, mir: &Mir<'tcx>, block_data: &BasicBlockData<'tcx> self.assert_iscleanup(mir, block_data, *target, is_cleanup); } } + TerminatorKind::FalseUnwind { + real_target, + unwind + } => { + self.assert_iscleanup(mir, block_data, real_target, is_cleanup); + if let Some(unwind) = unwind { + if is_cleanup { + span_mirbug!(self, block_data, "cleanup in cleanup block via false unwind"); + } + self.assert_iscleanup(mir, block_data, unwind, true); + } + } } } @@ -1233,13 +1255,16 @@ fn aggregate_field_ty( } } AggregateKind::Generator(def_id, substs, _) => { - if let Some(ty) = substs.upvar_tys(def_id, tcx).nth(field_index) { + // Try pre-transform fields first (upvars and current state) + if let Some(ty) = substs.pre_transforms_tys(def_id, tcx).nth(field_index) { Ok(ty) } else { + // Then try `field_tys` which contains all the fields, but it + // requires the final optimized MIR. match substs.field_tys(def_id, tcx).nth(field_index) { Some(ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { - field_count: substs.field_tys(def_id, tcx).count() + 1, + field_count: substs.field_tys(def_id, tcx).count(), }), } } diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs index e47e3c728df..668172749fe 100644 --- a/src/librustc_mir/borrow_check/nll/universal_regions.rs +++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs @@ -125,7 +125,7 @@ pub enum DefiningTy<'tcx> { /// The MIR represents some form of constant. The signature then /// is that it has no inputs and a single return value, which is /// the value of the constant. - Const(Ty<'tcx>), + Const(DefId, &'tcx Substs<'tcx>), } #[derive(Debug)] @@ -534,34 +534,42 @@ fn build(mut self) -> UniversalRegions<'tcx> { /// see `DefiningTy` for details. fn defining_ty(&self) -> DefiningTy<'tcx> { let tcx = self.infcx.tcx; - let closure_base_def_id = tcx.closure_base_def_id(self.mir_def_id); - let defining_ty = if self.mir_def_id == closure_base_def_id { - tcx.type_of(closure_base_def_id) - } else { - let tables = tcx.typeck_tables_of(self.mir_def_id); - tables.node_id_to_type(self.mir_hir_id) - }; - - let defining_ty = self.infcx - .replace_free_regions_with_nll_infer_vars(FR, &defining_ty); - match tcx.hir.body_owner_kind(self.mir_node_id) { - BodyOwnerKind::Fn => match defining_ty.sty { - ty::TyClosure(def_id, substs) => DefiningTy::Closure(def_id, substs), - ty::TyGenerator(def_id, substs, interior) => { - DefiningTy::Generator(def_id, substs, interior) + BodyOwnerKind::Fn => { + let defining_ty = if self.mir_def_id == closure_base_def_id { + tcx.type_of(closure_base_def_id) + } else { + let tables = tcx.typeck_tables_of(self.mir_def_id); + tables.node_id_to_type(self.mir_hir_id) + }; + + let defining_ty = self.infcx + .replace_free_regions_with_nll_infer_vars(FR, &defining_ty); + + match defining_ty.sty { + ty::TyClosure(def_id, substs) => DefiningTy::Closure(def_id, substs), + ty::TyGenerator(def_id, substs, interior) => { + DefiningTy::Generator(def_id, substs, interior) + } + ty::TyFnDef(def_id, substs) => DefiningTy::FnDef(def_id, substs), + _ => span_bug!( + tcx.def_span(self.mir_def_id), + "expected defining type for `{:?}`: `{:?}`", + self.mir_def_id, + defining_ty + ), } - ty::TyFnDef(def_id, substs) => DefiningTy::FnDef(def_id, substs), - _ => span_bug!( - tcx.def_span(self.mir_def_id), - "expected defining type for `{:?}`: `{:?}`", - self.mir_def_id, - defining_ty - ), - }, - BodyOwnerKind::Const | BodyOwnerKind::Static(..) => DefiningTy::Const(defining_ty), + } + + BodyOwnerKind::Const | BodyOwnerKind::Static(..) => { + assert_eq!(closure_base_def_id, self.mir_def_id); + let identity_substs = Substs::identity_for_item(tcx, closure_base_def_id); + let substs = self.infcx + .replace_free_regions_with_nll_infer_vars(FR, &identity_substs); + DefiningTy::Const(self.mir_def_id, substs) + } } } @@ -592,13 +600,7 @@ fn compute_indices( substs.substs } - DefiningTy::FnDef(_, substs) => substs, - - // When we encounter a constant body, just return whatever - // substitutions are in scope for that constant. - DefiningTy::Const(_) => { - identity_substs - } + DefiningTy::FnDef(_, substs) | DefiningTy::Const(_, substs) => substs, }; let global_mapping = iter::once((gcx.types.re_static, fr_static)); @@ -660,9 +662,14 @@ fn compute_inputs_and_output( sig.inputs_and_output() } - // For a constant body, there are no inputs, and one - // "output" (the type of the constant). - DefiningTy::Const(ty) => ty::Binder::dummy(tcx.mk_type_list(iter::once(ty))), + DefiningTy::Const(def_id, _) => { + // For a constant body, there are no inputs, and one + // "output" (the type of the constant). + assert_eq!(self.mir_def_id, def_id); + let ty = tcx.type_of(def_id); + let ty = indices.fold_to_region_vids(tcx, &ty); + ty::Binder::dummy(tcx.mk_type_list(iter::once(ty))) + } } } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 68b23d1ae17..28dc329e4fe 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -104,8 +104,8 @@ pub fn into_expr(&mut self, // Or: // // [block: If(lhs)] -false-> [else_block: If(rhs)] -true-> [true_block] - // | | (false) - // +----------true------------+-------------------> [false_block] + // | (true) | (false) + // [true_block] [false_block] let (true_block, false_block, mut else_block, join_block) = (this.cfg.start_new_block(), this.cfg.start_new_block(), @@ -147,20 +147,24 @@ pub fn into_expr(&mut self, join_block.unit() } ExprKind::Loop { condition: opt_cond_expr, body } => { - // [block] --> [loop_block] ~~> [loop_block_end] -1-> [exit_block] - // ^ | - // | 0 - // | | - // | v - // [body_block_end] <~~~ [body_block] + // [block] --> [loop_block] -/eval. cond./-> [loop_block_end] -1-> [exit_block] + // ^ | + // | 0 + // | | + // | v + // [body_block_end] <-/eval. body/-- [body_block] // // If `opt_cond_expr` is `None`, then the graph is somewhat simplified: // - // [block] --> [loop_block / body_block ] ~~> [body_block_end] [exit_block] - // ^ | - // | | - // +--------------------------+ - // + // [block] + // | + // [loop_block] -> [body_block] -/eval. body/-> [body_block_end] + // | ^ | + // false link | | + // | +-----------------------------------------+ + // +-> [diverge_cleanup] + // The false link is required to make sure borrowck considers unwinds through the + // body, even when the exact code in the body cannot unwind let loop_block = this.cfg.start_new_block(); let exit_block = this.cfg.start_new_block(); @@ -188,7 +192,13 @@ pub fn into_expr(&mut self, // always `()` anyway this.cfg.push_assign_unit(exit_block, source_info, destination); } else { - body_block = loop_block; + body_block = this.cfg.start_new_block(); + let diverge_cleanup = this.diverge_cleanup(); + this.cfg.terminate(loop_block, source_info, + TerminatorKind::FalseUnwind { + real_target: body_block, + unwind: Some(diverge_cleanup) + }) } // The “return” value of the loop body must always be an unit. We therefore diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 6cb92177766..8053a0a6948 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -38,6 +38,22 @@ pub fn match_expr(&mut self, -> BlockAnd<()> { let discriminant_place = unpack!(block = self.as_place(block, discriminant)); + // Matching on a `discriminant_place` with an uninhabited type doesn't + // generate any memory reads by itself, and so if the place "expression" + // contains unsafe operations like raw pointer dereferences or union + // field projections, we wouldn't know to require an `unsafe` block + // around a `match` equivalent to `std::intrinsics::unreachable()`. + // See issue #47412 for this hole being discovered in the wild. + // + // HACK(eddyb) Work around the above issue by adding a dummy inspection + // of `discriminant_place`, specifically by applying `Rvalue::Discriminant` + // (which will work regardless of type) and storing the result in a temp. + let dummy_source_info = self.source_info(span); + let dummy_access = Rvalue::Discriminant(discriminant_place.clone()); + let dummy_ty = dummy_access.ty(&self.local_decls, self.hir.tcx()); + let dummy_temp = self.temp(dummy_ty, dummy_source_info.span); + self.cfg.push_assign(block, dummy_source_info, &dummy_temp, dummy_access); + let mut arm_blocks = ArmBlocks { blocks: arms.iter() .map(|_| self.cfg.start_new_block()) @@ -728,7 +744,8 @@ fn bind_and_guard_matched_candidate<'pat>(&mut self, TerminatorKind::FalseEdges { real_target: block, imaginary_targets: - vec![candidate.next_candidate_pre_binding_block]}); + vec![candidate.next_candidate_pre_binding_block], + }); self.bind_matched_candidate(block, candidate.bindings); @@ -749,7 +766,8 @@ fn bind_and_guard_matched_candidate<'pat>(&mut self, TerminatorKind::FalseEdges { real_target: otherwise, imaginary_targets: - vec![candidate.next_candidate_pre_binding_block] }); + vec![candidate.next_candidate_pre_binding_block], + }); Some(otherwise) } else { self.cfg.terminate(block, candidate_source_info, diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs new file mode 100644 index 00000000000..244e8b5ccd7 --- /dev/null +++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs @@ -0,0 +1,118 @@ +// 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 use super::*; + +use rustc::mir::*; +use rustc::mir::visit::Visitor; +use dataflow::BitDenotation; + +/// This calculates if any part of a MIR local could have previously been borrowed. +/// This means that once a local has been borrowed, its bit will always be set +/// from that point and onwards, even if the borrow ends. You could also think of this +/// as computing the lifetimes of infinite borrows. +/// This is used to compute which locals are live during a yield expression for +/// immovable generators. +#[derive(Copy, Clone)] +pub struct HaveBeenBorrowedLocals<'a, 'tcx: 'a> { + mir: &'a Mir<'tcx>, +} + +impl<'a, 'tcx: 'a> HaveBeenBorrowedLocals<'a, 'tcx> { + pub fn new(mir: &'a Mir<'tcx>) + -> Self { + HaveBeenBorrowedLocals { mir: mir } + } + + pub fn mir(&self) -> &Mir<'tcx> { + self.mir + } +} + +impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> { + type Idx = Local; + fn name() -> &'static str { "has_been_borrowed_locals" } + fn bits_per_block(&self) -> usize { + self.mir.local_decls.len() + } + + fn start_block_effect(&self, _sets: &mut IdxSet) { + // Nothing is borrowed on function entry + } + + fn statement_effect(&self, + sets: &mut BlockSets, + loc: Location) { + BorrowedLocalsVisitor { + sets, + }.visit_statement(loc.block, &self.mir[loc.block].statements[loc.statement_index], loc); + } + + fn terminator_effect(&self, + sets: &mut BlockSets, + loc: Location) { + BorrowedLocalsVisitor { + sets, + }.visit_terminator(loc.block, self.mir[loc.block].terminator(), loc); + } + + fn propagate_call_return(&self, + _in_out: &mut IdxSet, + _call_bb: mir::BasicBlock, + _dest_bb: mir::BasicBlock, + _dest_place: &mir::Place) { + // Nothing to do when a call returns successfully + } +} + +impl<'a, 'tcx> BitwiseOperator for HaveBeenBorrowedLocals<'a, 'tcx> { + #[inline] + fn join(&self, pred1: usize, pred2: usize) -> usize { + pred1 | pred2 // "maybe" means we union effects of both preds + } +} + +impl<'a, 'tcx> InitialFlow for HaveBeenBorrowedLocals<'a, 'tcx> { + #[inline] + fn bottom_value() -> bool { + false // bottom = unborrowed + } +} + +struct BorrowedLocalsVisitor<'b, 'c: 'b> { + sets: &'b mut BlockSets<'c, Local>, +} + +fn find_local<'tcx>(place: &Place<'tcx>) -> Option { + match *place { + Place::Local(l) => Some(l), + Place::Static(..) => None, + Place::Projection(ref proj) => { + match proj.elem { + ProjectionElem::Deref => None, + _ => find_local(&proj.base) + } + } + } +} + +impl<'tcx, 'b, 'c> Visitor<'tcx> for BorrowedLocalsVisitor<'b, 'c> { + fn visit_rvalue(&mut self, + rvalue: &Rvalue<'tcx>, + location: Location) { + if let Rvalue::Ref(_, _, ref place) = *rvalue { + if let Some(local) = find_local(place) { + self.sets.gen(&local); + } + } + + self.super_rvalue(rvalue, location) + } +} diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index d7cd8830adb..e798cc93cb0 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -122,7 +122,7 @@ fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { let kind = match self.kind { mir::BorrowKind::Shared => "", mir::BorrowKind::Unique => "uniq ", - mir::BorrowKind::Mut => "mut ", + mir::BorrowKind::Mut { .. } => "mut ", }; let region = format!("{}", self.region); let region = if region.len() > 0 { format!("{} ", region) } else { region }; @@ -396,8 +396,7 @@ fn statement_effect_on_borrows(&self, // Issue #46746: Two-phase borrows handles // stmts of form `Tmp = &mut Borrow` ... match lhs { - Place::Local(..) => {} // okay - Place::Static(..) => unreachable!(), // (filtered by is_unsafe_place) + Place::Local(..) | Place::Static(..) => {} // okay Place::Projection(..) => { // ... can assign into projections, // e.g. `box (&mut _)`. Current @@ -518,6 +517,7 @@ fn terminator_effect_on_borrows(&self, mir::TerminatorKind::Yield {..} | mir::TerminatorKind::Goto {..} | mir::TerminatorKind::FalseEdges {..} | + mir::TerminatorKind::FalseUnwind {..} | mir::TerminatorKind::Unreachable => {} } } @@ -575,10 +575,10 @@ fn has_been_reserved(&self, b: &BorrowIndex) -> bool { /// has a reservation at the time). fn is_potential_use(context: PlaceContext) -> bool { match context { - // storage effects on an place do not activate it + // storage effects on a place do not activate it PlaceContext::StorageLive | PlaceContext::StorageDead => false, - // validation effects do not activate an place + // validation effects do not activate a place // // FIXME: Should they? Is it just another read? Or can we // guarantee it won't dereference the stored address? How @@ -589,11 +589,11 @@ fn is_potential_use(context: PlaceContext) -> bool { // AsmOutput existed, but it's not necessarily a pure overwrite. // so it's possible this should activate the place. PlaceContext::AsmOutput | - // pure overwrites of an place do not activate it. (note + // pure overwrites of a place do not activate it. (note // PlaceContext::Call is solely about dest place) PlaceContext::Store | PlaceContext::Call => false, - // reads of an place *do* activate it + // reads of a place *do* activate it PlaceContext::Move | PlaceContext::Copy | PlaceContext::Drop | diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index 106a88e703c..c5f5492cd2c 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -33,10 +33,14 @@ pub use self::storage_liveness::*; +mod borrowed_locals; + +pub use self::borrowed_locals::*; + #[allow(dead_code)] pub(super) mod borrows; -/// `MaybeInitializedLvals` tracks all l-values that might be +/// `MaybeInitializedPlaces` tracks all places that might be /// initialized upon reaching a particular point in the control flow /// for a function. /// @@ -63,35 +67,35 @@ /// } /// ``` /// -/// To determine whether an l-value *must* be initialized at a +/// To determine whether a place *must* be initialized at a /// particular control-flow point, one can take the set-difference -/// between this data and the data from `MaybeUninitializedLvals` at the +/// between this data and the data from `MaybeUninitializedPlaces` at the /// corresponding control-flow point. /// /// Similarly, at a given `drop` statement, the set-intersection -/// between this data and `MaybeUninitializedLvals` yields the set of -/// l-values that would require a dynamic drop-flag at that statement. -pub struct MaybeInitializedLvals<'a, 'gcx: 'tcx, 'tcx: 'a> { +/// between this data and `MaybeUninitializedPlaces` yields the set of +/// places that would require a dynamic drop-flag at that statement. +pub struct MaybeInitializedPlaces<'a, 'gcx: 'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>, } -impl<'a, 'gcx: 'tcx, 'tcx> MaybeInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx: 'tcx, 'tcx> MaybeInitializedPlaces<'a, 'gcx, 'tcx> { pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>) -> Self { - MaybeInitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe } + MaybeInitializedPlaces { tcx: tcx, mir: mir, mdpe: mdpe } } } -impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MaybeInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'gcx, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } } -/// `MaybeUninitializedLvals` tracks all l-values that might be +/// `MaybeUninitializedPlaces` tracks all places that might be /// uninitialized upon reaching a particular point in the control flow /// for a function. /// @@ -118,42 +122,42 @@ fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } /// } /// ``` /// -/// To determine whether an l-value *must* be uninitialized at a +/// To determine whether a place *must* be uninitialized at a /// particular control-flow point, one can take the set-difference -/// between this data and the data from `MaybeInitializedLvals` at the +/// between this data and the data from `MaybeInitializedPlaces` at the /// corresponding control-flow point. /// /// Similarly, at a given `drop` statement, the set-intersection -/// between this data and `MaybeInitializedLvals` yields the set of -/// l-values that would require a dynamic drop-flag at that statement. -pub struct MaybeUninitializedLvals<'a, 'gcx: 'tcx, 'tcx: 'a> { +/// between this data and `MaybeInitializedPlaces` yields the set of +/// places that would require a dynamic drop-flag at that statement. +pub struct MaybeUninitializedPlaces<'a, 'gcx: 'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>, } -impl<'a, 'gcx, 'tcx> MaybeUninitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> MaybeUninitializedPlaces<'a, 'gcx, 'tcx> { pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>) -> Self { - MaybeUninitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe } + MaybeUninitializedPlaces { tcx: tcx, mir: mir, mdpe: mdpe } } } -impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MaybeUninitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, 'gcx, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } } -/// `DefinitelyInitializedLvals` tracks all l-values that are definitely +/// `DefinitelyInitializedPlaces` tracks all places that are definitely /// initialized upon reaching a particular point in the control flow /// for a function. /// /// FIXME: Note that once flow-analysis is complete, this should be -/// the set-complement of MaybeUninitializedLvals; thus we can get rid +/// the set-complement of MaybeUninitializedPlaces; thus we can get rid /// of one or the other of these two. I'm inclined to get rid of -/// MaybeUninitializedLvals, simply because the sets will tend to be +/// MaybeUninitializedPlaces, simply because the sets will tend to be /// smaller in this analysis and thus easier for humans to process /// when debugging. /// @@ -180,43 +184,43 @@ fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } /// } /// ``` /// -/// To determine whether an l-value *may* be uninitialized at a +/// To determine whether a place *may* be uninitialized at a /// particular control-flow point, one can take the set-complement /// of this data. /// /// Similarly, at a given `drop` statement, the set-difference between -/// this data and `MaybeInitializedLvals` yields the set of l-values +/// this data and `MaybeInitializedPlaces` yields the set of places /// that would require a dynamic drop-flag at that statement. -pub struct DefinitelyInitializedLvals<'a, 'gcx: 'tcx, 'tcx: 'a> { +pub struct DefinitelyInitializedPlaces<'a, 'gcx: 'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>, } -impl<'a, 'gcx, 'tcx: 'a> DefinitelyInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx: 'a> DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> { pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>) -> Self { - DefinitelyInitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe } + DefinitelyInitializedPlaces { tcx: tcx, mir: mir, mdpe: mdpe } } } -impl<'a, 'gcx, 'tcx: 'a> HasMoveData<'tcx> for DefinitelyInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx: 'a> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } } /// `MovingOutStatements` tracks the statements that perform moves out -/// of particular l-values. More precisely, it tracks whether the +/// of particular places. More precisely, it tracks whether the /// *effect* of such moves (namely, the uninitialization of the -/// l-value in question) can reach some point in the control-flow of +/// place in question) can reach some point in the control-flow of /// the function, or if that effect is "killed" by some intervening -/// operation reinitializing that l-value. +/// operation reinitializing that place. /// /// The resulting dataflow is a more enriched version of -/// `MaybeUninitializedLvals`. Both structures on their own only tell -/// you if an l-value *might* be uninitialized at a given point in the +/// `MaybeUninitializedPlaces`. Both structures on their own only tell +/// you if a place *might* be uninitialized at a given point in the /// control flow. But `MovingOutStatements` also includes the added /// data of *which* particular statement causing the deinitialization /// that the borrow checker's error message may need to report. @@ -241,7 +245,7 @@ impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MovingOutStatements<'a, 'gcx, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } } -/// `EverInitializedLvals` tracks all l-values that might have ever been +/// `EverInitializedPlaces` tracks all places that might have ever been /// initialized upon reaching a particular point in the control flow /// for a function, without an intervening `Storage Dead`. /// @@ -270,28 +274,28 @@ fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } /// c = S; // {a, b, c, d } /// } /// ``` -pub struct EverInitializedLvals<'a, 'gcx: 'tcx, 'tcx: 'a> { +pub struct EverInitializedPlaces<'a, 'gcx: 'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>, } -impl<'a, 'gcx: 'tcx, 'tcx: 'a> EverInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx: 'tcx, 'tcx: 'a> EverInitializedPlaces<'a, 'gcx, 'tcx> { pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>) -> Self { - EverInitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe } + EverInitializedPlaces { tcx: tcx, mir: mir, mdpe: mdpe } } } -impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for EverInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'a, 'gcx, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } } -impl<'a, 'gcx, 'tcx> MaybeInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> MaybeInitializedPlaces<'a, 'gcx, 'tcx> { fn update_bits(sets: &mut BlockSets, path: MovePathIndex, state: DropFlagState) { @@ -302,7 +306,7 @@ fn update_bits(sets: &mut BlockSets, path: MovePathIndex, } } -impl<'a, 'gcx, 'tcx> MaybeUninitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> MaybeUninitializedPlaces<'a, 'gcx, 'tcx> { fn update_bits(sets: &mut BlockSets, path: MovePathIndex, state: DropFlagState) { @@ -313,7 +317,7 @@ fn update_bits(sets: &mut BlockSets, path: MovePathIndex, } } -impl<'a, 'gcx, 'tcx> DefinitelyInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> { fn update_bits(sets: &mut BlockSets, path: MovePathIndex, state: DropFlagState) { @@ -324,7 +328,7 @@ fn update_bits(sets: &mut BlockSets, path: MovePathIndex, } } -impl<'a, 'gcx, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitDenotation for MaybeInitializedPlaces<'a, 'gcx, 'tcx> { type Idx = MovePathIndex; fn name() -> &'static str { "maybe_init" } fn bits_per_block(&self) -> usize { @@ -375,7 +379,7 @@ fn propagate_call_return(&self, } } -impl<'a, 'gcx, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitDenotation for MaybeUninitializedPlaces<'a, 'gcx, 'tcx> { type Idx = MovePathIndex; fn name() -> &'static str { "maybe_uninit" } fn bits_per_block(&self) -> usize { @@ -430,7 +434,7 @@ fn propagate_call_return(&self, } } -impl<'a, 'gcx, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitDenotation for DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> { type Idx = MovePathIndex; fn name() -> &'static str { "definite_init" } fn bits_per_block(&self) -> usize { @@ -561,7 +565,7 @@ fn propagate_call_return(&self, } } -impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedPlaces<'a, 'gcx, 'tcx> { type Idx = InitIndex; fn name() -> &'static str { "ever_init" } fn bits_per_block(&self) -> usize { @@ -657,21 +661,21 @@ fn propagate_call_return(&self, } } -impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeInitializedPlaces<'a, 'gcx, 'tcx> { #[inline] fn join(&self, pred1: usize, pred2: usize) -> usize { pred1 | pred2 // "maybe" means we union effects of both preds } } -impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeUninitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeUninitializedPlaces<'a, 'gcx, 'tcx> { #[inline] fn join(&self, pred1: usize, pred2: usize) -> usize { pred1 | pred2 // "maybe" means we union effects of both preds } } -impl<'a, 'gcx, 'tcx> BitwiseOperator for DefinitelyInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitwiseOperator for DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> { #[inline] fn join(&self, pred1: usize, pred2: usize) -> usize { pred1 & pred2 // "definitely" means we intersect effects of both preds @@ -685,7 +689,7 @@ fn join(&self, pred1: usize, pred2: usize) -> usize { } } -impl<'a, 'gcx, 'tcx> BitwiseOperator for EverInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitwiseOperator for EverInitializedPlaces<'a, 'gcx, 'tcx> { #[inline] fn join(&self, pred1: usize, pred2: usize) -> usize { pred1 | pred2 // inits from both preds are in scope @@ -702,21 +706,21 @@ fn join(&self, pred1: usize, pred2: usize) -> usize { // propagating, or you start at all-ones and then use Intersect as // your merge when propagating. -impl<'a, 'gcx, 'tcx> InitialFlow for MaybeInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> InitialFlow for MaybeInitializedPlaces<'a, 'gcx, 'tcx> { #[inline] fn bottom_value() -> bool { false // bottom = uninitialized } } -impl<'a, 'gcx, 'tcx> InitialFlow for MaybeUninitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> InitialFlow for MaybeUninitializedPlaces<'a, 'gcx, 'tcx> { #[inline] fn bottom_value() -> bool { false // bottom = initialized (start_block_effect counters this at outset) } } -impl<'a, 'gcx, 'tcx> InitialFlow for DefinitelyInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> InitialFlow for DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> { #[inline] fn bottom_value() -> bool { true // bottom = initialized (start_block_effect counters this at outset) @@ -730,7 +734,7 @@ fn bottom_value() -> bool { } } -impl<'a, 'gcx, 'tcx> InitialFlow for EverInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> InitialFlow for EverInitializedPlaces<'a, 'gcx, 'tcx> { #[inline] fn bottom_value() -> bool { false // bottom = no initialized variables by default diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index b18fb7c7b9c..9c7d9b398cc 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -26,10 +26,11 @@ use std::usize; pub use self::impls::{MaybeStorageLive}; -pub use self::impls::{MaybeInitializedLvals, MaybeUninitializedLvals}; -pub use self::impls::{DefinitelyInitializedLvals, MovingOutStatements}; -pub use self::impls::EverInitializedLvals; +pub use self::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; +pub use self::impls::{DefinitelyInitializedPlaces, MovingOutStatements}; +pub use self::impls::EverInitializedPlaces; pub use self::impls::borrows::{Borrows, BorrowData}; +pub use self::impls::HaveBeenBorrowedLocals; pub(crate) use self::impls::borrows::{ActiveBorrows, Reservations, ReserveOrActivateIndex}; pub use self::at_location::{FlowAtLocation, FlowsAtLocation}; pub(crate) use self::drop_flag_effects::*; @@ -863,6 +864,14 @@ fn propagate_bits_into_graph_successors_of( self.propagate_bits_into_entry_set_for(in_out, changed, target); } } + mir::TerminatorKind::FalseUnwind { ref real_target, unwind } => { + self.propagate_bits_into_entry_set_for(in_out, changed, real_target); + if let Some(ref unwind) = unwind { + if !self.dead_unwinds.contains(&bb) { + self.propagate_bits_into_entry_set_for(in_out, changed, unwind); + } + } + } } } diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index cd36282eca0..635d99e7737 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -346,6 +346,7 @@ fn gather_terminator(&mut self, term: &Terminator<'tcx>) { TerminatorKind::Abort | TerminatorKind::GeneratorDrop | TerminatorKind::FalseEdges { .. } | + TerminatorKind::FalseUnwind { .. } | TerminatorKind::Unreachable => { } TerminatorKind::Return => { diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index bcf4662211e..7b6ebc6fba8 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -86,7 +86,7 @@ pub fn move_path_index(&self, move_data: &MoveData) -> MovePathIndex { /// It follows a tree structure. /// /// Given `struct X { m: M, n: N }` and `x: X`, moves like `drop x.m;` -/// move *out* of the l-value `x.m`. +/// move *out* of the place `x.m`. /// /// The MovePaths representing `x.m` and `x.n` are siblings (that is, /// one of them will link to the other via the `next_sibling` field, @@ -222,7 +222,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { } } -/// Tables mapping from an l-value to its MovePathIndex. +/// Tables mapping from a place to its MovePathIndex. #[derive(Debug)] pub struct MovePathLookup<'tcx> { locals: IndexVec, @@ -247,7 +247,7 @@ pub enum LookupResult { impl<'tcx> MovePathLookup<'tcx> { // Unlike the builder `fn move_path_for` below, this lookup // alternative will *not* create a MovePath on the fly for an - // unknown l-value, but will rather return the nearest available + // unknown place, but will rather return the nearest available // parent. pub fn find(&self, place: &Place<'tcx>) -> LookupResult { match *place { diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 848c2d3c811..00ab2e45995 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -17,10 +17,11 @@ use rustc::hir::def::{Def, CtorKind}; use rustc::middle::const_val::ConstVal; use rustc::ty::{self, AdtKind, VariantDef, Ty}; -use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow}; +use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability}; use rustc::ty::cast::CastKind as TyCastKind; use rustc::hir; use rustc::hir::def_id::LocalDefId; +use rustc::mir::{BorrowKind}; impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { type Output = Expr<'tcx>; @@ -111,7 +112,7 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, span, kind: ExprKind::Borrow { region: deref.region, - borrow_kind: to_borrow_kind(deref.mutbl), + borrow_kind: deref.mutbl.to_borrow_kind(), arg: expr.to_ref(), }, }; @@ -121,7 +122,7 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, Adjust::Borrow(AutoBorrow::Ref(r, m)) => { ExprKind::Borrow { region: r, - borrow_kind: to_borrow_kind(m), + borrow_kind: m.to_borrow_kind(), arg: expr.to_ref(), } } @@ -141,11 +142,43 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, span, kind: ExprKind::Borrow { region, - borrow_kind: to_borrow_kind(m), + borrow_kind: m.to_borrow_kind(), arg: expr.to_ref(), }, }; - ExprKind::Cast { source: expr.to_ref() } + let cast_expr = Expr { + temp_lifetime, + ty: adjustment.target, + span, + kind: ExprKind::Cast { source: expr.to_ref() } + }; + + // To ensure that both implicit and explicit coercions are + // handled the same way, we insert an extra layer of indirection here. + // For explicit casts (e.g. 'foo as *const T'), the source of the 'Use' + // will be an ExprKind::Hair with the appropriate cast expression. Here, + // we make our Use source the generated Cast from the original coercion. + // + // In both cases, this outer 'Use' ensures that the inner 'Cast' is handled by + // as_operand, not by as_rvalue - causing the cast result to be stored in a temporary. + // Ordinary, this is identical to using the cast directly as an rvalue. However, if the + // source of the cast was previously borrowed as mutable, storing the cast in a + // temporary gives the source a chance to expire before the cast is used. For + // structs with a self-referential *mut ptr, this allows assignment to work as + // expected. + // + // For example, consider the type 'struct Foo { field: *mut Foo }', + // The method 'fn bar(&mut self) { self.field = self }' + // triggers a coercion from '&mut self' to '*mut self'. In order + // for the assignment to be valid, the implicit borrow + // of 'self' involved in the coercion needs to end before the local + // containing the '*mut T' is assigned to 'self.field' - otherwise, + // we end up trying to assign to 'self.field' while we have another mutable borrow + // active. + // + // We only need to worry about this kind of thing for coercions from refs to ptrs, + // since they get rid of a borrow implicitly. + ExprKind::Use { source: cast_expr.to_ref() } } Adjust::Unsize => { ExprKind::Unsize { source: expr.to_ref() } @@ -255,7 +288,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }; ExprKind::Borrow { region, - borrow_kind: to_borrow_kind(mutbl), + borrow_kind: mutbl.to_borrow_kind(), arg: expr.to_ref(), } } @@ -610,10 +643,25 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } } -fn to_borrow_kind(m: hir::Mutability) -> BorrowKind { - match m { - hir::MutMutable => BorrowKind::Mut, - hir::MutImmutable => BorrowKind::Shared, +trait ToBorrowKind { fn to_borrow_kind(&self) -> BorrowKind; } + +impl ToBorrowKind for AutoBorrowMutability { + fn to_borrow_kind(&self) -> BorrowKind { + match *self { + AutoBorrowMutability::Mutable { allow_two_phase_borrow } => + BorrowKind::Mut { allow_two_phase_borrow }, + AutoBorrowMutability::Immutable => + BorrowKind::Shared, + } + } +} + +impl ToBorrowKind for hir::Mutability { + fn to_borrow_kind(&self) -> BorrowKind { + match *self { + hir::MutMutable => BorrowKind::Mut { allow_two_phase_borrow: false }, + hir::MutImmutable => BorrowKind::Shared, + } } } @@ -915,7 +963,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, let borrow_kind = match upvar_borrow.kind { ty::BorrowKind::ImmBorrow => BorrowKind::Shared, ty::BorrowKind::UniqueImmBorrow => BorrowKind::Unique, - ty::BorrowKind::MutBorrow => BorrowKind::Mut, + ty::BorrowKind::MutBorrow => BorrowKind::Mut { allow_two_phase_borrow: false } }; Expr { temp_lifetime, diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs index 2913f72460e..d3b084fde6a 100644 --- a/src/librustc_mir/interpret/const_eval.rs +++ b/src/librustc_mir/interpret/const_eval.rs @@ -243,6 +243,12 @@ fn call_intrinsic<'a>( ecx.write_primval(dest, PrimVal::from_u128(size), dest_layout.ty)?; } + "type_id" => { + let ty = substs.type_at(0); + let type_id = ecx.tcx.type_id_hash(ty) as u128; + ecx.write_primval(dest, PrimVal::from_u128(type_id), dest_layout.ty)?; + } + name => return Err(ConstEvalError::NeedsRfc(format!("calling intrinsic `{}`", name)).into()), } diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index baec0fea50f..52b87282180 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -172,7 +172,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> LayoutOf> for &'a EvalContext<'a, 'tcx type TyLayout = EvalResult<'tcx, TyLayout<'tcx>>; fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout { - (self.tcx, self.param_env).layout_of(ty) + self.tcx.layout_of(self.param_env.and(ty)) .map_err(|layout| EvalErrorKind::Layout(layout).into()) } } @@ -716,6 +716,10 @@ pub(super) fn eval_rvalue_into_place( ReifyFnPointer => { match self.eval_operand(operand)?.ty.sty { ty::TyFnDef(def_id, substs) => { + if self.tcx.has_attr(def_id, "rustc_args_required_const") { + bug!("reifying a fn ptr that requires \ + const arguments"); + } let instance = self.resolve(def_id, substs)?; let fn_ptr = self.memory.create_fn_alloc(instance); let valty = ValTy { diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index c2c6b23c083..701b7a07ac9 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -9,9 +9,9 @@ #[derive(Copy, Clone, Debug)] pub enum Place { - /// An place referring to a value allocated in the `Memory` system. + /// A place referring to a value allocated in the `Memory` system. Ptr { - /// An place may have an invalid (integral or undef) pointer, + /// A place may have an invalid (integral or undef) pointer, /// since it might be turned back into a reference /// before ever being dereferenced. ptr: Pointer, @@ -19,7 +19,7 @@ pub enum Place { extra: PlaceExtra, }, - /// An place referring to a value on the stack. Represented by a stack frame index paired with + /// A place referring to a value on the stack. Represented by a stack frame index paired with /// a Mir local index. Local { frame: usize, local: mir::Local }, } @@ -33,7 +33,7 @@ pub enum PlaceExtra { } impl<'tcx> Place { - /// Produces an Place that will error if attempted to be read from + /// Produces a Place that will error if attempted to be read from pub fn undef() -> Self { Self::from_primval_ptr(PrimVal::Undef.into(), Align::from_bytes(1, 1).unwrap()) } diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs index c8a0dbdd903..606bda51edb 100644 --- a/src/librustc_mir/interpret/terminator/mod.rs +++ b/src/librustc_mir/interpret/terminator/mod.rs @@ -165,6 +165,7 @@ pub(super) fn eval_terminator( Resume => unimplemented!(), Abort => unimplemented!(), FalseEdges { .. } => bug!("should have been eliminated by `simplify_branches` mir pass"), + FalseUnwind { .. } => bug!("should have been eliminated by `simplify_branches` mir pass"), Unreachable => return err!(Unreachable), } diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index f16187797d4..a80dfaef0da 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -636,7 +636,8 @@ fn visit_terminator_kind(&mut self, mir::TerminatorKind::Assert { .. } => {} mir::TerminatorKind::GeneratorDrop | mir::TerminatorKind::Yield { .. } | - mir::TerminatorKind::FalseEdges { .. } => bug!(), + mir::TerminatorKind::FalseEdges { .. } | + mir::TerminatorKind::FalseUnwind { .. } => bug!(), } self.super_terminator_kind(block, kind, location); diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index 806d787c845..e9471cdb4f9 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -107,6 +107,7 @@ use rustc::hir::def_id::DefId; use rustc::hir::map::DefPathData; use rustc::mir::mono::{Linkage, Visibility}; +use rustc::middle::exported_symbols::SymbolExportLevel; use rustc::ty::{self, TyCtxt, InstanceDef}; use rustc::ty::item_path::characteristic_def_id_of_type; use rustc::util::nodemap::{FxHashMap, FxHashSet}; @@ -322,7 +323,16 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .or_insert_with(make_codegen_unit); let mut can_be_internalized = true; - let (linkage, visibility) = match trans_item.explicit_linkage(tcx) { + let default_visibility = |id: DefId| { + if tcx.sess.target.target.options.default_hidden_visibility && + tcx.symbol_export_level(id) != SymbolExportLevel::C + { + Visibility::Hidden + } else { + Visibility::Default + } + }; + let (linkage, mut visibility) = match trans_item.explicit_linkage(tcx) { Some(explicit_linkage) => (explicit_linkage, Visibility::Default), None => { match trans_item { @@ -352,7 +362,8 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Visibility::Hidden } else if def_id.is_local() { if tcx.is_exported_symbol(def_id) { - Visibility::Default + can_be_internalized = false; + default_visibility(def_id) } else { Visibility::Hidden } @@ -375,7 +386,8 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, MonoItem::GlobalAsm(node_id) => { let def_id = tcx.hir.local_def_id(node_id); let visibility = if tcx.is_exported_symbol(def_id) { - Visibility::Default + can_be_internalized = false; + default_visibility(def_id) } else { Visibility::Hidden }; diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index c206d0ea9b5..e6ebdd3d6c1 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -294,22 +294,25 @@ fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { debug!("build_clone_shim(def_id={:?})", def_id); - let mut builder = CloneShimBuilder::new(tcx, def_id); + let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty); let is_copy = !self_ty.moves_by_default(tcx, tcx.param_env(def_id), builder.span); + let dest = Place::Local(RETURN_PLACE); + let src = Place::Local(Local::new(1+0)).deref(); + match self_ty.sty { _ if is_copy => builder.copy_shim(), ty::TyArray(ty, len) => { let len = len.val.to_const_int().unwrap().to_u64().unwrap(); - builder.array_shim(ty, len) + builder.array_shim(dest, src, ty, len) } ty::TyClosure(def_id, substs) => { builder.tuple_like_shim( - &substs.upvar_tys(def_id, tcx).collect::>(), - AggregateKind::Closure(def_id, substs) + dest, src, + substs.upvar_tys(def_id, tcx) ) } - ty::TyTuple(tys, _) => builder.tuple_like_shim(&**tys, AggregateKind::Tuple), + ty::TyTuple(tys, _) => builder.tuple_like_shim(dest, src, tys.iter().cloned()), _ => { bug!("clone shim for `{:?}` which is not `Copy` and is not an aggregate", self_ty) } @@ -328,8 +331,14 @@ struct CloneShimBuilder<'a, 'tcx: 'a> { } impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { - fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Self { - let sig = tcx.fn_sig(def_id); + fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, + self_ty: Ty<'tcx>) -> Self { + // we must subst the self_ty because it's + // otherwise going to be TySelf and we can't index + // or access fields of a Place of type TySelf. + let substs = tcx.mk_substs_trait(self_ty, &[]); + 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); @@ -377,6 +386,14 @@ fn block( }) } + /// Gives the index of an upcoming BasicBlock, with an offset. + /// offset=0 will give you the index of the next BasicBlock, + /// offset=1 will give the index of the next-to-next block, + /// offset=-1 will give you the index of the last-created block + fn block_index_offset(&mut self, offset: usize) -> BasicBlock { + BasicBlock::new(self.blocks.len() + offset) + } + fn make_statement(&self, kind: StatementKind<'tcx>) -> Statement<'tcx> { Statement { source_info: self.source_info(), @@ -404,11 +421,12 @@ fn make_place(&mut self, mutability: Mutability, ty: Ty<'tcx>) -> Place<'tcx> { fn make_clone_call( &mut self, + dest: Place<'tcx>, + src: Place<'tcx>, ty: Ty<'tcx>, - rcvr_field: Place<'tcx>, next: BasicBlock, cleanup: BasicBlock - ) -> Place<'tcx> { + ) { let tcx = self.tcx; let substs = Substs::for_item( @@ -439,13 +457,11 @@ fn make_clone_call( }) ); - let loc = self.make_place(Mutability::Not, ty); - - // `let ref_loc: &ty = &rcvr_field;` + // `let ref_loc: &ty = &src;` let statement = self.make_statement( StatementKind::Assign( ref_loc.clone(), - Rvalue::Ref(tcx.types.re_erased, BorrowKind::Shared, rcvr_field) + Rvalue::Ref(tcx.types.re_erased, BorrowKind::Shared, src) ) ); @@ -453,11 +469,9 @@ fn make_clone_call( self.block(vec![statement], TerminatorKind::Call { func, args: vec![Operand::Move(ref_loc)], - destination: Some((loc.clone(), next)), + destination: Some((dest, next)), cleanup: Some(cleanup), }, false); - - loc } fn loop_header( @@ -500,14 +514,12 @@ fn make_usize(&self, value: u64) -> Box> { } } - fn array_shim(&mut self, ty: Ty<'tcx>, len: u64) { + fn array_shim(&mut self, dest: Place<'tcx>, src: Place<'tcx>, ty: Ty<'tcx>, len: u64) { let tcx = self.tcx; let span = self.span; - let rcvr = Place::Local(Local::new(1+0)).deref(); let beg = self.local_decls.push(temp_decl(Mutability::Mut, tcx.types.usize, span)); let end = self.make_place(Mutability::Not, tcx.types.usize); - let ret = self.make_place(Mutability::Mut, tcx.mk_array(ty, len)); // BB #0 // `let mut beg = 0;` @@ -537,23 +549,17 @@ fn array_shim(&mut self, ty: Ty<'tcx>, len: u64) { self.loop_header(Place::Local(beg), end, BasicBlock::new(2), BasicBlock::new(4), false); // BB #2 - // `let cloned = Clone::clone(rcvr[beg])`; + // `dest[i] = Clone::clone(src[beg])`; // Goto #3 if ok, #5 if unwinding happens. - let rcvr_field = rcvr.clone().index(beg); - let cloned = self.make_clone_call(ty, rcvr_field, BasicBlock::new(3), BasicBlock::new(5)); + let dest_field = dest.clone().index(beg); + let src_field = src.clone().index(beg); + self.make_clone_call(dest_field, src_field, ty, BasicBlock::new(3), + BasicBlock::new(5)); // BB #3 - // `ret[beg] = cloned;` // `beg = beg + 1;` // `goto #1`; - let ret_field = ret.clone().index(beg); let statements = vec![ - self.make_statement( - StatementKind::Assign( - ret_field, - Rvalue::Use(Operand::Move(cloned)) - ) - ), self.make_statement( StatementKind::Assign( Place::Local(beg), @@ -568,14 +574,8 @@ fn array_shim(&mut self, ty: Ty<'tcx>, len: u64) { self.block(statements, TerminatorKind::Goto { target: BasicBlock::new(1) }, false); // BB #4 - // `return ret;` - let ret_statement = self.make_statement( - StatementKind::Assign( - Place::Local(RETURN_PLACE), - Rvalue::Use(Operand::Move(ret.clone())), - ) - ); - self.block(vec![ret_statement], TerminatorKind::Return, false); + // `return dest;` + self.block(vec![], TerminatorKind::Return, false); // BB #5 (cleanup) // `let end = beg;` @@ -600,9 +600,9 @@ fn array_shim(&mut self, ty: Ty<'tcx>, len: u64) { BasicBlock::new(7), BasicBlock::new(9), true); // BB #7 (cleanup) - // `drop(ret[beg])`; + // `drop(dest[beg])`; self.block(vec![], TerminatorKind::Drop { - location: ret.index(beg), + location: dest.index(beg), target: BasicBlock::new(8), unwind: None, }, true); @@ -626,55 +626,50 @@ fn array_shim(&mut self, ty: Ty<'tcx>, len: u64) { self.block(vec![], TerminatorKind::Resume, true); } - fn tuple_like_shim(&mut self, tys: &[ty::Ty<'tcx>], kind: AggregateKind<'tcx>) { - match kind { - AggregateKind::Tuple | AggregateKind::Closure(..) => (), - _ => bug!("only tuples and closures are accepted"), - }; + fn tuple_like_shim(&mut self, dest: Place<'tcx>, + src: Place<'tcx>, tys: I) + where I: Iterator> { + let mut previous_field = None; + for (i, ity) in tys.enumerate() { + let field = Field::new(i); + let src_field = src.clone().field(field, ity); - let rcvr = Place::Local(Local::new(1+0)).deref(); + let dest_field = dest.clone().field(field, ity); - let mut returns = Vec::new(); - for (i, ity) in tys.iter().enumerate() { - let rcvr_field = rcvr.clone().field(Field::new(i), *ity); + // #(2i + 1) is the cleanup block for the previous clone operation + let cleanup_block = self.block_index_offset(1); + // #(2i + 2) is the next cloning block + // (or the Return terminator if this is the last block) + let next_block = self.block_index_offset(2); // BB #(2i) - // `returns[i] = Clone::clone(&rcvr.i);` + // `dest.i = Clone::clone(&src.i);` // Goto #(2i + 2) if ok, #(2i + 1) if unwinding happens. - returns.push( - self.make_clone_call( - *ity, - rcvr_field, - BasicBlock::new(2 * i + 2), - BasicBlock::new(2 * i + 1), - ) + self.make_clone_call( + dest_field.clone(), + src_field, + ity, + next_block, + cleanup_block, ); // BB #(2i + 1) (cleanup) - if i == 0 { - // Nothing to drop, just resume. - self.block(vec![], TerminatorKind::Resume, true); - } else { + if let Some((previous_field, previous_cleanup)) = previous_field.take() { // Drop previous field and goto previous cleanup block. self.block(vec![], TerminatorKind::Drop { - location: returns[i - 1].clone(), - target: BasicBlock::new(2 * i - 1), + location: previous_field, + target: previous_cleanup, unwind: None, }, true); + } else { + // Nothing to drop, just resume. + self.block(vec![], TerminatorKind::Resume, true); } + + previous_field = Some((dest_field, cleanup_block)); } - // `return kind(returns[0], returns[1], ..., returns[tys.len() - 1]);` - let ret_statement = self.make_statement( - StatementKind::Assign( - Place::Local(RETURN_PLACE), - Rvalue::Aggregate( - box kind, - returns.into_iter().map(Operand::Move).collect() - ) - ) - ); - self.block(vec![ret_statement], TerminatorKind::Return, false); + self.block(vec![], TerminatorKind::Return, false); } } @@ -721,11 +716,14 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }), span )); + let borrow_kind = BorrowKind::Mut { + allow_two_phase_borrow: false, + }; statements.push(Statement { source_info, kind: StatementKind::Assign( Place::Local(ref_rcvr), - Rvalue::Ref(tcx.types.re_erased, BorrowKind::Mut, rcvr_l) + Rvalue::Ref(tcx.types.re_erased, borrow_kind, rcvr_l) ) }); Operand::Move(Place::Local(ref_rcvr)) diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index ae27f54e618..bbc7803b84d 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -76,7 +76,8 @@ fn visit_terminator(&mut self, TerminatorKind::Abort | TerminatorKind::Return | TerminatorKind::Unreachable | - TerminatorKind::FalseEdges { .. } => { + TerminatorKind::FalseEdges { .. } | + TerminatorKind::FalseUnwind { .. } => { // safe (at least as emitted during MIR construction) } diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 106bc39d0fc..9eca343cb5e 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -9,7 +9,7 @@ // except according to those terms. use dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex, LookupResult}; -use dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; +use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; 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}; @@ -60,11 +60,11 @@ fn run_pass<'a, 'tcx>(&self, let dead_unwinds = find_dead_unwinds(tcx, mir, id, &env); let flow_inits = do_dataflow(tcx, mir, id, &[], &dead_unwinds, - MaybeInitializedLvals::new(tcx, mir, &env), + MaybeInitializedPlaces::new(tcx, mir, &env), |bd, p| DebugFormatted::new(&bd.move_data().move_paths[p])); let flow_uninits = do_dataflow(tcx, mir, id, &[], &dead_unwinds, - MaybeUninitializedLvals::new(tcx, mir, &env), + MaybeUninitializedPlaces::new(tcx, mir, &env), |bd, p| DebugFormatted::new(&bd.move_data().move_paths[p])); ElaborateDropsCtxt { @@ -97,7 +97,7 @@ fn find_dead_unwinds<'a, 'tcx>( let mut dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); let flow_inits = do_dataflow(tcx, mir, id, &[], &dead_unwinds, - MaybeInitializedLvals::new(tcx, mir, &env), + MaybeInitializedPlaces::new(tcx, mir, &env), |bd, p| DebugFormatted::new(&bd.move_data().move_paths[p])); for (bb, bb_data) in mir.basic_blocks().iter_enumerated() { let location = match bb_data.terminator().kind { @@ -300,8 +300,8 @@ struct ElaborateDropsCtxt<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>, env: &'a MoveDataParamEnv<'tcx, 'tcx>, - flow_inits: DataflowResults>, - flow_uninits: DataflowResults>, + flow_inits: DataflowResults>, + flow_uninits: DataflowResults>, drop_flags: FxHashMap, patch: MirPatch<'tcx>, } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index ebd34f81deb..812665f5fa4 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -78,7 +78,8 @@ use transform::{MirPass, MirSource}; use transform::simplify; use transform::no_landing_pads::no_landing_pads; -use dataflow::{do_dataflow, DebugFormatted, MaybeStorageLive, state_for_location}; +use dataflow::{do_dataflow, DebugFormatted, state_for_location}; +use dataflow::{MaybeStorageLive, HaveBeenBorrowedLocals}; pub struct StateTransform; @@ -369,17 +370,33 @@ fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, HashMap) { let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); let node_id = tcx.hir.as_local_node_id(source.def_id).unwrap(); - let analysis = MaybeStorageLive::new(mir); + + // Calculate when MIR locals have live storage. This gives us an upper bound of their + // lifetimes. + let storage_live_analysis = MaybeStorageLive::new(mir); let storage_live = - do_dataflow(tcx, mir, node_id, &[], &dead_unwinds, analysis, + do_dataflow(tcx, mir, node_id, &[], &dead_unwinds, storage_live_analysis, |bd, p| DebugFormatted::new(&bd.mir().local_decls[p])); + // Find the MIR locals which do not use StorageLive/StorageDead statements. + // The storage of these locals are always live. let mut ignored = StorageIgnored(IdxSetBuf::new_filled(mir.local_decls.len())); ignored.visit_mir(mir); - let mut borrowed_locals = BorrowedLocals(IdxSetBuf::new_empty(mir.local_decls.len())); - borrowed_locals.visit_mir(mir); + // Calculate the MIR locals which have been previously + // borrowed (even if they are still active). + // This is only used for immovable generators. + let borrowed_locals = if !movable { + let analysis = HaveBeenBorrowedLocals::new(mir); + let result = + do_dataflow(tcx, mir, node_id, &[], &dead_unwinds, analysis, + |bd, p| DebugFormatted::new(&bd.mir().local_decls[p])); + Some((analysis, result)) + } else { + None + }; + // Calculate the liveness of MIR locals ignoring borrows. let mut set = liveness::LocalSet::new_empty(mir.local_decls.len()); let mut liveness = liveness::liveness_of_locals(mir, LivenessMode { include_regular_use: true, @@ -396,24 +413,41 @@ fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, statement_index: data.statements.len(), }; - let storage_liveness = state_for_location(loc, &analysis, &storage_live, mir); + if let Some((ref analysis, ref result)) = borrowed_locals { + let borrowed_locals = state_for_location(loc, + analysis, + result, + mir); + // The `liveness` variable contains the liveness of MIR locals ignoring borrows. + // This is correct for movable generators since borrows cannot live across + // suspension points. However for immovable generators we need to account for + // borrows, so we conseratively assume that all borrowed locals live forever. + // To do this we just union our `liveness` result with `borrowed_locals`, which + // contains all the locals which has been borrowed before this suspension point. + // If a borrow is converted to a raw reference, we must also assume that it lives + // forever. Note that the final liveness is still bounded by the storage liveness + // of the local, which happens using the `intersect` operation below. + liveness.outs[block].union(&borrowed_locals); + } + + let mut storage_liveness = state_for_location(loc, + &storage_live_analysis, + &storage_live, + mir); + // Store the storage liveness for later use so we can restore the state + // after a suspension point storage_liveness_map.insert(block, storage_liveness.clone()); - let mut live_locals = storage_liveness; - // Mark locals without storage statements as always having live storage - live_locals.union(&ignored.0); + storage_liveness.union(&ignored.0); - if !movable { - // For immovable generators we consider borrowed locals to always be live. - // This effectively makes those locals use just the storage liveness. - liveness.outs[block].union(&borrowed_locals.0); - } + // Locals live are live at this point only if they are used across + // suspension points (the `liveness` variable) + // and their storage is live (the `storage_liveness` variable) + storage_liveness.intersect(&liveness.outs[block]); - // Locals live are live at this point only if they are used across suspension points - // and their storage is live - live_locals.intersect(&liveness.outs[block]); + let live_locals = storage_liveness; // Add the locals life at this suspension point to the set of locals which live across // any suspension points diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 43ee75d1e2b..08a9757fb32 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -19,7 +19,6 @@ use rustc::mir::*; use rustc::mir::visit::*; use rustc::ty::{self, Instance, Ty, TyCtxt, TypeFoldable}; -use rustc::ty::layout::LayoutOf; use rustc::ty::subst::{Subst,Substs}; use std::collections::VecDeque; @@ -427,7 +426,7 @@ fn dest_needs_borrow(place: &Place) -> bool { debug!("Creating temp for return destination"); let dest = Rvalue::Ref( self.tcx.types.re_erased, - BorrowKind::Mut, + BorrowKind::Mut { allow_two_phase_borrow: false }, destination.0); let ty = dest.ty(caller_mir, self.tcx); @@ -512,7 +511,7 @@ fn cast_box_free_arg(&self, arg: Place<'tcx>, ptr_ty: Ty<'tcx>, callsite: &CallSite<'tcx>, caller_mir: &mut Mir<'tcx>) -> Local { let arg = Rvalue::Ref( self.tcx.types.re_erased, - BorrowKind::Mut, + BorrowKind::Mut { allow_two_phase_borrow: false }, arg.deref()); let ty = arg.ty(caller_mir, self.tcx); @@ -655,7 +654,7 @@ fn create_temp_if_necessary( fn type_size_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> Option { - (tcx, param_env).layout_of(ty).ok().map(|layout| layout.size.bytes()) + tcx.layout_of(param_env.and(ty)).ok().map(|layout| layout.size.bytes()) } fn subst_and_normalize<'a, 'tcx: 'a>( @@ -814,6 +813,9 @@ fn visit_terminator_kind(&mut self, block: BasicBlock, *target = self.update_target(*target); } } + TerminatorKind::FalseUnwind { real_target: _ , unwind: _ } => + // see the ordering of passes in the optimized_mir query. + bug!("False unwinds should have been removed before inlining") } } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 1545040f2da..b732eeb624c 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -71,9 +71,12 @@ pub enum Candidate { /// Borrow of a constant temporary. Ref(Location), - /// Array of indices found in the third argument of - /// a call to one of the simd_shuffleN intrinsics. - ShuffleIndices(BasicBlock) + /// Currently applied to function calls where the callee has the unstable + /// `#[rustc_args_required_const]` attribute as well as the SIMD shuffle + /// intrinsic. The intrinsic requires the arguments are indeed constant and + /// the attribute currently provides the semantic requirement that arguments + /// must be constant. + Argument { bb: BasicBlock, index: usize }, } struct TempCollector<'tcx> { @@ -303,10 +306,10 @@ fn promote_candidate(mut self, candidate: Candidate) { _ => bug!() } } - Candidate::ShuffleIndices(bb) => { + Candidate::Argument { bb, index } => { match self.source[bb].terminator_mut().kind { TerminatorKind::Call { ref mut args, .. } => { - Rvalue::Use(mem::replace(&mut args[2], new_operand)) + Rvalue::Use(mem::replace(&mut args[index], new_operand)) } _ => bug!() } @@ -359,15 +362,15 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>, } (statement.source_info.span, dest.ty(mir, tcx).to_ty(tcx)) } - Candidate::ShuffleIndices(bb) => { + Candidate::Argument { bb, index } => { let terminator = mir[bb].terminator(); let ty = match terminator.kind { TerminatorKind::Call { ref args, .. } => { - args[2].ty(mir, tcx) + args[index].ty(mir, tcx) } _ => { span_bug!(terminator.source_info.span, - "expected simd_shuffleN call to promote"); + "expected call argument to promote"); } }; (terminator.source_info.span, ty) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index b896e6ca853..2b9ee223b01 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -17,6 +17,7 @@ use rustc_data_structures::bitvec::BitVector; use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; +use rustc_data_structures::fx::FxHashSet; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::middle::const_val::ConstVal; @@ -30,6 +31,7 @@ use rustc::middle::lang_items; use syntax::abi::Abi; use syntax::attr; +use syntax::ast::LitKind; use syntax::feature_gate::UnstableFeatures; use syntax_pos::{Span, DUMMY_SP}; @@ -168,8 +170,20 @@ fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn not_const(&mut self) { self.add(Qualif::NOT_CONST); if self.mode != Mode::Fn { - span_err!(self.tcx.sess, self.span, E0019, - "{} contains unimplemented expression type", self.mode); + let mut err = struct_span_err!( + self.tcx.sess, + self.span, + E0019, + "{} contains unimplemented expression type", + self.mode + ); + if self.tcx.sess.teach(&err.get_code().unwrap()) { + err.note("A function call isn't allowed in the const's initialization expression \ + because the expression's value must be known at compile-time."); + err.note("Remember: you can't use a function call inside a const's initialization \ + expression! However, you can use it anywhere else."); + } + err.emit(); } } @@ -177,9 +191,19 @@ fn not_const(&mut self) { fn statement_like(&mut self) { self.add(Qualif::NOT_CONST); if self.mode != Mode::Fn { - span_err!(self.tcx.sess, self.span, E0016, - "blocks in {}s are limited to items and tail expressions", - self.mode); + let mut err = struct_span_err!( + self.tcx.sess, + self.span, + E0016, + "blocks in {}s are limited to items and tail expressions", + self.mode + ); + if self.tcx.sess.teach(&err.get_code().unwrap()) { + err.note("Blocks in constants may only contain items (such as constant, function \ + definition, etc...) and a tail expression."); + err.help("To avoid it, you have to replace the non-item object."); + } + err.emit(); } } @@ -327,7 +351,8 @@ fn qualify_const(&mut self) -> (Qualif, Rc>) { TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } | TerminatorKind::Unreachable | - TerminatorKind::FalseEdges { .. } => None, + TerminatorKind::FalseEdges { .. } | + TerminatorKind::FalseUnwind { .. } => None, TerminatorKind::Return => { // Check for unused values. This usually means @@ -407,7 +432,7 @@ fn qualify_const(&mut self) -> (Qualif, Rc>) { _ => {} } } - Candidate::ShuffleIndices(_) => {} + Candidate::Argument { .. } => {} } } @@ -472,9 +497,19 @@ fn visit_place(&mut self, } if self.mode == Mode::Const || self.mode == Mode::ConstFn { - span_err!(self.tcx.sess, self.span, E0013, - "{}s cannot refer to statics, use \ - a constant instead", self.mode); + let mut err = struct_span_err!(self.tcx.sess, self.span, E0013, + "{}s cannot refer to statics, use \ + a constant instead", self.mode); + if self.tcx.sess.teach(&err.get_code().unwrap()) { + err.note( + "Static and const variables can refer to other const variables. But a \ + const variable cannot refer to a static variable." + ); + err.help( + "To fix this, the value can be extracted as a const and then used." + ); + } + err.emit() } } Place::Projection(ref proj) => { @@ -495,13 +530,25 @@ fn visit_place(&mut self, if let ty::TyRawPtr(_) = base_ty.sty { this.add(Qualif::NOT_CONST); if this.mode != Mode::Fn { - struct_span_err!(this.tcx.sess, - this.span, E0396, + let mut err = struct_span_err!( + this.tcx.sess, + this.span, + E0396, "raw pointers cannot be dereferenced in {}s", - this.mode) - .span_label(this.span, - "dereference of raw pointer in constant") - .emit(); + this.mode + ); + err.span_label(this.span, + "dereference of raw pointer in constant"); + if this.tcx.sess.teach(&err.get_code().unwrap()) { + err.note( + "The value behind a raw pointer can't be determined \ + at compile-time (or even link-time), which means it \ + can't be used in a constant expression." + ); + err.help("A possible fix is to dereference your pointer \ + at some point in run-time."); + } + err.emit(); } } } @@ -600,7 +647,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { } let ty = place.ty(self.mir, self.tcx).to_ty(self.tcx); - if kind == BorrowKind::Mut { + if let BorrowKind::Mut { .. } = kind { // In theory, any zero-sized value could be borrowed // mutably without consequences. However, only &mut [] // is allowed right now, and only in functions. @@ -620,12 +667,22 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { if !allow { self.add(Qualif::NOT_CONST); if self.mode != Mode::Fn { - struct_span_err!(self.tcx.sess, self.span, E0017, - "references in {}s may only refer \ - to immutable values", self.mode) - .span_label(self.span, format!("{}s require immutable values", - self.mode)) - .emit(); + let mut err = struct_span_err!(self.tcx.sess, self.span, E0017, + "references in {}s may only refer \ + to immutable values", self.mode); + err.span_label(self.span, format!("{}s require immutable values", + self.mode)); + if self.tcx.sess.teach(&err.get_code().unwrap()) { + err.note("References in statics and constants may only refer to \ + immutable values.\n\n\ + Statics are shared everywhere, and if they refer to \ + mutable data one might violate memory safety since \ + holding multiple mutable references to shared data is \ + not allowed.\n\n\ + If you really want global mutable state, try using \ + static mut or a global UnsafeCell."); + } + err.emit(); } } } else { @@ -666,9 +723,42 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { (CastTy::FnPtr, CastTy::Int(_)) => { self.add(Qualif::NOT_CONST); if self.mode != Mode::Fn { - span_err!(self.tcx.sess, self.span, E0018, - "raw pointers cannot be cast to integers in {}s", - self.mode); + let mut err = struct_span_err!( + self.tcx.sess, + self.span, + E0018, + "raw pointers cannot be cast to integers in {}s", + self.mode + ); + if self.tcx.sess.teach(&err.get_code().unwrap()) { + err.note("\ +The value of static and constant integers must be known at compile time. You can't cast a pointer \ +to an integer because the address of a pointer can vary. + +For example, if you write: + +``` +static MY_STATIC: u32 = 42; +static MY_STATIC_ADDR: usize = &MY_STATIC as *const _ as usize; +static WHAT: usize = (MY_STATIC_ADDR^17) + MY_STATIC_ADDR; +``` + +Then `MY_STATIC_ADDR` would contain the address of `MY_STATIC`. However, the address can change \ +when the program is linked, as well as change between different executions due to ASLR, and many \ +linkers would not be able to calculate the value of `WHAT`. + +On the other hand, static and constant pointers can point either to a known numeric address or to \ +the address of a symbol. + +``` +static MY_STATIC: u32 = 42; +static MY_STATIC_ADDR: &'static u32 = &MY_STATIC; +const CONST_ADDR: *const u8 = 0x5f3759df as *const u8; +``` + +This does not pose a problem by itself because they can't be accessed directly."); + } + err.emit(); } } _ => {} @@ -699,10 +789,18 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { Rvalue::NullaryOp(NullOp::Box, _) => { self.add(Qualif::NOT_CONST); if self.mode != Mode::Fn { - struct_span_err!(self.tcx.sess, self.span, E0010, - "allocations are not allowed in {}s", self.mode) - .span_label(self.span, format!("allocation not allowed in {}s", self.mode)) - .emit(); + let mut err = struct_span_err!(self.tcx.sess, self.span, E0010, + "allocations are not allowed in {}s", self.mode); + err.span_label(self.span, format!("allocation not allowed in {}s", self.mode)); + if self.tcx.sess.teach(&err.get_code().unwrap()) { + err.note( + "The value of statics and constants must be known at compile time, \ + and they live for the entire lifetime of a program. Creating a boxed \ + value allocates memory on the heap at runtime, and therefore cannot \ + be done at compile time." + ); + } + err.emit(); } } @@ -730,14 +828,16 @@ fn visit_terminator_kind(&mut self, self.visit_operand(func, location); let fn_ty = func.ty(self.mir, self.tcx); + let mut callee_def_id = None; let (mut is_shuffle, mut is_const_fn) = (false, None); if let ty::TyFnDef(def_id, _) = fn_ty.sty { + callee_def_id = Some(def_id); match self.tcx.fn_sig(def_id).abi() { Abi::RustIntrinsic | Abi::PlatformIntrinsic => { assert!(!self.tcx.is_const_fn(def_id)); match &self.tcx.item_name(def_id)[..] { - "size_of" | "min_align_of" => is_const_fn = Some(def_id), + "size_of" | "min_align_of" | "type_id" => is_const_fn = Some(def_id), name if name.starts_with("simd_shuffle") => { is_shuffle = true; @@ -754,17 +854,39 @@ fn visit_terminator_kind(&mut self, } } + let constant_arguments = callee_def_id.and_then(|id| { + args_required_const(self.tcx, id) + }); for (i, arg) in args.iter().enumerate() { self.nest(|this| { this.visit_operand(arg, location); - if is_shuffle && i == 2 && this.mode == Mode::Fn { - let candidate = Candidate::ShuffleIndices(bb); + if this.mode != Mode::Fn { + return + } + let candidate = Candidate::Argument { bb, index: i }; + if is_shuffle && i == 2 { if this.can_promote() { this.promotion_candidates.push(candidate); } else { span_err!(this.tcx.sess, this.span, E0526, "shuffle indices are not constant"); } + return + } + + let constant_arguments = match constant_arguments.as_ref() { + Some(s) => s, + None => return, + }; + if !constant_arguments.contains(&i) { + return + } + if this.can_promote() { + this.promotion_candidates.push(candidate); + } else { + this.tcx.sess.span_err(this.span, + &format!("argument {} is required to be a constant", + i + 1)); } }); } @@ -904,9 +1026,22 @@ fn visit_assign(&mut self, // Avoid a generic error for other uses of arguments. if self.qualif.intersects(Qualif::FN_ARGUMENT) { let decl = &self.mir.local_decls[index]; - span_err!(self.tcx.sess, decl.source_info.span, E0022, - "arguments of constant functions can only \ - be immutable by-value bindings"); + let mut err = struct_span_err!( + self.tcx.sess, + decl.source_info.span, + E0022, + "arguments of constant functions can only be immutable by-value bindings" + ); + if self.tcx.sess.teach(&err.get_code().unwrap()) { + err.note("Constant functions are not allowed to mutate anything. Thus, \ + binding to an argument with a mutable pattern is not allowed."); + err.note("Remove any mutable bindings from the argument list to fix this \ + error. In case you need to mutate the argument, try lazily \ + initializing a global variable instead of using a const fn, or \ + refactoring the code to a functional style to avoid mutation if \ + possible."); + } + err.emit(); return; } } @@ -1085,3 +1220,16 @@ fn run_pass<'a, 'tcx>(&self, } } } + +fn args_required_const(tcx: TyCtxt, def_id: DefId) -> Option> { + let attrs = tcx.get_attrs(def_id); + let attr = attrs.iter().find(|a| a.check_name("rustc_args_required_const"))?; + let mut ret = FxHashSet(); + for meta in attr.meta_item_list()? { + match meta.literal()?.node { + LitKind::Int(a, _) => { ret.insert(a as usize); } + _ => return None, + } + } + Some(ret) +} diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs index e7cab469bc2..cd80d25c410 100644 --- a/src/librustc_mir/transform/remove_noop_landing_pads.rs +++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs @@ -75,7 +75,8 @@ fn is_nop_landing_pad(&self, bb: BasicBlock, mir: &Mir, nop_landing_pads: &BitVe TerminatorKind::Goto { .. } | TerminatorKind::Resume | TerminatorKind::SwitchInt { .. } | - TerminatorKind::FalseEdges { .. } => { + TerminatorKind::FalseEdges { .. } | + TerminatorKind::FalseUnwind { .. } => { terminator.successors().iter().all(|succ| { nop_landing_pads.contains(succ.index()) }) diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index b6153ea1fdb..76283edac72 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -22,7 +22,7 @@ use dataflow::MoveDataParamEnv; use dataflow::BitDenotation; use dataflow::DataflowResults; -use dataflow::{DefinitelyInitializedLvals, MaybeInitializedLvals, MaybeUninitializedLvals}; +use dataflow::{DefinitelyInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces}; use dataflow::move_paths::{MovePathIndex, LookupResult}; use dataflow::move_paths::{HasMoveData, MoveData}; use dataflow; @@ -50,15 +50,15 @@ fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, 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), + MaybeInitializedPlaces::new(tcx, mir, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i])); let flow_uninits = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, - MaybeUninitializedLvals::new(tcx, mir, &mdpe), + MaybeUninitializedPlaces::new(tcx, mir, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i])); let flow_def_inits = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, - DefinitelyInitializedLvals::new(tcx, mir, &mdpe), + DefinitelyInitializedPlaces::new(tcx, mir, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i])); if has_rustc_mir_with(&attributes, "rustc_peek_maybe_init").is_some() { diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs index 20c33bab1aa..41089f567bd 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -64,6 +64,9 @@ fn run_pass<'a, 'tcx>(&self, TerminatorKind::FalseEdges { real_target, .. } => { TerminatorKind::Goto { target: real_target } }, + TerminatorKind::FalseUnwind { real_target, .. } => { + TerminatorKind::Goto { target: real_target } + }, _ => continue }; } diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 3331bc9e59e..e2feb0ed390 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -531,7 +531,9 @@ fn destructor_call_block<'a>(&mut self, (succ, unwind): (BasicBlock, Unwind)) let result = BasicBlockData { statements: vec![self.assign( &Place::Local(ref_place), - Rvalue::Ref(tcx.types.re_erased, BorrowKind::Mut, self.place.clone()) + Rvalue::Ref(tcx.types.re_erased, + BorrowKind::Mut { allow_two_phase_borrow: false }, + self.place.clone()) )], terminator: Some(Terminator { kind: TerminatorKind::Call { @@ -560,7 +562,7 @@ fn destructor_call_block<'a>(&mut self, (succ, unwind): (BasicBlock, Unwind)) /// ptr = cur /// cur = cur.offset(1) /// } else { - /// ptr = &mut LV[cur] + /// ptr = &mut P[cur] /// cur = cur + 1 /// } /// drop(ptr) @@ -591,7 +593,7 @@ fn drop_loop(&mut self, } else { (Rvalue::Ref( tcx.types.re_erased, - BorrowKind::Mut, + BorrowKind::Mut { allow_two_phase_borrow: false }, self.place.clone().index(cur)), Rvalue::BinaryOp(BinOp::Add, copy(&Place::Local(cur)), one)) }; @@ -731,11 +733,13 @@ fn drop_loop_pair(&mut self, ety: Ty<'tcx>, ptr_based: bool) -> BasicBlock { if ptr_based { let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place)); let tmp = Place::Local(self.new_temp(tmp_ty)); - // tmp = &LV; + // tmp = &P; // cur = tmp as *mut T; // end = Offset(cur, len); drop_block_stmts.push(self.assign(&tmp, Rvalue::Ref( - tcx.types.re_erased, BorrowKind::Mut, self.place.clone() + tcx.types.re_erased, + BorrowKind::Mut { allow_two_phase_borrow: false }, + self.place.clone() ))); drop_block_stmts.push(self.assign(&cur, Rvalue::Cast( CastKind::Misc, Operand::Move(tmp.clone()), iter_ty diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 6df860492f0..59864182a7e 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -237,10 +237,20 @@ fn visit_pat(&mut self, p: &'tcx hir::Pat) { Ok(Ordering::Less) | Ok(Ordering::Equal) => {} Ok(Ordering::Greater) => { - struct_span_err!(self.tcx.sess, start.span, E0030, - "lower range bound must be less than or equal to upper") - .span_label(start.span, "lower bound larger than upper bound") - .emit(); + let mut err = struct_span_err!( + self.tcx.sess, + start.span, + E0030, + "lower range bound must be less than or equal to upper" + ); + err.span_label(start.span, "lower bound larger than upper bound"); + if self.tcx.sess.teach(&err.get_code().unwrap()) { + err.note("When matching against a range, the compiler verifies that \ + the range is non-empty. Range patterns include both \ + end-points, so this is equivalent to requiring the start of \ + the range to be less than or equal to the end of the range."); + } + err.emit(); } Err(ErrorReported) => {} } diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index c23f28fe220..008c71cc9ce 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -119,6 +119,11 @@ fn visit_expr(&mut self, e: &'hir hir::Expr) { kind.name()) .span_label(e.span, "can only break with a value inside `loop`") + .span_suggestion(e.span, + &format!("instead, use `break` on its own \ + without a value inside this `{}` loop", + kind.name()), + "break".to_string()) .emit(); } } diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs index b379a174b23..e4705674e22 100644 --- a/src/librustc_passes/mir_stats.rs +++ b/src/librustc_passes/mir_stats.rs @@ -123,6 +123,7 @@ fn visit_terminator_kind(&mut self, TerminatorKind::GeneratorDrop => "TerminatorKind::GeneratorDrop", TerminatorKind::Yield { .. } => "TerminatorKind::Yield", TerminatorKind::FalseEdges { .. } => "TerminatorKind::FalseEdges", + TerminatorKind::FalseUnwind { .. } => "TerminatorKind::FalseUnwind", }, kind); self.super_terminator_kind(block, kind, location); } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index ecf3c9e42d5..2da4bfedd3a 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3998,14 +3998,20 @@ fn report_conflict<'b>(&mut self, if let (Ok(snippet), false) = (cm.span_to_snippet(binding.span), binding.is_renamed_extern_crate()) { + let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() { + format!("Other{}", name) + } else { + format!("other_{}", name) + }; + err.span_suggestion(binding.span, rename_msg, if snippet.ends_with(';') { - format!("{} as Other{};", + format!("{} as {};", &snippet[..snippet.len()-1], - name) + suggested_name) } else { - format!("{} as Other{}", snippet, name) + format!("{} as {}", snippet, suggested_name) }); } else { err.span_label(binding.span, rename_msg); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 07b08e2e61a..8cb25f449b6 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -1026,9 +1026,17 @@ fn import_path_to_string(names: &[SpannedIdent], if names.is_empty() { import_directive_subclass_to_string(subclass) } else { - (format!("{}::{}", - names_to_string(names), - import_directive_subclass_to_string(subclass))) + // Note that this code looks a little wonky, it's currently here to + // hopefully help debug #48116, but otherwise isn't intended to + // cause any problems. + let x = format!( + "{}::{}", + names_to_string(names), + import_directive_subclass_to_string(subclass), + ); + assert!(!names.is_empty()); + assert!(!x.starts_with("::")); + return x } } } diff --git a/src/librustc_save_analysis/Cargo.toml b/src/librustc_save_analysis/Cargo.toml index 8b2658b2a88..005faa55b58 100644 --- a/src/librustc_save_analysis/Cargo.toml +++ b/src/librustc_save_analysis/Cargo.toml @@ -15,7 +15,7 @@ rustc_data_structures = { path = "../librustc_data_structures" } rustc_typeck = { path = "../librustc_typeck" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } -rls-data = "0.14" +rls-data = "0.15" rls-span = "0.4" # FIXME(#40527) should move rustc serialize out of tree rustc-serialize = "0.3" diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 69cef20622b..47530c42085 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -770,8 +770,12 @@ fn process_impl( impl_items: &'l [ast::ImplItem], ) { if let Some(impl_data) = self.save_ctxt.get_item_data(item) { - down_cast_data!(impl_data, RelationData, item.span); - self.dumper.dump_relation(impl_data); + if let super::Data::RelationData(rel, imp) = impl_data { + self.dumper.dump_relation(rel); + self.dumper.dump_impl(imp); + } else { + span_bug!(item.span, "unexpected data kind: {:?}", impl_data); + } } self.visit_ty(&typ); if let &Some(ref trait_ref) = trait_ref { diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index 2b35a412383..1b09df16a7d 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -13,7 +13,7 @@ use rustc_serialize::json::as_json; use rls_data::{self, Analysis, CratePreludeData, Def, DefKind, Import, MacroRef, Ref, RefKind, - Relation}; + Relation, Impl}; use rls_data::config::Config; use rls_span::{Column, Row}; @@ -142,4 +142,8 @@ pub fn dump_def(&mut self, access: &Access, mut data: Def) { pub fn dump_relation(&mut self, data: Relation) { self.result.relations.push(data); } + + pub fn dump_impl(&mut self, data: Impl) { + self.result.impls.push(data); + } } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 2e494fdfad8..490dc4e5ac4 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -45,6 +45,7 @@ use rustc::ty::{self, TyCtxt}; use rustc_typeck::hir_ty_to_ty; +use std::cell::Cell; use std::default::Default; use std::env; use std::fs::File; @@ -65,7 +66,7 @@ use span_utils::SpanUtils; use rls_data::{Def, DefKind, ExternalCrateData, GlobalCrateId, MacroRef, Ref, RefKind, Relation, - RelationKind, SpanData}; + RelationKind, SpanData, Impl, ImplKind}; use rls_data::config::Config; @@ -75,13 +76,14 @@ pub struct SaveContext<'l, 'tcx: 'l> { analysis: &'l ty::CrateAnalysis, span_utils: SpanUtils<'tcx>, config: Config, + impl_counter: Cell, } #[derive(Debug)] pub enum Data { RefData(Ref), DefData(Def), - RelationData(Relation), + RelationData(Relation, Impl), } impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { @@ -315,7 +317,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option { attributes: lower_attributes(item.attrs.to_owned(), self), })) } - ast::ItemKind::Impl(.., ref trait_ref, ref typ, _) => { + ast::ItemKind::Impl(.., ref trait_ref, ref typ, ref impls) => { if let ast::TyKind::Path(None, ref path) = typ.node { // Common case impl for a struct or something basic. if generated_code(path.span) { @@ -324,17 +326,39 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option { let sub_span = self.span_utils.sub_span_for_type_name(path.span); filter!(self.span_utils, sub_span, typ.span, None); + let impl_id = self.next_impl_id(); + let span = self.span_from_span(sub_span.unwrap()); + 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()), + kind: RelationKind::Impl { + id: impl_id, + }, + span: span.clone(), 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()), + }, + Impl { + id: impl_id, + kind: match *trait_ref { + Some(_) => ImplKind::Direct, + None => ImplKind::Inherent, + }, + span: span, + value: String::new(), + parent: None, + children: impls + .iter() + .map(|i| id_from_node_id(i.id, self)) + .collect(), + docs: String::new(), + sig: None, + attributes: vec![], }) }) } else { @@ -791,7 +815,7 @@ pub fn get_field_ref_data( field_ref: &ast::Field, variant: &ty::VariantDef, ) -> Option { - let f = variant.field_named(field_ref.ident.node.name); + let f = variant.find_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); @@ -870,6 +894,17 @@ fn docs_for_attrs(&self, attrs: &[Attribute]) -> String { result.push_str(&val.as_str()); } result.push('\n'); + } else if let Some(meta_list) = attr.meta_item_list() { + meta_list.into_iter() + .filter(|it| it.check_name("include")) + .filter_map(|it| it.meta_item_list().map(|l| l.to_owned())) + .flat_map(|it| it) + .filter(|meta| meta.check_name("contents")) + .filter_map(|meta| meta.value_str()) + .for_each(|val| { + result.push_str(&val.as_str()); + result.push('\n'); + }); } } } @@ -882,6 +917,12 @@ fn docs_for_attrs(&self, attrs: &[Attribute]) -> String { result } + + fn next_impl_id(&self) -> u32 { + let next = self.impl_counter.get(); + self.impl_counter.set(next + 1); + next + } } fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String { @@ -1088,6 +1129,7 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>( analysis, span_utils: SpanUtils::new(&tcx.sess), config: find_config(config), + impl_counter: Cell::new(0), }; handler.save(save_ctxt, krate, cratename) diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 9cabd9356e9..12698964d2e 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -545,7 +545,7 @@ pub fn is_ignore(&self) -> bool { self.mode == PassMode::Ignore } - /// Get the LLVM type for an place of the original Rust type of + /// Get the LLVM type for a place of the original Rust type of /// this argument/return, i.e. the result of `type_of::type_of`. pub fn memory_ty(&self, cx: &CodegenCx<'a, 'tcx>) -> Type { self.layout.llvm_type(cx) @@ -674,7 +674,7 @@ pub fn new_vtable(cx: &CodegenCx<'a, 'tcx>, _ => bug!("FnType::new_vtable: non-pair self {:?}", self_arg) } - let pointee = self_arg.layout.ty.builtin_deref(true, ty::NoPreference) + let pointee = self_arg.layout.ty.builtin_deref(true) .unwrap_or_else(|| { bug!("FnType::new_vtable: non-pointer self {:?}", self_arg) }).ty; diff --git a/src/librustc_trans/allocator.rs b/src/librustc_trans/allocator.rs index fd5aa1364d3..e1c145b122d 100644 --- a/src/librustc_trans/allocator.rs +++ b/src/librustc_trans/allocator.rs @@ -86,6 +86,10 @@ pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) name.as_ptr(), ty); + if tcx.sess.target.target.options.default_hidden_visibility { + llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden); + } + let callee = CString::new(kind.fn_name(method.name)).unwrap(); let callee = llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr(), diff --git a/src/librustc_trans/asm.rs b/src/librustc_trans/asm.rs index c7be0c4e67d..751f8148a2a 100644 --- a/src/librustc_trans/asm.rs +++ b/src/librustc_trans/asm.rs @@ -59,8 +59,9 @@ pub fn trans_inline_asm<'a, 'tcx>( // Default per-arch clobbers // Basically what clang does let arch_clobbers = match &bx.sess().target.target.arch[..] { - "x86" | "x86_64" => vec!["~{dirflag}", "~{fpsr}", "~{flags}"], - _ => Vec::new() + "x86" | "x86_64" => vec!["~{dirflag}", "~{fpsr}", "~{flags}"], + "mips" | "mips64" => vec!["~{$1}"], + _ => Vec::new() }; let all_constraints = diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index f050edcd513..4fe294a790f 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -166,7 +166,9 @@ pub(crate) fn link_binary(sess: &Session, // Remove the temporary object file and metadata if we aren't saving temps if !sess.opts.cg.save_temps { - if sess.opts.output_types.should_trans() { + if sess.opts.output_types.should_trans() && + !preserve_objects_for_their_debuginfo(sess) + { for obj in trans.modules.iter().filter_map(|m| m.object.as_ref()) { remove(sess, obj); } @@ -190,6 +192,52 @@ pub(crate) fn link_binary(sess: &Session, out_filenames } +/// Returns a boolean indicating whether we should preserve the object files on +/// the filesystem for their debug information. This is often useful with +/// split-dwarf like schemes. +fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool { + // If the objects don't have debuginfo there's nothing to preserve. + if sess.opts.debuginfo == NoDebugInfo { + return false + } + + // If we're only producing artifacts that are archives, no need to preserve + // the objects as they're losslessly contained inside the archives. + let output_linked = sess.crate_types.borrow() + .iter() + .any(|x| *x != config::CrateTypeRlib && *x != config::CrateTypeStaticlib); + if !output_linked { + return false + } + + // If we're on OSX then the equivalent of split dwarf is turned on by + // default. The final executable won't actually have any debug information + // except it'll have pointers to elsewhere. Historically we've always run + // `dsymutil` to "link all the dwarf together" but this is actually sort of + // a bummer for incremental compilation! (the whole point of split dwarf is + // that you don't do this sort of dwarf link). + // + // Basically as a result this just means that if we're on OSX and we're + // *not* running dsymutil then the object files are the only source of truth + // for debug information, so we must preserve them. + if sess.target.target.options.is_like_osx { + match sess.opts.debugging_opts.run_dsymutil { + // dsymutil is not being run, preserve objects + Some(false) => return true, + + // dsymutil is being run, no need to preserve the objects + Some(true) => return false, + + // The default historical behavior was to always run dsymutil, so + // we're preserving that temporarily, but we're likely to switch the + // default soon. + None => return false, + } + } + + false +} + fn filename_for_metadata(sess: &Session, crate_name: &str, outputs: &OutputFilenames) -> PathBuf { let out_filename = outputs.single_output_file.clone() .unwrap_or(outputs @@ -736,8 +784,12 @@ fn escape_string(s: &[u8]) -> String { // On macOS, debuggers need this utility to get run to do some munging of - // the symbols - if sess.target.target.options.is_like_osx && sess.opts.debuginfo != NoDebugInfo { + // the symbols. Note, though, that if the object files are being preserved + // for their debug information there's no need for us to run dsymutil. + if sess.target.target.options.is_like_osx && + sess.opts.debuginfo != NoDebugInfo && + !preserve_objects_for_their_debuginfo(sess) + { match Command::new("dsymutil").arg(out_filename).output() { Ok(..) => {} Err(e) => sess.fatal(&format!("failed to run dsymutil: {}", e)), diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index 15ff59c7df9..989ef8a9537 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -133,6 +133,8 @@ pub fn provide(providers: &mut Providers) { Arc::new(local_crate) }; + + providers.symbol_export_level = export_level; } pub fn provide_extern(providers: &mut Providers) { @@ -203,6 +205,7 @@ pub fn provide_extern(providers: &mut Providers) { Arc::new(crate_exports) }; + providers.symbol_export_level = export_level; } fn export_level(tcx: TyCtxt, sym_def_id: DefId) -> SymbolExportLevel { diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 8afa63a5e97..ded9a296817 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -759,7 +759,10 @@ extern "C" fn demangle_callback(input_ptr: *const c_char, if asm2wasm && config.emit_obj { let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); - binaryen_assemble(cgcx, diag_handler, &assembly, &obj_out); + let suffix = ".wasm.map"; // FIXME use target suffix + let map = cgcx.output_filenames.path(OutputType::Exe) + .with_extension(&suffix[1..]); + binaryen_assemble(cgcx, diag_handler, &assembly, &obj_out, &map); timeline.record("binaryen"); if !config.emit_asm { @@ -814,7 +817,8 @@ extern "C" fn demangle_callback(input_ptr: *const c_char, fn binaryen_assemble(cgcx: &CodegenContext, handler: &Handler, assembly: &Path, - object: &Path) { + object: &Path, + map: &Path) { use rustc_binaryen::{Module, ModuleOptions}; let input = fs::read(&assembly).and_then(|contents| { @@ -823,10 +827,10 @@ fn binaryen_assemble(cgcx: &CodegenContext, let mut options = ModuleOptions::new(); if cgcx.debuginfo != config::NoDebugInfo { options.debuginfo(true); + let map_file_name = map.file_name().unwrap(); + options.source_map_url(map_file_name.to_str().unwrap()); } - if cgcx.crate_types.contains(&config::CrateTypeExecutable) { - options.start("main"); - } + options.stack(1024 * 1024); options.import_memory(cgcx.wasm_import_memory); let assembled = input.and_then(|input| { @@ -834,7 +838,13 @@ fn binaryen_assemble(cgcx: &CodegenContext, .map_err(|e| io::Error::new(io::ErrorKind::Other, e)) }); let err = assembled.and_then(|binary| { - fs::write(&object, binary.data()) + fs::write(&object, binary.data()).and_then(|()| { + if cgcx.debuginfo != config::NoDebugInfo { + fs::write(map, binary.source_map()) + } else { + Ok(()) + } + }) }); if let Err(e) = err { handler.err(&format!("failed to run binaryen assembler: {}", e)); @@ -1452,7 +1462,7 @@ fn start_executing_work(tcx: TyCtxt, target_pointer_width: tcx.sess.target.target.target_pointer_width.clone(), binaryen_linker: tcx.sess.linker_flavor() == LinkerFlavor::Binaryen, debuginfo: tcx.sess.opts.debuginfo, - wasm_import_memory: wasm_import_memory, + wasm_import_memory, assembler_cmd, }; diff --git a/src/librustc_trans/cabi_x86_64.rs b/src/librustc_trans/cabi_x86_64.rs index 62bac8469ce..b8144a3ca7a 100644 --- a/src/librustc_trans/cabi_x86_64.rs +++ b/src/librustc_trans/cabi_x86_64.rs @@ -134,12 +134,13 @@ fn reg_component(cls: &[Option], i: &mut usize, size: Size) -> Option None, Some(Class::Int) => { *i += 1; - Some(match size.bytes() { - 1 => Reg::i8(), - 2 => Reg::i16(), - 3 | - 4 => Reg::i32(), - _ => Reg::i64() + Some(if size.bytes() < 8 { + Reg { + kind: RegKind::Integer, + size + } + } else { + Reg::i64() }) } Some(Class::Sse) => { diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 06b8d9ff7b3..a285e5f263a 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -464,8 +464,7 @@ impl<'a, 'tcx> LayoutOf> for &'a CodegenCx<'a, 'tcx> { type TyLayout = TyLayout<'tcx>; fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout { - (self.tcx, ty::ParamEnv::empty(traits::Reveal::All)) - .layout_of(ty) + self.tcx.layout_of(ty::ParamEnv::empty(traits::Reveal::All).and(ty)) .unwrap_or_else(|e| match e { LayoutError::SizeOverflow(_) => self.sess().fatal(&e.to_string()), _ => bug!("failed to get layout for `{}`: {}", ty, e) diff --git a/src/librustc_trans/llvm_util.rs b/src/librustc_trans/llvm_util.rs index 15988008de2..843231d376f 100644 --- a/src/librustc_trans/llvm_util.rs +++ b/src/librustc_trans/llvm_util.rs @@ -79,16 +79,16 @@ unsafe fn configure_llvm(sess: &Session) { // detection code will walk past the end of the feature array, // leading to crashes. -const ARM_WHITELIST: &'static [&'static str] = &["neon\0", "vfp2\0", "vfp3\0", "vfp4\0"]; +const ARM_WHITELIST: &'static [&'static str] = &["neon\0", "v7\0", "vfp2\0", "vfp3\0", "vfp4\0"]; -const AARCH64_WHITELIST: &'static [&'static str] = &["neon\0"]; +const AARCH64_WHITELIST: &'static [&'static str] = &["neon\0", "v7\0"]; const X86_WHITELIST: &'static [&'static str] = &["avx\0", "avx2\0", "bmi\0", "bmi2\0", "sse\0", "sse2\0", "sse3\0", "sse4.1\0", "sse4.2\0", "ssse3\0", "tbm\0", "lzcnt\0", "popcnt\0", "sse4a\0", "rdrnd\0", "rdseed\0", "fma\0", "xsave\0", "xsaveopt\0", "xsavec\0", - "xsaves\0", + "xsaves\0", "aes\0", "avx512bw\0", "avx512cd\0", "avx512dq\0", "avx512er\0", "avx512f\0", "avx512ifma\0", diff --git a/src/librustc_trans/mir/analyze.rs b/src/librustc_trans/mir/analyze.rs index bf82e1d50c4..f683703ce6d 100644 --- a/src/librustc_trans/mir/analyze.rs +++ b/src/librustc_trans/mir/analyze.rs @@ -242,7 +242,8 @@ fn discover_masters<'tcx>(result: &mut IndexVec, TerminatorKind::Unreachable | TerminatorKind::SwitchInt { .. } | TerminatorKind::Yield { .. } | - TerminatorKind::FalseEdges { .. } => { + TerminatorKind::FalseEdges { .. } | + TerminatorKind::FalseUnwind { .. } => { /* nothing to do */ } TerminatorKind::Call { cleanup: unwind, .. } | diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index af1e30a4b19..bb2a7840fae 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -608,8 +608,9 @@ fn trans_terminator(&mut self, cleanup); } mir::TerminatorKind::GeneratorDrop | - mir::TerminatorKind::Yield { .. } | - mir::TerminatorKind::FalseEdges { .. } => bug!("generator ops in trans"), + mir::TerminatorKind::Yield { .. } => bug!("generator ops in trans"), + mir::TerminatorKind::FalseEdges { .. } | + mir::TerminatorKind::FalseUnwind { .. } => bug!("borrowck false edges in trans"), } } diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index f519e27dce9..d470f92b752 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -212,7 +212,7 @@ enum Base { Static(ValueRef) } -/// An place as seen from a constant. +/// A place as seen from a constant. #[derive(Copy, Clone)] struct ConstPlace<'tcx> { base: Base, @@ -411,6 +411,11 @@ fn trans(&mut self) -> Result, ConstEvalErr<'tcx>> { self.cx.align_of(substs.type_at(0)).abi()); Ok(Const::new(llval, tcx.types.usize)) } + "type_id" => { + let llval = C_u64(self.cx, + self.cx.tcx.type_id_hash(substs.type_at(0))); + Ok(Const::new(llval, tcx.types.u64)) + } _ => span_bug!(span, "{:?} in constant", terminator.kind) } } else if let Some((op, is_checked)) = self.is_binop_lang_item(def_id) { @@ -709,6 +714,10 @@ fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>, mir::CastKind::ReifyFnPointer => { match operand.ty.sty { ty::TyFnDef(def_id, substs) => { + if tcx.has_attr(def_id, "rustc_args_required_const") { + bug!("reifying a fn ptr that requires \ + const arguments"); + } callee::resolve_and_get_fn(self.cx, def_id, substs) } _ => { @@ -743,7 +752,7 @@ fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>, operand.llval } mir::CastKind::Unsize => { - let pointee_ty = operand.ty.builtin_deref(true, ty::NoPreference) + let pointee_ty = operand.ty.builtin_deref(true) .expect("consts: unsizing got non-pointer type").ty; let (base, old_info) = if !self.cx.type_is_sized(pointee_ty) { // Normally, the source is a thin pointer and we are @@ -758,7 +767,7 @@ fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>, (operand.llval, None) }; - let unsized_ty = cast_ty.builtin_deref(true, ty::NoPreference) + let unsized_ty = cast_ty.builtin_deref(true) .expect("consts: unsizing got non-pointer target type").ty; let ptr_ty = self.cx.layout_of(unsized_ty).llvm_type(self.cx).ptr_to(); let base = consts::ptrcast(base, ptr_ty); @@ -865,7 +874,7 @@ fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>, } else { self.cx.tcx.data_layout.pointer_align }; - if bk == mir::BorrowKind::Mut { + if let mir::BorrowKind::Mut { .. } = bk { consts::addr_of_mut(self.cx, llval, align, "ref_mut") } else { consts::addr_of(self.cx, llval, align, "ref") diff --git a/src/librustc_trans/mir/operand.rs b/src/librustc_trans/mir/operand.rs index 25db9f9b4c8..e1b906646aa 100644 --- a/src/librustc_trans/mir/operand.rs +++ b/src/librustc_trans/mir/operand.rs @@ -9,7 +9,6 @@ // except according to those terms. use llvm::ValueRef; -use rustc::ty; use rustc::ty::layout::{self, Align, LayoutOf, TyLayout}; use rustc::mir; use rustc_data_structures::indexed_vec::Idx; @@ -100,7 +99,7 @@ pub fn immediate(self) -> ValueRef { } pub fn deref(self, cx: &CodegenCx<'a, 'tcx>) -> PlaceRef<'tcx> { - let projected_ty = self.layout.ty.builtin_deref(true, ty::NoPreference) + let projected_ty = self.layout.ty.builtin_deref(true) .unwrap_or_else(|| bug!("deref of non-pointer {:?}", self)).ty; let (llptr, llextra) = match self.val { OperandValue::Immediate(llptr) => (llptr, ptr::null_mut()), diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index d1bc4fe9001..2e876ec118d 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -195,6 +195,10 @@ pub fn trans_rvalue_operand(&mut self, mir::CastKind::ReifyFnPointer => { match operand.layout.ty.sty { ty::TyFnDef(def_id, substs) => { + if bx.cx.tcx.has_attr(def_id, "rustc_args_required_const") { + bug!("reifying a fn ptr that requires \ + const arguments"); + } OperandValue::Immediate( callee::resolve_and_get_fn(bx.cx, def_id, substs)) } diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index b1533cfad19..af957500f70 100644 --- a/src/librustc_trans/type_of.rs +++ b/src/librustc_trans/type_of.rs @@ -57,7 +57,9 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ty::TyClosure(..) | ty::TyGenerator(..) | ty::TyAdt(..) | - ty::TyDynamic(..) | + // FIXME(eddyb) producing readable type names for trait objects can result + // in problematically distinct types due to HRTB and subtyping (see #47638). + // ty::TyDynamic(..) | ty::TyForeign(..) | ty::TyStr => { let mut name = String::with_capacity(32); diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index d5e4aa69c5b..bf253a88d27 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -14,8 +14,8 @@ use rustc::infer; use rustc::infer::type_variable::TypeVariableOrigin; use rustc::traits::ObligationCauseCode; -use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference}; -use check::{FnCtxt, Expectation, Diverges}; +use rustc::ty::{self, Ty, TypeFoldable}; +use check::{FnCtxt, Expectation, Diverges, Needs}; use check::coercion::CoerceMany; use util::nodemap::FxHashMap; @@ -214,12 +214,25 @@ pub fn check_pat_walk( end.span }; - struct_span_err!(tcx.sess, span, E0029, - "only char and numeric types are allowed in range patterns") - .span_label(span, "ranges require char or numeric types") - .note(&format!("start type: {}", self.ty_to_string(lhs_ty))) - .note(&format!("end type: {}", self.ty_to_string(rhs_ty))) - .emit(); + let mut err = struct_span_err!( + tcx.sess, + span, + E0029, + "only char and numeric types are allowed in range patterns" + ); + err.span_label(span, "ranges require char or numeric types"); + err.note(&format!("start type: {}", self.ty_to_string(lhs_ty))); + err.note(&format!("end type: {}", self.ty_to_string(rhs_ty))); + if tcx.sess.teach(&err.get_code().unwrap()) { + err.note( + "In a match expression, only numbers and characters can be matched \ + against a range. This is because the compiler checks that the range \ + is non-empty at compile-time, and is unable to evaluate arbitrary \ + comparison functions. If you want to capture values of an orderable \ + type between two end-points, you can use a guard." + ); + } + err.emit(); return; } @@ -500,15 +513,30 @@ pub fn check_pat_walk( pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool { if let PatKind::Binding(..) = inner.node { - if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true, ty::NoPreference) { + if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) { if let ty::TyDynamic(..) = mt.ty.sty { // This is "x = SomeTrait" being reduced from // "let &x = &SomeTrait" or "let box x = Box", an error. let type_str = self.ty_to_string(expected); - struct_span_err!(self.tcx.sess, span, E0033, - "type `{}` cannot be dereferenced", type_str) - .span_label(span, format!("type `{}` cannot be dereferenced", type_str)) - .emit(); + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0033, + "type `{}` cannot be dereferenced", + type_str + ); + err.span_label(span, format!("type `{}` cannot be dereferenced", type_str)); + if self.tcx.sess.teach(&err.get_code().unwrap()) { + err.note("\ +This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \ +pattern. Every trait defines a type, but because the 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. + +You can read more about trait objects in the Trait Objects section of the Reference: \ +https://doc.rust-lang.org/reference/types.html#trait-objects"); + } + err.emit(); return false } } @@ -584,7 +612,7 @@ pub fn check_match(&self, }); let discrim_ty; if let Some(m) = contains_ref_bindings { - discrim_ty = self.check_expr_with_lvalue_pref(discrim, LvaluePreference::from_mutbl(m)); + discrim_ty = self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m)); } else { // ...but otherwise we want to use any supertype of the // discriminant. This is sort of a workaround, see note (*) in @@ -881,17 +909,33 @@ fn check_struct_pat_fields(&self, self.field_ty(span, f, substs) }) .unwrap_or_else(|| { - struct_span_err!(tcx.sess, span, E0026, - "{} `{}` does not have a field named `{}`", - kind_name, - tcx.item_path_str(variant.did), - field.name) - .span_label(span, - format!("{} `{}` does not have field `{}`", - kind_name, - tcx.item_path_str(variant.did), - field.name)) - .emit(); + let mut err = struct_span_err!( + tcx.sess, + span, + E0026, + "{} `{}` does not have a field named `{}`", + kind_name, + tcx.item_path_str(variant.did), + field.name + ); + err.span_label(span, + format!("{} `{}` does not have field `{}`", + kind_name, + tcx.item_path_str(variant.did), + field.name)); + if tcx.sess.teach(&err.get_code().unwrap()) { + err.note( + "This error indicates that a struct pattern attempted to \ + extract a non-existent field from a struct. Struct fields \ + are identified by the name used before the colon : so struct \ + patterns should resemble the declaration of the struct type \ + being matched.\n\n\ + If you are using shorthand field patterns but want to refer \ + to the struct field by a different name, you should rename \ + it explicitly." + ); + } + err.emit(); tcx.types.err }) @@ -927,6 +971,14 @@ fn check_struct_pat_fields(&self, if variant.ctor_kind == CtorKind::Fn { diag.note("trying to match a tuple variant with a struct variant pattern"); } + if tcx.sess.teach(&diag.get_code().unwrap()) { + diag.note( + "This error indicates that a pattern for a struct fails to specify a \ + sub-pattern for every one of the struct's fields. Ensure that each field \ + from the struct's definition is mentioned in the pattern, or use `..` to \ + ignore unwanted fields." + ); + } diag.emit(); } } diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index 169959d12b5..1d7c533178f 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -10,7 +10,7 @@ use astconv::AstConv; -use super::{FnCtxt, LvalueOp}; +use super::{FnCtxt, PlaceOp, Needs}; use super::method::MethodCallee; use rustc::infer::InferOk; @@ -18,7 +18,6 @@ use rustc::traits; use rustc::ty::{self, Ty, TraitRef}; use rustc::ty::{ToPredicate, TypeFoldable}; -use rustc::ty::{LvaluePreference, NoPreference}; use rustc::ty::adjustment::{Adjustment, Adjust, OverloadedDeref}; use syntax_pos::Span; @@ -85,7 +84,7 @@ fn next(&mut self) -> Option { // Otherwise, deref if type is derefable: let (kind, new_ty) = - if let Some(mt) = self.cur_ty.builtin_deref(self.include_raw_pointers, NoPreference) { + if let Some(mt) = self.cur_ty.builtin_deref(self.include_raw_pointers) { (AutoderefKind::Builtin, mt.ty) } else { let ty = self.overloaded_deref_ty(self.cur_ty)?; @@ -163,19 +162,19 @@ pub fn step_count(&self) -> usize { } /// Returns the adjustment steps. - pub fn adjust_steps(&self, pref: LvaluePreference) + pub fn adjust_steps(&self, needs: Needs) -> Vec> { - self.fcx.register_infer_ok_obligations(self.adjust_steps_as_infer_ok(pref)) + self.fcx.register_infer_ok_obligations(self.adjust_steps_as_infer_ok(needs)) } - pub fn adjust_steps_as_infer_ok(&self, pref: LvaluePreference) + pub fn adjust_steps_as_infer_ok(&self, needs: Needs) -> InferOk<'tcx, Vec>> { let mut obligations = vec![]; let targets = self.steps.iter().skip(1).map(|&(ty, _)| ty) .chain(iter::once(self.cur_ty)); let steps: Vec<_> = self.steps.iter().map(|&(source, kind)| { if let AutoderefKind::Overloaded = kind { - self.fcx.try_overloaded_deref(self.span, source, pref) + self.fcx.try_overloaded_deref(self.span, source, needs) .and_then(|InferOk { value: method, obligations: o }| { obligations.extend(o); if let ty::TyRef(region, mt) = method.sig.output().sty { @@ -238,8 +237,8 @@ pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'gcx, pub fn try_overloaded_deref(&self, span: Span, base_ty: Ty<'tcx>, - pref: LvaluePreference) + needs: Needs) -> Option>> { - self.try_overloaded_lvalue_op(span, base_ty, &[], pref, LvalueOp::Deref) + self.try_overloaded_place_op(span, base_ty, &[], needs, PlaceOp::Deref) } } diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 5c5e5f2735b..3d61ffe3933 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -8,15 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::{Expectation, FnCtxt, TupleArgumentsFlag}; +use super::{Expectation, FnCtxt, Needs, TupleArgumentsFlag}; use super::autoderef::Autoderef; use super::method::MethodCallee; use hir::def::Def; use hir::def_id::{DefId, LOCAL_CRATE}; use rustc::{infer, traits}; -use rustc::ty::{self, TyCtxt, TypeFoldable, LvaluePreference, Ty}; -use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow}; +use rustc::ty::{self, TyCtxt, TypeFoldable, Ty}; +use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability}; use syntax::abi; use syntax::symbol::Symbol; use syntax_pos::Span; @@ -96,7 +96,7 @@ fn try_overloaded_call_step(&self, // If the callee is a bare function or a closure, then we're all set. match adjusted_ty.sty { ty::TyFnDef(..) | ty::TyFnPtr(_) => { - let adjustments = autoderef.adjust_steps(LvaluePreference::NoPreference); + let adjustments = autoderef.adjust_steps(Needs::None); self.apply_adjustments(callee_expr, adjustments); return Some(CallStep::Builtin(adjusted_ty)); } @@ -113,7 +113,7 @@ fn try_overloaded_call_step(&self, infer::FnCall, &closure_ty) .0; - let adjustments = autoderef.adjust_steps(LvaluePreference::NoPreference); + let adjustments = autoderef.adjust_steps(Needs::None); self.record_deferred_call_resolution(def_id, DeferredCallResolution { call_expr, callee_expr, @@ -143,7 +143,7 @@ fn try_overloaded_call_step(&self, } self.try_overloaded_call_traits(call_expr, adjusted_ty).map(|(autoref, method)| { - let mut adjustments = autoderef.adjust_steps(LvaluePreference::NoPreference); + let mut adjustments = autoderef.adjust_steps(Needs::None); adjustments.extend(autoref); self.apply_adjustments(callee_expr, adjustments); CallStep::Overloaded(method) @@ -176,8 +176,17 @@ fn try_overloaded_call_traits(&self, let mut autoref = None; if borrow { if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty { + let mutbl = match mt.mutbl { + hir::MutImmutable => AutoBorrowMutability::Immutable, + hir::MutMutable => AutoBorrowMutability::Mutable { + // For initial two-phase borrow + // deployment, conservatively omit + // overloaded function call ops. + allow_two_phase_borrow: false, + } + }; autoref = Some(Adjustment { - kind: Adjust::Borrow(AutoBorrow::Ref(region, mt.mutbl)), + kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)), target: method.sig.inputs()[0] }); } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index edda557c98c..47e4b0272be 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -60,7 +60,7 @@ //! sort of a minor point so I've opted to leave it for later---after all //! we may want to adjust precisely when coercions occur. -use check::{Diverges, FnCtxt}; +use check::{Diverges, FnCtxt, Needs}; use rustc::hir; use rustc::hir::def_id::DefId; @@ -68,9 +68,8 @@ use rustc::infer::type_variable::TypeVariableOrigin; use rustc::lint; use rustc::traits::{self, ObligationCause, ObligationCauseCode}; -use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow}; -use rustc::ty::{self, LvaluePreference, TypeAndMut, - Ty, ClosureSubsts}; +use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability}; +use rustc::ty::{self, TypeAndMut, Ty, ClosureSubsts}; use rustc::ty::fold::TypeFoldable; use rustc::ty::error::TypeError; use rustc::ty::relate::RelateResult; @@ -410,9 +409,9 @@ fn coerce_borrowed_pointer(&self, return success(vec![], ty, obligations); } - let pref = LvaluePreference::from_mutbl(mt_b.mutbl); + let needs = Needs::maybe_mut_place(mt_b.mutbl); let InferOk { value: mut adjustments, obligations: o } - = autoderef.adjust_steps_as_infer_ok(pref); + = autoderef.adjust_steps_as_infer_ok(needs); obligations.extend(o); obligations.extend(autoderef.into_obligations()); @@ -422,8 +421,17 @@ fn coerce_borrowed_pointer(&self, ty::TyRef(r_borrow, _) => r_borrow, _ => span_bug!(span, "expected a ref type, got {:?}", ty), }; + let mutbl = match mt_b.mutbl { + hir::MutImmutable => AutoBorrowMutability::Immutable, + hir::MutMutable => AutoBorrowMutability::Mutable { + // Deref-coercion is a case where we deliberately + // disallow two-phase borrows in its initial + // deployment; see discussion on PR #47489. + allow_two_phase_borrow: false, + } + }; adjustments.push(Adjustment { - kind: Adjust::Borrow(AutoBorrow::Ref(r_borrow, mt_b.mutbl)), + kind: Adjust::Borrow(AutoBorrow::Ref(r_borrow, mutbl)), target: ty }); @@ -462,11 +470,17 @@ fn coerce_unsized(&self, source: Ty<'tcx>, target: Ty<'tcx>) -> CoerceResult<'tc let coercion = Coercion(self.cause.span); let r_borrow = self.next_region_var(coercion); + let mutbl = match mt_b.mutbl { + hir::MutImmutable => AutoBorrowMutability::Immutable, + hir::MutMutable => AutoBorrowMutability::Mutable { + allow_two_phase_borrow: false, + } + }; Some((Adjustment { kind: Adjust::Deref(None), target: mt_a.ty }, Adjustment { - kind: Adjust::Borrow(AutoBorrow::Ref(r_borrow, mt_b.mutbl)), + kind: Adjust::Borrow(AutoBorrow::Ref(r_borrow, mutbl)), target: self.tcx.mk_ref(r_borrow, ty::TypeAndMut { mutbl: mt_b.mutbl, ty: mt_a.ty @@ -872,6 +886,7 @@ fn try_find_coercion_lub(&self, ] => { match self.node_ty(expr.hir_id).sty { ty::TyRef(_, mt_orig) => { + let mutbl_adj: hir::Mutability = mutbl_adj.into(); // Reborrow that we can safely ignore, because // the next adjustment can only be a Deref // which will be merged into it. diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 570eecfc267..4c10f28eb8e 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -40,6 +40,8 @@ pub fn compare_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("compare_impl_method(impl_trait_ref={:?})", impl_trait_ref); + let impl_m_span = tcx.sess.codemap().def_span(impl_m_span); + if let Err(ErrorReported) = compare_self_type(tcx, impl_m, impl_m_span, @@ -186,6 +188,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, check_region_bounds_on_impl_method(tcx, impl_m_span, impl_m, + trait_m, &trait_m_generics, &impl_m_generics, trait_to_skol_substs)?; @@ -310,7 +313,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; let mut diag = struct_span_err!(tcx.sess, - cause.span, + cause.span(&tcx), E0053, "method `{}` has an incompatible type for trait", trait_m.name); @@ -346,10 +349,12 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, impl_m: &ty::AssociatedItem, + trait_m: &ty::AssociatedItem, trait_generics: &ty::Generics, impl_generics: &ty::Generics, trait_to_skol_substs: &Substs<'tcx>) -> Result<(), ErrorReported> { + let span = tcx.sess.codemap().def_span(span); let trait_params = &trait_generics.regions[..]; let impl_params = &impl_generics.regions[..]; @@ -371,14 +376,18 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // are zero. Since I don't quite know how to phrase things at // the moment, give a kind of vague error message. if trait_params.len() != impl_params.len() { - struct_span_err!(tcx.sess, - span, - E0195, - "lifetime parameters or bounds on method `{}` do not match the \ - trait declaration", - impl_m.name) - .span_label(span, "lifetimes do not match trait") - .emit(); + let mut err = struct_span_err!(tcx.sess, + span, + E0195, + "lifetime parameters or bounds on method `{}` do not match \ + the trait declaration", + impl_m.name); + err.span_label(span, "lifetimes do not match method in trait"); + if let Some(sp) = tcx.hir.span_if_local(trait_m.def_id) { + err.span_label(tcx.sess.codemap().def_span(sp), + "lifetimes in impl do not match this method in trait"); + } + err.emit(); return Err(ErrorReported); } @@ -424,9 +433,9 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a }).map(|(ref impl_arg, ref trait_arg)| { (impl_arg.span, Some(trait_arg.span)) }) - .unwrap_or_else(|| (cause.span, tcx.hir.span_if_local(trait_m.def_id))) + .unwrap_or_else(|| (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id))) } else { - (cause.span, tcx.hir.span_if_local(trait_m.def_id)) + (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id)) } } TypeError::Sorts(ExpectedFound { .. }) => { @@ -459,14 +468,14 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a { (impl_m_output.span(), Some(trait_m_output.span())) } else { - (cause.span, tcx.hir.span_if_local(trait_m.def_id)) + (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id)) } }) } else { - (cause.span, tcx.hir.span_if_local(trait_m.def_id)) + (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id)) } } - _ => (cause.span, tcx.hir.span_if_local(trait_m.def_id)), + _ => (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id)), } } diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index 781eeaef248..2e45e3b1f35 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -150,15 +150,15 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { } fn visit_pat(&mut self, pat: &'tcx Pat) { + intravisit::walk_pat(self, pat); + + self.expr_count += 1; + if let PatKind::Binding(..) = pat.node { let scope = self.region_scope_tree.var_scope(pat.hir_id.local_id); let ty = self.fcx.tables.borrow().pat_ty(pat); self.record(ty, Some(scope), None, pat.span); } - - self.expr_count += 1; - - intravisit::walk_pat(self, pat); } fn visit_expr(&mut self, expr: &'tcx Expr) { diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 3a9c4e1901d..20d58991496 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -11,13 +11,13 @@ use super::{probe, MethodCallee}; use astconv::AstConv; -use check::{FnCtxt, LvalueOp, callee}; +use check::{FnCtxt, PlaceOp, callee, Needs}; use hir::def_id::DefId; use rustc::ty::subst::Substs; use rustc::traits; -use rustc::ty::{self, LvaluePreference, NoPreference, PreferMutLvalue, Ty}; +use rustc::ty::{self, Ty}; use rustc::ty::subst::Subst; -use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, OverloadedDeref}; +use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability, OverloadedDeref}; use rustc::ty::fold::TypeFoldable; use rustc::infer::{self, InferOk}; use syntax_pos::Span; @@ -136,7 +136,7 @@ fn confirm(&mut self, }; if let Some(hir::MutMutable) = pick.autoref { - self.convert_lvalue_derefs_to_mutable(); + self.convert_place_derefs_to_mutable(); } ConfirmResult { callee, illegal_sized_bound } @@ -155,7 +155,7 @@ fn adjust_self_ty(&mut self, let (_, n) = autoderef.nth(pick.autoderefs).unwrap(); assert_eq!(n, pick.autoderefs); - let mut adjustments = autoderef.adjust_steps(LvaluePreference::NoPreference); + let mut adjustments = autoderef.adjust_steps(Needs::None); let mut target = autoderef.unambiguous_final_ty(); @@ -165,6 +165,14 @@ fn adjust_self_ty(&mut self, mutbl, ty: target }); + let mutbl = match mutbl { + hir::MutImmutable => AutoBorrowMutability::Immutable, + hir::MutMutable => AutoBorrowMutability::Mutable { + // Method call receivers are the primary use case + // for two-phase borrows. + allow_two_phase_borrow: true, + } + }; adjustments.push(Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)), target @@ -172,7 +180,7 @@ fn adjust_self_ty(&mut self, if let Some(unsize_target) = pick.unsize { target = self.tcx.mk_ref(region, ty::TypeAndMut { - mutbl, + mutbl: mutbl.into(), ty: unsize_target }); adjustments.push(Adjustment { @@ -416,7 +424,7 @@ fn add_obligations(&mut self, /// When we select a method with a mutable autoref, we have to go convert any /// auto-derefs, indices, etc from `Deref` and `Index` into `DerefMut` and `IndexMut` /// respectively. - fn convert_lvalue_derefs_to_mutable(&self) { + fn convert_place_derefs_to_mutable(&self) { // Gather up expressions we want to munge. let mut exprs = Vec::new(); exprs.push(self.self_expr); @@ -431,14 +439,14 @@ fn convert_lvalue_derefs_to_mutable(&self) { } } - debug!("convert_lvalue_derefs_to_mutable: exprs={:?}", exprs); + debug!("convert_place_derefs_to_mutable: exprs={:?}", exprs); // Fix up autoderefs and derefs. for (i, &expr) in exprs.iter().rev().enumerate() { - debug!("convert_lvalue_derefs_to_mutable: i={} expr={:?}", i, expr); + debug!("convert_place_derefs_to_mutable: i={} expr={:?}", i, expr); // Fix up the autoderefs. Autorefs can only occur immediately preceding - // overloaded lvalue ops, and will be fixed by them in order to get + // overloaded place ops, and will be fixed by them in order to get // the correct region. let mut source = self.node_ty(expr.hir_id); // Do not mutate adjustments in place, but rather take them, @@ -449,10 +457,10 @@ fn convert_lvalue_derefs_to_mutable(&self) { .adjustments_mut() .remove(expr.hir_id); if let Some(mut adjustments) = previous_adjustments { - let pref = LvaluePreference::PreferMutLvalue; + let needs = Needs::MutPlace; for adjustment in &mut adjustments { if let Adjust::Deref(Some(ref mut deref)) = adjustment.kind { - if let Some(ok) = self.try_overloaded_deref(expr.span, source, pref) { + if let Some(ok) = self.try_overloaded_deref(expr.span, source, needs) { let method = self.register_infer_ok_obligations(ok); if let ty::TyRef(region, mt) = method.sig.output().sty { *deref = OverloadedDeref { @@ -470,28 +478,28 @@ fn convert_lvalue_derefs_to_mutable(&self) { match expr.node { hir::ExprIndex(ref base_expr, ref index_expr) => { let index_expr_ty = self.node_ty(index_expr.hir_id); - self.convert_lvalue_op_to_mutable( - LvalueOp::Index, expr, base_expr, &[index_expr_ty]); + self.convert_place_op_to_mutable( + PlaceOp::Index, expr, base_expr, &[index_expr_ty]); } hir::ExprUnary(hir::UnDeref, ref base_expr) => { - self.convert_lvalue_op_to_mutable( - LvalueOp::Deref, expr, base_expr, &[]); + self.convert_place_op_to_mutable( + PlaceOp::Deref, expr, base_expr, &[]); } _ => {} } } } - fn convert_lvalue_op_to_mutable(&self, - op: LvalueOp, + fn convert_place_op_to_mutable(&self, + op: PlaceOp, expr: &hir::Expr, base_expr: &hir::Expr, arg_tys: &[Ty<'tcx>]) { - debug!("convert_lvalue_op_to_mutable({:?}, {:?}, {:?}, {:?})", + debug!("convert_place_op_to_mutable({:?}, {:?}, {:?}, {:?})", op, expr, base_expr, arg_tys); if !self.tables.borrow().is_method_call(expr) { - debug!("convert_lvalue_op_to_mutable - builtin, nothing to do"); + debug!("convert_place_op_to_mutable - builtin, nothing to do"); return } @@ -499,24 +507,24 @@ fn convert_lvalue_op_to_mutable(&self, .map_or_else(|| self.node_ty(expr.hir_id), |adj| adj.target); let base_ty = self.resolve_type_vars_if_possible(&base_ty); - // Need to deref because overloaded lvalue ops take self by-reference. - let base_ty = base_ty.builtin_deref(false, NoPreference) - .expect("lvalue op takes something that is not a ref") + // Need to deref because overloaded place ops take self by-reference. + let base_ty = base_ty.builtin_deref(false) + .expect("place op takes something that is not a ref") .ty; - let method = self.try_overloaded_lvalue_op( - expr.span, base_ty, arg_tys, PreferMutLvalue, op); + let method = self.try_overloaded_place_op( + expr.span, base_ty, arg_tys, Needs::MutPlace, op); let method = match method { Some(ok) => self.register_infer_ok_obligations(ok), None => return self.tcx.sess.delay_span_bug(expr.span, "re-trying op failed") }; - debug!("convert_lvalue_op_to_mutable: method={:?}", method); + debug!("convert_place_op_to_mutable: method={:?}", method); self.write_method_call(expr.hir_id, method); let (region, mutbl) = if let ty::TyRef(r, mt) = method.sig.inputs()[0].sty { (r, mt.mutbl) } else { - span_bug!(expr.span, "input to lvalue op is not a ref?"); + span_bug!(expr.span, "input to place op is not a ref?"); }; // Convert the autoref in the base expr to mutable with the correct @@ -529,11 +537,20 @@ fn convert_lvalue_op_to_mutable(&self, let mut source = base_expr_ty; for adjustment in &mut adjustments[..] { if let Adjust::Borrow(AutoBorrow::Ref(..)) = adjustment.kind { - debug!("convert_lvalue_op_to_mutable: converting autoref {:?}", adjustment); + debug!("convert_place_op_to_mutable: converting autoref {:?}", adjustment); + let mutbl = match mutbl { + hir::MutImmutable => AutoBorrowMutability::Immutable, + hir::MutMutable => AutoBorrowMutability::Mutable { + // For initial two-phase borrow + // deployment, conservatively omit + // overloaded operators. + allow_two_phase_borrow: false, + } + }; adjustment.kind = Adjust::Borrow(AutoBorrow::Ref(region, mutbl)); adjustment.target = self.tcx.mk_ref(region, ty::TypeAndMut { ty: source, - mutbl + mutbl: mutbl.into(), }); } source = adjustment.target; diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index c88bbd03af8..e8c3966f23f 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -326,13 +326,19 @@ fn create_steps(&self, if reached_raw_pointer && !self.tcx.sess.features.borrow().arbitrary_self_types { // this case used to be allowed by the compiler, - // so we do a future-compat lint here + // so we do a future-compat lint here for the 2015 epoch // (see https://github.com/rust-lang/rust/issues/46906) - self.tcx.lint_node( - lint::builtin::TYVAR_BEHIND_RAW_POINTER, - scope_expr_id, - span, - &format!("the type of this value must be known in this context")); + if self.tcx.sess.rust_2018() { + span_err!(self.tcx.sess, span, E0908, + "the type of this value must be known \ + to call a method on a raw pointer on it"); + } else { + self.tcx.lint_node( + lint::builtin::TYVAR_BEHIND_RAW_POINTER, + scope_expr_id, + span, + &format!("the type of this value must be known in this context")); + } } else { let t = self.structurally_resolved_type(span, final_ty); assert_eq!(t, self.tcx.types.err); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9b24c09036b..165b499cc62 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -95,13 +95,11 @@ use rustc::middle::region; use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode}; -use rustc::ty::{ParamTy, LvaluePreference, NoPreference, PreferMutLvalue}; use rustc::ty::{self, Ty, TyCtxt, Visibility, ToPredicate}; -use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; +use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc::ty::fold::TypeFoldable; use rustc::ty::maps::Providers; use rustc::ty::util::{Representability, IntTypeExt}; -use rustc::ty::layout::LayoutOf; use errors::{DiagnosticBuilder, DiagnosticId}; use require_c_abi_if_variadic; @@ -368,6 +366,21 @@ fn coercion_target_type(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, span: Span) -> Ty<'t } } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum Needs { + MutPlace, + None +} + +impl Needs { + fn maybe_mut_place(m: hir::Mutability) -> Self { + match m { + hir::MutMutable => Needs::MutPlace, + hir::MutImmutable => Needs::None, + } + } +} + #[derive(Copy, Clone)] pub struct UnsafetyState { pub def: ast::NodeId, @@ -410,7 +423,7 @@ pub fn recurse(&mut self, blk: &hir::Block) -> UnsafetyState { } #[derive(Debug, Copy, Clone)] -pub enum LvalueOp { +pub enum PlaceOp { Deref, Index } @@ -543,7 +556,7 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { /// foo();}` or `{return; 22}`, where we would warn on the /// `foo()` or `22`. /// - /// - To permit assignment into a local variable or other lvalue + /// - To permit assignment into a local variable or other place /// (including the "return slot") of type `!`. This is allowed /// if **either** the type of value being assigned is `!`, which /// means the current code is dead, **or** the expression's @@ -1001,7 +1014,9 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, let span = body.value.span; if body.is_generator && can_be_generator.is_some() { - fcx.yield_ty = Some(fcx.next_ty_var(TypeVariableOrigin::TypeInference(span))); + let yield_ty = fcx.next_ty_var(TypeVariableOrigin::TypeInference(span)); + fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType); + fcx.yield_ty = Some(yield_ty); } GatherLocalsVisitor { fcx: &fcx, }.visit_body(body); @@ -1537,7 +1552,7 @@ fn check_transparent<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: De let field_infos: Vec<_> = adt.non_enum_variant().fields.iter().map(|field| { let ty = field.ty(tcx, Substs::identity_for_item(tcx, field.did)); let param_env = tcx.param_env(field.did); - let layout = (tcx, param_env).layout_of(ty); + let layout = tcx.layout_of(param_env.and(ty)); // We are currently checking the type this field came from, so it must be local let span = tcx.hir.span_if_local(field.did).unwrap(); let zst = layout.map(|layout| layout.is_zst()).unwrap_or(false); @@ -2207,11 +2222,65 @@ fn select_obligations_where_possible(&self) { } } - /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait + fn is_place_expr(&self, expr: &hir::Expr) -> bool { + match expr.node { + hir::ExprPath(hir::QPath::Resolved(_, ref path)) => { + match path.def { + Def::Local(..) | Def::Upvar(..) | Def::Static(..) | Def::Err => true, + _ => false, + } + } + + hir::ExprType(ref e, _) => { + self.is_place_expr(e) + } + + hir::ExprUnary(hir::UnDeref, _) | + hir::ExprField(..) | + hir::ExprTupField(..) | + hir::ExprIndex(..) => { + true + } + + // Partially qualified paths in expressions can only legally + // refer to associated items which are always rvalues. + hir::ExprPath(hir::QPath::TypeRelative(..)) | + + hir::ExprCall(..) | + hir::ExprMethodCall(..) | + hir::ExprStruct(..) | + hir::ExprTup(..) | + hir::ExprIf(..) | + hir::ExprMatch(..) | + hir::ExprClosure(..) | + hir::ExprBlock(..) | + hir::ExprRepeat(..) | + hir::ExprArray(..) | + hir::ExprBreak(..) | + hir::ExprAgain(..) | + hir::ExprRet(..) | + hir::ExprWhile(..) | + hir::ExprLoop(..) | + hir::ExprAssign(..) | + hir::ExprInlineAsm(..) | + hir::ExprAssignOp(..) | + hir::ExprLit(_) | + hir::ExprUnary(..) | + hir::ExprBox(..) | + hir::ExprAddrOf(..) | + hir::ExprBinary(..) | + hir::ExprYield(..) | + hir::ExprCast(..) => { + false + } + } + } + + /// For the overloaded place expressions (`*x`, `x[3]`), the trait /// returns a type of `&T`, but the actual type we assign to the /// *expression* is `T`. So this function just peels off the return /// type by one layer to yield `T`. - fn make_overloaded_lvalue_return_type(&self, + fn make_overloaded_place_return_type(&self, method: MethodCallee<'tcx>) -> ty::TypeAndMut<'tcx> { @@ -2219,7 +2288,7 @@ fn make_overloaded_lvalue_return_type(&self, let ret_ty = method.sig.output(); // method returns &T, but the type as visible to user is T, so deref - ret_ty.builtin_deref(true, NoPreference).unwrap() + ret_ty.builtin_deref(true).unwrap() } fn lookup_indexing(&self, @@ -2227,7 +2296,7 @@ fn lookup_indexing(&self, base_expr: &'gcx hir::Expr, base_ty: Ty<'tcx>, idx_ty: Ty<'tcx>, - lvalue_pref: LvaluePreference) + needs: Needs) -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)> { // FIXME(#18741) -- this is almost but not quite the same as the @@ -2237,7 +2306,7 @@ fn lookup_indexing(&self, let mut autoderef = self.autoderef(base_expr.span, base_ty); let mut result = None; while result.is_none() && autoderef.next().is_some() { - result = self.try_index_step(expr, base_expr, &autoderef, lvalue_pref, idx_ty); + result = self.try_index_step(expr, base_expr, &autoderef, needs, idx_ty); } autoderef.finalize(); result @@ -2252,7 +2321,7 @@ fn try_index_step(&self, expr: &hir::Expr, base_expr: &hir::Expr, autoderef: &Autoderef<'a, 'gcx, 'tcx>, - lvalue_pref: LvaluePreference, + needs: Needs, index_ty: Ty<'tcx>) -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)> { @@ -2279,17 +2348,28 @@ fn try_index_step(&self, // type from the method signature. // If some lookup succeeded, install method in table let input_ty = self.next_ty_var(TypeVariableOrigin::AutoDeref(base_expr.span)); - let method = self.try_overloaded_lvalue_op( - expr.span, self_ty, &[input_ty], lvalue_pref, LvalueOp::Index); + let method = self.try_overloaded_place_op( + expr.span, self_ty, &[input_ty], needs, PlaceOp::Index); let result = method.map(|ok| { debug!("try_index_step: success, using overloaded indexing"); let method = self.register_infer_ok_obligations(ok); - let mut adjustments = autoderef.adjust_steps(lvalue_pref); + let mut adjustments = autoderef.adjust_steps(needs); if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty { + let mutbl = match mt.mutbl { + hir::MutImmutable => AutoBorrowMutability::Immutable, + hir::MutMutable => AutoBorrowMutability::Mutable { + // FIXME (#46747): arguably indexing is + // "just another kind of call"; perhaps it + // would be more consistent to allow + // two-phase borrows for .index() + // receivers here. + allow_two_phase_borrow: false, + } + }; adjustments.push(Adjustment { - kind: Adjust::Borrow(AutoBorrow::Ref(region, mt.mutbl)), + kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)), target: self.tcx.mk_ref(region, ty::TypeAndMut { mutbl: mt.mutbl, ty: adjusted_ty @@ -2305,7 +2385,7 @@ fn try_index_step(&self, self.apply_adjustments(base_expr, adjustments); self.write_method_call(expr.hir_id, method); - (input_ty, self.make_overloaded_lvalue_return_type(method).ty) + (input_ty, self.make_overloaded_place_return_type(method).ty) }); if result.is_some() { return result; @@ -2315,45 +2395,45 @@ fn try_index_step(&self, None } - fn resolve_lvalue_op(&self, op: LvalueOp, is_mut: bool) -> (Option, Symbol) { + fn resolve_place_op(&self, op: PlaceOp, is_mut: bool) -> (Option, Symbol) { let (tr, name) = match (op, is_mut) { - (LvalueOp::Deref, false) => + (PlaceOp::Deref, false) => (self.tcx.lang_items().deref_trait(), "deref"), - (LvalueOp::Deref, true) => + (PlaceOp::Deref, true) => (self.tcx.lang_items().deref_mut_trait(), "deref_mut"), - (LvalueOp::Index, false) => + (PlaceOp::Index, false) => (self.tcx.lang_items().index_trait(), "index"), - (LvalueOp::Index, true) => + (PlaceOp::Index, true) => (self.tcx.lang_items().index_mut_trait(), "index_mut"), }; (tr, Symbol::intern(name)) } - fn try_overloaded_lvalue_op(&self, + fn try_overloaded_place_op(&self, span: Span, base_ty: Ty<'tcx>, arg_tys: &[Ty<'tcx>], - lvalue_pref: LvaluePreference, - op: LvalueOp) + needs: Needs, + op: PlaceOp) -> Option>> { - debug!("try_overloaded_lvalue_op({:?},{:?},{:?},{:?})", + debug!("try_overloaded_place_op({:?},{:?},{:?},{:?})", span, base_ty, - lvalue_pref, + needs, op); - // Try Mut first, if preferred. - let (mut_tr, mut_op) = self.resolve_lvalue_op(op, true); - let method = match (lvalue_pref, mut_tr) { - (PreferMutLvalue, Some(trait_did)) => { + // Try Mut first, if needed. + let (mut_tr, mut_op) = self.resolve_place_op(op, true); + let method = match (needs, mut_tr) { + (Needs::MutPlace, Some(trait_did)) => { self.lookup_method_in_trait(span, mut_op, trait_did, base_ty, Some(arg_tys)) } _ => None, }; // Otherwise, fall back to the immutable version. - let (imm_tr, imm_op) = self.resolve_lvalue_op(op, false); + let (imm_tr, imm_op) = self.resolve_place_op(op, false); let method = match (method, imm_tr) { (None, Some(trait_did)) => { self.lookup_method_in_trait(span, imm_op, trait_did, base_ty, Some(arg_tys)) @@ -2738,18 +2818,18 @@ fn check_expr_meets_expectation_or_error(&self, fn check_expr_coercable_to_type(&self, expr: &'gcx hir::Expr, expected: Ty<'tcx>) -> Ty<'tcx> { - self.check_expr_coercable_to_type_with_lvalue_pref(expr, expected, NoPreference) + self.check_expr_coercable_to_type_with_needs(expr, expected, Needs::None) } - fn check_expr_coercable_to_type_with_lvalue_pref(&self, - expr: &'gcx hir::Expr, - expected: Ty<'tcx>, - lvalue_pref: LvaluePreference) - -> Ty<'tcx> { - let ty = self.check_expr_with_expectation_and_lvalue_pref( + fn check_expr_coercable_to_type_with_needs(&self, + expr: &'gcx hir::Expr, + expected: Ty<'tcx>, + needs: Needs) + -> Ty<'tcx> { + let ty = self.check_expr_with_expectation_and_needs( expr, ExpectHasType(expected), - lvalue_pref); + needs); self.demand_coerce(expr, ty, expected) } @@ -2761,16 +2841,15 @@ fn check_expr_with_hint(&self, expr: &'gcx hir::Expr, fn check_expr_with_expectation(&self, expr: &'gcx hir::Expr, expected: Expectation<'tcx>) -> Ty<'tcx> { - self.check_expr_with_expectation_and_lvalue_pref(expr, expected, NoPreference) + self.check_expr_with_expectation_and_needs(expr, expected, Needs::None) } fn check_expr(&self, expr: &'gcx hir::Expr) -> Ty<'tcx> { self.check_expr_with_expectation(expr, NoExpectation) } - fn check_expr_with_lvalue_pref(&self, expr: &'gcx hir::Expr, - lvalue_pref: LvaluePreference) -> Ty<'tcx> { - self.check_expr_with_expectation_and_lvalue_pref(expr, NoExpectation, lvalue_pref) + fn check_expr_with_needs(&self, expr: &'gcx hir::Expr, needs: Needs) -> Ty<'tcx> { + self.check_expr_with_expectation_and_needs(expr, NoExpectation, needs) } // determine the `self` type, using fresh variables for all variables @@ -2853,11 +2932,11 @@ fn check_method_call(&self, span: Span, args: &'gcx [hir::Expr], expected: Expectation<'tcx>, - lvalue_pref: LvaluePreference) -> Ty<'tcx> { + needs: Needs) -> Ty<'tcx> { let rcvr = &args[0]; - let rcvr_t = self.check_expr_with_lvalue_pref(&rcvr, lvalue_pref); + let rcvr_t = self.check_expr_with_needs(&rcvr, needs); // no need to check for bot/err -- callee does that - let rcvr_t = self.structurally_resolved_type(expr.span, rcvr_t); + let rcvr_t = self.structurally_resolved_type(args[0].span, rcvr_t); let method = match self.lookup_method(rcvr_t, segment, @@ -2965,10 +3044,10 @@ fn check_then_else(&self, // Check field access expressions fn check_field(&self, expr: &'gcx hir::Expr, - lvalue_pref: LvaluePreference, + needs: Needs, base: &'gcx hir::Expr, field: &Spanned) -> Ty<'tcx> { - let expr_t = self.check_expr_with_lvalue_pref(base, lvalue_pref); + let expr_t = self.check_expr_with_needs(base, needs); let expr_t = self.structurally_resolved_type(expr.span, expr_t); let mut private_candidate = None; @@ -2983,7 +3062,7 @@ fn check_field(&self, if let Some(field) = fields.iter().find(|f| f.name.to_ident() == ident) { let field_ty = self.field_ty(expr.span, field, substs); if field.vis.is_accessible_from(def_scope, self.tcx) { - let adjustments = autoderef.adjust_steps(lvalue_pref); + let adjustments = autoderef.adjust_steps(needs); self.apply_adjustments(base, adjustments); autoderef.finalize(); @@ -3102,10 +3181,10 @@ fn name_series_display(&self, names: Vec) -> String { // Check tuple index expressions fn check_tup_field(&self, expr: &'gcx hir::Expr, - lvalue_pref: LvaluePreference, + needs: Needs, base: &'gcx hir::Expr, idx: codemap::Spanned) -> Ty<'tcx> { - let expr_t = self.check_expr_with_lvalue_pref(base, lvalue_pref); + let expr_t = self.check_expr_with_needs(base, needs); let expr_t = self.structurally_resolved_type(expr.span, expr_t); let mut private_candidate = None; @@ -3146,7 +3225,7 @@ fn check_tup_field(&self, }; if let Some(field_ty) = field { - let adjustments = autoderef.adjust_steps(lvalue_pref); + let adjustments = autoderef.adjust_steps(needs); self.apply_adjustments(base, adjustments); autoderef.finalize(); return field_ty; @@ -3476,10 +3555,10 @@ fn check_expr_struct(&self, /// Note that inspecting a type's structure *directly* may expose the fact /// that there are actually multiple representations for `TyError`, so avoid /// that when err needs to be handled differently. - fn check_expr_with_expectation_and_lvalue_pref(&self, + fn check_expr_with_expectation_and_needs(&self, expr: &'gcx hir::Expr, expected: Expectation<'tcx>, - lvalue_pref: LvaluePreference) -> Ty<'tcx> { + needs: Needs) -> Ty<'tcx> { debug!(">> typechecking: expr={:?} expected={:?}", expr, expected); @@ -3492,7 +3571,7 @@ fn check_expr_with_expectation_and_lvalue_pref(&self, self.diverges.set(Diverges::Maybe); self.has_errors.set(false); - let ty = self.check_expr_kind(expr, expected, lvalue_pref); + let ty = self.check_expr_kind(expr, expected, needs); // Warn for non-block expressions with diverging children. match expr.node { @@ -3526,7 +3605,7 @@ fn check_expr_with_expectation_and_lvalue_pref(&self, fn check_expr_kind(&self, expr: &'gcx hir::Expr, expected: Expectation<'tcx>, - lvalue_pref: LvaluePreference) -> Ty<'tcx> { + needs: Needs) -> Ty<'tcx> { let tcx = self.tcx; let id = expr.id; match expr.node { @@ -3560,30 +3639,39 @@ fn check_expr_kind(&self, NoExpectation } }; - let lvalue_pref = match unop { - hir::UnDeref => lvalue_pref, - _ => NoPreference + let needs = match unop { + hir::UnDeref => needs, + _ => Needs::None }; - let mut oprnd_t = self.check_expr_with_expectation_and_lvalue_pref(&oprnd, + let mut oprnd_t = self.check_expr_with_expectation_and_needs(&oprnd, expected_inner, - lvalue_pref); + needs); if !oprnd_t.references_error() { oprnd_t = self.structurally_resolved_type(expr.span, oprnd_t); match unop { hir::UnDeref => { - if let Some(mt) = oprnd_t.builtin_deref(true, NoPreference) { + if let Some(mt) = oprnd_t.builtin_deref(true) { oprnd_t = mt.ty; } else if let Some(ok) = self.try_overloaded_deref( - expr.span, oprnd_t, lvalue_pref) { + expr.span, oprnd_t, needs) { let method = self.register_infer_ok_obligations(ok); if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty { + let mutbl = match mt.mutbl { + hir::MutImmutable => AutoBorrowMutability::Immutable, + hir::MutMutable => AutoBorrowMutability::Mutable { + // (It shouldn't actually matter for unary ops whether + // we enable two-phase borrows or not, since a unary + // op has no additional operands.) + allow_two_phase_borrow: false, + } + }; self.apply_adjustments(oprnd, vec![Adjustment { - kind: Adjust::Borrow(AutoBorrow::Ref(region, mt.mutbl)), + kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)), target: method.sig.inputs()[0] }]); } - oprnd_t = self.make_overloaded_lvalue_return_type(method).ty; + oprnd_t = self.make_overloaded_place_return_type(method).ty; self.write_method_call(expr.hir_id, method); } else { type_error_struct!(tcx.sess, expr.span, oprnd_t, E0614, @@ -3614,8 +3702,8 @@ fn check_expr_kind(&self, let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| { match ty.sty { ty::TyRef(_, ref mt) | ty::TyRawPtr(ref mt) => { - if self.tcx.expr_is_lval(&oprnd) { - // Lvalues may legitimately have unsized types. + if self.is_place_expr(&oprnd) { + // Places may legitimately have unsized types. // For example, dereferences of a fat pointer and // the last field of a struct can be unsized. ExpectHasType(mt.ty) @@ -3626,8 +3714,8 @@ fn check_expr_kind(&self, _ => NoExpectation } }); - let lvalue_pref = LvaluePreference::from_mutbl(mutbl); - let ty = self.check_expr_with_expectation_and_lvalue_pref(&oprnd, hint, lvalue_pref); + let needs = Needs::maybe_mut_place(mutbl); + let ty = self.check_expr_with_expectation_and_needs(&oprnd, hint, needs); let tm = ty::TypeAndMut { ty: ty, mutbl: mutbl }; if tm.ty.references_error() { @@ -3771,7 +3859,7 @@ fn check_expr_kind(&self, tcx.types.never } hir::ExprAssign(ref lhs, ref rhs) => { - let lhs_ty = self.check_expr_with_lvalue_pref(&lhs, PreferMutLvalue); + let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace); let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty); @@ -3783,7 +3871,7 @@ fn check_expr_kind(&self, _ => { // Only check this if not in an `if` condition, as the // mistyped comparison help is more appropriate. - if !self.tcx.expr_is_lval(&lhs) { + if !self.is_place_expr(&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") @@ -3872,7 +3960,7 @@ fn check_expr_kind(&self, self.check_call(expr, &callee, args, expected) } hir::ExprMethodCall(ref segment, span, ref args) => { - self.check_method_call(expr, segment, span, args, expected, lvalue_pref) + self.check_method_call(expr, segment, span, args, expected, needs) } hir::ExprCast(ref e, ref t) => { // Find the type of `e`. Supply hints based on the type we are casting to, @@ -4015,13 +4103,13 @@ fn check_expr_kind(&self, self.check_expr_struct(expr, expected, qpath, fields, base_expr) } hir::ExprField(ref base, ref field) => { - self.check_field(expr, lvalue_pref, &base, field) + self.check_field(expr, needs, &base, field) } hir::ExprTupField(ref base, idx) => { - self.check_tup_field(expr, lvalue_pref, &base, idx) + self.check_tup_field(expr, needs, &base, idx) } hir::ExprIndex(ref base, ref idx) => { - let base_t = self.check_expr_with_lvalue_pref(&base, lvalue_pref); + let base_t = self.check_expr_with_needs(&base, needs); let idx_t = self.check_expr(&idx); if base_t.references_error() { @@ -4030,7 +4118,7 @@ fn check_expr_kind(&self, idx_t } else { let base_t = self.structurally_resolved_type(expr.span, base_t); - match self.lookup_indexing(expr, base, base_t, idx_t, lvalue_pref) { + match self.lookup_indexing(expr, base, base_t, idx_t, needs) { Some((index_ty, element_ty)) => { self.demand_coerce(idx, idx_t, index_ty); element_ty @@ -4178,9 +4266,9 @@ pub fn check_decl_initializer(&self, // ref mut, for soundness (issue #23116). In particular, in // the latter case, we need to be clear that the type of the // referent for the reference that results is *equal to* the - // type of the lvalue it is referencing, and not some + // type of the place it is referencing, and not some // supertype thereof. - let init_ty = self.check_expr_with_lvalue_pref(init, LvaluePreference::from_mutbl(m)); + let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m)); self.demand_eqtype(init.span, local_ty, init_ty); init_ty } else { @@ -4809,6 +4897,8 @@ pub fn instantiate_value_path(&self, } } + self.check_rustc_args_require_const(def.def_id(), node_id, span); + debug!("instantiate_value_path: type of {:?} is {:?}", node_id, ty_substituted); @@ -4816,6 +4906,36 @@ pub fn instantiate_value_path(&self, ty_substituted } + fn check_rustc_args_require_const(&self, + def_id: DefId, + node_id: ast::NodeId, + span: Span) { + // We're only interested in functions tagged with + // #[rustc_args_required_const], so ignore anything that's not. + if !self.tcx.has_attr(def_id, "rustc_args_required_const") { + return + } + + // If our calling expression is indeed the function itself, we're good! + // If not, generate an error that this can only be called directly. + match self.tcx.hir.get(self.tcx.hir.get_parent_node(node_id)) { + Node::NodeExpr(expr) => { + match expr.node { + hir::ExprCall(ref callee, ..) => { + if callee.id == node_id { + return + } + } + _ => {} + } + } + _ => {} + } + + self.tcx.sess.span_err(span, "this function can only be invoked \ + directly, not through a function pointer"); + } + /// Report errors if the provided parameters are too few or too many. fn check_path_parameter_count(&self, span: Span, @@ -5023,7 +5143,7 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let lifetime_count = generics.lifetimes().count(); for leaf_ty in ty.walk() { - if let ty::TyParam(ParamTy {idx, ..}) = leaf_ty.sty { + if let ty::TyParam(ty::ParamTy {idx, ..}) = leaf_ty.sty { debug!("Found use of ty param num {}", idx); tps_used[idx as usize - lifetime_count] = true; } else if let ty::TyError = leaf_ty.sty { diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index e099d1c0c25..a6776a0fe86 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -10,11 +10,11 @@ //! Code related to processing overloaded binary and unary operators. -use super::FnCtxt; +use super::{FnCtxt, Needs}; use super::method::MethodCallee; -use rustc::ty::{self, Ty, TypeFoldable, NoPreference, PreferMutLvalue, TypeVariants}; +use rustc::ty::{self, Ty, TypeFoldable, TypeVariants}; use rustc::ty::TypeVariants::{TyStr, TyRef}; -use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow}; +use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability}; use rustc::infer::type_variable::TypeVariableOrigin; use errors; use syntax_pos::Span; @@ -40,10 +40,9 @@ pub fn check_binop_assign(&self, return_ty }; - let tcx = self.tcx; - if !tcx.expr_is_lval(lhs_expr) { + if !self.is_place_expr(lhs_expr) { struct_span_err!( - tcx.sess, lhs_expr.span, + self.tcx.sess, lhs_expr.span, E0067, "invalid left-hand side expression") .span_label( lhs_expr.span, @@ -166,18 +165,18 @@ fn check_overloaded_binop(&self, op, is_assign); - let lhs_pref = match is_assign { - IsAssign::Yes => PreferMutLvalue, - IsAssign::No => NoPreference + let lhs_needs = match is_assign { + IsAssign::Yes => Needs::MutPlace, + IsAssign::No => Needs::None }; // Find a suitable supertype of the LHS expression's type, by coercing to // a type variable, to pass as the `Self` to the trait, avoiding invariant // trait matching creating lifetime constraints that are too strict. // E.g. adding `&'a T` and `&'b T`, given `&'x T: Add<&'x T>`, will result // in `&'a T <: &'x T` and `&'b T <: &'x T`, instead of `'a = 'b = 'x`. - let lhs_ty = self.check_expr_coercable_to_type_with_lvalue_pref(lhs_expr, + let lhs_ty = self.check_expr_coercable_to_type_with_needs(lhs_expr, self.next_ty_var(TypeVariableOrigin::MiscVariable(lhs_expr.span)), - lhs_pref); + lhs_needs); let lhs_ty = self.resolve_type_vars_with_obligations(lhs_ty); // NB: As we have not yet type-checked the RHS, we don't have the @@ -199,8 +198,17 @@ fn check_overloaded_binop(&self, let by_ref_binop = !op.node.is_by_value(); if is_assign == IsAssign::Yes || by_ref_binop { if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty { + let mutbl = match mt.mutbl { + hir::MutImmutable => AutoBorrowMutability::Immutable, + hir::MutMutable => AutoBorrowMutability::Mutable { + // For initial two-phase borrow + // deployment, conservatively omit + // overloaded binary ops. + allow_two_phase_borrow: false, + } + }; let autoref = Adjustment { - kind: Adjust::Borrow(AutoBorrow::Ref(region, mt.mutbl)), + kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)), target: method.sig.inputs()[0] }; self.apply_adjustments(lhs_expr, vec![autoref]); @@ -208,8 +216,17 @@ fn check_overloaded_binop(&self, } if by_ref_binop { if let ty::TyRef(region, mt) = method.sig.inputs()[1].sty { + let mutbl = match mt.mutbl { + hir::MutImmutable => AutoBorrowMutability::Immutable, + hir::MutMutable => AutoBorrowMutability::Mutable { + // For initial two-phase borrow + // deployment, conservatively omit + // overloaded binary ops. + allow_two_phase_borrow: false, + } + }; let autoref = Adjustment { - kind: Adjust::Borrow(AutoBorrow::Ref(region, mt.mutbl)), + kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)), target: method.sig.inputs()[1] }; // HACK(eddyb) Bypass checks due to reborrows being in diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 64063ec5bed..b5bf59fef9a 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -1063,7 +1063,7 @@ fn link_autoref(&self, match *autoref { adjustment::AutoBorrow::Ref(r, m) => { self.link_region(expr.span, r, - ty::BorrowKind::from_mutbl(m), expr_cmt); + ty::BorrowKind::from_mutbl(m.into()), expr_cmt); } adjustment::AutoBorrow::RawPtr(m) => { diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index 07d5f813cbb..88a2dc817ae 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -82,29 +82,37 @@ fn check_for_overlapping_inherent_impls(&self, ty_def_id: DefId) { for (i, &impl1_def_id) in impls.iter().enumerate() { for &impl2_def_id in &impls[(i + 1)..] { - let used_to_be_allowed = self.tcx.infer_ctxt().enter(|infcx| { - if let Some(overlap) = - traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id, - IntercrateMode::Issue43355) - { + let used_to_be_allowed = traits::overlapping_impls( + self.tcx, + impl1_def_id, + impl2_def_id, + IntercrateMode::Issue43355, + |overlap| { self.check_for_common_items_in_impls( - impl1_def_id, impl2_def_id, overlap, false); + impl1_def_id, + impl2_def_id, + overlap, + false, + ); false - } else { - true - } - }); + }, + || true, + ); if used_to_be_allowed { - self.tcx.infer_ctxt().enter(|infcx| { - if let Some(overlap) = - traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id, - IntercrateMode::Fixed) - { - self.check_for_common_items_in_impls( - impl1_def_id, impl2_def_id, overlap, true); - } - }); + traits::overlapping_impls( + self.tcx, + impl1_def_id, + impl2_def_id, + IntercrateMode::Fixed, + |overlap| self.check_for_common_items_in_impls( + impl1_def_id, + impl2_def_id, + overlap, + true, + ), + || (), + ); } } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 7a91827faef..d5328a18c22 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -355,41 +355,35 @@ fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -fn ensure_no_ty_param_bounds(tcx: TyCtxt, - span: Span, - generics: &hir::Generics, - thing: &'static str) { +fn ensure_no_param_bounds(tcx: TyCtxt, + span: Span, + generics: &hir::Generics, + thing: &'static str) { let mut warn = false; for ty_param in generics.ty_params() { - for bound in ty_param.bounds.iter() { - match *bound { - hir::TraitTyParamBound(..) => { - warn = true; - } - hir::RegionTyParamBound(..) => { } - } + if !ty_param.bounds.is_empty() { + warn = true; } } - for predicate in generics.where_clause.predicates.iter() { - match *predicate { - hir::WherePredicate::BoundPredicate(..) => { - warn = true; - } - hir::WherePredicate::RegionPredicate(..) => { } - hir::WherePredicate::EqPredicate(..) => { } + for lft_param in generics.lifetimes() { + if !lft_param.bounds.is_empty() { + warn = true; } } + if !generics.where_clause.predicates.is_empty() { + warn = true; + } + if warn { // According to accepted RFC #XXX, we should // eventually accept these, but it will not be // part of this PR. Still, convert to warning to // make bootstrapping easier. span_warn!(tcx.sess, span, E0122, - "trait bounds are not (yet) enforced \ - in {} definitions", + "generic bounds are ignored in {}", thing); } } @@ -455,7 +449,7 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { } }, hir::ItemTy(_, ref generics) => { - ensure_no_ty_param_bounds(tcx, it.span, generics, "type"); + ensure_no_param_bounds(tcx, it.span, generics, "type aliases"); tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 18d573bd581..f59948e9fc4 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -732,8 +732,8 @@ fn main() { "##, E0067: r##" -The left-hand side of a compound assignment expression must be an lvalue -expression. An lvalue expression represents a memory location and includes +The left-hand side of a compound assignment expression must be a place +expression. A place expression represents a memory location and includes item paths (ie, namespaced variables), dereferences, indexing expressions, and field references. @@ -742,7 +742,7 @@ fn main() { ```compile_fail,E0067 use std::collections::LinkedList; -// Bad: assignment to non-lvalue expression +// Bad: assignment to non-place expression LinkedList::new() += 1; // ... @@ -783,14 +783,14 @@ fn foo() -> u8 { "##, E0070: r##" -The left-hand side of an assignment operator must be an lvalue expression. An -lvalue expression represents a memory location and can be a variable (with +The left-hand side of an assignment operator must be a place expression. An +place expression represents a memory location and can be a variable (with optional namespacing), a dereference, an indexing expression or a field reference. More details can be found in the [Expressions] section of the Reference. -[Expressions]: https://doc.rust-lang.org/reference/expressions.html#lvalues-rvalues-and-temporaries +[Expressions]: https://doc.rust-lang.org/reference/expressions.html#places-rvalues-and-temporaries Now, we can go further. Here are some erroneous code examples: @@ -806,7 +806,7 @@ fn some_other_func() {} fn some_function() { SOME_CONST = 14; // error : a constant value cannot be changed! - 1 = 3; // error : 1 isn't a valid lvalue! + 1 = 3; // error : 1 isn't a valid place! some_other_func() = 4; // error : we can't assign value to a function! SomeStruct.x = 12; // error : SomeStruct a structure name but it is used // like a variable! @@ -4698,6 +4698,55 @@ struct LengthWithUnit { the alignment of the zero-sized type is less than or equal to the data field's alignment. "##, + + +E0908: r##" +A method was called on a raw pointer whose inner type wasn't completely known. + +For example, you may have done something like: + +```compile_fail +# #![deny(warnings)] +let foo = &1; +let bar = foo as *const _; +if bar.is_null() { + // ... +} +``` + +Here, the type of `bar` isn't known; it could be a pointer to anything. Instead, +specify a type for the pointer (preferably something that makes sense for the +thing you're pointing to): + +``` +let foo = &1; +let bar = foo as *const i32; +if bar.is_null() { + // ... +} +``` + +Even though `is_null()` exists as a method on any raw pointer, Rust shows this +error because Rust allows for `self` to have arbitrary types (behind the +arbitrary_self_types feature flag). + +This means that someone can specify such a function: + +```ignore (cannot-doctest-feature-doesnt-exist-yet) +impl Foo { + fn is_null(self: *const Self) -> bool { + // do something else + } +} +``` + +and now when you call `.is_null()` on a raw pointer to `Foo`, there's ambiguity. + +Given that we don't know what type the pointer is, and there's potential +ambiguity for some types, we disallow calling methods on raw pointers when +the type is unknown. +"##, + } register_diagnostics! { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0929b833c19..66b5f3b5ea3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1051,6 +1051,10 @@ fn clean(&self, cx: &DocContext) -> Attributes { if UnstableFeatures::from_environment().is_nightly_build() { let dox = attrs.collapsed_doc_value().unwrap_or_else(String::new); for link in markdown_links(&dox, cx.render_type) { + // bail early for real links + if link.contains('/') { + continue; + } let (def, fragment) = { let mut kind = PathKind::Unknown; let path_str = if let Some(prefix) = @@ -2447,7 +2451,12 @@ fn clean(&self, cx: &DocContext) -> Type { let def_id = cx.tcx.hir.body_owner_def_id(n); let param_env = cx.tcx.param_env(def_id); let substs = Substs::identity_for_item(cx.tcx, def_id); - let n = cx.tcx.const_eval(param_env.and((def_id, substs))).unwrap(); + let n = cx.tcx.const_eval(param_env.and((def_id, substs))).unwrap_or_else(|_| { + cx.tcx.mk_const(ty::Const { + val: ConstVal::Unevaluated(def_id, substs), + ty: cx.tcx.types.usize + }) + }); let n = if let ConstVal::Integral(ConstInt::Usize(n)) = n.val { n.to_string() } else if let ConstVal::Unevaluated(def_id, _) = n.val { @@ -2577,7 +2586,9 @@ fn clean(&self, cx: &DocContext) -> Type { let mut n = cx.tcx.lift(&n).unwrap(); if let ConstVal::Unevaluated(def_id, substs) = n.val { let param_env = cx.tcx.param_env(def_id); - n = cx.tcx.const_eval(param_env.and((def_id, substs))).unwrap() + if let Ok(new_n) = cx.tcx.const_eval(param_env.and((def_id, substs))) { + n = new_n; + } }; let n = if let ConstVal::Integral(ConstInt::Usize(n)) = n.val { n.to_string() diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 63ebb16e5e0..0eb4f9ba7e5 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -106,7 +106,9 @@ pub fn where_clauses(cx: &DocContext, clauses: Vec) -> Vec { } PP::Parenthesized { ref mut output, .. } => { assert!(output.is_none()); - *output = Some(rhs.clone()); + if *rhs != clean::Type::Tuple(Vec::new()) { + *output = Some(rhs.clone()); + } } }; true diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index dce0c4b001a..82ced00644d 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -872,7 +872,7 @@ fn escape_href(ob: &mut String, s: &str) { let link_out = format!("{content}", link = link_buf, title = title.map_or(String::new(), - |t| format!(" title=\"{}\"", t)), + |t| format!(" title=\"{}\"", Escape(&t))), content = content.unwrap_or(String::new())); unsafe { hoedown_buffer_put(ob, link_out.as_ptr(), link_out.len()); } diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 0f9e7001c15..f688be89bee 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -47,6 +47,8 @@ // 2 for "In Return Types" var currentTab = 0; + var themesWidth = null; + function hasClass(elem, className) { if (elem && className && elem.className) { var elemClass = elem.className; @@ -121,10 +123,9 @@ sidebar.appendChild(div); } } - document.getElementsByTagName("body")[0].style.marginTop = '45px'; - var themePicker = document.getElementById("theme-picker"); - if (themePicker) { - themePicker.style.position = "fixed"; + var themePicker = document.getElementsByClassName("theme-picker"); + if (themePicker && themePicker.length > 0) { + themePicker[0].style.display = "none"; } } @@ -140,9 +141,9 @@ filler.remove(); } document.getElementsByTagName("body")[0].style.marginTop = ''; - var themePicker = document.getElementById("theme-picker"); - if (themePicker) { - themePicker.style.position = "absolute"; + var themePicker = document.getElementsByClassName("theme-picker"); + if (themePicker && themePicker.length > 0) { + themePicker[0].style.display = null; } } diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index d2eeb2e15b3..cd4f2cfa678 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -181,15 +181,19 @@ nav.sub { overflow: auto; } -.sidebar .current { +.sidebar .block > ul > li { margin-right: -20px; } -.content, nav { max-width: 960px; } +.content, nav { + max-width: 960px; +} /* Everything else */ -.js-only, .hidden { display: none !important; } +.js-only, .hidden { + display: none !important; +} .sidebar img { margin: 20px auto; @@ -218,7 +222,9 @@ nav.sub { border: none; } -.location a:first-child { font-weight: 500; } +.location a:first-child { + font-weight: 500; +} .block { padding: 0; @@ -299,7 +305,9 @@ nav.sub { -ms-user-select: none; user-select: none; } -.line-numbers span { cursor: pointer; } +.line-numbers span { + cursor: pointer; +} .docblock-short p { display: inline; @@ -317,7 +325,9 @@ nav.sub { text-overflow: ellipsis; margin: 0; } -.docblock-short code { white-space: nowrap; } +.docblock-short code { + white-space: nowrap; +} .docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 { border-bottom: 1px solid; @@ -384,7 +394,9 @@ h4 > code, h3 > code, .invisible > code { display: inline-block; } -#main { position: relative; } +#main { + position: relative; +} #main > .since { top: inherit; font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; @@ -428,7 +440,9 @@ h4 > code, h3 > code, .invisible > code { padding: 0; } -.content .item-list li { margin-bottom: 1em; } +.content .item-list li { + margin-bottom: 1em; +} .content .multi-column { -moz-column-count: 5; @@ -856,6 +870,7 @@ span.since { display: block; border-bottom: 1px solid; border-right: 1px solid; + height: 45px; } .sidebar-elems { @@ -875,13 +890,19 @@ span.since { } nav.sub { - margin: 0 auto; + width: calc(100% - 32px); + float: right; } .content { margin-left: 0px; } + #main { + margin-top: 45px; + padding: 0; + } + .content .in-band { width: 100%; } @@ -1028,6 +1049,24 @@ h4 > .important-traits { .show-it { display: block; + width: 246px; + } + + .show-it > .block.items { + margin: 8px 0; + } + + .show-it > .block.items > ul { + margin: 0; + } + + .show-it > .block.items > ul > li { + text-align: center; + margin: 2px 0; + } + + .show-it > .block.items > ul > li > a { + font-size: 21px; } /* Because of ios, we need to actually have a full height sidebar title so the @@ -1184,8 +1223,8 @@ kbd { @media (max-width: 700px) { .theme-picker { - left: 109px; - top: 7px; + left: 10px; + top: 54px; z-index: 1; } } diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 4c6bcab72b7..2d0fe55f70d 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -112,10 +112,13 @@ pre { } .content .highlighted a, .content .highlighted span { color: #eee !important; } .content .highlighted.trait { background-color: #013191; } +.content .highlighted.mod, +.content .highlighted.externcrate { background-color: #afc6e4; } .content .highlighted.mod { background-color: #803a1b; } .content .highlighted.externcrate { background-color: #396bac; } .content .highlighted.enum { background-color: #5b4e68; } .content .highlighted.struct { background-color: #194e9f; } +.content .highlighted.union { background-color: #b7bd49; } .content .highlighted.fn, .content .highlighted.method, .content .highlighted.tymethod { background-color: #4950ed; } @@ -127,7 +130,7 @@ pre { .content .highlighted.primitive { background-color: #00708a; } .content span.enum, .content a.enum, .block a.current.enum { color: #82b089; } -.content span.struct, .content a.struct, .block a.current.struct { color: #ff794d; } +.content span.struct, .content a.struct, .block a.current.struct { color: #2dbfb8; } .content span.type, .content a.type, .block a.current.type { color: #ff7f00; } .content span.foreigntype, .content a.foreigntype, .block a.current.foreigntype { color: #dd7de8; } .content span.macro, .content a.macro, .block a.current.macro { color: #09bd00; } @@ -383,6 +386,6 @@ kbd { @media (max-width: 700px) { #theme-picker { - background: #353535; + background: #f0f0f0; } } diff --git a/src/librustdoc/html/static/themes/main.css b/src/librustdoc/html/static/themes/main.css index e0764640e91..2334a272855 100644 --- a/src/librustdoc/html/static/themes/main.css +++ b/src/librustdoc/html/static/themes/main.css @@ -130,7 +130,7 @@ pre { .content .highlighted.primitive { background-color: #9aecff; } .content span.enum, .content a.enum, .block a.current.enum { color: #508157; } -.content span.struct, .content a.struct, .block a.current.struct { color: #df3600; } +.content span.struct, .content a.struct, .block a.current.struct { color: #ad448e; } .content span.type, .content a.type, .block a.current.type { color: #ba5d00; } .content span.foreigntype, .content a.foreigntype, .block a.current.foreigntype { color: #cd00e2; } .content span.macro, .content a.macro, .block a.current.macro { color: #068000; } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index e39fe20310c..a72026c7d6b 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -91,6 +91,7 @@ pub mod html { pub mod visit_ast; pub mod visit_lib; pub mod test; +pub mod theme; use clean::AttributesExt; @@ -267,6 +268,11 @@ pub fn opts() -> Vec { "additional themes which will be added to the generated docs", "FILES") }), + unstable("theme-checker", |o| { + o.optmulti("", "theme-checker", + "check if given theme is valid", + "FILES") + }), ] } @@ -316,6 +322,31 @@ pub fn main_args(args: &[String]) -> isize { return 0; } + let to_check = matches.opt_strs("theme-checker"); + if !to_check.is_empty() { + let paths = theme::load_css_paths(include_bytes!("html/static/themes/main.css")); + let mut errors = 0; + + println!("rustdoc: [theme-checker] Starting tests!"); + for theme_file in to_check.iter() { + print!(" - Checking \"{}\"...", theme_file); + let (success, differences) = theme::test_theme_against(theme_file, &paths); + if !differences.is_empty() || !success { + println!(" FAILED"); + errors += 1; + if !differences.is_empty() { + println!("{}", differences.join("\n")); + } + } else { + println!(" OK"); + } + } + if errors != 0 { + return 1; + } + return 0; + } + if matches.free.is_empty() { print_error("missing file operand"); return 1; @@ -369,12 +400,24 @@ pub fn main_args(args: &[String]) -> isize { } let mut themes = Vec::new(); - for theme in matches.opt_strs("themes").iter().map(|s| PathBuf::from(&s)) { - if !theme.is_file() { - eprintln!("rustdoc: option --themes arguments must all be files"); - return 1; + if matches.opt_present("themes") { + let paths = theme::load_css_paths(include_bytes!("html/static/themes/main.css")); + + for (theme_file, theme_s) in matches.opt_strs("themes") + .iter() + .map(|s| (PathBuf::from(&s), s.to_owned())) { + if !theme_file.is_file() { + println!("rustdoc: option --themes arguments must all be files"); + return 1; + } + let (success, ret) = theme::test_theme_against(&theme_file, &paths); + if !success || !ret.is_empty() { + println!("rustdoc: invalid theme: \"{}\"", theme_s); + println!(" Check what's wrong with the \"theme-checker\" option"); + return 1; + } + themes.push(theme_file); } - themes.push(theme); } let external_html = match ExternalHtml::load( diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index d61b80c9aa0..087d88419bc 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -238,6 +238,7 @@ fn drop(&mut self) { )); let emitter = errors::emitter::EmitterWriter::new(box Sink(data.clone()), Some(codemap.clone()), + false, false); let old = io::set_panic(Some(box Sink(data.clone()))); let _bomb = Bomb(data.clone(), old.unwrap_or(box io::stdout())); diff --git a/src/librustdoc/theme.rs b/src/librustdoc/theme.rs new file mode 100644 index 00000000000..1e4f64f5c52 --- /dev/null +++ b/src/librustdoc/theme.rs @@ -0,0 +1,379 @@ +// Copyright 2012-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::HashSet; +use std::fs::File; +use std::hash::{Hash, Hasher}; +use std::io::Read; +use std::path::Path; + +macro_rules! try_something { + ($e:expr, $out:expr) => ({ + match $e { + Ok(c) => c, + Err(e) => { + eprintln!("rustdoc: got an error: {}", e); + return $out; + } + } + }) +} + +#[derive(Debug, Clone, Eq)] +pub struct CssPath { + pub name: String, + pub children: HashSet, +} + +// This PartialEq implementation IS NOT COMMUTATIVE!!! +// +// The order is very important: the second object must have all first's rules. +// However, the first doesn't require to have all second's rules. +impl PartialEq for CssPath { + fn eq(&self, other: &CssPath) -> bool { + if self.name != other.name { + false + } else { + for child in &self.children { + if !other.children.iter().any(|c| child == c) { + return false; + } + } + true + } + } +} + +impl Hash for CssPath { + fn hash(&self, state: &mut H) { + self.name.hash(state); + for x in &self.children { + x.hash(state); + } + } +} + +impl CssPath { + fn new(name: String) -> CssPath { + CssPath { + name, + children: HashSet::new(), + } + } +} + +/// All variants contain the position they occur. +#[derive(Debug, Clone, Copy)] +enum Events { + StartLineComment(usize), + StartComment(usize), + EndComment(usize), + InBlock(usize), + OutBlock(usize), +} + +impl Events { + fn get_pos(&self) -> usize { + match *self { + Events::StartLineComment(p) | + Events::StartComment(p) | + Events::EndComment(p) | + Events::InBlock(p) | + Events::OutBlock(p) => p, + } + } + + fn is_comment(&self) -> bool { + match *self { + Events::StartLineComment(_) | + Events::StartComment(_) | + Events::EndComment(_) => true, + _ => false, + } + } +} + +fn previous_is_line_comment(events: &[Events]) -> bool { + if let Some(&Events::StartLineComment(_)) = events.last() { + true + } else { + false + } +} + +fn is_line_comment(pos: usize, v: &[u8], events: &[Events]) -> bool { + if let Some(&Events::StartComment(_)) = events.last() { + return false; + } + pos + 1 < v.len() && v[pos + 1] == b'/' +} + +fn load_css_events(v: &[u8]) -> Vec { + let mut pos = 0; + let mut events = Vec::with_capacity(100); + + while pos < v.len() - 1 { + match v[pos] { + b'/' if pos + 1 < v.len() && v[pos + 1] == b'*' => { + events.push(Events::StartComment(pos)); + pos += 1; + } + b'/' if is_line_comment(pos, v, &events) => { + events.push(Events::StartLineComment(pos)); + pos += 1; + } + b'\n' if previous_is_line_comment(&events) => { + events.push(Events::EndComment(pos)); + } + b'*' if pos + 1 < v.len() && v[pos + 1] == b'/' => { + events.push(Events::EndComment(pos + 2)); + pos += 1; + } + b'{' if !previous_is_line_comment(&events) => { + if let Some(&Events::StartComment(_)) = events.last() { + pos += 1; + continue + } + events.push(Events::InBlock(pos + 1)); + } + b'}' if !previous_is_line_comment(&events) => { + if let Some(&Events::StartComment(_)) = events.last() { + pos += 1; + continue + } + events.push(Events::OutBlock(pos + 1)); + } + _ => {} + } + pos += 1; + } + events +} + +fn get_useful_next(events: &[Events], pos: &mut usize) -> Option { + while *pos < events.len() { + if !events[*pos].is_comment() { + return Some(events[*pos]); + } + *pos += 1; + } + None +} + +fn get_previous_positions(events: &[Events], mut pos: usize) -> Vec { + let mut ret = Vec::with_capacity(3); + + ret.push(events[pos].get_pos()); + if pos > 0 { + pos -= 1; + } + loop { + if pos < 1 || !events[pos].is_comment() { + let x = events[pos].get_pos(); + if *ret.last().unwrap() != x { + ret.push(x); + } else { + ret.push(0); + } + break + } + ret.push(events[pos].get_pos()); + pos -= 1; + } + if ret.len() & 1 != 0 && events[pos].is_comment() { + ret.push(0); + } + ret.iter().rev().cloned().collect() +} + +fn build_rule(v: &[u8], positions: &[usize]) -> String { + positions.chunks(2) + .map(|x| ::std::str::from_utf8(&v[x[0]..x[1]]).unwrap_or("")) + .collect::() + .trim() + .replace("\n", " ") + .replace("/", "") + .replace("\t", " ") + .replace("{", "") + .replace("}", "") + .split(" ") + .filter(|s| s.len() > 0) + .collect::>() + .join(" ") +} + +fn inner(v: &[u8], events: &[Events], pos: &mut usize) -> HashSet { + let mut paths = Vec::with_capacity(50); + + while *pos < events.len() { + if let Some(Events::OutBlock(_)) = get_useful_next(events, pos) { + *pos += 1; + break + } + if let Some(Events::InBlock(_)) = get_useful_next(events, pos) { + paths.push(CssPath::new(build_rule(v, &get_previous_positions(events, *pos)))); + *pos += 1; + } + while let Some(Events::InBlock(_)) = get_useful_next(events, pos) { + if let Some(ref mut path) = paths.last_mut() { + for entry in inner(v, events, pos).iter() { + path.children.insert(entry.clone()); + } + } + } + if let Some(Events::OutBlock(_)) = get_useful_next(events, pos) { + *pos += 1; + } + } + paths.iter().cloned().collect() +} + +pub fn load_css_paths(v: &[u8]) -> CssPath { + let events = load_css_events(v); + let mut pos = 0; + + let mut parent = CssPath::new("parent".to_owned()); + parent.children = inner(v, &events, &mut pos); + parent +} + +pub fn get_differences(against: &CssPath, other: &CssPath, v: &mut Vec) { + if against.name != other.name { + return + } else { + for child in &against.children { + let mut found = false; + let mut found_working = false; + let mut tmp = Vec::new(); + + for other_child in &other.children { + if child.name == other_child.name { + if child != other_child { + get_differences(child, other_child, &mut tmp); + } else { + found_working = true; + } + found = true; + break + } + } + if found == false { + v.push(format!(" Missing \"{}\" rule", child.name)); + } else if found_working == false { + v.extend(tmp.iter().cloned()); + } + } + } +} + +pub fn test_theme_against>(f: &P, against: &CssPath) -> (bool, Vec) { + let mut file = try_something!(File::open(f), (false, Vec::new())); + let mut data = Vec::with_capacity(1000); + + try_something!(file.read_to_end(&mut data), (false, Vec::new())); + let paths = load_css_paths(&data); + let mut ret = Vec::new(); + get_differences(against, &paths, &mut ret); + (true, ret) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_comments_in_rules() { + let text = r#" +rule a {} + +rule b, c +// a line comment +{} + +rule d +// another line comment +e {} + +rule f/* a multine + +comment*/{} + +rule g/* another multine + +comment*/h + +i {} + +rule j/*commeeeeent + +you like things like "{}" in there? :) +*/ +end {}"#; + + let against = r#" +rule a {} + +rule b, c {} + +rule d e {} + +rule f {} + +rule gh i {} + +rule j end {} +"#; + + let mut ret = Vec::new(); + get_differences(&load_css_paths(against.as_bytes()), + &load_css_paths(text.as_bytes()), + &mut ret); + assert!(ret.is_empty()); + } + + #[test] + fn test_text() { + let text = r#" +a +/* sdfs +*/ b +c // sdf +d {} +"#; + let paths = load_css_paths(text.as_bytes()); + assert!(paths.children.contains(&CssPath::new("a b c d".to_owned()))); + } + + #[test] + fn test_comparison() { + let x = r#" +a { + b { + c {} + } +} +"#; + + let y = r#" +a { + b {} +} +"#; + + let against = load_css_paths(y.as_bytes()); + let other = load_css_paths(x.as_bytes()); + + let mut ret = Vec::new(); + get_differences(&against, &other, &mut ret); + assert!(ret.is_empty()); + get_differences(&other, &against, &mut ret); + assert_eq!(ret, vec![" Missing \"c\" rule".to_owned()]); + } +} diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 3430ecabcbe..c1fe4a89d6a 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -48,3 +48,4 @@ jemalloc = ["alloc_jemalloc"] force_alloc_system = [] panic-unwind = ["panic_unwind"] profiler = ["profiler_builtins"] +wasm_syscall = [] diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index b01420f36a0..82a687ae5e4 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1384,9 +1384,14 @@ impl<'a, K, Q: ?Sized, V, S> Index<&'a Q> for HashMap { type Output = V; + /// Returns a reference to the value corresponding to the supplied key. + /// + /// # Panics + /// + /// Panics if the key is not present in the `HashMap`. #[inline] - fn index(&self, index: &Q) -> &V { - self.get(index).expect("no entry found for key") + fn index(&self, key: &Q) -> &V { + self.get(key).expect("no entry found for key") } } diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index 9810dede618..ecf68f29d6f 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -1531,6 +1531,7 @@ fn test_to_degrees() { assert!(nan.to_degrees().is_nan()); assert_eq!(inf.to_degrees(), inf); assert_eq!(neg_inf.to_degrees(), neg_inf); + assert_eq!(1_f32.to_degrees(), 57.2957795130823208767981548141051703); } #[test] diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index a19fe825f21..e91d3a32a50 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -1026,9 +1026,9 @@ pub fn as_ptr(&self) -> *const c_char { /// The returned slice will **not** contain the trailing nul terminator that this C /// string has. /// - /// > **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. + /// > **Note**: This method is currently implemented as a constant-time + /// > cast, but it is planned to alter its definition in the future to + /// > perform the length calculation whenever this method is called. /// /// # Examples /// @@ -1077,9 +1077,9 @@ pub fn to_bytes_with_nul(&self) -> &[u8] { /// it will return an error with details of where UTF-8 validation failed. /// /// > **Note**: This method is currently implemented to check for validity - /// > after a 0-cost cast, but it is planned to alter its definition in the - /// > future to perform the length calculation in addition to the UTF-8 - /// > check whenever this method is called. + /// > after a constant-time cast, but it is planned to alter its definition + /// > in the future to perform the length calculation in addition to the + /// > UTF-8 check whenever this method is called. /// /// [`&str`]: ../primitive.str.html /// @@ -1110,9 +1110,9 @@ pub fn to_str(&self) -> Result<&str, str::Utf8Error> { /// with the result. /// /// > **Note**: This method is currently implemented to check for validity - /// > after a 0-cost cast, but it is planned to alter its definition in the - /// > future to perform the length calculation in addition to the UTF-8 - /// > check whenever this method is called. + /// > after a constant-time cast, but it is planned to alter its definition + /// > in the future to perform the length calculation in addition to the + /// > UTF-8 check whenever this method is called. /// /// [`Cow`]: ../borrow/enum.Cow.html /// [`Borrowed`]: ../borrow/enum.Cow.html#variant.Borrowed diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index d1f3ccbd2c6..5cea389531f 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -482,20 +482,42 @@ pub fn metadata(&self) -> io::Result { self.inner.file_attr().map(Metadata) } - /// Creates a new independently owned handle to the underlying file. - /// - /// The returned `File` is a reference to the same state that this object - /// references. Both handles will read and write with the same cursor - /// position. + /// Create a new `File` instance that shares the same underlying file handle + /// as the existing `File` instance. Reads, writes, and seeks will affect + /// both `File` instances simultaneously. /// /// # Examples /// + /// Create two handles for a file named `foo.txt`: + /// /// ```no_run /// use std::fs::File; /// /// # fn foo() -> std::io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let file_copy = f.try_clone()?; + /// let mut file = File::open("foo.txt")?; + /// let file_copy = file.try_clone()?; + /// # Ok(()) + /// # } + /// ``` + /// + /// Assuming there’s a file named `foo.txt` with contents `abcdef\n`, create + /// two handles, seek one of them, and read the remaining bytes from the + /// other handle: + /// + /// ```no_run + /// use std::fs::File; + /// use std::io::SeekFrom; + /// use std::io::prelude::*; + /// + /// # fn foo() -> std::io::Result<()> { + /// let mut file = File::open("foo.txt")?; + /// let mut file_copy = file.try_clone()?; + /// + /// file.seek(SeekFrom::Start(3))?; + /// + /// let mut contents = vec![]; + /// file_copy.read_to_end(&mut contents)?; + /// assert_eq!(contents, b"def\n"); /// # Ok(()) /// # } /// ``` @@ -1001,7 +1023,7 @@ pub fn accessed(&self) -> io::Result { self.0.accessed().map(FromInner::from_inner) } - /// Returns the creation time listed in the this metadata. + /// Returns the creation time listed in this metadata. /// /// The returned value corresponds to the `birthtime` field of `stat` on /// Unix platforms and the `ftCreationTime` field on Windows platforms. diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index f0b41f30251..bdd675e6e2b 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -292,8 +292,8 @@ pub fn last_os_error() -> Error { /// # if cfg!(target_os = "linux") { /// use std::io; /// - /// let error = io::Error::from_raw_os_error(98); - /// assert_eq!(error.kind(), io::ErrorKind::AddrInUse); + /// let error = io::Error::from_raw_os_error(22); + /// assert_eq!(error.kind(), io::ErrorKind::InvalidInput); /// # } /// ``` /// @@ -303,8 +303,8 @@ pub fn last_os_error() -> Error { /// # if cfg!(windows) { /// use std::io; /// - /// let error = io::Error::from_raw_os_error(10048); - /// assert_eq!(error.kind(), io::ErrorKind::AddrInUse); + /// let error = io::Error::from_raw_os_error(10022); + /// assert_eq!(error.kind(), io::ErrorKind::InvalidInput); /// # } /// ``` #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index a8049e676b3..642fa8775a4 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -260,6 +260,7 @@ #![feature(core_intrinsics)] #![feature(dropck_eyepatch)] #![feature(exact_size_is_empty)] +#![feature(external_doc)] #![feature(fs_read_write)] #![feature(fixed_size_array)] #![feature(float_from_str_radix)] diff --git a/src/libstd/os/raw.rs b/src/libstd/os/raw.rs deleted file mode 100644 index 279caf8053a..00000000000 --- a/src/libstd/os/raw.rs +++ /dev/null @@ -1,107 +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. - -//! Raw OS-specific types for the current platform/architecture - -#![stable(feature = "raw_os", since = "1.1.0")] - -use fmt; - -#[cfg(any(all(target_os = "linux", any(target_arch = "aarch64", - target_arch = "arm", - target_arch = "powerpc", - target_arch = "powerpc64", - target_arch = "s390x")), - all(target_os = "android", any(target_arch = "aarch64", - target_arch = "arm")), - all(target_os = "l4re", target_arch = "x86_64"), - all(target_os = "openbsd", target_arch = "aarch64"), - all(target_os = "fuchsia", target_arch = "aarch64")))] -#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8; -#[cfg(not(any(all(target_os = "linux", any(target_arch = "aarch64", - target_arch = "arm", - target_arch = "powerpc", - target_arch = "powerpc64", - target_arch = "s390x")), - all(target_os = "android", any(target_arch = "aarch64", - target_arch = "arm")), - all(target_os = "l4re", target_arch = "x86_64"), - all(target_os = "openbsd", target_arch = "aarch64"), - all(target_os = "fuchsia", target_arch = "aarch64"))))] -#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8; -#[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8; -#[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8; -#[stable(feature = "raw_os", since = "1.1.0")] pub type c_short = i16; -#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ushort = u16; -#[stable(feature = "raw_os", since = "1.1.0")] pub type c_int = i32; -#[stable(feature = "raw_os", since = "1.1.0")] pub type c_uint = u32; -#[cfg(any(target_pointer_width = "32", windows))] -#[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i32; -#[cfg(any(target_pointer_width = "32", windows))] -#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u32; -#[cfg(all(target_pointer_width = "64", not(windows)))] -#[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i64; -#[cfg(all(target_pointer_width = "64", not(windows)))] -#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u64; -#[stable(feature = "raw_os", since = "1.1.0")] pub type c_longlong = i64; -#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulonglong = u64; -#[stable(feature = "raw_os", since = "1.1.0")] pub type c_float = f32; -#[stable(feature = "raw_os", since = "1.1.0")] pub type c_double = f64; - -/// Type used to construct void pointers for use with C. -/// -/// This type is only useful as a pointer target. Do not use it as a -/// return type for FFI functions which have the `void` return type in -/// C. Use the unit type `()` or omit the return type instead. -// NB: For LLVM to recognize the void pointer type and by extension -// functions like malloc(), we need to have it represented as i8* in -// LLVM bitcode. The enum used here ensures this and prevents misuse -// of the "raw" type by only having private variants.. We need two -// variants, because the compiler complains about the repr attribute -// otherwise. -#[repr(u8)] -#[stable(feature = "raw_os", since = "1.1.0")] -pub enum c_void { - #[unstable(feature = "c_void_variant", reason = "should not have to exist", - issue = "0")] - #[doc(hidden)] __variant1, - #[unstable(feature = "c_void_variant", reason = "should not have to exist", - issue = "0")] - #[doc(hidden)] __variant2, -} - -#[stable(feature = "std_debug", since = "1.16.0")] -impl fmt::Debug for c_void { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad("c_void") - } -} - -#[cfg(test)] -#[allow(unused_imports)] -mod tests { - use any::TypeId; - use libc; - use mem; - - macro_rules! ok { - ($($t:ident)*) => {$( - assert!(TypeId::of::() == TypeId::of::(), - "{} is wrong", stringify!($t)); - )*} - } - - #[test] - fn same() { - use os::raw; - ok!(c_char c_schar c_uchar c_short c_ushort c_int c_uint c_long c_ulong - c_longlong c_ulonglong c_float c_double); - } -} diff --git a/src/libstd/os/raw/char.md b/src/libstd/os/raw/char.md new file mode 100644 index 00000000000..9a55767d965 --- /dev/null +++ b/src/libstd/os/raw/char.md @@ -0,0 +1,11 @@ +Equivalent to C's `char` type. + +[C's `char` type] is completely unlike [Rust's `char` type]; while Rust's type represents a unicode scalar value, C's `char` type is just an ordinary integer. This type will always be either [`i8`] or [`u8`], as the type is defined as being one byte long. + +C chars are most commonly used to make C strings. Unlike Rust, where the length of a string is included alongside the string, C strings mark the end of a string with the character `'\0'`. See [`CStr`] for more information. + +[C's `char` type]: https://en.wikipedia.org/wiki/C_data_types#Basic_types +[Rust's `char` type]: ../../primitive.char.html +[`CStr`]: ../../ffi/struct.CStr.html +[`i8`]: ../../primitive.i8.html +[`u8`]: ../../primitive.u8.html diff --git a/src/libstd/os/raw/double.md b/src/libstd/os/raw/double.md new file mode 100644 index 00000000000..6818dada317 --- /dev/null +++ b/src/libstd/os/raw/double.md @@ -0,0 +1,7 @@ +Equivalent to C's `double` type. + +This type will almost always be [`f64`], which is guaranteed to be an [IEEE-754 double-precision float] in Rust. That said, the standard technically only guarantees that it be a floating-point number with at least the precision of a [`float`], and it may be `f32` or something entirely different from the IEEE-754 standard. + +[IEEE-754 double-precision float]: https://en.wikipedia.org/wiki/IEEE_754 +[`float`]: type.c_float.html +[`f64`]: ../../primitive.f64.html diff --git a/src/libstd/os/raw/float.md b/src/libstd/os/raw/float.md new file mode 100644 index 00000000000..57d1071d0da --- /dev/null +++ b/src/libstd/os/raw/float.md @@ -0,0 +1,6 @@ +Equivalent to C's `float` type. + +This type will almost always be [`f32`], which is guaranteed to be an [IEEE-754 single-precision float] in Rust. That said, the standard technically only guarantees that it be a floating-point number, and it may have less precision than `f32` or not follow the IEEE-754 standard at all. + +[IEEE-754 single-precision float]: https://en.wikipedia.org/wiki/IEEE_754 +[`f32`]: ../../primitive.f32.html diff --git a/src/libstd/os/raw/int.md b/src/libstd/os/raw/int.md new file mode 100644 index 00000000000..a0d25fd21d8 --- /dev/null +++ b/src/libstd/os/raw/int.md @@ -0,0 +1,7 @@ +Equivalent to C's `signed int` (`int`) type. + +This type will almost always be [`i32`], but may differ on some esoteric systems. The C standard technically only requires that this type be a signed integer that is at least the size of a [`short`]; some systems define it as an [`i16`], for example. + +[`short`]: type.c_short.html +[`i32`]: ../../primitive.i32.html +[`i16`]: ../../primitive.i16.html diff --git a/src/libstd/os/raw/long.md b/src/libstd/os/raw/long.md new file mode 100644 index 00000000000..c620b402819 --- /dev/null +++ b/src/libstd/os/raw/long.md @@ -0,0 +1,7 @@ +Equivalent to C's `signed long` (`long`) type. + +This type will always be [`i32`] or [`i64`]. Most notably, many Linux-based systems assume an `i64`, but Windows assumes `i32`. The C standard technically only requires that this type be a signed integer that is at least 32 bits and at least the size of an [`int`], although in practice, no system would have a `long` that is neither an `i32` nor `i64`. + +[`int`]: type.c_int.html +[`i32`]: ../../primitive.i32.html +[`i64`]: ../../primitive.i64.html diff --git a/src/libstd/os/raw/longlong.md b/src/libstd/os/raw/longlong.md new file mode 100644 index 00000000000..ab3d6436568 --- /dev/null +++ b/src/libstd/os/raw/longlong.md @@ -0,0 +1,7 @@ +Equivalent to C's `signed long long` (`long long`) type. + +This type will almost always be [`i64`], but may differ on some systems. The C standard technically only requires that this type be a signed integer that is at least 64 bits and at least the size of a [`long`], although in practice, no system would have a `long long` that is not an `i64`, as most systems do not have a standardised [`i128`] type. + +[`long`]: type.c_int.html +[`i64`]: ../../primitive.i64.html +[`i128`]: ../../primitive.i128.html diff --git a/src/libstd/os/raw/mod.rs b/src/libstd/os/raw/mod.rs new file mode 100644 index 00000000000..d5eeb5252f0 --- /dev/null +++ b/src/libstd/os/raw/mod.rs @@ -0,0 +1,135 @@ +// 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. + +//! Platform-specific types, as defined by C. +//! +//! Code that interacts via FFI will almost certainly be using the +//! base types provided by C, which aren't nearly as nicely defined +//! as Rust's primitive types. This module provides types which will +//! match those defined by C, so that code that interacts with C will +//! refer to the correct types. + +#![stable(feature = "raw_os", since = "1.1.0")] + +use fmt; + +#[doc(include = "os/raw/char.md")] +#[cfg(any(all(target_os = "linux", any(target_arch = "aarch64", + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64", + target_arch = "s390x")), + all(target_os = "android", any(target_arch = "aarch64", + target_arch = "arm")), + all(target_os = "l4re", target_arch = "x86_64"), + all(target_os = "openbsd", target_arch = "aarch64"), + all(target_os = "fuchsia", target_arch = "aarch64")))] +#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8; +#[doc(include = "os/raw/char.md")] +#[cfg(not(any(all(target_os = "linux", any(target_arch = "aarch64", + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64", + target_arch = "s390x")), + all(target_os = "android", any(target_arch = "aarch64", + target_arch = "arm")), + all(target_os = "l4re", target_arch = "x86_64"), + all(target_os = "openbsd", target_arch = "aarch64"), + all(target_os = "fuchsia", target_arch = "aarch64"))))] +#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8; +#[doc(include = "os/raw/schar.md")] +#[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8; +#[doc(include = "os/raw/uchar.md")] +#[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8; +#[doc(include = "os/raw/short.md")] +#[stable(feature = "raw_os", since = "1.1.0")] pub type c_short = i16; +#[doc(include = "os/raw/ushort.md")] +#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ushort = u16; +#[doc(include = "os/raw/int.md")] +#[stable(feature = "raw_os", since = "1.1.0")] pub type c_int = i32; +#[doc(include = "os/raw/uint.md")] +#[stable(feature = "raw_os", since = "1.1.0")] pub type c_uint = u32; +#[doc(include = "os/raw/long.md")] +#[cfg(any(target_pointer_width = "32", windows))] +#[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i32; +#[doc(include = "os/raw/ulong.md")] +#[cfg(any(target_pointer_width = "32", windows))] +#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u32; +#[doc(include = "os/raw/long.md")] +#[cfg(all(target_pointer_width = "64", not(windows)))] +#[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i64; +#[doc(include = "os/raw/ulong.md")] +#[cfg(all(target_pointer_width = "64", not(windows)))] +#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u64; +#[doc(include = "os/raw/longlong.md")] +#[stable(feature = "raw_os", since = "1.1.0")] pub type c_longlong = i64; +#[doc(include = "os/raw/ulonglong.md")] +#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulonglong = u64; +#[doc(include = "os/raw/float.md")] +#[stable(feature = "raw_os", since = "1.1.0")] pub type c_float = f32; +#[doc(include = "os/raw/double.md")] +#[stable(feature = "raw_os", since = "1.1.0")] pub type c_double = f64; + +/// Equivalent to C's `void` type when used as a [pointer]. +/// +/// In essence, `*const c_void` is equivalent to C's `const void*` +/// and `*mut c_void` is equivalent to C's `void*`. That said, this is +/// *not* the same as C's `void` return type, which is Rust's `()` type. +/// +/// Ideally, this type would be equivalent to [`!`], but currently it may +/// be more ideal to use `c_void` for FFI purposes. +/// +/// [`!`]: ../../primitive.never.html +/// [pointer]: ../../primitive.pointer.html +// NB: For LLVM to recognize the void pointer type and by extension +// functions like malloc(), we need to have it represented as i8* in +// LLVM bitcode. The enum used here ensures this and prevents misuse +// of the "raw" type by only having private variants.. We need two +// variants, because the compiler complains about the repr attribute +// otherwise. +#[repr(u8)] +#[stable(feature = "raw_os", since = "1.1.0")] +pub enum c_void { + #[unstable(feature = "c_void_variant", reason = "should not have to exist", + issue = "0")] + #[doc(hidden)] __variant1, + #[unstable(feature = "c_void_variant", reason = "should not have to exist", + issue = "0")] + #[doc(hidden)] __variant2, +} + +#[stable(feature = "std_debug", since = "1.16.0")] +impl fmt::Debug for c_void { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("c_void") + } +} + +#[cfg(test)] +#[allow(unused_imports)] +mod tests { + use any::TypeId; + use libc; + use mem; + + macro_rules! ok { + ($($t:ident)*) => {$( + assert!(TypeId::of::() == TypeId::of::(), + "{} is wrong", stringify!($t)); + )*} + } + + #[test] + fn same() { + use os::raw; + ok!(c_char c_schar c_uchar c_short c_ushort c_int c_uint c_long c_ulong + c_longlong c_ulonglong c_float c_double); + } +} diff --git a/src/libstd/os/raw/schar.md b/src/libstd/os/raw/schar.md new file mode 100644 index 00000000000..6aa8b1211d8 --- /dev/null +++ b/src/libstd/os/raw/schar.md @@ -0,0 +1,6 @@ +Equivalent to C's `signed char` type. + +This type will always be [`i8`], but is included for completeness. It is defined as being a signed integer the same size as a C [`char`]. + +[`char`]: type.c_char.html +[`i8`]: ../../primitive.i8.html diff --git a/src/libstd/os/raw/short.md b/src/libstd/os/raw/short.md new file mode 100644 index 00000000000..be92c6c106d --- /dev/null +++ b/src/libstd/os/raw/short.md @@ -0,0 +1,6 @@ +Equivalent to C's `signed short` (`short`) type. + +This type will almost always be [`i16`], but may differ on some esoteric systems. The C standard technically only requires that this type be a signed integer with at least 16 bits; some systems may define it as `i32`, for example. + +[`char`]: type.c_char.html +[`i16`]: ../../primitive.i16.html diff --git a/src/libstd/os/raw/uchar.md b/src/libstd/os/raw/uchar.md new file mode 100644 index 00000000000..b6ca711f869 --- /dev/null +++ b/src/libstd/os/raw/uchar.md @@ -0,0 +1,6 @@ +Equivalent to C's `unsigned char` type. + +This type will always be [`u8`], but is included for completeness. It is defined as being an unsigned integer the same size as a C [`char`]. + +[`char`]: type.c_char.html +[`u8`]: ../../primitive.u8.html diff --git a/src/libstd/os/raw/uint.md b/src/libstd/os/raw/uint.md new file mode 100644 index 00000000000..6f7013a8ac1 --- /dev/null +++ b/src/libstd/os/raw/uint.md @@ -0,0 +1,7 @@ +Equivalent to C's `unsigned int` type. + +This type will almost always be [`u32`], but may differ on some esoteric systems. The C standard technically only requires that this type be an unsigned integer with the same size as an [`int`]; some systems define it as a [`u16`], for example. + +[`int`]: type.c_int.html +[`u32`]: ../../primitive.u32.html +[`u16`]: ../../primitive.u16.html diff --git a/src/libstd/os/raw/ulong.md b/src/libstd/os/raw/ulong.md new file mode 100644 index 00000000000..c350395080e --- /dev/null +++ b/src/libstd/os/raw/ulong.md @@ -0,0 +1,7 @@ +Equivalent to C's `unsigned long` type. + +This type will always be [`u32`] or [`u64`]. Most notably, many Linux-based systems assume an `u64`, but Windows assumes `u32`. The C standard technically only requires that this type be an unsigned integer with the size of a [`long`], although in practice, no system would have a `ulong` that is neither a `u32` nor `u64`. + +[`long`]: type.c_long.html +[`u32`]: ../../primitive.u32.html +[`u64`]: ../../primitive.u64.html diff --git a/src/libstd/os/raw/ulonglong.md b/src/libstd/os/raw/ulonglong.md new file mode 100644 index 00000000000..c41faf74c5c --- /dev/null +++ b/src/libstd/os/raw/ulonglong.md @@ -0,0 +1,7 @@ +Equivalent to C's `unsigned long long` type. + +This type will almost always be [`u64`], but may differ on some systems. The C standard technically only requires that this type be an unsigned integer with the size of a [`long long`], although in practice, no system would have a `long long` that is not a `u64`, as most systems do not have a standardised [`u128`] type. + +[`long long`]: type.c_longlong.html +[`u64`]: ../../primitive.u64.html +[`u128`]: ../../primitive.u128.html diff --git a/src/libstd/os/raw/ushort.md b/src/libstd/os/raw/ushort.md new file mode 100644 index 00000000000..d364abb3c8e --- /dev/null +++ b/src/libstd/os/raw/ushort.md @@ -0,0 +1,6 @@ +Equivalent to C's `unsigned short` type. + +This type will almost always be [`u16`], but may differ on some esoteric systems. The C standard technically only requires that this type be an unsigned integer with the same size as a [`short`]. + +[`short`]: type.c_short.html +[`u16`]: ../../primitive.u16.html diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index 560876006d3..112e1106093 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -198,7 +198,7 @@ impl UnwindSafe for *const T {} impl UnwindSafe for *mut T {} #[unstable(feature = "ptr_internals", issue = "0")] impl UnwindSafe for Unique {} -#[stable(feature = "nonnull", since = "1.24.0")] +#[stable(feature = "nonnull", since = "1.25.0")] impl UnwindSafe for NonNull {} #[stable(feature = "catch_unwind", since = "1.9.0")] impl UnwindSafe for Mutex {} diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 5c66ac6ddde..9b2f815b713 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -1843,4 +1843,10 @@ fn ContinueDebugEvent(dwProcessId: DWORD, dwThreadId: DWORD, } assert!(events > 0); } + + #[test] + fn test_command_implements_send() { + fn take_send_type(_: T) {} + take_send_type(Command::new("")) + } } diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs index c980ae75261..78a3b82546e 100644 --- a/src/libstd/sys/cloudabi/thread.rs +++ b/src/libstd/sys/cloudabi/thread.rs @@ -111,10 +111,11 @@ fn drop(&mut self) { #[cfg_attr(test, allow(dead_code))] pub mod guard { - pub unsafe fn current() -> Option { + pub type Guard = !; + pub unsafe fn current() -> Option { None } - pub unsafe fn init() -> Option { + pub unsafe fn init() -> Option { None } } diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs index c4aad8d86f8..c4719a94c7e 100644 --- a/src/libstd/sys/redox/thread.rs +++ b/src/libstd/sys/redox/thread.rs @@ -88,6 +88,7 @@ pub fn into_id(self) -> usize { } pub mod guard { - pub unsafe fn current() -> Option { None } - pub unsafe fn init() -> Option { None } + pub type Guard = !; + pub unsafe fn current() -> Option { None } + pub unsafe fn init() -> Option { None } } diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index c53bcdbf8e3..7e057401fab 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -45,7 +45,7 @@ pub struct Command { // other keys. program: CString, args: Vec, - argv: Vec<*const c_char>, + argv: Argv, env: CommandEnv, cwd: Option, @@ -58,6 +58,12 @@ pub struct Command { stderr: Option, } +// Create a new type for argv, so that we can make it `Send` +struct Argv(Vec<*const c_char>); + +// It is safe to make Argv Send, because it contains pointers to memory owned by `Command.args` +unsafe impl Send for Argv {} + // passed back to std::process with the pipes connected to the child, if any // were requested pub struct StdioPipes { @@ -92,7 +98,7 @@ pub fn new(program: &OsStr) -> Command { let mut saw_nul = false; let program = os2c(program, &mut saw_nul); Command { - argv: vec![program.as_ptr(), ptr::null()], + argv: Argv(vec![program.as_ptr(), ptr::null()]), program, args: Vec::new(), env: Default::default(), @@ -111,8 +117,8 @@ pub fn arg(&mut self, arg: &OsStr) { // Overwrite the trailing NULL pointer in `argv` and then add a new null // pointer. let arg = os2c(arg, &mut self.saw_nul); - self.argv[self.args.len() + 1] = arg.as_ptr(); - self.argv.push(ptr::null()); + self.argv.0[self.args.len() + 1] = arg.as_ptr(); + self.argv.0.push(ptr::null()); // Also make sure we keep track of the owned value to schedule a // destructor for this memory. @@ -133,7 +139,7 @@ pub fn saw_nul(&self) -> bool { self.saw_nul } pub fn get_argv(&self) -> &Vec<*const c_char> { - &self.argv + &self.argv.0 } #[allow(dead_code)] diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs index 51adbc24ae0..40453f9b8a1 100644 --- a/src/libstd/sys/unix/stack_overflow.rs +++ b/src/libstd/sys/unix/stack_overflow.rs @@ -57,9 +57,6 @@ mod imp { use sys_common::thread_info; - // This is initialized in init() and only read from after - static mut PAGE_SIZE: usize = 0; - #[cfg(any(target_os = "linux", target_os = "android"))] unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize { #[repr(C)] @@ -102,12 +99,12 @@ unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize { _data: *mut libc::c_void) { use sys_common::util::report_overflow; - let guard = thread_info::stack_guard().unwrap_or(0); + let guard = thread_info::stack_guard().unwrap_or(0..0); let addr = siginfo_si_addr(info); // If the faulting address is within the guard page, then we print a // message saying so and abort. - if guard != 0 && guard - PAGE_SIZE <= addr && addr < guard { + if guard.start <= addr && addr < guard.end { report_overflow(); rtabort!("stack overflow"); } else { @@ -123,8 +120,6 @@ unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize { static mut MAIN_ALTSTACK: *mut libc::c_void = ptr::null_mut(); pub unsafe fn init() { - PAGE_SIZE = ::sys::os::page_size(); - let mut action: sigaction = mem::zeroed(); action.sa_flags = SA_SIGINFO | SA_ONSTACK; action.sa_sigaction = signal_handler as sighandler_t; diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 525882c1e1e..72cdb9440b8 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -205,8 +205,10 @@ fn drop(&mut self) { not(target_os = "solaris")))] #[cfg_attr(test, allow(dead_code))] pub mod guard { - pub unsafe fn current() -> Option { None } - pub unsafe fn init() -> Option { None } + use ops::Range; + pub type Guard = Range; + pub unsafe fn current() -> Option { None } + pub unsafe fn init() -> Option { None } } @@ -222,14 +224,43 @@ pub mod guard { use libc; use libc::mmap; use libc::{PROT_NONE, MAP_PRIVATE, MAP_ANON, MAP_FAILED, MAP_FIXED}; + use ops::Range; use sys::os; - #[cfg(any(target_os = "macos", - target_os = "bitrig", - target_os = "openbsd", - target_os = "solaris"))] + // This is initialized in init() and only read from after + static mut PAGE_SIZE: usize = 0; + + pub type Guard = Range; + + #[cfg(target_os = "solaris")] + unsafe fn get_stack_start() -> Option<*mut libc::c_void> { + let mut current_stack: libc::stack_t = ::mem::zeroed(); + assert_eq!(libc::stack_getbounds(&mut current_stack), 0); + Some(current_stack.ss_sp) + } + + #[cfg(target_os = "macos")] unsafe fn get_stack_start() -> Option<*mut libc::c_void> { - current().map(|s| s as *mut libc::c_void) + let stackaddr = libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize - + libc::pthread_get_stacksize_np(libc::pthread_self()); + Some(stackaddr as *mut libc::c_void) + } + + #[cfg(any(target_os = "openbsd", target_os = "bitrig"))] + unsafe fn get_stack_start() -> Option<*mut libc::c_void> { + let mut current_stack: libc::stack_t = ::mem::zeroed(); + assert_eq!(libc::pthread_stackseg_np(libc::pthread_self(), + &mut current_stack), 0); + + let extra = if cfg!(target_os = "bitrig") {3} else {1} * PAGE_SIZE; + let stackaddr = if libc::pthread_main_np() == 1 { + // main thread + current_stack.ss_sp as usize - current_stack.ss_size + extra + } else { + // new thread + current_stack.ss_sp as usize - current_stack.ss_size + }; + Some(stackaddr as *mut libc::c_void) } #[cfg(any(target_os = "android", target_os = "freebsd", @@ -253,8 +284,9 @@ unsafe fn get_stack_start() -> Option<*mut libc::c_void> { ret } - pub unsafe fn init() -> Option { - let psize = os::page_size(); + pub unsafe fn init() -> Option { + PAGE_SIZE = os::page_size(); + let mut stackaddr = get_stack_start()?; // Ensure stackaddr is page aligned! A parent process might @@ -263,9 +295,9 @@ pub unsafe fn init() -> Option { // stackaddr < stackaddr + stacksize, so if stackaddr is not // page-aligned, calculate the fix such that stackaddr < // new_page_aligned_stackaddr < stackaddr + stacksize - let remainder = (stackaddr as usize) % psize; + let remainder = (stackaddr as usize) % PAGE_SIZE; if remainder != 0 { - stackaddr = ((stackaddr as usize) + psize - remainder) + stackaddr = ((stackaddr as usize) + PAGE_SIZE - remainder) as *mut libc::c_void; } @@ -280,60 +312,42 @@ pub unsafe fn init() -> Option { // 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) + let stackaddr = stackaddr as usize; + Some(stackaddr - PAGE_SIZE..stackaddr) } else { // Reallocate the last page of the stack. // This ensures SIGBUS will be raised on // stack overflow. - let result = mmap(stackaddr, psize, PROT_NONE, + let result = mmap(stackaddr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); if result != stackaddr || result == MAP_FAILED { panic!("failed to allocate a guard page"); } + let guardaddr = stackaddr as usize; let offset = if cfg!(target_os = "freebsd") { 2 } else { 1 }; - Some(stackaddr as usize + offset * psize) + Some(guardaddr..guardaddr + offset * PAGE_SIZE) } } - #[cfg(target_os = "solaris")] - pub unsafe fn current() -> Option { - let mut current_stack: libc::stack_t = ::mem::zeroed(); - assert_eq!(libc::stack_getbounds(&mut current_stack), 0); - Some(current_stack.ss_sp as usize) - } - - #[cfg(target_os = "macos")] - pub unsafe fn current() -> Option { - Some(libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize - - libc::pthread_get_stacksize_np(libc::pthread_self())) - } - - #[cfg(any(target_os = "openbsd", target_os = "bitrig"))] - pub unsafe fn current() -> Option { - let mut current_stack: libc::stack_t = ::mem::zeroed(); - assert_eq!(libc::pthread_stackseg_np(libc::pthread_self(), - &mut current_stack), 0); - - let extra = if cfg!(target_os = "bitrig") {3} else {1} * os::page_size(); - Some(if libc::pthread_main_np() == 1 { - // main thread - current_stack.ss_sp as usize - current_stack.ss_size + extra - } else { - // new thread - current_stack.ss_sp as usize - current_stack.ss_size - }) + #[cfg(any(target_os = "macos", + target_os = "bitrig", + target_os = "openbsd", + target_os = "solaris"))] + pub unsafe fn current() -> Option { + let stackaddr = get_stack_start()? as usize; + Some(stackaddr - PAGE_SIZE..stackaddr) } #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux", target_os = "netbsd", target_os = "l4re"))] - pub unsafe fn current() -> Option { + pub unsafe fn current() -> Option { let mut ret = None; let mut attr: libc::pthread_attr_t = ::mem::zeroed(); assert_eq!(libc::pthread_attr_init(&mut attr), 0); @@ -352,12 +366,23 @@ pub unsafe fn current() -> Option { assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackaddr, &mut size), 0); + let stackaddr = stackaddr as usize; ret = if cfg!(target_os = "freebsd") { - Some(stackaddr as usize - guardsize) + // FIXME does freebsd really fault *below* the guard addr? + let guardaddr = stackaddr - guardsize; + Some(guardaddr - PAGE_SIZE..guardaddr) } else if cfg!(target_os = "netbsd") { - Some(stackaddr as usize) + Some(stackaddr - guardsize..stackaddr) + } else if cfg!(all(target_os = "linux", target_env = "gnu")) { + // glibc used to include the guard area within the stack, as noted in the BUGS + // section of `man pthread_attr_getguardsize`. This has been corrected starting + // with glibc 2.27, and in some distro backports, so the guard is now placed at the + // end (below) the stack. There's no easy way for us to know which we have at + // runtime, so we'll just match any fault in the range right above or below the + // stack base to call that fault a stack overflow. + Some(stackaddr - guardsize..stackaddr + guardsize) } else { - Some(stackaddr as usize + guardsize) + Some(stackaddr..stackaddr + guardsize) }; } assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); diff --git a/src/libstd/sys/wasm/args.rs b/src/libstd/sys/wasm/args.rs index d2a4a7b19d5..b3c6b671e80 100644 --- a/src/libstd/sys/wasm/args.rs +++ b/src/libstd/sys/wasm/args.rs @@ -10,8 +10,8 @@ use ffi::OsString; use marker::PhantomData; -use mem; use vec; +use sys::ArgsSysCall; pub unsafe fn init(_argc: isize, _argv: *const *const u8) { // On wasm these should always be null, so there's nothing for us to do here @@ -21,38 +21,10 @@ pub unsafe fn cleanup() { } pub fn args() -> Args { - // When the runtime debugging is enabled we'll link to some extra runtime - // functions to actually implement this. These are for now just implemented - // in a node.js script but they're off by default as they're sort of weird - // in a web-wasm world. - if !super::DEBUG { - return Args { - iter: Vec::new().into_iter(), - _dont_send_or_sync_me: PhantomData, - } - } - - // You'll find the definitions of these in `src/etc/wasm32-shim.js`. These - // are just meant for debugging and should not be relied on. - extern { - fn rust_wasm_args_count() -> usize; - fn rust_wasm_args_arg_size(a: usize) -> usize; - fn rust_wasm_args_arg_fill(a: usize, ptr: *mut u8); - } - - unsafe { - let cnt = rust_wasm_args_count(); - let mut v = Vec::with_capacity(cnt); - for i in 0..cnt { - let n = rust_wasm_args_arg_size(i); - let mut data = vec![0; n]; - rust_wasm_args_arg_fill(i, data.as_mut_ptr()); - v.push(mem::transmute::, OsString>(data)); - } - Args { - iter: v.into_iter(), - _dont_send_or_sync_me: PhantomData, - } + let v = ArgsSysCall::perform(); + Args { + iter: v.into_iter(), + _dont_send_or_sync_me: PhantomData, } } diff --git a/src/libstd/sys/wasm/mod.rs b/src/libstd/sys/wasm/mod.rs index ba3d6a2813a..c02e5e809c8 100644 --- a/src/libstd/sys/wasm/mod.rs +++ b/src/libstd/sys/wasm/mod.rs @@ -26,17 +26,11 @@ use io; use os::raw::c_char; - -// Right now the wasm backend doesn't even have the ability to print to the -// console by default. Wasm can't import anything from JS! (you have to -// explicitly provide it). -// -// Sometimes that's a real bummer, though, so this flag can be set to `true` to -// enable calling various shims defined in `src/etc/wasm32-shim.js` which should -// help receive debug output and see what's going on. In general this flag -// currently controls "will we call out to our own defined shims in node.js", -// and this flag should always be `false` for release builds. -const DEBUG: bool = false; +use ptr; +use sys::os_str::Buf; +use sys_common::{AsInner, FromInner}; +use ffi::{OsString, OsStr}; +use time::Duration; pub mod args; #[cfg(feature = "backtrace")] @@ -92,7 +86,7 @@ pub unsafe fn strlen(mut s: *const c_char) -> usize { } pub unsafe fn abort_internal() -> ! { - ::intrinsics::abort(); + ExitSysCall::perform(1) } // We don't have randomness yet, but I totally used a random number generator to @@ -103,3 +97,218 @@ pub unsafe fn abort_internal() -> ! { pub fn hashmap_random_keys() -> (u64, u64) { (1, 2) } + +// Implement a minimal set of system calls to enable basic IO +pub enum SysCallIndex { + Read = 0, + Write = 1, + Exit = 2, + Args = 3, + GetEnv = 4, + SetEnv = 5, + Time = 6, +} + +#[repr(C)] +pub struct ReadSysCall { + fd: usize, + ptr: *mut u8, + len: usize, + result: usize, +} + +impl ReadSysCall { + pub fn perform(fd: usize, buffer: &mut [u8]) -> usize { + let mut call_record = ReadSysCall { + fd, + len: buffer.len(), + ptr: buffer.as_mut_ptr(), + result: 0 + }; + if unsafe { syscall(SysCallIndex::Read, &mut call_record) } { + call_record.result + } else { + 0 + } + } +} + +#[repr(C)] +pub struct WriteSysCall { + fd: usize, + ptr: *const u8, + len: usize, +} + +impl WriteSysCall { + pub fn perform(fd: usize, buffer: &[u8]) { + let mut call_record = WriteSysCall { + fd, + len: buffer.len(), + ptr: buffer.as_ptr() + }; + unsafe { syscall(SysCallIndex::Write, &mut call_record); } + } +} + +#[repr(C)] +pub struct ExitSysCall { + code: usize, +} + +impl ExitSysCall { + pub fn perform(code: usize) -> ! { + let mut call_record = ExitSysCall { + code + }; + unsafe { + syscall(SysCallIndex::Exit, &mut call_record); + ::intrinsics::abort(); + } + } +} + +fn receive_buffer Result>(estimate: usize, mut f: F) + -> Result, E> +{ + let mut buffer = vec![0; estimate]; + loop { + let result = f(&mut buffer)?; + if result <= buffer.len() { + buffer.truncate(result); + break; + } + buffer.resize(result, 0); + } + Ok(buffer) +} + +#[repr(C)] +pub struct ArgsSysCall { + ptr: *mut u8, + len: usize, + result: usize +} + +impl ArgsSysCall { + pub fn perform() -> Vec { + receive_buffer(1024, |buffer| -> Result { + let mut call_record = ArgsSysCall { + len: buffer.len(), + ptr: buffer.as_mut_ptr(), + result: 0 + }; + if unsafe { syscall(SysCallIndex::Args, &mut call_record) } { + Ok(call_record.result) + } else { + Ok(0) + } + }) + .unwrap() + .split(|b| *b == 0) + .map(|s| FromInner::from_inner(Buf { inner: s.to_owned() })) + .collect() + } +} + +#[repr(C)] +pub struct GetEnvSysCall { + key_ptr: *const u8, + key_len: usize, + value_ptr: *mut u8, + value_len: usize, + result: usize +} + +impl GetEnvSysCall { + pub fn perform(key: &OsStr) -> Option { + let key_buf = &AsInner::as_inner(key).inner; + receive_buffer(64, |buffer| { + let mut call_record = GetEnvSysCall { + key_len: key_buf.len(), + key_ptr: key_buf.as_ptr(), + value_len: buffer.len(), + value_ptr: buffer.as_mut_ptr(), + result: !0usize + }; + if unsafe { syscall(SysCallIndex::GetEnv, &mut call_record) } { + if call_record.result == !0usize { + Err(()) + } else { + Ok(call_record.result) + } + } else { + Err(()) + } + }).ok().map(|s| { + FromInner::from_inner(Buf { inner: s }) + }) + } +} + +#[repr(C)] +pub struct SetEnvSysCall { + key_ptr: *const u8, + key_len: usize, + value_ptr: *const u8, + value_len: usize +} + +impl SetEnvSysCall { + pub fn perform(key: &OsStr, value: Option<&OsStr>) { + let key_buf = &AsInner::as_inner(key).inner; + let value_buf = value.map(|v| &AsInner::as_inner(v).inner); + let mut call_record = SetEnvSysCall { + key_len: key_buf.len(), + key_ptr: key_buf.as_ptr(), + value_len: value_buf.map(|v| v.len()).unwrap_or(!0usize), + value_ptr: value_buf.map(|v| v.as_ptr()).unwrap_or(ptr::null()) + }; + unsafe { syscall(SysCallIndex::SetEnv, &mut call_record); } + } +} + +pub enum TimeClock { + Monotonic = 0, + System = 1, +} + +#[repr(C)] +pub struct TimeSysCall { + clock: usize, + secs_hi: usize, + secs_lo: usize, + nanos: usize +} + +impl TimeSysCall { + pub fn perform(clock: TimeClock) -> Duration { + let mut call_record = TimeSysCall { + clock: clock as usize, + secs_hi: 0, + secs_lo: 0, + nanos: 0 + }; + if unsafe { syscall(SysCallIndex::Time, &mut call_record) } { + Duration::new( + ((call_record.secs_hi as u64) << 32) | (call_record.secs_lo as u64), + call_record.nanos as u32 + ) + } else { + panic!("Time system call is not implemented by WebAssembly host"); + } + } +} + +unsafe fn syscall(index: SysCallIndex, data: &mut T) -> bool { + #[cfg(feature = "wasm_syscall")] + extern { + #[no_mangle] + fn rust_wasm_syscall(index: usize, data: *mut Void) -> usize; + } + + #[cfg(not(feature = "wasm_syscall"))] + unsafe fn rust_wasm_syscall(_index: usize, _data: *mut Void) -> usize { 0 } + + rust_wasm_syscall(index as usize, data as *mut T as *mut Void) != 0 +} diff --git a/src/libstd/sys/wasm/os.rs b/src/libstd/sys/wasm/os.rs index c98030f7ebf..23ca1754719 100644 --- a/src/libstd/sys/wasm/os.rs +++ b/src/libstd/sys/wasm/os.rs @@ -8,16 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::intrinsics; - use error::Error as StdError; use ffi::{OsString, OsStr}; use fmt; use io; -use mem; use path::{self, PathBuf}; use str; -use sys::{unsupported, Void}; +use sys::{unsupported, Void, ExitSysCall, GetEnvSysCall, SetEnvSysCall}; pub fn errno() -> i32 { 0 @@ -87,36 +84,15 @@ pub fn env() -> Env { } pub fn getenv(k: &OsStr) -> io::Result> { - // If we're debugging the runtime then we actually probe node.js to ask for - // the value of environment variables to help provide inputs to programs. - // The `extern` shims here are defined in `src/etc/wasm32-shim.js` and are - // intended for debugging only, you should not rely on them. - if !super::DEBUG { - return Ok(None) - } - - extern { - fn rust_wasm_getenv_len(k: *const u8, kl: usize) -> isize; - fn rust_wasm_getenv_data(k: *const u8, kl: usize, v: *mut u8); - } - unsafe { - let k: &[u8] = mem::transmute(k); - let n = rust_wasm_getenv_len(k.as_ptr(), k.len()); - if n == -1 { - return Ok(None) - } - let mut data = vec![0; n as usize]; - rust_wasm_getenv_data(k.as_ptr(), k.len(), data.as_mut_ptr()); - Ok(Some(mem::transmute(data))) - } + Ok(GetEnvSysCall::perform(k)) } -pub fn setenv(_k: &OsStr, _v: &OsStr) -> io::Result<()> { - unsupported() +pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { + Ok(SetEnvSysCall::perform(k, Some(v))) } -pub fn unsetenv(_n: &OsStr) -> io::Result<()> { - unsupported() +pub fn unsetenv(k: &OsStr) -> io::Result<()> { + Ok(SetEnvSysCall::perform(k, None)) } pub fn temp_dir() -> PathBuf { @@ -128,7 +104,7 @@ pub fn home_dir() -> Option { } pub fn exit(_code: i32) -> ! { - unsafe { intrinsics::abort() } + ExitSysCall::perform(_code as isize as usize) } pub fn getpid() -> u32 { diff --git a/src/libstd/sys/wasm/stdio.rs b/src/libstd/sys/wasm/stdio.rs index 0f75f240251..beb19c0ed2c 100644 --- a/src/libstd/sys/wasm/stdio.rs +++ b/src/libstd/sys/wasm/stdio.rs @@ -9,19 +9,19 @@ // except according to those terms. use io; -use sys::{Void, unsupported}; +use sys::{ReadSysCall, WriteSysCall}; -pub struct Stdin(Void); +pub struct Stdin; pub struct Stdout; pub struct Stderr; impl Stdin { pub fn new() -> io::Result { - unsupported() + Ok(Stdin) } - pub fn read(&self, _data: &mut [u8]) -> io::Result { - match self.0 {} + pub fn read(&self, data: &mut [u8]) -> io::Result { + Ok(ReadSysCall::perform(0, data)) } } @@ -31,19 +31,7 @@ pub fn new() -> io::Result { } pub fn write(&self, data: &[u8]) -> io::Result { - // If runtime debugging is enabled at compile time we'll invoke some - // runtime functions that are defined in our src/etc/wasm32-shim.js - // debugging script. Note that this ffi function call is intended - // *purely* for debugging only and should not be relied upon. - if !super::DEBUG { - return unsupported() - } - extern { - fn rust_wasm_write_stdout(data: *const u8, len: usize); - } - unsafe { - rust_wasm_write_stdout(data.as_ptr(), data.len()) - } + WriteSysCall::perform(1, data); Ok(data.len()) } @@ -58,16 +46,7 @@ pub fn new() -> io::Result { } pub fn write(&self, data: &[u8]) -> io::Result { - // See comments in stdout for what's going on here. - if !super::DEBUG { - return unsupported() - } - extern { - fn rust_wasm_write_stderr(data: *const u8, len: usize); - } - unsafe { - rust_wasm_write_stderr(data.as_ptr(), data.len()) - } + WriteSysCall::perform(2, data); Ok(data.len()) } diff --git a/src/libstd/sys/wasm/thread.rs b/src/libstd/sys/wasm/thread.rs index 13980e0cc19..6a066509b49 100644 --- a/src/libstd/sys/wasm/thread.rs +++ b/src/libstd/sys/wasm/thread.rs @@ -43,6 +43,7 @@ pub fn join(self) { } pub mod guard { - pub unsafe fn current() -> Option { None } - pub unsafe fn init() -> Option { None } + pub type Guard = !; + pub unsafe fn current() -> Option { None } + pub unsafe fn init() -> Option { None } } diff --git a/src/libstd/sys/wasm/time.rs b/src/libstd/sys/wasm/time.rs index c269def98f6..e52435e6339 100644 --- a/src/libstd/sys/wasm/time.rs +++ b/src/libstd/sys/wasm/time.rs @@ -8,56 +8,50 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use fmt; use time::Duration; +use sys::{TimeSysCall, TimeClock}; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] -pub struct Instant; +pub struct Instant(Duration); -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct SystemTime; +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub struct SystemTime(Duration); -pub const UNIX_EPOCH: SystemTime = SystemTime; +pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0)); impl Instant { pub fn now() -> Instant { - panic!("not supported on web assembly"); + Instant(TimeSysCall::perform(TimeClock::Monotonic)) } - pub fn sub_instant(&self, _other: &Instant) -> Duration { - panic!("can't sub yet"); + pub fn sub_instant(&self, other: &Instant) -> Duration { + self.0 - other.0 } - pub fn add_duration(&self, _other: &Duration) -> Instant { - panic!("can't add yet"); + pub fn add_duration(&self, other: &Duration) -> Instant { + Instant(self.0 + *other) } - pub fn sub_duration(&self, _other: &Duration) -> Instant { - panic!("can't sub yet"); + pub fn sub_duration(&self, other: &Duration) -> Instant { + Instant(self.0 - *other) } } impl SystemTime { pub fn now() -> SystemTime { - panic!("not supported on web assembly"); + SystemTime(TimeSysCall::perform(TimeClock::System)) } - pub fn sub_time(&self, _other: &SystemTime) + pub fn sub_time(&self, other: &SystemTime) -> Result { - panic!() - } - - pub fn add_duration(&self, _other: &Duration) -> SystemTime { - panic!() + self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0) } - pub fn sub_duration(&self, _other: &Duration) -> SystemTime { - panic!() + pub fn add_duration(&self, other: &Duration) -> SystemTime { + SystemTime(self.0 + *other) } -} -impl fmt::Debug for SystemTime { - fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { - panic!() + pub fn sub_duration(&self, other: &Duration) -> SystemTime { + SystemTime(self.0 - *other) } } diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index 74786d09285..43abfbb1f64 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -93,6 +93,7 @@ pub fn into_handle(self) -> Handle { self.handle } #[cfg_attr(test, allow(dead_code))] pub mod guard { - pub unsafe fn current() -> Option { None } - pub unsafe fn init() -> Option { None } + pub type Guard = !; + pub unsafe fn current() -> Option { None } + pub unsafe fn init() -> Option { None } } diff --git a/src/libstd/sys_common/thread_info.rs b/src/libstd/sys_common/thread_info.rs index 7970042b1d6..6a2b6742367 100644 --- a/src/libstd/sys_common/thread_info.rs +++ b/src/libstd/sys_common/thread_info.rs @@ -11,10 +11,11 @@ #![allow(dead_code)] // stack_guard isn't used right now on all platforms use cell::RefCell; +use sys::thread::guard::Guard; use thread::Thread; struct ThreadInfo { - stack_guard: Option, + stack_guard: Option, thread: Thread, } @@ -38,11 +39,11 @@ pub fn current_thread() -> Option { ThreadInfo::with(|info| info.thread.clone()) } -pub fn stack_guard() -> Option { - ThreadInfo::with(|info| info.stack_guard).and_then(|o| o) +pub fn stack_guard() -> Option { + ThreadInfo::with(|info| info.stack_guard.clone()).and_then(|o| o) } -pub fn set(stack_guard: Option, thread: Thread) { +pub fn set(stack_guard: Option, thread: Thread) { THREAD_INFO.with(|c| assert!(c.borrow().is_none())); THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{ stack_guard, diff --git a/src/libstd/time.rs b/src/libstd/time.rs new file mode 100644 index 00000000000..12f2a9bb85f --- /dev/null +++ b/src/libstd/time.rs @@ -0,0 +1,565 @@ +// 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. + +//! Temporal quantification. +//! +//! Example: +//! +//! ``` +//! use std::time::Duration; +//! +//! let five_seconds = Duration::new(5, 0); +//! // both declarations are equivalent +//! assert_eq!(Duration::new(5, 0), Duration::from_secs(5)); +//! ``` + +#![stable(feature = "time", since = "1.3.0")] + +use error::Error; +use fmt; +use ops::{Add, Sub, AddAssign, SubAssign}; +use sys::time; +use sys_common::FromInner; + +#[stable(feature = "time", since = "1.3.0")] +pub use core::time::Duration; + +/// A measurement of a monotonically nondecreasing clock. +/// Opaque and useful only with `Duration`. +/// +/// Instants are always guaranteed to be no less than any previously measured +/// instant when created, and are often useful for tasks such as measuring +/// benchmarks or timing how long an operation takes. +/// +/// Note, however, that instants are not guaranteed to be **steady**. In other +/// words, each tick of the underlying clock may not be the same length (e.g. +/// some seconds may be longer than others). An instant may jump forwards or +/// experience time dilation (slow down or speed up), but it will never go +/// backwards. +/// +/// Instants are opaque types that can only be compared to one another. There is +/// no method to get "the number of seconds" from an instant. Instead, it only +/// allows measuring the duration between two instants (or comparing two +/// instants). +/// +/// Example: +/// +/// ```no_run +/// use std::time::{Duration, Instant}; +/// use std::thread::sleep; +/// +/// fn main() { +/// let now = Instant::now(); +/// +/// // we sleep for 2 seconds +/// sleep(Duration::new(2, 0)); +/// // it prints '2' +/// println!("{}", now.elapsed().as_secs()); +/// } +/// ``` +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[stable(feature = "time2", since = "1.8.0")] +pub struct Instant(time::Instant); + +/// A measurement of the system clock, useful for talking to +/// external entities like the file system or other processes. +/// +/// Distinct from the [`Instant`] type, this time measurement **is not +/// monotonic**. This means that you can save a file to the file system, then +/// save another file to the file system, **and the second file has a +/// `SystemTime` measurement earlier than the first**. In other words, an +/// operation that happens after another operation in real time may have an +/// earlier `SystemTime`! +/// +/// Consequently, comparing two `SystemTime` instances to learn about the +/// duration between them returns a [`Result`] instead of an infallible [`Duration`] +/// to indicate that this sort of time drift may happen and needs to be handled. +/// +/// Although a `SystemTime` cannot be directly inspected, the [`UNIX_EPOCH`] +/// constant is provided in this module as an anchor in time to learn +/// information about a `SystemTime`. By calculating the duration from this +/// fixed point in time, a `SystemTime` can be converted to a human-readable time, +/// or perhaps some other string representation. +/// +/// [`Instant`]: ../../std/time/struct.Instant.html +/// [`Result`]: ../../std/result/enum.Result.html +/// [`Duration`]: ../../std/time/struct.Duration.html +/// [`UNIX_EPOCH`]: ../../std/time/constant.UNIX_EPOCH.html +/// +/// Example: +/// +/// ```no_run +/// use std::time::{Duration, SystemTime}; +/// use std::thread::sleep; +/// +/// fn main() { +/// let now = SystemTime::now(); +/// +/// // we sleep for 2 seconds +/// sleep(Duration::new(2, 0)); +/// match now.elapsed() { +/// Ok(elapsed) => { +/// // it prints '2' +/// println!("{}", elapsed.as_secs()); +/// } +/// Err(e) => { +/// // an error occurred! +/// println!("Error: {:?}", e); +/// } +/// } +/// } +/// ``` +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[stable(feature = "time2", since = "1.8.0")] +pub struct SystemTime(time::SystemTime); + +/// An error returned from the `duration_since` and `elapsed` methods on +/// `SystemTime`, used to learn how far in the opposite direction a system time +/// lies. +/// +/// # Examples +/// +/// ```no_run +/// use std::thread::sleep; +/// use std::time::{Duration, SystemTime}; +/// +/// let sys_time = SystemTime::now(); +/// sleep(Duration::from_secs(1)); +/// let new_sys_time = SystemTime::now(); +/// match sys_time.duration_since(new_sys_time) { +/// Ok(_) => {} +/// Err(e) => println!("SystemTimeError difference: {:?}", e.duration()), +/// } +/// ``` +#[derive(Clone, Debug)] +#[stable(feature = "time2", since = "1.8.0")] +pub struct SystemTimeError(Duration); + +impl Instant { + /// Returns an instant corresponding to "now". + /// + /// # Examples + /// + /// ``` + /// use std::time::Instant; + /// + /// let now = Instant::now(); + /// ``` + #[stable(feature = "time2", since = "1.8.0")] + pub fn now() -> Instant { + Instant(time::Instant::now()) + } + + /// Returns the amount of time elapsed from another instant to this one. + /// + /// # Panics + /// + /// This function will panic if `earlier` is later than `self`. + /// + /// # Examples + /// + /// ```no_run + /// use std::time::{Duration, Instant}; + /// use std::thread::sleep; + /// + /// let now = Instant::now(); + /// sleep(Duration::new(1, 0)); + /// let new_now = Instant::now(); + /// println!("{:?}", new_now.duration_since(now)); + /// ``` + #[stable(feature = "time2", since = "1.8.0")] + pub fn duration_since(&self, earlier: Instant) -> Duration { + self.0.sub_instant(&earlier.0) + } + + /// Returns the amount of time elapsed since this instant was created. + /// + /// # Panics + /// + /// This function may panic if the current time is earlier than this + /// instant, which is something that can happen if an `Instant` is + /// produced synthetically. + /// + /// # Examples + /// + /// ```no_run + /// use std::thread::sleep; + /// use std::time::{Duration, Instant}; + /// + /// let instant = Instant::now(); + /// let three_secs = Duration::from_secs(3); + /// sleep(three_secs); + /// assert!(instant.elapsed() >= three_secs); + /// ``` + #[stable(feature = "time2", since = "1.8.0")] + pub fn elapsed(&self) -> Duration { + Instant::now() - *self + } +} + +#[stable(feature = "time2", since = "1.8.0")] +impl Add for Instant { + type Output = Instant; + + fn add(self, other: Duration) -> Instant { + Instant(self.0.add_duration(&other)) + } +} + +#[stable(feature = "time_augmented_assignment", since = "1.9.0")] +impl AddAssign for Instant { + fn add_assign(&mut self, other: Duration) { + *self = *self + other; + } +} + +#[stable(feature = "time2", since = "1.8.0")] +impl Sub for Instant { + type Output = Instant; + + fn sub(self, other: Duration) -> Instant { + Instant(self.0.sub_duration(&other)) + } +} + +#[stable(feature = "time_augmented_assignment", since = "1.9.0")] +impl SubAssign for Instant { + fn sub_assign(&mut self, other: Duration) { + *self = *self - other; + } +} + +#[stable(feature = "time2", since = "1.8.0")] +impl Sub for Instant { + type Output = Duration; + + fn sub(self, other: Instant) -> Duration { + self.duration_since(other) + } +} + +#[stable(feature = "time2", since = "1.8.0")] +impl fmt::Debug for Instant { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.fmt(f) + } +} + +impl SystemTime { + /// Returns the system time corresponding to "now". + /// + /// # Examples + /// + /// ``` + /// use std::time::SystemTime; + /// + /// let sys_time = SystemTime::now(); + /// ``` + #[stable(feature = "time2", since = "1.8.0")] + pub fn now() -> SystemTime { + SystemTime(time::SystemTime::now()) + } + + /// Returns the amount of time elapsed from an earlier point in time. + /// + /// This function may fail because measurements taken earlier are not + /// guaranteed to always be before later measurements (due to anomalies such + /// as the system clock being adjusted either forwards or backwards). + /// + /// If successful, [`Ok`]`(`[`Duration`]`)` is returned where the duration represents + /// the amount of time elapsed from the specified measurement to this one. + /// + /// Returns an [`Err`] if `earlier` is later than `self`, and the error + /// contains how far from `self` the time is. + /// + /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok + /// [`Duration`]: ../../std/time/struct.Duration.html + /// [`Err`]: ../../std/result/enum.Result.html#variant.Err + /// + /// # Examples + /// + /// ``` + /// use std::time::SystemTime; + /// + /// let sys_time = SystemTime::now(); + /// let difference = sys_time.duration_since(sys_time) + /// .expect("SystemTime::duration_since failed"); + /// println!("{:?}", difference); + /// ``` + #[stable(feature = "time2", since = "1.8.0")] + pub fn duration_since(&self, earlier: SystemTime) + -> Result { + self.0.sub_time(&earlier.0).map_err(SystemTimeError) + } + + /// Returns the amount of time elapsed since this system time was created. + /// + /// This function may fail as the underlying system clock is susceptible to + /// drift and updates (e.g. the system clock could go backwards), so this + /// function may not always succeed. If successful, [`Ok`]`(`[`Duration`]`)` is + /// returned where the duration represents the amount of time elapsed from + /// this time measurement to the current time. + /// + /// Returns an [`Err`] if `self` is later than the current system time, and + /// the error contains how far from the current system time `self` is. + /// + /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok + /// [`Duration`]: ../../std/time/struct.Duration.html + /// [`Err`]: ../../std/result/enum.Result.html#variant.Err + /// + /// # Examples + /// + /// ```no_run + /// use std::thread::sleep; + /// use std::time::{Duration, SystemTime}; + /// + /// let sys_time = SystemTime::now(); + /// let one_sec = Duration::from_secs(1); + /// sleep(one_sec); + /// assert!(sys_time.elapsed().unwrap() >= one_sec); + /// ``` + #[stable(feature = "time2", since = "1.8.0")] + pub fn elapsed(&self) -> Result { + SystemTime::now().duration_since(*self) + } +} + +#[stable(feature = "time2", since = "1.8.0")] +impl Add for SystemTime { + type Output = SystemTime; + + fn add(self, dur: Duration) -> SystemTime { + SystemTime(self.0.add_duration(&dur)) + } +} + +#[stable(feature = "time_augmented_assignment", since = "1.9.0")] +impl AddAssign for SystemTime { + fn add_assign(&mut self, other: Duration) { + *self = *self + other; + } +} + +#[stable(feature = "time2", since = "1.8.0")] +impl Sub for SystemTime { + type Output = SystemTime; + + fn sub(self, dur: Duration) -> SystemTime { + SystemTime(self.0.sub_duration(&dur)) + } +} + +#[stable(feature = "time_augmented_assignment", since = "1.9.0")] +impl SubAssign for SystemTime { + fn sub_assign(&mut self, other: Duration) { + *self = *self - other; + } +} + +#[stable(feature = "time2", since = "1.8.0")] +impl fmt::Debug for SystemTime { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.fmt(f) + } +} + +/// An anchor in time which can be used to create new `SystemTime` instances or +/// learn about where in time a `SystemTime` lies. +/// +/// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with +/// respect to the system clock. Using `duration_since` on an existing +/// [`SystemTime`] instance can tell how far away from this point in time a +/// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a +/// [`SystemTime`] instance to represent another fixed point in time. +/// +/// [`SystemTime`]: ../../std/time/struct.SystemTime.html +/// +/// # Examples +/// +/// ```no_run +/// use std::time::{SystemTime, UNIX_EPOCH}; +/// +/// match SystemTime::now().duration_since(UNIX_EPOCH) { +/// Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()), +/// Err(_) => panic!("SystemTime before UNIX EPOCH!"), +/// } +/// ``` +#[stable(feature = "time2", since = "1.8.0")] +pub const UNIX_EPOCH: SystemTime = SystemTime(time::UNIX_EPOCH); + +impl SystemTimeError { + /// Returns the positive duration which represents how far forward the + /// second system time was from the first. + /// + /// A `SystemTimeError` is returned from the [`duration_since`] and [`elapsed`] + /// methods of [`SystemTime`] whenever the second system time represents a point later + /// in time than the `self` of the method call. + /// + /// [`duration_since`]: ../../std/time/struct.SystemTime.html#method.duration_since + /// [`elapsed`]: ../../std/time/struct.SystemTime.html#method.elapsed + /// [`SystemTime`]: ../../std/time/struct.SystemTime.html + /// + /// # Examples + /// + /// ```no_run + /// use std::thread::sleep; + /// use std::time::{Duration, SystemTime}; + /// + /// let sys_time = SystemTime::now(); + /// sleep(Duration::from_secs(1)); + /// let new_sys_time = SystemTime::now(); + /// match sys_time.duration_since(new_sys_time) { + /// Ok(_) => {} + /// Err(e) => println!("SystemTimeError difference: {:?}", e.duration()), + /// } + /// ``` + #[stable(feature = "time2", since = "1.8.0")] + pub fn duration(&self) -> Duration { + self.0 + } +} + +#[stable(feature = "time2", since = "1.8.0")] +impl Error for SystemTimeError { + fn description(&self) -> &str { "other time was not earlier than self" } +} + +#[stable(feature = "time2", since = "1.8.0")] +impl fmt::Display for SystemTimeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "second time provided was later than self") + } +} + +impl FromInner for SystemTime { + fn from_inner(time: time::SystemTime) -> SystemTime { + SystemTime(time) + } +} + +#[cfg(test)] +mod tests { + use super::{Instant, SystemTime, Duration, UNIX_EPOCH}; + + macro_rules! assert_almost_eq { + ($a:expr, $b:expr) => ({ + let (a, b) = ($a, $b); + if a != b { + let (a, b) = if a > b {(a, b)} else {(b, a)}; + assert!(a - Duration::new(0, 100) <= b); + } + }) + } + + #[test] + fn instant_monotonic() { + let a = Instant::now(); + let b = Instant::now(); + assert!(b >= a); + } + + #[test] + fn instant_elapsed() { + let a = Instant::now(); + a.elapsed(); + } + + #[test] + fn instant_math() { + let a = Instant::now(); + let b = Instant::now(); + let dur = b.duration_since(a); + assert_almost_eq!(b - dur, a); + assert_almost_eq!(a + dur, b); + + let second = Duration::new(1, 0); + assert_almost_eq!(a - second + second, a); + } + + #[test] + #[should_panic] + fn instant_duration_panic() { + let a = Instant::now(); + (a - Duration::new(1, 0)).duration_since(a); + } + + #[test] + fn system_time_math() { + let a = SystemTime::now(); + let b = SystemTime::now(); + match b.duration_since(a) { + Ok(dur) if dur == Duration::new(0, 0) => { + assert_almost_eq!(a, b); + } + Ok(dur) => { + assert!(b > a); + assert_almost_eq!(b - dur, a); + assert_almost_eq!(a + dur, b); + } + Err(dur) => { + let dur = dur.duration(); + assert!(a > b); + assert_almost_eq!(b + dur, a); + assert_almost_eq!(a - dur, b); + } + } + + let second = Duration::new(1, 0); + assert_almost_eq!(a.duration_since(a - second).unwrap(), second); + assert_almost_eq!(a.duration_since(a + second).unwrap_err() + .duration(), second); + + assert_almost_eq!(a - second + second, a); + + // A difference of 80 and 800 years cannot fit inside a 32-bit time_t + if !(cfg!(unix) && ::mem::size_of::<::libc::time_t>() <= 4) { + let eighty_years = second * 60 * 60 * 24 * 365 * 80; + assert_almost_eq!(a - eighty_years + eighty_years, a); + assert_almost_eq!(a - (eighty_years * 10) + (eighty_years * 10), a); + } + + let one_second_from_epoch = UNIX_EPOCH + Duration::new(1, 0); + let one_second_from_epoch2 = UNIX_EPOCH + Duration::new(0, 500_000_000) + + Duration::new(0, 500_000_000); + assert_eq!(one_second_from_epoch, one_second_from_epoch2); + } + + #[test] + fn system_time_elapsed() { + let a = SystemTime::now(); + drop(a.elapsed()); + } + + #[test] + fn since_epoch() { + let ts = SystemTime::now(); + let a = ts.duration_since(UNIX_EPOCH).unwrap(); + let b = ts.duration_since(UNIX_EPOCH - Duration::new(1, 0)).unwrap(); + assert!(b > a); + assert_eq!(b - a, Duration::new(1, 0)); + + let thirty_years = Duration::new(1, 0) * 60 * 60 * 24 * 365 * 30; + + // Right now for CI this test is run in an emulator, and apparently the + // aarch64 emulator's sense of time is that we're still living in the + // 70s. + // + // Otherwise let's assume that we're all running computers later than + // 2000. + if !cfg!(target_arch = "aarch64") { + assert!(a > thirty_years); + } + + // let's assume that we're all running computers earlier than 2090. + // Should give us ~70 years to fix this! + let hundred_twenty_years = thirty_years * 4; + assert!(a < hundred_twenty_years); + } +} diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs deleted file mode 100644 index ee444830be4..00000000000 --- a/src/libstd/time/duration.rs +++ /dev/null @@ -1,590 +0,0 @@ -// 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 iter::Sum; -use ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign}; - -const NANOS_PER_SEC: u32 = 1_000_000_000; -const NANOS_PER_MILLI: u32 = 1_000_000; -const NANOS_PER_MICRO: u32 = 1_000; -const MILLIS_PER_SEC: u64 = 1_000; -const MICROS_PER_SEC: u64 = 1_000_000; - -/// A `Duration` type to represent a span of time, typically used for system -/// timeouts. -/// -/// Each `Duration` is composed of a whole number of seconds and a fractional part -/// represented in nanoseconds. If the underlying system does not support -/// nanosecond-level precision, APIs binding a system timeout will typically round up -/// the number of nanoseconds. -/// -/// `Duration`s implement many common traits, including [`Add`], [`Sub`], and other -/// [`ops`] traits. -/// -/// [`Add`]: ../../std/ops/trait.Add.html -/// [`Sub`]: ../../std/ops/trait.Sub.html -/// [`ops`]: ../../std/ops/index.html -/// -/// # Examples -/// -/// ``` -/// use std::time::Duration; -/// -/// let five_seconds = Duration::new(5, 0); -/// let five_seconds_and_five_nanos = five_seconds + Duration::new(0, 5); -/// -/// assert_eq!(five_seconds_and_five_nanos.as_secs(), 5); -/// assert_eq!(five_seconds_and_five_nanos.subsec_nanos(), 5); -/// -/// let ten_millis = Duration::from_millis(10); -/// ``` -#[stable(feature = "duration", since = "1.3.0")] -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Default)] -pub struct Duration { - secs: u64, - nanos: u32, // Always 0 <= nanos < NANOS_PER_SEC -} - -impl Duration { - /// Creates a new `Duration` from the specified number of whole seconds and - /// additional nanoseconds. - /// - /// If the number of nanoseconds is greater than 1 billion (the number of - /// nanoseconds in a second), then it will carry over into the seconds provided. - /// - /// # Panics - /// - /// This constructor will panic if the carry from the nanoseconds overflows - /// the seconds counter. - /// - /// # Examples - /// - /// ``` - /// use std::time::Duration; - /// - /// let five_seconds = Duration::new(5, 0); - /// ``` - #[stable(feature = "duration", since = "1.3.0")] - #[inline] - pub fn new(secs: u64, nanos: u32) -> Duration { - let secs = secs.checked_add((nanos / NANOS_PER_SEC) as u64) - .expect("overflow in Duration::new"); - let nanos = nanos % NANOS_PER_SEC; - Duration { secs: secs, nanos: nanos } - } - - /// Creates a new `Duration` from the specified number of whole seconds. - /// - /// # Examples - /// - /// ``` - /// use std::time::Duration; - /// - /// let duration = Duration::from_secs(5); - /// - /// assert_eq!(5, duration.as_secs()); - /// assert_eq!(0, duration.subsec_nanos()); - /// ``` - #[stable(feature = "duration", since = "1.3.0")] - #[inline] - pub const fn from_secs(secs: u64) -> Duration { - Duration { secs: secs, nanos: 0 } - } - - /// Creates a new `Duration` from the specified number of milliseconds. - /// - /// # Examples - /// - /// ``` - /// use std::time::Duration; - /// - /// let duration = Duration::from_millis(2569); - /// - /// assert_eq!(2, duration.as_secs()); - /// assert_eq!(569_000_000, duration.subsec_nanos()); - /// ``` - #[stable(feature = "duration", since = "1.3.0")] - #[inline] - pub const fn from_millis(millis: u64) -> Duration { - Duration { - secs: millis / MILLIS_PER_SEC, - nanos: ((millis % MILLIS_PER_SEC) as u32) * NANOS_PER_MILLI, - } - } - - /// Creates a new `Duration` from the specified number of microseconds. - /// - /// # Examples - /// - /// ``` - /// #![feature(duration_from_micros)] - /// use std::time::Duration; - /// - /// let duration = Duration::from_micros(1_000_002); - /// - /// assert_eq!(1, duration.as_secs()); - /// assert_eq!(2000, duration.subsec_nanos()); - /// ``` - #[unstable(feature = "duration_from_micros", issue = "44400")] - #[inline] - pub const fn from_micros(micros: u64) -> Duration { - Duration { - secs: micros / MICROS_PER_SEC, - nanos: ((micros % MICROS_PER_SEC) as u32) * NANOS_PER_MICRO, - } - } - - /// Creates a new `Duration` from the specified number of nanoseconds. - /// - /// # Examples - /// - /// ``` - /// #![feature(duration_extras)] - /// use std::time::Duration; - /// - /// let duration = Duration::from_nanos(1_000_000_123); - /// - /// assert_eq!(1, duration.as_secs()); - /// assert_eq!(123, duration.subsec_nanos()); - /// ``` - #[unstable(feature = "duration_extras", issue = "46507")] - #[inline] - pub const fn from_nanos(nanos: u64) -> Duration { - Duration { - secs: nanos / (NANOS_PER_SEC as u64), - nanos: (nanos % (NANOS_PER_SEC as u64)) as u32, - } - } - - /// Returns the number of _whole_ seconds contained by this `Duration`. - /// - /// The returned value does not include the fractional (nanosecond) part of the - /// duration, which can be obtained using [`subsec_nanos`]. - /// - /// # Examples - /// - /// ``` - /// use std::time::Duration; - /// - /// let duration = Duration::new(5, 730023852); - /// assert_eq!(duration.as_secs(), 5); - /// ``` - /// - /// To determine the total number of seconds represented by the `Duration`, - /// use `as_secs` in combination with [`subsec_nanos`]: - /// - /// ``` - /// use std::time::Duration; - /// - /// let duration = Duration::new(5, 730023852); - /// - /// assert_eq!(5.730023852, - /// duration.as_secs() as f64 - /// + duration.subsec_nanos() as f64 * 1e-9); - /// ``` - /// - /// [`subsec_nanos`]: #method.subsec_nanos - #[stable(feature = "duration", since = "1.3.0")] - #[inline] - pub fn as_secs(&self) -> u64 { self.secs } - - /// Returns the fractional part of this `Duration`, in milliseconds. - /// - /// This method does **not** return the length of the duration when - /// represented by milliseconds. The returned number always represents a - /// fractional portion of a second (i.e. it is less than one thousand). - /// - /// # Examples - /// - /// ``` - /// #![feature(duration_extras)] - /// use std::time::Duration; - /// - /// let duration = Duration::from_millis(5432); - /// assert_eq!(duration.as_secs(), 5); - /// assert_eq!(duration.subsec_millis(), 432); - /// ``` - #[unstable(feature = "duration_extras", issue = "46507")] - #[inline] - pub fn subsec_millis(&self) -> u32 { self.nanos / NANOS_PER_MILLI } - - /// Returns the fractional part of this `Duration`, in microseconds. - /// - /// This method does **not** return the length of the duration when - /// represented by microseconds. The returned number always represents a - /// fractional portion of a second (i.e. it is less than one million). - /// - /// # Examples - /// - /// ``` - /// #![feature(duration_extras, duration_from_micros)] - /// use std::time::Duration; - /// - /// let duration = Duration::from_micros(1_234_567); - /// assert_eq!(duration.as_secs(), 1); - /// assert_eq!(duration.subsec_micros(), 234_567); - /// ``` - #[unstable(feature = "duration_extras", issue = "46507")] - #[inline] - pub fn subsec_micros(&self) -> u32 { self.nanos / NANOS_PER_MICRO } - - /// Returns the fractional part of this `Duration`, in nanoseconds. - /// - /// This method does **not** return the length of the duration when - /// represented by nanoseconds. The returned number always represents a - /// fractional portion of a second (i.e. it is less than one billion). - /// - /// # Examples - /// - /// ``` - /// use std::time::Duration; - /// - /// let duration = Duration::from_millis(5010); - /// assert_eq!(duration.as_secs(), 5); - /// assert_eq!(duration.subsec_nanos(), 10_000_000); - /// ``` - #[stable(feature = "duration", since = "1.3.0")] - #[inline] - pub fn subsec_nanos(&self) -> u32 { self.nanos } - - /// Checked `Duration` addition. Computes `self + other`, returning [`None`] - /// if overflow occurred. - /// - /// [`None`]: ../../std/option/enum.Option.html#variant.None - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// use std::time::Duration; - /// - /// assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), Some(Duration::new(0, 1))); - /// assert_eq!(Duration::new(1, 0).checked_add(Duration::new(std::u64::MAX, 0)), None); - /// ``` - #[stable(feature = "duration_checked_ops", since = "1.16.0")] - #[inline] - pub fn checked_add(self, rhs: Duration) -> Option { - if let Some(mut secs) = self.secs.checked_add(rhs.secs) { - let mut nanos = self.nanos + rhs.nanos; - if nanos >= NANOS_PER_SEC { - nanos -= NANOS_PER_SEC; - if let Some(new_secs) = secs.checked_add(1) { - secs = new_secs; - } else { - return None; - } - } - debug_assert!(nanos < NANOS_PER_SEC); - Some(Duration { - secs, - nanos, - }) - } else { - None - } - } - - /// Checked `Duration` subtraction. Computes `self - other`, returning [`None`] - /// if the result would be negative or if overflow occurred. - /// - /// [`None`]: ../../std/option/enum.Option.html#variant.None - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// use std::time::Duration; - /// - /// assert_eq!(Duration::new(0, 1).checked_sub(Duration::new(0, 0)), Some(Duration::new(0, 1))); - /// assert_eq!(Duration::new(0, 0).checked_sub(Duration::new(0, 1)), None); - /// ``` - #[stable(feature = "duration_checked_ops", since = "1.16.0")] - #[inline] - pub fn checked_sub(self, rhs: Duration) -> Option { - if let Some(mut secs) = self.secs.checked_sub(rhs.secs) { - let nanos = if self.nanos >= rhs.nanos { - self.nanos - rhs.nanos - } else { - if let Some(sub_secs) = secs.checked_sub(1) { - secs = sub_secs; - self.nanos + NANOS_PER_SEC - rhs.nanos - } else { - return None; - } - }; - debug_assert!(nanos < NANOS_PER_SEC); - Some(Duration { secs: secs, nanos: nanos }) - } else { - None - } - } - - /// Checked `Duration` multiplication. Computes `self * other`, returning - /// [`None`] if overflow occurred. - /// - /// [`None`]: ../../std/option/enum.Option.html#variant.None - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// use std::time::Duration; - /// - /// assert_eq!(Duration::new(0, 500_000_001).checked_mul(2), Some(Duration::new(1, 2))); - /// assert_eq!(Duration::new(std::u64::MAX - 1, 0).checked_mul(2), None); - /// ``` - #[stable(feature = "duration_checked_ops", since = "1.16.0")] - #[inline] - pub fn checked_mul(self, rhs: u32) -> Option { - // Multiply nanoseconds as u64, because it cannot overflow that way. - let total_nanos = self.nanos as u64 * rhs as u64; - let extra_secs = total_nanos / (NANOS_PER_SEC as u64); - let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32; - if let Some(secs) = self.secs - .checked_mul(rhs as u64) - .and_then(|s| s.checked_add(extra_secs)) { - debug_assert!(nanos < NANOS_PER_SEC); - Some(Duration { - secs, - nanos, - }) - } else { - None - } - } - - /// Checked `Duration` division. Computes `self / other`, returning [`None`] - /// if `other == 0`. - /// - /// [`None`]: ../../std/option/enum.Option.html#variant.None - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// use std::time::Duration; - /// - /// assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0))); - /// assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000))); - /// assert_eq!(Duration::new(2, 0).checked_div(0), None); - /// ``` - #[stable(feature = "duration_checked_ops", since = "1.16.0")] - #[inline] - pub fn checked_div(self, rhs: u32) -> Option { - if rhs != 0 { - let secs = self.secs / (rhs as u64); - let carry = self.secs - secs * (rhs as u64); - let extra_nanos = carry * (NANOS_PER_SEC as u64) / (rhs as u64); - let nanos = self.nanos / rhs + (extra_nanos as u32); - debug_assert!(nanos < NANOS_PER_SEC); - Some(Duration { secs: secs, nanos: nanos }) - } else { - None - } - } -} - -#[stable(feature = "duration", since = "1.3.0")] -impl Add for Duration { - type Output = Duration; - - fn add(self, rhs: Duration) -> Duration { - self.checked_add(rhs).expect("overflow when adding durations") - } -} - -#[stable(feature = "time_augmented_assignment", since = "1.9.0")] -impl AddAssign for Duration { - fn add_assign(&mut self, rhs: Duration) { - *self = *self + rhs; - } -} - -#[stable(feature = "duration", since = "1.3.0")] -impl Sub for Duration { - type Output = Duration; - - fn sub(self, rhs: Duration) -> Duration { - self.checked_sub(rhs).expect("overflow when subtracting durations") - } -} - -#[stable(feature = "time_augmented_assignment", since = "1.9.0")] -impl SubAssign for Duration { - fn sub_assign(&mut self, rhs: Duration) { - *self = *self - rhs; - } -} - -#[stable(feature = "duration", since = "1.3.0")] -impl Mul for Duration { - type Output = Duration; - - fn mul(self, rhs: u32) -> Duration { - self.checked_mul(rhs).expect("overflow when multiplying duration by scalar") - } -} - -#[stable(feature = "time_augmented_assignment", since = "1.9.0")] -impl MulAssign for Duration { - fn mul_assign(&mut self, rhs: u32) { - *self = *self * rhs; - } -} - -#[stable(feature = "duration", since = "1.3.0")] -impl Div for Duration { - type Output = Duration; - - fn div(self, rhs: u32) -> Duration { - self.checked_div(rhs).expect("divide by zero error when dividing duration by scalar") - } -} - -#[stable(feature = "time_augmented_assignment", since = "1.9.0")] -impl DivAssign for Duration { - fn div_assign(&mut self, rhs: u32) { - *self = *self / rhs; - } -} - -#[stable(feature = "duration_sum", since = "1.16.0")] -impl Sum for Duration { - fn sum>(iter: I) -> Duration { - iter.fold(Duration::new(0, 0), |a, b| a + b) - } -} - -#[stable(feature = "duration_sum", since = "1.16.0")] -impl<'a> Sum<&'a Duration> for Duration { - fn sum>(iter: I) -> Duration { - iter.fold(Duration::new(0, 0), |a, b| a + *b) - } -} - -#[cfg(test)] -mod tests { - use super::Duration; - - #[test] - fn creation() { - assert!(Duration::from_secs(1) != Duration::from_secs(0)); - assert_eq!(Duration::from_secs(1) + Duration::from_secs(2), - Duration::from_secs(3)); - assert_eq!(Duration::from_millis(10) + Duration::from_secs(4), - Duration::new(4, 10 * 1_000_000)); - assert_eq!(Duration::from_millis(4000), Duration::new(4, 0)); - } - - #[test] - fn secs() { - assert_eq!(Duration::new(0, 0).as_secs(), 0); - assert_eq!(Duration::from_secs(1).as_secs(), 1); - assert_eq!(Duration::from_millis(999).as_secs(), 0); - assert_eq!(Duration::from_millis(1001).as_secs(), 1); - } - - #[test] - fn nanos() { - assert_eq!(Duration::new(0, 0).subsec_nanos(), 0); - assert_eq!(Duration::new(0, 5).subsec_nanos(), 5); - assert_eq!(Duration::new(0, 1_000_000_001).subsec_nanos(), 1); - assert_eq!(Duration::from_secs(1).subsec_nanos(), 0); - assert_eq!(Duration::from_millis(999).subsec_nanos(), 999 * 1_000_000); - assert_eq!(Duration::from_millis(1001).subsec_nanos(), 1 * 1_000_000); - } - - #[test] - fn add() { - assert_eq!(Duration::new(0, 0) + Duration::new(0, 1), - Duration::new(0, 1)); - assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001), - Duration::new(1, 1)); - } - - #[test] - fn checked_add() { - assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), - Some(Duration::new(0, 1))); - assert_eq!(Duration::new(0, 500_000_000).checked_add(Duration::new(0, 500_000_001)), - Some(Duration::new(1, 1))); - assert_eq!(Duration::new(1, 0).checked_add(Duration::new(::u64::MAX, 0)), None); - } - - #[test] - fn sub() { - assert_eq!(Duration::new(0, 1) - Duration::new(0, 0), - Duration::new(0, 1)); - assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000), - Duration::new(0, 1)); - assert_eq!(Duration::new(1, 0) - Duration::new(0, 1), - Duration::new(0, 999_999_999)); - } - - #[test] - fn checked_sub() { - let zero = Duration::new(0, 0); - let one_nano = Duration::new(0, 1); - let one_sec = Duration::new(1, 0); - assert_eq!(one_nano.checked_sub(zero), Some(Duration::new(0, 1))); - assert_eq!(one_sec.checked_sub(one_nano), - Some(Duration::new(0, 999_999_999))); - assert_eq!(zero.checked_sub(one_nano), None); - assert_eq!(zero.checked_sub(one_sec), None); - } - - #[test] #[should_panic] - fn sub_bad1() { - Duration::new(0, 0) - Duration::new(0, 1); - } - - #[test] #[should_panic] - fn sub_bad2() { - Duration::new(0, 0) - Duration::new(1, 0); - } - - #[test] - fn mul() { - assert_eq!(Duration::new(0, 1) * 2, Duration::new(0, 2)); - assert_eq!(Duration::new(1, 1) * 3, Duration::new(3, 3)); - assert_eq!(Duration::new(0, 500_000_001) * 4, Duration::new(2, 4)); - assert_eq!(Duration::new(0, 500_000_001) * 4000, - Duration::new(2000, 4000)); - } - - #[test] - fn checked_mul() { - assert_eq!(Duration::new(0, 1).checked_mul(2), Some(Duration::new(0, 2))); - assert_eq!(Duration::new(1, 1).checked_mul(3), Some(Duration::new(3, 3))); - assert_eq!(Duration::new(0, 500_000_001).checked_mul(4), Some(Duration::new(2, 4))); - assert_eq!(Duration::new(0, 500_000_001).checked_mul(4000), - Some(Duration::new(2000, 4000))); - assert_eq!(Duration::new(::u64::MAX - 1, 0).checked_mul(2), None); - } - - #[test] - fn div() { - assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0)); - assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333)); - assert_eq!(Duration::new(99, 999_999_000) / 100, - Duration::new(0, 999_999_990)); - } - - #[test] - fn checked_div() { - assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0))); - assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000))); - assert_eq!(Duration::new(2, 0).checked_div(0), None); - } -} diff --git a/src/libstd/time/mod.rs b/src/libstd/time/mod.rs deleted file mode 100644 index 6ce3b3e8a00..00000000000 --- a/src/libstd/time/mod.rs +++ /dev/null @@ -1,567 +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. - -//! Temporal quantification. -//! -//! Example: -//! -//! ``` -//! use std::time::Duration; -//! -//! let five_seconds = Duration::new(5, 0); -//! // both declarations are equivalent -//! assert_eq!(Duration::new(5, 0), Duration::from_secs(5)); -//! ``` - -#![stable(feature = "time", since = "1.3.0")] - -use error::Error; -use fmt; -use ops::{Add, Sub, AddAssign, SubAssign}; -use sys::time; -use sys_common::FromInner; - -#[stable(feature = "time", since = "1.3.0")] -pub use self::duration::Duration; - -mod duration; - -/// A measurement of a monotonically nondecreasing clock. -/// Opaque and useful only with `Duration`. -/// -/// Instants are always guaranteed to be no less than any previously measured -/// instant when created, and are often useful for tasks such as measuring -/// benchmarks or timing how long an operation takes. -/// -/// Note, however, that instants are not guaranteed to be **steady**. In other -/// words, each tick of the underlying clock may not be the same length (e.g. -/// some seconds may be longer than others). An instant may jump forwards or -/// experience time dilation (slow down or speed up), but it will never go -/// backwards. -/// -/// Instants are opaque types that can only be compared to one another. There is -/// no method to get "the number of seconds" from an instant. Instead, it only -/// allows measuring the duration between two instants (or comparing two -/// instants). -/// -/// Example: -/// -/// ```no_run -/// use std::time::{Duration, Instant}; -/// use std::thread::sleep; -/// -/// fn main() { -/// let now = Instant::now(); -/// -/// // we sleep for 2 seconds -/// sleep(Duration::new(2, 0)); -/// // it prints '2' -/// println!("{}", now.elapsed().as_secs()); -/// } -/// ``` -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[stable(feature = "time2", since = "1.8.0")] -pub struct Instant(time::Instant); - -/// A measurement of the system clock, useful for talking to -/// external entities like the file system or other processes. -/// -/// Distinct from the [`Instant`] type, this time measurement **is not -/// monotonic**. This means that you can save a file to the file system, then -/// save another file to the file system, **and the second file has a -/// `SystemTime` measurement earlier than the first**. In other words, an -/// operation that happens after another operation in real time may have an -/// earlier `SystemTime`! -/// -/// Consequently, comparing two `SystemTime` instances to learn about the -/// duration between them returns a [`Result`] instead of an infallible [`Duration`] -/// to indicate that this sort of time drift may happen and needs to be handled. -/// -/// Although a `SystemTime` cannot be directly inspected, the [`UNIX_EPOCH`] -/// constant is provided in this module as an anchor in time to learn -/// information about a `SystemTime`. By calculating the duration from this -/// fixed point in time, a `SystemTime` can be converted to a human-readable time, -/// or perhaps some other string representation. -/// -/// [`Instant`]: ../../std/time/struct.Instant.html -/// [`Result`]: ../../std/result/enum.Result.html -/// [`Duration`]: ../../std/time/struct.Duration.html -/// [`UNIX_EPOCH`]: ../../std/time/constant.UNIX_EPOCH.html -/// -/// Example: -/// -/// ```no_run -/// use std::time::{Duration, SystemTime}; -/// use std::thread::sleep; -/// -/// fn main() { -/// let now = SystemTime::now(); -/// -/// // we sleep for 2 seconds -/// sleep(Duration::new(2, 0)); -/// match now.elapsed() { -/// Ok(elapsed) => { -/// // it prints '2' -/// println!("{}", elapsed.as_secs()); -/// } -/// Err(e) => { -/// // an error occurred! -/// println!("Error: {:?}", e); -/// } -/// } -/// } -/// ``` -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[stable(feature = "time2", since = "1.8.0")] -pub struct SystemTime(time::SystemTime); - -/// An error returned from the `duration_since` and `elapsed` methods on -/// `SystemTime`, used to learn how far in the opposite direction a system time -/// lies. -/// -/// # Examples -/// -/// ```no_run -/// use std::thread::sleep; -/// use std::time::{Duration, SystemTime}; -/// -/// let sys_time = SystemTime::now(); -/// sleep(Duration::from_secs(1)); -/// let new_sys_time = SystemTime::now(); -/// match sys_time.duration_since(new_sys_time) { -/// Ok(_) => {} -/// Err(e) => println!("SystemTimeError difference: {:?}", e.duration()), -/// } -/// ``` -#[derive(Clone, Debug)] -#[stable(feature = "time2", since = "1.8.0")] -pub struct SystemTimeError(Duration); - -impl Instant { - /// Returns an instant corresponding to "now". - /// - /// # Examples - /// - /// ``` - /// use std::time::Instant; - /// - /// let now = Instant::now(); - /// ``` - #[stable(feature = "time2", since = "1.8.0")] - pub fn now() -> Instant { - Instant(time::Instant::now()) - } - - /// Returns the amount of time elapsed from another instant to this one. - /// - /// # Panics - /// - /// This function will panic if `earlier` is later than `self`. - /// - /// # Examples - /// - /// ```no_run - /// use std::time::{Duration, Instant}; - /// use std::thread::sleep; - /// - /// let now = Instant::now(); - /// sleep(Duration::new(1, 0)); - /// let new_now = Instant::now(); - /// println!("{:?}", new_now.duration_since(now)); - /// ``` - #[stable(feature = "time2", since = "1.8.0")] - pub fn duration_since(&self, earlier: Instant) -> Duration { - self.0.sub_instant(&earlier.0) - } - - /// Returns the amount of time elapsed since this instant was created. - /// - /// # Panics - /// - /// This function may panic if the current time is earlier than this - /// instant, which is something that can happen if an `Instant` is - /// produced synthetically. - /// - /// # Examples - /// - /// ```no_run - /// use std::thread::sleep; - /// use std::time::{Duration, Instant}; - /// - /// let instant = Instant::now(); - /// let three_secs = Duration::from_secs(3); - /// sleep(three_secs); - /// assert!(instant.elapsed() >= three_secs); - /// ``` - #[stable(feature = "time2", since = "1.8.0")] - pub fn elapsed(&self) -> Duration { - Instant::now() - *self - } -} - -#[stable(feature = "time2", since = "1.8.0")] -impl Add for Instant { - type Output = Instant; - - fn add(self, other: Duration) -> Instant { - Instant(self.0.add_duration(&other)) - } -} - -#[stable(feature = "time_augmented_assignment", since = "1.9.0")] -impl AddAssign for Instant { - fn add_assign(&mut self, other: Duration) { - *self = *self + other; - } -} - -#[stable(feature = "time2", since = "1.8.0")] -impl Sub for Instant { - type Output = Instant; - - fn sub(self, other: Duration) -> Instant { - Instant(self.0.sub_duration(&other)) - } -} - -#[stable(feature = "time_augmented_assignment", since = "1.9.0")] -impl SubAssign for Instant { - fn sub_assign(&mut self, other: Duration) { - *self = *self - other; - } -} - -#[stable(feature = "time2", since = "1.8.0")] -impl Sub for Instant { - type Output = Duration; - - fn sub(self, other: Instant) -> Duration { - self.duration_since(other) - } -} - -#[stable(feature = "time2", since = "1.8.0")] -impl fmt::Debug for Instant { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.0.fmt(f) - } -} - -impl SystemTime { - /// Returns the system time corresponding to "now". - /// - /// # Examples - /// - /// ``` - /// use std::time::SystemTime; - /// - /// let sys_time = SystemTime::now(); - /// ``` - #[stable(feature = "time2", since = "1.8.0")] - pub fn now() -> SystemTime { - SystemTime(time::SystemTime::now()) - } - - /// Returns the amount of time elapsed from an earlier point in time. - /// - /// This function may fail because measurements taken earlier are not - /// guaranteed to always be before later measurements (due to anomalies such - /// as the system clock being adjusted either forwards or backwards). - /// - /// If successful, [`Ok`]`(`[`Duration`]`)` is returned where the duration represents - /// the amount of time elapsed from the specified measurement to this one. - /// - /// Returns an [`Err`] if `earlier` is later than `self`, and the error - /// contains how far from `self` the time is. - /// - /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok - /// [`Duration`]: ../../std/time/struct.Duration.html - /// [`Err`]: ../../std/result/enum.Result.html#variant.Err - /// - /// # Examples - /// - /// ``` - /// use std::time::SystemTime; - /// - /// let sys_time = SystemTime::now(); - /// let difference = sys_time.duration_since(sys_time) - /// .expect("SystemTime::duration_since failed"); - /// println!("{:?}", difference); - /// ``` - #[stable(feature = "time2", since = "1.8.0")] - pub fn duration_since(&self, earlier: SystemTime) - -> Result { - self.0.sub_time(&earlier.0).map_err(SystemTimeError) - } - - /// Returns the amount of time elapsed since this system time was created. - /// - /// This function may fail as the underlying system clock is susceptible to - /// drift and updates (e.g. the system clock could go backwards), so this - /// function may not always succeed. If successful, [`Ok`]`(`[`Duration`]`)` is - /// returned where the duration represents the amount of time elapsed from - /// this time measurement to the current time. - /// - /// Returns an [`Err`] if `self` is later than the current system time, and - /// the error contains how far from the current system time `self` is. - /// - /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok - /// [`Duration`]: ../../std/time/struct.Duration.html - /// [`Err`]: ../../std/result/enum.Result.html#variant.Err - /// - /// # Examples - /// - /// ```no_run - /// use std::thread::sleep; - /// use std::time::{Duration, SystemTime}; - /// - /// let sys_time = SystemTime::now(); - /// let one_sec = Duration::from_secs(1); - /// sleep(one_sec); - /// assert!(sys_time.elapsed().unwrap() >= one_sec); - /// ``` - #[stable(feature = "time2", since = "1.8.0")] - pub fn elapsed(&self) -> Result { - SystemTime::now().duration_since(*self) - } -} - -#[stable(feature = "time2", since = "1.8.0")] -impl Add for SystemTime { - type Output = SystemTime; - - fn add(self, dur: Duration) -> SystemTime { - SystemTime(self.0.add_duration(&dur)) - } -} - -#[stable(feature = "time_augmented_assignment", since = "1.9.0")] -impl AddAssign for SystemTime { - fn add_assign(&mut self, other: Duration) { - *self = *self + other; - } -} - -#[stable(feature = "time2", since = "1.8.0")] -impl Sub for SystemTime { - type Output = SystemTime; - - fn sub(self, dur: Duration) -> SystemTime { - SystemTime(self.0.sub_duration(&dur)) - } -} - -#[stable(feature = "time_augmented_assignment", since = "1.9.0")] -impl SubAssign for SystemTime { - fn sub_assign(&mut self, other: Duration) { - *self = *self - other; - } -} - -#[stable(feature = "time2", since = "1.8.0")] -impl fmt::Debug for SystemTime { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.0.fmt(f) - } -} - -/// An anchor in time which can be used to create new `SystemTime` instances or -/// learn about where in time a `SystemTime` lies. -/// -/// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with -/// respect to the system clock. Using `duration_since` on an existing -/// [`SystemTime`] instance can tell how far away from this point in time a -/// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a -/// [`SystemTime`] instance to represent another fixed point in time. -/// -/// [`SystemTime`]: ../../std/time/struct.SystemTime.html -/// -/// # Examples -/// -/// ```no_run -/// use std::time::{SystemTime, UNIX_EPOCH}; -/// -/// match SystemTime::now().duration_since(UNIX_EPOCH) { -/// Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()), -/// Err(_) => panic!("SystemTime before UNIX EPOCH!"), -/// } -/// ``` -#[stable(feature = "time2", since = "1.8.0")] -pub const UNIX_EPOCH: SystemTime = SystemTime(time::UNIX_EPOCH); - -impl SystemTimeError { - /// Returns the positive duration which represents how far forward the - /// second system time was from the first. - /// - /// A `SystemTimeError` is returned from the [`duration_since`] and [`elapsed`] - /// methods of [`SystemTime`] whenever the second system time represents a point later - /// in time than the `self` of the method call. - /// - /// [`duration_since`]: ../../std/time/struct.SystemTime.html#method.duration_since - /// [`elapsed`]: ../../std/time/struct.SystemTime.html#method.elapsed - /// [`SystemTime`]: ../../std/time/struct.SystemTime.html - /// - /// # Examples - /// - /// ```no_run - /// use std::thread::sleep; - /// use std::time::{Duration, SystemTime}; - /// - /// let sys_time = SystemTime::now(); - /// sleep(Duration::from_secs(1)); - /// let new_sys_time = SystemTime::now(); - /// match sys_time.duration_since(new_sys_time) { - /// Ok(_) => {} - /// Err(e) => println!("SystemTimeError difference: {:?}", e.duration()), - /// } - /// ``` - #[stable(feature = "time2", since = "1.8.0")] - pub fn duration(&self) -> Duration { - self.0 - } -} - -#[stable(feature = "time2", since = "1.8.0")] -impl Error for SystemTimeError { - fn description(&self) -> &str { "other time was not earlier than self" } -} - -#[stable(feature = "time2", since = "1.8.0")] -impl fmt::Display for SystemTimeError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "second time provided was later than self") - } -} - -impl FromInner for SystemTime { - fn from_inner(time: time::SystemTime) -> SystemTime { - SystemTime(time) - } -} - -#[cfg(test)] -mod tests { - use super::{Instant, SystemTime, Duration, UNIX_EPOCH}; - - macro_rules! assert_almost_eq { - ($a:expr, $b:expr) => ({ - let (a, b) = ($a, $b); - if a != b { - let (a, b) = if a > b {(a, b)} else {(b, a)}; - assert!(a - Duration::new(0, 100) <= b); - } - }) - } - - #[test] - fn instant_monotonic() { - let a = Instant::now(); - let b = Instant::now(); - assert!(b >= a); - } - - #[test] - fn instant_elapsed() { - let a = Instant::now(); - a.elapsed(); - } - - #[test] - fn instant_math() { - let a = Instant::now(); - let b = Instant::now(); - let dur = b.duration_since(a); - assert_almost_eq!(b - dur, a); - assert_almost_eq!(a + dur, b); - - let second = Duration::new(1, 0); - assert_almost_eq!(a - second + second, a); - } - - #[test] - #[should_panic] - fn instant_duration_panic() { - let a = Instant::now(); - (a - Duration::new(1, 0)).duration_since(a); - } - - #[test] - fn system_time_math() { - let a = SystemTime::now(); - let b = SystemTime::now(); - match b.duration_since(a) { - Ok(dur) if dur == Duration::new(0, 0) => { - assert_almost_eq!(a, b); - } - Ok(dur) => { - assert!(b > a); - assert_almost_eq!(b - dur, a); - assert_almost_eq!(a + dur, b); - } - Err(dur) => { - let dur = dur.duration(); - assert!(a > b); - assert_almost_eq!(b + dur, a); - assert_almost_eq!(a - dur, b); - } - } - - let second = Duration::new(1, 0); - assert_almost_eq!(a.duration_since(a - second).unwrap(), second); - assert_almost_eq!(a.duration_since(a + second).unwrap_err() - .duration(), second); - - assert_almost_eq!(a - second + second, a); - - // A difference of 80 and 800 years cannot fit inside a 32-bit time_t - if !(cfg!(unix) && ::mem::size_of::<::libc::time_t>() <= 4) { - let eighty_years = second * 60 * 60 * 24 * 365 * 80; - assert_almost_eq!(a - eighty_years + eighty_years, a); - assert_almost_eq!(a - (eighty_years * 10) + (eighty_years * 10), a); - } - - let one_second_from_epoch = UNIX_EPOCH + Duration::new(1, 0); - let one_second_from_epoch2 = UNIX_EPOCH + Duration::new(0, 500_000_000) - + Duration::new(0, 500_000_000); - assert_eq!(one_second_from_epoch, one_second_from_epoch2); - } - - #[test] - fn system_time_elapsed() { - let a = SystemTime::now(); - drop(a.elapsed()); - } - - #[test] - fn since_epoch() { - let ts = SystemTime::now(); - let a = ts.duration_since(UNIX_EPOCH).unwrap(); - let b = ts.duration_since(UNIX_EPOCH - Duration::new(1, 0)).unwrap(); - assert!(b > a); - assert_eq!(b - a, Duration::new(1, 0)); - - let thirty_years = Duration::new(1, 0) * 60 * 60 * 24 * 365 * 30; - - // Right now for CI this test is run in an emulator, and apparently the - // aarch64 emulator's sense of time is that we're still living in the - // 70s. - // - // Otherwise let's assume that we're all running computers later than - // 2000. - if !cfg!(target_arch = "aarch64") { - assert!(a > thirty_years); - } - - // let's assume that we're all running computers earlier than 2090. - // Should give us ~70 years to fix this! - let hundred_twenty_years = thirty_years * 4; - assert!(a < hundred_twenty_years); - } -} diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 73810b3fe81..c7ab6158256 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -883,7 +883,6 @@ pub struct Arm { pub pats: Vec>, pub guard: Option>, pub body: P, - pub beginning_vert: Option, // For RFC 1925 feature gate } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index a6a7f9e20b3..3601b9ba8a8 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -593,8 +593,30 @@ pub fn span_until_char(&self, sp: Span, c: char) -> Span { } } - /// Given a `Span`, try to get a shorter span ending just after the first - /// occurrence of `char` `c`. + /// Given a `Span`, get a new `Span` covering the first token and all its trailing whitespace or + /// the original `Span`. + /// + /// If `sp` points to `"let mut x"`, then a span pointing at `"let "` will be returned. + pub fn span_until_non_whitespace(&self, sp: Span) -> Span { + if let Ok(snippet) = self.span_to_snippet(sp) { + let mut offset = 0; + // get the bytes width of all the non-whitespace characters + for c in snippet.chars().take_while(|c| !c.is_whitespace()) { + offset += c.len_utf8(); + } + // get the bytes width of all the whitespace characters after that + for c in snippet[offset..].chars().take_while(|c| c.is_whitespace()) { + offset += c.len_utf8(); + } + if offset > 1 { + return sp.with_hi(BytePos(sp.lo().0 + offset as u32)); + } + } + sp + } + + /// Given a `Span`, try to get a shorter span ending just after the first occurrence of `char` + /// `c`. pub fn span_through_char(&self, sp: Span, c: char) -> Span { if let Ok(snippet) = self.span_to_snippet(sp) { if let Some(offset) = snippet.find(c) { diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index cf63592c2ec..2e6de96d65a 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -883,7 +883,6 @@ fn arm(&self, _span: Span, pats: Vec>, expr: P) -> ast::A pats, guard: None, body: expr, - beginning_vert: None, } } diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 3e3c1618fff..0621f728e2a 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -90,8 +90,8 @@ use errors::FatalError; use ext::tt::quoted::{self, TokenTree}; use parse::{Directory, ParseSess}; -use parse::parser::{PathStyle, Parser}; -use parse::token::{self, DocComment, Token, Nonterminal}; +use parse::parser::{Parser, PathStyle}; +use parse::token::{self, DocComment, Nonterminal, Token}; use print::pprust; use symbol::keywords; use tokenstream::TokenStream; @@ -100,11 +100,12 @@ use std::mem; use std::rc::Rc; use std::collections::HashMap; -use std::collections::hash_map::Entry::{Vacant, Occupied}; +use std::collections::hash_map::Entry::{Occupied, Vacant}; -// To avoid costly uniqueness checks, we require that `MatchSeq` always has -// a nonempty body. +// To avoid costly uniqueness checks, we require that `MatchSeq` always has a nonempty body. +/// Either a sequence of token trees or a single one. This is used as the representation of the +/// sequence of tokens that make up a matcher. #[derive(Clone)] enum TokenTreeOrTokenTreeVec { Tt(TokenTree), @@ -112,6 +113,8 @@ enum TokenTreeOrTokenTreeVec { } impl TokenTreeOrTokenTreeVec { + /// Returns the number of constituent top-level token trees of `self` (top-level in that it + /// will not recursively descend into subtrees). fn len(&self) -> usize { match *self { TtSeq(ref v) => v.len(), @@ -119,6 +122,7 @@ fn len(&self) -> usize { } } + /// The the `index`-th token tree of `self`. fn get_tt(&self, index: usize) -> TokenTree { match *self { TtSeq(ref v) => v[index].clone(), @@ -127,36 +131,98 @@ fn get_tt(&self, index: usize) -> TokenTree { } } -/// an unzipping of `TokenTree`s +/// An unzipping of `TokenTree`s... see the `stack` field of `MatcherPos`. +/// +/// This is used by `inner_parse_loop` to keep track of delimited submatchers that we have +/// descended into. #[derive(Clone)] struct MatcherTtFrame { + /// The "parent" matcher that we are descending into. elts: TokenTreeOrTokenTreeVec, + /// The position of the "dot" in `elts` at the time we descended. idx: usize, } +/// Represents a single "position" (aka "matcher position", aka "item"), as described in the module +/// documentation. #[derive(Clone)] struct MatcherPos { - stack: Vec, + /// The token or sequence of tokens that make up the matcher top_elts: TokenTreeOrTokenTreeVec, - sep: Option, + /// The position of the "dot" in this matcher idx: usize, - up: Option>, + /// The beginning position in the source that the beginning of this matcher corresponds to. In + /// other words, the token in the source at `sp_lo` is matched against the first token of the + /// matcher. + sp_lo: BytePos, + + /// For each named metavar in the matcher, we keep track of token trees matched against the + /// metavar by the black box parser. In particular, there may be more than one match per + /// metavar if we are in a repetition (each repetition matches each of the variables). + /// Moreover, matchers and repetitions can be nested; the `matches` field is shared (hence the + /// `Rc`) among all "nested" matchers. `match_lo`, `match_cur`, and `match_hi` keep track of + /// the current position of the `self` matcher position in the shared `matches` list. + /// + /// Also, note that while we are descending into a sequence, matchers are given their own + /// `matches` vector. Only once we reach the end of a full repetition of the sequence do we add + /// all bound matches from the submatcher into the shared top-level `matches` vector. If `sep` + /// and `up` are `Some`, then `matches` is _not_ the shared top-level list. Instead, if one + /// wants the shared `matches`, one should use `up.matches`. matches: Vec>>, + /// The position in `matches` corresponding to the first metavar in this matcher's sequence of + /// token trees. In other words, the first metavar in the first token of `top_elts` corresponds + /// to `matches[match_lo]`. match_lo: usize, + /// The position in `matches` corresponding to the metavar we are currently trying to match + /// against the source token stream. `match_lo <= match_cur <= match_hi`. match_cur: usize, + /// Similar to `match_lo` except `match_hi` is the position in `matches` of the _last_ metavar + /// in this matcher. match_hi: usize, - sp_lo: BytePos, + + // Specifically used if we are matching a repetition. If we aren't both should be `None`. + /// The KleeneOp of this sequence if we are in a repetition. + seq_op: Option, + /// The separator if we are in a repetition + sep: Option, + /// The "parent" matcher position if we are in a repetition. That is, the matcher position just + /// before we enter the sequence. + up: Option>, + + // Specifically used to "unzip" token trees. By "unzip", we mean to unwrap the delimiters from + // a delimited token tree (e.g. something wrapped in `(` `)`) or to get the contents of a doc + // comment... + /// When matching against matchers with nested delimited submatchers (e.g. `pat ( pat ( .. ) + /// pat ) pat`), we need to keep track of the matchers we are descending into. This stack does + /// that where the bottom of the stack is the outermost matcher. + // Also, throughout the comments, this "descent" is often referred to as "unzipping"... + stack: Vec, } impl MatcherPos { + /// Add `m` as a named match for the `idx`-th metavar. fn push_match(&mut self, idx: usize, m: NamedMatch) { let matches = Rc::make_mut(&mut self.matches[idx]); matches.push(m); } } +/// Represents the possible results of an attempted parse. +pub enum ParseResult { + /// Parsed successfully. + Success(T), + /// Arm failed to match. If the second parameter is `token::Eof`, it indicates an unexpected + /// end of macro invocation. Otherwise, it indicates that no rules expected the given token. + Failure(syntax_pos::Span, Token), + /// Fatal error (malformed macro?). Abort compilation. + Error(syntax_pos::Span, String), +} + +/// A `ParseResult` where the `Success` variant contains a mapping of `Ident`s to `NamedMatch`es. +/// This represents the mapping of metavars to the token trees they bind to. pub type NamedParseResult = ParseResult>>; +/// Count how many metavars are named in the given matcher `ms`. pub fn count_names(ms: &[TokenTree]) -> usize { ms.iter().fold(0, |count, elt| { count + match *elt { @@ -169,20 +235,39 @@ pub fn count_names(ms: &[TokenTree]) -> usize { }) } +/// Initialize `len` empty shared `Vec`s to be used to store matches of metavars. +fn create_matches(len: usize) -> Vec>> { + (0..len).into_iter().map(|_| Rc::new(Vec::new())).collect() +} + +/// Generate the top-level matcher position in which the "dot" is before the first token of the +/// matcher `ms` and we are going to start matching at position `lo` in the source. fn initial_matcher_pos(ms: Vec, lo: BytePos) -> Box { let match_idx_hi = count_names(&ms[..]); let matches = create_matches(match_idx_hi); Box::new(MatcherPos { - stack: vec![], - top_elts: TtSeq(ms), - sep: None, + // Start with the top level matcher given to us + top_elts: TtSeq(ms), // "elts" is an abbr. for "elements" + // The "dot" is before the first token of the matcher idx: 0, - up: None, + // We start matching with byte `lo` in the source code + sp_lo: lo, + + // Initialize `matches` to a bunch of empty `Vec`s -- one for each metavar in `top_elts`. + // `match_lo` for `top_elts` is 0 and `match_hi` is `matches.len()`. `match_cur` is 0 since + // we haven't actually matched anything yet. matches, match_lo: 0, match_cur: 0, match_hi: match_idx_hi, - sp_lo: lo + + // Haven't descended into any delimiters, so empty stack + stack: vec![], + + // Haven't descended into any sequences, so both of these are `None`. + seq_op: None, + sep: None, + up: None, }) } @@ -202,29 +287,36 @@ fn initial_matcher_pos(ms: Vec, lo: BytePos) -> Box { /// token tree. The depth of the `NamedMatch` structure will therefore depend /// 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(Rc>, syntax_pos::Span), - MatchedNonterminal(Rc) + MatchedNonterminal(Rc), } -fn nameize>(sess: &ParseSess, ms: &[TokenTree], mut res: I) - -> NamedParseResult { - fn n_rec>(sess: &ParseSess, m: &TokenTree, res: &mut I, - ret_val: &mut HashMap>) - -> Result<(), (syntax_pos::Span, String)> { +/// Takes a sequence of token trees `ms` representing a matcher which successfully matched input +/// and an iterator of items that matched input and produces a `NamedParseResult`. +fn nameize>( + sess: &ParseSess, + ms: &[TokenTree], + mut res: I, +) -> NamedParseResult { + // Recursively descend into each type of matcher (e.g. sequences, delimited, metavars) and make + // sure that each metavar has _exactly one_ binding. If a metavar does not have exactly one + // binding, then there is an error. If it does, then we insert the binding into the + // `NamedParseResult`. + fn n_rec>( + sess: &ParseSess, + m: &TokenTree, + res: &mut I, + ret_val: &mut HashMap>, + ) -> Result<(), (syntax_pos::Span, String)> { match *m { - TokenTree::Sequence(_, ref seq) => { - for next_m in &seq.tts { - n_rec(sess, next_m, res.by_ref(), ret_val)? - } - } - TokenTree::Delimited(_, ref delim) => { - for next_m in &delim.tts { - n_rec(sess, next_m, res.by_ref(), ret_val)?; - } - } + TokenTree::Sequence(_, ref seq) => for next_m in &seq.tts { + n_rec(sess, next_m, res.by_ref(), ret_val)? + }, + TokenTree::Delimited(_, ref delim) => for next_m in &delim.tts { + n_rec(sess, next_m, res.by_ref(), ret_val)?; + }, TokenTree::MetaVarDecl(span, _, id) if id.name == keywords::Invalid.name() => { if sess.missing_fragment_specifiers.borrow_mut().remove(&span) { return Err((span, "missing fragment specifier".to_string())); @@ -250,7 +342,7 @@ fn n_rec>(sess: &ParseSess, m: &TokenTree, res: &mu let mut ret_val = HashMap::new(); for m in ms { match n_rec(sess, m, res.by_ref(), &mut ret_val) { - Ok(_) => {}, + Ok(_) => {} Err((sp, msg)) => return Error(sp, msg), } } @@ -258,25 +350,20 @@ fn n_rec>(sess: &ParseSess, m: &TokenTree, res: &mu Success(ret_val) } -pub enum ParseResult { - Success(T), - /// Arm failed to match. If the second parameter is `token::Eof`, it - /// indicates an unexpected end of macro invocation. Otherwise, it - /// indicates that no rules expected the given token. - Failure(syntax_pos::Span, Token), - /// Fatal error (malformed macro?). Abort compilation. - Error(syntax_pos::Span, String) -} - +/// Generate an appropriate parsing failure message. For EOF, this is "unexpected end...". For +/// other tokens, this is "unexpected token...". pub fn parse_failure_msg(tok: Token) -> String { match tok { token::Eof => "unexpected end of macro invocation".to_string(), - _ => format!("no rules expected the token `{}`", pprust::token_to_string(&tok)), + _ => format!( + "no rules expected the token `{}`", + pprust::token_to_string(&tok) + ), } } /// Perform a token equality check, ignoring syntax context (that is, an unhygienic comparison) -fn token_name_eq(t1 : &Token, t2 : &Token) -> bool { +fn token_name_eq(t1: &Token, t2: &Token) -> bool { if let (Some(id1), Some(id2)) = (t1.ident(), t2.ident()) { id1.name == id2.name } else if let (&token::Lifetime(id1), &token::Lifetime(id2)) = (t1, t2) { @@ -286,80 +373,126 @@ fn token_name_eq(t1 : &Token, t2 : &Token) -> bool { } } -fn create_matches(len: usize) -> Vec>> { - (0..len).into_iter().map(|_| Rc::new(Vec::new())).collect() -} - -fn inner_parse_loop(sess: &ParseSess, - cur_items: &mut SmallVector>, - next_items: &mut Vec>, - eof_items: &mut SmallVector>, - bb_items: &mut SmallVector>, - token: &Token, - span: syntax_pos::Span) - -> ParseResult<()> { +/// Process the matcher positions of `cur_items` until it is empty. In the process, this will +/// produce more items in `next_items`, `eof_items`, and `bb_items`. +/// +/// For more info about the how this happens, see the module-level doc comments and the inline +/// comments of this function. +/// +/// # Parameters +/// +/// - `sess`: the parsing session into which errors are emitted. +/// - `cur_items`: the set of current items to be processed. This should be empty by the end of a +/// successful execution of this function. +/// - `next_items`: the set of newly generated items. These are used to replenish `cur_items` in +/// the function `parse`. +/// - `eof_items`: the set of items that would be valid if this was the EOF. +/// - `bb_items`: the set of items that are waiting for the black-box parser. +/// - `token`: the current token of the parser. +/// - `span`: the `Span` in the source code corresponding to the token trees we are trying to match +/// against the matcher positions in `cur_items`. +/// +/// # Returns +/// +/// A `ParseResult`. Note that matches are kept track of through the items generated. +fn inner_parse_loop( + sess: &ParseSess, + cur_items: &mut SmallVector>, + next_items: &mut Vec>, + eof_items: &mut SmallVector>, + bb_items: &mut SmallVector>, + token: &Token, + span: syntax_pos::Span, +) -> ParseResult<()> { + // Pop items from `cur_items` until it is empty. while let Some(mut item) = cur_items.pop() { - // When unzipped trees end, remove them + // When unzipped trees end, remove them. This corresponds to backtracking out of a + // delimited submatcher into which we already descended. In backtracking out again, we need + // to advance the "dot" past the delimiters in the outer matcher. while item.idx >= item.top_elts.len() { match item.stack.pop() { Some(MatcherTtFrame { elts, idx }) => { item.top_elts = elts; item.idx = idx + 1; } - None => break + None => break, } } + // Get the current position of the "dot" (`idx`) in `item` and the number of token trees in + // the matcher (`len`). let idx = item.idx; let len = item.top_elts.len(); - // at end of sequence + // If `idx >= len`, then we are at or past the end of the matcher of `item`. if idx >= len { - // We are repeating iff there is a parent + // We are repeating iff there is a parent. If the matcher is inside of a repetition, + // then we could be at the end of a sequence or at the beginning of the next + // repetition. if item.up.is_some() { - // Disregarding the separator, add the "up" case to the tokens that should be - // examined. - // (remove this condition to make trailing seps ok) + // At this point, regardless of whether there is a separator, we should add all + // matches from the complete repetition of the sequence to the shared, top-level + // `matches` list (actually, `up.matches`, which could itself not be the top-level, + // but anyway...). Moreover, we add another item to `cur_items` in which the "dot" + // is at the end of the `up` matcher. This ensures that the "dot" in the `up` + // matcher is also advanced sufficiently. + // + // NOTE: removing the condition `idx == len` allows trailing separators. if idx == len { + // Get the `up` matcher let mut new_pos = item.up.clone().unwrap(); - // update matches (the MBE "parse tree") by appending - // each tree as a subtree. - - // Only touch the binders we have actually bound + // Add matches from this repetition to the `matches` of `up` for idx in item.match_lo..item.match_hi { let sub = item.matches[idx].clone(); let span = span.with_lo(item.sp_lo); new_pos.push_match(idx, MatchedSeq(sub, span)); } + // Move the "dot" past the repetition in `up` new_pos.match_cur = item.match_hi; new_pos.idx += 1; cur_items.push(new_pos); } - // Check if we need a separator + // Check if we need a separator. if idx == len && item.sep.is_some() { - // We have a separator, and it is the current token. - if item.sep.as_ref().map(|sep| token_name_eq(token, sep)).unwrap_or(false) { + // We have a separator, and it is the current token. We can advance past the + // separator token. + if item.sep + .as_ref() + .map(|sep| token_name_eq(token, sep)) + .unwrap_or(false) + { item.idx += 1; next_items.push(item); } - } else { // we don't need a separator + } + // We don't need a separator. Move the "dot" back to the beginning of the matcher + // and try to match again UNLESS we are only allowed to have _one_ repetition. + else if item.seq_op != Some(quoted::KleeneOp::ZeroOrOne) { item.match_cur = item.match_lo; item.idx = 0; cur_items.push(item); } - } else { - // We aren't repeating, so we must be potentially at the end of the input. + } + // If we are not in a repetition, then being at the end of a matcher means that we have + // reached the potential end of the input. + else { eof_items.push(item); } - } else { + } + // We are in the middle of a matcher. + else { + // Look at what token in the matcher we are trying to match the current token (`token`) + // against. Depending on that, we may generate new items. match item.top_elts.get_tt(idx) { - /* need to descend into sequence */ + // Need to descend into a sequence TokenTree::Sequence(sp, seq) => { - if seq.op == quoted::KleeneOp::ZeroOrMore { - // Examine the case where there are 0 matches of this sequence + // Examine the case where there are 0 matches of this sequence + if seq.op == quoted::KleeneOp::ZeroOrMore + || seq.op == quoted::KleeneOp::ZeroOrOne + { let mut new_item = item.clone(); new_item.match_cur += seq.num_captures; new_item.idx += 1; @@ -369,11 +502,11 @@ fn inner_parse_loop(sess: &ParseSess, cur_items.push(new_item); } - // Examine the case where there is at least one match of this sequence let matches = create_matches(item.matches.len()); cur_items.push(Box::new(MatcherPos { stack: vec![], sep: seq.separator.clone(), + seq_op: Some(seq.op), idx: 0, matches, match_lo: item.match_cur, @@ -384,11 +517,16 @@ fn inner_parse_loop(sess: &ParseSess, top_elts: Tt(TokenTree::Sequence(sp, seq)), })); } + + // We need to match a metavar (but the identifier is invalid)... this is an error TokenTree::MetaVarDecl(span, _, id) if id.name == keywords::Invalid.name() => { if sess.missing_fragment_specifiers.borrow_mut().remove(&span) { return Error(span, "missing fragment specifier".to_string()); } } + + // We need to match a metavar with a valid ident... call out to the black-box + // parser by adding an item to `bb_items`. TokenTree::MetaVarDecl(_, _, id) => { // Built-in nonterminals never start with these tokens, // so we can eliminate them from consideration. @@ -396,6 +534,13 @@ fn inner_parse_loop(sess: &ParseSess, bb_items.push(item); } } + + // We need to descend into a delimited submatcher or a doc comment. To do this, we + // push the current matcher onto a stack and push a new item containing the + // submatcher onto `cur_items`. + // + // At the beginning of the loop, if we reach the end of the delimited submatcher, + // we pop the stack to backtrack out of the descent. seq @ TokenTree::Delimited(..) | seq @ TokenTree::Token(_, DocComment(..)) => { let lower_elts = mem::replace(&mut item.top_elts, Tt(seq)); let idx = item.idx; @@ -406,36 +551,76 @@ fn inner_parse_loop(sess: &ParseSess, item.idx = 0; cur_items.push(item); } + + // We just matched a normal token. We can just advance the parser. TokenTree::Token(_, ref t) if token_name_eq(t, token) => { item.idx += 1; next_items.push(item); } + + // There was another token that was not `token`... This means we can't add any + // rules. NOTE that this is not necessarily an error unless _all_ items in + // `cur_items` end up doing this. There may still be some other matchers that do + // end up working out. TokenTree::Token(..) | TokenTree::MetaVar(..) => {} } } } + // Yay a successful parse (so far)! Success(()) } -pub fn parse(sess: &ParseSess, - tts: TokenStream, - ms: &[TokenTree], - directory: Option, - recurse_into_modules: bool) - -> NamedParseResult { +/// Use the given sequence of token trees (`ms`) as a matcher. Match the given token stream `tts` +/// against it and return the match. +/// +/// # Parameters +/// +/// - `sess`: The session into which errors are emitted +/// - `tts`: The tokenstream we are matching against the pattern `ms` +/// - `ms`: A sequence of token trees representing a pattern against which we are matching +/// - `directory`: Information about the file locations (needed for the black-box parser) +/// - `recurse_into_modules`: Whether or not to recurse into modules (needed for the black-box +/// parser) +pub fn parse( + sess: &ParseSess, + tts: TokenStream, + ms: &[TokenTree], + directory: Option, + recurse_into_modules: bool, +) -> NamedParseResult { + // Create a parser that can be used for the "black box" parts. let mut parser = Parser::new(sess, tts, directory, recurse_into_modules, true); + + // A queue of possible matcher positions. We initialize it with the matcher position in which + // the "dot" is before the first token of the first token tree in `ms`. `inner_parse_loop` then + // processes all of these possible matcher positions and produces posible next positions into + // `next_items`. After some post-processing, the contents of `next_items` replenish `cur_items` + // and we start over again. let mut cur_items = SmallVector::one(initial_matcher_pos(ms.to_owned(), parser.span.lo())); - let mut next_items = Vec::new(); // or proceed normally + let mut next_items = Vec::new(); loop { - let mut bb_items = SmallVector::new(); // black-box parsed by parser.rs + // Matcher positions black-box parsed by parser.rs (`parser`) + let mut bb_items = SmallVector::new(); + + // Matcher positions that would be valid if the macro invocation was over now let mut eof_items = SmallVector::new(); assert!(next_items.is_empty()); - match inner_parse_loop(sess, &mut cur_items, &mut next_items, &mut eof_items, &mut bb_items, - &parser.token, parser.span) { - Success(_) => {}, + // Process `cur_items` until either we have finished the input or we need to get some + // parsing from the black-box parser done. The result is that `next_items` will contain a + // bunch of possible next matcher positions in `next_items`. + match inner_parse_loop( + sess, + &mut cur_items, + &mut next_items, + &mut eof_items, + &mut bb_items, + &parser.token, + parser.span, + ) { + Success(_) => {} Failure(sp, tok) => return Failure(sp, tok), Error(sp, msg) => return Error(sp, msg), } @@ -443,46 +628,75 @@ pub fn parse(sess: &ParseSess, // inner parse loop handled all cur_items, so it's empty assert!(cur_items.is_empty()); - /* error messages here could be improved with links to orig. rules */ + // We need to do some post processing after the `inner_parser_loop`. + // + // Error messages here could be improved with links to original rules. + + // If we reached the EOF, check that there is EXACTLY ONE possible matcher. Otherwise, + // either the parse is ambiguous (which should never happen) or their is a syntax error. if token_name_eq(&parser.token, &token::Eof) { if eof_items.len() == 1 { - let matches = eof_items[0].matches.iter_mut().map(|dv| { - Rc::make_mut(dv).pop().unwrap() - }); + let matches = eof_items[0] + .matches + .iter_mut() + .map(|dv| Rc::make_mut(dv).pop().unwrap()); return nameize(sess, ms, matches); } else if eof_items.len() > 1 { - return Error(parser.span, "ambiguity: multiple successful parses".to_string()); + return Error( + parser.span, + "ambiguity: multiple successful parses".to_string(), + ); } else { return Failure(parser.span, token::Eof); } - } else if (!bb_items.is_empty() && !next_items.is_empty()) || bb_items.len() > 1 { - let nts = bb_items.iter().map(|item| match item.top_elts.get_tt(item.idx) { - TokenTree::MetaVarDecl(_, bind, name) => { - format!("{} ('{}')", name, bind) - } - _ => panic!() - }).collect::>().join(" or "); - - return Error(parser.span, format!( - "local ambiguity: multiple parsing options: {}", - match next_items.len() { - 0 => format!("built-in NTs {}.", nts), - 1 => format!("built-in NTs {} or 1 other option.", nts), - n => format!("built-in NTs {} or {} other options.", nts, n), - } - )); - } else if bb_items.is_empty() && next_items.is_empty() { + } + // Another possibility is that we need to call out to parse some rust nonterminal + // (black-box) parser. However, if there is not EXACTLY ONE of these, something is wrong. + else if (!bb_items.is_empty() && !next_items.is_empty()) || bb_items.len() > 1 { + let nts = bb_items + .iter() + .map(|item| match item.top_elts.get_tt(item.idx) { + TokenTree::MetaVarDecl(_, bind, name) => format!("{} ('{}')", name, bind), + _ => panic!(), + }) + .collect::>() + .join(" or "); + + return Error( + parser.span, + format!( + "local ambiguity: multiple parsing options: {}", + match next_items.len() { + 0 => format!("built-in NTs {}.", nts), + 1 => format!("built-in NTs {} or 1 other option.", nts), + n => format!("built-in NTs {} or {} other options.", nts, n), + } + ), + ); + } + // If there are no posible next positions AND we aren't waiting for the black-box parser, + // then their is a syntax error. + else if bb_items.is_empty() && next_items.is_empty() { return Failure(parser.span, parser.token); - } else if !next_items.is_empty() { - /* Now process the next token */ + } + // Dump all possible `next_items` into `cur_items` for the next iteration. + else if !next_items.is_empty() { + // Now process the next token cur_items.extend(next_items.drain(..)); parser.bump(); - } else /* bb_items.len() == 1 */ { + } + // Finally, we have the case where we need to call the black-box parser to get some + // nonterminal. + else { + assert_eq!(bb_items.len(), 1); + let mut item = bb_items.pop().unwrap(); if let TokenTree::MetaVarDecl(span, _, ident) = item.top_elts.get_tt(item.idx) { let match_cur = item.match_cur; - item.push_match(match_cur, - MatchedNonterminal(Rc::new(parse_nt(&mut parser, span, &ident.name.as_str())))); + item.push_match( + match_cur, + MatchedNonterminal(Rc::new(parse_nt(&mut parser, span, &ident.name.as_str()))), + ); item.idx += 1; item.match_cur += 1; } else { @@ -512,20 +726,21 @@ fn may_be_ident(nt: &token::Nonterminal) -> bool { "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 + "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 '{'. + token::NtItem(_) + | token::NtPat(_) + | token::NtTy(_) + | token::NtIdent(_) + | token::NtMeta(_) + | token::NtPath(_) + | token::NtVis(_) => false, // none of these may start with '{'. _ => true, }, _ => false, @@ -562,6 +777,18 @@ fn may_be_ident(nt: &token::Nonterminal) -> bool { } } +/// A call to the "black-box" parser to parse some rust nonterminal. +/// +/// # Parameters +/// +/// - `p`: the "black-box" parser to use +/// - `sp`: the `Span` we want to parse +/// - `name`: the name of the metavar _matcher_ we want to match (e.g. `tt`, `ident`, `block`, +/// etc...) +/// +/// # Returns +/// +/// The parsed nonterminal. fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal { if name == "tt" { return token::NtTT(p.parse_token_tree()); @@ -591,12 +818,15 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal { "ident" => match p.token { token::Ident(sn) => { p.bump(); - token::NtIdent(Spanned::{node: sn, span: p.prev_span}) + token::NtIdent(Spanned:: { + node: sn, + span: p.prev_span, + }) } _ => { let token_str = pprust::token_to_string(&p.token); - p.fatal(&format!("expected ident, found {}", - &token_str[..])).emit(); + p.fatal(&format!("expected ident, found {}", &token_str[..])) + .emit(); FatalError.raise() } }, @@ -606,6 +836,6 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal { "lifetime" => token::NtLifetime(p.expect_lifetime()), // this is not supposed to happen, since it has been checked // when compiling the macro. - _ => p.span_bug(sp, "invalid fragment specifier") + _ => p.span_bug(sp, "invalid fragment specifier"), } } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 9efb4faa635..5254c751e6b 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -237,7 +237,8 @@ pub fn compile(sess: &ParseSess, features: &RefCell, def: &ast::Item) s.iter().map(|m| { if let MatchedNonterminal(ref nt) = *m { if let NtTT(ref tt) = **nt { - let tt = quoted::parse(tt.clone().into(), true, sess).pop().unwrap(); + let tt = quoted::parse(tt.clone().into(), true, sess, features, &def.attrs) + .pop().unwrap(); valid &= check_lhs_nt_follows(sess, features, &def.attrs, &tt); return tt; } @@ -253,7 +254,8 @@ pub fn compile(sess: &ParseSess, features: &RefCell, def: &ast::Item) s.iter().map(|m| { if let MatchedNonterminal(ref nt) = *m { if let NtTT(ref tt) = **nt { - return quoted::parse(tt.clone().into(), false, sess).pop().unwrap(); + return quoted::parse(tt.clone().into(), false, sess, features, &def.attrs) + .pop().unwrap(); } } sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs") diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index 0e21e3f6b00..982b60b81e4 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -8,16 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast; +use {ast, attr}; use ext::tt::macro_parser; -use parse::{ParseSess, token}; +use feature_gate::{self, emit_feature_err, Features, GateIssue}; +use parse::{token, ParseSess}; use print::pprust; use symbol::keywords; -use syntax_pos::{DUMMY_SP, Span, BytePos}; +use syntax_pos::{BytePos, Span, DUMMY_SP}; use tokenstream; +use std::cell::RefCell; +use std::iter::Peekable; use std::rc::Rc; +/// Contains the sub-token-trees of a "delimited" token tree, such as the contents of `(`. Note +/// that the delimiter itself might be `NoDelim`. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Delimited { pub delim: token::DelimToken, @@ -25,14 +30,17 @@ pub struct Delimited { } impl Delimited { + /// Return the opening delimiter (possibly `NoDelim`). pub fn open_token(&self) -> token::Token { token::OpenDelim(self.delim) } + /// Return the closing delimiter (possibly `NoDelim`). pub fn close_token(&self) -> token::Token { token::CloseDelim(self.delim) } + /// Return a `self::TokenTree` with a `Span` corresponding to the opening delimiter. pub fn open_tt(&self, span: Span) -> TokenTree { let open_span = if span == DUMMY_SP { DUMMY_SP @@ -42,6 +50,7 @@ pub fn open_tt(&self, span: Span) -> TokenTree { TokenTree::Token(open_span, self.open_token()) } + /// Return a `self::TokenTree` with a `Span` corresponding to the closing delimiter. pub fn close_tt(&self, span: Span) -> TokenTree { let close_span = if span == DUMMY_SP { DUMMY_SP @@ -68,12 +77,15 @@ pub struct SequenceRepetition { /// for token sequences. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] pub enum KleeneOp { + /// Kleene star (`*`) for zero or more repetitions ZeroOrMore, + /// Kleene plus (`+`) for one or more repetitions OneOrMore, + ZeroOrOne, } /// Similar to `tokenstream::TokenTree`, except that `$i`, `$i:ident`, and `$(...)` -/// are "first-class" token trees. +/// are "first-class" token trees. Useful for parsing macros. #[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)] pub enum TokenTree { Token(Span, token::Token), @@ -83,10 +95,15 @@ pub enum TokenTree { /// 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 */), + MetaVarDecl( + Span, + ast::Ident, /* name to bind */ + ast::Ident, /* kind of nonterminal */ + ), } impl TokenTree { + /// Return the number of tokens in the tree. pub fn len(&self) -> usize { match *self { TokenTree::Delimited(_, ref delimed) => match delimed.delim { @@ -98,6 +115,8 @@ pub fn len(&self) -> usize { } } + /// Returns true if the given token tree contains no other tokens. This is vacuously true for + /// single tokens or metavar/decls, but may be false for delimited trees or sequences. pub fn is_empty(&self) -> bool { match *self { TokenTree::Delimited(_, ref delimed) => match delimed.delim { @@ -109,6 +128,7 @@ pub fn is_empty(&self) -> bool { } } + /// Get the `index`-th sub-token-tree. This only makes sense for delimited trees and sequences. pub fn get_tt(&self, index: usize) -> TokenTree { match (self, index) { (&TokenTree::Delimited(_, ref delimed), _) if delimed.delim == token::NoDelim => { @@ -131,21 +151,51 @@ pub fn get_tt(&self, index: usize) -> TokenTree { /// Retrieve the `TokenTree`'s span. pub fn span(&self) -> Span { match *self { - TokenTree::Token(sp, _) | - TokenTree::MetaVar(sp, _) | - TokenTree::MetaVarDecl(sp, _, _) | - TokenTree::Delimited(sp, _) | - TokenTree::Sequence(sp, _) => sp, + TokenTree::Token(sp, _) + | TokenTree::MetaVar(sp, _) + | TokenTree::MetaVarDecl(sp, _, _) + | TokenTree::Delimited(sp, _) + | TokenTree::Sequence(sp, _) => sp, } } } -pub fn parse(input: tokenstream::TokenStream, expect_matchers: bool, sess: &ParseSess) - -> Vec { +/// Takes a `tokenstream::TokenStream` and returns a `Vec`. Specifically, this +/// takes a generic `TokenStream`, such as is used in the rest of the compiler, and returns a +/// collection of `TokenTree` for use in parsing a macro. +/// +/// # Parameters +/// +/// - `input`: a token stream to read from, the contents of which we are parsing. +/// - `expect_matchers`: `parse` can be used to parse either the "patterns" or the "body" of a +/// macro. Both take roughly the same form _except_ that in a pattern, metavars are declared with +/// their "matcher" type. For example `$var:expr` or `$id:ident`. In this example, `expr` and +/// `ident` are "matchers". They are not present in the body of a macro rule -- just in the +/// pattern, so we pass a parameter to indicate whether to expect them or not. +/// - `sess`: the parsing session. Any errors will be emitted to this session. +/// - `features`, `attrs`: language feature flags and attributes so that we know whether to use +/// unstable features or not. +/// +/// # Returns +/// +/// A collection of `self::TokenTree`. There may also be some errors emitted to `sess`. +pub fn parse( + input: tokenstream::TokenStream, + expect_matchers: bool, + sess: &ParseSess, + features: &RefCell, + attrs: &[ast::Attribute], +) -> Vec { + // Will contain the final collection of `self::TokenTree` let mut result = Vec::new(); - let mut trees = input.trees(); + + // For each token tree in `input`, parse the token into a `self::TokenTree`, consuming + // additional trees if need be. + let mut trees = input.trees().peekable(); while let Some(tree) = trees.next() { - let tree = parse_tree(tree, &mut trees, expect_matchers, sess); + // Given the parsed tree, if there is a metavar and we are expecting matchers, actually + // parse out the matcher (i.e. in `$id:ident` this would parse the `:` and `ident`). + let tree = parse_tree(tree, &mut trees, expect_matchers, sess, features, attrs); match tree { TokenTree::MetaVar(start_sp, ident) if expect_matchers => { let span = match trees.next() { @@ -154,101 +204,296 @@ pub fn parse(input: tokenstream::TokenStream, expect_matchers: bool, sess: &Pars Some(kind) => { let span = end_sp.with_lo(start_sp.lo()); result.push(TokenTree::MetaVarDecl(span, ident, kind)); - continue + continue; } _ => end_sp, }, - tree => tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(span), + tree => tree.as_ref() + .map(tokenstream::TokenTree::span) + .unwrap_or(span), }, - tree => tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(start_sp), + tree => tree.as_ref() + .map(tokenstream::TokenTree::span) + .unwrap_or(start_sp), }; sess.missing_fragment_specifiers.borrow_mut().insert(span); - result.push(TokenTree::MetaVarDecl(span, ident, keywords::Invalid.ident())); + result.push(TokenTree::MetaVarDecl( + span, + ident, + keywords::Invalid.ident(), + )); } + + // Not a metavar or no matchers allowed, so just return the tree _ => result.push(tree), } } result } -fn parse_tree(tree: tokenstream::TokenTree, - trees: &mut I, - expect_matchers: bool, - sess: &ParseSess) - -> TokenTree - where I: Iterator, +/// Takes a `tokenstream::TokenTree` and returns a `self::TokenTree`. Specifically, this takes a +/// generic `TokenTree`, such as is used in the rest of the compiler, and returns a `TokenTree` +/// for use in parsing a macro. +/// +/// Converting the given tree may involve reading more tokens. +/// +/// # Parameters +/// +/// - `tree`: the tree we wish to convert. +/// - `trees`: an iterator over trees. We may need to read more tokens from it in order to finish +/// converting `tree` +/// - `expect_matchers`: same as for `parse` (see above). +/// - `sess`: the parsing session. Any errors will be emitted to this session. +/// - `features`, `attrs`: language feature flags and attributes so that we know whether to use +/// unstable features or not. +fn parse_tree( + tree: tokenstream::TokenTree, + trees: &mut Peekable, + expect_matchers: bool, + sess: &ParseSess, + features: &RefCell, + attrs: &[ast::Attribute], +) -> TokenTree +where + I: Iterator, { + // Depending on what `tree` is, we could be parsing different parts of a macro match tree { + // `tree` is a `$` token. Look at the next token in `trees` tokenstream::TokenTree::Token(span, token::Dollar) => match trees.next() { + // `tree` is followed by a delimited set of token trees. This indicates the beginning + // of a repetition sequence in the macro (e.g. `$(pat)*`). Some(tokenstream::TokenTree::Delimited(span, delimited)) => { + // Must have `(` not `{` or `[` if delimited.delim != token::Paren { let tok = pprust::token_to_string(&token::OpenDelim(delimited.delim)); let msg = format!("expected `(`, found `{}`", tok); sess.span_diagnostic.span_err(span, &msg); } - let sequence = parse(delimited.tts.into(), expect_matchers, sess); - let (separator, op) = parse_sep_and_kleene_op(trees, span, sess); + // Parse the contents of the sequence itself + let sequence = parse(delimited.tts.into(), expect_matchers, sess, features, attrs); + // Get the Kleene operator and optional separator + let (separator, op) = parse_sep_and_kleene_op(trees, span, sess, features, attrs); + // Count the number of captured "names" (i.e. named metavars) let name_captures = macro_parser::count_names(&sequence); - TokenTree::Sequence(span, Rc::new(SequenceRepetition { - tts: sequence, - separator, - op, - num_captures: name_captures, - })) + TokenTree::Sequence( + span, + Rc::new(SequenceRepetition { + tts: sequence, + separator, + op, + num_captures: name_captures, + }), + ) } + + // `tree` is followed by an `ident`. This could be `$meta_var` or the `$crate` special + // metavariable that names the crate of the invokation. Some(tokenstream::TokenTree::Token(ident_span, ref token)) if token.is_ident() => { let ident = token.ident().unwrap(); let span = ident_span.with_lo(span.lo()); if ident.name == keywords::Crate.name() { - let ident = ast::Ident { name: keywords::DollarCrate.name(), ..ident }; + let ident = ast::Ident { + name: keywords::DollarCrate.name(), + ..ident + }; TokenTree::Token(span, token::Ident(ident)) } else { TokenTree::MetaVar(span, ident) } } + + // `tree` is followed by a random token. This is an error. Some(tokenstream::TokenTree::Token(span, tok)) => { - let msg = format!("expected identifier, found `{}`", pprust::token_to_string(&tok)); + let msg = format!( + "expected identifier, found `{}`", + pprust::token_to_string(&tok) + ); sess.span_diagnostic.span_err(span, &msg); TokenTree::MetaVar(span, keywords::Invalid.ident()) } + + // There are no more tokens. Just return the `$` we already have. None => TokenTree::Token(span, token::Dollar), }, + + // `tree` is an arbitrary token. Keep it. tokenstream::TokenTree::Token(span, tok) => TokenTree::Token(span, tok), - tokenstream::TokenTree::Delimited(span, delimited) => { - TokenTree::Delimited(span, Rc::new(Delimited { + + // `tree` is the beginning of a delimited set of tokens (e.g. `(` or `{`). We need to + // descend into the delimited set and further parse it. + tokenstream::TokenTree::Delimited(span, delimited) => TokenTree::Delimited( + span, + Rc::new(Delimited { delim: delimited.delim, - tts: parse(delimited.tts.into(), expect_matchers, sess), - })) - } + tts: parse(delimited.tts.into(), expect_matchers, sess, features, attrs), + }), + ), } } -fn parse_sep_and_kleene_op(input: &mut I, span: Span, sess: &ParseSess) - -> (Option, KleeneOp) - where I: Iterator, -{ - fn kleene_op(token: &token::Token) -> Option { - match *token { - token::BinOp(token::Star) => Some(KleeneOp::ZeroOrMore), - token::BinOp(token::Plus) => Some(KleeneOp::OneOrMore), - _ => None, - } +/// Takes a token and returns `Some(KleeneOp)` if the token is `+` `*` or `?`. Otherwise, return +/// `None`. +fn kleene_op(token: &token::Token) -> Option { + match *token { + token::BinOp(token::Star) => Some(KleeneOp::ZeroOrMore), + token::BinOp(token::Plus) => Some(KleeneOp::OneOrMore), + token::Question => Some(KleeneOp::ZeroOrOne), + _ => None, } +} - let span = match input.next() { +/// Parse the next token tree of the input looking for a KleeneOp. Returns +/// +/// - Ok(Ok(op)) if the next token tree is a KleeneOp +/// - Ok(Err(tok, span)) if the next token tree is a token but not a KleeneOp +/// - Err(span) if the next token tree is not a token +fn parse_kleene_op( + input: &mut I, + span: Span, +) -> Result, Span> +where + I: Iterator, +{ + match input.next() { Some(tokenstream::TokenTree::Token(span, tok)) => match kleene_op(&tok) { - Some(op) => return (None, op), - None => match input.next() { - Some(tokenstream::TokenTree::Token(span, tok2)) => match kleene_op(&tok2) { - Some(op) => return (Some(tok), op), - None => span, - }, - tree => tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(span), + Some(op) => Ok(Ok(op)), + None => Ok(Err((tok, span))), + }, + tree => Err(tree.as_ref() + .map(tokenstream::TokenTree::span) + .unwrap_or(span)), + } +} + +/// Attempt to parse a single Kleene star, possibly with a separator. +/// +/// For example, in a pattern such as `$(a),*`, `a` is the pattern to be repeated, `,` is the +/// separator, and `*` is the Kleene operator. This function is specifically concerned with parsing +/// the last two tokens of such a pattern: namely, the optional separator and the Kleene operator +/// itself. Note that here we are parsing the _macro_ itself, rather than trying to match some +/// stream of tokens in an invocation of a macro. +/// +/// This function will take some input iterator `input` corresponding to `span` and a parsing +/// session `sess`. If the next one (or possibly two) tokens in `input` correspond to a Kleene +/// operator and separator, then a tuple with `(separator, KleeneOp)` is returned. Otherwise, an +/// error with the appropriate span is emitted to `sess` and a dummy value is returned. +fn parse_sep_and_kleene_op( + input: &mut Peekable, + span: Span, + sess: &ParseSess, + features: &RefCell, + attrs: &[ast::Attribute], +) -> (Option, KleeneOp) +where + I: Iterator, +{ + // We basically look at two token trees here, denoted as #1 and #2 below + let span = match parse_kleene_op(input, span) { + // #1 is a `+` or `*` KleeneOp + // + // `?` is ambiguous: it could be a separator or a Kleene::ZeroOrOne, so we need to look + // ahead one more token to be sure. + Ok(Ok(op)) if op != KleeneOp::ZeroOrOne => return (None, op), + + // #1 is `?` token, but it could be a Kleene::ZeroOrOne without a separator or it could + // be a `?` separator followed by any Kleene operator. We need to look ahead 1 token to + // find out which. + Ok(Ok(op)) => { + assert_eq!(op, KleeneOp::ZeroOrOne); + + // Lookahead at #2. If it is a KleenOp, then #1 is a separator. + let is_1_sep = if let Some(&tokenstream::TokenTree::Token(_, ref tok2)) = input.peek() { + kleene_op(tok2).is_some() + } else { + false + }; + + if is_1_sep { + // #1 is a separator and #2 should be a KleepeOp::* + // (N.B. We need to advance the input iterator.) + match parse_kleene_op(input, span) { + // #2 is a KleeneOp (this is the only valid option) :) + Ok(Ok(op)) if op == KleeneOp::ZeroOrOne => { + if !features.borrow().macro_at_most_once_rep + && !attr::contains_name(attrs, "allow_internal_unstable") + { + let explain = feature_gate::EXPLAIN_MACRO_AT_MOST_ONCE_REP; + emit_feature_err( + sess, + "macro_at_most_once_rep", + span, + GateIssue::Language, + explain, + ); + } + return (Some(token::Question), op); + } + Ok(Ok(op)) => return (Some(token::Question), op), + + // #2 is a random token (this is an error) :( + Ok(Err((_, span))) => span, + + // #2 is not even a token at all :( + Err(span) => span, + } + } else { + if !features.borrow().macro_at_most_once_rep + && !attr::contains_name(attrs, "allow_internal_unstable") + { + let explain = feature_gate::EXPLAIN_MACRO_AT_MOST_ONCE_REP; + emit_feature_err( + sess, + "macro_at_most_once_rep", + span, + GateIssue::Language, + explain, + ); + } + + // #2 is a random tree and #1 is KleeneOp::ZeroOrOne + return (None, op); } + } + + // #1 is a separator followed by #2, a KleeneOp + Ok(Err((tok, span))) => match parse_kleene_op(input, span) { + // #2 is a KleeneOp :D + Ok(Ok(op)) if op == KleeneOp::ZeroOrOne => { + if !features.borrow().macro_at_most_once_rep + && !attr::contains_name(attrs, "allow_internal_unstable") + { + let explain = feature_gate::EXPLAIN_MACRO_AT_MOST_ONCE_REP; + emit_feature_err( + sess, + "macro_at_most_once_rep", + span, + GateIssue::Language, + explain, + ); + } + return (Some(tok), op); + } + Ok(Ok(op)) => return (Some(tok), op), + + // #2 is a random token :( + Ok(Err((_, span))) => span, + + // #2 is not a token at all :( + Err(span) => span, }, - tree => tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(span), + + // #1 is not a token + Err(span) => span, }; - sess.span_diagnostic.span_err(span, "expected `*` or `+`"); + if !features.borrow().macro_at_most_once_rep + && !attr::contains_name(attrs, "allow_internal_unstable") + { + sess.span_diagnostic + .span_err(span, "expected one of: `*`, `+`, or `?`"); + } else { + sess.span_diagnostic.span_err(span, "expected `*` or `+`"); + } (None, KleeneOp::ZeroOrMore) } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 9a2560b0458..ea916d5168c 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -386,9 +386,6 @@ pub fn new() -> Features { // allow `#[must_use]` on functions and comparison operators (RFC 1940) (active, fn_must_use, "1.21.0", Some(43302)), - // allow '|' at beginning of match arms (RFC 1925) - (active, match_beginning_vert, "1.21.0", Some(44101)), - // Future-proofing enums/structs with #[non_exhaustive] attribute (RFC 2008) (active, non_exhaustive, "1.22.0", Some(44109)), @@ -426,9 +423,6 @@ pub fn new() -> Features { // In-band lifetime bindings (e.g. `fn foo(x: &'a u8) -> &'a u8`) (active, in_band_lifetimes, "1.23.0", Some(44524)), - // Nested groups in `use` (RFC 2128) - (active, use_nested_groups, "1.23.0", Some(44494)), - // generic associated types (RFC 1598) (active, generic_associated_types, "1.23.0", Some(44265)), @@ -452,6 +446,9 @@ pub fn new() -> Features { // Allows `#[repr(transparent)]` attribute on newtype structs (active, repr_transparent, "1.25.0", Some(43036)), + + // Use `?` as the Kleene "at most one" operator + (active, macro_at_most_once_rep, "1.25.0", Some(48075)), ); declare_features! ( @@ -545,6 +542,10 @@ pub fn new() -> Features { (accepted, abi_sysv64, "1.24.0", Some(36167)), // Allows `repr(align(16))` struct attribute (RFC 1358) (accepted, repr_align, "1.24.0", Some(33626)), + // allow '|' at beginning of match arms (RFC 1925) + (accepted, match_beginning_vert, "1.25.0", Some(44101)), + // Nested groups in `use` (RFC 2128) + (accepted, use_nested_groups, "1.25.0", Some(44494)), ); // If you change this, please modify src/doc/unstable-book as well. You must @@ -788,6 +789,11 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool { is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), + ("rustc_serialize_exclude_null", Normal, Gated(Stability::Unstable, + "rustc_attrs", + "the `#[rustc_serialize_exclude_null]` attribute \ + is an internal-only feature", + cfg_fn!(rustc_attrs))), ("rustc_synthetic", Whitelisted, Gated(Stability::Unstable, "rustc_attrs", "this attribute \ @@ -981,6 +987,11 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool { "wasm_import_memory attribute is currently unstable", cfg_fn!(wasm_import_memory))), + ("rustc_args_required_const", Whitelisted, Gated(Stability::Unstable, + "rustc_attrs", + "never will be stable", + cfg_fn!(rustc_attrs))), + // Crate level attributes ("crate_name", CrateLevel, Ungated), ("crate_type", CrateLevel, Ungated), @@ -1250,6 +1261,9 @@ fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str = "Unsized tuple coercion is not stable enough for use and is subject to change"; +pub const EXPLAIN_MACRO_AT_MOST_ONCE_REP: &'static str = + "Using the `?` macro Kleene operator for \"at most one\" repetition is unstable"; + struct PostExpansionVisitor<'a> { context: &'a Context<'a>, } @@ -1678,11 +1692,6 @@ fn visit_expr(&mut self, e: &'a ast::Expr) { } fn visit_arm(&mut self, arm: &'a ast::Arm) { - if let Some(span) = arm.beginning_vert { - gate_feature_post!(&self, match_beginning_vert, - span, - "Use of a '|' at the beginning of a match arm is experimental") - } visit::walk_arm(self, arm) } @@ -1806,29 +1815,6 @@ fn visit_path(&mut self, path: &'a ast::Path, _id: NodeId) { visit::walk_path(self, path); } - fn visit_use_tree(&mut self, use_tree: &'a ast::UseTree, id: NodeId, nested: bool) { - if nested { - match use_tree.kind { - ast::UseTreeKind::Simple(_) => { - if use_tree.prefix.segments.len() != 1 { - gate_feature_post!(&self, use_nested_groups, use_tree.span, - "paths in `use` groups are experimental"); - } - } - ast::UseTreeKind::Glob => { - gate_feature_post!(&self, use_nested_groups, use_tree.span, - "glob imports in `use` groups are experimental"); - } - ast::UseTreeKind::Nested(_) => { - gate_feature_post!(&self, use_nested_groups, use_tree.span, - "nested groups in `use` are experimental"); - } - } - } - - visit::walk_use_tree(self, use_tree, id); - } - fn visit_vis(&mut self, vis: &'a ast::Visibility) { if let ast::Visibility::Crate(span, ast::CrateSugar::JustCrate) = *vis { gate_feature_post!(&self, crate_visibility_modifier, span, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 0f8fe57e380..921ed3565a4 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -340,14 +340,13 @@ pub fn fold_thin_attrs(attrs: ThinVec, fld: &mut T) -> Thi fold_attrs(attrs.into(), fld).into() } -pub fn noop_fold_arm(Arm {attrs, pats, guard, body, beginning_vert}: Arm, +pub fn noop_fold_arm(Arm {attrs, pats, guard, body}: Arm, fld: &mut T) -> Arm { Arm { attrs: fold_attrs(attrs, fld), pats: pats.move_map(|x| fld.fold_pat(x)), guard: guard.map(|x| fld.fold_expr(x)), body: fld.fold_expr(body), - beginning_vert, } } diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index 54c726d8462..98d5fa8f797 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -38,34 +38,41 @@ pub struct JsonEmitter { registry: Option, cm: Rc, pretty: bool, + /// Whether "approximate suggestions" are enabled in the config + approximate_suggestions: bool, } impl JsonEmitter { pub fn stderr(registry: Option, code_map: Rc, - pretty: bool) -> JsonEmitter { + pretty: bool, + approximate_suggestions: bool) -> JsonEmitter { JsonEmitter { dst: Box::new(io::stderr()), registry, cm: code_map, pretty, + approximate_suggestions, } } pub fn basic(pretty: bool) -> JsonEmitter { let file_path_mapping = FilePathMapping::empty(); - JsonEmitter::stderr(None, Rc::new(CodeMap::new(file_path_mapping)), pretty) + JsonEmitter::stderr(None, Rc::new(CodeMap::new(file_path_mapping)), + pretty, false) } pub fn new(dst: Box, registry: Option, code_map: Rc, - pretty: bool) -> JsonEmitter { + pretty: bool, + approximate_suggestions: bool) -> JsonEmitter { JsonEmitter { dst, registry, cm: code_map, pretty, + approximate_suggestions, } } } @@ -101,6 +108,7 @@ struct Diagnostic { } #[derive(RustcEncodable)] +#[allow(unused_attributes)] struct DiagnosticSpan { file_name: String, byte_start: u32, @@ -121,6 +129,9 @@ struct DiagnosticSpan { /// If we are suggesting a replacement, this will contain text /// that should be sliced in atop this span. suggested_replacement: Option, + /// If the suggestion is approximate + #[rustc_serialize_exclude_null] + suggestion_approximate: Option, /// Macro invocations that created the code at this span, if any. expansion: Option>, } @@ -188,7 +199,7 @@ fn flush(&mut self) -> io::Result<()> { } let buf = BufWriter::default(); let output = buf.clone(); - EmitterWriter::new(Box::new(buf), Some(je.cm.clone()), false).emit(db); + EmitterWriter::new(Box::new(buf), Some(je.cm.clone()), false, false).emit(db); let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap(); let output = String::from_utf8(output).unwrap(); @@ -220,7 +231,7 @@ fn from_sub_diagnostic(db: &SubDiagnostic, je: &JsonEmitter) -> Diagnostic { impl DiagnosticSpan { fn from_span_label(span: SpanLabel, - suggestion: Option<&String>, + suggestion: Option<(&String, bool)>, je: &JsonEmitter) -> DiagnosticSpan { Self::from_span_etc(span.span, @@ -233,7 +244,7 @@ fn from_span_label(span: SpanLabel, fn from_span_etc(span: Span, is_primary: bool, label: Option, - suggestion: Option<&String>, + suggestion: Option<(&String, bool)>, je: &JsonEmitter) -> DiagnosticSpan { // obtain the full backtrace from the `macro_backtrace` @@ -253,7 +264,7 @@ fn from_span_etc(span: Span, fn from_span_full(span: Span, is_primary: bool, label: Option, - suggestion: Option<&String>, + suggestion: Option<(&String, bool)>, mut backtrace: vec::IntoIter, je: &JsonEmitter) -> DiagnosticSpan { @@ -281,6 +292,13 @@ fn from_span_full(span: Span, def_site_span, }) }); + + let suggestion_approximate = if je.approximate_suggestions { + suggestion.map(|x| x.1) + } else { + None + }; + DiagnosticSpan { file_name: start.file.name.to_string(), byte_start: span.lo().0 - start.file.start_pos.0, @@ -291,7 +309,8 @@ fn from_span_full(span: Span, column_end: end.col.0 + 1, is_primary, text: DiagnosticSpanLine::from_span(span, je), - suggested_replacement: suggestion.cloned(), + suggested_replacement: suggestion.map(|x| x.0.clone()), + suggestion_approximate, expansion: backtrace_step, label, } @@ -309,14 +328,15 @@ fn from_suggestion(suggestion: &CodeSuggestion, je: &JsonEmitter) suggestion.substitutions .iter() .flat_map(|substitution| { - substitution.parts.iter().map(move |suggestion| { + substitution.parts.iter().map(move |suggestion_inner| { let span_label = SpanLabel { - span: suggestion.span, + span: suggestion_inner.span, is_primary: true, label: None, }; DiagnosticSpan::from_span_label(span_label, - Some(&suggestion.snippet), + Some((&suggestion_inner.snippet, + suggestion.approximate)), je) }) }) diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 3b4c5da10f2..9181cca215c 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -25,6 +25,7 @@ #![feature(match_default_bindings)] #![feature(i128_type)] #![feature(const_atomic_usize_new)] +#![feature(rustc_attrs)] // See librustc_cratesio_shim/Cargo.toml for a comment explaining this. #[allow(unused_extern_crates)] diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index b95c91548d0..11ab84a5729 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -246,14 +246,27 @@ fn err_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) { self.err_span(self.mk_sp(from_pos, to_pos), m) } + /// Pushes a character to a message string for error reporting + fn push_escaped_char_for_msg(m: &mut String, c: char) { + match c { + '\u{20}'...'\u{7e}' => { + // Don't escape \, ' or " for user-facing messages + m.push(c); + } + _ => { + for c in c.escape_default() { + m.push(c); + } + } + } + } + /// Report a lexical error spanning [`from_pos`, `to_pos`), appending an /// escaped character to the error message fn fatal_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) -> FatalError { let mut m = m.to_string(); m.push_str(": "); - for c in c.escape_default() { - m.push(c) - } + Self::push_escaped_char_for_msg(&mut m, c); self.fatal_span_(from_pos, to_pos, &m[..]) } fn struct_fatal_span_char(&self, @@ -264,9 +277,7 @@ fn struct_fatal_span_char(&self, -> DiagnosticBuilder<'a> { let mut m = m.to_string(); m.push_str(": "); - for c in c.escape_default() { - m.push(c) - } + Self::push_escaped_char_for_msg(&mut m, c); self.sess.span_diagnostic.struct_span_fatal(self.mk_sp(from_pos, to_pos), &m[..]) } @@ -275,9 +286,7 @@ fn struct_fatal_span_char(&self, fn err_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) { let mut m = m.to_string(); m.push_str(": "); - for c in c.escape_default() { - m.push(c) - } + Self::push_escaped_char_for_msg(&mut m, c); self.err_span_(from_pos, to_pos, &m[..]); } fn struct_err_span_char(&self, @@ -288,9 +297,7 @@ fn struct_err_span_char(&self, -> DiagnosticBuilder<'a> { let mut m = m.to_string(); m.push_str(": "); - for c in c.escape_default() { - m.push(c) - } + Self::push_escaped_char_for_msg(&mut m, c); self.sess.span_diagnostic.struct_span_err(self.mk_sp(from_pos, to_pos), &m[..]) } @@ -1745,6 +1752,7 @@ mod tests { fn mk_sess(cm: Rc) -> ParseSess { let emitter = errors::emitter::EmitterWriter::new(Box::new(io::sink()), Some(cm.clone()), + false, false); ParseSess { span_diagnostic: errors::Handler::with_emitter(true, false, Box::new(emitter)), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a3de31cc2ea..dc3745fc4a3 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -761,6 +761,18 @@ fn interpolated_or_expr_span(&self, }) } + fn expected_ident_found(&self) -> DiagnosticBuilder<'a> { + let mut err = self.struct_span_err(self.span, + &format!("expected identifier, found {}", + self.this_token_descr())); + if let Some(token_descr) = self.token_descr() { + err.span_label(self.span, format!("expected identifier, found {}", token_descr)); + } else { + err.span_label(self.span, "expected identifier"); + } + err + } + pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> { self.parse_ident_common(true) } @@ -769,15 +781,7 @@ fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> { match self.token { token::Ident(i) => { if self.token.is_reserved_ident() { - let mut err = self.struct_span_err(self.span, - &format!("expected identifier, found {}", - self.this_token_descr())); - if let Some(token_descr) = self.token_descr() { - err.span_label(self.span, format!("expected identifier, found {}", - token_descr)); - } else { - err.span_label(self.span, "expected identifier"); - } + let mut err = self.expected_ident_found(); if recover { err.emit(); } else { @@ -791,14 +795,7 @@ fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> { Err(if self.prev_token_kind == PrevTokenKind::DocComment { self.span_fatal_err(self.prev_span, Error::UselessDocComment) } else { - let mut err = self.fatal(&format!("expected identifier, found `{}`", - self.this_token_to_string())); - if let Some(token_descr) = self.token_descr() { - err.span_label(self.span, format!("expected identifier, found {}", - token_descr)); - } else { - err.span_label(self.span, "expected identifier"); - } + let mut err = self.expected_ident_found(); if self.token == token::Underscore { err.note("`_` is a wildcard pattern, not an identifier"); } @@ -1364,7 +1361,7 @@ pub fn parse_ty_bare_fn(&mut self, generic_params: Vec) self.expect_keyword(keywords::Fn)?; let (inputs, variadic) = self.parse_fn_args(false, true)?; - let ret_ty = self.parse_ret_ty()?; + let ret_ty = self.parse_ret_ty(false)?; let decl = P(FnDecl { inputs, output: ret_ty, @@ -1503,9 +1500,9 @@ fn parse_trait_item_(&mut self, } /// Parse optional return type [ -> TY ] in function decl - pub fn parse_ret_ty(&mut self) -> PResult<'a, FunctionRetTy> { + fn parse_ret_ty(&mut self, allow_plus: bool) -> PResult<'a, FunctionRetTy> { if self.eat(&token::RArrow) { - Ok(FunctionRetTy::Ty(self.parse_ty_no_plus()?)) + Ok(FunctionRetTy::Ty(self.parse_ty_common(allow_plus, true)?)) } else { Ok(FunctionRetTy::Default(self.span.with_hi(self.span.lo()))) } @@ -1530,6 +1527,7 @@ fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool) maybe_whole!(self, NtTy, |x| x); let lo = self.span; + let mut impl_dyn_multi = false; let node = if self.eat(&token::OpenDelim(token::Paren)) { // `(TYPE)` is a parenthesized type. // `(TYPE,)` is a tuple with a single field of type TYPE. @@ -1616,13 +1614,17 @@ fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool) self.parse_remaining_bounds(lifetime_defs, path, lo, parse_plus)? } } else if self.eat_keyword(keywords::Impl) { - // FIXME: figure out priority of `+` in `impl Trait1 + Trait2` (#34511). - TyKind::ImplTrait(self.parse_ty_param_bounds()?) + // Always parse bounds greedily for better error recovery. + let bounds = self.parse_ty_param_bounds()?; + impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus; + TyKind::ImplTrait(bounds) } else if self.check_keyword(keywords::Dyn) && self.look_ahead(1, |t| t.can_begin_bound() && !can_continue_type_after_ident(t)) { - // FIXME: figure out priority of `+` in `dyn Trait1 + Trait2` (#34511). self.bump(); // `dyn` - TyKind::TraitObject(self.parse_ty_param_bounds()?, TraitObjectSyntax::Dyn) + // Always parse bounds greedily for better error recovery. + let bounds = self.parse_ty_param_bounds()?; + impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus; + TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn) } else if self.check(&token::Question) || self.check_lifetime() && self.look_ahead(1, |t| t == &token::BinOp(token::Plus)) { // Bound list (trait object type) @@ -1658,6 +1660,7 @@ fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool) let ty = Ty { node, span, id: ast::DUMMY_NODE_ID }; // Try to recover from use of `+` with incorrect priority. + self.maybe_report_ambiguous_plus(allow_plus, impl_dyn_multi, &ty); self.maybe_recover_from_bad_type_plus(allow_plus, &ty)?; let ty = self.maybe_recover_from_bad_qpath(ty, allow_qpath_recovery)?; @@ -1675,6 +1678,15 @@ fn parse_remaining_bounds(&mut self, generic_params: Vec, path: as Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None)) } + fn maybe_report_ambiguous_plus(&mut self, allow_plus: bool, impl_dyn_multi: bool, ty: &Ty) { + if !allow_plus && impl_dyn_multi { + let sum_with_parens = format!("({})", pprust::ty_to_string(&ty)); + self.struct_span_err(ty.span, "ambiguous `+` in a type") + .span_suggestion(ty.span, "use parentheses to disambiguate", sum_with_parens) + .emit(); + } + } + fn maybe_recover_from_bad_type_plus(&mut self, allow_plus: bool, ty: &Ty) -> PResult<'a, ()> { // Do not add `+` to expected tokens. if !allow_plus || self.token != token::BinOp(token::Plus) { @@ -3383,11 +3395,7 @@ pub fn parse_arm(&mut self) -> PResult<'a, Arm> { let attrs = self.parse_outer_attributes()?; // Allow a '|' before the pats (RFC 1925) - let beginning_vert = if self.eat(&token::BinOp(token::Or)) { - Some(self.prev_span) - } else { - None - }; + self.eat(&token::BinOp(token::Or)); let pats = self.parse_pats()?; let guard = if self.eat_keyword(keywords::If) { Some(self.parse_expr()?) @@ -3411,7 +3419,6 @@ pub fn parse_arm(&mut self) -> PResult<'a, Arm> { pats, guard, body: expr, - beginning_vert, }) } @@ -4896,7 +4903,7 @@ fn parse_fn_args(&mut self, named_args: bool, allow_variadic: bool) pub fn parse_fn_decl(&mut self, allow_variadic: bool) -> PResult<'a, P> { let (args, variadic) = self.parse_fn_args(true, allow_variadic)?; - let ret_ty = self.parse_ret_ty()?; + let ret_ty = self.parse_ret_ty(true)?; Ok(P(FnDecl { inputs: args, @@ -5037,7 +5044,7 @@ fn parse_fn_decl_with_self(&mut self, parse_arg_fn: F) -> PResult<'a, P PResult<'a, P> { args } }; - let output = self.parse_ret_ty()?; + let output = self.parse_ret_ty(true)?; Ok(P(FnDecl { inputs: inputs_captures, diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 2be93c07d5a..7fbe781e9a1 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -112,6 +112,7 @@ fn ident_can_begin_expr(ident: ast::Ident) -> bool { keywords::Unsafe.name(), keywords::While.name(), keywords::Yield.name(), + keywords::Static.name(), ].contains(&ident.name) } diff --git a/src/libsyntax/test_snippet.rs b/src/libsyntax/test_snippet.rs index 5072f2e2793..3b4bba24d77 100644 --- a/src/libsyntax/test_snippet.rs +++ b/src/libsyntax/test_snippet.rs @@ -62,6 +62,7 @@ fn test_harness(file_text: &str, span_labels: Vec, expected_output: & let emitter = EmitterWriter::new(Box::new(Shared { data: output.clone() }), Some(code_map.clone()), + false, false); let handler = Handler::with_emitter(true, false, Box::new(emitter)); handler.span_err(msp, "foo"); diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index 3742fb8c804..d1de4dccd00 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -239,6 +239,12 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, } } + // If there are no outputs, the inline assembly is executed just for its side effects, + // so ensure that it is volatile + if outputs.is_empty() { + volatile = true; + } + MacEager::expr(P(ast::Expr { id: ast::DUMMY_NODE_ID, node: ast::ExprKind::InlineAsm(P(ast::InlineAsm { diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs index 0e6e96438d8..743f22b6b31 100644 --- a/src/libsyntax_ext/deriving/encodable.rs +++ b/src/libsyntax_ext/deriving/encodable.rs @@ -190,7 +190,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, Struct(_, ref fields) => { let emit_struct_field = cx.ident_of("emit_struct_field"); let mut stmts = Vec::new(); - for (i, &FieldInfo { name, ref self_, span, .. }) in fields.iter().enumerate() { + for (i, &FieldInfo { name, ref self_, span, attrs, .. }) in fields.iter().enumerate() { let name = match name { Some(id) => id.name, None => Symbol::intern(&format!("_field{}", i)), @@ -212,7 +212,19 @@ fn encodable_substructure(cx: &mut ExtCtxt, } else { cx.expr(span, ExprKind::Ret(Some(call))) }; - stmts.push(cx.stmt_expr(call)); + + // This exists for https://github.com/rust-lang/rust/pull/47540 + // + // If we decide to stabilize that flag this can be removed + let expr = if attrs.iter().any(|a| a.check_name("rustc_serialize_exclude_null")) { + let is_some = cx.ident_of("is_some"); + let condition = cx.expr_method_call(span, self_.clone(), is_some, vec![]); + cx.expr_if(span, condition, call, None) + } else { + call + }; + let stmt = cx.stmt_expr(expr); + stmts.push(stmt); } // unit structs have no fields and need to return Ok() diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 3660d2fe46a..0dfe9cb970e 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -1439,7 +1439,7 @@ fn build_enum_match_tuple<'b>(&self, &catch_all_substructure); // Final wrinkle: the self_args are expressions that deref - // down to desired l-values, but we cannot actually deref + // down to desired places, but we cannot actually deref // them when they are fed as r-values into a tuple // expression; here add a layer of borrowing, turning // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`. @@ -1516,7 +1516,7 @@ fn build_enum_match_tuple<'b>(&self, } else { // Final wrinkle: the self_args are expressions that deref - // down to desired l-values, but we cannot actually deref + // down to desired places, but we cannot actually deref // them when they are fed as r-values into a tuple // expression; here add a layer of borrowing, turning // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`. diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index dd1ec7284f6..294506625bc 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -347,13 +347,24 @@ pub fn macro_backtrace(mut self) -> Vec { /// Return a `Span` that would enclose both `self` and `end`. pub fn to(self, end: Span) -> Span { - let span = self.data(); - let end = end.data(); + let span_data = self.data(); + let end_data = end.data(); + // FIXME(jseyfried): self.ctxt should always equal end.ctxt here (c.f. issue #23480) + // Return the macro span on its own to avoid weird diagnostic output. It is preferable to + // have an incomplete span than a completely nonsensical one. + if span_data.ctxt != end_data.ctxt { + if span_data.ctxt == SyntaxContext::empty() { + return end; + } else if end_data.ctxt == SyntaxContext::empty() { + return self; + } + // both span fall within a macro + // FIXME(estebank) check if it is the *same* macro + } Span::new( - cmp::min(span.lo, end.lo), - cmp::max(span.hi, end.hi), - // FIXME(jseyfried): self.ctxt should always equal end.ctxt here (c.f. issue #23480) - if span.ctxt == SyntaxContext::empty() { end.ctxt } else { span.ctxt }, + cmp::min(span_data.lo, end_data.lo), + cmp::max(span_data.hi, end_data.hi), + if span_data.ctxt == SyntaxContext::empty() { end_data.ctxt } else { span_data.ctxt }, ) } diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index ffa27688cf1..9ea5f39b71f 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -72,6 +72,7 @@ use std::thread; use std::time::{Instant, Duration}; use std::borrow::Cow; +use std::process; const TEST_WARN_TIMEOUT_S: u64 = 60; const QUIET_MODE_MAX_COLUMN: usize = 100; // insert a '\n' after 100 tests in quiet mode @@ -266,19 +267,27 @@ pub fn display_output(mut self, display_output: bool) -> Options { pub fn test_main(args: &[String], tests: Vec, options: Options) { let mut opts = match parse_opts(args) { Some(Ok(o)) => o, - Some(Err(msg)) => panic!("{:?}", msg), + Some(Err(msg)) => { + eprintln!("error: {}", msg); + process::exit(101); + }, None => return, }; + opts.options = options; if opts.list { if let Err(e) = list_tests_console(&opts, tests) { - panic!("io error when listing tests: {:?}", e); + eprintln!("error: io error when listing tests: {:?}", e); + process::exit(101); } } else { match run_tests_console(&opts, tests) { Ok(true) => {} - Ok(false) => std::process::exit(101), - Err(e) => panic!("io error when running tests: {:?}", e), + Ok(false) => process::exit(101), + Err(e) => { + eprintln!("error: io error when listing tests: {:?}", e); + process::exit(101); + }, } } } diff --git a/src/llvm b/src/llvm index bc344d5bc23..9f81beaf326 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit bc344d5bc23c61ff9baf82d268a0edf199933cc3 +Subproject commit 9f81beaf32608fbe1fe0f2a82f974e800e9d8c62 diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index b2f1229891d..06d1301d700 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -836,6 +836,10 @@ struct LLVMRustThinLTOData { StringMap ImportLists; StringMap ExportLists; StringMap ModuleToDefinedGVSummaries; + +#if LLVM_VERSION_GE(7, 0) + LLVMRustThinLTOData() : Index(/* isPerformingAnalysis = */ false) {} +#endif }; // Just an argument to the `LLVMRustCreateThinLTOData` function below. @@ -918,7 +922,14 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, // // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp` #if LLVM_VERSION_GE(5, 0) +#if LLVM_VERSION_GE(7, 0) + auto deadIsPrevailing = [&](GlobalValue::GUID G) { + return PrevailingType::Unknown; + }; + computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols, deadIsPrevailing); +#else computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols); +#endif ComputeCrossModuleImport( Ret->Index, Ret->ModuleToDefinedGVSummaries, diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 611d63f6a4d..4dfc4029d75 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -552,9 +552,11 @@ static unsigned fromRust(LLVMRustDIFlags Flags) { if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) { Result |= DINode::DIFlags::FlagRValueReference; } +#if LLVM_VERSION_LE(4, 0) if (isSet(Flags & LLVMRustDIFlags::FlagExternalTypeRef)) { Result |= DINode::DIFlags::FlagExternalTypeRef; } +#endif if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) { Result |= DINode::DIFlags::FlagIntroducedVirtual; } diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger index 2635ca73303..3cd044708ce 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. -2018-01-25 +2018-02-09 diff --git a/src/test/codegen/abi-x86_64_sysv.rs b/src/test/codegen/abi-x86_64_sysv.rs new file mode 100644 index 00000000000..88666e9c1fd --- /dev/null +++ b/src/test/codegen/abi-x86_64_sysv.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. + +// only-x86_64 + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +pub struct S24 { + a: i8, + b: i8, + c: i8, +} + +pub struct S48 { + a: i16, + b: i16, + c: i8, +} + +// CHECK: i24 @struct_24_bits(i24 +#[no_mangle] +pub extern "sysv64" fn struct_24_bits(a: S24) -> S24 { + a +} + +// CHECK: i48 @struct_48_bits(i48 +#[no_mangle] +pub extern "sysv64" fn struct_48_bits(a: S48) -> S48 { + a +} diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs index f8945a6ee8d..0e98d3f9050 100644 --- a/src/test/codegen/function-arguments.rs +++ b/src/test/codegen/function-arguments.rs @@ -122,13 +122,13 @@ pub fn unsafe_slice(_: &[UnsafeInner]) { pub fn str(_: &[u8]) { } -// CHECK: @trait_borrow(%"core::ops::drop::Drop"* nonnull %arg0.0, {}* noalias nonnull readonly %arg0.1) +// CHECK: @trait_borrow({}* nonnull %arg0.0, {}* noalias nonnull readonly %arg0.1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn trait_borrow(_: &Drop) { } -// CHECK: @trait_box(%"core::ops::drop::Drop"* noalias nonnull, {}* noalias nonnull readonly) +// CHECK: @trait_box({}* noalias nonnull, {}* noalias nonnull readonly) #[no_mangle] pub fn trait_box(_: Box) { } diff --git a/src/test/codegen/no-output-asm-is-volatile.rs b/src/test/codegen/no-output-asm-is-volatile.rs new file mode 100644 index 00000000000..457d706a8ff --- /dev/null +++ b/src/test/codegen/no-output-asm-is-volatile.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. + +// compile-flags: -O + +// ignore-asmjs + +#![feature(asm)] +#![crate_type = "lib"] + +// Check that inline assembly expressions without any outputs +// are marked as having side effects / being volatile + +// CHECK-LABEL: @assembly +#[no_mangle] +pub fn assembly() { + unsafe { asm!("") } +// CHECK: tail call void asm sideeffect "", {{.*}} +} diff --git a/src/test/codegen/repeat-trusted-len.rs b/src/test/codegen/repeat-trusted-len.rs new file mode 100644 index 00000000000..43872f15d51 --- /dev/null +++ b/src/test/codegen/repeat-trusted-len.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -O +// ignore-tidy-linelength + +#![crate_type = "lib"] + +use std::iter; + +// CHECK-LABEL: @repeat_take_collect +#[no_mangle] +pub fn repeat_take_collect() -> Vec { +// CHECK: call void @llvm.memset.p0i8 + iter::repeat(42).take(100000).collect() +} diff --git a/src/test/codegen/repr-transparent-sysv64.rs b/src/test/codegen/repr-transparent-sysv64.rs new file mode 100644 index 00000000000..7a30983fdd3 --- /dev/null +++ b/src/test/codegen/repr-transparent-sysv64.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. + +// only-x86_64 + +// compile-flags: -C no-prepopulate-passes + +#![crate_type="lib"] +#![feature(repr_transparent)] + +#[repr(C)] +pub struct Rgb8 { r: u8, g: u8, b: u8 } + +#[repr(transparent)] +pub struct Rgb8Wrap(Rgb8); + +// CHECK: i24 @test_Rgb8Wrap(i24) +#[no_mangle] +pub extern "sysv64" fn test_Rgb8Wrap(_: Rgb8Wrap) -> Rgb8Wrap { loop {} } + +#[repr(C)] +pub union FloatBits { + float: f32, + bits: u32, +} + +#[repr(transparent)] +pub struct SmallUnion(FloatBits); + +// CHECK: i32 @test_SmallUnion(i32) +#[no_mangle] +pub extern "sysv64" fn test_SmallUnion(_: SmallUnion) -> SmallUnion { loop {} } diff --git a/src/test/codegen/repr-transparent.rs b/src/test/codegen/repr-transparent.rs index 31020d8b94f..087fa9b16b4 100644 --- a/src/test/codegen/repr-transparent.rs +++ b/src/test/codegen/repr-transparent.rs @@ -123,55 +123,13 @@ pub struct UnitPhantom { val: T, unit: PhantomData } pub extern fn test_Projection(_: StructWithProjection) -> StructWithProjection { loop {} } -// The rest of this file tests newtypes around small aggregates on an ABI where small aggregates are -// packed into one register. This is ABI-dependent, so instead we focus on one ABI and supply a -// dummy definition for other ABIs to keep FileCheck happy. +// All that remains to be tested are aggregates. They are tested in separate files called repr- +// transparent-*.rs with `only-*` or `ignore-*` directives, because the expected LLVM IR +// function signatures vary so much that it's not reasonably possible to cover all of them with a +// single CHECK line. // -// Bigger aggregates are tested in separate files called repr-transparent-aggregate-*.rs because -// there, the expected LLVM IR function signatures vary so much that it's not reasonably possible to -// cover all of them with a single CHECK line. Instead we group ABIs by the general "shape" of the -// signature and have a separate test file for each bin. -// -// PS: You may be wondering why we don't just compare the return types and argument types for -// equality with FileCheck regex captures. Well, rustc doesn't perform newtype unwrapping on -// newtypes containing aggregates. This is OK on all ABIs we support, but because LLVM has not -// gotten rid of pointee types yet, the IR function signature will be syntactically different (%Foo* -// vs %FooWrapper*). - -#[repr(C)] -pub struct Rgb8 { r: u8, g: u8, b: u8 } - -#[repr(transparent)] -pub struct Rgb8Wrap(Rgb8); - -// NB: closing parenthesis is missing because sometimes the argument has a name and sometimes not -// CHECK: define i32 @test_Rgb8Wrap(i32 -#[no_mangle] -#[cfg(all(target_arch="x86_64", target_os="linux"))] -pub extern fn test_Rgb8Wrap(_: Rgb8Wrap) -> Rgb8Wrap { loop {} } - -#[cfg(not(all(target_arch="x86_64", target_os="linux")))] -#[no_mangle] -pub extern fn test_Rgb8Wrap(_: u32) -> u32 { loop {} } - -// Same as with the small struct above: ABI-dependent, we only test the interesting case -// (ABIs that pack the aggregate into a scalar) and stub it out on other ABIs - -#[repr(C)] -pub union FloatBits { - float: f32, - bits: u32, -} - -#[repr(transparent)] -pub struct SmallUnion(FloatBits); - -// NB: closing parenthesis is missing because sometimes the argument has a name and sometimes not -// CHECK: define i32 @test_SmallUnion(i32 -#[no_mangle] -#[cfg(all(target_arch="x86_64", target_os="linux"))] -pub extern fn test_SmallUnion(_: SmallUnion) -> SmallUnion { loop {} } - -#[cfg(not(all(target_arch="x86_64", target_os="linux")))] -#[no_mangle] -pub extern fn test_SmallUnion(_: u32) -> u32 { loop {} } +// You may be wondering why we don't just compare the return types and argument types for equality +// with FileCheck regex captures. Well, rustc doesn't perform newtype unwrapping on newtypes +// containing aggregates. This is OK on all ABIs we support, but because LLVM has not gotten rid of +// pointee types yet, the IR function signature will be syntactically different (%Foo* vs +// %FooWrapper*). diff --git a/src/test/codegen/stack-probes.rs b/src/test/codegen/stack-probes.rs index 5b26dade9af..4a489f1edb3 100644 --- a/src/test/codegen/stack-probes.rs +++ b/src/test/codegen/stack-probes.rs @@ -15,7 +15,7 @@ // ignore-wasm // ignore-emscripten // ignore-windows -// no-system-llvm +// min-system-llvm-version 5.0 // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/src/test/compile-fail/E0001.rs b/src/test/compile-fail/E0001.rs deleted file mode 100644 index b72b0d66190..00000000000 --- a/src/test/compile-fail/E0001.rs +++ /dev/null @@ -1,20 +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. - -#![deny(unreachable_patterns)] - -fn main() { - let foo = Some(1); - match foo { - Some(_) => {/* ... */} - None => {/* ... */} - _ => {/* ... */} //~ ERROR unreachable pattern - } -} diff --git a/src/test/compile-fail/E0004-2.rs b/src/test/compile-fail/E0004-2.rs deleted file mode 100644 index 824b86cfa83..00000000000 --- a/src/test/compile-fail/E0004-2.rs +++ /dev/null @@ -1,15 +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. - -fn main() { - let x = Some(1); - - match x { } //~ ERROR E0004 -} diff --git a/src/test/compile-fail/E0004.rs b/src/test/compile-fail/E0004.rs deleted file mode 100644 index 8df07a0c1c5..00000000000 --- a/src/test/compile-fail/E0004.rs +++ /dev/null @@ -1,22 +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. - -enum Terminator { - HastaLaVistaBaby, - TalkToMyHand, -} - -fn main() { - let x = Terminator::HastaLaVistaBaby; - - match x { //~ ERROR E0004 - Terminator::TalkToMyHand => {} - } -} diff --git a/src/test/compile-fail/E0005.rs b/src/test/compile-fail/E0005.rs deleted file mode 100644 index 0405bba81b5..00000000000 --- a/src/test/compile-fail/E0005.rs +++ /dev/null @@ -1,14 +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. - -fn main() { - let x = Some(1); - let Some(y) = x; //~ ERROR E0005 -} diff --git a/src/test/compile-fail/E0007.rs b/src/test/compile-fail/E0007.rs deleted file mode 100644 index d5acbdebbe9..00000000000 --- a/src/test/compile-fail/E0007.rs +++ /dev/null @@ -1,19 +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. - -fn main() { - let x = Some("s".to_string()); - match x { - op_string @ Some(s) => {}, - //~^ ERROR E0007 - //~| ERROR E0303 - None => {}, - } -} diff --git a/src/test/compile-fail/E0008.rs b/src/test/compile-fail/E0008.rs deleted file mode 100644 index ba5720e6f0a..00000000000 --- a/src/test/compile-fail/E0008.rs +++ /dev/null @@ -1,17 +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. - -fn main() { - match Some("hi".to_string()) { - Some(s) if s.len() == 0 => {}, - //~^ ERROR E0008 - _ => {}, - } -} diff --git a/src/test/compile-fail/E0009.rs b/src/test/compile-fail/E0009.rs deleted file mode 100644 index 02e2e80e7ea..00000000000 --- a/src/test/compile-fail/E0009.rs +++ /dev/null @@ -1,19 +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. - -fn main() { - struct X { x: (), } - let x = Some((X { x: () }, X { x: () })); - match x { - Some((y, ref z)) => {}, - //~^ ERROR E0009 - None => panic!() - } -} diff --git a/src/test/compile-fail/E0010.rs b/src/test/compile-fail/E0010.rs deleted file mode 100644 index 66a9319a7df..00000000000 --- a/src/test/compile-fail/E0010.rs +++ /dev/null @@ -1,16 +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(box_syntax)] -#![allow(warnings)] - -const CON : Box = box 0; //~ ERROR E0010 - -fn main() {} diff --git a/src/test/compile-fail/E0017.rs b/src/test/compile-fail/E0017.rs deleted file mode 100644 index c98c35a1442..00000000000 --- a/src/test/compile-fail/E0017.rs +++ /dev/null @@ -1,18 +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. - -static X: i32 = 1; -const C: i32 = 2; - -const CR: &'static mut i32 = &mut C; //~ ERROR E0017 -static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 - //~| ERROR cannot borrow -static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017 -fn main() {} diff --git a/src/test/compile-fail/E0023.rs b/src/test/compile-fail/E0023.rs deleted file mode 100644 index 24032c59844..00000000000 --- a/src/test/compile-fail/E0023.rs +++ /dev/null @@ -1,24 +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. - -enum Fruit { - Apple(String, String), - Pear(u32), -} - - -fn main() { - let x = Fruit::Apple(String::new(), String::new()); - match x { - Fruit::Apple(a) => {}, //~ ERROR E0023 - Fruit::Apple(a, b, c) => {}, //~ ERROR E0023 - Fruit::Pear(1, 2) => {}, //~ ERROR E0023 - } -} diff --git a/src/test/compile-fail/E0025.rs b/src/test/compile-fail/E0025.rs deleted file mode 100644 index 81d0ea8a5e2..00000000000 --- a/src/test/compile-fail/E0025.rs +++ /dev/null @@ -1,20 +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. - -struct Foo { - a: u8, - b: u8, -} - -fn main() { - let x = Foo { a:1, b:2 }; - let Foo { a: x, a: y, b: 0 } = x; - //~^ ERROR field `a` bound multiple times in the pattern -} diff --git a/src/test/compile-fail/E0026.rs b/src/test/compile-fail/E0026.rs deleted file mode 100644 index f8ad7b5a30e..00000000000 --- a/src/test/compile-fail/E0026.rs +++ /dev/null @@ -1,22 +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. - -struct Thing { - x: u32, - y: u32 -} - -fn main() { - let thing = Thing { x: 0, y: 0 }; - match thing { - Thing { x, y, z } => {} - //~^ ERROR struct `Thing` does not have a field named `z` [E0026] - } -} diff --git a/src/test/compile-fail/E0027.rs b/src/test/compile-fail/E0027.rs deleted file mode 100644 index b63b0ab5dfd..00000000000 --- a/src/test/compile-fail/E0027.rs +++ /dev/null @@ -1,23 +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. - -struct Dog { - name: String, - age: u32, -} - -fn main() { - let d = Dog { name: "Rusty".to_string(), age: 8 }; - - match d { - Dog { age: x } => {} - //~^ ERROR pattern does not mention field `name` - } -} diff --git a/src/test/compile-fail/E0029.rs b/src/test/compile-fail/E0029.rs deleted file mode 100644 index 80d215bd327..00000000000 --- a/src/test/compile-fail/E0029.rs +++ /dev/null @@ -1,20 +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. - -fn main() { - let s = "hoho"; - - match s { - "hello" ... "world" => {} - //~^ ERROR only char and numeric types are allowed in range patterns - //~| ERROR non-reference pattern used to match a reference - _ => {} - } -} diff --git a/src/test/compile-fail/E0030.rs b/src/test/compile-fail/E0030.rs deleted file mode 100644 index ef3bded4bef..00000000000 --- a/src/test/compile-fail/E0030.rs +++ /dev/null @@ -1,17 +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. - - -fn main() { - match 5u32 { - 1000 ... 5 => {} - //~^ ERROR lower range bound must be less than or equal to upper - } -} diff --git a/src/test/compile-fail/E0033.rs b/src/test/compile-fail/E0033.rs deleted file mode 100644 index 3cdbb55f6de..00000000000 --- a/src/test/compile-fail/E0033.rs +++ /dev/null @@ -1,23 +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. - -trait SomeTrait { - fn foo(); -} - -fn main() { - let trait_obj: &SomeTrait = SomeTrait; - //~^ ERROR expected value, found trait `SomeTrait` - //~| ERROR E0038 - //~| method `foo` has no receiver - - let &invalid = trait_obj; - //~^ ERROR E0033 -} diff --git a/src/test/compile-fail/E0034.rs b/src/test/compile-fail/E0034.rs deleted file mode 100644 index 6eebd4d4d53..00000000000 --- a/src/test/compile-fail/E0034.rs +++ /dev/null @@ -1,31 +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. - -struct Test; - -trait Trait1 { - fn foo(); -} - -trait Trait2 { - fn foo(); -} - -impl Trait1 for Test { - fn foo() {} -} - -impl Trait2 for Test { - fn foo() {} -} - -fn main() { - Test::foo() //~ ERROR multiple applicable items in scope -} diff --git a/src/test/compile-fail/E0038.rs b/src/test/compile-fail/E0038.rs deleted file mode 100644 index 8087928c051..00000000000 --- a/src/test/compile-fail/E0038.rs +++ /dev/null @@ -1,21 +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. - -trait Trait { - fn foo(&self) -> Self; -} - -fn call_foo(x: Box) { - //~^ ERROR E0038 - let y = x.foo(); -} - -fn main() { -} diff --git a/src/test/compile-fail/E0040.rs b/src/test/compile-fail/E0040.rs deleted file mode 100644 index 8385d68c540..00000000000 --- a/src/test/compile-fail/E0040.rs +++ /dev/null @@ -1,25 +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. - -struct Foo { - x: i32, -} - -impl Drop for Foo { - fn drop(&mut self) { - println!("kaboom"); - } -} - -fn main() { - let mut x = Foo { x: -7 }; - x.drop(); - //~^ ERROR E0040 -} diff --git a/src/test/compile-fail/E0044.rs b/src/test/compile-fail/E0044.rs deleted file mode 100644 index 48fe2300031..00000000000 --- a/src/test/compile-fail/E0044.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern { fn some_func(x: T); } //~ ERROR E0044 - -fn main() { -} diff --git a/src/test/compile-fail/E0045.rs b/src/test/compile-fail/E0045.rs deleted file mode 100644 index 57c639dd143..00000000000 --- a/src/test/compile-fail/E0045.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern "Rust" { fn foo(x: u8, ...); } //~ ERROR E0045 - -fn main() { -} diff --git a/src/test/compile-fail/E0049.rs b/src/test/compile-fail/E0049.rs deleted file mode 100644 index 5867e11e9ac..00000000000 --- a/src/test/compile-fail/E0049.rs +++ /dev/null @@ -1,22 +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. - -trait Foo { - fn foo(x: T) -> Self; -} - -struct Bar; - -impl Foo for Bar { - fn foo(x: bool) -> Self { Bar } //~ ERROR E0049 -} - -fn main() { -} diff --git a/src/test/compile-fail/E0050.rs b/src/test/compile-fail/E0050.rs deleted file mode 100644 index 2ccc380c540..00000000000 --- a/src/test/compile-fail/E0050.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Foo { - fn foo(&self, x: u8) -> bool; - fn bar(&self, x: u8, y: u8, z: u8); - fn less(&self); -} - -struct Bar; - -impl Foo for Bar { - fn foo(&self) -> bool { true } //~ ERROR E0050 - fn bar(&self) { } //~ ERROR E0050 - fn less(&self, x: u8, y: u8, z: u8) { } //~ ERROR E0050 -} - -fn main() { -} diff --git a/src/test/compile-fail/E0054.rs b/src/test/compile-fail/E0054.rs deleted file mode 100644 index 158cd6ff9bb..00000000000 --- a/src/test/compile-fail/E0054.rs +++ /dev/null @@ -1,14 +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. - -fn main() { - let x = 5; - let x_is_nonzero = x as bool; //~ ERROR E0054 -} diff --git a/src/test/compile-fail/E0055.rs b/src/test/compile-fail/E0055.rs deleted file mode 100644 index 6e186b81cad..00000000000 --- a/src/test/compile-fail/E0055.rs +++ /dev/null @@ -1,23 +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. - -#![recursion_limit="2"] -struct Foo; - -impl Foo { - fn foo(&self) {} -} - -fn main() { - let foo = Foo; - let ref_foo = &&Foo; - ref_foo.foo(); - //~^ ERROR E0055 -} diff --git a/src/test/compile-fail/E0057.rs b/src/test/compile-fail/E0057.rs deleted file mode 100644 index 1fb5498b099..00000000000 --- a/src/test/compile-fail/E0057.rs +++ /dev/null @@ -1,16 +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. - -fn main() { - let f = |x| x * 3; - let a = f(); //~ ERROR E0057 - let b = f(4); - let c = f(2, 3); //~ ERROR E0057 -} diff --git a/src/test/compile-fail/E0059.rs b/src/test/compile-fail/E0059.rs deleted file mode 100644 index 4ae9b2f91d2..00000000000 --- a/src/test/compile-fail/E0059.rs +++ /dev/null @@ -1,16 +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(unboxed_closures)] - -fn foo>(f: F) -> F::Output { f(3) } //~ ERROR E0059 - -fn main() { -} diff --git a/src/test/compile-fail/E0060.rs b/src/test/compile-fail/E0060.rs deleted file mode 100644 index f4505209b66..00000000000 --- a/src/test/compile-fail/E0060.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern "C" { - fn printf(_: *const u8, ...) -> u32; -} - -fn main() { - unsafe { printf(); } - //~^ ERROR E0060 - //~| expected at least 1 parameter -} diff --git a/src/test/compile-fail/E0061.rs b/src/test/compile-fail/E0061.rs deleted file mode 100644 index 221e18cf89d..00000000000 --- a/src/test/compile-fail/E0061.rs +++ /dev/null @@ -1,23 +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. - -fn f(a: u16, b: &str) {} - -fn f2(a: u16) {} - -fn main() { - f(0); - //~^ ERROR E0061 - //~| expected 2 parameters - - f2(); - //~^ ERROR E0061 - //~| expected 1 parameter -} diff --git a/src/test/compile-fail/E0062.rs b/src/test/compile-fail/E0062.rs deleted file mode 100644 index 684c9464ff8..00000000000 --- a/src/test/compile-fail/E0062.rs +++ /dev/null @@ -1,21 +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. - -struct Foo { - x: i32 -} - -fn main() { - let x = Foo { - x: 0, - x: 0, - //~^ ERROR E0062 - }; -} diff --git a/src/test/compile-fail/E0063.rs b/src/test/compile-fail/E0063.rs deleted file mode 100644 index 0208aff066b..00000000000 --- a/src/test/compile-fail/E0063.rs +++ /dev/null @@ -1,50 +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. - -// ignore-tidy-linelength - -struct SingleFoo { - x: i32 -} - -struct PluralFoo { - x: i32, - y: i32, - z: i32 -} - -struct TruncatedFoo { - a: i32, - b: i32, - x: i32, - y: i32, - z: i32 -} - -struct TruncatedPluralFoo { - a: i32, - b: i32, - c: i32, - x: i32, - y: i32, - z: i32 -} - - -fn main() { - let w = SingleFoo { }; - //~^ ERROR missing field `x` in initializer of `SingleFoo` - let x = PluralFoo {x: 1}; - //~^ ERROR missing fields `y`, `z` in initializer of `PluralFoo` - let y = TruncatedFoo{x:1}; - //~^ missing fields `a`, `b`, `y` and 1 other field in initializer of `TruncatedFoo` - let z = TruncatedPluralFoo{x:1}; - //~^ ERROR missing fields `a`, `b`, `c` and 2 other fields in initializer of `TruncatedPluralFoo` -} diff --git a/src/test/compile-fail/E0067.rs b/src/test/compile-fail/E0067.rs deleted file mode 100644 index a3fc30ee1c7..00000000000 --- a/src/test/compile-fail/E0067.rs +++ /dev/null @@ -1,16 +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 std::collections::LinkedList; - -fn main() { - LinkedList::new() += 1; //~ ERROR E0368 - //~^ ERROR E0067 -} diff --git a/src/test/compile-fail/E0069.rs b/src/test/compile-fail/E0069.rs deleted file mode 100644 index a6a7898ed4e..00000000000 --- a/src/test/compile-fail/E0069.rs +++ /dev/null @@ -1,17 +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. - -fn foo() -> u8 { - return; - //~^ ERROR `return;` in a function whose return type is not `()` -} - -fn main() { -} diff --git a/src/test/compile-fail/E0070.rs b/src/test/compile-fail/E0070.rs deleted file mode 100644 index ba66bd03aef..00000000000 --- a/src/test/compile-fail/E0070.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -const SOME_CONST : i32 = 12; - -fn some_other_func() {} - -fn some_function() { - SOME_CONST = 14; //~ ERROR E0070 - 1 = 3; //~ ERROR E0070 - some_other_func() = 4; //~ ERROR E0070 - //~^ ERROR E0308 -} - -fn main() { -} diff --git a/src/test/compile-fail/E0071.rs b/src/test/compile-fail/E0071.rs deleted file mode 100644 index d71dc7966fa..00000000000 --- a/src/test/compile-fail/E0071.rs +++ /dev/null @@ -1,17 +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. - -enum Foo {} -type FooAlias = Foo; - -fn main() { - let u = FooAlias { value: 0 }; - //~^ ERROR expected struct, variant or union type, found enum `Foo` [E0071] -} diff --git a/src/test/compile-fail/E0075.rs b/src/test/compile-fail/E0075.rs deleted file mode 100644 index d7783904e2e..00000000000 --- a/src/test/compile-fail/E0075.rs +++ /dev/null @@ -1,17 +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(repr_simd)] - -#[repr(simd)] -struct Bad; //~ ERROR E0075 - -fn main() { -} diff --git a/src/test/compile-fail/E0076.rs b/src/test/compile-fail/E0076.rs deleted file mode 100644 index b159cf107ce..00000000000 --- a/src/test/compile-fail/E0076.rs +++ /dev/null @@ -1,18 +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(repr_simd)] - -#[repr(simd)] -struct Bad(u16, u32, u32); -//~^ ERROR E0076 - -fn main() { -} diff --git a/src/test/compile-fail/E0077.rs b/src/test/compile-fail/E0077.rs deleted file mode 100644 index b074e90b2c0..00000000000 --- a/src/test/compile-fail/E0077.rs +++ /dev/null @@ -1,17 +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(repr_simd)] - -#[repr(simd)] -struct Bad(String); //~ ERROR E0077 - -fn main() { -} diff --git a/src/test/compile-fail/E0080.rs b/src/test/compile-fail/E0080.rs deleted file mode 100644 index 2f199c48e46..00000000000 --- a/src/test/compile-fail/E0080.rs +++ /dev/null @@ -1,19 +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. - -enum Enum { - X = (1 << 500), //~ ERROR E0080 - //~| WARNING shift left with overflow - Y = (1 / 0) //~ ERROR E0080 - //~| WARNING divide by zero -} - -fn main() { -} diff --git a/src/test/compile-fail/E0081.rs b/src/test/compile-fail/E0081.rs deleted file mode 100644 index 3b571667336..00000000000 --- a/src/test/compile-fail/E0081.rs +++ /dev/null @@ -1,19 +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. - -enum Enum { - P = 3, - X = 3, - //~^ ERROR discriminant value `3isize` already exists - Y = 5 -} - -fn main() { -} diff --git a/src/test/compile-fail/E0084.rs b/src/test/compile-fail/E0084.rs deleted file mode 100644 index 2be206c9702..00000000000 --- a/src/test/compile-fail/E0084.rs +++ /dev/null @@ -1,15 +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. - -#[repr(i32)] //~ ERROR: E0084 -enum Foo {} - -fn main() { -} diff --git a/src/test/compile-fail/E0087.rs b/src/test/compile-fail/E0087.rs deleted file mode 100644 index 6dc08860614..00000000000 --- a/src/test/compile-fail/E0087.rs +++ /dev/null @@ -1,18 +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. - -fn foo() {} -fn bar() {} - -fn main() { - foo::(); //~ ERROR expected at most 0 type parameters, found 1 type parameter [E0087] - - bar::(); //~ ERROR expected at most 1 type parameter, found 2 type parameters [E0087] -} diff --git a/src/test/compile-fail/E0088.rs b/src/test/compile-fail/E0088.rs deleted file mode 100644 index db84a4edc48..00000000000 --- a/src/test/compile-fail/E0088.rs +++ /dev/null @@ -1,17 +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. - -fn f() {} -fn g<'a>() -> &'a u8 { loop {} } - -fn main() { - f::<'static>(); //~ ERROR E0088 - g::<'static, 'static>(); //~ ERROR E0088 -} diff --git a/src/test/compile-fail/E0089.rs b/src/test/compile-fail/E0089.rs deleted file mode 100644 index 21df9abd093..00000000000 --- a/src/test/compile-fail/E0089.rs +++ /dev/null @@ -1,15 +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. - -fn foo() {} - -fn main() { - foo::(); //~ ERROR expected 2 type parameters, found 1 type parameter [E0089] -} diff --git a/src/test/compile-fail/E0090.rs b/src/test/compile-fail/E0090.rs deleted file mode 100644 index 13b2131cc8b..00000000000 --- a/src/test/compile-fail/E0090.rs +++ /dev/null @@ -1,15 +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. - -fn foo<'a: 'b, 'b: 'a>() {} - -fn main() { - foo::<'static>(); //~ ERROR expected 2 lifetime parameters, found 1 lifetime parameter [E0090] -} diff --git a/src/test/compile-fail/E0091.rs b/src/test/compile-fail/E0091.rs deleted file mode 100644 index da988dbf819..00000000000 --- a/src/test/compile-fail/E0091.rs +++ /dev/null @@ -1,15 +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. - -type Foo = u32; //~ ERROR E0091 -type Foo2 = Box; //~ ERROR E0091 - -fn main() { -} diff --git a/src/test/compile-fail/E0092.rs b/src/test/compile-fail/E0092.rs deleted file mode 100644 index b08164ac06d..00000000000 --- a/src/test/compile-fail/E0092.rs +++ /dev/null @@ -1,17 +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(intrinsics)] -extern "rust-intrinsic" { - fn atomic_foo(); //~ ERROR E0092 -} - -fn main() { -} diff --git a/src/test/compile-fail/E0093.rs b/src/test/compile-fail/E0093.rs deleted file mode 100644 index d84f9f64911..00000000000 --- a/src/test/compile-fail/E0093.rs +++ /dev/null @@ -1,18 +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(intrinsics)] -extern "rust-intrinsic" { - fn foo(); - //~^ ERROR E0093 -} - -fn main() { -} diff --git a/src/test/compile-fail/E0094.rs b/src/test/compile-fail/E0094.rs deleted file mode 100644 index 3a31874b244..00000000000 --- a/src/test/compile-fail/E0094.rs +++ /dev/null @@ -1,17 +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(intrinsics)] -extern "rust-intrinsic" { - fn size_of() -> usize; //~ ERROR E0094 -} - -fn main() { -} diff --git a/src/test/compile-fail/E0106.rs b/src/test/compile-fail/E0106.rs deleted file mode 100644 index 0674930a11c..00000000000 --- a/src/test/compile-fail/E0106.rs +++ /dev/null @@ -1,36 +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. - -struct Foo { - x: &bool, - //~^ ERROR E0106 -} -enum Bar { - A(u8), - B(&bool), - //~^ ERROR E0106 -} -type MyStr = &str; - //~^ ERROR E0106 - -struct Baz<'a>(&'a str); -struct Buzz<'a, 'b>(&'a str, &'b str); - -struct Quux { - baz: Baz, - //~^ ERROR E0106 - //~| expected lifetime parameter - buzz: Buzz, - //~^ ERROR E0106 - //~| expected 2 lifetime parameters -} - -fn main() { -} diff --git a/src/test/compile-fail/E0107.rs b/src/test/compile-fail/E0107.rs deleted file mode 100644 index 16ebd3e9ca5..00000000000 --- a/src/test/compile-fail/E0107.rs +++ /dev/null @@ -1,33 +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. - -struct Foo<'a>(&'a str); -struct Buzz<'a, 'b>(&'a str, &'b str); - -enum Bar { - A, - B, - C, -} - -struct Baz<'a, 'b, 'c> { - buzz: Buzz<'a>, - //~^ ERROR E0107 - //~| expected 2 lifetime parameters - bar: Bar<'a>, - //~^ ERROR E0107 - //~| unexpected lifetime parameter - foo2: Foo<'a, 'b, 'c>, - //~^ ERROR E0107 - //~| 2 unexpected lifetime parameters -} - -fn main() { -} diff --git a/src/test/compile-fail/E0109.rs b/src/test/compile-fail/E0109.rs deleted file mode 100644 index 9fc47842250..00000000000 --- a/src/test/compile-fail/E0109.rs +++ /dev/null @@ -1,14 +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. - -type X = u32; //~ ERROR E0109 - -fn main() { -} diff --git a/src/test/compile-fail/E0110.rs b/src/test/compile-fail/E0110.rs deleted file mode 100644 index fd169f4acc5..00000000000 --- a/src/test/compile-fail/E0110.rs +++ /dev/null @@ -1,14 +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. - -type X = u32<'static>; //~ ERROR E0110 - -fn main() { -} diff --git a/src/test/compile-fail/E0116.rs b/src/test/compile-fail/E0116.rs deleted file mode 100644 index cd7d8dc3efb..00000000000 --- a/src/test/compile-fail/E0116.rs +++ /dev/null @@ -1,15 +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. - -impl Vec {} -//~^ ERROR E0116 - -fn main() { -} diff --git a/src/test/compile-fail/E0117.rs b/src/test/compile-fail/E0117.rs deleted file mode 100644 index 982f875c7b0..00000000000 --- a/src/test/compile-fail/E0117.rs +++ /dev/null @@ -1,16 +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. - -impl Drop for u32 {} //~ ERROR E0117 -//~| ERROR the Drop trait may only be implemented on structures -//~| implementing Drop requires a struct - -fn main() { -} diff --git a/src/test/compile-fail/E0118.rs b/src/test/compile-fail/E0118.rs deleted file mode 100644 index d37ff34b861..00000000000 --- a/src/test/compile-fail/E0118.rs +++ /dev/null @@ -1,18 +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. - -impl (u8, u8) { //~ ERROR E0118 - fn get_state(&self) -> String { - String::new() - } -} - -fn main() { -} diff --git a/src/test/compile-fail/E0119.rs b/src/test/compile-fail/E0119.rs deleted file mode 100644 index 9528631b304..00000000000 --- a/src/test/compile-fail/E0119.rs +++ /dev/null @@ -1,28 +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. - -trait MyTrait { - fn get(&self) -> usize; -} - -impl MyTrait for T { - fn get(&self) -> usize { 0 } -} - -struct Foo { - value: usize -} - -impl MyTrait for Foo { //~ ERROR E0119 - fn get(&self) -> usize { self.value } -} - -fn main() { -} diff --git a/src/test/compile-fail/E0120.rs b/src/test/compile-fail/E0120.rs deleted file mode 100644 index 8d09b877f00..00000000000 --- a/src/test/compile-fail/E0120.rs +++ /dev/null @@ -1,19 +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. - -trait MyTrait { fn foo() {} } - -impl Drop for MyTrait { - //~^ ERROR E0120 - fn drop(&mut self) {} -} - -fn main() { -} diff --git a/src/test/compile-fail/E0121.rs b/src/test/compile-fail/E0121.rs deleted file mode 100644 index b26b5f41bfe..00000000000 --- a/src/test/compile-fail/E0121.rs +++ /dev/null @@ -1,16 +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. - -fn foo() -> _ { 5 } //~ ERROR E0121 - -static BAR: _ = "test"; //~ ERROR E0121 - -fn main() { -} diff --git a/src/test/compile-fail/E0124.rs b/src/test/compile-fail/E0124.rs deleted file mode 100644 index 3ef20c6dd40..00000000000 --- a/src/test/compile-fail/E0124.rs +++ /dev/null @@ -1,18 +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. - -struct Foo { - field1: i32, - field1: i32, - //~^ ERROR field `field1` is already declared [E0124] -} - -fn main() { -} diff --git a/src/test/compile-fail/E0128.rs b/src/test/compile-fail/E0128.rs deleted file mode 100644 index 37071012825..00000000000 --- a/src/test/compile-fail/E0128.rs +++ /dev/null @@ -1,17 +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. - -struct Foo { //~ ERROR E0128 - field1: T, - field2: U, -} - -fn main() { -} diff --git a/src/test/compile-fail/E0130.rs b/src/test/compile-fail/E0130.rs deleted file mode 100644 index d11b59cdf33..00000000000 --- a/src/test/compile-fail/E0130.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern { - fn foo((a, b): (u32, u32)); - //~^ ERROR E0130 -} - -fn main() { -} diff --git a/src/test/compile-fail/E0131.rs b/src/test/compile-fail/E0131.rs deleted file mode 100644 index c7e31edd301..00000000000 --- a/src/test/compile-fail/E0131.rs +++ /dev/null @@ -1,13 +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. - -fn main() { - //~^ ERROR E0131 -} diff --git a/src/test/compile-fail/E0132.rs b/src/test/compile-fail/E0132.rs deleted file mode 100644 index 25ccb344aba..00000000000 --- a/src/test/compile-fail/E0132.rs +++ /dev/null @@ -1,17 +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(start)] - -#[start] -fn f< T >() {} //~ ERROR E0132 - -fn main() { -} diff --git a/src/test/compile-fail/E0133.rs b/src/test/compile-fail/E0133.rs deleted file mode 100644 index 2e54f65e7bf..00000000000 --- a/src/test/compile-fail/E0133.rs +++ /dev/null @@ -1,16 +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. - -unsafe fn f() { return; } - -fn main() { - f(); - //~^ ERROR E0133 -} diff --git a/src/test/compile-fail/E0137.rs b/src/test/compile-fail/E0137.rs deleted file mode 100644 index 067ebcc727c..00000000000 --- a/src/test/compile-fail/E0137.rs +++ /dev/null @@ -1,18 +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(main)] - -#[main] -fn foo() {} - -#[main] -fn f() {} -//~^ ERROR E0137 diff --git a/src/test/compile-fail/E0138.rs b/src/test/compile-fail/E0138.rs deleted file mode 100644 index 856616c8570..00000000000 --- a/src/test/compile-fail/E0138.rs +++ /dev/null @@ -1,18 +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(start)] - -#[start] -fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } - -#[start] -fn f(argc: isize, argv: *const *const u8) -> isize { 0 } -//~^ ERROR E0138 diff --git a/src/test/compile-fail/E0152.rs b/src/test/compile-fail/E0152.rs deleted file mode 100644 index ae501b94e3f..00000000000 --- a/src/test/compile-fail/E0152.rs +++ /dev/null @@ -1,17 +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(lang_items)] - -#[lang = "panic_fmt"] -struct Foo; //~ ERROR E0152 - -fn main() { -} diff --git a/src/test/compile-fail/E0161.rs b/src/test/compile-fail/E0161.rs deleted file mode 100644 index 81adf908302..00000000000 --- a/src/test/compile-fail/E0161.rs +++ /dev/null @@ -1,16 +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(box_syntax)] - -fn main() { - let _x: Box = box *"hello"; //~ ERROR E0161 - //~^ ERROR E0507 -} diff --git a/src/test/compile-fail/E0162.rs b/src/test/compile-fail/E0162.rs deleted file mode 100644 index e13b0af6f79..00000000000 --- a/src/test/compile-fail/E0162.rs +++ /dev/null @@ -1,18 +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. - -struct Irrefutable(i32); - -fn main() { - let irr = Irrefutable(0); - if let Irrefutable(x) = irr { //~ ERROR E0162 - println!("{}", x); - } -} diff --git a/src/test/compile-fail/E0164.rs b/src/test/compile-fail/E0164.rs deleted file mode 100644 index a7f10ddb5a7..00000000000 --- a/src/test/compile-fail/E0164.rs +++ /dev/null @@ -1,25 +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. - - -enum Foo {} - -impl Foo { - const B: u8 = 0; -} - -fn bar(foo: Foo) -> u32 { - match foo { - Foo::B(i) => i, //~ ERROR E0164 - } -} - -fn main() { -} diff --git a/src/test/compile-fail/E0165.rs b/src/test/compile-fail/E0165.rs deleted file mode 100644 index 142635fc6ee..00000000000 --- a/src/test/compile-fail/E0165.rs +++ /dev/null @@ -1,19 +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. - -struct Irrefutable(i32); - -fn main() { - let irr = Irrefutable(0); - while let Irrefutable(x) = irr { //~ ERROR E0165 - //~| irrefutable pattern - // ... - } -} diff --git a/src/test/compile-fail/E0184.rs b/src/test/compile-fail/E0184.rs deleted file mode 100644 index 5d72d00ffe8..00000000000 --- a/src/test/compile-fail/E0184.rs +++ /dev/null @@ -1,20 +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. - -#[derive(Copy)] //~ ERROR E0184 -struct Foo; - -impl Drop for Foo { - fn drop(&mut self) { - } -} - -fn main() { -} diff --git a/src/test/compile-fail/E0185.rs b/src/test/compile-fail/E0185.rs deleted file mode 100644 index 0cd3d00a735..00000000000 --- a/src/test/compile-fail/E0185.rs +++ /dev/null @@ -1,25 +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. - -trait Foo { - fn foo(); - //~^ NOTE trait method declared without `&self` -} - -struct Bar; - -impl Foo for Bar { - fn foo(&self) {} - //~^ ERROR E0185 - //~| NOTE `&self` used in impl -} - -fn main() { -} diff --git a/src/test/compile-fail/E0186.rs b/src/test/compile-fail/E0186.rs deleted file mode 100644 index 55a3490cac4..00000000000 --- a/src/test/compile-fail/E0186.rs +++ /dev/null @@ -1,23 +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. - -trait Foo { - fn foo(&self); //~ `&self` used in trait -} - -struct Bar; - -impl Foo for Bar { - fn foo() {} //~ ERROR E0186 - //~^ expected `&self` in impl -} - -fn main() { -} diff --git a/src/test/compile-fail/E0191.rs b/src/test/compile-fail/E0191.rs deleted file mode 100644 index 489ebb033f8..00000000000 --- a/src/test/compile-fail/E0191.rs +++ /dev/null @@ -1,18 +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. - -trait Trait { - type Bar; -} - -type Foo = Trait; //~ ERROR E0191 - -fn main() { -} diff --git a/src/test/compile-fail/E0192.rs b/src/test/compile-fail/E0192.rs deleted file mode 100644 index 92f5876ee04..00000000000 --- a/src/test/compile-fail/E0192.rs +++ /dev/null @@ -1,22 +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(optin_builtin_traits)] - -trait Trait { - type Bar; -} - -struct Foo; - -impl !Trait for Foo { } //~ ERROR E0192 - -fn main() { -} diff --git a/src/test/compile-fail/E0194.rs b/src/test/compile-fail/E0194.rs deleted file mode 100644 index 17e0751859d..00000000000 --- a/src/test/compile-fail/E0194.rs +++ /dev/null @@ -1,18 +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. - -trait Foo { - fn do_something(&self) -> T; - fn do_something_else(&self, bar: T); - //~^ ERROR E0194 -} - -fn main() { -} diff --git a/src/test/compile-fail/E0195.rs b/src/test/compile-fail/E0195.rs deleted file mode 100644 index 06dd903b23d..00000000000 --- a/src/test/compile-fail/E0195.rs +++ /dev/null @@ -1,24 +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. - -trait Trait { - fn bar<'a,'b:'a>(x: &'a str, y: &'b str); -} - -struct Foo; - -impl Trait for Foo { - fn bar<'a,'b>(x: &'a str, y: &'b str) { //~ ERROR E0195 - //~^ lifetimes do not match trait - } -} - -fn main() { -} diff --git a/src/test/compile-fail/E0197.rs b/src/test/compile-fail/E0197.rs deleted file mode 100644 index f25fa9b92b9..00000000000 --- a/src/test/compile-fail/E0197.rs +++ /dev/null @@ -1,16 +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. - -struct Foo; - -unsafe impl Foo { } //~ ERROR E0197 - -fn main() { -} diff --git a/src/test/compile-fail/E0198.rs b/src/test/compile-fail/E0198.rs deleted file mode 100644 index 1a779a41e66..00000000000 --- a/src/test/compile-fail/E0198.rs +++ /dev/null @@ -1,18 +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(optin_builtin_traits)] - -struct Foo; - -unsafe impl !Send for Foo { } //~ ERROR E0198 - -fn main() { -} diff --git a/src/test/compile-fail/E0199.rs b/src/test/compile-fail/E0199.rs deleted file mode 100644 index 1a5cd1941a9..00000000000 --- a/src/test/compile-fail/E0199.rs +++ /dev/null @@ -1,19 +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(optin_builtin_traits)] - -struct Foo; - -trait Bar { } -unsafe impl Bar for Foo { } //~ ERROR implementing the trait `Bar` is not unsafe [E0199] - -fn main() { -} diff --git a/src/test/compile-fail/E0200.rs b/src/test/compile-fail/E0200.rs deleted file mode 100644 index 6bfea0e59d7..00000000000 --- a/src/test/compile-fail/E0200.rs +++ /dev/null @@ -1,18 +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. - -struct Foo; - -unsafe trait Bar { } - -impl Bar for Foo { } //~ ERROR E0200 - -fn main() { -} diff --git a/src/test/compile-fail/E0201.rs b/src/test/compile-fail/E0201.rs deleted file mode 100644 index ff6cb55f388..00000000000 --- a/src/test/compile-fail/E0201.rs +++ /dev/null @@ -1,32 +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. - -struct Foo(u8); - -impl Foo { - fn bar(&self) -> bool { self.0 > 5 } - fn bar() {} //~ ERROR E0201 -} - -trait Baz { - type Quux; - fn baz(&self) -> bool; -} - -impl Baz for Foo { - type Quux = u32; - - fn baz(&self) -> bool { true } - fn baz(&self) -> bool { self.0 > 5 } //~ ERROR E0201 - type Quux = u32; //~ ERROR E0201 -} - -fn main() { -} diff --git a/src/test/compile-fail/E0206.rs b/src/test/compile-fail/E0206.rs deleted file mode 100644 index da0370b301b..00000000000 --- a/src/test/compile-fail/E0206.rs +++ /dev/null @@ -1,24 +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. - -type Foo = i32; - -impl Copy for Foo { } -//~^ ERROR the trait `Copy` may not be implemented for this type -//~| ERROR only traits defined in the current crate can be implemented for arbitrary types - -#[derive(Copy, Clone)] -struct Bar; - -impl Copy for &'static Bar { } -//~^ ERROR the trait `Copy` may not be implemented for this type - -fn main() { -} diff --git a/src/test/compile-fail/E0207.rs b/src/test/compile-fail/E0207.rs deleted file mode 100644 index bd87dbaf786..00000000000 --- a/src/test/compile-fail/E0207.rs +++ /dev/null @@ -1,20 +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. - -struct Foo; - -impl Foo { //~ ERROR E0207 - fn get(&self) -> T { - ::default() - } -} - -fn main() { -} diff --git a/src/test/compile-fail/E0214.rs b/src/test/compile-fail/E0214.rs deleted file mode 100644 index 2b090391c74..00000000000 --- a/src/test/compile-fail/E0214.rs +++ /dev/null @@ -1,14 +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. - -fn main() { - let v: Vec(&str) = vec!["foo"]; - //~^ ERROR E0214 -} diff --git a/src/test/compile-fail/E0220.rs b/src/test/compile-fail/E0220.rs deleted file mode 100644 index 2866ffcd637..00000000000 --- a/src/test/compile-fail/E0220.rs +++ /dev/null @@ -1,18 +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. - -trait Trait { - type Bar; -} - -type Foo = Trait; //~ ERROR E0220 - //~| ERROR E0191 -fn main() { -} diff --git a/src/test/compile-fail/E0221.rs b/src/test/compile-fail/E0221.rs deleted file mode 100644 index 99092465b0a..00000000000 --- a/src/test/compile-fail/E0221.rs +++ /dev/null @@ -1,37 +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. - -trait T1 {} -trait T2 {} - -trait Foo { - type A: T1; -} - -trait Bar : Foo { - type A: T2; - fn do_something() { - let _: Self::A; - //~^ ERROR E0221 - } -} - -trait T3 {} - -trait My : std::str::FromStr { - type Err: T3; - fn test() { - let _: Self::Err; - //~^ ERROR E0221 - } -} - -fn main() { -} diff --git a/src/test/compile-fail/E0223.rs b/src/test/compile-fail/E0223.rs deleted file mode 100644 index 0683197b2b6..00000000000 --- a/src/test/compile-fail/E0223.rs +++ /dev/null @@ -1,16 +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. - -trait MyTrait { type X; } - -fn main() { - let foo: MyTrait::X; - //~^ ERROR ambiguous associated type -} diff --git a/src/test/compile-fail/E0225.rs b/src/test/compile-fail/E0225.rs deleted file mode 100644 index 6c77443c5ed..00000000000 --- a/src/test/compile-fail/E0225.rs +++ /dev/null @@ -1,14 +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. - -fn main() { - let _: Box; - //~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] -} diff --git a/src/test/compile-fail/E0229.rs b/src/test/compile-fail/E0229.rs deleted file mode 100644 index b70fb092a54..00000000000 --- a/src/test/compile-fail/E0229.rs +++ /dev/null @@ -1,27 +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. - -pub trait Foo { - type A; - fn boo(&self) -> ::A; -} - -struct Bar; - -impl Foo for isize { - type A = usize; - fn boo(&self) -> usize { 42 } -} - -fn baz(x: &>::A) {} -//~^ ERROR associated type bindings are not allowed here [E0229] - -fn main() { -} diff --git a/src/test/compile-fail/E0232.rs b/src/test/compile-fail/E0232.rs deleted file mode 100644 index 04657c65c8e..00000000000 --- a/src/test/compile-fail/E0232.rs +++ /dev/null @@ -1,18 +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(on_unimplemented)] - -#[rustc_on_unimplemented] -//~^ ERROR E0232 -trait Bar {} - -fn main() { -} diff --git a/src/test/compile-fail/E0243.rs b/src/test/compile-fail/E0243.rs deleted file mode 100644 index 615ce0b5d42..00000000000 --- a/src/test/compile-fail/E0243.rs +++ /dev/null @@ -1,16 +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. - -struct Foo { x: T } -struct Bar { x: Foo } - //~^ ERROR wrong number of type arguments: expected 1, found 0 [E0243] - -fn main() { -} diff --git a/src/test/compile-fail/E0244.rs b/src/test/compile-fail/E0244.rs deleted file mode 100644 index 9a78b3139d0..00000000000 --- a/src/test/compile-fail/E0244.rs +++ /dev/null @@ -1,17 +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. - -struct Foo { x: bool } -struct Bar { x: Foo } - //~^ ERROR wrong number of type arguments: expected 0, found 2 [E0244] - - -fn main() { -} diff --git a/src/test/compile-fail/E0252.rs b/src/test/compile-fail/E0252.rs deleted file mode 100644 index 6b353c8cd1a..00000000000 --- a/src/test/compile-fail/E0252.rs +++ /dev/null @@ -1,23 +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 foo::baz; -use bar::baz; //~ ERROR E0252 - -mod foo { - pub struct baz; -} - -mod bar { - pub mod baz {} -} - -fn main() { -} diff --git a/src/test/compile-fail/E0253.rs b/src/test/compile-fail/E0253.rs deleted file mode 100644 index 186d9019aae..00000000000 --- a/src/test/compile-fail/E0253.rs +++ /dev/null @@ -1,20 +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. - -mod foo { - pub trait MyTrait { - fn do_something(); - } -} - -use foo::MyTrait::do_something; - //~^ ERROR E0253 - -fn main() {} diff --git a/src/test/compile-fail/E0254.rs b/src/test/compile-fail/E0254.rs deleted file mode 100644 index 46c74fe3735..00000000000 --- a/src/test/compile-fail/E0254.rs +++ /dev/null @@ -1,25 +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(alloc)] -#![allow(unused_extern_crates)] - -extern crate alloc; - -mod foo { - pub trait alloc { - fn do_something(); - } -} - -use foo::alloc; -//~^ ERROR E0254 - -fn main() {} diff --git a/src/test/compile-fail/E0255.rs b/src/test/compile-fail/E0255.rs deleted file mode 100644 index e05c6bede7e..00000000000 --- a/src/test/compile-fail/E0255.rs +++ /dev/null @@ -1,19 +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 bar::foo; - -fn foo() {} //~ ERROR E0255 - -mod bar { - pub fn foo() {} -} - -fn main() {} diff --git a/src/test/compile-fail/E0259.rs b/src/test/compile-fail/E0259.rs deleted file mode 100644 index 5a47541c708..00000000000 --- a/src/test/compile-fail/E0259.rs +++ /dev/null @@ -1,19 +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(alloc, libc)] -#![allow(unused_extern_crates)] - -extern crate alloc; - -extern crate libc as alloc; -//~^ ERROR E0259 - -fn main() {} diff --git a/src/test/compile-fail/E0260.rs b/src/test/compile-fail/E0260.rs deleted file mode 100644 index 1b01bb12203..00000000000 --- a/src/test/compile-fail/E0260.rs +++ /dev/null @@ -1,23 +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(alloc)] -#![allow(unused_extern_crates)] - -extern crate alloc; - -mod alloc { -//~^ ERROR the name `alloc` is defined multiple times [E0260] - pub trait MyTrait { - fn do_something(); - } -} - -fn main() {} diff --git a/src/test/compile-fail/E0261.rs b/src/test/compile-fail/E0261.rs deleted file mode 100644 index 558c1c38144..00000000000 --- a/src/test/compile-fail/E0261.rs +++ /dev/null @@ -1,19 +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. - -fn foo(x: &'a str) { } //~ ERROR E0261 - //~| undeclared lifetime - -struct Foo { - x: &'a str, //~ ERROR E0261 - //~| undeclared lifetime -} - -fn main() {} diff --git a/src/test/compile-fail/E0262.rs b/src/test/compile-fail/E0262.rs deleted file mode 100644 index 41b6acaee4a..00000000000 --- a/src/test/compile-fail/E0262.rs +++ /dev/null @@ -1,14 +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. - -fn foo<'static>(x: &'static str) { } //~ ERROR E0262 - //~| 'static is a reserved lifetime name - -fn main() {} diff --git a/src/test/compile-fail/E0263.rs b/src/test/compile-fail/E0263.rs deleted file mode 100644 index 722f1c25e07..00000000000 --- a/src/test/compile-fail/E0263.rs +++ /dev/null @@ -1,15 +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. - -fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) { - //~^ ERROR E0263 -} - -fn main() {} diff --git a/src/test/compile-fail/E0264.rs b/src/test/compile-fail/E0264.rs deleted file mode 100644 index 92332977e76..00000000000 --- a/src/test/compile-fail/E0264.rs +++ /dev/null @@ -1,18 +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(lang_items)] - -extern "C" { - #[lang = "cake"] - fn cake(); //~ ERROR E0264 -} - -fn main() {} diff --git a/src/test/compile-fail/E0267.rs b/src/test/compile-fail/E0267.rs deleted file mode 100644 index 6287256e866..00000000000 --- a/src/test/compile-fail/E0267.rs +++ /dev/null @@ -1,13 +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. - -fn main() { - let w = || { break; }; //~ ERROR E0267 -} diff --git a/src/test/compile-fail/E0268.rs b/src/test/compile-fail/E0268.rs deleted file mode 100644 index 41e88e2f492..00000000000 --- a/src/test/compile-fail/E0268.rs +++ /dev/null @@ -1,13 +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. - -fn main() { - break; //~ ERROR E0268 -} diff --git a/src/test/compile-fail/E0271.rs b/src/test/compile-fail/E0271.rs deleted file mode 100644 index d322c8b1caf..00000000000 --- a/src/test/compile-fail/E0271.rs +++ /dev/null @@ -1,21 +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. - -trait Trait { type AssociatedType; } - -fn foo(t: T) where T: Trait { - println!("in foo"); -} - -impl Trait for i8 { type AssociatedType = &'static str; } - -fn main() { - foo(3_i8); //~ ERROR E0271 -} diff --git a/src/test/compile-fail/E0275.rs b/src/test/compile-fail/E0275.rs deleted file mode 100644 index 8dfd1d9b4af..00000000000 --- a/src/test/compile-fail/E0275.rs +++ /dev/null @@ -1,18 +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. - -trait Foo {} - -struct Bar(T); - -impl Foo for T where Bar: Foo {} //~ ERROR E0275 - -fn main() { -} diff --git a/src/test/compile-fail/E0276.rs b/src/test/compile-fail/E0276.rs deleted file mode 100644 index 62e43b02ca8..00000000000 --- a/src/test/compile-fail/E0276.rs +++ /dev/null @@ -1,20 +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. - -trait Foo { - fn foo(x: T); -} - -impl Foo for bool { - fn foo(x: T) where T: Copy {} //~ ERROR E0276 -} - -fn main() { -} diff --git a/src/test/compile-fail/E0277-2.rs b/src/test/compile-fail/E0277-2.rs deleted file mode 100644 index 4d1c50002a3..00000000000 --- a/src/test/compile-fail/E0277-2.rs +++ /dev/null @@ -1,28 +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. - -struct Foo { - bar: Bar -} - -struct Bar { - baz: Baz -} - -struct Baz { - x: *const u8 -} - -fn is_send() { } - -fn main() { - is_send::(); - //~^ ERROR the trait bound `*const u8: std::marker::Send` is not satisfied in `Foo` -} diff --git a/src/test/compile-fail/E0277.rs b/src/test/compile-fail/E0277.rs deleted file mode 100644 index b29e4357015..00000000000 --- a/src/test/compile-fail/E0277.rs +++ /dev/null @@ -1,29 +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. - -// ignore-cloudabi no std::path - -use std::path::Path; - -trait Foo { - fn bar(&self); -} - -fn some_func(foo: T) { - foo.bar(); -} - -fn f(p: Path) { } -//~^ ERROR the trait bound `[u8]: std::marker::Sized` is not satisfied in `std::path::Path` - -fn main() { - some_func(5i32); - //~^ ERROR the trait bound `i32: Foo` is not satisfied -} diff --git a/src/test/compile-fail/E0282.rs b/src/test/compile-fail/E0282.rs deleted file mode 100644 index dfc702670ce..00000000000 --- a/src/test/compile-fail/E0282.rs +++ /dev/null @@ -1,13 +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. - -fn main() { - let x = "hello".chars().rev().collect(); //~ ERROR E0282 -} diff --git a/src/test/compile-fail/E0283.rs b/src/test/compile-fail/E0283.rs deleted file mode 100644 index 844c47f41b8..00000000000 --- a/src/test/compile-fail/E0283.rs +++ /dev/null @@ -1,29 +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. - -trait Generator { - fn create() -> u32; -} - -struct Impl; - -impl Generator for Impl { - fn create() -> u32 { 1 } -} - -struct AnotherImpl; - -impl Generator for AnotherImpl { - fn create() -> u32 { 2 } -} - -fn main() { - let cont: u32 = Generator::create(); //~ ERROR E0283 -} diff --git a/src/test/compile-fail/E0296.rs b/src/test/compile-fail/E0296.rs deleted file mode 100644 index 562fd00a18a..00000000000 --- a/src/test/compile-fail/E0296.rs +++ /dev/null @@ -1,13 +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. - -#![recursion_limit] //~ ERROR E0296 - -fn main() {} diff --git a/src/test/compile-fail/E0297.rs b/src/test/compile-fail/E0297.rs deleted file mode 100644 index afe4444c7af..00000000000 --- a/src/test/compile-fail/E0297.rs +++ /dev/null @@ -1,16 +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. - -fn main() { - let xs : Vec> = vec![Some(1), None]; - - for Some(x) in xs {} - //~^ ERROR E0005 -} diff --git a/src/test/compile-fail/E0301.rs b/src/test/compile-fail/E0301.rs deleted file mode 100644 index 06e98289b0d..00000000000 --- a/src/test/compile-fail/E0301.rs +++ /dev/null @@ -1,17 +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. - -fn main() { - match Some(()) { - None => { }, - option if option.take().is_none() => {}, //~ ERROR E0301 - Some(_) => { } - } -} diff --git a/src/test/compile-fail/E0302.rs b/src/test/compile-fail/E0302.rs deleted file mode 100644 index 6a5ad40b109..00000000000 --- a/src/test/compile-fail/E0302.rs +++ /dev/null @@ -1,17 +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. - -fn main() { - match Some(()) { - None => { }, - option if { option = None; false } => { }, //~ ERROR E0302 - Some(_) => { } - } -} diff --git a/src/test/compile-fail/E0303.rs b/src/test/compile-fail/E0303.rs deleted file mode 100644 index 6027414fdbd..00000000000 --- a/src/test/compile-fail/E0303.rs +++ /dev/null @@ -1,18 +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. - -fn main() { - match Some("hi".to_string()) { - ref op_string_ref @ Some(s) => {}, - //~^ ERROR pattern bindings are not allowed after an `@` [E0303] - //~| ERROR E0009 - None => {}, - } -} diff --git a/src/test/compile-fail/E0308-4.rs b/src/test/compile-fail/E0308-4.rs deleted file mode 100644 index bb4cd143416..00000000000 --- a/src/test/compile-fail/E0308-4.rs +++ /dev/null @@ -1,17 +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. - -fn main() { - let x = 1u8; - match x { - 0u8...3i8 => (), //~ ERROR E0308 - _ => () - } -} diff --git a/src/test/compile-fail/E0308.rs b/src/test/compile-fail/E0308.rs deleted file mode 100644 index 078f1d3a9a1..00000000000 --- a/src/test/compile-fail/E0308.rs +++ /dev/null @@ -1,18 +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(intrinsics)] - -extern "rust-intrinsic" { - fn size_of(); //~ ERROR E0308 -} - -fn main() { -} diff --git a/src/test/compile-fail/E0365.rs b/src/test/compile-fail/E0365.rs deleted file mode 100644 index 18a72b0ff9a..00000000000 --- a/src/test/compile-fail/E0365.rs +++ /dev/null @@ -1,18 +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. - -mod foo { - pub const X: u32 = 1; -} - -pub use foo as foo2; -//~^ ERROR `foo` is private, and cannot be re-exported [E0365] - -fn main() {} diff --git a/src/test/compile-fail/E0370.rs b/src/test/compile-fail/E0370.rs deleted file mode 100644 index cafe26c65ad..00000000000 --- a/src/test/compile-fail/E0370.rs +++ /dev/null @@ -1,20 +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. - -#![allow(dead_code)] - -#[deny(overflowing_literals)] -#[repr(i64)] -enum Foo { - X = 0x7fffffffffffffff, - Y, //~ ERROR E0370 -} - -fn main() {} diff --git a/src/test/compile-fail/E0374.rs b/src/test/compile-fail/E0374.rs deleted file mode 100644 index 6c4782d230d..00000000000 --- a/src/test/compile-fail/E0374.rs +++ /dev/null @@ -1,21 +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(coerce_unsized)] -use std::ops::CoerceUnsized; - -struct Foo { - a: i32, -} - -impl CoerceUnsized> for Foo //~ ERROR E0374 - where T: CoerceUnsized {} - -fn main() {} diff --git a/src/test/compile-fail/E0375.rs b/src/test/compile-fail/E0375.rs deleted file mode 100644 index 094ed35cc2d..00000000000 --- a/src/test/compile-fail/E0375.rs +++ /dev/null @@ -1,25 +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. - -// ignore-tidy-linelength - -#![feature(coerce_unsized)] -use std::ops::CoerceUnsized; - -struct Foo { - a: i32, - b: T, - c: U, -} - -impl CoerceUnsized> for Foo {} -//~^ ERROR E0375 - -fn main() {} diff --git a/src/test/compile-fail/E0376.rs b/src/test/compile-fail/E0376.rs deleted file mode 100644 index 65be358cc5f..00000000000 --- a/src/test/compile-fail/E0376.rs +++ /dev/null @@ -1,20 +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(coerce_unsized)] -use std::ops::CoerceUnsized; - -struct Foo { - a: T, -} - -impl CoerceUnsized for Foo {} //~ ERROR E0376 - -fn main() {} diff --git a/src/test/compile-fail/E0388.rs b/src/test/compile-fail/E0388.rs deleted file mode 100644 index c002badfef6..00000000000 --- a/src/test/compile-fail/E0388.rs +++ /dev/null @@ -1,19 +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. - -static X: i32 = 1; -const C: i32 = 2; - -const CR: &'static mut i32 = &mut C; //~ ERROR E0017 -static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 - //~| ERROR cannot borrow -static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017 - -fn main() {} diff --git a/src/test/compile-fail/E0389.rs b/src/test/compile-fail/E0389.rs deleted file mode 100644 index 445831bf8d7..00000000000 --- a/src/test/compile-fail/E0389.rs +++ /dev/null @@ -1,20 +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. - -struct FancyNum { - num: u8, -} - -fn main() { - let mut fancy = FancyNum{ num: 5 }; - let fancy_ref = &(&mut fancy); - fancy_ref.num = 6; //~ ERROR E0389 - println!("{}", fancy_ref.num); -} diff --git a/src/test/compile-fail/E0390.rs b/src/test/compile-fail/E0390.rs deleted file mode 100644 index cd530dbd6b4..00000000000 --- a/src/test/compile-fail/E0390.rs +++ /dev/null @@ -1,18 +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. - -struct Foo { - x: i32 -} - -impl *mut Foo {} //~ ERROR E0390 - -fn main() { -} diff --git a/src/test/compile-fail/E0392.rs b/src/test/compile-fail/E0392.rs deleted file mode 100644 index 4c3efcf4e8d..00000000000 --- a/src/test/compile-fail/E0392.rs +++ /dev/null @@ -1,14 +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. - -enum Foo { Bar } //~ ERROR E0392 - -fn main() { -} diff --git a/src/test/compile-fail/E0393.rs b/src/test/compile-fail/E0393.rs deleted file mode 100644 index 9165bc2837b..00000000000 --- a/src/test/compile-fail/E0393.rs +++ /dev/null @@ -1,17 +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. - -trait A {} - -fn together_we_will_rule_the_galaxy(son: &A) {} -//~^ ERROR E0393 - -fn main() { -} diff --git a/src/test/compile-fail/E0394.rs b/src/test/compile-fail/E0394.rs deleted file mode 100644 index dae8e14c5ef..00000000000 --- a/src/test/compile-fail/E0394.rs +++ /dev/null @@ -1,18 +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. - -#![allow(warnings)] - -static A: u32 = 0; -static B: u32 = A; -//~^ ERROR E0394 - -fn main() { -} diff --git a/src/test/compile-fail/E0395.rs b/src/test/compile-fail/E0395.rs deleted file mode 100644 index 00008ea6b6f..00000000000 --- a/src/test/compile-fail/E0395.rs +++ /dev/null @@ -1,16 +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. - -static FOO: i32 = 42; -static BAR: i32 = 42; - -static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR E0395 -fn main() { -} diff --git a/src/test/compile-fail/E0396.rs b/src/test/compile-fail/E0396.rs deleted file mode 100644 index 7f34acdfb90..00000000000 --- a/src/test/compile-fail/E0396.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -const REG_ADDR: *const u8 = 0x5f3759df as *const u8; - -const VALUE: u8 = unsafe { *REG_ADDR }; //~ ERROR E0396 - -fn main() { -} diff --git a/src/test/compile-fail/E0401.rs b/src/test/compile-fail/E0401.rs deleted file mode 100644 index 09bc950efd2..00000000000 --- a/src/test/compile-fail/E0401.rs +++ /dev/null @@ -1,18 +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. - -fn foo(x: T) { - fn bar(y: T) { //~ ERROR E0401 - } - bar(x); -} - -fn main() { -} diff --git a/src/test/compile-fail/E0403.rs b/src/test/compile-fail/E0403.rs deleted file mode 100644 index 6a68013dc6f..00000000000 --- a/src/test/compile-fail/E0403.rs +++ /dev/null @@ -1,14 +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. - -fn foo(s: T, u: T) {} //~ ERROR E0403 - -fn main() { -} diff --git a/src/test/compile-fail/E0404.rs b/src/test/compile-fail/E0404.rs deleted file mode 100644 index 1c088a71d7d..00000000000 --- a/src/test/compile-fail/E0404.rs +++ /dev/null @@ -1,17 +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. - -struct Foo; -struct Bar; - -impl Foo for Bar {} //~ ERROR E0404 - -fn main() { -} diff --git a/src/test/compile-fail/E0405.rs b/src/test/compile-fail/E0405.rs deleted file mode 100644 index 45d4b219ba8..00000000000 --- a/src/test/compile-fail/E0405.rs +++ /dev/null @@ -1,16 +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. - -struct Foo; - -impl SomeTrait for Foo {} //~ ERROR E0405 - -fn main() { -} diff --git a/src/test/compile-fail/E0407.rs b/src/test/compile-fail/E0407.rs deleted file mode 100644 index 41d8b4513ce..00000000000 --- a/src/test/compile-fail/E0407.rs +++ /dev/null @@ -1,24 +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. - -trait Foo { - fn a(); -} - -struct Bar; - -impl Foo for Bar { - fn a() {} - fn b() {} - //~^ ERROR E0407 -} - -fn main() { -} diff --git a/src/test/compile-fail/E0408.rs b/src/test/compile-fail/E0408.rs deleted file mode 100644 index 8ddeb20afdc..00000000000 --- a/src/test/compile-fail/E0408.rs +++ /dev/null @@ -1,18 +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. - -fn main() { - let x = Some(0); - - match x { - Some(y) | None => {} //~ ERROR variable `y` is not bound in all patterns - _ => () - } -} diff --git a/src/test/compile-fail/E0411.rs b/src/test/compile-fail/E0411.rs deleted file mode 100644 index 187986fbadb..00000000000 --- a/src/test/compile-fail/E0411.rs +++ /dev/null @@ -1,13 +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. - -fn main() { - ::foo; //~ ERROR E0411 -} diff --git a/src/test/compile-fail/E0412.rs b/src/test/compile-fail/E0412.rs deleted file mode 100644 index f62901cac31..00000000000 --- a/src/test/compile-fail/E0412.rs +++ /dev/null @@ -1,14 +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. - -impl Something {} //~ ERROR E0412 - -fn main() { -} diff --git a/src/test/compile-fail/E0415.rs b/src/test/compile-fail/E0415.rs deleted file mode 100644 index 2a5f0d3c229..00000000000 --- a/src/test/compile-fail/E0415.rs +++ /dev/null @@ -1,14 +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. - -fn foo(f: i32, f: i32) {} //~ ERROR E0415 - -fn main() { -} diff --git a/src/test/compile-fail/E0416.rs b/src/test/compile-fail/E0416.rs deleted file mode 100644 index 91077ab37f3..00000000000 --- a/src/test/compile-fail/E0416.rs +++ /dev/null @@ -1,15 +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. - -fn main() { - match (1, 2) { - (x, x) => {} //~ ERROR E0416 - } -} diff --git a/src/test/compile-fail/E0423.rs b/src/test/compile-fail/E0423.rs deleted file mode 100644 index f5fea77cf96..00000000000 --- a/src/test/compile-fail/E0423.rs +++ /dev/null @@ -1,15 +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. - -fn main () { - struct Foo { a: bool }; - - let f = Foo(); //~ ERROR E0423 -} diff --git a/src/test/compile-fail/E0424.rs b/src/test/compile-fail/E0424.rs deleted file mode 100644 index 445d0c5f3ed..00000000000 --- a/src/test/compile-fail/E0424.rs +++ /dev/null @@ -1,22 +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. - -struct Foo; - -impl Foo { - fn bar(self) {} - - fn foo() { - self.bar(); //~ ERROR E0424 - } -} - -fn main () { -} diff --git a/src/test/compile-fail/E0425.rs b/src/test/compile-fail/E0425.rs deleted file mode 100644 index 3786282031f..00000000000 --- a/src/test/compile-fail/E0425.rs +++ /dev/null @@ -1,18 +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. - -trait Foo { - fn bar() { - elf; //~ ERROR E0425 - } -} - -fn main () { -} diff --git a/src/test/compile-fail/E0426.rs b/src/test/compile-fail/E0426.rs deleted file mode 100644 index d6261d3a74e..00000000000 --- a/src/test/compile-fail/E0426.rs +++ /dev/null @@ -1,16 +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. - -fn main () { - loop { - break 'a; - //~^ ERROR E0426 - } -} diff --git a/src/test/compile-fail/E0428.rs b/src/test/compile-fail/E0428.rs deleted file mode 100644 index 3c709f3a399..00000000000 --- a/src/test/compile-fail/E0428.rs +++ /dev/null @@ -1,15 +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. - -struct Bar; //~ previous definition of the type `Bar` here -struct Bar; //~ ERROR E0428 - -fn main () { -} diff --git a/src/test/compile-fail/E0429.rs b/src/test/compile-fail/E0429.rs deleted file mode 100644 index f1cad200be6..00000000000 --- a/src/test/compile-fail/E0429.rs +++ /dev/null @@ -1,14 +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 std::fmt::self; //~ ERROR E0429 - -fn main () { -} diff --git a/src/test/compile-fail/E0430.rs b/src/test/compile-fail/E0430.rs deleted file mode 100644 index 992876dd294..00000000000 --- a/src/test/compile-fail/E0430.rs +++ /dev/null @@ -1,15 +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 std::fmt::{self, self}; //~ ERROR E0430 - //~^ ERROR E0252 - -fn main () { -} diff --git a/src/test/compile-fail/E0431.rs b/src/test/compile-fail/E0431.rs deleted file mode 100644 index 09ddc1efaf4..00000000000 --- a/src/test/compile-fail/E0431.rs +++ /dev/null @@ -1,14 +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 {self}; //~ ERROR E0431 - -fn main () { -} diff --git a/src/test/compile-fail/E0432.rs b/src/test/compile-fail/E0432.rs deleted file mode 100644 index 08d699ee4ca..00000000000 --- a/src/test/compile-fail/E0432.rs +++ /dev/null @@ -1,14 +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 something::Foo; //~ ERROR E0432 - -fn main () { -} diff --git a/src/test/compile-fail/E0433.rs b/src/test/compile-fail/E0433.rs deleted file mode 100644 index 916d6220eb9..00000000000 --- a/src/test/compile-fail/E0433.rs +++ /dev/null @@ -1,13 +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. - -fn main () { - let map = HashMap::new(); //~ ERROR E0433 -} diff --git a/src/test/compile-fail/E0434.rs b/src/test/compile-fail/E0434.rs deleted file mode 100644 index 747d9f72c42..00000000000 --- a/src/test/compile-fail/E0434.rs +++ /dev/null @@ -1,19 +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. - -fn foo() { - let y = 5; - fn bar() -> u32 { - y //~ ERROR E0434 - } -} - -fn main () { -} diff --git a/src/test/compile-fail/E0435.rs b/src/test/compile-fail/E0435.rs deleted file mode 100644 index 5246fda6aaf..00000000000 --- a/src/test/compile-fail/E0435.rs +++ /dev/null @@ -1,14 +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. - -fn main () { - let foo = 42u32; - let _: [u8; foo]; //~ ERROR E0435 -} diff --git a/src/test/compile-fail/E0437.rs b/src/test/compile-fail/E0437.rs deleted file mode 100644 index 7440a82773e..00000000000 --- a/src/test/compile-fail/E0437.rs +++ /dev/null @@ -1,18 +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. - -trait Foo {} - -impl Foo for i32 { - type Bar = bool; //~ ERROR E0437 -} - -fn main () { -} diff --git a/src/test/compile-fail/E0438.rs b/src/test/compile-fail/E0438.rs deleted file mode 100644 index 61d25134993..00000000000 --- a/src/test/compile-fail/E0438.rs +++ /dev/null @@ -1,19 +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. - - -trait Bar {} - -impl Bar for i32 { - const BAR: bool = true; //~ ERROR E0438 -} - -fn main () { -} diff --git a/src/test/compile-fail/E0439.rs b/src/test/compile-fail/E0439.rs deleted file mode 100644 index 52443432021..00000000000 --- a/src/test/compile-fail/E0439.rs +++ /dev/null @@ -1,18 +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(platform_intrinsics)] - -extern "platform-intrinsic" { - fn simd_shuffle(a: A, b: A, c: [u32; 8]) -> B; //~ ERROR E0439 -} - -fn main () { -} diff --git a/src/test/compile-fail/E0440.rs b/src/test/compile-fail/E0440.rs deleted file mode 100644 index 04e7584008d..00000000000 --- a/src/test/compile-fail/E0440.rs +++ /dev/null @@ -1,22 +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(repr_simd)] -#![feature(platform_intrinsics)] - -#[repr(simd)] -struct f64x2(f64, f64); - -extern "platform-intrinsic" { - fn x86_mm_movemask_pd(x: f64x2) -> i32; //~ ERROR E0440 -} - -fn main () { -} diff --git a/src/test/compile-fail/E0441.rs b/src/test/compile-fail/E0441.rs deleted file mode 100644 index 967ff643272..00000000000 --- a/src/test/compile-fail/E0441.rs +++ /dev/null @@ -1,21 +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(repr_simd)] -#![feature(platform_intrinsics)] - -#[repr(simd)] -struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16); - -extern "platform-intrinsic" { - fn x86_mm_adds_ep16(x: i16x8, y: i16x8) -> i16x8; //~ ERROR E0441 -} - -fn main() {} diff --git a/src/test/compile-fail/E0442.rs b/src/test/compile-fail/E0442.rs deleted file mode 100644 index ddd927054be..00000000000 --- a/src/test/compile-fail/E0442.rs +++ /dev/null @@ -1,29 +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(repr_simd)] -#![feature(platform_intrinsics)] - -#[repr(simd)] -struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8, - i8, i8, i8, i8, i8, i8, i8, i8); -#[repr(simd)] -struct i32x4(i32, i32, i32, i32); -#[repr(simd)] -struct i64x2(i64, i64); - -extern "platform-intrinsic" { - fn x86_mm_adds_epi16(x: i8x16, y: i32x4) -> i64x2; - //~^ ERROR E0442 - //~| ERROR E0442 - //~| ERROR E0442 -} - -fn main() {} diff --git a/src/test/compile-fail/E0443.rs b/src/test/compile-fail/E0443.rs deleted file mode 100644 index 24d1ee01dd4..00000000000 --- a/src/test/compile-fail/E0443.rs +++ /dev/null @@ -1,23 +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(repr_simd)] -#![feature(platform_intrinsics)] - -#[repr(simd)] -struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16); -#[repr(simd)] -struct i64x8(i64, i64, i64, i64, i64, i64, i64, i64); - -extern "platform-intrinsic" { - fn x86_mm_adds_epi16(x: i16x8, y: i16x8) -> i64x8; //~ ERROR E0443 -} - -fn main() {} diff --git a/src/test/compile-fail/E0444.rs b/src/test/compile-fail/E0444.rs deleted file mode 100644 index a424a3ca20e..00000000000 --- a/src/test/compile-fail/E0444.rs +++ /dev/null @@ -1,21 +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(repr_simd)] -#![feature(platform_intrinsics)] - -#[repr(simd)] -struct f64x2(f64, f64); - -extern "platform-intrinsic" { - fn x86_mm_movemask_pd(x: f64x2, y: f64x2, z: f64x2) -> i32; //~ ERROR E0444 -} - -fn main() {} diff --git a/src/test/compile-fail/E0445.rs b/src/test/compile-fail/E0445.rs deleted file mode 100644 index bca1b52d17a..00000000000 --- a/src/test/compile-fail/E0445.rs +++ /dev/null @@ -1,25 +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. - -trait Foo { - fn dummy(&self) { } -} - -pub trait Bar : Foo {} -//~^ ERROR private trait `Foo` in public interface [E0445] -//~| NOTE can't leak private trait -pub struct Bar2(pub T); -//~^ ERROR private trait `Foo` in public interface [E0445] -//~| NOTE can't leak private trait -pub fn foo (t: T) {} -//~^ ERROR private trait `Foo` in public interface [E0445] -//~| NOTE can't leak private trait - -fn main() {} diff --git a/src/test/compile-fail/E0446.rs b/src/test/compile-fail/E0446.rs deleted file mode 100644 index c5766618284..00000000000 --- a/src/test/compile-fail/E0446.rs +++ /dev/null @@ -1,19 +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. - -mod Foo { - struct Bar(u32); - - pub fn bar() -> Bar { //~ ERROR E0446 - Bar(0) - } -} - -fn main() {} diff --git a/src/test/compile-fail/E0449.rs b/src/test/compile-fail/E0449.rs deleted file mode 100644 index ac365db33e5..00000000000 --- a/src/test/compile-fail/E0449.rs +++ /dev/null @@ -1,24 +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. - -struct Bar; - -trait Foo { - fn foo(); -} - -pub impl Bar {} //~ ERROR E0449 - -pub impl Foo for Bar { //~ ERROR E0449 - pub fn foo() {} //~ ERROR E0449 -} - -fn main() { -} diff --git a/src/test/compile-fail/E0451.rs b/src/test/compile-fail/E0451.rs deleted file mode 100644 index af4e7d628bb..00000000000 --- a/src/test/compile-fail/E0451.rs +++ /dev/null @@ -1,29 +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. - -mod Bar { - pub struct Foo { - pub a: isize, - b: isize, - } - - pub struct FooTuple ( - pub isize, - isize, - ); -} - -fn pat_match(foo: Bar::Foo) { - let Bar::Foo{a:a, b:b} = foo; //~ ERROR E0451 -} - -fn main() { - let f = Bar::Foo{ a: 0, b: 0 }; //~ ERROR E0451 -} diff --git a/src/test/compile-fail/E0452.rs b/src/test/compile-fail/E0452.rs deleted file mode 100644 index 1665bbdd4c2..00000000000 --- a/src/test/compile-fail/E0452.rs +++ /dev/null @@ -1,14 +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. - -#![allow(foo = "")] //~ ERROR E0452 - -fn main() { -} diff --git a/src/test/compile-fail/E0453.rs b/src/test/compile-fail/E0453.rs deleted file mode 100644 index 8e51b84bab8..00000000000 --- a/src/test/compile-fail/E0453.rs +++ /dev/null @@ -1,16 +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. - -#![forbid(non_snake_case)] - -#[allow(non_snake_case)] -//~^ ERROR allow(non_snake_case) overruled by outer forbid(non_snake_case) -fn main() { -} diff --git a/src/test/compile-fail/E0454.rs b/src/test/compile-fail/E0454.rs deleted file mode 100644 index afd0f5f5e46..00000000000 --- a/src/test/compile-fail/E0454.rs +++ /dev/null @@ -1,15 +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. - -#[link(name = "")] extern {} -//~^ ERROR E0454 - -fn main() { -} diff --git a/src/test/compile-fail/E0458.rs b/src/test/compile-fail/E0458.rs deleted file mode 100644 index fea27ef8115..00000000000 --- a/src/test/compile-fail/E0458.rs +++ /dev/null @@ -1,15 +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. - -#[link(kind = "wonderful_unicorn")] extern {} //~ ERROR E0458 - //~| ERROR E0459 - -fn main() { -} diff --git a/src/test/compile-fail/E0459.rs b/src/test/compile-fail/E0459.rs deleted file mode 100644 index dc7ac714f22..00000000000 --- a/src/test/compile-fail/E0459.rs +++ /dev/null @@ -1,14 +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. - -#[link(kind = "dylib")] extern {} //~ ERROR E0459 - -fn main() { -} diff --git a/src/test/compile-fail/E0463.rs b/src/test/compile-fail/E0463.rs deleted file mode 100644 index aae83975b22..00000000000 --- a/src/test/compile-fail/E0463.rs +++ /dev/null @@ -1,17 +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(plugin)] -#![plugin(cookie_monster)] -//~^ ERROR E0463 -extern crate cake_is_a_lie; - -fn main() { -} diff --git a/src/test/compile-fail/E0478.rs b/src/test/compile-fail/E0478.rs deleted file mode 100644 index 8eb4003fc97..00000000000 --- a/src/test/compile-fail/E0478.rs +++ /dev/null @@ -1,18 +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. - -trait Wedding<'t>: 't { } - -struct Prince<'kiss, 'SnowWhite> { - child: Box + 'SnowWhite>, //~ ERROR E0478 -} - -fn main() { -} diff --git a/src/test/compile-fail/E0492.rs b/src/test/compile-fail/E0492.rs deleted file mode 100644 index 8e4964c97c5..00000000000 --- a/src/test/compile-fail/E0492.rs +++ /dev/null @@ -1,17 +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 std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT}; - -const A: AtomicUsize = ATOMIC_USIZE_INIT; -static B: &'static AtomicUsize = &A; //~ ERROR E0492 - -fn main() { -} diff --git a/src/test/compile-fail/E0494.rs b/src/test/compile-fail/E0494.rs deleted file mode 100644 index 5f8632ac1c2..00000000000 --- a/src/test/compile-fail/E0494.rs +++ /dev/null @@ -1,19 +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. - -struct Foo { - a: u32 -} - -static S : Foo = Foo { a : 0 }; -static A : &'static u32 = &S.a; //~ ERROR E0494 - -fn main() { -} diff --git a/src/test/compile-fail/E0496.rs b/src/test/compile-fail/E0496.rs deleted file mode 100644 index 4ca3cd9c13d..00000000000 --- a/src/test/compile-fail/E0496.rs +++ /dev/null @@ -1,21 +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. - -struct Foo<'a> { - a: &'a i32, -} - -impl<'a> Foo<'a> { - fn f<'a>(x: &'a i32) { //~ ERROR E0496 - } -} - -fn main() { -} diff --git a/src/test/compile-fail/E0499.rs b/src/test/compile-fail/E0499.rs deleted file mode 100644 index 9a64bfe2ea9..00000000000 --- a/src/test/compile-fail/E0499.rs +++ /dev/null @@ -1,15 +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. - -fn main() { - let mut i = 0; - let mut x = &mut i; - let mut a = &mut i; //~ ERROR E0499 -} diff --git a/src/test/compile-fail/E0502.rs b/src/test/compile-fail/E0502.rs deleted file mode 100644 index fce8513ca64..00000000000 --- a/src/test/compile-fail/E0502.rs +++ /dev/null @@ -1,18 +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. - -fn bar(x: &mut i32) {} -fn foo(a: &mut i32) { - let ref y = a; - bar(a); //~ ERROR E0502 -} - -fn main() { -} diff --git a/src/test/compile-fail/E0503.rs b/src/test/compile-fail/E0503.rs deleted file mode 100644 index 810eb8d9b07..00000000000 --- a/src/test/compile-fail/E0503.rs +++ /dev/null @@ -1,15 +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. - -fn main() { - let mut value = 3; - let _borrow = &mut value; - let _sum = value + 1; //~ ERROR E0503 -} diff --git a/src/test/compile-fail/E0504.rs b/src/test/compile-fail/E0504.rs deleted file mode 100644 index c594f241520..00000000000 --- a/src/test/compile-fail/E0504.rs +++ /dev/null @@ -1,25 +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. - -struct FancyNum { - num: u8, -} - -fn main() { - let fancy_num = FancyNum { num: 5 }; - let fancy_ref = &fancy_num; - - let x = move || { - println!("child function: {}", fancy_num.num); //~ ERROR E0504 - }; - - x(); - println!("main function: {}", fancy_ref.num); -} diff --git a/src/test/compile-fail/E0505.rs b/src/test/compile-fail/E0505.rs deleted file mode 100644 index 2d534b8a44a..00000000000 --- a/src/test/compile-fail/E0505.rs +++ /dev/null @@ -1,21 +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. - -struct Value {} - -fn eat(val: Value) {} - -fn main() { - let x = Value{}; - { - let _ref_to_val: &Value = &x; - eat(x); //~ ERROR E0505 - } -} diff --git a/src/test/compile-fail/E0507.rs b/src/test/compile-fail/E0507.rs deleted file mode 100644 index 87b1bf51bdb..00000000000 --- a/src/test/compile-fail/E0507.rs +++ /dev/null @@ -1,23 +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 std::cell::RefCell; - -struct TheDarkKnight; - -impl TheDarkKnight { - fn nothing_is_true(self) {} -} - -fn main() { - let x = RefCell::new(TheDarkKnight); - - x.borrow().nothing_is_true(); //~ ERROR E0507 -} diff --git a/src/test/compile-fail/E0509.rs b/src/test/compile-fail/E0509.rs deleted file mode 100644 index b92024cd6e2..00000000000 --- a/src/test/compile-fail/E0509.rs +++ /dev/null @@ -1,28 +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. - -struct FancyNum { - num: usize -} - -struct DropStruct { - fancy: FancyNum -} - -impl Drop for DropStruct { - fn drop(&mut self) { - } -} - -fn main() { - let drop_struct = DropStruct{fancy: FancyNum{num: 5}}; - let fancy_field = drop_struct.fancy; //~ ERROR E0509 - println!("Fancy: {}", fancy_field.num); -} diff --git a/src/test/compile-fail/E0511.rs b/src/test/compile-fail/E0511.rs deleted file mode 100644 index c5c03f81825..00000000000 --- a/src/test/compile-fail/E0511.rs +++ /dev/null @@ -1,19 +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(platform_intrinsics)] - -extern "platform-intrinsic" { - fn simd_add(a: T, b: T) -> T; -} - -fn main() { - unsafe { simd_add(0, 1); } //~ ERROR E0511 -} diff --git a/src/test/compile-fail/E0512.rs b/src/test/compile-fail/E0512.rs deleted file mode 100644 index 25f96271641..00000000000 --- a/src/test/compile-fail/E0512.rs +++ /dev/null @@ -1,15 +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. - -fn takes_u8(_: u8) {} - -fn main() { - unsafe { takes_u8(::std::mem::transmute(0u16)); } //~ ERROR E0512 -} diff --git a/src/test/compile-fail/E0516.rs b/src/test/compile-fail/E0516.rs deleted file mode 100644 index be2b89c5f39..00000000000 --- a/src/test/compile-fail/E0516.rs +++ /dev/null @@ -1,14 +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. - -fn main() { - let x: typeof(92) = 92; //~ ERROR E0516 - //~| reserved keyword -} diff --git a/src/test/compile-fail/E0517.rs b/src/test/compile-fail/E0517.rs deleted file mode 100644 index 561223ccdf1..00000000000 --- a/src/test/compile-fail/E0517.rs +++ /dev/null @@ -1,25 +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. - -#[repr(C)] //~ ERROR: E0517 -type Foo = u8; - -#[repr(packed)] //~ ERROR: E0517 -enum Foo2 {Bar, Baz} - -#[repr(u8)] //~ ERROR: E0517 -struct Foo3 {bar: bool, baz: bool} - -#[repr(C)] //~ ERROR: E0517 -impl Foo3 { -} - -fn main() { -} diff --git a/src/test/compile-fail/E0518.rs b/src/test/compile-fail/E0518.rs deleted file mode 100644 index 6d5b6e48e0d..00000000000 --- a/src/test/compile-fail/E0518.rs +++ /dev/null @@ -1,19 +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. - -#[inline(always)] //~ ERROR: E0518 -struct Foo; - -#[inline(never)] //~ ERROR: E0518 -impl Foo { -} - -fn main() { -} diff --git a/src/test/compile-fail/E0520.rs b/src/test/compile-fail/E0520.rs deleted file mode 100644 index eae5b11a819..00000000000 --- a/src/test/compile-fail/E0520.rs +++ /dev/null @@ -1,31 +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(specialization)] - -trait SpaceLlama { - fn fly(&self); -} - -impl SpaceLlama for T { - default fn fly(&self) {} -} - -impl SpaceLlama for T { - fn fly(&self) {} -} - -impl SpaceLlama for i32 { - default fn fly(&self) {} - //~^ ERROR E0520 -} - -fn main() { -} diff --git a/src/test/compile-fail/E0522.rs b/src/test/compile-fail/E0522.rs deleted file mode 100644 index 3d437785346..00000000000 --- a/src/test/compile-fail/E0522.rs +++ /dev/null @@ -1,17 +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(lang_items)] - -#[lang = "cookie"] -fn cookie() -> ! { -//~^^ ERROR definition of an unknown language item: `cookie` [E0522] - loop {} -} diff --git a/src/test/compile-fail/E0527.rs b/src/test/compile-fail/E0527.rs deleted file mode 100644 index 67d222e867e..00000000000 --- a/src/test/compile-fail/E0527.rs +++ /dev/null @@ -1,21 +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(slice_patterns)] - -fn main() { - let r = &[1, 2, 3, 4]; - match r { - &[a, b] => { - //~^ ERROR E0527 - println!("a={}, b={}", a, b); - } - } -} diff --git a/src/test/compile-fail/E0528.rs b/src/test/compile-fail/E0528.rs deleted file mode 100644 index e2aa2c067cb..00000000000 --- a/src/test/compile-fail/E0528.rs +++ /dev/null @@ -1,20 +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(slice_patterns)] - -fn main() { - let r = &[1, 2]; - match r { - &[a, b, c, rest..] => { - //~^ ERROR E0528 - } - } -} diff --git a/src/test/compile-fail/E0529.rs b/src/test/compile-fail/E0529.rs deleted file mode 100644 index 5262ad7b716..00000000000 --- a/src/test/compile-fail/E0529.rs +++ /dev/null @@ -1,20 +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(slice_patterns)] - -fn main() { - let r: f32 = 1.0; - match r { - [a, b] => { - //~^ ERROR E0529 - } - } -} diff --git a/src/test/compile-fail/E0530.rs b/src/test/compile-fail/E0530.rs deleted file mode 100644 index 4f674d0e671..00000000000 --- a/src/test/compile-fail/E0530.rs +++ /dev/null @@ -1,18 +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. - -fn main() { - static TEST: i32 = 0; - - let r: (i32, i32) = (0, 0); - match r { - TEST => {} //~ ERROR E0530 - } -} diff --git a/src/test/compile-fail/E0532.rs b/src/test/compile-fail/E0532.rs deleted file mode 100644 index 5dc3b5f94f3..00000000000 --- a/src/test/compile-fail/E0532.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn main() { - let value = 1; - - match SomeStruct(value) { - StructConst1(_) => { }, - //~^ ERROR expected tuple struct/variant, found constant `StructConst1` - _ => { }, - } - - struct SomeStruct(u8); - - const StructConst1 : SomeStruct = SomeStruct(1); - const StructConst2 : SomeStruct = SomeStruct(2); -} diff --git a/src/test/compile-fail/E0534.rs b/src/test/compile-fail/E0534.rs deleted file mode 100644 index fc465b26869..00000000000 --- a/src/test/compile-fail/E0534.rs +++ /dev/null @@ -1,16 +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. - -#[inline()] //~ ERROR E0534 -pub fn something() {} - -fn main() { - something(); -} diff --git a/src/test/compile-fail/E0558.rs b/src/test/compile-fail/E0558.rs deleted file mode 100644 index 64a6ee4cf58..00000000000 --- a/src/test/compile-fail/E0558.rs +++ /dev/null @@ -1,16 +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. - -#[export_name] -//~^ ERROR E0558 - -pub fn something() {} - -fn main() {} diff --git a/src/test/compile-fail/E0559.rs b/src/test/compile-fail/E0559.rs deleted file mode 100644 index da0f692cc28..00000000000 --- a/src/test/compile-fail/E0559.rs +++ /dev/null @@ -1,18 +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. - -enum Field { - Fool { x: u32 }, -} - -fn main() { - let s = Field::Fool { joke: 0 }; - //~^ ERROR E0559 -} diff --git a/src/test/compile-fail/E0560.rs b/src/test/compile-fail/E0560.rs deleted file mode 100644 index bbb7f08d62e..00000000000 --- a/src/test/compile-fail/E0560.rs +++ /dev/null @@ -1,18 +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. - -struct Simba { - mother: u32, -} - -fn main() { - let s = Simba { mother: 1, father: 0 }; - //~^ ERROR E0560 -} diff --git a/src/test/compile-fail/E0565-1.rs b/src/test/compile-fail/E0565-1.rs deleted file mode 100644 index d3e68c7c0da..00000000000 --- a/src/test/compile-fail/E0565-1.rs +++ /dev/null @@ -1,17 +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(attr_literals)] - -// deprecated doesn't currently support literals -#[deprecated("since")] //~ ERROR E0565 -fn f() { } - -fn main() { } diff --git a/src/test/compile-fail/E0565.rs b/src/test/compile-fail/E0565.rs deleted file mode 100644 index b2d369223e7..00000000000 --- a/src/test/compile-fail/E0565.rs +++ /dev/null @@ -1,17 +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(attr_literals)] - -// repr currently doesn't support literals -#[repr("C")] //~ ERROR E0565 -struct A { } - -fn main() { } diff --git a/src/test/compile-fail/E0572.rs b/src/test/compile-fail/E0572.rs deleted file mode 100644 index bbaab102de7..00000000000 --- a/src/test/compile-fail/E0572.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -const FOO: u32 = return 0; //~ ERROR E0572 - -fn main() {} diff --git a/src/test/compile-fail/E0582.rs b/src/test/compile-fail/E0582.rs deleted file mode 100644 index 5e6f65a18f4..00000000000 --- a/src/test/compile-fail/E0582.rs +++ /dev/null @@ -1,52 +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. - -// This test was derived from the wasm and parsell crates. They -// stopped compiling when #32330 is fixed. - -#![allow(dead_code, unused_variables)] - -use std::str::Chars; - -pub trait HasOutput { - type Output; -} - -#[derive(Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Debug)] -pub enum Token<'a> { - Begin(&'a str) -} - -fn mk_unexpected_char_err<'a>() -> Option<&'a i32> { - unimplemented!() -} - -fn foo<'a>(data: &mut Chars<'a>) { - bar(mk_unexpected_char_err) -} - -fn bar(t: F) - // No type can satisfy this requirement, since `'a` does not - // appear in any of the input types: - where F: for<'a> Fn() -> Option<&'a i32> - //~^ ERROR E0582 -{ -} - -fn baz(t: F) - // No type can satisfy this requirement, since `'a` does not - // appear in any of the input types: - where F: for<'a> Iterator - //~^ ERROR E0582 -{ -} - -fn main() { -} diff --git a/src/test/compile-fail/E0585.rs b/src/test/compile-fail/E0585.rs deleted file mode 100644 index 1acaf8c0b78..00000000000 --- a/src/test/compile-fail/E0585.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn main() { - /// Hello! I'm useless... - //~^ ERROR E0585 -} diff --git a/src/test/compile-fail/E0586.rs b/src/test/compile-fail/E0586.rs deleted file mode 100644 index c1bfc5c73a1..00000000000 --- a/src/test/compile-fail/E0586.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn main() { - let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; - let x = &tmp[1..=]; //~ ERROR E0586 -} diff --git a/src/test/compile-fail/E0597.rs b/src/test/compile-fail/E0597.rs deleted file mode 100644 index 2f4a1da91d8..00000000000 --- a/src/test/compile-fail/E0597.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo<'a> { - x: Option<&'a u32>, -} - -fn main() { - let mut x = Foo { x: None }; - let y = 0; - x.x = Some(&y); - //~^ `y` does not live long enough [E0597] -} diff --git a/src/test/compile-fail/E0599.rs b/src/test/compile-fail/E0599.rs deleted file mode 100644 index 30fca2bac03..00000000000 --- a/src/test/compile-fail/E0599.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo; - -fn main() { - || if let Foo::NotEvenReal() = Foo {}; //~ ERROR E0599 -} diff --git a/src/test/compile-fail/E0600.rs b/src/test/compile-fail/E0600.rs deleted file mode 100644 index 5457ff26608..00000000000 --- a/src/test/compile-fail/E0600.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn main() { - !"a"; //~ ERROR E0600 -} diff --git a/src/test/compile-fail/E0602.rs b/src/test/compile-fail/E0602.rs deleted file mode 100644 index cc3e436d433..00000000000 --- a/src/test/compile-fail/E0602.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// 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/E0603.rs b/src/test/compile-fail/E0603.rs deleted file mode 100644 index 1cc9f6bfa7d..00000000000 --- a/src/test/compile-fail/E0603.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod SomeModule { - const PRIVATE: u32 = 0x_a_bad_1dea_u32; -} - -fn main() { - SomeModule::PRIVATE; //~ ERROR E0603 -} diff --git a/src/test/compile-fail/E0604.rs b/src/test/compile-fail/E0604.rs deleted file mode 100644 index c5bf3a77b6c..00000000000 --- a/src/test/compile-fail/E0604.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn main() { - 1u32 as char; //~ ERROR E0604 -} diff --git a/src/test/compile-fail/E0605.rs b/src/test/compile-fail/E0605.rs deleted file mode 100644 index 4b5b8beb368..00000000000 --- a/src/test/compile-fail/E0605.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn main() { - let x = 0u8; - x as Vec; //~ ERROR E0605 - - let v = 0 as *const u8; - v as &u8; //~ ERROR E0605 -} diff --git a/src/test/compile-fail/E0606.rs b/src/test/compile-fail/E0606.rs deleted file mode 100644 index 55071736bfe..00000000000 --- a/src/test/compile-fail/E0606.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn main() { - &0u8 as u8; //~ ERROR E0606 -} diff --git a/src/test/compile-fail/E0607.rs b/src/test/compile-fail/E0607.rs deleted file mode 100644 index fa761f2c178..00000000000 --- a/src/test/compile-fail/E0607.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -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 deleted file mode 100644 index d47356a97ee..00000000000 --- a/src/test/compile-fail/E0608.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn main() { - 0u8[2]; //~ ERROR E0608 -} diff --git a/src/test/compile-fail/E0609.rs b/src/test/compile-fail/E0609.rs deleted file mode 100644 index ddfd9d5f21a..00000000000 --- a/src/test/compile-fail/E0609.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -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 deleted file mode 100644 index 522d8b0b943..00000000000 --- a/src/test/compile-fail/E0610.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -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 deleted file mode 100644 index 1e392d194b1..00000000000 --- a/src/test/compile-fail/E0611.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -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 deleted file mode 100644 index 429a8bb7eb7..00000000000 --- a/src/test/compile-fail/E0612.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -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 deleted file mode 100644 index 909f0eb8285..00000000000 --- a/src/test/compile-fail/E0614.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn main() { - let y = 0u32; - *y; //~ ERROR E0614 -} diff --git a/src/test/compile-fail/E0615.rs b/src/test/compile-fail/E0615.rs deleted file mode 100644 index abfa93d2fd0..00000000000 --- a/src/test/compile-fail/E0615.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -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 deleted file mode 100644 index 2fd9f94763d..00000000000 --- a/src/test/compile-fail/E0616.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -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 deleted file mode 100644 index 9375fd9cade..00000000000 --- a/src/test/compile-fail/E0617.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// 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 - //~| HELP cast the value to `c_double` - printf(::std::ptr::null(), 0i8); - //~^ ERROR can't pass `i8` to variadic function - //~| HELP cast the value to `c_int` - printf(::std::ptr::null(), 0i16); - //~^ ERROR can't pass `i16` to variadic function - //~| HELP cast the value to `c_int` - printf(::std::ptr::null(), 0u8); - //~^ ERROR can't pass `u8` to variadic function - //~| HELP cast the value to `c_uint` - printf(::std::ptr::null(), 0u16); - //~^ ERROR can't pass `u16` to variadic function - //~| HELP cast the value to `c_uint` - printf(::std::ptr::null(), printf); - //~^ ERROR can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function - //~| HELP cast the value to `unsafe extern "C" fn(*const i8, ...)` - } -} diff --git a/src/test/compile-fail/E0618.rs b/src/test/compile-fail/E0618.rs deleted file mode 100644 index f46bdb99801..00000000000 --- a/src/test/compile-fail/E0618.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum X { - Entry, -} - -fn main() { - X::Entry(); - //~^ ERROR expected function, found enum variant `X::Entry` [E0618] - 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 deleted file mode 100644 index a5a5ff7218d..00000000000 --- a/src/test/compile-fail/E0619.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn main() { - let x; - - match x { - (..) => {} //~ ERROR E0619 - _ => {} - } -} - diff --git a/src/test/compile-fail/E0620.rs b/src/test/compile-fail/E0620.rs deleted file mode 100644 index 5e945dfa5c8..00000000000 --- a/src/test/compile-fail/E0620.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -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 deleted file mode 100644 index 980461bedae..00000000000 --- a/src/test/compile-fail/E0621-does-not-trigger-for-closures.rs +++ /dev/null @@ -1,28 +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. - -// 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/E0622.rs b/src/test/compile-fail/E0622.rs deleted file mode 100644 index f2bde5b0364..00000000000 --- a/src/test/compile-fail/E0622.rs +++ /dev/null @@ -1,16 +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. - -#![feature(intrinsics)] -extern "rust-intrinsic" { - pub static breakpoint : unsafe extern "rust-intrinsic" fn(); - //~^ ERROR intrinsic must be a function [E0622] -} -fn main() { unsafe { breakpoint(); } } diff --git a/src/test/compile-fail/E0624.rs b/src/test/compile-fail/E0624.rs deleted file mode 100644 index 952e0b31c4c..00000000000 --- a/src/test/compile-fail/E0624.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod inner { - pub struct Foo; - - impl Foo { - fn method(&self) {} - } -} - -fn main() { - let foo = inner::Foo; - foo.method(); //~ ERROR method `method` is private [E0624] -} diff --git a/src/test/compile-fail/E0637.rs b/src/test/compile-fail/E0637.rs deleted file mode 100644 index 455529b088a..00000000000 --- a/src/test/compile-fail/E0637.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -#![feature(underscore_lifetimes)] - -struct Foo<'a: '_>(&'a u8); //~ ERROR invalid lifetime bound name: `'_` -fn foo<'a: '_>(_: &'a u8) {} //~ ERROR invalid lifetime bound name: `'_` - -struct Bar<'a>(&'a u8); -impl<'a: '_> Bar<'a> { //~ ERROR invalid lifetime bound name: `'_` - fn bar() {} -} - -fn main() {} diff --git a/src/test/compile-fail/E0657.rs b/src/test/compile-fail/E0657.rs deleted file mode 100644 index 4595e413081..00000000000 --- a/src/test/compile-fail/E0657.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -#![allow(warnings)] -#![feature(conservative_impl_trait, nested_impl_trait)] - -trait Id {} -trait Lt<'a> {} - -impl<'a> Lt<'a> for () {} -impl Id for T {} - -fn free_fn_capture_hrtb_in_impl_trait() - -> impl for<'a> Id> - //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level [E0657] -{ - () -} - -struct Foo; -impl Foo { - fn impl_fn_capture_hrtb_in_impl_trait() - -> impl for<'a> Id> - //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level - { - () - } -} - -fn main() {} diff --git a/src/test/compile-fail/E0658.rs b/src/test/compile-fail/E0658.rs deleted file mode 100644 index d30068eb1fe..00000000000 --- a/src/test/compile-fail/E0658.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn main() { - let _ = ::std::u128::MAX; //~ ERROR E0658 -} diff --git a/src/test/compile-fail/E0659.rs b/src/test/compile-fail/E0659.rs deleted file mode 100644 index 4bd452b0aac..00000000000 --- a/src/test/compile-fail/E0659.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod moon { - pub fn foo() {} -} - -mod earth { - pub fn foo() {} -} - -mod collider { - pub use moon::*; - pub use earth::*; -} - -fn main() { - collider::foo(); //~ ERROR E0659 -} diff --git a/src/test/compile-fail/absolute-paths-in-nested-use-groups.rs b/src/test/compile-fail/absolute-paths-in-nested-use-groups.rs index 8e5ba489c56..fe052f2f47f 100644 --- a/src/test/compile-fail/absolute-paths-in-nested-use-groups.rs +++ b/src/test/compile-fail/absolute-paths-in-nested-use-groups.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(use_nested_groups)] #![allow(unused_imports)] mod 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 52bb4a1b463..630a234fa66 100644 --- a/src/test/compile-fail/associated-const-type-parameter-arms.rs +++ b/src/test/compile-fail/associated-const-type-parameter-arms.rs @@ -16,6 +16,7 @@ pub trait Foo { } struct Abc; + impl Foo for Abc { const X: EFoo = EFoo::B; } @@ -27,8 +28,10 @@ impl Foo for Def { pub fn test(arg: EFoo) { match arg { - A::X => println!("A::X"), //~ error: statics cannot be referenced in patterns [E0158] - B::X => println!("B::X"), //~ error: statics cannot be referenced in patterns [E0158] + A::X => println!("A::X"), + //~^ error: associated consts cannot be referenced in patterns [E0158] + B::X => println!("B::X"), + //~^ error: associated consts cannot be referenced in patterns [E0158] _ => (), } } diff --git a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs index 062cc976a3d..1d08b807465 100644 --- a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs +++ b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs @@ -72,7 +72,7 @@ fn main() { { let mut e = Baz::X(2); let _e0 = e.x(); - match e { + match e { //[mir]~ ERROR cannot use `e` because it was mutably borrowed Baz::X(value) => value //[ast]~^ ERROR cannot use `e.0` because it was mutably borrowed //[mir]~^^ ERROR cannot use `e.0` because it was mutably borrowed @@ -110,7 +110,7 @@ fn main() { { let mut e = Box::new(Baz::X(3)); let _e0 = e.x(); - match *e { + match *e { //[mir]~ ERROR cannot use `*e` because it was mutably borrowed Baz::X(value) => value //[ast]~^ ERROR cannot use `e.0` because it was mutably borrowed //[mir]~^^ ERROR cannot use `e.0` because it was mutably borrowed @@ -127,25 +127,25 @@ fn main() { { let mut v = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let _v = &mut v; - match v { + match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed &[x, _, .., _, _] => println!("{}", x), //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed _ => panic!("other case"), } - match v { + match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed &[_, x, .., _, _] => println!("{}", x), //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed _ => panic!("other case"), } - match v { + match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed &[_, _, .., x, _] => println!("{}", x), //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed _ => panic!("other case"), } - match v { + match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed &[_, _, .., _, x] => println!("{}", x), //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed @@ -156,25 +156,25 @@ fn main() { { let mut v = &[1, 2, 3, 4, 5]; let _v = &mut v; - match v { + match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed &[x..] => println!("{:?}", x), //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed _ => panic!("other case"), } - match v { + match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed &[_, x..] => println!("{:?}", x), //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed _ => panic!("other case"), } - match v { + match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed &[x.., _] => println!("{:?}", x), //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed _ => panic!("other case"), } - match v { + match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed &[_, x.., _] => println!("{:?}", x), //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed @@ -187,7 +187,7 @@ enum E { A(X), B { x: X } } let mut e = E::A(3); let _e = &mut e; - match e { + match e { //[mir]~ ERROR cannot use `e` because it was mutably borrowed E::A(ref ax) => //[ast]~^ ERROR cannot borrow `e.0` as immutable because `e` is also borrowed as mutable //[mir]~^^ ERROR cannot borrow `e.0` as immutable because it is also borrowed as mutable @@ -205,14 +205,14 @@ enum E { A(X), B { x: X } } struct S { x: F, y: (u32, u32), }; let mut s = S { x: F { x: 1, y: 2}, y: (999, 998) }; let _s = &mut s; - match s { + match s { //[mir]~ ERROR cannot use `s` because it was mutably borrowed S { y: (ref y0, _), .. } => //[ast]~^ ERROR cannot borrow `s.y.0` as immutable because `s` is also borrowed as mutable //[mir]~^^ ERROR cannot borrow `s.y.0` as immutable because it is also borrowed as mutable println!("y0: {:?}", y0), _ => panic!("other case"), } - match s { + match s { //[mir]~ ERROR cannot use `s` because it was mutably borrowed S { x: F { y: ref x0, .. }, .. } => //[ast]~^ ERROR cannot borrow `s.x.y` as immutable because `s` is also borrowed as mutable //[mir]~^^ ERROR cannot borrow `s.x.y` as immutable because it is also borrowed as mutable @@ -263,7 +263,7 @@ unsafe fn bump2(mut block: *mut Block2) { struct F {x: u32, y: u32}; let mut v = &[F{x: 1, y: 2}, F{x: 3, y: 4}]; let _v = &mut v; - match v { + match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed &[_, F {x: ref xf, ..}] => println!("{}", xf), //[mir]~^ ERROR cannot borrow `v[..].x` as immutable because it is also borrowed as mutable // No errors in AST diff --git a/src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs b/src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs index 4336812af9b..3e57ac0ca19 100644 --- a/src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs +++ b/src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs @@ -19,7 +19,7 @@ enum Foo { fn match_enum() { let mut foo = Foo::B; let p = &mut foo; - let _ = match foo { + let _ = match foo { //[mir]~ ERROR [E0503] Foo::B => 1, //[mir]~ ERROR [E0503] _ => 2, Foo::A(x) => x //[ast]~ ERROR [E0503] @@ -31,7 +31,7 @@ fn match_enum() { fn main() { let mut x = 1; let _x = &mut x; - let _ = match x { + let _ = match x { //[mir]~ ERROR [E0503] x => x + 1, //[ast]~ ERROR [E0503] //[mir]~^ ERROR [E0503] y => y + 2, //[ast]~ ERROR [E0503] diff --git a/src/test/compile-fail/borrowck/two-phase-activation-sharing-interference.rs b/src/test/compile-fail/borrowck/two-phase-activation-sharing-interference.rs index a9797e4d215..709c00ba846 100644 --- a/src/test/compile-fail/borrowck/two-phase-activation-sharing-interference.rs +++ b/src/test/compile-fail/borrowck/two-phase-activation-sharing-interference.rs @@ -8,9 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// revisions: lxl nll -//[lxl]compile-flags: -Z borrowck=mir -Z two-phase-borrows -//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll +// ignore-tidy-linelength + +// revisions: lxl_beyond nll_beyond nll_target + +//[lxl_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref +//[nll_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref -Z nll +//[nll_target] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll // This is an important corner case pointed out by Niko: one is // allowed to initiate a shared borrow during a reservation, but it @@ -18,6 +22,14 @@ // // FIXME: for clarity, diagnostics for these cases might be better off // if they specifically said "cannot activate mutable borrow of `x`" +// +// The convention for the listed revisions: "lxl" means lexical +// lifetimes (which can be easier to reason about). "nll" means +// non-lexical lifetimes. "nll_target" means the initial conservative +// two-phase borrows that only applies to autoref-introduced borrows. +// "nll_beyond" means the generalization of two-phase borrows to all +// `&mut`-borrows (doing so makes it easier to write code for specific +// corner cases). #![allow(dead_code)] @@ -27,6 +39,7 @@ fn ok() { let mut x = 3; let y = &mut x; { let z = &x; read(z); } + //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable *y += 1; } @@ -34,9 +47,11 @@ fn not_ok() { let mut x = 3; let y = &mut x; let z = &x; + //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable *y += 1; - //[lxl]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable - //[nll]~^^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable + //[lxl_beyond]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable + //[nll_beyond]~^^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable + //[nll_target]~^^^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable read(z); } @@ -44,18 +59,21 @@ fn should_be_ok_with_nll() { let mut x = 3; let y = &mut x; let z = &x; + //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable read(z); *y += 1; - //[lxl]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable - // (okay with nll today) + //[lxl_beyond]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable + // (okay with (generalized) nll today) } fn should_also_eventually_be_ok_with_nll() { let mut x = 3; let y = &mut x; let _z = &x; + //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable *y += 1; - //[lxl]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable + //[lxl_beyond]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable + // (okay with (generalized) nll today) } fn main() { } diff --git a/src/test/compile-fail/borrowck/two-phase-allow-access-during-reservation.rs b/src/test/compile-fail/borrowck/two-phase-allow-access-during-reservation.rs index 7695bd3e465..dd174981fb1 100644 --- a/src/test/compile-fail/borrowck/two-phase-allow-access-during-reservation.rs +++ b/src/test/compile-fail/borrowck/two-phase-allow-access-during-reservation.rs @@ -8,9 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// revisions: lxl nll -//[lxl]compile-flags: -Z borrowck=mir -Z two-phase-borrows -//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll +// ignore-tidy-linelength + +// revisions: lxl_beyond nll_beyond nll_target +//[lxl_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two_phase_beyond_autoref +//[nll_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two_phase_beyond_autoref -Z nll +//[nll_target] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll // This is the second counter-example from Niko's blog post // smallcultfollowing.com/babysteps/blog/2017/03/01/nested-method-calls-via-two-phase-borrowing/ @@ -18,6 +21,14 @@ // It is "artificial". It is meant to illustrate directly that we // should allow an aliasing access during reservation, but *not* while // the mutable borrow is active. +// +// The convention for the listed revisions: "lxl" means lexical +// lifetimes (which can be easier to reason about). "nll" means +// non-lexical lifetimes. "nll_target" means the initial conservative +// two-phase borrows that only applies to autoref-introduced borrows. +// "nll_beyond" means the generalization of two-phase borrows to all +// `&mut`-borrows (doing so makes it easier to write code for specific +// corner cases). fn main() { /*0*/ let mut i = 0; @@ -25,11 +36,13 @@ fn main() { /*1*/ let p = &mut i; // (reservation of `i` starts here) /*2*/ let j = i; // OK: `i` is only reserved here + //[nll_target]~^ ERROR cannot use `i` because it was mutably borrowed [E0503] /*3*/ *p += 1; // (mutable borrow of `i` starts here, since `p` is used) - /*4*/ let k = i; //[lxl]~ ERROR cannot use `i` because it was mutably borrowed [E0503] - //[nll]~^ ERROR cannot use `i` because it was mutably borrowed [E0503] + /*4*/ let k = i; //[lxl_beyond]~ ERROR cannot use `i` because it was mutably borrowed [E0503] + //[nll_beyond]~^ ERROR cannot use `i` because it was mutably borrowed [E0503] + //[nll_target]~^^ ERROR cannot use `i` because it was mutably borrowed [E0503] /*5*/ *p += 1; diff --git a/src/test/compile-fail/borrowck/two-phase-nonrecv-autoref.rs b/src/test/compile-fail/borrowck/two-phase-nonrecv-autoref.rs new file mode 100644 index 00000000000..795d45a776d --- /dev/null +++ b/src/test/compile-fail/borrowck/two-phase-nonrecv-autoref.rs @@ -0,0 +1,260 @@ +// 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. + +// revisions: lxl nll g2p +//[lxl]compile-flags: -Z borrowck=mir -Z two-phase-borrows +//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll +//[g2p]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll -Z two-phase-beyond-autoref + +// This is a test checking that when we limit two-phase borrows to +// method receivers, we do not let other kinds of auto-ref to leak +// through. +// +// The g2p revision illustrates the "undesirable" behavior you would +// otherwise observe without limiting the phasing to autoref on method +// receivers (namely, in many cases demonstrated below, the error +// would not arise). + +// (If we revise the compiler or this test so that the g2p revision +// passes, turn the `rustc_attrs` feature back on and tag the `fn +// main` with `#[rustc_error]` so that this remains a valid +// compile-fail test.) +// +// #![feature(rustc_attrs)] + +use std::ops::{Index, IndexMut}; +use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; +use std::ops::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign}; + +// This is case outlined by Niko that we want to ensure we reject +// (at least initially). + +fn foo(x: &mut u32, y: u32) { + *x += y; +} + +fn deref_coercion(x: &mut u32) { + foo(x, *x); + //[lxl]~^ ERROR cannot use `*x` because it was mutably borrowed [E0503] + //[nll]~^^ ERROR cannot use `*x` because it was mutably borrowed [E0503] +} + +// While adding a flag to adjustments (indicating whether they +// should support two-phase borrows, here are the cases I +// encountered: +// +// - [x] Resolving overloaded_call_traits (call, call_mut, call_once) +// - [x] deref_coercion (shown above) +// - [x] coerce_unsized e.g. `&[T; n]`, `&mut [T; n] -> &[T]`, +// `&mut [T; n] -> &mut [T]`, `&Concrete -> &Trait` +// - [x] Method Call Receivers (the case we want to support!) +// - [x] ExprIndex and ExprUnary Deref; only need to handle coerce_index_op +// - [x] overloaded_binops + +fn overloaded_call_traits() { + // Regarding overloaded call traits, note that there is no + // scenario where adding two-phase borrows should "fix" these + // cases, because either we will resolve both invocations to + // `call_mut` (in which case the inner call requires a mutable + // borrow which will conflict with the outer reservation), or we + // will resolve both to `call` (which will just work, regardless + // of two-phase borrow support), or we will resolve both to + // `call_once` (in which case the inner call requires moving the + // receiver, invalidating the outer call). + + fn twice_ten_sm i32>(f: &mut F) { + f(f(10)); + //[lxl]~^ ERROR cannot borrow `*f` as mutable more than once at a time + //[lxl]~| ERROR cannot borrow `*f` as mutable more than once at a time + //[nll]~^^^ ERROR cannot borrow `*f` as mutable more than once at a time + //[nll]~| ERROR cannot borrow `*f` as mutable more than once at a time + //[g2p]~^^^^^ ERROR cannot borrow `*f` as mutable more than once at a time + } + fn twice_ten_si i32>(f: &mut F) { + f(f(10)); + } + fn twice_ten_so i32>(f: Box) { + f(f(10)); + //[lxl]~^ ERROR use of moved value: `*f` + //[nll]~^^ ERROR use of moved value: `*f` + //[g2p]~^^^ ERROR use of moved value: `*f` + } + + fn twice_ten_om(f: &mut FnMut(i32) -> i32) { + f(f(10)); + //[lxl]~^ ERROR cannot borrow `*f` as mutable more than once at a time + //[lxl]~| ERROR cannot borrow `*f` as mutable more than once at a time + //[nll]~^^^ ERROR cannot borrow `*f` as mutable more than once at a time + //[nll]~| ERROR cannot borrow `*f` as mutable more than once at a time + //[g2p]~^^^^^ ERROR cannot borrow `*f` as mutable more than once at a time + } + fn twice_ten_oi(f: &mut Fn(i32) -> i32) { + f(f(10)); + } + fn twice_ten_oo(f: Box i32>) { + f(f(10)); + //[lxl]~^ ERROR cannot move a value of type + //[lxl]~^^ ERROR cannot move a value of type + //[lxl]~^^^ ERROR use of moved value: `*f` + //[nll]~^^^^ ERROR cannot move a value of type + //[nll]~^^^^^ ERROR cannot move a value of type + //[nll]~^^^^^^ ERROR cannot move a value of type + //[nll]~^^^^^^^ ERROR cannot move a value of type + //[nll]~^^^^^^^^ ERROR use of moved value: `*f` + //[g2p]~^^^^^^^^^ ERROR cannot move a value of type + //[g2p]~^^^^^^^^^^ ERROR cannot move a value of type + //[g2p]~^^^^^^^^^^^ ERROR cannot move a value of type + //[g2p]~^^^^^^^^^^^^ ERROR cannot move a value of type + //[g2p]~^^^^^^^^^^^^^ ERROR use of moved value: `*f` + } + + twice_ten_sm(&mut |x| x + 1); + twice_ten_si(&mut |x| x + 1); + twice_ten_so(Box::new(|x| x + 1)); + twice_ten_om(&mut |x| x + 1); + twice_ten_oi(&mut |x| x + 1); + twice_ten_oo(Box::new(|x| x + 1)); +} + +trait TwoMethods { + fn m(&mut self, x: i32) -> i32 { x + 1 } + fn i(&self, x: i32) -> i32 { x + 1 } +} + +struct T; + +impl TwoMethods for T { } + +struct S; + +impl S { + fn m(&mut self, x: i32) -> i32 { x + 1 } + fn i(&self, x: i32) -> i32 { x + 1 } +} + +impl TwoMethods for [i32; 3] { } + +fn double_access(m: &mut [X], s: &[X]) { + m[0] = s[1]; +} + +fn coerce_unsized() { + let mut a = [1, 2, 3]; + + // This is not okay. + double_access(&mut a, &a); + //[lxl]~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502] + //[nll]~^^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502] + //[g2p]~^^^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502] + + // But this is okay. + a.m(a.i(10)); +} + +struct I(i32); + +impl Index for I { + type Output = i32; + fn index(&self, _: i32) -> &i32 { + &self.0 + } +} + +impl IndexMut for I { + fn index_mut(&mut self, _: i32) -> &mut i32 { + &mut self.0 + } +} + +fn coerce_index_op() { + let mut i = I(10); + i[i[3]] = 4; + //[lxl]~^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] + //[nll]~^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] + + i[3] = i[4]; + + i[i[3]] = i[4]; + //[lxl]~^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] + //[nll]~^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] +} + +struct A(i32); + +macro_rules! trivial_binop { + ($Trait:ident, $m:ident) => { + impl $Trait for A { fn $m(&mut self, rhs: i32) { self.0 = rhs; } } + } +} + +trivial_binop!(AddAssign, add_assign); +trivial_binop!(SubAssign, sub_assign); +trivial_binop!(MulAssign, mul_assign); +trivial_binop!(DivAssign, div_assign); +trivial_binop!(RemAssign, rem_assign); +trivial_binop!(BitAndAssign, bitand_assign); +trivial_binop!(BitOrAssign, bitor_assign); +trivial_binop!(BitXorAssign, bitxor_assign); +trivial_binop!(ShlAssign, shl_assign); +trivial_binop!(ShrAssign, shr_assign); + +fn overloaded_binops() { + let mut a = A(10); + a += a.0; + //[lxl]~^ ERROR cannot use `a.0` because it was mutably borrowed + //[nll]~^^ ERROR cannot use `a.0` because it was mutably borrowed + a -= a.0; + //[lxl]~^ ERROR cannot use `a.0` because it was mutably borrowed + //[nll]~^^ ERROR cannot use `a.0` because it was mutably borrowed + a *= a.0; + //[lxl]~^ ERROR cannot use `a.0` because it was mutably borrowed + //[nll]~^^ ERROR cannot use `a.0` because it was mutably borrowed + a /= a.0; + //[lxl]~^ ERROR cannot use `a.0` because it was mutably borrowed + //[nll]~^^ ERROR cannot use `a.0` because it was mutably borrowed + a &= a.0; + //[lxl]~^ ERROR cannot use `a.0` because it was mutably borrowed + //[nll]~^^ ERROR cannot use `a.0` because it was mutably borrowed + a |= a.0; + //[lxl]~^ ERROR cannot use `a.0` because it was mutably borrowed + //[nll]~^^ ERROR cannot use `a.0` because it was mutably borrowed + a ^= a.0; + //[lxl]~^ ERROR cannot use `a.0` because it was mutably borrowed + //[nll]~^^ ERROR cannot use `a.0` because it was mutably borrowed + a <<= a.0; + //[lxl]~^ ERROR cannot use `a.0` because it was mutably borrowed + //[nll]~^^ ERROR cannot use `a.0` because it was mutably borrowed + a >>= a.0; + //[lxl]~^ ERROR cannot use `a.0` because it was mutably borrowed + //[nll]~^^ ERROR cannot use `a.0` because it was mutably borrowed +} + +fn main() { + + // As a reminder, this is the basic case we want to ensure we handle. + let mut v = vec![1, 2, 3]; + v.push(v.len()); + + // (as a rule, pnkfelix does not like to write tests with dead code.) + + deref_coercion(&mut 5); + overloaded_call_traits(); + + + let mut s = S; + s.m(s.i(10)); + + let mut t = T; + t.m(t.i(10)); + + coerce_unsized(); + coerce_index_op(); + overloaded_binops(); +} diff --git a/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs b/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs index cc85315263a..b5fda4985f2 100644 --- a/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs +++ b/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs @@ -8,9 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// revisions: lxl nll -//[lxl]compile-flags: -Z borrowck=mir -Z two-phase-borrows -//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll +// ignore-tidy-linelength + +// revisions: lxl_beyond nll_beyond nll_target + +//[lxl_beyond]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref +//[nll_beyond]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref -Z nll +//[nll_target]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll // This is a corner case that the current implementation is (probably) // treating more conservatively than is necessary. But it also does @@ -19,6 +23,18 @@ // So this test is just making a note of the current behavior, with // the caveat that in the future, the rules may be loosened, at which // point this test might be thrown out. +// +// The convention for the listed revisions: "lxl" means lexical +// lifetimes (which can be easier to reason about). "nll" means +// non-lexical lifetimes. "nll_target" means the initial conservative +// two-phase borrows that only applies to autoref-introduced borrows. +// "nll_beyond" means the generalization of two-phase borrows to all +// `&mut`-borrows (doing so makes it easier to write code for specific +// corner cases). +// +// FIXME: in "nll_target", we currently see the same error reported +// twice. This is injected by `-Z two-phase-borrows`; not sure why as +// of yet. fn main() { let mut vec = vec![0, 1]; @@ -30,8 +46,10 @@ fn main() { // with the shared borrow. But in the current implementation, // its an error. delay = &mut vec; - //[lxl]~^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable - //[nll]~^^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable + //[lxl_beyond]~^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable + //[nll_beyond]~^^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable + //[nll_target]~^^^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable + //[nll_target]~| ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable shared[0]; } diff --git a/src/test/compile-fail/const-eval-overflow-4b.rs b/src/test/compile-fail/const-eval-overflow-4b.rs index 02072e9a1a1..6028df18839 100644 --- a/src/test/compile-fail/const-eval-overflow-4b.rs +++ b/src/test/compile-fail/const-eval-overflow-4b.rs @@ -22,7 +22,7 @@ : [u32; (i8::MAX as i8 + 1u8) as usize] //~^ ERROR mismatched types //~| expected i8, found u8 - //~| ERROR the trait bound `i8: std::ops::Add` is not satisfied + //~| ERROR cannot add `u8` to `i8` = [0; (i8::MAX as usize) + 1]; diff --git a/src/test/compile-fail/const-typeid-of.rs b/src/test/compile-fail/const-typeid-of.rs new file mode 100644 index 00000000000..401125cef09 --- /dev/null +++ b/src/test/compile-fail/const-typeid-of.rs @@ -0,0 +1,18 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::any::TypeId; + +struct A; + +fn main() { + const A_ID: TypeId = TypeId::of::(); + //~^ ERROR `std::any::TypeId::of` is not yet stable as a const fn +} diff --git a/src/test/compile-fail/dst-bad-assign-3.rs b/src/test/compile-fail/dst-bad-assign-3.rs index 1c3bad5ba56..759da7b2bde 100644 --- a/src/test/compile-fail/dst-bad-assign-3.rs +++ b/src/test/compile-fail/dst-bad-assign-3.rs @@ -13,7 +13,7 @@ #![feature(unsized_tuple_coercion)] type Fat = (isize, &'static str, T); -//~^ WARNING trait bounds are not (yet) enforced +//~^ WARNING bounds are ignored #[derive(PartialEq,Eq)] struct Bar; diff --git a/src/test/compile-fail/epoch-raw-pointer-method-2015.rs b/src/test/compile-fail/epoch-raw-pointer-method-2015.rs new file mode 100644 index 00000000000..a71db040b50 --- /dev/null +++ b/src/test/compile-fail/epoch-raw-pointer-method-2015.rs @@ -0,0 +1,23 @@ +// 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. + +// ignore-tidy-linelength +// compile-flags: -Zepoch=2015 -Zunstable-options + +// tests that epochs work with the tyvar warning-turned-error + +#[deny(warnings)] +fn main() { + let x = 0; + let y = &x as *const _; + let _ = y.is_null(); + //~^ error: the type of this value must be known in this context [tyvar_behind_raw_pointer] + //~^^ warning: this was previously accepted +} diff --git a/src/test/compile-fail/epoch-raw-pointer-method-2018.rs b/src/test/compile-fail/epoch-raw-pointer-method-2018.rs new file mode 100644 index 00000000000..c4815de2306 --- /dev/null +++ b/src/test/compile-fail/epoch-raw-pointer-method-2018.rs @@ -0,0 +1,22 @@ +// 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. + +// ignore-tidy-linelength +// compile-flags: -Zepoch=2018 -Zunstable-options + +// tests that epochs work with the tyvar warning-turned-error + +#[deny(warnings)] +fn main() { + let x = 0; + let y = &x as *const _; + let _ = y.is_null(); + //~^ error: the type of this value must be known to call a method on a raw pointer on it [E0908] +} diff --git a/src/test/compile-fail/issue-16048.rs b/src/test/compile-fail/issue-16048.rs index 5012556dedd..cda83fe54b0 100644 --- a/src/test/compile-fail/issue-16048.rs +++ b/src/test/compile-fail/issue-16048.rs @@ -10,6 +10,7 @@ trait NoLifetime { fn get<'p, T : Test<'p>>(&self) -> T; + //~^ NOTE lifetimes in impl do not match this method in trait } trait Test<'p> { @@ -28,8 +29,8 @@ fn new(buf: &'a mut [u8]) -> Foo<'a> { impl<'a> NoLifetime for Foo<'a> { fn get<'p, T : Test<'a>>(&self) -> T { -//~^ ERROR E0195 -//~| lifetimes do not match trait + //~^ ERROR E0195 + //~| NOTE lifetimes do not match method in trait return *self as T; } } diff --git a/src/test/compile-fail/issue-39388.rs b/src/test/compile-fail/issue-39388.rs index 15eef429eab..6da04937408 100644 --- a/src/test/compile-fail/issue-39388.rs +++ b/src/test/compile-fail/issue-39388.rs @@ -11,7 +11,7 @@ #![allow(unused_macros)] macro_rules! assign { - (($($a:tt)*) = ($($b:tt))*) => { //~ ERROR expected `*` or `+` + (($($a:tt)*) = ($($b:tt))*) => { //~ ERROR expected one of: `*`, `+`, or `?` $($a)* = $($b)* } } diff --git a/src/test/compile-fail/issue-42344.rs b/src/test/compile-fail/issue-42344.rs new file mode 100644 index 00000000000..2f11ff402be --- /dev/null +++ b/src/test/compile-fail/issue-42344.rs @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +static TAB: [&mut [u8]; 0] = []; + +pub unsafe fn test() { + TAB[0].iter_mut(); //~ ERROR cannot borrow data mutably in a `&` reference [E0389] +} + +pub fn main() {} diff --git a/src/test/compile-fail/issue-44415.rs b/src/test/compile-fail/issue-44415.rs new file mode 100644 index 00000000000..3b7089f4975 --- /dev/null +++ b/src/test/compile-fail/issue-44415.rs @@ -0,0 +1,22 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(const_fn)] +#![feature(core_intrinsics)] + +use std::intrinsics; + +struct Foo { + bytes: [u8; unsafe { intrinsics::size_of::() }], + //~^ ERROR unsupported cyclic reference between types/traits detected + x: usize, +} + +fn main() {} diff --git a/src/test/compile-fail/issue-46036.rs b/src/test/compile-fail/issue-46036.rs new file mode 100644 index 00000000000..b5cdded4d30 --- /dev/null +++ b/src/test/compile-fail/issue-46036.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. + +// Issue 46036: [NLL] false edges on infinite loops +// Infinite loops should create false edges to the cleanup block. +#![feature(nll)] + +struct Foo { x: &'static u32 } + +fn foo() { + let a = 3; + let foo = Foo { x: &a }; //~ ERROR E0597 + loop { } +} + +fn main() { } diff --git a/src/test/compile-fail/issue-46604.rs b/src/test/compile-fail/issue-46604.rs index 06aa4c343fe..dc14eca1e67 100644 --- a/src/test/compile-fail/issue-46604.rs +++ b/src/test/compile-fail/issue-46604.rs @@ -17,5 +17,6 @@ fn write>(buffer: T) { } fn main() { write(&buf); - buf[0]=2; //[mir]~ ERROR E0594 + buf[0]=2; //[ast]~ ERROR E0389 + //[mir]~^ ERROR E0594 } diff --git a/src/test/compile-fail/issue-47412.rs b/src/test/compile-fail/issue-47412.rs new file mode 100644 index 00000000000..7481befcb79 --- /dev/null +++ b/src/test/compile-fail/issue-47412.rs @@ -0,0 +1,31 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[derive(Copy, Clone)] +enum Void {} + +// Tests that we detect unsafe places (specifically, union fields and +// raw pointer dereferences), even when they're matched on while having +// an uninhabited type (equivalent to `std::intrinsics::unreachable()`). + +fn union_field() { + union Union { unit: (), void: Void } + let u = Union { unit: () }; + match u.void {} + //~^ ERROR access to union field requires unsafe function or block +} + +fn raw_ptr_deref() { + let ptr = std::ptr::null::(); + match *ptr {} + //~^ ERROR dereference of raw pointer requires unsafe function or block +} + +fn main() {} diff --git a/src/test/compile-fail/macro-at-most-once-rep-ambig.rs b/src/test/compile-fail/macro-at-most-once-rep-ambig.rs new file mode 100644 index 00000000000..a5660f8b41f --- /dev/null +++ b/src/test/compile-fail/macro-at-most-once-rep-ambig.rs @@ -0,0 +1,53 @@ +// 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 logic for parsing Kleene operators in macros has a special case to disambiguate `?`. +// Specifically, `$(pat)?` is the ZeroOrOne operator whereas `$(pat)?+` or `$(pat)?*` are the +// ZeroOrMore and OneOrMore operators using `?` as a separator. These tests are intended to +// exercise that logic in the macro parser. +// +// Moreover, we also throw in some tests for using a separator with `?`, which is meaningless but +// included for consistency with `+` and `*`. +// +// This test focuses on error cases. + +#![feature(macro_at_most_once_rep)] + +macro_rules! foo { + ($(a)?) => {} +} + +macro_rules! baz { + ($(a),?) => {} // comma separator is meaningless for `?` +} + +macro_rules! barplus { + ($(a)?+) => {} +} + +macro_rules! barstar { + ($(a)?*) => {} +} + +pub fn main() { + foo!(a?a?a); //~ ERROR no rules expected the token `?` + foo!(a?a); //~ ERROR no rules expected the token `?` + foo!(a?); //~ ERROR no rules expected the token `?` + baz!(a?a?a); //~ ERROR no rules expected the token `?` + baz!(a?a); //~ ERROR no rules expected the token `?` + baz!(a?); //~ ERROR no rules expected the token `?` + baz!(a,); //~ ERROR unexpected end of macro invocation + baz!(a?a?a,); //~ ERROR no rules expected the token `?` + baz!(a?a,); //~ ERROR no rules expected the token `?` + baz!(a?,); //~ ERROR no rules expected the token `?` + barplus!(); //~ ERROR unexpected end of macro invocation + barplus!(a?); //~ ERROR unexpected end of macro invocation + barstar!(a?); //~ ERROR unexpected end of macro invocation +} diff --git a/src/test/compile-fail/nll/do-not-ignore-lifetime-bounds-in-copy.rs b/src/test/compile-fail/nll/do-not-ignore-lifetime-bounds-in-copy.rs new file mode 100644 index 00000000000..2a4295fd90a --- /dev/null +++ b/src/test/compile-fail/nll/do-not-ignore-lifetime-bounds-in-copy.rs @@ -0,0 +1,23 @@ +// 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. + +// Test that the 'static bound from the Copy impl is respected. Regression test for #29149. + +#![feature(nll)] + +#[derive(Clone)] struct Foo<'a>(&'a u32); +impl Copy for Foo<'static> {} + +fn main() { + let s = 2; + let a = Foo(&s); //~ ERROR `s` does not live long enough [E0597] + drop(a); + drop(a); +} diff --git a/src/test/compile-fail/nll/reference-carried-through-struct-field.rs b/src/test/compile-fail/nll/reference-carried-through-struct-field.rs index 1c1fc4799c3..efa6cc273b6 100644 --- a/src/test/compile-fail/nll/reference-carried-through-struct-field.rs +++ b/src/test/compile-fail/nll/reference-carried-through-struct-field.rs @@ -19,8 +19,7 @@ fn foo() { let mut x = 22; let wrapper = Wrap { w: &mut x }; x += 1; //[ast]~ ERROR cannot assign to `x` because it is borrowed [E0506] - //[mir]~^ ERROR cannot assign to `x` because it is borrowed [E0506] - //[mir]~^^ ERROR cannot use `x` because it was mutably borrowed [E0503] + //[mir]~^ ERROR cannot use `x` because it was mutably borrowed [E0503] *wrapper.w += 1; } diff --git a/src/test/compile-fail/private-in-public-warn.rs b/src/test/compile-fail/private-in-public-warn.rs index dfcf4dc01b8..aa91ce27c37 100644 --- a/src/test/compile-fail/private-in-public-warn.rs +++ b/src/test/compile-fail/private-in-public-warn.rs @@ -58,7 +58,7 @@ trait PrivTr {} pub trait PubTr {} pub type Alias = T; //~ ERROR private trait `traits::PrivTr` in public interface - //~^ WARN trait bounds are not (yet) enforced in type definitions + //~^ WARN bounds are ignored in type aliases //~| WARNING hard error pub trait Tr1: PrivTr {} //~ ERROR private trait `traits::PrivTr` in public interface //~^ WARNING hard error diff --git a/src/test/compile-fail/regions-adjusted-lvalue-op.rs b/src/test/compile-fail/regions-adjusted-lvalue-op.rs index 167c8630707..bb02d6d8bba 100644 --- a/src/test/compile-fail/regions-adjusted-lvalue-op.rs +++ b/src/test/compile-fail/regions-adjusted-lvalue-op.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// check that we link regions in mutable lvalue ops correctly - issue #41774 +// check that we link regions in mutable place ops correctly - issue #41774 struct Data(i32); diff --git a/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs b/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs deleted file mode 100644 index 617de2c5dfe..00000000000 --- a/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs +++ /dev/null @@ -1,58 +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. - -// Check that explicit region bounds are allowed on the various -// nominal types (but not on other types) and that they are type -// checked. - -struct Inv<'a> { // invariant w/r/t 'a - x: &'a mut &'a isize -} - -pub trait Foo<'a, 't> { - fn no_bound<'b>(self, b: Inv<'b>); - fn has_bound<'b:'a>(self, b: Inv<'b>); - fn wrong_bound1<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>); - fn okay_bound<'b,'c,'d:'a+'b+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>); - fn another_bound<'x: 'a>(self, x: Inv<'x>, y: Inv<'t>); -} - -impl<'a, 't> Foo<'a, 't> for &'a isize { - fn no_bound<'b:'a>(self, b: Inv<'b>) { - //~^ ERROR lifetime parameters or bounds on method `no_bound` do not match - } - - fn has_bound<'b>(self, b: Inv<'b>) { - //~^ ERROR lifetime parameters or bounds on method `has_bound` do not match - } - - fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { - //~^ ERROR method not compatible with trait - // - // Note: This is a terrible error message. It is caused - // because, in the trait, 'b is early bound, and in the impl, - // 'c is early bound, so -- after substitution -- the - // lifetimes themselves look isomorphic. We fail because the - // lifetimes that appear in the types are in the wrong - // order. This should really be fixed by keeping more - // information about the lifetime declarations in the trait so - // that we can compare better to the impl, even in cross-crate - // cases. - } - - fn okay_bound<'b,'c,'e:'b+'c>(self, b: Inv<'b>, c: Inv<'c>, e: Inv<'e>) { - } - - fn another_bound<'x: 't>(self, x: Inv<'x>, y: Inv<'t>) { - //~^ ERROR E0276 - } -} - -fn main() { } diff --git a/src/test/compile-fail/rustc-args-required-const.rs b/src/test/compile-fail/rustc-args-required-const.rs new file mode 100644 index 00000000000..aac9299eaaf --- /dev/null +++ b/src/test/compile-fail/rustc-args-required-const.rs @@ -0,0 +1,36 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(attr_literals, rustc_attrs, const_fn)] + +#[rustc_args_required_const(0)] +fn foo(_a: i32) { +} + +#[rustc_args_required_const(1)] +fn bar(_a: i32, _b: i32) { +} + +const A: i32 = 3; + +const fn baz() -> i32 { + 3 +} + +fn main() { + foo(2); + foo(2 + 3); + foo(baz()); + let a = 4; + foo(A); + foo(a); //~ ERROR: argument 1 is required to be a constant + bar(a, 3); + bar(a, a); //~ ERROR: argument 2 is required to be a constant +} diff --git a/src/test/compile-fail/rustc-args-required-const2.rs b/src/test/compile-fail/rustc-args-required-const2.rs new file mode 100644 index 00000000000..aa63019307b --- /dev/null +++ b/src/test/compile-fail/rustc-args-required-const2.rs @@ -0,0 +1,20 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(attr_literals, rustc_attrs, const_fn)] + +#[rustc_args_required_const(0)] +fn foo(_a: i32) { +} + +fn main() { + let a = foo; //~ ERROR: this function can only be invoked directly + a(2); +} diff --git a/src/test/compile-fail/ufcs-qpath-self-mismatch.rs b/src/test/compile-fail/ufcs-qpath-self-mismatch.rs index 94a98b1582a..caf510071bd 100644 --- a/src/test/compile-fail/ufcs-qpath-self-mismatch.rs +++ b/src/test/compile-fail/ufcs-qpath-self-mismatch.rs @@ -12,7 +12,7 @@ fn main() { >::add(1, 2); - //~^ ERROR `i32: std::ops::Add` is not satisfied + //~^ ERROR cannot add `u32` to `i32` >::add(1u32, 2); //~^ ERROR mismatched types >::add(1, 2u32); diff --git a/src/test/incremental/hashes/loop_expressions.rs b/src/test/incremental/hashes/loop_expressions.rs index dcb937fd867..8599f8d7f9a 100644 --- a/src/test/incremental/hashes/loop_expressions.rs +++ b/src/test/incremental/hashes/loop_expressions.rs @@ -179,7 +179,7 @@ pub fn change_continue_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, TypeckTables")] +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, TypeckTables")] #[rustc_clean(cfg="cfail3")] pub fn change_continue_label() { let mut _x = 0; diff --git a/src/test/incremental/hashes/unary_and_binary_exprs.rs b/src/test/incremental/hashes/unary_and_binary_exprs.rs index 85f6ef60c5d..466690e7ca1 100644 --- a/src/test/incremental/hashes/unary_and_binary_exprs.rs +++ b/src/test/incremental/hashes/unary_and_binary_exprs.rs @@ -404,9 +404,9 @@ pub fn value_cast(a: u32) -> i32 { -// Change l-value in assignment ------------------------------------------------ +// Change place in assignment -------------------------------------------------- #[cfg(cfail1)] -pub fn lvalue() -> i32 { +pub fn place() -> i32 { let mut x = 10; let mut y = 11; x = 9; @@ -416,7 +416,7 @@ pub fn lvalue() -> i32 { #[cfg(not(cfail1))] #[rustc_clean(except="HirBody,MirOptimized,MirValidated", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -pub fn lvalue() -> i32 { +pub fn place() -> i32 { let mut x = 10; let mut y = 11; y = 9; diff --git a/src/test/mir-opt/end_region_2.rs b/src/test/mir-opt/end_region_2.rs index 56c3e2a38a0..d6084d5a6da 100644 --- a/src/test/mir-opt/end_region_2.rs +++ b/src/test/mir-opt/end_region_2.rs @@ -40,15 +40,21 @@ fn main() { // goto -> bb1; // } // bb1: { +// falseUnwind -> [real: bb2, cleanup: bb3]; +// } +// bb2: { // StorageLive(_2); // _2 = const true; // StorageLive(_3); // _3 = &'23_1rs _2; // StorageLive(_5); // _5 = _2; -// switchInt(move _5) -> [0u8: bb3, otherwise: bb2]; +// switchInt(move _5) -> [0u8: bb5, otherwise: bb4]; // } -// bb2: { +// bb3: { +// ... +// } +// bb4: { // _0 = (); // StorageDead(_5); // EndRegion('23_1rs); @@ -56,7 +62,7 @@ fn main() { // StorageDead(_2); // return; // } -// bb3: { +// bb5: { // _4 = (); // StorageDead(_5); // StorageLive(_7); diff --git a/src/test/mir-opt/end_region_3.rs b/src/test/mir-opt/end_region_3.rs index 8c0d56eba78..46548f1cce9 100644 --- a/src/test/mir-opt/end_region_3.rs +++ b/src/test/mir-opt/end_region_3.rs @@ -43,14 +43,20 @@ fn main() { // goto -> bb1; // } // bb1: { +// falseUnwind -> [real: bb2, cleanup: bb3]; +// } +// bb2: { // _1 = const true; // StorageLive(_3); // _3 = &'26_1rs _1; // StorageLive(_5); // _5 = _1; -// switchInt(move _5) -> [0u8: bb3, otherwise: bb2]; +// switchInt(move _5) -> [0u8: bb5, otherwise: bb4]; // } -// bb2: { +// bb3: { +// ... +// } +// bb4: { // _0 = (); // StorageDead(_5); // EndRegion('26_1rs); @@ -58,7 +64,7 @@ fn main() { // StorageDead(_1); // return; // } -// bb3: { +// bb5: { // _4 = (); // StorageDead(_5); // StorageLive(_7); diff --git a/src/test/mir-opt/end_region_9.rs b/src/test/mir-opt/end_region_9.rs index b313e296ac9..0f1d714cc6f 100644 --- a/src/test/mir-opt/end_region_9.rs +++ b/src/test/mir-opt/end_region_9.rs @@ -57,16 +57,24 @@ fn main() { // _1 = const false; // StorageLive(_2); // _2 = const 3i32; -// StorageLive(_4); -// goto -> bb1; +// falseUnwind -> [real: bb2, cleanup: bb1]; // } -// // bb1: { +// ... +// } +// bb2: { +// StorageLive(_4); +// goto -> bb3; +// } +// bb3: { +// falseUnwind -> [real: bb4, cleanup: bb1]; +// } +// bb4: { // StorageLive(_7); // _7 = _1; -// switchInt(move _7) -> [0u8: bb3, otherwise: bb2]; +// switchInt(move _7) -> [0u8: bb6, otherwise: bb5]; // } -// bb2: { +// bb5: { // _0 = (); // StorageDead(_7); // EndRegion('33_0rs); @@ -75,13 +83,13 @@ fn main() { // StorageDead(_1); // return; // } -// bb3: { +// bb6: { // _4 = &'33_0rs _2; // _6 = (); // StorageDead(_7); // _1 = const true; // _3 = (); -// goto -> bb1; +// goto -> bb3; // } // } // END rustc.main.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_cyclic.rs b/src/test/mir-opt/end_region_cyclic.rs index 37a6229feba..2a82e2675b6 100644 --- a/src/test/mir-opt/end_region_cyclic.rs +++ b/src/test/mir-opt/end_region_cyclic.rs @@ -67,16 +67,19 @@ fn query() -> bool { true } // goto -> bb1; // } // bb1: { +// falseUnwind -> [real: bb2, cleanup: bb3]; +// } +// bb2: { // StorageLive(_2); // StorageLive(_3); // StorageLive(_4); // _4 = std::option::Option<&'35_0rs S<'35_0rs>>::None; -// _3 = const >::new(move _4) -> [return: bb3, unwind: bb2]; +// _3 = const >::new(move _4) -> [return: bb4, unwind: bb3]; // } -// bb2: { +// bb3: { // resume; // } -// bb3: { +// bb4: { // StorageDead(_4); // _2 = S<'35_0rs> { r: move _3 }; // StorageDead(_3); @@ -89,27 +92,27 @@ fn query() -> bool { true } // _8 = &'35_0rs (*_9); // _7 = std::option::Option<&'35_0rs S<'35_0rs>>::Some(move _8,); // StorageDead(_8); -// _5 = const >::set(move _6, move _7) -> [return: bb4, unwind: bb2]; +// _5 = const >::set(move _6, move _7) -> [return: bb5, unwind: bb3]; // } -// bb4: { +// bb5: { // EndRegion('16s); // StorageDead(_7); // StorageDead(_6); // StorageDead(_9); // StorageLive(_11); -// _11 = const query() -> [return: bb5, unwind: bb2]; -// } -// bb5: { -// switchInt(move _11) -> [0u8: bb7, otherwise: bb6]; +// _11 = const query() -> [return: bb6, unwind: bb3]; // } // bb6: { +// switchInt(move _11) -> [0u8: bb8, otherwise: bb7]; +// } +// bb7: { // _0 = (); // StorageDead(_11); // EndRegion('35_0rs); // StorageDead(_2); // return; // } -// bb7: { +// bb8: { // _10 = (); // StorageDead(_11); // StorageLive(_14); @@ -121,9 +124,9 @@ fn query() -> bool { true } // _16 = &'35_0rs (*_17); // _15 = std::option::Option<&'35_0rs S<'35_0rs>>::Some(move _16,); // StorageDead(_16); -// _13 = const >::set(move _14, move _15) -> [return: bb8, unwind: bb2]; +// _13 = const >::set(move _14, move _15) -> [return: bb9, unwind: bb3]; // } -// bb8: { +// bb9: { // EndRegion('33s); // StorageDead(_15); // StorageDead(_14); diff --git a/src/test/mir-opt/issue-38669.rs b/src/test/mir-opt/issue-38669.rs index b5c188cf834..3151c064307 100644 --- a/src/test/mir-opt/issue-38669.rs +++ b/src/test/mir-opt/issue-38669.rs @@ -25,27 +25,30 @@ fn main() { // bb0: { // StorageLive(_1); // _1 = const false; -// goto -> bb1; +// goto -> bb2; // } -// // bb1: { +// resume; +// } +// bb2: { +// falseUnwind -> [real: bb3, cleanup: bb1]; +// } +// bb3: { // StorageLive(_4); // _4 = _1; -// switchInt(move _4) -> [0u8: bb3, otherwise: bb2]; +// switchInt(move _4) -> [0u8: bb5, otherwise: bb4]; // } -// -// bb2: { +// bb4: { // _0 = (); // StorageDead(_4); // StorageDead(_1); // return; // } -// -// bb3: { +// bb5: { // _3 = (); // StorageDead(_4); // _1 = const true; // _2 = (); -// goto -> bb1; +// goto -> bb2; // } // END rustc.main.SimplifyCfg-initial.after.mir diff --git a/src/test/mir-opt/loop_test.rs b/src/test/mir-opt/loop_test.rs new file mode 100644 index 00000000000..d36d8908094 --- /dev/null +++ b/src/test/mir-opt/loop_test.rs @@ -0,0 +1,49 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z identify_regions -Z emit-end-regions + +// Tests to make sure we correctly generate falseUnwind edges in loops + +fn main() { + // Exit early at runtime. Since only care about the generated MIR + // and not the runtime behavior (which is exercised by other tests) + // we just bail early. Without this the test just loops infinitely. + if true { + return; + } + loop { + let x = 1; + continue; + } +} + +// END RUST SOURCE +// START rustc.main.SimplifyCfg-qualify-consts.after.mir +// ... +// bb1: { // The cleanup block +// resume; +// } +// ... +// bb3: { // Entry into the loop +// _1 = (); +// goto -> bb4; +// } +// bb4: { // The loop_block +// falseUnwind -> [real: bb5, cleanup: bb1]; +// } +// bb5: { // The loop body (body_block) +// StorageLive(_5); +// _5 = const 1i32; +// StorageDead(_5); +// goto -> bb4; +// } +// ... +// END rustc.main.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/match_false_edges.rs b/src/test/mir-opt/match_false_edges.rs index 1f892b0f958..ba1b54d59f6 100644 --- a/src/test/mir-opt/match_false_edges.rs +++ b/src/test/mir-opt/match_false_edges.rs @@ -53,17 +53,18 @@ fn main() { // bb0: { // ... // _2 = std::option::Option::Some(const 42i32,); -// _5 = discriminant(_2); -// switchInt(move _5) -> [0isize: bb6, 1isize: bb4, otherwise: bb8]; +// _3 = discriminant(_2); +// _6 = discriminant(_2); +// switchInt(move _6) -> [0isize: bb6, 1isize: bb4, otherwise: bb8]; // } // bb1: { // resume; // } // bb2: { // arm1 -// StorageLive(_7); -// _7 = _3; -// _1 = (const 1i32, move _7); -// StorageDead(_7); +// StorageLive(_8); +// _8 = _4; +// _1 = (const 1i32, move _8); +// StorageDead(_8); // goto -> bb13; // } // bb3: { // binding3(empty) and arm3 @@ -86,24 +87,24 @@ fn main() { // unreachable; // } // bb9: { // binding1 and guard -// StorageLive(_3); -// _3 = ((_2 as Some).0: i32); -// StorageLive(_6); -// _6 = const guard() -> [return: bb10, unwind: bb1]; +// StorageLive(_4); +// _4 = ((_2 as Some).0: i32); +// StorageLive(_7); +// _7 = const guard() -> [return: bb10, unwind: bb1]; // } // bb10: { // end of guard -// switchInt(move _6) -> [0u8: bb11, otherwise: bb2]; +// switchInt(move _7) -> [0u8: bb11, otherwise: bb2]; // } // bb11: { // to pre_binding2 // falseEdges -> [real: bb5, imaginary: bb5]; // } // bb12: { // bindingNoLandingPads.before.mir2 and arm2 -// StorageLive(_4); -// _4 = ((_2 as Some).0: i32); -// StorageLive(_8); -// _8 = _4; -// _1 = (const 2i32, move _8); -// StorageDead(_8); +// StorageLive(_5); +// _5 = ((_2 as Some).0: i32); +// StorageLive(_9); +// _9 = _5; +// _1 = (const 2i32, move _9); +// StorageDead(_9); // goto -> bb13; // } // bb13: { @@ -116,17 +117,18 @@ fn main() { // bb0: { // ... // _2 = std::option::Option::Some(const 42i32,); -// _5 = discriminant(_2); -// switchInt(move _5) -> [0isize: bb5, 1isize: bb4, otherwise: bb8]; +// _3 = discriminant(_2); +// _6 = discriminant(_2); +// switchInt(move _6) -> [0isize: bb5, 1isize: bb4, otherwise: bb8]; // } // bb1: { // resume; // } // bb2: { // arm1 -// StorageLive(_7); -// _7 = _3; -// _1 = (const 1i32, move _7); -// StorageDead(_7); +// StorageLive(_8); +// _8 = _4; +// _1 = (const 1i32, move _8); +// StorageDead(_8); // goto -> bb13; // } // bb3: { // binding3(empty) and arm3 @@ -149,24 +151,24 @@ fn main() { // unreachable; // } // bb9: { // binding1 and guard -// StorageLive(_3); -// _3 = ((_2 as Some).0: i32); -// StorageLive(_6); -// _6 = const guard() -> [return: bb10, unwind: bb1]; +// StorageLive(_4); +// _4 = ((_2 as Some).0: i32); +// StorageLive(_7); +// _7 = const guard() -> [return: bb10, unwind: bb1]; // } // bb10: { // end of guard -// switchInt(move _6) -> [0u8: bb11, otherwise: bb2]; +// switchInt(move _7) -> [0u8: bb11, otherwise: bb2]; // } // bb11: { // to pre_binding2 // falseEdges -> [real: bb6, imaginary: bb5]; // } // bb12: { // binding2 and arm2 -// StorageLive(_4); -// _4 = ((_2 as Some).0: i32); -// StorageLive(_8); -// _8 = _4; -// _1 = (const 2i32, move _8); -// StorageDead(_8); +// StorageLive(_5); +// _5 = ((_2 as Some).0: i32); +// StorageLive(_9); +// _9 = _5; +// _1 = (const 2i32, move _9); +// StorageDead(_9); // goto -> bb13; // } // bb13: { @@ -179,8 +181,9 @@ fn main() { // bb0: { // ... // _2 = std::option::Option::Some(const 1i32,); -// _7 = discriminant(_2); -// switchInt(move _7) -> [1isize: bb4, otherwise: bb5]; +// _3 = discriminant(_2); +// _8 = discriminant(_2); +// switchInt(move _8) -> [1isize: bb4, otherwise: bb5]; // } // bb1: { // resume; @@ -210,41 +213,41 @@ fn main() { // unreachable; // } // bb9: { // binding1: Some(w) if guard() -// StorageLive(_3); -// _3 = ((_2 as Some).0: i32); -// StorageLive(_8); -// _8 = const guard() -> [return: bb10, unwind: bb1]; +// StorageLive(_4); +// _4 = ((_2 as Some).0: i32); +// StorageLive(_9); +// _9 = const guard() -> [return: bb10, unwind: bb1]; // } // bb10: { //end of guard -// switchInt(move _8) -> [0u8: bb11, otherwise: bb2]; +// switchInt(move _9) -> [0u8: bb11, otherwise: bb2]; // } // bb11: { // to pre_binding2 // falseEdges -> [real: bb5, imaginary: bb5]; // } // bb12: { // binding2 & arm2 -// StorageLive(_4); -// _4 = _2; +// StorageLive(_5); +// _5 = _2; // _1 = const 2i32; // goto -> bb17; // } // bb13: { // binding3: Some(y) if guard2(y) -// StorageLive(_5); -// _5 = ((_2 as Some).0: i32); -// StorageLive(_10); +// StorageLive(_6); +// _6 = ((_2 as Some).0: i32); // StorageLive(_11); -// _11 = _5; -// _10 = const guard2(move _11) -> [return: bb14, unwind: bb1]; +// StorageLive(_12); +// _12 = _6; +// _11 = const guard2(move _12) -> [return: bb14, unwind: bb1]; // } // bb14: { // end of guard2 -// StorageDead(_11); -// switchInt(move _10) -> [0u8: bb15, otherwise: bb3]; +// StorageDead(_12); +// switchInt(move _11) -> [0u8: bb15, otherwise: bb3]; // } // bb15: { // to pre_binding4 // falseEdges -> [real: bb7, imaginary: bb7]; // } // bb16: { // binding4 & arm4 -// StorageLive(_6); -// _6 = _2; +// StorageLive(_7); +// _7 = _2; // _1 = const 4i32; // goto -> bb17; // } diff --git a/src/test/mir-opt/nll/liveness-drop-intra-block.rs b/src/test/mir-opt/nll/liveness-drop-intra-block.rs index b060222a95f..64ffc744606 100644 --- a/src/test/mir-opt/nll/liveness-drop-intra-block.rs +++ b/src/test/mir-opt/nll/liveness-drop-intra-block.rs @@ -25,17 +25,17 @@ fn main() { // END RUST SOURCE // START rustc.main.nll.0.mir -// | Live variables on entry to bb2: [] -// bb2: { -// | Live variables on entry to bb2[0]: [] +// | Live variables on entry to bb3: [] +// bb3: { +// | Live variables on entry to bb3[0]: [] // _1 = const 55usize; -// | Live variables on entry to bb2[1]: [_1] +// | Live variables on entry to bb3[1]: [_1] // StorageLive(_3); -// | Live variables on entry to bb2[2]: [_1] +// | Live variables on entry to bb3[2]: [_1] // StorageLive(_4); -// | Live variables on entry to bb2[3]: [_1] +// | Live variables on entry to bb3[3]: [_1] // _4 = _1; -// | Live variables on entry to bb2[4]: [_4] -// _3 = const use_x(move _4) -> [return: bb3, unwind: bb1]; +// | Live variables on entry to bb3[4]: [_4] +// _3 = const use_x(move _4) -> [return: bb4, unwind: bb1]; // } // END rustc.main.nll.0.mir diff --git a/src/test/mir-opt/validate_5.rs b/src/test/mir-opt/validate_5.rs index c9408c1f2f8..d8d83fb5b45 100644 --- a/src/test/mir-opt/validate_5.rs +++ b/src/test/mir-opt/validate_5.rs @@ -52,12 +52,15 @@ fn main() { // Validate(Acquire, [_1: &ReFree(DefId(0/1:9 ~ validate_5[317d]::main[0]::{{closure}}[0]), BrEnv) [closure@NodeId(46)], _2: &ReFree(DefId(0/1:9 ~ validate_5[317d]::main[0]::{{closure}}[0]), BrAnon(0)) mut i32]); // StorageLive(_3); // StorageLive(_4); +// StorageLive(_5); // Validate(Suspend(ReScope(Node(ItemLocalId(9)))), [(*_2): i32]); -// _4 = &ReErased mut (*_2); -// Validate(Acquire, [(*_4): i32/ReScope(Node(ItemLocalId(9)))]); -// _3 = move _4 as *mut i32 (Misc); +// _5 = &ReErased mut (*_2); +// Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(9)))]); +// _4 = move _5 as *mut i32 (Misc); +// _3 = move _4; // EndRegion(ReScope(Node(ItemLocalId(9)))); // StorageDead(_4); +// StorageDead(_5); // Validate(Release, [_0: bool, _3: *mut i32]); // _0 = const write_42(move _3) -> bb1; // } diff --git a/src/test/parse-fail/bad-char-literals.rs b/src/test/parse-fail/bad-char-literals.rs index 96311d6de17..821015ece77 100644 --- a/src/test/parse-fail/bad-char-literals.rs +++ b/src/test/parse-fail/bad-char-literals.rs @@ -15,7 +15,7 @@ fn main() { // these literals are just silly. '''; - //~^ ERROR: character constant must be escaped: \' + //~^ ERROR: character constant must be escaped: ' // note that this is a literal "\n" byte ' diff --git a/src/test/parse-fail/closure-return-syntax.rs b/src/test/parse-fail/closure-return-syntax.rs index 1da67359180..4c77edec56f 100644 --- a/src/test/parse-fail/closure-return-syntax.rs +++ b/src/test/parse-fail/closure-return-syntax.rs @@ -13,5 +13,5 @@ fn main() { let x = || -> i32 22; - //~^ ERROR expected one of `!`, `(`, `::`, `<`, or `{`, found `22` + //~^ ERROR expected one of `!`, `(`, `+`, `::`, `<`, or `{`, found `22` } diff --git a/src/test/parse-fail/issue-24780.rs b/src/test/parse-fail/issue-24780.rs index 56b91699478..6fd4ee38a4d 100644 --- a/src/test/parse-fail/issue-24780.rs +++ b/src/test/parse-fail/issue-24780.rs @@ -15,6 +15,6 @@ // compile-flags: -Z parse-only fn foo() -> Vec> { - //~^ ERROR expected one of `!`, `::`, `where`, or `{`, found `>` + //~^ ERROR expected one of `!`, `+`, `::`, `where`, or `{`, found `>` Vec::new() } diff --git a/src/test/parse-fail/issue-33569.rs b/src/test/parse-fail/issue-33569.rs index 15d491719a6..af90d0a83c9 100644 --- a/src/test/parse-fail/issue-33569.rs +++ b/src/test/parse-fail/issue-33569.rs @@ -13,7 +13,7 @@ macro_rules! foo { { $+ } => { //~ ERROR expected identifier, found `+` //~^ ERROR missing fragment specifier - $(x)(y) //~ ERROR expected `*` or `+` + $(x)(y) //~ ERROR expected one of: `*`, `+`, or `?` } } diff --git a/src/test/parse-fail/lex-stray-backslash.rs b/src/test/parse-fail/lex-stray-backslash.rs new file mode 100644 index 00000000000..b6042bbdc1a --- /dev/null +++ b/src/test/parse-fail/lex-stray-backslash.rs @@ -0,0 +1,13 @@ +// 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. + +// compile-flags: -Z parse-only + +\ //~ ERROR: unknown start of token: \ diff --git a/src/test/run-make/output-filename-conflicts-with-directory/Makefile b/src/test/run-make/output-filename-conflicts-with-directory/Makefile new file mode 100644 index 00000000000..74e5dcfcf36 --- /dev/null +++ b/src/test/run-make/output-filename-conflicts-with-directory/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +all: + cp foo.rs $(TMPDIR)/foo.rs + mkdir $(TMPDIR)/foo + $(RUSTC) $(TMPDIR)/foo.rs -o $(TMPDIR)/foo 2>&1 \ + | $(CGREP) -e "the generated executable for the input file \".*foo\.rs\" conflicts with the existing directory \".*foo\"" diff --git a/src/test/run-make/output-filename-conflicts-with-directory/foo.rs b/src/test/run-make/output-filename-conflicts-with-directory/foo.rs new file mode 100644 index 00000000000..3f07b46791d --- /dev/null +++ b/src/test/run-make/output-filename-conflicts-with-directory/foo.rs @@ -0,0 +1,11 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() {} diff --git a/src/test/run-make/output-filename-overwrites-input/Makefile b/src/test/run-make/output-filename-overwrites-input/Makefile index 0554627d677..6377038b7be 100644 --- a/src/test/run-make/output-filename-overwrites-input/Makefile +++ b/src/test/run-make/output-filename-overwrites-input/Makefile @@ -2,8 +2,11 @@ all: cp foo.rs $(TMPDIR)/foo - $(RUSTC) $(TMPDIR)/foo 2>&1 \ + $(RUSTC) $(TMPDIR)/foo -o $(TMPDIR)/foo 2>&1 \ | $(CGREP) -e "the input file \".*foo\" would be overwritten by the generated executable" + cp bar.rs $(TMPDIR)/bar.rlib + $(RUSTC) $(TMPDIR)/bar.rlib -o $(TMPDIR)/bar.rlib 2>&1 \ + | $(CGREP) -e "the input file \".*bar.rlib\" would be overwritten by the generated executable" $(RUSTC) foo.rs 2>&1 && $(RUSTC) -Z ls $(TMPDIR)/foo 2>&1 cp foo.rs $(TMPDIR)/foo.rs $(RUSTC) $(TMPDIR)/foo.rs -o $(TMPDIR)/foo.rs 2>&1 \ diff --git a/src/test/run-make/output-filename-overwrites-input/bar.rs b/src/test/run-make/output-filename-overwrites-input/bar.rs new file mode 100644 index 00000000000..8e4e35fdee6 --- /dev/null +++ b/src/test/run-make/output-filename-overwrites-input/bar.rs @@ -0,0 +1,11 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "lib"] diff --git a/src/test/run-make/output-filename-overwrites-input/foo.rs b/src/test/run-make/output-filename-overwrites-input/foo.rs index 046d27a9f0f..3f07b46791d 100644 --- a/src/test/run-make/output-filename-overwrites-input/foo.rs +++ b/src/test/run-make/output-filename-overwrites-input/foo.rs @@ -1,4 +1,4 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/test/run-make/save-analysis-fail/foo.rs b/src/test/run-make/save-analysis-fail/foo.rs index 8a1b5793989..07322d8bbc3 100644 --- a/src/test/run-make/save-analysis-fail/foo.rs +++ b/src/test/run-make/save-analysis-fail/foo.rs @@ -451,3 +451,11 @@ fn test_format_args() { static EXTERN_FOO: u8; fn extern_foo(a: u8, b: i32) -> String; } + +struct Rls699 { + f: u32, +} + +fn new(f: u32) -> Rls699 { + Rls699 { fs } +} diff --git a/src/test/run-make/save-analysis/extra-docs.md b/src/test/run-make/save-analysis/extra-docs.md new file mode 100644 index 00000000000..0605ca517ff --- /dev/null +++ b/src/test/run-make/save-analysis/extra-docs.md @@ -0,0 +1 @@ +Extra docs for this struct. diff --git a/src/test/run-make/save-analysis/foo.rs b/src/test/run-make/save-analysis/foo.rs index 834a7554a55..5b4e4802957 100644 --- a/src/test/run-make/save-analysis/foo.rs +++ b/src/test/run-make/save-analysis/foo.rs @@ -12,6 +12,7 @@ #![feature(box_syntax)] #![feature(rustc_private)] #![feature(associated_type_defaults)] +#![feature(external_doc)] extern crate graphviz; // A simple rust project @@ -461,3 +462,6 @@ fn next(&mut self) -> Option { trait Foo { type Bar = FrameBuffer; } + +#[doc(include="extra-docs.md")] +struct StructWithDocs; diff --git a/src/test/run-make/stdin-non-utf8/Makefile b/src/test/run-make/stdin-non-utf8/Makefile new file mode 100644 index 00000000000..7948c442616 --- /dev/null +++ b/src/test/run-make/stdin-non-utf8/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: + cp non-utf8 $(TMPDIR)/non-utf.rs + cat $(TMPDIR)/non-utf.rs | $(RUSTC) - 2>&1 \ + | $(CGREP) "error: couldn't read from stdin, as it did not contain valid UTF-8" diff --git a/src/test/run-make/stdin-non-utf8/non-utf8 b/src/test/run-make/stdin-non-utf8/non-utf8 new file mode 100644 index 00000000000..bc87051a852 --- /dev/null +++ b/src/test/run-make/stdin-non-utf8/non-utf8 @@ -0,0 +1 @@ +Ò 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 b5d6ff595af..9ebc438ad5a 100644 --- a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs +++ b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs @@ -18,6 +18,7 @@ extern crate rustc; extern crate rustc_plugin; +use syntax::feature_gate::Features; use syntax::parse::token::{NtExpr, NtPat}; use syntax::ast::{Ident, Pat}; use syntax::tokenstream::{TokenTree}; @@ -31,11 +32,17 @@ use syntax_pos::Span; use rustc_plugin::Registry; +use std::cell::RefCell; + fn expand_mbe_matches(cx: &mut ExtCtxt, _: Span, args: &[TokenTree]) -> Box { let mbe_matcher = quote_tokens!(cx, $$matched:expr, $$($$pat:pat)|+); - let mbe_matcher = quoted::parse(mbe_matcher.into_iter().collect(), true, cx.parse_sess); + let mbe_matcher = quoted::parse(mbe_matcher.into_iter().collect(), + true, + cx.parse_sess, + &RefCell::new(Features::new()), + &[]); let map = match TokenTree::parse(cx, &mbe_matcher, args.iter().cloned().collect()) { Success(map) => map, Failure(_, tok) => { diff --git a/src/test/run-pass/backtrace-debuginfo.rs b/src/test/run-pass/backtrace-debuginfo.rs index e8b5f3490e5..2b82a894363 100644 --- a/src/test/run-pass/backtrace-debuginfo.rs +++ b/src/test/run-pass/backtrace-debuginfo.rs @@ -15,11 +15,14 @@ // Unfortunately, LLVM has no "disable" option for this, so we have to set // "enable" to 0 instead. -// compile-flags:-g -Cllvm-args=-enable-tail-merge=0 +// compile-flags:-g -Cllvm-args=-enable-tail-merge=0 -Cllvm-args=-opt-bisect-limit=0 // ignore-pretty issue #37195 // ignore-cloudabi spawning processes is not supported // ignore-emscripten spawning processes is not supported +// note that above `-opt-bisect-limit=0` is used to basically disable +// optimizations + use std::env; #[path = "backtrace-debuginfo-aux.rs"] mod aux; @@ -114,18 +117,26 @@ fn outer(mut counter: i32, main_pos: Pos) { inner_inlined(&mut counter, main_pos, pos!()); } -fn check_trace(output: &str, error: &str) { +fn check_trace(output: &str, error: &str) -> Result<(), String> { // reverse the position list so we can start with the last item (which was the first line) let mut remaining: Vec<&str> = output.lines().map(|s| s.trim()).rev().collect(); - assert!(error.contains("stack backtrace"), "no backtrace in the error: {}", error); + if !error.contains("stack backtrace") { + return Err(format!("no backtrace found in stderr:\n{}", error)) + } for line in error.lines() { if !remaining.is_empty() && line.contains(remaining.last().unwrap()) { remaining.pop(); } } - assert!(remaining.is_empty(), - "trace does not match position list: {}\n---\n{}", error, output); + if !remaining.is_empty() { + return Err(format!("trace does not match position list\n\ + still need to find {:?}\n\n\ + --- stdout\n{}\n\ + --- stderr\n{}", + remaining, output, error)) + } + Ok(()) } fn run_test(me: &str) { @@ -133,6 +144,7 @@ fn run_test(me: &str) { use std::process::Command; let mut i = 0; + let mut errors = Vec::new(); loop { let out = Command::new(me) .env("RUST_BACKTRACE", "full") @@ -143,10 +155,20 @@ fn run_test(me: &str) { assert!(output.contains("done."), "bad output for successful run: {}", output); break; } else { - check_trace(output, error); + if let Err(e) = check_trace(output, error) { + errors.push(e); + } } i += 1; } + if errors.len() > 0 { + for error in errors { + println!("---------------------------------------"); + println!("{}", error); + } + + panic!("found some errors"); + } } #[inline(never)] diff --git a/src/test/run-pass/const-typeid-of.rs b/src/test/run-pass/const-typeid-of.rs new file mode 100644 index 00000000000..ce29e55c6d7 --- /dev/null +++ b/src/test/run-pass/const-typeid-of.rs @@ -0,0 +1,43 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(core_intrinsics)] +#![feature(const_type_id)] + +use std::any::TypeId; + +struct A; + +static ID_ISIZE: TypeId = TypeId::of::(); + +pub fn main() { + assert_eq!(ID_ISIZE, TypeId::of::()); + + // sanity test of TypeId + const T: (TypeId, TypeId, TypeId) = (TypeId::of::(), + TypeId::of::<&'static str>(), + TypeId::of::()); + let (d, e, f) = (TypeId::of::(), TypeId::of::<&'static str>(), + TypeId::of::()); + + assert!(T.0 != T.1); + assert!(T.0 != T.2); + assert!(T.1 != T.2); + + assert_eq!(T.0, d); + assert_eq!(T.1, e); + assert_eq!(T.2, f); + + // Check fn pointer against collisions + const F: (TypeId, TypeId) = (TypeId::of:: A) -> A>(), + TypeId::of:: A, A) -> A>()); + + assert!(F.0 != F.1); +} diff --git a/src/test/run-pass/env-home-dir.rs b/src/test/run-pass/env-home-dir.rs index 22e440c6ffa..9bbff1eeb81 100644 --- a/src/test/run-pass/env-home-dir.rs +++ b/src/test/run-pass/env-home-dir.rs @@ -27,7 +27,10 @@ fn main() { if cfg!(target_os = "android") { assert!(home_dir().is_none()); } else { - assert!(home_dir().is_some()); + // When HOME is not set, some platforms return `None`, + // but others return `Some` with a default. + // Just check that it is not "/home/MountainView". + assert_ne!(home_dir(), Some(PathBuf::from("/home/MountainView"))); } } diff --git a/src/test/run-pass/generator/too-live-local-in-immovable-gen.rs b/src/test/run-pass/generator/too-live-local-in-immovable-gen.rs new file mode 100644 index 00000000000..2314533a681 --- /dev/null +++ b/src/test/run-pass/generator/too-live-local-in-immovable-gen.rs @@ -0,0 +1,28 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(generators)] + +fn main() { + unsafe { + static move || { + // Tests that the generator transformation finds out that `a` is not live + // during the yield expression. Type checking will also compute liveness + // and it should also find out that `a` is not live. + // The compiler will panic if the generator transformation finds that + // `a` is live and type checking finds it dead. + let a = { + yield (); + 4i32 + }; + &a; + }; + } +} diff --git a/src/test/run-pass/issue-18514.rs b/src/test/run-pass/issue-18514.rs index 88bf95f036b..2a1e55d867f 100644 --- a/src/test/run-pass/issue-18514.rs +++ b/src/test/run-pass/issue-18514.rs @@ -10,7 +10,7 @@ // Test that we don't ICE when translating a generic impl method from // an extern crate that contains a match expression on a local -// variable lvalue where one of the match case bodies contains an +// variable place where one of the match case bodies contains an // expression that autoderefs through an overloaded generic deref // impl. diff --git a/src/test/run-pass/issue-18845.rs b/src/test/run-pass/issue-18845.rs index 3d8e0556a56..241408ddef1 100644 --- a/src/test/run-pass/issue-18845.rs +++ b/src/test/run-pass/issue-18845.rs @@ -11,7 +11,7 @@ // This used to generate invalid IR in that even if we took the // `false` branch we'd still try to free the Box from the other // arm. This was due to treating `*Box::new(9)` as an rvalue datum -// instead of as an lvalue. +// instead of as a place. fn test(foo: bool) -> u8 { match foo { diff --git a/src/test/run-pass/issue-47139-1.rs b/src/test/run-pass/issue-47139-1.rs new file mode 100644 index 00000000000..cb87991a491 --- /dev/null +++ b/src/test/run-pass/issue-47139-1.rs @@ -0,0 +1,87 @@ +// 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 issue #47139: +// +// Coherence was encountering an (unnecessary) overflow trying to +// decide if the two impls of dummy overlap. +// +// The overflow went something like: +// +// - `&'a ?T: Insertable` ? +// - let ?T = Option ? +// - `Option: Insertable` ? +// - `Option<&'a ?U>: Insertable` ? +// - `&'a ?U: Insertable` ? +// +// While somewhere in the middle, a projection would occur, which +// broke cycle detection. +// +// It turned out that this cycle was being kicked off due to some +// extended diagnostic attempts in coherence, so removing those +// sidestepped the issue for now. + +#![allow(dead_code)] + +pub trait Insertable { + type Values; + + fn values(self) -> Self::Values; +} + +impl Insertable for Option + where + T: Insertable, + T::Values: Default, +{ + type Values = T::Values; + + fn values(self) -> Self::Values { + self.map(Insertable::values).unwrap_or_default() + } +} + +impl<'a, T> Insertable for &'a Option + where + Option<&'a T>: Insertable, +{ + type Values = as Insertable>::Values; + + fn values(self) -> Self::Values { + self.as_ref().values() + } +} + +impl<'a, T> Insertable for &'a [T] +{ + type Values = Self; + + fn values(self) -> Self::Values { + self + } +} + +trait Unimplemented { } + +trait Dummy { } + +struct Foo { t: T } + +impl<'a, U> Dummy for Foo<&'a U> + where &'a U: Insertable +{ +} + +impl Dummy for T + where T: Unimplemented +{ } + +fn main() { +} diff --git a/src/test/run-pass/issue-47139-2.rs b/src/test/run-pass/issue-47139-2.rs new file mode 100644 index 00000000000..08eaee5acd7 --- /dev/null +++ b/src/test/run-pass/issue-47139-2.rs @@ -0,0 +1,75 @@ +// 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 issue #47139: +// +// Same as issue-47139-1.rs, but the impls of dummy are in the +// opposite order. This influenced the way that coherence ran and in +// some cases caused the overflow to occur when it wouldn't otherwise. +// In an effort to make the regr test more robust, I am including both +// orderings. + +#![allow(dead_code)] + +pub trait Insertable { + type Values; + + fn values(self) -> Self::Values; +} + +impl Insertable for Option + where + T: Insertable, + T::Values: Default, +{ + type Values = T::Values; + + fn values(self) -> Self::Values { + self.map(Insertable::values).unwrap_or_default() + } +} + +impl<'a, T> Insertable for &'a Option + where + Option<&'a T>: Insertable, +{ + type Values = as Insertable>::Values; + + fn values(self) -> Self::Values { + self.as_ref().values() + } +} + +impl<'a, T> Insertable for &'a [T] +{ + type Values = Self; + + fn values(self) -> Self::Values { + self + } +} + +trait Unimplemented { } + +trait Dummy { } + +struct Foo { t: T } + +impl Dummy for T + where T: Unimplemented +{ } + +impl<'a, U> Dummy for Foo<&'a U> + where &'a U: Insertable +{ +} + +fn main() { +} diff --git a/src/test/run-pass/issue-47638.rs b/src/test/run-pass/issue-47638.rs new file mode 100644 index 00000000000..6f627b2a3c1 --- /dev/null +++ b/src/test/run-pass/issue-47638.rs @@ -0,0 +1,18 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn id<'c, 'b>(f: &'c &'b Fn(&i32)) -> &'c &'b Fn(&'static i32) { + f +} + +fn main() { + let f: &Fn(&i32) = &|x| {}; + id(&f); +} diff --git a/src/test/run-pass/issue-47673.rs b/src/test/run-pass/issue-47673.rs index 92f54a44f63..22f7f169e29 100644 --- a/src/test/run-pass/issue-47673.rs +++ b/src/test/run-pass/issue-47673.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(use_nested_groups)] #![allow(unused_import)] use {{}, {}}; diff --git a/src/test/run-pass/issue-47722.rs b/src/test/run-pass/issue-47722.rs new file mode 100644 index 00000000000..3b5d808e1f5 --- /dev/null +++ b/src/test/run-pass/issue-47722.rs @@ -0,0 +1,26 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// Tests that automatic coercions from &mut T to *mut T +// allow borrows of T to expire immediately - essentially, that +// they work identically to 'foo as *mut T' +#![feature(nll)] + +struct SelfReference { + self_reference: *mut SelfReference, +} + +impl SelfReference { + fn set_self_ref(&mut self) { + self.self_reference = self; + } +} + +fn main() {} diff --git a/src/test/run-pass/issue-47789.rs b/src/test/run-pass/issue-47789.rs new file mode 100644 index 00000000000..3148939992c --- /dev/null +++ b/src/test/run-pass/issue-47789.rs @@ -0,0 +1,20 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +#![feature(nll)] + +static mut x: &'static u32 = &0; + +fn foo() { + unsafe { x = &1; } +} + +fn main() { } diff --git a/src/test/run-pass/macro-at-most-once-rep.rs b/src/test/run-pass/macro-at-most-once-rep.rs new file mode 100644 index 00000000000..b7e942f9383 --- /dev/null +++ b/src/test/run-pass/macro-at-most-once-rep.rs @@ -0,0 +1,88 @@ +// 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 logic for parsing Kleene operators in macros has a special case to disambiguate `?`. +// Specifically, `$(pat)?` is the ZeroOrOne operator whereas `$(pat)?+` or `$(pat)?*` are the +// ZeroOrMore and OneOrMore operators using `?` as a separator. These tests are intended to +// exercise that logic in the macro parser. +// +// Moreover, we also throw in some tests for using a separator with `?`, which is meaningless but +// included for consistency with `+` and `*`. +// +// This test focuses on non-error cases and making sure the correct number of repetitions happen. + +#![feature(macro_at_most_once_rep)] + +macro_rules! foo { + ($($a:ident)? ; $num:expr) => { { + let mut x = 0; + + $( + x += $a; + )? + + assert_eq!(x, $num); + } } +} + +macro_rules! baz { + ($($a:ident),? ; $num:expr) => { { // comma separator is meaningless for `?` + let mut x = 0; + + $( + x += $a; + )? + + assert_eq!(x, $num); + } } +} + +macro_rules! barplus { + ($($a:ident)?+ ; $num:expr) => { { + let mut x = 0; + + $( + x += $a; + )+ + + assert_eq!(x, $num); + } } +} + +macro_rules! barstar { + ($($a:ident)?* ; $num:expr) => { { + let mut x = 0; + + $( + x += $a; + )* + + assert_eq!(x, $num); + } } +} + +pub fn main() { + let a = 1; + + // accept 0 or 1 repetitions + foo!( ; 0); + foo!(a ; 1); + baz!( ; 0); + baz!(a ; 1); + + // Make sure using ? as a separator works as before + barplus!(a ; 1); + barplus!(a?a ; 2); + barplus!(a?a?a ; 3); + barstar!( ; 0); + barstar!(a ; 1); + barstar!(a?a ; 2); + barstar!(a?a?a ; 3); +} diff --git a/src/test/run-pass/match-beginning-vert.rs b/src/test/run-pass/match-beginning-vert.rs new file mode 100644 index 00000000000..cdacfb2f057 --- /dev/null +++ b/src/test/run-pass/match-beginning-vert.rs @@ -0,0 +1,28 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +enum Foo { + A, + B, + C, + D, + E, +} +use Foo::*; + +fn main() { + for foo in &[A, B, C, D, E] { + match *foo { + | A => println!("A"), + | B | C if 1 < 2 => println!("BC!"), + | _ => {}, + } + } +} diff --git a/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs b/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs index c729f736115..4de8f6a7194 100644 --- a/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs +++ b/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that an `&mut self` method, when invoked on an lvalue whose -// type is `&mut [u8]`, passes in a pointer to the lvalue and not a +// Test that an `&mut self` method, when invoked on a place whose +// type is `&mut [u8]`, passes in a pointer to the place and not a // temporary. Issue #19147. use std::slice; diff --git a/src/test/run-pass/mir_drop_order.rs b/src/test/run-pass/mir_drop_order.rs index 41cb458c0b8..7ab133bbab4 100644 --- a/src/test/run-pass/mir_drop_order.rs +++ b/src/test/run-pass/mir_drop_order.rs @@ -41,7 +41,7 @@ fn main() { // all borrows are extended - nothing has been dropped yet assert_eq!(get(), vec![]); } - // in a let-statement, extended lvalues are dropped + // in a let-statement, extended places are dropped // *after* the let result (tho they have the same scope // as far as scope-based borrowck goes). assert_eq!(get(), vec![0, 2, 3, 1]); diff --git a/src/test/run-pass/nll/issue-47589.rs b/src/test/run-pass/nll/issue-47589.rs new file mode 100644 index 00000000000..393c18efad0 --- /dev/null +++ b/src/test/run-pass/nll/issue-47589.rs @@ -0,0 +1,33 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(nll)] + +pub struct DescriptorSet<'a> { + pub slots: Vec> +} + +pub trait ResourcesTrait<'r>: Sized { + type DescriptorSet: 'r; +} + +pub struct Resources; + +impl<'a> ResourcesTrait<'a> for Resources { + type DescriptorSet = DescriptorSet<'a>; +} + +pub enum AttachInfo<'a, R: ResourcesTrait<'a>> { + NextDescriptorSet(Box) +} + +fn main() { + let _x = DescriptorSet {slots: Vec::new()}; +} diff --git a/src/test/run-pass/sse2.rs b/src/test/run-pass/sse2.rs index c2414e5ff5d..22469b2fde0 100644 --- a/src/test/run-pass/sse2.rs +++ b/src/test/run-pass/sse2.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// min-llvm-version 4.0 +// no-system-llvm -- needs MCSubtargetInfo::getFeatureTable() // ignore-cloudabi no std::env #![feature(cfg_target_feature)] diff --git a/src/test/run-pass/stack-probes-lto.rs b/src/test/run-pass/stack-probes-lto.rs index 22555c8d6a7..4deced1297b 100644 --- a/src/test/run-pass/stack-probes-lto.rs +++ b/src/test/run-pass/stack-probes-lto.rs @@ -15,7 +15,7 @@ // ignore-emscripten no processes // ignore-musl FIXME #31506 // ignore-pretty -// no-system-llvm +// min-system-llvm-version 5.0 // compile-flags: -C lto // no-prefer-dynamic diff --git a/src/test/run-pass/stack-probes.rs b/src/test/run-pass/stack-probes.rs index 248ad701926..4224a65ffd7 100644 --- a/src/test/run-pass/stack-probes.rs +++ b/src/test/run-pass/stack-probes.rs @@ -14,7 +14,7 @@ // ignore-cloudabi no processes // ignore-emscripten no processes // ignore-musl FIXME #31506 -// no-system-llvm +// min-system-llvm-version 5.0 use std::mem; use std::process::Command; diff --git a/src/test/run-pass/type-ascription.rs b/src/test/run-pass/type-ascription.rs index bca384c6471..18fb8e2e408 100644 --- a/src/test/run-pass/type-ascription.rs +++ b/src/test/run-pass/type-ascription.rs @@ -40,6 +40,6 @@ fn main() { assert_eq!(b, 1: u16); let mut v = Vec::new(); - v: Vec = vec![1, 2, 3]; // Lvalue type ascription + v: Vec = vec![1, 2, 3]; // Place expression type ascription assert_eq!(v, [1u8, 2, 3]); } diff --git a/src/test/run-pass/use-nested-groups.rs b/src/test/run-pass/use-nested-groups.rs index 74a82afd462..be06e463e3b 100644 --- a/src/test/run-pass/use-nested-groups.rs +++ b/src/test/run-pass/use-nested-groups.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(use_nested_groups)] - mod a { pub enum B {} @@ -24,12 +22,19 @@ pub enum I {} } } +// Test every possible part of the syntax use a::{B, d::{self, *, g::H}}; +// Test a more common use case +use std::sync::{Arc, atomic::{AtomicBool, Ordering}}; + fn main() { let _: B; let _: E; let _: F; let _: H; let _: d::g::I; + + let _: Arc; + let _: Ordering; } diff --git a/src/test/rustdoc/auxiliary/unit-return.rs b/src/test/rustdoc/auxiliary/unit-return.rs new file mode 100644 index 00000000000..1b30a6a4328 --- /dev/null +++ b/src/test/rustdoc/auxiliary/unit-return.rs @@ -0,0 +1,13 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn f2(f: F) {} + +pub fn f3 () + Clone>(f: F) {} diff --git a/src/test/rustdoc/const-evalutation-ice.rs b/src/test/rustdoc/const-evalutation-ice.rs new file mode 100644 index 00000000000..9fed67ee583 --- /dev/null +++ b/src/test/rustdoc/const-evalutation-ice.rs @@ -0,0 +1,22 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Just check if we don't get an ICE for the _S type. + +#![feature(const_size_of)] + +use std::cell::Cell; +use std::mem; + +pub struct S { + s: Cell +} + +pub type _S = [usize; 0 - (mem::size_of::() != 4) as usize]; diff --git a/src/test/rustdoc/issue-47639.rs b/src/test/rustdoc/issue-47639.rs new file mode 100644 index 00000000000..167c3aaec4a --- /dev/null +++ b/src/test/rustdoc/issue-47639.rs @@ -0,0 +1,16 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// This should not ICE +pub fn test() { + macro_rules! foo { + () => () + } +} diff --git a/src/test/rustdoc/link-title-escape.rs b/src/test/rustdoc/link-title-escape.rs new file mode 100644 index 00000000000..eb53c3c2cb5 --- /dev/null +++ b/src/test/rustdoc/link-title-escape.rs @@ -0,0 +1,19 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z unstable-options --disable-commonmark + +#![crate_name = "foo"] + +//! hello [foo] +//! +//! [foo]: url 'title & & "things"' + +// @has 'foo/index.html' 'title & <stuff> & "things"' diff --git a/src/test/rustdoc/unit-return.rs b/src/test/rustdoc/unit-return.rs new file mode 100644 index 00000000000..757e8979edd --- /dev/null +++ b/src/test/rustdoc/unit-return.rs @@ -0,0 +1,27 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:unit-return.rs + +#![crate_name = "foo"] + +extern crate unit_return; + +// @has 'foo/fn.f0.html' '//*[@class="rust fn"]' 'F: FnMut(u8) + Clone' +pub fn f0(f: F) {} + +// @has 'foo/fn.f1.html' '//*[@class="rust fn"]' 'F: FnMut(u16) + Clone' +pub fn f1 () + Clone>(f: F) {} + +// @has 'foo/fn.f2.html' '//*[@class="rust fn"]' 'F: FnMut(u32) + Clone' +pub use unit_return::f2; + +// @has 'foo/fn.f3.html' '//*[@class="rust fn"]' 'F: FnMut(u64) + Clone' +pub use unit_return::f3; diff --git a/src/test/ui/associated-const-impl-wrong-lifetime.stderr b/src/test/ui/associated-const-impl-wrong-lifetime.stderr index a7aee9b19f1..ab0e1003a9e 100644 --- a/src/test/ui/associated-const-impl-wrong-lifetime.stderr +++ b/src/test/ui/associated-const-impl-wrong-lifetime.stderr @@ -9,11 +9,8 @@ error[E0308]: mismatched types note: the lifetime 'a as defined on the impl at 17:1... --> $DIR/associated-const-impl-wrong-lifetime.rs:17:1 | -17 | / impl<'a> Foo for &'a () { -18 | | const NAME: &'a str = "unit"; -19 | | //~^ ERROR mismatched types [E0308] -20 | | } - | |_^ +17 | impl<'a> Foo for &'a () { + | ^^^^^^^^^^^^^^^^^^^^^^^ = note: ...does not necessarily outlive the static lifetime error: aborting due to previous error diff --git a/src/test/ui/blind-item-item-shadow.stderr b/src/test/ui/blind-item-item-shadow.stderr index 855b3799eb5..d3588be2669 100644 --- a/src/test/ui/blind-item-item-shadow.stderr +++ b/src/test/ui/blind-item-item-shadow.stderr @@ -10,8 +10,8 @@ error[E0255]: the name `foo` is defined multiple times = note: `foo` must be defined only once in the type namespace of this module help: You can use `as` to change the binding name of the import | -13 | use foo::foo as Otherfoo; - | ^^^^^^^^^^^^^^^^^^^^ +13 | use foo::foo as other_foo; + | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-41962.rs b/src/test/ui/borrowck/issue-41962.rs index d592be11335..f7c33691ad0 100644 --- a/src/test/ui/borrowck/issue-41962.rs +++ b/src/test/ui/borrowck/issue-41962.rs @@ -18,6 +18,7 @@ pub fn main(){ //~^ ERROR use of partially moved value: `maybe` (Ast) [E0382] //~| ERROR use of moved value: `(maybe as std::prelude::v1::Some).0` (Ast) [E0382] //~| ERROR use of moved value: `maybe` (Mir) [E0382] + //~| ERROR use of moved value: `maybe` (Mir) [E0382] //~| ERROR use of moved value: `maybe.0` (Mir) [E0382] } } diff --git a/src/test/ui/borrowck/issue-41962.stderr b/src/test/ui/borrowck/issue-41962.stderr index 50d51c4d907..13305fd9656 100644 --- a/src/test/ui/borrowck/issue-41962.stderr +++ b/src/test/ui/borrowck/issue-41962.stderr @@ -16,6 +16,23 @@ error[E0382]: use of moved value: `(maybe as std::prelude::v1::Some).0` (Ast) | = note: move occurs because the value has type `std::vec::Vec`, which does not implement the `Copy` trait +error[E0382]: use of moved value: `maybe` (Mir) + --> $DIR/issue-41962.rs:17:9 + | +17 | if let Some(thing) = maybe { + | ^ ----- value moved here + | _________| + | | +18 | | //~^ ERROR use of partially moved value: `maybe` (Ast) [E0382] +19 | | //~| ERROR use of moved value: `(maybe as std::prelude::v1::Some).0` (Ast) [E0382] +20 | | //~| ERROR use of moved value: `maybe` (Mir) [E0382] +21 | | //~| ERROR use of moved value: `maybe` (Mir) [E0382] +22 | | //~| ERROR use of moved value: `maybe.0` (Mir) [E0382] +23 | | } + | |_________^ value used here after move + | + = note: move occurs because `maybe` has type `std::option::Option>`, which does not implement the `Copy` trait + error[E0382]: use of moved value: `maybe` (Mir) --> $DIR/issue-41962.rs:17:16 | @@ -35,5 +52,5 @@ error[E0382]: use of moved value: `maybe.0` (Mir) | = note: move occurs because `maybe.0` has type `std::vec::Vec`, which does not implement the `Copy` trait -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors diff --git a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.rs b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.rs new file mode 100644 index 00000000000..617de2c5dfe --- /dev/null +++ b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.rs @@ -0,0 +1,58 @@ +// 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. + +// Check that explicit region bounds are allowed on the various +// nominal types (but not on other types) and that they are type +// checked. + +struct Inv<'a> { // invariant w/r/t 'a + x: &'a mut &'a isize +} + +pub trait Foo<'a, 't> { + fn no_bound<'b>(self, b: Inv<'b>); + fn has_bound<'b:'a>(self, b: Inv<'b>); + fn wrong_bound1<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>); + fn okay_bound<'b,'c,'d:'a+'b+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>); + fn another_bound<'x: 'a>(self, x: Inv<'x>, y: Inv<'t>); +} + +impl<'a, 't> Foo<'a, 't> for &'a isize { + fn no_bound<'b:'a>(self, b: Inv<'b>) { + //~^ ERROR lifetime parameters or bounds on method `no_bound` do not match + } + + fn has_bound<'b>(self, b: Inv<'b>) { + //~^ ERROR lifetime parameters or bounds on method `has_bound` do not match + } + + fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { + //~^ ERROR method not compatible with trait + // + // Note: This is a terrible error message. It is caused + // because, in the trait, 'b is early bound, and in the impl, + // 'c is early bound, so -- after substitution -- the + // lifetimes themselves look isomorphic. We fail because the + // lifetimes that appear in the types are in the wrong + // order. This should really be fixed by keeping more + // information about the lifetime declarations in the trait so + // that we can compare better to the impl, even in cross-crate + // cases. + } + + fn okay_bound<'b,'c,'e:'b+'c>(self, b: Inv<'b>, c: Inv<'c>, e: Inv<'e>) { + } + + fn another_bound<'x: 't>(self, x: Inv<'x>, y: Inv<'t>) { + //~^ ERROR E0276 + } +} + +fn main() { } diff --git a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr new file mode 100644 index 00000000000..e8323247af9 --- /dev/null +++ b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr @@ -0,0 +1,48 @@ +error[E0195]: lifetime parameters or bounds on method `no_bound` do not match the trait declaration + --> $DIR/regions-bound-missing-bound-in-impl.rs:28:5 + | +20 | fn no_bound<'b>(self, b: Inv<'b>); + | ---------------------------------- lifetimes in impl do not match this method in trait +... +28 | fn no_bound<'b:'a>(self, b: Inv<'b>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait + +error[E0195]: lifetime parameters or bounds on method `has_bound` do not match the trait declaration + --> $DIR/regions-bound-missing-bound-in-impl.rs:32:5 + | +21 | fn has_bound<'b:'a>(self, b: Inv<'b>); + | -------------------------------------- lifetimes in impl do not match this method in trait +... +32 | fn has_bound<'b>(self, b: Inv<'b>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait + +error[E0308]: method not compatible with trait + --> $DIR/regions-bound-missing-bound-in-impl.rs:36:5 + | +36 | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected type `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'d>)` + found type `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'d>)` +note: the lifetime 'c as defined on the method body at 36:5... + --> $DIR/regions-bound-missing-bound-in-impl.rs:36:5 + | +36 | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...does not necessarily outlive the lifetime 'c as defined on the method body at 36:5 + --> $DIR/regions-bound-missing-bound-in-impl.rs:36:5 + | +36 | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0276]: impl has stricter requirements than trait + --> $DIR/regions-bound-missing-bound-in-impl.rs:53:5 + | +24 | fn another_bound<'x: 'a>(self, x: Inv<'x>, y: Inv<'t>); + | ------------------------------------------------------- definition of `another_bound` from trait +... +53 | fn another_bound<'x: 't>(self, x: Inv<'x>, y: Inv<'t>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `'x: 't` + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/closure-expected-type/expect-region-supply-region.stderr b/src/test/ui/closure-expected-type/expect-region-supply-region.stderr index ebb1e561e57..5c612522d9a 100644 --- a/src/test/ui/closure-expected-type/expect-region-supply-region.stderr +++ b/src/test/ui/closure-expected-type/expect-region-supply-region.stderr @@ -41,14 +41,8 @@ note: the anonymous lifetime #2 defined on the body at 47:29... note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 42:1 --> $DIR/expect-region-supply-region.rs:42:1 | -42 | / fn expect_bound_supply_named<'x>() { -43 | | let mut f: Option<&u32> = None; -44 | | -45 | | // Here we give a type annotation that `x` should be free. We get -... | -54 | | }); -55 | | } - | |_^ +42 | fn expect_bound_supply_named<'x>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/expect-region-supply-region.rs:47:33 @@ -61,14 +55,8 @@ error[E0308]: mismatched types note: the lifetime 'x as defined on the function body at 42:1... --> $DIR/expect-region-supply-region.rs:42:1 | -42 | / fn expect_bound_supply_named<'x>() { -43 | | let mut f: Option<&u32> = None; -44 | | -45 | | // Here we give a type annotation that `x` should be free. We get -... | -54 | | }); -55 | | } - | |_^ +42 | fn expect_bound_supply_named<'x>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 47:29 --> $DIR/expect-region-supply-region.rs:47:29 | diff --git a/src/test/ui/cross-file-errors/main.rs b/src/test/ui/cross-file-errors/main.rs new file mode 100644 index 00000000000..8eae79a21a9 --- /dev/null +++ b/src/test/ui/cross-file-errors/main.rs @@ -0,0 +1,16 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +mod underscore; + +fn main() { + underscore!(); +} diff --git a/src/test/ui/cross-file-errors/main.stderr b/src/test/ui/cross-file-errors/main.stderr new file mode 100644 index 00000000000..a1cdae10edf --- /dev/null +++ b/src/test/ui/cross-file-errors/main.stderr @@ -0,0 +1,11 @@ +error: expected expression, found `_` + --> $DIR/underscore.rs:18:9 + | +18 | _ + | ^ + | + ::: $DIR/main.rs:15:5 + | +15 | underscore!(); + | -------------- in this macro invocation + diff --git a/src/test/ui/cross-file-errors/underscore.rs b/src/test/ui/cross-file-errors/underscore.rs new file mode 100644 index 00000000000..312b3b8f4dd --- /dev/null +++ b/src/test/ui/cross-file-errors/underscore.rs @@ -0,0 +1,20 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// We want this file only so we can test cross-file error +// messages, but we don't want it in an external crate. +// ignore-test +#![crate_type = "lib"] + +macro_rules! underscore { + () => ( + _ + ) +} diff --git a/src/test/ui/double-import.stderr b/src/test/ui/double-import.stderr index fcd3f2696f2..2a0f9ee34f2 100644 --- a/src/test/ui/double-import.stderr +++ b/src/test/ui/double-import.stderr @@ -9,8 +9,8 @@ error[E0252]: the name `foo` is defined multiple times = note: `foo` must be defined only once in the value namespace of this module help: You can use `as` to change the binding name of the import | -23 | use sub2::foo as Otherfoo; //~ ERROR the name `foo` is defined multiple times - | ^^^^^^^^^^^^^^^^^^^^^ +23 | use sub2::foo as other_foo; //~ ERROR the name `foo` is defined multiple times + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0001.rs b/src/test/ui/error-codes/E0001.rs new file mode 100644 index 00000000000..b72b0d66190 --- /dev/null +++ b/src/test/ui/error-codes/E0001.rs @@ -0,0 +1,20 @@ +// 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. + +#![deny(unreachable_patterns)] + +fn main() { + let foo = Some(1); + match foo { + Some(_) => {/* ... */} + None => {/* ... */} + _ => {/* ... */} //~ ERROR unreachable pattern + } +} diff --git a/src/test/ui/error-codes/E0001.stderr b/src/test/ui/error-codes/E0001.stderr new file mode 100644 index 00000000000..d7d67af1492 --- /dev/null +++ b/src/test/ui/error-codes/E0001.stderr @@ -0,0 +1,14 @@ +error: unreachable pattern + --> $DIR/E0001.rs:18:9 + | +18 | _ => {/* ... */} //~ ERROR unreachable pattern + | ^ + | +note: lint level defined here + --> $DIR/E0001.rs:11:9 + | +11 | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0004-2.rs b/src/test/ui/error-codes/E0004-2.rs new file mode 100644 index 00000000000..824b86cfa83 --- /dev/null +++ b/src/test/ui/error-codes/E0004-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 main() { + let x = Some(1); + + match x { } //~ ERROR E0004 +} diff --git a/src/test/ui/error-codes/E0004-2.stderr b/src/test/ui/error-codes/E0004-2.stderr new file mode 100644 index 00000000000..2f4d26e2f32 --- /dev/null +++ b/src/test/ui/error-codes/E0004-2.stderr @@ -0,0 +1,14 @@ +error[E0004]: non-exhaustive patterns: type std::option::Option is non-empty + --> $DIR/E0004-2.rs:14:11 + | +14 | match x { } //~ ERROR E0004 + | ^ + | +help: Please ensure that all possible cases are being handled; possibly adding wildcards or more match arms. + --> $DIR/E0004-2.rs:14:11 + | +14 | match x { } //~ ERROR E0004 + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0004.rs b/src/test/ui/error-codes/E0004.rs new file mode 100644 index 00000000000..8df07a0c1c5 --- /dev/null +++ b/src/test/ui/error-codes/E0004.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. + +enum Terminator { + HastaLaVistaBaby, + TalkToMyHand, +} + +fn main() { + let x = Terminator::HastaLaVistaBaby; + + match x { //~ ERROR E0004 + Terminator::TalkToMyHand => {} + } +} diff --git a/src/test/ui/error-codes/E0004.stderr b/src/test/ui/error-codes/E0004.stderr new file mode 100644 index 00000000000..836afaf05ba --- /dev/null +++ b/src/test/ui/error-codes/E0004.stderr @@ -0,0 +1,8 @@ +error[E0004]: non-exhaustive patterns: `HastaLaVistaBaby` not covered + --> $DIR/E0004.rs:19:11 + | +19 | match x { //~ ERROR E0004 + | ^ pattern `HastaLaVistaBaby` not covered + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0005.rs b/src/test/ui/error-codes/E0005.rs new file mode 100644 index 00000000000..0405bba81b5 --- /dev/null +++ b/src/test/ui/error-codes/E0005.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. + +fn main() { + let x = Some(1); + let Some(y) = x; //~ ERROR E0005 +} diff --git a/src/test/ui/error-codes/E0005.stderr b/src/test/ui/error-codes/E0005.stderr new file mode 100644 index 00000000000..d052c12e9fe --- /dev/null +++ b/src/test/ui/error-codes/E0005.stderr @@ -0,0 +1,8 @@ +error[E0005]: refutable pattern in local binding: `None` not covered + --> $DIR/E0005.rs:13:9 + | +13 | let Some(y) = x; //~ ERROR E0005 + | ^^^^^^^ pattern `None` not covered + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0007.rs b/src/test/ui/error-codes/E0007.rs new file mode 100644 index 00000000000..d5acbdebbe9 --- /dev/null +++ b/src/test/ui/error-codes/E0007.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. + +fn main() { + let x = Some("s".to_string()); + match x { + op_string @ Some(s) => {}, + //~^ ERROR E0007 + //~| ERROR E0303 + None => {}, + } +} diff --git a/src/test/ui/error-codes/E0007.stderr b/src/test/ui/error-codes/E0007.stderr new file mode 100644 index 00000000000..1370cacd7cb --- /dev/null +++ b/src/test/ui/error-codes/E0007.stderr @@ -0,0 +1,14 @@ +error[E0007]: cannot bind by-move with sub-bindings + --> $DIR/E0007.rs:14:9 + | +14 | op_string @ Some(s) => {}, + | ^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it + +error[E0303]: pattern bindings are not allowed after an `@` + --> $DIR/E0007.rs:14:26 + | +14 | op_string @ Some(s) => {}, + | ^ not allowed after `@` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0008.rs b/src/test/ui/error-codes/E0008.rs new file mode 100644 index 00000000000..ba5720e6f0a --- /dev/null +++ b/src/test/ui/error-codes/E0008.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + match Some("hi".to_string()) { + Some(s) if s.len() == 0 => {}, + //~^ ERROR E0008 + _ => {}, + } +} diff --git a/src/test/ui/error-codes/E0008.stderr b/src/test/ui/error-codes/E0008.stderr new file mode 100644 index 00000000000..6ae4506a6e3 --- /dev/null +++ b/src/test/ui/error-codes/E0008.stderr @@ -0,0 +1,8 @@ +error[E0008]: cannot bind by-move into a pattern guard + --> $DIR/E0008.rs:13:14 + | +13 | Some(s) if s.len() == 0 => {}, + | ^ moves value into pattern guard + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0009.rs b/src/test/ui/error-codes/E0009.rs new file mode 100644 index 00000000000..02e2e80e7ea --- /dev/null +++ b/src/test/ui/error-codes/E0009.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. + +fn main() { + struct X { x: (), } + let x = Some((X { x: () }, X { x: () })); + match x { + Some((y, ref z)) => {}, + //~^ ERROR E0009 + None => panic!() + } +} diff --git a/src/test/ui/error-codes/E0009.stderr b/src/test/ui/error-codes/E0009.stderr new file mode 100644 index 00000000000..31db957621d --- /dev/null +++ b/src/test/ui/error-codes/E0009.stderr @@ -0,0 +1,10 @@ +error[E0009]: cannot bind by-move and by-ref in the same pattern + --> $DIR/E0009.rs:15:15 + | +15 | Some((y, ref z)) => {}, + | ^ ----- both by-ref and by-move used + | | + | by-move pattern here + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0010-teach.rs b/src/test/ui/error-codes/E0010-teach.rs new file mode 100644 index 00000000000..e5ccf32af14 --- /dev/null +++ b/src/test/ui/error-codes/E0010-teach.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. + +// compile-flags: -Z teach + +#![feature(box_syntax)] +#![allow(warnings)] + +const CON : Box = box 0; //~ ERROR E0010 + +fn main() {} diff --git a/src/test/ui/error-codes/E0010-teach.stderr b/src/test/ui/error-codes/E0010-teach.stderr new file mode 100644 index 00000000000..46f8101ca65 --- /dev/null +++ b/src/test/ui/error-codes/E0010-teach.stderr @@ -0,0 +1,10 @@ +error[E0010]: allocations are not allowed in constants + --> $DIR/E0010-teach.rs:16:24 + | +16 | const CON : Box = box 0; //~ ERROR E0010 + | ^^^^^ allocation not allowed in constants + | + = note: The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on the heap at runtime, and therefore cannot be done at compile time. + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0010.rs b/src/test/ui/error-codes/E0010.rs new file mode 100644 index 00000000000..66a9319a7df --- /dev/null +++ b/src/test/ui/error-codes/E0010.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(box_syntax)] +#![allow(warnings)] + +const CON : Box = box 0; //~ ERROR E0010 + +fn main() {} diff --git a/src/test/ui/error-codes/E0010.stderr b/src/test/ui/error-codes/E0010.stderr new file mode 100644 index 00000000000..5cef631e05e --- /dev/null +++ b/src/test/ui/error-codes/E0010.stderr @@ -0,0 +1,8 @@ +error[E0010]: allocations are not allowed in constants + --> $DIR/E0010.rs:14:24 + | +14 | const CON : Box = box 0; //~ ERROR E0010 + | ^^^^^ allocation not allowed in constants + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0017.rs b/src/test/ui/error-codes/E0017.rs new file mode 100644 index 00000000000..c98c35a1442 --- /dev/null +++ b/src/test/ui/error-codes/E0017.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. + +static X: i32 = 1; +const C: i32 = 2; + +const CR: &'static mut i32 = &mut C; //~ ERROR E0017 +static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 + //~| ERROR cannot borrow +static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017 +fn main() {} diff --git a/src/test/ui/error-codes/E0017.stderr b/src/test/ui/error-codes/E0017.stderr new file mode 100644 index 00000000000..f1fe1e58b34 --- /dev/null +++ b/src/test/ui/error-codes/E0017.stderr @@ -0,0 +1,26 @@ +error[E0017]: references in constants may only refer to immutable values + --> $DIR/E0017.rs:14:30 + | +14 | const CR: &'static mut i32 = &mut C; //~ ERROR E0017 + | ^^^^^^ constants require immutable values + +error[E0017]: references in statics may only refer to immutable values + --> $DIR/E0017.rs:15:39 + | +15 | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 + | ^^^^^^ statics require immutable values + +error[E0596]: cannot borrow immutable static item as mutable + --> $DIR/E0017.rs:15:44 + | +15 | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 + | ^ + +error[E0017]: references in statics may only refer to immutable values + --> $DIR/E0017.rs:17:38 + | +17 | static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017 + | ^^^^^^ statics require immutable values + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/error-codes/E0023.rs b/src/test/ui/error-codes/E0023.rs new file mode 100644 index 00000000000..24032c59844 --- /dev/null +++ b/src/test/ui/error-codes/E0023.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. + +enum Fruit { + Apple(String, String), + Pear(u32), +} + + +fn main() { + let x = Fruit::Apple(String::new(), String::new()); + match x { + Fruit::Apple(a) => {}, //~ ERROR E0023 + Fruit::Apple(a, b, c) => {}, //~ ERROR E0023 + Fruit::Pear(1, 2) => {}, //~ ERROR E0023 + } +} diff --git a/src/test/ui/error-codes/E0023.stderr b/src/test/ui/error-codes/E0023.stderr new file mode 100644 index 00000000000..582dffeb19c --- /dev/null +++ b/src/test/ui/error-codes/E0023.stderr @@ -0,0 +1,20 @@ +error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields + --> $DIR/E0023.rs:20:9 + | +20 | Fruit::Apple(a) => {}, //~ ERROR E0023 + | ^^^^^^^^^^^^^^^ expected 2 fields, found 1 + +error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields + --> $DIR/E0023.rs:21:9 + | +21 | Fruit::Apple(a, b, c) => {}, //~ ERROR E0023 + | ^^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 3 + +error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 1 field + --> $DIR/E0023.rs:22:9 + | +22 | Fruit::Pear(1, 2) => {}, //~ ERROR E0023 + | ^^^^^^^^^^^^^^^^^ expected 1 field, found 2 + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/error-codes/E0025.rs b/src/test/ui/error-codes/E0025.rs new file mode 100644 index 00000000000..81d0ea8a5e2 --- /dev/null +++ b/src/test/ui/error-codes/E0025.rs @@ -0,0 +1,20 @@ +// 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 { + a: u8, + b: u8, +} + +fn main() { + let x = Foo { a:1, b:2 }; + let Foo { a: x, a: y, b: 0 } = x; + //~^ ERROR field `a` bound multiple times in the pattern +} diff --git a/src/test/ui/error-codes/E0025.stderr b/src/test/ui/error-codes/E0025.stderr new file mode 100644 index 00000000000..480cd2a5cc8 --- /dev/null +++ b/src/test/ui/error-codes/E0025.stderr @@ -0,0 +1,10 @@ +error[E0025]: field `a` bound multiple times in the pattern + --> $DIR/E0025.rs:18:21 + | +18 | let Foo { a: x, a: y, b: 0 } = x; + | ---- ^^^^ multiple uses of `a` in pattern + | | + | first use of `a` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0026-teach.rs b/src/test/ui/error-codes/E0026-teach.rs new file mode 100644 index 00000000000..e0ce44a8b6f --- /dev/null +++ b/src/test/ui/error-codes/E0026-teach.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: -Z teach + +struct Thing { + x: u32, + y: u32 +} + +fn main() { + let thing = Thing { x: 0, y: 0 }; + match thing { + Thing { x, y, z } => {} + //~^ ERROR struct `Thing` does not have a field named `z` [E0026] + } +} diff --git a/src/test/ui/error-codes/E0026-teach.stderr b/src/test/ui/error-codes/E0026-teach.stderr new file mode 100644 index 00000000000..ee83cfb3535 --- /dev/null +++ b/src/test/ui/error-codes/E0026-teach.stderr @@ -0,0 +1,12 @@ +error[E0026]: struct `Thing` does not have a field named `z` + --> $DIR/E0026-teach.rs:21:23 + | +21 | Thing { x, y, z } => {} + | ^ struct `Thing` does not have field `z` + | + = note: This error indicates that a struct pattern attempted to extract a non-existent field from a struct. Struct fields are identified by the name used before the colon : so struct patterns should resemble the declaration of the struct type being matched. + + If you are using shorthand field patterns but want to refer to the struct field by a different name, you should rename it explicitly. + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0026.rs b/src/test/ui/error-codes/E0026.rs new file mode 100644 index 00000000000..f8ad7b5a30e --- /dev/null +++ b/src/test/ui/error-codes/E0026.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. + +struct Thing { + x: u32, + y: u32 +} + +fn main() { + let thing = Thing { x: 0, y: 0 }; + match thing { + Thing { x, y, z } => {} + //~^ ERROR struct `Thing` does not have a field named `z` [E0026] + } +} diff --git a/src/test/ui/error-codes/E0026.stderr b/src/test/ui/error-codes/E0026.stderr new file mode 100644 index 00000000000..c9819df3f9f --- /dev/null +++ b/src/test/ui/error-codes/E0026.stderr @@ -0,0 +1,8 @@ +error[E0026]: struct `Thing` does not have a field named `z` + --> $DIR/E0026.rs:19:23 + | +19 | Thing { x, y, z } => {} + | ^ struct `Thing` does not have field `z` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0027-teach.rs b/src/test/ui/error-codes/E0027-teach.rs new file mode 100644 index 00000000000..17e045bb8b0 --- /dev/null +++ b/src/test/ui/error-codes/E0027-teach.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. + +// compile-flags: -Z teach + +struct Dog { + name: String, + age: u32, +} + +fn main() { + let d = Dog { name: "Rusty".to_string(), age: 8 }; + + match d { + Dog { age: x } => {} + //~^ ERROR pattern does not mention field `name` + } +} diff --git a/src/test/ui/error-codes/E0027-teach.stderr b/src/test/ui/error-codes/E0027-teach.stderr new file mode 100644 index 00000000000..e9f9e4ba766 --- /dev/null +++ b/src/test/ui/error-codes/E0027-teach.stderr @@ -0,0 +1,10 @@ +error[E0027]: pattern does not mention field `name` + --> $DIR/E0027-teach.rs:22:9 + | +22 | Dog { age: x } => {} + | ^^^^^^^^^^^^^^ missing field `name` + | + = note: This error indicates that a pattern for a struct fails to specify a sub-pattern for every one of the struct's fields. Ensure that each field from the struct's definition is mentioned in the pattern, or use `..` to ignore unwanted fields. + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0027.rs b/src/test/ui/error-codes/E0027.rs new file mode 100644 index 00000000000..b63b0ab5dfd --- /dev/null +++ b/src/test/ui/error-codes/E0027.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 Dog { + name: String, + age: u32, +} + +fn main() { + let d = Dog { name: "Rusty".to_string(), age: 8 }; + + match d { + Dog { age: x } => {} + //~^ ERROR pattern does not mention field `name` + } +} diff --git a/src/test/ui/error-codes/E0027.stderr b/src/test/ui/error-codes/E0027.stderr new file mode 100644 index 00000000000..0f93a776b9e --- /dev/null +++ b/src/test/ui/error-codes/E0027.stderr @@ -0,0 +1,8 @@ +error[E0027]: pattern does not mention field `name` + --> $DIR/E0027.rs:20:9 + | +20 | Dog { age: x } => {} + | ^^^^^^^^^^^^^^ missing field `name` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0029-teach.rs b/src/test/ui/error-codes/E0029-teach.rs new file mode 100644 index 00000000000..ca85f58133c --- /dev/null +++ b/src/test/ui/error-codes/E0029-teach.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. + +// compile-flags: -Z teach + +fn main() { + let s = "hoho"; + + match s { + "hello" ... "world" => {} + //~^ ERROR only char and numeric types are allowed in range patterns + //~| ERROR non-reference pattern used to match a reference + _ => {} + } +} diff --git a/src/test/ui/error-codes/E0029-teach.stderr b/src/test/ui/error-codes/E0029-teach.stderr new file mode 100644 index 00000000000..dbb8d972f5c --- /dev/null +++ b/src/test/ui/error-codes/E0029-teach.stderr @@ -0,0 +1,20 @@ +error[E0658]: non-reference pattern used to match a reference (see issue #42640) + --> $DIR/E0029-teach.rs:17:9 + | +17 | "hello" ... "world" => {} + | ^^^^^^^^^^^^^^^^^^^ help: consider using a reference: `&"hello" ... "world"` + | + = help: add #![feature(match_default_bindings)] to the crate attributes to enable + +error[E0029]: only char and numeric types are allowed in range patterns + --> $DIR/E0029-teach.rs:17:9 + | +17 | "hello" ... "world" => {} + | ^^^^^^^^^^^^^^^^^^^ ranges require char or numeric types + | + = note: start type: &'static str + = note: end type: &'static str + = note: In a match expression, only numbers and characters can be matched against a range. This is because the compiler checks that the range is non-empty at compile-time, and is unable to evaluate arbitrary comparison functions. If you want to capture values of an orderable type between two end-points, you can use a guard. + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0029.rs b/src/test/ui/error-codes/E0029.rs new file mode 100644 index 00000000000..80d215bd327 --- /dev/null +++ b/src/test/ui/error-codes/E0029.rs @@ -0,0 +1,20 @@ +// 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 main() { + let s = "hoho"; + + match s { + "hello" ... "world" => {} + //~^ ERROR only char and numeric types are allowed in range patterns + //~| ERROR non-reference pattern used to match a reference + _ => {} + } +} diff --git a/src/test/ui/error-codes/E0029.stderr b/src/test/ui/error-codes/E0029.stderr new file mode 100644 index 00000000000..02fbd20386f --- /dev/null +++ b/src/test/ui/error-codes/E0029.stderr @@ -0,0 +1,19 @@ +error[E0658]: non-reference pattern used to match a reference (see issue #42640) + --> $DIR/E0029.rs:15:9 + | +15 | "hello" ... "world" => {} + | ^^^^^^^^^^^^^^^^^^^ help: consider using a reference: `&"hello" ... "world"` + | + = help: add #![feature(match_default_bindings)] to the crate attributes to enable + +error[E0029]: only char and numeric types are allowed in range patterns + --> $DIR/E0029.rs:15:9 + | +15 | "hello" ... "world" => {} + | ^^^^^^^^^^^^^^^^^^^ ranges require char or numeric types + | + = note: start type: &'static str + = note: end type: &'static str + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0030-teach.rs b/src/test/ui/error-codes/E0030-teach.rs new file mode 100644 index 00000000000..2af32eda62b --- /dev/null +++ b/src/test/ui/error-codes/E0030-teach.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. + +// compile-flags: -Z teach + +fn main() { + match 5u32 { + 1000 ... 5 => {} + //~^ ERROR lower range bound must be less than or equal to upper + } +} diff --git a/src/test/ui/error-codes/E0030-teach.stderr b/src/test/ui/error-codes/E0030-teach.stderr new file mode 100644 index 00000000000..40b3d790e12 --- /dev/null +++ b/src/test/ui/error-codes/E0030-teach.stderr @@ -0,0 +1,10 @@ +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/E0030-teach.rs:15:9 + | +15 | 1000 ... 5 => {} + | ^^^^ lower bound larger than upper bound + | + = note: When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range. + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0030.rs b/src/test/ui/error-codes/E0030.rs new file mode 100644 index 00000000000..ef3bded4bef --- /dev/null +++ b/src/test/ui/error-codes/E0030.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +fn main() { + match 5u32 { + 1000 ... 5 => {} + //~^ ERROR lower range bound must be less than or equal to upper + } +} diff --git a/src/test/ui/error-codes/E0030.stderr b/src/test/ui/error-codes/E0030.stderr new file mode 100644 index 00000000000..7bdecd0028e --- /dev/null +++ b/src/test/ui/error-codes/E0030.stderr @@ -0,0 +1,8 @@ +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/E0030.rs:14:9 + | +14 | 1000 ... 5 => {} + | ^^^^ lower bound larger than upper bound + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0033-teach.rs b/src/test/ui/error-codes/E0033-teach.rs new file mode 100644 index 00000000000..51a1390bf79 --- /dev/null +++ b/src/test/ui/error-codes/E0033-teach.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. + +// compile-flags: -Z teach + +trait SomeTrait { + fn foo(); +} + +fn main() { + let trait_obj: &SomeTrait = SomeTrait; + //~^ ERROR expected value, found trait `SomeTrait` + //~| ERROR E0038 + //~| method `foo` has no receiver + + let &invalid = trait_obj; + //~^ ERROR E0033 +} diff --git a/src/test/ui/error-codes/E0033-teach.stderr b/src/test/ui/error-codes/E0033-teach.stderr new file mode 100644 index 00000000000..ea60fcb6ccf --- /dev/null +++ b/src/test/ui/error-codes/E0033-teach.stderr @@ -0,0 +1,26 @@ +error[E0423]: expected value, found trait `SomeTrait` + --> $DIR/E0033-teach.rs:18:33 + | +18 | let trait_obj: &SomeTrait = SomeTrait; + | ^^^^^^^^^ not a value + +error[E0038]: the trait `SomeTrait` cannot be made into an object + --> $DIR/E0033-teach.rs:18:20 + | +18 | let trait_obj: &SomeTrait = SomeTrait; + | ^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object + | + = note: method `foo` has no receiver + +error[E0033]: type `&SomeTrait` cannot be dereferenced + --> $DIR/E0033-teach.rs:23:9 + | +23 | let &invalid = trait_obj; + | ^^^^^^^^ type `&SomeTrait` cannot be dereferenced + | + = note: This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a pattern. Every trait defines a type, but because the 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. + + You can read more about trait objects in the Trait Objects section of the Reference: https://doc.rust-lang.org/reference/types.html#trait-objects + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/error-codes/E0033.rs b/src/test/ui/error-codes/E0033.rs new file mode 100644 index 00000000000..3cdbb55f6de --- /dev/null +++ b/src/test/ui/error-codes/E0033.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. + +trait SomeTrait { + fn foo(); +} + +fn main() { + let trait_obj: &SomeTrait = SomeTrait; + //~^ ERROR expected value, found trait `SomeTrait` + //~| ERROR E0038 + //~| method `foo` has no receiver + + let &invalid = trait_obj; + //~^ ERROR E0033 +} diff --git a/src/test/ui/error-codes/E0033.stderr b/src/test/ui/error-codes/E0033.stderr new file mode 100644 index 00000000000..abc535ee2a6 --- /dev/null +++ b/src/test/ui/error-codes/E0033.stderr @@ -0,0 +1,22 @@ +error[E0423]: expected value, found trait `SomeTrait` + --> $DIR/E0033.rs:16:33 + | +16 | let trait_obj: &SomeTrait = SomeTrait; + | ^^^^^^^^^ not a value + +error[E0038]: the trait `SomeTrait` cannot be made into an object + --> $DIR/E0033.rs:16:20 + | +16 | let trait_obj: &SomeTrait = SomeTrait; + | ^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object + | + = note: method `foo` has no receiver + +error[E0033]: type `&SomeTrait` cannot be dereferenced + --> $DIR/E0033.rs:21:9 + | +21 | let &invalid = trait_obj; + | ^^^^^^^^ type `&SomeTrait` cannot be dereferenced + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/error-codes/E0034.rs b/src/test/ui/error-codes/E0034.rs new file mode 100644 index 00000000000..6eebd4d4d53 --- /dev/null +++ b/src/test/ui/error-codes/E0034.rs @@ -0,0 +1,31 @@ +// 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 Test; + +trait Trait1 { + fn foo(); +} + +trait Trait2 { + fn foo(); +} + +impl Trait1 for Test { + fn foo() {} +} + +impl Trait2 for Test { + fn foo() {} +} + +fn main() { + Test::foo() //~ ERROR multiple applicable items in scope +} diff --git a/src/test/ui/error-codes/E0034.stderr b/src/test/ui/error-codes/E0034.stderr new file mode 100644 index 00000000000..238fd0d67a0 --- /dev/null +++ b/src/test/ui/error-codes/E0034.stderr @@ -0,0 +1,19 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/E0034.rs:30:5 + | +30 | Test::foo() //~ ERROR multiple applicable items in scope + | ^^^^^^^^^ multiple `foo` found + | +note: candidate #1 is defined in an impl of the trait `Trait1` for the type `Test` + --> $DIR/E0034.rs:22:5 + | +22 | fn foo() {} + | ^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `Trait2` for the type `Test` + --> $DIR/E0034.rs:26:5 + | +26 | fn foo() {} + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0038.rs b/src/test/ui/error-codes/E0038.rs new file mode 100644 index 00000000000..8087928c051 --- /dev/null +++ b/src/test/ui/error-codes/E0038.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. + +trait Trait { + fn foo(&self) -> Self; +} + +fn call_foo(x: Box) { + //~^ ERROR E0038 + let y = x.foo(); +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0038.stderr b/src/test/ui/error-codes/E0038.stderr new file mode 100644 index 00000000000..e9423561f37 --- /dev/null +++ b/src/test/ui/error-codes/E0038.stderr @@ -0,0 +1,10 @@ +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/E0038.rs:15:1 + | +15 | fn call_foo(x: Box) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` cannot be made into an object + | + = note: method `foo` references the `Self` type in its arguments or return type + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0040.rs b/src/test/ui/error-codes/E0040.rs new file mode 100644 index 00000000000..8385d68c540 --- /dev/null +++ b/src/test/ui/error-codes/E0040.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. + +struct Foo { + x: i32, +} + +impl Drop for Foo { + fn drop(&mut self) { + println!("kaboom"); + } +} + +fn main() { + let mut x = Foo { x: -7 }; + x.drop(); + //~^ ERROR E0040 +} diff --git a/src/test/ui/error-codes/E0040.stderr b/src/test/ui/error-codes/E0040.stderr new file mode 100644 index 00000000000..73cb49fbf98 --- /dev/null +++ b/src/test/ui/error-codes/E0040.stderr @@ -0,0 +1,8 @@ +error[E0040]: explicit use of destructor method + --> $DIR/E0040.rs:23:7 + | +23 | x.drop(); + | ^^^^ explicit destructor calls not allowed + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0044.rs b/src/test/ui/error-codes/E0044.rs new file mode 100644 index 00000000000..48fe2300031 --- /dev/null +++ b/src/test/ui/error-codes/E0044.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. + +extern { fn some_func(x: T); } //~ ERROR E0044 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0044.stderr b/src/test/ui/error-codes/E0044.stderr new file mode 100644 index 00000000000..65a429c1fca --- /dev/null +++ b/src/test/ui/error-codes/E0044.stderr @@ -0,0 +1,14 @@ +error[E0044]: foreign items may not have type parameters + --> $DIR/E0044.rs:11:10 + | +11 | extern { fn some_func(x: T); } //~ ERROR E0044 + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using specialization instead of type parameters + --> $DIR/E0044.rs:11:10 + | +11 | extern { fn some_func(x: T); } //~ ERROR E0044 + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0045.rs b/src/test/ui/error-codes/E0045.rs new file mode 100644 index 00000000000..57c639dd143 --- /dev/null +++ b/src/test/ui/error-codes/E0045.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. + +extern "Rust" { fn foo(x: u8, ...); } //~ ERROR E0045 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0045.stderr b/src/test/ui/error-codes/E0045.stderr new file mode 100644 index 00000000000..cd400564669 --- /dev/null +++ b/src/test/ui/error-codes/E0045.stderr @@ -0,0 +1,8 @@ +error[E0045]: variadic function must have C or cdecl calling convention + --> $DIR/E0045.rs:11:17 + | +11 | extern "Rust" { fn foo(x: u8, ...); } //~ ERROR E0045 + | ^^^^^^^^^^^^^^^^^^^ variadics require C or cdecl calling convention + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0049.rs b/src/test/ui/error-codes/E0049.rs new file mode 100644 index 00000000000..5867e11e9ac --- /dev/null +++ b/src/test/ui/error-codes/E0049.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. + +trait Foo { + fn foo(x: T) -> Self; +} + +struct Bar; + +impl Foo for Bar { + fn foo(x: bool) -> Self { Bar } //~ ERROR E0049 +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0049.stderr b/src/test/ui/error-codes/E0049.stderr new file mode 100644 index 00000000000..e6f72bab50a --- /dev/null +++ b/src/test/ui/error-codes/E0049.stderr @@ -0,0 +1,11 @@ +error[E0049]: method `foo` has 0 type parameters but its trait declaration has 1 type parameter + --> $DIR/E0049.rs:18:5 + | +12 | fn foo(x: T) -> Self; + | --------------------------------- expected 1 type parameter +... +18 | fn foo(x: bool) -> Self { Bar } //~ ERROR E0049 + | ^^^^^^^^^^^^^^^^^^^^^^^ found 0 type parameters + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0050.rs b/src/test/ui/error-codes/E0050.rs new file mode 100644 index 00000000000..2ccc380c540 --- /dev/null +++ b/src/test/ui/error-codes/E0050.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. + +trait Foo { + fn foo(&self, x: u8) -> bool; + fn bar(&self, x: u8, y: u8, z: u8); + fn less(&self); +} + +struct Bar; + +impl Foo for Bar { + fn foo(&self) -> bool { true } //~ ERROR E0050 + fn bar(&self) { } //~ ERROR E0050 + fn less(&self, x: u8, y: u8, z: u8) { } //~ ERROR E0050 +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0050.stderr b/src/test/ui/error-codes/E0050.stderr new file mode 100644 index 00000000000..d95a2005b18 --- /dev/null +++ b/src/test/ui/error-codes/E0050.stderr @@ -0,0 +1,29 @@ +error[E0050]: method `foo` has 1 parameter but the declaration in trait `Foo::foo` has 2 + --> $DIR/E0050.rs:20:12 + | +12 | fn foo(&self, x: u8) -> bool; + | -- trait requires 2 parameters +... +20 | fn foo(&self) -> bool { true } //~ ERROR E0050 + | ^^^^^ expected 2 parameters, found 1 + +error[E0050]: method `bar` has 1 parameter but the declaration in trait `Foo::bar` has 4 + --> $DIR/E0050.rs:21:12 + | +13 | fn bar(&self, x: u8, y: u8, z: u8); + | -- trait requires 4 parameters +... +21 | fn bar(&self) { } //~ ERROR E0050 + | ^^^^^ expected 4 parameters, found 1 + +error[E0050]: method `less` has 4 parameters but the declaration in trait `Foo::less` has 1 + --> $DIR/E0050.rs:22:37 + | +14 | fn less(&self); + | ----- trait requires 1 parameter +... +22 | fn less(&self, x: u8, y: u8, z: u8) { } //~ ERROR E0050 + | ^^ expected 1 parameter, found 4 + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/error-codes/E0054.rs b/src/test/ui/error-codes/E0054.rs new file mode 100644 index 00000000000..158cd6ff9bb --- /dev/null +++ b/src/test/ui/error-codes/E0054.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. + +fn main() { + let x = 5; + let x_is_nonzero = x as bool; //~ ERROR E0054 +} diff --git a/src/test/ui/error-codes/E0054.stderr b/src/test/ui/error-codes/E0054.stderr new file mode 100644 index 00000000000..fc331579ef5 --- /dev/null +++ b/src/test/ui/error-codes/E0054.stderr @@ -0,0 +1,10 @@ +error[E0054]: cannot cast as `bool` + --> $DIR/E0054.rs:13:24 + | +13 | let x_is_nonzero = x as bool; //~ ERROR E0054 + | ^^^^^^^^^ unsupported cast + | + = help: compare with zero instead + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0055.rs b/src/test/ui/error-codes/E0055.rs new file mode 100644 index 00000000000..6e186b81cad --- /dev/null +++ b/src/test/ui/error-codes/E0055.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. + +#![recursion_limit="2"] +struct Foo; + +impl Foo { + fn foo(&self) {} +} + +fn main() { + let foo = Foo; + let ref_foo = &&Foo; + ref_foo.foo(); + //~^ ERROR E0055 +} diff --git a/src/test/ui/error-codes/E0055.stderr b/src/test/ui/error-codes/E0055.stderr new file mode 100644 index 00000000000..001178e97c0 --- /dev/null +++ b/src/test/ui/error-codes/E0055.stderr @@ -0,0 +1,10 @@ +error[E0055]: reached the recursion limit while auto-dereferencing Foo + --> $DIR/E0055.rs:21:13 + | +21 | ref_foo.foo(); + | ^^^ deref recursion limit reached + | + = help: consider adding a `#![recursion_limit="4"]` attribute to your crate + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0057.rs b/src/test/ui/error-codes/E0057.rs new file mode 100644 index 00000000000..1fb5498b099 --- /dev/null +++ b/src/test/ui/error-codes/E0057.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. + +fn main() { + let f = |x| x * 3; + let a = f(); //~ ERROR E0057 + let b = f(4); + let c = f(2, 3); //~ ERROR E0057 +} diff --git a/src/test/ui/error-codes/E0057.stderr b/src/test/ui/error-codes/E0057.stderr new file mode 100644 index 00000000000..450c87ca032 --- /dev/null +++ b/src/test/ui/error-codes/E0057.stderr @@ -0,0 +1,14 @@ +error[E0057]: this function takes 1 parameter but 0 parameters were supplied + --> $DIR/E0057.rs:13:13 + | +13 | let a = f(); //~ ERROR E0057 + | ^^^ expected 1 parameter + +error[E0057]: this function takes 1 parameter but 2 parameters were supplied + --> $DIR/E0057.rs:15:13 + | +15 | let c = f(2, 3); //~ ERROR E0057 + | ^^^^^^^ expected 1 parameter + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0059.rs b/src/test/ui/error-codes/E0059.rs new file mode 100644 index 00000000000..4ae9b2f91d2 --- /dev/null +++ b/src/test/ui/error-codes/E0059.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(unboxed_closures)] + +fn foo>(f: F) -> F::Output { f(3) } //~ ERROR E0059 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0059.stderr b/src/test/ui/error-codes/E0059.stderr new file mode 100644 index 00000000000..aca4b8881e2 --- /dev/null +++ b/src/test/ui/error-codes/E0059.stderr @@ -0,0 +1,8 @@ +error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit + --> $DIR/E0059.rs:13:41 + | +13 | fn foo>(f: F) -> F::Output { f(3) } //~ ERROR E0059 + | ^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0060.rs b/src/test/ui/error-codes/E0060.rs new file mode 100644 index 00000000000..f4505209b66 --- /dev/null +++ b/src/test/ui/error-codes/E0060.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. + +extern "C" { + fn printf(_: *const u8, ...) -> u32; +} + +fn main() { + unsafe { printf(); } + //~^ ERROR E0060 + //~| expected at least 1 parameter +} diff --git a/src/test/ui/error-codes/E0060.stderr b/src/test/ui/error-codes/E0060.stderr new file mode 100644 index 00000000000..8207220ba72 --- /dev/null +++ b/src/test/ui/error-codes/E0060.stderr @@ -0,0 +1,11 @@ +error[E0060]: this function takes at least 1 parameter but 0 parameters were supplied + --> $DIR/E0060.rs:16:14 + | +12 | fn printf(_: *const u8, ...) -> u32; + | ------------------------------------ defined here +... +16 | unsafe { printf(); } + | ^^^^^^^^ expected at least 1 parameter + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0061.rs b/src/test/ui/error-codes/E0061.rs new file mode 100644 index 00000000000..221e18cf89d --- /dev/null +++ b/src/test/ui/error-codes/E0061.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. + +fn f(a: u16, b: &str) {} + +fn f2(a: u16) {} + +fn main() { + f(0); + //~^ ERROR E0061 + //~| expected 2 parameters + + f2(); + //~^ ERROR E0061 + //~| expected 1 parameter +} diff --git a/src/test/ui/error-codes/E0061.stderr b/src/test/ui/error-codes/E0061.stderr new file mode 100644 index 00000000000..89d81b5acd7 --- /dev/null +++ b/src/test/ui/error-codes/E0061.stderr @@ -0,0 +1,20 @@ +error[E0061]: this function takes 2 parameters but 1 parameter was supplied + --> $DIR/E0061.rs:16:5 + | +11 | fn f(a: u16, b: &str) {} + | --------------------- defined here +... +16 | f(0); + | ^^^^ expected 2 parameters + +error[E0061]: this function takes 1 parameter but 0 parameters were supplied + --> $DIR/E0061.rs:20:5 + | +13 | fn f2(a: u16) {} + | ------------- defined here +... +20 | f2(); + | ^^^^ expected 1 parameter + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0062.rs b/src/test/ui/error-codes/E0062.rs new file mode 100644 index 00000000000..684c9464ff8 --- /dev/null +++ b/src/test/ui/error-codes/E0062.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. + +struct Foo { + x: i32 +} + +fn main() { + let x = Foo { + x: 0, + x: 0, + //~^ ERROR E0062 + }; +} diff --git a/src/test/ui/error-codes/E0062.stderr b/src/test/ui/error-codes/E0062.stderr new file mode 100644 index 00000000000..6c5ecf48045 --- /dev/null +++ b/src/test/ui/error-codes/E0062.stderr @@ -0,0 +1,10 @@ +error[E0062]: field `x` specified more than once + --> $DIR/E0062.rs:18:9 + | +17 | x: 0, + | ---- first use of `x` +18 | x: 0, + | ^^ used more than once + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0063.rs b/src/test/ui/error-codes/E0063.rs new file mode 100644 index 00000000000..0208aff066b --- /dev/null +++ b/src/test/ui/error-codes/E0063.rs @@ -0,0 +1,50 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength + +struct SingleFoo { + x: i32 +} + +struct PluralFoo { + x: i32, + y: i32, + z: i32 +} + +struct TruncatedFoo { + a: i32, + b: i32, + x: i32, + y: i32, + z: i32 +} + +struct TruncatedPluralFoo { + a: i32, + b: i32, + c: i32, + x: i32, + y: i32, + z: i32 +} + + +fn main() { + let w = SingleFoo { }; + //~^ ERROR missing field `x` in initializer of `SingleFoo` + let x = PluralFoo {x: 1}; + //~^ ERROR missing fields `y`, `z` in initializer of `PluralFoo` + let y = TruncatedFoo{x:1}; + //~^ missing fields `a`, `b`, `y` and 1 other field in initializer of `TruncatedFoo` + let z = TruncatedPluralFoo{x:1}; + //~^ ERROR missing fields `a`, `b`, `c` and 2 other fields in initializer of `TruncatedPluralFoo` +} diff --git a/src/test/ui/error-codes/E0063.stderr b/src/test/ui/error-codes/E0063.stderr new file mode 100644 index 00000000000..023819cc778 --- /dev/null +++ b/src/test/ui/error-codes/E0063.stderr @@ -0,0 +1,26 @@ +error[E0063]: missing field `x` in initializer of `SingleFoo` + --> $DIR/E0063.rs:42:13 + | +42 | let w = SingleFoo { }; + | ^^^^^^^^^ missing `x` + +error[E0063]: missing fields `y`, `z` in initializer of `PluralFoo` + --> $DIR/E0063.rs:44:13 + | +44 | let x = PluralFoo {x: 1}; + | ^^^^^^^^^ missing `y`, `z` + +error[E0063]: missing fields `a`, `b`, `y` and 1 other field in initializer of `TruncatedFoo` + --> $DIR/E0063.rs:46:13 + | +46 | let y = TruncatedFoo{x:1}; + | ^^^^^^^^^^^^ missing `a`, `b`, `y` and 1 other field + +error[E0063]: missing fields `a`, `b`, `c` and 2 other fields in initializer of `TruncatedPluralFoo` + --> $DIR/E0063.rs:48:13 + | +48 | let z = TruncatedPluralFoo{x:1}; + | ^^^^^^^^^^^^^^^^^^ missing `a`, `b`, `c` and 2 other fields + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/error-codes/E0067.rs b/src/test/ui/error-codes/E0067.rs new file mode 100644 index 00000000000..a3fc30ee1c7 --- /dev/null +++ b/src/test/ui/error-codes/E0067.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::collections::LinkedList; + +fn main() { + LinkedList::new() += 1; //~ ERROR E0368 + //~^ ERROR E0067 +} diff --git a/src/test/ui/error-codes/E0067.stderr b/src/test/ui/error-codes/E0067.stderr new file mode 100644 index 00000000000..a4e15619e8b --- /dev/null +++ b/src/test/ui/error-codes/E0067.stderr @@ -0,0 +1,16 @@ +error[E0368]: binary assignment operation `+=` cannot be applied to type `std::collections::LinkedList<_>` + --> $DIR/E0067.rs:14:5 + | +14 | LinkedList::new() += 1; //~ ERROR E0368 + | -----------------^^^^^ + | | + | cannot use `+=` on type `std::collections::LinkedList<_>` + +error[E0067]: invalid left-hand side expression + --> $DIR/E0067.rs:14:5 + | +14 | LinkedList::new() += 1; //~ ERROR E0368 + | ^^^^^^^^^^^^^^^^^ invalid expression for left-hand side + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0069.rs b/src/test/ui/error-codes/E0069.rs new file mode 100644 index 00000000000..a6a7898ed4e --- /dev/null +++ b/src/test/ui/error-codes/E0069.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn foo() -> u8 { + return; + //~^ ERROR `return;` in a function whose return type is not `()` +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0069.stderr b/src/test/ui/error-codes/E0069.stderr new file mode 100644 index 00000000000..8424531889f --- /dev/null +++ b/src/test/ui/error-codes/E0069.stderr @@ -0,0 +1,8 @@ +error[E0069]: `return;` in a function whose return type is not `()` + --> $DIR/E0069.rs:12:5 + | +12 | return; + | ^^^^^^ return type is not () + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0070.rs b/src/test/ui/error-codes/E0070.rs new file mode 100644 index 00000000000..ba66bd03aef --- /dev/null +++ b/src/test/ui/error-codes/E0070.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. + +const SOME_CONST : i32 = 12; + +fn some_other_func() {} + +fn some_function() { + SOME_CONST = 14; //~ ERROR E0070 + 1 = 3; //~ ERROR E0070 + some_other_func() = 4; //~ ERROR E0070 + //~^ ERROR E0308 +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0070.stderr b/src/test/ui/error-codes/E0070.stderr new file mode 100644 index 00000000000..e1316e2e130 --- /dev/null +++ b/src/test/ui/error-codes/E0070.stderr @@ -0,0 +1,29 @@ +error[E0070]: invalid left-hand side expression + --> $DIR/E0070.rs:16:5 + | +16 | SOME_CONST = 14; //~ ERROR E0070 + | ^^^^^^^^^^^^^^^ left-hand of expression not valid + +error[E0070]: invalid left-hand side expression + --> $DIR/E0070.rs:17:5 + | +17 | 1 = 3; //~ ERROR E0070 + | ^^^^^ left-hand of expression not valid + +error[E0308]: mismatched types + --> $DIR/E0070.rs:18:25 + | +18 | some_other_func() = 4; //~ ERROR E0070 + | ^ expected (), found integral variable + | + = note: expected type `()` + found type `{integer}` + +error[E0070]: invalid left-hand side expression + --> $DIR/E0070.rs:18:5 + | +18 | some_other_func() = 4; //~ ERROR E0070 + | ^^^^^^^^^^^^^^^^^^^^^ left-hand of expression not valid + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/error-codes/E0071.rs b/src/test/ui/error-codes/E0071.rs new file mode 100644 index 00000000000..d71dc7966fa --- /dev/null +++ b/src/test/ui/error-codes/E0071.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +enum Foo {} +type FooAlias = Foo; + +fn main() { + let u = FooAlias { value: 0 }; + //~^ ERROR expected struct, variant or union type, found enum `Foo` [E0071] +} diff --git a/src/test/ui/error-codes/E0071.stderr b/src/test/ui/error-codes/E0071.stderr new file mode 100644 index 00000000000..020dad3ac9f --- /dev/null +++ b/src/test/ui/error-codes/E0071.stderr @@ -0,0 +1,8 @@ +error[E0071]: expected struct, variant or union type, found enum `Foo` + --> $DIR/E0071.rs:15:13 + | +15 | let u = FooAlias { value: 0 }; + | ^^^^^^^^ not a struct + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0075.rs b/src/test/ui/error-codes/E0075.rs new file mode 100644 index 00000000000..d7783904e2e --- /dev/null +++ b/src/test/ui/error-codes/E0075.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(repr_simd)] + +#[repr(simd)] +struct Bad; //~ ERROR E0075 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0075.stderr b/src/test/ui/error-codes/E0075.stderr new file mode 100644 index 00000000000..39d27d6f7e4 --- /dev/null +++ b/src/test/ui/error-codes/E0075.stderr @@ -0,0 +1,8 @@ +error[E0075]: SIMD vector cannot be empty + --> $DIR/E0075.rs:14:1 + | +14 | struct Bad; //~ ERROR E0075 + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0076.rs b/src/test/ui/error-codes/E0076.rs new file mode 100644 index 00000000000..b159cf107ce --- /dev/null +++ b/src/test/ui/error-codes/E0076.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. + +#![feature(repr_simd)] + +#[repr(simd)] +struct Bad(u16, u32, u32); +//~^ ERROR E0076 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0076.stderr b/src/test/ui/error-codes/E0076.stderr new file mode 100644 index 00000000000..02ce47977c8 --- /dev/null +++ b/src/test/ui/error-codes/E0076.stderr @@ -0,0 +1,8 @@ +error[E0076]: SIMD vector should be homogeneous + --> $DIR/E0076.rs:14:1 + | +14 | struct Bad(u16, u32, u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ SIMD elements must have the same type + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0077.rs b/src/test/ui/error-codes/E0077.rs new file mode 100644 index 00000000000..b074e90b2c0 --- /dev/null +++ b/src/test/ui/error-codes/E0077.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(repr_simd)] + +#[repr(simd)] +struct Bad(String); //~ ERROR E0077 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0077.stderr b/src/test/ui/error-codes/E0077.stderr new file mode 100644 index 00000000000..7e7b55f9b7e --- /dev/null +++ b/src/test/ui/error-codes/E0077.stderr @@ -0,0 +1,8 @@ +error[E0077]: SIMD vector element type should be machine type + --> $DIR/E0077.rs:14:1 + | +14 | struct Bad(String); //~ ERROR E0077 + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0080.rs b/src/test/ui/error-codes/E0080.rs new file mode 100644 index 00000000000..2f199c48e46 --- /dev/null +++ b/src/test/ui/error-codes/E0080.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. + +enum Enum { + X = (1 << 500), //~ ERROR E0080 + //~| WARNING shift left with overflow + Y = (1 / 0) //~ ERROR E0080 + //~| WARNING divide by zero +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0080.stderr b/src/test/ui/error-codes/E0080.stderr new file mode 100644 index 00000000000..2ec2ad31b53 --- /dev/null +++ b/src/test/ui/error-codes/E0080.stderr @@ -0,0 +1,28 @@ +warning: constant evaluation error: attempt to shift left with overflow + --> $DIR/E0080.rs:12:9 + | +12 | X = (1 << 500), //~ ERROR E0080 + | ^^^^^^^^^^ + | + = note: #[warn(const_err)] on by default + +error[E0080]: constant evaluation error + --> $DIR/E0080.rs:12:9 + | +12 | X = (1 << 500), //~ ERROR E0080 + | ^^^^^^^^^^ attempt to shift left with overflow + +warning: constant evaluation error: attempt to divide by zero + --> $DIR/E0080.rs:14:9 + | +14 | Y = (1 / 0) //~ ERROR E0080 + | ^^^^^^^ + +error[E0080]: constant evaluation error + --> $DIR/E0080.rs:14:9 + | +14 | Y = (1 / 0) //~ ERROR E0080 + | ^^^^^^^ attempt to divide by zero + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0081.rs b/src/test/ui/error-codes/E0081.rs new file mode 100644 index 00000000000..3b571667336 --- /dev/null +++ b/src/test/ui/error-codes/E0081.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. + +enum Enum { + P = 3, + X = 3, + //~^ ERROR discriminant value `3isize` already exists + Y = 5 +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0081.stderr b/src/test/ui/error-codes/E0081.stderr new file mode 100644 index 00000000000..035638b2f31 --- /dev/null +++ b/src/test/ui/error-codes/E0081.stderr @@ -0,0 +1,10 @@ +error[E0081]: discriminant value `3isize` already exists + --> $DIR/E0081.rs:13:9 + | +12 | P = 3, + | - first use of `3isize` +13 | X = 3, + | ^ enum already has `3isize` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0084.rs b/src/test/ui/error-codes/E0084.rs new file mode 100644 index 00000000000..2be206c9702 --- /dev/null +++ b/src/test/ui/error-codes/E0084.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. + +#[repr(i32)] //~ ERROR: E0084 +enum Foo {} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0084.stderr b/src/test/ui/error-codes/E0084.stderr new file mode 100644 index 00000000000..b39a129ba16 --- /dev/null +++ b/src/test/ui/error-codes/E0084.stderr @@ -0,0 +1,10 @@ +error[E0084]: unsupported representation for zero-variant enum + --> $DIR/E0084.rs:11:1 + | +11 | #[repr(i32)] //~ ERROR: E0084 + | ^^^^^^^^^^^^ +12 | enum Foo {} + | ----------- zero-variant enum + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0087.rs b/src/test/ui/error-codes/E0087.rs new file mode 100644 index 00000000000..6dc08860614 --- /dev/null +++ b/src/test/ui/error-codes/E0087.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. + +fn foo() {} +fn bar() {} + +fn main() { + foo::(); //~ ERROR expected at most 0 type parameters, found 1 type parameter [E0087] + + bar::(); //~ ERROR expected at most 1 type parameter, found 2 type parameters [E0087] +} diff --git a/src/test/ui/error-codes/E0087.stderr b/src/test/ui/error-codes/E0087.stderr new file mode 100644 index 00000000000..20c8cd45dfa --- /dev/null +++ b/src/test/ui/error-codes/E0087.stderr @@ -0,0 +1,14 @@ +error[E0087]: too many type parameters provided: expected at most 0 type parameters, found 1 type parameter + --> $DIR/E0087.rs:15:11 + | +15 | foo::(); //~ ERROR expected at most 0 type parameters, found 1 type parameter [E0087] + | ^^^ expected 0 type parameters + +error[E0087]: too many type parameters provided: expected at most 1 type parameter, found 2 type parameters + --> $DIR/E0087.rs:17:16 + | +17 | bar::(); //~ ERROR expected at most 1 type parameter, found 2 type parameters [E0087] + | ^^^ expected 1 type parameter + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0088.rs b/src/test/ui/error-codes/E0088.rs new file mode 100644 index 00000000000..db84a4edc48 --- /dev/null +++ b/src/test/ui/error-codes/E0088.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn f() {} +fn g<'a>() -> &'a u8 { loop {} } + +fn main() { + f::<'static>(); //~ ERROR E0088 + g::<'static, 'static>(); //~ ERROR E0088 +} diff --git a/src/test/ui/error-codes/E0088.stderr b/src/test/ui/error-codes/E0088.stderr new file mode 100644 index 00000000000..615df88f1bb --- /dev/null +++ b/src/test/ui/error-codes/E0088.stderr @@ -0,0 +1,14 @@ +error[E0088]: too many lifetime parameters provided: expected at most 0 lifetime parameters, found 1 lifetime parameter + --> $DIR/E0088.rs:15:9 + | +15 | f::<'static>(); //~ ERROR E0088 + | ^^^^^^^ expected 0 lifetime parameters + +error[E0088]: too many lifetime parameters provided: expected at most 1 lifetime parameter, found 2 lifetime parameters + --> $DIR/E0088.rs:16:18 + | +16 | g::<'static, 'static>(); //~ ERROR E0088 + | ^^^^^^^ expected 1 lifetime parameter + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0089.rs b/src/test/ui/error-codes/E0089.rs new file mode 100644 index 00000000000..21df9abd093 --- /dev/null +++ b/src/test/ui/error-codes/E0089.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() {} + +fn main() { + foo::(); //~ ERROR expected 2 type parameters, found 1 type parameter [E0089] +} diff --git a/src/test/ui/error-codes/E0089.stderr b/src/test/ui/error-codes/E0089.stderr new file mode 100644 index 00000000000..38b45e27fa7 --- /dev/null +++ b/src/test/ui/error-codes/E0089.stderr @@ -0,0 +1,8 @@ +error[E0089]: too few type parameters provided: expected 2 type parameters, found 1 type parameter + --> $DIR/E0089.rs:14:5 + | +14 | foo::(); //~ ERROR expected 2 type parameters, found 1 type parameter [E0089] + | ^^^^^^^^^^ expected 2 type parameters + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0090.rs b/src/test/ui/error-codes/E0090.rs new file mode 100644 index 00000000000..13b2131cc8b --- /dev/null +++ b/src/test/ui/error-codes/E0090.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: 'b, 'b: 'a>() {} + +fn main() { + foo::<'static>(); //~ ERROR expected 2 lifetime parameters, found 1 lifetime parameter [E0090] +} diff --git a/src/test/ui/error-codes/E0090.stderr b/src/test/ui/error-codes/E0090.stderr new file mode 100644 index 00000000000..050082d84df --- /dev/null +++ b/src/test/ui/error-codes/E0090.stderr @@ -0,0 +1,8 @@ +error[E0090]: too few lifetime parameters provided: expected 2 lifetime parameters, found 1 lifetime parameter + --> $DIR/E0090.rs:14:5 + | +14 | foo::<'static>(); //~ ERROR expected 2 lifetime parameters, found 1 lifetime parameter [E0090] + | ^^^^^^^^^^^^^^ expected 2 lifetime parameters + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0091.rs b/src/test/ui/error-codes/E0091.rs new file mode 100644 index 00000000000..da988dbf819 --- /dev/null +++ b/src/test/ui/error-codes/E0091.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. + +type Foo = u32; //~ ERROR E0091 +type Foo2 = Box; //~ ERROR E0091 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0091.stderr b/src/test/ui/error-codes/E0091.stderr new file mode 100644 index 00000000000..7d951dd6dfd --- /dev/null +++ b/src/test/ui/error-codes/E0091.stderr @@ -0,0 +1,14 @@ +error[E0091]: type parameter `T` is unused + --> $DIR/E0091.rs:11:10 + | +11 | type Foo = u32; //~ ERROR E0091 + | ^ unused type parameter + +error[E0091]: type parameter `B` is unused + --> $DIR/E0091.rs:12:14 + | +12 | type Foo2 = Box; //~ ERROR E0091 + | ^ unused type parameter + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0092.rs b/src/test/ui/error-codes/E0092.rs new file mode 100644 index 00000000000..b08164ac06d --- /dev/null +++ b/src/test/ui/error-codes/E0092.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(intrinsics)] +extern "rust-intrinsic" { + fn atomic_foo(); //~ ERROR E0092 +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0092.stderr b/src/test/ui/error-codes/E0092.stderr new file mode 100644 index 00000000000..788f8994411 --- /dev/null +++ b/src/test/ui/error-codes/E0092.stderr @@ -0,0 +1,8 @@ +error[E0092]: unrecognized atomic operation function: `foo` + --> $DIR/E0092.rs:13:5 + | +13 | fn atomic_foo(); //~ ERROR E0092 + | ^^^^^^^^^^^^^^^^ unrecognized atomic operation + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0093.rs b/src/test/ui/error-codes/E0093.rs new file mode 100644 index 00000000000..d84f9f64911 --- /dev/null +++ b/src/test/ui/error-codes/E0093.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. + +#![feature(intrinsics)] +extern "rust-intrinsic" { + fn foo(); + //~^ ERROR E0093 +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0093.stderr b/src/test/ui/error-codes/E0093.stderr new file mode 100644 index 00000000000..959d64af433 --- /dev/null +++ b/src/test/ui/error-codes/E0093.stderr @@ -0,0 +1,8 @@ +error[E0093]: unrecognized intrinsic function: `foo` + --> $DIR/E0093.rs:13:5 + | +13 | fn foo(); + | ^^^^^^^^^ unrecognized intrinsic + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0094.rs b/src/test/ui/error-codes/E0094.rs new file mode 100644 index 00000000000..3a31874b244 --- /dev/null +++ b/src/test/ui/error-codes/E0094.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(intrinsics)] +extern "rust-intrinsic" { + fn size_of() -> usize; //~ ERROR E0094 +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0094.stderr b/src/test/ui/error-codes/E0094.stderr new file mode 100644 index 00000000000..fdef3d8877b --- /dev/null +++ b/src/test/ui/error-codes/E0094.stderr @@ -0,0 +1,8 @@ +error[E0094]: intrinsic has wrong number of type parameters: found 2, expected 1 + --> $DIR/E0094.rs:13:15 + | +13 | fn size_of() -> usize; //~ ERROR E0094 + | ^^^^^^ expected 1 type parameter + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0106.rs b/src/test/ui/error-codes/E0106.rs new file mode 100644 index 00000000000..0674930a11c --- /dev/null +++ b/src/test/ui/error-codes/E0106.rs @@ -0,0 +1,36 @@ +// 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 { + x: &bool, + //~^ ERROR E0106 +} +enum Bar { + A(u8), + B(&bool), + //~^ ERROR E0106 +} +type MyStr = &str; + //~^ ERROR E0106 + +struct Baz<'a>(&'a str); +struct Buzz<'a, 'b>(&'a str, &'b str); + +struct Quux { + baz: Baz, + //~^ ERROR E0106 + //~| expected lifetime parameter + buzz: Buzz, + //~^ ERROR E0106 + //~| expected 2 lifetime parameters +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0106.stderr b/src/test/ui/error-codes/E0106.stderr new file mode 100644 index 00000000000..98442804708 --- /dev/null +++ b/src/test/ui/error-codes/E0106.stderr @@ -0,0 +1,32 @@ +error[E0106]: missing lifetime specifier + --> $DIR/E0106.rs:12:8 + | +12 | x: &bool, + | ^ expected lifetime parameter + +error[E0106]: missing lifetime specifier + --> $DIR/E0106.rs:17:7 + | +17 | B(&bool), + | ^ expected lifetime parameter + +error[E0106]: missing lifetime specifier + --> $DIR/E0106.rs:20:14 + | +20 | type MyStr = &str; + | ^ expected lifetime parameter + +error[E0106]: missing lifetime specifier + --> $DIR/E0106.rs:27:10 + | +27 | baz: Baz, + | ^^^ expected lifetime parameter + +error[E0106]: missing lifetime specifiers + --> $DIR/E0106.rs:30:11 + | +30 | buzz: Buzz, + | ^^^^ expected 2 lifetime parameters + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/error-codes/E0107.rs b/src/test/ui/error-codes/E0107.rs new file mode 100644 index 00000000000..16ebd3e9ca5 --- /dev/null +++ b/src/test/ui/error-codes/E0107.rs @@ -0,0 +1,33 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo<'a>(&'a str); +struct Buzz<'a, 'b>(&'a str, &'b str); + +enum Bar { + A, + B, + C, +} + +struct Baz<'a, 'b, 'c> { + buzz: Buzz<'a>, + //~^ ERROR E0107 + //~| expected 2 lifetime parameters + bar: Bar<'a>, + //~^ ERROR E0107 + //~| unexpected lifetime parameter + foo2: Foo<'a, 'b, 'c>, + //~^ ERROR E0107 + //~| 2 unexpected lifetime parameters +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0107.stderr b/src/test/ui/error-codes/E0107.stderr new file mode 100644 index 00000000000..6283486039c --- /dev/null +++ b/src/test/ui/error-codes/E0107.stderr @@ -0,0 +1,20 @@ +error[E0107]: wrong number of lifetime parameters: expected 2, found 1 + --> $DIR/E0107.rs:21:11 + | +21 | buzz: Buzz<'a>, + | ^^^^^^^^ expected 2 lifetime parameters + +error[E0107]: wrong number of lifetime parameters: expected 0, found 1 + --> $DIR/E0107.rs:24:10 + | +24 | bar: Bar<'a>, + | ^^^^^^^ unexpected lifetime parameter + +error[E0107]: wrong number of lifetime parameters: expected 1, found 3 + --> $DIR/E0107.rs:27:11 + | +27 | foo2: Foo<'a, 'b, 'c>, + | ^^^^^^^^^^^^^^^ 2 unexpected lifetime parameters + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/error-codes/E0109.rs b/src/test/ui/error-codes/E0109.rs new file mode 100644 index 00000000000..9fc47842250 --- /dev/null +++ b/src/test/ui/error-codes/E0109.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. + +type X = u32; //~ ERROR E0109 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0109.stderr b/src/test/ui/error-codes/E0109.stderr new file mode 100644 index 00000000000..59da11140b1 --- /dev/null +++ b/src/test/ui/error-codes/E0109.stderr @@ -0,0 +1,8 @@ +error[E0109]: type parameters are not allowed on this type + --> $DIR/E0109.rs:11:14 + | +11 | type X = u32; //~ ERROR E0109 + | ^^^ type parameter not allowed + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0110.rs b/src/test/ui/error-codes/E0110.rs new file mode 100644 index 00000000000..fd169f4acc5 --- /dev/null +++ b/src/test/ui/error-codes/E0110.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. + +type X = u32<'static>; //~ ERROR E0110 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0110.stderr b/src/test/ui/error-codes/E0110.stderr new file mode 100644 index 00000000000..7417351c16d --- /dev/null +++ b/src/test/ui/error-codes/E0110.stderr @@ -0,0 +1,8 @@ +error[E0110]: lifetime parameters are not allowed on this type + --> $DIR/E0110.rs:11:14 + | +11 | type X = u32<'static>; //~ ERROR E0110 + | ^^^^^^^ lifetime parameter not allowed on this type + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0116.rs b/src/test/ui/error-codes/E0116.rs new file mode 100644 index 00000000000..cd7d8dc3efb --- /dev/null +++ b/src/test/ui/error-codes/E0116.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. + +impl Vec {} +//~^ ERROR E0116 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0116.stderr b/src/test/ui/error-codes/E0116.stderr new file mode 100644 index 00000000000..c090060e7d6 --- /dev/null +++ b/src/test/ui/error-codes/E0116.stderr @@ -0,0 +1,10 @@ +error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined + --> $DIR/E0116.rs:11:1 + | +11 | impl Vec {} + | ^^^^^^^^^^^^^^^ impl for type defined outside of crate. + | + = note: define and implement a trait or new type instead + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0117.rs b/src/test/ui/error-codes/E0117.rs new file mode 100644 index 00000000000..982f875c7b0 --- /dev/null +++ b/src/test/ui/error-codes/E0117.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. + +impl Drop for u32 {} //~ ERROR E0117 +//~| ERROR the Drop trait may only be implemented on structures +//~| implementing Drop requires a struct + +fn main() { +} diff --git a/src/test/ui/error-codes/E0117.stderr b/src/test/ui/error-codes/E0117.stderr new file mode 100644 index 00000000000..9856692659a --- /dev/null +++ b/src/test/ui/error-codes/E0117.stderr @@ -0,0 +1,17 @@ +error[E0120]: the Drop trait may only be implemented on structures + --> $DIR/E0117.rs:11:15 + | +11 | impl Drop for u32 {} //~ ERROR E0117 + | ^^^ implementing Drop requires a struct + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/E0117.rs:11:1 + | +11 | impl Drop for u32 {} //~ ERROR E0117 + | ^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate + | + = note: the impl does not reference any types defined in this crate + = note: define and implement a trait or new type instead + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0118.rs b/src/test/ui/error-codes/E0118.rs new file mode 100644 index 00000000000..d37ff34b861 --- /dev/null +++ b/src/test/ui/error-codes/E0118.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. + +impl (u8, u8) { //~ ERROR E0118 + fn get_state(&self) -> String { + String::new() + } +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0118.stderr b/src/test/ui/error-codes/E0118.stderr new file mode 100644 index 00000000000..8c78890b88a --- /dev/null +++ b/src/test/ui/error-codes/E0118.stderr @@ -0,0 +1,10 @@ +error[E0118]: no base type found for inherent implementation + --> $DIR/E0118.rs:11:6 + | +11 | impl (u8, u8) { //~ ERROR E0118 + | ^^^^^^^^ impl requires a base type + | + = note: either implement a trait on it or create a newtype to wrap it instead + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0119.rs b/src/test/ui/error-codes/E0119.rs new file mode 100644 index 00000000000..9528631b304 --- /dev/null +++ b/src/test/ui/error-codes/E0119.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. + +trait MyTrait { + fn get(&self) -> usize; +} + +impl MyTrait for T { + fn get(&self) -> usize { 0 } +} + +struct Foo { + value: usize +} + +impl MyTrait for Foo { //~ ERROR E0119 + fn get(&self) -> usize { self.value } +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0119.stderr b/src/test/ui/error-codes/E0119.stderr new file mode 100644 index 00000000000..91bb74a10d6 --- /dev/null +++ b/src/test/ui/error-codes/E0119.stderr @@ -0,0 +1,11 @@ +error[E0119]: conflicting implementations of trait `MyTrait` for type `Foo`: + --> $DIR/E0119.rs:23:1 + | +15 | impl MyTrait for T { + | --------------------- first implementation here +... +23 | impl MyTrait for Foo { //~ ERROR E0119 + | ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Foo` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0120.rs b/src/test/ui/error-codes/E0120.rs new file mode 100644 index 00000000000..8d09b877f00 --- /dev/null +++ b/src/test/ui/error-codes/E0120.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. + +trait MyTrait { fn foo() {} } + +impl Drop for MyTrait { + //~^ ERROR E0120 + fn drop(&mut self) {} +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0120.stderr b/src/test/ui/error-codes/E0120.stderr new file mode 100644 index 00000000000..7c666d9fd0a --- /dev/null +++ b/src/test/ui/error-codes/E0120.stderr @@ -0,0 +1,8 @@ +error[E0120]: the Drop trait may only be implemented on structures + --> $DIR/E0120.rs:13:15 + | +13 | impl Drop for MyTrait { + | ^^^^^^^ implementing Drop requires a struct + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0121.rs b/src/test/ui/error-codes/E0121.rs new file mode 100644 index 00000000000..b26b5f41bfe --- /dev/null +++ b/src/test/ui/error-codes/E0121.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. + +fn foo() -> _ { 5 } //~ ERROR E0121 + +static BAR: _ = "test"; //~ ERROR E0121 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0121.stderr b/src/test/ui/error-codes/E0121.stderr new file mode 100644 index 00000000000..fa54d678563 --- /dev/null +++ b/src/test/ui/error-codes/E0121.stderr @@ -0,0 +1,14 @@ +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/E0121.rs:11:13 + | +11 | fn foo() -> _ { 5 } //~ ERROR E0121 + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/E0121.rs:13:13 + | +13 | static BAR: _ = "test"; //~ ERROR E0121 + | ^ not allowed in type signatures + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0124.rs b/src/test/ui/error-codes/E0124.rs new file mode 100644 index 00000000000..3ef20c6dd40 --- /dev/null +++ b/src/test/ui/error-codes/E0124.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. + +struct Foo { + field1: i32, + field1: i32, + //~^ ERROR field `field1` is already declared [E0124] +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0124.stderr b/src/test/ui/error-codes/E0124.stderr new file mode 100644 index 00000000000..8e1ec51ea1c --- /dev/null +++ b/src/test/ui/error-codes/E0124.stderr @@ -0,0 +1,10 @@ +error[E0124]: field `field1` is already declared + --> $DIR/E0124.rs:13:5 + | +12 | field1: i32, + | ----------- `field1` first declared here +13 | field1: i32, + | ^^^^^^^^^^^ field already declared + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0128.rs b/src/test/ui/error-codes/E0128.rs new file mode 100644 index 00000000000..37071012825 --- /dev/null +++ b/src/test/ui/error-codes/E0128.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo { //~ ERROR E0128 + field1: T, + field2: U, +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0128.stderr b/src/test/ui/error-codes/E0128.stderr new file mode 100644 index 00000000000..fad2d0db8ab --- /dev/null +++ b/src/test/ui/error-codes/E0128.stderr @@ -0,0 +1,8 @@ +error[E0128]: type parameters with a default cannot use forward declared identifiers + --> $DIR/E0128.rs:11:14 + | +11 | struct Foo { //~ ERROR E0128 + | ^ defaulted type parameters cannot be forward declared + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0130.rs b/src/test/ui/error-codes/E0130.rs new file mode 100644 index 00000000000..d11b59cdf33 --- /dev/null +++ b/src/test/ui/error-codes/E0130.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern { + fn foo((a, b): (u32, u32)); + //~^ ERROR E0130 +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0130.stderr b/src/test/ui/error-codes/E0130.stderr new file mode 100644 index 00000000000..02aebe0362a --- /dev/null +++ b/src/test/ui/error-codes/E0130.stderr @@ -0,0 +1,8 @@ +error[E0130]: patterns aren't allowed in foreign function declarations + --> $DIR/E0130.rs:12:12 + | +12 | fn foo((a, b): (u32, u32)); + | ^^^^^^ pattern not allowed in foreign function + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0131.rs b/src/test/ui/error-codes/E0131.rs new file mode 100644 index 00000000000..c7e31edd301 --- /dev/null +++ b/src/test/ui/error-codes/E0131.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. + +fn main() { + //~^ ERROR E0131 +} diff --git a/src/test/ui/error-codes/E0131.stderr b/src/test/ui/error-codes/E0131.stderr new file mode 100644 index 00000000000..d97e00fb82d --- /dev/null +++ b/src/test/ui/error-codes/E0131.stderr @@ -0,0 +1,8 @@ +error[E0131]: main function is not allowed to have type parameters + --> $DIR/E0131.rs:11:8 + | +11 | fn main() { + | ^^^ main cannot have type parameters + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0132.rs b/src/test/ui/error-codes/E0132.rs new file mode 100644 index 00000000000..25ccb344aba --- /dev/null +++ b/src/test/ui/error-codes/E0132.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(start)] + +#[start] +fn f< T >() {} //~ ERROR E0132 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0132.stderr b/src/test/ui/error-codes/E0132.stderr new file mode 100644 index 00000000000..5c66d67b907 --- /dev/null +++ b/src/test/ui/error-codes/E0132.stderr @@ -0,0 +1,8 @@ +error[E0132]: start function is not allowed to have type parameters + --> $DIR/E0132.rs:14:5 + | +14 | fn f< T >() {} //~ ERROR E0132 + | ^^^^^ start function cannot have type parameters + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0133.rs b/src/test/ui/error-codes/E0133.rs new file mode 100644 index 00000000000..2e54f65e7bf --- /dev/null +++ b/src/test/ui/error-codes/E0133.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. + +unsafe fn f() { return; } + +fn main() { + f(); + //~^ ERROR E0133 +} diff --git a/src/test/ui/error-codes/E0133.stderr b/src/test/ui/error-codes/E0133.stderr new file mode 100644 index 00000000000..4d2ebd111dd --- /dev/null +++ b/src/test/ui/error-codes/E0133.stderr @@ -0,0 +1,8 @@ +error[E0133]: call to unsafe function requires unsafe function or block + --> $DIR/E0133.rs:14:5 + | +14 | f(); + | ^^^ call to unsafe function + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0137.rs b/src/test/ui/error-codes/E0137.rs new file mode 100644 index 00000000000..067ebcc727c --- /dev/null +++ b/src/test/ui/error-codes/E0137.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. + +#![feature(main)] + +#[main] +fn foo() {} + +#[main] +fn f() {} +//~^ ERROR E0137 diff --git a/src/test/ui/error-codes/E0137.stderr b/src/test/ui/error-codes/E0137.stderr new file mode 100644 index 00000000000..bc6bbffb18e --- /dev/null +++ b/src/test/ui/error-codes/E0137.stderr @@ -0,0 +1,11 @@ +error[E0137]: multiple functions with a #[main] attribute + --> $DIR/E0137.rs:17:1 + | +14 | fn foo() {} + | ----------- first #[main] function +... +17 | fn f() {} + | ^^^^^^^^^ additional #[main] function + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0138.rs b/src/test/ui/error-codes/E0138.rs new file mode 100644 index 00000000000..856616c8570 --- /dev/null +++ b/src/test/ui/error-codes/E0138.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. + +#![feature(start)] + +#[start] +fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } + +#[start] +fn f(argc: isize, argv: *const *const u8) -> isize { 0 } +//~^ ERROR E0138 diff --git a/src/test/ui/error-codes/E0138.stderr b/src/test/ui/error-codes/E0138.stderr new file mode 100644 index 00000000000..cee7cc5d906 --- /dev/null +++ b/src/test/ui/error-codes/E0138.stderr @@ -0,0 +1,11 @@ +error[E0138]: multiple 'start' functions + --> $DIR/E0138.rs:17:1 + | +14 | fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } + | ---------------------------------------------------------- previous `start` function here +... +17 | fn f(argc: isize, argv: *const *const u8) -> isize { 0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ multiple `start` functions + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0152.rs b/src/test/ui/error-codes/E0152.rs new file mode 100644 index 00000000000..ae501b94e3f --- /dev/null +++ b/src/test/ui/error-codes/E0152.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(lang_items)] + +#[lang = "panic_fmt"] +struct Foo; //~ ERROR E0152 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0152.stderr b/src/test/ui/error-codes/E0152.stderr new file mode 100644 index 00000000000..a1d5597f031 --- /dev/null +++ b/src/test/ui/error-codes/E0152.stderr @@ -0,0 +1,10 @@ +error[E0152]: duplicate lang item found: `panic_fmt`. + --> $DIR/E0152.rs:14:1 + | +14 | struct Foo; //~ ERROR E0152 + | ^^^^^^^^^^^ + | + = note: first defined in crate `std`. + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0161.rs b/src/test/ui/error-codes/E0161.rs new file mode 100644 index 00000000000..81adf908302 --- /dev/null +++ b/src/test/ui/error-codes/E0161.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(box_syntax)] + +fn main() { + let _x: Box = box *"hello"; //~ ERROR E0161 + //~^ ERROR E0507 +} diff --git a/src/test/ui/error-codes/E0161.stderr b/src/test/ui/error-codes/E0161.stderr new file mode 100644 index 00000000000..9914fdd2d61 --- /dev/null +++ b/src/test/ui/error-codes/E0161.stderr @@ -0,0 +1,14 @@ +error[E0161]: cannot move a value of type str: the size of str cannot be statically determined + --> $DIR/E0161.rs:14:28 + | +14 | let _x: Box = box *"hello"; //~ ERROR E0161 + | ^^^^^^^^ + +error[E0507]: cannot move out of borrowed content + --> $DIR/E0161.rs:14:28 + | +14 | let _x: Box = box *"hello"; //~ ERROR E0161 + | ^^^^^^^^ cannot move out of borrowed content + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0162.rs b/src/test/ui/error-codes/E0162.rs new file mode 100644 index 00000000000..e13b0af6f79 --- /dev/null +++ b/src/test/ui/error-codes/E0162.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. + +struct Irrefutable(i32); + +fn main() { + let irr = Irrefutable(0); + if let Irrefutable(x) = irr { //~ ERROR E0162 + println!("{}", x); + } +} diff --git a/src/test/ui/error-codes/E0162.stderr b/src/test/ui/error-codes/E0162.stderr new file mode 100644 index 00000000000..318a023d302 --- /dev/null +++ b/src/test/ui/error-codes/E0162.stderr @@ -0,0 +1,8 @@ +error[E0162]: irrefutable if-let pattern + --> $DIR/E0162.rs:15:12 + | +15 | if let Irrefutable(x) = irr { //~ ERROR E0162 + | ^^^^^^^^^^^^^^ irrefutable pattern + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0164.rs b/src/test/ui/error-codes/E0164.rs new file mode 100644 index 00000000000..a7f10ddb5a7 --- /dev/null +++ b/src/test/ui/error-codes/E0164.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. + + +enum Foo {} + +impl Foo { + const B: u8 = 0; +} + +fn bar(foo: Foo) -> u32 { + match foo { + Foo::B(i) => i, //~ ERROR E0164 + } +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0164.stderr b/src/test/ui/error-codes/E0164.stderr new file mode 100644 index 00000000000..a515c83d14b --- /dev/null +++ b/src/test/ui/error-codes/E0164.stderr @@ -0,0 +1,8 @@ +error[E0164]: expected tuple struct/variant, found associated constant `::B` + --> $DIR/E0164.rs:20:9 + | +20 | Foo::B(i) => i, //~ ERROR E0164 + | ^^^^^^^^^ not a tuple variant or struct + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0165.rs b/src/test/ui/error-codes/E0165.rs new file mode 100644 index 00000000000..142635fc6ee --- /dev/null +++ b/src/test/ui/error-codes/E0165.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 Irrefutable(i32); + +fn main() { + let irr = Irrefutable(0); + while let Irrefutable(x) = irr { //~ ERROR E0165 + //~| irrefutable pattern + // ... + } +} diff --git a/src/test/ui/error-codes/E0165.stderr b/src/test/ui/error-codes/E0165.stderr new file mode 100644 index 00000000000..3c90f19a0dc --- /dev/null +++ b/src/test/ui/error-codes/E0165.stderr @@ -0,0 +1,8 @@ +error[E0165]: irrefutable while-let pattern + --> $DIR/E0165.rs:15:15 + | +15 | while let Irrefutable(x) = irr { //~ ERROR E0165 + | ^^^^^^^^^^^^^^ irrefutable pattern + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0184.rs b/src/test/ui/error-codes/E0184.rs new file mode 100644 index 00000000000..5d72d00ffe8 --- /dev/null +++ b/src/test/ui/error-codes/E0184.rs @@ -0,0 +1,20 @@ +// 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. + +#[derive(Copy)] //~ ERROR E0184 +struct Foo; + +impl Drop for Foo { + fn drop(&mut self) { + } +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0184.stderr b/src/test/ui/error-codes/E0184.stderr new file mode 100644 index 00000000000..53bda3bb575 --- /dev/null +++ b/src/test/ui/error-codes/E0184.stderr @@ -0,0 +1,8 @@ +error[E0184]: the trait `Copy` may not be implemented for this type; the type has a destructor + --> $DIR/E0184.rs:11:10 + | +11 | #[derive(Copy)] //~ ERROR E0184 + | ^^^^ Copy not allowed on types with destructors + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0185.rs b/src/test/ui/error-codes/E0185.rs new file mode 100644 index 00000000000..0cd3d00a735 --- /dev/null +++ b/src/test/ui/error-codes/E0185.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. + +trait Foo { + fn foo(); + //~^ NOTE trait method declared without `&self` +} + +struct Bar; + +impl Foo for Bar { + fn foo(&self) {} + //~^ ERROR E0185 + //~| NOTE `&self` used in impl +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0185.stderr b/src/test/ui/error-codes/E0185.stderr new file mode 100644 index 00000000000..0d24a3712d5 --- /dev/null +++ b/src/test/ui/error-codes/E0185.stderr @@ -0,0 +1,11 @@ +error[E0185]: method `foo` has a `&self` declaration in the impl, but not in the trait + --> $DIR/E0185.rs:19:5 + | +12 | fn foo(); + | --------- trait method declared without `&self` +... +19 | fn foo(&self) {} + | ^^^^^^^^^^^^^ `&self` used in impl + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0186.rs b/src/test/ui/error-codes/E0186.rs new file mode 100644 index 00000000000..55a3490cac4 --- /dev/null +++ b/src/test/ui/error-codes/E0186.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. + +trait Foo { + fn foo(&self); //~ `&self` used in trait +} + +struct Bar; + +impl Foo for Bar { + fn foo() {} //~ ERROR E0186 + //~^ expected `&self` in impl +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0186.stderr b/src/test/ui/error-codes/E0186.stderr new file mode 100644 index 00000000000..598057db3a6 --- /dev/null +++ b/src/test/ui/error-codes/E0186.stderr @@ -0,0 +1,11 @@ +error[E0186]: method `foo` has a `&self` declaration in the trait, but not in the impl + --> $DIR/E0186.rs:18:5 + | +12 | fn foo(&self); //~ `&self` used in trait + | -------------- `&self` used in trait +... +18 | fn foo() {} //~ ERROR E0186 + | ^^^^^^^^ expected `&self` in impl + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0191.rs b/src/test/ui/error-codes/E0191.rs new file mode 100644 index 00000000000..489ebb033f8 --- /dev/null +++ b/src/test/ui/error-codes/E0191.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 Trait { + type Bar; +} + +type Foo = Trait; //~ ERROR E0191 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0191.stderr b/src/test/ui/error-codes/E0191.stderr new file mode 100644 index 00000000000..8f99a6ecffb --- /dev/null +++ b/src/test/ui/error-codes/E0191.stderr @@ -0,0 +1,8 @@ +error[E0191]: the value of the associated type `Bar` (from the trait `Trait`) must be specified + --> $DIR/E0191.rs:15:12 + | +15 | type Foo = Trait; //~ ERROR E0191 + | ^^^^^ missing associated type `Bar` value + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0192.rs b/src/test/ui/error-codes/E0192.rs new file mode 100644 index 00000000000..92f5876ee04 --- /dev/null +++ b/src/test/ui/error-codes/E0192.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(optin_builtin_traits)] + +trait Trait { + type Bar; +} + +struct Foo; + +impl !Trait for Foo { } //~ ERROR E0192 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0192.stderr b/src/test/ui/error-codes/E0192.stderr new file mode 100644 index 00000000000..b592c87efa7 --- /dev/null +++ b/src/test/ui/error-codes/E0192.stderr @@ -0,0 +1,8 @@ +error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and `Sync`) + --> $DIR/E0192.rs:19:1 + | +19 | impl !Trait for Foo { } //~ ERROR E0192 + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0194.rs b/src/test/ui/error-codes/E0194.rs new file mode 100644 index 00000000000..17e0751859d --- /dev/null +++ b/src/test/ui/error-codes/E0194.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 do_something(&self) -> T; + fn do_something_else(&self, bar: T); + //~^ ERROR E0194 +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0194.stderr b/src/test/ui/error-codes/E0194.stderr new file mode 100644 index 00000000000..360e8c08a3c --- /dev/null +++ b/src/test/ui/error-codes/E0194.stderr @@ -0,0 +1,11 @@ +error[E0194]: type parameter `T` shadows another type parameter of the same name + --> $DIR/E0194.rs:13:26 + | +11 | trait Foo { + | - first `T` declared here +12 | fn do_something(&self) -> T; +13 | fn do_something_else(&self, bar: T); + | ^ shadows another type parameter + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0195.rs b/src/test/ui/error-codes/E0195.rs new file mode 100644 index 00000000000..4f4d7ce0dba --- /dev/null +++ b/src/test/ui/error-codes/E0195.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. + +trait Trait { + fn bar<'a,'b:'a>(x: &'a str, y: &'b str); + //~^ NOTE lifetimes in impl do not match this method in trait +} + +struct Foo; + +impl Trait for Foo { + fn bar<'a,'b>(x: &'a str, y: &'b str) { //~ ERROR E0195 + //~^ NOTE lifetimes do not match method in trait + } +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0195.stderr b/src/test/ui/error-codes/E0195.stderr new file mode 100644 index 00000000000..3cce3d07994 --- /dev/null +++ b/src/test/ui/error-codes/E0195.stderr @@ -0,0 +1,11 @@ +error[E0195]: lifetime parameters or bounds on method `bar` do not match the trait declaration + --> $DIR/E0195.rs:19:5 + | +12 | fn bar<'a,'b:'a>(x: &'a str, y: &'b str); + | ----------------------------------------- lifetimes in impl do not match this method in trait +... +19 | fn bar<'a,'b>(x: &'a str, y: &'b str) { //~ ERROR E0195 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0197.rs b/src/test/ui/error-codes/E0197.rs new file mode 100644 index 00000000000..f25fa9b92b9 --- /dev/null +++ b/src/test/ui/error-codes/E0197.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. + +struct Foo; + +unsafe impl Foo { } //~ ERROR E0197 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0197.stderr b/src/test/ui/error-codes/E0197.stderr new file mode 100644 index 00000000000..277f523e497 --- /dev/null +++ b/src/test/ui/error-codes/E0197.stderr @@ -0,0 +1,8 @@ +error[E0197]: inherent impls cannot be unsafe + --> $DIR/E0197.rs:13:1 + | +13 | unsafe impl Foo { } //~ ERROR E0197 + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0198.rs b/src/test/ui/error-codes/E0198.rs new file mode 100644 index 00000000000..1a779a41e66 --- /dev/null +++ b/src/test/ui/error-codes/E0198.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. + +#![feature(optin_builtin_traits)] + +struct Foo; + +unsafe impl !Send for Foo { } //~ ERROR E0198 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0198.stderr b/src/test/ui/error-codes/E0198.stderr new file mode 100644 index 00000000000..a85419e9a13 --- /dev/null +++ b/src/test/ui/error-codes/E0198.stderr @@ -0,0 +1,8 @@ +error[E0198]: negative impls cannot be unsafe + --> $DIR/E0198.rs:15:1 + | +15 | unsafe impl !Send for Foo { } //~ ERROR E0198 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0199.rs b/src/test/ui/error-codes/E0199.rs new file mode 100644 index 00000000000..1a5cd1941a9 --- /dev/null +++ b/src/test/ui/error-codes/E0199.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. + +#![feature(optin_builtin_traits)] + +struct Foo; + +trait Bar { } +unsafe impl Bar for Foo { } //~ ERROR implementing the trait `Bar` is not unsafe [E0199] + +fn main() { +} diff --git a/src/test/ui/error-codes/E0199.stderr b/src/test/ui/error-codes/E0199.stderr new file mode 100644 index 00000000000..efbe066e52e --- /dev/null +++ b/src/test/ui/error-codes/E0199.stderr @@ -0,0 +1,8 @@ +error[E0199]: implementing the trait `Bar` is not unsafe + --> $DIR/E0199.rs:16:1 + | +16 | unsafe impl Bar for Foo { } //~ ERROR implementing the trait `Bar` is not unsafe [E0199] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0200.rs b/src/test/ui/error-codes/E0200.rs new file mode 100644 index 00000000000..6bfea0e59d7 --- /dev/null +++ b/src/test/ui/error-codes/E0200.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. + +struct Foo; + +unsafe trait Bar { } + +impl Bar for Foo { } //~ ERROR E0200 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0200.stderr b/src/test/ui/error-codes/E0200.stderr new file mode 100644 index 00000000000..fb71da23677 --- /dev/null +++ b/src/test/ui/error-codes/E0200.stderr @@ -0,0 +1,8 @@ +error[E0200]: the trait `Bar` requires an `unsafe impl` declaration + --> $DIR/E0200.rs:15:1 + | +15 | impl Bar for Foo { } //~ ERROR E0200 + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0201.rs b/src/test/ui/error-codes/E0201.rs new file mode 100644 index 00000000000..ff6cb55f388 --- /dev/null +++ b/src/test/ui/error-codes/E0201.rs @@ -0,0 +1,32 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo(u8); + +impl Foo { + fn bar(&self) -> bool { self.0 > 5 } + fn bar() {} //~ ERROR E0201 +} + +trait Baz { + type Quux; + fn baz(&self) -> bool; +} + +impl Baz for Foo { + type Quux = u32; + + fn baz(&self) -> bool { true } + fn baz(&self) -> bool { self.0 > 5 } //~ ERROR E0201 + type Quux = u32; //~ ERROR E0201 +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0201.stderr b/src/test/ui/error-codes/E0201.stderr new file mode 100644 index 00000000000..01dbee6e092 --- /dev/null +++ b/src/test/ui/error-codes/E0201.stderr @@ -0,0 +1,27 @@ +error[E0201]: duplicate definitions with name `bar`: + --> $DIR/E0201.rs:15:5 + | +14 | fn bar(&self) -> bool { self.0 > 5 } + | ------------------------------------ previous definition of `bar` here +15 | fn bar() {} //~ ERROR E0201 + | ^^^^^^^^^^^ duplicate definition + +error[E0201]: duplicate definitions with name `baz`: + --> $DIR/E0201.rs:27:5 + | +26 | fn baz(&self) -> bool { true } + | ------------------------------ previous definition of `baz` here +27 | fn baz(&self) -> bool { self.0 > 5 } //~ ERROR E0201 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition + +error[E0201]: duplicate definitions with name `Quux`: + --> $DIR/E0201.rs:28:5 + | +24 | type Quux = u32; + | ---------------- previous definition of `Quux` here +... +28 | type Quux = u32; //~ ERROR E0201 + | ^^^^^^^^^^^^^^^^ duplicate definition + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/error-codes/E0206.rs b/src/test/ui/error-codes/E0206.rs new file mode 100644 index 00000000000..da0370b301b --- /dev/null +++ b/src/test/ui/error-codes/E0206.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. + +type Foo = i32; + +impl Copy for Foo { } +//~^ ERROR the trait `Copy` may not be implemented for this type +//~| ERROR only traits defined in the current crate can be implemented for arbitrary types + +#[derive(Copy, Clone)] +struct Bar; + +impl Copy for &'static Bar { } +//~^ ERROR the trait `Copy` may not be implemented for this type + +fn main() { +} diff --git a/src/test/ui/error-codes/E0206.stderr b/src/test/ui/error-codes/E0206.stderr new file mode 100644 index 00000000000..8eeb94a42f4 --- /dev/null +++ b/src/test/ui/error-codes/E0206.stderr @@ -0,0 +1,23 @@ +error[E0206]: the trait `Copy` may not be implemented for this type + --> $DIR/E0206.rs:13:15 + | +13 | impl Copy for Foo { } + | ^^^ type is not a structure or enumeration + +error[E0206]: the trait `Copy` may not be implemented for this type + --> $DIR/E0206.rs:20:15 + | +20 | impl Copy for &'static Bar { } + | ^^^^^^^^^^^^ type is not a structure or enumeration + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/E0206.rs:13:1 + | +13 | impl Copy for Foo { } + | ^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate + | + = note: the impl does not reference any types defined in this crate + = note: define and implement a trait or new type instead + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/error-codes/E0207.rs b/src/test/ui/error-codes/E0207.rs new file mode 100644 index 00000000000..bd87dbaf786 --- /dev/null +++ b/src/test/ui/error-codes/E0207.rs @@ -0,0 +1,20 @@ +// 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; + +impl Foo { //~ ERROR E0207 + fn get(&self) -> T { + ::default() + } +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0207.stderr b/src/test/ui/error-codes/E0207.stderr new file mode 100644 index 00000000000..35f9109fe99 --- /dev/null +++ b/src/test/ui/error-codes/E0207.stderr @@ -0,0 +1,8 @@ +error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates + --> $DIR/E0207.rs:13:6 + | +13 | impl Foo { //~ ERROR E0207 + | ^ unconstrained type parameter + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0214.rs b/src/test/ui/error-codes/E0214.rs new file mode 100644 index 00000000000..2b090391c74 --- /dev/null +++ b/src/test/ui/error-codes/E0214.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. + +fn main() { + let v: Vec(&str) = vec!["foo"]; + //~^ ERROR E0214 +} diff --git a/src/test/ui/error-codes/E0214.stderr b/src/test/ui/error-codes/E0214.stderr new file mode 100644 index 00000000000..30f5b960a36 --- /dev/null +++ b/src/test/ui/error-codes/E0214.stderr @@ -0,0 +1,8 @@ +error[E0214]: parenthesized parameters may only be used with a trait + --> $DIR/E0214.rs:12:15 + | +12 | let v: Vec(&str) = vec!["foo"]; + | ^^^^^^ only traits may use parentheses + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0220.rs b/src/test/ui/error-codes/E0220.rs new file mode 100644 index 00000000000..2866ffcd637 --- /dev/null +++ b/src/test/ui/error-codes/E0220.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 Trait { + type Bar; +} + +type Foo = Trait; //~ ERROR E0220 + //~| ERROR E0191 +fn main() { +} diff --git a/src/test/ui/error-codes/E0220.stderr b/src/test/ui/error-codes/E0220.stderr new file mode 100644 index 00000000000..70b017b782f --- /dev/null +++ b/src/test/ui/error-codes/E0220.stderr @@ -0,0 +1,14 @@ +error[E0220]: associated type `F` not found for `Trait` + --> $DIR/E0220.rs:15:18 + | +15 | type Foo = Trait; //~ ERROR E0220 + | ^^^^^ associated type `F` not found + +error[E0191]: the value of the associated type `Bar` (from the trait `Trait`) must be specified + --> $DIR/E0220.rs:15:12 + | +15 | type Foo = Trait; //~ ERROR E0220 + | ^^^^^^^^^^^^ missing associated type `Bar` value + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0221.rs b/src/test/ui/error-codes/E0221.rs new file mode 100644 index 00000000000..99092465b0a --- /dev/null +++ b/src/test/ui/error-codes/E0221.rs @@ -0,0 +1,37 @@ +// 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 T1 {} +trait T2 {} + +trait Foo { + type A: T1; +} + +trait Bar : Foo { + type A: T2; + fn do_something() { + let _: Self::A; + //~^ ERROR E0221 + } +} + +trait T3 {} + +trait My : std::str::FromStr { + type Err: T3; + fn test() { + let _: Self::Err; + //~^ ERROR E0221 + } +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0221.stderr b/src/test/ui/error-codes/E0221.stderr new file mode 100644 index 00000000000..3dd9393d6b3 --- /dev/null +++ b/src/test/ui/error-codes/E0221.stderr @@ -0,0 +1,29 @@ +error[E0221]: ambiguous associated type `A` in bounds of `Self` + --> $DIR/E0221.rs:21:16 + | +15 | type A: T1; + | ----------- ambiguous `A` from `Foo` +... +19 | type A: T2; + | ----------- ambiguous `A` from `Bar` +20 | fn do_something() { +21 | let _: Self::A; + | ^^^^^^^ ambiguous associated type `A` + +error[E0221]: ambiguous associated type `Err` in bounds of `Self` + --> $DIR/E0221.rs:31:16 + | +29 | type Err: T3; + | ------------- ambiguous `Err` from `My` +30 | fn test() { +31 | let _: Self::Err; + | ^^^^^^^^^ ambiguous associated type `Err` + | +note: associated type `Self` could derive from `std::str::FromStr` + --> $DIR/E0221.rs:31:16 + | +31 | let _: Self::Err; + | ^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0223.rs b/src/test/ui/error-codes/E0223.rs new file mode 100644 index 00000000000..0683197b2b6 --- /dev/null +++ b/src/test/ui/error-codes/E0223.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. + +trait MyTrait { type X; } + +fn main() { + let foo: MyTrait::X; + //~^ ERROR ambiguous associated type +} diff --git a/src/test/ui/error-codes/E0223.stderr b/src/test/ui/error-codes/E0223.stderr new file mode 100644 index 00000000000..efd0d780658 --- /dev/null +++ b/src/test/ui/error-codes/E0223.stderr @@ -0,0 +1,10 @@ +error[E0223]: ambiguous associated type + --> $DIR/E0223.rs:14:14 + | +14 | let foo: MyTrait::X; + | ^^^^^^^^^^ ambiguous associated type + | + = note: specify the type using the syntax `::X` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0225.rs b/src/test/ui/error-codes/E0225.rs new file mode 100644 index 00000000000..6c77443c5ed --- /dev/null +++ b/src/test/ui/error-codes/E0225.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. + +fn main() { + let _: Box; + //~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] +} diff --git a/src/test/ui/error-codes/E0225.stderr b/src/test/ui/error-codes/E0225.stderr new file mode 100644 index 00000000000..35d40cb1017 --- /dev/null +++ b/src/test/ui/error-codes/E0225.stderr @@ -0,0 +1,8 @@ +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/E0225.rs:12:32 + | +12 | let _: Box; + | ^^^^^^^^^^^^^^ non-auto additional trait + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0229.rs b/src/test/ui/error-codes/E0229.rs new file mode 100644 index 00000000000..b70fb092a54 --- /dev/null +++ b/src/test/ui/error-codes/E0229.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. + +pub trait Foo { + type A; + fn boo(&self) -> ::A; +} + +struct Bar; + +impl Foo for isize { + type A = usize; + fn boo(&self) -> usize { 42 } +} + +fn baz(x: &>::A) {} +//~^ ERROR associated type bindings are not allowed here [E0229] + +fn main() { +} diff --git a/src/test/ui/error-codes/E0229.stderr b/src/test/ui/error-codes/E0229.stderr new file mode 100644 index 00000000000..6d88ef88bff --- /dev/null +++ b/src/test/ui/error-codes/E0229.stderr @@ -0,0 +1,8 @@ +error[E0229]: associated type bindings are not allowed here + --> $DIR/E0229.rs:23:25 + | +23 | fn baz(x: &>::A) {} + | ^^^^^ associated type not allowed here + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0232.rs b/src/test/ui/error-codes/E0232.rs new file mode 100644 index 00000000000..04657c65c8e --- /dev/null +++ b/src/test/ui/error-codes/E0232.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. + +#![feature(on_unimplemented)] + +#[rustc_on_unimplemented] +//~^ ERROR E0232 +trait Bar {} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0232.stderr b/src/test/ui/error-codes/E0232.stderr new file mode 100644 index 00000000000..e13ba62b073 --- /dev/null +++ b/src/test/ui/error-codes/E0232.stderr @@ -0,0 +1,10 @@ +error[E0232]: `#[rustc_on_unimplemented]` requires a value + --> $DIR/E0232.rs:13:1 + | +13 | #[rustc_on_unimplemented] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ value required here + | + = note: eg `#[rustc_on_unimplemented = "foo"]` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0243.rs b/src/test/ui/error-codes/E0243.rs new file mode 100644 index 00000000000..615ce0b5d42 --- /dev/null +++ b/src/test/ui/error-codes/E0243.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. + +struct Foo { x: T } +struct Bar { x: Foo } + //~^ ERROR wrong number of type arguments: expected 1, found 0 [E0243] + +fn main() { +} diff --git a/src/test/ui/error-codes/E0243.stderr b/src/test/ui/error-codes/E0243.stderr new file mode 100644 index 00000000000..82a90fff342 --- /dev/null +++ b/src/test/ui/error-codes/E0243.stderr @@ -0,0 +1,8 @@ +error[E0243]: wrong number of type arguments: expected 1, found 0 + --> $DIR/E0243.rs:12:17 + | +12 | struct Bar { x: Foo } + | ^^^ expected 1 type argument + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0244.rs b/src/test/ui/error-codes/E0244.rs new file mode 100644 index 00000000000..9a78b3139d0 --- /dev/null +++ b/src/test/ui/error-codes/E0244.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo { x: bool } +struct Bar { x: Foo } + //~^ ERROR wrong number of type arguments: expected 0, found 2 [E0244] + + +fn main() { +} diff --git a/src/test/ui/error-codes/E0244.stderr b/src/test/ui/error-codes/E0244.stderr new file mode 100644 index 00000000000..d873fbe9819 --- /dev/null +++ b/src/test/ui/error-codes/E0244.stderr @@ -0,0 +1,8 @@ +error[E0244]: wrong number of type arguments: expected 0, found 2 + --> $DIR/E0244.rs:12:23 + | +12 | struct Bar { x: Foo } + | ^^^^^^^^^ expected no type arguments + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0252.rs b/src/test/ui/error-codes/E0252.rs new file mode 100644 index 00000000000..6b353c8cd1a --- /dev/null +++ b/src/test/ui/error-codes/E0252.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. + +use foo::baz; +use bar::baz; //~ ERROR E0252 + +mod foo { + pub struct baz; +} + +mod bar { + pub mod baz {} +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0252.stderr b/src/test/ui/error-codes/E0252.stderr new file mode 100644 index 00000000000..f63597d6970 --- /dev/null +++ b/src/test/ui/error-codes/E0252.stderr @@ -0,0 +1,16 @@ +error[E0252]: the name `baz` is defined multiple times + --> $DIR/E0252.rs:12:5 + | +11 | use foo::baz; + | -------- previous import of the type `baz` here +12 | use bar::baz; //~ ERROR E0252 + | ^^^^^^^^ `baz` reimported here + | + = note: `baz` must be defined only once in the type namespace of this module +help: You can use `as` to change the binding name of the import + | +12 | use bar::baz as other_baz; //~ ERROR E0252 + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0253.rs b/src/test/ui/error-codes/E0253.rs new file mode 100644 index 00000000000..186d9019aae --- /dev/null +++ b/src/test/ui/error-codes/E0253.rs @@ -0,0 +1,20 @@ +// 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. + +mod foo { + pub trait MyTrait { + fn do_something(); + } +} + +use foo::MyTrait::do_something; + //~^ ERROR E0253 + +fn main() {} diff --git a/src/test/ui/error-codes/E0253.stderr b/src/test/ui/error-codes/E0253.stderr new file mode 100644 index 00000000000..e5a31153781 --- /dev/null +++ b/src/test/ui/error-codes/E0253.stderr @@ -0,0 +1,8 @@ +error[E0253]: `do_something` is not directly importable + --> $DIR/E0253.rs:17:5 + | +17 | use foo::MyTrait::do_something; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be imported directly + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0254.rs b/src/test/ui/error-codes/E0254.rs new file mode 100644 index 00000000000..46c74fe3735 --- /dev/null +++ b/src/test/ui/error-codes/E0254.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. + +#![feature(alloc)] +#![allow(unused_extern_crates)] + +extern crate alloc; + +mod foo { + pub trait alloc { + fn do_something(); + } +} + +use foo::alloc; +//~^ ERROR E0254 + +fn main() {} diff --git a/src/test/ui/error-codes/E0254.stderr b/src/test/ui/error-codes/E0254.stderr new file mode 100644 index 00000000000..4181c7b1f7f --- /dev/null +++ b/src/test/ui/error-codes/E0254.stderr @@ -0,0 +1,17 @@ +error[E0254]: the name `alloc` is defined multiple times + --> $DIR/E0254.rs:22:5 + | +14 | extern crate alloc; + | ------------------- previous import of the extern crate `alloc` here +... +22 | use foo::alloc; + | ^^^^^^^^^^ `alloc` reimported here + | + = note: `alloc` must be defined only once in the type namespace of this module +help: You can use `as` to change the binding name of the import + | +22 | use foo::alloc as other_alloc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0255.rs b/src/test/ui/error-codes/E0255.rs new file mode 100644 index 00000000000..e05c6bede7e --- /dev/null +++ b/src/test/ui/error-codes/E0255.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. + +use bar::foo; + +fn foo() {} //~ ERROR E0255 + +mod bar { + pub fn foo() {} +} + +fn main() {} diff --git a/src/test/ui/error-codes/E0255.stderr b/src/test/ui/error-codes/E0255.stderr new file mode 100644 index 00000000000..924ac49695c --- /dev/null +++ b/src/test/ui/error-codes/E0255.stderr @@ -0,0 +1,17 @@ +error[E0255]: the name `foo` is defined multiple times + --> $DIR/E0255.rs:13:1 + | +11 | use bar::foo; + | -------- previous import of the value `foo` here +12 | +13 | fn foo() {} //~ ERROR E0255 + | ^^^^^^^^ `foo` redefined here + | + = note: `foo` must be defined only once in the value namespace of this module +help: You can use `as` to change the binding name of the import + | +11 | use bar::foo as other_foo; + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0259.rs b/src/test/ui/error-codes/E0259.rs new file mode 100644 index 00000000000..5a47541c708 --- /dev/null +++ b/src/test/ui/error-codes/E0259.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. + +#![feature(alloc, libc)] +#![allow(unused_extern_crates)] + +extern crate alloc; + +extern crate libc as alloc; +//~^ ERROR E0259 + +fn main() {} diff --git a/src/test/ui/error-codes/E0259.stderr b/src/test/ui/error-codes/E0259.stderr new file mode 100644 index 00000000000..e05e4e1cac7 --- /dev/null +++ b/src/test/ui/error-codes/E0259.stderr @@ -0,0 +1,16 @@ +error[E0259]: the name `alloc` is defined multiple times + --> $DIR/E0259.rs:16:1 + | +14 | extern crate alloc; + | ------------------- previous import of the extern crate `alloc` here +15 | +16 | extern crate libc as alloc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `alloc` reimported here + | You can use `as` to change the binding name of the import + | + = note: `alloc` must be defined only once in the type namespace of this module + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0260.rs b/src/test/ui/error-codes/E0260.rs new file mode 100644 index 00000000000..1b01bb12203 --- /dev/null +++ b/src/test/ui/error-codes/E0260.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. + +#![feature(alloc)] +#![allow(unused_extern_crates)] + +extern crate alloc; + +mod alloc { +//~^ ERROR the name `alloc` is defined multiple times [E0260] + pub trait MyTrait { + fn do_something(); + } +} + +fn main() {} diff --git a/src/test/ui/error-codes/E0260.stderr b/src/test/ui/error-codes/E0260.stderr new file mode 100644 index 00000000000..3d899e636ee --- /dev/null +++ b/src/test/ui/error-codes/E0260.stderr @@ -0,0 +1,17 @@ +error[E0260]: the name `alloc` is defined multiple times + --> $DIR/E0260.rs:16:1 + | +14 | extern crate alloc; + | ------------------- previous import of the extern crate `alloc` here +15 | +16 | mod alloc { + | ^^^^^^^^^ `alloc` redefined here + | + = note: `alloc` must be defined only once in the type namespace of this module +help: You can use `as` to change the binding name of the import + | +14 | extern crate alloc as other_alloc; + | + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0261.rs b/src/test/ui/error-codes/E0261.rs new file mode 100644 index 00000000000..558c1c38144 --- /dev/null +++ b/src/test/ui/error-codes/E0261.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. + +fn foo(x: &'a str) { } //~ ERROR E0261 + //~| undeclared lifetime + +struct Foo { + x: &'a str, //~ ERROR E0261 + //~| undeclared lifetime +} + +fn main() {} diff --git a/src/test/ui/error-codes/E0261.stderr b/src/test/ui/error-codes/E0261.stderr new file mode 100644 index 00000000000..c8dd08211ec --- /dev/null +++ b/src/test/ui/error-codes/E0261.stderr @@ -0,0 +1,14 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/E0261.rs:11:12 + | +11 | fn foo(x: &'a str) { } //~ ERROR E0261 + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/E0261.rs:15:9 + | +15 | x: &'a str, //~ ERROR E0261 + | ^^ undeclared lifetime + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0262.rs b/src/test/ui/error-codes/E0262.rs new file mode 100644 index 00000000000..41b6acaee4a --- /dev/null +++ b/src/test/ui/error-codes/E0262.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. + +fn foo<'static>(x: &'static str) { } //~ ERROR E0262 + //~| 'static is a reserved lifetime name + +fn main() {} diff --git a/src/test/ui/error-codes/E0262.stderr b/src/test/ui/error-codes/E0262.stderr new file mode 100644 index 00000000000..0910009d2c0 --- /dev/null +++ b/src/test/ui/error-codes/E0262.stderr @@ -0,0 +1,8 @@ +error[E0262]: invalid lifetime parameter name: `'static` + --> $DIR/E0262.rs:11:8 + | +11 | fn foo<'static>(x: &'static str) { } //~ ERROR E0262 + | ^^^^^^^ 'static is a reserved lifetime name + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0263.rs b/src/test/ui/error-codes/E0263.rs new file mode 100644 index 00000000000..722f1c25e07 --- /dev/null +++ b/src/test/ui/error-codes/E0263.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, 'b, 'a>(x: &'a str, y: &'b str) { + //~^ ERROR E0263 +} + +fn main() {} diff --git a/src/test/ui/error-codes/E0263.stderr b/src/test/ui/error-codes/E0263.stderr new file mode 100644 index 00000000000..942718d50f7 --- /dev/null +++ b/src/test/ui/error-codes/E0263.stderr @@ -0,0 +1,10 @@ +error[E0263]: lifetime name `'a` declared twice in the same scope + --> $DIR/E0263.rs:11:16 + | +11 | fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) { + | -- ^^ declared twice + | | + | previous declaration here + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0264.rs b/src/test/ui/error-codes/E0264.rs new file mode 100644 index 00000000000..92332977e76 --- /dev/null +++ b/src/test/ui/error-codes/E0264.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. + +#![feature(lang_items)] + +extern "C" { + #[lang = "cake"] + fn cake(); //~ ERROR E0264 +} + +fn main() {} diff --git a/src/test/ui/error-codes/E0264.stderr b/src/test/ui/error-codes/E0264.stderr new file mode 100644 index 00000000000..b10494633ed --- /dev/null +++ b/src/test/ui/error-codes/E0264.stderr @@ -0,0 +1,8 @@ +error[E0264]: unknown external lang item: `cake` + --> $DIR/E0264.rs:15:5 + | +15 | fn cake(); //~ ERROR E0264 + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0267.rs b/src/test/ui/error-codes/E0267.rs new file mode 100644 index 00000000000..6287256e866 --- /dev/null +++ b/src/test/ui/error-codes/E0267.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. + +fn main() { + let w = || { break; }; //~ ERROR E0267 +} diff --git a/src/test/ui/error-codes/E0267.stderr b/src/test/ui/error-codes/E0267.stderr new file mode 100644 index 00000000000..2f6d9c72eeb --- /dev/null +++ b/src/test/ui/error-codes/E0267.stderr @@ -0,0 +1,8 @@ +error[E0267]: `break` inside of a closure + --> $DIR/E0267.rs:12:18 + | +12 | let w = || { break; }; //~ ERROR E0267 + | ^^^^^ cannot break inside of a closure + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0268.rs b/src/test/ui/error-codes/E0268.rs new file mode 100644 index 00000000000..41e88e2f492 --- /dev/null +++ b/src/test/ui/error-codes/E0268.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. + +fn main() { + break; //~ ERROR E0268 +} diff --git a/src/test/ui/error-codes/E0268.stderr b/src/test/ui/error-codes/E0268.stderr new file mode 100644 index 00000000000..cf89e46af04 --- /dev/null +++ b/src/test/ui/error-codes/E0268.stderr @@ -0,0 +1,8 @@ +error[E0268]: `break` outside of loop + --> $DIR/E0268.rs:12:5 + | +12 | break; //~ ERROR E0268 + | ^^^^^ cannot break outside of a loop + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0271.rs b/src/test/ui/error-codes/E0271.rs new file mode 100644 index 00000000000..d322c8b1caf --- /dev/null +++ b/src/test/ui/error-codes/E0271.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. + +trait Trait { type AssociatedType; } + +fn foo(t: T) where T: Trait { + println!("in foo"); +} + +impl Trait for i8 { type AssociatedType = &'static str; } + +fn main() { + foo(3_i8); //~ ERROR E0271 +} diff --git a/src/test/ui/error-codes/E0271.stderr b/src/test/ui/error-codes/E0271.stderr new file mode 100644 index 00000000000..c596b560ea7 --- /dev/null +++ b/src/test/ui/error-codes/E0271.stderr @@ -0,0 +1,16 @@ +error[E0271]: type mismatch resolving `::AssociatedType == u32` + --> $DIR/E0271.rs:20:5 + | +20 | foo(3_i8); //~ ERROR E0271 + | ^^^ expected reference, found u32 + | + = note: expected type `&'static str` + found type `u32` +note: required by `foo` + --> $DIR/E0271.rs:13:1 + | +13 | fn foo(t: T) where T: Trait { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0275.rs b/src/test/ui/error-codes/E0275.rs new file mode 100644 index 00000000000..8dfd1d9b4af --- /dev/null +++ b/src/test/ui/error-codes/E0275.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 {} + +struct Bar(T); + +impl Foo for T where Bar: Foo {} //~ ERROR E0275 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0275.stderr b/src/test/ui/error-codes/E0275.stderr new file mode 100644 index 00000000000..2dbe5be2155 --- /dev/null +++ b/src/test/ui/error-codes/E0275.stderr @@ -0,0 +1,79 @@ +error[E0275]: overflow evaluating the requirement `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: std::marker::Sized` + --> $DIR/E0275.rs:15:1 + | +15 | impl Foo for T where Bar: Foo {} //~ ERROR E0275 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a `#![recursion_limit="128"]` attribute to your crate + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>>` + = note: required because of the requirements on the impl of `Foo` for `Bar>` + = note: required because of the requirements on the impl of `Foo` for `Bar` +note: required by `Foo` + --> $DIR/E0275.rs:11:1 + | +11 | trait Foo {} + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0276.rs b/src/test/ui/error-codes/E0276.rs new file mode 100644 index 00000000000..62e43b02ca8 --- /dev/null +++ b/src/test/ui/error-codes/E0276.rs @@ -0,0 +1,20 @@ +// 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(x: T); +} + +impl Foo for bool { + fn foo(x: T) where T: Copy {} //~ ERROR E0276 +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0276.stderr b/src/test/ui/error-codes/E0276.stderr new file mode 100644 index 00000000000..bcbe81ac11a --- /dev/null +++ b/src/test/ui/error-codes/E0276.stderr @@ -0,0 +1,11 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/E0276.rs:16:5 + | +12 | fn foo(x: T); + | ---------------- definition of `foo` from trait +... +16 | fn foo(x: T) where T: Copy {} //~ ERROR E0276 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: std::marker::Copy` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0277-2.rs b/src/test/ui/error-codes/E0277-2.rs new file mode 100644 index 00000000000..4d1c50002a3 --- /dev/null +++ b/src/test/ui/error-codes/E0277-2.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. + +struct Foo { + bar: Bar +} + +struct Bar { + baz: Baz +} + +struct Baz { + x: *const u8 +} + +fn is_send() { } + +fn main() { + is_send::(); + //~^ ERROR the trait bound `*const u8: std::marker::Send` is not satisfied in `Foo` +} diff --git a/src/test/ui/error-codes/E0277-2.stderr b/src/test/ui/error-codes/E0277-2.stderr new file mode 100644 index 00000000000..6a0f21ef144 --- /dev/null +++ b/src/test/ui/error-codes/E0277-2.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `*const u8: std::marker::Send` is not satisfied in `Foo` + --> $DIR/E0277-2.rs:26:5 + | +26 | is_send::(); + | ^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely + | + = help: within `Foo`, the trait `std::marker::Send` is not implemented for `*const u8` + = note: required because it appears within the type `Baz` + = note: required because it appears within the type `Bar` + = note: required because it appears within the type `Foo` +note: required by `is_send` + --> $DIR/E0277-2.rs:23:1 + | +23 | fn is_send() { } + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0277.rs b/src/test/ui/error-codes/E0277.rs new file mode 100644 index 00000000000..b29e4357015 --- /dev/null +++ b/src/test/ui/error-codes/E0277.rs @@ -0,0 +1,29 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-cloudabi no std::path + +use std::path::Path; + +trait Foo { + fn bar(&self); +} + +fn some_func(foo: T) { + foo.bar(); +} + +fn f(p: Path) { } +//~^ ERROR the trait bound `[u8]: std::marker::Sized` is not satisfied in `std::path::Path` + +fn main() { + some_func(5i32); + //~^ ERROR the trait bound `i32: Foo` is not satisfied +} diff --git a/src/test/ui/error-codes/E0277.stderr b/src/test/ui/error-codes/E0277.stderr new file mode 100644 index 00000000000..38d14ed7bce --- /dev/null +++ b/src/test/ui/error-codes/E0277.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `[u8]: std::marker::Sized` is not satisfied in `std::path::Path` + --> $DIR/E0277.rs:23:6 + | +23 | fn f(p: Path) { } + | ^ `[u8]` does not have a constant size known at compile-time + | + = help: within `std::path::Path`, the trait `std::marker::Sized` is not implemented for `[u8]` + = note: required because it appears within the type `std::path::Path` + = note: all local variables must have a statically known size + +error[E0277]: the trait bound `i32: Foo` is not satisfied + --> $DIR/E0277.rs:27:5 + | +27 | some_func(5i32); + | ^^^^^^^^^ the trait `Foo` is not implemented for `i32` + | +note: required by `some_func` + --> $DIR/E0277.rs:19:1 + | +19 | fn some_func(foo: T) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0282.rs b/src/test/ui/error-codes/E0282.rs new file mode 100644 index 00000000000..dfc702670ce --- /dev/null +++ b/src/test/ui/error-codes/E0282.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. + +fn main() { + let x = "hello".chars().rev().collect(); //~ ERROR E0282 +} diff --git a/src/test/ui/error-codes/E0282.stderr b/src/test/ui/error-codes/E0282.stderr new file mode 100644 index 00000000000..835162740da --- /dev/null +++ b/src/test/ui/error-codes/E0282.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed + --> $DIR/E0282.rs:12:9 + | +12 | let x = "hello".chars().rev().collect(); //~ ERROR E0282 + | ^ + | | + | cannot infer type for `_` + | consider giving `x` a type + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0283.rs b/src/test/ui/error-codes/E0283.rs new file mode 100644 index 00000000000..844c47f41b8 --- /dev/null +++ b/src/test/ui/error-codes/E0283.rs @@ -0,0 +1,29 @@ +// 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 Generator { + fn create() -> u32; +} + +struct Impl; + +impl Generator for Impl { + fn create() -> u32 { 1 } +} + +struct AnotherImpl; + +impl Generator for AnotherImpl { + fn create() -> u32 { 2 } +} + +fn main() { + let cont: u32 = Generator::create(); //~ ERROR E0283 +} diff --git a/src/test/ui/error-codes/E0283.stderr b/src/test/ui/error-codes/E0283.stderr new file mode 100644 index 00000000000..9fdb6b178c4 --- /dev/null +++ b/src/test/ui/error-codes/E0283.stderr @@ -0,0 +1,14 @@ +error[E0283]: type annotations required: cannot resolve `_: Generator` + --> $DIR/E0283.rs:28:21 + | +28 | let cont: u32 = Generator::create(); //~ ERROR E0283 + | ^^^^^^^^^^^^^^^^^ + | +note: required by `Generator::create` + --> $DIR/E0283.rs:12:5 + | +12 | fn create() -> u32; + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0296.rs b/src/test/ui/error-codes/E0296.rs new file mode 100644 index 00000000000..562fd00a18a --- /dev/null +++ b/src/test/ui/error-codes/E0296.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. + +#![recursion_limit] //~ ERROR E0296 + +fn main() {} diff --git a/src/test/ui/error-codes/E0296.stderr b/src/test/ui/error-codes/E0296.stderr new file mode 100644 index 00000000000..f6a2adc0ad3 --- /dev/null +++ b/src/test/ui/error-codes/E0296.stderr @@ -0,0 +1,8 @@ +error[E0296]: malformed recursion limit attribute, expected #![recursion_limit="N"] + --> $DIR/E0296.rs:11:1 + | +11 | #![recursion_limit] //~ ERROR E0296 + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0297.rs b/src/test/ui/error-codes/E0297.rs new file mode 100644 index 00000000000..afe4444c7af --- /dev/null +++ b/src/test/ui/error-codes/E0297.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. + +fn main() { + let xs : Vec> = vec![Some(1), None]; + + for Some(x) in xs {} + //~^ ERROR E0005 +} diff --git a/src/test/ui/error-codes/E0297.stderr b/src/test/ui/error-codes/E0297.stderr new file mode 100644 index 00000000000..2dfed66ecac --- /dev/null +++ b/src/test/ui/error-codes/E0297.stderr @@ -0,0 +1,8 @@ +error[E0005]: refutable pattern in `for` loop binding: `None` not covered + --> $DIR/E0297.rs:14:9 + | +14 | for Some(x) in xs {} + | ^^^^^^^ pattern `None` not covered + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0301.rs b/src/test/ui/error-codes/E0301.rs new file mode 100644 index 00000000000..06e98289b0d --- /dev/null +++ b/src/test/ui/error-codes/E0301.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + match Some(()) { + None => { }, + option if option.take().is_none() => {}, //~ ERROR E0301 + Some(_) => { } + } +} diff --git a/src/test/ui/error-codes/E0301.stderr b/src/test/ui/error-codes/E0301.stderr new file mode 100644 index 00000000000..ff4ee32d47b --- /dev/null +++ b/src/test/ui/error-codes/E0301.stderr @@ -0,0 +1,8 @@ +error[E0301]: cannot mutably borrow in a pattern guard + --> $DIR/E0301.rs:14:19 + | +14 | option if option.take().is_none() => {}, //~ ERROR E0301 + | ^^^^^^ borrowed mutably in pattern guard + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0302.rs b/src/test/ui/error-codes/E0302.rs new file mode 100644 index 00000000000..6a5ad40b109 --- /dev/null +++ b/src/test/ui/error-codes/E0302.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + match Some(()) { + None => { }, + option if { option = None; false } => { }, //~ ERROR E0302 + Some(_) => { } + } +} diff --git a/src/test/ui/error-codes/E0302.stderr b/src/test/ui/error-codes/E0302.stderr new file mode 100644 index 00000000000..c7b33a490d1 --- /dev/null +++ b/src/test/ui/error-codes/E0302.stderr @@ -0,0 +1,8 @@ +error[E0302]: cannot assign in a pattern guard + --> $DIR/E0302.rs:14:21 + | +14 | option if { option = None; false } => { }, //~ ERROR E0302 + | ^^^^^^^^^^^^^ assignment in pattern guard + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0303.rs b/src/test/ui/error-codes/E0303.rs new file mode 100644 index 00000000000..6027414fdbd --- /dev/null +++ b/src/test/ui/error-codes/E0303.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. + +fn main() { + match Some("hi".to_string()) { + ref op_string_ref @ Some(s) => {}, + //~^ ERROR pattern bindings are not allowed after an `@` [E0303] + //~| ERROR E0009 + None => {}, + } +} diff --git a/src/test/ui/error-codes/E0303.stderr b/src/test/ui/error-codes/E0303.stderr new file mode 100644 index 00000000000..6528c97a560 --- /dev/null +++ b/src/test/ui/error-codes/E0303.stderr @@ -0,0 +1,17 @@ +error[E0009]: cannot bind by-move and by-ref in the same pattern + --> $DIR/E0303.rs:13:34 + | +13 | ref op_string_ref @ Some(s) => {}, + | -------------------------^- + | | | + | | by-move pattern here + | both by-ref and by-move used + +error[E0303]: pattern bindings are not allowed after an `@` + --> $DIR/E0303.rs:13:34 + | +13 | ref op_string_ref @ Some(s) => {}, + | ^ not allowed after `@` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0308-4.rs b/src/test/ui/error-codes/E0308-4.rs new file mode 100644 index 00000000000..bb4cd143416 --- /dev/null +++ b/src/test/ui/error-codes/E0308-4.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let x = 1u8; + match x { + 0u8...3i8 => (), //~ ERROR E0308 + _ => () + } +} diff --git a/src/test/ui/error-codes/E0308-4.stderr b/src/test/ui/error-codes/E0308-4.stderr new file mode 100644 index 00000000000..1e4beeae176 --- /dev/null +++ b/src/test/ui/error-codes/E0308-4.stderr @@ -0,0 +1,8 @@ +error[E0308]: mismatched types + --> $DIR/E0308-4.rs:14:9 + | +14 | 0u8...3i8 => (), //~ ERROR E0308 + | ^^^^^^^^^ expected u8, found i8 + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0308.rs b/src/test/ui/error-codes/E0308.rs new file mode 100644 index 00000000000..078f1d3a9a1 --- /dev/null +++ b/src/test/ui/error-codes/E0308.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. + +#![feature(intrinsics)] + +extern "rust-intrinsic" { + fn size_of(); //~ ERROR E0308 +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0308.stderr b/src/test/ui/error-codes/E0308.stderr new file mode 100644 index 00000000000..905b0210abf --- /dev/null +++ b/src/test/ui/error-codes/E0308.stderr @@ -0,0 +1,11 @@ +error[E0308]: intrinsic has wrong type + --> $DIR/E0308.rs:14:5 + | +14 | fn size_of(); //~ ERROR E0308 + | ^^^^^^^^^^^^^^^^ expected (), found usize + | + = note: expected type `unsafe extern "rust-intrinsic" fn()` + found type `unsafe extern "rust-intrinsic" fn() -> usize` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0365.rs b/src/test/ui/error-codes/E0365.rs new file mode 100644 index 00000000000..18a72b0ff9a --- /dev/null +++ b/src/test/ui/error-codes/E0365.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. + +mod foo { + pub const X: u32 = 1; +} + +pub use foo as foo2; +//~^ ERROR `foo` is private, and cannot be re-exported [E0365] + +fn main() {} diff --git a/src/test/ui/error-codes/E0365.stderr b/src/test/ui/error-codes/E0365.stderr new file mode 100644 index 00000000000..ccb13856df9 --- /dev/null +++ b/src/test/ui/error-codes/E0365.stderr @@ -0,0 +1,10 @@ +error[E0365]: `foo` is private, and cannot be re-exported + --> $DIR/E0365.rs:15:9 + | +15 | pub use foo as foo2; + | ^^^^^^^^^^^ re-export of private `foo` + | + = note: consider declaring type or module `foo` with `pub` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0370.rs b/src/test/ui/error-codes/E0370.rs new file mode 100644 index 00000000000..cafe26c65ad --- /dev/null +++ b/src/test/ui/error-codes/E0370.rs @@ -0,0 +1,20 @@ +// 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. + +#![allow(dead_code)] + +#[deny(overflowing_literals)] +#[repr(i64)] +enum Foo { + X = 0x7fffffffffffffff, + Y, //~ ERROR E0370 +} + +fn main() {} diff --git a/src/test/ui/error-codes/E0370.stderr b/src/test/ui/error-codes/E0370.stderr new file mode 100644 index 00000000000..1f248f4ed2c --- /dev/null +++ b/src/test/ui/error-codes/E0370.stderr @@ -0,0 +1,10 @@ +error[E0370]: enum discriminant overflowed + --> $DIR/E0370.rs:17:5 + | +17 | Y, //~ ERROR E0370 + | ^ overflowed on value after 9223372036854775807i64 + | + = note: explicitly set `Y = -9223372036854775808i64` if that is desired outcome + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0374.rs b/src/test/ui/error-codes/E0374.rs new file mode 100644 index 00000000000..6c4782d230d --- /dev/null +++ b/src/test/ui/error-codes/E0374.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. + +#![feature(coerce_unsized)] +use std::ops::CoerceUnsized; + +struct Foo { + a: i32, +} + +impl CoerceUnsized> for Foo //~ ERROR E0374 + where T: CoerceUnsized {} + +fn main() {} diff --git a/src/test/ui/error-codes/E0374.stderr b/src/test/ui/error-codes/E0374.stderr new file mode 100644 index 00000000000..edd463d705c --- /dev/null +++ b/src/test/ui/error-codes/E0374.stderr @@ -0,0 +1,9 @@ +error[E0374]: the trait `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced, none found + --> $DIR/E0374.rs:18:1 + | +18 | / impl CoerceUnsized> for Foo //~ ERROR E0374 +19 | | where T: CoerceUnsized {} + | |________________________________^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0375.rs b/src/test/ui/error-codes/E0375.rs new file mode 100644 index 00000000000..094ed35cc2d --- /dev/null +++ b/src/test/ui/error-codes/E0375.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. + +// ignore-tidy-linelength + +#![feature(coerce_unsized)] +use std::ops::CoerceUnsized; + +struct Foo { + a: i32, + b: T, + c: U, +} + +impl CoerceUnsized> for Foo {} +//~^ ERROR E0375 + +fn main() {} diff --git a/src/test/ui/error-codes/E0375.stderr b/src/test/ui/error-codes/E0375.stderr new file mode 100644 index 00000000000..a37591521c8 --- /dev/null +++ b/src/test/ui/error-codes/E0375.stderr @@ -0,0 +1,11 @@ +error[E0375]: implementing the trait `CoerceUnsized` requires multiple coercions + --> $DIR/E0375.rs:22:12 + | +22 | impl CoerceUnsized> for Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ requires multiple coercions + | + = note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced + = note: currently, 2 fields need coercions: b (T to U), c (U to T) + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0376.rs b/src/test/ui/error-codes/E0376.rs new file mode 100644 index 00000000000..65be358cc5f --- /dev/null +++ b/src/test/ui/error-codes/E0376.rs @@ -0,0 +1,20 @@ +// 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(coerce_unsized)] +use std::ops::CoerceUnsized; + +struct Foo { + a: T, +} + +impl CoerceUnsized for Foo {} //~ ERROR E0376 + +fn main() {} diff --git a/src/test/ui/error-codes/E0376.stderr b/src/test/ui/error-codes/E0376.stderr new file mode 100644 index 00000000000..d036adb4e29 --- /dev/null +++ b/src/test/ui/error-codes/E0376.stderr @@ -0,0 +1,8 @@ +error[E0376]: the trait `CoerceUnsized` may only be implemented for a coercion between structures + --> $DIR/E0376.rs:18:1 + | +18 | impl CoerceUnsized for Foo {} //~ ERROR E0376 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0388.rs b/src/test/ui/error-codes/E0388.rs new file mode 100644 index 00000000000..c002badfef6 --- /dev/null +++ b/src/test/ui/error-codes/E0388.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. + +static X: i32 = 1; +const C: i32 = 2; + +const CR: &'static mut i32 = &mut C; //~ ERROR E0017 +static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 + //~| ERROR cannot borrow +static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017 + +fn main() {} diff --git a/src/test/ui/error-codes/E0388.stderr b/src/test/ui/error-codes/E0388.stderr new file mode 100644 index 00000000000..ec210294cdb --- /dev/null +++ b/src/test/ui/error-codes/E0388.stderr @@ -0,0 +1,26 @@ +error[E0017]: references in constants may only refer to immutable values + --> $DIR/E0388.rs:14:30 + | +14 | const CR: &'static mut i32 = &mut C; //~ ERROR E0017 + | ^^^^^^ constants require immutable values + +error[E0017]: references in statics may only refer to immutable values + --> $DIR/E0388.rs:15:39 + | +15 | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 + | ^^^^^^ statics require immutable values + +error[E0596]: cannot borrow immutable static item as mutable + --> $DIR/E0388.rs:15:44 + | +15 | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 + | ^ + +error[E0017]: references in statics may only refer to immutable values + --> $DIR/E0388.rs:17:38 + | +17 | static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017 + | ^^^^^^ statics require immutable values + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/error-codes/E0389.rs b/src/test/ui/error-codes/E0389.rs new file mode 100644 index 00000000000..445831bf8d7 --- /dev/null +++ b/src/test/ui/error-codes/E0389.rs @@ -0,0 +1,20 @@ +// 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 FancyNum { + num: u8, +} + +fn main() { + let mut fancy = FancyNum{ num: 5 }; + let fancy_ref = &(&mut fancy); + fancy_ref.num = 6; //~ ERROR E0389 + println!("{}", fancy_ref.num); +} diff --git a/src/test/ui/error-codes/E0389.stderr b/src/test/ui/error-codes/E0389.stderr new file mode 100644 index 00000000000..e085329bac5 --- /dev/null +++ b/src/test/ui/error-codes/E0389.stderr @@ -0,0 +1,8 @@ +error[E0389]: cannot assign to data in a `&` reference + --> $DIR/E0389.rs:18:5 + | +18 | fancy_ref.num = 6; //~ ERROR E0389 + | ^^^^^^^^^^^^^^^^^ assignment into an immutable reference + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0390.rs b/src/test/ui/error-codes/E0390.rs new file mode 100644 index 00000000000..cd530dbd6b4 --- /dev/null +++ b/src/test/ui/error-codes/E0390.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. + +struct Foo { + x: i32 +} + +impl *mut Foo {} //~ ERROR E0390 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0390.stderr b/src/test/ui/error-codes/E0390.stderr new file mode 100644 index 00000000000..a10b0b87f37 --- /dev/null +++ b/src/test/ui/error-codes/E0390.stderr @@ -0,0 +1,14 @@ +error[E0390]: only a single inherent implementation marked with `#[lang = "mut_ptr"]` is allowed for the `*mut T` primitive + --> $DIR/E0390.rs:15:1 + | +15 | impl *mut Foo {} //~ ERROR E0390 + | ^^^^^^^^^^^^^^^^ + | +help: consider using a trait to implement these methods + --> $DIR/E0390.rs:15:1 + | +15 | impl *mut Foo {} //~ ERROR E0390 + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0392.rs b/src/test/ui/error-codes/E0392.rs new file mode 100644 index 00000000000..4c3efcf4e8d --- /dev/null +++ b/src/test/ui/error-codes/E0392.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. + +enum Foo { Bar } //~ ERROR E0392 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0392.stderr b/src/test/ui/error-codes/E0392.stderr new file mode 100644 index 00000000000..6c466cbb52e --- /dev/null +++ b/src/test/ui/error-codes/E0392.stderr @@ -0,0 +1,10 @@ +error[E0392]: parameter `T` is never used + --> $DIR/E0392.rs:11:10 + | +11 | enum Foo { Bar } //~ ERROR E0392 + | ^ unused type parameter + | + = help: consider removing `T` or using a marker such as `std::marker::PhantomData` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0393.rs b/src/test/ui/error-codes/E0393.rs new file mode 100644 index 00000000000..9165bc2837b --- /dev/null +++ b/src/test/ui/error-codes/E0393.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait A {} + +fn together_we_will_rule_the_galaxy(son: &A) {} +//~^ ERROR E0393 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0393.stderr b/src/test/ui/error-codes/E0393.stderr new file mode 100644 index 00000000000..10728e21901 --- /dev/null +++ b/src/test/ui/error-codes/E0393.stderr @@ -0,0 +1,10 @@ +error[E0393]: the type parameter `T` must be explicitly specified + --> $DIR/E0393.rs:13:43 + | +13 | fn together_we_will_rule_the_galaxy(son: &A) {} + | ^ missing reference to `T` + | + = note: because of the default `Self` reference, type parameters must be specified on object types + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0394.rs b/src/test/ui/error-codes/E0394.rs new file mode 100644 index 00000000000..dae8e14c5ef --- /dev/null +++ b/src/test/ui/error-codes/E0394.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. + +#![allow(warnings)] + +static A: u32 = 0; +static B: u32 = A; +//~^ ERROR E0394 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0394.stderr b/src/test/ui/error-codes/E0394.stderr new file mode 100644 index 00000000000..728cec10325 --- /dev/null +++ b/src/test/ui/error-codes/E0394.stderr @@ -0,0 +1,10 @@ +error[E0394]: cannot refer to other statics by value, use the address-of operator or a constant instead + --> $DIR/E0394.rs:14:17 + | +14 | static B: u32 = A; + | ^ referring to another static by value + | + = note: use the address-of operator or a constant instead + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0395.rs b/src/test/ui/error-codes/E0395.rs new file mode 100644 index 00000000000..00008ea6b6f --- /dev/null +++ b/src/test/ui/error-codes/E0395.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. + +static FOO: i32 = 42; +static BAR: i32 = 42; + +static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR E0395 +fn main() { +} diff --git a/src/test/ui/error-codes/E0395.stderr b/src/test/ui/error-codes/E0395.stderr new file mode 100644 index 00000000000..e6d76a696d3 --- /dev/null +++ b/src/test/ui/error-codes/E0395.stderr @@ -0,0 +1,8 @@ +error[E0395]: raw pointers cannot be compared in statics + --> $DIR/E0395.rs:14:22 + | +14 | static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR E0395 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comparing raw pointers in static + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0396.rs b/src/test/ui/error-codes/E0396.rs new file mode 100644 index 00000000000..7f34acdfb90 --- /dev/null +++ b/src/test/ui/error-codes/E0396.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. + +const REG_ADDR: *const u8 = 0x5f3759df as *const u8; + +const VALUE: u8 = unsafe { *REG_ADDR }; //~ ERROR E0396 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0396.stderr b/src/test/ui/error-codes/E0396.stderr new file mode 100644 index 00000000000..5c5c01cb988 --- /dev/null +++ b/src/test/ui/error-codes/E0396.stderr @@ -0,0 +1,8 @@ +error[E0396]: raw pointers cannot be dereferenced in constants + --> $DIR/E0396.rs:13:28 + | +13 | const VALUE: u8 = unsafe { *REG_ADDR }; //~ ERROR E0396 + | ^^^^^^^^^ dereference of raw pointer in constant + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0401.rs b/src/test/ui/error-codes/E0401.rs new file mode 100644 index 00000000000..09bc950efd2 --- /dev/null +++ b/src/test/ui/error-codes/E0401.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. + +fn foo(x: T) { + fn bar(y: T) { //~ ERROR E0401 + } + bar(x); +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0401.stderr b/src/test/ui/error-codes/E0401.stderr new file mode 100644 index 00000000000..d63aa378eee --- /dev/null +++ b/src/test/ui/error-codes/E0401.stderr @@ -0,0 +1,8 @@ +error[E0401]: can't use type parameters from outer function; try using a local type parameter instead + --> $DIR/E0401.rs:12:15 + | +12 | fn bar(y: T) { //~ ERROR E0401 + | ^ use of type variable from outer function + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0403.rs b/src/test/ui/error-codes/E0403.rs new file mode 100644 index 00000000000..6a68013dc6f --- /dev/null +++ b/src/test/ui/error-codes/E0403.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. + +fn foo(s: T, u: T) {} //~ ERROR E0403 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0403.stderr b/src/test/ui/error-codes/E0403.stderr new file mode 100644 index 00000000000..125af35cb57 --- /dev/null +++ b/src/test/ui/error-codes/E0403.stderr @@ -0,0 +1,10 @@ +error[E0403]: the name `T` is already used for a type parameter in this type parameter list + --> $DIR/E0403.rs:11:11 + | +11 | fn foo(s: T, u: T) {} //~ ERROR E0403 + | - ^ already used + | | + | first use of `T` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0404.rs b/src/test/ui/error-codes/E0404.rs new file mode 100644 index 00000000000..1c088a71d7d --- /dev/null +++ b/src/test/ui/error-codes/E0404.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo; +struct Bar; + +impl Foo for Bar {} //~ ERROR E0404 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0404.stderr b/src/test/ui/error-codes/E0404.stderr new file mode 100644 index 00000000000..c30d8c00b80 --- /dev/null +++ b/src/test/ui/error-codes/E0404.stderr @@ -0,0 +1,8 @@ +error[E0404]: expected trait, found struct `Foo` + --> $DIR/E0404.rs:14:6 + | +14 | impl Foo for Bar {} //~ ERROR E0404 + | ^^^ not a trait + +error: cannot continue compilation due to previous error + diff --git a/src/test/ui/error-codes/E0405.rs b/src/test/ui/error-codes/E0405.rs new file mode 100644 index 00000000000..45d4b219ba8 --- /dev/null +++ b/src/test/ui/error-codes/E0405.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. + +struct Foo; + +impl SomeTrait for Foo {} //~ ERROR E0405 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0405.stderr b/src/test/ui/error-codes/E0405.stderr new file mode 100644 index 00000000000..29bab3f6dd9 --- /dev/null +++ b/src/test/ui/error-codes/E0405.stderr @@ -0,0 +1,8 @@ +error[E0405]: cannot find trait `SomeTrait` in this scope + --> $DIR/E0405.rs:13:6 + | +13 | impl SomeTrait for Foo {} //~ ERROR E0405 + | ^^^^^^^^^ not found in this scope + +error: cannot continue compilation due to previous error + diff --git a/src/test/ui/error-codes/E0407.rs b/src/test/ui/error-codes/E0407.rs new file mode 100644 index 00000000000..41d8b4513ce --- /dev/null +++ b/src/test/ui/error-codes/E0407.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. + +trait Foo { + fn a(); +} + +struct Bar; + +impl Foo for Bar { + fn a() {} + fn b() {} + //~^ ERROR E0407 +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0407.stderr b/src/test/ui/error-codes/E0407.stderr new file mode 100644 index 00000000000..f71437cd6b0 --- /dev/null +++ b/src/test/ui/error-codes/E0407.stderr @@ -0,0 +1,8 @@ +error[E0407]: method `b` is not a member of trait `Foo` + --> $DIR/E0407.rs:19:5 + | +19 | fn b() {} + | ^^^^^^^^^ not a member of trait `Foo` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0408.rs b/src/test/ui/error-codes/E0408.rs new file mode 100644 index 00000000000..8ddeb20afdc --- /dev/null +++ b/src/test/ui/error-codes/E0408.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. + +fn main() { + let x = Some(0); + + match x { + Some(y) | None => {} //~ ERROR variable `y` is not bound in all patterns + _ => () + } +} diff --git a/src/test/ui/error-codes/E0408.stderr b/src/test/ui/error-codes/E0408.stderr new file mode 100644 index 00000000000..1c66bb0e5f0 --- /dev/null +++ b/src/test/ui/error-codes/E0408.stderr @@ -0,0 +1,10 @@ +error[E0408]: variable `y` is not bound in all patterns + --> $DIR/E0408.rs:15:19 + | +15 | Some(y) | None => {} //~ ERROR variable `y` is not bound in all patterns + | - ^^^^ pattern doesn't bind `y` + | | + | variable not in all patterns + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0411.rs b/src/test/ui/error-codes/E0411.rs new file mode 100644 index 00000000000..187986fbadb --- /dev/null +++ b/src/test/ui/error-codes/E0411.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. + +fn main() { + ::foo; //~ ERROR E0411 +} diff --git a/src/test/ui/error-codes/E0411.stderr b/src/test/ui/error-codes/E0411.stderr new file mode 100644 index 00000000000..dda922b5b68 --- /dev/null +++ b/src/test/ui/error-codes/E0411.stderr @@ -0,0 +1,8 @@ +error[E0411]: cannot find type `Self` in this scope + --> $DIR/E0411.rs:12:6 + | +12 | ::foo; //~ ERROR E0411 + | ^^^^ `Self` is only available in traits and impls + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0412.rs b/src/test/ui/error-codes/E0412.rs new file mode 100644 index 00000000000..f62901cac31 --- /dev/null +++ b/src/test/ui/error-codes/E0412.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. + +impl Something {} //~ ERROR E0412 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0412.stderr b/src/test/ui/error-codes/E0412.stderr new file mode 100644 index 00000000000..6ee2125af04 --- /dev/null +++ b/src/test/ui/error-codes/E0412.stderr @@ -0,0 +1,8 @@ +error[E0412]: cannot find type `Something` in this scope + --> $DIR/E0412.rs:11:6 + | +11 | impl Something {} //~ ERROR E0412 + | ^^^^^^^^^ not found in this scope + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0415.rs b/src/test/ui/error-codes/E0415.rs new file mode 100644 index 00000000000..2a5f0d3c229 --- /dev/null +++ b/src/test/ui/error-codes/E0415.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. + +fn foo(f: i32, f: i32) {} //~ ERROR E0415 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0415.stderr b/src/test/ui/error-codes/E0415.stderr new file mode 100644 index 00000000000..5e5cfe16e50 --- /dev/null +++ b/src/test/ui/error-codes/E0415.stderr @@ -0,0 +1,8 @@ +error[E0415]: identifier `f` is bound more than once in this parameter list + --> $DIR/E0415.rs:11:16 + | +11 | fn foo(f: i32, f: i32) {} //~ ERROR E0415 + | ^ used as parameter more than once + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0416.rs b/src/test/ui/error-codes/E0416.rs new file mode 100644 index 00000000000..91077ab37f3 --- /dev/null +++ b/src/test/ui/error-codes/E0416.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 main() { + match (1, 2) { + (x, x) => {} //~ ERROR E0416 + } +} diff --git a/src/test/ui/error-codes/E0416.stderr b/src/test/ui/error-codes/E0416.stderr new file mode 100644 index 00000000000..a48a3ade5c9 --- /dev/null +++ b/src/test/ui/error-codes/E0416.stderr @@ -0,0 +1,8 @@ +error[E0416]: identifier `x` is bound more than once in the same pattern + --> $DIR/E0416.rs:13:13 + | +13 | (x, x) => {} //~ ERROR E0416 + | ^ used in a pattern more than once + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0423.rs b/src/test/ui/error-codes/E0423.rs new file mode 100644 index 00000000000..f5fea77cf96 --- /dev/null +++ b/src/test/ui/error-codes/E0423.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 main () { + struct Foo { a: bool }; + + let f = Foo(); //~ ERROR E0423 +} diff --git a/src/test/ui/error-codes/E0423.stderr b/src/test/ui/error-codes/E0423.stderr new file mode 100644 index 00000000000..aee398efedd --- /dev/null +++ b/src/test/ui/error-codes/E0423.stderr @@ -0,0 +1,8 @@ +error[E0423]: expected function, found struct `Foo` + --> $DIR/E0423.rs:14:13 + | +14 | let f = Foo(); //~ ERROR E0423 + | ^^^ did you mean `Foo { /* fields */ }`? + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0424.rs b/src/test/ui/error-codes/E0424.rs new file mode 100644 index 00000000000..445d0c5f3ed --- /dev/null +++ b/src/test/ui/error-codes/E0424.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. + +struct Foo; + +impl Foo { + fn bar(self) {} + + fn foo() { + self.bar(); //~ ERROR E0424 + } +} + +fn main () { +} diff --git a/src/test/ui/error-codes/E0424.stderr b/src/test/ui/error-codes/E0424.stderr new file mode 100644 index 00000000000..d1fd432f4f0 --- /dev/null +++ b/src/test/ui/error-codes/E0424.stderr @@ -0,0 +1,8 @@ +error[E0424]: expected value, found module `self` + --> $DIR/E0424.rs:17:9 + | +17 | self.bar(); //~ ERROR E0424 + | ^^^^ `self` value is only available in methods with `self` parameter + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0425.rs b/src/test/ui/error-codes/E0425.rs new file mode 100644 index 00000000000..3786282031f --- /dev/null +++ b/src/test/ui/error-codes/E0425.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 bar() { + elf; //~ ERROR E0425 + } +} + +fn main () { +} diff --git a/src/test/ui/error-codes/E0425.stderr b/src/test/ui/error-codes/E0425.stderr new file mode 100644 index 00000000000..250ecaeb368 --- /dev/null +++ b/src/test/ui/error-codes/E0425.stderr @@ -0,0 +1,8 @@ +error[E0425]: cannot find value `elf` in this scope + --> $DIR/E0425.rs:13:9 + | +13 | elf; //~ ERROR E0425 + | ^^^ not found in this scope + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0426.rs b/src/test/ui/error-codes/E0426.rs new file mode 100644 index 00000000000..d6261d3a74e --- /dev/null +++ b/src/test/ui/error-codes/E0426.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. + +fn main () { + loop { + break 'a; + //~^ ERROR E0426 + } +} diff --git a/src/test/ui/error-codes/E0426.stderr b/src/test/ui/error-codes/E0426.stderr new file mode 100644 index 00000000000..bb05effd732 --- /dev/null +++ b/src/test/ui/error-codes/E0426.stderr @@ -0,0 +1,8 @@ +error[E0426]: use of undeclared label `'a` + --> $DIR/E0426.rs:13:15 + | +13 | break 'a; + | ^^ undeclared label `'a` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0428.rs b/src/test/ui/error-codes/E0428.rs new file mode 100644 index 00000000000..3c709f3a399 --- /dev/null +++ b/src/test/ui/error-codes/E0428.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. + +struct Bar; //~ previous definition of the type `Bar` here +struct Bar; //~ ERROR E0428 + +fn main () { +} diff --git a/src/test/ui/error-codes/E0428.stderr b/src/test/ui/error-codes/E0428.stderr new file mode 100644 index 00000000000..c739536c0ab --- /dev/null +++ b/src/test/ui/error-codes/E0428.stderr @@ -0,0 +1,12 @@ +error[E0428]: the name `Bar` is defined multiple times + --> $DIR/E0428.rs:12:1 + | +11 | struct Bar; //~ previous definition of the type `Bar` here + | ----------- previous definition of the type `Bar` here +12 | struct Bar; //~ ERROR E0428 + | ^^^^^^^^^^^ `Bar` redefined here + | + = note: `Bar` must be defined only once in the type namespace of this module + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0429.rs b/src/test/ui/error-codes/E0429.rs new file mode 100644 index 00000000000..f1cad200be6 --- /dev/null +++ b/src/test/ui/error-codes/E0429.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. + +use std::fmt::self; //~ ERROR E0429 + +fn main () { +} diff --git a/src/test/ui/error-codes/E0429.stderr b/src/test/ui/error-codes/E0429.stderr new file mode 100644 index 00000000000..96cf50500fd --- /dev/null +++ b/src/test/ui/error-codes/E0429.stderr @@ -0,0 +1,8 @@ +error[E0429]: `self` imports are only allowed within a { } list + --> $DIR/E0429.rs:11:5 + | +11 | use std::fmt::self; //~ ERROR E0429 + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0430.rs b/src/test/ui/error-codes/E0430.rs new file mode 100644 index 00000000000..992876dd294 --- /dev/null +++ b/src/test/ui/error-codes/E0430.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. + +use std::fmt::{self, self}; //~ ERROR E0430 + //~^ ERROR E0252 + +fn main () { +} diff --git a/src/test/ui/error-codes/E0430.stderr b/src/test/ui/error-codes/E0430.stderr new file mode 100644 index 00000000000..b5c80aa23f6 --- /dev/null +++ b/src/test/ui/error-codes/E0430.stderr @@ -0,0 +1,24 @@ +error[E0430]: `self` import can only appear once in an import list + --> $DIR/E0430.rs:11:16 + | +11 | use std::fmt::{self, self}; //~ ERROR E0430 + | ^^^^ ---- another `self` import appears here + | | + | can only appear once in an import list + +error[E0252]: the name `fmt` is defined multiple times + --> $DIR/E0430.rs:11:22 + | +11 | use std::fmt::{self, self}; //~ ERROR E0430 + | ---- ^^^^ `fmt` reimported here + | | + | previous import of the module `fmt` here + | + = note: `fmt` must be defined only once in the type namespace of this module +help: You can use `as` to change the binding name of the import + | +11 | use std::fmt::{self, self as other_fmt}; //~ ERROR E0430 + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0431.rs b/src/test/ui/error-codes/E0431.rs new file mode 100644 index 00000000000..09ddc1efaf4 --- /dev/null +++ b/src/test/ui/error-codes/E0431.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. + +use {self}; //~ ERROR E0431 + +fn main () { +} diff --git a/src/test/ui/error-codes/E0431.stderr b/src/test/ui/error-codes/E0431.stderr new file mode 100644 index 00000000000..c7a786b7402 --- /dev/null +++ b/src/test/ui/error-codes/E0431.stderr @@ -0,0 +1,8 @@ +error[E0431]: `self` import can only appear in an import list with a non-empty prefix + --> $DIR/E0431.rs:11:6 + | +11 | use {self}; //~ ERROR E0431 + | ^^^^ can only appear in an import list with a non-empty prefix + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0432.rs b/src/test/ui/error-codes/E0432.rs new file mode 100644 index 00000000000..08d699ee4ca --- /dev/null +++ b/src/test/ui/error-codes/E0432.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. + +use something::Foo; //~ ERROR E0432 + +fn main () { +} diff --git a/src/test/ui/error-codes/E0432.stderr b/src/test/ui/error-codes/E0432.stderr new file mode 100644 index 00000000000..6d808f038a3 --- /dev/null +++ b/src/test/ui/error-codes/E0432.stderr @@ -0,0 +1,8 @@ +error[E0432]: unresolved import `something` + --> $DIR/E0432.rs:11:5 + | +11 | use something::Foo; //~ ERROR E0432 + | ^^^^^^^^^ Maybe a missing `extern crate something;`? + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0433.rs b/src/test/ui/error-codes/E0433.rs new file mode 100644 index 00000000000..916d6220eb9 --- /dev/null +++ b/src/test/ui/error-codes/E0433.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. + +fn main () { + let map = HashMap::new(); //~ ERROR E0433 +} diff --git a/src/test/ui/error-codes/E0433.stderr b/src/test/ui/error-codes/E0433.stderr new file mode 100644 index 00000000000..691c5922f8f --- /dev/null +++ b/src/test/ui/error-codes/E0433.stderr @@ -0,0 +1,8 @@ +error[E0433]: failed to resolve. Use of undeclared type or module `HashMap` + --> $DIR/E0433.rs:12:15 + | +12 | let map = HashMap::new(); //~ ERROR E0433 + | ^^^^^^^ Use of undeclared type or module `HashMap` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0434.rs b/src/test/ui/error-codes/E0434.rs new file mode 100644 index 00000000000..747d9f72c42 --- /dev/null +++ b/src/test/ui/error-codes/E0434.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. + +fn foo() { + let y = 5; + fn bar() -> u32 { + y //~ ERROR E0434 + } +} + +fn main () { +} diff --git a/src/test/ui/error-codes/E0434.stderr b/src/test/ui/error-codes/E0434.stderr new file mode 100644 index 00000000000..06880acdb35 --- /dev/null +++ b/src/test/ui/error-codes/E0434.stderr @@ -0,0 +1,10 @@ +error[E0434]: can't capture dynamic environment in a fn item + --> $DIR/E0434.rs:14:9 + | +14 | y //~ ERROR E0434 + | ^ + | + = help: use the `|| { ... }` closure form instead + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0435.rs b/src/test/ui/error-codes/E0435.rs new file mode 100644 index 00000000000..5246fda6aaf --- /dev/null +++ b/src/test/ui/error-codes/E0435.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. + +fn main () { + let foo = 42u32; + let _: [u8; foo]; //~ ERROR E0435 +} diff --git a/src/test/ui/error-codes/E0435.stderr b/src/test/ui/error-codes/E0435.stderr new file mode 100644 index 00000000000..855903b7ec3 --- /dev/null +++ b/src/test/ui/error-codes/E0435.stderr @@ -0,0 +1,8 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/E0435.rs:13:17 + | +13 | let _: [u8; foo]; //~ ERROR E0435 + | ^^^ non-constant value + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0437.rs b/src/test/ui/error-codes/E0437.rs new file mode 100644 index 00000000000..7440a82773e --- /dev/null +++ b/src/test/ui/error-codes/E0437.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 {} + +impl Foo for i32 { + type Bar = bool; //~ ERROR E0437 +} + +fn main () { +} diff --git a/src/test/ui/error-codes/E0437.stderr b/src/test/ui/error-codes/E0437.stderr new file mode 100644 index 00000000000..ffad571d061 --- /dev/null +++ b/src/test/ui/error-codes/E0437.stderr @@ -0,0 +1,8 @@ +error[E0437]: type `Bar` is not a member of trait `Foo` + --> $DIR/E0437.rs:14:5 + | +14 | type Bar = bool; //~ ERROR E0437 + | ^^^^^^^^^^^^^^^^ not a member of trait `Foo` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0438.rs b/src/test/ui/error-codes/E0438.rs new file mode 100644 index 00000000000..61d25134993 --- /dev/null +++ b/src/test/ui/error-codes/E0438.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. + + +trait Bar {} + +impl Bar for i32 { + const BAR: bool = true; //~ ERROR E0438 +} + +fn main () { +} diff --git a/src/test/ui/error-codes/E0438.stderr b/src/test/ui/error-codes/E0438.stderr new file mode 100644 index 00000000000..df587395356 --- /dev/null +++ b/src/test/ui/error-codes/E0438.stderr @@ -0,0 +1,8 @@ +error[E0438]: const `BAR` is not a member of trait `Bar` + --> $DIR/E0438.rs:15:5 + | +15 | const BAR: bool = true; //~ ERROR E0438 + | ^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `Bar` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0439.rs b/src/test/ui/error-codes/E0439.rs new file mode 100644 index 00000000000..52443432021 --- /dev/null +++ b/src/test/ui/error-codes/E0439.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. + +#![feature(platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_shuffle(a: A, b: A, c: [u32; 8]) -> B; //~ ERROR E0439 +} + +fn main () { +} diff --git a/src/test/ui/error-codes/E0439.stderr b/src/test/ui/error-codes/E0439.stderr new file mode 100644 index 00000000000..77930d5e08d --- /dev/null +++ b/src/test/ui/error-codes/E0439.stderr @@ -0,0 +1,8 @@ +error[E0439]: invalid `simd_shuffle`, needs length: `simd_shuffle` + --> $DIR/E0439.rs:14:5 + | +14 | fn simd_shuffle(a: A, b: A, c: [u32; 8]) -> B; //~ ERROR E0439 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0440.rs b/src/test/ui/error-codes/E0440.rs new file mode 100644 index 00000000000..04e7584008d --- /dev/null +++ b/src/test/ui/error-codes/E0440.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(repr_simd)] +#![feature(platform_intrinsics)] + +#[repr(simd)] +struct f64x2(f64, f64); + +extern "platform-intrinsic" { + fn x86_mm_movemask_pd(x: f64x2) -> i32; //~ ERROR E0440 +} + +fn main () { +} diff --git a/src/test/ui/error-codes/E0440.stderr b/src/test/ui/error-codes/E0440.stderr new file mode 100644 index 00000000000..83210a996e0 --- /dev/null +++ b/src/test/ui/error-codes/E0440.stderr @@ -0,0 +1,8 @@ +error[E0440]: platform-specific intrinsic has wrong number of type parameters: found 1, expected 0 + --> $DIR/E0440.rs:18:5 + | +18 | fn x86_mm_movemask_pd(x: f64x2) -> i32; //~ ERROR E0440 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0441.rs b/src/test/ui/error-codes/E0441.rs new file mode 100644 index 00000000000..967ff643272 --- /dev/null +++ b/src/test/ui/error-codes/E0441.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. + +#![feature(repr_simd)] +#![feature(platform_intrinsics)] + +#[repr(simd)] +struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16); + +extern "platform-intrinsic" { + fn x86_mm_adds_ep16(x: i16x8, y: i16x8) -> i16x8; //~ ERROR E0441 +} + +fn main() {} diff --git a/src/test/ui/error-codes/E0441.stderr b/src/test/ui/error-codes/E0441.stderr new file mode 100644 index 00000000000..34a387e6459 --- /dev/null +++ b/src/test/ui/error-codes/E0441.stderr @@ -0,0 +1,8 @@ +error[E0441]: unrecognized platform-specific intrinsic function: `x86_mm_adds_ep16` + --> $DIR/E0441.rs:18:5 + | +18 | fn x86_mm_adds_ep16(x: i16x8, y: i16x8) -> i16x8; //~ ERROR E0441 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0442.rs b/src/test/ui/error-codes/E0442.rs new file mode 100644 index 00000000000..ddd927054be --- /dev/null +++ b/src/test/ui/error-codes/E0442.rs @@ -0,0 +1,29 @@ +// 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(repr_simd)] +#![feature(platform_intrinsics)] + +#[repr(simd)] +struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8, + i8, i8, i8, i8, i8, i8, i8, i8); +#[repr(simd)] +struct i32x4(i32, i32, i32, i32); +#[repr(simd)] +struct i64x2(i64, i64); + +extern "platform-intrinsic" { + fn x86_mm_adds_epi16(x: i8x16, y: i32x4) -> i64x2; + //~^ ERROR E0442 + //~| ERROR E0442 + //~| ERROR E0442 +} + +fn main() {} diff --git a/src/test/ui/error-codes/E0442.stderr b/src/test/ui/error-codes/E0442.stderr new file mode 100644 index 00000000000..6f19fd17eb2 --- /dev/null +++ b/src/test/ui/error-codes/E0442.stderr @@ -0,0 +1,20 @@ +error[E0442]: intrinsic argument 1 has wrong type: found vector with length 16, expected length 8 + --> $DIR/E0442.rs:23:5 + | +23 | fn x86_mm_adds_epi16(x: i8x16, y: i32x4) -> i64x2; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0442]: intrinsic argument 2 has wrong type: found vector with length 4, expected length 8 + --> $DIR/E0442.rs:23:5 + | +23 | fn x86_mm_adds_epi16(x: i8x16, y: i32x4) -> i64x2; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0442]: intrinsic return value has wrong type: found vector with length 2, expected length 8 + --> $DIR/E0442.rs:23:5 + | +23 | fn x86_mm_adds_epi16(x: i8x16, y: i32x4) -> i64x2; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/error-codes/E0443.rs b/src/test/ui/error-codes/E0443.rs new file mode 100644 index 00000000000..24d1ee01dd4 --- /dev/null +++ b/src/test/ui/error-codes/E0443.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. + +#![feature(repr_simd)] +#![feature(platform_intrinsics)] + +#[repr(simd)] +struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16); +#[repr(simd)] +struct i64x8(i64, i64, i64, i64, i64, i64, i64, i64); + +extern "platform-intrinsic" { + fn x86_mm_adds_epi16(x: i16x8, y: i16x8) -> i64x8; //~ ERROR E0443 +} + +fn main() {} diff --git a/src/test/ui/error-codes/E0443.stderr b/src/test/ui/error-codes/E0443.stderr new file mode 100644 index 00000000000..ebf8ef5ccf1 --- /dev/null +++ b/src/test/ui/error-codes/E0443.stderr @@ -0,0 +1,8 @@ +error[E0443]: intrinsic return value has wrong type: found `i64x8`, expected `i16x8` which was used for this vector type previously in this signature + --> $DIR/E0443.rs:20:5 + | +20 | fn x86_mm_adds_epi16(x: i16x8, y: i16x8) -> i64x8; //~ ERROR E0443 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0444.rs b/src/test/ui/error-codes/E0444.rs new file mode 100644 index 00000000000..a424a3ca20e --- /dev/null +++ b/src/test/ui/error-codes/E0444.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. + +#![feature(repr_simd)] +#![feature(platform_intrinsics)] + +#[repr(simd)] +struct f64x2(f64, f64); + +extern "platform-intrinsic" { + fn x86_mm_movemask_pd(x: f64x2, y: f64x2, z: f64x2) -> i32; //~ ERROR E0444 +} + +fn main() {} diff --git a/src/test/ui/error-codes/E0444.stderr b/src/test/ui/error-codes/E0444.stderr new file mode 100644 index 00000000000..e44d9457045 --- /dev/null +++ b/src/test/ui/error-codes/E0444.stderr @@ -0,0 +1,8 @@ +error[E0444]: platform-specific intrinsic has invalid number of arguments: found 3, expected 1 + --> $DIR/E0444.rs:18:5 + | +18 | fn x86_mm_movemask_pd(x: f64x2, y: f64x2, z: f64x2) -> i32; //~ ERROR E0444 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0445.rs b/src/test/ui/error-codes/E0445.rs new file mode 100644 index 00000000000..bca1b52d17a --- /dev/null +++ b/src/test/ui/error-codes/E0445.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. + +trait Foo { + fn dummy(&self) { } +} + +pub trait Bar : Foo {} +//~^ ERROR private trait `Foo` in public interface [E0445] +//~| NOTE can't leak private trait +pub struct Bar2(pub T); +//~^ ERROR private trait `Foo` in public interface [E0445] +//~| NOTE can't leak private trait +pub fn foo (t: T) {} +//~^ ERROR private trait `Foo` in public interface [E0445] +//~| NOTE can't leak private trait + +fn main() {} diff --git a/src/test/ui/error-codes/E0445.stderr b/src/test/ui/error-codes/E0445.stderr new file mode 100644 index 00000000000..7b599543e00 --- /dev/null +++ b/src/test/ui/error-codes/E0445.stderr @@ -0,0 +1,20 @@ +error[E0445]: private trait `Foo` in public interface + --> $DIR/E0445.rs:15:1 + | +15 | pub trait Bar : Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait + +error[E0445]: private trait `Foo` in public interface + --> $DIR/E0445.rs:18:1 + | +18 | pub struct Bar2(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait + +error[E0445]: private trait `Foo` in public interface + --> $DIR/E0445.rs:21:1 + | +21 | pub fn foo (t: T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/error-codes/E0446.rs b/src/test/ui/error-codes/E0446.rs new file mode 100644 index 00000000000..c5766618284 --- /dev/null +++ b/src/test/ui/error-codes/E0446.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. + +mod Foo { + struct Bar(u32); + + pub fn bar() -> Bar { //~ ERROR E0446 + Bar(0) + } +} + +fn main() {} diff --git a/src/test/ui/error-codes/E0446.stderr b/src/test/ui/error-codes/E0446.stderr new file mode 100644 index 00000000000..1b61ca9b177 --- /dev/null +++ b/src/test/ui/error-codes/E0446.stderr @@ -0,0 +1,10 @@ +error[E0446]: private type `Foo::Bar` in public interface + --> $DIR/E0446.rs:14:5 + | +14 | / pub fn bar() -> Bar { //~ ERROR E0446 +15 | | Bar(0) +16 | | } + | |_____^ can't leak private type + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0449.rs b/src/test/ui/error-codes/E0449.rs new file mode 100644 index 00000000000..ac365db33e5 --- /dev/null +++ b/src/test/ui/error-codes/E0449.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 Bar; + +trait Foo { + fn foo(); +} + +pub impl Bar {} //~ ERROR E0449 + +pub impl Foo for Bar { //~ ERROR E0449 + pub fn foo() {} //~ ERROR E0449 +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0449.stderr b/src/test/ui/error-codes/E0449.stderr new file mode 100644 index 00000000000..2270167303a --- /dev/null +++ b/src/test/ui/error-codes/E0449.stderr @@ -0,0 +1,24 @@ +error[E0449]: unnecessary visibility qualifier + --> $DIR/E0449.rs:17:1 + | +17 | pub impl Bar {} //~ ERROR E0449 + | ^^^^^^^^^^^^^^^ `pub` not needed here + | + = note: place qualifiers on individual impl items instead + +error[E0449]: unnecessary visibility qualifier + --> $DIR/E0449.rs:19:1 + | +19 | / pub impl Foo for Bar { //~ ERROR E0449 +20 | | pub fn foo() {} //~ ERROR E0449 +21 | | } + | |_^ `pub` not needed here + +error[E0449]: unnecessary visibility qualifier + --> $DIR/E0449.rs:20:5 + | +20 | pub fn foo() {} //~ ERROR E0449 + | ^^^^^^^^^^^^^^^ `pub` not needed here + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/error-codes/E0451.rs b/src/test/ui/error-codes/E0451.rs new file mode 100644 index 00000000000..af4e7d628bb --- /dev/null +++ b/src/test/ui/error-codes/E0451.rs @@ -0,0 +1,29 @@ +// 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. + +mod Bar { + pub struct Foo { + pub a: isize, + b: isize, + } + + pub struct FooTuple ( + pub isize, + isize, + ); +} + +fn pat_match(foo: Bar::Foo) { + let Bar::Foo{a:a, b:b} = foo; //~ ERROR E0451 +} + +fn main() { + let f = Bar::Foo{ a: 0, b: 0 }; //~ ERROR E0451 +} diff --git a/src/test/ui/error-codes/E0451.stderr b/src/test/ui/error-codes/E0451.stderr new file mode 100644 index 00000000000..0c29bee849b --- /dev/null +++ b/src/test/ui/error-codes/E0451.stderr @@ -0,0 +1,14 @@ +error[E0451]: field `b` of struct `Bar::Foo` is private + --> $DIR/E0451.rs:24:23 + | +24 | let Bar::Foo{a:a, b:b} = foo; //~ ERROR E0451 + | ^^^ field `b` is private + +error[E0451]: field `b` of struct `Bar::Foo` is private + --> $DIR/E0451.rs:28:29 + | +28 | let f = Bar::Foo{ a: 0, b: 0 }; //~ ERROR E0451 + | ^^^^ field `b` is private + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0452.rs b/src/test/ui/error-codes/E0452.rs new file mode 100644 index 00000000000..1665bbdd4c2 --- /dev/null +++ b/src/test/ui/error-codes/E0452.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. + +#![allow(foo = "")] //~ ERROR E0452 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0452.stderr b/src/test/ui/error-codes/E0452.stderr new file mode 100644 index 00000000000..d63d0edc2c6 --- /dev/null +++ b/src/test/ui/error-codes/E0452.stderr @@ -0,0 +1,8 @@ +error[E0452]: malformed lint attribute + --> $DIR/E0452.rs:11:10 + | +11 | #![allow(foo = "")] //~ ERROR E0452 + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0453.rs b/src/test/ui/error-codes/E0453.rs new file mode 100644 index 00000000000..8e51b84bab8 --- /dev/null +++ b/src/test/ui/error-codes/E0453.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. + +#![forbid(non_snake_case)] + +#[allow(non_snake_case)] +//~^ ERROR allow(non_snake_case) overruled by outer forbid(non_snake_case) +fn main() { +} diff --git a/src/test/ui/error-codes/E0453.stderr b/src/test/ui/error-codes/E0453.stderr new file mode 100644 index 00000000000..467784f3367 --- /dev/null +++ b/src/test/ui/error-codes/E0453.stderr @@ -0,0 +1,11 @@ +error[E0453]: allow(non_snake_case) overruled by outer forbid(non_snake_case) + --> $DIR/E0453.rs:13:9 + | +11 | #![forbid(non_snake_case)] + | -------------- `forbid` level set here +12 | +13 | #[allow(non_snake_case)] + | ^^^^^^^^^^^^^^ overruled by previous forbid + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0454.rs b/src/test/ui/error-codes/E0454.rs new file mode 100644 index 00000000000..afd0f5f5e46 --- /dev/null +++ b/src/test/ui/error-codes/E0454.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. + +#[link(name = "")] extern {} +//~^ ERROR E0454 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0454.stderr b/src/test/ui/error-codes/E0454.stderr new file mode 100644 index 00000000000..aee8b53e39d --- /dev/null +++ b/src/test/ui/error-codes/E0454.stderr @@ -0,0 +1,8 @@ +error[E0454]: #[link(name = "")] given with empty name + --> $DIR/E0454.rs:11:1 + | +11 | #[link(name = "")] extern {} + | ^^^^^^^^^^^^^^^^^^ empty name given + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0458.rs b/src/test/ui/error-codes/E0458.rs new file mode 100644 index 00000000000..fea27ef8115 --- /dev/null +++ b/src/test/ui/error-codes/E0458.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. + +#[link(kind = "wonderful_unicorn")] extern {} //~ ERROR E0458 + //~| ERROR E0459 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0458.stderr b/src/test/ui/error-codes/E0458.stderr new file mode 100644 index 00000000000..9cdd0d5f300 --- /dev/null +++ b/src/test/ui/error-codes/E0458.stderr @@ -0,0 +1,14 @@ +error[E0458]: unknown kind: `wonderful_unicorn` + --> $DIR/E0458.rs:11:1 + | +11 | #[link(kind = "wonderful_unicorn")] extern {} //~ ERROR E0458 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown kind + +error[E0459]: #[link(...)] specified without `name = "foo"` + --> $DIR/E0458.rs:11:1 + | +11 | #[link(kind = "wonderful_unicorn")] extern {} //~ ERROR E0458 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `name` argument + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0459.rs b/src/test/ui/error-codes/E0459.rs new file mode 100644 index 00000000000..dc7ac714f22 --- /dev/null +++ b/src/test/ui/error-codes/E0459.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. + +#[link(kind = "dylib")] extern {} //~ ERROR E0459 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0459.stderr b/src/test/ui/error-codes/E0459.stderr new file mode 100644 index 00000000000..512788e1948 --- /dev/null +++ b/src/test/ui/error-codes/E0459.stderr @@ -0,0 +1,8 @@ +error[E0459]: #[link(...)] specified without `name = "foo"` + --> $DIR/E0459.rs:11:1 + | +11 | #[link(kind = "dylib")] extern {} //~ ERROR E0459 + | ^^^^^^^^^^^^^^^^^^^^^^^ missing `name` argument + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0463.rs b/src/test/ui/error-codes/E0463.rs new file mode 100644 index 00000000000..aae83975b22 --- /dev/null +++ b/src/test/ui/error-codes/E0463.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(plugin)] +#![plugin(cookie_monster)] +//~^ ERROR E0463 +extern crate cake_is_a_lie; + +fn main() { +} diff --git a/src/test/ui/error-codes/E0463.stderr b/src/test/ui/error-codes/E0463.stderr new file mode 100644 index 00000000000..208c00cc7c9 --- /dev/null +++ b/src/test/ui/error-codes/E0463.stderr @@ -0,0 +1,8 @@ +error[E0463]: can't find crate for `cookie_monster` + --> $DIR/E0463.rs:12:11 + | +12 | #![plugin(cookie_monster)] + | ^^^^^^^^^^^^^^ can't find crate + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0478.rs b/src/test/ui/error-codes/E0478.rs new file mode 100644 index 00000000000..8eb4003fc97 --- /dev/null +++ b/src/test/ui/error-codes/E0478.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 Wedding<'t>: 't { } + +struct Prince<'kiss, 'SnowWhite> { + child: Box + 'SnowWhite>, //~ ERROR E0478 +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0478.stderr b/src/test/ui/error-codes/E0478.stderr new file mode 100644 index 00000000000..f909fa48c27 --- /dev/null +++ b/src/test/ui/error-codes/E0478.stderr @@ -0,0 +1,19 @@ +error[E0478]: lifetime bound not satisfied + --> $DIR/E0478.rs:14:5 + | +14 | child: Box + 'SnowWhite>, //~ ERROR E0478 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime 'SnowWhite as defined on the struct at 13:1 + --> $DIR/E0478.rs:13:1 + | +13 | struct Prince<'kiss, 'SnowWhite> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: but lifetime parameter must outlive the lifetime 'kiss as defined on the struct at 13:1 + --> $DIR/E0478.rs:13:1 + | +13 | struct Prince<'kiss, 'SnowWhite> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0492.rs b/src/test/ui/error-codes/E0492.rs new file mode 100644 index 00000000000..8e4964c97c5 --- /dev/null +++ b/src/test/ui/error-codes/E0492.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT}; + +const A: AtomicUsize = ATOMIC_USIZE_INIT; +static B: &'static AtomicUsize = &A; //~ ERROR E0492 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0492.stderr b/src/test/ui/error-codes/E0492.stderr new file mode 100644 index 00000000000..c1989662312 --- /dev/null +++ b/src/test/ui/error-codes/E0492.stderr @@ -0,0 +1,8 @@ +error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead + --> $DIR/E0492.rs:14:34 + | +14 | static B: &'static AtomicUsize = &A; //~ ERROR E0492 + | ^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0494.rs b/src/test/ui/error-codes/E0494.rs new file mode 100644 index 00000000000..5f8632ac1c2 --- /dev/null +++ b/src/test/ui/error-codes/E0494.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 Foo { + a: u32 +} + +static S : Foo = Foo { a : 0 }; +static A : &'static u32 = &S.a; //~ ERROR E0494 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0494.stderr b/src/test/ui/error-codes/E0494.stderr new file mode 100644 index 00000000000..1d5ded5bd9a --- /dev/null +++ b/src/test/ui/error-codes/E0494.stderr @@ -0,0 +1,8 @@ +error[E0494]: cannot refer to the interior of another static, use a constant instead + --> $DIR/E0494.rs:16:27 + | +16 | static A : &'static u32 = &S.a; //~ ERROR E0494 + | ^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0496.rs b/src/test/ui/error-codes/E0496.rs new file mode 100644 index 00000000000..4ca3cd9c13d --- /dev/null +++ b/src/test/ui/error-codes/E0496.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. + +struct Foo<'a> { + a: &'a i32, +} + +impl<'a> Foo<'a> { + fn f<'a>(x: &'a i32) { //~ ERROR E0496 + } +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0496.stderr b/src/test/ui/error-codes/E0496.stderr new file mode 100644 index 00000000000..ab9a08a5348 --- /dev/null +++ b/src/test/ui/error-codes/E0496.stderr @@ -0,0 +1,10 @@ +error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope + --> $DIR/E0496.rs:16:10 + | +15 | impl<'a> Foo<'a> { + | -- first declared here +16 | fn f<'a>(x: &'a i32) { //~ ERROR E0496 + | ^^ lifetime 'a already in scope + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0499.rs b/src/test/ui/error-codes/E0499.rs new file mode 100644 index 00000000000..9a64bfe2ea9 --- /dev/null +++ b/src/test/ui/error-codes/E0499.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 main() { + let mut i = 0; + let mut x = &mut i; + let mut a = &mut i; //~ ERROR E0499 +} diff --git a/src/test/ui/error-codes/E0499.stderr b/src/test/ui/error-codes/E0499.stderr new file mode 100644 index 00000000000..c3057d9b558 --- /dev/null +++ b/src/test/ui/error-codes/E0499.stderr @@ -0,0 +1,12 @@ +error[E0499]: cannot borrow `i` as mutable more than once at a time + --> $DIR/E0499.rs:14:22 + | +13 | let mut x = &mut i; + | - first mutable borrow occurs here +14 | let mut a = &mut i; //~ ERROR E0499 + | ^ second mutable borrow occurs here +15 | } + | - first borrow ends here + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0502.rs b/src/test/ui/error-codes/E0502.rs new file mode 100644 index 00000000000..fce8513ca64 --- /dev/null +++ b/src/test/ui/error-codes/E0502.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. + +fn bar(x: &mut i32) {} +fn foo(a: &mut i32) { + let ref y = a; + bar(a); //~ ERROR E0502 +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0502.stderr b/src/test/ui/error-codes/E0502.stderr new file mode 100644 index 00000000000..e578cffe564 --- /dev/null +++ b/src/test/ui/error-codes/E0502.stderr @@ -0,0 +1,12 @@ +error[E0502]: cannot borrow `*a` as mutable because `a` is also borrowed as immutable + --> $DIR/E0502.rs:14:9 + | +13 | let ref y = a; + | ----- immutable borrow occurs here +14 | bar(a); //~ ERROR E0502 + | ^ mutable borrow occurs here +15 | } + | - immutable borrow ends here + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0503.rs b/src/test/ui/error-codes/E0503.rs new file mode 100644 index 00000000000..810eb8d9b07 --- /dev/null +++ b/src/test/ui/error-codes/E0503.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 main() { + let mut value = 3; + let _borrow = &mut value; + let _sum = value + 1; //~ ERROR E0503 +} diff --git a/src/test/ui/error-codes/E0503.stderr b/src/test/ui/error-codes/E0503.stderr new file mode 100644 index 00000000000..112e2c47780 --- /dev/null +++ b/src/test/ui/error-codes/E0503.stderr @@ -0,0 +1,10 @@ +error[E0503]: cannot use `value` because it was mutably borrowed + --> $DIR/E0503.rs:14:16 + | +13 | let _borrow = &mut value; + | ----- borrow of `value` occurs here +14 | let _sum = value + 1; //~ ERROR E0503 + | ^^^^^ use of borrowed `value` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0504.rs b/src/test/ui/error-codes/E0504.rs new file mode 100644 index 00000000000..c594f241520 --- /dev/null +++ b/src/test/ui/error-codes/E0504.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. + +struct FancyNum { + num: u8, +} + +fn main() { + let fancy_num = FancyNum { num: 5 }; + let fancy_ref = &fancy_num; + + let x = move || { + println!("child function: {}", fancy_num.num); //~ ERROR E0504 + }; + + x(); + println!("main function: {}", fancy_ref.num); +} diff --git a/src/test/ui/error-codes/E0504.stderr b/src/test/ui/error-codes/E0504.stderr new file mode 100644 index 00000000000..0f1b183dba9 --- /dev/null +++ b/src/test/ui/error-codes/E0504.stderr @@ -0,0 +1,11 @@ +error[E0504]: cannot move `fancy_num` into closure because it is borrowed + --> $DIR/E0504.rs:20:40 + | +17 | let fancy_ref = &fancy_num; + | --------- borrow of `fancy_num` occurs here +... +20 | println!("child function: {}", fancy_num.num); //~ ERROR E0504 + | ^^^^^^^^^ move into closure occurs here + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0505.rs b/src/test/ui/error-codes/E0505.rs new file mode 100644 index 00000000000..2d534b8a44a --- /dev/null +++ b/src/test/ui/error-codes/E0505.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. + +struct Value {} + +fn eat(val: Value) {} + +fn main() { + let x = Value{}; + { + let _ref_to_val: &Value = &x; + eat(x); //~ ERROR E0505 + } +} diff --git a/src/test/ui/error-codes/E0505.stderr b/src/test/ui/error-codes/E0505.stderr new file mode 100644 index 00000000000..dfb327d48ea --- /dev/null +++ b/src/test/ui/error-codes/E0505.stderr @@ -0,0 +1,10 @@ +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/E0505.rs:19:13 + | +18 | let _ref_to_val: &Value = &x; + | - borrow of `x` occurs here +19 | eat(x); //~ ERROR E0505 + | ^ move out of `x` occurs here + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0507.rs b/src/test/ui/error-codes/E0507.rs new file mode 100644 index 00000000000..87b1bf51bdb --- /dev/null +++ b/src/test/ui/error-codes/E0507.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. + +use std::cell::RefCell; + +struct TheDarkKnight; + +impl TheDarkKnight { + fn nothing_is_true(self) {} +} + +fn main() { + let x = RefCell::new(TheDarkKnight); + + x.borrow().nothing_is_true(); //~ ERROR E0507 +} diff --git a/src/test/ui/error-codes/E0507.stderr b/src/test/ui/error-codes/E0507.stderr new file mode 100644 index 00000000000..407ebb8fc7b --- /dev/null +++ b/src/test/ui/error-codes/E0507.stderr @@ -0,0 +1,8 @@ +error[E0507]: cannot move out of borrowed content + --> $DIR/E0507.rs:22:5 + | +22 | x.borrow().nothing_is_true(); //~ ERROR E0507 + | ^^^^^^^^^^ cannot move out of borrowed content + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0509.rs b/src/test/ui/error-codes/E0509.rs new file mode 100644 index 00000000000..b92024cd6e2 --- /dev/null +++ b/src/test/ui/error-codes/E0509.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. + +struct FancyNum { + num: usize +} + +struct DropStruct { + fancy: FancyNum +} + +impl Drop for DropStruct { + fn drop(&mut self) { + } +} + +fn main() { + let drop_struct = DropStruct{fancy: FancyNum{num: 5}}; + let fancy_field = drop_struct.fancy; //~ ERROR E0509 + println!("Fancy: {}", fancy_field.num); +} diff --git a/src/test/ui/error-codes/E0509.stderr b/src/test/ui/error-codes/E0509.stderr new file mode 100644 index 00000000000..6da0fdbeb34 --- /dev/null +++ b/src/test/ui/error-codes/E0509.stderr @@ -0,0 +1,11 @@ +error[E0509]: cannot move out of type `DropStruct`, which implements the `Drop` trait + --> $DIR/E0509.rs:26:23 + | +26 | let fancy_field = drop_struct.fancy; //~ ERROR E0509 + | ^^^^^^^^^^^^^^^^^ + | | + | cannot move out of here + | help: consider using a reference instead: `&drop_struct.fancy` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0511.rs b/src/test/ui/error-codes/E0511.rs new file mode 100644 index 00000000000..c5c03f81825 --- /dev/null +++ b/src/test/ui/error-codes/E0511.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. + +#![feature(platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_add(a: T, b: T) -> T; +} + +fn main() { + unsafe { simd_add(0, 1); } //~ ERROR E0511 +} diff --git a/src/test/ui/error-codes/E0511.stderr b/src/test/ui/error-codes/E0511.stderr new file mode 100644 index 00000000000..b714350393b --- /dev/null +++ b/src/test/ui/error-codes/E0511.stderr @@ -0,0 +1,8 @@ +error[E0511]: invalid monomorphization of `simd_add` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/E0511.rs:18:14 + | +18 | unsafe { simd_add(0, 1); } //~ ERROR E0511 + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0512.rs b/src/test/ui/error-codes/E0512.rs new file mode 100644 index 00000000000..25f96271641 --- /dev/null +++ b/src/test/ui/error-codes/E0512.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 takes_u8(_: u8) {} + +fn main() { + unsafe { takes_u8(::std::mem::transmute(0u16)); } //~ ERROR E0512 +} diff --git a/src/test/ui/error-codes/E0512.stderr b/src/test/ui/error-codes/E0512.stderr new file mode 100644 index 00000000000..ad25bb216a3 --- /dev/null +++ b/src/test/ui/error-codes/E0512.stderr @@ -0,0 +1,11 @@ +error[E0512]: transmute called with types of different sizes + --> $DIR/E0512.rs:14:23 + | +14 | unsafe { takes_u8(::std::mem::transmute(0u16)); } //~ ERROR E0512 + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: u16 (16 bits) + = note: target type: u8 (8 bits) + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0516.rs b/src/test/ui/error-codes/E0516.rs new file mode 100644 index 00000000000..be2b89c5f39 --- /dev/null +++ b/src/test/ui/error-codes/E0516.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. + +fn main() { + let x: typeof(92) = 92; //~ ERROR E0516 + //~| reserved keyword +} diff --git a/src/test/ui/error-codes/E0516.stderr b/src/test/ui/error-codes/E0516.stderr new file mode 100644 index 00000000000..620929653f6 --- /dev/null +++ b/src/test/ui/error-codes/E0516.stderr @@ -0,0 +1,8 @@ +error[E0516]: `typeof` is a reserved keyword but unimplemented + --> $DIR/E0516.rs:12:12 + | +12 | let x: typeof(92) = 92; //~ ERROR E0516 + | ^^^^^^^^^^ reserved keyword + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0517.rs b/src/test/ui/error-codes/E0517.rs new file mode 100644 index 00000000000..561223ccdf1 --- /dev/null +++ b/src/test/ui/error-codes/E0517.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. + +#[repr(C)] //~ ERROR: E0517 +type Foo = u8; + +#[repr(packed)] //~ ERROR: E0517 +enum Foo2 {Bar, Baz} + +#[repr(u8)] //~ ERROR: E0517 +struct Foo3 {bar: bool, baz: bool} + +#[repr(C)] //~ ERROR: E0517 +impl Foo3 { +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0517.stderr b/src/test/ui/error-codes/E0517.stderr new file mode 100644 index 00000000000..968c47fa7a2 --- /dev/null +++ b/src/test/ui/error-codes/E0517.stderr @@ -0,0 +1,35 @@ +error[E0517]: attribute should be applied to struct, enum or union + --> $DIR/E0517.rs:11:8 + | +11 | #[repr(C)] //~ ERROR: E0517 + | ^ +12 | type Foo = u8; + | -------------- not a struct, enum or union + +error[E0517]: attribute should be applied to struct or union + --> $DIR/E0517.rs:14:8 + | +14 | #[repr(packed)] //~ ERROR: E0517 + | ^^^^^^ +15 | enum Foo2 {Bar, Baz} + | -------------------- not a struct or union + +error[E0517]: attribute should be applied to enum + --> $DIR/E0517.rs:17:8 + | +17 | #[repr(u8)] //~ ERROR: E0517 + | ^^ +18 | struct Foo3 {bar: bool, baz: bool} + | ---------------------------------- not an enum + +error[E0517]: attribute should be applied to struct, enum or union + --> $DIR/E0517.rs:20:8 + | +20 | #[repr(C)] //~ ERROR: E0517 + | ^ +21 | / impl Foo3 { +22 | | } + | |_- not a struct, enum or union + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/error-codes/E0518.rs b/src/test/ui/error-codes/E0518.rs new file mode 100644 index 00000000000..6d5b6e48e0d --- /dev/null +++ b/src/test/ui/error-codes/E0518.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. + +#[inline(always)] //~ ERROR: E0518 +struct Foo; + +#[inline(never)] //~ ERROR: E0518 +impl Foo { +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0518.stderr b/src/test/ui/error-codes/E0518.stderr new file mode 100644 index 00000000000..99a4a63cc9f --- /dev/null +++ b/src/test/ui/error-codes/E0518.stderr @@ -0,0 +1,19 @@ +error[E0518]: attribute should be applied to function + --> $DIR/E0518.rs:11:1 + | +11 | #[inline(always)] //~ ERROR: E0518 + | ^^^^^^^^^^^^^^^^^ +12 | struct Foo; + | ----------- not a function + +error[E0518]: attribute should be applied to function + --> $DIR/E0518.rs:14:1 + | +14 | #[inline(never)] //~ ERROR: E0518 + | ^^^^^^^^^^^^^^^^ +15 | / impl Foo { +16 | | } + | |_- not a function + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0520.rs b/src/test/ui/error-codes/E0520.rs new file mode 100644 index 00000000000..eae5b11a819 --- /dev/null +++ b/src/test/ui/error-codes/E0520.rs @@ -0,0 +1,31 @@ +// 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(specialization)] + +trait SpaceLlama { + fn fly(&self); +} + +impl SpaceLlama for T { + default fn fly(&self) {} +} + +impl SpaceLlama for T { + fn fly(&self) {} +} + +impl SpaceLlama for i32 { + default fn fly(&self) {} + //~^ ERROR E0520 +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0520.stderr b/src/test/ui/error-codes/E0520.stderr new file mode 100644 index 00000000000..272c38859ab --- /dev/null +++ b/src/test/ui/error-codes/E0520.stderr @@ -0,0 +1,15 @@ +error[E0520]: `fly` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/E0520.rs:26:5 + | +21 | / impl SpaceLlama for T { +22 | | fn fly(&self) {} +23 | | } + | |_- parent `impl` is here +... +26 | default fn fly(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `fly` + | + = note: to specialize, `fly` in the parent `impl` must be marked `default` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0522.rs b/src/test/ui/error-codes/E0522.rs new file mode 100644 index 00000000000..3d437785346 --- /dev/null +++ b/src/test/ui/error-codes/E0522.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(lang_items)] + +#[lang = "cookie"] +fn cookie() -> ! { +//~^^ ERROR definition of an unknown language item: `cookie` [E0522] + loop {} +} diff --git a/src/test/ui/error-codes/E0522.stderr b/src/test/ui/error-codes/E0522.stderr new file mode 100644 index 00000000000..819fab0088f --- /dev/null +++ b/src/test/ui/error-codes/E0522.stderr @@ -0,0 +1,10 @@ +error[E0601]: main function not found + +error[E0522]: definition of an unknown language item: `cookie` + --> $DIR/E0522.rs:13:1 + | +13 | #[lang = "cookie"] + | ^^^^^^^^^^^^^^^^^^ definition of unknown language item `cookie` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0527.rs b/src/test/ui/error-codes/E0527.rs new file mode 100644 index 00000000000..67d222e867e --- /dev/null +++ b/src/test/ui/error-codes/E0527.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. + +#![feature(slice_patterns)] + +fn main() { + let r = &[1, 2, 3, 4]; + match r { + &[a, b] => { + //~^ ERROR E0527 + println!("a={}, b={}", a, b); + } + } +} diff --git a/src/test/ui/error-codes/E0527.stderr b/src/test/ui/error-codes/E0527.stderr new file mode 100644 index 00000000000..7cd705e6d0b --- /dev/null +++ b/src/test/ui/error-codes/E0527.stderr @@ -0,0 +1,8 @@ +error[E0527]: pattern requires 2 elements but array has 4 + --> $DIR/E0527.rs:16:10 + | +16 | &[a, b] => { + | ^^^^^^ expected 4 elements + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0528.rs b/src/test/ui/error-codes/E0528.rs new file mode 100644 index 00000000000..e2aa2c067cb --- /dev/null +++ b/src/test/ui/error-codes/E0528.rs @@ -0,0 +1,20 @@ +// 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(slice_patterns)] + +fn main() { + let r = &[1, 2]; + match r { + &[a, b, c, rest..] => { + //~^ ERROR E0528 + } + } +} diff --git a/src/test/ui/error-codes/E0528.stderr b/src/test/ui/error-codes/E0528.stderr new file mode 100644 index 00000000000..ff75b07ced6 --- /dev/null +++ b/src/test/ui/error-codes/E0528.stderr @@ -0,0 +1,8 @@ +error[E0528]: pattern requires at least 3 elements but array has 2 + --> $DIR/E0528.rs:16:10 + | +16 | &[a, b, c, rest..] => { + | ^^^^^^^^^^^^^^^^^ pattern cannot match array of 2 elements + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0529.rs b/src/test/ui/error-codes/E0529.rs new file mode 100644 index 00000000000..5262ad7b716 --- /dev/null +++ b/src/test/ui/error-codes/E0529.rs @@ -0,0 +1,20 @@ +// 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(slice_patterns)] + +fn main() { + let r: f32 = 1.0; + match r { + [a, b] => { + //~^ ERROR E0529 + } + } +} diff --git a/src/test/ui/error-codes/E0529.stderr b/src/test/ui/error-codes/E0529.stderr new file mode 100644 index 00000000000..be9039be2b6 --- /dev/null +++ b/src/test/ui/error-codes/E0529.stderr @@ -0,0 +1,8 @@ +error[E0529]: expected an array or slice, found `f32` + --> $DIR/E0529.rs:16:9 + | +16 | [a, b] => { + | ^^^^^^ pattern cannot match with input type `f32` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0530.rs b/src/test/ui/error-codes/E0530.rs new file mode 100644 index 00000000000..4f674d0e671 --- /dev/null +++ b/src/test/ui/error-codes/E0530.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. + +fn main() { + static TEST: i32 = 0; + + let r: (i32, i32) = (0, 0); + match r { + TEST => {} //~ ERROR E0530 + } +} diff --git a/src/test/ui/error-codes/E0530.stderr b/src/test/ui/error-codes/E0530.stderr new file mode 100644 index 00000000000..7c0306cc772 --- /dev/null +++ b/src/test/ui/error-codes/E0530.stderr @@ -0,0 +1,11 @@ +error[E0530]: match bindings cannot shadow statics + --> $DIR/E0530.rs:16:9 + | +12 | static TEST: i32 = 0; + | --------------------- a static `TEST` is defined here +... +16 | TEST => {} //~ ERROR E0530 + | ^^^^ cannot be named the same as a static + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0532.rs b/src/test/ui/error-codes/E0532.rs new file mode 100644 index 00000000000..5dc3b5f94f3 --- /dev/null +++ b/src/test/ui/error-codes/E0532.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. + +fn main() { + let value = 1; + + match SomeStruct(value) { + StructConst1(_) => { }, + //~^ ERROR expected tuple struct/variant, found constant `StructConst1` + _ => { }, + } + + struct SomeStruct(u8); + + const StructConst1 : SomeStruct = SomeStruct(1); + const StructConst2 : SomeStruct = SomeStruct(2); +} diff --git a/src/test/ui/error-codes/E0532.stderr b/src/test/ui/error-codes/E0532.stderr new file mode 100644 index 00000000000..4eb91ce35d4 --- /dev/null +++ b/src/test/ui/error-codes/E0532.stderr @@ -0,0 +1,8 @@ +error[E0532]: expected tuple struct/variant, found constant `StructConst1` + --> $DIR/E0532.rs:15:9 + | +15 | StructConst1(_) => { }, + | ^^^^^^^^^^^^ not a tuple struct/variant + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0534.rs b/src/test/ui/error-codes/E0534.rs new file mode 100644 index 00000000000..fc465b26869 --- /dev/null +++ b/src/test/ui/error-codes/E0534.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. + +#[inline()] //~ ERROR E0534 +pub fn something() {} + +fn main() { + something(); +} diff --git a/src/test/ui/error-codes/E0534.stderr b/src/test/ui/error-codes/E0534.stderr new file mode 100644 index 00000000000..fe7a5483e59 --- /dev/null +++ b/src/test/ui/error-codes/E0534.stderr @@ -0,0 +1,8 @@ +error[E0534]: expected one argument + --> $DIR/E0534.rs:11:1 + | +11 | #[inline()] //~ ERROR E0534 + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0558.rs b/src/test/ui/error-codes/E0558.rs new file mode 100644 index 00000000000..64a6ee4cf58 --- /dev/null +++ b/src/test/ui/error-codes/E0558.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. + +#[export_name] +//~^ ERROR E0558 + +pub fn something() {} + +fn main() {} diff --git a/src/test/ui/error-codes/E0558.stderr b/src/test/ui/error-codes/E0558.stderr new file mode 100644 index 00000000000..c116201794d --- /dev/null +++ b/src/test/ui/error-codes/E0558.stderr @@ -0,0 +1,8 @@ +error[E0558]: export_name attribute has invalid format + --> $DIR/E0558.rs:11:1 + | +11 | #[export_name] + | ^^^^^^^^^^^^^^ did you mean #[export_name="*"]? + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0559.rs b/src/test/ui/error-codes/E0559.rs new file mode 100644 index 00000000000..da0f692cc28 --- /dev/null +++ b/src/test/ui/error-codes/E0559.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. + +enum Field { + Fool { x: u32 }, +} + +fn main() { + let s = Field::Fool { joke: 0 }; + //~^ ERROR E0559 +} diff --git a/src/test/ui/error-codes/E0559.stderr b/src/test/ui/error-codes/E0559.stderr new file mode 100644 index 00000000000..5d145a95180 --- /dev/null +++ b/src/test/ui/error-codes/E0559.stderr @@ -0,0 +1,10 @@ +error[E0559]: variant `Field::Fool` has no field named `joke` + --> $DIR/E0559.rs:16:27 + | +16 | let s = Field::Fool { joke: 0 }; + | ^^^^^ `Field::Fool` does not have this field + | + = note: available fields are: `x` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0560.rs b/src/test/ui/error-codes/E0560.rs new file mode 100644 index 00000000000..bbb7f08d62e --- /dev/null +++ b/src/test/ui/error-codes/E0560.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. + +struct Simba { + mother: u32, +} + +fn main() { + let s = Simba { mother: 1, father: 0 }; + //~^ ERROR E0560 +} diff --git a/src/test/ui/error-codes/E0560.stderr b/src/test/ui/error-codes/E0560.stderr new file mode 100644 index 00000000000..a0185aa8af6 --- /dev/null +++ b/src/test/ui/error-codes/E0560.stderr @@ -0,0 +1,10 @@ +error[E0560]: struct `Simba` has no field named `father` + --> $DIR/E0560.rs:16:32 + | +16 | let s = Simba { mother: 1, father: 0 }; + | ^^^^^^^ `Simba` does not have this field + | + = note: available fields are: `mother` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0565-1.rs b/src/test/ui/error-codes/E0565-1.rs new file mode 100644 index 00000000000..d3e68c7c0da --- /dev/null +++ b/src/test/ui/error-codes/E0565-1.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(attr_literals)] + +// deprecated doesn't currently support literals +#[deprecated("since")] //~ ERROR E0565 +fn f() { } + +fn main() { } diff --git a/src/test/ui/error-codes/E0565-1.stderr b/src/test/ui/error-codes/E0565-1.stderr new file mode 100644 index 00000000000..65b917ad4bd --- /dev/null +++ b/src/test/ui/error-codes/E0565-1.stderr @@ -0,0 +1,8 @@ +error[E0565]: unsupported literal + --> $DIR/E0565-1.rs:14:14 + | +14 | #[deprecated("since")] //~ ERROR E0565 + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0565.rs b/src/test/ui/error-codes/E0565.rs new file mode 100644 index 00000000000..b2d369223e7 --- /dev/null +++ b/src/test/ui/error-codes/E0565.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(attr_literals)] + +// repr currently doesn't support literals +#[repr("C")] //~ ERROR E0565 +struct A { } + +fn main() { } diff --git a/src/test/ui/error-codes/E0565.stderr b/src/test/ui/error-codes/E0565.stderr new file mode 100644 index 00000000000..0041b7689a6 --- /dev/null +++ b/src/test/ui/error-codes/E0565.stderr @@ -0,0 +1,8 @@ +error[E0565]: unsupported literal + --> $DIR/E0565.rs:14:8 + | +14 | #[repr("C")] //~ ERROR E0565 + | ^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0572.rs b/src/test/ui/error-codes/E0572.rs new file mode 100644 index 00000000000..bbaab102de7 --- /dev/null +++ b/src/test/ui/error-codes/E0572.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. + +const FOO: u32 = return 0; //~ ERROR E0572 + +fn main() {} diff --git a/src/test/ui/error-codes/E0572.stderr b/src/test/ui/error-codes/E0572.stderr new file mode 100644 index 00000000000..cad313b90a6 --- /dev/null +++ b/src/test/ui/error-codes/E0572.stderr @@ -0,0 +1,8 @@ +error[E0572]: return statement outside of function body + --> $DIR/E0572.rs:11:18 + | +11 | const FOO: u32 = return 0; //~ ERROR E0572 + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0582.rs b/src/test/ui/error-codes/E0582.rs new file mode 100644 index 00000000000..5e6f65a18f4 --- /dev/null +++ b/src/test/ui/error-codes/E0582.rs @@ -0,0 +1,52 @@ +// 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. + +// This test was derived from the wasm and parsell crates. They +// stopped compiling when #32330 is fixed. + +#![allow(dead_code, unused_variables)] + +use std::str::Chars; + +pub trait HasOutput { + type Output; +} + +#[derive(Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Debug)] +pub enum Token<'a> { + Begin(&'a str) +} + +fn mk_unexpected_char_err<'a>() -> Option<&'a i32> { + unimplemented!() +} + +fn foo<'a>(data: &mut Chars<'a>) { + bar(mk_unexpected_char_err) +} + +fn bar(t: F) + // No type can satisfy this requirement, since `'a` does not + // appear in any of the input types: + where F: for<'a> Fn() -> Option<&'a i32> + //~^ ERROR E0582 +{ +} + +fn baz(t: F) + // No type can satisfy this requirement, since `'a` does not + // appear in any of the input types: + where F: for<'a> Iterator + //~^ ERROR E0582 +{ +} + +fn main() { +} diff --git a/src/test/ui/error-codes/E0582.stderr b/src/test/ui/error-codes/E0582.stderr new file mode 100644 index 00000000000..ac206834023 --- /dev/null +++ b/src/test/ui/error-codes/E0582.stderr @@ -0,0 +1,14 @@ +error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/E0582.rs:38:30 + | +38 | where F: for<'a> Fn() -> Option<&'a i32> + | ^^^^^^^^^^^^^^^ + +error[E0582]: binding for associated type `Item` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/E0582.rs:46:31 + | +46 | where F: for<'a> Iterator + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0585.rs b/src/test/ui/error-codes/E0585.rs new file mode 100644 index 00000000000..1acaf8c0b78 --- /dev/null +++ b/src/test/ui/error-codes/E0585.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() { + /// Hello! I'm useless... + //~^ ERROR E0585 +} diff --git a/src/test/ui/error-codes/E0585.stderr b/src/test/ui/error-codes/E0585.stderr new file mode 100644 index 00000000000..49967f4ad81 --- /dev/null +++ b/src/test/ui/error-codes/E0585.stderr @@ -0,0 +1,10 @@ +error[E0585]: found a documentation comment that doesn't document anything + --> $DIR/E0585.rs:12:5 + | +12 | /// Hello! I'm useless... + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: doc comments must come before what they document, maybe a comment was intended with `//`? + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0586.rs b/src/test/ui/error-codes/E0586.rs new file mode 100644 index 00000000000..c1bfc5c73a1 --- /dev/null +++ b/src/test/ui/error-codes/E0586.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 tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; + let x = &tmp[1..=]; //~ ERROR E0586 +} diff --git a/src/test/ui/error-codes/E0586.stderr b/src/test/ui/error-codes/E0586.stderr new file mode 100644 index 00000000000..3cf16bdc3c3 --- /dev/null +++ b/src/test/ui/error-codes/E0586.stderr @@ -0,0 +1,10 @@ +error[E0586]: inclusive range with no end + --> $DIR/E0586.rs:13:22 + | +13 | let x = &tmp[1..=]; //~ ERROR E0586 + | ^ + | + = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0597.rs b/src/test/ui/error-codes/E0597.rs new file mode 100644 index 00000000000..2f4a1da91d8 --- /dev/null +++ b/src/test/ui/error-codes/E0597.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. + +struct Foo<'a> { + x: Option<&'a u32>, +} + +fn main() { + let mut x = Foo { x: None }; + let y = 0; + x.x = Some(&y); + //~^ `y` does not live long enough [E0597] +} diff --git a/src/test/ui/error-codes/E0597.stderr b/src/test/ui/error-codes/E0597.stderr new file mode 100644 index 00000000000..7316ee6475f --- /dev/null +++ b/src/test/ui/error-codes/E0597.stderr @@ -0,0 +1,13 @@ +error[E0597]: `y` does not live long enough + --> $DIR/E0597.rs:18:17 + | +18 | x.x = Some(&y); + | ^ borrowed value does not live long enough +19 | //~^ `y` does not live long enough [E0597] +20 | } + | - `y` 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 + diff --git a/src/test/ui/error-codes/E0599.rs b/src/test/ui/error-codes/E0599.rs new file mode 100644 index 00000000000..30fca2bac03 --- /dev/null +++ b/src/test/ui/error-codes/E0599.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. + +struct Foo; + +fn main() { + || if let Foo::NotEvenReal() = Foo {}; //~ ERROR E0599 +} diff --git a/src/test/ui/error-codes/E0599.stderr b/src/test/ui/error-codes/E0599.stderr new file mode 100644 index 00000000000..0274506926f --- /dev/null +++ b/src/test/ui/error-codes/E0599.stderr @@ -0,0 +1,11 @@ +error[E0599]: no associated item named `NotEvenReal` found for type `Foo` in the current scope + --> $DIR/E0599.rs:14:15 + | +11 | struct Foo; + | ----------- associated item `NotEvenReal` not found for this +... +14 | || if let Foo::NotEvenReal() = Foo {}; //~ ERROR E0599 + | ^^^^^^^^^^^^^^^^^^ associated item not found in `Foo` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0600.rs b/src/test/ui/error-codes/E0600.rs new file mode 100644 index 00000000000..5457ff26608 --- /dev/null +++ b/src/test/ui/error-codes/E0600.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() { + !"a"; //~ ERROR E0600 +} diff --git a/src/test/ui/error-codes/E0600.stderr b/src/test/ui/error-codes/E0600.stderr new file mode 100644 index 00000000000..fec5f416919 --- /dev/null +++ b/src/test/ui/error-codes/E0600.stderr @@ -0,0 +1,8 @@ +error[E0600]: cannot apply unary operator `!` to type `&'static str` + --> $DIR/E0600.rs:12:5 + | +12 | !"a"; //~ ERROR E0600 + | ^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0602.rs b/src/test/ui/error-codes/E0602.rs new file mode 100644 index 00000000000..cc3e436d433 --- /dev/null +++ b/src/test/ui/error-codes/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/ui/error-codes/E0602.stderr b/src/test/ui/error-codes/E0602.stderr new file mode 100644 index 00000000000..cb6c05326e2 --- /dev/null +++ b/src/test/ui/error-codes/E0602.stderr @@ -0,0 +1,6 @@ +error[E0602]: unknown lint: `bogus` + | + = note: requested on the command line with `-D bogus` + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0603.rs b/src/test/ui/error-codes/E0603.rs new file mode 100644 index 00000000000..1cc9f6bfa7d --- /dev/null +++ b/src/test/ui/error-codes/E0603.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. + +mod SomeModule { + const PRIVATE: u32 = 0x_a_bad_1dea_u32; +} + +fn main() { + SomeModule::PRIVATE; //~ ERROR E0603 +} diff --git a/src/test/ui/error-codes/E0603.stderr b/src/test/ui/error-codes/E0603.stderr new file mode 100644 index 00000000000..1d8e2fa9340 --- /dev/null +++ b/src/test/ui/error-codes/E0603.stderr @@ -0,0 +1,8 @@ +error[E0603]: constant `PRIVATE` is private + --> $DIR/E0603.rs:16:5 + | +16 | SomeModule::PRIVATE; //~ ERROR E0603 + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0604.rs b/src/test/ui/error-codes/E0604.rs new file mode 100644 index 00000000000..c5bf3a77b6c --- /dev/null +++ b/src/test/ui/error-codes/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/ui/error-codes/E0604.stderr b/src/test/ui/error-codes/E0604.stderr new file mode 100644 index 00000000000..78d1c4dd476 --- /dev/null +++ b/src/test/ui/error-codes/E0604.stderr @@ -0,0 +1,8 @@ +error[E0604]: only `u8` can be cast as `char`, not `u32` + --> $DIR/E0604.rs:12:5 + | +12 | 1u32 as char; //~ ERROR E0604 + | ^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0605.rs b/src/test/ui/error-codes/E0605.rs new file mode 100644 index 00000000000..4b5b8beb368 --- /dev/null +++ b/src/test/ui/error-codes/E0605.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. + +fn main() { + let x = 0u8; + x as Vec; //~ ERROR E0605 + + let v = 0 as *const u8; + v as &u8; //~ ERROR E0605 +} diff --git a/src/test/ui/error-codes/E0605.stderr b/src/test/ui/error-codes/E0605.stderr new file mode 100644 index 00000000000..0b44de25fb5 --- /dev/null +++ b/src/test/ui/error-codes/E0605.stderr @@ -0,0 +1,18 @@ +error[E0605]: non-primitive cast: `u8` as `std::vec::Vec` + --> $DIR/E0605.rs:13:5 + | +13 | x as Vec; //~ ERROR E0605 + | ^^^^^^^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait + +error[E0605]: non-primitive cast: `*const u8` as `&u8` + --> $DIR/E0605.rs:16:5 + | +16 | v as &u8; //~ ERROR E0605 + | ^^^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0606.rs b/src/test/ui/error-codes/E0606.rs new file mode 100644 index 00000000000..55071736bfe --- /dev/null +++ b/src/test/ui/error-codes/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/ui/error-codes/E0606.stderr b/src/test/ui/error-codes/E0606.stderr new file mode 100644 index 00000000000..17051da1319 --- /dev/null +++ b/src/test/ui/error-codes/E0606.stderr @@ -0,0 +1,14 @@ +error[E0606]: casting `&u8` as `u8` is invalid + --> $DIR/E0606.rs:12:5 + | +12 | &0u8 as u8; //~ ERROR E0606 + | ^^^^^^^^^^ cannot cast `&u8` as `u8` + | +help: did you mean `*&0u8`? + --> $DIR/E0606.rs:12:5 + | +12 | &0u8 as u8; //~ ERROR E0606 + | ^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0607.rs b/src/test/ui/error-codes/E0607.rs new file mode 100644 index 00000000000..fa761f2c178 --- /dev/null +++ b/src/test/ui/error-codes/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/ui/error-codes/E0607.stderr b/src/test/ui/error-codes/E0607.stderr new file mode 100644 index 00000000000..5dfe6ad59b8 --- /dev/null +++ b/src/test/ui/error-codes/E0607.stderr @@ -0,0 +1,8 @@ +error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]` + --> $DIR/E0607.rs:13:5 + | +13 | v as *const [u8]; //~ ERROR E0607 + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0608.rs b/src/test/ui/error-codes/E0608.rs new file mode 100644 index 00000000000..d47356a97ee --- /dev/null +++ b/src/test/ui/error-codes/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/ui/error-codes/E0608.stderr b/src/test/ui/error-codes/E0608.stderr new file mode 100644 index 00000000000..ab75fe82af3 --- /dev/null +++ b/src/test/ui/error-codes/E0608.stderr @@ -0,0 +1,8 @@ +error[E0608]: cannot index into a value of type `u8` + --> $DIR/E0608.rs:12:5 + | +12 | 0u8[2]; //~ ERROR E0608 + | ^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0609.rs b/src/test/ui/error-codes/E0609.rs new file mode 100644 index 00000000000..ddfd9d5f21a --- /dev/null +++ b/src/test/ui/error-codes/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/ui/error-codes/E0609.stderr b/src/test/ui/error-codes/E0609.stderr new file mode 100644 index 00000000000..561164cd277 --- /dev/null +++ b/src/test/ui/error-codes/E0609.stderr @@ -0,0 +1,16 @@ +error[E0609]: no field `foo` on type `Foo` + --> $DIR/E0609.rs:18:15 + | +18 | let _ = x.foo; //~ ERROR E0609 + | ^^^ unknown field + | + = note: available fields are: `x` + +error[E0609]: no field `1` on type `Bar` + --> $DIR/E0609.rs:21:5 + | +21 | y.1; //~ ERROR E0609 + | ^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0610.rs b/src/test/ui/error-codes/E0610.rs new file mode 100644 index 00000000000..522d8b0b943 --- /dev/null +++ b/src/test/ui/error-codes/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/ui/error-codes/E0610.stderr b/src/test/ui/error-codes/E0610.stderr new file mode 100644 index 00000000000..351e9208e95 --- /dev/null +++ b/src/test/ui/error-codes/E0610.stderr @@ -0,0 +1,8 @@ +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/E0610.rs:13:15 + | +13 | let _ = x.foo; //~ ERROR E0610 + | ^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0611.rs b/src/test/ui/error-codes/E0611.rs new file mode 100644 index 00000000000..1e392d194b1 --- /dev/null +++ b/src/test/ui/error-codes/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/ui/error-codes/E0611.stderr b/src/test/ui/error-codes/E0611.stderr new file mode 100644 index 00000000000..33fe78bc18c --- /dev/null +++ b/src/test/ui/error-codes/E0611.stderr @@ -0,0 +1,8 @@ +error[E0611]: field `0` of tuple-struct `a::Foo` is private + --> $DIR/E0611.rs:21:4 + | +21 | y.0; //~ ERROR E0611 + | ^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0612.rs b/src/test/ui/error-codes/E0612.rs new file mode 100644 index 00000000000..429a8bb7eb7 --- /dev/null +++ b/src/test/ui/error-codes/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/ui/error-codes/E0612.stderr b/src/test/ui/error-codes/E0612.stderr new file mode 100644 index 00000000000..21fdaf84dc9 --- /dev/null +++ b/src/test/ui/error-codes/E0612.stderr @@ -0,0 +1,8 @@ +error[E0612]: attempted out-of-bounds tuple index `1` on type `Foo` + --> $DIR/E0612.rs:15:4 + | +15 | y.1; //~ ERROR E0612 + | ^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0614.rs b/src/test/ui/error-codes/E0614.rs new file mode 100644 index 00000000000..909f0eb8285 --- /dev/null +++ b/src/test/ui/error-codes/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/ui/error-codes/E0614.stderr b/src/test/ui/error-codes/E0614.stderr new file mode 100644 index 00000000000..242cc36f0b9 --- /dev/null +++ b/src/test/ui/error-codes/E0614.stderr @@ -0,0 +1,8 @@ +error[E0614]: type `u32` cannot be dereferenced + --> $DIR/E0614.rs:13:5 + | +13 | *y; //~ ERROR E0614 + | ^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0615.rs b/src/test/ui/error-codes/E0615.rs new file mode 100644 index 00000000000..abfa93d2fd0 --- /dev/null +++ b/src/test/ui/error-codes/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/ui/error-codes/E0615.stderr b/src/test/ui/error-codes/E0615.stderr new file mode 100644 index 00000000000..fb3f9269f7c --- /dev/null +++ b/src/test/ui/error-codes/E0615.stderr @@ -0,0 +1,10 @@ +error[E0615]: attempted to take value of method `method` on type `Foo` + --> $DIR/E0615.rs:21:7 + | +21 | f.method; //~ ERROR E0615 + | ^^^^^^ + | + = help: maybe a `()` to call it is missing? + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0616.rs b/src/test/ui/error-codes/E0616.rs new file mode 100644 index 00000000000..2fd9f94763d --- /dev/null +++ b/src/test/ui/error-codes/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/ui/error-codes/E0616.stderr b/src/test/ui/error-codes/E0616.stderr new file mode 100644 index 00000000000..1dccd06b376 --- /dev/null +++ b/src/test/ui/error-codes/E0616.stderr @@ -0,0 +1,8 @@ +error[E0616]: field `x` of struct `a::Foo` is private + --> $DIR/E0616.rs:23:5 + | +23 | f.x; //~ ERROR E0616 + | ^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0617.rs b/src/test/ui/error-codes/E0617.rs new file mode 100644 index 00000000000..9375fd9cade --- /dev/null +++ b/src/test/ui/error-codes/E0617.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. + +// 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 + //~| HELP cast the value to `c_double` + printf(::std::ptr::null(), 0i8); + //~^ ERROR can't pass `i8` to variadic function + //~| HELP cast the value to `c_int` + printf(::std::ptr::null(), 0i16); + //~^ ERROR can't pass `i16` to variadic function + //~| HELP cast the value to `c_int` + printf(::std::ptr::null(), 0u8); + //~^ ERROR can't pass `u8` to variadic function + //~| HELP cast the value to `c_uint` + printf(::std::ptr::null(), 0u16); + //~^ ERROR can't pass `u16` to variadic function + //~| HELP cast the value to `c_uint` + printf(::std::ptr::null(), printf); + //~^ ERROR can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function + //~| HELP cast the value to `unsafe extern "C" fn(*const i8, ...)` + } +} diff --git a/src/test/ui/error-codes/E0617.stderr b/src/test/ui/error-codes/E0617.stderr new file mode 100644 index 00000000000..49d63538624 --- /dev/null +++ b/src/test/ui/error-codes/E0617.stderr @@ -0,0 +1,42 @@ +error[E0617]: can't pass `f32` to variadic function + --> $DIR/E0617.rs:19:36 + | +19 | printf(::std::ptr::null(), 0f32); + | ^^^^ help: cast the value to `c_double`: `0f32 as c_double` + +error[E0617]: can't pass `i8` to variadic function + --> $DIR/E0617.rs:22:36 + | +22 | printf(::std::ptr::null(), 0i8); + | ^^^ help: cast the value to `c_int`: `0i8 as c_int` + +error[E0617]: can't pass `i16` to variadic function + --> $DIR/E0617.rs:25:36 + | +25 | printf(::std::ptr::null(), 0i16); + | ^^^^ help: cast the value to `c_int`: `0i16 as c_int` + +error[E0617]: can't pass `u8` to variadic function + --> $DIR/E0617.rs:28:36 + | +28 | printf(::std::ptr::null(), 0u8); + | ^^^ help: cast the value to `c_uint`: `0u8 as c_uint` + +error[E0617]: can't pass `u16` to variadic function + --> $DIR/E0617.rs:31:36 + | +31 | printf(::std::ptr::null(), 0u16); + | ^^^^ help: cast the value to `c_uint`: `0u16 as c_uint` + +error[E0617]: can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function + --> $DIR/E0617.rs:34:36 + | +34 | printf(::std::ptr::null(), printf); + | ^^^^^^ +help: cast the value to `unsafe extern "C" fn(*const i8, ...)` + | +34 | printf(::std::ptr::null(), printf as unsafe extern "C" fn(*const i8, ...)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/error-codes/E0618.rs b/src/test/ui/error-codes/E0618.rs new file mode 100644 index 00000000000..f46bdb99801 --- /dev/null +++ b/src/test/ui/error-codes/E0618.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. + +enum X { + Entry, +} + +fn main() { + X::Entry(); + //~^ ERROR expected function, found enum variant `X::Entry` [E0618] + let x = 0i32; + x(); + //~^ ERROR expected function, found `i32` [E0618] +} diff --git a/src/test/ui/error-codes/E0618.stderr b/src/test/ui/error-codes/E0618.stderr new file mode 100644 index 00000000000..87024376596 --- /dev/null +++ b/src/test/ui/error-codes/E0618.stderr @@ -0,0 +1,23 @@ +error[E0618]: expected function, found enum variant `X::Entry` + --> $DIR/E0618.rs:16:5 + | +12 | Entry, + | ----- `X::Entry` defined here +... +16 | X::Entry(); + | ^^^^^^^^^^ not a function +help: `X::Entry` is a unit variant, you need to write it without the parenthesis + | +16 | X::Entry; + | ^^^^^^^^ + +error[E0618]: expected function, found `i32` + --> $DIR/E0618.rs:19:5 + | +18 | let x = 0i32; + | - `i32` defined here +19 | x(); + | ^^^ not a function + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0619.rs b/src/test/ui/error-codes/E0619.rs new file mode 100644 index 00000000000..a5a5ff7218d --- /dev/null +++ b/src/test/ui/error-codes/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/ui/error-codes/E0619.stderr b/src/test/ui/error-codes/E0619.stderr new file mode 100644 index 00000000000..cec336cfcec --- /dev/null +++ b/src/test/ui/error-codes/E0619.stderr @@ -0,0 +1,8 @@ +error[E0619]: the type of this value must be known in this context + --> $DIR/E0619.rs:15:9 + | +15 | (..) => {} //~ ERROR E0619 + | ^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0620.rs b/src/test/ui/error-codes/E0620.rs new file mode 100644 index 00000000000..5e945dfa5c8 --- /dev/null +++ b/src/test/ui/error-codes/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/ui/error-codes/E0620.stderr b/src/test/ui/error-codes/E0620.stderr new file mode 100644 index 00000000000..564a9472ac9 --- /dev/null +++ b/src/test/ui/error-codes/E0620.stderr @@ -0,0 +1,14 @@ +error[E0620]: cast to unsized type: `&[usize; 2]` as `[usize]` + --> $DIR/E0620.rs:12:16 + | +12 | let _foo = &[1_usize, 2] as [usize]; //~ ERROR E0620 + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using an implicit coercion to `&[usize]` instead + --> $DIR/E0620.rs:12:16 + | +12 | let _foo = &[1_usize, 2] as [usize]; //~ ERROR E0620 + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.rs b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.rs new file mode 100644 index 00000000000..980461bedae --- /dev/null +++ b/src/test/ui/error-codes/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/ui/error-codes/E0621-does-not-trigger-for-closures.stderr b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.stderr new file mode 100644 index 00000000000..c529a838bf7 --- /dev/null +++ b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.stderr @@ -0,0 +1,29 @@ +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements + --> $DIR/E0621-does-not-trigger-for-closures.rs:25:5 + | +25 | invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495 + | ^^^^^^ + | +note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 25:16... + --> $DIR/E0621-does-not-trigger-for-closures.rs:25:16 + | +25 | invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...so that reference does not outlive borrowed content + --> $DIR/E0621-does-not-trigger-for-closures.rs:25:45 + | +25 | invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495 + | ^ +note: but, the lifetime must be valid for the call at 25:5... + --> $DIR/E0621-does-not-trigger-for-closures.rs:25:5 + | +25 | invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...so type `&i32` of expression is valid during the expression + --> $DIR/E0621-does-not-trigger-for-closures.rs:25:5 + | +25 | invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0622.rs b/src/test/ui/error-codes/E0622.rs new file mode 100644 index 00000000000..f2bde5b0364 --- /dev/null +++ b/src/test/ui/error-codes/E0622.rs @@ -0,0 +1,16 @@ +// 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. + +#![feature(intrinsics)] +extern "rust-intrinsic" { + pub static breakpoint : unsafe extern "rust-intrinsic" fn(); + //~^ ERROR intrinsic must be a function [E0622] +} +fn main() { unsafe { breakpoint(); } } diff --git a/src/test/ui/error-codes/E0622.stderr b/src/test/ui/error-codes/E0622.stderr new file mode 100644 index 00000000000..977f44a9c97 --- /dev/null +++ b/src/test/ui/error-codes/E0622.stderr @@ -0,0 +1,8 @@ +error[E0622]: intrinsic must be a function + --> $DIR/E0622.rs:13:5 + | +13 | pub static breakpoint : unsafe extern "rust-intrinsic" fn(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0624.rs b/src/test/ui/error-codes/E0624.rs new file mode 100644 index 00000000000..952e0b31c4c --- /dev/null +++ b/src/test/ui/error-codes/E0624.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 inner { + pub struct Foo; + + impl Foo { + fn method(&self) {} + } +} + +fn main() { + let foo = inner::Foo; + foo.method(); //~ ERROR method `method` is private [E0624] +} diff --git a/src/test/ui/error-codes/E0624.stderr b/src/test/ui/error-codes/E0624.stderr new file mode 100644 index 00000000000..0afb05a8a5e --- /dev/null +++ b/src/test/ui/error-codes/E0624.stderr @@ -0,0 +1,8 @@ +error[E0624]: method `method` is private + --> $DIR/E0624.rs:21:9 + | +21 | foo.method(); //~ ERROR method `method` is private [E0624] + | ^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0637.rs b/src/test/ui/error-codes/E0637.rs new file mode 100644 index 00000000000..455529b088a --- /dev/null +++ b/src/test/ui/error-codes/E0637.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(underscore_lifetimes)] + +struct Foo<'a: '_>(&'a u8); //~ ERROR invalid lifetime bound name: `'_` +fn foo<'a: '_>(_: &'a u8) {} //~ ERROR invalid lifetime bound name: `'_` + +struct Bar<'a>(&'a u8); +impl<'a: '_> Bar<'a> { //~ ERROR invalid lifetime bound name: `'_` + fn bar() {} +} + +fn main() {} diff --git a/src/test/ui/error-codes/E0637.stderr b/src/test/ui/error-codes/E0637.stderr new file mode 100644 index 00000000000..e314afd221e --- /dev/null +++ b/src/test/ui/error-codes/E0637.stderr @@ -0,0 +1,20 @@ +error[E0637]: invalid lifetime bound name: `'_` + --> $DIR/E0637.rs:12:16 + | +12 | struct Foo<'a: '_>(&'a u8); //~ ERROR invalid lifetime bound name: `'_` + | ^^ `'_` is a reserved lifetime name + +error[E0637]: invalid lifetime bound name: `'_` + --> $DIR/E0637.rs:13:12 + | +13 | fn foo<'a: '_>(_: &'a u8) {} //~ ERROR invalid lifetime bound name: `'_` + | ^^ `'_` is a reserved lifetime name + +error[E0637]: invalid lifetime bound name: `'_` + --> $DIR/E0637.rs:16:10 + | +16 | impl<'a: '_> Bar<'a> { //~ ERROR invalid lifetime bound name: `'_` + | ^^ `'_` is a reserved lifetime name + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/error-codes/E0657.rs b/src/test/ui/error-codes/E0657.rs new file mode 100644 index 00000000000..4595e413081 --- /dev/null +++ b/src/test/ui/error-codes/E0657.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. +#![allow(warnings)] +#![feature(conservative_impl_trait, nested_impl_trait)] + +trait Id {} +trait Lt<'a> {} + +impl<'a> Lt<'a> for () {} +impl Id for T {} + +fn free_fn_capture_hrtb_in_impl_trait() + -> impl for<'a> Id> + //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level [E0657] +{ + () +} + +struct Foo; +impl Foo { + fn impl_fn_capture_hrtb_in_impl_trait() + -> impl for<'a> Id> + //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level + { + () + } +} + +fn main() {} diff --git a/src/test/ui/error-codes/E0657.stderr b/src/test/ui/error-codes/E0657.stderr new file mode 100644 index 00000000000..d3b53d37a30 --- /dev/null +++ b/src/test/ui/error-codes/E0657.stderr @@ -0,0 +1,14 @@ +error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level + --> $DIR/E0657.rs:20:32 + | +20 | -> impl for<'a> Id> + | ^^ + +error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level + --> $DIR/E0657.rs:29:36 + | +29 | -> impl for<'a> Id> + | ^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/error-codes/E0658.rs b/src/test/ui/error-codes/E0658.rs new file mode 100644 index 00000000000..d30068eb1fe --- /dev/null +++ b/src/test/ui/error-codes/E0658.rs @@ -0,0 +1,13 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let _ = ::std::u128::MAX; //~ ERROR E0658 +} diff --git a/src/test/ui/error-codes/E0658.stderr b/src/test/ui/error-codes/E0658.stderr new file mode 100644 index 00000000000..c18d8090233 --- /dev/null +++ b/src/test/ui/error-codes/E0658.stderr @@ -0,0 +1,10 @@ +error[E0658]: use of unstable library feature 'i128' (see issue #35118) + --> $DIR/E0658.rs:12:13 + | +12 | let _ = ::std::u128::MAX; //~ ERROR E0658 + | ^^^^^^^^^^^^^^^^ + | + = help: add #![feature(i128)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0659.rs b/src/test/ui/error-codes/E0659.rs new file mode 100644 index 00000000000..4bd452b0aac --- /dev/null +++ b/src/test/ui/error-codes/E0659.rs @@ -0,0 +1,26 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod moon { + pub fn foo() {} +} + +mod earth { + pub fn foo() {} +} + +mod collider { + pub use moon::*; + pub use earth::*; +} + +fn main() { + collider::foo(); //~ ERROR E0659 +} diff --git a/src/test/ui/error-codes/E0659.stderr b/src/test/ui/error-codes/E0659.stderr new file mode 100644 index 00000000000..c2410e2f733 --- /dev/null +++ b/src/test/ui/error-codes/E0659.stderr @@ -0,0 +1,20 @@ +error[E0659]: `foo` is ambiguous + --> $DIR/E0659.rs:25:5 + | +25 | collider::foo(); //~ ERROR E0659 + | ^^^^^^^^^^^^^ + | +note: `foo` could refer to the name imported here + --> $DIR/E0659.rs:20:13 + | +20 | pub use moon::*; + | ^^^^^^^ +note: `foo` could also refer to the name imported here + --> $DIR/E0659.rs:21:13 + | +21 | pub use earth::*; + | ^^^^^^^^ + = note: consider adding an explicit import of `foo` to disambiguate + +error: aborting due to previous error + diff --git a/src/test/ui/feature-gate-macro_at_most_once_rep.rs b/src/test/ui/feature-gate-macro_at_most_once_rep.rs new file mode 100644 index 00000000000..19f5aca5730 --- /dev/null +++ b/src/test/ui/feature-gate-macro_at_most_once_rep.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. + +// Test that `?` macro Kleene operator can not be used when the `macro_at_most_once_rep` feature +// gate is not used. + +macro_rules! m { ($(a)?) => {} } +//~^ ERROR Using the `?` macro Kleene operator for "at most one" repetition is unstable + +fn main() { + m!(); +} diff --git a/src/test/ui/feature-gate-macro_at_most_once_rep.stderr b/src/test/ui/feature-gate-macro_at_most_once_rep.stderr new file mode 100644 index 00000000000..02dbab07bde --- /dev/null +++ b/src/test/ui/feature-gate-macro_at_most_once_rep.stderr @@ -0,0 +1,10 @@ +error[E0658]: Using the `?` macro Kleene operator for "at most one" repetition is unstable (see issue #48075) + --> $DIR/feature-gate-macro_at_most_once_rep.rs:14:20 + | +14 | macro_rules! m { ($(a)?) => {} } + | ^^^ + | + = help: add #![feature(macro_at_most_once_rep)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/ui/feature-gate-match_beginning_vert.rs b/src/test/ui/feature-gate-match_beginning_vert.rs deleted file mode 100644 index 9085563c99d..00000000000 --- a/src/test/ui/feature-gate-match_beginning_vert.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(dead_code)] -enum Foo { - A, - B, - C, - D, - E, -} -use Foo::*; - -fn main() { - let x = Foo::A; - match x { - | A => println!("A"), - //~^ ERROR: Use of a '|' at the beginning of a match arm is experimental (see issue #44101) - | B | C => println!("BC!"), - //~^ ERROR: Use of a '|' at the beginning of a match arm is experimental (see issue #44101) - | _ => {}, - //~^ ERROR: Use of a '|' at the beginning of a match arm is experimental (see issue #44101) - }; - match x { - A | B | C => println!("ABC!"), - _ => {}, - }; -} - diff --git a/src/test/ui/feature-gate-match_beginning_vert.stderr b/src/test/ui/feature-gate-match_beginning_vert.stderr deleted file mode 100644 index 1d45dedb497..00000000000 --- a/src/test/ui/feature-gate-match_beginning_vert.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error[E0658]: Use of a '|' at the beginning of a match arm is experimental (see issue #44101) - --> $DIR/feature-gate-match_beginning_vert.rs:24:9 - | -24 | | A => println!("A"), - | ^ - | - = help: add #![feature(match_beginning_vert)] to the crate attributes to enable - -error[E0658]: Use of a '|' at the beginning of a match arm is experimental (see issue #44101) - --> $DIR/feature-gate-match_beginning_vert.rs:26:9 - | -26 | | B | C => println!("BC!"), - | ^ - | - = help: add #![feature(match_beginning_vert)] to the crate attributes to enable - -error[E0658]: Use of a '|' at the beginning of a match arm is experimental (see issue #44101) - --> $DIR/feature-gate-match_beginning_vert.rs:28:9 - | -28 | | _ => {}, - | ^ - | - = help: add #![feature(match_beginning_vert)] to the crate attributes to enable - -error: aborting due to 3 previous errors - diff --git a/src/test/ui/feature-gate-use_nested_groups.rs b/src/test/ui/feature-gate-use_nested_groups.rs deleted file mode 100644 index 56413a999d7..00000000000 --- a/src/test/ui/feature-gate-use_nested_groups.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![allow(unused_imports, dead_code)] - -mod a { - pub enum B {} - pub enum C {} - - pub mod d { - pub enum E {} - pub enum F {} - - pub mod g { - pub enum H {} - } - } -} - -use a::{B, d::{*, g::H}}; //~ ERROR glob imports in `use` groups are experimental - //~^ ERROR nested groups in `use` are experimental - //~^^ ERROR paths in `use` groups are experimental - -fn main() {} diff --git a/src/test/ui/feature-gate-use_nested_groups.stderr b/src/test/ui/feature-gate-use_nested_groups.stderr deleted file mode 100644 index 6ae691c384b..00000000000 --- a/src/test/ui/feature-gate-use_nested_groups.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error[E0658]: nested groups in `use` are experimental (see issue #44494) - --> $DIR/feature-gate-use_nested_groups.rs:27:12 - | -27 | use a::{B, d::{*, g::H}}; //~ ERROR glob imports in `use` groups are experimental - | ^^^^^^^^^^^^ - | - = help: add #![feature(use_nested_groups)] to the crate attributes to enable - -error[E0658]: glob imports in `use` groups are experimental (see issue #44494) - --> $DIR/feature-gate-use_nested_groups.rs:27:16 - | -27 | use a::{B, d::{*, g::H}}; //~ ERROR glob imports in `use` groups are experimental - | ^ - | - = help: add #![feature(use_nested_groups)] to the crate attributes to enable - -error[E0658]: paths in `use` groups are experimental (see issue #44494) - --> $DIR/feature-gate-use_nested_groups.rs:27:19 - | -27 | use a::{B, d::{*, g::H}}; //~ ERROR glob imports in `use` groups are experimental - | ^^^^ - | - = help: add #![feature(use_nested_groups)] to the crate attributes to enable - -error: aborting due to 3 previous errors - diff --git a/src/test/ui/generator/generator-with-nll.stderr b/src/test/ui/generator/generator-with-nll.stderr index 0a52a928f69..0f7d2e540d8 100644 --- a/src/test/ui/generator/generator-with-nll.stderr +++ b/src/test/ui/generator/generator-with-nll.stderr @@ -1,12 +1,3 @@ -error[E0626]: borrow may still be in use when generator yields (Mir) - --> $DIR/generator-with-nll.rs:20:17 - | -20 | let b = &mut true; //~ ERROR borrow may still be in use when generator yields (Ast) - | ^^^^^^^^^ -21 | //~^ borrow may still be in use when generator yields (Mir) -22 | yield (); - | -------- possible yield occurs here - error[E0626]: borrow may still be in use when generator yields (Ast) --> $DIR/generator-with-nll.rs:19:23 | @@ -25,5 +16,14 @@ error[E0626]: borrow may still be in use when generator yields (Ast) 22 | yield (); | -------- possible yield occurs here +error[E0626]: borrow may still be in use when generator yields (Mir) + --> $DIR/generator-with-nll.rs:20:17 + | +20 | let b = &mut true; //~ ERROR borrow may still be in use when generator yields (Ast) + | ^^^^^^^^^ +21 | //~^ borrow may still be in use when generator yields (Mir) +22 | yield (); + | -------- possible yield occurs here + error: aborting due to 3 previous errors diff --git a/src/test/ui/generator/issue-48048.rs b/src/test/ui/generator/issue-48048.rs new file mode 100644 index 00000000000..89739bd591c --- /dev/null +++ b/src/test/ui/generator/issue-48048.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(generators)] + +fn main() { + let x = (|_| {},); + + || { + let x = x; + + x.0({ //~ ERROR borrow may still be in use when generator yields + yield; + }); + }; +} diff --git a/src/test/ui/generator/issue-48048.stderr b/src/test/ui/generator/issue-48048.stderr new file mode 100644 index 00000000000..fd1667128ab --- /dev/null +++ b/src/test/ui/generator/issue-48048.stderr @@ -0,0 +1,10 @@ +error[E0626]: borrow may still be in use when generator yields + --> $DIR/issue-48048.rs:19:9 + | +19 | x.0({ //~ ERROR borrow may still be in use when generator yields + | ^^^ +20 | yield; + | ----- possible yield occurs here + +error: aborting due to previous error + diff --git a/src/test/ui/generator/pattern-borrow.rs b/src/test/ui/generator/pattern-borrow.rs new file mode 100644 index 00000000000..557a5e62f7e --- /dev/null +++ b/src/test/ui/generator/pattern-borrow.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(generators)] + +enum Test { A(i32), B, } + +fn main() { } + +fn fun(test: Test) { + move || { + if let Test::A(ref _a) = test { //~ ERROR borrow may still be in use when generator yields + yield (); + } + }; +} diff --git a/src/test/ui/generator/pattern-borrow.stderr b/src/test/ui/generator/pattern-borrow.stderr new file mode 100644 index 00000000000..6b39b272d0e --- /dev/null +++ b/src/test/ui/generator/pattern-borrow.stderr @@ -0,0 +1,10 @@ +error[E0626]: borrow may still be in use when generator yields + --> $DIR/pattern-borrow.rs:19:24 + | +19 | if let Test::A(ref _a) = test { //~ ERROR borrow may still be in use when generator yields + | ^^^^^^ +20 | yield (); + | -------- possible yield occurs here + +error: aborting due to previous error + diff --git a/src/test/ui/generator/sized-yield.rs b/src/test/ui/generator/sized-yield.rs new file mode 100644 index 00000000000..f38ebf8b946 --- /dev/null +++ b/src/test/ui/generator/sized-yield.rs @@ -0,0 +1,21 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(generators, generator_trait)] + +use std::ops::Generator; + +fn main() { + let s = String::from("foo"); + let mut gen = move || { //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied + yield s[..]; + }; + gen.resume(); //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied +} diff --git a/src/test/ui/generator/sized-yield.stderr b/src/test/ui/generator/sized-yield.stderr new file mode 100644 index 00000000000..7adb2cc5598 --- /dev/null +++ b/src/test/ui/generator/sized-yield.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied + --> $DIR/sized-yield.rs:17:26 + | +17 | let mut gen = move || { //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied + | __________________________^ +18 | | yield s[..]; +19 | | }; + | |____^ `str` does not have a constant size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `str` + = note: the yield type of a generator must have a statically known size + +error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied + --> $DIR/sized-yield.rs:20:8 + | +20 | gen.resume(); //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied + | ^^^^^^ `str` does not have a constant size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `str` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/generator/yield-while-local-borrowed.stderr b/src/test/ui/generator/yield-while-local-borrowed.stderr index 7961dd97441..114fe8ffcab 100644 --- a/src/test/ui/generator/yield-while-local-borrowed.stderr +++ b/src/test/ui/generator/yield-while-local-borrowed.stderr @@ -1,12 +1,3 @@ -error[E0626]: borrow may still be in use when generator yields (Mir) - --> $DIR/yield-while-local-borrowed.rs:24:17 - | -24 | let a = &mut 3; - | ^^^^^^ -... -27 | yield(); - | ------- possible yield occurs here - error[E0626]: borrow may still be in use when generator yields (Ast) --> $DIR/yield-while-local-borrowed.rs:24:22 | @@ -25,6 +16,15 @@ error[E0626]: borrow may still be in use when generator yields (Ast) 55 | yield(); | ------- possible yield occurs here +error[E0626]: borrow may still be in use when generator yields (Mir) + --> $DIR/yield-while-local-borrowed.rs:24:17 + | +24 | let a = &mut 3; + | ^^^^^^ +... +27 | yield(); + | ------- possible yield occurs here + error[E0626]: borrow may still be in use when generator yields (Mir) --> $DIR/yield-while-local-borrowed.rs:52:21 | diff --git a/src/test/ui/impl-trait/equality.rs b/src/test/ui/impl-trait/equality.rs index 36df4f0eb4d..9d9d4cef311 100644 --- a/src/test/ui/impl-trait/equality.rs +++ b/src/test/ui/impl-trait/equality.rs @@ -32,7 +32,7 @@ fn sum_to(n: u32) -> impl Foo { 0 } else { n + sum_to(n - 1) - //~^ ERROR the trait bound `u32: std::ops::Add` is not satisfied + //~^ ERROR cannot add `impl Foo` to `u32` } } diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index 3fc08a0900f..8ec81903803 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -7,7 +7,7 @@ error[E0308]: mismatched types = note: expected type `i32` found type `u32` -error[E0277]: the trait bound `u32: std::ops::Add` is not satisfied +error[E0277]: cannot add `impl Foo` to `u32` --> $DIR/equality.rs:34:11 | 34 | n + sum_to(n - 1) diff --git a/src/test/ui/impl-trait/impl-trait-plus-priority.rs b/src/test/ui/impl-trait/impl-trait-plus-priority.rs new file mode 100644 index 00000000000..f451123ca27 --- /dev/null +++ b/src/test/ui/impl-trait/impl-trait-plus-priority.rs @@ -0,0 +1,59 @@ +// 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 parse-only -Z continue-parse-after-error + +fn f() -> impl A + {} // OK +fn f() -> impl A + B {} // OK +fn f() -> dyn A + B {} // OK +fn f() -> A + B {} // OK + +impl S { + fn f(self) -> impl A + { // OK + let _ = |a, b| -> impl A + {}; // OK + } + fn f(self) -> impl A + B { // OK + let _ = |a, b| -> impl A + B {}; // OK + } + fn f(self) -> dyn A + B { // OK + let _ = |a, b| -> dyn A + B {}; // OK + } + fn f(self) -> A + B { // OK + let _ = |a, b| -> A + B {}; // OK + } +} + +type A = fn() -> impl A +; +//~^ ERROR ambiguous `+` in a type +type A = fn() -> impl A + B; +//~^ ERROR ambiguous `+` in a type +type A = fn() -> dyn A + B; +//~^ ERROR ambiguous `+` in a type +type A = fn() -> A + B; +//~^ ERROR expected a path on the left-hand side of `+`, not `fn() -> A` + +type A = Fn() -> impl A +; +//~^ ERROR ambiguous `+` in a type +type A = Fn() -> impl A + B; +//~^ ERROR ambiguous `+` in a type +type A = Fn() -> dyn A + B; +//~^ ERROR ambiguous `+` in a type +type A = Fn() -> A + B; // OK, interpreted as `(Fn() -> A) + B` for compatibility + +type A = &impl A +; +//~^ ERROR ambiguous `+` in a type +type A = &impl A + B; +//~^ ERROR ambiguous `+` in a type +type A = &dyn A + B; +//~^ ERROR ambiguous `+` in a type +type A = &A + B; +//~^ ERROR expected a path on the left-hand side of `+`, not `&A` + +fn main() {} diff --git a/src/test/ui/impl-trait/impl-trait-plus-priority.stderr b/src/test/ui/impl-trait/impl-trait-plus-priority.stderr new file mode 100644 index 00000000000..885c3941971 --- /dev/null +++ b/src/test/ui/impl-trait/impl-trait-plus-priority.stderr @@ -0,0 +1,68 @@ +error: ambiguous `+` in a type + --> $DIR/impl-trait-plus-priority.rs:33:18 + | +33 | type A = fn() -> impl A +; + | ^^^^^^^^ help: use parentheses to disambiguate: `(impl A)` + +error: ambiguous `+` in a type + --> $DIR/impl-trait-plus-priority.rs:35:18 + | +35 | type A = fn() -> impl A + B; + | ^^^^^^^^^^ help: use parentheses to disambiguate: `(impl A + B)` + +error: ambiguous `+` in a type + --> $DIR/impl-trait-plus-priority.rs:37:18 + | +37 | type A = fn() -> dyn A + B; + | ^^^^^^^^^ help: use parentheses to disambiguate: `(dyn A + B)` + +error[E0178]: expected a path on the left-hand side of `+`, not `fn() -> A` + --> $DIR/impl-trait-plus-priority.rs:39:10 + | +39 | type A = fn() -> A + B; + | ^^^^^^^^^^^^^ perhaps you forgot parentheses? + +error: ambiguous `+` in a type + --> $DIR/impl-trait-plus-priority.rs:42:18 + | +42 | type A = Fn() -> impl A +; + | ^^^^^^^^ help: use parentheses to disambiguate: `(impl A)` + +error: ambiguous `+` in a type + --> $DIR/impl-trait-plus-priority.rs:44:18 + | +44 | type A = Fn() -> impl A + B; + | ^^^^^^^^^^ help: use parentheses to disambiguate: `(impl A + B)` + +error: ambiguous `+` in a type + --> $DIR/impl-trait-plus-priority.rs:46:18 + | +46 | type A = Fn() -> dyn A + B; + | ^^^^^^^^^ help: use parentheses to disambiguate: `(dyn A + B)` + +error: ambiguous `+` in a type + --> $DIR/impl-trait-plus-priority.rs:50:11 + | +50 | type A = &impl A +; + | ^^^^^^^^ help: use parentheses to disambiguate: `(impl A)` + +error: ambiguous `+` in a type + --> $DIR/impl-trait-plus-priority.rs:52:11 + | +52 | type A = &impl A + B; + | ^^^^^^^^^^ help: use parentheses to disambiguate: `(impl A + B)` + +error: ambiguous `+` in a type + --> $DIR/impl-trait-plus-priority.rs:54:11 + | +54 | type A = &dyn A + B; + | ^^^^^^^^^ help: use parentheses to disambiguate: `(dyn A + B)` + +error[E0178]: expected a path on the left-hand side of `+`, not `&A` + --> $DIR/impl-trait-plus-priority.rs:56:10 + | +56 | type A = &A + B; + | ^^^^^^ help: try adding parentheses: `&(A + B)` + +error: aborting due to 11 previous errors + diff --git a/src/test/ui/impl-trait/trait_type.stderr b/src/test/ui/impl-trait/trait_type.stderr index 7a0d01a8ec2..1417c71ca12 100644 --- a/src/test/ui/impl-trait/trait_type.stderr +++ b/src/test/ui/impl-trait/trait_type.stderr @@ -2,7 +2,7 @@ error[E0053]: method `fmt` has an incompatible type for trait --> $DIR/trait_type.rs:17:4 | 17 | fn fmt(&self, x: &str) -> () { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability | = note: expected type `fn(&MyType, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>` found type `fn(&MyType, &str)` @@ -19,7 +19,7 @@ error[E0186]: method `fmt` has a `&self` declaration in the trait, but not in th --> $DIR/trait_type.rs:27:4 | 27 | fn fmt() -> () { } - | ^^^^^^^^^^^^^^^^^^ expected `&self` in impl + | ^^^^^^^^^^^^^^ expected `&self` in impl | = note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>` diff --git a/src/test/ui/imports/duplicate.stderr b/src/test/ui/imports/duplicate.stderr index a74401314a1..6e5b91a11c9 100644 --- a/src/test/ui/imports/duplicate.stderr +++ b/src/test/ui/imports/duplicate.stderr @@ -9,8 +9,8 @@ error[E0252]: the name `foo` is defined multiple times = note: `foo` must be defined only once in the value namespace of this module help: You can use `as` to change the binding name of the import | -25 | use a::foo as Otherfoo; //~ ERROR the name `foo` is defined multiple times - | ^^^^^^^^^^^^^^^^^^ +25 | use a::foo as other_foo; //~ ERROR the name `foo` is defined multiple times + | ^^^^^^^^^^^^^^^^^^^ error[E0659]: `foo` is ambiguous --> $DIR/duplicate.rs:56:9 diff --git a/src/test/ui/in-band-lifetimes/ellided-lifetimes.rs b/src/test/ui/in-band-lifetimes/ellided-lifetimes.rs new file mode 100644 index 00000000000..5151abd6823 --- /dev/null +++ b/src/test/ui/in-band-lifetimes/ellided-lifetimes.rs @@ -0,0 +1,19 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +#![allow(warnings)] +#![allow(unused_variables, dead_code, unused, bad_style)] +#![deny(elided_lifetime_in_path)] + +struct Foo<'a> { x: &'a u32 } +fn foo(x: &Foo) { + //~^ ERROR: hidden lifetime parameters are deprecated, try `Foo<'_>` +} + +fn main() {} diff --git a/src/test/ui/in-band-lifetimes/ellided-lifetimes.stderr b/src/test/ui/in-band-lifetimes/ellided-lifetimes.stderr new file mode 100644 index 00000000000..613a7be6ed2 --- /dev/null +++ b/src/test/ui/in-band-lifetimes/ellided-lifetimes.stderr @@ -0,0 +1,14 @@ +error: hidden lifetime parameters are deprecated, try `Foo<'_>` + --> $DIR/ellided-lifetimes.rs:15:12 + | +15 | fn foo(x: &Foo) { + | ^^^ + | +note: lint level defined here + --> $DIR/ellided-lifetimes.rs:12:9 + | +12 | #![deny(elided_lifetime_in_path)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs new file mode 100644 index 00000000000..f845762cefd --- /dev/null +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs @@ -0,0 +1,22 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::ops::Deref; +trait Trait {} + +struct Struct; + +impl Deref for Struct { + type Target = Trait; + fn deref(&self) -> &Trait { + unimplemented!(); + } +} +//~^^^^ ERROR cannot infer an appropriate lifetime for lifetime parameter diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr new file mode 100644 index 00000000000..7aab31eb909 --- /dev/null +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr @@ -0,0 +1,22 @@ +error[E0601]: main function not found + +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements + --> $DIR/mismatched_trait_impl-2.rs:18:5 + | +18 | fn deref(&self) -> &Trait { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 18:5... + --> $DIR/mismatched_trait_impl-2.rs:18:5 + | +18 | / fn deref(&self) -> &Trait { +19 | | unimplemented!(); +20 | | } + | |_____^ + = note: ...but the lifetime must also be valid for the static lifetime... + = note: ...so that the method type is compatible with trait: + expected fn(&Struct) -> &Trait + 'static + found fn(&Struct) -> &Trait + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr index e96f7181a6d..fd6be01da9f 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr @@ -1,10 +1,8 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements --> $DIR/mismatched_trait_impl.rs:19:5 | -19 | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer -20 | | x -21 | | } - | |_____^ +19 | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 19:5... --> $DIR/mismatched_trait_impl.rs:19:5 @@ -13,27 +11,14 @@ note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on th 20 | | x 21 | | } | |_____^ -note: ...so that method type is compatible with trait (expected fn(&i32, &'a u32, &u32) -> &'a u32, found fn(&i32, &u32, &u32) -> &u32) - --> $DIR/mismatched_trait_impl.rs:19:5 - | -19 | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer -20 | | x -21 | | } - | |_____^ -note: but, the lifetime must be valid for the lifetime 'a as defined on the method body at 19:5... +note: ...but the lifetime must also be valid for the lifetime 'a as defined on the method body at 19:5... --> $DIR/mismatched_trait_impl.rs:19:5 | -19 | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer -20 | | x -21 | | } - | |_____^ -note: ...so that method type is compatible with trait (expected fn(&i32, &'a u32, &u32) -> &'a u32, found fn(&i32, &u32, &u32) -> &u32) - --> $DIR/mismatched_trait_impl.rs:19:5 - | -19 | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer -20 | | x -21 | | } - | |_____^ +19 | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...so that the method type is compatible with trait: + expected fn(&i32, &'a u32, &u32) -> &'a u32 + found fn(&i32, &u32, &u32) -> &u32 error: aborting due to previous error diff --git a/src/test/ui/issue-26093.rs b/src/test/ui/issue-26093.rs index 3489a2ca9be..22751c4a37c 100644 --- a/src/test/ui/issue-26093.rs +++ b/src/test/ui/issue-26093.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -macro_rules! not_an_lvalue { +macro_rules! not_a_place { ($thing:expr) => { $thing = 42; //~^ ERROR invalid left-hand side expression @@ -16,5 +16,5 @@ macro_rules! not_an_lvalue { } fn main() { - not_an_lvalue!(99); + not_a_place!(99); } diff --git a/src/test/ui/issue-26093.stderr b/src/test/ui/issue-26093.stderr index c2b81b2ce43..b850852623f 100644 --- a/src/test/ui/issue-26093.stderr +++ b/src/test/ui/issue-26093.stderr @@ -4,8 +4,8 @@ error[E0070]: invalid left-hand side expression 13 | $thing = 42; | ^^^^^^^^^^^ left-hand of expression not valid ... -19 | not_an_lvalue!(99); - | ------------------- in this macro invocation +19 | not_a_place!(99); + | ----------------- in this macro invocation error: aborting due to previous error diff --git a/src/test/ui/issue-26886.stderr b/src/test/ui/issue-26886.stderr index cb2eca87068..e6424e535ee 100644 --- a/src/test/ui/issue-26886.stderr +++ b/src/test/ui/issue-26886.stderr @@ -24,8 +24,8 @@ error[E0252]: the name `sync` is defined multiple times = note: `sync` must be defined only once in the type namespace of this module help: You can use `as` to change the binding name of the import | -14 | use std::sync as Othersync; //~ ERROR the name `sync` is defined multiple times - | ^^^^^^^^^^^^^^^^^^^^^^ +14 | use std::sync as other_sync; //~ ERROR the name `sync` is defined multiple times + | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issue-27942.stderr b/src/test/ui/issue-27942.stderr index b580b8e7313..b24544743d8 100644 --- a/src/test/ui/issue-27942.stderr +++ b/src/test/ui/issue-27942.stderr @@ -14,14 +14,8 @@ note: the anonymous lifetime #1 defined on the method body at 15:5... note: ...does not necessarily outlive the lifetime 'a as defined on the trait at 13:1 --> $DIR/issue-27942.rs:13:1 | -13 | / pub trait Buffer<'a, R: Resources<'a>> { -14 | | -15 | | fn select(&self) -> BufferViewHandle; -16 | | //~^ ERROR mismatched types -... | -19 | | //~| lifetime mismatch -20 | | } - | |_^ +13 | pub trait Buffer<'a, R: Resources<'a>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/issue-27942.rs:15:5 @@ -34,14 +28,8 @@ error[E0308]: mismatched types note: the lifetime 'a as defined on the trait at 13:1... --> $DIR/issue-27942.rs:13:1 | -13 | / pub trait Buffer<'a, R: Resources<'a>> { -14 | | -15 | | fn select(&self) -> BufferViewHandle; -16 | | //~^ ERROR mismatched types -... | -19 | | //~| lifetime mismatch -20 | | } - | |_^ +13 | pub trait Buffer<'a, R: Resources<'a>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...does not necessarily outlive the anonymous lifetime #1 defined on the method body at 15:5 --> $DIR/issue-27942.rs:15:5 | diff --git a/src/test/ui/issue-37884.stderr b/src/test/ui/issue-37884.stderr index 439b123975f..c4ad232ae7e 100644 --- a/src/test/ui/issue-37884.stderr +++ b/src/test/ui/issue-37884.stderr @@ -24,14 +24,8 @@ note: the anonymous lifetime #1 defined on the method body at 16:5... note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 13:1 --> $DIR/issue-37884.rs:13:1 | -13 | / impl<'a, T: 'a> Iterator for RepeatMut<'a, T> { -14 | | -15 | | type Item = &'a mut T; -16 | | fn next(&'a mut self) -> Option -... | -21 | | } -22 | | } - | |_^ +13 | impl<'a, T: 'a> Iterator for RepeatMut<'a, T> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issue-45697-1.rs b/src/test/ui/issue-45697-1.rs new file mode 100644 index 00000000000..7734b14b2ab --- /dev/null +++ b/src/test/ui/issue-45697-1.rs @@ -0,0 +1,35 @@ +// 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. + +// Test that assignments to an `&mut` pointer which is found in a +// borrowed (but otherwise non-aliasable) location is illegal. + +// compile-flags: -Z emit-end-regions -Z borrowck=compare -C overflow-checks=on + +struct S<'a> { + pointer: &'a mut isize +} + +fn copy_borrowed_ptr<'a>(p: &'a mut S<'a>) -> S<'a> { + S { pointer: &mut *p.pointer } +} + +fn main() { + let mut x = 1; + + { + let mut y = S { pointer: &mut x }; + let z = copy_borrowed_ptr(&mut y); + *y.pointer += 1; + //~^ ERROR cannot assign to `*y.pointer` because it is borrowed (Ast) [E0506] + //~| ERROR cannot use `*y.pointer` because it was mutably borrowed (Mir) [E0503] + *z.pointer += 1; + } +} diff --git a/src/test/ui/issue-45697-1.stderr b/src/test/ui/issue-45697-1.stderr new file mode 100644 index 00000000000..09f32b93acc --- /dev/null +++ b/src/test/ui/issue-45697-1.stderr @@ -0,0 +1,18 @@ +error[E0506]: cannot assign to `*y.pointer` because it is borrowed (Ast) + --> $DIR/issue-45697-1.rs:30:9 + | +29 | let z = copy_borrowed_ptr(&mut y); + | - borrow of `*y.pointer` occurs here +30 | *y.pointer += 1; + | ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here + +error[E0503]: cannot use `*y.pointer` because it was mutably borrowed (Mir) + --> $DIR/issue-45697-1.rs:30:9 + | +29 | let z = copy_borrowed_ptr(&mut y); + | ------ borrow of `y` occurs here +30 | *y.pointer += 1; + | ^^^^^^^^^^^^^^^ use of borrowed `y` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/issue-45697.rs b/src/test/ui/issue-45697.rs new file mode 100644 index 00000000000..4e93eccd6f6 --- /dev/null +++ b/src/test/ui/issue-45697.rs @@ -0,0 +1,35 @@ +// 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. + +// Test that assignments to an `&mut` pointer which is found in a +// borrowed (but otherwise non-aliasable) location is illegal. + +// compile-flags: -Z emit-end-regions -Z borrowck=compare -C overflow-checks=off + +struct S<'a> { + pointer: &'a mut isize +} + +fn copy_borrowed_ptr<'a>(p: &'a mut S<'a>) -> S<'a> { + S { pointer: &mut *p.pointer } +} + +fn main() { + let mut x = 1; + + { + let mut y = S { pointer: &mut x }; + let z = copy_borrowed_ptr(&mut y); + *y.pointer += 1; + //~^ ERROR cannot assign to `*y.pointer` because it is borrowed (Ast) [E0506] + //~| ERROR cannot use `*y.pointer` because it was mutably borrowed (Mir) [E0503] + *z.pointer += 1; + } +} diff --git a/src/test/ui/issue-45697.stderr b/src/test/ui/issue-45697.stderr new file mode 100644 index 00000000000..e9b723d57b5 --- /dev/null +++ b/src/test/ui/issue-45697.stderr @@ -0,0 +1,18 @@ +error[E0506]: cannot assign to `*y.pointer` because it is borrowed (Ast) + --> $DIR/issue-45697.rs:30:9 + | +29 | let z = copy_borrowed_ptr(&mut y); + | - borrow of `*y.pointer` occurs here +30 | *y.pointer += 1; + | ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here + +error[E0503]: cannot use `*y.pointer` because it was mutably borrowed (Mir) + --> $DIR/issue-45697.rs:30:9 + | +29 | let z = copy_borrowed_ptr(&mut y); + | ------ borrow of `y` occurs here +30 | *y.pointer += 1; + | ^^^^^^^^^^^^^^^ use of borrowed `y` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/issue-46472.stderr b/src/test/ui/issue-46472.stderr index 2f332a7a558..7b5cce218e9 100644 --- a/src/test/ui/issue-46472.stderr +++ b/src/test/ui/issue-46472.stderr @@ -10,12 +10,8 @@ error[E0597]: borrowed value does not live long enough (Ast) note: borrowed value must be valid for the lifetime 'a as defined on the function body at 13:1... --> $DIR/issue-46472.rs:13:1 | -13 | / fn bar<'a>() -> &'a mut u32 { -14 | | &mut 4 -15 | | //~^ ERROR borrowed value does not live long enough (Ast) [E0597] -16 | | //~| ERROR borrowed value does not live long enough (Mir) [E0597] -17 | | } - | |_^ +13 | fn bar<'a>() -> &'a mut u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0597]: borrowed value does not live long enough (Mir) --> $DIR/issue-46472.rs:14:10 @@ -29,12 +25,8 @@ error[E0597]: borrowed value does not live long enough (Mir) note: borrowed value must be valid for the lifetime 'a as defined on the function body at 13:1... --> $DIR/issue-46472.rs:13:1 | -13 | / fn bar<'a>() -> &'a mut u32 { -14 | | &mut 4 -15 | | //~^ ERROR borrowed value does not live long enough (Ast) [E0597] -16 | | //~| ERROR borrowed value does not live long enough (Mir) [E0597] -17 | | } - | |_^ +13 | fn bar<'a>() -> &'a mut u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issue-47706-trait.rs b/src/test/ui/issue-47706-trait.rs new file mode 100644 index 00000000000..86a9da49a05 --- /dev/null +++ b/src/test/ui/issue-47706-trait.rs @@ -0,0 +1,16 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait T { + fn f(&self, _: ()) { + None::<()>.map(Self::f); + } + //~^^ ERROR function is expected to take a single 0-tuple as argument +} diff --git a/src/test/ui/issue-47706-trait.stderr b/src/test/ui/issue-47706-trait.stderr new file mode 100644 index 00000000000..320e98dee4a --- /dev/null +++ b/src/test/ui/issue-47706-trait.stderr @@ -0,0 +1,12 @@ +error[E0601]: main function not found + +error[E0593]: function is expected to take a single 0-tuple as argument, but it takes 2 distinct arguments + --> $DIR/issue-47706-trait.rs:13:20 + | +12 | fn f(&self, _: ()) { + | ------------------ takes 2 distinct arguments +13 | None::<()>.map(Self::f); + | ^^^ expected function that takes a single 0-tuple as argument + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs new file mode 100644 index 00000000000..a68b4f76352 --- /dev/null +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs @@ -0,0 +1,34 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// must-compile-successfully + +#![warn(unused)] // UI tests pass `-A unused` (#43896) + +struct SoulHistory { + corridors_of_light: usize, + hours_are_suns: bool, + endless_and_singing: bool +} + +fn main() { + let i_think_continually = 2; + let who_from_the_womb_remembered = SoulHistory { + corridors_of_light: 5, + hours_are_suns: true, + endless_and_singing: true + }; + + if let SoulHistory { corridors_of_light, + mut hours_are_suns, + endless_and_singing: true } = who_from_the_womb_remembered { + hours_are_suns = false; + } +} diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr new file mode 100644 index 00000000000..694fe69e016 --- /dev/null +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr @@ -0,0 +1,40 @@ +warning: unused variable: `i_think_continually` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:22:9 + | +22 | let i_think_continually = 2; + | ^^^^^^^^^^^^^^^^^^^ help: consider using `_i_think_continually` instead + | +note: lint level defined here + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:13:9 + | +13 | #![warn(unused)] // UI tests pass `-A unused` (#43896) + | ^^^^^^ + = note: #[warn(unused_variables)] implied by #[warn(unused)] + +warning: unused variable: `corridors_of_light` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:29:26 + | +29 | if let SoulHistory { corridors_of_light, + | ^^^^^^^^^^^^^^^^^^ help: try ignoring the field: `corridors_of_light: _` + +warning: variable `hours_are_suns` is assigned to, but never used + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:30:26 + | +30 | mut hours_are_suns, + | ^^^^^^^^^^^^^^^^^^ + | + = note: consider using `_hours_are_suns` instead + +warning: value assigned to `hours_are_suns` is never read + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:32:9 + | +32 | hours_are_suns = false; + | ^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:13:9 + | +13 | #![warn(unused)] // UI tests pass `-A unused` (#43896) + | ^^^^^^ + = note: #[warn(unused_assignments)] implied by #[warn(unused)] + diff --git a/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs b/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs new file mode 100644 index 00000000000..b4e6c5074e3 --- /dev/null +++ b/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs @@ -0,0 +1,40 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// must-compile-successfully + +#![warn(unused_parens)] + +macro_rules! the_worship_the_heart_lifts_above { + ( @as_expr, $e:expr) => { $e }; + ( @generate_fn, $name:tt) => { + #[allow(dead_code)] fn the_moth_for_the_star<'a>() -> Option<&'a str> { + Some(the_worship_the_heart_lifts_above!( @as_expr, $name )) + } + }; + ( $name:ident ) => { the_worship_the_heart_lifts_above!( @generate_fn, (stringify!($name))); } + // ↑ Notably, this does 𝘯𝘰𝘵 warn: we're declining to lint unused parens in + // function/method arguments inside of nested macros because of situations + // like those reported in Issue #47775 +} + +macro_rules! and_the_heavens_reject_not { + () => { + // ↓ But let's test that we still lint for unused parens around + // function args inside of simple, one-deep macros. + #[allow(dead_code)] fn the_night_for_the_morrow() -> Option { Some((2)) } + //~^ WARN unnecessary parentheses around function argument + } +} + +the_worship_the_heart_lifts_above!(rah); +and_the_heavens_reject_not!(); + +fn main() {} diff --git a/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.stderr b/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.stderr new file mode 100644 index 00000000000..097ec1b1c80 --- /dev/null +++ b/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.stderr @@ -0,0 +1,15 @@ +warning: unnecessary parentheses around function argument + --> $DIR/issue-47775-nested-macro-unnecessary-parens-arg.rs:32:83 + | +32 | #[allow(dead_code)] fn the_night_for_the_morrow() -> Option { Some((2)) } + | ^^^ help: remove these parentheses +... +38 | and_the_heavens_reject_not!(); + | ------------------------------ in this macro invocation + | +note: lint level defined here + --> $DIR/issue-47775-nested-macro-unnecessary-parens-arg.rs:13:9 + | +13 | #![warn(unused_parens)] + | ^^^^^^^^^^^^^ + diff --git a/src/test/ui/lint/suggestions.rs b/src/test/ui/lint/suggestions.rs index dfcaede1402..e35675eacd8 100644 --- a/src/test/ui/lint/suggestions.rs +++ b/src/test/ui/lint/suggestions.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-tab + #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896 #![feature(no_debug)] @@ -46,11 +48,15 @@ fn main() { let mut a = (1); // should suggest no `mut`, no parens //~^ WARN does not need to be mutable //~| WARN unnecessary parentheses + // the line after `mut` has a `\t` at the beginning, this is on purpose + let mut + b = 1; + //~^^ WARN does not need to be mutable let d = Equinox { warp_factor: 9.975 }; match d { Equinox { warp_factor: warp_factor } => {} // should suggest shorthand //~^ WARN this pattern is redundant } - println!("{}", a); + println!("{} {}", a, b); } } diff --git a/src/test/ui/lint/suggestions.stderr b/src/test/ui/lint/suggestions.stderr index 8b30f552d37..90d6bd312e4 100644 --- a/src/test/ui/lint/suggestions.stderr +++ b/src/test/ui/lint/suggestions.stderr @@ -1,41 +1,53 @@ warning: unnecessary parentheses around assigned value - --> $DIR/suggestions.rs:46:21 + --> $DIR/suggestions.rs:48:21 | -46 | let mut a = (1); // should suggest no `mut`, no parens +48 | let mut a = (1); // should suggest no `mut`, no parens | ^^^ help: remove these parentheses | note: lint level defined here - --> $DIR/suggestions.rs:11:21 + --> $DIR/suggestions.rs:13:21 | -11 | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896 +13 | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896 | ^^^^^^^^^^^^^ warning: use of deprecated attribute `no_debug`: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand. See https://github.com/rust-lang/rust/issues/29721 - --> $DIR/suggestions.rs:41:1 + --> $DIR/suggestions.rs:43:1 | -41 | #[no_debug] // should suggest removal of deprecated attribute +43 | #[no_debug] // should suggest removal of deprecated attribute | ^^^^^^^^^^^ help: remove this attribute | = note: #[warn(deprecated)] on by default warning: variable does not need to be mutable - --> $DIR/suggestions.rs:46:13 + --> $DIR/suggestions.rs:48:13 | -46 | let mut a = (1); // should suggest no `mut`, no parens - | ---^^ +48 | let mut a = (1); // should suggest no `mut`, no parens + | ----^ | | | help: remove this `mut` | note: lint level defined here - --> $DIR/suggestions.rs:11:9 + --> $DIR/suggestions.rs:13:9 | -11 | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896 +13 | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896 | ^^^^^^^^^^ +warning: variable does not need to be mutable + --> $DIR/suggestions.rs:52:13 + | +52 | let mut + | _____________^ + | |_____________| + | || +53 | || b = 1; + | ||____________-^ + | |____________| + | help: remove this `mut` + warning: static is marked #[no_mangle], but not exported - --> $DIR/suggestions.rs:14:14 + --> $DIR/suggestions.rs:16:14 | -14 | #[no_mangle] static SHENZHOU: usize = 1; // should suggest `pub` +16 | #[no_mangle] static SHENZHOU: usize = 1; // should suggest `pub` | -^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | help: try making it public: `pub` @@ -43,9 +55,9 @@ warning: static is marked #[no_mangle], but not exported = note: #[warn(private_no_mangle_statics)] on by default error: const items should never be #[no_mangle] - --> $DIR/suggestions.rs:16:14 + --> $DIR/suggestions.rs:18:14 | -16 | #[no_mangle] const DISCOVERY: usize = 1; // should suggest `pub static` rather than `const` +18 | #[no_mangle] const DISCOVERY: usize = 1; // should suggest `pub static` rather than `const` | -----^^^^^^^^^^^^^^^^^^^^^^ | | | help: try a static value: `pub static` @@ -53,19 +65,19 @@ error: const items should never be #[no_mangle] = note: #[deny(no_mangle_const_items)] on by default warning: functions generic over types must be mangled - --> $DIR/suggestions.rs:20:1 + --> $DIR/suggestions.rs:22:1 | -19 | #[no_mangle] // should suggest removal (generics can't be no-mangle) +21 | #[no_mangle] // should suggest removal (generics can't be no-mangle) | ------------ help: remove this attribute -20 | pub fn defiant(_t: T) {} +22 | pub fn defiant(_t: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: #[warn(no_mangle_generic_items)] on by default warning: function is marked #[no_mangle], but not exported - --> $DIR/suggestions.rs:24:1 + --> $DIR/suggestions.rs:26:1 | -24 | fn rio_grande() {} // should suggest `pub` +26 | fn rio_grande() {} // should suggest `pub` | -^^^^^^^^^^^^^^^^^ | | | help: try making it public: `pub` @@ -73,29 +85,29 @@ warning: function is marked #[no_mangle], but not exported = note: #[warn(private_no_mangle_fns)] on by default warning: static is marked #[no_mangle], but not exported - --> $DIR/suggestions.rs:31:18 + --> $DIR/suggestions.rs:33:18 | -31 | #[no_mangle] pub static DAUNTLESS: bool = true; +33 | #[no_mangle] pub static DAUNTLESS: bool = true; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: function is marked #[no_mangle], but not exported - --> $DIR/suggestions.rs:33:18 + --> $DIR/suggestions.rs:35:18 | -33 | #[no_mangle] pub fn val_jean() {} +35 | #[no_mangle] pub fn val_jean() {} | ^^^^^^^^^^^^^^^^^^^^ warning: denote infinite loops with `loop { ... }` - --> $DIR/suggestions.rs:44:5 + --> $DIR/suggestions.rs:46:5 | -44 | while true { // should suggest `loop` +46 | while true { // should suggest `loop` | ^^^^^^^^^^ help: use `loop` | = note: #[warn(while_true)] on by default warning: the `warp_factor:` in this pattern is redundant - --> $DIR/suggestions.rs:51:23 + --> $DIR/suggestions.rs:57:23 | -51 | Equinox { warp_factor: warp_factor } => {} // should suggest shorthand +57 | Equinox { warp_factor: warp_factor } => {} // should suggest shorthand | ------------^^^^^^^^^^^^ | | | help: remove this diff --git a/src/test/ui/loop-break-value-no-repeat.stderr b/src/test/ui/loop-break-value-no-repeat.stderr index 296b3b191e3..982de00b4fa 100644 --- a/src/test/ui/loop-break-value-no-repeat.stderr +++ b/src/test/ui/loop-break-value-no-repeat.stderr @@ -3,6 +3,10 @@ error[E0571]: `break` with value from a `for` loop | 22 | break 22 //~ ERROR `break` with value from a `for` loop | ^^^^^^^^ can only break with a value inside `loop` +help: instead, use `break` on its own without a value inside this `for` loop + | +22 | break //~ ERROR `break` with value from a `for` loop + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/macro_backtrace/main.stderr b/src/test/ui/macro_backtrace/main.stderr index 5990f71b3ca..48138ee711b 100644 --- a/src/test/ui/macro_backtrace/main.stderr +++ b/src/test/ui/macro_backtrace/main.stderr @@ -22,7 +22,7 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found 27 | ping!(); | -------- in this macro invocation | - ::: + ::: :1:1 | 1 | ( ) => { pong ! ( ) ; } | ------------------------- @@ -42,7 +42,7 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found 28 | deep!(); | -------- in this macro invocation (#1) | - ::: + ::: :1:1 | 1 | ( ) => { foo ! ( ) ; } | ------------------------ @@ -50,7 +50,7 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found | | in this macro invocation (#2) | in this expansion of `deep!` (#1) | - ::: + ::: :1:1 | 1 | ( ) => { bar ! ( ) ; } | ------------------------ @@ -58,7 +58,7 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found | | in this macro invocation (#3) | in this expansion of `foo!` (#2) | - ::: + ::: :1:1 | 1 | ( ) => { ping ! ( ) ; } | ------------------------- @@ -66,7 +66,7 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found | | in this macro invocation (#4) | in this expansion of `bar!` (#3) | - ::: + ::: :1:1 | 1 | ( ) => { pong ! ( ) ; } | ------------------------- diff --git a/src/test/ui/macros/span-covering-argument-1.rs b/src/test/ui/macros/span-covering-argument-1.rs new file mode 100644 index 00000000000..bfc137fc7b2 --- /dev/null +++ b/src/test/ui/macros/span-covering-argument-1.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! bad { + ($s:ident whatever) => { + { + let $s = 0; + *&mut $s = 0; + //~^ ERROR cannot borrow immutable local variable `foo` as mutable [E0596] + } + } +} + +fn main() { + bad!(foo whatever); +} diff --git a/src/test/ui/macros/span-covering-argument-1.stderr b/src/test/ui/macros/span-covering-argument-1.stderr new file mode 100644 index 00000000000..677d2f10fd6 --- /dev/null +++ b/src/test/ui/macros/span-covering-argument-1.stderr @@ -0,0 +1,13 @@ +error[E0596]: cannot borrow immutable local variable `foo` as mutable + --> $DIR/span-covering-argument-1.rs:15:19 + | +14 | let $s = 0; + | -- consider changing this to `mut $s` +15 | *&mut $s = 0; + | ^^ cannot borrow mutably +... +22 | bad!(foo whatever); + | ------------------- in this macro invocation + +error: aborting due to previous error + diff --git a/src/test/ui/mismatched_types/binops.rs b/src/test/ui/mismatched_types/binops.rs index e45616cd67a..3f2cb59b11d 100644 --- a/src/test/ui/mismatched_types/binops.rs +++ b/src/test/ui/mismatched_types/binops.rs @@ -9,10 +9,10 @@ // except according to those terms. fn main() { - 1 + Some(1); //~ ERROR is not satisfied - 2 as usize - Some(1); //~ ERROR is not satisfied - 3 * (); //~ ERROR is not satisfied - 4 / ""; //~ ERROR is not satisfied + 1 + Some(1); //~ ERROR cannot add `std::option::Option<{integer}>` to `{integer}` + 2 as usize - Some(1); //~ ERROR cannot subtract `std::option::Option<{integer}>` from `usize` + 3 * (); //~ ERROR cannot multiply `()` to `{integer}` + 4 / ""; //~ ERROR cannot divide `{integer}` by `&str` 5 < String::new(); //~ ERROR is not satisfied 6 == Ok(1); //~ ERROR is not satisfied } diff --git a/src/test/ui/mismatched_types/binops.stderr b/src/test/ui/mismatched_types/binops.stderr index 8541ad52e01..828cf636951 100644 --- a/src/test/ui/mismatched_types/binops.stderr +++ b/src/test/ui/mismatched_types/binops.stderr @@ -1,31 +1,31 @@ -error[E0277]: the trait bound `{integer}: std::ops::Add>` is not satisfied +error[E0277]: cannot add `std::option::Option<{integer}>` to `{integer}` --> $DIR/binops.rs:12:7 | -12 | 1 + Some(1); //~ ERROR is not satisfied +12 | 1 + Some(1); //~ ERROR cannot add `std::option::Option<{integer}>` to `{integer}` | ^ no implementation for `{integer} + std::option::Option<{integer}>` | = help: the trait `std::ops::Add>` is not implemented for `{integer}` -error[E0277]: the trait bound `usize: std::ops::Sub>` is not satisfied +error[E0277]: cannot subtract `std::option::Option<{integer}>` from `usize` --> $DIR/binops.rs:13:16 | -13 | 2 as usize - Some(1); //~ ERROR is not satisfied +13 | 2 as usize - Some(1); //~ ERROR cannot subtract `std::option::Option<{integer}>` from `usize` | ^ no implementation for `usize - std::option::Option<{integer}>` | = help: the trait `std::ops::Sub>` is not implemented for `usize` -error[E0277]: the trait bound `{integer}: std::ops::Mul<()>` is not satisfied +error[E0277]: cannot multiply `()` to `{integer}` --> $DIR/binops.rs:14:7 | -14 | 3 * (); //~ ERROR is not satisfied +14 | 3 * (); //~ ERROR cannot multiply `()` to `{integer}` | ^ no implementation for `{integer} * ()` | = help: the trait `std::ops::Mul<()>` is not implemented for `{integer}` -error[E0277]: the trait bound `{integer}: std::ops::Div<&str>` is not satisfied +error[E0277]: cannot divide `{integer}` by `&str` --> $DIR/binops.rs:15:7 | -15 | 4 / ""; //~ ERROR is not satisfied +15 | 4 / ""; //~ ERROR cannot divide `{integer}` by `&str` | ^ no implementation for `{integer} / &str` | = help: the trait `std::ops::Div<&str>` is not implemented for `{integer}` diff --git a/src/test/ui/mismatched_types/closure-arg-count.rs b/src/test/ui/mismatched_types/closure-arg-count.rs index 96e5201716c..34232e81cbd 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.rs +++ b/src/test/ui/mismatched_types/closure-arg-count.rs @@ -36,6 +36,9 @@ fn main() { //~^ ERROR closure is expected to take let _it = vec![1, 2, 3].into_iter().enumerate().map(qux); //~^ ERROR function is expected to take + + let _it = vec![1, 2, 3].into_iter().map(usize::checked_add); + //~^ ERROR function is expected to take } fn foo() {} diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index be00ee4d74e..d2a6d6da814 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -90,7 +90,7 @@ error[E0593]: function is expected to take a single 2-tuple as argument, but it 32 | let _it = vec![1, 2, 3].into_iter().enumerate().map(foo); | ^^^ expected function that takes a single 2-tuple as argument ... -41 | fn foo() {} +44 | fn foo() {} | -------- takes 0 arguments error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments @@ -107,8 +107,14 @@ error[E0593]: function is expected to take a single 2-tuple as argument, but it 37 | let _it = vec![1, 2, 3].into_iter().enumerate().map(qux); | ^^^ expected function that takes a single 2-tuple as argument ... -42 | fn qux(x: usize, y: usize) {} +45 | fn qux(x: usize, y: usize) {} | -------------------------- takes 2 distinct arguments -error: aborting due to 11 previous errors +error[E0593]: function is expected to take 1 argument, but it takes 2 arguments + --> $DIR/closure-arg-count.rs:40:41 + | +40 | let _it = vec![1, 2, 3].into_iter().map(usize::checked_add); + | ^^^ expected function that takes 1 argument + +error: aborting due to 12 previous errors diff --git a/src/test/ui/nll/borrowed-match-issue-45045.rs b/src/test/ui/nll/borrowed-match-issue-45045.rs index 8688bfa86dc..4b95bbd5a05 100644 --- a/src/test/ui/nll/borrowed-match-issue-45045.rs +++ b/src/test/ui/nll/borrowed-match-issue-45045.rs @@ -21,7 +21,7 @@ fn main() { let mut e = Xyz::A; let f = &mut e; let g = f; - match e { + match e { //~ cannot use `e` because it was mutably borrowed [E0503] Xyz::A => println!("a"), //~^ cannot use `e` because it was mutably borrowed [E0503] Xyz::B => println!("b"), diff --git a/src/test/ui/nll/borrowed-match-issue-45045.stderr b/src/test/ui/nll/borrowed-match-issue-45045.stderr index 15ca30010a5..f5271b99c4b 100644 --- a/src/test/ui/nll/borrowed-match-issue-45045.stderr +++ b/src/test/ui/nll/borrowed-match-issue-45045.stderr @@ -1,3 +1,16 @@ +error[E0503]: cannot use `e` because it was mutably borrowed + --> $DIR/borrowed-match-issue-45045.rs:24:5 + | +22 | let f = &mut e; + | ------ borrow of `e` occurs here +23 | let g = f; +24 | / match e { //~ cannot use `e` because it was mutably borrowed [E0503] +25 | | Xyz::A => println!("a"), +26 | | //~^ cannot use `e` because it was mutably borrowed [E0503] +27 | | Xyz::B => println!("b"), +28 | | }; + | |_____^ use of borrowed `e` + error[E0503]: cannot use `e` because it was mutably borrowed --> $DIR/borrowed-match-issue-45045.rs:25:9 | @@ -7,5 +20,5 @@ error[E0503]: cannot use `e` because it was mutably borrowed 25 | Xyz::A => println!("a"), | ^^^^^^ use of borrowed `e` -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/trait-associated-constant.rs b/src/test/ui/nll/trait-associated-constant.rs new file mode 100644 index 00000000000..b0f5fbf7160 --- /dev/null +++ b/src/test/ui/nll/trait-associated-constant.rs @@ -0,0 +1,42 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test cases where we put various lifetime constraints on trait +// associated constants. + +#![feature(rustc_attrs)] + +use std::option::Option; + +trait Anything<'a: 'b, 'b> { + const AC: Option<&'b str>; +} + +struct OKStruct { } + +impl<'a: 'b, 'b> Anything<'a, 'b> for OKStruct { + const AC: Option<&'b str> = None; +} + +struct FailStruct1 { } + +impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct1 { + const AC: Option<&'c str> = None; + //~^ ERROR: mismatched types +} + +struct FailStruct2 { } + +impl<'a: 'b, 'b> Anything<'a, 'b> for FailStruct2 { + const AC: Option<&'a str> = None; + //~^ ERROR: mismatched types +} + +fn main() {} diff --git a/src/test/ui/nll/trait-associated-constant.stderr b/src/test/ui/nll/trait-associated-constant.stderr new file mode 100644 index 00000000000..21c1a6ded93 --- /dev/null +++ b/src/test/ui/nll/trait-associated-constant.stderr @@ -0,0 +1,40 @@ +error[E0308]: mismatched types + --> $DIR/trait-associated-constant.rs:31:5 + | +31 | const AC: Option<&'c str> = None; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected type `std::option::Option<&'b str>` + found type `std::option::Option<&'c str>` +note: the lifetime 'c as defined on the impl at 30:1... + --> $DIR/trait-associated-constant.rs:30:1 + | +30 | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct1 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 30:1 + --> $DIR/trait-associated-constant.rs:30:1 + | +30 | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct1 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/trait-associated-constant.rs:38:5 + | +38 | const AC: Option<&'a str> = None; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected type `std::option::Option<&'b str>` + found type `std::option::Option<&'a str>` +note: the lifetime 'a as defined on the impl at 37:1... + --> $DIR/trait-associated-constant.rs:37:1 + | +37 | impl<'a: 'b, 'b> Anything<'a, 'b> for FailStruct2 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 37:1 + --> $DIR/trait-associated-constant.rs:37:1 + | +37 | impl<'a: 'b, 'b> Anything<'a, 'b> for FailStruct2 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/on-unimplemented/auxiliary/no_debug.rs b/src/test/ui/on-unimplemented/auxiliary/no_debug.rs new file mode 100644 index 00000000000..0f833c62637 --- /dev/null +++ b/src/test/ui/on-unimplemented/auxiliary/no_debug.rs @@ -0,0 +1,14 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// ignore-tidy-linelength + +#![crate_type = "lib"] + +pub struct Bar; diff --git a/src/test/ui/on-unimplemented/no-debug.rs b/src/test/ui/on-unimplemented/no-debug.rs new file mode 100644 index 00000000000..fff6122c6b3 --- /dev/null +++ b/src/test/ui/on-unimplemented/no-debug.rs @@ -0,0 +1,27 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:no_debug.rs + +extern crate no_debug; + +use no_debug::Bar; + +struct Foo; + +fn main() { + println!("{:?} {:?}", Foo, Bar); + println!("{} {}", Foo, Bar); +} +//~^^^ ERROR `Foo` doesn't implement `std::fmt::Debug` +//~| ERROR `no_debug::Bar` doesn't implement `std::fmt::Debug` +//~^^^^ ERROR `Foo` doesn't implement `std::fmt::Display` +//~| ERROR `no_debug::Bar` doesn't implement `std::fmt::Display` + diff --git a/src/test/ui/on-unimplemented/no-debug.stderr b/src/test/ui/on-unimplemented/no-debug.stderr new file mode 100644 index 00000000000..af5b1e91211 --- /dev/null +++ b/src/test/ui/on-unimplemented/no-debug.stderr @@ -0,0 +1,38 @@ +error[E0277]: `Foo` doesn't implement `std::fmt::Debug` + --> $DIR/no-debug.rs:20:27 + | +20 | println!("{:?} {:?}", Foo, Bar); + | ^^^ `Foo` cannot be formatted using `:?`; add `#[derive(Debug)]` or manually implement `std::fmt::Debug` + | + = help: the trait `std::fmt::Debug` is not implemented for `Foo` + = note: required by `std::fmt::Debug::fmt` + +error[E0277]: `no_debug::Bar` doesn't implement `std::fmt::Debug` + --> $DIR/no-debug.rs:20:32 + | +20 | println!("{:?} {:?}", Foo, Bar); + | ^^^ `no_debug::Bar` cannot be formatted using `:?` because it doesn't implement `std::fmt::Debug` + | + = help: the trait `std::fmt::Debug` is not implemented for `no_debug::Bar` + = note: required by `std::fmt::Debug::fmt` + +error[E0277]: `Foo` doesn't implement `std::fmt::Display` + --> $DIR/no-debug.rs:21:23 + | +21 | println!("{} {}", Foo, Bar); + | ^^^ `Foo` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string + | + = help: the trait `std::fmt::Display` is not implemented for `Foo` + = note: required by `std::fmt::Display::fmt` + +error[E0277]: `no_debug::Bar` doesn't implement `std::fmt::Display` + --> $DIR/no-debug.rs:21:28 + | +21 | println!("{} {}", Foo, Bar); + | ^^^ `no_debug::Bar` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string + | + = help: the trait `std::fmt::Display` is not implemented for `no_debug::Bar` + = note: required by `std::fmt::Display::fmt` + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/param-bounds-ignored.rs b/src/test/ui/param-bounds-ignored.rs new file mode 100644 index 00000000000..9e09102f2d4 --- /dev/null +++ b/src/test/ui/param-bounds-ignored.rs @@ -0,0 +1,33 @@ +// 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. + +// must-compile-successfully + +use std::rc::Rc; + +type SVec = Vec; +type VVec<'b, 'a: 'b> = Vec<&'a i32>; +type WVec<'b, T: 'b> = Vec; + +fn foo<'a>(y: &'a i32) { + // If the bounds above would matter, the code below would be rejected. + let mut x : SVec<_> = Vec::new(); + x.push(Rc::new(42)); + + let mut x : VVec<'static, 'a> = Vec::new(); + x.push(y); + + let mut x : WVec<'static, & 'a i32> = Vec::new(); + x.push(y); +} + +fn main() { + foo(&42); +} diff --git a/src/test/ui/param-bounds-ignored.stderr b/src/test/ui/param-bounds-ignored.stderr new file mode 100644 index 00000000000..19aa9c5d6e5 --- /dev/null +++ b/src/test/ui/param-bounds-ignored.stderr @@ -0,0 +1,18 @@ +warning[E0122]: generic bounds are ignored in type aliases + --> $DIR/param-bounds-ignored.rs:15:1 + | +15 | type SVec = Vec; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning[E0122]: generic bounds are ignored in type aliases + --> $DIR/param-bounds-ignored.rs:16:1 + | +16 | type VVec<'b, 'a: 'b> = Vec<&'a i32>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning[E0122]: generic bounds are ignored in type aliases + --> $DIR/param-bounds-ignored.rs:17:1 + | +17 | type WVec<'b, T: 'b> = Vec; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/src/test/ui/recursive-requirements.rs b/src/test/ui/recursive-requirements.rs new file mode 100644 index 00000000000..2c0f0338b2d --- /dev/null +++ b/src/test/ui/recursive-requirements.rs @@ -0,0 +1,27 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::marker::PhantomData; + +struct AssertSync(PhantomData); + +pub struct Foo { + bar: *const Bar, + phantom: PhantomData, +} + +pub struct Bar { + foo: *const Foo, + phantom: PhantomData, +} + +fn main() { + let _: AssertSync = unimplemented!(); //~ ERROR E0275 +} diff --git a/src/test/ui/recursive-requirements.stderr b/src/test/ui/recursive-requirements.stderr new file mode 100644 index 00000000000..8cf2c65b1e2 --- /dev/null +++ b/src/test/ui/recursive-requirements.stderr @@ -0,0 +1,14 @@ +error[E0275]: overflow evaluating the requirement `Foo: std::marker::Sync` + --> $DIR/recursive-requirements.rs:26:12 + | +26 | let _: AssertSync = unimplemented!(); //~ ERROR E0275 + | ^^^^^^^^^^^^^^^ + | + = help: consider adding a `#![recursion_limit="128"]` attribute to your crate + = note: required because it appears within the type `std::marker::PhantomData` + = note: required because it appears within the type `Bar` + = note: required because it appears within the type `std::marker::PhantomData` + = note: required because it appears within the type `Foo` + +error: aborting due to previous error + diff --git a/src/test/ui/resolve-conflict-item-vs-import.stderr b/src/test/ui/resolve-conflict-item-vs-import.stderr index 03ef66681e4..e2245b8a8b1 100644 --- a/src/test/ui/resolve-conflict-item-vs-import.stderr +++ b/src/test/ui/resolve-conflict-item-vs-import.stderr @@ -10,8 +10,8 @@ error[E0255]: the name `transmute` is defined multiple times = note: `transmute` must be defined only once in the value namespace of this module help: You can use `as` to change the binding name of the import | -11 | use std::mem::transmute as Othertransmute; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +11 | use std::mem::transmute as other_transmute; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 7e19c7492ce..31728dbf08d 100644 --- a/src/test/ui/span/issue-24690.stderr +++ b/src/test/ui/span/issue-24690.stderr @@ -2,7 +2,7 @@ warning: unused variable: `theOtherTwo` --> $DIR/issue-24690.rs:23:9 | 23 | let theOtherTwo = 2; //~ WARN should have a snake case name - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ help: consider using `_theOtherTwo` instead | note: lint level defined here --> $DIR/issue-24690.rs:18:9 @@ -10,7 +10,6 @@ note: lint level defined here 18 | #![warn(unused)] | ^^^^^^ = note: #[warn(unused_variables)] implied by #[warn(unused)] - = note: to avoid this warning, consider using `_theOtherTwo` instead warning: variable `theTwo` should have a snake case name such as `the_two` --> $DIR/issue-24690.rs:22:9 diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.rs b/src/test/ui/span/issue-42234-unknown-receiver-type.rs new file mode 100644 index 00000000000..d9cdd99c245 --- /dev/null +++ b/src/test/ui/span/issue-42234-unknown-receiver-type.rs @@ -0,0 +1,27 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// When the type of a method call's receiver is unknown, the span should point +// to the receiver (and not the entire call, as was previously the case before +// the fix of which this tests). + +fn shines_a_beacon_through_the_darkness() { + let x: Option<_> = None; + x.unwrap().method_that_could_exist_on_some_type(); + //~^ ERROR 17:5: 17:15: the type of this value must be known in this context +} + +fn courier_to_des_moines_and_points_west(data: &[u32]) -> String { + data.iter() //~ ERROR 22:5: 23:20: the type of this value must be known in this context + .sum::<_>() + .to_string() +} + +fn main() {} diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.stderr b/src/test/ui/span/issue-42234-unknown-receiver-type.stderr new file mode 100644 index 00000000000..ed756cdc553 --- /dev/null +++ b/src/test/ui/span/issue-42234-unknown-receiver-type.stderr @@ -0,0 +1,15 @@ +error[E0619]: the type of this value must be known in this context + --> $DIR/issue-42234-unknown-receiver-type.rs:17:5 + | +17 | x.unwrap().method_that_could_exist_on_some_type(); + | ^^^^^^^^^^ + +error[E0619]: the type of this value must be known in this context + --> $DIR/issue-42234-unknown-receiver-type.rs:22:5 + | +22 | / data.iter() //~ ERROR 22:5: 23:20: the type of this value must be known in this context +23 | | .sum::<_>() + | |___________________^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/span/macro-span-replacement.stderr b/src/test/ui/span/macro-span-replacement.stderr index 2a0e71e192c..728cd12e2c6 100644 --- a/src/test/ui/span/macro-span-replacement.stderr +++ b/src/test/ui/span/macro-span-replacement.stderr @@ -1,8 +1,8 @@ warning: struct is never used: `S` - --> $DIR/macro-span-replacement.rs:17:9 + --> $DIR/macro-span-replacement.rs:17:14 | 17 | $b $a; //~ WARN struct is never used - | ^^^^^^ + | ^ ... 22 | m!(S struct); | ------------- in this macro invocation diff --git a/src/test/ui/span/multiline-span-simple.rs b/src/test/ui/span/multiline-span-simple.rs index f8e4cbcbf19..dd09534480e 100644 --- a/src/test/ui/span/multiline-span-simple.rs +++ b/src/test/ui/span/multiline-span-simple.rs @@ -20,7 +20,7 @@ fn main() { let x = 1; let y = 2; let z = 3; - foo(1 as u32 + //~ ERROR not satisfied + foo(1 as u32 + //~ ERROR cannot add `()` to `u32` bar(x, diff --git a/src/test/ui/span/multiline-span-simple.stderr b/src/test/ui/span/multiline-span-simple.stderr index b068798630e..a18dfeb31d9 100644 --- a/src/test/ui/span/multiline-span-simple.stderr +++ b/src/test/ui/span/multiline-span-simple.stderr @@ -1,7 +1,7 @@ -error[E0277]: the trait bound `u32: std::ops::Add<()>` is not satisfied +error[E0277]: cannot add `()` to `u32` --> $DIR/multiline-span-simple.rs:23:18 | -23 | foo(1 as u32 + //~ ERROR not satisfied +23 | foo(1 as u32 + //~ ERROR cannot add `()` to `u32` | ^ no implementation for `u32 + ()` | = help: the trait `std::ops::Add<()>` is not implemented for `u32` diff --git a/src/test/ui/static-lifetime.stderr b/src/test/ui/static-lifetime.stderr index a99dbf21e54..24ba27b27ad 100644 --- a/src/test/ui/static-lifetime.stderr +++ b/src/test/ui/static-lifetime.stderr @@ -8,7 +8,7 @@ note: lifetime parameter instantiated with the lifetime 'a as defined on the imp --> $DIR/static-lifetime.rs:13:1 | 13 | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} //~ ERROR lifetime bound - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: but lifetime parameter must outlive the static lifetime error: aborting due to previous error diff --git a/src/test/ui/suggestions/for-c-in-str.stderr b/src/test/ui/suggestions/for-c-in-str.stderr index 7a6dc9a5040..88a7b1b49d6 100644 --- a/src/test/ui/suggestions/for-c-in-str.stderr +++ b/src/test/ui/suggestions/for-c-in-str.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `&str: std::iter::Iterator` is not satisfied --> $DIR/for-c-in-str.rs:14:14 | 14 | for c in "asdf" { - | ^^^^^^ `&str` is not an iterator; maybe try calling `.iter()` or a similar method + | ^^^^^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()` | = help: the trait `std::iter::Iterator` is not implemented for `&str` = note: required by `std::iter::IntoIterator::into_iter` diff --git a/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr b/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr index d2ac15f7ffc..01dba62a851 100644 --- a/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr +++ b/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr @@ -7,7 +7,7 @@ error[E0259]: the name `std` is defined multiple times = note: `std` must be defined only once in the type namespace of this module help: You can use `as` to change the binding name of the import | -11 | extern crate std as Otherstd; +11 | extern crate std as other_std; | error: aborting due to previous error diff --git a/src/test/ui/use-mod.stderr b/src/test/ui/use-mod.stderr index bb64909e64a..1c9f306f493 100644 --- a/src/test/ui/use-mod.stderr +++ b/src/test/ui/use-mod.stderr @@ -25,7 +25,7 @@ error[E0252]: the name `bar` is defined multiple times = note: `bar` must be defined only once in the type namespace of this module help: You can use `as` to change the binding name of the import | -15 | self as Otherbar +15 | self as other_bar | error: aborting due to 3 previous errors diff --git a/src/test/ui/use-nested-groups-error.rs b/src/test/ui/use-nested-groups-error.rs new file mode 100644 index 00000000000..0a68d34ade9 --- /dev/null +++ b/src/test/ui/use-nested-groups-error.rs @@ -0,0 +1,25 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod a { + pub mod b1 { + pub enum C2 {} + } + + pub enum B2 {} +} + +use a::{b1::{C1, C2}, B2}; +//~^ ERROR unresolved import `a::b1::C1` + +fn main() { + let _: C2; + let _: B2; +} diff --git a/src/test/ui/use-nested-groups-error.stderr b/src/test/ui/use-nested-groups-error.stderr new file mode 100644 index 00000000000..c4edb626be0 --- /dev/null +++ b/src/test/ui/use-nested-groups-error.stderr @@ -0,0 +1,8 @@ +error[E0432]: unresolved import `a::b1::C1` + --> $DIR/use-nested-groups-error.rs:19:14 + | +19 | use a::{b1::{C1, C2}, B2}; + | ^^ no `C1` in `a::b1`. Did you mean to use `C2`? + +error: aborting due to previous error + diff --git a/src/tools/clippy b/src/tools/clippy index 7d7fef16902..ce47e529d29 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 7d7fef1690218bbb406cf3bcadf7bb29dbb40cc5 +Subproject commit ce47e529d29f0bf19b31ae80b37b467e42fb97e2 diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index ff662736bdd..80750f9a3fe 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -167,7 +167,7 @@ fn ignore_llvm(config: &Config, line: &str) -> bool { .expect("Malformed llvm version directive"); // Ignore if using system LLVM and actual version // is smaller the minimum required version - !(config.system_llvm && &actual_version[..] < min_version) + config.system_llvm && &actual_version[..] < min_version } else { false } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index bf5fc00428d..a87809dd7bc 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -79,7 +79,7 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec { if lines_since_mismatch >= context_size && lines_since_mismatch > 0 { @@ -91,7 +91,8 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec { @@ -104,8 +105,7 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec { @@ -1343,7 +1343,7 @@ fn document(&self, out_dir: &Path) -> ProcRes { fn exec_compiled_test(&self) -> ProcRes { let env = &self.props.exec_env; - match &*self.config.target { + let proc_res = match &*self.config.target { // This is pretty similar to below, we're transforming: // // program arg1 arg2 @@ -1398,11 +1398,19 @@ fn exec_compiled_test(&self) -> ProcRes { None, ) } + }; + + if proc_res.status.success() { + // delete the executable after running it to save space. + // it is ok if the deletion failed. + let _ = fs::remove_file(self.make_exe_name()); } + + proc_res } /// For each `aux-build: foo/bar` annotation, we check to find the - /// file in a `aux` directory relative to the test itself. + /// file in a `auxiliary` directory relative to the test itself. fn compute_aux_test_paths(&self, rel_ab: &str) -> TestPaths { let test_ab = self.testpaths .file diff --git a/src/tools/miri b/src/tools/miri index 919604e1ead..61833b9aeab 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 919604e1ead8294c8ca14f101be4380ea1ea370c +Subproject commit 61833b9aeab8bf8f0c0c0e42b7c96b6eceb37d0d diff --git a/src/tools/rls b/src/tools/rls index 511321ae1c2..dee42bda815 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 511321ae1c2fa3f0e334885fecf406dd6c882836 +Subproject commit dee42bda8156a28ead609080e27b02173bb9c29e diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml index bc35cbe9fbb..539b434e9ec 100644 --- a/src/tools/rustbook/Cargo.toml +++ b/src/tools/rustbook/Cargo.toml @@ -8,5 +8,5 @@ license = "MIT/Apache-2.0" clap = "2.25.0" [dependencies.mdbook] -version = "0.0.28" +version = "0.1.2" default-features = false diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs index 50f4364e448..87a63a34cb6 100644 --- a/src/tools/rustbook/src/main.rs +++ b/src/tools/rustbook/src/main.rs @@ -13,7 +13,6 @@ extern crate clap; use std::env; -use std::io::{self, Write}; use std::path::{Path, PathBuf}; use clap::{App, ArgMatches, SubCommand, AppSettings}; @@ -45,14 +44,19 @@ fn main() { }; if let Err(e) = res { - writeln!(&mut io::stderr(), "An error occured:\n{}", e).ok(); + eprintln!("Error: {}", e); + + for cause in e.iter().skip(1) { + eprintln!("\tCaused By: {}", cause); + } + ::std::process::exit(101); } } // Build command implementation pub fn build(args: &ArgMatches) -> Result<()> { let book_dir = get_book_dir(args); - let mut book = MDBook::new(&book_dir).read_config()?; + let mut book = MDBook::load(&book_dir)?; // Set this to allow us to catch bugs in advance. book.config.build.create_missing = false; diff --git a/src/tools/rustdoc-themes/Cargo.toml b/src/tools/rustdoc-themes/Cargo.toml new file mode 100644 index 00000000000..c0e2f527301 --- /dev/null +++ b/src/tools/rustdoc-themes/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "rustdoc-themes" +version = "0.1.0" +authors = ["Guillaume Gomez "] + +[[bin]] +name = "rustdoc-themes" +path = "main.rs" diff --git a/src/tools/rustdoc-themes/main.rs b/src/tools/rustdoc-themes/main.rs new file mode 100644 index 00000000000..4028cb4e8b6 --- /dev/null +++ b/src/tools/rustdoc-themes/main.rs @@ -0,0 +1,59 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::env::args; +use std::fs::read_dir; +use std::path::Path; +use std::process::{Command, exit}; + +const FILES_TO_IGNORE: &[&str] = &["main.css"]; + +fn get_folders>(folder_path: P) -> Vec { + let mut ret = Vec::with_capacity(10); + + for entry in read_dir(folder_path.as_ref()).expect("read_dir failed") { + let entry = entry.expect("Couldn't unwrap entry"); + let path = entry.path(); + + if !path.is_file() { + continue + } + let filename = path.file_name().expect("file_name failed"); + if FILES_TO_IGNORE.iter().any(|x| x == &filename) { + continue + } + ret.push(format!("{}", path.display())); + } + ret +} + +fn main() { + let argv: Vec = args().collect(); + + if argv.len() < 3 { + eprintln!("Needs rustdoc binary path"); + exit(1); + } + let rustdoc_bin = &argv[1]; + let themes_folder = &argv[2]; + let themes = get_folders(&themes_folder); + if themes.is_empty() { + eprintln!("No theme found in \"{}\"...", themes_folder); + exit(1); + } + let status = Command::new(rustdoc_bin) + .args(&["-Z", "unstable-options", "--theme-checker"]) + .args(&themes) + .status() + .expect("failed to execute child"); + if !status.success() { + exit(1); + } +} diff --git a/src/tools/rustfmt b/src/tools/rustfmt index e0e3e22248c..346238f4974 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit e0e3e22248cd14ebbe0253e9720261a0328bfc59 +Subproject commit 346238f49740d6c98102a6a59811b1625c73a9d7 diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index bc2767c7bcc..159c9e035b7 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -33,6 +33,8 @@ "openssl", // BSD+advertising clause, cargo, mdbook "pest", // MPL2, mdbook via handlebars "thread-id", // Apache-2.0, mdbook + "toml-query", // MPL-2.0, mdbook + "is-match", // MPL-2.0, mdbook "cssparser", // MPL-2.0, rustdoc "smallvec", // MPL-2.0, rustdoc "fuchsia-zircon-sys", // BSD-3-Clause, rustdoc, rustc, cargo