Skip to content

Commit 6272b60

Browse files
committed
Auto merge of #47690 - estebank:for-block-277, r=nikomatsakis
For E0277 on `for` loops, point at the "head" expression When E0277's span points at a `for` loop, the actual issue is in the element being iterated. Instead of pointing at the entire loop, point only at the first line (when possible) so that the span ends in the element for which E0277 was triggered.
2 parents 5c41fce + 106e5c5 commit 6272b60

File tree

9 files changed

+69
-54
lines changed

9 files changed

+69
-54
lines changed

src/librustc/hir/lowering.rs

+23-23
Original file line numberDiff line numberDiff line change
@@ -3033,7 +3033,7 @@ impl<'a> LoweringContext<'a> {
30333033

30343034
// `match <sub_expr> { ... }`
30353035
let arms = hir_vec![pat_arm, break_arm];
3036-
let match_expr = self.expr(e.span,
3036+
let match_expr = self.expr(sub_expr.span,
30373037
hir::ExprMatch(sub_expr,
30383038
arms,
30393039
hir::MatchSource::WhileLetDesugar),
@@ -3071,24 +3071,25 @@ impl<'a> LoweringContext<'a> {
30713071

30723072
// expand <head>
30733073
let head = self.lower_expr(head);
3074+
let head_sp = head.span;
30743075

30753076
let iter = self.str_to_ident("iter");
30763077

30773078
let next_ident = self.str_to_ident("__next");
3078-
let next_pat = self.pat_ident_binding_mode(e.span,
3079+
let next_pat = self.pat_ident_binding_mode(pat.span,
30793080
next_ident,
30803081
hir::BindingAnnotation::Mutable);
30813082

30823083
// `::std::option::Option::Some(val) => next = val`
30833084
let pat_arm = {
30843085
let val_ident = self.str_to_ident("val");
3085-
let val_pat = self.pat_ident(e.span, val_ident);
3086-
let val_expr = P(self.expr_ident(e.span, val_ident, val_pat.id));
3087-
let next_expr = P(self.expr_ident(e.span, next_ident, next_pat.id));
3088-
let assign = P(self.expr(e.span,
3086+
let val_pat = self.pat_ident(pat.span, val_ident);
3087+
let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat.id));
3088+
let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat.id));
3089+
let assign = P(self.expr(pat.span,
30893090
hir::ExprAssign(next_expr, val_expr),
30903091
ThinVec::new()));
3091-
let some_pat = self.pat_some(e.span, val_pat);
3092+
let some_pat = self.pat_some(pat.span, val_pat);
30923093
self.arm(hir_vec![some_pat], assign)
30933094
};
30943095

@@ -3101,46 +3102,45 @@ impl<'a> LoweringContext<'a> {
31013102
};
31023103

31033104
// `mut iter`
3104-
let iter_pat = self.pat_ident_binding_mode(e.span,
3105+
let iter_pat = self.pat_ident_binding_mode(head_sp,
31053106
iter,
31063107
hir::BindingAnnotation::Mutable);
31073108

31083109
// `match ::std::iter::Iterator::next(&mut iter) { ... }`
31093110
let match_expr = {
3110-
let iter = P(self.expr_ident(e.span, iter, iter_pat.id));
3111-
let ref_mut_iter = self.expr_mut_addr_of(e.span, iter);
3111+
let iter = P(self.expr_ident(head_sp, iter, iter_pat.id));
3112+
let ref_mut_iter = self.expr_mut_addr_of(head_sp, iter);
31123113
let next_path = &["iter", "Iterator", "next"];
3113-
let next_path = P(self.expr_std_path(e.span, next_path, ThinVec::new()));
3114-
let next_expr = P(self.expr_call(e.span, next_path,
3114+
let next_path = P(self.expr_std_path(head_sp, next_path, ThinVec::new()));
3115+
let next_expr = P(self.expr_call(head_sp, next_path,
31153116
hir_vec![ref_mut_iter]));
31163117
let arms = hir_vec![pat_arm, break_arm];
31173118

3118-
P(self.expr(e.span,
3119+
P(self.expr(head_sp,
31193120
hir::ExprMatch(next_expr, arms,
31203121
hir::MatchSource::ForLoopDesugar),
31213122
ThinVec::new()))
31223123
};
3123-
let match_stmt = respan(e.span, hir::StmtExpr(match_expr, self.next_id().node_id));
3124+
let match_stmt = respan(head_sp, hir::StmtExpr(match_expr, self.next_id().node_id));
31243125

3125-
let next_expr = P(self.expr_ident(e.span, next_ident, next_pat.id));
3126+
let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat.id));
31263127

31273128
// `let mut __next`
3128-
let next_let = self.stmt_let_pat(e.span,
3129+
let next_let = self.stmt_let_pat(head_sp,
31293130
None,
31303131
next_pat,
31313132
hir::LocalSource::ForLoopDesugar);
31323133

31333134
// `let <pat> = __next`
31343135
let pat = self.lower_pat(pat);
3135-
let pat_let = self.stmt_let_pat(e.span,
3136+
let pat_let = self.stmt_let_pat(head_sp,
31363137
Some(next_expr),
31373138
pat,
31383139
hir::LocalSource::ForLoopDesugar);
31393140

3140-
let body_block = self.with_loop_scope(e.id,
3141-
|this| this.lower_block(body, false));
3141+
let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
31423142
let body_expr = P(self.expr_block(body_block, ThinVec::new()));
3143-
let body_stmt = respan(e.span, hir::StmtExpr(body_expr, self.next_id().node_id));
3143+
let body_stmt = respan(body.span, hir::StmtExpr(body_expr, self.next_id().node_id));
31443144

31453145
let loop_block = P(self.block_all(e.span,
31463146
hir_vec![next_let,
@@ -3167,12 +3167,12 @@ impl<'a> LoweringContext<'a> {
31673167
// `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
31683168
let into_iter_expr = {
31693169
let into_iter_path = &["iter", "IntoIterator", "into_iter"];
3170-
let into_iter = P(self.expr_std_path(e.span, into_iter_path,
3170+
let into_iter = P(self.expr_std_path(head_sp, into_iter_path,
31713171
ThinVec::new()));
3172-
P(self.expr_call(e.span, into_iter, hir_vec![head]))
3172+
P(self.expr_call(head_sp, into_iter, hir_vec![head]))
31733173
};
31743174

3175-
let match_expr = P(self.expr_match(e.span,
3175+
let match_expr = P(self.expr_match(head_sp,
31763176
into_iter_expr,
31773177
hir_vec![iter_arm],
31783178
hir::MatchSource::ForLoopDesugar));

src/librustc_errors/emitter.rs

+1
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,7 @@ impl EmitterWriter {
767767
}
768768
// Check to make sure we're not in any <*macros>
769769
if !cm.span_to_filename(def_site).is_macros() &&
770+
!trace.macro_decl_name.starts_with("desugaring of ") &&
770771
!trace.macro_decl_name.starts_with("#[") ||
771772
always_backtrace {
772773
new_labels.push((trace.call_site,

src/test/compile-fail/issue-20605.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
fn changer<'a>(mut things: Box<Iterator<Item=&'a mut u8>>) {
1212
for item in *things { *item = 0 }
13-
//~^ ERROR `std::iter::Iterator<Item=&mut u8>: std::marker::Sized` is not satisfied
13+
//~^ ERROR the trait bound `std::iter::Iterator<Item=&mut u8>: std::marker::Sized` is not satisfied
1414
}
1515

1616
fn main() {}

src/test/ui/const-fn-error.stderr

+6-12
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,16 @@ error[E0016]: blocks in constant functions are limited to items and tail express
1313
| ^
1414

1515
error[E0015]: calls in constant functions are limited to constant functions, struct and enum constructors
16-
--> $DIR/const-fn-error.rs:17:5
16+
--> $DIR/const-fn-error.rs:17:14
1717
|
18-
17 | / for i in 0..x { //~ ERROR calls in constant functions
19-
18 | | //~| ERROR constant function contains unimplemented
20-
19 | | sum += i;
21-
20 | | }
22-
| |_____^
18+
17 | for i in 0..x { //~ ERROR calls in constant functions
19+
| ^^^^
2320

2421
error[E0019]: constant function contains unimplemented expression type
25-
--> $DIR/const-fn-error.rs:17:5
22+
--> $DIR/const-fn-error.rs:17:14
2623
|
27-
17 | / for i in 0..x { //~ ERROR calls in constant functions
28-
18 | | //~| ERROR constant function contains unimplemented
29-
19 | | sum += i;
30-
20 | | }
31-
| |_____^
24+
17 | for i in 0..x { //~ ERROR calls in constant functions
25+
| ^^^^
3226

3327
error[E0080]: constant evaluation error
3428
--> $DIR/const-fn-error.rs:21:5

src/test/ui/issue-33941.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _,
88
found type `&_`
99

1010
error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as std::iter::Iterator>::Item == &_`
11-
--> $DIR/issue-33941.rs:14:5
11+
--> $DIR/issue-33941.rs:14:14
1212
|
1313
14 | for _ in HashMap::new().iter().cloned() {} //~ ERROR type mismatch
14-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference
1515
|
1616
= note: expected type `(&_, &_)`
1717
found type `&_`
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// E0277 should point exclusively at line 14, not the entire for loop span
12+
13+
fn main() {
14+
for c in "asdf" {
15+
//~^ ERROR the trait bound `&str: std::iter::Iterator` is not satisfied
16+
//~| NOTE `&str` is not an iterator
17+
//~| HELP the trait `std::iter::Iterator` is not implemented for `&str`
18+
//~| NOTE required by `std::iter::IntoIterator::into_iter`
19+
println!("");
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0277]: the trait bound `&str: std::iter::Iterator` is not satisfied
2+
--> $DIR/for-c-in-str.rs:14:14
3+
|
4+
14 | for c in "asdf" {
5+
| ^^^^^^ `&str` is not an iterator; maybe try calling `.iter()` or a similar method
6+
|
7+
= help: the trait `std::iter::Iterator` is not implemented for `&str`
8+
= note: required by `std::iter::IntoIterator::into_iter`
9+
10+
error: aborting due to previous error
11+

src/test/ui/suggestions/try-on-option.stderr

+1-4
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@ error[E0277]: the `?` operator can only be used in a function that returns `Resu
1010
--> $DIR/try-on-option.rs:23:5
1111
|
1212
23 | x?; //~ the `?` operator
13-
| --
14-
| |
15-
| cannot use the `?` operator in a function that returns `u32`
16-
| in this macro invocation
13+
| ^^ cannot use the `?` operator in a function that returns `u32`
1714
|
1815
= help: the trait `std::ops::Try` is not implemented for `u32`
1916
= note: required by `std::ops::Try::from_error`

src/test/ui/suggestions/try-operator-on-main.stderr

+3-12
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@ error[E0277]: the `?` operator can only be used in a function that returns `Resu
22
--> $DIR/try-operator-on-main.rs:19:5
33
|
44
19 | std::fs::File::open("foo")?; //~ ERROR the `?` operator can only
5-
| ---------------------------
6-
| |
7-
| cannot use the `?` operator in a function that returns `()`
8-
| in this macro invocation
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
96
|
107
= help: the trait `std::ops::Try` is not implemented for `()`
118
= note: required by `std::ops::Try::from_error`
@@ -14,10 +11,7 @@ error[E0277]: the `?` operator can only be applied to values that implement `std
1411
--> $DIR/try-operator-on-main.rs:22:5
1512
|
1613
22 | ()?; //~ ERROR the `?` operator can only
17-
| ---
18-
| |
19-
| the `?` operator cannot be applied to type `()`
20-
| in this macro invocation
14+
| ^^^ the `?` operator cannot be applied to type `()`
2115
|
2216
= help: the trait `std::ops::Try` is not implemented for `()`
2317
= note: required by `std::ops::Try::into_result`
@@ -38,10 +32,7 @@ error[E0277]: the `?` operator can only be applied to values that implement `std
3832
--> $DIR/try-operator-on-main.rs:32:5
3933
|
4034
32 | ()?; //~ ERROR the `?` operator can only
41-
| ---
42-
| |
43-
| the `?` operator cannot be applied to type `()`
44-
| in this macro invocation
35+
| ^^^ the `?` operator cannot be applied to type `()`
4536
|
4637
= help: the trait `std::ops::Try` is not implemented for `()`
4738
= note: required by `std::ops::Try::into_result`

0 commit comments

Comments
 (0)