From c4c94151321b8018ceb06ccff359109b8fed6bfe Mon Sep 17 00:00:00 2001 From: mejrs <> Date: Mon, 26 Sep 2022 00:55:35 +0200 Subject: [PATCH 1/4] Wrapper suggestions --- .../src/check/method/suggest.rs | 213 ++++++++++++------ compiler/rustc_span/src/symbol.rs | 2 + library/core/src/cell.rs | 1 + library/std/src/thread/local.rs | 1 + src/test/ui/suggestions/inner_type.fixed | 30 +++ src/test/ui/suggestions/inner_type.rs | 30 +++ src/test/ui/suggestions/inner_type.stderr | 51 +++++ src/test/ui/suggestions/inner_type2.rs | 26 +++ src/test/ui/suggestions/inner_type2.stderr | 29 +++ 9 files changed, 316 insertions(+), 67 deletions(-) create mode 100644 src/test/ui/suggestions/inner_type.fixed create mode 100644 src/test/ui/suggestions/inner_type.rs create mode 100644 src/test/ui/suggestions/inner_type.stderr create mode 100644 src/test/ui/suggestions/inner_type2.rs create mode 100644 src/test/ui/suggestions/inner_type2.stderr diff --git a/compiler/rustc_hir_analysis/src/check/method/suggest.rs b/compiler/rustc_hir_analysis/src/check/method/suggest.rs index 0e77ed0a4fe28..1ff2575bcc5dd 100644 --- a/compiler/rustc_hir_analysis/src/check/method/suggest.rs +++ b/compiler/rustc_hir_analysis/src/check/method/suggest.rs @@ -2,6 +2,7 @@ //! found or is otherwise invalid. use crate::check::FnCtxt; +use rustc_ast::ast::Mutability; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{ pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, @@ -30,7 +31,7 @@ use rustc_trait_selection::traits::{ use std::cmp::Ordering; use std::iter; -use super::probe::{IsSuggestion, Mode, ProbeScope}; +use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope}; use super::{CandidateSource, MethodError, NoMatchData}; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -983,7 +984,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_for_field_method(&mut err, source, span, actual, item_name); } - self.check_for_unwrap_self(&mut err, source, span, actual, item_name); + self.check_for_inner_self(&mut err, source, span, actual, item_name); bound_spans.sort(); bound_spans.dedup(); @@ -1395,7 +1396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn check_for_unwrap_self( + fn check_for_inner_self( &self, err: &mut Diagnostic, source: SelfSource<'tcx>, @@ -1408,81 +1409,159 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id)); let ty::Adt(kind, substs) = actual.kind() else { return; }; - if !kind.is_enum() { - return; - } + match kind.adt_kind() { + ty::AdtKind::Enum => { + let matching_variants: Vec<_> = kind + .variants() + .iter() + .flat_map(|variant| { + let [field] = &variant.fields[..] else { return None; }; + let field_ty = field.ty(tcx, substs); + + // Skip `_`, since that'll just lead to ambiguity. + if self.resolve_vars_if_possible(field_ty).is_ty_var() { + return None; + } - let matching_variants: Vec<_> = kind - .variants() - .iter() - .flat_map(|variant| { - let [field] = &variant.fields[..] else { return None; }; - let field_ty = field.ty(tcx, substs); + self.lookup_probe( + span, + item_name, + field_ty, + call_expr, + ProbeScope::AllTraits, + ) + .ok() + .map(|pick| (variant, field, pick)) + }) + .collect(); + + let ret_ty_matches = |diagnostic_item| { + if let Some(ret_ty) = self + .ret_coercion + .as_ref() + .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty())) + && let ty::Adt(kind, _) = ret_ty.kind() + && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did()) + { + true + } else { + false + } + }; - // Skip `_`, since that'll just lead to ambiguity. - if self.resolve_vars_if_possible(field_ty).is_ty_var() { - return None; + match &matching_variants[..] { + [(_, field, pick)] => { + let self_ty = field.ty(tcx, substs); + err.span_note( + tcx.def_span(pick.item.def_id), + &format!("the method `{item_name}` exists on the type `{self_ty}`"), + ); + let (article, kind, variant, question) = + if tcx.is_diagnostic_item(sym::Result, kind.did()) { + ("a", "Result", "Err", ret_ty_matches(sym::Result)) + } else if tcx.is_diagnostic_item(sym::Option, kind.did()) { + ("an", "Option", "None", ret_ty_matches(sym::Option)) + } else { + return; + }; + if question { + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + format!( + "use the `?` operator to extract the `{self_ty}` value, propagating \ + {article} `{kind}::{variant}` value to the caller" + ), + "?", + Applicability::MachineApplicable, + ); + } else { + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + format!( + "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \ + panicking if the value is {article} `{kind}::{variant}`" + ), + ".expect(\"REASON\")", + Applicability::HasPlaceholders, + ); + } + } + // FIXME(compiler-errors): Support suggestions for other matching enum variants + _ => {} } - - self.lookup_probe(span, item_name, field_ty, call_expr, ProbeScope::AllTraits) - .ok() - .map(|pick| (variant, field, pick)) - }) - .collect(); - - let ret_ty_matches = |diagnostic_item| { - if let Some(ret_ty) = self - .ret_coercion - .as_ref() - .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty())) - && let ty::Adt(kind, _) = ret_ty.kind() - && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did()) - { - true - } else { - false } - }; - - match &matching_variants[..] { - [(_, field, pick)] => { - let self_ty = field.ty(tcx, substs); - err.span_note( - tcx.def_span(pick.item.def_id), - &format!("the method `{item_name}` exists on the type `{self_ty}`"), - ); - let (article, kind, variant, question) = - if Some(kind.did()) == tcx.get_diagnostic_item(sym::Result) { - ("a", "Result", "Err", ret_ty_matches(sym::Result)) - } else if Some(kind.did()) == tcx.get_diagnostic_item(sym::Option) { - ("an", "Option", "None", ret_ty_matches(sym::Option)) - } else { - return; - }; - if question { + // Target wrapper types - types that wrap or pretend to wrap another type, + // perhaps this inner type is meant to be called? + ty::AdtKind::Struct | ty::AdtKind::Union => { + let [first] = ***substs else { return; }; + let ty::GenericArgKind::Type(ty) = first.unpack() else { return; }; + let Ok(pick) = self.lookup_probe( + span, + item_name, + ty, + call_expr, + ProbeScope::AllTraits, + ) else { return; }; + + let name = self.ty_to_value_string(actual); + let inner_id = kind.did(); + + if tcx.is_diagnostic_item(sym::LocalKey, inner_id) { + err.help("use `with` or `try_with` to access the contents of threadlocals"); + } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() { + err.help(format!( + "if this `{name}` has been initialized, \ + use one of the `assume_init` methods to access the inner value" + )); + } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) { + match pick.autoref_or_ptr_adjustment { + Some(AutorefOrPtrAdjustment::Autoref { + mutbl: Mutability::Not, .. + }) => { + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + format!( + "use `.borrow()` to borrow the {ty}, \ + panicking if any outstanding mutable borrows exist." + ), + ".borrow()", + Applicability::MaybeIncorrect, + ); + } + Some(AutorefOrPtrAdjustment::Autoref { + mutbl: Mutability::Mut, .. + }) => { + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + format!( + "use `.borrow_mut()` to mutably borrow the {ty}, \ + panicking if any outstanding borrows exist." + ), + ".borrow_mut()", + Applicability::MaybeIncorrect, + ); + } + _ => return, + } + } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) { err.span_suggestion_verbose( expr.span.shrink_to_hi(), format!( - "use the `?` operator to extract the `{self_ty}` value, propagating \ - {article} `{kind}::{variant}` value to the caller" + "use `.lock()` to borrow the {ty}, \ + blocking the current thread until it can be acquired" ), - "?", - Applicability::MachineApplicable, + ".lock().unwrap()", + Applicability::MaybeIncorrect, ); } else { - err.span_suggestion_verbose( - expr.span.shrink_to_hi(), - format!( - "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \ - panicking if the value is {article} `{kind}::{variant}`" - ), - ".expect(\"REASON\")", - Applicability::HasPlaceholders, - ); - } + return; + }; + + err.span_note( + tcx.def_span(pick.item.def_id), + &format!("the method `{item_name}` exists on the type `{ty}`"), + ); } - // FIXME(compiler-errors): Support suggestions for other matching enum variants - _ => {} } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 502ef67fc6767..6101c1c47e380 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -224,6 +224,7 @@ symbols! { Left, LinkedList, LintPass, + LocalKey, Mutex, MutexGuard, N, @@ -266,6 +267,7 @@ symbols! { Rc, Ready, Receiver, + RefCell, Relaxed, Release, Result, diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 1abbb39497a0f..cf7b1b358c940 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -614,6 +614,7 @@ impl Cell<[T; N]> { /// A mutable memory location with dynamically checked borrow rules /// /// See the [module-level documentation](self) for more. +#[rustc_diagnostic_item = "RefCell"] #[stable(feature = "rust1", since = "1.0.0")] pub struct RefCell { borrow: Cell, diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 8aedfc4a6b819..1d728349951bf 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -95,6 +95,7 @@ use crate::fmt; /// [loader lock]: https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices /// [`JoinHandle::join`]: crate::thread::JoinHandle::join /// [`with`]: LocalKey::with +#[rustc_diagnostic_item = "LocalKey"] #[stable(feature = "rust1", since = "1.0.0")] pub struct LocalKey { // This outer `LocalKey` type is what's going to be stored in statics, diff --git a/src/test/ui/suggestions/inner_type.fixed b/src/test/ui/suggestions/inner_type.fixed new file mode 100644 index 0000000000000..f6dc7c4ce1722 --- /dev/null +++ b/src/test/ui/suggestions/inner_type.fixed @@ -0,0 +1,30 @@ +// compile-flags: --edition=2021 +// run-rustfix + +pub struct Struct { + pub p: T, +} + +impl Struct { + pub fn method(&self) {} + + pub fn some_mutable_method(&mut self) {} +} + +fn main() { + let other_item = std::cell::RefCell::new(Struct { p: 42_u32 }); + + other_item.borrow().method(); + //~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599] + //~| HELP use `.borrow()` to borrow the Struct, panicking if any outstanding mutable borrows exist. + + other_item.borrow_mut().some_mutable_method(); + //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599] + //~| HELP use `.borrow_mut()` to mutably borrow the Struct, panicking if any outstanding borrows exist. + + let another_item = std::sync::Mutex::new(Struct { p: 42_u32 }); + + another_item.lock().unwrap().method(); + //~^ ERROR no method named `method` found for struct `Mutex` in the current scope [E0599] + //~| HELP use `.lock()` to borrow the Struct, blocking the current thread until it can be acquired +} \ No newline at end of file diff --git a/src/test/ui/suggestions/inner_type.rs b/src/test/ui/suggestions/inner_type.rs new file mode 100644 index 0000000000000..b42067c047c04 --- /dev/null +++ b/src/test/ui/suggestions/inner_type.rs @@ -0,0 +1,30 @@ +// compile-flags: --edition=2021 +// run-rustfix + +pub struct Struct { + pub p: T, +} + +impl Struct { + pub fn method(&self) {} + + pub fn some_mutable_method(&mut self) {} +} + +fn main() { + let other_item = std::cell::RefCell::new(Struct { p: 42_u32 }); + + other_item.method(); + //~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599] + //~| HELP use `.borrow()` to borrow the Struct, panicking if any outstanding mutable borrows exist. + + other_item.some_mutable_method(); + //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599] + //~| HELP use `.borrow_mut()` to mutably borrow the Struct, panicking if any outstanding borrows exist. + + let another_item = std::sync::Mutex::new(Struct { p: 42_u32 }); + + another_item.method(); + //~^ ERROR no method named `method` found for struct `Mutex` in the current scope [E0599] + //~| HELP use `.lock()` to borrow the Struct, blocking the current thread until it can be acquired +} \ No newline at end of file diff --git a/src/test/ui/suggestions/inner_type.stderr b/src/test/ui/suggestions/inner_type.stderr new file mode 100644 index 0000000000000..f2b25944c8b2d --- /dev/null +++ b/src/test/ui/suggestions/inner_type.stderr @@ -0,0 +1,51 @@ +error[E0599]: no method named `method` found for struct `RefCell` in the current scope + --> $DIR/inner_type.rs:17:16 + | +LL | other_item.method(); + | ^^^^^^ method not found in `RefCell>` + | +note: the method `method` exists on the type `Struct` + --> $DIR/inner_type.rs:9:5 + | +LL | pub fn method(&self) {} + | ^^^^^^^^^^^^^^^^^^^^ +help: use `.borrow()` to borrow the Struct, panicking if any outstanding mutable borrows exist. + | +LL | other_item.borrow().method(); + | +++++++++ + +error[E0599]: no method named `some_mutable_method` found for struct `RefCell` in the current scope + --> $DIR/inner_type.rs:21:16 + | +LL | other_item.some_mutable_method(); + | ^^^^^^^^^^^^^^^^^^^ method not found in `RefCell>` + | +note: the method `some_mutable_method` exists on the type `Struct` + --> $DIR/inner_type.rs:11:5 + | +LL | pub fn some_mutable_method(&mut self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: use `.borrow_mut()` to mutably borrow the Struct, panicking if any outstanding borrows exist. + | +LL | other_item.borrow_mut().some_mutable_method(); + | +++++++++++++ + +error[E0599]: no method named `method` found for struct `Mutex` in the current scope + --> $DIR/inner_type.rs:27:18 + | +LL | another_item.method(); + | ^^^^^^ method not found in `Mutex>` + | +note: the method `method` exists on the type `Struct` + --> $DIR/inner_type.rs:9:5 + | +LL | pub fn method(&self) {} + | ^^^^^^^^^^^^^^^^^^^^ +help: use `.lock()` to borrow the Struct, blocking the current thread until it can be acquired + | +LL | another_item.lock().unwrap().method(); + | ++++++++++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/inner_type2.rs b/src/test/ui/suggestions/inner_type2.rs new file mode 100644 index 0000000000000..694c0adfd06c2 --- /dev/null +++ b/src/test/ui/suggestions/inner_type2.rs @@ -0,0 +1,26 @@ +pub struct Struct { + pub p: T, +} + +impl Struct { + pub fn method(&self) {} + + pub fn some_mutable_method(&mut self) {} +} + +thread_local! { + static STRUCT: Struct = Struct { + p: 42_u32 + }; +} + +fn main() { + STRUCT.method(); + //~^ ERROR no method named `method` found for struct `LocalKey` in the current scope [E0599] + //~| HELP use `with` or `try_with` to access the contents of threadlocals + + let item = std::mem::MaybeUninit::new(Struct { p: 42_u32 }); + item.method(); + //~^ ERROR no method named `method` found for union `MaybeUninit` in the current scope [E0599] + //~| HELP if this `MaybeUninit::>` has been initialized, use one of the `assume_init` methods to access the inner value +} \ No newline at end of file diff --git a/src/test/ui/suggestions/inner_type2.stderr b/src/test/ui/suggestions/inner_type2.stderr new file mode 100644 index 0000000000000..40e7a7ab41e44 --- /dev/null +++ b/src/test/ui/suggestions/inner_type2.stderr @@ -0,0 +1,29 @@ +error[E0599]: no method named `method` found for struct `LocalKey` in the current scope + --> $DIR/inner_type2.rs:18:12 + | +LL | STRUCT.method(); + | ^^^^^^ method not found in `LocalKey>` + | + = help: use `with` or `try_with` to access the contents of threadlocals +note: the method `method` exists on the type `Struct` + --> $DIR/inner_type2.rs:6:5 + | +LL | pub fn method(&self) {} + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0599]: no method named `method` found for union `MaybeUninit` in the current scope + --> $DIR/inner_type2.rs:23:10 + | +LL | item.method(); + | ^^^^^^ method not found in `MaybeUninit>` + | + = help: if this `MaybeUninit::>` has been initialized, use one of the `assume_init` methods to access the inner value +note: the method `method` exists on the type `Struct` + --> $DIR/inner_type2.rs:6:5 + | +LL | pub fn method(&self) {} + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. From f3ac328d584b83bb7f0b4faa0f7a5699151b3ce9 Mon Sep 17 00:00:00 2001 From: mejrs <> Date: Tue, 27 Sep 2022 13:06:31 +0200 Subject: [PATCH 2/4] Address feedback --- .../src/check/method/suggest.rs | 61 ++++++++++++++----- compiler/rustc_span/src/symbol.rs | 1 + library/core/src/cell.rs | 2 +- library/std/src/sync/rwlock.rs | 1 + library/std/src/thread/local.rs | 2 +- src/test/ui/suggestions/inner_type.fixed | 16 ++++- src/test/ui/suggestions/inner_type.rs | 16 ++++- src/test/ui/suggestions/inner_type.stderr | 40 ++++++++++-- src/test/ui/suggestions/inner_type2.rs | 2 +- src/test/ui/suggestions/inner_type2.stderr | 2 +- 10 files changed, 113 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/method/suggest.rs b/compiler/rustc_hir_analysis/src/check/method/suggest.rs index 1ff2575bcc5dd..c43dc8c134dd3 100644 --- a/compiler/rustc_hir_analysis/src/check/method/suggest.rs +++ b/compiler/rustc_hir_analysis/src/check/method/suggest.rs @@ -1428,7 +1428,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_name, field_ty, call_expr, - ProbeScope::AllTraits, + ProbeScope::TraitsInScope, ) .ok() .map(|pick| (variant, field, pick)) @@ -1500,59 +1500,88 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_name, ty, call_expr, - ProbeScope::AllTraits, + ProbeScope::TraitsInScope, ) else { return; }; let name = self.ty_to_value_string(actual); let inner_id = kind.did(); + let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) = + pick.autoref_or_ptr_adjustment + { + Some(mutbl) + } else { + None + }; if tcx.is_diagnostic_item(sym::LocalKey, inner_id) { - err.help("use `with` or `try_with` to access the contents of threadlocals"); + err.help("use `with` or `try_with` to access thread local storage"); } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() { err.help(format!( "if this `{name}` has been initialized, \ use one of the `assume_init` methods to access the inner value" )); } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) { - match pick.autoref_or_ptr_adjustment { - Some(AutorefOrPtrAdjustment::Autoref { - mutbl: Mutability::Not, .. - }) => { + match mutable { + Some(Mutability::Not) => { err.span_suggestion_verbose( expr.span.shrink_to_hi(), format!( - "use `.borrow()` to borrow the {ty}, \ - panicking if any outstanding mutable borrows exist." + "use `.borrow()` to borrow the `{ty}`, \ + panicking if any outstanding mutable borrows exist." ), ".borrow()", Applicability::MaybeIncorrect, ); } - Some(AutorefOrPtrAdjustment::Autoref { - mutbl: Mutability::Mut, .. - }) => { + Some(Mutability::Mut) => { err.span_suggestion_verbose( expr.span.shrink_to_hi(), format!( - "use `.borrow_mut()` to mutably borrow the {ty}, \ - panicking if any outstanding borrows exist." + "use `.borrow_mut()` to mutably borrow the `{ty}`, \ + panicking if any outstanding borrows exist." ), ".borrow_mut()", Applicability::MaybeIncorrect, ); } - _ => return, + None => return, } } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) { err.span_suggestion_verbose( expr.span.shrink_to_hi(), format!( - "use `.lock()` to borrow the {ty}, \ + "use `.lock()` to borrow the `{ty}`, \ blocking the current thread until it can be acquired" ), ".lock().unwrap()", Applicability::MaybeIncorrect, ); + } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) { + match mutable { + Some(Mutability::Not) => { + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + format!( + "use `.read()` to borrow the `{ty}`, \ + blocking the current thread until it can be acquired" + ), + ".read().unwrap()", + Applicability::MaybeIncorrect, + ); + } + Some(Mutability::Mut) => { + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + format!( + "use `.write()` to mutably borrow the `{ty}`, \ + blocking the current thread until it can be acquired" + ), + ".write().unwrap()", + Applicability::MaybeIncorrect, + ); + } + None => return, + } } else { return; }; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6101c1c47e380..67ffc573b990a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -276,6 +276,7 @@ symbols! { Rust, RustcDecodable, RustcEncodable, + RwLock, RwLockReadGuard, RwLockWriteGuard, Send, diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index cf7b1b358c940..288cab1ef3994 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -614,7 +614,7 @@ impl Cell<[T; N]> { /// A mutable memory location with dynamically checked borrow rules /// /// See the [module-level documentation](self) for more. -#[rustc_diagnostic_item = "RefCell"] +#[cfg_attr(not(test), rustc_diagnostic_item = "RefCell")] #[stable(feature = "rust1", since = "1.0.0")] pub struct RefCell { borrow: Cell, diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index 9ab781561e9b1..ee2c79b6669b8 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -76,6 +76,7 @@ use crate::sys_common::rwlock as sys; /// /// [`Mutex`]: super::Mutex #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "RwLock")] pub struct RwLock { inner: sys::MovableRwLock, poison: poison::Flag, diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 1d728349951bf..ffd17dc99093a 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -95,7 +95,7 @@ use crate::fmt; /// [loader lock]: https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices /// [`JoinHandle::join`]: crate::thread::JoinHandle::join /// [`with`]: LocalKey::with -#[rustc_diagnostic_item = "LocalKey"] +#[cfg_attr(not(test), rustc_diagnostic_item = "LocalKey")] #[stable(feature = "rust1", since = "1.0.0")] pub struct LocalKey { // This outer `LocalKey` type is what's going to be stored in statics, diff --git a/src/test/ui/suggestions/inner_type.fixed b/src/test/ui/suggestions/inner_type.fixed index f6dc7c4ce1722..327bf7caa7257 100644 --- a/src/test/ui/suggestions/inner_type.fixed +++ b/src/test/ui/suggestions/inner_type.fixed @@ -16,15 +16,25 @@ fn main() { other_item.borrow().method(); //~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599] - //~| HELP use `.borrow()` to borrow the Struct, panicking if any outstanding mutable borrows exist. + //~| HELP use `.borrow()` to borrow the `Struct`, panicking if any outstanding mutable borrows exist. other_item.borrow_mut().some_mutable_method(); //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599] - //~| HELP use `.borrow_mut()` to mutably borrow the Struct, panicking if any outstanding borrows exist. + //~| HELP use `.borrow_mut()` to mutably borrow the `Struct`, panicking if any outstanding borrows exist. let another_item = std::sync::Mutex::new(Struct { p: 42_u32 }); another_item.lock().unwrap().method(); //~^ ERROR no method named `method` found for struct `Mutex` in the current scope [E0599] - //~| HELP use `.lock()` to borrow the Struct, blocking the current thread until it can be acquired + //~| HELP use `.lock()` to borrow the `Struct`, blocking the current thread until it can be acquired + + let another_item = std::sync::RwLock::new(Struct { p: 42_u32 }); + + another_item.read().unwrap().method(); + //~^ ERROR no method named `method` found for struct `RwLock` in the current scope [E0599] + //~| HELP use `.read()` to borrow the `Struct`, blocking the current thread until it can be acquired + + another_item.write().unwrap().some_mutable_method(); + //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599] + //~| HELP use `.write()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired } \ No newline at end of file diff --git a/src/test/ui/suggestions/inner_type.rs b/src/test/ui/suggestions/inner_type.rs index b42067c047c04..a8c1c5d386a1e 100644 --- a/src/test/ui/suggestions/inner_type.rs +++ b/src/test/ui/suggestions/inner_type.rs @@ -16,15 +16,25 @@ fn main() { other_item.method(); //~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599] - //~| HELP use `.borrow()` to borrow the Struct, panicking if any outstanding mutable borrows exist. + //~| HELP use `.borrow()` to borrow the `Struct`, panicking if any outstanding mutable borrows exist. other_item.some_mutable_method(); //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599] - //~| HELP use `.borrow_mut()` to mutably borrow the Struct, panicking if any outstanding borrows exist. + //~| HELP use `.borrow_mut()` to mutably borrow the `Struct`, panicking if any outstanding borrows exist. let another_item = std::sync::Mutex::new(Struct { p: 42_u32 }); another_item.method(); //~^ ERROR no method named `method` found for struct `Mutex` in the current scope [E0599] - //~| HELP use `.lock()` to borrow the Struct, blocking the current thread until it can be acquired + //~| HELP use `.lock()` to borrow the `Struct`, blocking the current thread until it can be acquired + + let another_item = std::sync::RwLock::new(Struct { p: 42_u32 }); + + another_item.method(); + //~^ ERROR no method named `method` found for struct `RwLock` in the current scope [E0599] + //~| HELP use `.read()` to borrow the `Struct`, blocking the current thread until it can be acquired + + another_item.some_mutable_method(); + //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599] + //~| HELP use `.write()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired } \ No newline at end of file diff --git a/src/test/ui/suggestions/inner_type.stderr b/src/test/ui/suggestions/inner_type.stderr index f2b25944c8b2d..00d52f0f1d33a 100644 --- a/src/test/ui/suggestions/inner_type.stderr +++ b/src/test/ui/suggestions/inner_type.stderr @@ -9,7 +9,7 @@ note: the method `method` exists on the type `Struct` | LL | pub fn method(&self) {} | ^^^^^^^^^^^^^^^^^^^^ -help: use `.borrow()` to borrow the Struct, panicking if any outstanding mutable borrows exist. +help: use `.borrow()` to borrow the `Struct`, panicking if any outstanding mutable borrows exist. | LL | other_item.borrow().method(); | +++++++++ @@ -25,7 +25,7 @@ note: the method `some_mutable_method` exists on the type `Struct` | LL | pub fn some_mutable_method(&mut self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: use `.borrow_mut()` to mutably borrow the Struct, panicking if any outstanding borrows exist. +help: use `.borrow_mut()` to mutably borrow the `Struct`, panicking if any outstanding borrows exist. | LL | other_item.borrow_mut().some_mutable_method(); | +++++++++++++ @@ -41,11 +41,43 @@ note: the method `method` exists on the type `Struct` | LL | pub fn method(&self) {} | ^^^^^^^^^^^^^^^^^^^^ -help: use `.lock()` to borrow the Struct, blocking the current thread until it can be acquired +help: use `.lock()` to borrow the `Struct`, blocking the current thread until it can be acquired | LL | another_item.lock().unwrap().method(); | ++++++++++++++++ -error: aborting due to 3 previous errors +error[E0599]: no method named `method` found for struct `RwLock` in the current scope + --> $DIR/inner_type.rs:33:18 + | +LL | another_item.method(); + | ^^^^^^ method not found in `RwLock>` + | +note: the method `method` exists on the type `Struct` + --> $DIR/inner_type.rs:9:5 + | +LL | pub fn method(&self) {} + | ^^^^^^^^^^^^^^^^^^^^ +help: use `.read()` to borrow the `Struct`, blocking the current thread until it can be acquired + | +LL | another_item.read().unwrap().method(); + | ++++++++++++++++ + +error[E0599]: no method named `some_mutable_method` found for struct `RwLock` in the current scope + --> $DIR/inner_type.rs:37:18 + | +LL | another_item.some_mutable_method(); + | ^^^^^^^^^^^^^^^^^^^ method not found in `RwLock>` + | +note: the method `some_mutable_method` exists on the type `Struct` + --> $DIR/inner_type.rs:11:5 + | +LL | pub fn some_mutable_method(&mut self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: use `.write()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired + | +LL | another_item.write().unwrap().some_mutable_method(); + | +++++++++++++++++ + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/inner_type2.rs b/src/test/ui/suggestions/inner_type2.rs index 694c0adfd06c2..8dea8100c289c 100644 --- a/src/test/ui/suggestions/inner_type2.rs +++ b/src/test/ui/suggestions/inner_type2.rs @@ -17,7 +17,7 @@ thread_local! { fn main() { STRUCT.method(); //~^ ERROR no method named `method` found for struct `LocalKey` in the current scope [E0599] - //~| HELP use `with` or `try_with` to access the contents of threadlocals + //~| HELP use `with` or `try_with` to access thread local storage let item = std::mem::MaybeUninit::new(Struct { p: 42_u32 }); item.method(); diff --git a/src/test/ui/suggestions/inner_type2.stderr b/src/test/ui/suggestions/inner_type2.stderr index 40e7a7ab41e44..eddfd9d63409d 100644 --- a/src/test/ui/suggestions/inner_type2.stderr +++ b/src/test/ui/suggestions/inner_type2.stderr @@ -4,7 +4,7 @@ error[E0599]: no method named `method` found for struct `LocalKey` in the curren LL | STRUCT.method(); | ^^^^^^ method not found in `LocalKey>` | - = help: use `with` or `try_with` to access the contents of threadlocals + = help: use `with` or `try_with` to access thread local storage note: the method `method` exists on the type `Struct` --> $DIR/inner_type2.rs:6:5 | From e9224b37968f8bf56c0bbac206312ef84dad3b74 Mon Sep 17 00:00:00 2001 From: mejrs <> Date: Tue, 27 Sep 2022 23:12:52 +0200 Subject: [PATCH 3/4] Add newline --- src/test/ui/suggestions/inner_type.fixed | 2 +- src/test/ui/suggestions/inner_type.rs | 2 +- src/test/ui/suggestions/inner_type2.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/ui/suggestions/inner_type.fixed b/src/test/ui/suggestions/inner_type.fixed index 327bf7caa7257..811b959b8c04d 100644 --- a/src/test/ui/suggestions/inner_type.fixed +++ b/src/test/ui/suggestions/inner_type.fixed @@ -37,4 +37,4 @@ fn main() { another_item.write().unwrap().some_mutable_method(); //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599] //~| HELP use `.write()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired -} \ No newline at end of file +} diff --git a/src/test/ui/suggestions/inner_type.rs b/src/test/ui/suggestions/inner_type.rs index a8c1c5d386a1e..96c797a6d81d7 100644 --- a/src/test/ui/suggestions/inner_type.rs +++ b/src/test/ui/suggestions/inner_type.rs @@ -37,4 +37,4 @@ fn main() { another_item.some_mutable_method(); //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599] //~| HELP use `.write()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired -} \ No newline at end of file +} diff --git a/src/test/ui/suggestions/inner_type2.rs b/src/test/ui/suggestions/inner_type2.rs index 8dea8100c289c..c56ea7c030d8e 100644 --- a/src/test/ui/suggestions/inner_type2.rs +++ b/src/test/ui/suggestions/inner_type2.rs @@ -23,4 +23,4 @@ fn main() { item.method(); //~^ ERROR no method named `method` found for union `MaybeUninit` in the current scope [E0599] //~| HELP if this `MaybeUninit::>` has been initialized, use one of the `assume_init` methods to access the inner value -} \ No newline at end of file +} From 4ff83cee95cf73708cc5455f4ecce5eb1c21ffc6 Mon Sep 17 00:00:00 2001 From: mejrs <> Date: Wed, 28 Sep 2022 02:36:58 +0200 Subject: [PATCH 4/4] Deduplicate some logic --- .../src/check/method/suggest.rs | 74 +++++++------------ src/test/ui/suggestions/inner_type.fixed | 10 +-- src/test/ui/suggestions/inner_type.rs | 10 +-- src/test/ui/suggestions/inner_type.stderr | 10 +-- 4 files changed, 42 insertions(+), 62 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/method/suggest.rs b/compiler/rustc_hir_analysis/src/check/method/suggest.rs index c43dc8c134dd3..0e82e4956c7c1 100644 --- a/compiler/rustc_hir_analysis/src/check/method/suggest.rs +++ b/compiler/rustc_hir_analysis/src/check/method/suggest.rs @@ -1521,67 +1521,47 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { use one of the `assume_init` methods to access the inner value" )); } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) { - match mutable { - Some(Mutability::Not) => { - err.span_suggestion_verbose( - expr.span.shrink_to_hi(), - format!( - "use `.borrow()` to borrow the `{ty}`, \ - panicking if any outstanding mutable borrows exist." - ), - ".borrow()", - Applicability::MaybeIncorrect, - ); - } + let (suggestion, borrow_kind, panic_if) = match mutable { + Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"), Some(Mutability::Mut) => { - err.span_suggestion_verbose( - expr.span.shrink_to_hi(), - format!( - "use `.borrow_mut()` to mutably borrow the `{ty}`, \ - panicking if any outstanding borrows exist." - ), - ".borrow_mut()", - Applicability::MaybeIncorrect, - ); + (".borrow_mut()", "mutably borrow", "any borrows exist") } None => return, - } + }; + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + format!( + "use `{suggestion}` to {borrow_kind} the `{ty}`, \ + panicking if {panic_if}" + ), + suggestion, + Applicability::MaybeIncorrect, + ); } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) { err.span_suggestion_verbose( expr.span.shrink_to_hi(), format!( - "use `.lock()` to borrow the `{ty}`, \ + "use `.lock().unwrap()` to borrow the `{ty}`, \ blocking the current thread until it can be acquired" ), ".lock().unwrap()", Applicability::MaybeIncorrect, ); } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) { - match mutable { - Some(Mutability::Not) => { - err.span_suggestion_verbose( - expr.span.shrink_to_hi(), - format!( - "use `.read()` to borrow the `{ty}`, \ - blocking the current thread until it can be acquired" - ), - ".read().unwrap()", - Applicability::MaybeIncorrect, - ); - } - Some(Mutability::Mut) => { - err.span_suggestion_verbose( - expr.span.shrink_to_hi(), - format!( - "use `.write()` to mutably borrow the `{ty}`, \ - blocking the current thread until it can be acquired" - ), - ".write().unwrap()", - Applicability::MaybeIncorrect, - ); - } + let (suggestion, borrow_kind) = match mutable { + Some(Mutability::Not) => (".read().unwrap()", "borrow"), + Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"), None => return, - } + }; + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + format!( + "use `{suggestion}` to {borrow_kind} the `{ty}`, \ + blocking the current thread until it can be acquired" + ), + suggestion, + Applicability::MaybeIncorrect, + ); } else { return; }; diff --git a/src/test/ui/suggestions/inner_type.fixed b/src/test/ui/suggestions/inner_type.fixed index 811b959b8c04d..7af7391ca851d 100644 --- a/src/test/ui/suggestions/inner_type.fixed +++ b/src/test/ui/suggestions/inner_type.fixed @@ -16,25 +16,25 @@ fn main() { other_item.borrow().method(); //~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599] - //~| HELP use `.borrow()` to borrow the `Struct`, panicking if any outstanding mutable borrows exist. + //~| HELP use `.borrow()` to borrow the `Struct`, panicking if a mutable borrow exists other_item.borrow_mut().some_mutable_method(); //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599] - //~| HELP use `.borrow_mut()` to mutably borrow the `Struct`, panicking if any outstanding borrows exist. + //~| HELP .borrow_mut()` to mutably borrow the `Struct`, panicking if any borrows exist let another_item = std::sync::Mutex::new(Struct { p: 42_u32 }); another_item.lock().unwrap().method(); //~^ ERROR no method named `method` found for struct `Mutex` in the current scope [E0599] - //~| HELP use `.lock()` to borrow the `Struct`, blocking the current thread until it can be acquired + //~| HELP use `.lock().unwrap()` to borrow the `Struct`, blocking the current thread until it can be acquired let another_item = std::sync::RwLock::new(Struct { p: 42_u32 }); another_item.read().unwrap().method(); //~^ ERROR no method named `method` found for struct `RwLock` in the current scope [E0599] - //~| HELP use `.read()` to borrow the `Struct`, blocking the current thread until it can be acquired + //~| HELP use `.read().unwrap()` to borrow the `Struct`, blocking the current thread until it can be acquired another_item.write().unwrap().some_mutable_method(); //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599] - //~| HELP use `.write()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired + //~| HELP use `.write().unwrap()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired } diff --git a/src/test/ui/suggestions/inner_type.rs b/src/test/ui/suggestions/inner_type.rs index 96c797a6d81d7..4aca50716258a 100644 --- a/src/test/ui/suggestions/inner_type.rs +++ b/src/test/ui/suggestions/inner_type.rs @@ -16,25 +16,25 @@ fn main() { other_item.method(); //~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599] - //~| HELP use `.borrow()` to borrow the `Struct`, panicking if any outstanding mutable borrows exist. + //~| HELP use `.borrow()` to borrow the `Struct`, panicking if a mutable borrow exists other_item.some_mutable_method(); //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599] - //~| HELP use `.borrow_mut()` to mutably borrow the `Struct`, panicking if any outstanding borrows exist. + //~| HELP .borrow_mut()` to mutably borrow the `Struct`, panicking if any borrows exist let another_item = std::sync::Mutex::new(Struct { p: 42_u32 }); another_item.method(); //~^ ERROR no method named `method` found for struct `Mutex` in the current scope [E0599] - //~| HELP use `.lock()` to borrow the `Struct`, blocking the current thread until it can be acquired + //~| HELP use `.lock().unwrap()` to borrow the `Struct`, blocking the current thread until it can be acquired let another_item = std::sync::RwLock::new(Struct { p: 42_u32 }); another_item.method(); //~^ ERROR no method named `method` found for struct `RwLock` in the current scope [E0599] - //~| HELP use `.read()` to borrow the `Struct`, blocking the current thread until it can be acquired + //~| HELP use `.read().unwrap()` to borrow the `Struct`, blocking the current thread until it can be acquired another_item.some_mutable_method(); //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599] - //~| HELP use `.write()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired + //~| HELP use `.write().unwrap()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired } diff --git a/src/test/ui/suggestions/inner_type.stderr b/src/test/ui/suggestions/inner_type.stderr index 00d52f0f1d33a..5ac3d04f10414 100644 --- a/src/test/ui/suggestions/inner_type.stderr +++ b/src/test/ui/suggestions/inner_type.stderr @@ -9,7 +9,7 @@ note: the method `method` exists on the type `Struct` | LL | pub fn method(&self) {} | ^^^^^^^^^^^^^^^^^^^^ -help: use `.borrow()` to borrow the `Struct`, panicking if any outstanding mutable borrows exist. +help: use `.borrow()` to borrow the `Struct`, panicking if a mutable borrow exists | LL | other_item.borrow().method(); | +++++++++ @@ -25,7 +25,7 @@ note: the method `some_mutable_method` exists on the type `Struct` | LL | pub fn some_mutable_method(&mut self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: use `.borrow_mut()` to mutably borrow the `Struct`, panicking if any outstanding borrows exist. +help: use `.borrow_mut()` to mutably borrow the `Struct`, panicking if any borrows exist | LL | other_item.borrow_mut().some_mutable_method(); | +++++++++++++ @@ -41,7 +41,7 @@ note: the method `method` exists on the type `Struct` | LL | pub fn method(&self) {} | ^^^^^^^^^^^^^^^^^^^^ -help: use `.lock()` to borrow the `Struct`, blocking the current thread until it can be acquired +help: use `.lock().unwrap()` to borrow the `Struct`, blocking the current thread until it can be acquired | LL | another_item.lock().unwrap().method(); | ++++++++++++++++ @@ -57,7 +57,7 @@ note: the method `method` exists on the type `Struct` | LL | pub fn method(&self) {} | ^^^^^^^^^^^^^^^^^^^^ -help: use `.read()` to borrow the `Struct`, blocking the current thread until it can be acquired +help: use `.read().unwrap()` to borrow the `Struct`, blocking the current thread until it can be acquired | LL | another_item.read().unwrap().method(); | ++++++++++++++++ @@ -73,7 +73,7 @@ note: the method `some_mutable_method` exists on the type `Struct` | LL | pub fn some_mutable_method(&mut self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: use `.write()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired +help: use `.write().unwrap()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired | LL | another_item.write().unwrap().some_mutable_method(); | +++++++++++++++++