Skip to content

Commit

Permalink
Fix suggestions span for when expr is from macro expansions
Browse files Browse the repository at this point in the history
  • Loading branch information
jieyouxu committed Jun 28, 2023
1 parent 08fd6f7 commit 25d065b
Show file tree
Hide file tree
Showing 7 changed files with 314 additions and 10 deletions.
31 changes: 21 additions & 10 deletions compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -982,14 +982,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
let ty = self.normalize(expr.span, ty);
if self.can_coerce(found, ty) {
err.multipart_suggestion(
"you might have meant to return this value",
vec![
(expr.span.shrink_to_lo(), "return ".to_string()),
(expr.span.shrink_to_hi(), ";".to_string()),
],
Applicability::MaybeIncorrect,
);
if let Some(node) = self.tcx.hir().find(fn_id)
&& let Some(owner_node) = node.as_owner()
&& let Some(span) = expr.span.find_ancestor_inside(owner_node.span())
{
err.multipart_suggestion(
"you might have meant to return this value",
vec![
(span.shrink_to_lo(), "return ".to_string()),
(span.shrink_to_hi(), ";".to_string()),
],
Applicability::MaybeIncorrect,
);
}
}
}
}
Expand Down Expand Up @@ -1177,10 +1182,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
),
))
{
let mut span = expr.span;
while expr.span.eq_ctxt(span) && let Some(parent_callsite) = span.parent_callsite()
{
span = parent_callsite;
}

let sugg = if expr.precedence().order() >= PREC_POSTFIX {
vec![(expr.span.shrink_to_hi(), ".into()".to_owned())]
vec![(span.shrink_to_hi(), ".into()".to_owned())]
} else {
vec![(expr.span.shrink_to_lo(), "(".to_owned()), (expr.span.shrink_to_hi(), ").into()".to_owned())]
vec![(span.shrink_to_lo(), "(".to_owned()), (span.shrink_to_hi(), ").into()".to_owned())]
};
diag.multipart_suggestion(
format!("call `Into::into` on this expression to convert `{expr_ty}` into `{expected_ty}`"),
Expand Down
55 changes: 55 additions & 0 deletions tests/ui/typeck/issue-110017-format-into-help-deletes-macro.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// run-rustfix
#![allow(dead_code)]

pub fn foo(x: &str) -> Result<(), Box<dyn std::error::Error>> {
Err(format!("error: {x}").into())
//~^ ERROR mismatched types
}

macro_rules! outer {
($x: expr) => {
inner!($x)
}
}

macro_rules! inner {
($x: expr) => {
format!("error: {}", $x).into()
//~^ ERROR mismatched types
}
}

fn bar(x: &str) -> Result<(), Box<dyn std::error::Error>> {
Err(outer!(x))
}

macro_rules! entire_fn_outer {
() => {
entire_fn!();
}
}

macro_rules! entire_fn {
() => {
pub fn baz(x: &str) -> Result<(), Box<dyn std::error::Error>> {
Err(format!("error: {x}").into())
//~^ ERROR mismatched types
}
}
}

entire_fn_outer!();

macro_rules! nontrivial {
($x: expr) => {
Err(format!("error: {}", $x).into())
//~^ ERROR mismatched types
}
}

pub fn qux(x: &str) -> Result<(), Box<dyn std::error::Error>> {
nontrivial!(x)
}


fn main() {}
55 changes: 55 additions & 0 deletions tests/ui/typeck/issue-110017-format-into-help-deletes-macro.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// run-rustfix
#![allow(dead_code)]

pub fn foo(x: &str) -> Result<(), Box<dyn std::error::Error>> {
Err(format!("error: {x}"))
//~^ ERROR mismatched types
}

macro_rules! outer {
($x: expr) => {
inner!($x)
}
}

macro_rules! inner {
($x: expr) => {
format!("error: {}", $x)
//~^ ERROR mismatched types
}
}

fn bar(x: &str) -> Result<(), Box<dyn std::error::Error>> {
Err(outer!(x))
}

macro_rules! entire_fn_outer {
() => {
entire_fn!();
}
}

macro_rules! entire_fn {
() => {
pub fn baz(x: &str) -> Result<(), Box<dyn std::error::Error>> {
Err(format!("error: {x}"))
//~^ ERROR mismatched types
}
}
}

entire_fn_outer!();

macro_rules! nontrivial {
($x: expr) => {
Err(format!("error: {}", $x))
//~^ ERROR mismatched types
}
}

pub fn qux(x: &str) -> Result<(), Box<dyn std::error::Error>> {
nontrivial!(x)
}


fn main() {}
59 changes: 59 additions & 0 deletions tests/ui/typeck/issue-110017-format-into-help-deletes-macro.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
error[E0308]: mismatched types
--> $DIR/issue-110017-format-into-help-deletes-macro.rs:5:10
|
LL | Err(format!("error: {x}"))
| ^^^^^^^^^^^^^^^^^^^^^ expected `Box<dyn Error>`, found `String`
|
= note: expected struct `Box<dyn std::error::Error>`
found struct `String`
= note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
help: call `Into::into` on this expression to convert `String` into `Box<dyn std::error::Error>`
|
LL | Err(format!("error: {x}").into())
| +++++++

error[E0308]: mismatched types
--> $DIR/issue-110017-format-into-help-deletes-macro.rs:23:10
|
LL | Err(outer!(x))
| ^^^^^^^^^ expected `Box<dyn Error>`, found `String`
|
= note: expected struct `Box<dyn std::error::Error>`
found struct `String`
= 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)
help: call `Into::into` on this expression to convert `String` into `Box<dyn std::error::Error>`
|
LL | format!("error: {}", $x).into()
| +++++++

error[E0308]: mismatched types
--> $DIR/issue-110017-format-into-help-deletes-macro.rs:41:2
|
LL | entire_fn_outer!();
| ^^^^^^^^^^^^^^^^^^ expected `Box<dyn Error>`, found `String`
|
= note: expected struct `Box<dyn std::error::Error>`
found struct `String`
= 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)
help: call `Into::into` on this expression to convert `String` into `Box<dyn std::error::Error>`
|
LL | Err(format!("error: {x}").into())
| +++++++

