Skip to content

Commit

Permalink
Auto merge of #112043 - jieyouxu:suggestion_macro_expansion_source_ca…
Browse files Browse the repository at this point in the history
…llsites, r=cjgillot

Fix suggestion spans for expr from macro expansions

### Issue #112007: rustc shows expanded `writeln!` macro in code suggestion

#### Before This PR

```
help: consider using a semicolon here
  |
6 |     };
  |      +
help: you might have meant to return this value
 --> C:\Users\hayle\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\core\src\macros\mod.rs:557:9
  |
55|         return $dst.write_fmt($crate::format_args_nl!($($arg)*));
  |         ++++++                                                  +
```

#### After This PR

```
help: consider using a semicolon here
   |
LL |     };
   |      +
help: you might have meant to return this value
   |
LL |         return writeln!(w, "but not here");
   |         ++++++                            +
```

### Issue #110017: `format!` `.into()` suggestion deletes the `format` macro

#### Before This PR

```
help: call `Into::into` on this expression to convert `String` into `Box<dyn std::error::Error>`
 --> /Users/eric/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/macros.rs:121:12
  |
12|         res.into()
  |            +++++++
```

#### After This PR

```
help: call `Into::into` on this expression to convert `String` into `Box<dyn std::error::Error>`
   |
LL |     Err(format!("error: {x}").into())
   |                              +++++++
```

---

Fixes #112007.
Fixes #110017.
  • Loading branch information
bors committed Aug 3, 2023
2 parents a922d1c + 25d065b commit c115ec1
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 @@ -994,14 +994,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 @@ -1185,10 +1190,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 c115ec1

Please sign in to comment.