Skip to content

Commit 25d065b

Browse files
committed
Fix suggestions span for when expr is from macro expansions
1 parent 08fd6f7 commit 25d065b

7 files changed

+314
-10
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+21-10
Original file line numberDiff line numberDiff line change
@@ -982,14 +982,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
982982
};
983983
let ty = self.normalize(expr.span, ty);
984984
if self.can_coerce(found, ty) {
985-
err.multipart_suggestion(
986-
"you might have meant to return this value",
987-
vec![
988-
(expr.span.shrink_to_lo(), "return ".to_string()),
989-
(expr.span.shrink_to_hi(), ";".to_string()),
990-
],
991-
Applicability::MaybeIncorrect,
992-
);
985+
if let Some(node) = self.tcx.hir().find(fn_id)
986+
&& let Some(owner_node) = node.as_owner()
987+
&& let Some(span) = expr.span.find_ancestor_inside(owner_node.span())
988+
{
989+
err.multipart_suggestion(
990+
"you might have meant to return this value",
991+
vec![
992+
(span.shrink_to_lo(), "return ".to_string()),
993+
(span.shrink_to_hi(), ";".to_string()),
994+
],
995+
Applicability::MaybeIncorrect,
996+
);
997+
}
993998
}
994999
}
9951000
}
@@ -1177,10 +1182,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11771182
),
11781183
))
11791184
{
1185+
let mut span = expr.span;
1186+
while expr.span.eq_ctxt(span) && let Some(parent_callsite) = span.parent_callsite()
1187+
{
1188+
span = parent_callsite;
1189+
}
1190+
11801191
let sugg = if expr.precedence().order() >= PREC_POSTFIX {
1181-
vec![(expr.span.shrink_to_hi(), ".into()".to_owned())]
1192+
vec![(span.shrink_to_hi(), ".into()".to_owned())]
11821193
} else {
1183-
vec![(expr.span.shrink_to_lo(), "(".to_owned()), (expr.span.shrink_to_hi(), ").into()".to_owned())]
1194+
vec![(span.shrink_to_lo(), "(".to_owned()), (span.shrink_to_hi(), ").into()".to_owned())]
11841195
};
11851196
diag.multipart_suggestion(
11861197
format!("call `Into::into` on this expression to convert `{expr_ty}` into `{expected_ty}`"),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// run-rustfix
2+
#![allow(dead_code)]
3+
4+
pub fn foo(x: &str) -> Result<(), Box<dyn std::error::Error>> {
5+
Err(format!("error: {x}").into())
6+
//~^ ERROR mismatched types
7+
}
8+
9+
macro_rules! outer {
10+
($x: expr) => {
11+
inner!($x)
12+
}
13+
}
14+
15+
macro_rules! inner {
16+
($x: expr) => {
17+
format!("error: {}", $x).into()
18+
//~^ ERROR mismatched types
19+
}
20+
}
21+
22+
fn bar(x: &str) -> Result<(), Box<dyn std::error::Error>> {
23+
Err(outer!(x))
24+
}
25+
26+
macro_rules! entire_fn_outer {
27+
() => {
28+
entire_fn!();
29+
}
30+
}
31+
32+
macro_rules! entire_fn {
33+
() => {
34+
pub fn baz(x: &str) -> Result<(), Box<dyn std::error::Error>> {
35+
Err(format!("error: {x}").into())
36+
//~^ ERROR mismatched types
37+
}
38+
}
39+
}
40+
41+
entire_fn_outer!();
42+
43+
macro_rules! nontrivial {
44+
($x: expr) => {
45+
Err(format!("error: {}", $x).into())
46+
//~^ ERROR mismatched types
47+
}
48+
}
49+
50+
pub fn qux(x: &str) -> Result<(), Box<dyn std::error::Error>> {
51+
nontrivial!(x)
52+
}
53+
54+
55+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// run-rustfix
2+
#![allow(dead_code)]
3+
4+
pub fn foo(x: &str) -> Result<(), Box<dyn std::error::Error>> {
5+
Err(format!("error: {x}"))
6+
//~^ ERROR mismatched types
7+
}
8+
9+
macro_rules! outer {
10+
($x: expr) => {
11+
inner!($x)
12+
}
13+
}
14+
15+
macro_rules! inner {
16+
($x: expr) => {
17+
format!("error: {}", $x)
18+
//~^ ERROR mismatched types
19+
}
20+
}
21+
22+
fn bar(x: &str) -> Result<(), Box<dyn std::error::Error>> {
23+
Err(outer!(x))
24+
}
25+
26+
macro_rules! entire_fn_outer {
27+
() => {
28+
entire_fn!();
29+
}
30+
}
31+
32+
macro_rules! entire_fn {
33+
() => {
34+
pub fn baz(x: &str) -> Result<(), Box<dyn std::error::Error>> {
35+
Err(format!("error: {x}"))
36+
//~^ ERROR mismatched types
37+
}
38+
}
39+
}
40+
41+
entire_fn_outer!();
42+
43+
macro_rules! nontrivial {
44+
($x: expr) => {
45+
Err(format!("error: {}", $x))
46+
//~^ ERROR mismatched types
47+
}
48+
}
49+
50+
pub fn qux(x: &str) -> Result<(), Box<dyn std::error::Error>> {
51+
nontrivial!(x)
52+
}
53+
54+
55+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-110017-format-into-help-deletes-macro.rs:5:10
3+
|
4+
LL | Err(format!("error: {x}"))
5+
| ^^^^^^^^^^^^^^^^^^^^^ expected `Box<dyn Error>`, found `String`
6+
|
7+
= note: expected struct `Box<dyn std::error::Error>`
8+
found struct `String`
9+
= note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
10+
help: call `Into::into` on this expression to convert `String` into `Box<dyn std::error::Error>`
11+
|
12+
LL | Err(format!("error: {x}").into())
13+
| +++++++
14+
15+
error[E0308]: mismatched types
16+
--> $DIR/issue-110017-format-into-help-deletes-macro.rs:23:10
17+
|
18+
LL | Err(outer!(x))
19+
| ^^^^^^^^^ expected `Box<dyn Error>`, found `String`
20+
|
21+
= note: expected struct `Box<dyn std::error::Error>`
22+
found struct `String`
23+
= note: this error originates in the macro `format` which comes from the expansion of the macro `outer` (in Nightly builds, run with -Z macro-backtrace for more info)
24+
help: call `Into::into` on this expression to convert `String` into `Box<dyn std::error::Error>`
25+
|
26+
LL | format!("error: {}", $x).into()
27+
| +++++++
28+
29+
error[E0308]: mismatched types
30+
--> $DIR/issue-110017-format-into-help-deletes-macro.rs:41:2
31+
|
32+
LL | entire_fn_outer!();
33+
| ^^^^^^^^^^^^^^^^^^ expected `Box<dyn Error>`, found `String`
34+
|
35+
= note: expected struct `Box<dyn std::error::Error>`
36+
found struct `String`
37+
= note: this error originates in the macro `format` which comes from the expansion of the macro `entire_fn_outer` (in Nightly builds, run with -Z macro-backtrace for more info)
38+
help: call `Into::into` on this expression to convert `String` into `Box<dyn std::error::Error>`
39+
|
40+
LL | Err(format!("error: {x}").into())
41+
| +++++++
42+
43+
error[E0308]: mismatched types
44+
--> $DIR/issue-110017-format-into-help-deletes-macro.rs:51:5
45+
|
46+
LL | nontrivial!(x)
47+
| ^^^^^^^^^^^^^^ expected `Box<dyn Error>`, found `String`
48+
|
49+
= note: expected struct `Box<dyn std::error::Error>`
50+
found struct `String`
51+
= note: this error originates in the macro `format` which comes from the expansion of the macro `nontrivial` (in Nightly builds, run with -Z macro-backtrace for more info)
52+
help: call `Into::into` on this expression to convert `String` into `Box<dyn std::error::Error>`
53+
|
54+
LL | Err(format!("error: {}", $x).into())
55+
| +++++++
56+
57+
error: aborting due to 4 previous errors
58+
59+
For more information about this error, try `rustc --explain E0308`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// run-rustfix
2+
#![allow(dead_code)]
3+
4+
// https://github.com/rust-lang/rust/issues/112007
5+
fn bug_report<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
6+
if true {
7+
writeln!(w, "`;?` here ->")?;
8+
} else {
9+
return writeln!(w, "but not here");
10+
//~^ ERROR mismatched types
11+
};
12+
Ok(())
13+
}
14+
15+
macro_rules! baz {
16+
($w: expr) => {
17+
bar!($w)
18+
}
19+
}
20+
21+
macro_rules! bar {
22+
($w: expr) => {
23+
writeln!($w, "but not here")
24+
//~^ ERROR mismatched types
25+
}
26+
}
27+
28+
fn foo<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
29+
if true {
30+
writeln!(w, "`;?` here ->")?;
31+
} else {
32+
return baz!(w);
33+
};
34+
Ok(())
35+
}
36+
37+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// run-rustfix
2+
#![allow(dead_code)]
3+
4+
// https://github.com/rust-lang/rust/issues/112007
5+
fn bug_report<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
6+
if true {
7+
writeln!(w, "`;?` here ->")?;
8+
} else {
9+
writeln!(w, "but not here")
10+
//~^ ERROR mismatched types
11+
}
12+
Ok(())
13+
}
14+
15+
macro_rules! baz {
16+
($w: expr) => {
17+
bar!($w)
18+
}
19+
}
20+
21+
macro_rules! bar {
22+
($w: expr) => {
23+
writeln!($w, "but not here")
24+
//~^ ERROR mismatched types
25+
}
26+
}
27+
28+
fn foo<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
29+
if true {
30+
writeln!(w, "`;?` here ->")?;
31+
} else {
32+
baz!(w)
33+
}
34+
Ok(())
35+
}
36+
37+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-112007-leaked-writeln-macro-internals.rs:9:9
3+
|
4+
LL | / if true {
5+
LL | | writeln!(w, "`;?` here ->")?;
6+
LL | | } else {
7+
LL | | writeln!(w, "but not here")
8+
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Result<(), Error>`
9+
LL | |
10+
LL | | }
11+
| |_____- expected this to be `()`
12+
|
13+
= note: expected unit type `()`
14+
found enum `Result<(), std::fmt::Error>`
15+
= note: this error originates in the macro `writeln` (in Nightly builds, run with -Z macro-backtrace for more info)
16+
help: consider using a semicolon here
17+
|
18+
LL | };
19+
| +
20+
help: you might have meant to return this value
21+
|
22+
LL | return writeln!(w, "but not here");
23+
| ++++++ +
24+
25+
error[E0308]: mismatched types
26+
--> $DIR/issue-112007-leaked-writeln-macro-internals.rs:32:9
27+
|
28+
LL | / if true {
29+
LL | | writeln!(w, "`;?` here ->")?;
30+
LL | | } else {
31+
LL | | baz!(w)
32+
| | ^^^^^^^ expected `()`, found `Result<(), Error>`
33+
LL | | }
34+
| |_____- expected this to be `()`
35+
|
36+
= note: expected unit type `()`
37+
found enum `Result<(), std::fmt::Error>`
38+
= note: this error originates in the macro `writeln` which comes from the expansion of the macro `baz` (in Nightly builds, run with -Z macro-backtrace for more info)
39+
help: consider using a semicolon here
40+
|
41+
LL | };
42+
| +
43+
help: you might have meant to return this value
44+
|
45+
LL | return baz!(w);
46+
| ++++++ +
47+
48+
error: aborting due to 2 previous errors
49+
50+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)