From 3a6a29b4ecfdb7f641ca699fcd66a09b4baaae6a Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 31 Jul 2019 21:00:35 +0200 Subject: [PATCH 01/23] Use associated_type_bounds where applicable - closes #61738 --- src/liballoc/borrow.rs | 12 +- src/liballoc/lib.rs | 1 + src/liballoc/tests/str.rs | 10 +- src/libcore/convert.rs | 4 +- src/libcore/future/future.rs | 3 +- src/libcore/iter/adapters/flatten.rs | 61 +++++---- src/libcore/iter/traits/collect.rs | 4 +- src/libcore/lib.rs | 1 + src/libcore/pin.rs | 10 +- src/libcore/str/mod.rs | 116 +++++++++++------- src/librustc/lib.rs | 1 + src/librustc/traits/select.rs | 2 +- src/librustc/traits/structural_impls.rs | 6 +- src/librustc/ty/context.rs | 4 +- src/librustc/ty/layout.rs | 6 +- src/librustc/ty/query/on_disk_cache.rs | 3 +- src/librustc_codegen_ssa/back/command.rs | 4 +- src/librustc_codegen_ssa/lib.rs | 1 + src/librustc_data_structures/lib.rs | 1 + .../owning_ref/mod.rs | 8 +- src/librustc_mir/dataflow/mod.rs | 11 +- src/librustc_mir/lib.rs | 1 + src/libserialize/collection_impls.rs | 10 +- src/libserialize/lib.rs | 1 + src/libstd/sys/sgx/abi/usercalls/alloc.rs | 12 +- 25 files changed, 169 insertions(+), 124 deletions(-) diff --git a/src/liballoc/borrow.rs b/src/liballoc/borrow.rs index d5e15b3719c2e..a9c5bce4c25fc 100644 --- a/src/liballoc/borrow.rs +++ b/src/liballoc/borrow.rs @@ -329,8 +329,8 @@ impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for Cow<'_, B> - where B: fmt::Debug + ToOwned, - ::Owned: fmt::Debug +where + B: fmt::Debug + ToOwned, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { @@ -342,8 +342,8 @@ impl fmt::Debug for Cow<'_, B> #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for Cow<'_, B> - where B: fmt::Display + ToOwned, - ::Owned: fmt::Display +where + B: fmt::Display + ToOwned, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { @@ -355,8 +355,8 @@ impl fmt::Display for Cow<'_, B> #[stable(feature = "default", since = "1.11.0")] impl Default for Cow<'_, B> - where B: ToOwned, - ::Owned: Default +where + B: ToOwned, { /// Creates an owned Cow<'a, B> with the default value for the contained owned value. fn default() -> Self { diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index deea74daa52d5..a1936b36ac6bf 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -122,6 +122,7 @@ #![feature(alloc_layout_extra)] #![feature(try_trait)] #![feature(mem_take)] +#![feature(associated_type_bounds)] // Allow testing this library diff --git a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs index c5198ca39fedf..4332b2e90fdaf 100644 --- a/src/liballoc/tests/str.rs +++ b/src/liballoc/tests/str.rs @@ -1638,10 +1638,12 @@ mod pattern { } } - fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str, - right: Vec) - where P::Searcher: ReverseSearcher<'a> - { + fn cmp_search_to_vec<'a>( + rev: bool, + pat: impl Pattern<'a, Searcher: ReverseSearcher<'a>>, + haystack: &'a str, + right: Vec + ) { let mut searcher = pat.into_searcher(haystack); let mut v = vec![]; loop { diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 624b13d96472c..641621f492baf 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -513,7 +513,7 @@ impl AsRef for &mut T where T: AsRef // FIXME (#45742): replace the above impls for &/&mut with the following more general one: // // As lifts over Deref -// impl AsRef for D where D::Target: AsRef { +// impl>, U: ?Sized> AsRef for D { // fn as_ref(&self) -> &U { // self.deref().as_ref() // } @@ -530,7 +530,7 @@ impl AsMut for &mut T where T: AsMut // FIXME (#45742): replace the above impl for &mut with the following more general one: // // AsMut lifts over DerefMut -// impl AsMut for D where D::Target: AsMut { +// impl>, U: ?Sized> AsMut for D { // fn as_mut(&mut self) -> &mut U { // self.deref_mut().as_mut() // } diff --git a/src/libcore/future/future.rs b/src/libcore/future/future.rs index 593c01060ca49..f14ed38b9b0f2 100644 --- a/src/libcore/future/future.rs +++ b/src/libcore/future/future.rs @@ -111,8 +111,7 @@ impl Future for &mut F { #[stable(feature = "futures_api", since = "1.36.0")] impl

Future for Pin

