+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::<char>` 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<bool>` for `AtomicBool`][46293]
+- [impl `From<{CString, &CStr}>` for `{Arc<CStr>, Rc<CStr>}`][45990]
+- [impl `From<{OsString, &OsStr}>` for `{Arc<OsStr>, Rc<OsStr>}`][45990]
+- [impl `From<{PathBuf, &Path}>` for `{Arc<Path>, Rc<Path>}`][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<RecvError>` 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::<usize>()];`, `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)
==========================
# 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
# 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
# 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
# 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
#
#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"
"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)",
]
[[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)",
[[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)",
[[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)",
"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"
"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"
[[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]]
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)",
]
[[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)",
"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)",
"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"
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]]
[[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)",
[[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)",
]
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)",
"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"
[[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)",
"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)",
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"
"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"
"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"
"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"
"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"
"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"
"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"
"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"
"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",
-Subproject commit 1c9bf65aa0e371b84755a8ddd6e79497fac57171
+Subproject commit 17841e155edf858c8ea7802dd5f5ecbef54b989f
serde_json = "1.0.2"
toml = "0.4"
lazy_static = "0.2"
+time = "0.1"
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,
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.
///
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.
})
.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);
// 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());
//
// 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())
}
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);
}
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" {
}
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");
}
pub fn librustc_stamp(build: &Build, compiler: Compiler, target: Interned<String>) -> PathBuf {
build.cargo_out(compiler, Mode::Librustc, target).join(".librustc-check.stamp")
}
-
//
// 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() {
//! 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::*;
pub target_config: HashMap<Interned<String>, Target>,
pub full_bootstrap: bool,
pub extended: bool,
+ pub tools: Option<HashSet<String>>,
pub sanitizers: bool,
pub profiler: bool,
pub ignore_git: bool,
// rust codegen options
pub rust_optimize: bool,
pub rust_codegen_units: Option<u32>,
+ pub rust_thinlto: bool,
pub rust_debug_assertions: bool,
pub rust_debuginfo: bool,
pub rust_debuginfo_lines: bool,
pub debug_jemalloc: bool,
pub use_jemalloc: bool,
pub backtrace: bool, // support for RUST_BACKTRACE
+ pub wasm_syscall: bool,
// misc
pub low_priority: bool,
python: Option<String>,
full_bootstrap: Option<bool>,
extended: Option<bool>,
+ tools: Option<HashSet<String>>,
verbose: Option<usize>,
sanitizers: Option<bool>,
profiler: Option<bool>,
struct Rust {
optimize: Option<bool>,
codegen_units: Option<u32>,
+ thinlto: Option<bool>,
debug_assertions: Option<bool>,
debuginfo: Option<bool>,
debuginfo_lines: Option<bool>,
test_miri: Option<bool>,
save_toolstates: Option<String>,
codegen_backends: Option<Vec<String>>,
+ wasm_syscall: Option<bool>,
}
/// TOML representation of how each build target is configured.
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);
// 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;
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);
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);
"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);
# 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")
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")
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" {
}
// 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);
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)) {
t!(fs::copy(&page_src, &page_dst));
// template in month/year and version number
replace_in_file(&page_dst,
- &[("<INSERT DATE HERE>", month_year),
+ &[("<INSERT DATE HERE>", &month_year),
("<INSERT VERSION HERE>", channel::CFG_RELEASE_NUM)]);
}
.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);
}
use builder::{Builder, RunConfig, ShouldRun, Step};
use cache::Interned;
+use config::Config;
pub fn install_docs(builder: &Builder, stage: u32, host: Interned<String>) {
install_sh(builder, "docs", "rust-docs", stage, Some(host));
pub host: Interned<String>,
}
+ 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;
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;
extern crate getopts;
extern crate num_cpus;
extern crate toml;
+extern crate time;
#[cfg(unix)]
extern crate libc;
if self.config.profiler {
features.push_str(" profiler");
}
+ if self.config.wasm_syscall {
+ features.push_str(" wasm_syscall");
+ }
features
}
}
}
- /// 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<String>) -> Option<&Path> {
if let Some(linker) = self.config.target_config.get(&target)
.and_then(|c| c.linker.as_ref()) {
}
// http://llvm.org/docs/HowToCrossCompileLLVM.html
- if target != build.build {
+ if target != build.build && !emscripten {
builder.ensure(Llvm {
target: build.build,
emscripten: false,
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 {
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<String>,
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" },
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)]
}
}
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;
}
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");
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)]
-FROM ubuntu:16.04
+FROM ubuntu:18.04
RUN apt-get update && apt-get install -y --no-install-recommends \
clang \
--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
# 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
# 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'..."
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"
-Subproject commit d3812c3accaee7ad23068ed4fc089cc05c7a538f
+Subproject commit 9b2dcac06c3e23235f8997b3c5f2325a6d3382df
-Subproject commit 194eb8d5f1753fb5f4501011cebdc1b585712474
+Subproject commit ec5660820dea91df470dab0b9eb26ef798f20889
-Subproject commit fec3182d0b0a3cf8122e192b3270064a5b19be5b
+Subproject commit ad5ddd62c098d5b424151beda574ae7df2154df1
-Subproject commit 1d791b55b23ec5389fbd5b3cee80db3f8bbdd162
+Subproject commit 254df654a9b75abf6ca08806535dbe1fad41be3f
-Subproject commit 4ebb8169dfe569b3dcbeab560607800bb717978a
+Subproject commit 919980be7df4ea7d45a9dca8efc34da89bcf7d6b
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
### 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
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<T: ?Sized>(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
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
- `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`
--- /dev/null
+# `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"...
+ => {}
+}
+```
+
+------------------------
+
+++ /dev/null
-# `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
+++ /dev/null
-# `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}};`
<!-- Upgrade code should be different for each platform -->
<?if $(sys.BUILDARCH)="x64" ?>
<?if $(env.CFG_ABI)="GNU" ?>
- <!-- UpgradeCode shoud stay the same for all MSI versions in channel -->
+ <!-- UpgradeCode should stay the same for all MSI versions in channel -->
<?if $(env.CFG_CHANNEL)="stable" ?>
<?define UpgradeCode="B440B077-F8D1-4730-8E1D-D6D37702B4CE" ?>
<?elseif $(env.CFG_CHANNEL)="beta" ?>
<!-- Path of cmd.exe for the shortcut -->
<Property Id="SHORTCUTTARGET" Value="%windir%\System32\cmd.exe" />
- <!-- Microsoft Installer will resolve any Enviroment Variables in the working directory at install time -->
+ <!-- Microsoft Installer will resolve any Environment Variables in the working directory at install time -->
<Property Id="SHORTCUTWKDIR" Value="%SystemDrive%\" />
<InstallUISequence>
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
(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:
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
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);
+}
{
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")
# 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
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:
-Subproject commit 0a95675bab808c49f86208bacc89c5d9c53ac43f
+Subproject commit 345447948f7a51eca970fa036cefd613d54a4f79
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[cfg(stage0)]
pub fn of<T: ?Sized + 'static>() -> TypeId {
TypeId {
t: unsafe { intrinsics::type_id::<T>() },
}
}
+
+ /// Returns the `TypeId` of the type this generic function has been
+ /// instantiated with.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::any::{Any, TypeId};
+ ///
+ /// fn is_string<T: ?Sized + Any>(_s: &T) -> bool {
+ /// TypeId::of::<String>() == TypeId::of::<T>()
+ /// }
+ ///
+ /// 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<T: ?Sized + 'static>() -> TypeId {
+ TypeId {
+ t: unsafe { intrinsics::type_id::<T>() },
+ }
+ }
}
/// 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,
}
///
/// # 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
///
/// }
/// ```
#[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.
///
/// 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.
#[stable(feature = "rust1", since = "1.0.0")]
impl Debug for bool {
+ #[inline]
fn fmt(&self, f: &mut Formatter) -> Result {
Display::fmt(self, f)
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Debug for () {
+ #[inline]
fn fmt(&self, f: &mut Formatter) -> Result {
f.pad("()")
}
($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)
}
/// 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);
/// }
/// [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.
/// 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:
//!
//! 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")]
use iter_private::TrustedRandomAccess;
use ops::Try;
use usize;
+use intrinsics;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::iterator::Iterator;
(f(inner_hint.0), inner_hint.1.map(f))
}
}
+
+ #[inline]
+ fn nth(&mut self, mut n: usize) -> Option<Self::Item> {
+ 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.
#[unstable(feature = "fused", issue = "35602")]
impl<I> FusedIterator for Take<I> where I: FusedIterator {}
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<I: TrustedLen> TrustedLen for Take<I> {}
+
/// An iterator to maintain state while iterating another iterator.
///
/// This `struct` is created by the [`scan`] method on [`Iterator`]. See its
use convert::TryFrom;
use mem;
-use ops::{self, Add, Sub};
+use ops::{self, Add, Sub, Try};
use usize;
use super::{FusedIterator, TrustedLen};
#[unstable(feature = "fused", issue = "35602")]
impl<A: Step> FusedIterator for ops::RangeFrom<A> {}
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<A: Step> TrustedLen for ops::RangeFrom<A> {}
+
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
impl<A: Step> Iterator for ops::RangeInclusive<A> {
type Item = A;
#[inline]
fn next(&mut self) -> Option<A> {
- 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
}
}
fn max(mut self) -> Option<A> {
self.next_back()
}
+
+ #[inline]
+ fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R where
+ Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
+ {
+ 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<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
#[inline]
fn next_back(&mut self) -> Option<A> {
- 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<B, F, R>(&mut self, init: B, mut f: F) -> R where
+ Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
+ {
+ 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)
}
}
#[unstable(feature = "fused", issue = "35602")]
impl<A: Clone> FusedIterator for Repeat<A> {}
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<A: Clone> TrustedLen for Repeat<A> {}
+
/// Creates a new iterator that endlessly repeats a single element.
///
/// The `repeat()` function repeats a single value over and over and over and
/// 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
///
#![feature(untagged_unions)]
#![feature(unwind_attributes)]
#![feature(doc_spotlight)]
+#![feature(rustc_const_unstable)]
#[prelude_import]
#[allow(unused)]
pub mod str;
pub mod hash;
pub mod fmt;
+pub mod time;
// note: does not need to be public
mod char_private;
/// }
/// }
///
-/// // 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.")?;
/// Type | size_of::\<Type>()
/// ---- | ---------------
/// () | 0
+/// bool | 1
/// u8 | 1
/// u16 | 2
/// u32 | 4
/// 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.
/// 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)
}
/// ```
#[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<RHS=Self> {
/// The resulting type after applying the `+` operator.
#[stable(feature = "rust1", since = "1.0.0")]
/// ```
#[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<RHS=Self> {
/// The resulting type after applying the `-` operator.
#[stable(feature = "rust1", since = "1.0.0")]
/// ```
#[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<RHS=Self> {
/// The resulting type after applying the `*` operator.
#[stable(feature = "rust1", since = "1.0.0")]
/// ```
#[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<RHS=Self> {
/// The resulting type after applying the `/` operator.
#[stable(feature = "rust1", since = "1.0.0")]
/// ```
#[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<RHS=Self> {
/// The resulting type after applying the `%` operator.
#[stable(feature = "rust1", since = "1.0.0")]
/// ```
#[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<Rhs=Self> {
/// Performs the `+=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
/// ```
#[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<Rhs=Self> {
/// Performs the `-=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
/// ```
#[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<Rhs=Self> {
/// Performs the `*=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
/// ```
#[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<Rhs=Self> {
/// Performs the `/=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
/// ```
#[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<Rhs=Self> {
/// Performs the `%=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
/// ```
#[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<RHS=Self> {
/// The resulting type after applying the `&` operator.
#[stable(feature = "rust1", since = "1.0.0")]
/// ```
#[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<RHS=Self> {
/// The resulting type after applying the `|` operator.
#[stable(feature = "rust1", since = "1.0.0")]
/// ```
#[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<RHS=Self> {
/// The resulting type after applying the `^` operator.
#[stable(feature = "rust1", since = "1.0.0")]
/// ```
#[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<RHS> {
/// The resulting type after applying the `<<` operator.
#[stable(feature = "rust1", since = "1.0.0")]
/// ```
#[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<RHS> {
/// The resulting type after applying the `>>` operator.
#[stable(feature = "rust1", since = "1.0.0")]
/// ```
#[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<Rhs=Self> {
/// Performs the `&=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
/// ```
#[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<Rhs=Self> {
/// Performs the `|=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
/// ```
#[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<Rhs=Self> {
/// Performs the `^=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
/// ```
#[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<Rhs> {
/// Performs the `<<=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
/// ```
#[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<Rhs=Self> {
/// Performs the `>>=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
}
/// 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<T> = NonNull<T>;
/// 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<T: ?Sized> {
pointer: NonZero<*const T>,
}
-#[stable(feature = "nonnull", since = "1.24.0")]
-impl<T: ?Sized> fmt::Debug for NonNull<T> {
- 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<T: ?Sized> !Send for NonNull<T> { }
/// `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<T: ?Sized> !Sync for NonNull<T> { }
impl<T: Sized> NonNull<T> {
///
/// 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::<T>() as *mut T;
/// # 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<Self> {
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
}
/// 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()
}
/// 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<U>(self) -> NonNull<U> {
+ 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<T: ?Sized> Clone for NonNull<T> {
fn clone(&self) -> Self {
*self
}
}
-#[stable(feature = "nonnull", since = "1.24.0")]
+#[stable(feature = "nonnull", since = "1.25.0")]
impl<T: ?Sized> Copy for NonNull<T> { }
-#[stable(feature = "nonnull", since = "1.24.0")]
+#[stable(feature = "nonnull", since = "1.25.0")]
impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> { }
-#[stable(feature = "nonnull", since = "1.24.0")]
+#[stable(feature = "nonnull", since = "1.25.0")]
+impl<T: ?Sized> fmt::Debug for NonNull<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Pointer::fmt(&self.as_ptr(), f)
+ }
+}
+
+#[stable(feature = "nonnull", since = "1.25.0")]
impl<T: ?Sized> fmt::Pointer for NonNull<T> {
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<T: ?Sized> Eq for NonNull<T> {}
+
+#[stable(feature = "nonnull", since = "1.25.0")]
+impl<T: ?Sized> PartialEq for NonNull<T> {
+ fn eq(&self, other: &Self) -> bool {
+ self.as_ptr() == other.as_ptr()
+ }
+}
+
+#[stable(feature = "nonnull", since = "1.25.0")]
+impl<T: ?Sized> Ord for NonNull<T> {
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.as_ptr().cmp(&other.as_ptr())
+ }
+}
+
+#[stable(feature = "nonnull", since = "1.25.0")]
+impl<T: ?Sized> PartialOrd for NonNull<T> {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ self.as_ptr().partial_cmp(&other.as_ptr())
+ }
+}
+
+#[stable(feature = "nonnull", since = "1.25.0")]
+impl<T: ?Sized> hash::Hash for NonNull<T> {
+ fn hash<H: hash::Hasher>(&self, state: &mut H) {
+ self.as_ptr().hash(state)
+ }
+}
+
+#[stable(feature = "nonnull", since = "1.25.0")]
impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
fn from(unique: Unique<T>) -> 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<T> {
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<T> {
fn from(reference: &'a T) -> Self {
NonNull { pointer: NonZero::from(reference) }
$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.
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
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
}
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
}
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
}
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
}
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
}
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
}
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
}
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
}
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
}
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
}
}
}
+#[inline]
+unsafe fn atomic_nand<T>(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<T>(dst: *mut T, val: T, order: Ordering) -> T {
match order {
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);
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);
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<Self::Item> { Some(21) }
+ fn nth(&mut self, n: usize) -> Option<Self::Item> {
+ self.0 += n as Bigger + 1;
+ Some(42)
+ }
+ }
+
+ let mut it = Test(0);
+ let root = usize::MAX >> (::std::mem::size_of::<usize>() * 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() {
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);
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]
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: TrustedLen>(_: 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]
assert_eq!(r.min(), None);
}
+#[test]
+fn test_range_inclusive_folds() {
+ assert_eq!((1..=10).sum::<i32>(), 55);
+ assert_eq!((1..=10).rev().sum::<i32>(), 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]
#![feature(try_from)]
#![feature(try_trait)]
#![feature(exact_chunks)]
+#![feature(atomic_nand)]
extern crate core;
extern crate test;
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Duration> {
+ 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<Duration> {
+ 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<Duration> {
+ // 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<Duration> {
+ 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<u32> 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<u32> for Duration {
+ fn mul_assign(&mut self, rhs: u32) {
+ *self = *self * rhs;
+ }
+}
+
+#[stable(feature = "duration", since = "1.3.0")]
+impl Div<u32> 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<u32> 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<I: Iterator<Item=Duration>>(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<I: Iterator<Item=&'a Duration>>(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);
+ }
+}
/// 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),
#![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,
// 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();
})
}
- DotEq => unreachable!(),
+ DotEq => joint!('.', Eq),
OpenDelim(..) | CloseDelim(..) => unreachable!(),
Whitespace | Comment | Shebang(..) | Eof => unreachable!(),
};
- `'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
[] TargetFeaturesEnabled(DefId),
[] InstanceDefSizeEstimate { instance_def: InstanceDef<'tcx> },
+
+ [] GetSymbolExportLevel(DefId),
+
);
trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
}
```
+### 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
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);
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,
impl_stable_hash_for!(struct mir::UnsafetyViolation { source_info, description, kind });
impl_stable_hash_for!(struct mir::UnsafetyCheckResult { violations, unsafe_blocks });
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
+for mir::BorrowKind {
+ #[inline]
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'gcx>,
+ hasher: &mut StableHasher<W>) {
+ 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<StableHashingContext<'gcx>>
for mir::UnsafetyViolationKind {
#[inline]
target.hash_stable(hcx, hasher);
}
}
+ mir::TerminatorKind::FalseUnwind { ref real_target, ref unwind } => {
+ real_target.hash_stable(hcx, hasher);
+ unwind.hash_stable(hcx, hasher);
+ }
}
}
}
impl_stable_hash_for!(struct ty::adjustment::OverloadedDeref<'tcx> { region, mutbl });
impl_stable_hash_for!(struct ty::UpvarBorrow<'tcx> { kind, region });
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::adjustment::AutoBorrowMutability {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'gcx>,
+ hasher: &mut StableHasher<W>) {
+ 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 {
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;
&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)
}
}
};
- let span = cause.span;
+ let span = cause.span(&self.tcx);
diag.span_label(span, terr.to_string());
if let Some((sp, msg)) = secondary_span {
"did you mean `{}(/* fields */)`?",
self.tcx.item_path_str(def_id)
);
- diag.span_label(cause.span, message);
+ diag.span_label(span, message);
}
}
}
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) => {
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,
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
#![feature(macro_vis_matcher)]
#![feature(match_default_bindings)]
#![feature(never_type)]
+#![feature(non_exhaustive)]
#![feature(nonzero)]
#![feature(quote)]
#![feature(refcell_replace_swap)]
#![feature(specialization)]
#![feature(unboxed_closures)]
#![feature(underscore_lifetimes)]
+#![feature(universal_impl_trait)]
#![feature(trace_macros)]
#![feature(catch_expr)]
#![feature(test)]
"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)]
UNUSED_MUT,
COERCE_NEVER,
SINGLE_USE_LIFETIME,
- TYVAR_BEHIND_RAW_POINTER
+ TYVAR_BEHIND_RAW_POINTER,
+ ELIDED_LIFETIME_IN_PATH
+
)
}
}
type TyLayout = Result<TyLayout<'tcx>, 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))
}
}
// 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");
+ }
}
}
}
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();
}
}
expr.span,
cmt_base,
r,
- ty::BorrowKind::from_mutbl(m),
+ ty::BorrowKind::from_mutbl(m.into()),
AutoRef);
}
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::*;
#[derive(Copy, Clone, Debug)]
struct LocalInfo {
id: NodeId,
- name: ast::Name
+ name: ast::Name,
+ is_shorthand: bool,
}
#[derive(Copy, Clone, Debug)]
}
}
+ 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<CaptureInfo>) {
self.capture_info_map.insert(node_id, Rc::new(cs));
}
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);
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);
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)
}));
})
}
}
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)
}
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)
}
}
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)
}
});
}
}
- 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,
//
// The two kinds of graphs are:
//
- // Tracked lvalue Untracked lvalue
+ // Tracked place Untracked place
// ----------------------++-----------------------
// ||
// | || |
// (rvalue) || (rvalue)
// | || |
// v || v
- // (write of lvalue) || (lvalue components)
+ // (write of place) || (place components)
// | || |
// v || v
// (succ) || (succ)
//
// 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.
}
}
- // 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
}
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);
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);
}
}
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 {
}
}
_ => {
- // 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);
}
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
//! | 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)
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
}
// 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);
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)
// 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)
ret
}
- fn cat_overloaded_lvalue(&self,
+ fn cat_overloaded_place(&self,
expr: &hir::Expr,
base: &hir::Expr,
implicit: bool)
-> McResult<cmt<'tcx>> {
- 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,
});
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: {:?}",
}
}
- /// 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
"static item".to_string()
}
Categorization::Rvalue(..) => {
- "non-lvalue".to_string()
+ "non-place".to_string()
}
Categorization::Local(vid) => {
if tcx.hir.is_argument(vid) {
}
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) {
/// 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()
}
// 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 `<rvalue>` that appears in a let initializer
/// | (ET)
/// | <rvalue>
///
- /// 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<Scope>) {
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() {
}
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);
}
}
- 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.
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,
+ }
+ }
}
///////////////////////////////////////////////////////////////////////////
},
/// 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)
/// }
/// ```
///
///
/// ```
/// 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 {
/// 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<BasicBlock>
+ /// The list of blocks control flow could conceptually take, but won't
+ /// in practice
+ imaginary_targets: Vec<BasicBlock>,
+ },
+ /// 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<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(),
}
}
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],
}
}
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)
}
}
write!(fmt, ")")
},
- FalseEdges { .. } => write!(fmt, "falseEdges")
+ FalseEdges { .. } => write!(fmt, "falseEdges"),
+ FalseUnwind { .. } => write!(fmt, "falseUnwind"),
}
}
l.resize(imaginary_targets.len() + 1, "imaginary".into());
l
}
+ FalseUnwind { unwind: Some(_), .. } => vec!["real".into(), "cleanup".into()],
+ FalseUnwind { unwind: None, .. } => vec!["real".into()],
}
}
}
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`
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.
/// 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,
}
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,
Return |
GeneratorDrop |
Unreachable |
- FalseEdges { .. } => false
+ FalseEdges { .. } |
+ FalseUnwind { .. } => false
}
}
}
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)
})
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),
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
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);
+ }
+ }
}
}
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, .. } |
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 |
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,
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 {
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;
};
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
+ }
}
) }
"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,
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<String> = (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:
`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<bool> = (None, parse_opt_bool, [TRACKED],
+ "run `dsymutil` and delete intermediate object files"),
}
pub fn default_lib_output() -> CrateType {
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};
impl_dep_tracking_hash_via_hash!(cstore::NativeLibraryKind);
impl_dep_tracking_hash_via_hash!(Sanitizer);
impl_dep_tracking_hash_via_hash!(Option<Sanitizer>);
+ 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);
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};
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,
let emitter: Box<Emitter> = 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))
}
};
pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
let emitter: Box<Emitter> = 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);
pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
let emitter: Box<Emitter> = 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);
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.
pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>,
}
-/// 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<OverlapResult<'tcx>>
+/// 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={:?}, \
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>,
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>,
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 {
// 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()
}
.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();
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);
} 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,
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 {
fn report_arg_count_mismatch(
&self,
span: Span,
- found_span: Span,
+ found_span: Option<Span>,
expected_args: Vec<ArgKind>,
found_args: Vec<ArgKind>,
is_closure: bool,
);
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::<Vec<String>>().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::<Vec<String>>().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::<Vec<String>>()
- .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::<Vec<String>>()
- .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::<Vec<String>>()
+ .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::<Vec<String>>()
+ .join(", "))
+ } else {
+ "".to_owned()
+ },
+ );
+ err.span_suggestion(found_span,
+ "change the closure to accept a tuple instead of \
+ individual arguments",
+ sugg);
+ }
}
}
{
self.note_obligation_cause_code(err,
&obligation.predicate,
- &obligation.cause.code);
+ &obligation.cause.code,
+ &mut vec![]);
}
fn note_obligation_cause_code<T>(&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;
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");
}
}
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);
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(
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 {
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.
VariableType(ast::NodeId),
/// Return type must be Sized
SizedReturnType,
+ /// Yield type must be Sized
+ SizedYieldType,
/// [T,..n] --> T must be Copy
RepeatVec,
pub subcommands: Vec<OnUnimplementedDirective>,
pub message: Option<OnUnimplementedFormatString>,
pub label: Option<OnUnimplementedFormatString>,
+ pub note: Option<OnUnimplementedFormatString>,
}
pub struct OnUnimplementedNote {
pub message: Option<String>,
pub label: Option<String>,
+ pub note: Option<String>,
}
impl OnUnimplementedNote {
pub fn empty() -> Self {
- OnUnimplementedNote { message: None, label: None }
+ OnUnimplementedNote { message: None, label: None, note: None }
}
}
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() {
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) =
if errored {
Err(ErrorReported)
} else {
- Ok(OnUnimplementedDirective { condition, message, label, subcommands })
+ Ok(OnUnimplementedDirective { condition, message, label, subcommands, note })
}
}
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,
pub fn evaluate(&self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
trait_ref: ty::TraitRef<'tcx>,
- options: &[(&str, Option<&str>)])
+ options: &[(String, Option<String>)])
-> 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
}))
}) {
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)),
}
}
}
inferred_obligations: SnapshotVec<InferredObligationsSnapshotVecDelegate<'tcx>>,
- intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>,
+ intercrate_ambiguity_causes: Option<Vec<IntercrateAmbiguityCause>>,
}
-#[derive(Clone)]
+#[derive(Clone, Debug)]
pub enum IntercrateAmbiguityCause {
DownstreamCrate {
trait_desc: String,
freshener: infcx.freshener(),
intercrate: None,
inferred_obligations: SnapshotVec::new(),
- intercrate_ambiguity_causes: Vec::new(),
+ intercrate_ambiguity_causes: None,
}
}
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<IntercrateAmbiguityCause> {
+ assert!(self.intercrate.is_some());
+ self.intercrate_ambiguity_causes.take().unwrap_or(vec![])
+ }
+
pub fn infcx(&self) -> &'cx InferCtxt<'cx, 'gcx, 'tcx> {
self.infcx
}
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<R, F>(&mut self, f: F) -> R
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;
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);
}
};
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));
}
} else {
Ok((le, ge))
}
- } else {
- Ok((false, false))
- }
- })?;
+ },
+ || Ok((false, false)),
+ )?;
if le && !ge {
debug!("descending as child of TraitRef {:?}",
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 ?)
super::VariableType(id) => 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),
super::VariableType(_) |
super::ReturnType(_) |
super::SizedReturnType |
+ super::SizedYieldType |
super::ReturnNoExpression |
super::RepeatVec |
super::FieldSized(_) |
super::VariableType(_) |
super::ReturnType(_) |
super::SizedReturnType |
+ super::SizedYieldType |
super::ReturnNoExpression |
super::RepeatVec |
super::FieldSized(_) |
/// Go from a mut raw pointer to a const raw pointer.
MutToConstPointer,
- /// Dereference once, producing an lvalue.
+ /// Dereference once, producing a place.
Deref(Option<OverloadedDeref<'tcx>>),
/// Take the address and produce either a `&` or `*` pointer.
}
}
+#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)]
+pub enum AutoBorrowMutability {
+ Mutable { allow_two_phase_borrow: bool },
+ Immutable,
+}
+
+impl From<AutoBorrowMutability> 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),
}
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
};
}
-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);
}
};
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);
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
}))
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.
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))
}
}
- 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))?;
})
}
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 {
// 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::<Result<Vec<_>, _>>()?,
+ univariant(&tys.map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
&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::<Result<Vec<_>, _>>()?,
+ univariant(&tys.map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
&ReprOptions::default(),
StructKind::AlwaysSized)?
}
StructKind::MaybeUnsized
};
- univariant(&tys.iter().map(|ty| cx.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
+ univariant(&tys.iter().map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
&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 {
// 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::<Result<Vec<_>, _>>()
}).collect::<Result<Vec<_>, _>>()?;
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<T>.
- 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, _) => {
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
};
/// 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;
}
};
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);
}
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);
}
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));
}
}
}
-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()
}
}
fn layout_of(self, ty: T) -> Self::TyLayout;
}
-impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for (TyCtxt<'a, 'tcx, 'tcx>, ty::ParamEnv<'tcx>) {
+impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
type TyLayout = Result<TyLayout<'tcx>, 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
// 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<Ty<'tcx>> for (ty::maps::TyCtxtAt<'a, 'tcx, 'tcx>,
- ty::ParamEnv<'tcx>) {
+impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for LayoutCx<'tcx, ty::maps::TyCtxtAt<'a, 'tcx, 'tcx>> {
type TyLayout = Result<TyLayout<'tcx>, 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
// 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<TyLayout<'tcx>, 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<TyLayout<'tcx>, 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<C>(&self, cx: C, variant_index: usize) -> Self
where C: LayoutOf<Ty<'tcx>> + HasTyCtxt<'tcx>,
-> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>),
[] fn export_name: ExportName(DefId) -> Option<Symbol>,
[] 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<CodegenUnit<'tcx>>,
[] fn compile_codegen_unit: CompileCodegenUnit(InternedString) -> Stats,
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
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};
}
}
-#[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 {
}
}
- 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<AssociatedItem> {
self.associated_items(id)
.filter(|item| item.kind == AssociatedKind::Method && item.defaultness.has_value())
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<Item=Ty<'tcx>> + '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<Item=Ty<'tcx>> + '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))
}
}
///
/// 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<TypeAndMut<'tcx>>
- {
+ pub fn builtin_deref(&self, explicit: bool) -> Option<TypeAndMut<'tcx>> {
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),
#![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;
pub type NodeMap<T> = FxHashMap<ast::NodeId, T>;
pub type DefIdMap<T> = FxHashMap<DefId, T>;
+pub type HirIdMap<T> = FxHashMap<HirId, T>;
pub type ItemLocalMap<T> = FxHashMap<ItemLocalId, T>;
pub type NodeSet = FxHashSet<ast::NodeId>;
pub type DefIdSet = FxHashSet<DefId>;
+pub type HirIdSet = FxHashSet<HirId>;
pub type ItemLocalSet = FxHashSet<ItemLocalId>;
pub fn NodeMap<T>() -> NodeMap<T> { FxHashMap() }
/// 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 {
no_builtins: false,
i128_lowering: false,
codegen_backend: "llvm".to_string(),
+ default_hidden_visibility: false,
}
}
}
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()) {
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()
// 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( )
}
})
// performing LTO with compiler-builtins.
no_builtins: true,
+ // no dynamic linking, no need for default visibility!
+ default_hidden_visibility: true,
+
.. Default::default()
};
Ok(Target {
#include <stdint.h>
#include <string>
+#include <sstream>
#include <stdlib.h>
#include "s2wasm.h"
struct BinaryenRustModule {
BufferWithRandomAccess buffer;
+ std::string sourceMapJSON;
};
struct BinaryenRustModuleOptions {
bool ignoreUnknownSymbols;
bool debugInfo;
std::string startFunction;
+ std::string sourceMapUrl;
BinaryenRustModuleOptions() :
globalBase(0),
importMemory(false),
ignoreUnknownSymbols(false),
debugInfo(false),
- startFunction("")
+ startFunction(""),
+ sourceMapUrl("")
{}
};
options->startFunction = start;
}
+extern "C" void
+BinaryenRustModuleOptionsSetSourceMapUrl(BinaryenRustModuleOptions *options,
+ char *sourceMapUrl) {
+ options->sourceMapUrl = sourceMapUrl;
+}
+
extern "C" void
BinaryenRustModuleOptionsSetStackAllocation(BinaryenRustModuleOptions *options,
uint64_t stack) {
{
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<std::ostringstream> sourceMapStream = nullptr;
+ {
+ sourceMapStream = make_unique<std::ostringstream>();
+ writer.setSourceMap(sourceMapStream.get(), options->sourceMapUrl);
+ }
// FIXME: support symbol maps?
// writer.setSymbolMap(symbolMap);
writer.write();
+
+ if (sourceMapStream) {
+ ret->sourceMapJSON = sourceMapStream->str();
+ }
}
return ret.release();
}
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;
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 {
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 {
-> *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()
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,
# 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
```
and a variable `a: Box<S>`, 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:
#### 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
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.
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.
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`.
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<Ty>
- MUTABILITY(LV, MQ)
+MUTABILITY(*P, MQ) // M-Deref-Unique
+ TYPE(P) = Box<Ty>
+ MUTABILITY(P, MQ)
```
### Checking mutability of immutable pointer types
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
`&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`.
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
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
`&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`.
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<Ty>
- LIFETIME(LV, LT, MQ)
+LIFETIME(*P, LT, MQ) // L-Deref-Send
+ TYPE(P) = Box<Ty>
+ LIFETIME(P, LT, MQ)
```
### Checking lifetime for derefs of references
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'
```
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,
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,
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<Ty>
- RESTRICTIONS(LV, LT, ACTIONS|MUTATE|CLAIM) = RS
+RESTRICTIONS(*P, LT, ACTIONS) = RS, (*P, ACTIONS) // R-Deref-Send-Pointer
+ TYPE(P) = Box<Ty>
+ RESTRICTIONS(P, LT, ACTIONS|MUTATE|CLAIM) = RS
```
### Restrictions for loans of immutable borrowed referents
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]
```
(`*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()`?
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:
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.
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:
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
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 {
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;
}
// 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 }}`
};
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 {
/// 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,
}
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.
}
}
+
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");
}
}
}
+
+ fn span_e0158(&self, span: Span, text: &str) {
+ span_err!(self.tcx.sess, span, E0158, "{}", text)
+ }
}
impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
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;
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) }
})
};
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)
}
}
#[derive(Clone, Debug)]
pub enum PatternError<'tcx> {
+ AssociatedConstInPattern(Span),
StaticInPattern(Span),
ConstEval(ConstEvalErr<'tcx>),
}
BindingMode::ByValue => mutability == Mutability::Mut,
BindingMode::ByRef(_, bk) => {
write!(f, "ref ")?;
- bk == BorrowKind::Mut
+ match bk { BorrowKind::Mut { .. } => true, _ => false }
}
};
if is_mut {
(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)),
-> 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);
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
}
}
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());
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T1, T2>(from: &[T1], to: &mut [T2], byte_count: usize) {
- let from_size = from.len() * mem::size_of::<T1>();
- let to_size = to.len() * mem::size_of::<T2>();
- 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]);
- }
-}
pub mod base_n;
pub mod bitslice;
pub mod bitvec;
-pub mod blake2b;
pub mod graph;
pub mod indexed_set;
pub mod indexed_vec;
pub mod unify;
pub mod fx;
pub mod tuple_slice;
-pub mod veccell;
pub mod control_flow_graph;
pub mod flock;
pub mod sync;
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T> {
- data: UnsafeCell<Vec<T>>,
-}
-
-impl<T> VecCell<T> {
- pub fn with_capacity(capacity: usize) -> VecCell<T> {
- 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<T>) -> Vec<T> {
- unsafe {
- let v = self.data.get();
- mem::swap(&mut *v, &mut data);
- }
- data
- }
-}
};
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,
)?
};
- 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
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<PathBuf> {
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
);
}
}
}
+ 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<F, T>(output_paths: &Vec<PathBuf>, f: F) -> Option<T>
+ where F: Fn(&PathBuf) -> Option<T> {
+ 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<PathBuf>, 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<PathBuf>) -> Option<PathBuf> {
+ 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<PathBuf>) {
// Write out dependency rules to the dep-info file if requested
if !sess.opts.output_types.contains_key(&OutputType::DepInfo) {
return;
.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(" "))?;
}
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("");
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)",
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());
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),
},
};
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));
}
// Extract input (string or file and optional path) from matches.
-fn make_input(free_matches: &[String]) -> Option<(Input, Option<PathBuf>)> {
+fn make_input(free_matches: &[String]) -> Option<(Input, Option<PathBuf>, Option<io::Error>)> {
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
let emitter =
Box::new(errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto,
None,
+ false,
false));
let handler = errors::Handler::with_emitter(true, false, emitter);
}],
msg: msg.to_owned(),
show_code_when_inline: false,
+ approximate: false,
});
self
}
}],
msg: msg.to_owned(),
show_code_when_inline: true,
+ approximate: false,
});
self
}
}).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<String>) -> &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
}
msg: &str,
suggestions: Vec<String>)
-> &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<String>)
+ -> &mut Self);
forward!(pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self);
forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self);
dst: Destination,
cm: Option<Rc<CodeMapper>>,
short_message: bool,
+ teach: bool,
}
struct FileWithAnnotatedLines {
impl EmitterWriter {
pub fn stderr(color_config: ColorConfig,
code_map: Option<Rc<CodeMapper>>,
- 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<Write + Send>,
code_map: Option<Rc<CodeMapper>>,
- short_message: bool)
+ short_message: bool,
+ teach: bool)
-> EmitterWriter {
EmitterWriter {
dst: Raw(dst),
cm: code_map,
- short_message: short_message,
+ short_message,
+ teach,
}
}
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(),
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);
+ }
+ _ => {}
}
}
// 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);
pub substitutions: Vec<Substitution>,
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)]
cm: Option<Rc<CodeMapper>>,
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)
}
// Code for annotating snippets.
-use syntax_pos::{Span, FileMap};
-use CodeMapper;
-use std::rc::Rc;
use Level;
-#[derive(Clone)]
-pub struct SnippetData {
- codemap: Rc<CodeMapper>,
- files: Vec<FileInfo>,
-}
-
-#[derive(Clone)]
-pub struct FileInfo {
- file: Rc<FileMap>,
-
- /// 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<Span>,
-
- lines: Vec<Line>,
-}
-
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub struct Line {
pub line_index: usize,
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;
+ }
+ }
+ }
+ }
}
// 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 {
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);
}
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);
}
"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,
Origin::Mir,
),
- (BorrowKind::Mut, _, _, BorrowKind::Mut, _, _) => self.tcx
+ (BorrowKind::Mut { .. }, _, _, BorrowKind::Mut { .. }, _, _) => self.tcx
.cannot_mutably_borrow_multiply(
span,
&desc_place,
Origin::Mir,
),
- (BorrowKind::Mut, _, lft, BorrowKind::Unique, _, _) => self.tcx
+ (BorrowKind::Mut { .. }, _, lft, BorrowKind::Unique, _, _) => self.tcx
.cannot_reborrow_already_uniquely_borrowed(
span,
&desc_place,
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({:?}): <suppressed>",
- (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({:?}): <suppressed>",
- (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(
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()
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;
// (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<ActiveBorrows<'b, 'gcx, 'tcx>>,
- pub inits: FlowAtLocation<MaybeInitializedLvals<'b, 'gcx, 'tcx>>,
- pub uninits: FlowAtLocation<MaybeUninitializedLvals<'b, 'gcx, 'tcx>>,
+ pub inits: FlowAtLocation<MaybeInitializedPlaces<'b, 'gcx, 'tcx>>,
+ pub uninits: FlowAtLocation<MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
pub move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
- pub ever_inits: FlowAtLocation<EverInitializedLvals<'b, 'gcx, 'tcx>>,
+ pub ever_inits: FlowAtLocation<EverInitializedPlaces<'b, 'gcx, 'tcx>>,
}
impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> {
pub fn new(
borrows: FlowAtLocation<ActiveBorrows<'b, 'gcx, 'tcx>>,
- inits: FlowAtLocation<MaybeInitializedLvals<'b, 'gcx, 'tcx>>,
- uninits: FlowAtLocation<MaybeUninitializedLvals<'b, 'gcx, 'tcx>>,
+ inits: FlowAtLocation<MaybeInitializedPlaces<'b, 'gcx, 'tcx>>,
+ uninits: FlowAtLocation<MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
- ever_inits: FlowAtLocation<EverInitializedLvals<'b, 'gcx, 'tcx>>,
+ ever_inits: FlowAtLocation<EverInitializedPlaces<'b, 'gcx, 'tcx>>,
) -> Self {
Flows {
borrows,
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;
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;
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(
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(
id,
&attributes,
&dead_unwinds,
- EverInitializedLvals::new(tcx, mir, &mdpe),
+ EverInitializedPlaces::new(tcx, mir, &mdpe),
|bd, i| DebugFormatted::new(&bd.move_data().inits[i]),
));
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(),
};
/// 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<Local>,
- /// Same as the above, but for statics (thread-locals)
- storage_dead_or_drop_error_reported_s: FxHashSet<DefId>,
+ /// 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
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),
JustWrite,
flow_state,
);
-
- self.consume_rvalue(
- ContextKind::AssignRhs.new(location),
- (rhs, span),
- location,
- flow_state,
- );
}
StatementKind::SetDiscriminant {
ref place,
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
}
}
#[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`."
}
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
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,
}
}
+ 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,
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;
}
}
(Reservation(kind), BorrowKind::Unique)
- | (Reservation(kind), BorrowKind::Mut)
+ | (Reservation(kind), BorrowKind::Mut { .. })
| (Activation(kind, _), _)
| (Write(kind), _) => {
match rw {
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 {
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))
// mutable borrow before we check it.
match borrow.kind {
BorrowKind::Shared => return,
- BorrowKind::Unique | BorrowKind::Mut => {}
+ BorrowKind::Unique | BorrowKind::Mut { .. } => {}
}
self.access_place(
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;
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
}
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;
universal_regions: UniversalRegions<'tcx>,
mir: &Mir<'tcx>,
param_env: ty::ParamEnv<'gcx>,
- flow_inits: &mut FlowAtLocation<MaybeInitializedLvals<'cx, 'gcx, 'tcx>>,
+ flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'cx, 'gcx, 'tcx>>,
move_data: &MoveData<'tcx>,
) -> (
RegionInferenceContext<'tcx>,
&substs[..]
));
}
- DefiningTy::Const(ty) => {
+ DefiningTy::Const(def_id, substs) => {
err.note(&format!(
- "defining type: {:?}",
- ty
+ "defining constant type: {:?} with substs {:#?}",
+ def_id,
+ &substs[..]
));
}
}
// 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;
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;
/// 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();
// 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<RegionVid, Vec<usize>> {
+ 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:
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;
cx: &mut TypeChecker<'_, 'gcx, 'tcx>,
mir: &Mir<'tcx>,
liveness: &LivenessResults,
- flow_inits: &mut FlowAtLocation<MaybeInitializedLvals<'_, 'gcx, 'tcx>>,
+ flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
move_data: &MoveData<'tcx>,
) {
let tcx = cx.tcx();
tcx: TyCtxt<'typeck, 'gcx, 'tcx>,
mir: &'gen Mir<'tcx>,
liveness: &'gen LivenessResults,
- flow_inits: &'gen mut FlowAtLocation<MaybeInitializedLvals<'flow, 'gcx, 'tcx>>,
+ flow_inits: &'gen mut FlowAtLocation<MaybeInitializedPlaces<'flow, 'gcx, 'tcx>>,
move_data: &'gen MoveData<'tcx>,
}
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);
}
}
}
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};
mir_def_id: DefId,
universal_regions: &UniversalRegions<'tcx>,
liveness: &LivenessResults,
- flow_inits: &mut FlowAtLocation<MaybeInitializedLvals<'_, 'gcx, 'tcx>>,
+ flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
move_data: &MoveData<'tcx>,
) -> MirTypeckRegionConstraints<'tcx> {
let body_id = infcx.tcx.hir.as_local_node_id(mir_def_id).unwrap();
}
};
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
}
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)
}
}
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(),
}),
};
}
| TerminatorKind::GeneratorDrop
| TerminatorKind::Unreachable
| TerminatorKind::Drop { .. }
- | TerminatorKind::FalseEdges { .. } => {
+ | TerminatorKind::FalseEdges { .. }
+ | TerminatorKind::FalseUnwind { .. } => {
// no checks needed for these
}
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);
+ }
+ }
}
}
}
}
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(),
}),
}
}
/// 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)]
/// 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)
+ }
}
}
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));
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)))
+ }
}
}
// 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(),
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();
// 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
-> 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())
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);
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,
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Local>) {
+ // Nothing is borrowed on function entry
+ }
+
+ fn statement_effect(&self,
+ sets: &mut BlockSets<Local>,
+ loc: Location) {
+ BorrowedLocalsVisitor {
+ sets,
+ }.visit_statement(loc.block, &self.mir[loc.block].statements[loc.statement_index], loc);
+ }
+
+ fn terminator_effect(&self,
+ sets: &mut BlockSets<Local>,
+ loc: Location) {
+ BorrowedLocalsVisitor {
+ sets,
+ }.visit_terminator(loc.block, self.mir[loc.block].terminator(), loc);
+ }
+
+ fn propagate_call_return(&self,
+ _in_out: &mut IdxSet<Local>,
+ _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<Local> {
+ 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)
+ }
+}
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 };
// 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
mir::TerminatorKind::Yield {..} |
mir::TerminatorKind::Goto {..} |
mir::TerminatorKind::FalseEdges {..} |
+ mir::TerminatorKind::FalseUnwind {..} |
mir::TerminatorKind::Unreachable => {}
}
}
/// 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
// 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 |
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.
///
/// }
/// ```
///
-/// 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.
///
/// }
/// ```
///
-/// 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.
///
/// }
/// ```
///
-/// 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.
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`.
///
/// 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<MovePathIndex>, path: MovePathIndex,
state: DropFlagState)
{
}
}
-impl<'a, 'gcx, 'tcx> MaybeUninitializedLvals<'a, 'gcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> MaybeUninitializedPlaces<'a, 'gcx, 'tcx> {
fn update_bits(sets: &mut BlockSets<MovePathIndex>, path: MovePathIndex,
state: DropFlagState)
{
}
}
-impl<'a, 'gcx, 'tcx> DefinitelyInitializedLvals<'a, 'gcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> {
fn update_bits(sets: &mut BlockSets<MovePathIndex>, path: MovePathIndex,
state: DropFlagState)
{
}
}
-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 {
}
}
-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 {
}
}
-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 {
}
}
-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 {
}
}
-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
}
}
-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
// 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)
}
}
-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
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::*;
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);
+ }
+ }
+ }
}
}
TerminatorKind::Abort |
TerminatorKind::GeneratorDrop |
TerminatorKind::FalseEdges { .. } |
+ TerminatorKind::FalseUnwind { .. } |
TerminatorKind::Unreachable => { }
TerminatorKind::Return => {
/// 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,
}
}
-/// 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<Local, MovePathIndex>,
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 {
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>;
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(),
},
};
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(),
}
}
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() }
};
ExprKind::Borrow {
region,
- borrow_kind: to_borrow_kind(mutbl),
+ borrow_kind: mutbl.to_borrow_kind(),
arg: expr.to_ref(),
}
}
}
}
-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,
+ }
}
}
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,
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()),
}
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())
}
}
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 {
#[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,
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 },
}
}
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())
}
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),
}
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);
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};
.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 {
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
}
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
};
{
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::<Vec<_>>(),
- 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)
}
}
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);
})
}
+ /// 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(),
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(
})
);
- 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)
)
);
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(
}
}
- 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;`
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),
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;`
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);
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<I>(&mut self, dest: Place<'tcx>,
+ src: Place<'tcx>, tys: I)
+ where I: Iterator<Item = ty::Ty<'tcx>> {
+ 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);
}
}
}),
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))
TerminatorKind::Abort |
TerminatorKind::Return |
TerminatorKind::Unreachable |
- TerminatorKind::FalseEdges { .. } => {
+ TerminatorKind::FalseEdges { .. } |
+ TerminatorKind::FalseUnwind { .. } => {
// safe (at least as emitted during MIR construction)
}
// 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};
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 {
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 {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
mir: &'a Mir<'tcx>,
env: &'a MoveDataParamEnv<'tcx, 'tcx>,
- flow_inits: DataflowResults<MaybeInitializedLvals<'a, 'tcx, 'tcx>>,
- flow_uninits: DataflowResults<MaybeUninitializedLvals<'a, 'tcx, 'tcx>>,
+ flow_inits: DataflowResults<MaybeInitializedPlaces<'a, 'tcx, 'tcx>>,
+ flow_uninits: DataflowResults<MaybeUninitializedPlaces<'a, 'tcx, 'tcx>>,
drop_flags: FxHashMap<MovePathIndex, Local>,
patch: MirPatch<'tcx>,
}
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;
HashMap<BasicBlock, liveness::LocalSet>) {
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,
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
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;
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);
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);
fn type_size_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>) -> Option<u64> {
- (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>(
*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")
}
}
/// 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> {
_ => 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!()
}
}
(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)
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;
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};
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();
}
}
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();
}
}
TerminatorKind::GeneratorDrop |
TerminatorKind::Yield { .. } |
TerminatorKind::Unreachable |
- TerminatorKind::FalseEdges { .. } => None,
+ TerminatorKind::FalseEdges { .. } |
+ TerminatorKind::FalseUnwind { .. } => None,
TerminatorKind::Return => {
// Check for unused values. This usually means
_ => {}
}
}
- Candidate::ShuffleIndices(_) => {}
+ Candidate::Argument { .. } => {}
}
}
}
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) => {
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();
}
}
}
}
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.
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 {
(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();
}
}
_ => {}
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();
}
}
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;
}
}
+ 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));
}
});
}
// 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;
}
}
}
}
}
+
+fn args_required_const(tcx: TyCtxt, def_id: DefId) -> Option<FxHashSet<usize>> {
+ 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)
+}
TerminatorKind::Goto { .. } |
TerminatorKind::Resume |
TerminatorKind::SwitchInt { .. } |
- TerminatorKind::FalseEdges { .. } => {
+ TerminatorKind::FalseEdges { .. } |
+ TerminatorKind::FalseUnwind { .. } => {
terminator.successors().iter().all(|succ| {
nop_landing_pads.contains(succ.index())
})
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;
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() {
TerminatorKind::FalseEdges { real_target, .. } => {
TerminatorKind::Goto { target: real_target }
},
+ TerminatorKind::FalseUnwind { real_target, .. } => {
+ TerminatorKind::Goto { target: real_target }
+ },
_ => continue
};
}
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 {
/// ptr = cur
/// cur = cur.offset(1)
/// } else {
- /// ptr = &mut LV[cur]
+ /// ptr = &mut P[cur]
/// cur = cur + 1
/// }
/// drop(ptr)
} 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))
};
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
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) => {}
}
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();
}
}
TerminatorKind::GeneratorDrop => "TerminatorKind::GeneratorDrop",
TerminatorKind::Yield { .. } => "TerminatorKind::Yield",
TerminatorKind::FalseEdges { .. } => "TerminatorKind::FalseEdges",
+ TerminatorKind::FalseUnwind { .. } => "TerminatorKind::FalseUnwind",
}, kind);
self.super_terminator_kind(block, kind, location);
}
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);
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
}
}
}
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"
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 {
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};
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);
+ }
}
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;
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;
analysis: &'l ty::CrateAnalysis,
span_utils: SpanUtils<'tcx>,
config: Config,
+ impl_counter: Cell<u32>,
}
#[derive(Debug)]
pub enum Data {
RefData(Ref),
DefData(Def),
- RelationData(Relation),
+ RelationData(Relation, Impl),
}
impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
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) {
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 {
field_ref: &ast::Field,
variant: &ty::VariantDef,
) -> Option<Ref> {
- 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);
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');
+ });
}
}
}
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 {
analysis,
span_utils: SpanUtils::new(&tcx.sess),
config: find_config(config),
+ impl_counter: Cell::new(0),
};
handler.save(save_ctxt, krate, cratename)
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)
_ => 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;
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(),
// 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 =
// 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);
}
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
// 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)),
Arc::new(local_crate)
};
+
+ providers.symbol_export_level = export_level;
}
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 {
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 {
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| {
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| {
.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));
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,
};
None => 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) => {
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)
// 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",
TerminatorKind::Unreachable |
TerminatorKind::SwitchInt { .. } |
TerminatorKind::Yield { .. } |
- TerminatorKind::FalseEdges { .. } => {
+ TerminatorKind::FalseEdges { .. } |
+ TerminatorKind::FalseUnwind { .. } => {
/* nothing to do */
}
TerminatorKind::Call { cleanup: unwind, .. } |
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"),
}
}
Static(ValueRef)
}
-/// An place as seen from a constant.
+/// A place as seen from a constant.
#[derive(Copy, Clone)]
struct ConstPlace<'tcx> {
base: Base,
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) {
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)
}
_ => {
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
(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);
} 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")
// 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;
}
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()),
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))
}
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);
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;
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;
}
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<SomeTrait>", 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
}
}
});
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
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
})
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();
}
}
use astconv::AstConv;
-use super::{FnCtxt, LvalueOp};
+use super::{FnCtxt, PlaceOp, Needs};
use super::method::MethodCallee;
use rustc::infer::InferOk;
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;
// 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)?;
}
/// Returns the adjustment steps.
- pub fn adjust_steps(&self, pref: LvaluePreference)
+ pub fn adjust_steps(&self, needs: Needs)
-> Vec<Adjustment<'tcx>> {
- 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<Adjustment<'tcx>>> {
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 {
pub fn try_overloaded_deref(&self,
span: Span,
base_ty: Ty<'tcx>,
- pref: LvaluePreference)
+ needs: Needs)
-> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
- self.try_overloaded_lvalue_op(span, base_ty, &[], pref, LvalueOp::Deref)
+ self.try_overloaded_place_op(span, base_ty, &[], needs, PlaceOp::Deref)
}
}
// 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;
// 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));
}
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,
}
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)
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]
});
}
//! 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;
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;
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());
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
});
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
] => {
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.
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,
check_region_bounds_on_impl_method(tcx,
impl_m_span,
impl_m,
+ trait_m,
&trait_m_generics,
&impl_m_generics,
trait_to_skol_substs)?;
};
let mut diag = struct_span_err!(tcx.sess,
- cause.span,
+ cause.span(&tcx),
E0053,
"method `{}` has an incompatible type for trait",
trait_m.name);
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[..];
// 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);
}
}).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 { .. }) => {
{
(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)),
}
}
}
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) {
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;
};
if let Some(hir::MutMutable) = pick.autoref {
- self.convert_lvalue_derefs_to_mutable();
+ self.convert_place_derefs_to_mutable();
}
ConfirmResult { callee, illegal_sized_bound }
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();
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
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 {
/// 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);
}
}
- 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,
.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 {
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
}
.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
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;
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);
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;
}
}
+#[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,
}
#[derive(Debug, Copy, Clone)]
-pub enum LvalueOp {
+pub enum PlaceOp {
Deref,
Index
}
/// 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
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);
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);
}
}
- /// 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>
{
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,
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
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
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>)>
{
// 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
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;
None
}
- fn resolve_lvalue_op(&self, op: LvalueOp, is_mut: bool) -> (Option<DefId>, Symbol) {
+ fn resolve_place_op(&self, op: PlaceOp, is_mut: bool) -> (Option<DefId>, 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<InferOk<'tcx, MethodCallee<'tcx>>>
{
- 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))
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)
}
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
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,
// Check field access expressions
fn check_field(&self,
expr: &'gcx hir::Expr,
- lvalue_pref: LvaluePreference,
+ needs: Needs,
base: &'gcx hir::Expr,
field: &Spanned<ast::Name>) -> 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;
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();
// 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<usize>) -> 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;
};
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;
/// 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);
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 {
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 {
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,
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)
_ => 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() {
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);
_ => {
// 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")
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,
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() {
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
// 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 {
}
}
+ self.check_rustc_args_require_const(def.def_id(), node_id, span);
+
debug!("instantiate_value_path: type of {:?} is {:?}",
node_id,
ty_substituted);
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,
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 {
//! 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;
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,
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
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]);
}
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
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) => {
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,
+ ),
+ || (),
+ );
}
}
}
}
}
-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);
}
}
}
},
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);
"##,
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.
```compile_fail,E0067
use std::collections::LinkedList;
-// Bad: assignment to non-lvalue expression
+// Bad: assignment to non-place expression
LinkedList::new() += 1;
// ...
"##,
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:
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!
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! {
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) =
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 {
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()
}
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
let link_out = format!("<a href=\"{link}\"{title}>{content}</a>",
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()); }
// 2 for "In Return Types"
var currentTab = 0;
+ var themesWidth = null;
+
function hasClass(elem, className) {
if (elem && className && elem.className) {
var elemClass = elem.className;
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";
}
}
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;
}
}
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;
border: none;
}
-.location a:first-child { font-weight: 500; }
+.location a:first-child {
+ font-weight: 500;
+}
.block {
padding: 0;
-ms-user-select: none;
user-select: none;
}
-.line-numbers span { cursor: pointer; }
+.line-numbers span {
+ cursor: pointer;
+}
.docblock-short p {
display: inline;
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;
display: inline-block;
}
-#main { position: relative; }
+#main {
+ position: relative;
+}
#main > .since {
top: inherit;
font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
padding: 0;
}
-.content .item-list li { margin-bottom: 1em; }
+.content .item-list li {
+ margin-bottom: 1em;
+}
.content .multi-column {
-moz-column-count: 5;
display: block;
border-bottom: 1px solid;
border-right: 1px solid;
+ height: 45px;
}
.sidebar-elems {
}
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%;
}
.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
@media (max-width: 700px) {
.theme-picker {
- left: 109px;
- top: 7px;
+ left: 10px;
+ top: 54px;
z-index: 1;
}
}
}
.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; }
.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; }
@media (max-width: 700px) {
#theme-picker {
- background: #353535;
+ background: #f0f0f0;
}
}
.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; }
pub mod visit_ast;
pub mod visit_lib;
pub mod test;
+pub mod theme;
use clean::AttributesExt;
"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")
+ }),
]
}
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;
}
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(
));
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()));
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<CssPath>,
+}
+
+// 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<H: Hasher>(&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<Events> {
+ 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<Events> {
+ 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<usize> {
+ 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::<String>()
+ .trim()
+ .replace("\n", " ")
+ .replace("/", "")
+ .replace("\t", " ")
+ .replace("{", "")
+ .replace("}", "")
+ .split(" ")
+ .filter(|s| s.len() > 0)
+ .collect::<Vec<&str>>()
+ .join(" ")
+}
+
+fn inner(v: &[u8], events: &[Events], pos: &mut usize) -> HashSet<CssPath> {
+ 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<String>) {
+ 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<P: AsRef<Path>>(f: &P, against: &CssPath) -> (bool, Vec<String>) {
+ 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()]);
+ }
+}
force_alloc_system = []
panic-unwind = ["panic_unwind"]
profiler = ["profiler_builtins"]
+wasm_syscall = []
{
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")
}
}
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]
/// 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
///
/// 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
///
/// 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
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(())
/// # }
/// ```
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.
/// # 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);
/// # }
/// ```
///
/// # 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")]
#![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)]
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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::<libc::$t>() == TypeId::of::<raw::$t>(),
- "{} 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);
- }
-}
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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::<libc::$t>() == TypeId::of::<raw::$t>(),
+ "{} 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);
+ }
+}
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *mut T {}
#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: UnwindSafe + ?Sized> UnwindSafe for Unique<T> {}
-#[stable(feature = "nonnull", since = "1.24.0")]
+#[stable(feature = "nonnull", since = "1.25.0")]
impl<T: RefUnwindSafe + ?Sized> UnwindSafe for NonNull<T> {}
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T: ?Sized> UnwindSafe for Mutex<T> {}
}
assert!(events > 0);
}
+
+ #[test]
+ fn test_command_implements_send() {
+ fn take_send_type<T: Send>(_: T) {}
+ take_send_type(Command::new(""))
+ }
}
#[cfg_attr(test, allow(dead_code))]
pub mod guard {
- pub unsafe fn current() -> Option<usize> {
+ pub type Guard = !;
+ pub unsafe fn current() -> Option<Guard> {
None
}
- pub unsafe fn init() -> Option<usize> {
+ pub unsafe fn init() -> Option<Guard> {
None
}
}
}
pub mod guard {
- pub unsafe fn current() -> Option<usize> { None }
- pub unsafe fn init() -> Option<usize> { None }
+ pub type Guard = !;
+ pub unsafe fn current() -> Option<Guard> { None }
+ pub unsafe fn init() -> Option<Guard> { None }
}
// other keys.
program: CString,
args: Vec<CString>,
- argv: Vec<*const c_char>,
+ argv: Argv,
env: CommandEnv<DefaultEnvKey>,
cwd: Option<CString>,
stderr: Option<Stdio>,
}
+// 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 {
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(),
// 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.
self.saw_nul
}
pub fn get_argv(&self) -> &Vec<*const c_char> {
- &self.argv
+ &self.argv.0
}
#[allow(dead_code)]
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)]
_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 {
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;
not(target_os = "solaris")))]
#[cfg_attr(test, allow(dead_code))]
pub mod guard {
- pub unsafe fn current() -> Option<usize> { None }
- pub unsafe fn init() -> Option<usize> { None }
+ use ops::Range;
+ pub type Guard = Range<usize>;
+ pub unsafe fn current() -> Option<Guard> { None }
+ pub unsafe fn init() -> Option<Guard> { None }
}
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<usize>;
+
+ #[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",
ret
}
- pub unsafe fn init() -> Option<usize> {
- let psize = os::page_size();
+ pub unsafe fn init() -> Option<Guard> {
+ PAGE_SIZE = os::page_size();
+
let mut stackaddr = get_stack_start()?;
// Ensure stackaddr is page aligned! A parent process might
// 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;
}
// 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<usize> {
- 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<usize> {
- 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<usize> {
- 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<Guard> {
+ 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<usize> {
+ pub unsafe fn current() -> Option<Guard> {
let mut ret = None;
let mut attr: libc::pthread_attr_t = ::mem::zeroed();
assert_eq!(libc::pthread_attr_init(&mut attr), 0);
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);
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
}
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::<Vec<u8>, 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,
}
}
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")]
}
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
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<E, F: FnMut(&mut [u8]) -> Result<usize, E>>(estimate: usize, mut f: F)
+ -> Result<Vec<u8>, 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<OsString> {
+ receive_buffer(1024, |buffer| -> Result<usize, !> {
+ 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<OsString> {
+ 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<T>(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
+}
// 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
}
pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> {
- // 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 {
}
pub fn exit(_code: i32) -> ! {
- unsafe { intrinsics::abort() }
+ ExitSysCall::perform(_code as isize as usize)
}
pub fn getpid() -> u32 {
// 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<Stdin> {
- unsupported()
+ Ok(Stdin)
}
- pub fn read(&self, _data: &mut [u8]) -> io::Result<usize> {
- match self.0 {}
+ pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
+ Ok(ReadSysCall::perform(0, data))
}
}
}
pub fn write(&self, data: &[u8]) -> io::Result<usize> {
- // 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())
}
}
pub fn write(&self, data: &[u8]) -> io::Result<usize> {
- // 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())
}
}
pub mod guard {
- pub unsafe fn current() -> Option<usize> { None }
- pub unsafe fn init() -> Option<usize> { None }
+ pub type Guard = !;
+ pub unsafe fn current() -> Option<Guard> { None }
+ pub unsafe fn init() -> Option<Guard> { None }
}
// 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<Duration, Duration> {
- 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)
}
}
#[cfg_attr(test, allow(dead_code))]
pub mod guard {
- pub unsafe fn current() -> Option<usize> { None }
- pub unsafe fn init() -> Option<usize> { None }
+ pub type Guard = !;
+ pub unsafe fn current() -> Option<Guard> { None }
+ pub unsafe fn init() -> Option<Guard> { None }
}
#![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<usize>,
+ stack_guard: Option<Guard>,
thread: Thread,
}
ThreadInfo::with(|info| info.thread.clone())
}
-pub fn stack_guard() -> Option<usize> {
- ThreadInfo::with(|info| info.stack_guard).and_then(|o| o)
+pub fn stack_guard() -> Option<Guard> {
+ ThreadInfo::with(|info| info.stack_guard.clone()).and_then(|o| o)
}
-pub fn set(stack_guard: Option<usize>, thread: Thread) {
+pub fn set(stack_guard: Option<Guard>, thread: Thread) {
THREAD_INFO.with(|c| assert!(c.borrow().is_none()));
THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{
stack_guard,
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Duration> 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<Duration> for Instant {
+ fn add_assign(&mut self, other: Duration) {
+ *self = *self + other;
+ }
+}
+
+#[stable(feature = "time2", since = "1.8.0")]
+impl Sub<Duration> 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<Duration> for Instant {
+ fn sub_assign(&mut self, other: Duration) {
+ *self = *self - other;
+ }
+}
+
+#[stable(feature = "time2", since = "1.8.0")]
+impl Sub<Instant> 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<Duration, SystemTimeError> {
+ 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<Duration, SystemTimeError> {
+ SystemTime::now().duration_since(*self)
+ }
+}
+
+#[stable(feature = "time2", since = "1.8.0")]
+impl Add<Duration> 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<Duration> for SystemTime {
+ fn add_assign(&mut self, other: Duration) {
+ *self = *self + other;
+ }
+}
+
+#[stable(feature = "time2", since = "1.8.0")]
+impl Sub<Duration> 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<Duration> 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<time::SystemTime> 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);
+ }
+}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Duration> {
- 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<Duration> {
- 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<Duration> {
- // 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<Duration> {
- 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<u32> 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<u32> for Duration {
- fn mul_assign(&mut self, rhs: u32) {
- *self = *self * rhs;
- }
-}
-
-#[stable(feature = "duration", since = "1.3.0")]
-impl Div<u32> 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<u32> 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<I: Iterator<Item=Duration>>(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<I: Iterator<Item=&'a Duration>>(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);
- }
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Duration> 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<Duration> for Instant {
- fn add_assign(&mut self, other: Duration) {
- *self = *self + other;
- }
-}
-
-#[stable(feature = "time2", since = "1.8.0")]
-impl Sub<Duration> 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<Duration> for Instant {
- fn sub_assign(&mut self, other: Duration) {
- *self = *self - other;
- }
-}
-
-#[stable(feature = "time2", since = "1.8.0")]
-impl Sub<Instant> 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<Duration, SystemTimeError> {
- 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<Duration, SystemTimeError> {
- SystemTime::now().duration_since(*self)
- }
-}
-
-#[stable(feature = "time2", since = "1.8.0")]
-impl Add<Duration> 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<Duration> for SystemTime {
- fn add_assign(&mut self, other: Duration) {
- *self = *self + other;
- }
-}
-
-#[stable(feature = "time2", since = "1.8.0")]
-impl Sub<Duration> 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<Duration> 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<time::SystemTime> 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);
- }
-}
pub pats: Vec<P<Pat>>,
pub guard: Option<P<Expr>>,
pub body: P<Expr>,
- pub beginning_vert: Option<Span>, // For RFC 1925 feature gate
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
}
}
- /// 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) {
pats,
guard: None,
body: expr,
- beginning_vert: None,
}
}
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;
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),
}
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(),
}
}
+ /// The the `index`-th token tree of `self`.
fn get_tt(&self, index: usize) -> TokenTree {
match *self {
TtSeq(ref v) => v[index].clone(),
}
}
-/// 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<MatcherTtFrame>,
+ /// The token or sequence of tokens that make up the matcher
top_elts: TokenTreeOrTokenTreeVec,
- sep: Option<Token>,
+ /// The position of the "dot" in this matcher
idx: usize,
- up: Option<Box<MatcherPos>>,
+ /// 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<Rc<Vec<NamedMatch>>>,
+ /// 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<quoted::KleeneOp>,
+ /// The separator if we are in a repetition
+ sep: Option<Token>,
+ /// The "parent" matcher position if we are in a repetition. That is, the matcher position just
+ /// before we enter the sequence.
+ up: Option<Box<MatcherPos>>,
+
+ // 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<MatcherTtFrame>,
}
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<T> {
+ /// 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<HashMap<Ident, Rc<NamedMatch>>>;
+/// 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 {
})
}
+/// Initialize `len` empty shared `Vec`s to be used to store matches of metavars.
+fn create_matches(len: usize) -> Vec<Rc<Vec<NamedMatch>>> {
+ (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<TokenTree>, lo: BytePos) -> Box<MatcherPos> {
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,
})
}
/// 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<Vec<NamedMatch>>, syntax_pos::Span),
- MatchedNonterminal(Rc<Nonterminal>)
+ MatchedNonterminal(Rc<Nonterminal>),
}
-fn nameize<I: Iterator<Item=NamedMatch>>(sess: &ParseSess, ms: &[TokenTree], mut res: I)
- -> NamedParseResult {
- fn n_rec<I: Iterator<Item=NamedMatch>>(sess: &ParseSess, m: &TokenTree, res: &mut I,
- ret_val: &mut HashMap<Ident, Rc<NamedMatch>>)
- -> 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<I: Iterator<Item = NamedMatch>>(
+ 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<I: Iterator<Item = NamedMatch>>(
+ sess: &ParseSess,
+ m: &TokenTree,
+ res: &mut I,
+ ret_val: &mut HashMap<Ident, Rc<NamedMatch>>,
+ ) -> 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()));
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),
}
}
Success(ret_val)
}
-pub enum ParseResult<T> {
- 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) {
}
}
-fn create_matches(len: usize) -> Vec<Rc<Vec<NamedMatch>>> {
- (0..len).into_iter().map(|_| Rc::new(Vec::new())).collect()
-}
-
-fn inner_parse_loop(sess: &ParseSess,
- cur_items: &mut SmallVector<Box<MatcherPos>>,
- next_items: &mut Vec<Box<MatcherPos>>,
- eof_items: &mut SmallVector<Box<MatcherPos>>,
- bb_items: &mut SmallVector<Box<MatcherPos>>,
- 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<Box<MatcherPos>>,
+ next_items: &mut Vec<Box<MatcherPos>>,
+ eof_items: &mut SmallVector<Box<MatcherPos>>,
+ bb_items: &mut SmallVector<Box<MatcherPos>>,
+ 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;
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,
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.
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;
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<Directory>,
- 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<Directory>,
+ 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),
}
// 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::<Vec<String>>().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::<Vec<String>>()
+ .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 {
"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,
}
}
+/// 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());
"ident" => match p.token {
token::Ident(sn) => {
p.bump();
- token::NtIdent(Spanned::<Ident>{node: sn, span: p.prev_span})
+ token::NtIdent(Spanned::<Ident> {
+ 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()
}
},
"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"),
}
}
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;
}
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")
// 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,
}
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
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
/// 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),
/// 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 {
}
}
+ /// 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 {
}
}
+ /// 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 => {
/// 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<TokenTree> {
+/// Takes a `tokenstream::TokenStream` and returns a `Vec<self::TokenTree>`. 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<Features>,
+ attrs: &[ast::Attribute],
+) -> Vec<TokenTree> {
+ // 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() {
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<I>(tree: tokenstream::TokenTree,
- trees: &mut I,
- expect_matchers: bool,
- sess: &ParseSess)
- -> TokenTree
- where I: Iterator<Item = tokenstream::TokenTree>,
+/// 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<I>(
+ tree: tokenstream::TokenTree,
+ trees: &mut Peekable<I>,
+ expect_matchers: bool,
+ sess: &ParseSess,
+ features: &RefCell<Features>,
+ attrs: &[ast::Attribute],
+) -> TokenTree
+where
+ I: Iterator<Item = tokenstream::TokenTree>,
{
+ // 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<I>(input: &mut I, span: Span, sess: &ParseSess)
- -> (Option<token::Token>, KleeneOp)
- where I: Iterator<Item = tokenstream::TokenTree>,
-{
- fn kleene_op(token: &token::Token) -> Option<KleeneOp> {
- 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<KleeneOp> {
+ 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<I>(
+ input: &mut I,
+ span: Span,
+) -> Result<Result<KleeneOp, (token::Token, Span)>, Span>
+where
+ I: Iterator<Item = tokenstream::TokenTree>,
+{
+ 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<I>(
+ input: &mut Peekable<I>,
+ span: Span,
+ sess: &ParseSess,
+ features: &RefCell<Features>,
+ attrs: &[ast::Attribute],
+) -> (Option<token::Token>, KleeneOp)
+where
+ I: Iterator<Item = tokenstream::TokenTree>,
+{
+ // 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)
}
// 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)),
// 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)),
// 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! (
(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
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 \
"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),
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>,
}
}
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)
}
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,
fold_attrs(attrs.into(), fld).into()
}
-pub fn noop_fold_arm<T: Folder>(Arm {attrs, pats, guard, body, beginning_vert}: Arm,
+pub fn noop_fold_arm<T: Folder>(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,
}
}
registry: Option<Registry>,
cm: Rc<CodeMapper + 'static>,
pretty: bool,
+ /// Whether "approximate suggestions" are enabled in the config
+ approximate_suggestions: bool,
}
impl JsonEmitter {
pub fn stderr(registry: Option<Registry>,
code_map: Rc<CodeMap>,
- 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<Write + Send>,
registry: Option<Registry>,
code_map: Rc<CodeMap>,
- pretty: bool) -> JsonEmitter {
+ pretty: bool,
+ approximate_suggestions: bool) -> JsonEmitter {
JsonEmitter {
dst,
registry,
cm: code_map,
pretty,
+ approximate_suggestions,
}
}
}
}
#[derive(RustcEncodable)]
+#[allow(unused_attributes)]
struct DiagnosticSpan {
file_name: String,
byte_start: u32,
/// If we are suggesting a replacement, this will contain text
/// that should be sliced in atop this span.
suggested_replacement: Option<String>,
+ /// If the suggestion is approximate
+ #[rustc_serialize_exclude_null]
+ suggestion_approximate: Option<bool>,
/// Macro invocations that created the code at this span, if any.
expansion: Option<Box<DiagnosticSpanMacroExpansion>>,
}
}
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();
impl DiagnosticSpan {
fn from_span_label(span: SpanLabel,
- suggestion: Option<&String>,
+ suggestion: Option<(&String, bool)>,
je: &JsonEmitter)
-> DiagnosticSpan {
Self::from_span_etc(span.span,
fn from_span_etc(span: Span,
is_primary: bool,
label: Option<String>,
- suggestion: Option<&String>,
+ suggestion: Option<(&String, bool)>,
je: &JsonEmitter)
-> DiagnosticSpan {
// obtain the full backtrace from the `macro_backtrace`
fn from_span_full(span: Span,
is_primary: bool,
label: Option<String>,
- suggestion: Option<&String>,
+ suggestion: Option<(&String, bool)>,
mut backtrace: vec::IntoIter<MacroBacktrace>,
je: &JsonEmitter)
-> DiagnosticSpan {
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,
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,
}
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)
})
})
#![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)]
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,
-> 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[..])
}
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,
-> 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[..])
}
fn mk_sess(cm: Rc<CodeMap>) -> 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)),
})
}
+ 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)
}
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 {
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");
}
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,
}
/// 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())))
}
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.
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)
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)?;
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) {
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()?)
pats,
guard,
body: expr,
- beginning_vert,
})
}
pub fn parse_fn_decl(&mut self, allow_variadic: bool) -> PResult<'a, P<FnDecl>> {
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,
self.expect(&token::CloseDelim(token::Paren))?;
Ok(P(FnDecl {
inputs: fn_inputs,
- output: self.parse_ret_ty()?,
+ output: self.parse_ret_ty(true)?,
variadic: false
}))
}
args
}
};
- let output = self.parse_ret_ty()?;
+ let output = self.parse_ret_ty(true)?;
Ok(P(FnDecl {
inputs: inputs_captures,
keywords::Unsafe.name(),
keywords::While.name(),
keywords::Yield.name(),
+ keywords::Static.name(),
].contains(&ident.name)
}
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");
}
}
+ // 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 {
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)),
} 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()
&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, ...)`.
} 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, ...)`.
/// 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 },
)
}
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
pub fn test_main(args: &[String], tests: Vec<TestDescAndFn>, 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);
+ },
}
}
}
-Subproject commit bc344d5bc23c61ff9baf82d268a0edf199933cc3
+Subproject commit 9f81beaf32608fbe1fe0f2a82f974e800e9d8c62
StringMap<FunctionImporter::ImportMapTy> ImportLists;
StringMap<FunctionImporter::ExportSetTy> ExportLists;
StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries;
+
+#if LLVM_VERSION_GE(7, 0)
+ LLVMRustThinLTOData() : Index(/* isPerformingAnalysis = */ false) {}
+#endif
};
// Just an argument to the `LLVMRustCreateThinLTOData` function below.
//
// 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,
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;
}
# 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
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
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<Drop>) {
}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 "", {{.*}}
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<u8> {
+// CHECK: call void @llvm.memset.p0i8
+ iter::repeat(42).take(100000).collect()
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 {} }
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*).
// ignore-wasm
// ignore-emscripten
// ignore-windows
-// no-system-llvm
+// min-system-llvm-version 5.0
// compile-flags: -C no-prepopulate-passes
#![crate_type = "lib"]
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 => {}
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 => {},
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
- _ => {},
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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!()
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<i32> = box 0; //~ ERROR E0010
-
-fn main() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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]
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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`
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
- _ => {}
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Trait>) {
- //~^ ERROR E0038
- let y = x.foo();
-}
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-extern { fn some_func<T>(x: T); } //~ ERROR E0044
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-trait Foo {
- fn foo<T: Default>(x: T) -> Self;
-}
-
-struct Bar;
-
-impl Foo for Bar {
- fn foo(x: bool) -> Self { Bar } //~ ERROR E0049
-}
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(unboxed_closures)]
-
-fn foo<F: Fn<i32>>(f: F) -> F::Output { f(3) } //~ ERROR E0059
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
- };
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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`
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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]
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn foo() {}
-fn bar<T>() {}
-
-fn main() {
- foo::<f64>(); //~ ERROR expected at most 0 type parameters, found 1 type parameter [E0087]
-
- bar::<f64, u64>(); //~ ERROR expected at most 1 type parameter, found 2 type parameters [E0087]
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn foo<T, U>() {}
-
-fn main() {
- foo::<f64>(); //~ ERROR expected 2 type parameters, found 1 type parameter [E0089]
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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]
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-type Foo<T> = u32; //~ ERROR E0091
-type Foo2<A, B> = Box<A>; //~ ERROR E0091
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T, U>() -> usize; //~ ERROR E0094
-}
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-type X = u32<i32>; //~ ERROR E0109
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-impl Vec<u8> {}
-//~^ ERROR E0116
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-trait MyTrait {
- fn get(&self) -> usize;
-}
-
-impl<T> 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-struct Foo<T=U, U=()> { //~ ERROR E0128
- field1: T,
- field2: U,
-}
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main<T>() {
- //~^ ERROR E0131
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<str> = box *"hello"; //~ ERROR E0161
- //~^ ERROR E0507
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
- // ...
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-trait Foo<T> {
- fn do_something(&self) -> T;
- fn do_something_else<T: Clone>(&self, bar: T);
- //~^ ERROR E0194
-}
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-struct Foo;
-
-impl<T: Default> Foo { //~ ERROR E0207
- fn get(&self) -> T {
- <T as Default>::default()
- }
-}
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-trait Trait {
- type Bar;
-}
-
-type Foo = Trait<F=i32>; //~ ERROR E0220
- //~| ERROR E0191
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- let _: Box<std::io::Read + std::io::Write>;
- //~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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) -> <Self as Foo>::A;
-}
-
-struct Bar;
-
-impl Foo for isize {
- type A = usize;
- fn boo(&self) -> usize { 42 }
-}
-
-fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
-//~^ ERROR associated type bindings are not allowed here [E0229]
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-struct Foo<T> { x: T }
-struct Bar { x: Foo }
- //~^ ERROR wrong number of type arguments: expected 1, found 0 [E0243]
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-struct Foo { x: bool }
-struct Bar<S, T> { x: Foo<S, T> }
- //~^ ERROR wrong number of type arguments: expected 0, found 2 [E0244]
-
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- let w = || { break; }; //~ ERROR E0267
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- break; //~ ERROR E0268
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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: T) where T: Trait<AssociatedType=u32> {
- println!("in foo");
-}
-
-impl Trait for i8 { type AssociatedType = &'static str; }
-
-fn main() {
- foo(3_i8); //~ ERROR E0271
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-trait Foo {}
-
-struct Bar<T>(T);
-
-impl<T> Foo for T where Bar<T>: Foo {} //~ ERROR E0275
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-trait Foo {
- fn foo<T>(x: T);
-}
-
-impl Foo for bool {
- fn foo<T>(x: T) where T: Copy {} //~ ERROR E0276
-}
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T: Send>() { }
-
-fn main() {
- is_send::<Foo>();
- //~^ ERROR the trait bound `*const u8: std::marker::Send` is not satisfied in `Foo`
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T: Foo>(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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![recursion_limit] //~ ERROR E0296
-
-fn main() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- let xs : Vec<Option<i32>> = vec![Some(1), None];
-
- for Some(x) in xs {}
- //~^ ERROR E0005
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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(_) => { }
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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(_) => { }
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 => {},
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
- _ => ()
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T>(); //~ ERROR E0308
-}
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T: ?Sized> {
- a: i32,
-}
-
-impl<T, U> CoerceUnsized<Foo<U>> for Foo<T> //~ ERROR E0374
- where T: CoerceUnsized<U> {}
-
-fn main() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T: ?Sized, U: ?Sized> {
- a: i32,
- b: T,
- c: U,
-}
-
-impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {}
-//~^ ERROR E0375
-
-fn main() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T: ?Sized> {
- a: T,
-}
-
-impl<T, U> CoerceUnsized<U> for Foo<T> {} //~ ERROR E0376
-
-fn main() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-enum Foo<T> { Bar } //~ ERROR E0392
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-trait A<T=Self> {}
-
-fn together_we_will_rule_the_galaxy(son: &A) {}
-//~^ ERROR E0393
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn foo<T>(x: T) {
- fn bar(y: T) { //~ ERROR E0401
- }
- bar(x);
-}
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn foo<T, T>(s: T, u: T) {} //~ ERROR E0403
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
- _ => ()
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- <Self>::foo; //~ ERROR E0411
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-impl Something {} //~ ERROR E0412
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 () {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 () {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main () {
- loop {
- break 'a;
- //~^ ERROR E0426
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 () {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 () {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 () {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use {self}; //~ ERROR E0431
-
-fn main () {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use something::Foo; //~ ERROR E0432
-
-fn main () {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 () {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 () {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 () {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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,B>(a: A, b: A, c: [u32; 8]) -> B; //~ ERROR E0439
-}
-
-fn main () {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T>(x: f64x2) -> i32; //~ ERROR E0440
-}
-
-fn main () {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T: Foo>(pub T);
-//~^ ERROR private trait `Foo` in public interface [E0445]
-//~| NOTE can't leak private trait
-pub fn foo<T: Foo> (t: T) {}
-//~^ ERROR private trait `Foo` in public interface [E0445]
-//~| NOTE can't leak private trait
-
-fn main() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![allow(foo = "")] //~ ERROR E0452
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[link(name = "")] extern {}
-//~^ ERROR E0454
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Wedding<'kiss> + 'SnowWhite>, //~ ERROR E0478
-}
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T>(a: T, b: T) -> T;
-}
-
-fn main() {
- unsafe { simd_add(0, 1); } //~ ERROR E0511
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T> SpaceLlama for T {
- default fn fly(&self) {}
-}
-
-impl<T: Clone> SpaceLlama for T {
- fn fly(&self) {}
-}
-
-impl SpaceLlama for i32 {
- default fn fly(&self) {}
- //~^ ERROR E0520
-}
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 {}
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
- }
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
- }
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
- }
- }
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
- }
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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();
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() { }
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() { }
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Ch, Str> {
- 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<F>(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<F>(t: F)
- // No type can satisfy this requirement, since `'a` does not
- // appear in any of the input types:
- where F: for<'a> Iterator<Item=&'a i32>
- //~^ ERROR E0582
-{
-}
-
-fn main() {
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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]
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- !"a"; //~ ERROR E0600
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- 1u32 as char; //~ ERROR E0604
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<u8>; //~ ERROR E0605
-
- let v = 0 as *const u8;
- v as &u8; //~ ERROR E0605
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- &0u8 as u8; //~ ERROR E0606
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- 0u8[2]; //~ ERROR E0608
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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, ...)`
- }
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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]
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
- _ => {}
- }
-}
-
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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(); } }
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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]
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T> {}
-trait Lt<'a> {}
-
-impl<'a> Lt<'a> for () {}
-impl<T> Id<T> for T {}
-
-fn free_fn_capture_hrtb_in_impl_trait()
- -> impl for<'a> Id<impl Lt<'a>>
- //~^ 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<impl Lt<'a>>
- //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level
- {
- ()
- }
-}
-
-fn main() {}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
-}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(use_nested_groups)]
#![allow(unused_imports)]
mod foo {}
}
struct Abc;
+
impl Foo for Abc {
const X: EFoo = EFoo::B;
}
pub fn test<A: Foo, B: Foo>(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]
_ => (),
}
}
{
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
{
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
{
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
{
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
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
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
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
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]
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]
// 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
//
// 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)]
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;
}
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);
}
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() { }
// 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/
// 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;
/*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;
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<F: FnMut(i32) -> 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<F: Fn(i32) -> i32>(f: &mut F) {
+ f(f(10));
+ }
+ fn twice_ten_so<F: FnOnce(i32) -> i32>(f: Box<F>) {
+ 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<FnOnce(i32) -> 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<X: Copy>(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<i32> for I {
+ type Output = i32;
+ fn index(&self, _: i32) -> &i32 {
+ &self.0
+ }
+}
+
+impl IndexMut<i32> 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<i32> 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();
+}
// 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
// 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];
// 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];
}
: [u32; (i8::MAX as i8 + 1u8) as usize]
//~^ ERROR mismatched types
//~| expected i8, found u8
- //~| ERROR the trait bound `i8: std::ops::Add<u8>` is not satisfied
+ //~| ERROR cannot add `u8` to `i8`
= [0; (i8::MAX as usize) + 1];
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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::<A>();
+ //~^ ERROR `std::any::TypeId::of` is not yet stable as a const fn
+}
#![feature(unsized_tuple_coercion)]
type Fat<T: ?Sized> = (isize, &'static str, T);
-//~^ WARNING trait bounds are not (yet) enforced
+//~^ WARNING bounds are ignored
#[derive(PartialEq,Eq)]
struct Bar;
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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]
+}
trait NoLifetime {
fn get<'p, T : Test<'p>>(&self) -> T;
+ //~^ NOTE lifetimes in impl do not match this method in trait
}
trait Test<'p> {
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;
}
}
#![allow(unused_macros)]
macro_rules! assign {
- (($($a:tt)*) = ($($b:tt))*) => { //~ ERROR expected `*` or `+`
+ (($($a:tt)*) = ($($b:tt))*) => { //~ ERROR expected one of: `*`, `+`, or `?`
$($a)* = $($b)*
}
}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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::<Foo>() }],
+ //~^ ERROR unsupported cyclic reference between types/traits detected
+ x: usize,
+}
+
+fn main() {}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() { }
fn main() {
write(&buf);
- buf[0]=2; //[mir]~ ERROR E0594
+ buf[0]=2; //[ast]~ ERROR E0389
+ //[mir]~^ ERROR E0594
}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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::<Void>();
+ match *ptr {}
+ //~^ ERROR dereference of raw pointer requires unsafe function or block
+}
+
+fn main() {}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
+}
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;
}
pub trait PubTr {}
pub type Alias<T: PrivTr> = 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
// 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);
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() { }
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
+}
fn main() {
<i32 as Add<u32>>::add(1, 2);
- //~^ ERROR `i32: std::ops::Add<u32>` is not satisfied
+ //~^ ERROR cannot add `u32` to `i32`
<i32 as Add<i32>>::add(1u32, 2);
//~^ ERROR mismatched types
<i32 as Add<i32>>::add(1, 2u32);
}
#[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;
-// 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;
#[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;
// 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);
// StorageDead(_2);
// return;
// }
-// bb3: {
+// bb5: {
// _4 = ();
// StorageDead(_5);
// StorageLive(_7);
// 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);
// StorageDead(_1);
// return;
// }
-// bb3: {
+// bb5: {
// _4 = ();
// StorageDead(_5);
// StorageLive(_7);
// _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);
// 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
// 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 <std::cell::Cell<T>>::new(move _4) -> [return: bb3, unwind: bb2];
+// _3 = const <std::cell::Cell<T>>::new(move _4) -> [return: bb4, unwind: bb3];
// }
-// bb2: {
+// bb3: {
// resume;
// }
-// bb3: {
+// bb4: {
// StorageDead(_4);
// _2 = S<'35_0rs> { r: move _3 };
// StorageDead(_3);
// _8 = &'35_0rs (*_9);
// _7 = std::option::Option<&'35_0rs S<'35_0rs>>::Some(move _8,);
// StorageDead(_8);
-// _5 = const <std::cell::Cell<T>>::set(move _6, move _7) -> [return: bb4, unwind: bb2];
+// _5 = const <std::cell::Cell<T>>::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);
// _16 = &'35_0rs (*_17);
// _15 = std::option::Option<&'35_0rs S<'35_0rs>>::Some(move _16,);
// StorageDead(_16);
-// _13 = const <std::cell::Cell<T>>::set(move _14, move _15) -> [return: bb8, unwind: bb2];
+// _13 = const <std::cell::Cell<T>>::set(move _14, move _15) -> [return: bb9, unwind: bb3];
// }
-// bb8: {
+// bb9: {
// EndRegion('33s);
// StorageDead(_15);
// StorageDead(_14);
// 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
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
// bb0: {
// ...
// _2 = std::option::Option<i32>::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
// 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: {
// bb0: {
// ...
// _2 = std::option::Option<i32>::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
// 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: {
// bb0: {
// ...
// _2 = std::option::Option<i32>::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;
// 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;
// }
// 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
// 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;
// }
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
'
fn main() {
let x = || -> i32 22;
- //~^ ERROR expected one of `!`, `(`, `::`, `<`, or `{`, found `22`
+ //~^ ERROR expected one of `!`, `(`, `+`, `::`, `<`, or `{`, found `22`
}
// compile-flags: -Z parse-only
fn foo() -> Vec<usize>> {
- //~^ ERROR expected one of `!`, `::`, `where`, or `{`, found `>`
+ //~^ ERROR expected one of `!`, `+`, `::`, `where`, or `{`, found `>`
Vec::new()
}
macro_rules! foo {
{ $+ } => { //~ ERROR expected identifier, found `+`
//~^ ERROR missing fragment specifier
- $(x)(y) //~ ERROR expected `*` or `+`
+ $(x)(y) //~ ERROR expected one of: `*`, `+`, or `?`
}
}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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: \
--- /dev/null
+-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\""
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {}
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 \
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "lib"]
-// 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.
//
static EXTERN_FOO: u8;
fn extern_foo(a: u8, b: i32) -> String;
}
+
+struct Rls699 {
+ f: u32,
+}
+
+fn new(f: u32) -> Rls699 {
+ Rls699 { fs }
+}
--- /dev/null
+Extra docs for this struct.
#![feature(box_syntax)]
#![feature(rustc_private)]
#![feature(associated_type_defaults)]
+#![feature(external_doc)]
extern crate graphviz;
// A simple rust project
trait Foo {
type Bar = FrameBuffer;
}
+
+#[doc(include="extra-docs.md")]
+struct StructWithDocs;
--- /dev/null
+-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"
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};
use syntax_pos::Span;
use rustc_plugin::Registry;
+use std::cell::RefCell;
+
fn expand_mbe_matches(cx: &mut ExtCtxt, _: Span, args: &[TokenTree])
-> Box<MacResult + 'static> {
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) => {
// 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;
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) {
use std::process::Command;
let mut i = 0;
+ let mut errors = Vec::new();
loop {
let out = Command::new(me)
.env("RUST_BACKTRACE", "full")
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)]
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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::<isize>();
+
+pub fn main() {
+ assert_eq!(ID_ISIZE, TypeId::of::<isize>());
+
+ // sanity test of TypeId
+ const T: (TypeId, TypeId, TypeId) = (TypeId::of::<usize>(),
+ TypeId::of::<&'static str>(),
+ TypeId::of::<A>());
+ let (d, e, f) = (TypeId::of::<usize>(), TypeId::of::<&'static str>(),
+ TypeId::of::<A>());
+
+ 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::<fn(fn(A) -> A) -> A>(),
+ TypeId::of::<fn(fn() -> A, A) -> A>());
+
+ assert!(F.0 != F.1);
+}
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")));
}
}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
+ };
+ }
+}
// 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.
// 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 {
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<?U> ?
+// - `Option<?U>: 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<T> Insertable for Option<T>
+ 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<T>
+ where
+ Option<&'a T>: Insertable,
+{
+ type Values = <Option<&'a T> 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: T }
+
+impl<'a, U> Dummy for Foo<&'a U>
+ where &'a U: Insertable
+{
+}
+
+impl<T> Dummy for T
+ where T: Unimplemented
+{ }
+
+fn main() {
+}
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T> Insertable for Option<T>
+ 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<T>
+ where
+ Option<&'a T>: Insertable,
+{
+ type Values = <Option<&'a T> 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: T }
+
+impl<T> Dummy for T
+ where T: Unimplemented
+{ }
+
+impl<'a, U> Dummy for Foo<&'a U>
+ where &'a U: Insertable
+{
+}
+
+fn main() {
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(use_nested_groups)]
#![allow(unused_import)]
use {{}, {}};
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() { }
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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!"),
+ | _ => {},
+ }
+ }
+}
// 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;
// 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]);
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<AttachInfo<'a, Resources>>
+}
+
+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<R::DescriptorSet>)
+}
+
+fn main() {
+ let _x = DescriptorSet {slots: Vec::new()};
+}
// 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)]
// 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
// 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;
assert_eq!(b, 1: u16);
let mut v = Vec::new();
- v: Vec<u8> = vec![1, 2, 3]; // Lvalue type ascription
+ v: Vec<u8> = vec![1, 2, 3]; // Place expression type ascription
assert_eq!(v, [1u8, 2, 3]);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(use_nested_groups)]
-
mod a {
pub enum B {}
}
}
+// 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<AtomicBool>;
+ let _: Ordering;
}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub fn f2<F: FnMut(u32) + Clone>(f: F) {}
+
+pub fn f3<F: FnMut(u64) -> () + Clone>(f: F) {}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<usize>
+}
+
+pub type _S = [usize; 0 - (mem::size_of::<S>() != 4) as usize];
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 {
+ () => ()
+ }
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 & <stuff> & "things"'
+
+// @has 'foo/index.html' 'title & <stuff> & "things"'
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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: FnMut(u8) + Clone>(f: F) {}
+
+// @has 'foo/fn.f1.html' '//*[@class="rust fn"]' 'F: FnMut(u16) + Clone'
+pub fn f1<F: FnMut(u16) -> () + 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;
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
= 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
//~^ 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]
}
}
|
= note: move occurs because the value has type `std::vec::Vec<bool>`, 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<std::vec::Vec<bool>>`, which does not implement the `Copy` trait
+
error[E0382]: use of moved value: `maybe` (Mir)
--> $DIR/issue-41962.rs:17:16
|
|
= note: move occurs because `maybe.0` has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() { }
--- /dev/null
+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
+
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
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
|
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[macro_use]
+mod underscore;
+
+fn main() {
+ underscore!();
+}
--- /dev/null
+error: expected expression, found `_`
+ --> $DIR/underscore.rs:18:9
+ |
+18 | _
+ | ^
+ |
+ ::: $DIR/main.rs:15:5
+ |
+15 | underscore!();
+ | -------------- in this macro invocation
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 {
+ () => (
+ _
+ )
+}
= 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
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+error[E0004]: non-exhaustive patterns: type std::option::Option<i32> 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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 => {}
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 => {},
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+ _ => {},
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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!()
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<i32> = box 0; //~ ERROR E0010
+
+fn main() {}
--- /dev/null
+error[E0010]: allocations are not allowed in constants
+ --> $DIR/E0010-teach.rs:16:24
+ |
+16 | const CON : Box<i32> = 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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<i32> = box 0; //~ ERROR E0010
+
+fn main() {}
--- /dev/null
+error[E0010]: allocations are not allowed in constants
+ --> $DIR/E0010.rs:14:24
+ |
+14 | const CON : Box<i32> = box 0; //~ ERROR E0010
+ | ^^^^^ allocation not allowed in constants
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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]
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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]
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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`
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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`
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+ _ => {}
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+ _ => {}
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Trait>) {
+ //~^ ERROR E0038
+ let y = x.foo();
+}
+
+fn main() {
+}
--- /dev/null
+error[E0038]: the trait `Trait` cannot be made into an object
+ --> $DIR/E0038.rs:15:1
+ |
+15 | fn call_foo(x: Box<Trait>) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern { fn some_func<T>(x: T); } //~ ERROR E0044
+
+fn main() {
+}
--- /dev/null
+error[E0044]: foreign items may not have type parameters
+ --> $DIR/E0044.rs:11:10
+ |
+11 | extern { fn some_func<T>(x: T); } //~ ERROR E0044
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider using specialization instead of type parameters
+ --> $DIR/E0044.rs:11:10
+ |
+11 | extern { fn some_func<T>(x: T); } //~ ERROR E0044
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Foo {
+ fn foo<T: Default>(x: T) -> Self;
+}
+
+struct Bar;
+
+impl Foo for Bar {
+ fn foo(x: bool) -> Self { Bar } //~ ERROR E0049
+}
+
+fn main() {
+}
--- /dev/null
+error[E0049]: method `foo` has 0 type parameters but its trait declaration has 1 type parameter
+ --> $DIR/E0049.rs:18:5
+ |
+12 | fn foo<T: Default>(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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(unboxed_closures)]
+
+fn foo<F: Fn<i32>>(f: F) -> F::Output { f(3) } //~ ERROR E0059
+
+fn main() {
+}
--- /dev/null
+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: Fn<i32>>(f: F) -> F::Output { f(3) } //~ ERROR E0059
+ | ^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+ };
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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`
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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]
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+error[E0075]: SIMD vector cannot be empty
+ --> $DIR/E0075.rs:14:1
+ |
+14 | struct Bad; //~ ERROR E0075
+ | ^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo() {}
+fn bar<T>() {}
+
+fn main() {
+ foo::<f64>(); //~ ERROR expected at most 0 type parameters, found 1 type parameter [E0087]
+
+ bar::<f64, u64>(); //~ ERROR expected at most 1 type parameter, found 2 type parameters [E0087]
+}
--- /dev/null
+error[E0087]: too many type parameters provided: expected at most 0 type parameters, found 1 type parameter
+ --> $DIR/E0087.rs:15:11
+ |
+15 | foo::<f64>(); //~ 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::<f64, u64>(); //~ ERROR expected at most 1 type parameter, found 2 type parameters [E0087]
+ | ^^^ expected 1 type parameter
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo<T, U>() {}
+
+fn main() {
+ foo::<f64>(); //~ ERROR expected 2 type parameters, found 1 type parameter [E0089]
+}
--- /dev/null
+error[E0089]: too few type parameters provided: expected 2 type parameters, found 1 type parameter
+ --> $DIR/E0089.rs:14:5
+ |
+14 | foo::<f64>(); //~ ERROR expected 2 type parameters, found 1 type parameter [E0089]
+ | ^^^^^^^^^^ expected 2 type parameters
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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]
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+type Foo<T> = u32; //~ ERROR E0091
+type Foo2<A, B> = Box<A>; //~ ERROR E0091
+
+fn main() {
+}
--- /dev/null
+error[E0091]: type parameter `T` is unused
+ --> $DIR/E0091.rs:11:10
+ |
+11 | type Foo<T> = u32; //~ ERROR E0091
+ | ^ unused type parameter
+
+error[E0091]: type parameter `B` is unused
+ --> $DIR/E0091.rs:12:14
+ |
+12 | type Foo2<A, B> = Box<A>; //~ ERROR E0091
+ | ^ unused type parameter
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+error[E0093]: unrecognized intrinsic function: `foo`
+ --> $DIR/E0093.rs:13:5
+ |
+13 | fn foo();
+ | ^^^^^^^^^ unrecognized intrinsic
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T, U>() -> usize; //~ ERROR E0094
+}
+
+fn main() {
+}
--- /dev/null
+error[E0094]: intrinsic has wrong number of type parameters: found 2, expected 1
+ --> $DIR/E0094.rs:13:15
+ |
+13 | fn size_of<T, U>() -> usize; //~ ERROR E0094
+ | ^^^^^^ expected 1 type parameter
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+type X = u32<i32>; //~ ERROR E0109
+
+fn main() {
+}
--- /dev/null
+error[E0109]: type parameters are not allowed on this type
+ --> $DIR/E0109.rs:11:14
+ |
+11 | type X = u32<i32>; //~ ERROR E0109
+ | ^^^ type parameter not allowed
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+impl Vec<u8> {}
+//~^ ERROR E0116
+
+fn main() {
+}
--- /dev/null
+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<u8> {}
+ | ^^^^^^^^^^^^^^^ impl for type defined outside of crate.
+ |
+ = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait MyTrait {
+ fn get(&self) -> usize;
+}
+
+impl<T> 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() {
+}
--- /dev/null
+error[E0119]: conflicting implementations of trait `MyTrait` for type `Foo`:
+ --> $DIR/E0119.rs:23:1
+ |
+15 | impl<T> MyTrait for T {
+ | --------------------- first implementation here
+...
+23 | impl MyTrait for Foo { //~ ERROR E0119
+ | ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Foo`
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo<T=U, U=()> { //~ ERROR E0128
+ field1: T,
+ field2: U,
+}
+
+fn main() {
+}
--- /dev/null
+error[E0128]: type parameters with a default cannot use forward declared identifiers
+ --> $DIR/E0128.rs:11:14
+ |
+11 | struct Foo<T=U, U=()> { //~ ERROR E0128
+ | ^ defaulted type parameters cannot be forward declared
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main<T>() {
+ //~^ ERROR E0131
+}
--- /dev/null
+error[E0131]: main function is not allowed to have type parameters
+ --> $DIR/E0131.rs:11:8
+ |
+11 | fn main<T>() {
+ | ^^^ main cannot have type parameters
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<str> = box *"hello"; //~ ERROR E0161
+ //~^ ERROR E0507
+}
--- /dev/null
+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<str> = box *"hello"; //~ ERROR E0161
+ | ^^^^^^^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/E0161.rs:14:28
+ |
+14 | let _x: Box<str> = box *"hello"; //~ ERROR E0161
+ | ^^^^^^^^ cannot move out of borrowed content
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+error[E0164]: expected tuple struct/variant, found associated constant `<Foo>::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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+ // ...
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Foo<T> {
+ fn do_something(&self) -> T;
+ fn do_something_else<T: Clone>(&self, bar: T);
+ //~^ ERROR E0194
+}
+
+fn main() {
+}
--- /dev/null
+error[E0194]: type parameter `T` shadows another type parameter of the same name
+ --> $DIR/E0194.rs:13:26
+ |
+11 | trait Foo<T> {
+ | - first `T` declared here
+12 | fn do_something(&self) -> T;
+13 | fn do_something_else<T: Clone>(&self, bar: T);
+ | ^ shadows another type parameter
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+error[E0197]: inherent impls cannot be unsafe
+ --> $DIR/E0197.rs:13:1
+ |
+13 | unsafe impl Foo { } //~ ERROR E0197
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo;
+
+impl<T: Default> Foo { //~ ERROR E0207
+ fn get(&self) -> T {
+ <T as Default>::default()
+ }
+}
+
+fn main() {
+}
--- /dev/null
+error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
+ --> $DIR/E0207.rs:13:6
+ |
+13 | impl<T: Default> Foo { //~ ERROR E0207
+ | ^ unconstrained type parameter
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Trait {
+ type Bar;
+}
+
+type Foo = Trait<F=i32>; //~ ERROR E0220
+ //~| ERROR E0191
+fn main() {
+}
--- /dev/null
+error[E0220]: associated type `F` not found for `Trait`
+ --> $DIR/E0220.rs:15:18
+ |
+15 | type Foo = Trait<F=i32>; //~ 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<F=i32>; //~ ERROR E0220
+ | ^^^^^^^^^^^^ missing associated type `Bar` value
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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 `<Type as MyTrait>::X`
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let _: Box<std::io::Read + std::io::Write>;
+ //~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+}
--- /dev/null
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/E0225.rs:12:32
+ |
+12 | let _: Box<std::io::Read + std::io::Write>;
+ | ^^^^^^^^^^^^^^ non-auto additional trait
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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) -> <Self as Foo>::A;
+}
+
+struct Bar;
+
+impl Foo for isize {
+ type A = usize;
+ fn boo(&self) -> usize { 42 }
+}
+
+fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
+//~^ ERROR associated type bindings are not allowed here [E0229]
+
+fn main() {
+}
--- /dev/null
+error[E0229]: associated type bindings are not allowed here
+ --> $DIR/E0229.rs:23:25
+ |
+23 | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
+ | ^^^^^ associated type not allowed here
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo<T> { x: T }
+struct Bar { x: Foo }
+ //~^ ERROR wrong number of type arguments: expected 1, found 0 [E0243]
+
+fn main() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo { x: bool }
+struct Bar<S, T> { x: Foo<S, T> }
+ //~^ ERROR wrong number of type arguments: expected 0, found 2 [E0244]
+
+
+fn main() {
+}
--- /dev/null
+error[E0244]: wrong number of type arguments: expected 0, found 2
+ --> $DIR/E0244.rs:12:23
+ |
+12 | struct Bar<S, T> { x: Foo<S, T> }
+ | ^^^^^^^^^ expected no type arguments
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+error[E0264]: unknown external lang item: `cake`
+ --> $DIR/E0264.rs:15:5
+ |
+15 | fn cake(); //~ ERROR E0264
+ | ^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let w = || { break; }; //~ ERROR E0267
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ break; //~ ERROR E0268
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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: T) where T: Trait<AssociatedType=u32> {
+ println!("in foo");
+}
+
+impl Trait for i8 { type AssociatedType = &'static str; }
+
+fn main() {
+ foo(3_i8); //~ ERROR E0271
+}
--- /dev/null
+error[E0271]: type mismatch resolving `<i8 as Trait>::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: T) where T: Trait<AssociatedType=u32> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Foo {}
+
+struct Bar<T>(T);
+
+impl<T> Foo for T where Bar<T>: Foo {} //~ ERROR E0275
+
+fn main() {
+}
--- /dev/null
+error[E0275]: overflow evaluating the requirement `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: std::marker::Sized`
+ --> $DIR/E0275.rs:15:1
+ |
+15 | impl<T> Foo for T where Bar<T>: 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<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<T>>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<T>>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<T>>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<T>>`
+ = note: required because of the requirements on the impl of `Foo` for `Bar<T>`
+note: required by `Foo`
+ --> $DIR/E0275.rs:11:1
+ |
+11 | trait Foo {}
+ | ^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Foo {
+ fn foo<T>(x: T);
+}
+
+impl Foo for bool {
+ fn foo<T>(x: T) where T: Copy {} //~ ERROR E0276
+}
+
+fn main() {
+}
--- /dev/null
+error[E0276]: impl has stricter requirements than trait
+ --> $DIR/E0276.rs:16:5
+ |
+12 | fn foo<T>(x: T);
+ | ---------------- definition of `foo` from trait
+...
+16 | fn foo<T>(x: T) where T: Copy {} //~ ERROR E0276
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: std::marker::Copy`
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T: Send>() { }
+
+fn main() {
+ is_send::<Foo>();
+ //~^ ERROR the trait bound `*const u8: std::marker::Send` is not satisfied in `Foo`
+}
--- /dev/null
+error[E0277]: the trait bound `*const u8: std::marker::Send` is not satisfied in `Foo`
+ --> $DIR/E0277-2.rs:26:5
+ |
+26 | is_send::<Foo>();
+ | ^^^^^^^^^^^^^^ `*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<T: Send>() { }
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T: Foo>(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
+}
--- /dev/null
+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<T: Foo>(foo: T) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![recursion_limit] //~ ERROR E0296
+
+fn main() {}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let xs : Vec<Option<i32>> = vec![Some(1), None];
+
+ for Some(x) in xs {}
+ //~^ ERROR E0005
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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(_) => { }
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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(_) => { }
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 => {},
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+ _ => ()
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T>(); //~ ERROR E0308
+}
+
+fn main() {
+}
--- /dev/null
+error[E0308]: intrinsic has wrong type
+ --> $DIR/E0308.rs:14:5
+ |
+14 | fn size_of<T>(); //~ 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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T: ?Sized> {
+ a: i32,
+}
+
+impl<T, U> CoerceUnsized<Foo<U>> for Foo<T> //~ ERROR E0374
+ where T: CoerceUnsized<U> {}
+
+fn main() {}
--- /dev/null
+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<T, U> CoerceUnsized<Foo<U>> for Foo<T> //~ ERROR E0374
+19 | | where T: CoerceUnsized<U> {}
+ | |________________________________^
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T: ?Sized, U: ?Sized> {
+ a: i32,
+ b: T,
+ c: U,
+}
+
+impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {}
+//~^ ERROR E0375
+
+fn main() {}
--- /dev/null
+error[E0375]: implementing the trait `CoerceUnsized` requires multiple coercions
+ --> $DIR/E0375.rs:22:12
+ |
+22 | impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ 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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T: ?Sized> {
+ a: T,
+}
+
+impl<T, U> CoerceUnsized<U> for Foo<T> {} //~ ERROR E0376
+
+fn main() {}
--- /dev/null
+error[E0376]: the trait `CoerceUnsized` may only be implemented for a coercion between structures
+ --> $DIR/E0376.rs:18:1
+ |
+18 | impl<T, U> CoerceUnsized<U> for Foo<T> {} //~ ERROR E0376
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+enum Foo<T> { Bar } //~ ERROR E0392
+
+fn main() {
+}
--- /dev/null
+error[E0392]: parameter `T` is never used
+ --> $DIR/E0392.rs:11:10
+ |
+11 | enum Foo<T> { 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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait A<T=Self> {}
+
+fn together_we_will_rule_the_galaxy(son: &A) {}
+//~^ ERROR E0393
+
+fn main() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo<T>(x: T) {
+ fn bar(y: T) { //~ ERROR E0401
+ }
+ bar(x);
+}
+
+fn main() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo<T, T>(s: T, u: T) {} //~ ERROR E0403
+
+fn main() {
+}
--- /dev/null
+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<T, T>(s: T, u: T) {} //~ ERROR E0403
+ | - ^ already used
+ | |
+ | first use of `T`
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+ _ => ()
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ <Self>::foo; //~ ERROR E0411
+}
--- /dev/null
+error[E0411]: cannot find type `Self` in this scope
+ --> $DIR/E0411.rs:12:6
+ |
+12 | <Self>::foo; //~ ERROR E0411
+ | ^^^^ `Self` is only available in traits and impls
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+impl Something {} //~ ERROR E0412
+
+fn main() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 () {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 () {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main () {
+ loop {
+ break 'a;
+ //~^ ERROR E0426
+ }
+}
--- /dev/null
+error[E0426]: use of undeclared label `'a`
+ --> $DIR/E0426.rs:13:15
+ |
+13 | break 'a;
+ | ^^ undeclared label `'a`
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 () {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 () {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 () {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use {self}; //~ ERROR E0431
+
+fn main () {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use something::Foo; //~ ERROR E0432
+
+fn main () {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 () {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 () {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 () {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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,B>(a: A, b: A, c: [u32; 8]) -> B; //~ ERROR E0439
+}
+
+fn main () {
+}
--- /dev/null
+error[E0439]: invalid `simd_shuffle`, needs length: `simd_shuffle`
+ --> $DIR/E0439.rs:14:5
+ |
+14 | fn simd_shuffle<A,B>(a: A, b: A, c: [u32; 8]) -> B; //~ ERROR E0439
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T>(x: f64x2) -> i32; //~ ERROR E0440
+}
+
+fn main () {
+}
--- /dev/null
+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<T>(x: f64x2) -> i32; //~ ERROR E0440
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T: Foo>(pub T);
+//~^ ERROR private trait `Foo` in public interface [E0445]
+//~| NOTE can't leak private trait
+pub fn foo<T: Foo> (t: T) {}
+//~^ ERROR private trait `Foo` in public interface [E0445]
+//~| NOTE can't leak private trait
+
+fn main() {}
--- /dev/null
+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<T: Foo>(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: Foo> (t: T) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+
+error: aborting due to 3 previous errors
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(foo = "")] //~ ERROR E0452
+
+fn main() {
+}
--- /dev/null
+error[E0452]: malformed lint attribute
+ --> $DIR/E0452.rs:11:10
+ |
+11 | #![allow(foo = "")] //~ ERROR E0452
+ | ^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[link(name = "")] extern {}
+//~^ ERROR E0454
+
+fn main() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Wedding<'kiss> + 'SnowWhite>, //~ ERROR E0478
+}
+
+fn main() {
+}
--- /dev/null
+error[E0478]: lifetime bound not satisfied
+ --> $DIR/E0478.rs:14:5
+ |
+14 | child: Box<Wedding<'kiss> + '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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T>(a: T, b: T) -> T;
+}
+
+fn main() {
+ unsafe { simd_add(0, 1); } //~ ERROR E0511
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T> SpaceLlama for T {
+ default fn fly(&self) {}
+}
+
+impl<T: Clone> SpaceLlama for T {
+ fn fly(&self) {}
+}
+
+impl SpaceLlama for i32 {
+ default fn fly(&self) {}
+ //~^ ERROR E0520
+}
+
+fn main() {
+}
--- /dev/null
+error[E0520]: `fly` specializes an item from a parent `impl`, but that item is not marked `default`
+ --> $DIR/E0520.rs:26:5
+ |
+21 | / impl<T: Clone> 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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 {}
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
+ }
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+ }
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+ }
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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();
+}
--- /dev/null
+error[E0534]: expected one argument
+ --> $DIR/E0534.rs:11:1
+ |
+11 | #[inline()] //~ ERROR E0534
+ | ^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() { }
--- /dev/null
+error[E0565]: unsupported literal
+ --> $DIR/E0565-1.rs:14:14
+ |
+14 | #[deprecated("since")] //~ ERROR E0565
+ | ^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() { }
--- /dev/null
+error[E0565]: unsupported literal
+ --> $DIR/E0565.rs:14:8
+ |
+14 | #[repr("C")] //~ ERROR E0565
+ | ^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Ch, Str> {
+ 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<F>(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<F>(t: F)
+ // No type can satisfy this requirement, since `'a` does not
+ // appear in any of the input types:
+ where F: for<'a> Iterator<Item=&'a i32>
+ //~^ ERROR E0582
+{
+}
+
+fn main() {
+}
--- /dev/null
+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<Item=&'a i32>
+ | ^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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]
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ !"a"; //~ ERROR E0600
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+error[E0602]: unknown lint: `bogus`
+ |
+ = note: requested on the command line with `-D bogus`
+
+error: aborting due to previous error
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+error[E0603]: constant `PRIVATE` is private
+ --> $DIR/E0603.rs:16:5
+ |
+16 | SomeModule::PRIVATE; //~ ERROR E0603
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ 1u32 as char; //~ ERROR E0604
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<u8>; //~ ERROR E0605
+
+ let v = 0 as *const u8;
+ v as &u8; //~ ERROR E0605
+}
--- /dev/null
+error[E0605]: non-primitive cast: `u8` as `std::vec::Vec<u8>`
+ --> $DIR/E0605.rs:13:5
+ |
+13 | x as Vec<u8>; //~ 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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ &0u8 as u8; //~ ERROR E0606
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ 0u8[2]; //~ ERROR E0608
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+error[E0614]: type `u32` cannot be dereferenced
+ --> $DIR/E0614.rs:13:5
+ |
+13 | *y; //~ ERROR E0614
+ | ^^
+
+error: aborting due to previous error
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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, ...)`
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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]
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+ _ => {}
+ }
+}
+
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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(); } }
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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]
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T> {}
+trait Lt<'a> {}
+
+impl<'a> Lt<'a> for () {}
+impl<T> Id<T> for T {}
+
+fn free_fn_capture_hrtb_in_impl_trait()
+ -> impl for<'a> Id<impl Lt<'a>>
+ //~^ 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<impl Lt<'a>>
+ //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level
+ {
+ ()
+ }
+}
+
+fn main() {}
--- /dev/null
+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<impl Lt<'a>>
+ | ^^
+
+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<impl Lt<'a>>
+ | ^^
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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!();
+}
--- /dev/null
+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
+
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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!"),
- _ => {},
- };
-}
-
+++ /dev/null
-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
-
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-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
-
-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
|
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
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
+ });
+ };
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 ();
+ }
+ };
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
-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
|
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
|
0
} else {
n + sum_to(n - 1)
- //~^ ERROR the trait bound `u32: std::ops::Add<impl Foo>` is not satisfied
+ //~^ ERROR cannot add `impl Foo` to `u32`
}
}
= note: expected type `i32`
found type `u32`
-error[E0277]: the trait bound `u32: std::ops::Add<impl Foo>` is not satisfied
+error[E0277]: cannot add `impl Foo` to `u32`
--> $DIR/equality.rs:34:11
|
34 | n + sum_to(n - 1)
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--> $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)`
--> $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>`
= 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
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
--- /dev/null
+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
+
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
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
// 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
}
fn main() {
- not_an_lvalue!(99);
+ not_a_place!(99);
}
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
= 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
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<R>;
-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
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<R>;
-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
|
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<Self::Item>
-... |
-21 | | }
-22 | | }
- | |_^
+13 | impl<'a, T: 'a> Iterator for RepeatMut<'a, T> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
+ }
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
+ }
+}
--- /dev/null
+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
+
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
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
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
+ }
+}
--- /dev/null
+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)]
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<isize> { Some((2)) }
+ //~^ WARN unnecessary parentheses around function argument
+ }
+}
+
+the_worship_the_heart_lifts_above!(rah);
+and_the_heavens_reject_not!();
+
+fn main() {}
--- /dev/null
+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<isize> { 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)]
+ | ^^^^^^^^^^^^^
+
// 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)]
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);
}
}
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`
= 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`
= 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: T) {}
+22 | pub fn defiant<T>(_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`
= 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
|
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
27 | ping!();
| -------- in this macro invocation
|
- ::: <ping macros>
+ ::: <ping macros>:1:1
|
1 | ( ) => { pong ! ( ) ; }
| -------------------------
28 | deep!();
| -------- in this macro invocation (#1)
|
- ::: <deep macros>
+ ::: <deep macros>:1:1
|
1 | ( ) => { foo ! ( ) ; }
| ------------------------
| | in this macro invocation (#2)
| in this expansion of `deep!` (#1)
|
- ::: <foo macros>
+ ::: <foo macros>:1:1
|
1 | ( ) => { bar ! ( ) ; }
| ------------------------
| | in this macro invocation (#3)
| in this expansion of `foo!` (#2)
|
- ::: <bar macros>
+ ::: <bar macros>:1:1
|
1 | ( ) => { ping ! ( ) ; }
| -------------------------
| | in this macro invocation (#4)
| in this expansion of `bar!` (#3)
|
- ::: <ping macros>
+ ::: <ping macros>:1:1
|
1 | ( ) => { pong ! ( ) ; }
| -------------------------
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
+}
--- /dev/null
+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
+
// 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
}
-error[E0277]: the trait bound `{integer}: std::ops::Add<std::option::Option<{integer}>>` 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<std::option::Option<{integer}>>` is not implemented for `{integer}`
-error[E0277]: the trait bound `usize: std::ops::Sub<std::option::Option<{integer}>>` 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<std::option::Option<{integer}>>` 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}`
//~^ 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() {}
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
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
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"),
+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
|
25 | Xyz::A => println!("a"),
| ^^^^^^ use of borrowed `e`
-error: aborting due to previous error
+error: aborting due to 2 previous errors
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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`
+
--- /dev/null
+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
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T: Send> = Vec<T>;
+type VVec<'b, 'a: 'b> = Vec<&'a i32>;
+type WVec<'b, T: 'b> = Vec<T>;
+
+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);
+}
--- /dev/null
+warning[E0122]: generic bounds are ignored in type aliases
+ --> $DIR/param-bounds-ignored.rs:15:1
+ |
+15 | type SVec<T: Send> = Vec<T>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+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<T>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::marker::PhantomData;
+
+struct AssertSync<T: Sync>(PhantomData<T>);
+
+pub struct Foo {
+ bar: *const Bar,
+ phantom: PhantomData<Bar>,
+}
+
+pub struct Bar {
+ foo: *const Foo,
+ phantom: PhantomData<Foo>,
+}
+
+fn main() {
+ let _: AssertSync<Foo> = unimplemented!(); //~ ERROR E0275
+}
--- /dev/null
+error[E0275]: overflow evaluating the requirement `Foo: std::marker::Sync`
+ --> $DIR/recursive-requirements.rs:26:12
+ |
+26 | let _: AssertSync<Foo> = 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<Foo>`
+ = note: required because it appears within the type `Bar`
+ = note: required because it appears within the type `std::marker::PhantomData<Bar>`
+ = note: required because it appears within the type `Foo`
+
+error: aborting due to previous error
+
= 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
--> $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
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
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+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
+
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
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,
-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`
--> $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
--> $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`
= 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
= 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
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
+}
--- /dev/null
+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
+
-Subproject commit 7d7fef1690218bbb406cf3bcadf7bb29dbb40cc5
+Subproject commit ce47e529d29f0bf19b31ae80b37b467e42fb97e2
.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
}
let mut results = Vec::new();
let mut mismatch = Mismatch::new(0);
- for result in diff::lines(actual, expected) {
+ for result in diff::lines(expected, actual) {
match result {
diff::Result::Left(str) => {
if lines_since_mismatch >= context_size && lines_since_mismatch > 0 {
mismatch.lines.push(DiffLine::Context(line.to_owned()));
}
- mismatch.lines.push(DiffLine::Resulting(str.to_owned()));
+ mismatch.lines.push(DiffLine::Expected(str.to_owned()));
+ line_number += 1;
lines_since_mismatch = 0;
}
diff::Result::Right(str) => {
mismatch.lines.push(DiffLine::Context(line.to_owned()));
}
- mismatch.lines.push(DiffLine::Expected(str.to_owned()));
- line_number += 1;
+ mismatch.lines.push(DiffLine::Resulting(str.to_owned()));
lines_since_mismatch = 0;
}
diff::Result::Both(str, _) => {
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
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
-Subproject commit 919604e1ead8294c8ca14f101be4380ea1ea370c
+Subproject commit 61833b9aeab8bf8f0c0c0e42b7c96b6eceb37d0d
-Subproject commit 511321ae1c2fa3f0e334885fecf406dd6c882836
+Subproject commit dee42bda8156a28ead609080e27b02173bb9c29e
clap = "2.25.0"
[dependencies.mdbook]
-version = "0.0.28"
+version = "0.1.2"
default-features = false
extern crate clap;
use std::env;
-use std::io::{self, Write};
use std::path::{Path, PathBuf};
use clap::{App, ArgMatches, SubCommand, AppSettings};
};
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;
--- /dev/null
+[package]
+name = "rustdoc-themes"
+version = "0.1.0"
+authors = ["Guillaume Gomez <guillaume1.gomez@gmail.com>"]
+
+[[bin]]
+name = "rustdoc-themes"
+path = "main.rs"
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<P: AsRef<Path>>(folder_path: P) -> Vec<String> {
+ 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<String> = 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);
+ }
+}
-Subproject commit e0e3e22248cd14ebbe0253e9720261a0328bfc59
+Subproject commit 346238f49740d6c98102a6a59811b1625c73a9d7
"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