From de2ecea3592c81eae5c0ce4e3d26729f7d552c34 Mon Sep 17 00:00:00 2001 From: CrLF0710 Date: Sun, 1 Jul 2018 16:51:44 +0800 Subject: [PATCH 01/34] Provide llvm-strip in llvm-tools component Shipping this tool gives people reliable way to reduce the generated executable size. I'm not sure if this strip tool is available from the llvm version current rust is built on. But let's take a look. @japaric --- src/bootstrap/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index b5d450b88392d..148f22bd0a5b6 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -204,7 +204,8 @@ const LLVM_TOOLS: &[&str] = &[ "llvm-objcopy", // used to transform ELFs into binary format which flashing tools consume "llvm-objdump", // used to disassemble programs "llvm-profdata", // used to inspect and merge files generated by profiles - "llvm-size", // prints the size of the linker sections of a program + "llvm-size", // used to prints the size of the linker sections of a program + "llvm-strip", // used to discard symbols from binary files to reduce their size ]; /// A structure representing a Rust compiler. From 603553458639cd65f3cc75b9b74f8176af81aa2b Mon Sep 17 00:00:00 2001 From: Kerollmops Date: Wed, 4 Jul 2018 21:54:45 +0200 Subject: [PATCH 02/34] Implement `Option::replace` in the core library --- src/libcore/option.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 20bc173f7e154..db0a807d152a4 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -845,6 +845,33 @@ impl Option { pub fn take(&mut self) -> Option { mem::replace(self, None) } + + /// Replaces the actual value in the option by the value given in parameter, + /// returning the old value if present, + /// leaving a `Some` in its place without deinitializing either one. + /// + /// [`Some`]: #variant.Some + /// + /// # Examples + /// + /// ``` + /// #![feature(option_replace)] + /// + /// let mut x = Some(2); + /// let old = x.replace(5); + /// assert_eq!(x, Some(5)); + /// assert_eq!(old, Some(2)); + /// + /// let mut x = None; + /// let old = x.replace(3); + /// assert_eq!(x, Some(3)); + /// assert_eq!(old, None); + /// ``` + #[inline] + #[unstable(feature = "option_replace", issue = "51998")] + pub fn replace(&mut self, value: T) -> Option { + mem::replace(self, Some(value)) + } } impl<'a, T: Clone> Option<&'a T> { From 2c2add6e0259efd9b375c849d1bde187972b65b3 Mon Sep 17 00:00:00 2001 From: Kevin Zajler Date: Sun, 8 Jul 2018 18:07:17 +0200 Subject: [PATCH 03/34] Update std::ascii::ASCIIExt deprecation notes --- src/libstd/ascii.rs | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index 6472edb0aa7d3..376410677346c 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -163,7 +163,9 @@ pub trait AsciiExt { /// # Note /// /// This method will be deprecated in favor of the identically-named - /// inherent methods on `u8`, `char`, `[u8]` and `str`. + /// inherent methods on `u8` and `char`. + /// For `[u8]` use `.iter().all(u8::is_ascii_alphabetic)`. + /// For `str` use `.bytes().all(u8::is_ascii_alphabetic)`. #[unstable(feature = "ascii_ctype", issue = "39658")] #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_alphabetic(&self) -> bool { unimplemented!(); } @@ -176,7 +178,9 @@ pub trait AsciiExt { /// # Note /// /// This method will be deprecated in favor of the identically-named - /// inherent methods on `u8`, `char`, `[u8]` and `str`. + /// inherent methods on `u8` and `char`. + /// For `[u8]` use `.iter().all(u8::is_ascii_uppercase)`. + /// For `str` use `.bytes().all(u8::is_ascii_uppercase)`. #[unstable(feature = "ascii_ctype", issue = "39658")] #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_uppercase(&self) -> bool { unimplemented!(); } @@ -189,7 +193,9 @@ pub trait AsciiExt { /// # Note /// /// This method will be deprecated in favor of the identically-named - /// inherent methods on `u8`, `char`, `[u8]` and `str`. + /// inherent methods on `u8` and `char`. + /// For `[u8]` use `.iter().all(u8::is_ascii_lowercase)`. + /// For `str` use `.bytes().all(u8::is_ascii_lowercase)`. #[unstable(feature = "ascii_ctype", issue = "39658")] #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_lowercase(&self) -> bool { unimplemented!(); } @@ -203,7 +209,9 @@ pub trait AsciiExt { /// # Note /// /// This method will be deprecated in favor of the identically-named - /// inherent methods on `u8`, `char`, `[u8]` and `str`. + /// inherent methods on `u8` and `char`. + /// For `[u8]` use `.iter().all(u8::is_ascii_alphanumeric)`. + /// For `str` use `.bytes().all(u8::is_ascii_alphanumeric)`. #[unstable(feature = "ascii_ctype", issue = "39658")] #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_alphanumeric(&self) -> bool { unimplemented!(); } @@ -216,7 +224,9 @@ pub trait AsciiExt { /// # Note /// /// This method will be deprecated in favor of the identically-named - /// inherent methods on `u8`, `char`, `[u8]` and `str`. + /// inherent methods on `u8` and `char`. + /// For `[u8]` use `.iter().all(u8::is_ascii_digit)`. + /// For `str` use `.bytes().all(u8::is_ascii_digit)`. #[unstable(feature = "ascii_ctype", issue = "39658")] #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_digit(&self) -> bool { unimplemented!(); } @@ -230,7 +240,9 @@ pub trait AsciiExt { /// # Note /// /// This method will be deprecated in favor of the identically-named - /// inherent methods on `u8`, `char`, `[u8]` and `str`. + /// inherent methods on `u8` and `char`. + /// For `[u8]` use `.iter().all(u8::is_ascii_hexdigit)`. + /// For `str` use `.bytes().all(u8::is_ascii_hexdigit)`. #[unstable(feature = "ascii_ctype", issue = "39658")] #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_hexdigit(&self) -> bool { unimplemented!(); } @@ -248,7 +260,9 @@ pub trait AsciiExt { /// # Note /// /// This method will be deprecated in favor of the identically-named - /// inherent methods on `u8`, `char`, `[u8]` and `str`. + /// inherent methods on `u8` and `char`. + /// For `[u8]` use `.iter().all(u8::is_ascii_punctuation)`. + /// For `str` use `.bytes().all(u8::is_ascii_punctuation)`. #[unstable(feature = "ascii_ctype", issue = "39658")] #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_punctuation(&self) -> bool { unimplemented!(); } @@ -261,7 +275,9 @@ pub trait AsciiExt { /// # Note /// /// This method will be deprecated in favor of the identically-named - /// inherent methods on `u8`, `char`, `[u8]` and `str`. + /// inherent methods on `u8` and `char`. + /// For `[u8]` use `.iter().all(u8::is_ascii_graphic)`. + /// For `str` use `.bytes().all(u8::is_ascii_graphic)`. #[unstable(feature = "ascii_ctype", issue = "39658")] #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_graphic(&self) -> bool { unimplemented!(); } @@ -291,7 +307,9 @@ pub trait AsciiExt { /// # Note /// /// This method will be deprecated in favor of the identically-named - /// inherent methods on `u8`, `char`, `[u8]` and `str`. + /// inherent methods on `u8` and `char`. + /// For `[u8]` use `.iter().all(u8::is_ascii_whitespace)`. + /// For `str` use `.bytes().all(u8::is_ascii_whitespace)`. #[unstable(feature = "ascii_ctype", issue = "39658")] #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_whitespace(&self) -> bool { unimplemented!(); } @@ -304,7 +322,9 @@ pub trait AsciiExt { /// # Note /// /// This method will be deprecated in favor of the identically-named - /// inherent methods on `u8`, `char`, `[u8]` and `str`. + /// inherent methods on `u8` and `char`. + /// For `[u8]` use `.iter().all(u8::is_ascii_control)`. + /// For `str` use `.bytes().all(u8::is_ascii_control)`. #[unstable(feature = "ascii_ctype", issue = "39658")] #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_control(&self) -> bool { unimplemented!(); } From af87a3594a9f852de0eb7fec7a2f2e7c5fdb4fe8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20RENAULT?= Date: Mon, 9 Jul 2018 14:50:54 +0200 Subject: [PATCH 04/34] Add a basic test to `Option::replace` --- src/libcore/tests/lib.rs | 1 + src/libcore/tests/option.rs | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 9d4a5213992a1..ca7db6e4639a5 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -44,6 +44,7 @@ #![feature(reverse_bits)] #![feature(iterator_find_map)] #![feature(slice_internals)] +#![feature(option_replace)] extern crate core; extern crate test; diff --git a/src/libcore/tests/option.rs b/src/libcore/tests/option.rs index 22109e28edd9b..bc3e61a4f541f 100644 --- a/src/libcore/tests/option.rs +++ b/src/libcore/tests/option.rs @@ -297,3 +297,18 @@ fn test_try() { } assert_eq!(try_option_err(), Err(NoneError)); } + +#[test] +fn test_replace() { + let mut x = Some(2); + let old = x.replace(5); + + assert_eq!(x, Some(5)); + assert_eq!(old, Some(2)); + + let mut x = None; + let old = x.replace(3); + + assert_eq!(x, Some(3)); + assert_eq!(old, None); +} From c8f0e6f210caccdaea7dc59fd970c81018ddfb00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20RENAULT?= Date: Mon, 9 Jul 2018 14:52:32 +0200 Subject: [PATCH 05/34] Fix the documentation of `Option::replace` --- src/libcore/option.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index db0a807d152a4..f3e823670aaab 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -848,7 +848,7 @@ impl Option { /// Replaces the actual value in the option by the value given in parameter, /// returning the old value if present, - /// leaving a `Some` in its place without deinitializing either one. + /// leaving a [`Some`] in its place without deinitializing either one. /// /// [`Some`]: #variant.Some /// From 5336df7e3c8df350c20ec6e3be5a3afffd0a2d54 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Wed, 11 Jul 2018 16:26:15 +0900 Subject: [PATCH 06/34] Add UI tests for diagnostics comparing types They highlight how types are displayed in those cases, and will show how the current output is altered by the next patch. --- src/test/ui/type-mismatch.rs | 86 ++++++ src/test/ui/type-mismatch.stderr | 432 +++++++++++++++++++++++++++++++ 2 files changed, 518 insertions(+) create mode 100644 src/test/ui/type-mismatch.rs create mode 100644 src/test/ui/type-mismatch.stderr diff --git a/src/test/ui/type-mismatch.rs b/src/test/ui/type-mismatch.rs new file mode 100644 index 0000000000000..2592b07eda781 --- /dev/null +++ b/src/test/ui/type-mismatch.rs @@ -0,0 +1,86 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Qux {} +struct A; +struct B; +impl Qux for A {} +impl Qux for B {} + +struct Foo(T, U, V); + +struct foo; +struct bar; + +fn want(t: T) {} + +fn have_usize(f: usize) { + want::(f); //~ ERROR mismatched types + want::(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types +} + +fn have_foo(f: foo) { + want::(f); //~ ERROR mismatched types + want::(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types +} + +fn have_foo_foo(f: Foo) { + want::(f); //~ ERROR mismatched types + want::(f); //~ ERROR mismatched types + want::(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::<&Foo>(f); //~ ERROR mismatched types + want::<&Foo>(f); //~ ERROR mismatched types +} + +fn have_foo_foo_b(f: Foo) { + want::(f); //~ ERROR mismatched types + want::(f); //~ ERROR mismatched types + want::(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::<&Foo>(f); //~ ERROR mismatched types + want::<&Foo>(f); //~ ERROR mismatched types +} + +fn have_foo_foo_b_a(f: Foo) { + want::(f); //~ ERROR mismatched types + want::(f); //~ ERROR mismatched types + want::(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::<&Foo>(f); //~ ERROR mismatched types + want::<&Foo>(f); //~ ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/type-mismatch.stderr b/src/test/ui/type-mismatch.stderr new file mode 100644 index 0000000000000..634f3b402a128 --- /dev/null +++ b/src/test/ui/type-mismatch.stderr @@ -0,0 +1,432 @@ +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:25:17 + | +LL | want::(f); //~ ERROR mismatched types + | ^ expected struct `foo`, found usize + | + = note: expected type `foo` + found type `usize` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:26:17 + | +LL | want::(f); //~ ERROR mismatched types + | ^ expected struct `bar`, found usize + | + = note: expected type `bar` + found type `usize` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:27:24 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected struct `Foo`, found usize + | + = note: expected type `Foo` + found type `usize` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:28:27 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected struct `Foo`, found usize + | + = note: expected type `Foo` + found type `usize` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:29:22 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected struct `Foo`, found usize + | + = note: expected type `Foo` + found type `usize` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:30:25 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected struct `Foo`, found usize + | + = note: expected type `Foo` + found type `usize` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:31:22 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected struct `Foo`, found usize + | + = note: expected type `Foo` + found type `usize` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:32:25 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected struct `Foo`, found usize + | + = note: expected type `Foo` + found type `usize` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:36:19 + | +LL | want::(f); //~ ERROR mismatched types + | ^ expected usize, found struct `foo` + | + = note: expected type `usize` + found type `foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:37:17 + | +LL | want::(f); //~ ERROR mismatched types + | ^ expected struct `bar`, found struct `foo` + | + = note: expected type `bar` + found type `foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:38:24 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected struct `Foo`, found struct `foo` + | + = note: expected type `Foo` + found type `foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:39:27 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected struct `Foo`, found struct `foo` + | + = note: expected type `Foo` + found type `foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:40:22 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected struct `Foo`, found struct `foo` + | + = note: expected type `Foo` + found type `foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:41:25 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected struct `Foo`, found struct `foo` + | + = note: expected type `Foo` + found type `foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:42:22 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected struct `Foo`, found struct `foo` + | + = note: expected type `Foo` + found type `foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:43:25 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected struct `Foo`, found struct `foo` + | + = note: expected type `Foo` + found type `foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:47:19 + | +LL | want::(f); //~ ERROR mismatched types + | ^ expected usize, found struct `Foo` + | + = note: expected type `usize` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:48:17 + | +LL | want::(f); //~ ERROR mismatched types + | ^ expected struct `foo`, found struct `Foo` + | + = note: expected type `foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:49:17 + | +LL | want::(f); //~ ERROR mismatched types + | ^ expected struct `bar`, found struct `Foo` + | + = note: expected type `bar` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:50:24 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected usize, found struct `foo` + | + = note: expected type `Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:51:27 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected usize, found struct `foo` + | + = note: expected type `Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:52:25 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected struct `B`, found struct `A` + | + = note: expected type `Foo<_, B, _>` + found type `Foo<_, A, _>` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:53:22 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected struct `bar`, found struct `foo` + | + = note: expected type `Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:54:25 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected struct `bar`, found struct `foo` + | + = note: expected type `Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:55:23 + | +LL | want::<&Foo>(f); //~ ERROR mismatched types + | ^ + | | + | expected &Foo, found struct `Foo` + | help: consider borrowing here: `&f` + | + = note: expected type `&Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:56:26 + | +LL | want::<&Foo>(f); //~ ERROR mismatched types + | ^ expected reference, found struct `Foo` + | + = note: expected type `&Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:60:19 + | +LL | want::(f); //~ ERROR mismatched types + | ^ expected usize, found struct `Foo` + | + = note: expected type `usize` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:61:17 + | +LL | want::(f); //~ ERROR mismatched types + | ^ expected struct `foo`, found struct `Foo` + | + = note: expected type `foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:62:17 + | +LL | want::(f); //~ ERROR mismatched types + | ^ expected struct `bar`, found struct `Foo` + | + = note: expected type `bar` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:63:24 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected usize, found struct `foo` + | + = note: expected type `Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:64:27 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected usize, found struct `foo` + | + = note: expected type `Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:65:22 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected struct `A`, found struct `B` + | + = note: expected type `Foo<_, A, _>` + found type `Foo<_, B, _>` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:66:22 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected struct `bar`, found struct `foo` + | + = note: expected type `Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:67:25 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected struct `bar`, found struct `foo` + | + = note: expected type `Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:68:23 + | +LL | want::<&Foo>(f); //~ ERROR mismatched types + | ^ expected &Foo, found struct `Foo` + | + = note: expected type `&Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:69:26 + | +LL | want::<&Foo>(f); //~ ERROR mismatched types + | ^ + | | + | expected reference, found struct `Foo` + | help: consider borrowing here: `&f` + | + = note: expected type `&Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:73:19 + | +LL | want::(f); //~ ERROR mismatched types + | ^ expected usize, found struct `Foo` + | + = note: expected type `usize` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:74:17 + | +LL | want::(f); //~ ERROR mismatched types + | ^ expected struct `foo`, found struct `Foo` + | + = note: expected type `foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:75:17 + | +LL | want::(f); //~ ERROR mismatched types + | ^ expected struct `bar`, found struct `Foo` + | + = note: expected type `bar` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:76:24 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected usize, found struct `foo` + | + = note: expected type `Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:77:27 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected usize, found struct `foo` + | + = note: expected type `Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:78:22 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected struct `A`, found struct `B` + | + = note: expected type `Foo<_, A, B>` + found type `Foo<_, B, A>` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:79:25 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected struct `B`, found struct `A` + | + = note: expected type `Foo<_, _, B>` + found type `Foo<_, _, A>` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:80:22 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected struct `bar`, found struct `foo` + | + = note: expected type `Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:81:25 + | +LL | want::>(f); //~ ERROR mismatched types + | ^ expected struct `bar`, found struct `foo` + | + = note: expected type `Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:82:23 + | +LL | want::<&Foo>(f); //~ ERROR mismatched types + | ^ expected &Foo, found struct `Foo` + | + = note: expected type `&Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:83:26 + | +LL | want::<&Foo>(f); //~ ERROR mismatched types + | ^ expected reference, found struct `Foo` + | + = note: expected type `&Foo` + found type `Foo` + +error: aborting due to 47 previous errors + +For more information about this error, try `rustc --explain E0308`. From b5c2b79fb21f835fd20f176ca0f9c4d7e89ac095 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Wed, 11 Jul 2018 15:24:24 +0900 Subject: [PATCH 07/34] Don't display default generic parameters in diagnostics that compare types. Fixes #52097 --- src/librustc/infer/error_reporting/mod.rs | 70 ++++++++++++++++++++--- src/test/ui/type-mismatch.stderr | 48 ++++++++-------- 2 files changed, 87 insertions(+), 31 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 1377176bc7fb8..062145058193d 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -60,13 +60,13 @@ use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePa use super::region_constraints::GenericKind; use super::lexical_region_resolve::RegionResolutionError; -use std::fmt; +use std::{cmp, fmt}; use hir; use hir::map as hir_map; use hir::def_id::DefId; use middle::region; use traits::{ObligationCause, ObligationCauseCode}; -use ty::{self, Region, Ty, TyCtxt, TypeFoldable, TypeVariants}; +use ty::{self, subst::Subst, Region, Ty, TyCtxt, TypeFoldable, TypeVariants}; use ty::error::TypeError; use syntax::ast::DUMMY_NODE_ID; use syntax_pos::{Pos, Span}; @@ -672,6 +672,43 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } + /// For generic types with parameters with defaults, remove the parameters corresponding to + /// the defaults. This repeats a lot of the logic found in `PrintContext::parameterized`. + fn strip_generic_default_params( + &self, + def_id: DefId, + substs: &ty::subst::Substs<'tcx> + ) -> &'tcx ty::subst::Substs<'tcx> { + let generics = self.tcx.generics_of(def_id); + let mut num_supplied_defaults = 0; + let mut type_params = generics.params.iter().rev().filter_map(|param| match param.kind { + ty::GenericParamDefKind::Lifetime => None, + ty::GenericParamDefKind::Type { has_default, .. } => { + Some((param.def_id, has_default)) + } + }).peekable(); + let has_default = { + let has_default = type_params.peek().map(|(_, has_default)| has_default); + *has_default.unwrap_or(&false) + }; + if has_default { + let types = substs.types().rev(); + for ((def_id, has_default), actual) in type_params.zip(types) { + if !has_default { + break; + } + if self.tcx.type_of(def_id).subst(self.tcx, substs) != actual { + break; + } + num_supplied_defaults += 1; + } + } + let len = generics.params.len(); + let mut generics = generics.clone(); + generics.params.truncate(len - num_supplied_defaults); + substs.truncate_to(self.tcx, &generics) + } + /// Compare two given types, eliding parts that are the same between them and highlighting /// relevant differences, and return two representation of those types for highlighted printing. fn cmp(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> (DiagnosticStyledString, DiagnosticStyledString) { @@ -713,6 +750,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { match (&t1.sty, &t2.sty) { (&ty::TyAdt(def1, sub1), &ty::TyAdt(def2, sub2)) => { + let sub_no_defaults_1 = self.strip_generic_default_params(def1.did, sub1); + let sub_no_defaults_2 = self.strip_generic_default_params(def2.did, sub2); let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new()); let path1 = self.tcx.item_path_str(def1.did.clone()); let path2 = self.tcx.item_path_str(def2.did.clone()); @@ -728,8 +767,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { values.0.push_normal(path1); values.1.push_normal(path2); + // Avoid printing out default generic parameters that are common to both + // types. + let len1 = sub_no_defaults_1.len(); + let len2 = sub_no_defaults_2.len(); + let common_len = cmp::min(len1, len2); + let remainder1: Vec<_> = sub1.types().skip(common_len).collect(); + let remainder2: Vec<_> = sub2.types().skip(common_len).collect(); + let common_default_params = + remainder1.iter().rev().zip(remainder2.iter().rev()) + .filter(|(a, b)| a == b).count(); + let len = sub1.len() - common_default_params; + // Only draw `<...>` if there're lifetime/type arguments. - let len = sub1.len(); if len > 0 { values.0.push_normal("<"); values.1.push_normal("<"); @@ -774,7 +824,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // ^ elided type as this type argument was the same in both sides let type_arguments = sub1.types().zip(sub2.types()); let regions_len = sub1.regions().collect::>().len(); - for (i, (ta1, ta2)) in type_arguments.enumerate() { + for (i, (ta1, ta2)) in type_arguments.take(len).enumerate() { let i = i + regions_len; if ta1 == ta2 { values.0.push_normal("_"); @@ -804,7 +854,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { &mut values.0, &mut values.1, path1.clone(), - sub1, + sub_no_defaults_1, path2.clone(), &t2, ).is_some() @@ -816,8 +866,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Bar // Foo> // ------- this type argument is exactly the same as the other type - if self.cmp_type_arg(&mut values.1, &mut values.0, path2, sub2, path1, &t1) - .is_some() + if self.cmp_type_arg( + &mut values.1, + &mut values.0, + path2, + sub_no_defaults_2, + path1, + &t1, + ).is_some() { return values; } diff --git a/src/test/ui/type-mismatch.stderr b/src/test/ui/type-mismatch.stderr index 634f3b402a128..4ba1a7f37c4a1 100644 --- a/src/test/ui/type-mismatch.stderr +++ b/src/test/ui/type-mismatch.stderr @@ -112,7 +112,7 @@ error[E0308]: mismatched types LL | want::>(f); //~ ERROR mismatched types | ^ expected struct `Foo`, found struct `foo` | - = note: expected type `Foo` + = note: expected type `Foo` found type `foo` error[E0308]: mismatched types @@ -121,7 +121,7 @@ error[E0308]: mismatched types LL | want::>(f); //~ ERROR mismatched types | ^ expected struct `Foo`, found struct `foo` | - = note: expected type `Foo` + = note: expected type `Foo` found type `foo` error[E0308]: mismatched types @@ -158,7 +158,7 @@ LL | want::(f); //~ ERROR mismatched types | ^ expected struct `foo`, found struct `Foo` | = note: expected type `foo` - found type `Foo` + found type `Foo` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:49:17 @@ -175,8 +175,8 @@ error[E0308]: mismatched types LL | want::>(f); //~ ERROR mismatched types | ^ expected usize, found struct `foo` | - = note: expected type `Foo` - found type `Foo` + = note: expected type `Foo` + found type `Foo` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:51:27 @@ -184,8 +184,8 @@ error[E0308]: mismatched types LL | want::>(f); //~ ERROR mismatched types | ^ expected usize, found struct `foo` | - = note: expected type `Foo` - found type `Foo` + = note: expected type `Foo` + found type `Foo` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:52:25 @@ -193,8 +193,8 @@ error[E0308]: mismatched types LL | want::>(f); //~ ERROR mismatched types | ^ expected struct `B`, found struct `A` | - = note: expected type `Foo<_, B, _>` - found type `Foo<_, A, _>` + = note: expected type `Foo<_, B>` + found type `Foo<_, A>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:53:22 @@ -202,8 +202,8 @@ error[E0308]: mismatched types LL | want::>(f); //~ ERROR mismatched types | ^ expected struct `bar`, found struct `foo` | - = note: expected type `Foo` - found type `Foo` + = note: expected type `Foo` + found type `Foo` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:54:25 @@ -211,8 +211,8 @@ error[E0308]: mismatched types LL | want::>(f); //~ ERROR mismatched types | ^ expected struct `bar`, found struct `foo` | - = note: expected type `Foo` - found type `Foo` + = note: expected type `Foo` + found type `Foo` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:55:23 @@ -251,7 +251,7 @@ LL | want::(f); //~ ERROR mismatched types | ^ expected struct `foo`, found struct `Foo` | = note: expected type `foo` - found type `Foo` + found type `Foo` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:62:17 @@ -268,8 +268,8 @@ error[E0308]: mismatched types LL | want::>(f); //~ ERROR mismatched types | ^ expected usize, found struct `foo` | - = note: expected type `Foo` - found type `Foo` + = note: expected type `Foo` + found type `Foo` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:64:27 @@ -277,8 +277,8 @@ error[E0308]: mismatched types LL | want::>(f); //~ ERROR mismatched types | ^ expected usize, found struct `foo` | - = note: expected type `Foo` - found type `Foo` + = note: expected type `Foo` + found type `Foo` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:65:22 @@ -286,8 +286,8 @@ error[E0308]: mismatched types LL | want::>(f); //~ ERROR mismatched types | ^ expected struct `A`, found struct `B` | - = note: expected type `Foo<_, A, _>` - found type `Foo<_, B, _>` + = note: expected type `Foo<_, A>` + found type `Foo<_, B>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:66:22 @@ -295,8 +295,8 @@ error[E0308]: mismatched types LL | want::>(f); //~ ERROR mismatched types | ^ expected struct `bar`, found struct `foo` | - = note: expected type `Foo` - found type `Foo` + = note: expected type `Foo` + found type `Foo` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:67:25 @@ -304,8 +304,8 @@ error[E0308]: mismatched types LL | want::>(f); //~ ERROR mismatched types | ^ expected struct `bar`, found struct `foo` | - = note: expected type `Foo` - found type `Foo` + = note: expected type `Foo` + found type `Foo` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:68:23 From 0d7b2e6e28dbaada91aac03964b345036894967a Mon Sep 17 00:00:00 2001 From: ljedrz Date: Thu, 12 Jul 2018 10:26:22 +0200 Subject: [PATCH 08/34] Deny bare trait objects in src/librustc_save_analysis --- src/librustc_save_analysis/json_dumper.rs | 4 ++-- src/librustc_save_analysis/lib.rs | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index 1b09df16a7d16..2fe7d73de8aa0 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -46,7 +46,7 @@ impl<'b, W: Write> DumpOutput for WriteOutput<'b, W> { } pub struct CallbackOutput<'b> { - callback: &'b mut FnMut(&Analysis), + callback: &'b mut dyn FnMut(&Analysis), } impl<'b> DumpOutput for CallbackOutput<'b> { @@ -67,7 +67,7 @@ impl<'b, W: Write> JsonDumper> { impl<'b> JsonDumper> { pub fn with_callback( - callback: &'b mut FnMut(&Analysis), + callback: &'b mut dyn FnMut(&Analysis), config: Config, ) -> JsonDumper> { JsonDumper { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 447b5f1fe47e7..055fbb236d8fa 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -13,6 +13,7 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(custom_attribute)] #![allow(unused_attributes)] +#![deny(bare_trait_objects)] #![recursion_limit="256"] @@ -1088,7 +1089,7 @@ impl<'a> SaveHandler for DumpHandler<'a> { /// Call a callback with the results of save-analysis. pub struct CallbackHandler<'b> { - pub callback: &'b mut FnMut(&rls_data::Analysis), + pub callback: &'b mut dyn FnMut(&rls_data::Analysis), } impl<'b> SaveHandler for CallbackHandler<'b> { From f29ac5a680f57851f68ad2584972e605402156a9 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Thu, 12 Jul 2018 10:57:04 +0200 Subject: [PATCH 09/34] Deny bare trait objects in librustc_typeck --- src/librustc_typeck/astconv.rs | 2 +- src/librustc_typeck/check/closure.rs | 4 ++-- src/librustc_typeck/check/coercion.rs | 4 ++-- src/librustc_typeck/check/writeback.rs | 6 +++--- src/librustc_typeck/coherence/builtin.rs | 2 +- src/librustc_typeck/collect.rs | 6 +++--- src/librustc_typeck/diagnostics.rs | 4 ++-- src/librustc_typeck/lib.rs | 1 + 8 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 2e467d315bedd..5e38c0bbcb4a3 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -98,7 +98,7 @@ struct ParamRange { /// This type must not appear anywhere in other converted types. const TRAIT_OBJECT_DUMMY_SELF: ty::TypeVariants<'static> = ty::TyInfer(ty::FreshTy(0)); -impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { +impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { pub fn ast_region_to_region(&self, lifetime: &hir::Lifetime, def: Option<&ty::GenericParamDef>) diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index cfe9e420c5fee..f2745d06390e8 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -604,7 +604,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// If there is no expected signature, then we will convert the /// types that the user gave into a signature. fn supplied_sig_of_closure(&self, decl: &hir::FnDecl) -> ty::PolyFnSig<'tcx> { - let astconv: &AstConv = self; + let astconv: &dyn AstConv = self; // First, convert the types that the user supplied (if any). let supplied_arguments = decl.inputs.iter().map(|a| astconv.ast_ty_to_ty(a)); @@ -630,7 +630,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// so should yield an error, but returns back a signature where /// all parameters are of type `TyErr`. fn error_sig_of_closure(&self, decl: &hir::FnDecl) -> ty::PolyFnSig<'tcx> { - let astconv: &AstConv = self; + let astconv: &dyn AstConv = self; let supplied_arguments = decl.inputs.iter().map(|a| { // Convert the types that the user supplied (if any), but ignore them. diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index e276dcff0601d..e3b0b8cccf31c 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -1071,7 +1071,7 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> pub fn coerce_forced_unit<'a>(&mut self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, cause: &ObligationCause<'tcx>, - augment_error: &mut FnMut(&mut DiagnosticBuilder), + augment_error: &mut dyn FnMut(&mut DiagnosticBuilder), label_unit_as_expected: bool) { self.coerce_inner(fcx, @@ -1090,7 +1090,7 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> cause: &ObligationCause<'tcx>, expression: Option<&'gcx hir::Expr>, mut expression_ty: Ty<'tcx>, - augment_error: Option<&mut FnMut(&mut DiagnosticBuilder)>, + augment_error: Option<&mut dyn FnMut(&mut DiagnosticBuilder)>, label_expression_as_expected: bool) { // Incorporate whatever type inference information we have diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 2445cae98607a..b7233217d5f3b 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -526,7 +526,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } } - fn resolve(&self, x: &T, span: &Locatable) -> T::Lifted + fn resolve(&self, x: &T, span: &dyn Locatable) -> T::Lifted where T: TypeFoldable<'tcx> + ty::Lift<'gcx>, { @@ -580,14 +580,14 @@ impl Locatable for hir::HirId { struct Resolver<'cx, 'gcx: 'cx + 'tcx, 'tcx: 'cx> { tcx: TyCtxt<'cx, 'gcx, 'tcx>, infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, - span: &'cx Locatable, + span: &'cx dyn Locatable, body: &'gcx hir::Body, } impl<'cx, 'gcx, 'tcx> Resolver<'cx, 'gcx, 'tcx> { fn new( fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>, - span: &'cx Locatable, + span: &'cx dyn Locatable, body: &'gcx hir::Body, ) -> Resolver<'cx, 'gcx, 'tcx> { Resolver { diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index dde1368026068..393904583ca42 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -212,7 +212,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>, let cause = ObligationCause::misc(span, impl_node_id); let check_mutbl = |mt_a: ty::TypeAndMut<'gcx>, mt_b: ty::TypeAndMut<'gcx>, - mk_ptr: &Fn(Ty<'gcx>) -> Ty<'gcx>| { + mk_ptr: &dyn Fn(Ty<'gcx>) -> Ty<'gcx>| { if (mt_a.mutbl, mt_b.mutbl) == (hir::MutImmutable, hir::MutMutable) { infcx.report_mismatched_types(&cause, mk_ptr(mt_b.ty), diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index fa2f9885964de..5fa98e3ebe695 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1244,7 +1244,7 @@ fn impl_polarity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } // Is it marked with ?Sized -fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, +fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &dyn AstConv<'gcx, 'tcx>, ast_bounds: &[hir::GenericBound], span: Span) -> bool { @@ -1598,7 +1598,7 @@ pub enum SizedByDefault { Yes, No, } /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the /// built-in trait (formerly known as kind): Send. -pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, +pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &dyn AstConv<'gcx, 'tcx>, param_ty: Ty<'tcx>, ast_bounds: &[hir::GenericBound], sized_by_default: SizedByDefault, @@ -1646,7 +1646,7 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, /// because this can be anywhere from 0 predicates (`T:?Sized` adds no /// predicates) to 1 (`T:Foo`) to many (`T:Bar` adds `T:Bar` /// and `::X == i32`). -fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>, +fn predicates_from_bound<'tcx>(astconv: &dyn AstConv<'tcx, 'tcx>, param_ty: Ty<'tcx>, bound: &hir::GenericBound) -> Vec> diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index dd09bf96da594..4d957c9aa4520 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -2338,7 +2338,7 @@ Rust does not currently support this. A simple example that causes this error: ```compile_fail,E0225 fn main() { - let _: Box; + let _: Box; } ``` @@ -2348,7 +2348,7 @@ auto traits. For example, the following compiles correctly: ``` fn main() { - let _: Box; + let _: Box; } ``` "##, diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index b18e5ca54ff47..b50f55effad45 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -70,6 +70,7 @@ This API is completely unstable and subject to change. html_root_url = "https://doc.rust-lang.org/nightly/")] #![allow(non_camel_case_types)] +#![deny(bare_trait_objects)] #![feature(box_patterns)] #![feature(box_syntax)] From 0878453119ebced0182128f5661bdc3722279fae Mon Sep 17 00:00:00 2001 From: ljedrz Date: Thu, 12 Jul 2018 12:49:29 +0200 Subject: [PATCH 10/34] Deny bare trait objects in src/libserialize --- src/libserialize/json.rs | 16 ++++++++-------- src/libserialize/lib.rs | 2 ++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 9959d5ce40d2d..88cc93731131d 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -371,7 +371,7 @@ impl From for EncoderError { pub type EncodeResult = Result<(), EncoderError>; pub type DecodeResult = Result; -fn escape_str(wr: &mut fmt::Write, v: &str) -> EncodeResult { +fn escape_str(wr: &mut dyn fmt::Write, v: &str) -> EncodeResult { wr.write_str("\"")?; let mut start = 0; @@ -433,11 +433,11 @@ fn escape_str(wr: &mut fmt::Write, v: &str) -> EncodeResult { Ok(()) } -fn escape_char(writer: &mut fmt::Write, v: char) -> EncodeResult { +fn escape_char(writer: &mut dyn fmt::Write, v: char) -> EncodeResult { escape_str(writer, v.encode_utf8(&mut [0; 4])) } -fn spaces(wr: &mut fmt::Write, mut n: usize) -> EncodeResult { +fn spaces(wr: &mut dyn fmt::Write, mut n: usize) -> EncodeResult { const BUF: &'static str = " "; while n >= BUF.len() { @@ -461,14 +461,14 @@ fn fmt_number_or_null(v: f64) -> string::String { /// A structure for implementing serialization to JSON. pub struct Encoder<'a> { - writer: &'a mut (fmt::Write+'a), + writer: &'a mut (dyn fmt::Write+'a), is_emitting_map_key: bool, } impl<'a> Encoder<'a> { /// Creates a new JSON encoder whose output will be written to the writer /// specified. - pub fn new(writer: &'a mut fmt::Write) -> Encoder<'a> { + pub fn new(writer: &'a mut dyn fmt::Write) -> Encoder<'a> { Encoder { writer: writer, is_emitting_map_key: false, } } } @@ -707,7 +707,7 @@ impl<'a> ::Encoder for Encoder<'a> { /// Another encoder for JSON, but prints out human-readable JSON instead of /// compact data pub struct PrettyEncoder<'a> { - writer: &'a mut (fmt::Write+'a), + writer: &'a mut (dyn fmt::Write+'a), curr_indent: usize, indent: usize, is_emitting_map_key: bool, @@ -715,7 +715,7 @@ pub struct PrettyEncoder<'a> { impl<'a> PrettyEncoder<'a> { /// Creates a new encoder whose output will be written to the specified writer - pub fn new(writer: &'a mut fmt::Write) -> PrettyEncoder<'a> { + pub fn new(writer: &'a mut dyn fmt::Write) -> PrettyEncoder<'a> { PrettyEncoder { writer, curr_indent: 0, @@ -2053,7 +2053,7 @@ impl> Builder { } /// Decodes a json value from an `&mut io::Read` -pub fn from_reader(rdr: &mut Read) -> Result { +pub fn from_reader(rdr: &mut dyn Read) -> Result { let mut contents = Vec::new(); match rdr.read_to_end(&mut contents) { Ok(c) => c, diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index a5f4b32b329e7..7c1bb69434d5f 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -14,6 +14,8 @@ Core encoding and decoding interfaces. */ +#![deny(bare_trait_objects)] + #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", From 21d9ac1d04cd59044fa96a3064dd0b56c648655a Mon Sep 17 00:00:00 2001 From: ljedrz Date: Thu, 12 Jul 2018 13:26:29 +0200 Subject: [PATCH 11/34] Deny bare trait objects in librustc_target and libtest --- src/librustc_target/lib.rs | 2 ++ src/librustc_target/spec/mod.rs | 2 +- src/libtest/lib.rs | 15 +++++++++------ 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs index 8f4911574398b..e611d26da56de 100644 --- a/src/librustc_target/lib.rs +++ b/src/librustc_target/lib.rs @@ -21,6 +21,8 @@ //! one that doesn't; the one that doesn't might get decent parallel //! build speedups. +#![deny(bare_trait_objects)] + #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 19e353c6a942d..484563aa30249 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -229,7 +229,7 @@ macro_rules! supported_targets { } } - pub fn get_targets() -> Box> { + pub fn get_targets() -> Box> { Box::new(TARGETS.iter().filter_map(|t| -> Option { load_specific(t) .and(Ok(t.to_string())) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index a4d1797c3ec5b..6b547dff9120e 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -26,6 +26,9 @@ // NB: this is also specified in this crate's Cargo.toml, but libsyntax contains logic specific to // this crate, which relies on this attribute (rather than the value of `--crate-name` passed by // cargo) to detect this crate. + +#![deny(bare_trait_objects)] + #![crate_name = "test"] #![unstable(feature = "test", issue = "27812")] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", @@ -165,8 +168,8 @@ pub trait TDynBenchFn: Send { pub enum TestFn { StaticTestFn(fn()), StaticBenchFn(fn(&mut Bencher)), - DynTestFn(Box), - DynBenchFn(Box), + DynTestFn(Box), + DynBenchFn(Box), } impl TestFn { @@ -840,7 +843,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec) -> io::Resu fn callback( event: &TestEvent, st: &mut ConsoleTestState, - out: &mut OutputFormatter, + out: &mut dyn OutputFormatter, ) -> io::Result<()> { match (*event).clone() { TeFiltered(ref filtered_tests) => { @@ -897,7 +900,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec) -> io::Resu let is_multithreaded = opts.test_threads.unwrap_or_else(get_concurrency) > 1; - let mut out: Box = match opts.format { + let mut out: Box = match opts.format { OutputFormat::Pretty => Box::new(PrettyFormatter::new( output, use_color(opts), @@ -1386,7 +1389,7 @@ pub fn run_test( desc: TestDesc, monitor_ch: Sender, nocapture: bool, - testfn: Box, + testfn: Box, ) { // Buffer for capturing standard I/O let data = Arc::new(Mutex::new(Vec::new())); @@ -1459,7 +1462,7 @@ fn __rust_begin_short_backtrace(f: F) { f() } -fn calc_result(desc: &TestDesc, task_result: Result<(), Box>) -> TestResult { +fn calc_result(desc: &TestDesc, task_result: Result<(), Box>) -> TestResult { match (&desc.should_panic, task_result) { (&ShouldPanic::No, Ok(())) | (&ShouldPanic::Yes, Err(_)) => TrOk, (&ShouldPanic::YesWithMessage(msg), Err(ref err)) => { From 5058af70039d4cf417f6cc94617da7b5d647182a Mon Sep 17 00:00:00 2001 From: ljedrz Date: Thu, 12 Jul 2018 13:50:22 +0200 Subject: [PATCH 12/34] Deny bare trait objects in the rest of rust --- src/build_helper/lib.rs | 2 ++ src/liballoc_jemalloc/lib.rs | 1 + src/liballoc_system/lib.rs | 1 + src/libarena/lib.rs | 1 + src/libfmt_macros/lib.rs | 2 ++ src/libgraphviz/lib.rs | 2 ++ src/libpanic_abort/lib.rs | 1 + src/libproc_macro/lib.rs | 1 + src/libprofiler_builtins/lib.rs | 1 + src/librustc_apfloat/lib.rs | 2 ++ src/librustc_asan/lib.rs | 2 ++ src/librustc_borrowck/lib.rs | 1 + src/librustc_incremental/lib.rs | 2 ++ src/librustc_lint/lib.rs | 2 ++ src/librustc_llvm/lib.rs | 1 + src/librustc_lsan/lib.rs | 2 ++ src/librustc_mir/lib.rs | 2 ++ src/librustc_msan/lib.rs | 2 ++ src/librustc_passes/lib.rs | 2 ++ src/librustc_platform_intrinsics/lib.rs | 1 + src/librustc_plugin/lib.rs | 2 ++ src/librustc_privacy/lib.rs | 2 ++ src/librustc_traits/lib.rs | 2 ++ src/librustc_tsan/lib.rs | 2 ++ src/libsyntax_pos/lib.rs | 2 ++ src/libunwind/lib.rs | 2 ++ 26 files changed, 43 insertions(+) diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index 2f9953330f42c..4d767f0968976 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![deny(bare_trait_objects)] + use std::fs::File; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs index b3b20715511a7..413b212281b74 100644 --- a/src/liballoc_jemalloc/lib.rs +++ b/src/liballoc_jemalloc/lib.rs @@ -10,6 +10,7 @@ #![no_std] #![allow(unused_attributes)] +#![deny(bare_trait_objects)] #![unstable(feature = "alloc_jemalloc", reason = "implementation detail of std, does not provide any public API", issue = "0")] diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index 64348e05de7db..c6c0abefbab23 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -10,6 +10,7 @@ #![no_std] #![allow(unused_attributes)] +#![deny(bare_trait_objects)] #![unstable(feature = "alloc_system", reason = "this library is unlikely to be stabilized in its current \ form or name", diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 0f4a5d16e1759..6f692923c8534 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -30,6 +30,7 @@ #![cfg_attr(test, feature(test))] #![allow(deprecated)] +#![deny(bare_trait_objects)] extern crate alloc; extern crate rustc_data_structures; diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index a77751d65d08c..51c3efb41ad97 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -14,6 +14,8 @@ //! Parsing does not happen at runtime: structures of `std::fmt::rt` are //! generated instead. +#![deny(bare_trait_objects)] + #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index 158d010151586..9e71ed4063e87 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -283,6 +283,8 @@ //! //! * [DOT language](http://www.graphviz.org/doc/info/lang.html) +#![deny(bare_trait_objects)] + #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index 392bf17968fbd..02ab28507d7d8 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -21,6 +21,7 @@ issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")] #![panic_runtime] #![allow(unused_features)] +#![deny(bare_trait_objects)] #![feature(core_intrinsics)] #![feature(libc)] diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 876cf295acc1b..7c0cf9eaddebe 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -22,6 +22,7 @@ //! See [the book](../book/first-edition/procedural-macros.html) for more. #![stable(feature = "proc_macro_lib", since = "1.15.0")] +#![deny(bare_trait_objects)] #![deny(missing_docs)] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", diff --git a/src/libprofiler_builtins/lib.rs b/src/libprofiler_builtins/lib.rs index 6d0d6d115b716..3d91505cd772a 100644 --- a/src/libprofiler_builtins/lib.rs +++ b/src/libprofiler_builtins/lib.rs @@ -15,4 +15,5 @@ reason = "internal implementation detail of rustc right now", issue = "0")] #![allow(unused_features)] +#![deny(bare_trait_objects)] #![feature(staged_api)] diff --git a/src/librustc_apfloat/lib.rs b/src/librustc_apfloat/lib.rs index 08438805a703e..c7cd958016dca 100644 --- a/src/librustc_apfloat/lib.rs +++ b/src/librustc_apfloat/lib.rs @@ -40,6 +40,8 @@ //! //! This API is completely unstable and subject to change. +#![deny(bare_trait_objects)] + #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] diff --git a/src/librustc_asan/lib.rs b/src/librustc_asan/lib.rs index 0c78fd74a234e..7bd1e98f85dc2 100644 --- a/src/librustc_asan/lib.rs +++ b/src/librustc_asan/lib.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![deny(bare_trait_objects)] + #![sanitizer_runtime] #![feature(alloc_system)] #![feature(sanitizer_runtime)] diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs index a5a20af0e4e4a..d583a32c43198 100644 --- a/src/librustc_borrowck/lib.rs +++ b/src/librustc_borrowck/lib.rs @@ -13,6 +13,7 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![allow(non_camel_case_types)] +#![deny(bare_trait_objects)] #![feature(from_ref)] #![feature(quote)] diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs index 3839c133a6eb2..2ef88041d338f 100644 --- a/src/librustc_incremental/lib.rs +++ b/src/librustc_incremental/lib.rs @@ -10,6 +10,8 @@ //! Support for serializing the dep-graph and reloading it. +#![deny(bare_trait_objects)] + #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 359b056b5a2d1..9f8ef6ef43244 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -19,6 +19,8 @@ //! //! This API is completely unstable and subject to change. +#![deny(bare_trait_objects)] + #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 741758cb954ba..c60016cde0d1b 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -12,6 +12,7 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] #![allow(dead_code)] +#![deny(bare_trait_objects)] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", diff --git a/src/librustc_lsan/lib.rs b/src/librustc_lsan/lib.rs index 0c78fd74a234e..7bd1e98f85dc2 100644 --- a/src/librustc_lsan/lib.rs +++ b/src/librustc_lsan/lib.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![deny(bare_trait_objects)] + #![sanitizer_runtime] #![feature(alloc_system)] #![feature(sanitizer_runtime)] diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index dc0d0b244633f..c042c68d40bcf 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -14,6 +14,8 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! */ +#![deny(bare_trait_objects)] + #![feature(slice_patterns)] #![feature(slice_sort_by_cached_key)] #![feature(from_ref)] diff --git a/src/librustc_msan/lib.rs b/src/librustc_msan/lib.rs index 0c78fd74a234e..7bd1e98f85dc2 100644 --- a/src/librustc_msan/lib.rs +++ b/src/librustc_msan/lib.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![deny(bare_trait_objects)] + #![sanitizer_runtime] #![feature(alloc_system)] #![feature(sanitizer_runtime)] diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 41f1e7829658a..15d7c0fdaa338 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -14,6 +14,8 @@ //! //! This API is completely unstable and subject to change. +#![deny(bare_trait_objects)] + #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] diff --git a/src/librustc_platform_intrinsics/lib.rs b/src/librustc_platform_intrinsics/lib.rs index b57debdd99486..92e83fd70fa3a 100644 --- a/src/librustc_platform_intrinsics/lib.rs +++ b/src/librustc_platform_intrinsics/lib.rs @@ -9,6 +9,7 @@ // except according to those terms. #![allow(bad_style)] +#![deny(bare_trait_objects)] pub struct Intrinsic { pub inputs: &'static [&'static Type], diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs index 348aa6a7cef4c..b2c492f204f33 100644 --- a/src/librustc_plugin/lib.rs +++ b/src/librustc_plugin/lib.rs @@ -60,6 +60,8 @@ //! See the [`plugin` feature](../unstable-book/language-features/plugin.html) of //! the Unstable Book for more examples. +#![deny(bare_trait_objects)] + #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 3919ba13076f6..f69e664ea46b3 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![deny(bare_trait_objects)] + #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] diff --git a/src/librustc_traits/lib.rs b/src/librustc_traits/lib.rs index 1da3907915a07..cd55b5ddc5bf1 100644 --- a/src/librustc_traits/lib.rs +++ b/src/librustc_traits/lib.rs @@ -11,6 +11,8 @@ //! New recursive solver modeled on Chalk's recursive solver. Most of //! the guts are broken up into modules; see the comments in those modules. +#![deny(bare_trait_objects)] + #![feature(crate_in_paths)] #![feature(crate_visibility_modifier)] #![feature(extern_prelude)] diff --git a/src/librustc_tsan/lib.rs b/src/librustc_tsan/lib.rs index 0c78fd74a234e..7bd1e98f85dc2 100644 --- a/src/librustc_tsan/lib.rs +++ b/src/librustc_tsan/lib.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![deny(bare_trait_objects)] + #![sanitizer_runtime] #![feature(alloc_system)] #![feature(sanitizer_runtime)] diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 61af70af47d85..cc09a944e4ccc 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -14,6 +14,8 @@ //! //! This API is completely unstable and subject to change. +#![deny(bare_trait_objects)] + #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] diff --git a/src/libunwind/lib.rs b/src/libunwind/lib.rs index 2b3c19c067ed4..ea5eee3cc7d46 100644 --- a/src/libunwind/lib.rs +++ b/src/libunwind/lib.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![deny(bare_trait_objects)] + #![no_std] #![unstable(feature = "panic_unwind", issue = "32837")] From e93de9556a63a4743bd286cda73e4b505916c599 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 12 Jul 2018 09:10:39 -0700 Subject: [PATCH 13/34] Fix ICE when using a pointer cast as array size --- src/librustc/ty/relate.rs | 7 ++++++- src/test/ui/issue-52023-array-size-pointer-cast.rs | 13 +++++++++++++ .../ui/issue-52023-array-size-pointer-cast.stderr | 9 +++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/issue-52023-array-size-pointer-cast.rs create mode 100644 src/test/ui/issue-52023-array-size-pointer-cast.stderr diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 265c6aee39726..4e8f33d6a4a03 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -20,6 +20,7 @@ use ty::{self, Ty, TyCtxt, TypeFoldable}; use ty::error::{ExpectedFound, TypeError}; use mir::interpret::GlobalId; use util::common::ErrorReported; +use syntax_pos::DUMMY_SP; use std::rc::Rc; use std::iter; use rustc_target::spec::abi; @@ -503,7 +504,11 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, "array length could not be evaluated"); Err(ErrorReported) } - _ => bug!("arrays should not have {:?} as length", x) + _ => { + tcx.sess.delay_span_bug(DUMMY_SP, + &format!("arrays should not have {:?} as length", x)); + Err(ErrorReported) + } } }; match (to_u64(sz_a), to_u64(sz_b)) { diff --git a/src/test/ui/issue-52023-array-size-pointer-cast.rs b/src/test/ui/issue-52023-array-size-pointer-cast.rs new file mode 100644 index 0000000000000..f3bee1a631580 --- /dev/null +++ b/src/test/ui/issue-52023-array-size-pointer-cast.rs @@ -0,0 +1,13 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let _ = [0; (&0 as *const i32) as usize]; //~ ERROR raw pointers cannot be cast +} diff --git a/src/test/ui/issue-52023-array-size-pointer-cast.stderr b/src/test/ui/issue-52023-array-size-pointer-cast.stderr new file mode 100644 index 0000000000000..888de82e379c8 --- /dev/null +++ b/src/test/ui/issue-52023-array-size-pointer-cast.stderr @@ -0,0 +1,9 @@ +error[E0018]: raw pointers cannot be cast to integers in constants + --> $DIR/issue-52023-array-size-pointer-cast.rs:12:17 + | +LL | let _ = [0; (&0 as *const i32) as usize]; //~ ERROR raw pointers cannot be cast + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0018`. From 4c340a28adf4ecd48e17da9fc3d1d73f696bf0c6 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Thu, 12 Jul 2018 09:23:00 -0600 Subject: [PATCH 14/34] Backport 1.27.1 release notes to master --- RELEASES.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index cf80c166759bf..503ce7ede0d7d 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -140,6 +140,29 @@ Compatibility Notes [`{Any + Send + Sync}::downcast_ref`]: https://doc.rust-lang.org/std/any/trait.Any.html#method.downcast_ref-2 [`{Any + Send + Sync}::is`]: https://doc.rust-lang.org/std/any/trait.Any.html#method.is-2 +Version 1.27.1 (2018-07-10) +=========================== + +Security Notes +-------------- + +- rustdoc would execute plugins in the /tmp/rustdoc/plugins directory + when running, which enabled executing code as some other user on a + given machine. This release fixes that vulnerability; you can read + more about this on the [blog][rustdoc-sec]. The associated CVE is [CVE-2018-1000622]. + + Thank you to Red Hat for responsibily disclosing this vulnerability to us. + +Compatibility Notes +------------------- + +- The borrow checker was fixed to avoid an additional potential unsoundness when using + match ergonomics: [#51415][51415], [#49534][49534]. + +[51415]: https://github.com/rust-lang/rust/issues/51415 +[49534]: https://github.com/rust-lang/rust/issues/49534 +[rustdoc-sec]: https://blog.rust-lang.org/2018/07/06/security-advisory-for-rustdoc.html +[CVE-2018-1000622]: https://cve.mitre.org/cgi-bin/cvename.cgi?name=%20CVE-2018-1000622 Version 1.27.0 (2018-06-21) ========================== From 72f096b6288f00d14a47d7fc1dff7c4939ad2e2a Mon Sep 17 00:00:00 2001 From: ljedrz Date: Thu, 12 Jul 2018 18:59:56 +0200 Subject: [PATCH 15/34] Resolve FIXME(#27942) --- src/librustc/infer/error_reporting/mod.rs | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 1377176bc7fb8..c1849c63a7df3 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -193,32 +193,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let scope = region.free_region_binding_scope(self); let node = self.hir.as_local_node_id(scope).unwrap_or(DUMMY_NODE_ID); - let unknown; let tag = match self.hir.find(node) { Some(hir_map::NodeBlock(_)) | Some(hir_map::NodeExpr(_)) => "body", Some(hir_map::NodeItem(it)) => Self::item_scope_tag(&it), Some(hir_map::NodeTraitItem(it)) => Self::trait_item_scope_tag(&it), Some(hir_map::NodeImplItem(it)) => Self::impl_item_scope_tag(&it), - - // this really should not happen, but it does: - // FIXME(#27942) - Some(_) => { - unknown = format!( - "unexpected node ({}) for scope {:?}. \ - Please report a bug.", - self.hir.node_to_string(node), - scope - ); - &unknown - } - None => { - unknown = format!( - "unknown node for scope {:?}. \ - Please report a bug.", - scope - ); - &unknown - } + _ => unreachable!() }; let (prefix, span) = match *region { ty::ReEarlyBound(ref br) => { From 9ead0d82e119a2281ad38ab80562c0f22af57a8b Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 12 Jul 2018 12:32:35 -0700 Subject: [PATCH 16/34] Update llvm-rebuild-trigger in light of LLVM 7 upgrade --- src/rustllvm/llvm-rebuild-trigger | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger index 5a0292bb6a16e..1722211c9e89f 100644 --- a/src/rustllvm/llvm-rebuild-trigger +++ b/src/rustllvm/llvm-rebuild-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2018-05-18 \ No newline at end of file +2018-07-12 \ No newline at end of file From 4f4e91a69d75b5de66d53399027cc1835387a423 Mon Sep 17 00:00:00 2001 From: Sean McArthur Date: Thu, 12 Jul 2018 15:43:57 -0700 Subject: [PATCH 17/34] task: remove wrong comments about non-existent LocalWake trait --- src/libcore/task/wake.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs index 418d5af006f74..d3df8b50ee2ee 100644 --- a/src/libcore/task/wake.rs +++ b/src/libcore/task/wake.rs @@ -113,8 +113,8 @@ impl LocalWaker { /// but you otherwise shouldn't call it directly. /// /// If you're working with the standard library then it's recommended to - /// use the `LocalWaker::from` function instead which works with the safe - /// `Rc` type and the safe `LocalWake` trait. + /// use the `local_waker_from_nonlocal` or `local_waker` to convert a `Waker` + /// into a `LocalWaker`. /// /// For this function to be used safely, it must be sound to call `inner.wake_local()` /// on the current thread. @@ -197,9 +197,7 @@ impl Drop for LocalWaker { /// customization. /// /// When using `std`, a default implementation of the `UnsafeWake` trait is provided for -/// `Arc` where `T: Wake` and `Rc` where `T: LocalWake`. -/// -/// Although the methods on `UnsafeWake` take pointers rather than references, +/// `Arc` where `T: Wake`. pub unsafe trait UnsafeWake: Send + Sync { /// Creates a clone of this `UnsafeWake` and stores it behind a `Waker`. /// From 8cc4fd6c23ab0d59a6c11967ca6b949e4c9f0ab4 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Thu, 12 Jul 2018 19:37:49 -0700 Subject: [PATCH 18/34] dead-code lint: say "constructed", "called" for structs, functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Respectively. This is a sequel to November 2017's #46103 / 1a9dc2e9. It had been reported (more than once—at least #19140, #44083, and #44565) that the "never used" language was confusing for enum variants that were "used" as match patterns, so the wording was changed to say never "constructed" specifically for enum variants. More recently, the same issue was raised for structs (#52325). It seems consistent to say "constructed" here, too, for the same reasons. While we're here, we can also use more specific word "called" for unused functions and methods. (We declined to do this in #46103, but the rationale given in the commit message doesn't actually make sense.) This resolves #52325. --- src/librustc/middle/dead.rs | 10 ++++++++-- src/test/compile-fail/fail-no-dead-code-core.rs | 2 +- src/test/compile-fail/fail-no-dead-code.rs | 2 +- src/test/compile-fail/lint-dead-code-1.rs | 10 +++++----- src/test/compile-fail/lint-dead-code-2.rs | 6 +++--- src/test/compile-fail/lint-dead-code-3.rs | 6 +++--- src/test/compile-fail/test-warns-dead-code.rs | 2 +- .../ui-fulldeps/lint-plugin-cmdline-allow.stderr | 2 +- src/test/ui/path-lookahead.rs | 4 ++-- src/test/ui/path-lookahead.stderr | 8 ++++---- src/test/ui/span/macro-span-replacement.rs | 2 +- src/test/ui/span/macro-span-replacement.stderr | 4 ++-- .../ui/span/unused-warning-point-at-signature.rs | 6 +++--- .../ui/span/unused-warning-point-at-signature.stderr | 12 ++++++------ 14 files changed, 41 insertions(+), 35 deletions(-) diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 42775e3a1837f..368b955a42aaa 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -567,12 +567,17 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { hir::ItemImpl(..) => self.tcx.sess.codemap().def_span(item.span), _ => item.span, }; + let participle = match item.node { + hir::ItemFn(..) => "called", + hir::ItemStruct(..) => "constructed", + _ => "used" + }; self.warn_dead_code( item.id, span, item.name, item.node.descriptive_variant(), - "used", + participle, ); } else { // Only continue if we didn't warn @@ -622,7 +627,8 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { hir::ImplItemKind::Method(_, body_id) => { if !self.symbol_is_live(impl_item.id, None) { let span = self.tcx.sess.codemap().def_span(impl_item.span); - self.warn_dead_code(impl_item.id, span, impl_item.ident.name, "method", "used"); + self.warn_dead_code(impl_item.id, span, impl_item.ident.name, + "method", "called"); } self.visit_nested_body(body_id) } diff --git a/src/test/compile-fail/fail-no-dead-code-core.rs b/src/test/compile-fail/fail-no-dead-code-core.rs index aed76e36fca14..da00d6e981aa9 100644 --- a/src/test/compile-fail/fail-no-dead-code-core.rs +++ b/src/test/compile-fail/fail-no-dead-code-core.rs @@ -14,7 +14,7 @@ #[macro_use] extern crate core; -fn foo() { //~ ERROR function is never used +fn foo() { //~ ERROR function is never called // none of these should have any dead_code exposed to the user panic!(); diff --git a/src/test/compile-fail/fail-no-dead-code.rs b/src/test/compile-fail/fail-no-dead-code.rs index 6e5d3a313556e..f7161558157db 100644 --- a/src/test/compile-fail/fail-no-dead-code.rs +++ b/src/test/compile-fail/fail-no-dead-code.rs @@ -11,7 +11,7 @@ #![deny(dead_code)] #![allow(unreachable_code)] -fn foo() { //~ ERROR function is never used +fn foo() { //~ ERROR function is never called // none of these should have any dead_code exposed to the user panic!(); diff --git a/src/test/compile-fail/lint-dead-code-1.rs b/src/test/compile-fail/lint-dead-code-1.rs index d6ca5e6b1d969..b771e9726a99c 100644 --- a/src/test/compile-fail/lint-dead-code-1.rs +++ b/src/test/compile-fail/lint-dead-code-1.rs @@ -19,7 +19,7 @@ pub use foo2::Bar2; mod foo { - pub struct Bar; //~ ERROR: struct is never used + pub struct Bar; //~ ERROR: struct is never constructed } mod foo2 { @@ -42,7 +42,7 @@ const CONST_USED_IN_ENUM_DISCRIMINANT: isize = 11; pub type typ = *const UsedStruct4; pub struct PubStruct; -struct PrivStruct; //~ ERROR: struct is never used +struct PrivStruct; //~ ERROR: struct is never constructed struct UsedStruct1 { #[allow(dead_code)] x: isize @@ -95,17 +95,17 @@ pub fn pub_fn() { } f::(); } -fn priv_fn() { //~ ERROR: function is never used +fn priv_fn() { //~ ERROR: function is never called let unused_struct = PrivStruct; } fn used_fn() {} -fn foo() { //~ ERROR: function is never used +fn foo() { //~ ERROR: function is never called bar(); let unused_enum = priv_enum::foo2; } -fn bar() { //~ ERROR: function is never used +fn bar() { //~ ERROR: function is never called foo(); } diff --git a/src/test/compile-fail/lint-dead-code-2.rs b/src/test/compile-fail/lint-dead-code-2.rs index 4a0e4f4319e0a..e4c2761fcb7e2 100644 --- a/src/test/compile-fail/lint-dead-code-2.rs +++ b/src/test/compile-fail/lint-dead-code-2.rs @@ -29,10 +29,10 @@ impl Bar for Foo { fn live_fn() {} -fn dead_fn() {} //~ ERROR: function is never used +fn dead_fn() {} //~ ERROR: function is never called #[main] -fn dead_fn2() {} //~ ERROR: function is never used +fn dead_fn2() {} //~ ERROR: function is never called fn used_fn() {} @@ -45,7 +45,7 @@ fn start(_: isize, _: *const *const u8) -> isize { } // this is not main -fn main() { //~ ERROR: function is never used +fn main() { //~ ERROR: function is never called dead_fn(); dead_fn2(); } diff --git a/src/test/compile-fail/lint-dead-code-3.rs b/src/test/compile-fail/lint-dead-code-3.rs index f680e39544933..c4f16e113b934 100644 --- a/src/test/compile-fail/lint-dead-code-3.rs +++ b/src/test/compile-fail/lint-dead-code-3.rs @@ -20,14 +20,14 @@ extern { pub fn extern_foo(); } -struct Foo; //~ ERROR: struct is never used +struct Foo; //~ ERROR: struct is never constructed impl Foo { - fn foo(&self) { //~ ERROR: method is never used + fn foo(&self) { //~ ERROR: method is never called bar() } } -fn bar() { //~ ERROR: function is never used +fn bar() { //~ ERROR: function is never called fn baz() {} Foo.foo(); diff --git a/src/test/compile-fail/test-warns-dead-code.rs b/src/test/compile-fail/test-warns-dead-code.rs index 0e25f1e965ab9..8e50154685364 100644 --- a/src/test/compile-fail/test-warns-dead-code.rs +++ b/src/test/compile-fail/test-warns-dead-code.rs @@ -12,6 +12,6 @@ #![deny(dead_code)] -fn dead() {} //~ error: function is never used: `dead` +fn dead() {} //~ error: function is never called: `dead` fn main() {} diff --git a/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr b/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr index cda6ea8bb903b..6cba74367c550 100644 --- a/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr +++ b/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr @@ -1,4 +1,4 @@ -warning: function is never used: `lintme` +warning: function is never called: `lintme` --> $DIR/lint-plugin-cmdline-allow.rs:20:1 | LL | fn lintme() { } diff --git a/src/test/ui/path-lookahead.rs b/src/test/ui/path-lookahead.rs index 367a256015558..ecc08feceb744 100644 --- a/src/test/ui/path-lookahead.rs +++ b/src/test/ui/path-lookahead.rs @@ -14,11 +14,11 @@ // Parser test for #37765 -fn with_parens(arg: T) -> String { //~WARN function is never used: `with_parens` +fn with_parens(arg: T) -> String { //~WARN function is never called: `with_parens` return (::to_string(&arg)); //~WARN unnecessary parentheses around `return` value } -fn no_parens(arg: T) -> String { //~WARN function is never used: `no_parens` +fn no_parens(arg: T) -> String { //~WARN function is never called: `no_parens` return ::to_string(&arg); } diff --git a/src/test/ui/path-lookahead.stderr b/src/test/ui/path-lookahead.stderr index 89df5e894aa34..5de59c097923a 100644 --- a/src/test/ui/path-lookahead.stderr +++ b/src/test/ui/path-lookahead.stderr @@ -11,10 +11,10 @@ LL | #![warn(unused)] | ^^^^^^ = note: #[warn(unused_parens)] implied by #[warn(unused)] -warning: function is never used: `with_parens` +warning: function is never called: `with_parens` --> $DIR/path-lookahead.rs:17:1 | -LL | fn with_parens(arg: T) -> String { //~WARN function is never used: `with_parens` +LL | fn with_parens(arg: T) -> String { //~WARN function is never called: `with_parens` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here @@ -24,9 +24,9 @@ LL | #![warn(unused)] | ^^^^^^ = note: #[warn(dead_code)] implied by #[warn(unused)] -warning: function is never used: `no_parens` +warning: function is never called: `no_parens` --> $DIR/path-lookahead.rs:21:1 | -LL | fn no_parens(arg: T) -> String { //~WARN function is never used: `no_parens` +LL | fn no_parens(arg: T) -> String { //~WARN function is never called: `no_parens` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/span/macro-span-replacement.rs b/src/test/ui/span/macro-span-replacement.rs index 4fe35042300e7..7374f15746851 100644 --- a/src/test/ui/span/macro-span-replacement.rs +++ b/src/test/ui/span/macro-span-replacement.rs @@ -14,7 +14,7 @@ macro_rules! m { ($a:tt $b:tt) => { - $b $a; //~ WARN struct is never used + $b $a; //~ WARN struct is never constructed } } diff --git a/src/test/ui/span/macro-span-replacement.stderr b/src/test/ui/span/macro-span-replacement.stderr index bb59fa206df1d..b12ca86d3c929 100644 --- a/src/test/ui/span/macro-span-replacement.stderr +++ b/src/test/ui/span/macro-span-replacement.stderr @@ -1,7 +1,7 @@ -warning: struct is never used: `S` +warning: struct is never constructed: `S` --> $DIR/macro-span-replacement.rs:17:14 | -LL | $b $a; //~ WARN struct is never used +LL | $b $a; //~ WARN struct is never constructed | ^ ... LL | m!(S struct); diff --git a/src/test/ui/span/unused-warning-point-at-signature.rs b/src/test/ui/span/unused-warning-point-at-signature.rs index 6a7071d49aed6..f399d61f41867 100644 --- a/src/test/ui/span/unused-warning-point-at-signature.rs +++ b/src/test/ui/span/unused-warning-point-at-signature.rs @@ -19,18 +19,18 @@ enum Enum { //~ WARN enum is never used D, } -struct Struct { //~ WARN struct is never used +struct Struct { //~ WARN struct is never constructed a: usize, b: usize, c: usize, d: usize, } -fn func() -> usize { //~ WARN function is never used +fn func() -> usize { //~ WARN function is never called 3 } -fn //~ WARN function is never used +fn //~ WARN function is never called func_complete_span() -> usize { diff --git a/src/test/ui/span/unused-warning-point-at-signature.stderr b/src/test/ui/span/unused-warning-point-at-signature.stderr index de234344d8409..dd05960b8208f 100644 --- a/src/test/ui/span/unused-warning-point-at-signature.stderr +++ b/src/test/ui/span/unused-warning-point-at-signature.stderr @@ -11,22 +11,22 @@ LL | #![warn(unused)] | ^^^^^^ = note: #[warn(dead_code)] implied by #[warn(unused)] -warning: struct is never used: `Struct` +warning: struct is never constructed: `Struct` --> $DIR/unused-warning-point-at-signature.rs:22:1 | -LL | struct Struct { //~ WARN struct is never used +LL | struct Struct { //~ WARN struct is never constructed | ^^^^^^^^^^^^^ -warning: function is never used: `func` +warning: function is never called: `func` --> $DIR/unused-warning-point-at-signature.rs:29:1 | -LL | fn func() -> usize { //~ WARN function is never used +LL | fn func() -> usize { //~ WARN function is never called | ^^^^^^^^^^^^^^^^^^ -warning: function is never used: `func_complete_span` +warning: function is never called: `func_complete_span` --> $DIR/unused-warning-point-at-signature.rs:33:1 | -LL | / fn //~ WARN function is never used +LL | / fn //~ WARN function is never called LL | | func_complete_span() LL | | -> usize LL | | { From f8eb9a685cb58aeea3b25cecf7a510f6ba5c92d5 Mon Sep 17 00:00:00 2001 From: ashtneoi Date: Tue, 10 Jul 2018 21:31:07 -0700 Subject: [PATCH 19/34] Add `ref mut` suggestion test --- src/test/ui/suggestions/suggest-ref-mut.rs | 31 +++++++++++++++++++ .../ui/suggestions/suggest-ref-mut.stderr | 21 +++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 src/test/ui/suggestions/suggest-ref-mut.rs create mode 100644 src/test/ui/suggestions/suggest-ref-mut.stderr diff --git a/src/test/ui/suggestions/suggest-ref-mut.rs b/src/test/ui/suggestions/suggest-ref-mut.rs new file mode 100644 index 0000000000000..1f5c5b033286c --- /dev/null +++ b/src/test/ui/suggestions/suggest-ref-mut.rs @@ -0,0 +1,31 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(nll)] + +fn main() { + let ref foo = 16; + //~^ HELP + //~| SUGGESTION ref mut foo + *foo = 32; + //~^ ERROR + if let Some(ref bar) = Some(16) { + //~^ HELP + //~| SUGGESTION ref mut bar + *bar = 32; + //~^ ERROR + } + match 16 { + ref quo => { *quo = 32; }, + //~^ ERROR + //~| HELP + //~| SUGGESTION ref mut quo + } +} diff --git a/src/test/ui/suggestions/suggest-ref-mut.stderr b/src/test/ui/suggestions/suggest-ref-mut.stderr new file mode 100644 index 0000000000000..6e151a995b826 --- /dev/null +++ b/src/test/ui/suggestions/suggest-ref-mut.stderr @@ -0,0 +1,21 @@ +error[E0594]: cannot assign to `*foo` which is behind a `&` reference + --> $DIR/suggest-ref-mut.rs:17:5 + | +LL | *foo = 32; + | ^^^^^^^^^ cannot assign + +error[E0594]: cannot assign to `*bar` which is behind a `&` reference + --> $DIR/suggest-ref-mut.rs:22:9 + | +LL | *bar = 32; + | ^^^^^^^^^ cannot assign + +error[E0594]: cannot assign to `*quo` which is behind a `&` reference + --> $DIR/suggest-ref-mut.rs:26:22 + | +LL | ref quo => { *quo = 32; }, + | ^^^^^^^^^ cannot assign + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0594`. From 52d6ae854d0f4c33aa65ad1c151bf7e1700de476 Mon Sep 17 00:00:00 2001 From: ashtneoi Date: Tue, 10 Jul 2018 22:58:43 -0700 Subject: [PATCH 20/34] Reimplement some "add `mut`" suggestions under NLL Specifically, `&self` -> `&mut self` and explicit `ref` -> `ref mut`. Implicit `ref` isn't handled yet and causes an ICE. --- src/librustc_mir/borrow_check/mod.rs | 99 +++++++++++++------ src/librustc_mir/lib.rs | 2 + .../ui/did_you_mean/issue-38147-1.nll.stderr | 2 +- .../ui/did_you_mean/issue-39544.nll.stderr | 6 +- .../ui/suggestions/suggest-ref-mut.stderr | 14 ++- 5 files changed, 88 insertions(+), 35 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 1a66a2d2cb902..243f378377f9a 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -29,6 +29,8 @@ use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::small_vec::SmallVec; +use core::unicode::property::Pattern_White_Space; + use std::rc::Rc; use syntax_pos::Span; @@ -1837,17 +1839,45 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Place::Projection(box Projection { base: Place::Local(local), elem: ProjectionElem::Deref, - }) if self.mir.local_decls[*local].is_nonref_binding() => - { - let (err_help_span, suggested_code) = - find_place_to_suggest_ampmut(self.tcx, self.mir, *local); + }) if self.mir.local_decls[*local].is_user_variable.is_some() => { + let local_decl = &self.mir.local_decls[*local]; + let (err_help_span, suggested_code) = match local_decl.is_user_variable { + Some(ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf)) => { + suggest_ampmut_self(local_decl) + }, + + Some(ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm { + binding_mode: ty::BindingMode::BindByValue(_), + opt_ty_info, + .. + }))) => { + if let Some(x) = try_suggest_ampmut_rhs( + self.tcx, self.mir, *local, + ) { + x + } else { + suggest_ampmut_type(local_decl, opt_ty_info) + } + }, + + Some(ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm { + binding_mode: ty::BindingMode::BindByReference(_), + .. + }))) => { + suggest_ref_mut(self.tcx, local_decl) + }, + + Some(ClearCrossCrate::Clear) => bug!("saw cleared local state"), + + None => bug!(), + }; + err.span_suggestion( err_help_span, "consider changing this to be a mutable reference", suggested_code, ); - let local_decl = &self.mir.local_decls[*local]; if let Some(name) = local_decl.name { err.span_label( span, @@ -1874,13 +1904,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err.emit(); return true; - // Returns the span to highlight and the associated text to - // present when suggesting that the user use an `&mut`. - // + fn suggest_ampmut_self<'cx, 'gcx, 'tcx>( + local_decl: &mir::LocalDecl<'tcx>, + ) -> (Span, String) { + (local_decl.source_info.span, "&mut self".to_string()) + } + // When we want to suggest a user change a local variable to be a `&mut`, there // are three potential "obvious" things to highlight: // - // let ident [: Type] [= RightHandSideExresssion]; + // let ident [: Type] [= RightHandSideExpression]; // ^^^^^ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ // (1.) (2.) (3.) // @@ -1889,48 +1922,58 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // for example, if the RHS is present and the Type is not, then the type is going to // be inferred *from* the RHS, which means we should highlight that (and suggest // that they borrow the RHS mutably). - fn find_place_to_suggest_ampmut<'cx, 'gcx, 'tcx>( + // + // This implementation attempts to emulate AST-borrowck prioritization + // by trying (3.), then (2.) and finally falling back on (1.). + + fn try_suggest_ampmut_rhs<'cx, 'gcx, 'tcx>( tcx: TyCtxt<'cx, 'gcx, 'tcx>, mir: &Mir<'tcx>, local: Local, - ) -> (Span, String) { - // This implementation attempts to emulate AST-borrowck prioritization - // by trying (3.), then (2.) and finally falling back on (1.). + ) -> Option<(Span, String)> { let locations = mir.find_assignments(local); if locations.len() > 0 { let assignment_rhs_span = mir.source_info(locations[0]).span; let snippet = tcx.sess.codemap().span_to_snippet(assignment_rhs_span); if let Ok(src) = snippet { - // pnkfelix inherited code; believes intention is - // highlighted text will always be `&` and - // thus can transform to `&mut` by slicing off - // first ASCII character and prepending "&mut ". if src.starts_with('&') { let borrowed_expr = src[1..].to_string(); - return (assignment_rhs_span, format!("&mut {}", borrowed_expr)); + return Some((assignment_rhs_span, format!("&mut {}", borrowed_expr))); } } } + None + } - let local_decl = &mir.local_decls[local]; - let highlight_span = match local_decl.is_user_variable { + fn suggest_ampmut_type<'tcx>( + local_decl: &mir::LocalDecl<'tcx>, + opt_ty_info: Option, + ) -> (Span, String) { + let highlight_span = match opt_ty_info { // if this is a variable binding with an explicit type, // try to highlight that for the suggestion. - Some(ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm { - opt_ty_info: Some(ty_span), - .. - }))) => ty_span, - - Some(ClearCrossCrate::Clear) => bug!("saw cleared local state"), + Some(ty_span) => ty_span, // otherwise, just highlight the span associated with // the (MIR) LocalDecl. - _ => local_decl.source_info.span, + None => local_decl.source_info.span, }; let ty_mut = local_decl.ty.builtin_deref(true).unwrap(); assert_eq!(ty_mut.mutbl, hir::MutImmutable); - return (highlight_span, format!("&mut {}", ty_mut.ty)); + (highlight_span, format!("&mut {}", ty_mut.ty)) + } + + fn suggest_ref_mut<'cx, 'gcx, 'tcx>( + tcx: TyCtxt<'cx, 'gcx, 'tcx>, + local_decl: &mir::LocalDecl<'tcx>, + ) -> (Span, String) { + let hi_span = local_decl.source_info.span; + let hi_src = tcx.sess.codemap().span_to_snippet(hi_span).unwrap(); + assert!(hi_src.starts_with("ref")); + assert!(hi_src["ref".len()..].starts_with(Pattern_White_Space)); + let suggestion = format!("ref mut{}", &hi_src["ref".len()..]); + (hi_span, suggestion) } } diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index dc0d0b244633f..92c0a2b475c20 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -33,6 +33,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(never_type)] #![feature(specialization)] #![feature(try_trait)] +#![feature(unicode_internals)] #![recursion_limit="256"] @@ -56,6 +57,7 @@ extern crate rustc_target; extern crate log_settings; extern crate rustc_apfloat; extern crate byteorder; +extern crate core; mod diagnostics; diff --git a/src/test/ui/did_you_mean/issue-38147-1.nll.stderr b/src/test/ui/did_you_mean/issue-38147-1.nll.stderr index 76b8c8ebf6029..d156d64b9d693 100644 --- a/src/test/ui/did_you_mean/issue-38147-1.nll.stderr +++ b/src/test/ui/did_you_mean/issue-38147-1.nll.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable item `*self.s` as mutable --> $DIR/issue-38147-1.rs:27:9 | LL | fn f(&self) { - | ----- help: consider changing this to be a mutable reference: `&mut Foo<'_>` + | ----- help: consider changing this to be a mutable reference: `&mut self` LL | self.s.push('x'); //~ ERROR cannot borrow data mutably | ^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable diff --git a/src/test/ui/did_you_mean/issue-39544.nll.stderr b/src/test/ui/did_you_mean/issue-39544.nll.stderr index 02c1debca69b2..e2d2fcd63db12 100644 --- a/src/test/ui/did_you_mean/issue-39544.nll.stderr +++ b/src/test/ui/did_you_mean/issue-39544.nll.stderr @@ -10,7 +10,7 @@ error[E0596]: cannot borrow immutable item `self.x` as mutable --> $DIR/issue-39544.rs:26:17 | LL | fn foo<'z>(&'z self) { - | -------- help: consider changing this to be a mutable reference: `&mut Z` + | -------- help: consider changing this to be a mutable reference: `&mut self` LL | let _ = &mut self.x; //~ ERROR cannot borrow | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable @@ -18,7 +18,7 @@ error[E0596]: cannot borrow immutable item `self.x` as mutable --> $DIR/issue-39544.rs:30:17 | LL | fn foo1(&self, other: &Z) { - | ----- help: consider changing this to be a mutable reference: `&mut Z` + | ----- help: consider changing this to be a mutable reference: `&mut self` LL | let _ = &mut self.x; //~ ERROR cannot borrow | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable @@ -35,7 +35,7 @@ error[E0596]: cannot borrow immutable item `self.x` as mutable --> $DIR/issue-39544.rs:35:17 | LL | fn foo2<'a>(&'a self, other: &Z) { - | -------- help: consider changing this to be a mutable reference: `&mut Z` + | -------- help: consider changing this to be a mutable reference: `&mut self` LL | let _ = &mut self.x; //~ ERROR cannot borrow | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable diff --git a/src/test/ui/suggestions/suggest-ref-mut.stderr b/src/test/ui/suggestions/suggest-ref-mut.stderr index 6e151a995b826..d1590b3934e0b 100644 --- a/src/test/ui/suggestions/suggest-ref-mut.stderr +++ b/src/test/ui/suggestions/suggest-ref-mut.stderr @@ -1,20 +1,28 @@ error[E0594]: cannot assign to `*foo` which is behind a `&` reference --> $DIR/suggest-ref-mut.rs:17:5 | +LL | let ref foo = 16; + | ------- help: consider changing this to be a mutable reference: `ref mut foo` +... LL | *foo = 32; - | ^^^^^^^^^ cannot assign + | ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written error[E0594]: cannot assign to `*bar` which is behind a `&` reference --> $DIR/suggest-ref-mut.rs:22:9 | +LL | if let Some(ref bar) = Some(16) { + | ------- help: consider changing this to be a mutable reference: `ref mut bar` +... LL | *bar = 32; - | ^^^^^^^^^ cannot assign + | ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written error[E0594]: cannot assign to `*quo` which is behind a `&` reference --> $DIR/suggest-ref-mut.rs:26:22 | LL | ref quo => { *quo = 32; }, - | ^^^^^^^^^ cannot assign + | ------- ^^^^^^^^^ `quo` is a `&` reference, so the data it refers to cannot be written + | | + | help: consider changing this to be a mutable reference: `ref mut quo` error: aborting due to 3 previous errors From 6fd1a9fff79d906ecadcc9eab3962d84d38c7061 Mon Sep 17 00:00:00 2001 From: ashtneoi Date: Tue, 10 Jul 2018 23:14:12 -0700 Subject: [PATCH 21/34] Don't try to suggest `ref mut` for implicit `ref` --- src/librustc_mir/borrow_check/mod.rs | 34 +++++++++++-------- .../enum.nll.stderr | 6 ++-- .../explicit-mut.nll.stderr | 6 ++-- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 243f378377f9a..95601f1337139 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1841,9 +1841,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { elem: ProjectionElem::Deref, }) if self.mir.local_decls[*local].is_user_variable.is_some() => { let local_decl = &self.mir.local_decls[*local]; - let (err_help_span, suggested_code) = match local_decl.is_user_variable { + let suggestion = match local_decl.is_user_variable { Some(ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf)) => { - suggest_ampmut_self(local_decl) + Some(suggest_ampmut_self(local_decl)) }, Some(ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm { @@ -1854,9 +1854,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if let Some(x) = try_suggest_ampmut_rhs( self.tcx, self.mir, *local, ) { - x + Some(x) } else { - suggest_ampmut_type(local_decl, opt_ty_info) + Some(suggest_ampmut_type(local_decl, opt_ty_info)) } }, @@ -1872,11 +1872,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { None => bug!(), }; - err.span_suggestion( - err_help_span, - "consider changing this to be a mutable reference", - suggested_code, - ); + if let Some((err_help_span, suggested_code)) = suggestion { + err.span_suggestion( + err_help_span, + "consider changing this to be a mutable reference", + suggested_code, + ); + } if let Some(name) = local_decl.name { err.span_label( @@ -1967,13 +1969,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { fn suggest_ref_mut<'cx, 'gcx, 'tcx>( tcx: TyCtxt<'cx, 'gcx, 'tcx>, local_decl: &mir::LocalDecl<'tcx>, - ) -> (Span, String) { + ) -> Option<(Span, String)> { let hi_span = local_decl.source_info.span; let hi_src = tcx.sess.codemap().span_to_snippet(hi_span).unwrap(); - assert!(hi_src.starts_with("ref")); - assert!(hi_src["ref".len()..].starts_with(Pattern_White_Space)); - let suggestion = format!("ref mut{}", &hi_src["ref".len()..]); - (hi_span, suggestion) + if hi_src.starts_with("ref") + && hi_src["ref".len()..].starts_with(Pattern_White_Space) + { + let suggestion = format!("ref mut{}", &hi_src["ref".len()..]); + Some((hi_span, suggestion)) + } else { + None + } } } diff --git a/src/test/ui/rfc-2005-default-binding-mode/enum.nll.stderr b/src/test/ui/rfc-2005-default-binding-mode/enum.nll.stderr index 8aa7e8a417c2b..a9b2bca434cba 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/enum.nll.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/enum.nll.stderr @@ -2,19 +2,19 @@ error[E0594]: cannot assign to `*x` which is behind a `&` reference --> $DIR/enum.rs:19:5 | LL | *x += 1; //~ ERROR cannot assign to immutable - | ^^^^^^^ cannot assign + | ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written error[E0594]: cannot assign to `*x` which is behind a `&` reference --> $DIR/enum.rs:23:9 | LL | *x += 1; //~ ERROR cannot assign to immutable - | ^^^^^^^ cannot assign + | ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written error[E0594]: cannot assign to `*x` which is behind a `&` reference --> $DIR/enum.rs:29:9 | LL | *x += 1; //~ ERROR cannot assign to immutable - | ^^^^^^^ cannot assign + | ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written error: aborting due to 3 previous errors diff --git a/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.nll.stderr b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.nll.stderr index 4e00dec761621..4c6149a8b7b30 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.nll.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.nll.stderr @@ -2,19 +2,19 @@ error[E0594]: cannot assign to `*n` which is behind a `&` reference --> $DIR/explicit-mut.rs:17:13 | LL | *n += 1; //~ ERROR cannot assign to immutable - | ^^^^^^^ cannot assign + | ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written error[E0594]: cannot assign to `*n` which is behind a `&` reference --> $DIR/explicit-mut.rs:25:13 | LL | *n += 1; //~ ERROR cannot assign to immutable - | ^^^^^^^ cannot assign + | ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written error[E0594]: cannot assign to `*n` which is behind a `&` reference --> $DIR/explicit-mut.rs:33:13 | LL | *n += 1; //~ ERROR cannot assign to immutable - | ^^^^^^^ cannot assign + | ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written error: aborting due to 3 previous errors From b8b04f6385ce9909a165ff47c5ebf49ded1fc6db Mon Sep 17 00:00:00 2001 From: ashtneoi Date: Tue, 10 Jul 2018 23:23:13 -0700 Subject: [PATCH 22/34] Put the two halves of suggest_ampmut back together --- src/librustc_mir/borrow_check/mod.rs | 38 ++++++++++++---------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 95601f1337139..039f43cd213f7 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1850,22 +1850,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { binding_mode: ty::BindingMode::BindByValue(_), opt_ty_info, .. - }))) => { - if let Some(x) = try_suggest_ampmut_rhs( - self.tcx, self.mir, *local, - ) { - Some(x) - } else { - Some(suggest_ampmut_type(local_decl, opt_ty_info)) - } - }, + }))) => Some(suggest_ampmut( + self.tcx, + self.mir, + *local, + local_decl, + opt_ty_info, + )), Some(ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm { binding_mode: ty::BindingMode::BindByReference(_), .. - }))) => { - suggest_ref_mut(self.tcx, local_decl) - }, + }))) => suggest_ref_mut(self.tcx, local_decl), Some(ClearCrossCrate::Clear) => bug!("saw cleared local state"), @@ -1927,12 +1923,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // // This implementation attempts to emulate AST-borrowck prioritization // by trying (3.), then (2.) and finally falling back on (1.). - - fn try_suggest_ampmut_rhs<'cx, 'gcx, 'tcx>( + fn suggest_ampmut<'cx, 'gcx, 'tcx>( tcx: TyCtxt<'cx, 'gcx, 'tcx>, mir: &Mir<'tcx>, local: Local, - ) -> Option<(Span, String)> { + local_decl: &mir::LocalDecl<'tcx>, + opt_ty_info: Option, + ) -> (Span, String) { let locations = mir.find_assignments(local); if locations.len() > 0 { let assignment_rhs_span = mir.source_info(locations[0]).span; @@ -1940,17 +1937,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if let Ok(src) = snippet { if src.starts_with('&') { let borrowed_expr = src[1..].to_string(); - return Some((assignment_rhs_span, format!("&mut {}", borrowed_expr))); + return ( + assignment_rhs_span, + format!("&mut {}", borrowed_expr), + ); } } } - None - } - fn suggest_ampmut_type<'tcx>( - local_decl: &mir::LocalDecl<'tcx>, - opt_ty_info: Option, - ) -> (Span, String) { let highlight_span = match opt_ty_info { // if this is a variable binding with an explicit type, // try to highlight that for the suggestion. From 73a979ad63ea20821996809aaccb82767ac84658 Mon Sep 17 00:00:00 2001 From: ashtneoi Date: Wed, 11 Jul 2018 00:44:55 -0700 Subject: [PATCH 23/34] Simplify match expression --- src/librustc_mir/borrow_check/mod.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 039f43cd213f7..b754fde9069a5 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1841,31 +1841,29 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { elem: ProjectionElem::Deref, }) if self.mir.local_decls[*local].is_user_variable.is_some() => { let local_decl = &self.mir.local_decls[*local]; - let suggestion = match local_decl.is_user_variable { - Some(ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf)) => { + let suggestion = match local_decl.is_user_variable.as_ref().unwrap() { + ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf) => { Some(suggest_ampmut_self(local_decl)) }, - Some(ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm { + ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm { binding_mode: ty::BindingMode::BindByValue(_), opt_ty_info, .. - }))) => Some(suggest_ampmut( + })) => Some(suggest_ampmut( self.tcx, self.mir, *local, local_decl, - opt_ty_info, + *opt_ty_info, )), - Some(ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm { + ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm { binding_mode: ty::BindingMode::BindByReference(_), .. - }))) => suggest_ref_mut(self.tcx, local_decl), - - Some(ClearCrossCrate::Clear) => bug!("saw cleared local state"), + })) => suggest_ref_mut(self.tcx, local_decl), - None => bug!(), + ClearCrossCrate::Clear => bug!("saw cleared local state"), }; if let Some((err_help_span, suggested_code)) = suggestion { From 77d5f397716778fcc82a60ea9d6102c0cfea15f6 Mon Sep 17 00:00:00 2001 From: ashtneoi Date: Wed, 11 Jul 2018 03:45:25 -0700 Subject: [PATCH 24/34] Also test `&mut self` suggestion --- src/test/ui/suggestions/suggest-ref-mut.rs | 11 +++++++++++ src/test/ui/suggestions/suggest-ref-mut.stderr | 17 +++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/test/ui/suggestions/suggest-ref-mut.rs b/src/test/ui/suggestions/suggest-ref-mut.rs index 1f5c5b033286c..30b5371af1ac5 100644 --- a/src/test/ui/suggestions/suggest-ref-mut.rs +++ b/src/test/ui/suggestions/suggest-ref-mut.rs @@ -10,6 +10,17 @@ #![feature(nll)] +struct X(usize); + +impl X { + fn zap(&self) { + //~^ HELP + //~| SUGGESTION &mut self + self.0 = 32; + //~^ ERROR + } +} + fn main() { let ref foo = 16; //~^ HELP diff --git a/src/test/ui/suggestions/suggest-ref-mut.stderr b/src/test/ui/suggestions/suggest-ref-mut.stderr index d1590b3934e0b..0b2b240ef53a8 100644 --- a/src/test/ui/suggestions/suggest-ref-mut.stderr +++ b/src/test/ui/suggestions/suggest-ref-mut.stderr @@ -1,5 +1,14 @@ +error[E0594]: cannot assign to `self.0` which is behind a `&` reference + --> $DIR/suggest-ref-mut.rs:19:9 + | +LL | fn zap(&self) { + | ----- help: consider changing this to be a mutable reference: `&mut self` +... +LL | self.0 = 32; + | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written + error[E0594]: cannot assign to `*foo` which is behind a `&` reference - --> $DIR/suggest-ref-mut.rs:17:5 + --> $DIR/suggest-ref-mut.rs:28:5 | LL | let ref foo = 16; | ------- help: consider changing this to be a mutable reference: `ref mut foo` @@ -8,7 +17,7 @@ LL | *foo = 32; | ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written error[E0594]: cannot assign to `*bar` which is behind a `&` reference - --> $DIR/suggest-ref-mut.rs:22:9 + --> $DIR/suggest-ref-mut.rs:33:9 | LL | if let Some(ref bar) = Some(16) { | ------- help: consider changing this to be a mutable reference: `ref mut bar` @@ -17,13 +26,13 @@ LL | *bar = 32; | ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written error[E0594]: cannot assign to `*quo` which is behind a `&` reference - --> $DIR/suggest-ref-mut.rs:26:22 + --> $DIR/suggest-ref-mut.rs:37:22 | LL | ref quo => { *quo = 32; }, | ------- ^^^^^^^^^ `quo` is a `&` reference, so the data it refers to cannot be written | | | help: consider changing this to be a mutable reference: `ref mut quo` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0594`. From 246caea009fd7b652d00f1b0a94108b7ac5b7938 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Thu, 31 May 2018 22:31:13 +0800 Subject: [PATCH 25/34] fix wrong replacing --- src/librustc_borrowck/borrowck/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 7c2d5ba094ffa..072f94661e429 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -1214,7 +1214,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { db.span_label( let_span, format!("consider changing this to `{}`", - snippet.replace("ref ", "ref mut ")) + snippet.replacen("ref ", "ref mut ", 1)) ); } } From 4e5d22889bb299290fba61c9b51afe75bac583a0 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Thu, 31 May 2018 23:00:58 +0800 Subject: [PATCH 26/34] update test --- src/test/ui/suggestions/issue-51244.rs | 14 ++++++++++++++ src/test/ui/suggestions/issue-51244.stderr | 11 +++++++++++ 2 files changed, 25 insertions(+) create mode 100644 src/test/ui/suggestions/issue-51244.rs create mode 100644 src/test/ui/suggestions/issue-51244.stderr diff --git a/src/test/ui/suggestions/issue-51244.rs b/src/test/ui/suggestions/issue-51244.rs new file mode 100644 index 0000000000000..efb8a03a45cbc --- /dev/null +++ b/src/test/ui/suggestions/issue-51244.rs @@ -0,0 +1,14 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let ref my_ref @ _ = 0; + *my_ref = 0; +} diff --git a/src/test/ui/suggestions/issue-51244.stderr b/src/test/ui/suggestions/issue-51244.stderr new file mode 100644 index 0000000000000..b6663c3789ebc --- /dev/null +++ b/src/test/ui/suggestions/issue-51244.stderr @@ -0,0 +1,11 @@ +error[E0594]: cannot assign to immutable borrowed content `*my_ref` + --> $DIR/issue-51244.rs:13:5 + | +LL | let ref my_ref @ _ = 0; + | -------------- consider changing this to `ref mut my_ref @ _` +LL | *my_ref = 0; + | ^^^^^^^^^^^ cannot borrow as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. From 1662daa23d77d77107743926efee72e8254d8f35 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Fri, 1 Jun 2018 12:08:31 +0800 Subject: [PATCH 27/34] lint with ref_span --- src/librustc_borrowck/borrowck/mod.rs | 12 +++++------- src/test/ui/suggestions/issue-51244.stderr | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 072f94661e429..f09feac51fcfb 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -1209,14 +1209,12 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { let let_span = self.tcx.hir.span(node_id); match self.local_binding_mode(node_id) { ty::BindByReference(..) => { - let snippet = self.tcx.sess.codemap().span_to_snippet(let_span); - if let Ok(snippet) = snippet { + let ref_span = self.tcx.sess.codemap().span_until_whitespace(let_span); + if let Ok(_) = self.tcx.sess.codemap().span_to_snippet(let_span) { db.span_label( - let_span, - format!("consider changing this to `{}`", - snippet.replacen("ref ", "ref mut ", 1)) - ); - } + ref_span, + format!("consider changing this to `{}`", "ref mut")); + }; } ty::BindByValue(..) => { if let (Some(local_ty), is_implicit_self) = self.local_ty(node_id) { diff --git a/src/test/ui/suggestions/issue-51244.stderr b/src/test/ui/suggestions/issue-51244.stderr index b6663c3789ebc..f653a2a3359b1 100644 --- a/src/test/ui/suggestions/issue-51244.stderr +++ b/src/test/ui/suggestions/issue-51244.stderr @@ -2,7 +2,7 @@ error[E0594]: cannot assign to immutable borrowed content `*my_ref` --> $DIR/issue-51244.rs:13:5 | LL | let ref my_ref @ _ = 0; - | -------------- consider changing this to `ref mut my_ref @ _` + | --- consider changing this to `ref mut` LL | *my_ref = 0; | ^^^^^^^^^^^ cannot borrow as mutable From af5edc32df6a30bc7c8caa01bb9700b38354e21f Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Fri, 1 Jun 2018 19:00:15 +0800 Subject: [PATCH 28/34] replace ref --- src/librustc_borrowck/borrowck/mod.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index f09feac51fcfb..aa00ccd1f08cd 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -1209,11 +1209,16 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { let let_span = self.tcx.hir.span(node_id); match self.local_binding_mode(node_id) { ty::BindByReference(..) => { - let ref_span = self.tcx.sess.codemap().span_until_whitespace(let_span); - if let Ok(_) = self.tcx.sess.codemap().span_to_snippet(let_span) { + if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(let_span) { + let replace_str = if snippet.starts_with("ref ") { + snippet.replacen("ref ", "ref mut ", 1) + } else { + snippet + }; db.span_label( - ref_span, - format!("consider changing this to `{}`", "ref mut")); + let_span, + format!("consider changing this to `{}`", replace_str) + ); }; } ty::BindByValue(..) => { From 212da122f798b1a4a58f41c7eeb8111dffaee4cb Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Fri, 1 Jun 2018 21:03:24 +0800 Subject: [PATCH 29/34] update test --- src/test/ui/suggestions/issue-51244.rs | 2 +- src/test/ui/suggestions/issue-51244.stderr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/ui/suggestions/issue-51244.rs b/src/test/ui/suggestions/issue-51244.rs index efb8a03a45cbc..50a21184a98b9 100644 --- a/src/test/ui/suggestions/issue-51244.rs +++ b/src/test/ui/suggestions/issue-51244.rs @@ -10,5 +10,5 @@ fn main() { let ref my_ref @ _ = 0; - *my_ref = 0; + *my_ref = 0; //~ ERROR cannot assign to immutable borrowed content `*my_ref` [E0594] } diff --git a/src/test/ui/suggestions/issue-51244.stderr b/src/test/ui/suggestions/issue-51244.stderr index f653a2a3359b1..b4ce29756235b 100644 --- a/src/test/ui/suggestions/issue-51244.stderr +++ b/src/test/ui/suggestions/issue-51244.stderr @@ -2,8 +2,8 @@ error[E0594]: cannot assign to immutable borrowed content `*my_ref` --> $DIR/issue-51244.rs:13:5 | LL | let ref my_ref @ _ = 0; - | --- consider changing this to `ref mut` -LL | *my_ref = 0; + | -------------- consider changing this to `ref mut my_ref @ _` +LL | *my_ref = 0; //~ ERROR cannot assign to immutable borrowed content `*my_ref` [E0594] | ^^^^^^^^^^^ cannot borrow as mutable error: aborting due to previous error From 8932684ccc3b4a24a301bd68a6c21a182dfd6028 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Sun, 3 Jun 2018 12:06:21 +0800 Subject: [PATCH 30/34] add nll stderr --- src/test/ui/suggestions/issue-51244.nll.stderr | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/test/ui/suggestions/issue-51244.nll.stderr diff --git a/src/test/ui/suggestions/issue-51244.nll.stderr b/src/test/ui/suggestions/issue-51244.nll.stderr new file mode 100644 index 0000000000000..95b71c41cfa7b --- /dev/null +++ b/src/test/ui/suggestions/issue-51244.nll.stderr @@ -0,0 +1,11 @@ +error[E0594]: cannot assign to data in a `&` reference + --> $DIR/issue-51244.rs:13:5 + | +LL | let ref my_ref @ _ = 0; + | -------------- help: consider changing this to be a mutable reference: `&mut ef my_ref @ _` +LL | *my_ref = 0; //~ ERROR cannot assign to immutable borrowed content `*my_ref` [E0594] + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. From 7a70140ed5a3fb5aa747d219f19f8b1d55812807 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Thu, 14 Jun 2018 09:12:50 +0800 Subject: [PATCH 31/34] span_suggestion --- src/librustc_borrowck/borrowck/mod.rs | 5 +++-- src/test/ui/nll/issue-51244.rs | 16 ++++++++++++++++ .../issue-51244.stderr} | 4 ++-- .../ui/rfc-2005-default-binding-mode/enum.stderr | 6 +++--- .../explicit-mut.stderr | 6 +++--- src/test/ui/suggestions/issue-51244.stderr | 2 +- 6 files changed, 28 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/nll/issue-51244.rs rename src/test/ui/{suggestions/issue-51244.nll.stderr => nll/issue-51244.stderr} (72%) diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index aa00ccd1f08cd..6a42189fb152f 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -1215,9 +1215,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } else { snippet }; - db.span_label( + db.span_suggestion( let_span, - format!("consider changing this to `{}`", replace_str) + "use a mutable reference instead", + replace_str, ); }; } diff --git a/src/test/ui/nll/issue-51244.rs b/src/test/ui/nll/issue-51244.rs new file mode 100644 index 0000000000000..56d9449c4679d --- /dev/null +++ b/src/test/ui/nll/issue-51244.rs @@ -0,0 +1,16 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(nll)] + +fn main() { + let ref my_ref @ _ = 0; + *my_ref = 0; //~ ERROR cannot assign to data in a `&` reference [E0594] +} diff --git a/src/test/ui/suggestions/issue-51244.nll.stderr b/src/test/ui/nll/issue-51244.stderr similarity index 72% rename from src/test/ui/suggestions/issue-51244.nll.stderr rename to src/test/ui/nll/issue-51244.stderr index 95b71c41cfa7b..f1f47fc61ce8b 100644 --- a/src/test/ui/suggestions/issue-51244.nll.stderr +++ b/src/test/ui/nll/issue-51244.stderr @@ -1,9 +1,9 @@ error[E0594]: cannot assign to data in a `&` reference - --> $DIR/issue-51244.rs:13:5 + --> $DIR/issue-51244.rs:15:5 | LL | let ref my_ref @ _ = 0; | -------------- help: consider changing this to be a mutable reference: `&mut ef my_ref @ _` -LL | *my_ref = 0; //~ ERROR cannot assign to immutable borrowed content `*my_ref` [E0594] +LL | *my_ref = 0; //~ ERROR cannot assign to data in a `&` reference [E0594] | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/rfc-2005-default-binding-mode/enum.stderr b/src/test/ui/rfc-2005-default-binding-mode/enum.stderr index a7f3b507508e8..26d51e9338152 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/enum.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/enum.stderr @@ -2,7 +2,7 @@ error[E0594]: cannot assign to immutable borrowed content `*x` --> $DIR/enum.rs:19:5 | LL | let Wrap(x) = &Wrap(3); - | - consider changing this to `x` + | - help: use a mutable reference instead: `x` LL | *x += 1; //~ ERROR cannot assign to immutable | ^^^^^^^ cannot borrow as mutable @@ -10,7 +10,7 @@ error[E0594]: cannot assign to immutable borrowed content `*x` --> $DIR/enum.rs:23:9 | LL | if let Some(x) = &Some(3) { - | - consider changing this to `x` + | - help: use a mutable reference instead: `x` LL | *x += 1; //~ ERROR cannot assign to immutable | ^^^^^^^ cannot borrow as mutable @@ -18,7 +18,7 @@ error[E0594]: cannot assign to immutable borrowed content `*x` --> $DIR/enum.rs:29:9 | LL | while let Some(x) = &Some(3) { - | - consider changing this to `x` + | - help: use a mutable reference instead: `x` LL | *x += 1; //~ ERROR cannot assign to immutable | ^^^^^^^ cannot borrow as mutable diff --git a/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.stderr b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.stderr index f2b9bde41ab33..2f5eb8a3d8ecc 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.stderr @@ -2,7 +2,7 @@ error[E0594]: cannot assign to immutable borrowed content `*n` --> $DIR/explicit-mut.rs:17:13 | LL | Some(n) => { - | - consider changing this to `n` + | - help: use a mutable reference instead: `n` LL | *n += 1; //~ ERROR cannot assign to immutable | ^^^^^^^ cannot borrow as mutable @@ -10,7 +10,7 @@ error[E0594]: cannot assign to immutable borrowed content `*n` --> $DIR/explicit-mut.rs:25:13 | LL | Some(n) => { - | - consider changing this to `n` + | - help: use a mutable reference instead: `n` LL | *n += 1; //~ ERROR cannot assign to immutable | ^^^^^^^ cannot borrow as mutable @@ -18,7 +18,7 @@ error[E0594]: cannot assign to immutable borrowed content `*n` --> $DIR/explicit-mut.rs:33:13 | LL | Some(n) => { - | - consider changing this to `n` + | - help: use a mutable reference instead: `n` LL | *n += 1; //~ ERROR cannot assign to immutable | ^^^^^^^ cannot borrow as mutable diff --git a/src/test/ui/suggestions/issue-51244.stderr b/src/test/ui/suggestions/issue-51244.stderr index b4ce29756235b..997a74295e565 100644 --- a/src/test/ui/suggestions/issue-51244.stderr +++ b/src/test/ui/suggestions/issue-51244.stderr @@ -2,7 +2,7 @@ error[E0594]: cannot assign to immutable borrowed content `*my_ref` --> $DIR/issue-51244.rs:13:5 | LL | let ref my_ref @ _ = 0; - | -------------- consider changing this to `ref mut my_ref @ _` + | -------------- help: use a mutable reference instead: `ref mut my_ref @ _` LL | *my_ref = 0; //~ ERROR cannot assign to immutable borrowed content `*my_ref` [E0594] | ^^^^^^^^^^^ cannot borrow as mutable From 323df7b5049f6026a5bed335e2d7bb1df89b47ef Mon Sep 17 00:00:00 2001 From: ashtneoi Date: Thu, 12 Jul 2018 13:11:47 -0700 Subject: [PATCH 32/34] Bless tests and update ERROR --- src/test/ui/nll/issue-51244.rs | 3 ++- src/test/ui/nll/issue-51244.stderr | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/test/ui/nll/issue-51244.rs b/src/test/ui/nll/issue-51244.rs index 56d9449c4679d..f00ad3d6505be 100644 --- a/src/test/ui/nll/issue-51244.rs +++ b/src/test/ui/nll/issue-51244.rs @@ -12,5 +12,6 @@ fn main() { let ref my_ref @ _ = 0; - *my_ref = 0; //~ ERROR cannot assign to data in a `&` reference [E0594] + *my_ref = 0; + //~^ ERROR cannot assign to `*my_ref` which is behind a `&` reference [E0594] } diff --git a/src/test/ui/nll/issue-51244.stderr b/src/test/ui/nll/issue-51244.stderr index f1f47fc61ce8b..4e04aec8fe1af 100644 --- a/src/test/ui/nll/issue-51244.stderr +++ b/src/test/ui/nll/issue-51244.stderr @@ -1,10 +1,10 @@ -error[E0594]: cannot assign to data in a `&` reference +error[E0594]: cannot assign to `*my_ref` which is behind a `&` reference --> $DIR/issue-51244.rs:15:5 | LL | let ref my_ref @ _ = 0; - | -------------- help: consider changing this to be a mutable reference: `&mut ef my_ref @ _` -LL | *my_ref = 0; //~ ERROR cannot assign to data in a `&` reference [E0594] - | ^^^^^^^^^^^ + | -------------- help: consider changing this to be a mutable reference: `ref mut my_ref @ _` +LL | *my_ref = 0; + | ^^^^^^^^^^^ `my_ref` is a `&` reference, so the data it refers to cannot be written error: aborting due to previous error From 531a68cea711be0b803799fd30cc6cca43bea449 Mon Sep 17 00:00:00 2001 From: ashtneoi Date: Thu, 12 Jul 2018 15:39:36 -0700 Subject: [PATCH 33/34] Factor out suggest_ref_mut; use it in rustc_borrowck Also teach rustc_borrowck not to show useless help messages like "use a mutable reference instead: `x`". --- src/librustc_borrowck/borrowck/mod.rs | 13 +++++------- src/librustc_mir/borrow_check/mod.rs | 21 ++----------------- src/librustc_mir/util/mod.rs | 20 ++++++++++++++++++ .../rfc-2005-default-binding-mode/enum.stderr | 6 ------ .../explicit-mut.stderr | 6 ------ 5 files changed, 27 insertions(+), 39 deletions(-) diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 6a42189fb152f..79b4382369217 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -39,6 +39,7 @@ use rustc::middle::free_region::RegionRelations; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::query::Providers; use rustc_mir::util::borrowck_errors::{BorrowckErrors, Origin}; +use rustc_mir::util::suggest_ref_mut; use rustc::util::nodemap::FxHashSet; use std::cell::RefCell; @@ -1206,21 +1207,17 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.note_immutable_local(db, error_node_id, node_id) } Some(ImmutabilityBlame::LocalDeref(node_id)) => { - let let_span = self.tcx.hir.span(node_id); match self.local_binding_mode(node_id) { ty::BindByReference(..) => { - if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(let_span) { - let replace_str = if snippet.starts_with("ref ") { - snippet.replacen("ref ", "ref mut ", 1) - } else { - snippet - }; + let let_span = self.tcx.hir.span(node_id); + let suggestion = suggest_ref_mut(self.tcx, let_span); + if let Some((let_span, replace_str)) = suggestion { db.span_suggestion( let_span, "use a mutable reference instead", replace_str, ); - }; + } } ty::BindByValue(..) => { if let (Some(local_ty), is_implicit_self) = self.local_ty(node_id) { diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index b754fde9069a5..7078d77f3fb2b 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -29,8 +29,6 @@ use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::small_vec::SmallVec; -use core::unicode::property::Pattern_White_Space; - use std::rc::Rc; use syntax_pos::Span; @@ -46,6 +44,7 @@ use dataflow::{EverInitializedPlaces, MovingOutStatements}; use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; use util::borrowck_errors::{BorrowckErrors, Origin}; use util::collect_writes::FindAssignments; +use util::suggest_ref_mut; use self::borrow_set::{BorrowData, BorrowSet}; use self::flows::Flows; @@ -1861,7 +1860,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm { binding_mode: ty::BindingMode::BindByReference(_), .. - })) => suggest_ref_mut(self.tcx, local_decl), + })) => suggest_ref_mut(self.tcx, local_decl.source_info.span), ClearCrossCrate::Clear => bug!("saw cleared local state"), }; @@ -1957,22 +1956,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { assert_eq!(ty_mut.mutbl, hir::MutImmutable); (highlight_span, format!("&mut {}", ty_mut.ty)) } - - fn suggest_ref_mut<'cx, 'gcx, 'tcx>( - tcx: TyCtxt<'cx, 'gcx, 'tcx>, - local_decl: &mir::LocalDecl<'tcx>, - ) -> Option<(Span, String)> { - let hi_span = local_decl.source_info.span; - let hi_src = tcx.sess.codemap().span_to_snippet(hi_span).unwrap(); - if hi_src.starts_with("ref") - && hi_src["ref".len()..].starts_with(Pattern_White_Space) - { - let suggestion = format!("ref mut{}", &hi_src["ref".len()..]); - Some((hi_span, suggestion)) - } else { - None - } - } } /// Adds the place into the used mutable variables set diff --git a/src/librustc_mir/util/mod.rs b/src/librustc_mir/util/mod.rs index 19cd376688627..78e9dd23e83ae 100644 --- a/src/librustc_mir/util/mod.rs +++ b/src/librustc_mir/util/mod.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::unicode::property::Pattern_White_Space; +use rustc::ty; +use syntax_pos::Span; + pub mod borrowck_errors; pub mod elaborate_drops; pub mod def_use; @@ -23,3 +27,19 @@ pub use self::alignment::is_disaligned; pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty, PassWhere}; pub use self::graphviz::{write_mir_graphviz}; pub use self::graphviz::write_node_label as write_graphviz_node_label; + +/// If possible, suggest replacing `ref` with `ref mut`. +pub fn suggest_ref_mut<'cx, 'gcx, 'tcx>( + tcx: ty::TyCtxt<'cx, 'gcx, 'tcx>, + pattern_span: Span, +) -> Option<(Span, String)> { + let hi_src = tcx.sess.codemap().span_to_snippet(pattern_span).unwrap(); + if hi_src.starts_with("ref") + && hi_src["ref".len()..].starts_with(Pattern_White_Space) + { + let replacement = format!("ref mut{}", &hi_src["ref".len()..]); + Some((pattern_span, replacement)) + } else { + None + } +} diff --git a/src/test/ui/rfc-2005-default-binding-mode/enum.stderr b/src/test/ui/rfc-2005-default-binding-mode/enum.stderr index 26d51e9338152..ad05de9f3575f 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/enum.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/enum.stderr @@ -1,24 +1,18 @@ error[E0594]: cannot assign to immutable borrowed content `*x` --> $DIR/enum.rs:19:5 | -LL | let Wrap(x) = &Wrap(3); - | - help: use a mutable reference instead: `x` LL | *x += 1; //~ ERROR cannot assign to immutable | ^^^^^^^ cannot borrow as mutable error[E0594]: cannot assign to immutable borrowed content `*x` --> $DIR/enum.rs:23:9 | -LL | if let Some(x) = &Some(3) { - | - help: use a mutable reference instead: `x` LL | *x += 1; //~ ERROR cannot assign to immutable | ^^^^^^^ cannot borrow as mutable error[E0594]: cannot assign to immutable borrowed content `*x` --> $DIR/enum.rs:29:9 | -LL | while let Some(x) = &Some(3) { - | - help: use a mutable reference instead: `x` LL | *x += 1; //~ ERROR cannot assign to immutable | ^^^^^^^ cannot borrow as mutable diff --git a/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.stderr b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.stderr index 2f5eb8a3d8ecc..8da67a6b5ee65 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.stderr @@ -1,24 +1,18 @@ error[E0594]: cannot assign to immutable borrowed content `*n` --> $DIR/explicit-mut.rs:17:13 | -LL | Some(n) => { - | - help: use a mutable reference instead: `n` LL | *n += 1; //~ ERROR cannot assign to immutable | ^^^^^^^ cannot borrow as mutable error[E0594]: cannot assign to immutable borrowed content `*n` --> $DIR/explicit-mut.rs:25:13 | -LL | Some(n) => { - | - help: use a mutable reference instead: `n` LL | *n += 1; //~ ERROR cannot assign to immutable | ^^^^^^^ cannot borrow as mutable error[E0594]: cannot assign to immutable borrowed content `*n` --> $DIR/explicit-mut.rs:33:13 | -LL | Some(n) => { - | - help: use a mutable reference instead: `n` LL | *n += 1; //~ ERROR cannot assign to immutable | ^^^^^^^ cannot borrow as mutable From 1ed861910f1a875c7bf19ee398cad1570b92aad4 Mon Sep 17 00:00:00 2001 From: ashtneoi Date: Thu, 12 Jul 2018 23:11:57 -0700 Subject: [PATCH 34/34] Bless one more test --- src/test/ui/suggestions/issue-51244.nll.stderr | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/test/ui/suggestions/issue-51244.nll.stderr diff --git a/src/test/ui/suggestions/issue-51244.nll.stderr b/src/test/ui/suggestions/issue-51244.nll.stderr new file mode 100644 index 0000000000000..ce02ae2aec23f --- /dev/null +++ b/src/test/ui/suggestions/issue-51244.nll.stderr @@ -0,0 +1,11 @@ +error[E0594]: cannot assign to `*my_ref` which is behind a `&` reference + --> $DIR/issue-51244.rs:13:5 + | +LL | let ref my_ref @ _ = 0; + | -------------- help: consider changing this to be a mutable reference: `ref mut my_ref @ _` +LL | *my_ref = 0; //~ ERROR cannot assign to immutable borrowed content `*my_ref` [E0594] + | ^^^^^^^^^^^ `my_ref` is a `&` reference, so the data it refers to cannot be written + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`.