Skip to content

Commit 3f1c637

Browse files
authored
Rollup merge of rust-lang#78111 - SNCPlay42:not-always-self, r=lcnr
Trait predicate ambiguities are not always in `Self` When reporting ambiguities in trait predicates, the compiler incorrectly assumed the ambiguity was always in the type the trait should be implemented on, and never the generic parameters of the trait. This caused silly suggestions for predicates like `<KnownType as Trait<_>>`, such as giving explicit types to completely unrelated variables that happened to be of type `KnownType`. This also reverts rust-lang#73027, which worked around this issue in some cases and does not appear to be necessary any more. fixes rust-lang#77982 fixes rust-lang#78055
2 parents aebeec7 + c146e8c commit 3f1c637

File tree

8 files changed

+123
-62
lines changed

8 files changed

+123
-62
lines changed

compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs

+2-15
Original file line numberDiff line numberDiff line change
@@ -91,17 +91,6 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> {
9191
if let (None, Some(ty)) =
9292
(self.found_local_pattern, self.node_ty_contains_target(local.hir_id))
9393
{
94-
// FIXME: There's a trade-off here - we can either check that our target span
95-
// is contained in `local.span` or not. If we choose to check containment
96-
// we can avoid some spurious suggestions (see #72690), but we lose
97-
// the ability to report on things like:
98-
//
99-
// ```
100-
// let x = vec![];
101-
// ```
102-
//
103-
// because the target span will be in the macro expansion of `vec![]`.
104-
// At present we choose not to check containment.
10594
self.found_local_pattern = Some(&*local.pat);
10695
self.found_node_ty = Some(ty);
10796
}
@@ -113,10 +102,8 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> {
113102
if let (None, Some(ty)) =
114103
(self.found_arg_pattern, self.node_ty_contains_target(param.hir_id))
115104
{
116-
if self.target_span.contains(param.pat.span) {
117-
self.found_arg_pattern = Some(&*param.pat);
118-
self.found_node_ty = Some(ty);
119-
}
105+
self.found_arg_pattern = Some(&*param.pat);
106+
self.found_node_ty = Some(ty);
120107
}
121108
}
122109
intravisit::walk_body(self, body);

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

+15-15
Original file line numberDiff line numberDiff line change
@@ -1462,9 +1462,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
14621462
let bound_predicate = predicate.bound_atom();
14631463
let mut err = match bound_predicate.skip_binder() {
14641464
ty::PredicateAtom::Trait(data, _) => {
1465-
let self_ty = data.trait_ref.self_ty();
14661465
let trait_ref = bound_predicate.rebind(data.trait_ref);
1467-
debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind(), trait_ref);
1466+
debug!("trait_ref {:?}", trait_ref);
14681467

14691468
if predicate.references_error() {
14701469
return;
@@ -1479,6 +1478,17 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
14791478
// known, since we don't dispatch based on region
14801479
// relationships.
14811480

1481+
// Pick the first substitution that still contains inference variables as the one
1482+
// we're going to emit an error for. If there are none (see above), fall back to
1483+
// the substitution for `Self`.
1484+
let subst = {
1485+
let substs = data.trait_ref.substs;
1486+
substs
1487+
.iter()
1488+
.find(|s| s.has_infer_types_or_consts())
1489+
.unwrap_or_else(|| substs[0])
1490+
};
1491+
14821492
// This is kind of a hack: it frequently happens that some earlier
14831493
// error prevents types from being fully inferred, and then we get
14841494
// a bunch of uninteresting errors saying something like "<generic
@@ -1495,21 +1505,11 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
14951505
// check upstream for type errors and don't add the obligations to
14961506
// begin with in those cases.
14971507
if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) {
1498-
self.emit_inference_failure_err(
1499-
body_id,
1500-
span,
1501-
self_ty.into(),
1502-
ErrorCode::E0282,
1503-
)
1504-
.emit();
1508+
self.emit_inference_failure_err(body_id, span, subst, ErrorCode::E0282).emit();
15051509
return;
15061510
}
1507-
let mut err = self.emit_inference_failure_err(
1508-
body_id,
1509-
span,
1510-
self_ty.into(),
1511-
ErrorCode::E0283,
1512-
);
1511+
let mut err =
1512+
self.emit_inference_failure_err(body_id, span, subst, ErrorCode::E0283);
15131513
err.note(&format!("cannot satisfy `{}`", predicate));
15141514
if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code {
15151515
self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());

src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0282]: type annotations needed
2-
--> $DIR/expect-two-infer-vars-supply-ty-with-bound-region.rs:8:5
2+
--> $DIR/expect-two-infer-vars-supply-ty-with-bound-region.rs:8:27
33
|
44
LL | with_closure(|x: u32, y| {});
5-
| ^^^^^^^^^^^^ cannot infer type for type parameter `B` declared on the function `with_closure`
5+
| ^ consider giving this closure parameter a type
66

77
error: aborting due to previous error
88

src/test/ui/issues/issue-23046.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pub fn let_<'var, VAR, F: for<'v> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>>
1414
}
1515

