mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Auto merge of #112043 - jieyouxu:suggestion_macro_expansion_source_callsites, 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.
This commit is contained in:
commit
c115ec11d2
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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}`"),
|
||||
|
@ -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() {}
|
@ -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() {}
|
@ -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`.
|
@ -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() {}
|
@ -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() {}
|
@ -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`.
|
Loading…
Reference in New Issue
Block a user