Skip to content

Commit 8551cab

Browse files
committed
Account for multiple trait bounds in bare trait object suggestion
Note the parentheses in the last suggestion: ``` error[E0277]: the size for values of type `(dyn Foo + Send + 'static)` cannot be known at compilation time --> $DIR/not-on-bare-trait.rs:7:8 | LL | fn foo(_x: Foo + Send) { | ^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Foo + Send + 'static)` = help: unsized fn params are gated as an unstable feature help: you can use `impl Trait` as the argument type | LL | fn foo(_x: impl Foo + Send) { | ++++ help: function arguments must have a statically known size, borrowed types always have a known size | LL | fn foo(_x: &(Foo + Send)) { | ++ + ```
1 parent 0487500 commit 8551cab

File tree

3 files changed

+56
-8
lines changed

3 files changed

+56
-8
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3202,9 +3202,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
32023202
}
32033203
ObligationCauseCode::SizedArgumentType(ty_span) => {
32043204
if let Some(span) = ty_span {
3205-
if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder()
3205+
let trait_len = if let ty::PredicateKind::Clause(clause) =
3206+
predicate.kind().skip_binder()
32063207
&& let ty::ClauseKind::Trait(trait_pred) = clause
3207-
&& let ty::Dynamic(..) = trait_pred.self_ty().kind()
3208+
&& let ty::Dynamic(preds, ..) = trait_pred.self_ty().kind()
32083209
{
32093210
let span = if let Ok(snippet) =
32103211
self.tcx.sess.source_map().span_to_snippet(span)
@@ -3221,12 +3222,39 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
32213222
"impl ".to_string(),
32223223
Applicability::MaybeIncorrect,
32233224
);
3224-
}
3225-
err.span_suggestion_verbose(
3226-
span.shrink_to_lo(),
3225+
preds
3226+
.iter()
3227+
.filter(|pred| {
3228+
// We only want to count `dyn Foo + Bar`, not `dyn Foo<Bar>`,
3229+
// because the later doesn't need parentheses.
3230+
matches!(
3231+
pred.skip_binder(),
3232+
ty::ExistentialPredicate::Trait(_)
3233+
| ty::ExistentialPredicate::AutoTrait(_)
3234+
)
3235+
})
3236+
.count()
3237+
} else {
3238+
1
3239+
};
3240+
let sugg = if trait_len == 1 {
3241+
vec![(span.shrink_to_lo(), "&".to_string())]
3242+
} else if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
3243+
&& snippet.starts_with('(')
3244+
{
3245+
// We don't want to suggest `&((dyn Foo + Bar))` when we have
3246+
// `(dyn Foo + Bar)`.
3247+
vec![(span.shrink_to_lo(), "&".to_string())]
3248+
} else {
3249+
vec![
3250+
(span.shrink_to_lo(), "&(".to_string()),
3251+
(span.shrink_to_hi(), ")".to_string()),
3252+
]
3253+
};
3254+
err.multipart_suggestion_verbose(
32273255
"function arguments must have a statically known size, borrowed types \
32283256
always have a known size",
3229-
"&",
3257+
sugg,
32303258
Applicability::MachineApplicable,
32313259
);
32323260
} else {

tests/ui/traits/bound/not-on-bare-trait.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,8 @@ fn foo(_x: Foo + Send) {
99
//~| WARN trait objects without an explicit `dyn` are deprecated
1010
//~| WARN this is accepted in the current edition
1111
}
12+
fn bar(_x: (dyn Foo + Send)) {
13+
//~^ ERROR the size for values of type
14+
}
1215

1316
fn main() {}

tests/ui/traits/bound/not-on-bare-trait.stderr

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,26 @@ LL | fn foo(_x: impl Foo + Send) {
3434
| ++++
3535
help: function arguments must have a statically known size, borrowed types always have a known size
3636
|
37-
LL | fn foo(_x: &Foo + Send) {
37+
LL | fn foo(_x: &(Foo + Send)) {
38+
| ++ +
39+
40+
error[E0277]: the size for values of type `(dyn Foo + Send + 'static)` cannot be known at compilation time
41+
--> $DIR/not-on-bare-trait.rs:12:8
42+
|
43+
LL | fn bar(_x: (dyn Foo + Send)) {
44+
| ^^ doesn't have a size known at compile-time
45+
|
46+
= help: the trait `Sized` is not implemented for `(dyn Foo + Send + 'static)`
47+
= help: unsized fn params are gated as an unstable feature
48+
help: you can use `impl Trait` as the argument type
49+
|
50+
LL | fn bar(_x: impl (dyn Foo + Send)) {
51+
| ++++
52+
help: function arguments must have a statically known size, borrowed types always have a known size
53+
|
54+
LL | fn bar(_x: &(dyn Foo + Send)) {
3855
| +
3956

40-
error: aborting due to 1 previous error; 1 warning emitted
57+
error: aborting due to 2 previous errors; 1 warning emitted
4158

4259
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)