Skip to content

Commit

Permalink
Suggest adding super trait constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank committed May 12, 2020
1 parent d903a9d commit 545320a
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 13 deletions.
45 changes: 41 additions & 4 deletions src/librustc_trait_selection/traits/error_reporting/suggestions.rs
Expand Up @@ -15,7 +15,7 @@ use rustc_middle::ty::{
self, suggest_constraining_type_param, AdtKind, DefIdTree, Infer, InferTy, ToPredicate, Ty,
TyCtxt, TypeFoldable, WithConstness,
};
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{MultiSpan, Span, DUMMY_SP};
use std::fmt;

Expand Down Expand Up @@ -173,6 +173,7 @@ fn suggest_restriction(
fn_sig: Option<&hir::FnSig<'_>>,
projection: Option<&ty::ProjectionTy<'_>>,
trait_ref: ty::PolyTraitRef<'_>,
super_traits: Option<(&Ident, &hir::GenericBounds<'_>)>,
) {
let span = generics.where_clause.span_for_predicates_or_empty_place();
if span.from_expansion() || span.desugaring_kind().is_some() {
Expand Down Expand Up @@ -262,8 +263,22 @@ fn suggest_restriction(
);
} else {
// Trivial case: `T` needs an extra bound: `T: Bound`.
let (sp, sugg) =
predicate_constraint(generics, trait_ref.without_const().to_predicate().to_string());
let (sp, sugg) = match super_traits {
None => {
predicate_constraint(generics, trait_ref.without_const().to_predicate().to_string())
}
Some((ident, bounds)) => match bounds {
[.., bound] => (
bound.span().shrink_to_hi(),
format!(" + {}", trait_ref.print_only_trait_path().to_string()),
),
[] => (
ident.span.shrink_to_hi(),
format!(": {}", trait_ref.print_only_trait_path().to_string()),
),
},
};

let appl = Applicability::MachineApplicable;
err.span_suggestion(sp, &format!("consider further restricting {}", msg), sugg, appl);
}
Expand All @@ -288,13 +303,33 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
let mut hir_id = body_id;
while let Some(node) = self.tcx.hir().find(hir_id) {
match node {
hir::Node::Item(hir::Item {
ident,
kind: hir::ItemKind::Trait(_, _, generics, bounds, _),
..
}) if param_ty && self_ty == self.tcx.types.self_param => {
// Restricting `Self` for a single method.
suggest_restriction(
&generics,
"`Self`",
err,
None,
projection,
trait_ref,
Some((ident, bounds)),
);
return;
}

hir::Node::TraitItem(hir::TraitItem {
generics,
kind: hir::TraitItemKind::Fn(..),
..
}) if param_ty && self_ty == self.tcx.types.self_param => {
// Restricting `Self` for a single method.
suggest_restriction(&generics, "`Self`", err, None, projection, trait_ref);
suggest_restriction(
&generics, "`Self`", err, None, projection, trait_ref, None,
);
return;
}

Expand All @@ -319,6 +354,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
Some(fn_sig),
projection,
trait_ref,
None,
);
return;
}
Expand All @@ -336,6 +372,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
None,
projection,
trait_ref,
None,
);
return;
}
Expand Down
16 changes: 12 additions & 4 deletions src/test/ui/associated-types/defaults-unsound-62211-1.stderr
Expand Up @@ -2,7 +2,9 @@ error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied
--> $DIR/defaults-unsound-62211-1.rs:21:18
|
LL | trait UncheckedCopy: Sized {
| -------------------------- required by `UncheckedCopy`
| --------------------------- help: consider further restricting `Self`: `+ std::marker::Copy`
| |
| required by `UncheckedCopy`
...
LL | type Output: Copy
| ^^^^ the trait `std::marker::Copy` is not implemented for `Self`
Expand All @@ -11,7 +13,9 @@ error[E0277]: cannot add-assign `&'static str` to `Self`
--> $DIR/defaults-unsound-62211-1.rs:25:7
|
LL | trait UncheckedCopy: Sized {
| -------------------------- required by `UncheckedCopy`
| --------------------------- help: consider further restricting `Self`: `+ std::ops::AddAssign<&'static str>`
| |
| required by `UncheckedCopy`
...
LL | + AddAssign<&'static str>
| ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str`
Expand All @@ -22,7 +26,9 @@ error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied
--> $DIR/defaults-unsound-62211-1.rs:23:7
|
LL | trait UncheckedCopy: Sized {
| -------------------------- required by `UncheckedCopy`
| --------------------------- help: consider further restricting `Self`: `+ std::ops::Deref`
| |
| required by `UncheckedCopy`
...
LL | + Deref<Target = str>
| ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self`
Expand All @@ -31,7 +37,9 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display`
--> $DIR/defaults-unsound-62211-1.rs:28:7
|
LL | trait UncheckedCopy: Sized {
| -------------------------- required by `UncheckedCopy`
| --------------------------- help: consider further restricting `Self`: `+ std::fmt::Display`
| |
| required by `UncheckedCopy`
...
LL | + Display = Self;
| ^^^^^^^ `Self` cannot be formatted with the default formatter
Expand Down
16 changes: 12 additions & 4 deletions src/test/ui/associated-types/defaults-unsound-62211-2.stderr
Expand Up @@ -2,7 +2,9 @@ error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied
--> $DIR/defaults-unsound-62211-2.rs:21:18
|
LL | trait UncheckedCopy: Sized {
| -------------------------- required by `UncheckedCopy`
| --------------------------- help: consider further restricting `Self`: `+ std::marker::Copy`
| |
| required by `UncheckedCopy`
...
LL | type Output: Copy
| ^^^^ the trait `std::marker::Copy` is not implemented for `Self`
Expand All @@ -11,7 +13,9 @@ error[E0277]: cannot add-assign `&'static str` to `Self`
--> $DIR/defaults-unsound-62211-2.rs:25:7
|
LL | trait UncheckedCopy: Sized {
| -------------------------- required by `UncheckedCopy`
| --------------------------- help: consider further restricting `Self`: `+ std::ops::AddAssign<&'static str>`
| |
| required by `UncheckedCopy`
...
LL | + AddAssign<&'static str>
| ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str`
Expand All @@ -22,7 +26,9 @@ error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied
--> $DIR/defaults-unsound-62211-2.rs:23:7
|
LL | trait UncheckedCopy: Sized {
| -------------------------- required by `UncheckedCopy`
| --------------------------- help: consider further restricting `Self`: `+ std::ops::Deref`
| |
| required by `UncheckedCopy`
...
LL | + Deref<Target = str>
| ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self`
Expand All @@ -31,7 +37,9 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display`
--> $DIR/defaults-unsound-62211-2.rs:28:7
|
LL | trait UncheckedCopy: Sized {
| -------------------------- required by `UncheckedCopy`
| --------------------------- help: consider further restricting `Self`: `+ std::fmt::Display`
| |
| required by `UncheckedCopy`
...
LL | + Display = Self;
| ^^^^^^^ `Self` cannot be formatted with the default formatter
Expand Down
4 changes: 3 additions & 1 deletion src/test/ui/associated-types/issue-63593.stderr
Expand Up @@ -2,7 +2,9 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation
--> $DIR/issue-63593.rs:9:5
|
LL | trait MyTrait {
| ------------- required by `MyTrait`
| -------------- help: consider further restricting `Self`: `: std::marker::Sized`
| |
| required by `MyTrait`
LL | type This = Self;
| ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
Expand Down
@@ -0,0 +1,11 @@
use std::ops::{Add, Sub, Mul, Div};

trait ArithmeticOps: Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + Div<Output=Self> {}
//~^ ERROR the size for values of type `Self` cannot be known at compilation time

impl<T> ArithmeticOps for T where T: Add<Output=T> + Sub<Output=T> + Mul<Output=T> + Div<Output=T> {
// Nothing to implement, since T already supports the other traits.
// It has the functions it needs already
}

fn main() {}
@@ -0,0 +1,17 @@
error[E0277]: the size for values of type `Self` cannot be known at compilation time
--> $DIR/trait-with-supertraits-needing-sized-self.rs:3:22
|
LL | trait ArithmeticOps: Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + Div<Output=Self> {}
| ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - help: consider further restricting `Self`: `+ std::marker::Sized`
|
::: $SRC_DIR/libcore/ops/arith.rs:LL:COL
|
LL | pub trait Add<Rhs = Self> {
| --- required by this bound in `std::ops::Add`
|
= help: the trait `std::marker::Sized` is not implemented for `Self`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>

error: aborting due to previous error

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

0 comments on commit 545320a

Please sign in to comment.