Skip to content

Commit 9634559

Browse files
authored
Rollup merge of #91443 - compiler-errors:bad_collect_into_slice, r=wesleywiser
Better suggestions when user tries to collect into an unsized `[_]` 1. Extend the predicate on `rustc_on_unimplemented` to support substitutions like note, label, etc (i.e. treat it as a `OnUnimplementedFormatString`) so we can have slightly more general `rustc_on_unimplemented` special-cases. 2. Add a `rustc_on_unimplemented` if we fail on `FromIterator<A> for [A]` which happens when we don't explicitly collect into a `vec<A>`, but then pass the return from a `.collect` call into something that takes a slice. Fixes #91423
2 parents e7aca89 + fea0015 commit 9634559

File tree

5 files changed

+106
-12
lines changed

5 files changed

+106
-12
lines changed

compiler/rustc_span/src/symbol.rs

+3
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,7 @@ symbols! {
668668
fill,
669669
finish,
670670
flags,
671+
float,
671672
float_to_int_unchecked,
672673
floorf32,
673674
floorf64,
@@ -771,6 +772,8 @@ symbols! {
771772
inline_const_pat,
772773
inout,
773774
instruction_set,
775+
integer_: "integer",
776+
integral,
774777
intel,
775778
into_future,
776779
into_iter,

compiler/rustc_trait_selection/src/traits/on_unimplemented.rs

+36-12
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ impl<'tcx> OnUnimplementedDirective {
6262
let mut errored = false;
6363
let mut item_iter = items.iter();
6464

65+
let parse_value = |value_str| {
66+
OnUnimplementedFormatString::try_parse(tcx, trait_def_id, value_str, span).map(Some)
67+
};
68+
6569
let condition = if is_root {
6670
None
6771
} else {
@@ -86,7 +90,14 @@ impl<'tcx> OnUnimplementedDirective {
8690
None,
8791
)
8892
})?;
89-
attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |_| true);
93+
attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |item| {
94+
if let Some(symbol) = item.value_str() {
95+
if parse_value(symbol).is_err() {
96+
errored = true;
97+
}
98+
}
99+
true
100+
});
90101
Some(cond.clone())
91102
};
92103

@@ -97,10 +108,6 @@ impl<'tcx> OnUnimplementedDirective {
97108
let mut subcommands = vec![];
98109
let mut append_const_msg = None;
99110

