Skip to content

Commit 5cc99ee

Browse files
committed
Handle missing projection restriction
1 parent daa8491 commit 5cc99ee

13 files changed

+134
-25
lines changed

src/librustc/traits/error_reporting.rs

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -975,11 +975,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
975975
trait_ref.self_ty(),
976976
trait_ref.self_ty().kind,
977977
);
978-
let param_ty = if let ty::Param(param_ty) = &trait_ref.self_ty().kind {
979-
param_ty
980-
} else {
981-
err.help(&format!("consider adding a `where {}` bound", trait_ref.to_predicate()));
982-
return;
978+
let (param_ty, projection) = match &trait_ref.self_ty().kind {
979+
ty::Param(param_ty) => (Some(param_ty), None),
980+
ty::Projection(projection) => (None, Some(projection)),
981+
_ => {
982+
err.help(&format!("consider adding a `where {}` bound", trait_ref.to_predicate()));
983+
return;
984+
}
983985
};
984986

985987
let mut hir_id = body_id;
@@ -996,7 +998,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
996998
hir::Node::ImplItem(hir::ImplItem {
997999
generics,
9981000
kind: hir::ImplItemKind::Method(hir::MethodSig { decl, .. }, _), ..
999-
}) if param_ty.name.as_str() == "Self" => {
1001+
}) if param_ty.map(|p| p.name.as_str() == "Self").unwrap_or(false) => {
10001002
if !generics.where_clause.predicates.is_empty() {
10011003
err.span_suggestion(
10021004
generics.where_clause.span().unwrap().shrink_to_hi(),
@@ -1014,6 +1016,34 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
10141016
}
10151017
return;
10161018
}
1019+
hir::Node::Item(hir::Item {
1020+
kind: hir::ItemKind::Fn(decl, _, generics, _), ..
1021+
}) |
1022+
hir::Node::TraitItem(hir::TraitItem {
1023+
generics,
1024+
kind: hir::TraitItemKind::Method(hir::MethodSig { decl, .. }, _), ..
1025+
}) |
1026+
hir::Node::ImplItem(hir::ImplItem {
1027+
generics,
1028+
kind: hir::ImplItemKind::Method(hir::MethodSig { decl, .. }, _), ..
1029+
}) if projection.is_some() => {
1030+
if !generics.where_clause.predicates.is_empty() {
1031+
err.span_suggestion(
1032+
generics.where_clause.span().unwrap().shrink_to_hi(),
1033+
"consider further restricting the associated type",
1034+
format!(", {}", trait_ref.to_predicate()),
1035+
Applicability::MachineApplicable,
1036+
);
1037+
} else {
1038+
err.span_suggestion(
1039+
decl.output.span().shrink_to_hi(),
1040+
"consider further restricting the associated type",
1041+
format!(" where {}", trait_ref.to_predicate()),
1042+
Applicability::MachineApplicable,
1043+
);
1044+
}
1045+
return;
1046+
}
10171047
hir::Node::Item(hir::Item { kind: hir::ItemKind::Struct(_, generics), span, .. }) |
10181048
hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, generics), span, .. }) |
10191049
hir::Node::Item(hir::Item { kind: hir::ItemKind::Union(_, generics), span, .. }) |
@@ -1036,9 +1066,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
10361066
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }), span, ..
10371067
}) |
10381068
hir::Node::TraitItem(hir::TraitItem { generics, span, .. }) |
1039-
hir::Node::ImplItem(hir::ImplItem { generics, span, .. }) => {
1069+
hir::Node::ImplItem(hir::ImplItem { generics, span, .. })
1070+
if param_ty.is_some() => {
10401071
let restrict_msg = "consider further restricting this bound";
1041-
let param_name = param_ty.name.as_str();
1072+
let param_name = param_ty.unwrap().name.as_str();
10421073
for param in &generics.params {
10431074
if param_name == param.name.ident().as_str() {
10441075
if param_name.starts_with("impl ") {
@@ -1064,7 +1095,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
10641095
generics.where_clause.span().unwrap().shrink_to_hi(),
10651096
&format!(
10661097
"consider further restricting type parameter `{}`",
1067-
param_ty,
1098+
param_name,
10681099
),
10691100
format!(", {}", trait_ref.to_predicate()),
10701101
Applicability::MachineApplicable,

src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ LL | impl Case1 for S1 {
99
error[E0277]: `<<T as Case1>::C as std::iter::Iterator>::Item` is not an iterator
1010
--> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1
1111
|
12-
LL | / fn assume_case1<T: Case1>() {
12+
LL | fn assume_case1<T: Case1>() {
13+
| ^ - help: consider further restricting the associated type: `where <<T as Case1>::C as std::iter::Iterator>::Item: std::iter::Iterator`
14+
| _|
15+
| |
1316
LL | |
1417
LL | |
1518
LL | |
@@ -19,15 +22,17 @@ LL | | }
1922
| |_^ `<<T as Case1>::C as std::iter::Iterator>::Item` is not an iterator
2023
|
2124
= help: the trait `std::iter::Iterator` is not implemented for `<<T as Case1>::C as std::iter::Iterator>::Item`
22-
= help: consider adding a `where <<T as Case1>::C as std::iter::Iterator>::Item: std::iter::Iterator` bound
2325

2426
error[E0277]: `<<T as Case1>::C as std::iter::Iterator>::Item` cannot be sent between threads safely
2527
--> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1
2628
|
2729
LL | trait Case1 {
2830
| ----------- required by `Case1`
2931
...
30-
LL | / fn assume_case1<T: Case1>() {
32+
LL | fn assume_case1<T: Case1>() {
33+
| ^ - help: consider further restricting the associated type: `where <<T as Case1>::C as std::iter::Iterator>::Item: std::marker::Send`
34+
| _|
35+
| |
3136
LL | |
3237
LL | |
3338
LL | |
@@ -37,15 +42,17 @@ LL | | }
3742
| |_^ `<<T as Case1>::C as std::iter::Iterator>::Item` cannot be sent between threads safely
3843
|
3944
= help: the trait `std::marker::Send` is not implemented for `<<T as Case1>::C as std::iter::Iterator>::Item`
40-
= help: consider adding a `where <<T as Case1>::C as std::iter::Iterator>::Item: std::marker::Send` bound
4145

4246
error[E0277]: `<<T as Case1>::C as std::iter::Iterator>::Item` cannot be shared between threads safely
4347
--> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1
4448
|
4549
LL | trait Case1 {
4650
| ----------- required by `Case1`
4751
...
48-
LL | / fn assume_case1<T: Case1>() {
52+
LL | fn assume_case1<T: Case1>() {
53+
| ^ - help: consider further restricting the associated type: `where <<T as Case1>::C as std::iter::Iterator>::Item: std::marker::Sync`
54+
| _|
55+
| |
4956
LL | |
5057
LL | |
5158
LL | |
@@ -55,7 +62,6 @@ LL | | }
5562
| |_^ `<<T as Case1>::C as std::iter::Iterator>::Item` cannot be shared between threads safely
5663
|
5764
= help: the trait `std::marker::Sync` is not implemented for `<<T as Case1>::C as std::iter::Iterator>::Item`
58-
= help: consider adding a `where <<T as Case1>::C as std::iter::Iterator>::Item: std::marker::Sync` bound
5965

6066
error[E0277]: `<_ as Lam<&'a u8>>::App` doesn't implement `std::fmt::Debug`
6167
--> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// run-rustfix
2+
// Test equality constraints on associated types in a where clause.
3+
#![allow(dead_code)]
4+
5+
pub trait ToInt {
6+
fn to_int(&self) -> isize;
7+
}
8+
9+
pub trait GetToInt
10+
{
11+
type R;
12+
13+
fn get(&self) -> <Self as GetToInt>::R;
14+
}
15+
16+
fn foo<G>(g: G) -> isize
17+
where G : GetToInt, <G as GetToInt>::R: ToInt
18+
{
19+
ToInt::to_int(&g.get()) //~ ERROR E0277
20+
}
21+
22+
fn bar<G : GetToInt>(g: G) -> isize
23+
where G::R : ToInt
24+
{
25+
ToInt::to_int(&g.get()) // OK
26+
}
27+
28+
pub fn main() {
29+
}

src/test/ui/associated-types/associated-types-bound-failure.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
// run-rustfix
12
// Test equality constraints on associated types in a where clause.
3+
#![allow(dead_code)]
24

35
pub trait ToInt {
46
fn to_int(&self) -> isize;

src/test/ui/associated-types/associated-types-bound-failure.stderr

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
error[E0277]: the trait bound `<G as GetToInt>::R: ToInt` is not satisfied
2-
--> $DIR/associated-types-bound-failure.rs:17:19
2+
--> $DIR/associated-types-bound-failure.rs:19:19
33
|
44
LL | fn to_int(&self) -> isize;
55
| -------------------------- required by `ToInt::to_int`
66
...
7+
LL | where G : GetToInt
8+
| - help: consider further restricting the associated type: `, <G as GetToInt>::R: ToInt`
9+
LL | {
710
LL | ToInt::to_int(&g.get())
811
| ^^^^^^^^ the trait `ToInt` is not implemented for `<G as GetToInt>::R`
9-
|
10-
= help: consider adding a `where <G as GetToInt>::R: ToInt` bound
1112

1213
error: aborting due to previous error
1314

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// run-rustfix
2+
#![allow(dead_code, unused_variables)]
3+
4+
trait Get {
5+
type Value: ?Sized;
6+
fn get(&self) -> <Self as Get>::Value;
7+
}
8+
9+
fn foo<T:Get>(t: T) where <T as Get>::Value: std::marker::Sized{
10+
let x = t.get(); //~ ERROR the size for values of type
11+
}
12+
13+
fn main() {
14+
}

src/test/ui/associated-types/associated-types-unsized.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// run-rustfix
2+
#![allow(dead_code, unused_variables)]
3+
14
trait Get {
25
type Value: ?Sized;
36
fn get(&self) -> <Self as Get>::Value;

src/test/ui/associated-types/associated-types-unsized.stderr

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
error[E0277]: the size for values of type `<T as Get>::Value` cannot be known at compilation time
2-
--> $DIR/associated-types-unsized.rs:7:9
2+
--> $DIR/associated-types-unsized.rs:10:9
33
|
4+
LL | fn foo<T:Get>(t: T) {
5+
| - help: consider further restricting the associated type: `where <T as Get>::Value: std::marker::Sized`
46
LL | let x = t.get();
57
| ^ doesn't have a size known at compile-time
68
|
79
= help: the trait `std::marker::Sized` is not implemented for `<T as Get>::Value`
810
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
9-
= help: consider adding a `where <T as Get>::Value: std::marker::Sized` bound
1011
= note: all local variables must have a statically known size
1112
= help: unsized locals are gated as an unstable feature
1213

src/test/ui/issues/issue-22872.stderr

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
error[E0277]: `<P as Process<'_>>::Item` is not an iterator
22
--> $DIR/issue-22872.rs:20:40
33
|
4+
LL | fn push_process<P>(process: P) where P: Process<'static> {
5+
| - help: consider further restricting the associated type: `, <P as Process<'_>>::Item: std::iter::Iterator`
46
LL | let _: Box<dyn for<'b> Wrap<'b>> = Box::new(Wrapper(process));
57
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ `<P as Process<'_>>::Item` is not an iterator
68
|
79
= help: the trait `std::iter::Iterator` is not implemented for `<P as Process<'_>>::Item`
8-
= help: consider adding a `where <P as Process<'_>>::Item: std::iter::Iterator` bound
910
= note: required because of the requirements on the impl of `for<'b> Wrap<'b>` for `Wrapper<P>`
1011
= note: required for the cast to the object type `dyn for<'b> Wrap<'b>`
1112

src/test/ui/issues/issue-42312.stderr

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ error[E0277]: the size for values of type `<Self as std::ops::Deref>::Target` ca
22
--> $DIR/issue-42312.rs:4:29
33
|
44
LL | fn baz(_: Self::Target) where Self: Deref {}
5-
| ^ doesn't have a size known at compile-time
5+
| ^ - help: consider further restricting the associated type: `, <Self as std::ops::Deref>::Target: std::marker::Sized`
6+
| |
7+
| doesn't have a size known at compile-time
68
|
79
= help: the trait `std::marker::Sized` is not implemented for `<Self as std::ops::Deref>::Target`
810
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
9-
= help: consider adding a `where <Self as std::ops::Deref>::Target: std::marker::Sized` bound
1011
= note: all function arguments must have a statically known size
1112
= help: unsized locals are gated as an unstable feature
1213

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// run-rustfix
2+
// Test that we do not consider associated types to be sendable without
3+
// some applicable trait bound (and we don't ICE).
4+
#![allow(dead_code)]
5+
6+
trait Trait {
7+
type AssocType;
8+
fn dummy(&self) { }
9+
}
10+
fn bar<T:Trait+Send>() where <T as Trait>::AssocType: std::marker::Send{
11+
is_send::<T::AssocType>(); //~ ERROR E0277
12+
}
13+
14+
fn is_send<T:Send>() {
15+
}
16+
17+
fn main() { }

src/test/ui/typeck/typeck-default-trait-impl-assoc-type.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
// run-rustfix
12
// Test that we do not consider associated types to be sendable without
23
// some applicable trait bound (and we don't ICE).
4+
#![allow(dead_code)]
35

46
trait Trait {
57
type AssocType;

src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
error[E0277]: `<T as Trait>::AssocType` cannot be sent between threads safely
2-
--> $DIR/typeck-default-trait-impl-assoc-type.rs:9:5
2+
--> $DIR/typeck-default-trait-impl-assoc-type.rs:11:5
33
|
4+
LL | fn bar<T:Trait+Send>() {
5+
| - help: consider further restricting the associated type: `where <T as Trait>::AssocType: std::marker::Send`
46
LL | is_send::<T::AssocType>();
57
| ^^^^^^^^^^^^^^^^^^^^^^^ `<T as Trait>::AssocType` cannot be sent between threads safely
68
...
79
LL | fn is_send<T:Send>() {
810
| ------- ---- required by this bound in `is_send`
911
|
1012
= help: the trait `std::marker::Send` is not implemented for `<T as Trait>::AssocType`
11-
= help: consider adding a `where <T as Trait>::AssocType: std::marker::Send` bound
1213

1314
error: aborting due to previous error
1415

0 commit comments

Comments
 (0)