Skip to content

Commit 02e3fb8

Browse files
committed
When possible point at argument causing item obligation failure
1 parent 9b9d2af commit 02e3fb8

File tree

66 files changed

+674
-513
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+674
-513
lines changed

src/librustc_typeck/check/mod.rs

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3253,6 +3253,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
32533253
formal_tys.clone()
32543254
};
32553255

3256+
let mut final_arg_types: Vec<(usize, Ty<'_>)> = vec![];
3257+
32563258
// Check the arguments.
32573259
// We do this in a pretty awful way: first we type-check any arguments
32583260
// that are not closures, then we type-check the closures. This is so
@@ -3265,7 +3267,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
32653267
// an "opportunistic" vtable resolution of any trait bounds on
32663268
// the call. This helps coercions.
32673269
if check_closures {
3268-
self.select_obligations_where_possible(false);
3270+
// We don't use `select_obligations_where_possible` to try to figure out if the
3271+
// obligation is comming from a single fn call argument, and if it is, we point
3272+
// at the expression corresponding to that argument, instead of the call.
3273+
if let Err(
3274+
mut errors,
3275+
) = self.fulfillment_cx.borrow_mut().select_where_possible(self) {
3276+
for error in &mut errors {
3277+
if let ty::Predicate::Trait(predicate) = error.obligation.predicate {
3278+
let mut referenced_in = vec![];
3279+
for (i, ty) in &final_arg_types {
3280+
let ty = self.resolve_vars_if_possible(ty);
3281+
info!("final ty {} {:?}", i, ty);
3282+
for ty in ty.walk() {
3283+
info!("walk {:?}", ty);
3284+
if ty == predicate.skip_binder().self_ty() {
3285+
referenced_in.push(*i);
3286+
}
3287+
}
3288+
}
3289+
if referenced_in.len() == 1 {
3290+
error.obligation.cause.span = args[referenced_in[0]].span;
3291+
}
3292+
}
3293+
}
3294+
self.report_fulfillment_errors(&errors, self.inh.body_id, false);
3295+
}
32693296
}
32703297

32713298
// For C-variadic functions, we don't have a declared type for all of
@@ -3311,6 +3338,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
33113338
// We're processing function arguments so we definitely want to use
33123339
// two-phase borrows.
33133340
self.demand_coerce(&arg, checked_ty, coerce_ty, AllowTwoPhase::Yes);
3341+
final_arg_types.push((i, coerce_ty));
33143342

33153343
// 3. Relate the expected type and the formal one,
33163344
// if the expected type was used for the coercion.
@@ -3514,8 +3542,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
35143542

35153543
// Check bounds on type arguments used in the path.
35163544
let bounds = self.instantiate_bounds(path_span, did, substs);
3517-
let cause = traits::ObligationCause::new(path_span, self.body_id,
3518-
traits::ItemObligation(did));
3545+
let cause = traits::ObligationCause::new(
3546+
path_span,
3547+
self.body_id,
3548+
traits::ItemObligation(did),
3549+
);
35193550
self.add_obligations_for_parameters(cause, &bounds);
35203551

35213552
Some((variant, ty))
@@ -4639,7 +4670,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
46394670
let bounds = self.instantiate_bounds(span, def_id, &substs);
46404671
self.add_obligations_for_parameters(
46414672
traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def_id)),
4642-
&bounds);
4673+
&bounds,
4674+
);
46434675

46444676
// Substitute the values for the type parameters into the type of
46454677
// the referenced item.

src/librustc_typeck/check/wfcheck.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ fn check_where_clauses<'tcx, 'fcx>(
506506
});
507507