1616
fn main() {
17-
let ex = |x| {
18-
let_(add(x,x), |y| { //~ ERROR type annotations needed
17+
let ex = |x| { //~ ERROR type annotations needed
18+
let_(add(x,x), |y| {
1919
let_(add(x, x), |x|x)})};
2020
}

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

+4-9
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
1-
error[E0282]: type annotations needed for the closure `fn(Expr<'_, _>) -> Expr<'_, _>`
2-
--> $DIR/issue-23046.rs:18:9
1+
error[E0282]: type annotations needed for `Expr<'_, VAR>`
2+
--> $DIR/issue-23046.rs:17:15
33
|
4-
LL | let_(add(x,x), |y| {
5-
| ^^^^ cannot infer type for type parameter `VAR` declared on the function `let_`
6-
|
7-
help: give this closure an explicit return type without `_` placeholders
8-
|
9-
LL | let_(add(x, x), |x|-> Expr<'_, _> { x })})};
10-
| ^^^^^^^^^^^^^^^^ ^
4+
LL | let ex = |x| {
5+
| ^ consider giving this closure parameter the explicit type `Expr<'_, VAR>`, where the type parameter `VAR` is specified
116

127
error: aborting due to previous error
138

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

+14-19
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0283]: type annotations needed
22
--> $DIR/issue-72690.rs:7:5
33
|
44
LL | String::from("x".as_ref());
5-
| ^^^^^^^^^^^^ cannot infer type for struct `String`
5+
| ^^^^^^^^^^^^ cannot infer type for reference `&_`
66
|
77
= note: cannot satisfy `String: From<&_>`
88
= note: required by `from`
@@ -13,19 +13,21 @@ error[E0282]: type annotations needed
1313
LL | |x| String::from("x".as_ref());
1414
| ^ consider giving this closure parameter a type
1515

16-
error[E0283]: type annotations needed
16+
error[E0283]: type annotations needed for `&T`
1717
--> $DIR/issue-72690.rs:15:17
1818
|
1919
LL | let _ = "x".as_ref();
20-
| ^^^^^^ cannot infer type for type `str`
20+
| - ^^^^^^ cannot infer type for type parameter `T` declared on the trait `AsRef`
21+
| |
22+
| consider giving this pattern the explicit type `&T`, where the type parameter `T` is specified
2123
|
2224
= note: cannot satisfy `str: AsRef<_>`
2325

2426
error[E0283]: type annotations needed
2527
--> $DIR/issue-72690.rs:19:5
2628
|
2729
LL | String::from("x".as_ref());
28-
| ^^^^^^^^^^^^ cannot infer type for struct `String`
30+
| ^^^^^^^^^^^^ cannot infer type for reference `&_`
2931
|
3032
= note: cannot satisfy `String: From<&_>`
3133
= note: required by `from`
@@ -34,7 +36,7 @@ error[E0283]: type annotations needed
3436
--> $DIR/issue-72690.rs:25:5
3537
|
3638
LL | String::from("x".as_ref());
37-
| ^^^^^^^^^^^^ cannot infer type for struct `String`
39+
| ^^^^^^^^^^^^ cannot infer type for reference `&_`
3840
|
3941
= note: cannot satisfy `String: From<&_>`
4042
= note: required by `from`
@@ -43,41 +45,34 @@ error[E0283]: type annotations needed
4345
--> $DIR/issue-72690.rs:33:5
4446
|
4547
LL | String::from("x".as_ref());
46-
| ^^^^^^^^^^^^ cannot infer type for struct `String`
48+
| ^^^^^^^^^^^^ cannot infer type for reference `&_`
4749
|
4850
= note: cannot satisfy `String: From<&_>`
4951
= note: required by `from`
5052

51-
error[E0283]: type annotations needed for `String`
53+
error[E0283]: type annotations needed
5254
--> $DIR/issue-72690.rs:41:5
5355
|
5456
LL | String::from("x".as_ref());
55-
| ^^^^^^^^^^^^ cannot infer type for struct `String`
56-
LL | let _ = String::from("x");
57-
| - consider giving this pattern a type
57+
| ^^^^^^^^^^^^ cannot infer type for reference `&_`
5858
|
5959
= note: cannot satisfy `String: From<&_>`
6060
= note: required by `from`
6161

62-
error[E0283]: type annotations needed for `String`
62+
error[E0283]: type annotations needed
6363
--> $DIR/issue-72690.rs:47:5
6464
|
65-
LL | let _ = String::from("x");
66-
| - consider giving this pattern a type
6765
LL | String::from("x".as_ref());
68-
| ^^^^^^^^^^^^ cannot infer type for struct `String`
66+
| ^^^^^^^^^^^^ cannot infer type for reference `&_`
6967
|
7068
= note: cannot satisfy `String: From<&_>`
7169
= note: required by `from`
7270

73-
error[E0283]: type annotations needed for `String`
71+
error[E0283]: type annotations needed
7472
--> $DIR/issue-72690.rs:55:5
7573
|
76-
LL | let _ = String::from("x");
77-
| - consider giving this pattern a type
78-
...
7974
LL | String::from("x".as_ref());
80-
| ^^^^^^^^^^^^ cannot infer type for struct `String`
75+
| ^^^^^^^^^^^^ cannot infer type for reference `&_`
8176
|
8277
= note: cannot satisfy `String: From<&_>`
8378
= note: required by `from`

src/test/ui/traits/issue-77982.rs

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use std::collections::HashMap;
2+
3+
fn what() {
4+
let descr = String::new();
5+
let mut opts = HashMap::<String, ()>::new();
6+
let opt = String::new();
7+
8+
opts.get(opt.as_ref()); //~ ERROR type annotations needed
9+
}
10+
11+
fn main() {
12+
let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect();
13+
//~^ ERROR type annotations needed
14+
}
15+
16+
trait Foo<'a, T: ?Sized> {
17+
fn foo(&self) -> Box<T> {
18+
todo!()
19+
}
20+
}
21+
22+
trait Bar<'a, T: ?Sized> {
23+
fn bar(&self) -> Box<T> {
24+
todo!()
25+
}
26+
}
27+
28+
impl Foo<'static, u32> for () {}
29+
impl<'a> Foo<'a, i16> for () {}
30+
31+
impl<'a> Bar<'static, u32> for &'a () {}
32+
impl<'a> Bar<'a, i16> for &'a () {}
33+
34+
fn foo() {
35+
let _ = ().foo(); //~ ERROR type annotations needed
36+
}
37+
38+
fn bar() {
39+
let _ = (&()).bar(); //~ ERROR type annotations needed
40+
}

src/test/ui/traits/issue-77982.stderr

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
error[E0283]: type annotations needed
2+
--> $DIR/issue-77982.rs:8:10
3+
|
4+
LL | opts.get(opt.as_ref());
5+
| ^^^ ------------ this method call resolves to `&T`
6+
| |
7+
| cannot infer type for type parameter `Q` declared on the associated function `get`
8+
|
9+
= note: cannot satisfy `String: Borrow<_>`
10+
11+
error[E0283]: type annotations needed
12+
--> $DIR/issue-77982.rs:12:44
13+
|
14+
LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect();
15+
| ^^^^^^^^^ ----------- this method call resolves to `T`
16+
| |
17+
| cannot infer type for type parameter `T` declared on the trait `From`
18+
|
19+
= note: cannot satisfy `u32: From<_>`
20+
= note: required by `from`
21+
22+
error[E0283]: type annotations needed for `Box<T>`
23+
--> $DIR/issue-77982.rs:35:16
24+
|
25+
LL | let _ = ().foo();
26+
| - ^^^ cannot infer type for type parameter `T` declared on the trait `Foo`
27+
| |
28+
| consider giving this pattern the explicit type `Box<T>`, where the type parameter `T` is specified
29+
|
30+
= note: cannot satisfy `(): Foo<'_, _>`
31+
32+
error[E0283]: type annotations needed for `Box<T>`
33+
--> $DIR/issue-77982.rs:39:19
34+
|
35+
LL | let _ = (&()).bar();
36+
| - ^^^ cannot infer type for type parameter `T` declared on the trait `Bar`
37+
| |
38+
| consider giving this pattern the explicit type `Box<T>`, where the type parameter `T` is specified
39+
|
40+
= note: cannot satisfy `&(): Bar<'_, _>`
41+
42+
error: aborting due to 4 previous errors
43+
44+
For more information about this error, try `rustc --explain E0283`.

0 commit comments

Comments
 (0)