From af1e4f6d7ced700a03ed0f39259d7c9f6be1fb5e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 23 Oct 2017 13:34:22 +0200 Subject: [PATCH 01/17] add missing docs for MetadataExt --- src/libstd/sys/unix/ext/fs.rs | 246 ++++++++++++++++++++++++++++++++++ 1 file changed, 246 insertions(+) diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index 3e631ad40ac7f..d23cae40cfaff 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -215,36 +215,282 @@ impl OpenOptionsExt for OpenOptions { // casts and rely on manual lowering to `stat` if the raw type is desired. #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { + /// Returns the ID of the device containing the file. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::os::unix::fs::MetadataExt; + /// + /// # use std::io; + /// # fn f() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let dev_id = meta.dev(); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn dev(&self) -> u64; + /// Returns the inode number. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::os::unix::fs::MetadataExt; + /// + /// # use std::io; + /// # fn f() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let inode = meta.ino(); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn ino(&self) -> u64; + /// Returns the rights applied to this file. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::os::unix::fs::MetadataExt; + /// + /// # use std::io; + /// # fn f() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let mode = meta.mode(); + /// let user_has_write_access = mode & 0o200; + /// let user_has_read_write_access = mode & 0o600; + /// let group_has_read_access = mode & 0o040; + /// let others_have_exec_access = mode & 0o001; + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn mode(&self) -> u32; + /// Returns the number of hard links pointing to this file. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::os::unix::fs::MetadataExt; + /// + /// # use std::io; + /// # fn f() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let nb_hard_links = meta.nlink(); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn nlink(&self) -> u64; + /// Returns the user ID of the owner of this file. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::os::unix::fs::MetadataExt; + /// + /// # use std::io; + /// # fn f() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let user_id = meta.uid(); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn uid(&self) -> u32; + /// Returns the group ID of the owner of this file. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::os::unix::fs::MetadataExt; + /// + /// # use std::io; + /// # fn f() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let group_id = meta.gid(); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn gid(&self) -> u32; + /// Returns the device ID of this file (if it is a special one). + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::os::unix::fs::MetadataExt; + /// + /// # use std::io; + /// # fn f() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let device_id = meta.rdev(); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn rdev(&self) -> u64; + /// Returns the total size of this file in bytes. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::os::unix::fs::MetadataExt; + /// + /// # use std::io; + /// # fn f() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let file_size = meta.size(); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn size(&self) -> u64; + /// Returns the time of the last access to the file. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::os::unix::fs::MetadataExt; + /// + /// # use std::io; + /// # fn f() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let last_access_time = meta.atime(); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn atime(&self) -> i64; + /// Returns the time of the last access to the file in nanoseconds. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::os::unix::fs::MetadataExt; + /// + /// # use std::io; + /// # fn f() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let nano_last_access_time = meta.atime_nsec(); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn atime_nsec(&self) -> i64; + /// Returns the time of the last modification of the file. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::os::unix::fs::MetadataExt; + /// + /// # use std::io; + /// # fn f() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let last_modification_time = meta.mtime(); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn mtime(&self) -> i64; + /// Returns the time of the last modification of the file in nanoseconds. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::os::unix::fs::MetadataExt; + /// + /// # use std::io; + /// # fn f() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let nano_last_modification_time = meta.mtime_nsec(); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn mtime_nsec(&self) -> i64; + /// Returns the time of the last status change of the file. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::os::unix::fs::MetadataExt; + /// + /// # use std::io; + /// # fn f() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let last_status_change_time = meta.ctime(); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn ctime(&self) -> i64; + /// Returns the time of the last status change of the file in nanoseconds. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::os::unix::fs::MetadataExt; + /// + /// # use std::io; + /// # fn f() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let nano_last_status_change_time = meta.ctime_nsec(); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn ctime_nsec(&self) -> i64; + /// Returns the blocksize for filesystem I/O. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::os::unix::fs::MetadataExt; + /// + /// # use std::io; + /// # fn f() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let blocksize = meta.blksize(); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn blksize(&self) -> u64; + /// Returns the number of blocks allocated to the file, in 512-byte units. + /// + /// Please note that this may be smaller than `st_size / 512` when the file has holes. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::os::unix::fs::MetadataExt; + /// + /// # use std::io; + /// # fn f() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let blocks = meta.blocks(); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn blocks(&self) -> u64; } From 71534c45cc4e850c4265bc1c2491a522583e1185 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 1 Nov 2017 13:39:44 +0100 Subject: [PATCH 02/17] RwLock guards are Sync if T is Currently, the compiler requires `T` to also be `Send`. There is no reason for that. `&Rw{Read,Write}LockGuard` only provides a shared referenced to `T`, sending that across threads is safe if `T` is `Sync`. --- src/libstd/sync/rwlock.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 5555f364e6e8d..d59a0b65a6940 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -10,7 +10,6 @@ use cell::UnsafeCell; use fmt; -use marker; use mem; use ops::{Deref, DerefMut}; use ptr; @@ -102,7 +101,10 @@ pub struct RwLockReadGuard<'a, T: ?Sized + 'a> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T: ?Sized> !marker::Send for RwLockReadGuard<'a, T> {} +impl<'a, T: ?Sized> !Send for RwLockReadGuard<'a, T> {} + +#[stable(feature = "rwlock_guard_sync", since = "1.23.0")] +unsafe impl<'a, T: ?Sized + Sync> Sync for RwLockReadGuard<'a, T> {} /// RAII structure used to release the exclusive write access of a lock when /// dropped. @@ -121,7 +123,10 @@ pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T: ?Sized> !marker::Send for RwLockWriteGuard<'a, T> {} +impl<'a, T: ?Sized> !Send for RwLockWriteGuard<'a, T> {} + +#[stable(feature = "rwlock_guard_sync", since = "1.23.0")] +unsafe impl<'a, T: ?Sized + Sync> Sync for RwLockWriteGuard<'a, T> {} impl RwLock { /// Creates a new instance of an `RwLock` which is unlocked. From 568700097950cf66b09dfdf3d608d4f51e0f64ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 2 Nov 2017 11:26:46 +0200 Subject: [PATCH 03/17] Update the std::thread docs and clarify that panics can nowadays be caught --- src/libstd/thread/mod.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 28a33c7ec1465..8c60d9c7bf075 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -25,11 +25,15 @@ //! //! Fatal logic errors in Rust cause *thread panic*, during which //! a thread will unwind the stack, running destructors and freeing -//! owned resources. Thread panic is unrecoverable from within -//! the panicking thread (i.e. there is no 'try/catch' in Rust), but -//! the panic may optionally be detected from a different thread. If -//! the main thread panics, the application will exit with a non-zero -//! exit code. +//! owned resources. While not meant as a 'try/catch' mechanism, panics +//! in Rust can nonetheless be caught with +//! ['catch_unwind'](../../std/panic/fn.catch_unwind.html) and recovered +//! from, or alternatively be resumed with +//! ['resume_unwind'](../../std/panic/fn.resume_unwind.html). If the panic +//! is not caught the thread will exit, but the panic may optionally be +//! detected from a different thread with `join`. If the main thread panics +//! without the panic being caught, the application will exit with a +//! non-zero exit code. //! //! When the main thread of a Rust program terminates, the entire program shuts //! down, even if other threads are still running. However, this module provides From 283b4a1b0bcf94fed0ebc3bfd84e87d17ca1b587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 2 Nov 2017 18:29:52 +0200 Subject: [PATCH 04/17] Use ` instead of ' for function names --- src/libstd/thread/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 8c60d9c7bf075..da5965d801c25 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -27,9 +27,9 @@ //! a thread will unwind the stack, running destructors and freeing //! owned resources. While not meant as a 'try/catch' mechanism, panics //! in Rust can nonetheless be caught with -//! ['catch_unwind'](../../std/panic/fn.catch_unwind.html) and recovered +//! [`catch_unwind`](../../std/panic/fn.catch_unwind.html) and recovered //! from, or alternatively be resumed with -//! ['resume_unwind'](../../std/panic/fn.resume_unwind.html). If the panic +//! [`resume_unwind`](../../std/panic/fn.resume_unwind.html). If the panic //! is not caught the thread will exit, but the panic may optionally be //! detected from a different thread with `join`. If the main thread panics //! without the panic being caught, the application will exit with a From a12f5119101060909de1938d7d4a96854cc02780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 2 Nov 2017 18:30:02 +0200 Subject: [PATCH 05/17] Mention that panics can't possibly be caught when compiling with panic=abort --- src/libstd/thread/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index da5965d801c25..97220ad993b4a 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -26,7 +26,7 @@ //! Fatal logic errors in Rust cause *thread panic*, during which //! a thread will unwind the stack, running destructors and freeing //! owned resources. While not meant as a 'try/catch' mechanism, panics -//! in Rust can nonetheless be caught with +//! in Rust can nonetheless be caught (unless compiling with `panic=abort`) with //! [`catch_unwind`](../../std/panic/fn.catch_unwind.html) and recovered //! from, or alternatively be resumed with //! [`resume_unwind`](../../std/panic/fn.resume_unwind.html). If the panic From b86bba594023591f4d6c795cf4da115640c3a918 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 2 Nov 2017 19:09:31 +0200 Subject: [PATCH 06/17] Make join a link to the function's documentation --- src/libstd/thread/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 97220ad993b4a..ee49bf796b86f 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -31,7 +31,7 @@ //! from, or alternatively be resumed with //! [`resume_unwind`](../../std/panic/fn.resume_unwind.html). If the panic //! is not caught the thread will exit, but the panic may optionally be -//! detected from a different thread with `join`. If the main thread panics +//! detected from a different thread with [`join`]. If the main thread panics //! without the panic being caught, the application will exit with a //! non-zero exit code. //! From 784528b8da35d1f82c696887c293b215f0a1b4b4 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Sat, 28 Oct 2017 09:54:05 +0200 Subject: [PATCH 07/17] rustbuild: don't try to install rls if ToolState is not Testing The Dist Step is not ran in that case so we would end up trying to install something that we didn't dist. Signed-off-by: Marc-Antoine Perennou --- src/bootstrap/install.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 608924c9c28d1..1b5f6373c52f4 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -186,8 +186,11 @@ install!((self, builder, _config), install_cargo(builder, self.stage, self.target); }; Rls, "rls", _config.extended, only_hosts: true, { - builder.ensure(dist::Rls { stage: self.stage, target: self.target }); - install_rls(builder, self.stage, self.target); + if builder.ensure(dist::Rls { stage: self.stage, target: self.target }).is_some() { + install_rls(builder, self.stage, self.target); + } else { + println!("skipping Install RLS stage{} ({})", self.stage, self.target); + } }; Analysis, "analysis", _config.extended, only_hosts: false, { builder.ensure(dist::Analysis { From 6363b06ffccf1570e77641db8323d54a72f7db9e Mon Sep 17 00:00:00 2001 From: Ryan Scheel Date: Sat, 4 Nov 2017 20:53:27 -0700 Subject: [PATCH 08/17] Update reference link in doc's 404 It's currently linking to a page that says it's on the page I'm changing the link too. --- src/doc/not_found.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/not_found.md b/src/doc/not_found.md index 5d632ebc68f7a..ebe7c59313fa5 100644 --- a/src/doc/not_found.md +++ b/src/doc/not_found.md @@ -22,7 +22,7 @@ Some things that might be helpful to you though: # Reference * [The Rust official site](https://www.rust-lang.org) -* [The Rust reference](https://doc.rust-lang.org/reference.html) +* [The Rust reference](https://doc.rust-lang.org/reference/index.html) # Docs From 5abc5240730c3db243300444f0ee79847f4046fb Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Sat, 4 Nov 2017 14:13:44 -0500 Subject: [PATCH 09/17] rustdoc: add #[allow(unused)] to every doctest also modify the order crate attributes are applied, to have a better order of how things can override lints, either per-crate or per-test --- src/librustdoc/test.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 9316805b9322a..9bbd16355be38 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -337,15 +337,23 @@ pub fn make_test(s: &str, let mut prog = String::new(); - // First push any outer attributes from the example, assuming they - // are intended to be crate attributes. - prog.push_str(&crate_attrs); + if opts.attrs.is_empty() { + // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some + // lints that are commonly triggered in doctests. The crate-level test attributes are + // commonly used to make tests fail in case they trigger warnings, so having this there in + // that case may cause some tests to pass when they shouldn't have. + prog.push_str("#![allow(unused)]\n"); + } - // Next, any attributes for other aspects such as lints. + // Next, any attributes that came from the crate root via #![doc(test(attr(...)))]. for attr in &opts.attrs { prog.push_str(&format!("#![{}]\n", attr)); } + // Now push any outer attributes from the example, assuming they + // are intended to be crate attributes. + prog.push_str(&crate_attrs); + // Don't inject `extern crate std` because it's already injected by the // compiler. if !s.contains("extern crate") && !opts.no_crate_inject && cratename != Some("std") { From ce2768ab95cbac4c4b918c9f382cd5316e286a7a Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Sun, 5 Nov 2017 10:24:05 -0600 Subject: [PATCH 10/17] add #![allow(unused)] to the playground link rustdoc tests --- src/test/rustdoc/playground-arg.rs | 2 +- src/test/rustdoc/playground.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/rustdoc/playground-arg.rs b/src/test/rustdoc/playground-arg.rs index f0d55ef6e9fcd..478477dea61ed 100644 --- a/src/test/rustdoc/playground-arg.rs +++ b/src/test/rustdoc/playground-arg.rs @@ -21,4 +21,4 @@ pub fn dummy() {} // ensure that `extern crate foo;` was inserted into code snips automatically: -// @matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=extern%20crate%20foo%3B%0Afn%20main()%20%7B%0Ause%20foo%3A%3Adummy%3B%0Adummy()%3B%0A%7D"]' "Run" +// @matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=%23!%5Ballow(unused)%5D%0Aextern%20crate%20foo%3B%0Afn%20main()%20%7B%0Ause%20foo%3A%3Adummy%3B%0Adummy()%3B%0A%7D"]' "Run" diff --git a/src/test/rustdoc/playground.rs b/src/test/rustdoc/playground.rs index 9eb8dec51a7f2..8e193efaf8504 100644 --- a/src/test/rustdoc/playground.rs +++ b/src/test/rustdoc/playground.rs @@ -34,6 +34,6 @@ //! } //! ``` -// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=fn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D%0A"]' "Run" -// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=fn%20main()%20%7B%0Aprintln!(%22Hello%2C%20world!%22)%3B%0A%7D"]' "Run" -// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Bfeature(something)%5D%0A%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D%0A&version=nightly"]' "Run" +// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D%0A"]' "Run" +// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn%20main()%20%7B%0Aprintln!(%22Hello%2C%20world!%22)%3B%0A%7D"]' "Run" +// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D%0A&version=nightly"]' "Run" From 45a0aa4b4d4fb124f8db4e8b037465b457e66147 Mon Sep 17 00:00:00 2001 From: Alec Theriault Date: Sun, 5 Nov 2017 09:28:00 -0800 Subject: [PATCH 11/17] Pretty print parens around casts on the LHS of '<' When pretty printing a cast expression occuring on the LHS of a '<' or '<<' expression, we should add parens around the cast. Otherwise, the '<'/'<<' gets interpreted as the beginning of the generics for the type on the RHS of the cast. --- src/librustc/hir/print.rs | 9 +++++++++ src/libsyntax/print/pprust.rs | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 24a0b5fcea9b8..54f66453db87d 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1253,6 +1253,15 @@ impl<'a> State<'a> { Fixity::None => (prec + 1, prec + 1), }; + let left_prec = match (&lhs.node, op.node) { + // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is + // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead + // of `(x as i32) < ...`. We need to convince it _not_ to do that. + (&hir::ExprCast { .. }, hir::BinOp_::BiLt) | + (&hir::ExprCast { .. }, hir::BinOp_::BiShl) => parser::PREC_FORCE_PAREN, + _ => left_prec, + }; + self.print_expr_maybe_paren(lhs, left_prec)?; self.s.space()?; self.word_space(op.node.as_str())?; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 8a970fd409895..e6ffbb2cce9f3 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1986,6 +1986,15 @@ impl<'a> State<'a> { Fixity::None => (prec + 1, prec + 1), }; + let left_prec = match (&lhs.node, op.node) { + // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is + // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead + // of `(x as i32) < ...`. We need to convince it _not_ to do that. + (&ast::ExprKind::Cast { .. }, ast::BinOpKind::Lt) | + (&ast::ExprKind::Cast { .. }, ast::BinOpKind::Shl) => parser::PREC_FORCE_PAREN, + _ => left_prec, + }; + self.print_expr_maybe_paren(lhs, left_prec)?; self.s.space()?; self.word_space(op.node.to_string())?; From de959afab5042c44d78703050353cb5b20d442d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 3 Nov 2017 17:30:14 -0700 Subject: [PATCH 12/17] Handle anon lifetime arg being returned with named lifetime return type When there's a lifetime mismatch between an argument with an anonymous lifetime being returned in a method with a return type that has a named lifetime, show specialized lifetime error pointing at argument with a hint to give it an explicit lifetime matching the return type. ``` error[E0621]: explicit lifetime required in the type of `other` --> file2.rs:21:21 | 17 | fn bar(&self, other: Foo) -> Foo<'a> { | ----- consider changing the type of `other` to `Foo<'a>` ... 21 | other | ^^^^^ lifetime `'a` required ``` Follow up to #44124 and #42669. --- .../error_reporting/different_lifetimes.rs | 55 ++++++++++++------- .../error_reporting/named_anon_conflict.rs | 16 ++---- src/librustc/infer/error_reporting/util.rs | 1 + .../regions-infer-at-fn-not-param.rs | 2 +- ...oth-anon-regions-earlybound-regions.stderr | 6 +- .../lifetime-errors/ex4-anon-named-regions.rs | 30 ++++++++++ .../ex4-anon-named-regions.stderr | 11 ++++ 7 files changed, 87 insertions(+), 34 deletions(-) create mode 100644 src/test/ui/lifetime-errors/ex4-anon-named-regions.rs create mode 100644 src/test/ui/lifetime-errors/ex4-anon-named-regions.stderr diff --git a/src/librustc/infer/error_reporting/different_lifetimes.rs b/src/librustc/infer/error_reporting/different_lifetimes.rs index ee30db2625519..d7e0877d95c28 100644 --- a/src/librustc/infer/error_reporting/different_lifetimes.rs +++ b/src/librustc/infer/error_reporting/different_lifetimes.rs @@ -21,25 +21,42 @@ use hir::intravisit::{self, Visitor, NestedVisitorMap}; use infer::error_reporting::util::AnonymousArgInfo; impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - // This method prints the error message for lifetime errors when both the concerned regions - // are anonymous. - // Consider a case where we have - // fn foo(x: &mut Vec<&u8>, y: &u8) - // { x.push(y); }. - // The example gives - // fn foo(x: &mut Vec<&u8>, y: &u8) { - // --- --- these references are declared with different lifetimes... - // x.push(y); - // ^ ...but data from `y` flows into `x` here - // It has been extended for the case of structs too. - // Consider the example - // struct Ref<'a> { x: &'a u32 } - // fn foo(mut x: Vec, y: Ref) { - // --- --- these structs are declared with different lifetimes... - // x.push(y); - // ^ ...but data from `y` flows into `x` here - // } - // It will later be extended to trait objects. + /// Print the error message for lifetime errors when both the concerned regions are anonymous. + /// + /// Consider a case where we have + /// + /// ```no_run + /// fn foo(x: &mut Vec<&u8>, y: &u8) { + /// x.push(y); + /// } + /// ``` + /// + /// The example gives + /// + /// ```text + /// fn foo(x: &mut Vec<&u8>, y: &u8) { + /// --- --- these references are declared with different lifetimes... + /// x.push(y); + /// ^ ...but data from `y` flows into `x` here + /// ``` + /// + /// It has been extended for the case of structs too. + /// + /// Consider the example + /// + /// ```no_run + /// struct Ref<'a> { x: &'a u32 } + /// ``` + /// + /// ```text + /// fn foo(mut x: Vec, y: Ref) { + /// --- --- these structs are declared with different lifetimes... + /// x.push(y); + /// ^ ...but data from `y` flows into `x` here + /// } + /// ```` + /// + /// It will later be extended to trait objects. pub fn try_report_anon_anon_conflict(&self, error: &RegionResolutionError<'tcx>) -> bool { let (span, sub, sup) = match *error { ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup), diff --git a/src/librustc/infer/error_reporting/named_anon_conflict.rs b/src/librustc/infer/error_reporting/named_anon_conflict.rs index 80fb4ce8e0392..4563d955413e0 100644 --- a/src/librustc/infer/error_reporting/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/named_anon_conflict.rs @@ -16,18 +16,15 @@ use infer::region_inference::RegionResolutionError; use ty; impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - // This method generates the error message for the case when - // the function arguments consist of a named region and an anonymous - // region and corresponds to `ConcreteFailure(..)` + /// Generate an error message for when the function arguments consist of a named region and + /// an anonymous region and corresponds to `ConcreteFailure(..)` pub fn try_report_named_anon_conflict(&self, error: &RegionResolutionError<'tcx>) -> bool { let (span, sub, sup) = match *error { ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup), _ => return false, // inapplicable }; - debug!("try_report_named_anon_conflict(sub={:?}, sup={:?})", - sub, - sup); + debug!("try_report_named_anon_conflict(sub={:?}, sup={:?})", sub, sup); // Determine whether the sub and sup consist of one named region ('a) // and one anonymous (elided) region. If so, find the parameter arg @@ -53,10 +50,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { }; debug!("try_report_named_anon_conflict: named = {:?}", named); - debug!("try_report_named_anon_conflict: anon_arg_info = {:?}", - anon_arg_info); - debug!("try_report_named_anon_conflict: region_info = {:?}", - region_info); + debug!("try_report_named_anon_conflict: anon_arg_info = {:?}", anon_arg_info); + debug!("try_report_named_anon_conflict: region_info = {:?}", region_info); let (arg, new_ty, br, is_first, scope_def_id, is_impl_item) = (anon_arg_info.arg, anon_arg_info.arg_ty, @@ -101,6 +96,5 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .span_label(span, format!("lifetime `{}` required", named)) .emit(); return true; - } } diff --git a/src/librustc/infer/error_reporting/util.rs b/src/librustc/infer/error_reporting/util.rs index 47db3f1b7926a..6bcd98a7a6814 100644 --- a/src/librustc/infer/error_reporting/util.rs +++ b/src/librustc/infer/error_reporting/util.rs @@ -221,6 +221,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { _ => false, } } + ty::ReEarlyBound(_) => true, _ => false, } } diff --git a/src/test/compile-fail/regions-infer-at-fn-not-param.rs b/src/test/compile-fail/regions-infer-at-fn-not-param.rs index 0c250e38258ce..ec73bf90b6e52 100644 --- a/src/test/compile-fail/regions-infer-at-fn-not-param.rs +++ b/src/test/compile-fail/regions-infer-at-fn-not-param.rs @@ -21,7 +21,7 @@ struct not_parameterized2 { } fn take1<'a>(p: parameterized1) -> parameterized1<'a> { p } -//~^ ERROR mismatched types +//~^ ERROR explicit lifetime required in the type of `p` fn take3(p: not_parameterized1) -> not_parameterized1 { p } fn take4(p: not_parameterized2) -> not_parameterized2 { p } diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-earlybound-regions.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-earlybound-regions.stderr index 58f2cb94cec1d..6c5ed672604c3 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-earlybound-regions.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-earlybound-regions.stderr @@ -1,11 +1,11 @@ -error[E0623]: lifetime mismatch +error[E0621]: explicit lifetime required in the type of `y` --> $DIR/ex3-both-anon-regions-earlybound-regions.rs:17:12 | 13 | fn baz<'a, 'b, T>(x: &mut Vec<&'a T>, y: &T) - | ----- -- these two types are declared with different lifetimes... + | - consider changing the type of `y` to `&'a T` ... 17 | x.push(y); - | ^ ...but data from `y` flows into `x` here + | ^ lifetime `'a` required error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex4-anon-named-regions.rs b/src/test/ui/lifetime-errors/ex4-anon-named-regions.rs new file mode 100644 index 0000000000000..55752f753ef12 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex4-anon-named-regions.rs @@ -0,0 +1,30 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[derive(Clone)] +enum Foo<'a> { + Bar(&'a str), +} + +impl<'a> Foo<'a> { + fn bar(&self, other: Foo) -> Foo<'a> { + match *self { + Foo::Bar(s) => { + if s == "test" { + other + } else { + self.clone() + } + } + } + } +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex4-anon-named-regions.stderr b/src/test/ui/lifetime-errors/ex4-anon-named-regions.stderr new file mode 100644 index 0000000000000..4a127bbc551f0 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex4-anon-named-regions.stderr @@ -0,0 +1,11 @@ +error[E0621]: explicit lifetime required in the type of `other` + --> $DIR/ex4-anon-named-regions.rs:21:21 + | +17 | fn bar(&self, other: Foo) -> Foo<'a> { + | ----- consider changing the type of `other` to `Foo<'a>` +... +21 | other + | ^^^^^ lifetime `'a` required + +error: aborting due to previous error + From 005d14d5c810519517cc2507b5c304df7be9a6ed Mon Sep 17 00:00:00 2001 From: Alec Theriault Date: Sun, 5 Nov 2017 12:27:46 -0800 Subject: [PATCH 13/17] Added tests --- src/test/pretty/cast-lt.pp | 26 ++++++++++++++++++++++++++ src/test/pretty/cast-lt.rs | 24 ++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 src/test/pretty/cast-lt.pp create mode 100644 src/test/pretty/cast-lt.rs diff --git a/src/test/pretty/cast-lt.pp b/src/test/pretty/cast-lt.pp new file mode 100644 index 0000000000000..1e611f5075f69 --- /dev/null +++ b/src/test/pretty/cast-lt.pp @@ -0,0 +1,26 @@ +#![feature(prelude_import)] +#![no_std] +#[prelude_import] +use std::prelude::v1::*; +#[macro_use] +extern crate std as std; +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// pretty-compare-only +// pretty-mode:expanded +// pp-exact:cast-lt.pp + +// #4264 fixed-length vector types + +macro_rules! negative(( $ e : expr ) => { $ e < 0 }); + +fn main() { (1 as i32) < 0; } + diff --git a/src/test/pretty/cast-lt.rs b/src/test/pretty/cast-lt.rs new file mode 100644 index 0000000000000..c0ee62380ed00 --- /dev/null +++ b/src/test/pretty/cast-lt.rs @@ -0,0 +1,24 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// pretty-compare-only +// pretty-mode:expanded +// pp-exact:cast-lt.pp + +// #4264 fixed-length vector types + +macro_rules! negative { + ($e:expr) => { $e < 0 } +} + +fn main() { + negative!(1 as i32); +} + From 3761c0d246f8deb9ebb83567991bbbc0c090d75d Mon Sep 17 00:00:00 2001 From: Alec Theriault Date: Sun, 5 Nov 2017 20:53:46 -0800 Subject: [PATCH 14/17] Fix comments --- src/test/pretty/cast-lt.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/test/pretty/cast-lt.rs b/src/test/pretty/cast-lt.rs index c0ee62380ed00..87b5274545f38 100644 --- a/src/test/pretty/cast-lt.rs +++ b/src/test/pretty/cast-lt.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -12,8 +12,6 @@ // pretty-mode:expanded // pp-exact:cast-lt.pp -// #4264 fixed-length vector types - macro_rules! negative { ($e:expr) => { $e < 0 } } From c3ea358121e493ace14308e153b70692439fb154 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sun, 5 Nov 2017 09:20:59 -0500 Subject: [PATCH 15/17] Display all emission types in error msg if user inputs invalid option. before: ``` > rustc --emit foo error: unknown emission type: `foo` ``` after: ``` > rustc --emit foo error: unknown emission type: `foo` - expected one of: `llvm-bc`, `asm`, `llvm-ir`, `mir`, `obj`, `metadata`, `link`, `dep-info` ``` --- src/librustc/session/config.rs | 48 +++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 8401d493b9dbf..a27371926de86 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -138,6 +138,34 @@ impl OutputType { } } + fn from_shorthand(shorthand: &str) -> Option { + Some(match shorthand { + "asm" => OutputType::Assembly, + "llvm-ir" => OutputType::LlvmAssembly, + "mir" => OutputType::Mir, + "llvm-bc" => OutputType::Bitcode, + "obj" => OutputType::Object, + "metadata" => OutputType::Metadata, + "link" => OutputType::Exe, + "dep-info" => OutputType::DepInfo, + _ => return None, + }) + } + + fn shorthands_display() -> String { + format!( + "`{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`", + OutputType::Bitcode.shorthand(), + OutputType::Assembly.shorthand(), + OutputType::LlvmAssembly.shorthand(), + OutputType::Mir.shorthand(), + OutputType::Object.shorthand(), + OutputType::Metadata.shorthand(), + OutputType::Exe.shorthand(), + OutputType::DepInfo.shorthand(), + ) + } + pub fn extension(&self) -> &'static str { match *self { OutputType::Bitcode => "bc", @@ -1479,19 +1507,13 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) for list in matches.opt_strs("emit") { for output_type in list.split(',') { let mut parts = output_type.splitn(2, '='); - let output_type = match parts.next().unwrap() { - "asm" => OutputType::Assembly, - "llvm-ir" => OutputType::LlvmAssembly, - "mir" => OutputType::Mir, - "llvm-bc" => OutputType::Bitcode, - "obj" => OutputType::Object, - "metadata" => OutputType::Metadata, - "link" => OutputType::Exe, - "dep-info" => OutputType::DepInfo, - part => { - early_error(error_format, &format!("unknown emission type: `{}`", - part)) - } + let shorthand = parts.next().unwrap(); + let output_type = match OutputType::from_shorthand(shorthand) { + Some(output_type) => output_type, + None => early_error(error_format, &format!( + "unknown emission type: `{}` - expected one of: {}", + shorthand, OutputType::shorthands_display(), + )), }; let path = parts.next().map(PathBuf::from); output_types.insert(output_type, path); From 805333b2b5602e421124787c7f944c4a7eacdb62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 6 Nov 2017 21:02:31 -0800 Subject: [PATCH 16/17] review comments --- src/librustc/infer/error_reporting/named_anon_conflict.rs | 4 ++-- ... => ex1-return-one-existing-name-early-bound-in-struct.rs} | 0 ...ex1-return-one-existing-name-early-bound-in-struct.stderr} | 2 +- ...-regions.rs => ex2a-push-one-existing-name-early-bound.rs} | 0 ....stderr => ex2a-push-one-existing-name-early-bound.stderr} | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename src/test/ui/lifetime-errors/{ex4-anon-named-regions.rs => ex1-return-one-existing-name-early-bound-in-struct.rs} (100%) rename src/test/ui/lifetime-errors/{ex4-anon-named-regions.stderr => ex1-return-one-existing-name-early-bound-in-struct.stderr} (82%) rename src/test/ui/lifetime-errors/{ex3-both-anon-regions-earlybound-regions.rs => ex2a-push-one-existing-name-early-bound.rs} (100%) rename src/test/ui/lifetime-errors/{ex3-both-anon-regions-earlybound-regions.stderr => ex2a-push-one-existing-name-early-bound.stderr} (83%) diff --git a/src/librustc/infer/error_reporting/named_anon_conflict.rs b/src/librustc/infer/error_reporting/named_anon_conflict.rs index 4563d955413e0..6d3b950784097 100644 --- a/src/librustc/infer/error_reporting/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/named_anon_conflict.rs @@ -16,8 +16,8 @@ use infer::region_inference::RegionResolutionError; use ty; impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - /// Generate an error message for when the function arguments consist of a named region and - /// an anonymous region and corresponds to `ConcreteFailure(..)` + /// When given a `ConcreteFailure` for a function with arguments containing a named region and + /// an anonymous region, emit an descriptive diagnostic error. pub fn try_report_named_anon_conflict(&self, error: &RegionResolutionError<'tcx>) -> bool { let (span, sub, sup) = match *error { ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup), diff --git a/src/test/ui/lifetime-errors/ex4-anon-named-regions.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.rs similarity index 100% rename from src/test/ui/lifetime-errors/ex4-anon-named-regions.rs rename to src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.rs diff --git a/src/test/ui/lifetime-errors/ex4-anon-named-regions.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr similarity index 82% rename from src/test/ui/lifetime-errors/ex4-anon-named-regions.stderr rename to src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr index 4a127bbc551f0..d1660a620b6c7 100644 --- a/src/test/ui/lifetime-errors/ex4-anon-named-regions.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr @@ -1,5 +1,5 @@ error[E0621]: explicit lifetime required in the type of `other` - --> $DIR/ex4-anon-named-regions.rs:21:21 + --> $DIR/ex1-return-one-existing-name-early-bound-in-struct.rs:21:21 | 17 | fn bar(&self, other: Foo) -> Foo<'a> { | ----- consider changing the type of `other` to `Foo<'a>` diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-earlybound-regions.rs b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.rs similarity index 100% rename from src/test/ui/lifetime-errors/ex3-both-anon-regions-earlybound-regions.rs rename to src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.rs diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-earlybound-regions.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr similarity index 83% rename from src/test/ui/lifetime-errors/ex3-both-anon-regions-earlybound-regions.stderr rename to src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr index 6c5ed672604c3..980f14a51d9b1 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-earlybound-regions.stderr +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr @@ -1,5 +1,5 @@ error[E0621]: explicit lifetime required in the type of `y` - --> $DIR/ex3-both-anon-regions-earlybound-regions.rs:17:12 + --> $DIR/ex2a-push-one-existing-name-early-bound.rs:17:12 | 13 | fn baz<'a, 'b, T>(x: &mut Vec<&'a T>, y: &T) | - consider changing the type of `y` to `&'a T` From aa38a1ee5092fb81e23b0cbd215535de08ae7b28 Mon Sep 17 00:00:00 2001 From: Alec Theriault Date: Mon, 6 Nov 2017 22:18:14 -0800 Subject: [PATCH 17/17] Update comments in cast-lt.pp --- src/test/pretty/cast-lt.pp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/test/pretty/cast-lt.pp b/src/test/pretty/cast-lt.pp index 1e611f5075f69..b21158abfe551 100644 --- a/src/test/pretty/cast-lt.pp +++ b/src/test/pretty/cast-lt.pp @@ -4,7 +4,7 @@ use std::prelude::v1::*; #[macro_use] extern crate std as std; -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -18,8 +18,6 @@ // pretty-mode:expanded // pp-exact:cast-lt.pp -// #4264 fixed-length vector types - macro_rules! negative(( $ e : expr ) => { $ e < 0 }); fn main() { (1 as i32) < 0; }