Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 7bf75ab

Browse files
committed
Restrict suggestion only to built-in derive traits
Address review comments and rebase. Add more tests.
1 parent b0c41eb commit 7bf75ab

File tree

4 files changed

+92
-14
lines changed

4 files changed

+92
-14
lines changed

‎compiler/rustc_hir_typeck/src/method/suggest.rs

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,7 @@ use rustc_span::symbol::{kw, sym, Ident};
3131
use rustc_span::{
3232
edit_distance, ErrorGuaranteed, ExpnKind, FileName, MacroKind, Span, Symbol, DUMMY_SP,
3333
};
34-
use rustc_trait_selection::error_reporting::traits::on_unimplemented::{
35-
OnUnimplementedNote, TypeErrCtxtExt as _,
36-
};
37-
use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt;
34+
use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedNote;
3835
use rustc_trait_selection::infer::InferCtxtExt;
3936
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
4037
use rustc_trait_selection::traits::{
@@ -1374,16 +1371,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13741371
else {
13751372
continue;
13761373
};
1374+
let lang = tcx.lang_items();
1375+
if ![
1376+
lang.copy_trait(),
1377+
lang.clone_trait(),
1378+
tcx.get_diagnostic_item(sym::Debug),
1379+
tcx.get_diagnostic_item(sym::Eq),
1380+
tcx.get_diagnostic_item(sym::PartialEq),
1381+
tcx.get_diagnostic_item(sym::Default),
1382+
]
1383+
.contains(&Some(trait_pred.def_id()))
1384+
{
1385+
// We restrict ourselves only to built-in `derive`s.
1386+
continue;
1387+
}
13771388
let (adt, params) = match trait_pred.self_ty().kind() {
13781389
ty::Adt(adt, params) if adt.did().is_local() => (*adt, params),
13791390
_ => continue,
13801391
};
1381-
if self
1382-
.tcx
1392+
if tcx
13831393
.all_impls(trait_pred.def_id())
1384-
.filter_map(|imp_did| {
1385-
self.tcx.impl_trait_header(imp_did).map(|h| (imp_did, h))
1386-
})
1394+
.filter_map(|imp_did| tcx.impl_trait_header(imp_did).map(|h| (imp_did, h)))
13871395
.filter(|(did, header)| {
13881396
let imp = header.trait_ref.instantiate_identity();
13891397
let impl_adt = match imp.self_ty().ty_adt_def() {
@@ -1392,7 +1400,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13921400
};
13931401
header.polarity == ty::ImplPolarity::Positive
13941402
&& impl_adt == adt
1395-
&& self.tcx.is_automatically_derived(*did)
1403+
&& tcx.is_automatically_derived(*did)
13961404
})
13971405
.count()
13981406
== 1
@@ -1413,7 +1421,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14131421
// The type param at hand is a local type, try to suggest
14141422
// `derive(Trait)`.
14151423
let trait_ref =
1416-
ty::TraitRef::new(tcx, trait_pred.trait_ref.def_id, [ty]);
1424+
ty::TraitRef::identity(tcx, trait_pred.trait_ref.def_id)
1425+
.with_self_ty(tcx, ty);
14171426
let trait_pred = ty::Binder::dummy(ty::TraitPredicate {
14181427
trait_ref,
14191428
polarity: ty::PredicatePolarity::Positive,

‎tests/ui/suggestions/type-or-type-param-missing-transitive-trait-contraint.fixed

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ struct Ctx<A> {
77
a_map: HashMap<String, B<A>>,
88
}
99

10-
#[derive(Clone)]
10+
#[derive(Clone, PartialEq, Eq)]
1111
struct B<A> {
1212
a: A,
1313
}
@@ -17,9 +17,18 @@ fn foo<Z: std::clone::Clone>(ctx: &mut Ctx<Z>) {
1717
}
1818

1919
#[derive(Clone)]
20+
#[derive(PartialEq)]
2021
struct S;
2122
fn bar(ctx: &mut Ctx<S>) {
2223
let a_map = ctx.a_map.clone(); //~ ERROR E0599
2324
}
2425

26+
fn qux<Z>(ctx: &mut Ctx<Z>) where Z: PartialEq {
27+
ctx.a_map["a"].eq(&ctx.a_map["a"]); //~ ERROR E0599
28+
}
29+
30+
fn qut(ctx: &mut Ctx<S>) {
31+
ctx.a_map["a"].eq(&ctx.a_map["a"]); //~ ERROR E0599
32+
}
33+
2534
fn main() {}

‎tests/ui/suggestions/type-or-type-param-missing-transitive-trait-contraint.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ struct Ctx<A> {
77
a_map: HashMap<String, B<A>>,
88
}
99

10-
#[derive(Clone)]
10+
#[derive(Clone,PartialEq,Eq)]
1111
struct B<A> {
1212
a: A,
1313
}
@@ -21,4 +21,12 @@ fn bar(ctx: &mut Ctx<S>) {
2121
let a_map = ctx.a_map.clone(); //~ ERROR E0599
2222
}
2323

24+
fn qux<Z>(ctx: &mut Ctx<Z>) {
25+
ctx.a_map["a"].eq(&ctx.a_map["a"]); //~ ERROR E0599
26+
}
27+
28+
fn qut(ctx: &mut Ctx<S>) {
29+
ctx.a_map["a"].eq(&ctx.a_map["a"]); //~ ERROR E0599
30+
}
31+
2432
fn main() {}

‎tests/ui/suggestions/type-or-type-param-missing-transitive-trait-contraint.stderr

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,58 @@ LL + #[derive(Clone)]
3333
LL | struct S;
3434
|
3535

36-
error: aborting due to 2 previous errors
36+
error[E0599]: the method `eq` exists for struct `B<Z>`, but its trait bounds were not satisfied
37+
--> $DIR/type-or-type-param-missing-transitive-trait-contraint.rs:25:20
38+
|
39+
LL | struct B<A> {
40+
| ----------- method `eq` not found for this struct because it doesn't satisfy `B<Z>: Iterator` or `B<Z>: PartialEq`
41+
...
42+
LL | ctx.a_map["a"].eq(&ctx.a_map["a"]);
43+
| ^^ method cannot be called on `B<Z>` due to unsatisfied trait bounds
44+
|
45+
note: trait bound `Z: PartialEq` was not satisfied
46+
--> $DIR/type-or-type-param-missing-transitive-trait-contraint.rs:10:17
47+
|
48+
LL | #[derive(Clone, PartialEq, Eq)]
49+
| ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
50+
= note: the following trait bounds were not satisfied:
51+
`B<Z>: Iterator`
52+
which is required by `&mut B<Z>: Iterator`
53+
note: the trait `Iterator` must be implemented
54+
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
55+
help: consider restricting the type parameter to satisfy the trait bound
56+
|
57+
LL | fn qux<Z>(ctx: &mut Ctx<Z>) where Z: PartialEq {
58+
| ++++++++++++++++++
59+
60+
error[E0599]: the method `eq` exists for struct `B<S>`, but its trait bounds were not satisfied
61+
--> $DIR/type-or-type-param-missing-transitive-trait-contraint.rs:29:20
62+
|
63+
LL | struct B<A> {
64+
| ----------- method `eq` not found for this struct because it doesn't satisfy `B<S>: Iterator` or `B<S>: PartialEq`
65+
...
66+
LL | struct S;
67+
| -------- doesn't satisfy `S: PartialEq`
68+
...
69+
LL | ctx.a_map["a"].eq(&ctx.a_map["a"]);
70+
| ^^ method cannot be called on `B<S>` due to unsatisfied trait bounds
71+
|
72+
note: trait bound `S: PartialEq` was not satisfied
73+
--> $DIR/type-or-type-param-missing-transitive-trait-contraint.rs:10:17
74+
|
75+
LL | #[derive(Clone, PartialEq, Eq)]
76+
| ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
77+
= note: the following trait bounds were not satisfied:
78+
`B<S>: Iterator`
79+
which is required by `&mut B<S>: Iterator`
80+
note: the trait `Iterator` must be implemented
81+
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
82+
help: consider annotating `S` with `#[derive(PartialEq)]`
83+
|
84+
LL + #[derive(PartialEq)]
85+
LL | struct S;
86+
|
87+
88+
error: aborting due to 4 previous errors
3789

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

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /