From f43e3a86a7286057a748c731b732200e2ccde466 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 1 Dec 2021 18:50:46 -0800 Subject: [PATCH 1/2] Allow substitutions in `rustc_on_unimplemented` predicate --- compiler/rustc_span/src/symbol.rs | 3 ++ .../src/traits/on_unimplemented.rs | 48 ++++++++++++++----- 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 70fad4911f9c7..ef0a1792d58af 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -668,6 +668,7 @@ symbols! { fill, finish, flags, + float, float_to_int_unchecked, floorf32, floorf64, @@ -771,6 +772,8 @@ symbols! { inline_const_pat, inout, instruction_set, + integer_: "integer", + integral, intel, into_future, into_iter, diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs index 6b20476b95594..bdf677a63b632 100644 --- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs @@ -62,6 +62,10 @@ impl<'tcx> OnUnimplementedDirective { let mut errored = false; let mut item_iter = items.iter(); + let parse_value = |value_str| { + OnUnimplementedFormatString::try_parse(tcx, trait_def_id, value_str, span).map(Some) + }; + let condition = if is_root { None } else { @@ -86,7 +90,14 @@ impl<'tcx> OnUnimplementedDirective { None, ) })?; - attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |_| true); + attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |item| { + if let Some(symbol) = item.value_str() { + if parse_value(symbol).is_err() { + errored = true; + } + } + true + }); Some(cond.clone()) }; @@ -97,10 +108,6 @@ impl<'tcx> OnUnimplementedDirective { let mut subcommands = vec![]; let mut append_const_msg = None; - let parse_value = |value_str| { - OnUnimplementedFormatString::try_parse(tcx, trait_def_id, value_str, span).map(Some) - }; - for item in item_iter { if item.has_name(sym::message) && message.is_none() { if let Some(message_) = item.value_str() { @@ -221,6 +228,9 @@ impl<'tcx> OnUnimplementedDirective { let mut append_const_msg = None; info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options); + let options_map: FxHashMap = + options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect(); + for command in self.subcommands.iter().chain(Some(self)).rev() { if let Some(ref condition) = command.condition { if !attr::eval_condition( @@ -229,7 +239,11 @@ impl<'tcx> OnUnimplementedDirective { Some(tcx.features()), &mut |c| { c.ident().map_or(false, |ident| { - options.contains(&(ident.name, c.value_str().map(|s| s.to_string()))) + let value = c.value_str().map(|s| { + OnUnimplementedFormatString(s).format(tcx, trait_ref, &options_map) + }); + + options.contains(&(ident.name, value)) }) }, ) { @@ -257,13 +271,11 @@ impl<'tcx> OnUnimplementedDirective { append_const_msg = command.append_const_msg.clone(); } - let options: FxHashMap = - options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect(); OnUnimplementedNote { - label: label.map(|l| l.format(tcx, trait_ref, &options)), - message: message.map(|m| m.format(tcx, trait_ref, &options)), - note: note.map(|n| n.format(tcx, trait_ref, &options)), - enclosing_scope: enclosing_scope.map(|e_s| e_s.format(tcx, trait_ref, &options)), + label: label.map(|l| l.format(tcx, trait_ref, &options_map)), + message: message.map(|m| m.format(tcx, trait_ref, &options_map)), + note: note.map(|n| n.format(tcx, trait_ref, &options_map)), + enclosing_scope: enclosing_scope.map(|e_s| e_s.format(tcx, trait_ref, &options_map)), append_const_msg, } } @@ -306,6 +318,12 @@ impl<'tcx> OnUnimplementedFormatString { Position::ArgumentNamed(s) if s == sym::from_desugaring => (), // `{ItemContext}` is allowed Position::ArgumentNamed(s) if s == sym::ItemContext => (), + // `{integral}` and `{integer}` and `{float}` are allowed + Position::ArgumentNamed(s) + if s == sym::integral || s == sym::integer_ || s == sym::float => + { + () + } // So is `{A}` if A is a type parameter Position::ArgumentNamed(s) => { match generics.params.iter().find(|param| param.name == s) { @@ -385,6 +403,12 @@ impl<'tcx> OnUnimplementedFormatString { &empty_string } else if s == sym::ItemContext { &item_context + } else if s == sym::integral { + "{integral}" + } else if s == sym::integer_ { + "{integer}" + } else if s == sym::float { + "{float}" } else { bug!( "broken on_unimplemented {:?} for {:?}: \ From fea0015f9320f59c46821957a01f688f79a02546 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 1 Dec 2021 18:51:27 -0800 Subject: [PATCH 2/2] Suggest collecting into `Vec<_>` when collecting into `[_]` --- library/core/src/iter/traits/collect.rs | 26 +++++++++++++++++++ src/test/ui/iterators/collect-into-slice.rs | 15 +++++++++++ .../ui/iterators/collect-into-slice.stderr | 26 +++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 src/test/ui/iterators/collect-into-slice.rs create mode 100644 src/test/ui/iterators/collect-into-slice.stderr diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index fc14620a2df84..637d7bc44885e 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -81,6 +81,32 @@ /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented( + on( + _Self = "[{A}]", + message = "a value of type `{Self}` cannot be built since `{Self}` has no definite size", + label = "try explicitly collecting into a `Vec<{A}>`", + ), + on( + all( + A = "{integer}", + any( + _Self = "[i8]", + _Self = "[i16]", + _Self = "[i32]", + _Self = "[i64]", + _Self = "[i128]", + _Self = "[isize]", + _Self = "[u8]", + _Self = "[u16]", + _Self = "[u32]", + _Self = "[u64]", + _Self = "[u128]", + _Self = "[usize]" + ) + ), + message = "a value of type `{Self}` cannot be built since `{Self}` has no definite size", + label = "try explicitly collecting into a `Vec<{A}>`", + ), message = "a value of type `{Self}` cannot be built from an iterator \ over elements of type `{A}`", label = "value of type `{Self}` cannot be built from `std::iter::Iterator`" diff --git a/src/test/ui/iterators/collect-into-slice.rs b/src/test/ui/iterators/collect-into-slice.rs new file mode 100644 index 0000000000000..905752dec7478 --- /dev/null +++ b/src/test/ui/iterators/collect-into-slice.rs @@ -0,0 +1,15 @@ +fn process_slice(data: &[i32]) { + //~^ NOTE required by a bound in this + todo!() +} + +fn main() { + let some_generated_vec = (0..10).collect(); + //~^ ERROR the size for values of type `[i32]` cannot be known at compilation time + //~| ERROR a value of type `[i32]` cannot be built since `[i32]` has no definite size + //~| NOTE try explicitly collecting into a `Vec<{integer}>` + //~| NOTE required by a bound in `collect` + //~| NOTE all local variables must have a statically known size + //~| NOTE doesn't have a size known at compile-time + process_slice(&some_generated_vec); +} diff --git a/src/test/ui/iterators/collect-into-slice.stderr b/src/test/ui/iterators/collect-into-slice.stderr new file mode 100644 index 0000000000000..521f239451d2f --- /dev/null +++ b/src/test/ui/iterators/collect-into-slice.stderr @@ -0,0 +1,26 @@ +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time + --> $DIR/collect-into-slice.rs:7:9 + | +LL | let some_generated_vec = (0..10).collect(); + | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[i32]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + +error[E0277]: a value of type `[i32]` cannot be built since `[i32]` has no definite size + --> $DIR/collect-into-slice.rs:7:38 + | +LL | let some_generated_vec = (0..10).collect(); + | ^^^^^^^ try explicitly collecting into a `Vec<{integer}>` + | + = help: the trait `FromIterator<{integer}>` is not implemented for `[i32]` +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | fn collect>(self) -> B + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`.