100-
let parse_value = |value_str| {
101-
OnUnimplementedFormatString::try_parse(tcx, trait_def_id, value_str, span).map(Some)
102-
};
103-
104111
for item in item_iter {
105112
if item.has_name(sym::message) && message.is_none() {
106113
if let Some(message_) = item.value_str() {
@@ -221,6 +228,9 @@ impl<'tcx> OnUnimplementedDirective {
221228
let mut append_const_msg = None;
222229
info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options);
223230

231+
let options_map: FxHashMap<Symbol, String> =
232+
options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect();
233+
224234
for command in self.subcommands.iter().chain(Some(self)).rev() {
225235
if let Some(ref condition) = command.condition {
226236
if !attr::eval_condition(
@@ -229,7 +239,11 @@ impl<'tcx> OnUnimplementedDirective {
229239
Some(tcx.features()),
230240
&mut |c| {
231241
c.ident().map_or(false, |ident| {
232-
options.contains(&(ident.name, c.value_str().map(|s| s.to_string())))
242+
let value = c.value_str().map(|s| {
243+
OnUnimplementedFormatString(s).format(tcx, trait_ref, &options_map)
244+
});
245+
246+
options.contains(&(ident.name, value))
233247
})
234248
},
235249
) {
@@ -257,13 +271,11 @@ impl<'tcx> OnUnimplementedDirective {
257271
append_const_msg = command.append_const_msg.clone();
258272
}
259273

260-
let options: FxHashMap<Symbol, String> =
261-
options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect();
262274
OnUnimplementedNote {
263-
label: label.map(|l| l.format(tcx, trait_ref, &options)),
264-
message: message.map(|m| m.format(tcx, trait_ref, &options)),
265-
note: note.map(|n| n.format(tcx, trait_ref, &options)),
266-
enclosing_scope: enclosing_scope.map(|e_s| e_s.format(tcx, trait_ref, &options)),
275+
label: label.map(|l| l.format(tcx, trait_ref, &options_map)),
276+
message: message.map(|m| m.format(tcx, trait_ref, &options_map)),
277+
note: note.map(|n| n.format(tcx, trait_ref, &options_map)),
278+
enclosing_scope: enclosing_scope.map(|e_s| e_s.format(tcx, trait_ref, &options_map)),
267279
append_const_msg,
268280
}
269281
}
@@ -306,6 +318,12 @@ impl<'tcx> OnUnimplementedFormatString {
306318
Position::ArgumentNamed(s) if s == sym::from_desugaring => (),
307319
// `{ItemContext}` is allowed
308320
Position::ArgumentNamed(s) if s == sym::ItemContext => (),
321+
// `{integral}` and `{integer}` and `{float}` are allowed
322+
Position::ArgumentNamed(s)
323+
if s == sym::integral || s == sym::integer_ || s == sym::float =>
324+
{
325+
()
326+
}
309327
// So is `{A}` if A is a type parameter
310328
Position::ArgumentNamed(s) => {
311329
match generics.params.iter().find(|param| param.name == s) {
@@ -385,6 +403,12 @@ impl<'tcx> OnUnimplementedFormatString {
385403
&empty_string
386404
} else if s == sym::ItemContext {
387405
&item_context
406+
} else if s == sym::integral {
407+
"{integral}"
408+
} else if s == sym::integer_ {
409+
"{integer}"
410+
} else if s == sym::float {
411+
"{float}"
388412
} else {
389413
bug!(
390414
"broken on_unimplemented {:?} for {:?}: \

library/core/src/iter/traits/collect.rs

+26
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,32 @@
8181
/// ```
8282
#[stable(feature = "rust1", since = "1.0.0")]
8383
#[rustc_on_unimplemented(
84+
on(
85+
_Self = "[{A}]",
86+
message = "a value of type `{Self}` cannot be built since `{Self}` has no definite size",
87+
label = "try explicitly collecting into a `Vec<{A}>`",
88+
),
89+
on(
90+
all(
91+
A = "{integer}",
92+
any(
93+
_Self = "[i8]",
94+
_Self = "[i16]",
95+
_Self = "[i32]",
96+
_Self = "[i64]",
97+
_Self = "[i128]",
98+
_Self = "[isize]",
99+
_Self = "[u8]",
100+
_Self = "[u16]",
101+
_Self = "[u32]",
102+
_Self = "[u64]",
103+
_Self = "[u128]",
104+
_Self = "[usize]"
105+
)
106+
),
107+
message = "a value of type `{Self}` cannot be built since `{Self}` has no definite size",
108+
label = "try explicitly collecting into a `Vec<{A}>`",
109+
),
84110
message = "a value of type `{Self}` cannot be built from an iterator \
85111
over elements of type `{A}`",
86112
label = "value of type `{Self}` cannot be built from `std::iter::Iterator<Item={A}>`"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
fn process_slice(data: &[i32]) {
2+
//~^ NOTE required by a bound in this
3+
todo!()
4+
}
5+
6+
fn main() {
7+
let some_generated_vec = (0..10).collect();
8+
//~^ ERROR the size for values of type `[i32]` cannot be known at compilation time
9+
//~| ERROR a value of type `[i32]` cannot be built since `[i32]` has no definite size
10+
//~| NOTE try explicitly collecting into a `Vec<{integer}>`
11+
//~| NOTE required by a bound in `collect`
12+
//~| NOTE all local variables must have a statically known size
13+
//~| NOTE doesn't have a size known at compile-time
14+
process_slice(&some_generated_vec);
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
2+
--> $DIR/collect-into-slice.rs:7:9
3+
|
4+
LL | let some_generated_vec = (0..10).collect();
5+
| ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
6+
|
7+
= help: the trait `Sized` is not implemented for `[i32]`
8+
= note: all local variables must have a statically known size
9+
= help: unsized locals are gated as an unstable feature
10+
11+
error[E0277]: a value of type `[i32]` cannot be built since `[i32]` has no definite size
12+
--> $DIR/collect-into-slice.rs:7:38
13+
|
14+
LL | let some_generated_vec = (0..10).collect();
15+
| ^^^^^^^ try explicitly collecting into a `Vec<{integer}>`
16+
|
17+
= help: the trait `FromIterator<{integer}>` is not implemented for `[i32]`
18+
note: required by a bound in `collect`
19+
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
20+
|
21+
LL | fn collect<B: FromIterator<Self::Item>>(self) -> B
22+
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
23+
24+
error: aborting due to 2 previous errors
25+
26+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)