where - P: Unpin + ops::DerefMut, - P::Target: Future, + P: Unpin + ops::DerefMut, { type Output = <

::Target as Future>::Output; diff --git a/src/libcore/iter/adapters/flatten.rs b/src/libcore/iter/adapters/flatten.rs index 8c2aae477bf2a..d8d41a2a31ef6 100644 --- a/src/libcore/iter/adapters/flatten.rs +++ b/src/libcore/iter/adapters/flatten.rs @@ -24,15 +24,17 @@ impl U> FlatMap { } #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for FlatMap - where ::IntoIter: Clone +impl Clone for FlatMap +where + U: Clone + IntoIterator, { fn clone(&self) -> Self { FlatMap { inner: self.inner.clone() } } } #[stable(feature = "core_impl_debug", since = "1.9.0")] -impl fmt::Debug for FlatMap - where U::IntoIter: fmt::Debug +impl fmt::Debug for FlatMap +where + U: IntoIterator, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("FlatMap").field("inner", &self.inner).finish() @@ -68,9 +70,10 @@ impl Iterator for FlatMap #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for FlatMap - where F: FnMut(I::Item) -> U, - U: IntoIterator, - U::IntoIter: DoubleEndedIterator +where + F: FnMut(I::Item) -> U, + U: IntoIterator, + U::IntoIter: DoubleEndedIterator, { #[inline] fn next_back(&mut self) -> Option { self.inner.next_back() } @@ -105,11 +108,13 @@ impl FusedIterator for FlatMap #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "iterator_flatten", since = "1.29.0")] pub struct Flatten -where I::Item: IntoIterator { +where + I::Item: IntoIterator, +{ inner: FlattenCompat::IntoIter>, } -impl Flatten -where I::Item: IntoIterator { + +impl> Flatten { pub(in super::super) fn new(iter: I) -> Flatten { Flatten { inner: FlattenCompat::new(iter) } } @@ -117,8 +122,9 @@ where I::Item: IntoIterator { #[stable(feature = "iterator_flatten", since = "1.29.0")] impl fmt::Debug for Flatten - where I: Iterator + fmt::Debug, U: Iterator + fmt::Debug, - I::Item: IntoIterator, +where + I: fmt::Debug + Iterator>, + U: fmt::Debug + Iterator, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Flatten").field("inner", &self.inner).finish() @@ -127,16 +133,18 @@ impl fmt::Debug for Flatten #[stable(feature = "iterator_flatten", since = "1.29.0")] impl Clone for Flatten - where I: Iterator + Clone, U: Iterator + Clone, - I::Item: IntoIterator, +where + I: Clone + Iterator>, + U: Clone + Iterator, { fn clone(&self) -> Self { Flatten { inner: self.inner.clone() } } } #[stable(feature = "iterator_flatten", since = "1.29.0")] impl Iterator for Flatten - where I: Iterator, U: Iterator, - I::Item: IntoIterator +where + I: Iterator>, + U: Iterator, { type Item = U::Item; @@ -163,8 +171,9 @@ impl Iterator for Flatten #[stable(feature = "iterator_flatten", since = "1.29.0")] impl DoubleEndedIterator for Flatten - where I: DoubleEndedIterator, U: DoubleEndedIterator, - I::Item: IntoIterator +where + I: DoubleEndedIterator>, + U: DoubleEndedIterator, { #[inline] fn next_back(&mut self) -> Option { self.inner.next_back() } @@ -186,8 +195,10 @@ impl DoubleEndedIterator for Flatten #[stable(feature = "iterator_flatten", since = "1.29.0")] impl FusedIterator for Flatten - where I: FusedIterator, U: Iterator, - I::Item: IntoIterator {} +where + I: FusedIterator>, + U: Iterator, +{} /// Real logic of both `Flatten` and `FlatMap` which simply delegate to /// this type. @@ -205,8 +216,9 @@ impl FlattenCompat { } impl Iterator for FlattenCompat - where I: Iterator, U: Iterator, - I::Item: IntoIterator +where + I: Iterator>, + U: Iterator, { type Item = U::Item; @@ -274,8 +286,9 @@ impl Iterator for FlattenCompat } impl DoubleEndedIterator for FlattenCompat - where I: DoubleEndedIterator, U: DoubleEndedIterator, - I::Item: IntoIterator +where + I: DoubleEndedIterator>, + U: DoubleEndedIterator, { #[inline] fn next_back(&mut self) -> Option { diff --git a/src/libcore/iter/traits/collect.rs b/src/libcore/iter/traits/collect.rs index 1865160bc3cf4..9f15de33425f4 100644 --- a/src/libcore/iter/traits/collect.rs +++ b/src/libcore/iter/traits/collect.rs @@ -195,8 +195,8 @@ pub trait FromIterator: Sized { /// /// ```rust /// fn collect_as_strings(collection: T) -> Vec -/// where T: IntoIterator, -/// T::Item: std::fmt::Debug, +/// where +/// T: IntoIterator, /// { /// collection /// .into_iter() diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 4d627383fd7cc..678ff7687921b 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -132,6 +132,7 @@ #![feature(maybe_uninit_slice, maybe_uninit_array)] #![feature(external_doc)] #![feature(mem_take)] +#![feature(associated_type_bounds)] #[prelude_import] #[allow(unused)] diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 88a56174629f9..243209d022b49 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -439,10 +439,7 @@ where } } -impl Pin

-where - P::Target: Unpin, -{ +impl> Pin

{ /// Construct a new `Pin

` around a pointer to some data of a type that /// implements [`Unpin`]. /// @@ -730,10 +727,7 @@ impl Deref for Pin

{ } #[stable(feature = "pin", since = "1.33.0")] -impl DerefMut for Pin

-where - P::Target: Unpin -{ +impl> DerefMut for Pin

{ fn deref_mut(&mut self) -> &mut P::Target { Pin::get_mut(Pin::as_mut(self)) } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 4faf9ff4d2ee2..f20cb7bfbc3bd 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -851,8 +851,9 @@ unsafe impl TrustedRandomAccess for Bytes<'_> { /// wrapper types of the form X<'a, P> macro_rules! derive_pattern_clone { (clone $t:ident with |$s:ident| $e:expr) => { - impl<'a, P: Pattern<'a>> Clone for $t<'a, P> - where P::Searcher: Clone + impl<'a, P> Clone for $t<'a, P> + where + P: Pattern<'a, Searcher: Clone>, { fn clone(&self) -> Self { let $s = self; @@ -928,8 +929,9 @@ macro_rules! generate_pattern_iterators { pub struct $forward_iterator<'a, P: Pattern<'a>>($internal_iterator<'a, P>); $(#[$common_stability_attribute])* - impl<'a, P: Pattern<'a>> fmt::Debug for $forward_iterator<'a, P> - where P::Searcher: fmt::Debug + impl<'a, P> fmt::Debug for $forward_iterator<'a, P> + where + P: Pattern<'a, Searcher: fmt::Debug>, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple(stringify!($forward_iterator)) @@ -949,8 +951,9 @@ macro_rules! generate_pattern_iterators { } $(#[$common_stability_attribute])* - impl<'a, P: Pattern<'a>> Clone for $forward_iterator<'a, P> - where P::Searcher: Clone + impl<'a, P> Clone for $forward_iterator<'a, P> + where + P: Pattern<'a, Searcher: Clone>, { fn clone(&self) -> Self { $forward_iterator(self.0.clone()) @@ -962,8 +965,9 @@ macro_rules! generate_pattern_iterators { pub struct $reverse_iterator<'a, P: Pattern<'a>>($internal_iterator<'a, P>); $(#[$common_stability_attribute])* - impl<'a, P: Pattern<'a>> fmt::Debug for $reverse_iterator<'a, P> - where P::Searcher: fmt::Debug + impl<'a, P> fmt::Debug for $reverse_iterator<'a, P> + where + P: Pattern<'a, Searcher: fmt::Debug>, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple(stringify!($reverse_iterator)) @@ -973,8 +977,9 @@ macro_rules! generate_pattern_iterators { } $(#[$common_stability_attribute])* - impl<'a, P: Pattern<'a>> Iterator for $reverse_iterator<'a, P> - where P::Searcher: ReverseSearcher<'a> + impl<'a, P> Iterator for $reverse_iterator<'a, P> + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, { type Item = $iterty; @@ -985,8 +990,9 @@ macro_rules! generate_pattern_iterators { } $(#[$common_stability_attribute])* - impl<'a, P: Pattern<'a>> Clone for $reverse_iterator<'a, P> - where P::Searcher: Clone + impl<'a, P> Clone for $reverse_iterator<'a, P> + where + P: Pattern<'a, Searcher: Clone>, { fn clone(&self) -> Self { $reverse_iterator(self.0.clone()) @@ -997,8 +1003,10 @@ macro_rules! generate_pattern_iterators { impl<'a, P: Pattern<'a>> FusedIterator for $forward_iterator<'a, P> {} #[stable(feature = "fused", since = "1.26.0")] - impl<'a, P: Pattern<'a>> FusedIterator for $reverse_iterator<'a, P> - where P::Searcher: ReverseSearcher<'a> {} + impl<'a, P> FusedIterator for $reverse_iterator<'a, P> + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, + {} generate_pattern_iterators!($($t)* with $(#[$common_stability_attribute])*, $forward_iterator, @@ -1010,8 +1018,9 @@ macro_rules! generate_pattern_iterators { $reverse_iterator:ident, $iterty:ty } => { $(#[$common_stability_attribute])* - impl<'a, P: Pattern<'a>> DoubleEndedIterator for $forward_iterator<'a, P> - where P::Searcher: DoubleEndedSearcher<'a> + impl<'a, P> DoubleEndedIterator for $forward_iterator<'a, P> + where + P: Pattern<'a, Searcher: DoubleEndedSearcher<'a>>, { #[inline] fn next_back(&mut self) -> Option<$iterty> { @@ -1020,8 +1029,9 @@ macro_rules! generate_pattern_iterators { } $(#[$common_stability_attribute])* - impl<'a, P: Pattern<'a>> DoubleEndedIterator for $reverse_iterator<'a, P> - where P::Searcher: DoubleEndedSearcher<'a> + impl<'a, P> DoubleEndedIterator for $reverse_iterator<'a, P> + where + P: Pattern<'a, Searcher: DoubleEndedSearcher<'a>>, { #[inline] fn next_back(&mut self) -> Option<$iterty> { @@ -1049,7 +1059,10 @@ struct SplitInternal<'a, P: Pattern<'a>> { finished: bool, } -impl<'a, P: Pattern<'a>> fmt::Debug for SplitInternal<'a, P> where P::Searcher: fmt::Debug { +impl<'a, P> fmt::Debug for SplitInternal<'a, P> +where + P: Pattern<'a, Searcher: fmt::Debug>, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("SplitInternal") .field("start", &self.start) @@ -1166,7 +1179,10 @@ struct SplitNInternal<'a, P: Pattern<'a>> { count: usize, } -impl<'a, P: Pattern<'a>> fmt::Debug for SplitNInternal<'a, P> where P::Searcher: fmt::Debug { +impl<'a, P> fmt::Debug for SplitNInternal<'a, P> +where + P: Pattern<'a, Searcher: fmt::Debug>, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("SplitNInternal") .field("iter", &self.iter) @@ -1222,7 +1238,10 @@ derive_pattern_clone!{ struct MatchIndicesInternal<'a, P: Pattern<'a>>(P::Searcher); -impl<'a, P: Pattern<'a>> fmt::Debug for MatchIndicesInternal<'a, P> where P::Searcher: fmt::Debug { +impl<'a, P> fmt::Debug for MatchIndicesInternal<'a, P> +where + P: Pattern<'a, Searcher: fmt::Debug>, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("MatchIndicesInternal") .field(&self.0) @@ -1273,7 +1292,10 @@ derive_pattern_clone!{ struct MatchesInternal<'a, P: Pattern<'a>>(P::Searcher); -impl<'a, P: Pattern<'a>> fmt::Debug for MatchesInternal<'a, P> where P::Searcher: fmt::Debug { +impl<'a, P> fmt::Debug for MatchesInternal<'a, P> +where + P: Pattern<'a, Searcher: fmt::Debug>, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("MatchesInternal") .field(&self.0) @@ -2882,8 +2904,9 @@ impl str { /// assert!(!bananas.ends_with("nana")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool - where P::Searcher: ReverseSearcher<'a> + pub fn ends_with<'a, P>(&'a self, pat: P) -> bool + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, { pat.is_suffix_of(self) } @@ -2975,8 +2998,9 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option - where P::Searcher: ReverseSearcher<'a> + pub fn rfind<'a, P>(&'a self, pat: P) -> Option + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, { pat.into_searcher(self).next_match_back().map(|(i, _)| i) } @@ -3142,8 +3166,9 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P> - where P::Searcher: ReverseSearcher<'a> + pub fn rsplit<'a, P>(&'a self, pat: P) -> RSplit<'a, P> + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, { RSplit(self.split(pat).0) } @@ -3233,8 +3258,9 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn rsplit_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplitTerminator<'a, P> - where P::Searcher: ReverseSearcher<'a> + pub fn rsplit_terminator<'a, P>(&'a self, pat: P) -> RSplitTerminator<'a, P> + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, { RSplitTerminator(self.split_terminator(pat).0) } @@ -3333,8 +3359,9 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> RSplitN<'a, P> - where P::Searcher: ReverseSearcher<'a> + pub fn rsplitn<'a, P>(&'a self, n: usize, pat: P) -> RSplitN<'a, P> + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, { RSplitN(self.splitn(n, pat).0) } @@ -3406,8 +3433,9 @@ impl str { /// ``` #[stable(feature = "str_matches", since = "1.2.0")] #[inline] - pub fn rmatches<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatches<'a, P> - where P::Searcher: ReverseSearcher<'a> + pub fn rmatches<'a, P>(&'a self, pat: P) -> RMatches<'a, P> + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, { RMatches(self.matches(pat).0) } @@ -3491,8 +3519,9 @@ impl str { /// ``` #[stable(feature = "str_match_indices", since = "1.5.0")] #[inline] - pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P> - where P::Searcher: ReverseSearcher<'a> + pub fn rmatch_indices<'a, P>(&'a self, pat: P) -> RMatchIndices<'a, P> + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, { RMatchIndices(self.match_indices(pat).0) } @@ -3700,8 +3729,9 @@ impl str { #[must_use = "this returns the trimmed string as a new slice, \ without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] - pub fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str - where P::Searcher: DoubleEndedSearcher<'a> + pub fn trim_matches<'a, P>(&'a self, pat: P) -> &'a str + where + P: Pattern<'a, Searcher: DoubleEndedSearcher<'a>>, { let mut i = 0; let mut j = 0; @@ -3792,8 +3822,9 @@ impl str { #[must_use = "this returns the trimmed string as a new slice, \ without modifying the original"] #[stable(feature = "trim_direction", since = "1.30.0")] - pub fn trim_end_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str - where P::Searcher: ReverseSearcher<'a> + pub fn trim_end_matches<'a, P>(&'a self, pat: P) -> &'a str + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, { let mut j = 0; let mut matcher = pat.into_searcher(self); @@ -3880,8 +3911,9 @@ impl str { reason = "superseded by `trim_end_matches`", suggestion = "trim_end_matches", )] - pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str - where P::Searcher: ReverseSearcher<'a> + pub fn trim_right_matches<'a, P>(&'a self, pat: P) -> &'a str + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, { self.trim_end_matches(pat) } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 8e0581b41ef7a..8d4cd51e4608c 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -61,6 +61,7 @@ #![feature(proc_macro_hygiene)] #![feature(log_syntax)] #![feature(mem_take)] +#![feature(associated_type_bounds)] #![recursion_limit="512"] diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index da582c015e4ea..d4ae366262cbf 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -3901,7 +3901,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // each predicate must be preceded by the obligations required // to normalize it. // for example, if we have: - // impl> Foo for V where U::Item: Copy + // impl, V: Iterator> Foo for V // the impl will have the following predicates: // ::Item = U, // U: Iterator, U: Sized, diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 129a400d28f4c..05b698eb4c4ea 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -980,8 +980,7 @@ EnumTypeFoldableImpl! { (chalk_engine::DelayedLiteral::Negative)(a), (chalk_engine::DelayedLiteral::Positive)(a, b), } where - C: chalk_engine::context::Context + Clone, - C::CanonicalConstrainedSubst: TypeFoldable<'tcx>, + C: chalk_engine::context::Context> + Clone, } EnumTypeFoldableImpl! { @@ -989,8 +988,7 @@ EnumTypeFoldableImpl! { (chalk_engine::Literal::Negative)(a), (chalk_engine::Literal::Positive)(a), } where - C: chalk_engine::context::Context + Clone, - C::GoalInEnvironment: Clone + TypeFoldable<'tcx>, + C: chalk_engine::context::Context> + Clone, } CloneTypeFoldableAndLiftImpls! { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index dadc126eba48e..ef74d9e5b2899 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2663,8 +2663,8 @@ impl<'tcx> TyCtxt<'tcx> { unsafety: hir::Unsafety, abi: abi::Abi) -> , ty::FnSig<'tcx>>>::Output - where I: Iterator, - I::Item: InternIteratorElement, ty::FnSig<'tcx>> + where + I: Iterator, ty::FnSig<'tcx>>>, { inputs.chain(iter::once(output)).intern_with(|xs| ty::FnSig { inputs_and_output: self.intern_type_list(xs), diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 1c9a5ad621854..a9d1fd1fffc92 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -2027,9 +2027,9 @@ impl ty::query::TyCtxtAt<'tcx> { impl<'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> where - C: LayoutOf> + HasTyCtxt<'tcx>, - C::TyLayout: MaybeResult>, - C: HasParamEnv<'tcx>, + C: LayoutOf, TyLayout: MaybeResult>> + + HasTyCtxt<'tcx> + + HasParamEnv<'tcx>, { fn for_variant(this: TyLayout<'tcx>, cx: &C, variant_index: VariantIdx) -> TyLayout<'tcx> { let details = match this.variants { diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 45bc89f5a84ab..40bcd028db58d 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -1055,9 +1055,8 @@ fn encode_query_results<'a, 'tcx, Q, E>( query_result_index: &mut EncodedQueryResultIndex, ) -> Result<(), E::Error> where - Q: super::config::QueryDescription<'tcx>, + Q: super::config::QueryDescription<'tcx, Value: Encodable>, E: 'a + TyEncoder, - Q::Value: Encodable, { let desc = &format!("encode_query_results for {}", ::std::any::type_name::()); diff --git a/src/librustc_codegen_ssa/back/command.rs b/src/librustc_codegen_ssa/back/command.rs index d610805b5bbd0..340cc772e5f07 100644 --- a/src/librustc_codegen_ssa/back/command.rs +++ b/src/librustc_codegen_ssa/back/command.rs @@ -50,8 +50,8 @@ impl Command { } pub fn args(&mut self, args: I) -> &mut Command - where I: IntoIterator, - I::Item: AsRef, + where + I: IntoIterator>, { for arg in args { self._arg(arg.as_ref()); diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs index 73ef16e009146..0e3c3a77b28f4 100644 --- a/src/librustc_codegen_ssa/lib.rs +++ b/src/librustc_codegen_ssa/lib.rs @@ -11,6 +11,7 @@ #![feature(nll)] #![feature(trusted_len)] #![feature(mem_take)] +#![feature(associated_type_bounds)] #![recursion_limit="256"] diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 8fb0ea0271b97..9f103437d368e 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -23,6 +23,7 @@ #![feature(core_intrinsics)] #![feature(integer_atomics)] #![feature(test)] +#![feature(associated_type_bounds)] #![cfg_attr(unix, feature(libc))] diff --git a/src/librustc_data_structures/owning_ref/mod.rs b/src/librustc_data_structures/owning_ref/mod.rs index ea9c5283aee7d..b835b1706b85f 100644 --- a/src/librustc_data_structures/owning_ref/mod.rs +++ b/src/librustc_data_structures/owning_ref/mod.rs @@ -847,7 +847,9 @@ pub trait ToHandleMut { } impl OwningHandle - where O: StableAddress, O::Target: ToHandle, H: Deref, +where + O: StableAddress>, + H: Deref, { /// Creates a new `OwningHandle` for a type that implements `ToHandle`. For types /// that don't implement `ToHandle`, callers may invoke `new_with_fn`, which accepts @@ -858,7 +860,9 @@ impl OwningHandle } impl OwningHandle - where O: StableAddress, O::Target: ToHandleMut, H: DerefMut, +where + O: StableAddress>, + H: DerefMut, { /// Creates a new mutable `OwningHandle` for a type that implements `ToHandleMut`. pub fn new_mut(o: O) -> Self { diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index 3bdd3e3da048e..7fe2a890a5371 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -589,10 +589,8 @@ impl GenKillSet { self.gen_set.insert(e); self.kill_set.remove(e); } - fn gen_all(&mut self, i: I) - where I: IntoIterator, - I::Item: Borrow - { + + fn gen_all(&mut self, i: impl IntoIterator>) { for j in i { self.gen(*j.borrow()); } @@ -603,10 +601,7 @@ impl GenKillSet { self.kill_set.insert(e); } - fn kill_all(&mut self, i: I) - where I: IntoIterator, - I::Item: Borrow - { + fn kill_all(&mut self, i: impl IntoIterator>) { for j in i { self.kill(*j.borrow()); } diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 20d5e54d2ce49..cccf7b9545bdb 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -23,6 +23,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(trusted_len)] #![feature(try_blocks)] #![feature(mem_take)] +#![feature(associated_type_bounds)] #![recursion_limit="256"] diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs index 80aeecb84d72b..d981740780e6f 100644 --- a/src/libserialize/collection_impls.rs +++ b/src/libserialize/collection_impls.rs @@ -9,10 +9,7 @@ use std::sync::Arc; use smallvec::{Array, SmallVec}; -impl Encodable for SmallVec - where A: Array, - A::Item: Encodable -{ +impl> Encodable for SmallVec { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_seq(self.len(), |s| { for (i, e) in self.iter().enumerate() { @@ -23,10 +20,7 @@ impl Encodable for SmallVec } } -impl Decodable for SmallVec - where A: Array, - A::Item: Decodable -{ +impl> Decodable for SmallVec { fn decode(d: &mut D) -> Result, D::Error> { d.read_seq(|d, len| { let mut vec = SmallVec::with_capacity(len); diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 2ad85c603d1e4..67a48ca4af902 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -13,6 +13,7 @@ Core encoding and decoding interfaces. #![feature(specialization)] #![feature(never_type)] #![feature(nll)] +#![feature(associated_type_bounds)] #![cfg_attr(test, feature(test))] pub use self::serialize::{Decoder, Encoder, Decodable, Encodable}; diff --git a/src/libstd/sys/sgx/abi/usercalls/alloc.rs b/src/libstd/sys/sgx/abi/usercalls/alloc.rs index c9ff53d0a4fd6..75dd0d429c214 100644 --- a/src/libstd/sys/sgx/abi/usercalls/alloc.rs +++ b/src/libstd/sys/sgx/abi/usercalls/alloc.rs @@ -522,7 +522,11 @@ impl Drop for User where T: UserSafe { impl, U> CoerceUnsized> for UserRef {} #[unstable(feature = "sgx_platform", issue = "56975")] -impl> Index for UserRef<[T]> where [T]: UserSafe, I::Output: UserSafe { +impl Index for UserRef<[T]> +where + [T]: UserSafe, + I: SliceIndex<[T], Output: UserSafe>, +{ type Output = UserRef; #[inline] @@ -538,7 +542,11 @@ impl> Index for UserRef<[T]> where [T]: UserSafe, I::Ou } #[unstable(feature = "sgx_platform", issue = "56975")] -impl> IndexMut for UserRef<[T]> where [T]: UserSafe, I::Output: UserSafe { +impl IndexMut for UserRef<[T]> +where + [T]: UserSafe, + I: SliceIndex<[T], Output: UserSafe>, +{ #[inline] fn index_mut(&mut self, index: I) -> &mut UserRef { unsafe { From 322a7d6387a875d9f751c1b332f84c181e57ac64 Mon Sep 17 00:00:00 2001 From: Jack Date: Thu, 8 Aug 2019 19:16:08 -0400 Subject: [PATCH 02/23] Add test for issue 36804 --- src/test/ui/specialization/issue-36804.rs | 31 +++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/test/ui/specialization/issue-36804.rs diff --git a/src/test/ui/specialization/issue-36804.rs b/src/test/ui/specialization/issue-36804.rs new file mode 100644 index 0000000000000..36cb939bc48fb --- /dev/null +++ b/src/test/ui/specialization/issue-36804.rs @@ -0,0 +1,31 @@ +// check-pass +#![feature(specialization)] + +pub struct Cloned(I); + +impl<'a, I, T: 'a> Iterator for Cloned +where + I: Iterator, + T: Clone, +{ + type Item = T; + + fn next(&mut self) -> Option { + unimplemented!() + } +} + +impl<'a, I, T: 'a> Iterator for Cloned +where + I: Iterator, + T: Copy, +{ + fn count(self) -> usize { + unimplemented!() + } +} + +fn main() { + let a = [1,2,3,4]; + Cloned(a.iter()).count(); +} From 3d231acceeb6a1af8108577b65bd60745f7dcf17 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 9 Aug 2019 00:33:57 +0200 Subject: [PATCH 03/23] Add missing #![feature(associated_type_bounds)] --- src/liballoc/tests/lib.rs | 1 + src/libcore/iter/traits/collect.rs | 2 ++ src/libstd/lib.rs | 1 + 3 files changed, 4 insertions(+) diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index 6d774f3fecd92..5723a30c0f34f 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -8,6 +8,7 @@ #![feature(trusted_len)] #![feature(try_reserve)] #![feature(unboxed_closures)] +#![feature(associated_type_bounds)] use std::hash::{Hash, Hasher}; use std::collections::hash_map::DefaultHasher; diff --git a/src/libcore/iter/traits/collect.rs b/src/libcore/iter/traits/collect.rs index 9f15de33425f4..015184cbba254 100644 --- a/src/libcore/iter/traits/collect.rs +++ b/src/libcore/iter/traits/collect.rs @@ -194,6 +194,8 @@ pub trait FromIterator: Sized { /// `Item`: /// /// ```rust +/// #![feature(associated_type_bounds)] +/// /// fn collect_as_strings(collection: T) -> Vec /// where /// T: IntoIterator, diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index cfee49a7b555c..10e3c34506311 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -238,6 +238,7 @@ #![feature(arbitrary_self_types)] #![feature(array_error_internals)] #![feature(asm)] +#![feature(associated_type_bounds)] #![feature(bind_by_move_pattern_guards)] #![feature(box_syntax)] #![feature(c_variadic)] From 77bfd7fd1a939638a19ca30efad767c81bdd3d8b Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 9 Aug 2019 13:40:54 +0200 Subject: [PATCH 04/23] Don't use associated type bounds in docs until it is stable --- src/libcore/iter/traits/collect.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libcore/iter/traits/collect.rs b/src/libcore/iter/traits/collect.rs index 015184cbba254..25439136b8538 100644 --- a/src/libcore/iter/traits/collect.rs +++ b/src/libcore/iter/traits/collect.rs @@ -194,11 +194,10 @@ pub trait FromIterator: Sized { /// `Item`: /// /// ```rust -/// #![feature(associated_type_bounds)] -/// /// fn collect_as_strings(collection: T) -> Vec /// where -/// T: IntoIterator, +/// T: IntoIterator, +/// T::Item: std::fmt::Debug, /// { /// collection /// .into_iter() From c076392143e483f60429d148ac58522e423eea9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 6 Aug 2019 14:20:39 -0700 Subject: [PATCH 05/23] Tweak mismatched types error on break expressions --- src/librustc_typeck/check/expr.rs | 16 ++++++++++- src/test/ui/issues/issue-27042.stderr | 9 ++++--- src/test/ui/loops/loop-break-value.stderr | 18 ++++++++----- .../ui/loops/loop-labeled-break-value.stderr | 27 ++++++++++++------- .../ui/loops/loop-properly-diverging-2.stderr | 9 ++++--- 5 files changed, 57 insertions(+), 22 deletions(-) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index d825358beaade..c567741be3980 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -548,7 +548,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { coerce.coerce(self, &cause, e, e_ty); } else { assert!(e_ty.is_unit()); - coerce.coerce_forced_unit(self, &cause, &mut |_| (), true); + let ty = coerce.expected_ty(); + coerce.coerce_forced_unit(self, &cause, &mut |err| { + let msg = "give it a value of the expected type"; + let label = destination.label + .map(|l| format!(" {}", l.ident)) + .unwrap_or_else(String::new); + let sugg = format!("break{} {}", label, match ty.sty { + ty::Bool => "true", + ty::Char => "'a'", + ty::Int(_) | ty::Uint(_) => "42", + ty::Float(_) => "3.14159", + _ => "value", + }); + err.span_suggestion(expr.span, msg, sugg, Applicability::HasPlaceholders); + }, false); } } else { // If `ctxt.coerce` is `None`, we can just ignore diff --git a/src/test/ui/issues/issue-27042.stderr b/src/test/ui/issues/issue-27042.stderr index 4beb752854b9c..7678984a518ba 100644 --- a/src/test/ui/issues/issue-27042.stderr +++ b/src/test/ui/issues/issue-27042.stderr @@ -12,10 +12,13 @@ error[E0308]: mismatched types --> $DIR/issue-27042.rs:6:16 | LL | loop { break }; - | ^^^^^ expected (), found i32 + | ^^^^^ + | | + | expected i32, found () + | help: give it a value of the expected type: `break 42` | - = note: expected type `()` - found type `i32` + = note: expected type `i32` + found type `()` error[E0308]: mismatched types --> $DIR/issue-27042.rs:8:9 diff --git a/src/test/ui/loops/loop-break-value.stderr b/src/test/ui/loops/loop-break-value.stderr index 1e167905ec8d7..7310790b880c2 100644 --- a/src/test/ui/loops/loop-break-value.stderr +++ b/src/test/ui/loops/loop-break-value.stderr @@ -90,10 +90,13 @@ error[E0308]: mismatched types --> $DIR/loop-break-value.rs:4:31 | LL | let val: ! = loop { break break; }; - | ^^^^^ expected (), found ! + | ^^^^^ + | | + | expected !, found () + | help: give it a value of the expected type: `break value` | - = note: expected type `()` - found type `!` + = note: expected type `!` + found type `()` error[E0308]: mismatched types --> $DIR/loop-break-value.rs:11:19 @@ -153,10 +156,13 @@ error[E0308]: mismatched types --> $DIR/loop-break-value.rs:90:9 | LL | break; - | ^^^^^ expected (), found integer + | ^^^^^ + | | + | expected integer, found () + | help: give it a value of the expected type: `break value` | - = note: expected type `()` - found type `{integer}` + = note: expected type `{integer}` + found type `()` error: aborting due to 16 previous errors diff --git a/src/test/ui/loops/loop-labeled-break-value.stderr b/src/test/ui/loops/loop-labeled-break-value.stderr index ad7cb4b0c2e5f..8b9468cacc1f9 100644 --- a/src/test/ui/loops/loop-labeled-break-value.stderr +++ b/src/test/ui/loops/loop-labeled-break-value.stderr @@ -2,28 +2,37 @@ error[E0308]: mismatched types --> $DIR/loop-labeled-break-value.rs:3:29 | LL | let _: i32 = loop { break }; - | ^^^^^ expected (), found i32 + | ^^^^^ + | | + | expected i32, found () + | help: give it a value of the expected type: `break 42` | - = note: expected type `()` - found type `i32` + = note: expected type `i32` + found type `()` error[E0308]: mismatched types --> $DIR/loop-labeled-break-value.rs:6:37 | LL | let _: i32 = 'inner: loop { break 'inner }; - | ^^^^^^^^^^^^ expected (), found i32 + | ^^^^^^^^^^^^ + | | + | expected i32, found () + | help: give it a value of the expected type: `break 'inner 42` | - = note: expected type `()` - found type `i32` + = note: expected type `i32` + found type `()` error[E0308]: mismatched types --> $DIR/loop-labeled-break-value.rs:9:45 | LL | let _: i32 = 'inner2: loop { loop { break 'inner2 } }; - | ^^^^^^^^^^^^^ expected (), found i32 + | ^^^^^^^^^^^^^ + | | + | expected i32, found () + | help: give it a value of the expected type: `break 'inner2 42` | - = note: expected type `()` - found type `i32` + = note: expected type `i32` + found type `()` error: aborting due to 3 previous errors diff --git a/src/test/ui/loops/loop-properly-diverging-2.stderr b/src/test/ui/loops/loop-properly-diverging-2.stderr index 6293fdb058a0f..3758bbf9f6f31 100644 --- a/src/test/ui/loops/loop-properly-diverging-2.stderr +++ b/src/test/ui/loops/loop-properly-diverging-2.stderr @@ -2,10 +2,13 @@ error[E0308]: mismatched types --> $DIR/loop-properly-diverging-2.rs:2:23 | LL | let x: i32 = loop { break }; - | ^^^^^ expected (), found i32 + | ^^^^^ + | | + | expected i32, found () + | help: give it a value of the expected type: `break 42` | - = note: expected type `()` - found type `i32` + = note: expected type `i32` + found type `()` error: aborting due to previous error From 799b13ada59d0663e98a02744d21d2c3b08501ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 6 Aug 2019 17:24:39 -0700 Subject: [PATCH 06/23] Do not suggest using ! with break --- src/librustc_typeck/check/expr.rs | 1 + src/test/ui/loops/loop-break-value.stderr | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index c567741be3980..5c859b9fd3254 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -559,6 +559,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Char => "'a'", ty::Int(_) | ty::Uint(_) => "42", ty::Float(_) => "3.14159", + ty::Error | ty::Never => return, _ => "value", }); err.span_suggestion(expr.span, msg, sugg, Applicability::HasPlaceholders); diff --git a/src/test/ui/loops/loop-break-value.stderr b/src/test/ui/loops/loop-break-value.stderr index 7310790b880c2..fef5b5873068f 100644 --- a/src/test/ui/loops/loop-break-value.stderr +++ b/src/test/ui/loops/loop-break-value.stderr @@ -90,10 +90,7 @@ error[E0308]: mismatched types --> $DIR/loop-break-value.rs:4:31 | LL | let val: ! = loop { break break; }; - | ^^^^^ - | | - | expected !, found () - | help: give it a value of the expected type: `break value` + | ^^^^^ expected !, found () | = note: expected type `!` found type `()` From 4fbbf99c509042e89572f8575c875889874edb45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 6 Aug 2019 22:20:42 -0700 Subject: [PATCH 07/23] Be more accurate when mentioning type of found match arms --- src/librustc/infer/error_reporting/mod.rs | 38 +++++-------------- .../ui/match/match-arm-resolving-to-never.rs | 19 ++++++++++ .../match/match-arm-resolving-to-never.stderr | 22 +++++++++++ 3 files changed, 51 insertions(+), 28 deletions(-) create mode 100644 src/test/ui/match/match-arm-resolving-to-never.rs create mode 100644 src/test/ui/match/match-arm-resolving-to-never.stderr diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 8d0ead5c8fe90..2ffcd2c4ace7b 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -662,19 +662,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } _ => { + // `last_ty` can be `!`, `expected` will have better info when present. + let t = self.resolve_vars_if_possible(&match exp_found { + Some(ty::error::ExpectedFound { expected, .. }) => expected, + _ => last_ty, + }); let msg = "`match` arms have incompatible types"; err.span_label(cause.span, msg); if prior_arms.len() <= 4 { for sp in prior_arms { - err.span_label(*sp, format!( - "this is found to be of type `{}`", - self.resolve_vars_if_possible(&last_ty), - )); + err.span_label( *sp, format!("this is found to be of type `{}`", t)); } } else if let Some(sp) = prior_arms.last() { - err.span_label(*sp, format!( - "this and all prior arms are found to be of type `{}`", last_ty, - )); + err.span_label( + *sp, + format!("this and all prior arms are found to be of type `{}`", t), + ); } } }, @@ -1143,27 +1146,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } (_, false, _) => { if let Some(exp_found) = exp_found { - let (def_id, ret_ty) = match exp_found.found.sty { - ty::FnDef(def, _) => { - (Some(def), Some(self.tcx.fn_sig(def).output())) - } - _ => (None, None), - }; - - let exp_is_struct = match exp_found.expected.sty { - ty::Adt(def, _) => def.is_struct(), - _ => false, - }; - - if let (Some(def_id), Some(ret_ty)) = (def_id, ret_ty) { - if exp_is_struct && &exp_found.expected == ret_ty.skip_binder() { - let message = format!( - "did you mean `{}(/* fields */)`?", - self.tcx.def_path_str(def_id) - ); - diag.span_label(span, message); - } - } self.suggest_as_ref_where_appropriate(span, &exp_found, diag); } diff --git a/src/test/ui/match/match-arm-resolving-to-never.rs b/src/test/ui/match/match-arm-resolving-to-never.rs new file mode 100644 index 0000000000000..8f54023305e83 --- /dev/null +++ b/src/test/ui/match/match-arm-resolving-to-never.rs @@ -0,0 +1,19 @@ +enum E { + A, + B, + C, + D, + E, + F, +} + +fn main() { + match E::F { + E::A => 1, + E::B => 2, + E::C => 3, + E::D => 4, + E::E => unimplemented!(""), + E::F => "", //~ ERROR match arms have incompatible types + }; +} diff --git a/src/test/ui/match/match-arm-resolving-to-never.stderr b/src/test/ui/match/match-arm-resolving-to-never.stderr new file mode 100644 index 0000000000000..24ce97f86e760 --- /dev/null +++ b/src/test/ui/match/match-arm-resolving-to-never.stderr @@ -0,0 +1,22 @@ +error[E0308]: match arms have incompatible types + --> $DIR/match-arm-resolving-to-never.rs:17:17 + | +LL | / match E::F { +LL | | E::A => 1, +LL | | E::B => 2, +LL | | E::C => 3, +LL | | E::D => 4, +LL | | E::E => unimplemented!(""), + | | ------------------ this and all prior arms are found to be of type `{integer}` +LL | | E::F => "", + | | ^^ expected integer, found reference +LL | | }; + | |_____- `match` arms have incompatible types + | + = note: expected type `{integer}` + found type `&'static str` + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 01a61394f8d69c1720fcdf77eaac635600ff87e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 6 Aug 2019 22:22:04 -0700 Subject: [PATCH 08/23] Change wording for function without return value Fix #62677 --- src/librustc_typeck/check/mod.rs | 2 +- .../ui/block-result/consider-removing-last-semi.stderr | 4 ++-- src/test/ui/block-result/issue-11714.stderr | 2 +- src/test/ui/block-result/issue-13428.stderr | 4 ++-- .../coercion/coercion-missing-tail-expected-type.stderr | 4 ++-- src/test/ui/issues/issue-32323.stderr | 2 +- src/test/ui/issues/issue-43162.stderr | 2 +- src/test/ui/issues/issue-44023.stderr | 2 +- src/test/ui/issues/issue-6458-4.stderr | 2 +- src/test/ui/liveness/liveness-forgot-ret.stderr | 2 +- src/test/ui/liveness/liveness-missing-ret2.stderr | 2 +- .../ui/liveness/liveness-return-last-stmt-semi.stderr | 8 ++++---- src/test/ui/missing/missing-return.stderr | 2 +- src/test/ui/parser/issue-62881.stderr | 2 +- src/test/ui/parser/issue-62895.stderr | 2 +- 15 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 08033b46b8004..da9b02fcf513a 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3709,7 +3709,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.consider_hint_about_removing_semicolon(blk, expected_ty, err); } if let Some(fn_span) = fn_span { - err.span_label(fn_span, "this function's body doesn't return"); + err.span_label(fn_span, "this function's body doesn't return a value"); } }, false); } diff --git a/src/test/ui/block-result/consider-removing-last-semi.stderr b/src/test/ui/block-result/consider-removing-last-semi.stderr index 618d020ce08b5..7f8bb67c946e6 100644 --- a/src/test/ui/block-result/consider-removing-last-semi.stderr +++ b/src/test/ui/block-result/consider-removing-last-semi.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn f() -> String { | - ^^^^^^ expected struct `std::string::String`, found () | | - | this function's body doesn't return + | this function's body doesn't return a value LL | 0u8; LL | "bla".to_string(); | - help: consider removing this semicolon @@ -18,7 +18,7 @@ error[E0308]: mismatched types LL | fn g() -> String { | - ^^^^^^ expected struct `std::string::String`, found () | | - | this function's body doesn't return + | this function's body doesn't return a value LL | "this won't work".to_string(); LL | "removeme".to_string(); | - help: consider removing this semicolon diff --git a/src/test/ui/block-result/issue-11714.stderr b/src/test/ui/block-result/issue-11714.stderr index d73489a602df4..569e012540c4f 100644 --- a/src/test/ui/block-result/issue-11714.stderr +++ b/src/test/ui/block-result/issue-11714.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn blah() -> i32 { | ---- ^^^ expected i32, found () | | - | this function's body doesn't return + | this function's body doesn't return a value ... LL | ; | - help: consider removing this semicolon diff --git a/src/test/ui/block-result/issue-13428.stderr b/src/test/ui/block-result/issue-13428.stderr index 18adb15c9615d..ca48910026d9a 100644 --- a/src/test/ui/block-result/issue-13428.stderr +++ b/src/test/ui/block-result/issue-13428.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn foo() -> String { | --- ^^^^^^ expected struct `std::string::String`, found () | | - | this function's body doesn't return + | this function's body doesn't return a value ... LL | ; | - help: consider removing this semicolon @@ -18,7 +18,7 @@ error[E0308]: mismatched types LL | fn bar() -> String { | --- ^^^^^^ expected struct `std::string::String`, found () | | - | this function's body doesn't return + | this function's body doesn't return a value LL | "foobar".to_string() LL | ; | - help: consider removing this semicolon diff --git a/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr b/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr index 057de5b625e87..a7ac930ba670e 100644 --- a/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr +++ b/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn plus_one(x: i32) -> i32 { | -------- ^^^ expected i32, found () | | - | this function's body doesn't return + | this function's body doesn't return a value LL | x + 1; | - help: consider removing this semicolon | @@ -17,7 +17,7 @@ error[E0308]: mismatched types LL | fn foo() -> Result { | --- ^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found () | | - | this function's body doesn't return + | this function's body doesn't return a value LL | Ok(1); | - help: consider removing this semicolon | diff --git a/src/test/ui/issues/issue-32323.stderr b/src/test/ui/issues/issue-32323.stderr index 0339fdc55b9c8..6b8bca078b5e6 100644 --- a/src/test/ui/issues/issue-32323.stderr +++ b/src/test/ui/issues/issue-32323.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | pub fn f<'a, T: Tr<'a>>() -> >::Out {} | - ^^^^^^^^^^^^^^^^^^ expected associated type, found () | | - | this function's body doesn't return + | this function's body doesn't return a value | = note: expected type `>::Out` found type `()` diff --git a/src/test/ui/issues/issue-43162.stderr b/src/test/ui/issues/issue-43162.stderr index cd11959ede6cb..fd62ac30ab195 100644 --- a/src/test/ui/issues/issue-43162.stderr +++ b/src/test/ui/issues/issue-43162.stderr @@ -16,7 +16,7 @@ error[E0308]: mismatched types LL | fn foo() -> bool { | --- ^^^^ expected bool, found () | | - | this function's body doesn't return + | this function's body doesn't return a value LL | LL | break true; | - help: consider removing this semicolon diff --git a/src/test/ui/issues/issue-44023.stderr b/src/test/ui/issues/issue-44023.stderr index 153be363c1dea..cad202129a719 100644 --- a/src/test/ui/issues/issue-44023.stderr +++ b/src/test/ui/issues/issue-44023.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn საჭმელად_გემრიელი_სადილი ( ) -> isize { | ------------------------ ^^^^^ expected isize, found () | | - | this function's body doesn't return + | this function's body doesn't return a value | = note: expected type `isize` found type `()` diff --git a/src/test/ui/issues/issue-6458-4.stderr b/src/test/ui/issues/issue-6458-4.stderr index 90b493e1634c4..d4f5b2ba41f69 100644 --- a/src/test/ui/issues/issue-6458-4.stderr +++ b/src/test/ui/issues/issue-6458-4.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn foo(b: bool) -> Result { | --- ^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found () | | - | this function's body doesn't return + | this function's body doesn't return a value LL | Err("bar".to_string()); | - help: consider removing this semicolon | diff --git a/src/test/ui/liveness/liveness-forgot-ret.stderr b/src/test/ui/liveness/liveness-forgot-ret.stderr index a970b80fdbbd9..6d917393663b0 100644 --- a/src/test/ui/liveness/liveness-forgot-ret.stderr +++ b/src/test/ui/liveness/liveness-forgot-ret.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; } | - ^^^^^ expected isize, found () | | - | this function's body doesn't return + | this function's body doesn't return a value | = note: expected type `isize` found type `()` diff --git a/src/test/ui/liveness/liveness-missing-ret2.stderr b/src/test/ui/liveness/liveness-missing-ret2.stderr index ab7d411880bba..a71b9296702b7 100644 --- a/src/test/ui/liveness/liveness-missing-ret2.stderr +++ b/src/test/ui/liveness/liveness-missing-ret2.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn f() -> isize { | - ^^^^^ expected isize, found () | | - | this function's body doesn't return + | this function's body doesn't return a value | = note: expected type `isize` found type `()` diff --git a/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr b/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr index a5d9734c069ec..3a08699170643 100644 --- a/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr +++ b/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr @@ -5,7 +5,7 @@ LL | macro_rules! test { () => { fn foo() -> i32 { 1; } } } | --- ^^^ - help: consider removing this semicolon | | | | | expected i32, found () - | this function's body doesn't return + | this function's body doesn't return a value ... LL | test!(); | -------- in this macro invocation @@ -19,7 +19,7 @@ error[E0308]: mismatched types LL | fn no_return() -> i32 {} | --------- ^^^ expected i32, found () | | - | this function's body doesn't return + | this function's body doesn't return a value | = note: expected type `i32` found type `()` @@ -30,7 +30,7 @@ error[E0308]: mismatched types LL | fn bar(x: u32) -> u32 { | --- ^^^ expected u32, found () | | - | this function's body doesn't return + | this function's body doesn't return a value LL | x * 2; | - help: consider removing this semicolon | @@ -43,7 +43,7 @@ error[E0308]: mismatched types LL | fn baz(x: u64) -> u32 { | --- ^^^ expected u32, found () | | - | this function's body doesn't return + | this function's body doesn't return a value | = note: expected type `u32` found type `()` diff --git a/src/test/ui/missing/missing-return.stderr b/src/test/ui/missing/missing-return.stderr index 42466e2fc6574..c7d7116a9cd7c 100644 --- a/src/test/ui/missing/missing-return.stderr +++ b/src/test/ui/missing/missing-return.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn f() -> isize { } | - ^^^^^ expected isize, found () | | - | this function's body doesn't return + | this function's body doesn't return a value | = note: expected type `isize` found type `()` diff --git a/src/test/ui/parser/issue-62881.stderr b/src/test/ui/parser/issue-62881.stderr index 85c3575fd9288..b2e2da35a2700 100644 --- a/src/test/ui/parser/issue-62881.stderr +++ b/src/test/ui/parser/issue-62881.stderr @@ -19,7 +19,7 @@ error[E0308]: mismatched types LL | fn f() -> isize { fn f() -> isize {} pub f< | - ^^^^^ expected isize, found () | | - | this function's body doesn't return + | this function's body doesn't return a value | = note: expected type `isize` found type `()` diff --git a/src/test/ui/parser/issue-62895.stderr b/src/test/ui/parser/issue-62895.stderr index 7def7b562ca59..6c3a8fb766c0a 100644 --- a/src/test/ui/parser/issue-62895.stderr +++ b/src/test/ui/parser/issue-62895.stderr @@ -38,7 +38,7 @@ error[E0308]: mismatched types LL | fn v() -> isize { | - ^^^^^ expected isize, found () | | - | this function's body doesn't return + | this function's body doesn't return a value | = note: expected type `isize` found type `()` From 94fe8a3c1761acadd5043b24ad821b0b369922ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 6 Aug 2019 22:29:10 -0700 Subject: [PATCH 09/23] Suggest calling function on type error when finding bare fn --- src/librustc_typeck/check/mod.rs | 43 ++++++++++++++++++++ src/test/ui/issues/issue-35241.stderr | 5 ++- src/test/ui/resolve/privacy-enum-ctor.stderr | 24 +++++++++-- src/test/ui/substs-ppaux.normal.stderr | 32 +++++++++++++-- src/test/ui/substs-ppaux.verbose.stderr | 32 +++++++++++++-- 5 files changed, 124 insertions(+), 12 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index da9b02fcf513a..6600f83393857 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3819,6 +3819,41 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pointing_at_return_type } + fn suggest_fn_call( + &self, + err: &mut DiagnosticBuilder<'tcx>, + expr: &hir::Expr, + expected: Ty<'tcx>, + found: Ty<'tcx>, + ) -> bool { + if let ty::FnDef(..) | ty::FnPtr(_) = &found.sty { + let sig = found.fn_sig(self.tcx); + let sig = self + .replace_bound_vars_with_fresh_vars(expr.span, infer::FnCall, &sig) + .0; + let sig = self.normalize_associated_types_in(expr.span, &sig); + if let Ok(_) = self.try_coerce(expr, sig.output(), expected, AllowTwoPhase::No) { + if let Ok(code) = self.sess().source_map().span_to_snippet(expr.span) { + err.span_suggestion(expr.span, "use parentheses to call this function", format!( + "{}({})", + code, + if sig.inputs().len() > 0 { + "..." + } else { + "" + }), if sig.inputs().len() > 0 { + Applicability::MachineApplicable + } else { + Applicability::HasPlaceholders + } + ); + return true; + } + } + } + false + } + pub fn suggest_ref_or_into( &self, err: &mut DiagnosticBuilder<'tcx>, @@ -3833,6 +3868,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { suggestion, Applicability::MachineApplicable, ); + } else if let (ty::FnDef(def_id, ..), true) = ( + &found.sty, + self.suggest_fn_call(err, expr, expected, found), + ) { + if let Some(sp) = self.tcx.hir().span_if_local(*def_id) { + let sp = self.sess().source_map().def_span(sp); + err.span_label(sp, &format!("{} defined here", found)); + } } else if !self.check_for_cast(err, expr, found, expected) { let is_struct_pat_shorthand_field = self.is_hir_id_from_struct_pattern_shorthand_field( expr.hir_id, diff --git a/src/test/ui/issues/issue-35241.stderr b/src/test/ui/issues/issue-35241.stderr index 8fda58abadb6e..248e6f0f46b19 100644 --- a/src/test/ui/issues/issue-35241.stderr +++ b/src/test/ui/issues/issue-35241.stderr @@ -1,11 +1,14 @@ error[E0308]: mismatched types --> $DIR/issue-35241.rs:3:20 | +LL | struct Foo(u32); + | ---------------- fn(u32) -> Foo {Foo} defined here +LL | LL | fn test() -> Foo { Foo } | --- ^^^ | | | | | expected struct `Foo`, found fn item - | | did you mean `Foo(/* fields */)`? + | | help: use parentheses to call this function: `Foo(...)` | expected `Foo` because of return type | = note: expected type `Foo` diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr index a1a8714ab3f38..07cbffb009406 100644 --- a/src/test/ui/resolve/privacy-enum-ctor.stderr +++ b/src/test/ui/resolve/privacy-enum-ctor.stderr @@ -195,8 +195,14 @@ LL | let _: Z = m::n::Z::Unit {}; error[E0308]: mismatched types --> $DIR/privacy-enum-ctor.rs:27:20 | +LL | Fn(u8), + | ------ fn(u8) -> m::n::Z {m::n::Z::Fn} defined here +... LL | let _: Z = Z::Fn; - | ^^^^^ expected enum `m::n::Z`, found fn item + | ^^^^^ + | | + | expected enum `m::n::Z`, found fn item + | help: use parentheses to call this function: `Z::Fn(...)` | = note: expected type `m::n::Z` found type `fn(u8) -> m::n::Z {m::n::Z::Fn}` @@ -219,8 +225,14 @@ LL | let _ = Z::Unit; error[E0308]: mismatched types --> $DIR/privacy-enum-ctor.rs:43:16 | +LL | Fn(u8), + | ------ fn(u8) -> m::E {m::E::Fn} defined here +... LL | let _: E = m::E::Fn; - | ^^^^^^^^ expected enum `m::E`, found fn item + | ^^^^^^^^ + | | + | expected enum `m::E`, found fn item + | help: use parentheses to call this function: `m::E::Fn(...)` | = note: expected type `m::E` found type `fn(u8) -> m::E {m::E::Fn}` @@ -243,8 +255,14 @@ LL | let _: E = m::E::Unit; error[E0308]: mismatched types --> $DIR/privacy-enum-ctor.rs:51:16 | +LL | Fn(u8), + | ------ fn(u8) -> m::E {m::E::Fn} defined here +... LL | let _: E = E::Fn; - | ^^^^^ expected enum `m::E`, found fn item + | ^^^^^ + | | + | expected enum `m::E`, found fn item + | help: use parentheses to call this function: `E::Fn(...)` | = note: expected type `m::E` found type `fn(u8) -> m::E {m::E::Fn}` diff --git a/src/test/ui/substs-ppaux.normal.stderr b/src/test/ui/substs-ppaux.normal.stderr index 123dd86b90549..b3b879ef9acbe 100644 --- a/src/test/ui/substs-ppaux.normal.stderr +++ b/src/test/ui/substs-ppaux.normal.stderr @@ -1,8 +1,14 @@ error[E0308]: mismatched types --> $DIR/substs-ppaux.rs:16:17 | +LL | fn bar<'a, T>() where T: 'a {} + | --------------------------- fn() {>::bar::<'static, char>} defined here +... LL | let x: () = >::bar::<'static, char>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found fn item + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected (), found fn item + | help: use parentheses to call this function: `>::bar::<'static, char>()` | = note: expected type `()` found type `fn() {>::bar::<'static, char>}` @@ -10,8 +16,14 @@ LL | let x: () = >::bar::<'static, char>; error[E0308]: mismatched types --> $DIR/substs-ppaux.rs:25:17 | +LL | fn bar<'a, T>() where T: 'a {} + | --------------------------- fn() {>::bar::<'static, char>} defined here +... LL | let x: () = >::bar::<'static, char>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found fn item + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected (), found fn item + | help: use parentheses to call this function: `>::bar::<'static, char>()` | = note: expected type `()` found type `fn() {>::bar::<'static, char>}` @@ -19,8 +31,14 @@ LL | let x: () = >::bar::<'static, char>; error[E0308]: mismatched types --> $DIR/substs-ppaux.rs:33:17 | +LL | fn baz() {} + | -------- fn() {>::baz} defined here +... LL | let x: () = >::baz; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found fn item + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected (), found fn item + | help: use parentheses to call this function: `>::baz()` | = note: expected type `()` found type `fn() {>::baz}` @@ -28,8 +46,14 @@ LL | let x: () = >::baz; error[E0308]: mismatched types --> $DIR/substs-ppaux.rs:41:17 | +LL | fn foo<'z>() where &'z (): Sized { + | -------------------------------- fn() {foo::<'static>} defined here +... LL | let x: () = foo::<'static>; - | ^^^^^^^^^^^^^^ expected (), found fn item + | ^^^^^^^^^^^^^^ + | | + | expected (), found fn item + | help: use parentheses to call this function: `foo::<'static>()` | = note: expected type `()` found type `fn() {foo::<'static>}` diff --git a/src/test/ui/substs-ppaux.verbose.stderr b/src/test/ui/substs-ppaux.verbose.stderr index 9167346282bab..363018db232d8 100644 --- a/src/test/ui/substs-ppaux.verbose.stderr +++ b/src/test/ui/substs-ppaux.verbose.stderr @@ -1,8 +1,14 @@ error[E0308]: mismatched types --> $DIR/substs-ppaux.rs:16:17 | +LL | fn bar<'a, T>() where T: 'a {} + | --------------------------- fn() {>::bar::} defined here +... LL | let x: () = >::bar::<'static, char>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found fn item + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected (), found fn item + | help: use parentheses to call this function: `>::bar::<'static, char>()` | = note: expected type `()` found type `fn() {>::bar::}` @@ -10,8 +16,14 @@ LL | let x: () = >::bar::<'static, char>; error[E0308]: mismatched types --> $DIR/substs-ppaux.rs:25:17 | +LL | fn bar<'a, T>() where T: 'a {} + | --------------------------- fn() {>::bar::} defined here +... LL | let x: () = >::bar::<'static, char>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found fn item + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected (), found fn item + | help: use parentheses to call this function: `>::bar::<'static, char>()` | = note: expected type `()` found type `fn() {>::bar::}` @@ -19,8 +31,14 @@ LL | let x: () = >::bar::<'static, char>; error[E0308]: mismatched types --> $DIR/substs-ppaux.rs:33:17 | +LL | fn baz() {} + | -------- fn() {>::baz} defined here +... LL | let x: () = >::baz; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found fn item + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected (), found fn item + | help: use parentheses to call this function: `>::baz()` | = note: expected type `()` found type `fn() {>::baz}` @@ -28,8 +46,14 @@ LL | let x: () = >::baz; error[E0308]: mismatched types --> $DIR/substs-ppaux.rs:41:17 | +LL | fn foo<'z>() where &'z (): Sized { + | -------------------------------- fn() {foo::} defined here +... LL | let x: () = foo::<'static>; - | ^^^^^^^^^^^^^^ expected (), found fn item + | ^^^^^^^^^^^^^^ + | | + | expected (), found fn item + | help: use parentheses to call this function: `foo::<'static>()` | = note: expected type `()` found type `fn() {foo::}` From 195d837f18e2efb7d621d6568212a59c29fc184e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 8 Aug 2019 12:01:22 -0700 Subject: [PATCH 10/23] When suggesting fn call use an appropriate number of placeholder arguments --- src/librustc_typeck/check/mod.rs | 43 ++++++--- src/test/ui/issues/issue-35241.stderr | 2 +- src/test/ui/resolve/privacy-enum-ctor.stderr | 6 +- .../fn-or-tuple-struct-without-args.rs | 20 ++++ .../fn-or-tuple-struct-without-args.stderr | 93 +++++++++++++++++++ 5 files changed, 148 insertions(+), 16 deletions(-) create mode 100644 src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs create mode 100644 src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 6600f83393857..130cc8f3a6050 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3833,19 +3833,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .0; let sig = self.normalize_associated_types_in(expr.span, &sig); if let Ok(_) = self.try_coerce(expr, sig.output(), expected, AllowTwoPhase::No) { - if let Ok(code) = self.sess().source_map().span_to_snippet(expr.span) { - err.span_suggestion(expr.span, "use parentheses to call this function", format!( - "{}({})", - code, - if sig.inputs().len() > 0 { - "..." - } else { - "" - }), if sig.inputs().len() > 0 { - Applicability::MachineApplicable - } else { - Applicability::HasPlaceholders + let (mut sugg_call, applicability) = if sig.inputs().is_empty() { + (String::new(), Applicability::MachineApplicable) + } else { + ("...".to_owned(), Applicability::HasPlaceholders) + }; + let mut msg = "call this function"; + if let ty::FnDef(def_id, ..) = found.sty { + match self.tcx.hir().get_if_local(def_id) { + Some(Node::Item(hir::Item { + node: ItemKind::Fn(.., body_id), + .. + })) => { + let body = self.tcx.hir().body(*body_id); + sugg_call = body.arguments.iter() + .map(|arg| hir::print::to_string( + hir::print::NO_ANN, + |s| s.print_pat(&arg.pat), + )).collect::>().join(", "); + } + Some(Node::Ctor(hir::VariantData::Tuple(field, _))) => { + sugg_call = field.iter().map(|_| "_").collect::>().join(", "); + msg = "instatiate this tuple struct"; } + _ => {} + } + }; + if let Ok(code) = self.sess().source_map().span_to_snippet(expr.span) { + err.span_suggestion( + expr.span, + &format!("use parentheses to {}", msg), + format!("{}({})", code, sugg_call), + applicability, ); return true; } diff --git a/src/test/ui/issues/issue-35241.stderr b/src/test/ui/issues/issue-35241.stderr index 248e6f0f46b19..8befc6873857e 100644 --- a/src/test/ui/issues/issue-35241.stderr +++ b/src/test/ui/issues/issue-35241.stderr @@ -8,7 +8,7 @@ LL | fn test() -> Foo { Foo } | --- ^^^ | | | | | expected struct `Foo`, found fn item - | | help: use parentheses to call this function: `Foo(...)` + | | help: use parentheses to instatiate this tuple struct: `Foo(_)` | expected `Foo` because of return type | = note: expected type `Foo` diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr index 07cbffb009406..49092562feeba 100644 --- a/src/test/ui/resolve/privacy-enum-ctor.stderr +++ b/src/test/ui/resolve/privacy-enum-ctor.stderr @@ -202,7 +202,7 @@ LL | let _: Z = Z::Fn; | ^^^^^ | | | expected enum `m::n::Z`, found fn item - | help: use parentheses to call this function: `Z::Fn(...)` + | help: use parentheses to instatiate this tuple struct: `Z::Fn(_)` | = note: expected type `m::n::Z` found type `fn(u8) -> m::n::Z {m::n::Z::Fn}` @@ -232,7 +232,7 @@ LL | let _: E = m::E::Fn; | ^^^^^^^^ | | | expected enum `m::E`, found fn item - | help: use parentheses to call this function: `m::E::Fn(...)` + | help: use parentheses to instatiate this tuple struct: `m::E::Fn(_)` | = note: expected type `m::E` found type `fn(u8) -> m::E {m::E::Fn}` @@ -262,7 +262,7 @@ LL | let _: E = E::Fn; | ^^^^^ | | | expected enum `m::E`, found fn item - | help: use parentheses to call this function: `E::Fn(...)` + | help: use parentheses to instatiate this tuple struct: `E::Fn(_)` | = note: expected type `m::E` found type `fn(u8) -> m::E {m::E::Fn}` diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs new file mode 100644 index 0000000000000..6758c1d5f238e --- /dev/null +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs @@ -0,0 +1,20 @@ +fn foo(a: usize, b: usize) -> usize { a } + +fn bar() -> usize { 42 } + +struct S(usize, usize); +struct V(); + +trait T { + fn baz(x: usize, y: usize) -> usize { x } + fn bat() -> usize { 42 } +} + +fn main() { + let _: usize = foo; //~ ERROR mismatched types + let _: S = S; //~ ERROR mismatched types + let _: usize = bar; //~ ERROR mismatched types + let _: V = V; //~ ERROR mismatched types + let _: usize = T::baz; //~ ERROR mismatched types + let _: usize = T::bat; //~ ERROR mismatched types +} diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr new file mode 100644 index 0000000000000..524c779979e3b --- /dev/null +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr @@ -0,0 +1,93 @@ +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:14:20 + | +LL | fn foo(a: usize, b: usize) -> usize { a } + | ----------------------------------- fn(usize, usize) -> usize {foo} defined here +... +LL | let _: usize = foo; + | ^^^ + | | + | expected usize, found fn item + | help: use parentheses to call this function: `foo(a, b)` + | + = note: expected type `usize` + found type `fn(usize, usize) -> usize {foo}` + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:15:16 + | +LL | struct S(usize, usize); + | ----------------------- fn(usize, usize) -> S {S} defined here +... +LL | let _: S = S; + | ^ + | | + | expected struct `S`, found fn item + | help: use parentheses to instatiate this tuple struct: `S(_, _)` + | + = note: expected type `S` + found type `fn(usize, usize) -> S {S}` + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:16:20 + | +LL | fn bar() -> usize { 42 } + | ----------------- fn() -> usize {bar} defined here +... +LL | let _: usize = bar; + | ^^^ + | | + | expected usize, found fn item + | help: use parentheses to call this function: `bar()` + | + = note: expected type `usize` + found type `fn() -> usize {bar}` + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:17:16 + | +LL | struct V(); + | ----------- fn() -> V {V} defined here +... +LL | let _: V = V; + | ^ + | | + | expected struct `V`, found fn item + | help: use parentheses to instatiate this tuple struct: `V()` + | + = note: expected type `V` + found type `fn() -> V {V}` + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:18:20 + | +LL | fn baz(x: usize, y: usize) -> usize { x } + | ----------------------------------- fn(usize, usize) -> usize {<_ as T>::baz} defined here +... +LL | let _: usize = T::baz; + | ^^^^^^ + | | + | expected usize, found fn item + | help: use parentheses to call this function: `T::baz(...)` + | + = note: expected type `usize` + found type `fn(usize, usize) -> usize {<_ as T>::baz}` + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:19:20 + | +LL | fn bat() -> usize { 42 } + | ----------------- fn() -> usize {<_ as T>::bat} defined here +... +LL | let _: usize = T::bat; + | ^^^^^^ + | | + | expected usize, found fn item + | help: use parentheses to call this function: `T::bat()` + | + = note: expected type `usize` + found type `fn() -> usize {<_ as T>::bat}` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. From b7f7756566c9e10983ee51bc97afe9852838299a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 8 Aug 2019 12:31:24 -0700 Subject: [PATCH 11/23] Recover parser from `foo(_, _)` --- src/libsyntax/parse/parser.rs | 70 +++++++++++++------ src/test/ui/issues/issue-34334.rs | 1 + src/test/ui/issues/issue-34334.stderr | 10 ++- ...fn-or-tuple-struct-with-underscore-args.rs | 19 +++++ ...r-tuple-struct-with-underscore-args.stderr | 38 ++++++++++ 5 files changed, 116 insertions(+), 22 deletions(-) create mode 100644 src/test/ui/suggestions/fn-or-tuple-struct-with-underscore-args.rs create mode 100644 src/test/ui/suggestions/fn-or-tuple-struct-with-underscore-args.stderr diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d85c2df16a350..30e16592113b6 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2052,9 +2052,23 @@ impl<'a> Parser<'a> { while self.token != token::CloseDelim(token::Paren) { es.push(match self.parse_expr() { Ok(es) => es, - Err(err) => { + Err(mut err) => { // recover from parse error in tuple list - return Ok(self.recover_seq_parse_error(token::Paren, lo, Err(err))); + match self.token.kind { + token::Ident(name, false) + if name == kw::Underscore && self.look_ahead(1, |t| { + t == &token::Comma + }) => { + // Special-case handling of `Foo<(_, _, _)>` + err.emit(); + let sp = self.token.span; + self.bump(); + self.mk_expr(sp, ExprKind::Err, ThinVec::new()) + } + _ => return Ok( + self.recover_seq_parse_error(token::Paren, lo, Err(err)), + ), + } } }); recovered = self.expect_one_of( @@ -2456,9 +2470,10 @@ impl<'a> Parser<'a> { } /// Parses `a.b` or `a(13)` or `a[4]` or just `a`. - fn parse_dot_or_call_expr(&mut self, - already_parsed_attrs: Option>) - -> PResult<'a, P> { + fn parse_dot_or_call_expr( + &mut self, + already_parsed_attrs: Option>, + ) -> PResult<'a, P> { let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?; let b = self.parse_bottom_expr(); @@ -2466,16 +2481,16 @@ impl<'a> Parser<'a> { self.parse_dot_or_call_expr_with(b, span, attrs) } - fn parse_dot_or_call_expr_with(&mut self, - e0: P, - lo: Span, - mut attrs: ThinVec) - -> PResult<'a, P> { + fn parse_dot_or_call_expr_with( + &mut self, + e0: P, + lo: Span, + mut attrs: ThinVec, + ) -> PResult<'a, P> { // Stitch the list of outer attributes onto the return value. // A little bit ugly, but the best way given the current code // structure - self.parse_dot_or_call_expr_with_(e0, lo) - .map(|expr| + self.parse_dot_or_call_expr_with_(e0, lo).map(|expr| expr.map(|mut expr| { attrs.extend::>(expr.attrs.into()); expr.attrs = attrs; @@ -2483,10 +2498,7 @@ impl<'a> Parser<'a> { ExprKind::If(..) if !expr.attrs.is_empty() => { // Just point to the first attribute in there... let span = expr.attrs[0].span; - - self.span_err(span, - "attributes are not yet allowed on `if` \ - expressions"); + self.span_err(span, "attributes are not yet allowed on `if` expressions"); } _ => {} } @@ -2624,7 +2636,24 @@ impl<'a> Parser<'a> { } fn parse_paren_expr_seq(&mut self) -> PResult<'a, Vec>> { - self.parse_paren_comma_seq(|p| p.parse_expr()).map(|(r, _)| r) + self.parse_paren_comma_seq(|p| { + match p.parse_expr() { + Ok(expr) => Ok(expr), + Err(mut err) => match p.token.kind { + token::Ident(name, false) + if name == kw::Underscore && p.look_ahead(1, |t| { + t == &token::Comma + }) => { + // Special-case handling of `foo(_, _, _)` + err.emit(); + let sp = p.token.span; + p.bump(); + Ok(p.mk_expr(sp, ExprKind::Err, ThinVec::new())) + } + _ => Err(err), + }, + } + }).map(|(r, _)| r) } crate fn process_potential_macro_variable(&mut self) { @@ -2806,9 +2835,10 @@ impl<'a> Parser<'a> { /// This parses an expression accounting for associativity and precedence of the operators in /// the expression. #[inline] - fn parse_assoc_expr(&mut self, - already_parsed_attrs: Option>) - -> PResult<'a, P> { + fn parse_assoc_expr( + &mut self, + already_parsed_attrs: Option>, + ) -> PResult<'a, P> { self.parse_assoc_expr_with(0, already_parsed_attrs.into()) } diff --git a/src/test/ui/issues/issue-34334.rs b/src/test/ui/issues/issue-34334.rs index 928d217441ef2..4457d71cbb4a7 100644 --- a/src/test/ui/issues/issue-34334.rs +++ b/src/test/ui/issues/issue-34334.rs @@ -5,6 +5,7 @@ fn main () { //~| ERROR mismatched types //~| ERROR invalid left-hand side expression //~| ERROR expected expression, found reserved identifier `_` + //~| ERROR expected expression, found reserved identifier `_` let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect(); //~^ ERROR no method named `iter` found for type `()` in the current scope } diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr index e8386fd8de9e5..7f89caf92abe1 100644 --- a/src/test/ui/issues/issue-34334.stderr +++ b/src/test/ui/issues/issue-34334.stderr @@ -4,6 +4,12 @@ error: expected expression, found reserved identifier `_` LL | let sr: Vec<(u32, _, _) = vec![]; | ^ expected expression +error: expected expression, found reserved identifier `_` + --> $DIR/issue-34334.rs:2:26 + | +LL | let sr: Vec<(u32, _, _) = vec![]; + | ^ expected expression + error: expected one of `,` or `>`, found `=` --> $DIR/issue-34334.rs:2:29 | @@ -36,12 +42,12 @@ LL | let sr: Vec<(u32, _, _) = vec![]; | ^^^^^^^^^^^^^^^^^^^^^^^^ left-hand of expression not valid error[E0599]: no method named `iter` found for type `()` in the current scope - --> $DIR/issue-34334.rs:8:36 + --> $DIR/issue-34334.rs:9:36 | LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect(); | ^^^^ -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0070, E0308, E0423, E0599. For more information about an error, try `rustc --explain E0070`. diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-with-underscore-args.rs b/src/test/ui/suggestions/fn-or-tuple-struct-with-underscore-args.rs new file mode 100644 index 0000000000000..a8ea3faefe876 --- /dev/null +++ b/src/test/ui/suggestions/fn-or-tuple-struct-with-underscore-args.rs @@ -0,0 +1,19 @@ +fn foo(a: usize, b: usize) -> usize { a } + +struct S(usize, usize); + +trait T { + fn baz(x: usize, y: usize) -> usize { x } +} + +fn main() { + let _: usize = foo(_, _); + //~^ ERROR expected expression + //~| ERROR expected expression + let _: S = S(_, _); + //~^ ERROR expected expression + //~| ERROR expected expression + let _: usize = T::baz(_, _); + //~^ ERROR expected expression + //~| ERROR expected expression +} diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-with-underscore-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-with-underscore-args.stderr new file mode 100644 index 0000000000000..a6d1c4b859f2f --- /dev/null +++ b/src/test/ui/suggestions/fn-or-tuple-struct-with-underscore-args.stderr @@ -0,0 +1,38 @@ +error: expected expression, found reserved identifier `_` + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:10:24 + | +LL | let _: usize = foo(_, _); + | ^ expected expression + +error: expected expression, found reserved identifier `_` + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:10:27 + | +LL | let _: usize = foo(_, _); + | ^ expected expression + +error: expected expression, found reserved identifier `_` + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:13:18 + | +LL | let _: S = S(_, _); + | ^ expected expression + +error: expected expression, found reserved identifier `_` + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:13:21 + | +LL | let _: S = S(_, _); + | ^ expected expression + +error: expected expression, found reserved identifier `_` + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:16:27 + | +LL | let _: usize = T::baz(_, _); + | ^ expected expression + +error: expected expression, found reserved identifier `_` + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:16:30 + | +LL | let _: usize = T::baz(_, _); + | ^ expected expression + +error: aborting due to 6 previous errors + From 0d53f699eaa7d1fec1e6013a6a42b39992c119d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 8 Aug 2019 12:32:18 -0700 Subject: [PATCH 12/23] review comments --- src/librustc_typeck/check/expr.rs | 13 ++--- src/librustc_typeck/check/mod.rs | 89 +++++++++++++++++-------------- 2 files changed, 56 insertions(+), 46 deletions(-) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 5c859b9fd3254..9680f61d69903 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -550,18 +550,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { assert!(e_ty.is_unit()); let ty = coerce.expected_ty(); coerce.coerce_forced_unit(self, &cause, &mut |err| { - let msg = "give it a value of the expected type"; - let label = destination.label - .map(|l| format!(" {}", l.ident)) - .unwrap_or_else(String::new); - let sugg = format!("break{} {}", label, match ty.sty { + let val = match ty.sty { ty::Bool => "true", ty::Char => "'a'", ty::Int(_) | ty::Uint(_) => "42", ty::Float(_) => "3.14159", ty::Error | ty::Never => return, _ => "value", - }); + }; + let msg = "give it a value of the expected type"; + let label = destination.label + .map(|l| format!(" {}", l.ident)) + .unwrap_or_else(String::new); + let sugg = format!("break{} {}", label, val); err.span_suggestion(expr.span, msg, sugg, Applicability::HasPlaceholders); }, false); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 130cc8f3a6050..be2af2db66d59 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3819,6 +3819,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pointing_at_return_type } + /// When encountering an fn-like ctor that needs to unify with a value, check whether calling + /// the ctor would successfully solve the type mismatch and if so, suggest it: + /// ``` + /// fn foo(x: usize) -> usize { x } + /// let x: usize = foo; // suggest calling the `foo` function: `foo(42)` + /// ``` fn suggest_fn_call( &self, err: &mut DiagnosticBuilder<'tcx>, @@ -3826,48 +3832,51 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, found: Ty<'tcx>, ) -> bool { - if let ty::FnDef(..) | ty::FnPtr(_) = &found.sty { - let sig = found.fn_sig(self.tcx); - let sig = self - .replace_bound_vars_with_fresh_vars(expr.span, infer::FnCall, &sig) - .0; - let sig = self.normalize_associated_types_in(expr.span, &sig); - if let Ok(_) = self.try_coerce(expr, sig.output(), expected, AllowTwoPhase::No) { - let (mut sugg_call, applicability) = if sig.inputs().is_empty() { - (String::new(), Applicability::MachineApplicable) - } else { - ("...".to_owned(), Applicability::HasPlaceholders) - }; - let mut msg = "call this function"; - if let ty::FnDef(def_id, ..) = found.sty { - match self.tcx.hir().get_if_local(def_id) { - Some(Node::Item(hir::Item { - node: ItemKind::Fn(.., body_id), - .. - })) => { - let body = self.tcx.hir().body(*body_id); - sugg_call = body.arguments.iter() - .map(|arg| hir::print::to_string( - hir::print::NO_ANN, - |s| s.print_pat(&arg.pat), - )).collect::>().join(", "); - } - Some(Node::Ctor(hir::VariantData::Tuple(field, _))) => { - sugg_call = field.iter().map(|_| "_").collect::>().join(", "); - msg = "instatiate this tuple struct"; - } - _ => {} + match found.sty { + ty::FnDef(..) | ty::FnPtr(_) => {} + _ => return false, + } + + let sig = found.fn_sig(self.tcx); + let sig = self + .replace_bound_vars_with_fresh_vars(expr.span, infer::FnCall, &sig) + .0; + let sig = self.normalize_associated_types_in(expr.span, &sig); + if let Ok(_) = self.try_coerce(expr, sig.output(), expected, AllowTwoPhase::No) { + let (mut sugg_call, applicability) = if sig.inputs().is_empty() { + (String::new(), Applicability::MachineApplicable) + } else { + ("...".to_owned(), Applicability::HasPlaceholders) + }; + let mut msg = "call this function"; + if let ty::FnDef(def_id, ..) = found.sty { + match self.tcx.hir().get_if_local(def_id) { + Some(Node::Item(hir::Item { + node: ItemKind::Fn(.., body_id), + .. + })) => { + let body = self.tcx.hir().body(*body_id); + sugg_call = body.arguments.iter() + .map(|arg| hir::print::to_string( + hir::print::NO_ANN, + |s| s.print_pat(&arg.pat), + )).collect::>().join(", "); } - }; - if let Ok(code) = self.sess().source_map().span_to_snippet(expr.span) { - err.span_suggestion( - expr.span, - &format!("use parentheses to {}", msg), - format!("{}({})", code, sugg_call), - applicability, - ); - return true; + Some(Node::Ctor(hir::VariantData::Tuple(field, _))) => { + sugg_call = field.iter().map(|_| "_").collect::>().join(", "); + msg = "instatiate this tuple struct"; + } + _ => {} } + }; + if let Ok(code) = self.sess().source_map().span_to_snippet(expr.span) { + err.span_suggestion( + expr.span, + &format!("use parentheses to {}", msg), + format!("{}({})", code, sugg_call), + applicability, + ); + return true; } } false From efa62d66e36306fba6025528aee381dd165fa8bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 8 Aug 2019 14:53:00 -0700 Subject: [PATCH 13/23] Tweak wording of fn without explicit return --- src/librustc_typeck/check/mod.rs | 5 ++++- .../ui/block-result/consider-removing-last-semi.stderr | 4 ++-- src/test/ui/block-result/issue-11714.stderr | 2 +- src/test/ui/block-result/issue-13428.stderr | 4 ++-- .../coercion/coercion-missing-tail-expected-type.stderr | 4 ++-- src/test/ui/issues/issue-32323.stderr | 2 +- src/test/ui/issues/issue-43162.stderr | 2 +- src/test/ui/issues/issue-44023.stderr | 2 +- src/test/ui/issues/issue-6458-4.stderr | 2 +- src/test/ui/liveness/liveness-forgot-ret.stderr | 2 +- src/test/ui/liveness/liveness-missing-ret2.stderr | 2 +- .../ui/liveness/liveness-return-last-stmt-semi.stderr | 8 ++++---- src/test/ui/missing/missing-return.stderr | 2 +- src/test/ui/parser/issue-62881.stderr | 2 +- src/test/ui/parser/issue-62895.stderr | 2 +- 15 files changed, 24 insertions(+), 21 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index be2af2db66d59..726922c8e5346 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3709,7 +3709,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.consider_hint_about_removing_semicolon(blk, expected_ty, err); } if let Some(fn_span) = fn_span { - err.span_label(fn_span, "this function's body doesn't return a value"); + err.span_label( + fn_span, + "this function's body doesn't `return` a value", + ); } }, false); } diff --git a/src/test/ui/block-result/consider-removing-last-semi.stderr b/src/test/ui/block-result/consider-removing-last-semi.stderr index 7f8bb67c946e6..f3dfc8b12eafe 100644 --- a/src/test/ui/block-result/consider-removing-last-semi.stderr +++ b/src/test/ui/block-result/consider-removing-last-semi.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn f() -> String { | - ^^^^^^ expected struct `std::string::String`, found () | | - | this function's body doesn't return a value + | this function's body doesn't `return` a value LL | 0u8; LL | "bla".to_string(); | - help: consider removing this semicolon @@ -18,7 +18,7 @@ error[E0308]: mismatched types LL | fn g() -> String { | - ^^^^^^ expected struct `std::string::String`, found () | | - | this function's body doesn't return a value + | this function's body doesn't `return` a value LL | "this won't work".to_string(); LL | "removeme".to_string(); | - help: consider removing this semicolon diff --git a/src/test/ui/block-result/issue-11714.stderr b/src/test/ui/block-result/issue-11714.stderr index 569e012540c4f..021a25ece2f4d 100644 --- a/src/test/ui/block-result/issue-11714.stderr +++ b/src/test/ui/block-result/issue-11714.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn blah() -> i32 { | ---- ^^^ expected i32, found () | | - | this function's body doesn't return a value + | this function's body doesn't `return` a value ... LL | ; | - help: consider removing this semicolon diff --git a/src/test/ui/block-result/issue-13428.stderr b/src/test/ui/block-result/issue-13428.stderr index ca48910026d9a..8fa6ae9c528b4 100644 --- a/src/test/ui/block-result/issue-13428.stderr +++ b/src/test/ui/block-result/issue-13428.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn foo() -> String { | --- ^^^^^^ expected struct `std::string::String`, found () | | - | this function's body doesn't return a value + | this function's body doesn't `return` a value ... LL | ; | - help: consider removing this semicolon @@ -18,7 +18,7 @@ error[E0308]: mismatched types LL | fn bar() -> String { | --- ^^^^^^ expected struct `std::string::String`, found () | | - | this function's body doesn't return a value + | this function's body doesn't `return` a value LL | "foobar".to_string() LL | ; | - help: consider removing this semicolon diff --git a/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr b/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr index a7ac930ba670e..6ecb1d3eaef4a 100644 --- a/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr +++ b/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn plus_one(x: i32) -> i32 { | -------- ^^^ expected i32, found () | | - | this function's body doesn't return a value + | this function's body doesn't `return` a value LL | x + 1; | - help: consider removing this semicolon | @@ -17,7 +17,7 @@ error[E0308]: mismatched types LL | fn foo() -> Result { | --- ^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found () | | - | this function's body doesn't return a value + | this function's body doesn't `return` a value LL | Ok(1); | - help: consider removing this semicolon | diff --git a/src/test/ui/issues/issue-32323.stderr b/src/test/ui/issues/issue-32323.stderr index 6b8bca078b5e6..376676bda7dbf 100644 --- a/src/test/ui/issues/issue-32323.stderr +++ b/src/test/ui/issues/issue-32323.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | pub fn f<'a, T: Tr<'a>>() -> >::Out {} | - ^^^^^^^^^^^^^^^^^^ expected associated type, found () | | - | this function's body doesn't return a value + | this function's body doesn't `return` a value | = note: expected type `>::Out` found type `()` diff --git a/src/test/ui/issues/issue-43162.stderr b/src/test/ui/issues/issue-43162.stderr index fd62ac30ab195..22d347778c8f4 100644 --- a/src/test/ui/issues/issue-43162.stderr +++ b/src/test/ui/issues/issue-43162.stderr @@ -16,7 +16,7 @@ error[E0308]: mismatched types LL | fn foo() -> bool { | --- ^^^^ expected bool, found () | | - | this function's body doesn't return a value + | this function's body doesn't `return` a value LL | LL | break true; | - help: consider removing this semicolon diff --git a/src/test/ui/issues/issue-44023.stderr b/src/test/ui/issues/issue-44023.stderr index cad202129a719..7760af8145b07 100644 --- a/src/test/ui/issues/issue-44023.stderr +++ b/src/test/ui/issues/issue-44023.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn საჭმელად_გემრიელი_სადილი ( ) -> isize { | ------------------------ ^^^^^ expected isize, found () | | - | this function's body doesn't return a value + | this function's body doesn't `return` a value | = note: expected type `isize` found type `()` diff --git a/src/test/ui/issues/issue-6458-4.stderr b/src/test/ui/issues/issue-6458-4.stderr index d4f5b2ba41f69..e29be76087416 100644 --- a/src/test/ui/issues/issue-6458-4.stderr +++ b/src/test/ui/issues/issue-6458-4.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn foo(b: bool) -> Result { | --- ^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found () | | - | this function's body doesn't return a value + | this function's body doesn't `return` a value LL | Err("bar".to_string()); | - help: consider removing this semicolon | diff --git a/src/test/ui/liveness/liveness-forgot-ret.stderr b/src/test/ui/liveness/liveness-forgot-ret.stderr index 6d917393663b0..68cbdb2cfdba6 100644 --- a/src/test/ui/liveness/liveness-forgot-ret.stderr +++ b/src/test/ui/liveness/liveness-forgot-ret.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; } | - ^^^^^ expected isize, found () | | - | this function's body doesn't return a value + | this function's body doesn't `return` a value | = note: expected type `isize` found type `()` diff --git a/src/test/ui/liveness/liveness-missing-ret2.stderr b/src/test/ui/liveness/liveness-missing-ret2.stderr index a71b9296702b7..62e0aa5d29d95 100644 --- a/src/test/ui/liveness/liveness-missing-ret2.stderr +++ b/src/test/ui/liveness/liveness-missing-ret2.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn f() -> isize { | - ^^^^^ expected isize, found () | | - | this function's body doesn't return a value + | this function's body doesn't `return` a value | = note: expected type `isize` found type `()` diff --git a/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr b/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr index 3a08699170643..c5018af74f347 100644 --- a/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr +++ b/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr @@ -5,7 +5,7 @@ LL | macro_rules! test { () => { fn foo() -> i32 { 1; } } } | --- ^^^ - help: consider removing this semicolon | | | | | expected i32, found () - | this function's body doesn't return a value + | this function's body doesn't `return` a value ... LL | test!(); | -------- in this macro invocation @@ -19,7 +19,7 @@ error[E0308]: mismatched types LL | fn no_return() -> i32 {} | --------- ^^^ expected i32, found () | | - | this function's body doesn't return a value + | this function's body doesn't `return` a value | = note: expected type `i32` found type `()` @@ -30,7 +30,7 @@ error[E0308]: mismatched types LL | fn bar(x: u32) -> u32 { | --- ^^^ expected u32, found () | | - | this function's body doesn't return a value + | this function's body doesn't `return` a value LL | x * 2; | - help: consider removing this semicolon | @@ -43,7 +43,7 @@ error[E0308]: mismatched types LL | fn baz(x: u64) -> u32 { | --- ^^^ expected u32, found () | | - | this function's body doesn't return a value + | this function's body doesn't `return` a value | = note: expected type `u32` found type `()` diff --git a/src/test/ui/missing/missing-return.stderr b/src/test/ui/missing/missing-return.stderr index c7d7116a9cd7c..4cd516ba81d6a 100644 --- a/src/test/ui/missing/missing-return.stderr +++ b/src/test/ui/missing/missing-return.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn f() -> isize { } | - ^^^^^ expected isize, found () | | - | this function's body doesn't return a value + | this function's body doesn't `return` a value | = note: expected type `isize` found type `()` diff --git a/src/test/ui/parser/issue-62881.stderr b/src/test/ui/parser/issue-62881.stderr index b2e2da35a2700..11b8836a89a76 100644 --- a/src/test/ui/parser/issue-62881.stderr +++ b/src/test/ui/parser/issue-62881.stderr @@ -19,7 +19,7 @@ error[E0308]: mismatched types LL | fn f() -> isize { fn f() -> isize {} pub f< | - ^^^^^ expected isize, found () | | - | this function's body doesn't return a value + | this function's body doesn't `return` a value | = note: expected type `isize` found type `()` diff --git a/src/test/ui/parser/issue-62895.stderr b/src/test/ui/parser/issue-62895.stderr index 6c3a8fb766c0a..d9d3baf622708 100644 --- a/src/test/ui/parser/issue-62895.stderr +++ b/src/test/ui/parser/issue-62895.stderr @@ -38,7 +38,7 @@ error[E0308]: mismatched types LL | fn v() -> isize { | - ^^^^^ expected isize, found () | | - | this function's body doesn't return a value + | this function's body doesn't `return` a value | = note: expected type `isize` found type `()` From 52da091ee687f3d065713626a10b4cc961f04f75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 8 Aug 2019 14:59:24 -0700 Subject: [PATCH 14/23] Differentiate between tuple structs and tuple variants --- src/librustc/hir/map/mod.rs | 2 +- src/librustc_typeck/check/mod.rs | 29 ++++++++----- src/test/ui/resolve/privacy-enum-ctor.stderr | 6 +-- .../fn-or-tuple-struct-without-args.rs | 6 +++ .../fn-or-tuple-struct-without-args.stderr | 41 +++++++++++++++---- 5 files changed, 62 insertions(+), 22 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 0d477ae796822..b85738dd29a6d 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -287,7 +287,7 @@ impl<'hir> Map<'hir> { self.definitions.def_index_to_hir_id(def_id.to_def_id().index) } - fn def_kind(&self, hir_id: HirId) -> Option { + pub fn def_kind(&self, hir_id: HirId) -> Option { let node = if let Some(node) = self.find(hir_id) { node } else { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 726922c8e5346..629b8da355e23 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3839,6 +3839,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::FnDef(..) | ty::FnPtr(_) => {} _ => return false, } + let hir = self.tcx.hir(); let sig = found.fn_sig(self.tcx); let sig = self @@ -3849,25 +3850,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (mut sugg_call, applicability) = if sig.inputs().is_empty() { (String::new(), Applicability::MachineApplicable) } else { - ("...".to_owned(), Applicability::HasPlaceholders) + ("...".to_string(), Applicability::HasPlaceholders) }; let mut msg = "call this function"; if let ty::FnDef(def_id, ..) = found.sty { - match self.tcx.hir().get_if_local(def_id) { + match hir.get_if_local(def_id) { Some(Node::Item(hir::Item { node: ItemKind::Fn(.., body_id), .. })) => { - let body = self.tcx.hir().body(*body_id); + let body = hir.body(*body_id); sugg_call = body.arguments.iter() - .map(|arg| hir::print::to_string( - hir::print::NO_ANN, - |s| s.print_pat(&arg.pat), - )).collect::>().join(", "); + .map(|arg| match &arg.pat.node { + hir::PatKind::Binding(_, _, ident, None) => ident.to_string(), + _ => "_".to_string(), + }).collect::>().join(", "); } - Some(Node::Ctor(hir::VariantData::Tuple(field, _))) => { - sugg_call = field.iter().map(|_| "_").collect::>().join(", "); - msg = "instatiate this tuple struct"; + Some(Node::Ctor(hir::VariantData::Tuple(fields, _))) => { + sugg_call = fields.iter().map(|_| "_").collect::>().join(", "); + match hir.as_local_hir_id(def_id).and_then(|hir_id| hir.def_kind(hir_id)) { + Some(hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, _)) => { + msg = "instatiate this tuple variant"; + } + Some(hir::def::DefKind::Ctor(hir::def::CtorOf::Struct, _)) => { + msg = "instatiate this tuple struct"; + } + _ => {} + } } _ => {} } diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr index 49092562feeba..3e924f7d161bd 100644 --- a/src/test/ui/resolve/privacy-enum-ctor.stderr +++ b/src/test/ui/resolve/privacy-enum-ctor.stderr @@ -202,7 +202,7 @@ LL | let _: Z = Z::Fn; | ^^^^^ | | | expected enum `m::n::Z`, found fn item - | help: use parentheses to instatiate this tuple struct: `Z::Fn(_)` + | help: use parentheses to instatiate this tuple variant: `Z::Fn(_)` | = note: expected type `m::n::Z` found type `fn(u8) -> m::n::Z {m::n::Z::Fn}` @@ -232,7 +232,7 @@ LL | let _: E = m::E::Fn; | ^^^^^^^^ | | | expected enum `m::E`, found fn item - | help: use parentheses to instatiate this tuple struct: `m::E::Fn(_)` + | help: use parentheses to instatiate this tuple variant: `m::E::Fn(_)` | = note: expected type `m::E` found type `fn(u8) -> m::E {m::E::Fn}` @@ -262,7 +262,7 @@ LL | let _: E = E::Fn; | ^^^^^ | | | expected enum `m::E`, found fn item - | help: use parentheses to instatiate this tuple struct: `E::Fn(_)` + | help: use parentheses to instatiate this tuple variant: `E::Fn(_)` | = note: expected type `m::E` found type `fn(u8) -> m::E {m::E::Fn}` diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs index 6758c1d5f238e..838ef78e4fd6a 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs @@ -3,6 +3,10 @@ fn foo(a: usize, b: usize) -> usize { a } fn bar() -> usize { 42 } struct S(usize, usize); +enum E { + A(usize), + B { a: usize }, +} struct V(); trait T { @@ -17,4 +21,6 @@ fn main() { let _: V = V; //~ ERROR mismatched types let _: usize = T::baz; //~ ERROR mismatched types let _: usize = T::bat; //~ ERROR mismatched types + let _: E = E::A; //~ ERROR mismatched types + let _: E = E::B; //~ ERROR expected value, found struct variant `E::B` } diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr index 524c779979e3b..cb128822fcce8 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr @@ -1,5 +1,14 @@ +error[E0423]: expected value, found struct variant `E::B` + --> $DIR/fn-or-tuple-struct-without-args.rs:25:16 + | +LL | let _: E = E::B; + | ^^^- + | | | + | | help: a tuple variant with a similar name exists: `A` + | did you mean `E::B { /* fields */ }`? + error[E0308]: mismatched types - --> $DIR/fn-or-tuple-struct-without-args.rs:14:20 + --> $DIR/fn-or-tuple-struct-without-args.rs:18:20 | LL | fn foo(a: usize, b: usize) -> usize { a } | ----------------------------------- fn(usize, usize) -> usize {foo} defined here @@ -14,7 +23,7 @@ LL | let _: usize = foo; found type `fn(usize, usize) -> usize {foo}` error[E0308]: mismatched types - --> $DIR/fn-or-tuple-struct-without-args.rs:15:16 + --> $DIR/fn-or-tuple-struct-without-args.rs:19:16 | LL | struct S(usize, usize); | ----------------------- fn(usize, usize) -> S {S} defined here @@ -29,7 +38,7 @@ LL | let _: S = S; found type `fn(usize, usize) -> S {S}` error[E0308]: mismatched types - --> $DIR/fn-or-tuple-struct-without-args.rs:16:20 + --> $DIR/fn-or-tuple-struct-without-args.rs:20:20 | LL | fn bar() -> usize { 42 } | ----------------- fn() -> usize {bar} defined here @@ -44,7 +53,7 @@ LL | let _: usize = bar; found type `fn() -> usize {bar}` error[E0308]: mismatched types - --> $DIR/fn-or-tuple-struct-without-args.rs:17:16 + --> $DIR/fn-or-tuple-struct-without-args.rs:21:16 | LL | struct V(); | ----------- fn() -> V {V} defined here @@ -59,7 +68,7 @@ LL | let _: V = V; found type `fn() -> V {V}` error[E0308]: mismatched types - --> $DIR/fn-or-tuple-struct-without-args.rs:18:20 + --> $DIR/fn-or-tuple-struct-without-args.rs:22:20 | LL | fn baz(x: usize, y: usize) -> usize { x } | ----------------------------------- fn(usize, usize) -> usize {<_ as T>::baz} defined here @@ -74,7 +83,7 @@ LL | let _: usize = T::baz; found type `fn(usize, usize) -> usize {<_ as T>::baz}` error[E0308]: mismatched types - --> $DIR/fn-or-tuple-struct-without-args.rs:19:20 + --> $DIR/fn-or-tuple-struct-without-args.rs:23:20 | LL | fn bat() -> usize { 42 } | ----------------- fn() -> usize {<_ as T>::bat} defined here @@ -88,6 +97,22 @@ LL | let _: usize = T::bat; = note: expected type `usize` found type `fn() -> usize {<_ as T>::bat}` -error: aborting due to 6 previous errors +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:24:16 + | +LL | A(usize), + | -------- fn(usize) -> E {E::A} defined here +... +LL | let _: E = E::A; + | ^^^^ + | | + | expected enum `E`, found fn item + | help: use parentheses to instatiate this tuple variant: `E::A(_)` + | + = note: expected type `E` + found type `fn(usize) -> E {E::A}` + +error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0308, E0423. +For more information about an error, try `rustc --explain E0308`. From 5a54945b6f637eadd4848874db39b49d2764839f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 8 Aug 2019 15:53:32 -0700 Subject: [PATCH 15/23] Extend suggestion support for traits and foreign items --- src/librustc_typeck/check/mod.rs | 25 +++- .../fn-or-tuple-struct-without-args.rs | 21 ++- .../fn-or-tuple-struct-without-args.stderr | 132 ++++++++++++++++-- 3 files changed, 161 insertions(+), 17 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 629b8da355e23..d389563aea639 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3858,11 +3858,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(Node::Item(hir::Item { node: ItemKind::Fn(.., body_id), .. + })) | + Some(Node::ImplItem(hir::ImplItem { + node: hir::ImplItemKind::Method(_, body_id), + .. + })) | + Some(Node::TraitItem(hir::TraitItem { + node: hir::TraitItemKind::Method(.., hir::TraitMethod::Provided(body_id)), + .. })) => { let body = hir.body(*body_id); sugg_call = body.arguments.iter() .map(|arg| match &arg.pat.node { - hir::PatKind::Binding(_, _, ident, None) => ident.to_string(), + hir::PatKind::Binding(_, _, ident, None) + if ident.name != kw::SelfLower => ident.to_string(), _ => "_".to_string(), }).collect::>().join(", "); } @@ -3878,6 +3887,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => {} } } + Some(Node::ForeignItem(hir::ForeignItem { + node: hir::ForeignItemKind::Fn(_, idents, _), + .. + })) | + Some(Node::TraitItem(hir::TraitItem { + node: hir::TraitItemKind::Method(.., hir::TraitMethod::Required(idents)), + .. + })) => sugg_call = idents.iter() + .map(|ident| if ident.name != kw::SelfLower { + ident.to_string() + } else { + "_".to_string() + }).collect::>() + .join(", "), _ => {} } }; diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs index 838ef78e4fd6a..9b6b10748172b 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs @@ -11,7 +11,18 @@ struct V(); trait T { fn baz(x: usize, y: usize) -> usize { x } - fn bat() -> usize { 42 } + fn bat(x: usize) -> usize { 42 } + fn bax(x: usize) -> usize { 42 } + fn bach(x: usize) -> usize; + fn ban(&self) -> usize { 42 } + fn bal(&self) -> usize; +} + +struct X; + +impl T for X { + fn bach(x: usize) -> usize { 42 } + fn bal(&self) -> usize { 42 } } fn main() { @@ -23,4 +34,12 @@ fn main() { let _: usize = T::bat; //~ ERROR mismatched types let _: E = E::A; //~ ERROR mismatched types let _: E = E::B; //~ ERROR expected value, found struct variant `E::B` + let _: usize = X::baz; //~ ERROR mismatched types + let _: usize = X::bat; //~ ERROR mismatched types + let _: usize = X::bax; //~ ERROR mismatched types + let _: usize = X::bach; //~ ERROR mismatched types + let _: usize = X::ban; //~ ERROR mismatched types + let _: usize = X::bal; //~ ERROR mismatched types + let _: usize = X.ban; //~ ERROR attempted to take value of method + let _: usize = X.bal; //~ ERROR attempted to take value of method } diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr index cb128822fcce8..e3012144513fd 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr @@ -1,5 +1,5 @@ error[E0423]: expected value, found struct variant `E::B` - --> $DIR/fn-or-tuple-struct-without-args.rs:25:16 + --> $DIR/fn-or-tuple-struct-without-args.rs:36:16 | LL | let _: E = E::B; | ^^^- @@ -8,7 +8,7 @@ LL | let _: E = E::B; | did you mean `E::B { /* fields */ }`? error[E0308]: mismatched types - --> $DIR/fn-or-tuple-struct-without-args.rs:18:20 + --> $DIR/fn-or-tuple-struct-without-args.rs:29:20 | LL | fn foo(a: usize, b: usize) -> usize { a } | ----------------------------------- fn(usize, usize) -> usize {foo} defined here @@ -23,7 +23,7 @@ LL | let _: usize = foo; found type `fn(usize, usize) -> usize {foo}` error[E0308]: mismatched types - --> $DIR/fn-or-tuple-struct-without-args.rs:19:16 + --> $DIR/fn-or-tuple-struct-without-args.rs:30:16 | LL | struct S(usize, usize); | ----------------------- fn(usize, usize) -> S {S} defined here @@ -38,7 +38,7 @@ LL | let _: S = S; found type `fn(usize, usize) -> S {S}` error[E0308]: mismatched types - --> $DIR/fn-or-tuple-struct-without-args.rs:20:20 + --> $DIR/fn-or-tuple-struct-without-args.rs:31:20 | LL | fn bar() -> usize { 42 } | ----------------- fn() -> usize {bar} defined here @@ -53,7 +53,7 @@ LL | let _: usize = bar; found type `fn() -> usize {bar}` error[E0308]: mismatched types - --> $DIR/fn-or-tuple-struct-without-args.rs:21:16 + --> $DIR/fn-or-tuple-struct-without-args.rs:32:16 | LL | struct V(); | ----------- fn() -> V {V} defined here @@ -68,7 +68,7 @@ LL | let _: V = V; found type `fn() -> V {V}` error[E0308]: mismatched types - --> $DIR/fn-or-tuple-struct-without-args.rs:22:20 + --> $DIR/fn-or-tuple-struct-without-args.rs:33:20 | LL | fn baz(x: usize, y: usize) -> usize { x } | ----------------------------------- fn(usize, usize) -> usize {<_ as T>::baz} defined here @@ -77,28 +77,28 @@ LL | let _: usize = T::baz; | ^^^^^^ | | | expected usize, found fn item - | help: use parentheses to call this function: `T::baz(...)` + | help: use parentheses to call this function: `T::baz(x, y)` | = note: expected type `usize` found type `fn(usize, usize) -> usize {<_ as T>::baz}` error[E0308]: mismatched types - --> $DIR/fn-or-tuple-struct-without-args.rs:23:20 + --> $DIR/fn-or-tuple-struct-without-args.rs:34:20 | -LL | fn bat() -> usize { 42 } - | ----------------- fn() -> usize {<_ as T>::bat} defined here +LL | fn bat(x: usize) -> usize { 42 } + | ------------------------- fn(usize) -> usize {<_ as T>::bat} defined here ... LL | let _: usize = T::bat; | ^^^^^^ | | | expected usize, found fn item - | help: use parentheses to call this function: `T::bat()` + | help: use parentheses to call this function: `T::bat(x)` | = note: expected type `usize` - found type `fn() -> usize {<_ as T>::bat}` + found type `fn(usize) -> usize {<_ as T>::bat}` error[E0308]: mismatched types - --> $DIR/fn-or-tuple-struct-without-args.rs:24:16 + --> $DIR/fn-or-tuple-struct-without-args.rs:35:16 | LL | A(usize), | -------- fn(usize) -> E {E::A} defined here @@ -112,7 +112,109 @@ LL | let _: E = E::A; = note: expected type `E` found type `fn(usize) -> E {E::A}` -error: aborting due to 8 previous errors +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:37:20 + | +LL | fn baz(x: usize, y: usize) -> usize { x } + | ----------------------------------- fn(usize, usize) -> usize {::baz} defined here +... +LL | let _: usize = X::baz; + | ^^^^^^ + | | + | expected usize, found fn item + | help: use parentheses to call this function: `X::baz(x, y)` + | + = note: expected type `usize` + found type `fn(usize, usize) -> usize {::baz}` + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:38:20 + | +LL | fn bat(x: usize) -> usize { 42 } + | ------------------------- fn(usize) -> usize {::bat} defined here +... +LL | let _: usize = X::bat; + | ^^^^^^ + | | + | expected usize, found fn item + | help: use parentheses to call this function: `X::bat(x)` + | + = note: expected type `usize` + found type `fn(usize) -> usize {::bat}` + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:39:20 + | +LL | fn bax(x: usize) -> usize { 42 } + | ------------------------- fn(usize) -> usize {::bax} defined here +... +LL | let _: usize = X::bax; + | ^^^^^^ + | | + | expected usize, found fn item + | help: use parentheses to call this function: `X::bax(x)` + | + = note: expected type `usize` + found type `fn(usize) -> usize {::bax}` + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:40:20 + | +LL | fn bach(x: usize) -> usize; + | --------------------------- fn(usize) -> usize {::bach} defined here +... +LL | let _: usize = X::bach; + | ^^^^^^^ + | | + | expected usize, found fn item + | help: use parentheses to call this function: `X::bach(x)` + | + = note: expected type `usize` + found type `fn(usize) -> usize {::bach}` + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:41:20 + | +LL | fn ban(&self) -> usize { 42 } + | ---------------------- for<'r> fn(&'r X) -> usize {::ban} defined here +... +LL | let _: usize = X::ban; + | ^^^^^^ + | | + | expected usize, found fn item + | help: use parentheses to call this function: `X::ban(_)` + | + = note: expected type `usize` + found type `for<'r> fn(&'r X) -> usize {::ban}` + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:42:20 + | +LL | fn bal(&self) -> usize; + | ----------------------- for<'r> fn(&'r X) -> usize {::bal} defined here +... +LL | let _: usize = X::bal; + | ^^^^^^ + | | + | expected usize, found fn item + | help: use parentheses to call this function: `X::bal(_)` + | + = note: expected type `usize` + found type `for<'r> fn(&'r X) -> usize {::bal}` + +error[E0615]: attempted to take value of method `ban` on type `X` + --> $DIR/fn-or-tuple-struct-without-args.rs:43:22 + | +LL | let _: usize = X.ban; + | ^^^ help: use parentheses to call the method: `ban()` + +error[E0615]: attempted to take value of method `bal` on type `X` + --> $DIR/fn-or-tuple-struct-without-args.rs:44:22 + | +LL | let _: usize = X.bal; + | ^^^ help: use parentheses to call the method: `bal()` + +error: aborting due to 16 previous errors -Some errors have detailed explanations: E0308, E0423. +Some errors have detailed explanations: E0308, E0423, E0615. For more information about an error, try `rustc --explain E0308`. From 33d1082d6e3cb9fe5e0fd090f52a3effa9871fce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 8 Aug 2019 15:55:18 -0700 Subject: [PATCH 16/23] review comment: review wording or missing return error --- src/librustc_typeck/check/mod.rs | 3 ++- .../ui/block-result/consider-removing-last-semi.stderr | 4 ++-- src/test/ui/block-result/issue-11714.stderr | 2 +- src/test/ui/block-result/issue-13428.stderr | 4 ++-- .../coercion/coercion-missing-tail-expected-type.stderr | 4 ++-- src/test/ui/issues/issue-32323.stderr | 2 +- src/test/ui/issues/issue-43162.stderr | 2 +- src/test/ui/issues/issue-44023.stderr | 2 +- src/test/ui/issues/issue-6458-4.stderr | 2 +- src/test/ui/liveness/liveness-forgot-ret.stderr | 2 +- src/test/ui/liveness/liveness-missing-ret2.stderr | 2 +- .../ui/liveness/liveness-return-last-stmt-semi.stderr | 8 ++++---- src/test/ui/missing/missing-return.stderr | 2 +- src/test/ui/parser/issue-62881.stderr | 2 +- src/test/ui/parser/issue-62895.stderr | 2 +- 15 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d389563aea639..086f3d419576a 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3711,7 +3711,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(fn_span) = fn_span { err.span_label( fn_span, - "this function's body doesn't `return` a value", + "this function implicitly returns `()` as its body has no tail \ + or `return` expression", ); } }, false); diff --git a/src/test/ui/block-result/consider-removing-last-semi.stderr b/src/test/ui/block-result/consider-removing-last-semi.stderr index f3dfc8b12eafe..4c421e6ada405 100644 --- a/src/test/ui/block-result/consider-removing-last-semi.stderr +++ b/src/test/ui/block-result/consider-removing-last-semi.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn f() -> String { | - ^^^^^^ expected struct `std::string::String`, found () | | - | this function's body doesn't `return` a value + | this function implicitly returns `()` as its body has no tail or `return` expression LL | 0u8; LL | "bla".to_string(); | - help: consider removing this semicolon @@ -18,7 +18,7 @@ error[E0308]: mismatched types LL | fn g() -> String { | - ^^^^^^ expected struct `std::string::String`, found () | | - | this function's body doesn't `return` a value + | this function implicitly returns `()` as its body has no tail or `return` expression LL | "this won't work".to_string(); LL | "removeme".to_string(); | - help: consider removing this semicolon diff --git a/src/test/ui/block-result/issue-11714.stderr b/src/test/ui/block-result/issue-11714.stderr index 021a25ece2f4d..a0bdbd693f2cf 100644 --- a/src/test/ui/block-result/issue-11714.stderr +++ b/src/test/ui/block-result/issue-11714.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn blah() -> i32 { | ---- ^^^ expected i32, found () | | - | this function's body doesn't `return` a value + | this function implicitly returns `()` as its body has no tail or `return` expression ... LL | ; | - help: consider removing this semicolon diff --git a/src/test/ui/block-result/issue-13428.stderr b/src/test/ui/block-result/issue-13428.stderr index 8fa6ae9c528b4..53f8eaa1ae227 100644 --- a/src/test/ui/block-result/issue-13428.stderr +++ b/src/test/ui/block-result/issue-13428.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn foo() -> String { | --- ^^^^^^ expected struct `std::string::String`, found () | | - | this function's body doesn't `return` a value + | this function implicitly returns `()` as its body has no tail or `return` expression ... LL | ; | - help: consider removing this semicolon @@ -18,7 +18,7 @@ error[E0308]: mismatched types LL | fn bar() -> String { | --- ^^^^^^ expected struct `std::string::String`, found () | | - | this function's body doesn't `return` a value + | this function implicitly returns `()` as its body has no tail or `return` expression LL | "foobar".to_string() LL | ; | - help: consider removing this semicolon diff --git a/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr b/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr index 6ecb1d3eaef4a..fde41567d8002 100644 --- a/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr +++ b/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn plus_one(x: i32) -> i32 { | -------- ^^^ expected i32, found () | | - | this function's body doesn't `return` a value + | this function implicitly returns `()` as its body has no tail or `return` expression LL | x + 1; | - help: consider removing this semicolon | @@ -17,7 +17,7 @@ error[E0308]: mismatched types LL | fn foo() -> Result { | --- ^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found () | | - | this function's body doesn't `return` a value + | this function implicitly returns `()` as its body has no tail or `return` expression LL | Ok(1); | - help: consider removing this semicolon | diff --git a/src/test/ui/issues/issue-32323.stderr b/src/test/ui/issues/issue-32323.stderr index 376676bda7dbf..138b058f44d9e 100644 --- a/src/test/ui/issues/issue-32323.stderr +++ b/src/test/ui/issues/issue-32323.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | pub fn f<'a, T: Tr<'a>>() -> >::Out {} | - ^^^^^^^^^^^^^^^^^^ expected associated type, found () | | - | this function's body doesn't `return` a value + | this function implicitly returns `()` as its body has no tail or `return` expression | = note: expected type `>::Out` found type `()` diff --git a/src/test/ui/issues/issue-43162.stderr b/src/test/ui/issues/issue-43162.stderr index 22d347778c8f4..e90531bce3e86 100644 --- a/src/test/ui/issues/issue-43162.stderr +++ b/src/test/ui/issues/issue-43162.stderr @@ -16,7 +16,7 @@ error[E0308]: mismatched types LL | fn foo() -> bool { | --- ^^^^ expected bool, found () | | - | this function's body doesn't `return` a value + | this function implicitly returns `()` as its body has no tail or `return` expression LL | LL | break true; | - help: consider removing this semicolon diff --git a/src/test/ui/issues/issue-44023.stderr b/src/test/ui/issues/issue-44023.stderr index 7760af8145b07..4a27531b4be8f 100644 --- a/src/test/ui/issues/issue-44023.stderr +++ b/src/test/ui/issues/issue-44023.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn საჭმელად_გემრიელი_სადილი ( ) -> isize { | ------------------------ ^^^^^ expected isize, found () | | - | this function's body doesn't `return` a value + | this function implicitly returns `()` as its body has no tail or `return` expression | = note: expected type `isize` found type `()` diff --git a/src/test/ui/issues/issue-6458-4.stderr b/src/test/ui/issues/issue-6458-4.stderr index e29be76087416..4db3daede758f 100644 --- a/src/test/ui/issues/issue-6458-4.stderr +++ b/src/test/ui/issues/issue-6458-4.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn foo(b: bool) -> Result { | --- ^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found () | | - | this function's body doesn't `return` a value + | this function implicitly returns `()` as its body has no tail or `return` expression LL | Err("bar".to_string()); | - help: consider removing this semicolon | diff --git a/src/test/ui/liveness/liveness-forgot-ret.stderr b/src/test/ui/liveness/liveness-forgot-ret.stderr index 68cbdb2cfdba6..24106f775794c 100644 --- a/src/test/ui/liveness/liveness-forgot-ret.stderr +++ b/src/test/ui/liveness/liveness-forgot-ret.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; } | - ^^^^^ expected isize, found () | | - | this function's body doesn't `return` a value + | this function implicitly returns `()` as its body has no tail or `return` expression | = note: expected type `isize` found type `()` diff --git a/src/test/ui/liveness/liveness-missing-ret2.stderr b/src/test/ui/liveness/liveness-missing-ret2.stderr index 62e0aa5d29d95..9502e4467499c 100644 --- a/src/test/ui/liveness/liveness-missing-ret2.stderr +++ b/src/test/ui/liveness/liveness-missing-ret2.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn f() -> isize { | - ^^^^^ expected isize, found () | | - | this function's body doesn't `return` a value + | this function implicitly returns `()` as its body has no tail or `return` expression | = note: expected type `isize` found type `()` diff --git a/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr b/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr index c5018af74f347..7ee4cb178a6c5 100644 --- a/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr +++ b/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr @@ -5,7 +5,7 @@ LL | macro_rules! test { () => { fn foo() -> i32 { 1; } } } | --- ^^^ - help: consider removing this semicolon | | | | | expected i32, found () - | this function's body doesn't `return` a value + | this function implicitly returns `()` as its body has no tail or `return` expression ... LL | test!(); | -------- in this macro invocation @@ -19,7 +19,7 @@ error[E0308]: mismatched types LL | fn no_return() -> i32 {} | --------- ^^^ expected i32, found () | | - | this function's body doesn't `return` a value + | this function implicitly returns `()` as its body has no tail or `return` expression | = note: expected type `i32` found type `()` @@ -30,7 +30,7 @@ error[E0308]: mismatched types LL | fn bar(x: u32) -> u32 { | --- ^^^ expected u32, found () | | - | this function's body doesn't `return` a value + | this function implicitly returns `()` as its body has no tail or `return` expression LL | x * 2; | - help: consider removing this semicolon | @@ -43,7 +43,7 @@ error[E0308]: mismatched types LL | fn baz(x: u64) -> u32 { | --- ^^^ expected u32, found () | | - | this function's body doesn't `return` a value + | this function implicitly returns `()` as its body has no tail or `return` expression | = note: expected type `u32` found type `()` diff --git a/src/test/ui/missing/missing-return.stderr b/src/test/ui/missing/missing-return.stderr index 4cd516ba81d6a..541e9fa4a4016 100644 --- a/src/test/ui/missing/missing-return.stderr +++ b/src/test/ui/missing/missing-return.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn f() -> isize { } | - ^^^^^ expected isize, found () | | - | this function's body doesn't `return` a value + | this function implicitly returns `()` as its body has no tail or `return` expression | = note: expected type `isize` found type `()` diff --git a/src/test/ui/parser/issue-62881.stderr b/src/test/ui/parser/issue-62881.stderr index 11b8836a89a76..40f64ec8fd0e2 100644 --- a/src/test/ui/parser/issue-62881.stderr +++ b/src/test/ui/parser/issue-62881.stderr @@ -19,7 +19,7 @@ error[E0308]: mismatched types LL | fn f() -> isize { fn f() -> isize {} pub f< | - ^^^^^ expected isize, found () | | - | this function's body doesn't `return` a value + | this function implicitly returns `()` as its body has no tail or `return` expression | = note: expected type `isize` found type `()` diff --git a/src/test/ui/parser/issue-62895.stderr b/src/test/ui/parser/issue-62895.stderr index d9d3baf622708..4c872d0c9d367 100644 --- a/src/test/ui/parser/issue-62895.stderr +++ b/src/test/ui/parser/issue-62895.stderr @@ -38,7 +38,7 @@ error[E0308]: mismatched types LL | fn v() -> isize { | - ^^^^^ expected isize, found () | | - | this function's body doesn't `return` a value + | this function implicitly returns `()` as its body has no tail or `return` expression | = note: expected type `isize` found type `()` From bc1a4f52e3bcb092142267c7d1e6b90b718d557e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 8 Aug 2019 16:56:57 -0700 Subject: [PATCH 17/23] review comments: typo and rewording --- src/librustc_typeck/check/mod.rs | 8 ++++---- .../ui/block-result/consider-removing-last-semi.stderr | 4 ++-- src/test/ui/block-result/issue-11714.stderr | 2 +- src/test/ui/block-result/issue-13428.stderr | 4 ++-- .../coercion/coercion-missing-tail-expected-type.stderr | 4 ++-- src/test/ui/issues/issue-32323.stderr | 2 +- src/test/ui/issues/issue-35241.stderr | 2 +- src/test/ui/issues/issue-43162.stderr | 2 +- src/test/ui/issues/issue-44023.stderr | 2 +- src/test/ui/issues/issue-6458-4.stderr | 2 +- src/test/ui/liveness/liveness-forgot-ret.stderr | 2 +- src/test/ui/liveness/liveness-missing-ret2.stderr | 2 +- .../ui/liveness/liveness-return-last-stmt-semi.stderr | 8 ++++---- src/test/ui/missing/missing-return.stderr | 2 +- src/test/ui/parser/issue-62881.stderr | 2 +- src/test/ui/parser/issue-62895.stderr | 2 +- src/test/ui/resolve/privacy-enum-ctor.stderr | 6 +++--- .../ui/suggestions/fn-or-tuple-struct-without-args.stderr | 6 +++--- 18 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 086f3d419576a..4fb28db6e94fa 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3711,8 +3711,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(fn_span) = fn_span { err.span_label( fn_span, - "this function implicitly returns `()` as its body has no tail \ - or `return` expression", + "implicitly returns `()` as its body has no tail or `return` \ + expression", ); } }, false); @@ -3880,10 +3880,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sugg_call = fields.iter().map(|_| "_").collect::>().join(", "); match hir.as_local_hir_id(def_id).and_then(|hir_id| hir.def_kind(hir_id)) { Some(hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, _)) => { - msg = "instatiate this tuple variant"; + msg = "instantiate this tuple variant"; } Some(hir::def::DefKind::Ctor(hir::def::CtorOf::Struct, _)) => { - msg = "instatiate this tuple struct"; + msg = "instantiate this tuple struct"; } _ => {} } diff --git a/src/test/ui/block-result/consider-removing-last-semi.stderr b/src/test/ui/block-result/consider-removing-last-semi.stderr index 4c421e6ada405..f4984ca446309 100644 --- a/src/test/ui/block-result/consider-removing-last-semi.stderr +++ b/src/test/ui/block-result/consider-removing-last-semi.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn f() -> String { | - ^^^^^^ expected struct `std::string::String`, found () | | - | this function implicitly returns `()` as its body has no tail or `return` expression + | implicitly returns `()` as its body has no tail or `return` expression LL | 0u8; LL | "bla".to_string(); | - help: consider removing this semicolon @@ -18,7 +18,7 @@ error[E0308]: mismatched types LL | fn g() -> String { | - ^^^^^^ expected struct `std::string::String`, found () | | - | this function implicitly returns `()` as its body has no tail or `return` expression + | implicitly returns `()` as its body has no tail or `return` expression LL | "this won't work".to_string(); LL | "removeme".to_string(); | - help: consider removing this semicolon diff --git a/src/test/ui/block-result/issue-11714.stderr b/src/test/ui/block-result/issue-11714.stderr index a0bdbd693f2cf..cfb42c601279a 100644 --- a/src/test/ui/block-result/issue-11714.stderr +++ b/src/test/ui/block-result/issue-11714.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn blah() -> i32 { | ---- ^^^ expected i32, found () | | - | this function implicitly returns `()` as its body has no tail or `return` expression + | implicitly returns `()` as its body has no tail or `return` expression ... LL | ; | - help: consider removing this semicolon diff --git a/src/test/ui/block-result/issue-13428.stderr b/src/test/ui/block-result/issue-13428.stderr index 53f8eaa1ae227..f7cafab3d773b 100644 --- a/src/test/ui/block-result/issue-13428.stderr +++ b/src/test/ui/block-result/issue-13428.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn foo() -> String { | --- ^^^^^^ expected struct `std::string::String`, found () | | - | this function implicitly returns `()` as its body has no tail or `return` expression + | implicitly returns `()` as its body has no tail or `return` expression ... LL | ; | - help: consider removing this semicolon @@ -18,7 +18,7 @@ error[E0308]: mismatched types LL | fn bar() -> String { | --- ^^^^^^ expected struct `std::string::String`, found () | | - | this function implicitly returns `()` as its body has no tail or `return` expression + | implicitly returns `()` as its body has no tail or `return` expression LL | "foobar".to_string() LL | ; | - help: consider removing this semicolon diff --git a/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr b/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr index fde41567d8002..955793e8586e7 100644 --- a/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr +++ b/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn plus_one(x: i32) -> i32 { | -------- ^^^ expected i32, found () | | - | this function implicitly returns `()` as its body has no tail or `return` expression + | implicitly returns `()` as its body has no tail or `return` expression LL | x + 1; | - help: consider removing this semicolon | @@ -17,7 +17,7 @@ error[E0308]: mismatched types LL | fn foo() -> Result { | --- ^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found () | | - | this function implicitly returns `()` as its body has no tail or `return` expression + | implicitly returns `()` as its body has no tail or `return` expression LL | Ok(1); | - help: consider removing this semicolon | diff --git a/src/test/ui/issues/issue-32323.stderr b/src/test/ui/issues/issue-32323.stderr index 138b058f44d9e..6256dc0c55022 100644 --- a/src/test/ui/issues/issue-32323.stderr +++ b/src/test/ui/issues/issue-32323.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | pub fn f<'a, T: Tr<'a>>() -> >::Out {} | - ^^^^^^^^^^^^^^^^^^ expected associated type, found () | | - | this function implicitly returns `()` as its body has no tail or `return` expression + | implicitly returns `()` as its body has no tail or `return` expression | = note: expected type `>::Out` found type `()` diff --git a/src/test/ui/issues/issue-35241.stderr b/src/test/ui/issues/issue-35241.stderr index 8befc6873857e..586146cbaa4ee 100644 --- a/src/test/ui/issues/issue-35241.stderr +++ b/src/test/ui/issues/issue-35241.stderr @@ -8,7 +8,7 @@ LL | fn test() -> Foo { Foo } | --- ^^^ | | | | | expected struct `Foo`, found fn item - | | help: use parentheses to instatiate this tuple struct: `Foo(_)` + | | help: use parentheses to instantiate this tuple struct: `Foo(_)` | expected `Foo` because of return type | = note: expected type `Foo` diff --git a/src/test/ui/issues/issue-43162.stderr b/src/test/ui/issues/issue-43162.stderr index e90531bce3e86..6d3e8b5ba2323 100644 --- a/src/test/ui/issues/issue-43162.stderr +++ b/src/test/ui/issues/issue-43162.stderr @@ -16,7 +16,7 @@ error[E0308]: mismatched types LL | fn foo() -> bool { | --- ^^^^ expected bool, found () | | - | this function implicitly returns `()` as its body has no tail or `return` expression + | implicitly returns `()` as its body has no tail or `return` expression LL | LL | break true; | - help: consider removing this semicolon diff --git a/src/test/ui/issues/issue-44023.stderr b/src/test/ui/issues/issue-44023.stderr index 4a27531b4be8f..258ffe558e9ba 100644 --- a/src/test/ui/issues/issue-44023.stderr +++ b/src/test/ui/issues/issue-44023.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn საჭმელად_გემრიელი_სადილი ( ) -> isize { | ------------------------ ^^^^^ expected isize, found () | | - | this function implicitly returns `()` as its body has no tail or `return` expression + | implicitly returns `()` as its body has no tail or `return` expression | = note: expected type `isize` found type `()` diff --git a/src/test/ui/issues/issue-6458-4.stderr b/src/test/ui/issues/issue-6458-4.stderr index 4db3daede758f..ecf729e1032b1 100644 --- a/src/test/ui/issues/issue-6458-4.stderr +++ b/src/test/ui/issues/issue-6458-4.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn foo(b: bool) -> Result { | --- ^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found () | | - | this function implicitly returns `()` as its body has no tail or `return` expression + | implicitly returns `()` as its body has no tail or `return` expression LL | Err("bar".to_string()); | - help: consider removing this semicolon | diff --git a/src/test/ui/liveness/liveness-forgot-ret.stderr b/src/test/ui/liveness/liveness-forgot-ret.stderr index 24106f775794c..4baf351f7eb2d 100644 --- a/src/test/ui/liveness/liveness-forgot-ret.stderr +++ b/src/test/ui/liveness/liveness-forgot-ret.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; } | - ^^^^^ expected isize, found () | | - | this function implicitly returns `()` as its body has no tail or `return` expression + | implicitly returns `()` as its body has no tail or `return` expression | = note: expected type `isize` found type `()` diff --git a/src/test/ui/liveness/liveness-missing-ret2.stderr b/src/test/ui/liveness/liveness-missing-ret2.stderr index 9502e4467499c..1f60560b45043 100644 --- a/src/test/ui/liveness/liveness-missing-ret2.stderr +++ b/src/test/ui/liveness/liveness-missing-ret2.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn f() -> isize { | - ^^^^^ expected isize, found () | | - | this function implicitly returns `()` as its body has no tail or `return` expression + | implicitly returns `()` as its body has no tail or `return` expression | = note: expected type `isize` found type `()` diff --git a/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr b/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr index 7ee4cb178a6c5..2497d93daa494 100644 --- a/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr +++ b/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr @@ -5,7 +5,7 @@ LL | macro_rules! test { () => { fn foo() -> i32 { 1; } } } | --- ^^^ - help: consider removing this semicolon | | | | | expected i32, found () - | this function implicitly returns `()` as its body has no tail or `return` expression + | implicitly returns `()` as its body has no tail or `return` expression ... LL | test!(); | -------- in this macro invocation @@ -19,7 +19,7 @@ error[E0308]: mismatched types LL | fn no_return() -> i32 {} | --------- ^^^ expected i32, found () | | - | this function implicitly returns `()` as its body has no tail or `return` expression + | implicitly returns `()` as its body has no tail or `return` expression | = note: expected type `i32` found type `()` @@ -30,7 +30,7 @@ error[E0308]: mismatched types LL | fn bar(x: u32) -> u32 { | --- ^^^ expected u32, found () | | - | this function implicitly returns `()` as its body has no tail or `return` expression + | implicitly returns `()` as its body has no tail or `return` expression LL | x * 2; | - help: consider removing this semicolon | @@ -43,7 +43,7 @@ error[E0308]: mismatched types LL | fn baz(x: u64) -> u32 { | --- ^^^ expected u32, found () | | - | this function implicitly returns `()` as its body has no tail or `return` expression + | implicitly returns `()` as its body has no tail or `return` expression | = note: expected type `u32` found type `()` diff --git a/src/test/ui/missing/missing-return.stderr b/src/test/ui/missing/missing-return.stderr index 541e9fa4a4016..3c8ecdcfbcbe4 100644 --- a/src/test/ui/missing/missing-return.stderr +++ b/src/test/ui/missing/missing-return.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn f() -> isize { } | - ^^^^^ expected isize, found () | | - | this function implicitly returns `()` as its body has no tail or `return` expression + | implicitly returns `()` as its body has no tail or `return` expression | = note: expected type `isize` found type `()` diff --git a/src/test/ui/parser/issue-62881.stderr b/src/test/ui/parser/issue-62881.stderr index 40f64ec8fd0e2..3d58b6fba0baf 100644 --- a/src/test/ui/parser/issue-62881.stderr +++ b/src/test/ui/parser/issue-62881.stderr @@ -19,7 +19,7 @@ error[E0308]: mismatched types LL | fn f() -> isize { fn f() -> isize {} pub f< | - ^^^^^ expected isize, found () | | - | this function implicitly returns `()` as its body has no tail or `return` expression + | implicitly returns `()` as its body has no tail or `return` expression | = note: expected type `isize` found type `()` diff --git a/src/test/ui/parser/issue-62895.stderr b/src/test/ui/parser/issue-62895.stderr index 4c872d0c9d367..39ce980964b77 100644 --- a/src/test/ui/parser/issue-62895.stderr +++ b/src/test/ui/parser/issue-62895.stderr @@ -38,7 +38,7 @@ error[E0308]: mismatched types LL | fn v() -> isize { | - ^^^^^ expected isize, found () | | - | this function implicitly returns `()` as its body has no tail or `return` expression + | implicitly returns `()` as its body has no tail or `return` expression | = note: expected type `isize` found type `()` diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr index 3e924f7d161bd..2538bbbf8067f 100644 --- a/src/test/ui/resolve/privacy-enum-ctor.stderr +++ b/src/test/ui/resolve/privacy-enum-ctor.stderr @@ -202,7 +202,7 @@ LL | let _: Z = Z::Fn; | ^^^^^ | | | expected enum `m::n::Z`, found fn item - | help: use parentheses to instatiate this tuple variant: `Z::Fn(_)` + | help: use parentheses to instantiate this tuple variant: `Z::Fn(_)` | = note: expected type `m::n::Z` found type `fn(u8) -> m::n::Z {m::n::Z::Fn}` @@ -232,7 +232,7 @@ LL | let _: E = m::E::Fn; | ^^^^^^^^ | | | expected enum `m::E`, found fn item - | help: use parentheses to instatiate this tuple variant: `m::E::Fn(_)` + | help: use parentheses to instantiate this tuple variant: `m::E::Fn(_)` | = note: expected type `m::E` found type `fn(u8) -> m::E {m::E::Fn}` @@ -262,7 +262,7 @@ LL | let _: E = E::Fn; | ^^^^^ | | | expected enum `m::E`, found fn item - | help: use parentheses to instatiate this tuple variant: `E::Fn(_)` + | help: use parentheses to instantiate this tuple variant: `E::Fn(_)` | = note: expected type `m::E` found type `fn(u8) -> m::E {m::E::Fn}` diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr index e3012144513fd..0686b56f97ded 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr @@ -32,7 +32,7 @@ LL | let _: S = S; | ^ | | | expected struct `S`, found fn item - | help: use parentheses to instatiate this tuple struct: `S(_, _)` + | help: use parentheses to instantiate this tuple struct: `S(_, _)` | = note: expected type `S` found type `fn(usize, usize) -> S {S}` @@ -62,7 +62,7 @@ LL | let _: V = V; | ^ | | | expected struct `V`, found fn item - | help: use parentheses to instatiate this tuple struct: `V()` + | help: use parentheses to instantiate this tuple struct: `V()` | = note: expected type `V` found type `fn() -> V {V}` @@ -107,7 +107,7 @@ LL | let _: E = E::A; | ^^^^ | | | expected enum `E`, found fn item - | help: use parentheses to instatiate this tuple variant: `E::A(_)` + | help: use parentheses to instantiate this tuple variant: `E::A(_)` | = note: expected type `E` found type `fn(usize) -> E {E::A}` From 45a5bc7619d19e58cbb1497f571e2ba987d1d53b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 9 Aug 2019 07:57:16 -0700 Subject: [PATCH 18/23] fix tests --- .../async-block-control-flow-static-semantics.stderr | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr index 96927ac9632d6..f3f2d14584ef7 100644 --- a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr +++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr @@ -16,7 +16,7 @@ error[E0308]: mismatched types LL | fn return_targets_async_block_not_fn() -> u8 { | --------------------------------- ^^ expected u8, found () | | - | this function's body doesn't return + | implicitly returns `()` as its body has no tail or `return` expression | = note: expected type `u8` found type `()` @@ -57,7 +57,7 @@ error[E0308]: mismatched types LL | fn rethrow_targets_async_block_not_fn() -> Result { | ---------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found () | | - | this function's body doesn't return + | implicitly returns `()` as its body has no tail or `return` expression | = note: expected type `std::result::Result` found type `()` @@ -68,7 +68,7 @@ error[E0308]: mismatched types LL | fn rethrow_targets_async_block_not_async_fn() -> Result { | ---------------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found () | | - | this function's body doesn't return + | implicitly returns `()` as its body has no tail or `return` expression | = note: expected type `std::result::Result` found type `()` From 7c96d90c2081f3ca84b3786a125cf2c415335e40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 8 Aug 2019 18:24:00 -0700 Subject: [PATCH 19/23] More explicit diagnostic when using a `vec![]` in a pattern ``` error: unexpected `(` after qualified path --> $DIR/vec-macro-in-pattern.rs:3:14 | LL | Some(vec![x]) => (), | ^^^^^^^ | | | unexpected `(` after qualified path | in this macro invocation | use a slice pattern here instead | = help: for more information, see https://doc.rust-lang.org/edition-guide/rust-2018/slice-patterns.html = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) ``` --- src/libsyntax/ext/expand.rs | 28 +++++++++++++++---- src/libsyntax/ext/tt/macro_rules.rs | 23 +++++++++++++++ src/test/ui/proc-macro/lifetimes.stderr | 2 +- .../ui/suggestions/vec-macro-in-pattern.rs | 6 ++++ .../suggestions/vec-macro-in-pattern.stderr | 15 ++++++++++ .../ui/type/ascription/issue-47666.stderr | 1 + 6 files changed, 68 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/suggestions/vec-macro-in-pattern.rs create mode 100644 src/test/ui/suggestions/vec-macro-in-pattern.stderr diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 964c81dd46641..36f059531d39d 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -686,12 +686,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> { ); } - fn parse_ast_fragment(&mut self, - toks: TokenStream, - kind: AstFragmentKind, - path: &Path, - span: Span) - -> AstFragment { + fn parse_ast_fragment( + &mut self, + toks: TokenStream, + kind: AstFragmentKind, + path: &Path, + span: Span, + ) -> AstFragment { let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::>()); match parser.parse_ast_fragment(kind, false) { Ok(fragment) => { @@ -700,6 +701,21 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } Err(mut err) => { err.set_span(span); + match kind { + AstFragmentKind::Ty => { + err.span_label( + span, + "this macro call doesn't expand to a type", + ); + } + AstFragmentKind::Pat => { + err.span_label( + span, + "this macro call doesn't expand to a pattern", + ); + } + _ => {} + }; err.emit(); self.cx.trace_macros_diag(); kind.dummy(span) diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 7401f25641236..a9d0b739d6ac7 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -70,6 +70,29 @@ impl<'a> ParserAnyMacro<'a> { } else if !parser.sess.source_map().span_to_filename(parser.token.span).is_real() { e.span_label(site_span, "in this macro invocation"); } + match kind { + AstFragmentKind::Ty => { + e.span_label( + site_span, + "this macro call doesn't expand to a type", + ); + } + AstFragmentKind::Pat if macro_ident.name == sym::vec => { + e.span_label( + site_span, + "use a slice pattern here instead", + ); + e.help("for more information, see https://doc.rust-lang.org/edition-guide/\ + rust-2018/slice-patterns.html"); + } + AstFragmentKind::Pat => { + e.span_label( + site_span, + "this macro call doesn't expand to a pattern", + ); + } + _ => {} + }; e })); diff --git a/src/test/ui/proc-macro/lifetimes.stderr b/src/test/ui/proc-macro/lifetimes.stderr index 2356a119530bb..6e91201405cc6 100644 --- a/src/test/ui/proc-macro/lifetimes.stderr +++ b/src/test/ui/proc-macro/lifetimes.stderr @@ -2,7 +2,7 @@ error: expected type, found `'` --> $DIR/lifetimes.rs:9:10 | LL | type A = single_quote_alone!(); - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ this macro call doesn't expand to a type error: aborting due to previous error diff --git a/src/test/ui/suggestions/vec-macro-in-pattern.rs b/src/test/ui/suggestions/vec-macro-in-pattern.rs new file mode 100644 index 0000000000000..5c42a6bdbd44e --- /dev/null +++ b/src/test/ui/suggestions/vec-macro-in-pattern.rs @@ -0,0 +1,6 @@ +fn main() { + match Some(vec![3]) { + Some(vec![x]) => (), //~ ERROR unexpected `(` after qualified path + _ => (), + } +} diff --git a/src/test/ui/suggestions/vec-macro-in-pattern.stderr b/src/test/ui/suggestions/vec-macro-in-pattern.stderr new file mode 100644 index 0000000000000..f94cb93a520b5 --- /dev/null +++ b/src/test/ui/suggestions/vec-macro-in-pattern.stderr @@ -0,0 +1,15 @@ +error: unexpected `(` after qualified path + --> $DIR/vec-macro-in-pattern.rs:3:14 + | +LL | Some(vec![x]) => (), + | ^^^^^^^ + | | + | unexpected `(` after qualified path + | in this macro invocation + | use a slice pattern here instead + | + = help: for more information, see https://doc.rust-lang.org/edition-guide/rust-2018/slice-patterns.html + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/type/ascription/issue-47666.stderr b/src/test/ui/type/ascription/issue-47666.stderr index 965bbe5ea41f7..2f052341faead 100644 --- a/src/test/ui/type/ascription/issue-47666.stderr +++ b/src/test/ui/type/ascription/issue-47666.stderr @@ -6,6 +6,7 @@ LL | let _ = Option:Some(vec![0, 1]); | | | | | expected type | | in this macro invocation + | | this macro call doesn't expand to a type | help: maybe write a path separator here: `::` | = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` From 75c5ad2e827a077c3738dee11d9e0dc99962f384 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 9 Aug 2019 09:39:30 -0700 Subject: [PATCH 20/23] review comments: use structured suggestion --- src/libsyntax/ext/expand.rs | 17 +----- src/libsyntax/ext/tt/macro_rules.rs | 53 ++++++++++++------- .../ui/suggestions/vec-macro-in-pattern.fixed | 8 +++ .../ui/suggestions/vec-macro-in-pattern.rs | 6 ++- .../suggestions/vec-macro-in-pattern.stderr | 8 +-- 5 files changed, 52 insertions(+), 40 deletions(-) create mode 100644 src/test/ui/suggestions/vec-macro-in-pattern.fixed diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 36f059531d39d..9a3195b1165b1 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -6,6 +6,7 @@ use crate::config::StripUnconfigured; use crate::ext::base::*; use crate::ext::proc_macro::collect_derives; use crate::ext::hygiene::{ExpnId, SyntaxContext, ExpnInfo, ExpnKind}; +use crate::ext::tt::macro_rules::annotate_err_with_kind; use crate::ext::placeholders::{placeholder, PlaceholderExpander}; use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err}; use crate::mut_visit::*; @@ -701,21 +702,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } Err(mut err) => { err.set_span(span); - match kind { - AstFragmentKind::Ty => { - err.span_label( - span, - "this macro call doesn't expand to a type", - ); - } - AstFragmentKind::Pat => { - err.span_label( - span, - "this macro call doesn't expand to a pattern", - ); - } - _ => {} - }; + annotate_err_with_kind(&mut err, kind, span); err.emit(); self.cx.trace_macros_diag(); kind.dummy(span) diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index a9d0b739d6ac7..b057a9ad44d0b 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -17,7 +17,7 @@ use crate::symbol::{kw, sym, Symbol}; use crate::tokenstream::{DelimSpan, TokenStream, TokenTree}; use crate::{ast, attr, attr::TransparencyError}; -use errors::FatalError; +use errors::{DiagnosticBuilder, FatalError}; use log::debug; use syntax_pos::Span; @@ -43,6 +43,18 @@ pub struct ParserAnyMacro<'a> { arm_span: Span, } +pub fn annotate_err_with_kind(err: &mut DiagnosticBuilder<'_>, kind: AstFragmentKind, span: Span) { + match kind { + AstFragmentKind::Ty => { + err.span_label(span, "this macro call doesn't expand to a type"); + } + AstFragmentKind::Pat => { + err.span_label(span, "this macro call doesn't expand to a pattern"); + } + _ => {} + }; +} + impl<'a> ParserAnyMacro<'a> { pub fn make(mut self: Box>, kind: AstFragmentKind) -> AstFragment { let ParserAnyMacro { site_span, macro_ident, ref mut parser, arm_span } = *self; @@ -71,27 +83,30 @@ impl<'a> ParserAnyMacro<'a> { e.span_label(site_span, "in this macro invocation"); } match kind { - AstFragmentKind::Ty => { - e.span_label( - site_span, - "this macro call doesn't expand to a type", - ); - } AstFragmentKind::Pat if macro_ident.name == sym::vec => { - e.span_label( - site_span, - "use a slice pattern here instead", - ); + let mut suggestion = None; + if let Ok(code) = parser.sess.source_map().span_to_snippet(site_span) { + if let Some(bang) = code.find('!') { + suggestion = Some(code[bang + 1..].to_string()); + } + } + if let Some(suggestion) = suggestion { + e.span_suggestion( + site_span, + "use a slice pattern here instead", + suggestion, + Applicability::MachineApplicable, + ); + } else { + e.span_label( + site_span, + "use a slice pattern here instead", + ); + } e.help("for more information, see https://doc.rust-lang.org/edition-guide/\ - rust-2018/slice-patterns.html"); - } - AstFragmentKind::Pat => { - e.span_label( - site_span, - "this macro call doesn't expand to a pattern", - ); + rust-2018/slice-patterns.html"); } - _ => {} + _ => annotate_err_with_kind(&mut e, kind, site_span), }; e })); diff --git a/src/test/ui/suggestions/vec-macro-in-pattern.fixed b/src/test/ui/suggestions/vec-macro-in-pattern.fixed new file mode 100644 index 0000000000000..e1695d6820a81 --- /dev/null +++ b/src/test/ui/suggestions/vec-macro-in-pattern.fixed @@ -0,0 +1,8 @@ +// run-rustfix +fn main() { + // everything after `.as_ref` should be suggested + match Some(vec![3]).as_ref().map(|v| v.as_slice()) { + Some([_x]) => (), //~ ERROR unexpected `(` after qualified path + _ => (), + } +} diff --git a/src/test/ui/suggestions/vec-macro-in-pattern.rs b/src/test/ui/suggestions/vec-macro-in-pattern.rs index 5c42a6bdbd44e..4843629fbcf90 100644 --- a/src/test/ui/suggestions/vec-macro-in-pattern.rs +++ b/src/test/ui/suggestions/vec-macro-in-pattern.rs @@ -1,6 +1,8 @@ +// run-rustfix fn main() { - match Some(vec![3]) { - Some(vec![x]) => (), //~ ERROR unexpected `(` after qualified path + // everything after `.as_ref` should be suggested + match Some(vec![3]).as_ref().map(|v| v.as_slice()) { + Some(vec![_x]) => (), //~ ERROR unexpected `(` after qualified path _ => (), } } diff --git a/src/test/ui/suggestions/vec-macro-in-pattern.stderr b/src/test/ui/suggestions/vec-macro-in-pattern.stderr index f94cb93a520b5..59ca8ebbf6339 100644 --- a/src/test/ui/suggestions/vec-macro-in-pattern.stderr +++ b/src/test/ui/suggestions/vec-macro-in-pattern.stderr @@ -1,12 +1,12 @@ error: unexpected `(` after qualified path - --> $DIR/vec-macro-in-pattern.rs:3:14 + --> $DIR/vec-macro-in-pattern.rs:5:14 | -LL | Some(vec![x]) => (), - | ^^^^^^^ +LL | Some(vec![_x]) => (), + | ^^^^^^^^ | | | unexpected `(` after qualified path | in this macro invocation - | use a slice pattern here instead + | help: use a slice pattern here instead: `[_x]` | = help: for more information, see https://doc.rust-lang.org/edition-guide/rust-2018/slice-patterns.html = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) From 4dd96d2b0fc87e7081009ab26ba396e3638a4ada Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 9 Aug 2019 20:04:18 +0200 Subject: [PATCH 21/23] check against more collisions for TypeId of fn pointer --- src/test/ui/typeid-intrinsic.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/test/ui/typeid-intrinsic.rs b/src/test/ui/typeid-intrinsic.rs index c2611158e65ef..5bc4e0c217f40 100644 --- a/src/test/ui/typeid-intrinsic.rs +++ b/src/test/ui/typeid-intrinsic.rs @@ -78,10 +78,20 @@ pub fn main() { assert_eq!(TypeId::of::(), other1::id_u32_iterator()); assert_eq!(other1::id_i32_iterator(), other2::id_i32_iterator()); assert_eq!(other1::id_u32_iterator(), other2::id_u32_iterator()); - assert!(other1::id_i32_iterator() != other1::id_u32_iterator()); - assert!(TypeId::of::() != TypeId::of::()); + assert_ne!(other1::id_i32_iterator(), other1::id_u32_iterator()); + assert_ne!(TypeId::of::(), TypeId::of::()); // Check fn pointer against collisions - assert!(TypeId::of:: A) -> A>() != - TypeId::of:: A, A) -> A>()); + assert_ne!( + TypeId::of:: A) -> A>(), + TypeId::of:: A, A) -> A>() + ); + assert_ne!( + TypeId::of:: fn(&'a i32) -> &'a i32>(), + TypeId::of:: fn(&'a i32) -> &'static i32>() + ); + assert_ne!( + TypeId::of:: fn(&'a i32, &'b i32) -> &'a i32>(), + TypeId::of:: fn(&'b i32, &'a i32) -> &'a i32>() + ); } From b9865d9e3fdd87a5b7e45153effef3055d85f70e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 9 Aug 2019 12:52:02 -0700 Subject: [PATCH 22/23] Mention that tuple structs are private if their fields are --- src/librustc_resolve/lib.rs | 31 +++++- src/test/ui/privacy/privacy5.stderr | 96 +++++++++++++++++++ .../ui/resolve/privacy-struct-ctor.stderr | 12 +++ .../ui/rfc-2008-non-exhaustive/struct.stderr | 2 + .../ui/rfc-2008-non-exhaustive/variant.stderr | 6 ++ 5 files changed, 144 insertions(+), 3 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e7feccf506957..ce2bc79ff6034 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -50,7 +50,7 @@ use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind}; use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path}; use syntax::ast::{QSelf, TraitItem, TraitItemKind, TraitRef, Ty, TyKind}; use syntax::ptr::P; -use syntax::{span_err, struct_span_err, unwrap_or, walk_list}; +use syntax::{struct_span_err, unwrap_or, walk_list}; use syntax_pos::{Span, DUMMY_SP, MultiSpan}; use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; @@ -4789,8 +4789,33 @@ impl<'a> Resolver<'a> { let mut reported_spans = FxHashSet::default(); for &PrivacyError(dedup_span, ident, binding) in &self.privacy_errors { if reported_spans.insert(dedup_span) { - span_err!(self.session, ident.span, E0603, "{} `{}` is private", - binding.descr(), ident.name); + let mut err = struct_span_err!( + self.session, + ident.span, + E0603, + "{} `{}` is private", + binding.descr(), + ident.name, + ); + // FIXME: use the ctor's `def_id` to check wether any of the fields is not visible + match binding.kind { + NameBindingKind::Res(Res::Def(DefKind::Ctor( + CtorOf::Struct, + CtorKind::Fn, + ), _def_id), _) => { + err.note("a tuple struct constructor is private if any of its fields \ + is private"); + } + NameBindingKind::Res(Res::Def(DefKind::Ctor( + CtorOf::Variant, + CtorKind::Fn, + ), _def_id), _) => { + err.note("a tuple variant constructor is private if any of its fields \ + is private"); + } + _ => {} + } + err.emit(); } } } diff --git a/src/test/ui/privacy/privacy5.stderr b/src/test/ui/privacy/privacy5.stderr index 7568c346b2489..532d1ac1e2fb8 100644 --- a/src/test/ui/privacy/privacy5.stderr +++ b/src/test/ui/privacy/privacy5.stderr @@ -3,288 +3,384 @@ error[E0603]: tuple struct `A` is private | LL | let a = a::A(()); | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:52:16 | LL | let b = a::B(2); | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:53:16 | LL | let c = a::C(2, 3); | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:56:12 | LL | let a::A(()) = a; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:57:12 | LL | let a::A(_) = a; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:58:18 | LL | match a { a::A(()) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:59:18 | LL | match a { a::A(_) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:61:12 | LL | let a::B(_) = b; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:62:12 | LL | let a::B(_b) = b; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:63:18 | LL | match b { a::B(_) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:64:18 | LL | match b { a::B(_b) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:65:18 | LL | match b { a::B(1) => {} a::B(_) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:65:32 | LL | match b { a::B(1) => {} a::B(_) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:68:12 | LL | let a::C(_, _) = c; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:69:12 | LL | let a::C(_a, _) = c; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:70:12 | LL | let a::C(_, _b) = c; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:71:12 | LL | let a::C(_a, _b) = c; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:72:18 | LL | match c { a::C(_, _) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:73:18 | LL | match c { a::C(_a, _) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:74:18 | LL | match c { a::C(_, _b) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:75:18 | LL | match c { a::C(_a, _b) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:83:17 | LL | let a2 = a::A; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:84:17 | LL | let b2 = a::B; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:85:17 | LL | let c2 = a::C; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:90:20 | LL | let a = other::A(()); | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:91:20 | LL | let b = other::B(2); | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:92:20 | LL | let c = other::C(2, 3); | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:95:16 | LL | let other::A(()) = a; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:96:16 | LL | let other::A(_) = a; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:97:22 | LL | match a { other::A(()) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:98:22 | LL | match a { other::A(_) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:100:16 | LL | let other::B(_) = b; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:101:16 | LL | let other::B(_b) = b; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:102:22 | LL | match b { other::B(_) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:103:22 | LL | match b { other::B(_b) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:104:22 | LL | match b { other::B(1) => {} other::B(_) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:104:40 | LL | match b { other::B(1) => {} other::B(_) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:107:16 | LL | let other::C(_, _) = c; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:108:16 | LL | let other::C(_a, _) = c; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:109:16 | LL | let other::C(_, _b) = c; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:110:16 | LL | let other::C(_a, _b) = c; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:111:22 | LL | match c { other::C(_, _) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:112:22 | LL | match c { other::C(_a, _) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:113:22 | LL | match c { other::C(_, _b) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:114:22 | LL | match c { other::C(_a, _b) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:122:21 | LL | let a2 = other::A; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:123:21 | LL | let b2 = other::B; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:124:21 | LL | let c2 = other::C; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error: aborting due to 48 previous errors diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr index 9bf7d19117448..72d62fe45ce74 100644 --- a/src/test/ui/resolve/privacy-struct-ctor.stderr +++ b/src/test/ui/resolve/privacy-struct-ctor.stderr @@ -34,36 +34,48 @@ error[E0603]: tuple struct `Z` is private | LL | n::Z; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `S` is private --> $DIR/privacy-struct-ctor.rs:29:8 | LL | m::S; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `S` is private --> $DIR/privacy-struct-ctor.rs:31:19 | LL | let _: S = m::S(2); | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `Z` is private --> $DIR/privacy-struct-ctor.rs:35:11 | LL | m::n::Z; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `S` is private --> $DIR/privacy-struct-ctor.rs:41:16 | LL | xcrate::m::S; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `Z` is private --> $DIR/privacy-struct-ctor.rs:45:19 | LL | xcrate::m::n::Z; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private error: aborting due to 10 previous errors diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr index 96040f11b525f..d75a376286fcc 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr @@ -15,6 +15,8 @@ error[E0603]: tuple struct `TupleStruct` is private | LL | let ts_explicit = structs::TupleStruct(640, 480); | ^^^^^^^^^^^ + | + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: unit struct `UnitStruct` is private --> $DIR/struct.rs:32:32 diff --git a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr index d9d6ea21b8bd4..ac0025ec75807 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr @@ -3,6 +3,8 @@ error[E0603]: tuple variant `Tuple` is private | LL | let variant_tuple = NonExhaustiveVariants::Tuple(640); | ^^^^^ + | + = note: a tuple variant constructor is private if any of its fields is private error[E0603]: unit variant `Unit` is private --> $DIR/variant.rs:14:47 @@ -21,12 +23,16 @@ error[E0603]: tuple variant `Tuple` is private | LL | NonExhaustiveVariants::Tuple(fe_tpl) => "", | ^^^^^ + | + = note: a tuple variant constructor is private if any of its fields is private error[E0603]: tuple variant `Tuple` is private --> $DIR/variant.rs:26:35 | LL | if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct { | ^^^^^ + | + = note: a tuple variant constructor is private if any of its fields is private error[E0639]: cannot create non-exhaustive variant using struct expression --> $DIR/variant.rs:8:26 From cbcc7dd182b9bf67d664508b82284c5539ef8819 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 28 Jul 2019 01:51:21 +0300 Subject: [PATCH 23/23] Give built-in macros stable addresses in the standard library --- src/libcore/clone.rs | 8 + src/libcore/cmp.rs | 32 +++ src/libcore/default.rs | 8 + src/libcore/fmt/mod.rs | 15 ++ src/libcore/hash/mod.rs | 15 ++ src/libcore/macros.rs | 185 ++++++------------ src/libcore/marker.rs | 8 + src/libcore/prelude/v1.rs | 38 ++-- src/libstd/lib.rs | 51 +++-- src/test/ui/imports/issue-53512.rs | 3 +- src/test/ui/imports/issue-53512.stderr | 8 +- .../ui/macros/builtin-prelude-no-accidents.rs | 8 + .../builtin-prelude-no-accidents.stderr | 21 ++ src/test/ui/macros/builtin-std-paths-fail.rs | 21 ++ .../ui/macros/builtin-std-paths-fail.stderr | 75 +++++++ src/test/ui/macros/builtin-std-paths.rs | 32 +++ 16 files changed, 364 insertions(+), 164 deletions(-) create mode 100644 src/test/ui/macros/builtin-prelude-no-accidents.rs create mode 100644 src/test/ui/macros/builtin-prelude-no-accidents.stderr create mode 100644 src/test/ui/macros/builtin-std-paths-fail.rs create mode 100644 src/test/ui/macros/builtin-std-paths-fail.stderr create mode 100644 src/test/ui/macros/builtin-std-paths.rs diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 9e32acb97d360..0c99356390bda 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -133,6 +133,14 @@ pub trait Clone : Sized { } } +/// Derive macro generating an impl of the trait `Clone`. +#[cfg(not(bootstrap))] +#[rustc_builtin_macro] +#[rustc_macro_transparency = "semitransparent"] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow_internal_unstable(core_intrinsics, derive_clone_copy)] +pub macro Clone($item:item) { /* compiler built-in */ } + // FIXME(aburka): these structs are used solely by #[derive] to // assert that every component of a type implements Clone or Copy. // diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index f9613556a1ebc..38a52d97da212 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -200,6 +200,14 @@ pub trait PartialEq { fn ne(&self, other: &Rhs) -> bool { !self.eq(other) } } +/// Derive macro generating an impl of the trait `PartialEq`. +#[cfg(not(bootstrap))] +#[rustc_builtin_macro] +#[rustc_macro_transparency = "semitransparent"] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow_internal_unstable(core_intrinsics)] +pub macro PartialEq($item:item) { /* compiler built-in */ } + /// Trait for equality comparisons which are [equivalence relations]( /// https://en.wikipedia.org/wiki/Equivalence_relation). /// @@ -256,6 +264,14 @@ pub trait Eq: PartialEq { fn assert_receiver_is_total_eq(&self) {} } +/// Derive macro generating an impl of the trait `Eq`. +#[cfg(not(bootstrap))] +#[rustc_builtin_macro] +#[rustc_macro_transparency = "semitransparent"] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow_internal_unstable(core_intrinsics, derive_eq)] +pub macro Eq($item:item) { /* compiler built-in */ } + // FIXME: this struct is used solely by #[derive] to // assert that every component of a type implements Eq. // @@ -600,6 +616,14 @@ pub trait Ord: Eq + PartialOrd { } } +/// Derive macro generating an impl of the trait `Ord`. +#[cfg(not(bootstrap))] +#[rustc_builtin_macro] +#[rustc_macro_transparency = "semitransparent"] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow_internal_unstable(core_intrinsics)] +pub macro Ord($item:item) { /* compiler built-in */ } + #[stable(feature = "rust1", since = "1.0.0")] impl Eq for Ordering {} @@ -842,6 +866,14 @@ pub trait PartialOrd: PartialEq { } } +/// Derive macro generating an impl of the trait `PartialOrd`. +#[cfg(not(bootstrap))] +#[rustc_builtin_macro] +#[rustc_macro_transparency = "semitransparent"] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow_internal_unstable(core_intrinsics)] +pub macro PartialOrd($item:item) { /* compiler built-in */ } + /// Compares and returns the minimum of two values. /// /// Returns the first argument if the comparison determines them to be equal. diff --git a/src/libcore/default.rs b/src/libcore/default.rs index 5ad05b3824764..8d95e9de15849 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -115,6 +115,14 @@ pub trait Default: Sized { fn default() -> Self; } +/// Derive macro generating an impl of the trait `Default`. +#[cfg(not(bootstrap))] +#[rustc_builtin_macro] +#[rustc_macro_transparency = "semitransparent"] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow_internal_unstable(core_intrinsics)] +pub macro Default($item:item) { /* compiler built-in */ } + macro_rules! default_impl { ($t:ty, $v:expr, $doc:tt) => { #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 4a7c6af7adab7..0ea01d4b84a2c 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -545,6 +545,21 @@ pub trait Debug { fn fmt(&self, f: &mut Formatter<'_>) -> Result; } +// Separate module to reexport the macro `Debug` from prelude without the trait `Debug`. +#[cfg(not(bootstrap))] +pub(crate) mod macros { + /// Derive macro generating an impl of the trait `Debug`. + #[rustc_builtin_macro] + #[rustc_macro_transparency = "semitransparent"] + #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] + #[allow_internal_unstable(core_intrinsics)] + pub macro Debug($item:item) { /* compiler built-in */ } +} +#[cfg(not(bootstrap))] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[doc(inline)] +pub use macros::Debug; + /// Format trait for an empty format, `{}`. /// /// `Display` is similar to [`Debug`][debug], but `Display` is for user-facing diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 38e3864284240..c4cbf40a93a15 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -198,6 +198,21 @@ pub trait Hash { } } +// Separate module to reexport the macro `Hash` from prelude without the trait `Hash`. +#[cfg(not(bootstrap))] +pub(crate) mod macros { + /// Derive macro generating an impl of the trait `Hash`. + #[rustc_builtin_macro] + #[rustc_macro_transparency = "semitransparent"] + #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] + #[allow_internal_unstable(core_intrinsics)] + pub macro Hash($item:item) { /* compiler built-in */ } +} +#[cfg(not(bootstrap))] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[doc(inline)] +pub use macros::Hash; + /// A trait for hashing an arbitrary stream of bytes. /// /// Instances of `Hasher` usually represent state that is changed while hashing diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 667b35d0f775a..f9dc53874acb1 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -714,9 +714,9 @@ pub(crate) mod builtin { /// [`panic!`]: ../std/macro.panic.html #[stable(feature = "compile_error_macro", since = "1.20.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro compile_error { - ($msg:expr) => ({ /* compiler built-in */ }), + #[macro_export] + macro_rules! compile_error { + ($msg:expr) => ({ /* compiler built-in */ }); ($msg:expr,) => ({ /* compiler built-in */ }) } @@ -768,8 +768,10 @@ pub(crate) mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(fmt_internals)] #[rustc_builtin_macro] - pub macro format_args { - ($fmt:expr) => ({ /* compiler built-in */ }), + #[macro_export] + #[rustc_macro_transparency = "opaque"] + macro_rules! format_args { + ($fmt:expr) => ({ /* compiler built-in */ }); ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) } @@ -779,8 +781,10 @@ pub(crate) mod builtin { language use and is subject to change")] #[allow_internal_unstable(fmt_internals)] #[rustc_builtin_macro] - pub macro format_args_nl { - ($fmt:expr) => ({ /* compiler built-in */ }), + #[macro_export] + #[rustc_macro_transparency = "opaque"] + macro_rules! format_args_nl { + ($fmt:expr) => ({ /* compiler built-in */ }); ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) } @@ -817,9 +821,9 @@ pub(crate) mod builtin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro env { - ($name:expr) => ({ /* compiler built-in */ }), + #[macro_export] + macro_rules! env { + ($name:expr) => ({ /* compiler built-in */ }); ($name:expr,) => ({ /* compiler built-in */ }) } @@ -844,9 +848,9 @@ pub(crate) mod builtin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro option_env { - ($name:expr) => ({ /* compiler built-in */ }), + #[macro_export] + macro_rules! option_env { + ($name:expr) => ({ /* compiler built-in */ }); ($name:expr,) => ({ /* compiler built-in */ }) } @@ -877,9 +881,9 @@ pub(crate) mod builtin { #[unstable(feature = "concat_idents", issue = "29599", reason = "`concat_idents` is not stable enough for use and is subject to change")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro concat_idents { - ($($e:ident),+) => ({ /* compiler built-in */ }), + #[macro_export] + macro_rules! concat_idents { + ($($e:ident),+) => ({ /* compiler built-in */ }); ($($e:ident,)+) => ({ /* compiler built-in */ }) } @@ -900,9 +904,9 @@ pub(crate) mod builtin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro concat { - ($($e:expr),*) => ({ /* compiler built-in */ }), + #[macro_export] + macro_rules! concat { + ($($e:expr),*) => ({ /* compiler built-in */ }); ($($e:expr,)*) => ({ /* compiler built-in */ }) } @@ -929,8 +933,8 @@ pub(crate) mod builtin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro line() { /* compiler built-in */ } + #[macro_export] + macro_rules! line { () => { /* compiler built-in */ } } /// Expands to the column number at which it was invoked. /// @@ -955,15 +959,15 @@ pub(crate) mod builtin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro column() { /* compiler built-in */ } + #[macro_export] + macro_rules! column { () => { /* compiler built-in */ } } /// Same as `column`, but less likely to be shadowed. #[unstable(feature = "__rust_unstable_column", issue = "0", reason = "internal implementation detail of the `panic` macro")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro __rust_unstable_column() { /* compiler built-in */ } + #[macro_export] + macro_rules! __rust_unstable_column { () => { /* compiler built-in */ } } /// Expands to the file name in which it was invoked. /// @@ -987,8 +991,8 @@ pub(crate) mod builtin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro file() { /* compiler built-in */ } + #[macro_export] + macro_rules! file { () => { /* compiler built-in */ } } /// Stringifies its arguments. /// @@ -1007,8 +1011,8 @@ pub(crate) mod builtin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro stringify($($t:tt)*) { /* compiler built-in */ } + #[macro_export] + macro_rules! stringify { ($($t:tt)*) => { /* compiler built-in */ } } /// Includes a utf8-encoded file as a string. /// @@ -1042,9 +1046,9 @@ pub(crate) mod builtin { /// Compiling 'main.rs' and running the resulting binary will print "adiós". #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro include_str { - ($file:expr) => ({ /* compiler built-in */ }), + #[macro_export] + macro_rules! include_str { + ($file:expr) => ({ /* compiler built-in */ }); ($file:expr,) => ({ /* compiler built-in */ }) } @@ -1080,9 +1084,9 @@ pub(crate) mod builtin { /// Compiling 'main.rs' and running the resulting binary will print "adiós". #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro include_bytes { - ($file:expr) => ({ /* compiler built-in */ }), + #[macro_export] + macro_rules! include_bytes { + ($file:expr) => ({ /* compiler built-in */ }); ($file:expr,) => ({ /* compiler built-in */ }) } @@ -1105,8 +1109,8 @@ pub(crate) mod builtin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro module_path() { /* compiler built-in */ } + #[macro_export] + macro_rules! module_path { () => { /* compiler built-in */ } } /// Evaluates boolean combinations of configuration flags at compile-time. /// @@ -1130,8 +1134,8 @@ pub(crate) mod builtin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro cfg($($cfg:tt)*) { /* compiler built-in */ } + #[macro_export] + macro_rules! cfg { ($($cfg:tt)*) => { /* compiler built-in */ } } /// Parses a file as an expression or an item according to the context. /// @@ -1174,9 +1178,9 @@ pub(crate) mod builtin { /// "🙈🙊🙉🙈🙊🙉". #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro include { - ($file:expr) => ({ /* compiler built-in */ }), + #[macro_export] + macro_rules! include { + ($file:expr) => ({ /* compiler built-in */ }); ($file:expr,) => ({ /* compiler built-in */ }) } @@ -1227,10 +1231,10 @@ pub(crate) mod builtin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro assert { - ($cond:expr) => ({ /* compiler built-in */ }), - ($cond:expr,) => ({ /* compiler built-in */ }), + #[macro_export] + macro_rules! assert { + ($cond:expr) => ({ /* compiler built-in */ }); + ($cond:expr,) => ({ /* compiler built-in */ }); ($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ }) } @@ -1238,34 +1242,34 @@ pub(crate) mod builtin { #[unstable(feature = "asm", issue = "29722", reason = "inline assembly is not stable enough for use and is subject to change")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro asm("assembly template" - : $("output"(operand),)* - : $("input"(operand),)* - : $("clobbers",)* - : $("options",)*) { /* compiler built-in */ } + #[macro_export] + macro_rules! asm { ("assembly template" + : $("output"(operand),)* + : $("input"(operand),)* + : $("clobbers",)* + : $("options",)*) => { /* compiler built-in */ } } /// Module-level inline assembly. #[unstable(feature = "global_asm", issue = "35119", reason = "`global_asm!` is not stable enough for use and is subject to change")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro global_asm("assembly") { /* compiler built-in */ } + #[macro_export] + macro_rules! global_asm { ("assembly") => { /* compiler built-in */ } } /// Prints passed tokens into the standard output. #[unstable(feature = "log_syntax", issue = "29598", reason = "`log_syntax!` is not stable enough for use and is subject to change")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro log_syntax($($arg:tt)*) { /* compiler built-in */ } + #[macro_export] + macro_rules! log_syntax { ($($arg:tt)*) => { /* compiler built-in */ } } /// Enables or disables tracing functionality used for debugging other macros. #[unstable(feature = "trace_macros", issue = "29598", reason = "`trace_macros` is not stable enough for use and is subject to change")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro trace_macros { - (true) => ({ /* compiler built-in */ }), + #[macro_export] + macro_rules! trace_macros { + (true) => ({ /* compiler built-in */ }); (false) => ({ /* compiler built-in */ }) } @@ -1299,69 +1303,6 @@ pub(crate) mod builtin { #[rustc_macro_transparency = "semitransparent"] pub macro global_allocator($item:item) { /* compiler built-in */ } - /// Derive macro generating an impl of the trait `Clone`. - #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - #[stable(feature = "rust1", since = "1.0.0")] - #[allow_internal_unstable(core_intrinsics, derive_clone_copy)] - pub macro Clone($item:item) { /* compiler built-in */ } - - /// Derive macro generating an impl of the trait `Copy`. - #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - #[stable(feature = "rust1", since = "1.0.0")] - #[allow_internal_unstable(core_intrinsics, derive_clone_copy)] - pub macro Copy($item:item) { /* compiler built-in */ } - - /// Derive macro generating an impl of the trait `Debug`. - #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - #[stable(feature = "rust1", since = "1.0.0")] - #[allow_internal_unstable(core_intrinsics)] - pub macro Debug($item:item) { /* compiler built-in */ } - - /// Derive macro generating an impl of the trait `Default`. - #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - #[stable(feature = "rust1", since = "1.0.0")] - #[allow_internal_unstable(core_intrinsics)] - pub macro Default($item:item) { /* compiler built-in */ } - - /// Derive macro generating an impl of the trait `Eq`. - #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - #[stable(feature = "rust1", since = "1.0.0")] - #[allow_internal_unstable(core_intrinsics, derive_eq)] - pub macro Eq($item:item) { /* compiler built-in */ } - - /// Derive macro generating an impl of the trait `Hash`. - #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - #[stable(feature = "rust1", since = "1.0.0")] - #[allow_internal_unstable(core_intrinsics)] - pub macro Hash($item:item) { /* compiler built-in */ } - - /// Derive macro generating an impl of the trait `Ord`. - #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - #[stable(feature = "rust1", since = "1.0.0")] - #[allow_internal_unstable(core_intrinsics)] - pub macro Ord($item:item) { /* compiler built-in */ } - - /// Derive macro generating an impl of the trait `PartialEq`. - #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - #[stable(feature = "rust1", since = "1.0.0")] - #[allow_internal_unstable(core_intrinsics)] - pub macro PartialEq($item:item) { /* compiler built-in */ } - - /// Derive macro generating an impl of the trait `PartialOrd`. - #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - #[stable(feature = "rust1", since = "1.0.0")] - #[allow_internal_unstable(core_intrinsics)] - pub macro PartialOrd($item:item) { /* compiler built-in */ } - /// Unstable implementation detail of the `rustc` compiler, do not use. #[rustc_builtin_macro] #[rustc_macro_transparency = "semitransparent"] diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 79a188dbac99d..78a273611650c 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -288,6 +288,14 @@ pub trait Copy : Clone { // Empty. } +/// Derive macro generating an impl of the trait `Copy`. +#[cfg(not(bootstrap))] +#[rustc_builtin_macro] +#[rustc_macro_transparency = "semitransparent"] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow_internal_unstable(core_intrinsics, derive_clone_copy)] +pub macro Copy($item:item) { /* compiler built-in */ } + /// Types for which it is safe to share references between threads. /// /// This trait is automatically implemented when the compiler determines diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs index c503d8c701938..84cf85f339c99 100644 --- a/src/libcore/prelude/v1.rs +++ b/src/libcore/prelude/v1.rs @@ -48,24 +48,20 @@ pub use crate::result::Result::{self, Ok, Err}; // Re-exported built-in macros #[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] -#[allow(deprecated)] #[doc(no_inline)] -pub use crate::macros::builtin::{ - Clone, - Copy, - Debug, - Default, - Eq, - Hash, - Ord, - PartialEq, - PartialOrd, - RustcDecodable, - RustcEncodable, +pub use crate::fmt::macros::Debug; +#[cfg(not(bootstrap))] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[doc(no_inline)] +pub use crate::hash::macros::Hash; + +#[cfg(not(bootstrap))] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[doc(no_inline)] +pub use crate::{ __rust_unstable_column, asm, assert, - bench, cfg, column, compile_error, @@ -75,7 +71,6 @@ pub use crate::macros::builtin::{ file, format_args, format_args_nl, - global_allocator, global_asm, include, include_bytes, @@ -85,7 +80,18 @@ pub use crate::macros::builtin::{ module_path, option_env, stringify, + trace_macros, +}; + +#[cfg(not(bootstrap))] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow(deprecated)] +#[doc(no_inline)] +pub use crate::macros::builtin::{ + RustcDecodable, + RustcEncodable, + bench, + global_allocator, test, test_case, - trace_macros, }; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 54abf72d3075a..e03626fb7f565 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -326,16 +326,6 @@ use prelude::v1::*; // Access to Bencher, etc. #[cfg(test)] extern crate test; -// Re-export a few macros from core -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::{assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne}; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::{unreachable, unimplemented, write, writeln, todo}; -// FIXME: change this to `#[allow(deprecated)]` when we update nightly compiler. -#[allow(deprecated_in_future)] -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::r#try; - #[allow(unused_imports)] // macros from `alloc` are not used on all platforms #[macro_use] extern crate alloc as alloc_crate; @@ -520,33 +510,52 @@ mod std_detect; #[cfg(not(test))] pub use std_detect::detect; -// Document built-in macros in the crate root for consistency with libcore and existing tradition. -// FIXME: Attribute and derive macros are not reexported because rustdoc renders them -// as reexports rather than as macros, and that's not what we want. -#[cfg(rustdoc)] +// Re-export macros defined in libcore. +#[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated_in_future)] +pub use core::{ + // Stable + assert_eq, + assert_ne, + debug_assert_eq, + debug_assert_ne, + debug_assert, + r#try, + unimplemented, + unreachable, + write, + writeln, + // Unstable + todo, +}; + +// Re-export built-in macros defined through libcore. +#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] -pub use crate::prelude::v1::{ - __rust_unstable_column, - asm, +pub use core::{ + // Stable assert, cfg, column, compile_error, concat, - concat_idents, env, file, format_args, - format_args_nl, - global_asm, include, include_bytes, include_str, line, - log_syntax, module_path, option_env, stringify, + // Unstable + __rust_unstable_column, + asm, + concat_idents, + format_args_nl, + global_asm, + log_syntax, trace_macros, }; diff --git a/src/test/ui/imports/issue-53512.rs b/src/test/ui/imports/issue-53512.rs index 615b36a0b21ec..67470f854cedf 100644 --- a/src/test/ui/imports/issue-53512.rs +++ b/src/test/ui/imports/issue-53512.rs @@ -1,6 +1,7 @@ // Macro from prelude is shadowed by non-existent import recovered as `Res::Err`. -use std::assert; //~ ERROR unresolved import `std::assert` +mod m {} +use m::assert; //~ ERROR unresolved import `m::assert` fn main() { assert!(true); diff --git a/src/test/ui/imports/issue-53512.stderr b/src/test/ui/imports/issue-53512.stderr index f902fc488882f..05fe111b38bc6 100644 --- a/src/test/ui/imports/issue-53512.stderr +++ b/src/test/ui/imports/issue-53512.stderr @@ -1,8 +1,8 @@ -error[E0432]: unresolved import `std::assert` - --> $DIR/issue-53512.rs:3:5 +error[E0432]: unresolved import `m::assert` + --> $DIR/issue-53512.rs:4:5 | -LL | use std::assert; - | ^^^^^^^^^^^ no `assert` in the root +LL | use m::assert; + | ^^^^^^^^^ no `assert` in `m` error: aborting due to previous error diff --git a/src/test/ui/macros/builtin-prelude-no-accidents.rs b/src/test/ui/macros/builtin-prelude-no-accidents.rs new file mode 100644 index 0000000000000..ac82f343acc02 --- /dev/null +++ b/src/test/ui/macros/builtin-prelude-no-accidents.rs @@ -0,0 +1,8 @@ +// Names of public modules in libstd and libcore don't accidentally get into prelude +// because macros with the same names are in prelude. + +fn main() { + env::current_dir; //~ ERROR use of undeclared type or module `env` + type A = panic::PanicInfo; //~ ERROR use of undeclared type or module `panic` + type B = vec::Vec; //~ ERROR use of undeclared type or module `vec` +} diff --git a/src/test/ui/macros/builtin-prelude-no-accidents.stderr b/src/test/ui/macros/builtin-prelude-no-accidents.stderr new file mode 100644 index 0000000000000..914e906df58b3 --- /dev/null +++ b/src/test/ui/macros/builtin-prelude-no-accidents.stderr @@ -0,0 +1,21 @@ +error[E0433]: failed to resolve: use of undeclared type or module `env` + --> $DIR/builtin-prelude-no-accidents.rs:5:5 + | +LL | env::current_dir; + | ^^^ use of undeclared type or module `env` + +error[E0433]: failed to resolve: use of undeclared type or module `panic` + --> $DIR/builtin-prelude-no-accidents.rs:6:14 + | +LL | type A = panic::PanicInfo; + | ^^^^^ use of undeclared type or module `panic` + +error[E0433]: failed to resolve: use of undeclared type or module `vec` + --> $DIR/builtin-prelude-no-accidents.rs:7:14 + | +LL | type B = vec::Vec; + | ^^^ use of undeclared type or module `vec` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/macros/builtin-std-paths-fail.rs b/src/test/ui/macros/builtin-std-paths-fail.rs new file mode 100644 index 0000000000000..33de3d5184b1f --- /dev/null +++ b/src/test/ui/macros/builtin-std-paths-fail.rs @@ -0,0 +1,21 @@ +#[derive( + core::RustcDecodable, //~ ERROR could not find `RustcDecodable` in `core` + core::RustcDecodable, //~ ERROR could not find `RustcDecodable` in `core` +)] +#[core::bench] //~ ERROR could not find `bench` in `core` +#[core::global_allocator] //~ ERROR could not find `global_allocator` in `core` +#[core::test_case] //~ ERROR could not find `test_case` in `core` +#[core::test] //~ ERROR could not find `test` in `core` +struct Core; + +#[derive( + std::RustcDecodable, //~ ERROR could not find `RustcDecodable` in `std` + std::RustcDecodable, //~ ERROR could not find `RustcDecodable` in `std` +)] +#[std::bench] //~ ERROR could not find `bench` in `std` +#[std::global_allocator] //~ ERROR could not find `global_allocator` in `std` +#[std::test_case] //~ ERROR could not find `test_case` in `std` +#[std::test] //~ ERROR could not find `test` in `std` +struct Std; + +fn main() {} diff --git a/src/test/ui/macros/builtin-std-paths-fail.stderr b/src/test/ui/macros/builtin-std-paths-fail.stderr new file mode 100644 index 0000000000000..6de689076b849 --- /dev/null +++ b/src/test/ui/macros/builtin-std-paths-fail.stderr @@ -0,0 +1,75 @@ +error[E0433]: failed to resolve: could not find `bench` in `core` + --> $DIR/builtin-std-paths-fail.rs:5:9 + | +LL | #[core::bench] + | ^^^^^ could not find `bench` in `core` + +error[E0433]: failed to resolve: could not find `global_allocator` in `core` + --> $DIR/builtin-std-paths-fail.rs:6:9 + | +LL | #[core::global_allocator] + | ^^^^^^^^^^^^^^^^ could not find `global_allocator` in `core` + +error[E0433]: failed to resolve: could not find `test_case` in `core` + --> $DIR/builtin-std-paths-fail.rs:7:9 + | +LL | #[core::test_case] + | ^^^^^^^^^ could not find `test_case` in `core` + +error[E0433]: failed to resolve: could not find `test` in `core` + --> $DIR/builtin-std-paths-fail.rs:8:9 + | +LL | #[core::test] + | ^^^^ could not find `test` in `core` + +error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` + --> $DIR/builtin-std-paths-fail.rs:2:11 + | +LL | core::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` + +error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` + --> $DIR/builtin-std-paths-fail.rs:3:11 + | +LL | core::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` + +error[E0433]: failed to resolve: could not find `bench` in `std` + --> $DIR/builtin-std-paths-fail.rs:15:8 + | +LL | #[std::bench] + | ^^^^^ could not find `bench` in `std` + +error[E0433]: failed to resolve: could not find `global_allocator` in `std` + --> $DIR/builtin-std-paths-fail.rs:16:8 + | +LL | #[std::global_allocator] + | ^^^^^^^^^^^^^^^^ could not find `global_allocator` in `std` + +error[E0433]: failed to resolve: could not find `test_case` in `std` + --> $DIR/builtin-std-paths-fail.rs:17:8 + | +LL | #[std::test_case] + | ^^^^^^^^^ could not find `test_case` in `std` + +error[E0433]: failed to resolve: could not find `test` in `std` + --> $DIR/builtin-std-paths-fail.rs:18:8 + | +LL | #[std::test] + | ^^^^ could not find `test` in `std` + +error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` + --> $DIR/builtin-std-paths-fail.rs:12:10 + | +LL | std::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std` + +error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` + --> $DIR/builtin-std-paths-fail.rs:13:10 + | +LL | std::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std` + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/macros/builtin-std-paths.rs b/src/test/ui/macros/builtin-std-paths.rs new file mode 100644 index 0000000000000..2083f9ba3dc34 --- /dev/null +++ b/src/test/ui/macros/builtin-std-paths.rs @@ -0,0 +1,32 @@ +// check-pass + +#[derive( + core::clone::Clone, + core::marker::Copy, + core::fmt::Debug, + core::default::Default, + core::cmp::Eq, + core::hash::Hash, + core::cmp::Ord, + core::cmp::PartialEq, + core::cmp::PartialOrd, +)] +struct Core; + +#[derive( + std::clone::Clone, + std::marker::Copy, + std::fmt::Debug, + std::default::Default, + std::cmp::Eq, + std::hash::Hash, + std::cmp::Ord, + std::cmp::PartialEq, + std::cmp::PartialOrd, +)] +struct Std; + +fn main() { + core::column!(); + std::column!(); +}