Skip to content

Commit 545320a

Browse files
committed
Suggest adding super trait constraints
1 parent d903a9d commit 545320a

File tree

6 files changed

+96
-13
lines changed

6 files changed

+96
-13
lines changed

src/librustc_trait_selection/traits/error_reporting/suggestions.rs

+41-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_middle::ty::{
1515
self, suggest_constraining_type_param, AdtKind, DefIdTree, Infer, InferTy, ToPredicate, Ty,
1616
TyCtxt, TypeFoldable, WithConstness,
1717
};
18-
use rustc_span::symbol::{kw, sym, Symbol};
18+
use rustc_span::symbol::{kw, sym, Ident, Symbol};
1919
use rustc_span::{MultiSpan, Span, DUMMY_SP};
2020
use std::fmt;
2121

@@ -173,6 +173,7 @@ fn suggest_restriction(
173173
fn_sig: Option<&hir::FnSig<'_>>,
174174
projection: Option<&ty::ProjectionTy<'_>>,
175175
trait_ref: ty::PolyTraitRef<'_>,
176+
super_traits: Option<(&Ident, &hir::GenericBounds<'_>)>,
176177
) {
177178
let span = generics.where_clause.span_for_predicates_or_empty_place();
178179
if span.from_expansion() || span.desugaring_kind().is_some() {
@@ -262,8 +263,22 @@ fn suggest_restriction(
262263
);
263264
} else {
264265
// Trivial case: `T` needs an extra bound: `T: Bound`.
265-
let (sp, sugg) =
266-
predicate_constraint(generics, trait_ref.without_const().to_predicate().to_string());
266+
let (sp, sugg) = match super_traits {
267+
None => {
268+
predicate_constraint(generics, trait_ref.without_const().to_predicate().to_string())
269+
}
270+
Some((ident, bounds)) => match bounds {
271+
[.., bound] => (
272+
bound.span().shrink_to_hi(),
273+
format!(" + {}", trait_ref.print_only_trait_path().to_string()),
274+
),
275+
[] => (
276+
ident.span.shrink_to_hi(),
277+
format!(": {}", trait_ref.print_only_trait_path().to_string()),
278+
),
279+
},
280+
};
281+
267282
let appl = Applicability::MachineApplicable;
268283
err.span_suggestion(sp, &format!("consider further restricting {}", msg), sugg, appl);
269284
}
@@ -288,13 +303,33 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
288303
let mut hir_id = body_id;
289304
while let Some(node) = self.tcx.hir().find(hir_id) {
290305
match node {
306+
hir::Node::Item(hir::Item {
307+
ident,
308+
kind: hir::ItemKind::Trait(_, _, generics, bounds, _),
309+
..
310+
}) if param_ty && self_ty == self.tcx.types.self_param => {
311+
// Restricting `Self` for a single method.
312+
suggest_restriction(
313+
&generics,
314+
"`Self`",
315+
err,
316+
None,
317+
projection,
318+
trait_ref,
319+
Some((ident, bounds)),
320+
);
321+
return;
322+
}
323+
291324
hir::Node::TraitItem(hir::TraitItem {
292325
generics,
293326
kind: hir::TraitItemKind::Fn(..),
294327
..
295328
}) if param_ty && self_ty == self.tcx.types.self_param => {
296329
// Restricting `Self` for a single method.
297-
suggest_restriction(&generics, "`Self`", err, None, projection, trait_ref);
330+
suggest_restriction(
331+
&generics, "`Self`", err, None, projection, trait_ref, None,
332+
);
298333
return;
299334
}
300335

@@ -319,6 +354,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
319354
Some(fn_sig),
320355
projection,
321356
trait_ref,
357+
None,
322358
);
323359
return;
324360
}
@@ -336,6 +372,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
336372
None,
337373
projection,
338374
trait_ref,
375+
None,
339376
);
340377
return;
341378
}

src/test/ui/associated-types/defaults-unsound-62211-1.stderr