error[E0308]: mismatched types
--> $DIR/issue-110017-format-into-help-deletes-macro.rs:51:5
|
LL | nontrivial!(x)
| ^^^^^^^^^^^^^^ expected `Box<dyn Error>`, found `String`
|
= note: expected struct `Box<dyn std::error::Error>`
found struct `String`
= 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)
help: call `Into::into` on this expression to convert `String` into `Box<dyn std::error::Error>`
|
LL | Err(format!("error: {}", $x).into())
| +++++++

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0308`.
37 changes: 37 additions & 0 deletions tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// run-rustfix
#![allow(dead_code)]

// https://github.com/rust-lang/rust/issues/112007
fn bug_report<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
if true {
writeln!(w, "`;?` here ->")?;
} else {
return writeln!(w, "but not here");
//~^ ERROR mismatched types
};
Ok(())
}

macro_rules! baz {
($w: expr) => {
bar!($w)
}
}

macro_rules! bar {
($w: expr) => {
writeln!($w, "but not here")
//~^ ERROR mismatched types
}
}

fn foo<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
if true {
writeln!(w, "`;?` here ->")?;
} else {
return baz!(w);
};
Ok(())
}

fn main() {}
37 changes: 37 additions & 0 deletions tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// run-rustfix
#![allow(dead_code)]

// https://github.com/rust-lang/rust/issues/112007
fn bug_report<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
if true {
writeln!(w, "`;?` here ->")?;
} else {
writeln!(w, "but not here")
//~^ ERROR mismatched types
}
Ok(())
}

macro_rules! baz {
($w: expr) => {
bar!($w)
}
}

macro_rules! bar {
($w: expr) => {
writeln!($w, "but not here")
//~^ ERROR mismatched types
}
}

fn foo<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
if true {
writeln!(w, "`;?` here ->")?;
} else {
baz!(w)
}
Ok(())
}

fn main() {}
50 changes: 50 additions & 0 deletions tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
error[E0308]: mismatched types
--> $DIR/issue-112007-leaked-writeln-macro-internals.rs:9:9
|
LL | / if true {
LL | | writeln!(w, "`;?` here ->")?;
LL | | } else {
LL | | writeln!(w, "but not here")
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Result<(), Error>`
LL | |
LL | | }
| |_____- expected this to be `()`
|
= note: expected unit type `()`
found enum `Result<(), std::fmt::Error>`
= note: this error originates in the macro `writeln` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider using a semicolon here
|
LL | };
| +
help: you might have meant to return this value
|
LL | return writeln!(w, "but not here");
| ++++++ +

error[E0308]: mismatched types
--> $DIR/issue-112007-leaked-writeln-macro-internals.rs:32:9
|
LL | / if true {
LL | | writeln!(w, "`;?` here ->")?;
LL | | } else {
LL | | baz!(w)
| | ^^^^^^^ expected `()`, found `Result<(), Error>`
LL | | }
| |_____- expected this to be `()`
|
= note: expected unit type `()`
found enum `Result<(), std::fmt::Error>`
= 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)
help: consider using a semicolon here
|
LL | };
| +
help: you might have meant to return this value
|
LL | return baz!(w);
| ++++++ +

error: aborting due to 2 previous errors

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

0 comments on commit 25d065b

Please sign in to comment.