From e5b3c7ef1439fa946b3ba49a3bbbadc34d801a84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 7 Feb 2024 02:35:49 +0000 Subject: [PATCH] Add `rustc_confusables` annotations to some stdlib APIs Help with common API confusion, like asking for `push` when the data structure really has `append`. ``` error[E0599]: no method named `size` found for struct `Vec<{integer}>` in the current scope --> $DIR/rustc_confusables_std_cases.rs:17:7 | LL | x.size(); | ^^^^ | help: you might have meant to use `len` | LL | x.len(); | ~~~ help: there is a method with a similar name | LL | x.resize(); | ~~~~~~ ``` #59450 --- .../rustc_hir_typeck/src/method/suggest.rs | 59 ++++++++------- .../alloc/src/collections/binary_heap/mod.rs | 2 + library/alloc/src/collections/btree/map.rs | 3 + .../alloc/src/collections/btree/map/entry.rs | 3 + library/alloc/src/collections/btree/set.rs | 5 ++ library/alloc/src/collections/linked_list.rs | 10 +++ .../alloc/src/collections/vec_deque/mod.rs | 5 ++ library/alloc/src/string.rs | 3 + library/alloc/src/vec/mod.rs | 3 + library/core/src/cell.rs | 2 + library/proc_macro/src/bridge/scoped_cell.rs | 1 + library/std/src/collections/hash/map.rs | 2 + library/std/src/collections/hash/set.rs | 3 + library/std/src/ffi/os_str.rs | 1 + library/std/src/path.rs | 1 + library/std/src/thread/local.rs | 2 + tests/ui/attributes/rustc_confusables.rs | 2 +- tests/ui/attributes/rustc_confusables.stderr | 7 +- .../attributes/rustc_confusables_std_cases.rs | 21 ++++++ .../rustc_confusables_std_cases.stderr | 74 +++++++++++++++++++ 20 files changed, 180 insertions(+), 29 deletions(-) create mode 100644 tests/ui/attributes/rustc_confusables_std_cases.rs create mode 100644 tests/ui/attributes/rustc_confusables_std_cases.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index cc111af5d8f..b7ca5413243 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1209,32 +1209,6 @@ pub fn report_no_match_method_error( err.note(format!( "the {item_kind} was found for\n{type_candidates}{additional_types}" )); - } else { - 'outer: for inherent_impl_did in - self.tcx.inherent_impls(adt.did()).into_iter().flatten() - { - for inherent_method in - self.tcx.associated_items(inherent_impl_did).in_definition_order() - { - if let Some(attr) = self - .tcx - .get_attr(inherent_method.def_id, sym::rustc_confusables) - && let Some(candidates) = parse_confusables(attr) - && candidates.contains(&item_name.name) - { - err.span_suggestion_verbose( - item_name.span, - format!( - "you might have meant to use `{}`", - inherent_method.name - ), - inherent_method.name, - Applicability::MaybeIncorrect, - ); - break 'outer; - } - } - } } } } else { @@ -1260,6 +1234,34 @@ pub fn report_no_match_method_error( label_span_not_found(&mut err); } + let mut confusable_suggested = None; + if let ty::Adt(adt, _) = rcvr_ty.kind() { + 'outer: for inherent_impl_did in + self.tcx.inherent_impls(adt.did()).into_iter().flatten() + { + for inherent_method in + self.tcx.associated_items(inherent_impl_did).in_definition_order() + { + if let Some(attr) = + self.tcx.get_attr(inherent_method.def_id, sym::rustc_confusables) + && let Some(candidates) = parse_confusables(attr) + && candidates.contains(&item_name.name) + { + { + err.span_suggestion_verbose( + item_name.span, + format!("you might have meant to use `{}`", inherent_method.name), + inherent_method.name, + Applicability::MaybeIncorrect, + ); + confusable_suggested = Some(inherent_method.name); + break 'outer; + } + } + } + } + } + // Don't suggest (for example) `expr.field.clone()` if `expr.clone()` // can't be called due to `typeof(expr): Clone` not holding. if unsatisfied_predicates.is_empty() { @@ -1361,7 +1363,10 @@ pub fn report_no_match_method_error( } else if let Some(similar_candidate) = similar_candidate { // Don't emit a suggestion if we found an actual method // that had unsatisfied trait bounds - if unsatisfied_predicates.is_empty() { + if unsatisfied_predicates.is_empty() + // ...or if we already suggested that name because of `rustc_confusable` annotation. + && Some(similar_candidate.name) != confusable_suggested + { let def_kind = similar_candidate.kind.as_def_kind(); // Methods are defined within the context of a struct and their first parameter is always self, // which represents the instance of the struct the method is being called on diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index c89a3806280..83b2678f7f5 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -607,6 +607,7 @@ pub fn pop(&mut self) -> Option { /// occurs when capacity is exhausted and needs a resize. The resize cost /// has been amortized in the previous figures. #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("append", "put")] pub fn push(&mut self, item: T) { let old_len = self.len(); self.data.push(item); @@ -1264,6 +1265,7 @@ pub fn allocator(&self) -> &A { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("length", "size")] pub fn len(&self) -> usize { self.data.len() } diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index addcc71a2d4..80be4ee57c5 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -979,6 +979,7 @@ pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> /// assert_eq!(map[&37], "c"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("push", "put", "set")] pub fn insert(&mut self, key: K, value: V) -> Option where K: Ord, @@ -1041,6 +1042,7 @@ pub fn try_insert(&mut self, key: K, value: V) -> Result<&mut V, OccupiedError<' /// assert_eq!(map.remove(&1), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("delete", "take")] pub fn remove(&mut self, key: &Q) -> Option where K: Borrow + Ord, @@ -2495,6 +2497,7 @@ pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> { issue = "71835", implied_by = "const_btree_new" )] + #[rustc_confusables("length", "size")] pub const fn len(&self) -> usize { self.length } diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs index e9366eec9ce..0a894258f46 100644 --- a/library/alloc/src/collections/btree/map/entry.rs +++ b/library/alloc/src/collections/btree/map/entry.rs @@ -347,6 +347,7 @@ pub fn into_key(self) -> K { /// assert_eq!(map["poneyland"], 37); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("push", "put")] pub fn insert(mut self, value: V) -> &'a mut V { let out_ptr = match self.handle { None => { @@ -524,6 +525,7 @@ pub fn into_mut(self) -> &'a mut V { /// assert_eq!(map["poneyland"], 15); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("push", "put")] pub fn insert(&mut self, value: V) -> V { mem::replace(self.get_mut(), value) } @@ -546,6 +548,7 @@ pub fn insert(&mut self, value: V) -> V { /// // println!("{}", map["poneyland"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("delete", "take")] pub fn remove(self) -> V { self.remove_kv().1 } diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 0e03551286e..ed91ae1a66e 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -790,6 +790,7 @@ pub fn is_superset(&self, other: &BTreeSet) -> bool /// ``` #[must_use] #[stable(feature = "map_first_last", since = "1.66.0")] + #[rustc_confusables("front")] pub fn first(&self) -> Option<&T> where T: Ord, @@ -816,6 +817,7 @@ pub fn first(&self) -> Option<&T> /// ``` #[must_use] #[stable(feature = "map_first_last", since = "1.66.0")] + #[rustc_confusables("back")] pub fn last(&self) -> Option<&T> where T: Ord, @@ -896,6 +898,7 @@ pub fn pop_last(&mut self) -> Option /// assert_eq!(set.len(), 1); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("push", "put")] pub fn insert(&mut self, value: T) -> bool where T: Ord, @@ -919,6 +922,7 @@ pub fn insert(&mut self, value: T) -> bool /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 10); /// ``` #[stable(feature = "set_recovery", since = "1.9.0")] + #[rustc_confusables("swap")] pub fn replace(&mut self, value: T) -> Option where T: Ord, @@ -1152,6 +1156,7 @@ pub fn iter(&self) -> Iter<'_, T> { issue = "71835", implied_by = "const_btree_new" )] + #[rustc_confusables("length", "size")] pub const fn len(&self) -> usize { self.map.len() } diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 9e109feb3d3..6dfb82ac807 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -656,6 +656,7 @@ pub fn is_empty(&self) -> bool { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("length", "size")] pub fn len(&self) -> usize { self.len } @@ -740,6 +741,7 @@ pub fn contains(&self, x: &T) -> bool #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("first")] pub fn front(&self) -> Option<&T> { unsafe { self.head.as_ref().map(|node| &node.as_ref().element) } } @@ -890,6 +892,7 @@ pub fn pop_front(&mut self) -> Option { /// assert_eq!(3, *d.back().unwrap()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("push", "append")] pub fn push_back(&mut self, elt: T) { let node = Box::new_in(Node::new(elt), &self.alloc); let node_ptr = NonNull::from(Box::leak(node)); @@ -1004,6 +1007,7 @@ pub fn split_off(&mut self, at: usize) -> LinkedList /// assert_eq!(d.remove(0), 1); /// ``` #[unstable(feature = "linked_list_remove", issue = "69210")] + #[rustc_confusables("delete", "take")] pub fn remove(&mut self, at: usize) -> T { let len = self.len(); assert!(at < len, "Cannot remove at an index outside of the list bounds"); @@ -1478,6 +1482,7 @@ pub fn peek_prev(&self) -> Option<&'a T> { /// or None if the list is empty. #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] + #[rustc_confusables("first")] pub fn front(&self) -> Option<&'a T> { self.list.front() } @@ -1486,6 +1491,7 @@ pub fn front(&self) -> Option<&'a T> { /// or None if the list is empty. #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] + #[rustc_confusables("last")] pub fn back(&self) -> Option<&'a T> { self.list.back() } @@ -1788,6 +1794,7 @@ pub fn push_front(&mut self, elt: T) { /// /// This operation should compute in *O*(1) time. #[unstable(feature = "linked_list_cursors", issue = "58533")] + #[rustc_confusables("push", "append")] pub fn push_back(&mut self, elt: T) { // Safety: We know that `push_back` does not change the position in // memory of other nodes. This ensures that `self.current` remains @@ -1834,6 +1841,7 @@ pub fn pop_front(&mut self) -> Option { /// /// This operation should compute in *O*(1) time. #[unstable(feature = "linked_list_cursors", issue = "58533")] + #[rustc_confusables("pop")] pub fn pop_back(&mut self) -> Option { if self.list.is_empty() { None @@ -1854,6 +1862,7 @@ pub fn pop_back(&mut self) -> Option { /// or None if the list is empty. #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] + #[rustc_confusables("first")] pub fn front(&self) -> Option<&T> { self.list.front() } @@ -1870,6 +1879,7 @@ pub fn front_mut(&mut self) -> Option<&mut T> { /// or None if the list is empty. #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] + #[rustc_confusables("last")] pub fn back(&self) -> Option<&T> { self.list.back() } diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index bcba6525fda..c35bab5ef66 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -1209,6 +1209,7 @@ pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) { /// assert_eq!(deque.len(), 1); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("length", "size")] pub fn len(&self) -> usize { self.len } @@ -1491,6 +1492,7 @@ pub fn contains(&self, x: &T) -> bool /// assert_eq!(d.front(), Some(&1)); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("first")] pub fn front(&self) -> Option<&T> { self.get(0) } @@ -1535,6 +1537,7 @@ pub fn front_mut(&mut self) -> Option<&mut T> { /// assert_eq!(d.back(), Some(&2)); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("last")] pub fn back(&self) -> Option<&T> { self.get(self.len.wrapping_sub(1)) } @@ -1654,6 +1657,7 @@ pub fn push_front(&mut self, value: T) { /// assert_eq!(3, *buf.back().unwrap()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("push", "put", "append")] pub fn push_back(&mut self, value: T) { if self.is_full() { self.grow(); @@ -1813,6 +1817,7 @@ pub fn insert(&mut self, index: usize, value: T) { /// assert_eq!(buf, [1, 3]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("delete", "take")] pub fn remove(&mut self, index: usize) -> Option { if self.len <= index { return None; diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 4d6968157de..6ad783bee27 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -1445,6 +1445,7 @@ pub fn pop(&mut self) -> Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("delete", "take")] pub fn remove(&mut self, idx: usize) -> char { let ch = match self[idx..].chars().next() { Some(ch) => ch, @@ -1639,6 +1640,7 @@ fn drop(&mut self) { #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("set")] pub fn insert(&mut self, idx: usize, ch: char) { assert!(self.is_char_boundary(idx)); let mut bits = [0; 4]; @@ -1738,6 +1740,7 @@ pub unsafe fn as_mut_vec(&mut self) -> &mut Vec { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("length", "size")] pub fn len(&self) -> usize { self.vec.len() } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 08e3cdedc66..b59699219eb 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1554,6 +1554,7 @@ fn assert_failed(index: usize, len: usize) -> ! { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[track_caller] + #[rustc_confusables("delete", "take")] pub fn remove(&mut self, index: usize) -> T { #[cold] #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] @@ -1915,6 +1916,7 @@ fn drop(&mut self) { #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("push_back", "put", "append")] pub fn push(&mut self, value: T) { // This will panic or abort if we would allocate > isize::MAX bytes // or if the length increment would overflow for zero-sized types. @@ -2141,6 +2143,7 @@ pub fn clear(&mut self) { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("length", "size")] pub fn len(&self) -> usize { self.len } diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index c77fa371cc7..19b05448c87 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -471,6 +471,7 @@ fn is_nonoverlapping(src: *const T, dst: *const T) -> bool { /// ``` #[inline] #[stable(feature = "move_cell", since = "1.17.0")] + #[rustc_confusables("swap")] pub fn replace(&self, val: T) -> T { // SAFETY: This can cause data races if called from a separate thread, // but `Cell` is `!Sync` so this won't happen. @@ -862,6 +863,7 @@ pub const fn into_inner(self) -> T { #[inline] #[stable(feature = "refcell_replace", since = "1.24.0")] #[track_caller] + #[rustc_confusables("swap")] pub fn replace(&self, t: T) -> T { mem::replace(&mut *self.borrow_mut(), t) } diff --git a/library/proc_macro/src/bridge/scoped_cell.rs b/library/proc_macro/src/bridge/scoped_cell.rs index 53eae1ebdb0..a8b34143908 100644 --- a/library/proc_macro/src/bridge/scoped_cell.rs +++ b/library/proc_macro/src/bridge/scoped_cell.rs @@ -25,6 +25,7 @@ pub const fn new(value: >::Out) -> Self { /// running `f`, which gets the old value, mutably. /// The old value will be restored after `f` exits, even /// by panic, including modifications made to it by `f`. + #[rustc_confusables("swap")] pub fn replace<'a, R>( &self, replacement: >::Out, diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 0d4c1fa05cc..627befb63a1 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -1101,6 +1101,7 @@ pub fn get_mut(&mut self, k: &Q) -> Option<&mut V> /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("push", "append")] pub fn insert(&mut self, k: K, v: V) -> Option { self.base.insert(k, v) } @@ -1155,6 +1156,7 @@ pub fn try_insert(&mut self, key: K, value: V) -> Result<&mut V, OccupiedError<' /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("delete", "take")] pub fn remove(&mut self, k: &Q) -> Option where K: Borrow, diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index dcb2fa0f771..371201ff44c 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -885,6 +885,7 @@ pub fn is_superset(&self, other: &HashSet) -> bool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("push", "append")] pub fn insert(&mut self, value: T) -> bool { self.base.insert(value) } @@ -906,6 +907,7 @@ pub fn insert(&mut self, value: T) -> bool { /// ``` #[inline] #[stable(feature = "set_recovery", since = "1.9.0")] + #[rustc_confusables("swap")] pub fn replace(&mut self, value: T) -> Option { self.base.replace(value) } @@ -930,6 +932,7 @@ pub fn replace(&mut self, value: T) -> Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("delete", "take")] pub fn remove(&mut self, value: &Q) -> bool where T: Borrow, diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 28747ad8f34..bbcbbc52843 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -255,6 +255,7 @@ pub fn into_string(self) -> Result { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[rustc_confusables("append", "put")] pub fn push>(&mut self, s: T) { self.inner.push_slice(&s.as_ref().inner) } diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 60562f64c90..89fbd5c4c64 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1270,6 +1270,7 @@ pub fn as_path(&self) -> &Path { /// assert_eq!(path, PathBuf::from("/etc")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("append", "put")] pub fn push>(&mut self, path: P) { self._push(path.as_ref()) } diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index d1213e2f166..34d30a259ee 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -435,6 +435,7 @@ pub fn take(&'static self) -> T /// assert_eq!(X.replace(3), 2); /// ``` #[stable(feature = "local_key_cell_methods", since = "1.73.0")] + #[rustc_confusables("swap")] pub fn replace(&'static self, value: T) -> T { self.with(|cell| cell.replace(value)) } @@ -606,6 +607,7 @@ pub fn take(&'static self) -> T /// X.with_borrow(|v| assert_eq!(*v, vec![1, 2, 3])); /// ``` #[stable(feature = "local_key_cell_methods", since = "1.73.0")] + #[rustc_confusables("swap")] pub fn replace(&'static self, value: T) -> T { self.with(|cell| cell.replace(value)) } diff --git a/tests/ui/attributes/rustc_confusables.rs b/tests/ui/attributes/rustc_confusables.rs index a88432ead75..fed6c49ce6c 100644 --- a/tests/ui/attributes/rustc_confusables.rs +++ b/tests/ui/attributes/rustc_confusables.rs @@ -21,7 +21,7 @@ fn main() { //~^ ERROR no method named x.pulled(); //~^ ERROR no method named - //~| HELP there is a method with a similar name + //~| HELP you might have meant to use `pull` } struct Bar; diff --git a/tests/ui/attributes/rustc_confusables.stderr b/tests/ui/attributes/rustc_confusables.stderr index 9fd4470cdbb..93c31fd5a34 100644 --- a/tests/ui/attributes/rustc_confusables.stderr +++ b/tests/ui/attributes/rustc_confusables.stderr @@ -60,7 +60,12 @@ error[E0599]: no method named `pulled` found for struct `rustc_confusables_acros --> $DIR/rustc_confusables.rs:22:7 | LL | x.pulled(); - | ^^^^^^ help: there is a method with a similar name: `pull` + | ^^^^^^ + | +help: you might have meant to use `pull` + | +LL | x.pull(); + | ~~~~ error: aborting due to 9 previous errors diff --git a/tests/ui/attributes/rustc_confusables_std_cases.rs b/tests/ui/attributes/rustc_confusables_std_cases.rs new file mode 100644 index 00000000000..f408a09a81f --- /dev/null +++ b/tests/ui/attributes/rustc_confusables_std_cases.rs @@ -0,0 +1,21 @@ +use std::collections::BTreeSet; +use std::collections::VecDeque; + +fn main() { + let mut x = BTreeSet::new(); + x.push(1); //~ ERROR E0599 + //~^ HELP you might have meant to use `insert` + let mut x = Vec::new(); + x.push_back(1); //~ ERROR E0599 + //~^ HELP you might have meant to use `push` + let mut x = VecDeque::new(); + x.push(1); //~ ERROR E0599 + //~^ HELP you might have meant to use `push_back` + let mut x = vec![1, 2, 3]; + x.length(); //~ ERROR E0599 + //~^ HELP you might have meant to use `len` + x.size(); //~ ERROR E0599 + //~^ HELP you might have meant to use `len` + //~| HELP there is a method with a similar name + String::new().push(""); //~ ERROR E0308 +} diff --git a/tests/ui/attributes/rustc_confusables_std_cases.stderr b/tests/ui/attributes/rustc_confusables_std_cases.stderr new file mode 100644 index 00000000000..ce3bf3921dc --- /dev/null +++ b/tests/ui/attributes/rustc_confusables_std_cases.stderr @@ -0,0 +1,74 @@ +error[E0599]: no method named `push` found for struct `BTreeSet` in the current scope + --> $DIR/rustc_confusables_std_cases.rs:6:7 + | +LL | x.push(1); + | ^^^^ method not found in `BTreeSet<_>` + | +help: you might have meant to use `insert` + | +LL | x.insert(1); + | ~~~~~~ + +error[E0599]: no method named `push_back` found for struct `Vec<_>` in the current scope + --> $DIR/rustc_confusables_std_cases.rs:9:7 + | +LL | x.push_back(1); + | ^^^^^^^^^ method not found in `Vec<_>` + | +help: you might have meant to use `push` + | +LL | x.push(1); + | ~~~~ + +error[E0599]: no method named `push` found for struct `VecDeque` in the current scope + --> $DIR/rustc_confusables_std_cases.rs:12:7 + | +LL | x.push(1); + | ^^^^ method not found in `VecDeque<_>` + | +help: you might have meant to use `push_back` + | +LL | x.push_back(1); + | ~~~~~~~~~ + +error[E0599]: no method named `length` found for struct `Vec<{integer}>` in the current scope + --> $DIR/rustc_confusables_std_cases.rs:15:7 + | +LL | x.length(); + | ^^^^^^ + | +help: you might have meant to use `len` + | +LL | x.len(); + | ~~~ + +error[E0599]: no method named `size` found for struct `Vec<{integer}>` in the current scope + --> $DIR/rustc_confusables_std_cases.rs:17:7 + | +LL | x.size(); + | ^^^^ + | +help: you might have meant to use `len` + | +LL | x.len(); + | ~~~ +help: there is a method with a similar name + | +LL | x.resize(); + | ~~~~~~ + +error[E0308]: mismatched types + --> $DIR/rustc_confusables_std_cases.rs:20:24 + | +LL | String::new().push(""); + | ---- ^^ expected `char`, found `&str` + | | + | arguments to this method are incorrect + | +note: method defined here + --> $SRC_DIR/alloc/src/string.rs:LL:COL + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0308, E0599. +For more information about an error, try `rustc --explain E0308`.