+12-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied
22
--> $DIR/defaults-unsound-62211-1.rs:21:18
33
|
44
LL | trait UncheckedCopy: Sized {
5-
| -------------------------- required by `UncheckedCopy`
5+
| --------------------------- help: consider further restricting `Self`: `+ std::marker::Copy`
6+
| |
7+
| required by `UncheckedCopy`
68
...
79
LL | type Output: Copy
810
| ^^^^ the trait `std::marker::Copy` is not implemented for `Self`
@@ -11,7 +13,9 @@ error[E0277]: cannot add-assign `&'static str` to `Self`
1113
--> $DIR/defaults-unsound-62211-1.rs:25:7
1214
|
1315
LL | trait UncheckedCopy: Sized {
14-
| -------------------------- required by `UncheckedCopy`
16+
| --------------------------- help: consider further restricting `Self`: `+ std::ops::AddAssign<&'static str>`
17+
| |
18+
| required by `UncheckedCopy`
1519
...
1620
LL | + AddAssign<&'static str>
1721
| ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str`
@@ -22,7 +26,9 @@ error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied
2226
--> $DIR/defaults-unsound-62211-1.rs:23:7
2327
|
2428
LL | trait UncheckedCopy: Sized {
25-
| -------------------------- required by `UncheckedCopy`
29+
| --------------------------- help: consider further restricting `Self`: `+ std::ops::Deref`
30+
| |
31+
| required by `UncheckedCopy`
2632
...
2733
LL | + Deref<Target = str>
2834
| ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self`
@@ -31,7 +37,9 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display`
3137
--> $DIR/defaults-unsound-62211-1.rs:28:7
3238
|
3339
LL | trait UncheckedCopy: Sized {
34-
| -------------------------- required by `UncheckedCopy`
40+
| --------------------------- help: consider further restricting `Self`: `+ std::fmt::Display`
41+
| |
42+
| required by `UncheckedCopy`
3543
...
3644
LL | + Display = Self;
3745
| ^^^^^^^ `Self` cannot be formatted with the default formatter

src/test/ui/associated-types/defaults-unsound-62211-2.stderr

+12-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied
22
--> $DIR/defaults-unsound-62211-2.rs:21:18
33
|
44
LL | trait UncheckedCopy: Sized {
5-
| -------------------------- required by `UncheckedCopy`
5+
| --------------------------- help: consider further restricting `Self`: `+ std::marker::Copy`
6+
| |
7+
| required by `UncheckedCopy`
68
...
79
LL | type Output: Copy
810
| ^^^^ the trait `std::marker::Copy` is not implemented for `Self`
@@ -11,7 +13,9 @@ error[E0277]: cannot add-assign `&'static str` to `Self`
1113
--> $DIR/defaults-unsound-62211-2.rs:25:7
1214
|
1315
LL | trait UncheckedCopy: Sized {
14-
| -------------------------- required by `UncheckedCopy`
16+
| --------------------------- help: consider further restricting `Self`: `+ std::ops::AddAssign<&'static str>`
17+
| |
18+
| required by `UncheckedCopy`
1519
...
1620
LL | + AddAssign<&'static str>
1721
| ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str`
@@ -22,7 +26,9 @@ error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied
2226
--> $DIR/defaults-unsound-62211-2.rs:23:7
2327
|
2428
LL | trait UncheckedCopy: Sized {
25-
| -------------------------- required by `UncheckedCopy`
29+
| --------------------------- help: consider further restricting `Self`: `+ std::ops::Deref`
30+
| |
31+
| required by `UncheckedCopy`
2632
...
2733
LL | + Deref<Target = str>
2834
| ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self`
@@ -31,7 +37,9 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display`
3137
--> $DIR/defaults-unsound-62211-2.rs:28:7
3238
|
3339
LL | trait UncheckedCopy: Sized {
34-
| -------------------------- required by `UncheckedCopy`
40+
| --------------------------- help: consider further restricting `Self`: `+ std::fmt::Display`
41+
| |
42+
| required by `UncheckedCopy`
3543
...
3644
LL | + Display = Self;
3745
| ^^^^^^^ `Self` cannot be formatted with the default formatter

src/test/ui/associated-types/issue-63593.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation
22
--> $DIR/issue-63593.rs:9:5
33
|
44
LL | trait MyTrait {
5-
| ------------- required by `MyTrait`
5+
| -------------- help: consider further restricting `Self`: `: std::marker::Sized`
6+
| |
7+
| required by `MyTrait`
68
LL | type This = Self;
79
| ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
810
|
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
use std::ops::{Add, Sub, Mul, Div};
2+
3+
trait ArithmeticOps: Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + Div<Output=Self> {}
4+
//~^ ERROR the size for values of type `Self` cannot be known at compilation time
5+
6+
impl<T> ArithmeticOps for T where T: Add<Output=T> + Sub<Output=T> + Mul<Output=T> + Div<Output=T> {
7+
// Nothing to implement, since T already supports the other traits.
8+
// It has the functions it needs already
9+
}
10+
11+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0277]: the size for values of type `Self` cannot be known at compilation time
2+
--> $DIR/trait-with-supertraits-needing-sized-self.rs:3:22
3+
|
4+
LL | trait ArithmeticOps: Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + Div<Output=Self> {}
5+
| ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - help: consider further restricting `Self`: `+ std::marker::Sized`
6+
|
7+
::: $SRC_DIR/libcore/ops/arith.rs:LL:COL
8+
|
9+
LL | pub trait Add<Rhs = Self> {
10+
| --- required by this bound in `std::ops::Add`
11+
|
12+
= help: the trait `std::marker::Sized` is not implemented for `Self`
13+
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
14+
15+
error: aborting due to previous error
16+
17+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)