From 820aa5b2ef9b527a67b46ef70f001151f5d66441 Mon Sep 17 00:00:00 2001 From: Alessandro Ghedini Date: Wed, 28 Aug 2019 23:55:28 +0100 Subject: [PATCH 01/25] Stabilize pin_into_inner in 1.39.0 FCP: https://github.com/rust-lang/rust/issues/60245#issuecomment-522258129 Closes #60245 --- src/libcore/pin.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 6efeaf9ee7d2e..1080fd32a8862 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -462,7 +462,7 @@ impl> Pin

{ /// can ignore the pinning invariants when unwrapping it. /// /// [`Unpin`]: ../../std/marker/trait.Unpin.html - #[unstable(feature = "pin_into_inner", issue = "60245")] + #[stable(feature = "pin_into_inner", since = "1.39.0")] #[inline(always)] pub fn into_inner(pin: Pin

) -> P { pin.pointer @@ -569,7 +569,7 @@ impl Pin

{ /// /// [`Unpin`]: ../../std/marker/trait.Unpin.html /// [`Pin::into_inner`]: #method.into_inner - #[unstable(feature = "pin_into_inner", issue = "60245")] + #[stable(feature = "pin_into_inner", since = "1.39.0")] #[inline(always)] pub unsafe fn into_inner_unchecked(pin: Pin

) -> P { pin.pointer From 86487329bb385f74bed67718f2358436ddca1aa4 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Thu, 29 Aug 2019 13:22:16 -0700 Subject: [PATCH 02/25] Add `Place::is_indirect` This returns whether a `Place` references the same region of memory as its base, or equivalently whether it contains a `Deref` projection. This is helpful for analyses that must track state for locals, since an assignment to `x` or `x.field` is fundamentally different than one to `*x`, which may mutate any memory region. --- src/librustc/mir/mod.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 858b77af80468..a07f12cd9c5f2 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1801,6 +1801,23 @@ pub enum ProjectionElem { Downcast(Option, VariantIdx), } +impl ProjectionElem { + /// Returns `true` if the target of this projection may refer to a different region of memory + /// than the base. + fn is_indirect(&self) -> bool { + match self { + Self::Deref => true, + + | Self::Field(_, _) + | Self::Index(_) + | Self::ConstantIndex { .. } + | Self::Subslice { .. } + | Self::Downcast(_, _) + => false + } + } +} + /// Alias for projections as they appear in places, where the base is a place /// and the index is a local. pub type PlaceElem<'tcx> = ProjectionElem>; @@ -1862,6 +1879,14 @@ impl<'tcx> Place<'tcx> { } } + /// Returns `true` if this `Place` contains a `Deref` projection. + /// + /// If `Place::is_indirect` returns false, the caller knows that the `Place` refers to the + /// same region of memory as its base. + pub fn is_indirect(&self) -> bool { + self.iterate(|_, mut projections| projections.any(|proj| proj.elem.is_indirect())) + } + /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or /// a single deref of a local. // From 0e597d4c479b4533e38016b1adbe565b44aab922 Mon Sep 17 00:00:00 2001 From: Xiang Fan Date: Fri, 30 Aug 2019 21:17:36 +0800 Subject: [PATCH 03/25] Rev::rposition counts from the wrong end Because of a compiler bug that adding `Self: ExactSizeIterator` makes the compiler forget `Self::Item` is `::Item`, we remove this specialization for now. --- src/libcore/iter/adapters/mod.rs | 7 ------- src/libcore/tests/iter.rs | 6 ++++++ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index f50781890ab22..8e1ac6082c8a8 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -66,13 +66,6 @@ impl Iterator for Rev where I: DoubleEndedIterator { { self.iter.rfind(predicate) } - - #[inline] - fn rposition

(&mut self, predicate: P) -> Option where - P: FnMut(Self::Item) -> bool - { - self.iter.position(predicate) - } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 3a4f76852a0d7..8e0658d87c1fb 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1688,6 +1688,12 @@ fn test_rposition() { assert!(v.iter().rposition(g).is_none()); } +#[test] +fn test_rev_rposition() { + let v = [0, 0, 1, 1]; + assert_eq!(v.iter().rev().rposition(|&x| x == 1), Some(1)); +} + #[test] #[should_panic] fn test_rposition_panic() { From 96ac02b8b3aeebc463d434c57b4a2ada9a3003e6 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Thu, 29 Aug 2019 13:30:53 -0700 Subject: [PATCH 04/25] Use new `Place::is_indirect` API where possible --- src/librustc_mir/borrow_check/path_utils.rs | 23 ++++++------------- .../dataflow/impls/borrowed_locals.rs | 17 ++++---------- 2 files changed, 11 insertions(+), 29 deletions(-) diff --git a/src/librustc_mir/borrow_check/path_utils.rs b/src/librustc_mir/borrow_check/path_utils.rs index 43a012e1494f8..bac08090817d9 100644 --- a/src/librustc_mir/borrow_check/path_utils.rs +++ b/src/librustc_mir/borrow_check/path_utils.rs @@ -3,7 +3,7 @@ use crate::borrow_check::places_conflict; use crate::borrow_check::AccessDepth; use crate::dataflow::indexes::BorrowIndex; use rustc::mir::{BasicBlock, Location, Body, Place, PlaceBase}; -use rustc::mir::{ProjectionElem, BorrowKind}; +use rustc::mir::BorrowKind; use rustc::ty::{self, TyCtxt}; use rustc_data_structures::graph::dominators::Dominators; @@ -133,20 +133,11 @@ pub(super) fn is_active<'tcx>( /// Determines if a given borrow is borrowing local data /// This is called for all Yield statements on movable generators pub(super) fn borrow_of_local_data(place: &Place<'_>) -> bool { - place.iterate(|place_base, place_projection| { - match place_base { - PlaceBase::Static(..) => return false, - PlaceBase::Local(..) => {}, - } - - for proj in place_projection { - // Reborrow of already borrowed data is ignored - // Any errors will be caught on the initial borrow - if proj.elem == ProjectionElem::Deref { - return false; - } - } + match place.base { + PlaceBase::Static(_) => false, - true - }) + // Reborrow of already borrowed data is ignored + // Any errors will be caught on the initial borrow + PlaceBase::Local(_) => !place.is_indirect(), + } } diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs index d94ebdbae24ae..1c43a553cc3c9 100644 --- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs +++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs @@ -93,19 +93,10 @@ struct BorrowedLocalsVisitor<'gk> { } fn find_local(place: &Place<'_>) -> Option { - place.iterate(|place_base, place_projection| { - for proj in place_projection { - if proj.elem == ProjectionElem::Deref { - return None; - } - } - - if let PlaceBase::Local(local) = place_base { - Some(*local) - } else { - None - } - }) + match place.base { + PlaceBase::Local(local) if !place.is_indirect() => Some(local), + _ => None, + } } impl<'tcx> Visitor<'tcx> for BorrowedLocalsVisitor<'_> { From 5187a3e15723c85cd7ef3418b0c0e61c79709f4c Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 31 Aug 2019 07:08:23 +0200 Subject: [PATCH 05/25] Harden param_attrs test wrt. usage of proc macro attrs. --- .../auxiliary/ident-mac.rs | 11 + .../proc-macro-cannot-be-used.rs | 60 +++++ .../proc-macro-cannot-be-used.stderr | 228 ++++++++++++++++++ 3 files changed, 299 insertions(+) create mode 100644 src/test/ui/rfc-2565-param-attrs/auxiliary/ident-mac.rs create mode 100644 src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs create mode 100644 src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr diff --git a/src/test/ui/rfc-2565-param-attrs/auxiliary/ident-mac.rs b/src/test/ui/rfc-2565-param-attrs/auxiliary/ident-mac.rs new file mode 100644 index 0000000000000..b62cf31205fd3 --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/auxiliary/ident-mac.rs @@ -0,0 +1,11 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn id(_: TokenStream, input: TokenStream) -> TokenStream { input } diff --git a/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs new file mode 100644 index 0000000000000..8defa26e48d8d --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs @@ -0,0 +1,60 @@ +// aux-build:ident-mac.rs + +#![feature(param_attrs)] +#![feature(c_variadic)] + +extern crate ident_mac; +use ident_mac::id; + +struct W(u8); + +extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); } +//~^ ERROR the attribute `id` is currently unknown to the compiler +//~| ERROR the attribute `id` is currently unknown to the compiler + +unsafe extern "C" fn cvar(arg1: i32, #[id] mut args: ...) {} +//~^ ERROR the attribute `id` is currently unknown to the compiler + +type Alias = extern "C" fn(#[id] u8, #[id] ...); + //~^ ERROR the attribute `id` is currently unknown to the compiler + //~| ERROR the attribute `id` is currently unknown to the compiler + +fn free(#[id] arg1: u8) { + //~^ ERROR the attribute `id` is currently unknown to the compiler + let lam = |#[id] W(x), #[id] y| (); + //~^ ERROR the attribute `id` is currently unknown to the compiler + //~| ERROR the attribute `id` is currently unknown to the compiler +} + +impl W { + fn inherent1(#[id] self, #[id] arg1: u8) {} + //~^ ERROR the attribute `id` is currently unknown to the compiler + //~| ERROR the attribute `id` is currently unknown to the compiler + fn inherent2(#[id] &self, #[id] arg1: u8) {} + //~^ ERROR the attribute `id` is currently unknown to the compiler + //~| ERROR the attribute `id` is currently unknown to the compiler + fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {} + //~^ ERROR the attribute `id` is currently unknown to the compiler + //~| ERROR the attribute `id` is currently unknown to the compiler + fn inherent4<'a>(#[id] self: Box, #[id] arg1: u8) {} + //~^ ERROR the attribute `id` is currently unknown to the compiler + //~| ERROR the attribute `id` is currently unknown to the compiler +} + +trait A { + fn trait1(#[id] self, #[id] arg1: u8); + //~^ ERROR the attribute `id` is currently unknown to the compiler + //~| ERROR the attribute `id` is currently unknown to the compiler + fn trait2(#[id] &self, #[id] arg1: u8); + //~^ ERROR the attribute `id` is currently unknown to the compiler + //~| ERROR the attribute `id` is currently unknown to the compiler + fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8); + //~^ ERROR the attribute `id` is currently unknown to the compiler + //~| ERROR the attribute `id` is currently unknown to the compiler + fn trait4<'a>(#[id] self: Box, #[id] arg1: u8, #[id] Vec); + //~^ ERROR the attribute `id` is currently unknown to the compiler + //~| ERROR the attribute `id` is currently unknown to the compiler + //~| ERROR the attribute `id` is currently unknown to the compiler +} + +fn main() {} diff --git a/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr new file mode 100644 index 0000000000000..69b9a46b3d502 --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr @@ -0,0 +1,228 @@ +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:11:21 + | +LL | extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); } + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:11:38 + | +LL | extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); } + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:15:38 + | +LL | unsafe extern "C" fn cvar(arg1: i32, #[id] mut args: ...) {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:18:28 + | +LL | type Alias = extern "C" fn(#[id] u8, #[id] ...); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:18:38 + | +LL | type Alias = extern "C" fn(#[id] u8, #[id] ...); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:22:9 + | +LL | fn free(#[id] arg1: u8) { + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:24:16 + | +LL | let lam = |#[id] W(x), #[id] y| (); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:24:28 + | +LL | let lam = |#[id] W(x), #[id] y| (); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:30:18 + | +LL | fn inherent1(#[id] self, #[id] arg1: u8) {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:30:30 + | +LL | fn inherent1(#[id] self, #[id] arg1: u8) {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:33:18 + | +LL | fn inherent2(#[id] &self, #[id] arg1: u8) {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:33:31 + | +LL | fn inherent2(#[id] &self, #[id] arg1: u8) {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:36:22 + | +LL | fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:36:42 + | +LL | fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:39:22 + | +LL | fn inherent4<'a>(#[id] self: Box, #[id] arg1: u8) {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:39:45 + | +LL | fn inherent4<'a>(#[id] self: Box, #[id] arg1: u8) {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:45:15 + | +LL | fn trait1(#[id] self, #[id] arg1: u8); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:45:27 + | +LL | fn trait1(#[id] self, #[id] arg1: u8); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:48:15 + | +LL | fn trait2(#[id] &self, #[id] arg1: u8); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:48:28 + | +LL | fn trait2(#[id] &self, #[id] arg1: u8); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:51:19 + | +LL | fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:51:39 + | +LL | fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:54:19 + | +LL | fn trait4<'a>(#[id] self: Box, #[id] arg1: u8, #[id] Vec); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:54:42 + | +LL | fn trait4<'a>(#[id] self: Box, #[id] arg1: u8, #[id] Vec); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:54:58 + | +LL | fn trait4<'a>(#[id] self: Box, #[id] arg1: u8, #[id] Vec); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error: aborting due to 25 previous errors + +For more information about this error, try `rustc --explain E0658`. From 7bb2d8b0765e6737f43b501135d91bc8ab64db7a Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 31 Aug 2019 15:43:24 +0100 Subject: [PATCH 06/25] Slightly clean up the error for recursive `async fn` * Make it clear that type erasure is required, not just pointer indirection. * Don't make the message specific to direct recursion. --- src/librustc_typeck/check/mod.rs | 4 ++-- .../ui/async-await/recursive-async-impl-trait-type.stderr | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a80550486d627..7855008a28221 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1420,8 +1420,8 @@ fn check_opaque_for_cycles<'tcx>( tcx.sess, span, E0733, "recursion in an `async fn` requires boxing", ) - .span_label(span, "an `async fn` cannot invoke itself directly") - .note("a recursive `async fn` must be rewritten to return a boxed future.") + .span_label(span, "recursive `async fn`") + .note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`.") .emit(); } else { let mut err = struct_span_err!( diff --git a/src/test/ui/async-await/recursive-async-impl-trait-type.stderr b/src/test/ui/async-await/recursive-async-impl-trait-type.stderr index 8781a9c444d0a..9ee014021804e 100644 --- a/src/test/ui/async-await/recursive-async-impl-trait-type.stderr +++ b/src/test/ui/async-await/recursive-async-impl-trait-type.stderr @@ -2,9 +2,9 @@ error[E0733]: recursion in an `async fn` requires boxing --> $DIR/recursive-async-impl-trait-type.rs:5:40 | LL | async fn recursive_async_function() -> () { - | ^^ an `async fn` cannot invoke itself directly + | ^^ recursive `async fn` | - = note: a recursive `async fn` must be rewritten to return a boxed future. + = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`. error: aborting due to previous error From 877faf38440ada48b0c27100fa3c456b35bc5612 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 31 Aug 2019 15:44:09 +0100 Subject: [PATCH 07/25] Check impl trait substs when checking for recursive types This prevents mutual `async fn` recursion --- src/librustc/ty/util.rs | 6 ++-- ...utually-recursive-async-impl-trait-type.rs | 13 +++++++ ...lly-recursive-async-impl-trait-type.stderr | 19 ++++++++++ ...-impl-trait-type--through-non-recursize.rs | 25 +++++++++++++ ...l-trait-type--through-non-recursize.stderr | 35 +++++++++++++++++++ 5 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/async-await/mutually-recursive-async-impl-trait-type.rs create mode 100644 src/test/ui/async-await/mutually-recursive-async-impl-trait-type.stderr create mode 100644 src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs create mode 100644 src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 7a77418050cdb..a08c82a0ae82f 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -709,8 +709,10 @@ impl<'tcx> TyCtxt<'tcx> { substs: SubstsRef<'tcx>, ) -> Option> { if self.found_recursion { - None - } else if self.seen_opaque_tys.insert(def_id) { + return None; + } + let substs = substs.fold_with(self); + if self.seen_opaque_tys.insert(def_id) { let generic_ty = self.tcx.type_of(def_id); let concrete_ty = generic_ty.subst(self.tcx, substs); let expanded_ty = self.fold_ty(concrete_ty); diff --git a/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.rs b/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.rs new file mode 100644 index 0000000000000..bb2a61f03ce1f --- /dev/null +++ b/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.rs @@ -0,0 +1,13 @@ +// edition:2018 +// Test that impl trait does not allow creating recursive types that are +// otherwise forbidden when using `async` and `await`. + +async fn rec_1() { //~ ERROR recursion in an `async fn` + rec_2().await; +} + +async fn rec_2() { //~ ERROR recursion in an `async fn` + rec_1().await; +} + +fn main() {} diff --git a/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.stderr b/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.stderr new file mode 100644 index 0000000000000..9249308936e54 --- /dev/null +++ b/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.stderr @@ -0,0 +1,19 @@ +error[E0733]: recursion in an `async fn` requires boxing + --> $DIR/mutually-recursive-async-impl-trait-type.rs:5:18 + | +LL | async fn rec_1() { + | ^ recursive `async fn` + | + = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`. + +error[E0733]: recursion in an `async fn` requires boxing + --> $DIR/mutually-recursive-async-impl-trait-type.rs:9:18 + | +LL | async fn rec_2() { + | ^ recursive `async fn` + | + = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`. + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0733`. diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs b/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs new file mode 100644 index 0000000000000..cfd9c0ec5b45b --- /dev/null +++ b/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs @@ -0,0 +1,25 @@ +// Test that impl trait does not allow creating recursive types that are +// otherwise forbidden. Even when there's an opaque type in another crate +// hiding this. + +fn id(t: T) -> impl Sized { t } + +fn recursive_id() -> impl Sized { //~ ERROR opaque type expands to a recursive type + id(recursive_id2()) +} + +fn recursive_id2() -> impl Sized { //~ ERROR opaque type expands to a recursive type + id(recursive_id()) +} + +fn wrap(t: T) -> impl Sized { (t,) } + +fn recursive_wrap() -> impl Sized { //~ ERROR opaque type expands to a recursive type + wrap(recursive_wrap2()) +} + +fn recursive_wrap2() -> impl Sized { //~ ERROR opaque type expands to a recursive type + wrap(recursive_wrap()) +} + +fn main() {} diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr new file mode 100644 index 0000000000000..7572c6c1bf057 --- /dev/null +++ b/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr @@ -0,0 +1,35 @@ +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:7:22 + | +LL | fn recursive_id() -> impl Sized { + | ^^^^^^^^^^ expands to a recursive type + | + = note: type resolves to itself + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:11:23 + | +LL | fn recursive_id2() -> impl Sized { + | ^^^^^^^^^^ expands to a recursive type + | + = note: type resolves to itself + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:17:24 + | +LL | fn recursive_wrap() -> impl Sized { + | ^^^^^^^^^^ expands to a recursive type + | + = note: expanded type is `((impl Sized,),)` + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:21:25 + | +LL | fn recursive_wrap2() -> impl Sized { + | ^^^^^^^^^^ expands to a recursive type + | + = note: expanded type is `((impl Sized,),)` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0720`. From 754a875e15f778ed5bdd49b4208956b3003949c4 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 31 Aug 2019 16:31:50 +0100 Subject: [PATCH 08/25] Add some more tests for underscore imports --- .../auxiliary/duplicate.rs | 0 .../auxiliary/underscore-imports.rs | 0 .../basic.rs | 0 .../basic.stderr | 0 src/test/ui/underscore-imports/cycle.rs | 18 +++++++++++++++ .../duplicate.rs | 0 .../intercrate.rs | 0 src/test/ui/underscore-imports/shadow.rs | 23 +++++++++++++++++++ src/test/ui/underscore-imports/shadow.stderr | 13 +++++++++++ .../unused-2018.rs | 0 .../unused-2018.stderr | 0 11 files changed, 54 insertions(+) rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/auxiliary/duplicate.rs (100%) rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/auxiliary/underscore-imports.rs (100%) rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/basic.rs (100%) rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/basic.stderr (100%) create mode 100644 src/test/ui/underscore-imports/cycle.rs rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/duplicate.rs (100%) rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/intercrate.rs (100%) create mode 100644 src/test/ui/underscore-imports/shadow.rs create mode 100644 src/test/ui/underscore-imports/shadow.stderr rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/unused-2018.rs (100%) rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/unused-2018.stderr (100%) diff --git a/src/test/ui/rfc-2166-underscore-imports/auxiliary/duplicate.rs b/src/test/ui/underscore-imports/auxiliary/duplicate.rs similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/auxiliary/duplicate.rs rename to src/test/ui/underscore-imports/auxiliary/duplicate.rs diff --git a/src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs b/src/test/ui/underscore-imports/auxiliary/underscore-imports.rs similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs rename to src/test/ui/underscore-imports/auxiliary/underscore-imports.rs diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.rs b/src/test/ui/underscore-imports/basic.rs similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/basic.rs rename to src/test/ui/underscore-imports/basic.rs diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.stderr b/src/test/ui/underscore-imports/basic.stderr similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/basic.stderr rename to src/test/ui/underscore-imports/basic.stderr diff --git a/src/test/ui/underscore-imports/cycle.rs b/src/test/ui/underscore-imports/cycle.rs new file mode 100644 index 0000000000000..bacf9b2d5a96a --- /dev/null +++ b/src/test/ui/underscore-imports/cycle.rs @@ -0,0 +1,18 @@ +// Check that cyclic glob imports are allowed with underscore imports + +// check-pass + +mod x { + pub use crate::y::*; + pub use std::ops::Deref as _; +} + +mod y { + pub use crate::x::*; + pub use std::ops::Deref as _; +} + +pub fn main() { + use x::*; + (&0).deref(); +} diff --git a/src/test/ui/rfc-2166-underscore-imports/duplicate.rs b/src/test/ui/underscore-imports/duplicate.rs similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/duplicate.rs rename to src/test/ui/underscore-imports/duplicate.rs diff --git a/src/test/ui/rfc-2166-underscore-imports/intercrate.rs b/src/test/ui/underscore-imports/intercrate.rs similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/intercrate.rs rename to src/test/ui/underscore-imports/intercrate.rs diff --git a/src/test/ui/underscore-imports/shadow.rs b/src/test/ui/underscore-imports/shadow.rs new file mode 100644 index 0000000000000..325f2001b9ede --- /dev/null +++ b/src/test/ui/underscore-imports/shadow.rs @@ -0,0 +1,23 @@ +// Check that underscore imports don't cause glob imports to be unshadowed + +mod a { + pub use std::ops::Deref as Shadow; +} + +mod b { + pub use crate::a::*; + macro_rules! m { + ($i:ident) => { pub struct $i; } + } + m!(Shadow); +} + +mod c { + use crate::b::Shadow as _; // Only imports the struct + + fn f(x: &()) { + x.deref(); //~ ERROR no method named `deref` found + } +} + +fn main() {} diff --git a/src/test/ui/underscore-imports/shadow.stderr b/src/test/ui/underscore-imports/shadow.stderr new file mode 100644 index 0000000000000..92adca2c70490 --- /dev/null +++ b/src/test/ui/underscore-imports/shadow.stderr @@ -0,0 +1,13 @@ +error[E0599]: no method named `deref` found for type `&()` in the current scope + --> $DIR/shadow.rs:19:11 + | +LL | x.deref(); + | ^^^^^ + | + = help: items from traits can only be used if the trait is in scope + = note: the following trait is implemented but not in scope, perhaps add a `use` for it: + `use std::ops::Deref;` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/rfc-2166-underscore-imports/unused-2018.rs b/src/test/ui/underscore-imports/unused-2018.rs similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/unused-2018.rs rename to src/test/ui/underscore-imports/unused-2018.rs diff --git a/src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr b/src/test/ui/underscore-imports/unused-2018.stderr similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr rename to src/test/ui/underscore-imports/unused-2018.stderr From b0bb3017c12d8e2cafb6a9852a10e12dc8e044e9 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 2 Sep 2019 13:50:44 +0200 Subject: [PATCH 09/25] Update xLTO compatibility table in rustc book. --- src/doc/rustc/src/linker-plugin-lto.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc/src/linker-plugin-lto.md b/src/doc/rustc/src/linker-plugin-lto.md index 2ae726c4ba61d..6f1bbe60569fd 100644 --- a/src/doc/rustc/src/linker-plugin-lto.md +++ b/src/doc/rustc/src/linker-plugin-lto.md @@ -105,5 +105,6 @@ The following table shows known good combinations of toolchain versions. | Rust 1.34 | ✗ | ✓ | | Rust 1.35 | ✗ | ✓ | | Rust 1.36 | ✗ | ✓ | +| Rust 1.37 | ✗ | ✓ | Note that the compatibility policy for this feature might change in the future. From 3ea932ab0e622104c97d3818350388de3012c833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 2 Sep 2019 18:21:58 -0700 Subject: [PATCH 10/25] Refer to "`self` type" instead of "receiver type" --- src/librustc/infer/error_reporting/mod.rs | 2 +- src/librustc/traits/object_safety.rs | 16 ++-- src/librustc_typeck/check/wfcheck.rs | 36 ++++----- src/librustc_typeck/error_codes.rs | 78 ++++++++++++++++++- src/test/ui/did_you_mean/issue-40006.stderr | 2 +- src/test/ui/error-codes/E0033-teach.rs | 2 +- src/test/ui/error-codes/E0033-teach.stderr | 2 +- src/test/ui/error-codes/E0033.rs | 2 +- src/test/ui/error-codes/E0033.stderr | 2 +- .../explicit-self-lifetime-mismatch.rs | 4 +- .../explicit-self-lifetime-mismatch.stderr | 4 +- src/test/ui/issues/issue-17740.rs | 4 +- src/test/ui/issues/issue-17740.stderr | 4 +- src/test/ui/issues/issue-17905-2.rs | 4 +- src/test/ui/issues/issue-17905-2.stderr | 4 +- src/test/ui/issues/issue-19380.stderr | 2 +- src/test/ui/issues/issue-56806.rs | 5 +- src/test/ui/issues/issue-56806.stderr | 5 +- .../object-safety-no-static.stderr | 2 +- src/test/ui/resolve/issue-3907-2.stderr | 2 +- src/test/ui/span/issue-27522.rs | 2 +- src/test/ui/span/issue-27522.stderr | 5 +- src/test/ui/traits/trait-object-safety.stderr | 4 +- src/test/ui/ufcs/ufcs-explicit-self-bad.rs | 14 ++-- .../ui/ufcs/ufcs-explicit-self-bad.stderr | 23 +++--- 25 files changed, 155 insertions(+), 75 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 9be73cf3c6d16..baaccea16cb9b 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -1627,7 +1627,7 @@ impl<'tcx> ObligationCause<'tcx> { MainFunctionType => Error0580("main function has wrong type"), StartFunctionType => Error0308("start function has wrong type"), IntrinsicType => Error0308("intrinsic has wrong type"), - MethodReceiver => Error0308("mismatched method receiver"), + MethodReceiver => Error0308("mismatched `self` parameter type"), // In the case where we have no more specific thing to // say, also take a look at the error code, maybe we can diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 7ea7bf0257cf7..aac722b56a983 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -47,13 +47,15 @@ impl ObjectSafetyViolation { "the trait cannot use `Self` as a type parameter \ in the supertraits or where-clauses".into(), ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod) => - format!("method `{}` has no receiver", name).into(), - ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf) => - format!("method `{}` references the `Self` type \ - in its arguments or return type", name).into(), - ObjectSafetyViolation::Method(name, - MethodViolationCode::WhereClauseReferencesSelf(_)) => - format!("method `{}` references the `Self` type in where clauses", name).into(), + format!("associated function `{}` has no `self` parameter", name).into(), + ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf) => format!( + "method `{}` references the `Self` type in its arguments or return type", + name, + ).into(), + ObjectSafetyViolation::Method( + name, + MethodViolationCode::WhereClauseReferencesSelf(_), + ) => format!("method `{}` references the `Self` type in where clauses", name).into(), ObjectSafetyViolation::Method(name, MethodViolationCode::Generic) => format!("method `{}` has generic type parameters", name).into(), ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver) => diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index f95b3e44bf0f7..ac8ee43dd0801 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -762,19 +762,19 @@ fn check_opaque_types<'fcx, 'tcx>( substituted_predicates } +const HELP_FOR_SELF_TYPE: &str = + "consider changing to `self`, `&self`, `&mut self`, `self: Box`, \ + `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one \ + of the previous types except `Self`)"; + fn check_method_receiver<'fcx, 'tcx>( fcx: &FnCtxt<'fcx, 'tcx>, method_sig: &hir::MethodSig, method: &ty::AssocItem, self_ty: Ty<'tcx>, ) { - const HELP_FOR_SELF_TYPE: &str = - "consider changing to `self`, `&self`, `&mut self`, `self: Box`, \ - `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one \ - of the previous types except `Self`)"; // Check that the method has a valid receiver type, given the type `Self`. - debug!("check_method_receiver({:?}, self_ty={:?})", - method, self_ty); + debug!("check_method_receiver({:?}, self_ty={:?})", method, self_ty); if !method.method_has_self_argument { return; @@ -805,12 +805,7 @@ fn check_method_receiver<'fcx, 'tcx>( if fcx.tcx.features().arbitrary_self_types { if !receiver_is_valid(fcx, span, receiver_ty, self_ty, true) { // Report error; `arbitrary_self_types` was enabled. - fcx.tcx.sess.diagnostic().mut_span_err( - span, &format!("invalid method receiver type: {:?}", receiver_ty) - ).note("type of `self` must be `Self` or a type that dereferences to it") - .help(HELP_FOR_SELF_TYPE) - .code(DiagnosticId::Error("E0307".into())) - .emit(); + e0307(fcx, span, receiver_ty); } } else { if !receiver_is_valid(fcx, span, receiver_ty, self_ty, false) { @@ -830,17 +825,22 @@ fn check_method_receiver<'fcx, 'tcx>( .emit(); } else { // Report error; would not have worked with `arbitrary_self_types`. - fcx.tcx.sess.diagnostic().mut_span_err( - span, &format!("invalid method receiver type: {:?}", receiver_ty) - ).note("type must be `Self` or a type that dereferences to it") - .help(HELP_FOR_SELF_TYPE) - .code(DiagnosticId::Error("E0307".into())) - .emit(); + e0307(fcx, span, receiver_ty); } } } } +fn e0307(fcx: &FnCtxt<'fcx, 'tcx>, span: Span, receiver_ty: Ty<'_>) { + fcx.tcx.sess.diagnostic().mut_span_err( + span, + &format!("invalid `self` parameter type: {:?}", receiver_ty) + ).note("type of `self` must be `Self` or a type that dereferences to it") + .help(HELP_FOR_SELF_TYPE) + .code(DiagnosticId::Error("E0307".into())) + .emit(); +} + /// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If /// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly /// through a `*const/mut T` raw pointer. If the feature is not enabled, the requirements are more diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index b52183d4b1b56..ae0f17892959d 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -2425,6 +2425,83 @@ struct Bar { x: Foo } ``` "##, +E0307: r##" +This error indicates that the `self` parameter in a method has an invalid +"reciever type". + +Methods take a special first parameter, of which there are three variants: +`self`, `&self`, and `&mut self`. The type `Self` acts as an alias to the +type of the current trait implementor, or "receiver type". Besides the +already mentioned `Self`, `&Self` and `&mut Self` valid receiver types, the +following are also valid, if less common: `self: Box`, +`self: Rc`, `self: Arc`, and `self: Pin

` (where P is one of +the previous types except `Self`). + +``` +# struct Foo; +trait Trait { + fn foo(&self); +// ^^^^^ this let's you refer to the type that implements this trait +} +impl Trait for Foo { +// ^^^ this is the "receiver type" + fn foo(&self) {} +// ^^^^^ this is of type `Foo` +} +``` + +The above is equivalent to: + +``` +# struct Foo; +# trait Trait { +# fn foo(&self); +# } +impl Trait for Foo { + fn foo(&self: &Foo) {} +} +``` + +When using an invalid reciver type, like in the following example, + +```compile_fail,E0307 +# struct Foo; +# struct Bar; +# trait Trait { +# fn foo(&self); +# } +impl Trait for Struct { + fn foo(&self: &Bar) {} +} +``` + +The nightly feature [Arbintrary self types][AST] extends the accepted +receiver type to also include any type that can dereference to `Self`: + +``` +#![feature(arbitrary_self_types)] + +struct Foo; +struct Bar; + +// Because you can dereference `Bar` into `Foo`... +impl std::ops::Deref for Bar { + type Target = Foo; + + fn deref(&self) -> &Foo { + &Foo + } +} + +impl Foo { + fn foo(self: Bar) {} +// ^^^^^^^^^ ...it can be used as the receiver type +} +``` + +[AST]: https://doc.rust-lang.org/unstable-book/language-features/arbitrary-self-types.html +"##, + E0321: r##" A cross-crate opt-out trait was implemented on something which wasn't a struct or enum type. Erroneous code example: @@ -4851,7 +4928,6 @@ register_diagnostics! { // E0247, // E0248, // value used as a type, now reported earlier during resolution as E0412 // E0249, - E0307, // invalid method `self` type // E0319, // trait impls for defaulted traits allowed just for structs/enums // E0372, // coherence not object safe E0377, // the trait `CoerceUnsized` may only be implemented for a coercion diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index 87e48cd1e1cd9..6f219a6e0b1fe 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -62,7 +62,7 @@ error[E0038]: the trait `X` cannot be made into an object LL | impl dyn X { | ^^^^^ the trait `X` cannot be made into an object | - = note: method `xxx` has no receiver + = note: associated function `xxx` has no `self` parameter error: aborting due to 9 previous errors diff --git a/src/test/ui/error-codes/E0033-teach.rs b/src/test/ui/error-codes/E0033-teach.rs index 6a27b07fa8b77..9b5e719781281 100644 --- a/src/test/ui/error-codes/E0033-teach.rs +++ b/src/test/ui/error-codes/E0033-teach.rs @@ -8,7 +8,7 @@ fn main() { let trait_obj: &dyn SomeTrait = SomeTrait; //~^ ERROR expected value, found trait `SomeTrait` //~| ERROR E0038 - //~| method `foo` has no receiver + //~| associated function `foo` has no `self` parameter let &invalid = trait_obj; //~^ ERROR E0033 diff --git a/src/test/ui/error-codes/E0033-teach.stderr b/src/test/ui/error-codes/E0033-teach.stderr index fb630de7fc147..1d4c2d788a43b 100644 --- a/src/test/ui/error-codes/E0033-teach.stderr +++ b/src/test/ui/error-codes/E0033-teach.stderr @@ -10,7 +10,7 @@ error[E0038]: the trait `SomeTrait` cannot be made into an object LL | let trait_obj: &dyn SomeTrait = SomeTrait; | ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object | - = note: method `foo` has no receiver + = note: associated function `foo` has no `self` parameter error[E0033]: type `&dyn SomeTrait` cannot be dereferenced --> $DIR/E0033-teach.rs:13:9 diff --git a/src/test/ui/error-codes/E0033.rs b/src/test/ui/error-codes/E0033.rs index 582600e110ba0..86dacfd1a47ba 100644 --- a/src/test/ui/error-codes/E0033.rs +++ b/src/test/ui/error-codes/E0033.rs @@ -6,7 +6,7 @@ fn main() { let trait_obj: &dyn SomeTrait = SomeTrait; //~^ ERROR expected value, found trait `SomeTrait` //~| ERROR E0038 - //~| method `foo` has no receiver + //~| associated function `foo` has no `self` parameter let &invalid = trait_obj; //~^ ERROR E0033 diff --git a/src/test/ui/error-codes/E0033.stderr b/src/test/ui/error-codes/E0033.stderr index fe9f45d86a6a0..803d7917e5638 100644 --- a/src/test/ui/error-codes/E0033.stderr +++ b/src/test/ui/error-codes/E0033.stderr @@ -10,7 +10,7 @@ error[E0038]: the trait `SomeTrait` cannot be made into an object LL | let trait_obj: &dyn SomeTrait = SomeTrait; | ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object | - = note: method `foo` has no receiver + = note: associated function `foo` has no `self` parameter error[E0033]: type `&dyn SomeTrait` cannot be dereferenced --> $DIR/E0033.rs:11:9 diff --git a/src/test/ui/explicit/explicit-self-lifetime-mismatch.rs b/src/test/ui/explicit/explicit-self-lifetime-mismatch.rs index 82c64bcf6a767..9ab8e13893bc7 100644 --- a/src/test/ui/explicit/explicit-self-lifetime-mismatch.rs +++ b/src/test/ui/explicit/explicit-self-lifetime-mismatch.rs @@ -6,11 +6,11 @@ struct Foo<'a,'b> { impl<'a,'b> Foo<'a,'b> { fn bar(self: Foo<'b,'a> - //~^ ERROR mismatched method receiver + //~^ ERROR mismatched `self` parameter type //~| expected type `Foo<'a, 'b>` //~| found type `Foo<'b, 'a>` //~| lifetime mismatch - //~| ERROR mismatched method receiver + //~| ERROR mismatched `self` parameter type //~| expected type `Foo<'a, 'b>` //~| found type `Foo<'b, 'a>` //~| lifetime mismatch diff --git a/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr b/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr index e6f9eded9a4f3..4bf2d573d4f96 100644 --- a/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr +++ b/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr @@ -1,4 +1,4 @@ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/explicit-self-lifetime-mismatch.rs:8:12 | LL | Foo<'b,'a> @@ -17,7 +17,7 @@ note: ...does not necessarily outlive the lifetime 'a as defined on the impl at LL | impl<'a,'b> Foo<'a,'b> { | ^^ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/explicit-self-lifetime-mismatch.rs:8:12 | LL | Foo<'b,'a> diff --git a/src/test/ui/issues/issue-17740.rs b/src/test/ui/issues/issue-17740.rs index c131b895849ae..b47568400c3b7 100644 --- a/src/test/ui/issues/issue-17740.rs +++ b/src/test/ui/issues/issue-17740.rs @@ -4,11 +4,11 @@ struct Foo<'a> { impl <'a> Foo<'a>{ fn bar(self: &mut Foo) { - //~^ mismatched method receiver + //~^ mismatched `self` parameter type //~| expected type `Foo<'a>` //~| found type `Foo<'_>` //~| lifetime mismatch - //~| mismatched method receiver + //~| mismatched `self` parameter type //~| expected type `Foo<'a>` //~| found type `Foo<'_>` //~| lifetime mismatch diff --git a/src/test/ui/issues/issue-17740.stderr b/src/test/ui/issues/issue-17740.stderr index 7ab0fa4d818b0..b8a0a0676319a 100644 --- a/src/test/ui/issues/issue-17740.stderr +++ b/src/test/ui/issues/issue-17740.stderr @@ -1,4 +1,4 @@ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/issue-17740.rs:6:18 | LL | fn bar(self: &mut Foo) { @@ -23,7 +23,7 @@ note: ...does not necessarily outlive the lifetime 'a as defined on the impl at LL | impl <'a> Foo<'a>{ | ^^ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/issue-17740.rs:6:18 | LL | fn bar(self: &mut Foo) { diff --git a/src/test/ui/issues/issue-17905-2.rs b/src/test/ui/issues/issue-17905-2.rs index 259d945018938..44279cc867b46 100644 --- a/src/test/ui/issues/issue-17905-2.rs +++ b/src/test/ui/issues/issue-17905-2.rs @@ -6,8 +6,8 @@ impl Pair< isize > { fn say(self: &Pair<&str, isize>) { -//~^ ERROR mismatched method receiver -//~| ERROR mismatched method receiver +//~^ ERROR mismatched `self` parameter type +//~| ERROR mismatched `self` parameter type println!("{:?}", self); } } diff --git a/src/test/ui/issues/issue-17905-2.stderr b/src/test/ui/issues/issue-17905-2.stderr index e3909e0c1253f..585bc9c14883b 100644 --- a/src/test/ui/issues/issue-17905-2.stderr +++ b/src/test/ui/issues/issue-17905-2.stderr @@ -1,4 +1,4 @@ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/issue-17905-2.rs:8:18 | LL | fn say(self: &Pair<&str, isize>) { @@ -21,7 +21,7 @@ note: ...does not necessarily outlive the lifetime '_ as defined on the impl at LL | &str, | ^ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/issue-17905-2.rs:8:18 | LL | fn say(self: &Pair<&str, isize>) { diff --git a/src/test/ui/issues/issue-19380.stderr b/src/test/ui/issues/issue-19380.stderr index 27e3ff57bf9ab..d70a7c2b5299c 100644 --- a/src/test/ui/issues/issue-19380.stderr +++ b/src/test/ui/issues/issue-19380.stderr @@ -4,7 +4,7 @@ error[E0038]: the trait `Qiz` cannot be made into an object LL | foos: &'static [&'static (dyn Qiz + 'static)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Qiz` cannot be made into an object | - = note: method `qiz` has no receiver + = note: associated function `qiz` has no `self` parameter error: aborting due to previous error diff --git a/src/test/ui/issues/issue-56806.rs b/src/test/ui/issues/issue-56806.rs index b6454e578e6af..b1dac26d65a15 100644 --- a/src/test/ui/issues/issue-56806.rs +++ b/src/test/ui/issues/issue-56806.rs @@ -1,7 +1,6 @@ pub trait Trait { fn dyn_instead_of_self(self: Box); - //~^ ERROR invalid method receiver type: std::boxed::Box<(dyn Trait + 'static)> + //~^ ERROR invalid `self` parameter type } -pub fn main() { -} +pub fn main() {} diff --git a/src/test/ui/issues/issue-56806.stderr b/src/test/ui/issues/issue-56806.stderr index fae6a26720f36..a4f9aadcfef3e 100644 --- a/src/test/ui/issues/issue-56806.stderr +++ b/src/test/ui/issues/issue-56806.stderr @@ -1,11 +1,12 @@ -error[E0307]: invalid method receiver type: std::boxed::Box<(dyn Trait + 'static)> +error[E0307]: invalid `self` parameter type: std::boxed::Box<(dyn Trait + 'static)> --> $DIR/issue-56806.rs:2:34 | LL | fn dyn_instead_of_self(self: Box); | ^^^^^^^^^^^^^^ | - = note: type must be `Self` or a type that dereferences to it + = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error: aborting due to previous error +For more information about this error, try `rustc --explain E0307`. diff --git a/src/test/ui/object-safety/object-safety-no-static.stderr b/src/test/ui/object-safety/object-safety-no-static.stderr index da8dd657c2a9d..c189c358b4223 100644 --- a/src/test/ui/object-safety/object-safety-no-static.stderr +++ b/src/test/ui/object-safety/object-safety-no-static.stderr @@ -4,7 +4,7 @@ error[E0038]: the trait `Foo` cannot be made into an object LL | fn foo_implicit(b: Box) -> Box { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object | - = note: method `foo` has no receiver + = note: associated function `foo` has no `self` parameter error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-3907-2.stderr b/src/test/ui/resolve/issue-3907-2.stderr index 968c1f3e463d0..63ac11dc8ae01 100644 --- a/src/test/ui/resolve/issue-3907-2.stderr +++ b/src/test/ui/resolve/issue-3907-2.stderr @@ -4,7 +4,7 @@ error[E0038]: the trait `issue_3907::Foo` cannot be made into an object LL | fn bar(_x: Foo) {} | ^^^^^^^^^^^^^^^ the trait `issue_3907::Foo` cannot be made into an object | - = note: method `bar` has no receiver + = note: associated function `bar` has no `self` parameter error: aborting due to previous error diff --git a/src/test/ui/span/issue-27522.rs b/src/test/ui/span/issue-27522.rs index 5c9893f64a6ee..7a0cfb679ed67 100644 --- a/src/test/ui/span/issue-27522.rs +++ b/src/test/ui/span/issue-27522.rs @@ -3,7 +3,7 @@ struct SomeType {} trait Foo { - fn handler(self: &SomeType); //~ ERROR invalid method receiver type + fn handler(self: &SomeType); //~ ERROR invalid `self` parameter type } fn main() {} diff --git a/src/test/ui/span/issue-27522.stderr b/src/test/ui/span/issue-27522.stderr index 88dfee1cada3f..8a254a9685543 100644 --- a/src/test/ui/span/issue-27522.stderr +++ b/src/test/ui/span/issue-27522.stderr @@ -1,11 +1,12 @@ -error[E0307]: invalid method receiver type: &SomeType +error[E0307]: invalid `self` parameter type: &SomeType --> $DIR/issue-27522.rs:6:22 | LL | fn handler(self: &SomeType); | ^^^^^^^^^ | - = note: type must be `Self` or a type that dereferences to it + = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error: aborting due to previous error +For more information about this error, try `rustc --explain E0307`. diff --git a/src/test/ui/traits/trait-object-safety.stderr b/src/test/ui/traits/trait-object-safety.stderr index 68edc17870534..7f6bc0ebb70e5 100644 --- a/src/test/ui/traits/trait-object-safety.stderr +++ b/src/test/ui/traits/trait-object-safety.stderr @@ -4,7 +4,7 @@ error[E0038]: the trait `Tr` cannot be made into an object LL | let _: &dyn Tr = &St; | ^^^ the trait `Tr` cannot be made into an object | - = note: method `foo` has no receiver + = note: associated function `foo` has no `self` parameter = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Tr>` for `&St` error[E0038]: the trait `Tr` cannot be made into an object @@ -13,7 +13,7 @@ error[E0038]: the trait `Tr` cannot be made into an object LL | let _: &dyn Tr = &St; | ^^^^^^^ the trait `Tr` cannot be made into an object | - = note: method `foo` has no receiver + = note: associated function `foo` has no `self` parameter error: aborting due to 2 previous errors diff --git a/src/test/ui/ufcs/ufcs-explicit-self-bad.rs b/src/test/ui/ufcs/ufcs-explicit-self-bad.rs index c6ff94a5e7606..bdb8e197fbe49 100644 --- a/src/test/ui/ufcs/ufcs-explicit-self-bad.rs +++ b/src/test/ui/ufcs/ufcs-explicit-self-bad.rs @@ -6,7 +6,7 @@ struct Foo { impl Foo { fn foo(self: isize, x: isize) -> isize { - //~^ ERROR invalid method receiver type + //~^ ERROR invalid `self` parameter type self.f + x } } @@ -17,11 +17,11 @@ struct Bar { impl Bar { fn foo(self: Bar, x: isize) -> isize { - //~^ ERROR invalid method receiver type + //~^ ERROR invalid `self` parameter type x } fn bar(self: &Bar, x: isize) -> isize { - //~^ ERROR invalid method receiver type + //~^ ERROR invalid `self` parameter type x } } @@ -34,14 +34,14 @@ trait SomeTrait { impl<'a, T> SomeTrait for &'a Bar { fn dummy1(self: &&'a Bar) { } - fn dummy2(self: &Bar) {} //~ ERROR mismatched method receiver - //~^ ERROR mismatched method receiver + fn dummy2(self: &Bar) {} //~ ERROR mismatched `self` parameter type + //~^ ERROR mismatched `self` parameter type fn dummy3(self: &&Bar) {} - //~^ ERROR mismatched method receiver + //~^ ERROR mismatched `self` parameter type //~| expected type `&'a Bar` //~| found type `&Bar` //~| lifetime mismatch - //~| ERROR mismatched method receiver + //~| ERROR mismatched `self` parameter type //~| expected type `&'a Bar` //~| found type `&Bar` //~| lifetime mismatch diff --git a/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr b/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr index 6da20e37577b0..b2fe1b281fc99 100644 --- a/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr +++ b/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr @@ -1,31 +1,31 @@ -error[E0307]: invalid method receiver type: isize +error[E0307]: invalid `self` parameter type: isize --> $DIR/ufcs-explicit-self-bad.rs:8:18 | LL | fn foo(self: isize, x: isize) -> isize { | ^^^^^ | - = note: type must be `Self` or a type that dereferences to it + = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) -error[E0307]: invalid method receiver type: Bar +error[E0307]: invalid `self` parameter type: Bar --> $DIR/ufcs-explicit-self-bad.rs:19:18 | LL | fn foo(self: Bar, x: isize) -> isize { | ^^^^^^^^^^ | - = note: type must be `Self` or a type that dereferences to it + = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) -error[E0307]: invalid method receiver type: &Bar +error[E0307]: invalid `self` parameter type: &Bar --> $DIR/ufcs-explicit-self-bad.rs:23:18 | LL | fn bar(self: &Bar, x: isize) -> isize { | ^^^^^^^^^^^ | - = note: type must be `Self` or a type that dereferences to it + = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/ufcs-explicit-self-bad.rs:37:21 | LL | fn dummy2(self: &Bar) {} @@ -44,7 +44,7 @@ note: ...does not necessarily outlive the lifetime 'a as defined on the impl at LL | impl<'a, T> SomeTrait for &'a Bar { | ^^ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/ufcs-explicit-self-bad.rs:37:21 | LL | fn dummy2(self: &Bar) {} @@ -63,7 +63,7 @@ note: ...does not necessarily outlive the anonymous lifetime #1 defined on the m LL | fn dummy2(self: &Bar) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/ufcs-explicit-self-bad.rs:39:21 | LL | fn dummy3(self: &&Bar) {} @@ -82,7 +82,7 @@ note: ...does not necessarily outlive the lifetime 'a as defined on the impl at LL | impl<'a, T> SomeTrait for &'a Bar { | ^^ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/ufcs-explicit-self-bad.rs:39:21 | LL | fn dummy3(self: &&Bar) {} @@ -103,4 +103,5 @@ LL | fn dummy3(self: &&Bar) {} error: aborting due to 7 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0307, E0308. +For more information about an error, try `rustc --explain E0307`. From c1e5e5c56717c5fe224db425d891c274a3f3cb5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 2 Sep 2019 20:22:22 -0700 Subject: [PATCH 11/25] On object safety violation, point at source when possible --- src/librustc/traits/error_reporting.rs | 5 +- src/librustc/traits/object_safety.rs | 54 +++++++++++-------- .../associated-const-in-trait.stderr | 5 +- ...mpl-trait-for-trait-object-safe.old.stderr | 4 +- ...impl-trait-for-trait-object-safe.re.stderr | 4 +- src/test/ui/did_you_mean/issue-40006.stderr | 5 +- src/test/ui/error-codes/E0033-teach.rs | 3 +- src/test/ui/error-codes/E0033-teach.stderr | 7 +-- src/test/ui/error-codes/E0033.rs | 3 +- src/test/ui/error-codes/E0033.stderr | 7 +-- src/test/ui/error-codes/E0038.stderr | 5 +- src/test/ui/issues/issue-18959.stderr | 5 +- src/test/ui/issues/issue-19380.stderr | 5 +- src/test/ui/issues/issue-19538.stderr | 9 ++-- src/test/ui/issues/issue-50781.stderr | 4 +- .../object-safety-associated-consts.stderr | 5 +- .../object-safety-generics.stderr | 10 ++-- .../object-safety-mentions-Self.stderr | 10 ++-- .../object-safety-no-static.stderr | 5 +- src/test/ui/resolve/issue-3907-2.stderr | 2 - ...rbitrary-self-types-not-object-safe.stderr | 9 ++-- src/test/ui/traits/trait-item-privacy.stderr | 13 +++-- src/test/ui/traits/trait-object-safety.stderr | 9 ++-- src/test/ui/traits/trait-test-2.stderr | 15 ++++-- ...ter-defaults-referencing-Self-ppaux.stderr | 5 +- src/test/ui/wf/wf-object-safe.stderr | 5 +- 26 files changed, 129 insertions(+), 84 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index b38e1f5f83937..03cc00d87e3cd 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1384,7 +1384,10 @@ impl<'tcx> TyCtxt<'tcx> { let mut reported_violations = FxHashSet::default(); for violation in violations { if reported_violations.insert(violation.clone()) { - err.note(&violation.error_msg()); + match violation.span() { + Some(span) => err.span_label(span, violation.error_msg()), + None => err.note(&violation.error_msg()), + }; } } Some(err) diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index aac722b56a983..50f497e302e6d 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -32,10 +32,10 @@ pub enum ObjectSafetyViolation { SupertraitSelf, /// Method has something illegal. - Method(ast::Name, MethodViolationCode), + Method(ast::Name, MethodViolationCode, Span), /// Associated const. - AssocConst(ast::Name), + AssocConst(ast::Name, Span), } impl ObjectSafetyViolation { @@ -46,24 +46,33 @@ impl ObjectSafetyViolation { ObjectSafetyViolation::SupertraitSelf => "the trait cannot use `Self` as a type parameter \ in the supertraits or where-clauses".into(), - ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod) => + ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod, _) => format!("associated function `{}` has no `self` parameter", name).into(), - ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf) => format!( + ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf, _) => format!( "method `{}` references the `Self` type in its arguments or return type", name, ).into(), ObjectSafetyViolation::Method( name, - MethodViolationCode::WhereClauseReferencesSelf(_), + MethodViolationCode::WhereClauseReferencesSelf, + _, ) => format!("method `{}` references the `Self` type in where clauses", name).into(), - ObjectSafetyViolation::Method(name, MethodViolationCode::Generic) => + ObjectSafetyViolation::Method(name, MethodViolationCode::Generic, _) => format!("method `{}` has generic type parameters", name).into(), - ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver) => + ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver, _) => format!("method `{}`'s receiver cannot be dispatched on", name).into(), - ObjectSafetyViolation::AssocConst(name) => + ObjectSafetyViolation::AssocConst(name, _) => format!("the trait cannot contain associated consts like `{}`", name).into(), } } + + pub fn span(&self) -> Option { + match self { + ObjectSafetyViolation::AssocConst(_, span) | + ObjectSafetyViolation::Method(_, _, span) => Some(*span), + _ => None, + } + } } /// Reasons a method might not be object-safe. @@ -76,7 +85,7 @@ pub enum MethodViolationCode { ReferencesSelf, /// e.g., `fn foo(&self) where Self: Clone` - WhereClauseReferencesSelf(Span), + WhereClauseReferencesSelf, /// e.g., `fn foo()` Generic, @@ -90,9 +99,10 @@ impl<'tcx> TyCtxt<'tcx> { /// astconv -- currently, `Self` in supertraits. This is needed /// because `object_safety_violations` can't be used during /// type collection. - pub fn astconv_object_safety_violations(self, trait_def_id: DefId) - -> Vec - { + pub fn astconv_object_safety_violations( + self, + trait_def_id: DefId, + ) -> Vec { debug_assert!(self.generics_of(trait_def_id).has_self); let violations = traits::supertrait_def_ids(self, trait_def_id) .filter(|&def_id| self.predicates_reference_self(def_id, true)) @@ -130,7 +140,7 @@ impl<'tcx> TyCtxt<'tcx> { } match self.virtual_call_violation_for_method(trait_def_id, method) { - None | Some(MethodViolationCode::WhereClauseReferencesSelf(_)) => true, + None | Some(MethodViolationCode::WhereClauseReferencesSelf) => true, Some(_) => false, } } @@ -140,12 +150,15 @@ impl<'tcx> TyCtxt<'tcx> { let mut violations: Vec<_> = self.associated_items(trait_def_id) .filter(|item| item.kind == ty::AssocKind::Method) .filter_map(|item| - self.object_safety_violation_for_method(trait_def_id, &item) - .map(|code| ObjectSafetyViolation::Method(item.ident.name, code)) + self.object_safety_violation_for_method(trait_def_id, &item).map(|code| { + ObjectSafetyViolation::Method(item.ident.name, code, item.ident.span) + }) ).filter(|violation| { - if let ObjectSafetyViolation::Method(_, - MethodViolationCode::WhereClauseReferencesSelf(span)) = violation - { + if let ObjectSafetyViolation::Method( + _, + MethodViolationCode::WhereClauseReferencesSelf, + span, + ) = violation { // Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id. // It's also hard to get a use site span, so we use the method definition span. self.lint_node_note( @@ -171,7 +184,7 @@ impl<'tcx> TyCtxt<'tcx> { violations.extend(self.associated_items(trait_def_id) .filter(|item| item.kind == ty::AssocKind::Const) - .map(|item| ObjectSafetyViolation::AssocConst(item.ident.name))); + .map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span))); debug!("object_safety_violations_for_trait(trait_def_id={:?}) = {:?}", trait_def_id, @@ -327,8 +340,7 @@ impl<'tcx> TyCtxt<'tcx> { .visit_tys_shallow(|t| { self.contains_illegal_self_type_reference(trait_def_id, t) }) { - let span = self.def_span(method.def_id); - return Some(MethodViolationCode::WhereClauseReferencesSelf(span)); + return Some(MethodViolationCode::WhereClauseReferencesSelf); } let receiver_ty = self.liberate_late_bound_regions( diff --git a/src/test/ui/associated-const/associated-const-in-trait.stderr b/src/test/ui/associated-const/associated-const-in-trait.stderr index dff268a55c909..a5d7fc5b70246 100644 --- a/src/test/ui/associated-const/associated-const-in-trait.stderr +++ b/src/test/ui/associated-const/associated-const-in-trait.stderr @@ -1,10 +1,11 @@ error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/associated-const-in-trait.rs:9:6 | +LL | const N: usize; + | - the trait cannot contain associated consts like `N` +... LL | impl dyn Trait { | ^^^^^^^^^ the trait `Trait` cannot be made into an object - | - = note: the trait cannot contain associated consts like `N` error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr index c38d7456a9952..2626eab3cbf23 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr +++ b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr @@ -1,10 +1,10 @@ error[E0038]: the trait `NotObjectSafe` cannot be made into an object --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:11:6 | +LL | trait NotObjectSafe { fn eq(&self, other: Self); } + | -- method `eq` references the `Self` type in its arguments or return type LL | impl NotObjectSafe for dyn NotObjectSafe { } | ^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object - | - = note: method `eq` references the `Self` type in its arguments or return type error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr index c38d7456a9952..2626eab3cbf23 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr +++ b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr @@ -1,10 +1,10 @@ error[E0038]: the trait `NotObjectSafe` cannot be made into an object --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:11:6 | +LL | trait NotObjectSafe { fn eq(&self, other: Self); } + | -- method `eq` references the `Self` type in its arguments or return type LL | impl NotObjectSafe for dyn NotObjectSafe { } | ^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object - | - = note: method `eq` references the `Self` type in its arguments or return type error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index 6f219a6e0b1fe..5b384045a486a 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -61,8 +61,9 @@ error[E0038]: the trait `X` cannot be made into an object | LL | impl dyn X { | ^^^^^ the trait `X` cannot be made into an object - | - = note: associated function `xxx` has no `self` parameter +... +LL | fn xxx() { ### } + | --- associated function `xxx` has no `self` parameter error: aborting due to 9 previous errors diff --git a/src/test/ui/error-codes/E0033-teach.rs b/src/test/ui/error-codes/E0033-teach.rs index 9b5e719781281..1943965139423 100644 --- a/src/test/ui/error-codes/E0033-teach.rs +++ b/src/test/ui/error-codes/E0033-teach.rs @@ -1,14 +1,13 @@ // compile-flags: -Z teach trait SomeTrait { - fn foo(); + fn foo(); //~ associated function `foo` has no `self` parameter } fn main() { let trait_obj: &dyn SomeTrait = SomeTrait; //~^ ERROR expected value, found trait `SomeTrait` //~| ERROR E0038 - //~| associated function `foo` has no `self` parameter let &invalid = trait_obj; //~^ ERROR E0033 diff --git a/src/test/ui/error-codes/E0033-teach.stderr b/src/test/ui/error-codes/E0033-teach.stderr index 1d4c2d788a43b..80f3d4441bd9f 100644 --- a/src/test/ui/error-codes/E0033-teach.stderr +++ b/src/test/ui/error-codes/E0033-teach.stderr @@ -7,13 +7,14 @@ LL | let trait_obj: &dyn SomeTrait = SomeTrait; error[E0038]: the trait `SomeTrait` cannot be made into an object --> $DIR/E0033-teach.rs:8:20 | +LL | fn foo(); + | --- associated function `foo` has no `self` parameter +... LL | let trait_obj: &dyn SomeTrait = SomeTrait; | ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object - | - = note: associated function `foo` has no `self` parameter error[E0033]: type `&dyn SomeTrait` cannot be dereferenced - --> $DIR/E0033-teach.rs:13:9 + --> $DIR/E0033-teach.rs:12:9 | LL | let &invalid = trait_obj; | ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced diff --git a/src/test/ui/error-codes/E0033.rs b/src/test/ui/error-codes/E0033.rs index 86dacfd1a47ba..e5f0530f45ff8 100644 --- a/src/test/ui/error-codes/E0033.rs +++ b/src/test/ui/error-codes/E0033.rs @@ -1,12 +1,11 @@ trait SomeTrait { - fn foo(); + fn foo(); //~ associated function `foo` has no `self` parameter } fn main() { let trait_obj: &dyn SomeTrait = SomeTrait; //~^ ERROR expected value, found trait `SomeTrait` //~| ERROR E0038 - //~| associated function `foo` has no `self` parameter let &invalid = trait_obj; //~^ ERROR E0033 diff --git a/src/test/ui/error-codes/E0033.stderr b/src/test/ui/error-codes/E0033.stderr index 803d7917e5638..c2843796cc851 100644 --- a/src/test/ui/error-codes/E0033.stderr +++ b/src/test/ui/error-codes/E0033.stderr @@ -7,13 +7,14 @@ LL | let trait_obj: &dyn SomeTrait = SomeTrait; error[E0038]: the trait `SomeTrait` cannot be made into an object --> $DIR/E0033.rs:6:20 | +LL | fn foo(); + | --- associated function `foo` has no `self` parameter +... LL | let trait_obj: &dyn SomeTrait = SomeTrait; | ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object - | - = note: associated function `foo` has no `self` parameter error[E0033]: type `&dyn SomeTrait` cannot be dereferenced - --> $DIR/E0033.rs:11:9 + --> $DIR/E0033.rs:10:9 | LL | let &invalid = trait_obj; | ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced diff --git a/src/test/ui/error-codes/E0038.stderr b/src/test/ui/error-codes/E0038.stderr index e3d7593e42a71..93a7681393b29 100644 --- a/src/test/ui/error-codes/E0038.stderr +++ b/src/test/ui/error-codes/E0038.stderr @@ -1,10 +1,11 @@ error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/E0038.rs:5:1 | +LL | fn foo(&self) -> Self; + | --- method `foo` references the `Self` type in its arguments or return type +... LL | fn call_foo(x: Box) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` cannot be made into an object - | - = note: method `foo` references the `Self` type in its arguments or return type error: aborting due to previous error diff --git a/src/test/ui/issues/issue-18959.stderr b/src/test/ui/issues/issue-18959.stderr index 63c33b7f4472d..d5e7092801ecd 100644 --- a/src/test/ui/issues/issue-18959.stderr +++ b/src/test/ui/issues/issue-18959.stderr @@ -1,10 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/issue-18959.rs:11:1 | +LL | pub trait Foo { fn foo(&self, ext_thing: &T); } + | --- method `foo` has generic type parameters +... LL | fn foo(b: &dyn Bar) { | ^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object - | - = note: method `foo` has generic type parameters error: aborting due to previous error diff --git a/src/test/ui/issues/issue-19380.stderr b/src/test/ui/issues/issue-19380.stderr index d70a7c2b5299c..92bfdf1f26e93 100644 --- a/src/test/ui/issues/issue-19380.stderr +++ b/src/test/ui/issues/issue-19380.stderr @@ -1,10 +1,11 @@ error[E0038]: the trait `Qiz` cannot be made into an object --> $DIR/issue-19380.rs:11:3 | +LL | fn qiz(); + | --- associated function `qiz` has no `self` parameter +... LL | foos: &'static [&'static (dyn Qiz + 'static)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Qiz` cannot be made into an object - | - = note: associated function `qiz` has no `self` parameter error: aborting due to previous error diff --git a/src/test/ui/issues/issue-19538.stderr b/src/test/ui/issues/issue-19538.stderr index e5da0a9b0dac3..5415a45f7d621 100644 --- a/src/test/ui/issues/issue-19538.stderr +++ b/src/test/ui/issues/issue-19538.stderr @@ -1,18 +1,21 @@ error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/issue-19538.rs:17:15 | +LL | fn foo(&self, val: T); + | --- method `foo` has generic type parameters +... LL | let test: &mut dyn Bar = &mut thing; | ^^^^^^^^^^^^ the trait `Bar` cannot be made into an object - | - = note: method `foo` has generic type parameters error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/issue-19538.rs:17:30 | +LL | fn foo(&self, val: T); + | --- method `foo` has generic type parameters +... LL | let test: &mut dyn Bar = &mut thing; | ^^^^^^^^^^ the trait `Bar` cannot be made into an object | - = note: method `foo` has generic type parameters = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&mut dyn Bar>` for `&mut Thing` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-50781.stderr b/src/test/ui/issues/issue-50781.stderr index c98f78c51ee5f..02475ea97e3d1 100644 --- a/src/test/ui/issues/issue-50781.stderr +++ b/src/test/ui/issues/issue-50781.stderr @@ -1,8 +1,8 @@ error: the trait `X` cannot be made into an object - --> $DIR/issue-50781.rs:6:5 + --> $DIR/issue-50781.rs:6:8 | LL | fn foo(&self) where Self: Trait; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^ | note: lint level defined here --> $DIR/issue-50781.rs:1:9 diff --git a/src/test/ui/object-safety/object-safety-associated-consts.stderr b/src/test/ui/object-safety/object-safety-associated-consts.stderr index 55f9e3f9f138b..7d5aa00356e0b 100644 --- a/src/test/ui/object-safety/object-safety-associated-consts.stderr +++ b/src/test/ui/object-safety/object-safety-associated-consts.stderr @@ -1,10 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/object-safety-associated-consts.rs:9:1 | +LL | const X: usize; + | - the trait cannot contain associated consts like `X` +... LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object - | - = note: the trait cannot contain associated consts like `X` error: aborting due to previous error diff --git a/src/test/ui/object-safety/object-safety-generics.stderr b/src/test/ui/object-safety/object-safety-generics.stderr index d66cdb98448d4..b25e0052e4163 100644 --- a/src/test/ui/object-safety/object-safety-generics.stderr +++ b/src/test/ui/object-safety/object-safety-generics.stderr @@ -1,18 +1,20 @@ error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/object-safety-generics.rs:14:1 | +LL | fn bar(&self, t: T); + | --- method `bar` has generic type parameters +... LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object - | - = note: method `bar` has generic type parameters error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/object-safety-generics.rs:19:1 | +LL | fn bar(&self, t: T); + | --- method `bar` has generic type parameters +... LL | fn make_bar_explicit(t: &T) -> &dyn Bar { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object - | - = note: method `bar` has generic type parameters error: aborting due to 2 previous errors diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.stderr b/src/test/ui/object-safety/object-safety-mentions-Self.stderr index c0c471c2b1e72..e2d1e773809bb 100644 --- a/src/test/ui/object-safety/object-safety-mentions-Self.stderr +++ b/src/test/ui/object-safety/object-safety-mentions-Self.stderr @@ -1,18 +1,20 @@ error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/object-safety-mentions-Self.rs:17:1 | +LL | fn bar(&self, x: &Self); + | --- method `bar` references the `Self` type in its arguments or return type +... LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object - | - = note: method `bar` references the `Self` type in its arguments or return type error[E0038]: the trait `Baz` cannot be made into an object --> $DIR/object-safety-mentions-Self.rs:22:1 | +LL | fn bar(&self) -> Self; + | --- method `bar` references the `Self` type in its arguments or return type +... LL | fn make_baz(t: &T) -> &dyn Baz { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Baz` cannot be made into an object - | - = note: method `bar` references the `Self` type in its arguments or return type error: aborting due to 2 previous errors diff --git a/src/test/ui/object-safety/object-safety-no-static.stderr b/src/test/ui/object-safety/object-safety-no-static.stderr index c189c358b4223..0de783f60ea47 100644 --- a/src/test/ui/object-safety/object-safety-no-static.stderr +++ b/src/test/ui/object-safety/object-safety-no-static.stderr @@ -1,10 +1,11 @@ error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/object-safety-no-static.rs:8:1 | +LL | fn foo(); + | --- associated function `foo` has no `self` parameter +... LL | fn foo_implicit(b: Box) -> Box { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object - | - = note: associated function `foo` has no `self` parameter error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-3907-2.stderr b/src/test/ui/resolve/issue-3907-2.stderr index 63ac11dc8ae01..087d1a5b9d365 100644 --- a/src/test/ui/resolve/issue-3907-2.stderr +++ b/src/test/ui/resolve/issue-3907-2.stderr @@ -3,8 +3,6 @@ error[E0038]: the trait `issue_3907::Foo` cannot be made into an object | LL | fn bar(_x: Foo) {} | ^^^^^^^^^^^^^^^ the trait `issue_3907::Foo` cannot be made into an object - | - = note: associated function `bar` has no `self` parameter error: aborting due to previous error diff --git a/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr b/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr index e45bc2657f1ea..9fb1500afce47 100644 --- a/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr +++ b/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr @@ -1,18 +1,21 @@ error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/arbitrary-self-types-not-object-safe.rs:31:32 | +LL | fn foo(self: &Rc) -> usize; + | --- method `foo`'s receiver cannot be dispatched on +... LL | let x = Rc::new(5usize) as Rc; | ^^^^^^^^^^^ the trait `Foo` cannot be made into an object - | - = note: method `foo`'s receiver cannot be dispatched on error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/arbitrary-self-types-not-object-safe.rs:31:13 | +LL | fn foo(self: &Rc) -> usize; + | --- method `foo`'s receiver cannot be dispatched on +... LL | let x = Rc::new(5usize) as Rc; | ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object | - = note: method `foo`'s receiver cannot be dispatched on = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::rc::Rc` error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr index de699a69fa8bc..aec648d7b8473 100644 --- a/src/test/ui/traits/trait-item-privacy.stderr +++ b/src/test/ui/traits/trait-item-privacy.stderr @@ -103,12 +103,17 @@ LL | C::A; error[E0038]: the trait `assoc_const::C` cannot be made into an object --> $DIR/trait-item-privacy.rs:101:5 | +LL | const A: u8 = 0; + | - the trait cannot contain associated consts like `A` +... +LL | const B: u8 = 0; + | - the trait cannot contain associated consts like `B` +... +LL | const C: u8 = 0; + | - the trait cannot contain associated consts like `C` +... LL | C::A; | ^^^^ the trait `assoc_const::C` cannot be made into an object - | - = note: the trait cannot contain associated consts like `C` - = note: the trait cannot contain associated consts like `B` - = note: the trait cannot contain associated consts like `A` error[E0223]: ambiguous associated type --> $DIR/trait-item-privacy.rs:115:12 diff --git a/src/test/ui/traits/trait-object-safety.stderr b/src/test/ui/traits/trait-object-safety.stderr index 7f6bc0ebb70e5..3ac1e96b30c95 100644 --- a/src/test/ui/traits/trait-object-safety.stderr +++ b/src/test/ui/traits/trait-object-safety.stderr @@ -1,19 +1,22 @@ error[E0038]: the trait `Tr` cannot be made into an object --> $DIR/trait-object-safety.rs:15:22 | +LL | fn foo(); + | --- associated function `foo` has no `self` parameter +... LL | let _: &dyn Tr = &St; | ^^^ the trait `Tr` cannot be made into an object | - = note: associated function `foo` has no `self` parameter = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Tr>` for `&St` error[E0038]: the trait `Tr` cannot be made into an object --> $DIR/trait-object-safety.rs:15:12 | +LL | fn foo(); + | --- associated function `foo` has no `self` parameter +... LL | let _: &dyn Tr = &St; | ^^^^^^^ the trait `Tr` cannot be made into an object - | - = note: associated function `foo` has no `self` parameter error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/trait-test-2.stderr b/src/test/ui/traits/trait-test-2.stderr index 5d5251925a1ae..4d2aca0d4094a 100644 --- a/src/test/ui/traits/trait-test-2.stderr +++ b/src/test/ui/traits/trait-test-2.stderr @@ -13,20 +13,25 @@ LL | 10.blah::(); error[E0038]: the trait `bar` cannot be made into an object --> $DIR/trait-test-2.rs:11:16 | +LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } + | --- ---- method `blah` has generic type parameters + | | + | method `dup` references the `Self` type in its arguments or return type +... LL | (box 10 as Box).dup(); | ^^^^^^^^^^^^ the trait `bar` cannot be made into an object - | - = note: method `dup` references the `Self` type in its arguments or return type - = note: method `blah` has generic type parameters error[E0038]: the trait `bar` cannot be made into an object --> $DIR/trait-test-2.rs:11:6 | +LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } + | --- ---- method `blah` has generic type parameters + | | + | method `dup` references the `Self` type in its arguments or return type +... LL | (box 10 as Box).dup(); | ^^^^^^ the trait `bar` cannot be made into an object | - = note: method `dup` references the `Self` type in its arguments or return type - = note: method `blah` has generic type parameters = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::boxed::Box<{integer}>` error: aborting due to 4 previous errors diff --git a/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr b/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr index 58727ea0fef99..03df5b8211889 100644 --- a/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr +++ b/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr @@ -13,10 +13,11 @@ LL | let y = x as dyn MyAdd; error[E0038]: the trait `MyAdd` cannot be made into an object --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:18 | +LL | trait MyAdd { fn add(&self, other: &Rhs) -> Self; } + | --- method `add` references the `Self` type in its arguments or return type +... LL | let y = x as dyn MyAdd; | ^^^^^^^^^^^^^^ the trait `MyAdd` cannot be made into an object - | - = note: method `add` references the `Self` type in its arguments or return type error: aborting due to 2 previous errors diff --git a/src/test/ui/wf/wf-object-safe.stderr b/src/test/ui/wf/wf-object-safe.stderr index 3b264ecd580ec..d11af11f05051 100644 --- a/src/test/ui/wf/wf-object-safe.stderr +++ b/src/test/ui/wf/wf-object-safe.stderr @@ -1,10 +1,11 @@ error[E0038]: the trait `A` cannot be made into an object --> $DIR/wf-object-safe.rs:9:13 | +LL | fn foo(&self, _x: &Self); + | --- method `foo` references the `Self` type in its arguments or return type +... LL | let _x: &dyn A; | ^^^^^^ the trait `A` cannot be made into an object - | - = note: method `foo` references the `Self` type in its arguments or return type error: aborting due to previous error From bb99fc31d0a8f962662e636938cf96f0f70d3803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 2 Sep 2019 21:08:34 -0700 Subject: [PATCH 12/25] review comment: update error code descr --- src/librustc_typeck/error_codes.rs | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index ae0f17892959d..ebfa6acf23e00 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -212,7 +212,7 @@ match string { E0033: r##" This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a pattern. Every trait defines a type, but because the -size of trait implementors isn't fixed, this type has no compile-time size. +size of trait implementers isn't fixed, this type has no compile-time size. Therefore, all accesses to trait types must be through pointers. If you encounter this error you should try to avoid dereferencing the pointer. @@ -2430,23 +2430,23 @@ This error indicates that the `self` parameter in a method has an invalid "reciever type". Methods take a special first parameter, of which there are three variants: -`self`, `&self`, and `&mut self`. The type `Self` acts as an alias to the -type of the current trait implementor, or "receiver type". Besides the -already mentioned `Self`, `&Self` and `&mut Self` valid receiver types, the -following are also valid, if less common: `self: Box`, -`self: Rc`, `self: Arc`, and `self: Pin

` (where P is one of -the previous types except `Self`). +`self`, `&self`, and `&mut self`. These are syntactic sugar for +`self: Self`, `self: &Self`, and `self: &mut Self` respectively. The type +`Self` acts as an alias to the type of the current trait implementer, or +"receiver type". Besides the already mentioned `Self`, `&Self` and +`&mut Self` valid receiver types, the following are also valid: +`self: Box`, `self: Rc`, `self: Arc`, and `self: Pin

` +(where P is one of the previous types except `Self`). ``` # struct Foo; trait Trait { fn foo(&self); -// ^^^^^ this let's you refer to the type that implements this trait } + impl Trait for Foo { -// ^^^ this is the "receiver type" fn foo(&self) {} -// ^^^^^ this is of type `Foo` +// ^^^^^ this the receiver type `&Foo` } ``` @@ -2458,11 +2458,12 @@ The above is equivalent to: # fn foo(&self); # } impl Trait for Foo { - fn foo(&self: &Foo) {} + fn foo(self: &Foo) {} } ``` -When using an invalid reciver type, like in the following example, +E0307 will be emitted by the compiler when using an invalid reciver type, +like in the following example: ```compile_fail,E0307 # struct Foo; @@ -2471,12 +2472,13 @@ When using an invalid reciver type, like in the following example, # fn foo(&self); # } impl Trait for Struct { - fn foo(&self: &Bar) {} + fn foo(self: &Bar) {} } ``` The nightly feature [Arbintrary self types][AST] extends the accepted -receiver type to also include any type that can dereference to `Self`: +set of receiver types to also include any type that can dereference to +`Self`: ``` #![feature(arbitrary_self_types)] From efe85943b3a5e7b3920db5a5a53183c75fc80d0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 2 Sep 2019 22:11:29 -0700 Subject: [PATCH 13/25] account for DUMMY_SP and correct wording --- src/librustc/error_codes.rs | 2 +- src/librustc/traits/object_safety.rs | 8 ++++---- .../coherence-impl-trait-for-trait-object-safe.old.stderr | 2 +- .../coherence-impl-trait-for-trait-object-safe.re.stderr | 2 +- src/test/ui/error-codes/E0038.stderr | 2 +- .../ui/object-safety/object-safety-mentions-Self.stderr | 4 ++-- src/test/ui/resolve/issue-3907-2.stderr | 2 ++ src/test/ui/traits/trait-test-2.stderr | 4 ++-- .../type-parameter-defaults-referencing-Self-ppaux.stderr | 2 +- src/test/ui/wf/wf-object-safe.stderr | 2 +- 10 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 2d09013f675a7..937a9ea6c1bd4 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -39,7 +39,7 @@ Generally, `Self: Sized` is used to indicate that the trait should not be used as a trait object. If the trait comes from your own crate, consider removing this restriction. -### Method references the `Self` type in its arguments or return type +### Method references the `Self` type in its parameters or return type This happens when a trait has a method like the following: diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 50f497e302e6d..5392e9100c6d1 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -20,7 +20,7 @@ use std::borrow::Cow; use std::iter::{self}; use syntax::ast::{self}; use syntax::symbol::InternedString; -use syntax_pos::Span; +use syntax_pos::{Span, DUMMY_SP}; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum ObjectSafetyViolation { @@ -49,7 +49,7 @@ impl ObjectSafetyViolation { ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod, _) => format!("associated function `{}` has no `self` parameter", name).into(), ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf, _) => format!( - "method `{}` references the `Self` type in its arguments or return type", + "method `{}` references the `Self` type in its parameters or return type", name, ).into(), ObjectSafetyViolation::Method( @@ -67,9 +67,9 @@ impl ObjectSafetyViolation { } pub fn span(&self) -> Option { - match self { + match *self { ObjectSafetyViolation::AssocConst(_, span) | - ObjectSafetyViolation::Method(_, _, span) => Some(*span), + ObjectSafetyViolation::Method(_, _, span) if span != DUMMY_SP => Some(span), _ => None, } } diff --git a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr index 2626eab3cbf23..18a7cea95bdb9 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr +++ b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr @@ -2,7 +2,7 @@ error[E0038]: the trait `NotObjectSafe` cannot be made into an object --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:11:6 | LL | trait NotObjectSafe { fn eq(&self, other: Self); } - | -- method `eq` references the `Self` type in its arguments or return type + | -- method `eq` references the `Self` type in its parameters or return type LL | impl NotObjectSafe for dyn NotObjectSafe { } | ^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object diff --git a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr index 2626eab3cbf23..18a7cea95bdb9 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr +++ b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr @@ -2,7 +2,7 @@ error[E0038]: the trait `NotObjectSafe` cannot be made into an object --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:11:6 | LL | trait NotObjectSafe { fn eq(&self, other: Self); } - | -- method `eq` references the `Self` type in its arguments or return type + | -- method `eq` references the `Self` type in its parameters or return type LL | impl NotObjectSafe for dyn NotObjectSafe { } | ^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object diff --git a/src/test/ui/error-codes/E0038.stderr b/src/test/ui/error-codes/E0038.stderr index 93a7681393b29..5c4d6d53c4626 100644 --- a/src/test/ui/error-codes/E0038.stderr +++ b/src/test/ui/error-codes/E0038.stderr @@ -2,7 +2,7 @@ error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/E0038.rs:5:1 | LL | fn foo(&self) -> Self; - | --- method `foo` references the `Self` type in its arguments or return type + | --- method `foo` references the `Self` type in its parameters or return type ... LL | fn call_foo(x: Box) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` cannot be made into an object diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.stderr b/src/test/ui/object-safety/object-safety-mentions-Self.stderr index e2d1e773809bb..971e79cb0210f 100644 --- a/src/test/ui/object-safety/object-safety-mentions-Self.stderr +++ b/src/test/ui/object-safety/object-safety-mentions-Self.stderr @@ -2,7 +2,7 @@ error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/object-safety-mentions-Self.rs:17:1 | LL | fn bar(&self, x: &Self); - | --- method `bar` references the `Self` type in its arguments or return type + | --- method `bar` references the `Self` type in its parameters or return type ... LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object @@ -11,7 +11,7 @@ error[E0038]: the trait `Baz` cannot be made into an object --> $DIR/object-safety-mentions-Self.rs:22:1 | LL | fn bar(&self) -> Self; - | --- method `bar` references the `Self` type in its arguments or return type + | --- method `bar` references the `Self` type in its parameters or return type ... LL | fn make_baz(t: &T) -> &dyn Baz { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Baz` cannot be made into an object diff --git a/src/test/ui/resolve/issue-3907-2.stderr b/src/test/ui/resolve/issue-3907-2.stderr index 087d1a5b9d365..63ac11dc8ae01 100644 --- a/src/test/ui/resolve/issue-3907-2.stderr +++ b/src/test/ui/resolve/issue-3907-2.stderr @@ -3,6 +3,8 @@ error[E0038]: the trait `issue_3907::Foo` cannot be made into an object | LL | fn bar(_x: Foo) {} | ^^^^^^^^^^^^^^^ the trait `issue_3907::Foo` cannot be made into an object + | + = note: associated function `bar` has no `self` parameter error: aborting due to previous error diff --git a/src/test/ui/traits/trait-test-2.stderr b/src/test/ui/traits/trait-test-2.stderr index 4d2aca0d4094a..83c2c06527493 100644 --- a/src/test/ui/traits/trait-test-2.stderr +++ b/src/test/ui/traits/trait-test-2.stderr @@ -16,7 +16,7 @@ error[E0038]: the trait `bar` cannot be made into an object LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } | --- ---- method `blah` has generic type parameters | | - | method `dup` references the `Self` type in its arguments or return type + | method `dup` references the `Self` type in its parameters or return type ... LL | (box 10 as Box).dup(); | ^^^^^^^^^^^^ the trait `bar` cannot be made into an object @@ -27,7 +27,7 @@ error[E0038]: the trait `bar` cannot be made into an object LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } | --- ---- method `blah` has generic type parameters | | - | method `dup` references the `Self` type in its arguments or return type + | method `dup` references the `Self` type in its parameters or return type ... LL | (box 10 as Box).dup(); | ^^^^^^ the trait `bar` cannot be made into an object diff --git a/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr b/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr index 03df5b8211889..b315fe9df8afd 100644 --- a/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr +++ b/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr @@ -14,7 +14,7 @@ error[E0038]: the trait `MyAdd` cannot be made into an object --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:18 | LL | trait MyAdd { fn add(&self, other: &Rhs) -> Self; } - | --- method `add` references the `Self` type in its arguments or return type + | --- method `add` references the `Self` type in its parameters or return type ... LL | let y = x as dyn MyAdd; | ^^^^^^^^^^^^^^ the trait `MyAdd` cannot be made into an object diff --git a/src/test/ui/wf/wf-object-safe.stderr b/src/test/ui/wf/wf-object-safe.stderr index d11af11f05051..0d8441f87e7e7 100644 --- a/src/test/ui/wf/wf-object-safe.stderr +++ b/src/test/ui/wf/wf-object-safe.stderr @@ -2,7 +2,7 @@ error[E0038]: the trait `A` cannot be made into an object --> $DIR/wf-object-safe.rs:9:13 | LL | fn foo(&self, _x: &Self); - | --- method `foo` references the `Self` type in its arguments or return type + | --- method `foo` references the `Self` type in its parameters or return type ... LL | let _x: &dyn A; | ^^^^^^ the trait `A` cannot be made into an object From 8c74eb77902dc5c4fdf853e9159dd5fadd00601d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Sep 2019 17:21:58 +1000 Subject: [PATCH 14/25] Move path parsing earlier. It's a hot enough path that moving it slightly earlier gives a tiny but easy speedup. --- src/libsyntax/parse/parser/expr.rs | 56 ++++++++++++++++-------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index 5b9f0f1df6718..e502a08f4b253 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -889,6 +889,36 @@ impl<'a> Parser<'a> { hi = path.span; return Ok(self.mk_expr(lo.to(hi), ExprKind::Path(Some(qself), path), attrs)); } + if self.token.is_path_start() { + let path = self.parse_path(PathStyle::Expr)?; + + // `!`, as an operator, is prefix, so we know this isn't that + if self.eat(&token::Not) { + // MACRO INVOCATION expression + let (delim, tts) = self.expect_delimited_token_tree()?; + hi = self.prev_span; + ex = ExprKind::Mac(Mac { + path, + tts, + delim, + span: lo.to(hi), + prior_type_ascription: self.last_type_ascription, + }); + } else if self.check(&token::OpenDelim(token::Brace)) { + if let Some(expr) = self.maybe_parse_struct_expr(lo, &path, &attrs) { + return expr; + } else { + hi = path.span; + ex = ExprKind::Path(None, path); + } + } else { + hi = path.span; + ex = ExprKind::Path(None, path); + } + + let expr = self.mk_expr(lo.to(hi), ex, attrs); + return self.maybe_recover_from_bad_qpath(expr, true); + } if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) { return self.parse_lambda_expr(attrs); } @@ -1007,32 +1037,6 @@ impl<'a> Parser<'a> { let (await_hi, e_kind) = self.parse_incorrect_await_syntax(lo, self.prev_span)?; hi = await_hi; ex = e_kind; - } else if self.token.is_path_start() { - let path = self.parse_path(PathStyle::Expr)?; - - // `!`, as an operator, is prefix, so we know this isn't that - if self.eat(&token::Not) { - // MACRO INVOCATION expression - let (delim, tts) = self.expect_delimited_token_tree()?; - hi = self.prev_span; - ex = ExprKind::Mac(Mac { - path, - tts, - delim, - span: lo.to(hi), - prior_type_ascription: self.last_type_ascription, - }); - } else if self.check(&token::OpenDelim(token::Brace)) { - if let Some(expr) = self.maybe_parse_struct_expr(lo, &path, &attrs) { - return expr; - } else { - hi = path.span; - ex = ExprKind::Path(None, path); - } - } else { - hi = path.span; - ex = ExprKind::Path(None, path); - } } else { if !self.unclosed_delims.is_empty() && self.check(&token::Semi) { // Don't complain about bare semicolons after unclosed braces From 23c76ff7b912f16f6fdbde167306b08e59353427 Mon Sep 17 00:00:00 2001 From: Daniel Henry-Mantilla Date: Tue, 3 Sep 2019 12:17:03 +0200 Subject: [PATCH 15/25] Added warning around code with reference to uninit bytes --- src/libstd/io/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 5060f368229bb..495c0c8d17256 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -371,6 +371,14 @@ where loop { if g.len == g.buf.len() { unsafe { + // FIXME(danielhenrymantilla): #42788 + // + // - This creates a (mut) reference to a slice of + // _uninitialized integers_. + // + // - This having defined behavior is **unstable**: + // it could become UB in the future, + // at which point it would have be changed. g.buf.reserve(reservation_size(r)); let capacity = g.buf.capacity(); g.buf.set_len(capacity); From e85b181638f228b6dd6b0aa10d41552f4de5ea58 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 3 Sep 2019 15:33:30 +0200 Subject: [PATCH 16/25] unused_parens: fix for or-patterns + &(mut x) --- src/librustc_lint/unused.rs | 81 ++++++++-- .../ui/lint/issue-54538-unused-parens-lint.rs | 90 ++++++++--- .../issue-54538-unused-parens-lint.stderr | 149 ++++++++++++++---- 3 files changed, 256 insertions(+), 64 deletions(-) diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 90e467713968b..39c0698aeec9f 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -398,18 +398,37 @@ impl UnusedParens { } } - fn check_unused_parens_pat(&self, - cx: &EarlyContext<'_>, - value: &ast::Pat, - msg: &str) { - if let ast::PatKind::Paren(_) = value.node { + fn check_unused_parens_pat( + &self, + cx: &EarlyContext<'_>, + value: &ast::Pat, + avoid_or: bool, + avoid_mut: bool, + ) { + use ast::{PatKind, BindingMode::ByValue, Mutability::Mutable}; + + if let PatKind::Paren(inner) = &value.node { + match inner.node { + // The lint visitor will visit each subpattern of `p`. We do not want to lint + // any range pattern no matter where it occurs in the pattern. For something like + // `&(a..=b)`, there is a recursive `check_pat` on `a` and `b`, but we will assume + // that if there are unnecessary parens they serve a purpose of readability. + PatKind::Range(..) => return, + // Avoid `p0 | .. | pn` if we should. + PatKind::Or(..) if avoid_or => return, + // Avoid `mut x` and `mut x @ p` if we should: + PatKind::Ident(ByValue(Mutable), ..) if avoid_mut => return, + // Otherwise proceed with linting. + _ => {} + } + let pattern_text = if let Ok(snippet) = cx.sess().source_map() .span_to_snippet(value.span) { snippet } else { pprust::pat_to_string(value) }; - Self::remove_outer_parens(cx, value.span, &pattern_text, msg, (false, false)); + Self::remove_outer_parens(cx, value.span, &pattern_text, "pattern", (false, false)); } } @@ -474,6 +493,13 @@ impl EarlyLintPass for UnusedParens { fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { use syntax::ast::ExprKind::*; let (value, msg, followed_by_block, left_pos, right_pos) = match e.node { + Let(ref pats, ..) => { + for p in pats { + self.check_unused_parens_pat(cx, p, false, false); + } + return; + } + If(ref cond, ref block, ..) => { let left = e.span.lo() + syntax_pos::BytePos(2); let right = block.span.lo(); @@ -486,7 +512,8 @@ impl EarlyLintPass for UnusedParens { (cond, "`while` condition", true, Some(left), Some(right)) }, - ForLoop(_, ref cond, ref block, ..) => { + ForLoop(ref pat, ref cond, ref block, ..) => { + self.check_unused_parens_pat(cx, pat, false, false); (cond, "`for` head expression", true, None, Some(block.span.lo())) } @@ -531,26 +558,46 @@ impl EarlyLintPass for UnusedParens { } fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &ast::Pat) { - use ast::PatKind::{Paren, Range}; - // The lint visitor will visit each subpattern of `p`. We do not want to lint any range - // pattern no matter where it occurs in the pattern. For something like `&(a..=b)`, there - // is a recursive `check_pat` on `a` and `b`, but we will assume that if there are - // unnecessary parens they serve a purpose of readability. - if let Paren(ref pat) = p.node { - match pat.node { - Range(..) => {} - _ => self.check_unused_parens_pat(cx, &p, "pattern") - } + use ast::{PatKind::*, Mutability}; + match &p.node { + // Do not lint on `(..)` as that will result in the other arms being useless. + Paren(_) + // The other cases do not contain sub-patterns. + | Wild | Rest | Lit(..) | Mac(..) | Range(..) | Ident(.., None) | Path(..) => return, + // These are list-like patterns; parens can always be removed. + TupleStruct(_, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps { + self.check_unused_parens_pat(cx, p, false, false); + }, + Struct(_, fps, _) => for f in fps { + self.check_unused_parens_pat(cx, &f.pat, false, false); + }, + // Avoid linting on `i @ (p0 | .. | pn)` and `box (p0 | .. | pn)`, #64106. + Ident(.., Some(p)) | Box(p) => self.check_unused_parens_pat(cx, p, true, false), + // Avoid linting on `&(mut x)` as `&mut x` has a different meaning, #55342. + // Also avoid linting on `& mut? (p0 | .. | pn)`, #64106. + Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Immutable), } } fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) { if let ast::StmtKind::Local(ref local) = s.node { + self.check_unused_parens_pat(cx, &local.pat, false, false); + if let Some(ref value) = local.init { self.check_unused_parens_expr(cx, &value, "assigned value", false, None, None); } } } + + fn check_param(&mut self, cx: &EarlyContext<'_>, param: &ast::Param) { + self.check_unused_parens_pat(cx, ¶m.pat, true, false); + } + + fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) { + for p in &arm.pats { + self.check_unused_parens_pat(cx, p, false, false); + } + } } declare_lint! { diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.rs b/src/test/ui/lint/issue-54538-unused-parens-lint.rs index eda9e2cdfaa2f..c442c39fe010e 100644 --- a/src/test/ui/lint/issue-54538-unused-parens-lint.rs +++ b/src/test/ui/lint/issue-54538-unused-parens-lint.rs @@ -1,25 +1,75 @@ -// build-pass (FIXME(62277): could be check-pass?) +#![feature(box_patterns)] + +#![feature(or_patterns)] +//~^ WARN the feature `or_patterns` is incomplete #![allow(ellipsis_inclusive_range_patterns)] #![allow(unreachable_patterns)] #![allow(unused_variables)] -#![warn(unused_parens)] +#![deny(unused_parens)] + +fn lint_on_top_level() { + let (a) = 0; //~ ERROR unnecessary parentheses around pattern + for (a) in 0..1 {} //~ ERROR unnecessary parentheses around pattern + if let (a) = 0 {} //~ ERROR unnecessary parentheses around pattern + while let (a) = 0 {} //~ ERROR unnecessary parentheses around pattern + fn foo((a): u8) {} //~ ERROR unnecessary parentheses around pattern + let _ = |(a): u8| 0; //~ ERROR unnecessary parentheses around pattern +} + +// Don't lint in these cases (#64106). +fn or_patterns_no_lint() { + match Box::new(0) { + box (0 | 1) => {} // Should not lint as `box 0 | 1` binds as `(box 0) | 1`. + _ => {} + } + + match 0 { + x @ (0 | 1) => {} // Should not lint as `x @ 0 | 1` binds as `(x @ 0) | 1`. + _ => {} + } + + if let &(0 | 1) = &0 {} // Should also not lint. + if let &mut (0 | 1) = &mut 0 {} // Same. + + fn foo((Ok(a) | Err(a)): Result) {} // Doesn't parse if we remove parens for now. + //~^ ERROR identifier `a` is bound more than once + + let _ = |(Ok(a) | Err(a)): Result| 1; // `|Ok(a) | Err(a)| 1` parses as bit-or. + //~^ ERROR identifier `a` is bound more than once +} + +fn or_patterns_will_lint() { + if let (0 | 1) = 0 {} //~ ERROR unnecessary parentheses around pattern + if let ((0 | 1),) = (0,) {} //~ ERROR unnecessary parentheses around pattern + if let [(0 | 1)] = [0] {} //~ ERROR unnecessary parentheses around pattern + if let 0 | (1 | 2) = 0 {} //~ ERROR unnecessary parentheses around pattern + struct TS(u8); + if let TS((0 | 1)) = TS(0) {} //~ ERROR unnecessary parentheses around pattern + struct NS { f: u8 } + if let NS { f: (0 | 1) } = (NS { f: 0 }) {} //~ ERROR unnecessary parentheses around pattern +} + +// Don't lint on `&(mut x)` because `&mut x` means something else (#55342). +fn deref_mut_binding_no_lint() { + let &(mut x) = &0; +} fn main() { match 1 { - (_) => {} //~ WARNING: unnecessary parentheses around pattern - (y) => {} //~ WARNING: unnecessary parentheses around pattern - (ref r) => {} //~ WARNING: unnecessary parentheses around pattern - (e @ 1...2) => {} //~ WARNING: unnecessary parentheses around outer pattern - (1...2) => {} // Non ambiguous range pattern should not warn + (_) => {} //~ ERROR unnecessary parentheses around pattern + (y) => {} //~ ERROR unnecessary parentheses around pattern + (ref r) => {} //~ ERROR unnecessary parentheses around pattern + (e @ 1...2) => {} //~ ERROR unnecessary parentheses around pattern + (1...2) => {} // Non ambiguous range pattern should not warn e @ (3...4) => {} // Non ambiguous range pattern should not warn } match &1 { - (e @ &(1...2)) => {} //~ WARNING: unnecessary parentheses around outer pattern - &(_) => {} //~ WARNING: unnecessary parentheses around pattern - e @ &(1...2) => {} // Ambiguous range pattern should not warn - &(1...2) => {} // Ambiguous range pattern should not warn + (e @ &(1...2)) => {} //~ ERROR unnecessary parentheses around pattern + &(_) => {} //~ ERROR unnecessary parentheses around pattern + e @ &(1...2) => {} // Ambiguous range pattern should not warn + &(1...2) => {} // Ambiguous range pattern should not warn } match &1 { @@ -28,19 +78,19 @@ fn main() { } match 1 { - (_) => {} //~ WARNING: unnecessary parentheses around pattern - (y) => {} //~ WARNING: unnecessary parentheses around pattern - (ref r) => {} //~ WARNING: unnecessary parentheses around pattern - (e @ 1..=2) => {} //~ WARNING: unnecessary parentheses around outer pattern - (1..=2) => {} // Non ambiguous range pattern should not warn + (_) => {} //~ ERROR unnecessary parentheses around pattern + (y) => {} //~ ERROR unnecessary parentheses around pattern + (ref r) => {} //~ ERROR unnecessary parentheses around pattern + (e @ 1..=2) => {} //~ ERROR unnecessary parentheses around pattern + (1..=2) => {} // Non ambiguous range pattern should not warn e @ (3..=4) => {} // Non ambiguous range pattern should not warn } match &1 { - (e @ &(1..=2)) => {} //~ WARNING: unnecessary parentheses around outer pattern - &(_) => {} //~ WARNING: unnecessary parentheses around pattern - e @ &(1..=2) => {} // Ambiguous range pattern should not warn - &(1..=2) => {} // Ambiguous range pattern should not warn + (e @ &(1..=2)) => {} //~ ERROR unnecessary parentheses around pattern + &(_) => {} //~ ERROR unnecessary parentheses around pattern + e @ &(1..=2) => {} // Ambiguous range pattern should not warn + &(1..=2) => {} // Ambiguous range pattern should not warn } match &1 { diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.stderr b/src/test/ui/lint/issue-54538-unused-parens-lint.stderr index 3b312198952a5..a3e0fb938b3c6 100644 --- a/src/test/ui/lint/issue-54538-unused-parens-lint.stderr +++ b/src/test/ui/lint/issue-54538-unused-parens-lint.stderr @@ -1,78 +1,173 @@ -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:10:9 +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/issue-54538-unused-parens-lint.rs:35:25 | -LL | (_) => {} +LL | fn foo((Ok(a) | Err(a)): Result) {} // Doesn't parse if we remove parens for now. + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/issue-54538-unused-parens-lint.rs:38:27 + | +LL | let _ = |(Ok(a) | Err(a)): Result| 1; // `|Ok(a) | Err(a)| 1` parses as bit-or. + | ^ used in a pattern more than once + +warning: the feature `or_patterns` is incomplete and may cause the compiler to crash + --> $DIR/issue-54538-unused-parens-lint.rs:3:12 + | +LL | #![feature(or_patterns)] + | ^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:12:9 + | +LL | let (a) = 0; | ^^^ help: remove these parentheses | note: lint level defined here - --> $DIR/issue-54538-unused-parens-lint.rs:6:9 + --> $DIR/issue-54538-unused-parens-lint.rs:9:9 | -LL | #![warn(unused_parens)] +LL | #![deny(unused_parens)] | ^^^^^^^^^^^^^ -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:11:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:13:9 + | +LL | for (a) in 0..1 {} + | ^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:14:12 + | +LL | if let (a) = 0 {} + | ^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:15:15 + | +LL | while let (a) = 0 {} + | ^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:16:12 + | +LL | fn foo((a): u8) {} + | ^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:17:14 + | +LL | let _ = |(a): u8| 0; + | ^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:43:12 + | +LL | if let (0 | 1) = 0 {} + | ^^^^^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:44:13 + | +LL | if let ((0 | 1),) = (0,) {} + | ^^^^^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:45:13 + | +LL | if let [(0 | 1)] = [0] {} + | ^^^^^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:46:16 + | +LL | if let 0 | (1 | 2) = 0 {} + | ^^^^^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:48:15 + | +LL | if let TS((0 | 1)) = TS(0) {} + | ^^^^^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:50:20 + | +LL | if let NS { f: (0 | 1) } = (NS { f: 0 }) {} + | ^^^^^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:60:9 + | +LL | (_) => {} + | ^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:61:9 | LL | (y) => {} | ^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:12:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:62:9 | LL | (ref r) => {} | ^^^^^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:13:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:63:9 | LL | (e @ 1...2) => {} | ^^^^^^^^^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:19:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:69:9 | LL | (e @ &(1...2)) => {} | ^^^^^^^^^^^^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:20:10 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:70:10 | LL | &(_) => {} | ^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:31:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:81:9 | LL | (_) => {} | ^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:32:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:82:9 | LL | (y) => {} | ^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:33:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:83:9 | LL | (ref r) => {} | ^^^^^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:34:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:84:9 | LL | (e @ 1..=2) => {} | ^^^^^^^^^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:40:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:90:9 | LL | (e @ &(1..=2)) => {} | ^^^^^^^^^^^^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:41:10 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:91:10 | LL | &(_) => {} | ^^^ help: remove these parentheses +error: aborting due to 26 previous errors + +For more information about this error, try `rustc --explain E0416`. From b03d3dc478ba13f405cf9a877a4894de096a1cc1 Mon Sep 17 00:00:00 2001 From: Daniel Henry-Mantilla Date: Tue, 3 Sep 2019 15:36:21 +0200 Subject: [PATCH 17/25] Changed comment to better reflect std's exceptional situation --- src/libstd/io/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 495c0c8d17256..0386dbd490d03 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -374,11 +374,11 @@ where // FIXME(danielhenrymantilla): #42788 // // - This creates a (mut) reference to a slice of - // _uninitialized integers_. + // _uninitialized_ integers, which is **undefined behavior** // - // - This having defined behavior is **unstable**: - // it could become UB in the future, - // at which point it would have be changed. + // - Only the standard library gets to soundly "ignore" this, + // based on its privileged knowledge of unstable rustc + // internals; g.buf.reserve(reservation_size(r)); let capacity = g.buf.capacity(); g.buf.set_len(capacity); From 28b518474ed2a5dee812e4f356f71f4c60628421 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 3 Sep 2019 08:03:09 -0700 Subject: [PATCH 18/25] review comments: error code text --- src/librustc_typeck/error_codes.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index ebfa6acf23e00..a2b1f16ef3de7 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -2431,26 +2431,28 @@ This error indicates that the `self` parameter in a method has an invalid Methods take a special first parameter, of which there are three variants: `self`, `&self`, and `&mut self`. These are syntactic sugar for -`self: Self`, `self: &Self`, and `self: &mut Self` respectively. The type -`Self` acts as an alias to the type of the current trait implementer, or -"receiver type". Besides the already mentioned `Self`, `&Self` and -`&mut Self` valid receiver types, the following are also valid: -`self: Box`, `self: Rc`, `self: Arc`, and `self: Pin

` -(where P is one of the previous types except `Self`). +`self: Self`, `self: &Self`, and `self: &mut Self` respectively. ``` # struct Foo; trait Trait { fn foo(&self); +// ^^^^^ `self` here is a reference to the receiver object } impl Trait for Foo { fn foo(&self) {} -// ^^^^^ this the receiver type `&Foo` +// ^^^^^ the receiver type is `&Foo` } ``` -The above is equivalent to: +The type `Self` acts as an alias to the type of the current trait +implementer, or "receiver type". Besides the already mentioned `Self`, +`&Self` and `&mut Self` valid receiver types, the following are also valid: +`self: Box`, `self: Rc`, `self: Arc`, and `self: Pin

` +(where P is one of the previous types except `Self`). Note that `Self` can +also be the underlying implementing type, like `Foo` in the following +example: ``` # struct Foo; From 4a79633ad2ff5ce1641405daefc41a13d786dacf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 3 Sep 2019 08:05:54 -0700 Subject: [PATCH 19/25] review comments --- src/librustc/traits/object_safety.rs | 4 +++- src/test/ui/self/arbitrary-self-types-not-object-safe.stderr | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 5392e9100c6d1..f7f459cd27f68 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -60,13 +60,15 @@ impl ObjectSafetyViolation { ObjectSafetyViolation::Method(name, MethodViolationCode::Generic, _) => format!("method `{}` has generic type parameters", name).into(), ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver, _) => - format!("method `{}`'s receiver cannot be dispatched on", name).into(), + format!("method `{}`'s `self` parameter cannot be dispatched on", name).into(), ObjectSafetyViolation::AssocConst(name, _) => format!("the trait cannot contain associated consts like `{}`", name).into(), } } pub fn span(&self) -> Option { + // When `span` comes from a separate crate, it'll be `DUMMY_SP`. Treat it as `None` so + // diagnostics use a `note` instead of a `span_label`. match *self { ObjectSafetyViolation::AssocConst(_, span) | ObjectSafetyViolation::Method(_, _, span) if span != DUMMY_SP => Some(span), diff --git a/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr b/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr index 9fb1500afce47..e6eba377a9578 100644 --- a/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr +++ b/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr @@ -2,7 +2,7 @@ error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/arbitrary-self-types-not-object-safe.rs:31:32 | LL | fn foo(self: &Rc) -> usize; - | --- method `foo`'s receiver cannot be dispatched on + | --- method `foo`'s `self` parameter cannot be dispatched on ... LL | let x = Rc::new(5usize) as Rc; | ^^^^^^^^^^^ the trait `Foo` cannot be made into an object @@ -11,7 +11,7 @@ error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/arbitrary-self-types-not-object-safe.rs:31:13 | LL | fn foo(self: &Rc) -> usize; - | --- method `foo`'s receiver cannot be dispatched on + | --- method `foo`'s `self` parameter cannot be dispatched on ... LL | let x = Rc::new(5usize) as Rc; | ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object From e16ce8007a129fc3829d5ed9c1fed5cd4fb6c2c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 3 Sep 2019 08:07:35 -0700 Subject: [PATCH 20/25] fix error code test --- src/librustc_typeck/error_codes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index a2b1f16ef3de7..093446d28533e 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -2473,7 +2473,7 @@ like in the following example: # trait Trait { # fn foo(&self); # } -impl Trait for Struct { +impl Trait for Foo { fn foo(self: &Bar) {} } ``` From b6f9523dc662ebc23f72356999ae263de9616a2d Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Wed, 4 Sep 2019 13:52:28 +0000 Subject: [PATCH 21/25] Fix doc links in `std::cmp` module These links are rendered in `core::cmp` but not in `std::cmp`. --- src/libcore/cmp.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 607427a85d67a..7ec2295f97e36 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -9,14 +9,22 @@ //! * [`Ord`] and [`PartialOrd`] are traits that allow you to define total and //! partial orderings between values, respectively. Implementing them overloads //! the `<`, `<=`, `>`, and `>=` operators. -//! * [`Ordering`][cmp::Ordering] is an enum returned by the -//! main functions of [`Ord`] and [`PartialOrd`], and describes an ordering. -//! * [`Reverse`][cmp::Reverse] is a struct that allows you to easily reverse -//! an ordering. -//! * [`max`][cmp::max] and [`min`][cmp::min] are functions that build off of -//! [`Ord`] and allow you to find the maximum or minimum of two values. +//! * [`Ordering`] is an enum returned by the main functions of [`Ord`] and +//! [`PartialOrd`], and describes an ordering. +//! * [`Reverse`] is a struct that allows you to easily reverse an ordering. +//! * [`max`] and [`min`] are functions that build off of [`Ord`] and allow you +//! to find the maximum or minimum of two values. //! //! For more details, see the respective documentation of each item in the list. +//! +//! [`Eq`]: trait.Eq.html +//! [`PartialEq`]: trait.PartialEq.html +//! [`Ord`]: trait.Ord.html +//! [`PartialOrd`]: trait.PartialOrd.html +//! [`Ordering`]: enum.Ordering.html +//! [`Reverse`]: struct.Reverse.html +//! [`max`]: fn.max.html +//! [`min`]: fn.min.html #![stable(feature = "rust1", since = "1.0.0")] From 8e067243e450528c9c61f8f0e5f91e3fc7ec707d Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Wed, 4 Sep 2019 23:25:51 +0800 Subject: [PATCH 22/25] fix a few typos in comments --- src/librustc_llvm/build.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 40ddd65164290..62a3757757b80 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -54,7 +54,7 @@ fn main() { // LLVM are compiled the same way, but for us that's typically the case. // // We *want* detect this cross compiling situation by asking llvm-config - // what it's host-target is. If that's not the TARGET, then we're cross + // what its host-target is. If that's not the TARGET, then we're cross // compiling. Unfortunately `llvm-config` seems either be buggy, or we're // misconfiguring it, because the `i686-pc-windows-gnu` build of LLVM will // report itself with a `--host-target` of `x86_64-pc-windows-gnu`. This @@ -62,7 +62,7 @@ fn main() { // havoc ensues. // // In any case, if we're cross compiling, this generally just means that we - // can't trust all the output of llvm-config becaues it might be targeted + // can't trust all the output of llvm-config because it might be targeted // for the host rather than the target. As a result a bunch of blocks below // are gated on `if !is_crossed` let target = env::var("TARGET").expect("TARGET was not set"); @@ -166,7 +166,7 @@ fn main() { let (llvm_kind, llvm_link_arg) = detect_llvm_link(); - // Link in all LLVM libraries, if we're uwring the "wrong" llvm-config then + // Link in all LLVM libraries, if we're using the "wrong" llvm-config then // we don't pick up system libs because unfortunately they're for the host // of llvm-config, not the target that we're attempting to link. let mut cmd = Command::new(&llvm_config); From 843fba3ed18b9aa9e3f6a2bfa030e1df8179503b Mon Sep 17 00:00:00 2001 From: Vitaly _Vi Shukela Date: Mon, 22 Jul 2019 00:54:42 +0300 Subject: [PATCH 23/25] Stabilize checked_duration_since for 1.39.0 Resolves #58402. --- src/libstd/lib.rs | 1 - src/libstd/time.rs | 6 ++---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index c3882bacf87eb..71050b0dcd1f5 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -244,7 +244,6 @@ #![feature(cfg_target_has_atomic)] #![feature(cfg_target_thread_local)] #![feature(char_error_internals)] -#![feature(checked_duration_since)] #![feature(clamp)] #![feature(compiler_builtins_lib)] #![feature(concat_idents)] diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 98371b9ba3d7e..d59085cd44a6f 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -221,7 +221,6 @@ impl Instant { /// # Examples /// /// ```no_run - /// #![feature(checked_duration_since)] /// use std::time::{Duration, Instant}; /// use std::thread::sleep; /// @@ -231,7 +230,7 @@ impl Instant { /// println!("{:?}", new_now.checked_duration_since(now)); /// println!("{:?}", now.checked_duration_since(new_now)); // None /// ``` - #[unstable(feature = "checked_duration_since", issue = "58402")] + #[stable(feature = "checked_duration_since", since = "1.39.0")] pub fn checked_duration_since(&self, earlier: Instant) -> Option { self.0.checked_sub_instant(&earlier.0) } @@ -242,7 +241,6 @@ impl Instant { /// # Examples /// /// ```no_run - /// #![feature(checked_duration_since)] /// use std::time::{Duration, Instant}; /// use std::thread::sleep; /// @@ -252,7 +250,7 @@ impl Instant { /// println!("{:?}", new_now.saturating_duration_since(now)); /// println!("{:?}", now.saturating_duration_since(new_now)); // 0ns /// ``` - #[unstable(feature = "checked_duration_since", issue = "58402")] + #[stable(feature = "checked_duration_since", since = "1.39.0")] pub fn saturating_duration_since(&self, earlier: Instant) -> Duration { self.checked_duration_since(earlier).unwrap_or(Duration::new(0, 0)) } From 5545582a6f6111872cdda54d18f43a7da24661f4 Mon Sep 17 00:00:00 2001 From: Vitaly _Vi Shukela Date: Thu, 5 Sep 2019 01:25:07 +0300 Subject: [PATCH 24/25] Avoid feature name 'checked_duration_since' in a Tidy test --- src/tools/tidy/src/features/tests.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/tidy/src/features/tests.rs b/src/tools/tidy/src/features/tests.rs index fa7a931ec865c..994523ac1abce 100644 --- a/src/tools/tidy/src/features/tests.rs +++ b/src/tools/tidy/src/features/tests.rs @@ -2,8 +2,8 @@ use super::*; #[test] fn test_find_attr_val() { - let s = r#"#[unstable(feature = "checked_duration_since", issue = "58402")]"#; - assert_eq!(find_attr_val(s, "feature"), Some("checked_duration_since")); + let s = r#"#[unstable(feature = "tidy_test_never_used_anywhere_else", issue = "58402")]"#; + assert_eq!(find_attr_val(s, "feature"), Some("tidy_test_never_used_anywhere_else")); assert_eq!(find_attr_val(s, "issue"), Some("58402")); assert_eq!(find_attr_val(s, "since"), None); } From fe2c6b174830f8f1c79c4b34ba7f015cca41ee2c Mon Sep 17 00:00:00 2001 From: Giles Cope Date: Thu, 5 Sep 2019 00:08:52 +0100 Subject: [PATCH 25/25] Opaque type locations in error message for clarity. --- src/librustc/infer/error_reporting/mod.rs | 17 +++++++++++++++-- .../ui/suggestions/opaque-type-error.stderr | 4 ++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 9be73cf3c6d16..267256e9d08d4 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -60,6 +60,7 @@ use crate::ty::error::TypeError; use crate::ty::{self, subst::{Subst, SubstsRef}, Region, Ty, TyCtxt, TypeFoldable}; use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString}; use std::{cmp, fmt}; +use std::borrow::Cow; use syntax_pos::{Pos, Span}; mod note; @@ -1140,8 +1141,20 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &"type", expected, found, - &format!(" ({})", values.expected.sort_string(self.tcx)), - &format!(" ({})", values.found.sort_string(self.tcx)), + &format!(" ({})", + if let ty::Opaque(def_id, _) = values.expected.sty { + Cow::from(format!("opaque type at {}", self.tcx.sess + .source_map().mk_substr_filename(self.tcx.def_span(def_id)))) + } else { + values.expected.sort_string(self.tcx) + }), + &format!(" ({})", + if let ty::Opaque(def_id, _) = values.found.sty { + Cow::from(format!("opaque type at {}", self.tcx.sess + .source_map().mk_substr_filename(self.tcx.def_span(def_id)))) + } else { + values.found.sort_string(self.tcx) + }), ); } (_, false, _) => { diff --git a/src/test/ui/suggestions/opaque-type-error.stderr b/src/test/ui/suggestions/opaque-type-error.stderr index 3c9ea05aeceb2..450cbd4799fdc 100644 --- a/src/test/ui/suggestions/opaque-type-error.stderr +++ b/src/test/ui/suggestions/opaque-type-error.stderr @@ -10,8 +10,8 @@ LL | | thing_two() LL | | }.await | |_____- if and else have incompatible types | - = note: expected type `impl std::future::Future` (opaque type) - found type `impl std::future::Future` (opaque type) + = note: expected type `impl std::future::Future` (opaque type at <$DIR/opaque-type-error.rs:8:19>) + found type `impl std::future::Future` (opaque type at <$DIR/opaque-type-error.rs:12:19>) = note: distinct uses of `impl Trait` result in different opaque types = help: if both `Future`s have the same `Output` type, consider `.await`ing on both of them