508508
// Now we build the substituted predicates.
509-
let default_obligations = predicates.predicates.iter().flat_map(|&(pred, _)| {
509+
let default_obligations = predicates.predicates.iter().flat_map(|&(pred, sp)| {
510510
#[derive(Default)]
511511
struct CountParams { params: FxHashSet<u32> }
512512
impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams {
@@ -539,9 +539,9 @@ fn check_where_clauses<'tcx, 'fcx>(
539539
// Avoid duplication of predicates that contain no parameters, for example.
540540
None
541541
} else {
542-
Some(substituted_pred)
542+
Some((substituted_pred, sp))
543543
}
544-
}).map(|pred| {
544+
}).map(|(pred, sp)| {
545545
// Convert each of those into an obligation. So if you have
546546
// something like `struct Foo<T: Copy = String>`, we would
547547
// take that predicate `T: Copy`, substitute to `String: Copy`
@@ -551,8 +551,8 @@ fn check_where_clauses<'tcx, 'fcx>(
551551
// Note the subtle difference from how we handle `predicates`
552552
// below: there, we are not trying to prove those predicates
553553
// to be *true* but merely *well-formed*.
554-
let pred = fcx.normalize_associated_types_in(span, &pred);
555-
let cause = traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def_id));
554+
let pred = fcx.normalize_associated_types_in(sp, &pred);
555+
let cause = traits::ObligationCause::new(sp, fcx.body_id, traits::ItemObligation(def_id));
556556
traits::Obligation::new(cause, fcx.param_env, pred)
557557
});
558558

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error[E0277]: the trait bound `<G as GetToInt>::R: ToInt` is not satisfied
2-
--> $DIR/associated-types-bound-failure.rs:17:5
2+
--> $DIR/associated-types-bound-failure.rs:17:19
33
|
44
LL | fn to_int(&self) -> isize;
55
| -------------------------- required by `ToInt::to_int`
66
...
77
LL | ToInt::to_int(&g.get())
8-
| ^^^^^^^^^^^^^ the trait `ToInt` is not implemented for `<G as GetToInt>::R`
8+
| ^^^^^^^^ the trait `ToInt` is not implemented for `<G as GetToInt>::R`
99
|
1010
= help: consider adding a `where <G as GetToInt>::R: ToInt` bound
1111

src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ async fn foo2() -> Result<(), ()> {
1414
}
1515
async fn foo3() -> Result<(), ()> {
1616
let _ = await bar()?; //~ ERROR incorrect use of `await`
17-
//~^ ERROR the `?` operator can only be applied to values that implement `std::ops::Try`
17+
//~^ ERROR the trait bound `impl std::future::Future: std::ops::Try` is not satisfied
18+
//~| ERROR the trait bound `impl std::future::Future: std::ops::Try` is not satisfied
1819
Ok(())
1920
}
2021
async fn foo21() -> Result<(), ()> {

src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -17,117 +17,117 @@ LL | let _ = await bar()?;
1717
| ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await`
1818

1919
error: incorrect use of `await`
20-
--> $DIR/incorrect-syntax-suggestions.rs:21:13
20+
--> $DIR/incorrect-syntax-suggestions.rs:22:13
2121
|
2222
LL | let _ = await { bar() };
2323
| ^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ bar() }.await`
2424

2525
error: incorrect use of `await`
26-
--> $DIR/incorrect-syntax-suggestions.rs:25:13
26+
--> $DIR/incorrect-syntax-suggestions.rs:26:13
2727
|
2828
LL | let _ = await(bar());
2929
| ^^^^^^^^^^^^ help: `await` is a postfix operation: `(bar()).await`
3030

3131
error: incorrect use of `await`
32-
--> $DIR/incorrect-syntax-suggestions.rs:29:13
32+
--> $DIR/incorrect-syntax-suggestions.rs:30:13
3333
|
3434
LL | let _ = await { bar() }?;
3535
| ^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ bar() }.await`
3636

3737
error: incorrect use of `await`
38-
--> $DIR/incorrect-syntax-suggestions.rs:33:14
38+
--> $DIR/incorrect-syntax-suggestions.rs:34:14
3939
|
4040
LL | let _ = (await bar())?;
4141
| ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
4242

4343
error: incorrect use of `await`
44-
--> $DIR/incorrect-syntax-suggestions.rs:37:24
44+
--> $DIR/incorrect-syntax-suggestions.rs:38:24
4545
|
4646
LL | let _ = bar().await();
4747
| ^^ help: `await` is not a method call, remove the parentheses
4848

4949
error: incorrect use of `await`
50-
--> $DIR/incorrect-syntax-suggestions.rs:41:24
50+
--> $DIR/incorrect-syntax-suggestions.rs:42:24
5151
|
5252
LL | let _ = bar().await()?;
5353
| ^^ help: `await` is not a method call, remove the parentheses
5454

5555
error: incorrect use of `await`
56-
--> $DIR/incorrect-syntax-suggestions.rs:53:13
56+
--> $DIR/incorrect-syntax-suggestions.rs:54:13
5757
|
5858
LL | let _ = await bar();
5959
| ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
6060

6161
error: incorrect use of `await`
62-
--> $DIR/incorrect-syntax-suggestions.rs:58:13
62+
--> $DIR/incorrect-syntax-suggestions.rs:59:13
6363
|
6464
LL | let _ = await? bar();
6565
| ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await?`
6666

6767
error: incorrect use of `await`
68-
--> $DIR/incorrect-syntax-suggestions.rs:63:13
68+
--> $DIR/incorrect-syntax-suggestions.rs:64:13
6969
|
7070
LL | let _ = await bar()?;
7171
| ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await`
7272

7373
error: incorrect use of `await`
74-
--> $DIR/incorrect-syntax-suggestions.rs:68:14
74+
--> $DIR/incorrect-syntax-suggestions.rs:69:14
7575
|
7676
LL | let _ = (await bar())?;
7777
| ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
7878

7979
error: incorrect use of `await`
80-
--> $DIR/incorrect-syntax-suggestions.rs:73:24
80+
--> $DIR/incorrect-syntax-suggestions.rs:74:24
8181
|
8282
LL | let _ = bar().await();
8383
| ^^ help: `await` is not a method call, remove the parentheses
8484

8585
error: incorrect use of `await`
86-
--> $DIR/incorrect-syntax-suggestions.rs:78:24
86+
--> $DIR/incorrect-syntax-suggestions.rs:79:24
8787
|
8888
LL | let _ = bar().await()?;
8989
| ^^ help: `await` is not a method call, remove the parentheses
9090

9191
error: incorrect use of `await`
92-
--> $DIR/incorrect-syntax-suggestions.rs:106:13
92+
--> $DIR/incorrect-syntax-suggestions.rs:107:13
9393
|
9494
LL | let _ = await!(bar());
9595
| ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
9696

9797
error: incorrect use of `await`
98-
--> $DIR/incorrect-syntax-suggestions.rs:110:13
98+
--> $DIR/incorrect-syntax-suggestions.rs:111:13
9999
|
100100
LL | let _ = await!(bar())?;
101101
| ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
102102

103103
error: incorrect use of `await`
104-
--> $DIR/incorrect-syntax-suggestions.rs:115:17
104+
--> $DIR/incorrect-syntax-suggestions.rs:116:17
105105
|
106106
LL | let _ = await!(bar())?;
107107
| ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
108108

109109
error: incorrect use of `await`
110-
--> $DIR/incorrect-syntax-suggestions.rs:123:17
110+
--> $DIR/incorrect-syntax-suggestions.rs:124:17
111111
|
112112
LL | let _ = await!(bar())?;
113113
| ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
114114

115115
error: expected expression, found `=>`
116-
--> $DIR/incorrect-syntax-suggestions.rs:131:25
116+
--> $DIR/incorrect-syntax-suggestions.rs:132:25
117117
|
118118
LL | match await { await => () }
119119
| ----- ^^ expected expression
120120
| |
121121
| while parsing this incorrect await expression
122122

123123
error: incorrect use of `await`
124-
--> $DIR/incorrect-syntax-suggestions.rs:131:11
124+
--> $DIR/incorrect-syntax-suggestions.rs:132:11
125125
|
126126
LL | match await { await => () }
127127
| ^^^^^^^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ await => () }.await`
128128

129129
error: expected one of `.`, `?`, `{`, or an operator, found `}`
130-
--> $DIR/incorrect-syntax-suggestions.rs:134:1
130+
--> $DIR/incorrect-syntax-suggestions.rs:135:1
131131
|
132132
LL | match await { await => () }
133133
| ----- - expected one of `.`, `?`, `{`, or an operator here
@@ -138,110 +138,115 @@ LL | }
138138
| ^ unexpected token
139139

140140
error[E0728]: `await` is only allowed inside `async` functions and blocks
141-
--> $DIR/incorrect-syntax-suggestions.rs:53:13
141+
--> $DIR/incorrect-syntax-suggestions.rs:54:13
142142
|
143143
LL | fn foo9() -> Result<(), ()> {
144144
| ---- this is not `async`
145145
LL | let _ = await bar();
146146
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
147147

148148
error[E0728]: `await` is only allowed inside `async` functions and blocks
149-
--> $DIR/incorrect-syntax-suggestions.rs:58:13
149+
--> $DIR/incorrect-syntax-suggestions.rs:59:13
150150
|
151151
LL | fn foo10() -> Result<(), ()> {
152152
| ----- this is not `async`
153153
LL | let _ = await? bar();
154154
| ^^^^^^^^^^^^ only allowed inside `async` functions and blocks
155155

156156
error[E0728]: `await` is only allowed inside `async` functions and blocks
157-
--> $DIR/incorrect-syntax-suggestions.rs:63:13
157+
--> $DIR/incorrect-syntax-suggestions.rs:64:13
158158
|
159159
LL | fn foo11() -> Result<(), ()> {
160160
| ----- this is not `async`
161161
LL | let _ = await bar()?;
162162
| ^^^^^^^^^^^^ only allowed inside `async` functions and blocks
163163

164164
error[E0728]: `await` is only allowed inside `async` functions and blocks
165-
--> $DIR/incorrect-syntax-suggestions.rs:68:14
165+
--> $DIR/incorrect-syntax-suggestions.rs:69:14
166166
|
167167
LL | fn foo12() -> Result<(), ()> {
168168
| ----- this is not `async`
169169
LL | let _ = (await bar())?;
170170
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
171171

172172
error[E0728]: `await` is only allowed inside `async` functions and blocks
173-
--> $DIR/incorrect-syntax-suggestions.rs:73:13
173+
--> $DIR/incorrect-syntax-suggestions.rs:74:13
174174
|
175175
LL | fn foo13() -> Result<(), ()> {
176176
| ----- this is not `async`
177177
LL | let _ = bar().await();
178178
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
179179

180180
error[E0728]: `await` is only allowed inside `async` functions and blocks
181-
--> $DIR/incorrect-syntax-suggestions.rs:78:13
181+
--> $DIR/incorrect-syntax-suggestions.rs:79:13
182182
|
183183
LL | fn foo14() -> Result<(), ()> {
184184
| ----- this is not `async`
185185
LL | let _ = bar().await()?;
186186
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
187187

188188
error[E0728]: `await` is only allowed inside `async` functions and blocks
189-
--> $DIR/incorrect-syntax-suggestions.rs:83:13
189+
--> $DIR/incorrect-syntax-suggestions.rs:84:13
190190
|
191191
LL | fn foo15() -> Result<(), ()> {
192192
| ----- this is not `async`
193193
LL | let _ = bar().await;
194194
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
195195

196196
error[E0728]: `await` is only allowed inside `async` functions and blocks
197-
--> $DIR/incorrect-syntax-suggestions.rs:87:13
197+
--> $DIR/incorrect-syntax-suggestions.rs:88:13
198198
|
199199
LL | fn foo16() -> Result<(), ()> {
200200
| ----- this is not `async`
201201
LL | let _ = bar().await?;
202202
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
203203

204204
error[E0728]: `await` is only allowed inside `async` functions and blocks
205-
--> $DIR/incorrect-syntax-suggestions.rs:92:17
205+
--> $DIR/incorrect-syntax-suggestions.rs:93:17
206206
|
207207
LL | fn foo() -> Result<(), ()> {
208208
| --- this is not `async`
209209
LL | let _ = bar().await?;
210210
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
211211

212212
error[E0728]: `await` is only allowed inside `async` functions and blocks
213-
--> $DIR/incorrect-syntax-suggestions.rs:99:17
213+
--> $DIR/incorrect-syntax-suggestions.rs:100:17
214214
|
215215
LL | let foo = || {
216216
| -- this is not `async`
217217
LL | let _ = bar().await?;
218218
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
219219

220220
error[E0728]: `await` is only allowed inside `async` functions and blocks
221-
--> $DIR/incorrect-syntax-suggestions.rs:115:17
221+
--> $DIR/incorrect-syntax-suggestions.rs:116:17
222222
|
223223
LL | fn foo() -> Result<(), ()> {
224224
| --- this is not `async`
225225
LL | let _ = await!(bar())?;
226226
| ^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
227227

228228
error[E0728]: `await` is only allowed inside `async` functions and blocks
229-
--> $DIR/incorrect-syntax-suggestions.rs:123:17
229+
--> $DIR/incorrect-syntax-suggestions.rs:124:17
230230
|
231231
LL | let foo = || {
232232
| -- this is not `async`
233233
LL | let _ = await!(bar())?;
234234
| ^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
235235

236-
error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try`
236+
error[E0277]: the trait bound `impl std::future::Future: std::ops::Try` is not satisfied
237237
--> $DIR/incorrect-syntax-suggestions.rs:16:19
238238
|
239239
LL | let _ = await bar()?;
240-
| ^^^^^^ the `?` operator cannot be applied to type `impl std::future::Future`
240+
| ^^^^^ the trait `std::ops::Try` is not implemented for `impl std::future::Future`
241241
|
242-
= help: the trait `std::ops::Try` is not implemented for `impl std::future::Future`
243242
= note: required by `std::ops::Try::into_result`
244243

245-
error: aborting due to 35 previous errors
244+
error[E0277]: the trait bound `impl std::future::Future: std::ops::Try` is not satisfied
245+
--> $DIR/incorrect-syntax-suggestions.rs:16:19
246+
|
247+
LL | let _ = await bar()?;
248+
| ^^^^^^ the trait `std::ops::Try` is not implemented for `impl std::future::Future`
249+
250+
error: aborting due to 36 previous errors
246251

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

0 commit comments

Comments
 (0)