Skip to content

Commit ee7e717

Browse files
author
Lukas Markeffsky
committed
tweak suggestion for argument-position impl ?Sized
1 parent 5a65be8 commit ee7e717

File tree

3 files changed

+74
-12
lines changed

3 files changed

+74
-12
lines changed

compiler/rustc_middle/src/ty/diagnostics.rs

+29-12
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnostic
1414
use rustc_hir as hir;
1515
use rustc_hir::def::DefKind;
1616
use rustc_hir::def_id::DefId;
17-
use rustc_hir::WherePredicate;
18-
use rustc_span::Span;
17+
use rustc_hir::{PredicateOrigin, WherePredicate};
18+
use rustc_span::{BytePos, Span};
1919
use rustc_type_ir::sty::TyKind::*;
2020

2121
impl<'tcx> IntoDiagnosticArg for Ty<'tcx> {
@@ -156,10 +156,11 @@ enum SuggestChangingConstraintsMessage<'a> {
156156
RestrictBoundFurther,
157157
RestrictType { ty: &'a str },
158158
RestrictTypeFurther { ty: &'a str },
159-
RemovingQSized,
159+
RemoveMaybeUnsized,
160+
ReplaceMaybeUnsizedWithSized,
160161
}
161162

162-
fn suggest_removing_unsized_bound(
163+
fn suggest_changing_unsized_bound(
163164
generics: &hir::Generics<'_>,
164165
suggestions: &mut Vec<(Span, String, SuggestChangingConstraintsMessage<'_>)>,
165166
param: &hir::GenericParam<'_>,
@@ -183,12 +184,25 @@ fn suggest_removing_unsized_bound(
183184
if poly.trait_ref.trait_def_id() != def_id {
184185
continue;
185186
}
186-
let sp = generics.span_for_bound_removal(where_pos, pos);
187-
suggestions.push((
188-
sp,
189-
String::new(),
190-
SuggestChangingConstraintsMessage::RemovingQSized,
191-
));
187+
if predicate.origin == PredicateOrigin::ImplTrait && predicate.bounds.len() == 1 {
188+
// For `impl ?Sized` with no other bounds, suggest `impl Sized` instead.
189+
let bound_span = bound.span();
190+
if bound_span.can_be_used_for_suggestions() {
191+
let question_span = bound_span.with_hi(bound_span.lo() + BytePos(1));
192+
suggestions.push((
193+
question_span,
194+
String::new(),
195+
SuggestChangingConstraintsMessage::ReplaceMaybeUnsizedWithSized,
196+
));
197+
}
198+
} else {
199+
let sp = generics.span_for_bound_removal(where_pos, pos);
200+
suggestions.push((
201+
sp,
202+
String::new(),
203+
SuggestChangingConstraintsMessage::RemoveMaybeUnsized,
204+
));
205+
}
192206
}
193207
}
194208
}
@@ -245,7 +259,7 @@ pub fn suggest_constraining_type_params<'a>(
245259
param.span,
246260
format!("this type parameter needs to be `{}`", constraint),
247261
);
248-
suggest_removing_unsized_bound(generics, &mut suggestions, param, def_id);
262+
suggest_changing_unsized_bound(generics, &mut suggestions, param, def_id);
249263
}
250264
}
251265

@@ -395,9 +409,12 @@ pub fn suggest_constraining_type_params<'a>(
395409
SuggestChangingConstraintsMessage::RestrictTypeFurther { ty } => {
396410
Cow::from(format!("consider further restricting type parameter `{}`", ty))
397411
}
398-
SuggestChangingConstraintsMessage::RemovingQSized => {
412+
SuggestChangingConstraintsMessage::RemoveMaybeUnsized => {
399413
Cow::from("consider removing the `?Sized` bound to make the type parameter `Sized`")
400414
}
415+
SuggestChangingConstraintsMessage::ReplaceMaybeUnsizedWithSized => {
416+
Cow::from("consider replacing `?Sized` with `Sized`")
417+
}
401418
};
402419

403420
err.span_suggestion_verbose(span, msg, suggestion, applicability);

tests/ui/trait-bounds/apit-unsized.rs

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
fn foo(_: impl Iterator<Item = i32> + ?Sized) {} //~ ERROR [E0277]
2+
fn bar(_: impl ?Sized) {} //~ ERROR [E0277]
3+
4+
fn main() {}
+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
error[E0277]: the size for values of type `impl Iterator<Item = i32> + ?Sized` cannot be known at compilation time
2+
--> $DIR/apit-unsized.rs:1:8
3+
|
4+
LL | fn foo(_: impl Iterator<Item = i32> + ?Sized) {}
5+
| ^ ---------------------------------- this type parameter needs to be `std::marker::Sized`
6+
| |
7+
| doesn't have a size known at compile-time
8+
|
9+
= help: unsized fn params are gated as an unstable feature
10+
help: consider removing the `?Sized` bound to make the type parameter `Sized`
11+
|
12+
LL - fn foo(_: impl Iterator<Item = i32> + ?Sized) {}
13+
LL + fn foo(_: impl Iterator<Item = i32>) {}
14+
|
15+
help: function arguments must have a statically known size, borrowed types always have a known size
16+
|
17+
LL | fn foo(_: &impl Iterator<Item = i32> + ?Sized) {}
18+
| +
19+
20+
error[E0277]: the size for values of type `impl ?Sized` cannot be known at compilation time
21+
--> $DIR/apit-unsized.rs:2:8
22+
|
23+
LL | fn bar(_: impl ?Sized) {}
24+
| ^ ----------- this type parameter needs to be `std::marker::Sized`
25+
| |
26+
| doesn't have a size known at compile-time
27+
|
28+
= help: unsized fn params are gated as an unstable feature
29+
help: consider replacing `?Sized` with `Sized`
30+
|
31+
LL - fn bar(_: impl ?Sized) {}
32+
LL + fn bar(_: impl Sized) {}
33+
|
34+
help: function arguments must have a statically known size, borrowed types always have a known size
35+
|
36+
LL | fn bar(_: &impl ?Sized) {}
37+
| +
38+
39+
error: aborting due to 2 previous errors
40+
41+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)