about summary refs log tree commit diff
path: root/tests/ui
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-04-12 21:46:57 +0200
committerGitHub <noreply@github.com>2024-04-12 21:46:57 +0200
commitca28e9554f732cea8299e058ef8175b4441dee6f (patch)
tree1b7baa7f1b73ee3dc8bcd7004d534c5f794e535d /tests/ui
parent322e92bdaee73946b8b78d1fb6d9c808ce1436e9 (diff)
parent420e3f1d5cf8e156d6f4ae636ce5bbaa6b7c9c70 (diff)
downloadrust-ca28e9554f732cea8299e058ef8175b4441dee6f.tar.gz
rust-ca28e9554f732cea8299e058ef8175b4441dee6f.zip
Rollup merge of #123654 - jieyouxu:question-mark-span, r=Nadrieril
typeck: fix `?` suggestion span

Noticed in <https://github.com/rust-lang/rust/pull/112043#issuecomment-2043565292>, if the

```
use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller
```

suggestion is applied to a macro that comes from a non-local crate (e.g. the stdlib), the suggestion span can become non-local, which will cause newer rustfix versions to fail.

This PR tries to remedy the problem by recursively probing ancestors of the expression span, trying to identify the most ancestor span that is (1) still local, and (2) still shares the same syntax context as the expression.

This is the same strategy used in https://github.com/rust-lang/rust/pull/112043.

The test unfortunately cannot `//@ run-rustfix` because there are two conflicting MaybeIncorrect suggestions that when collectively applied, cause the fixed source file to become non-compilable.

Also avoid running `//@ run-rustfix` for `tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.rs` because that also contains conflicting suggestions.

cc `@ehuss` who noticed this. This question mark span fix + not running rustfix on the tests containing conflicting MaybeIncorrect suggestions should hopefully unblock rustfix from updating.
Diffstat (limited to 'tests/ui')
-rw-r--r--tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.fixed37
-rw-r--r--tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.rs18
-rw-r--r--tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.stderr12
-rw-r--r--tests/ui/typeck/question-mark-operator-suggestion-span.rs22
-rw-r--r--tests/ui/typeck/question-mark-operator-suggestion-span.stderr31
5 files changed, 76 insertions, 44 deletions
diff --git a/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.fixed b/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.fixed
deleted file mode 100644
index dcb256de18f..00000000000
--- a/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.fixed
+++ /dev/null
@@ -1,37 +0,0 @@
-//@ 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() {}
diff --git a/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.rs b/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.rs
index 58cd6cbf20c..7ec9f0d4cdb 100644
--- a/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.rs
+++ b/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.rs
@@ -1,8 +1,16 @@
-//@ run-rustfix
-#![allow(dead_code)]
+// Check that we don't leak stdlib implementation details through suggestions.
+// Also check that the suggestion provided tries as hard as it can to see through local macros.
+//
+// FIXME(jieyouxu): this test is NOT run-rustfix because this test contains conflicting
+// MaybeIncorrect suggestions:
+//
+// 1. `return ... ;`
+// 2. `?`
+//
+// when the suggestions are applied to the same file, it becomes uncompilable.
 
 // https://github.com/rust-lang/rust/issues/112007
-fn bug_report<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
+pub fn bug_report<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
     if true {
         writeln!(w, "`;?` here ->")?;
     } else {
@@ -25,7 +33,7 @@ macro_rules! bar {
     }
 }
 
-fn foo<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
+pub fn foo<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
     if true {
         writeln!(w, "`;?` here ->")?;
     } else {
@@ -34,4 +42,4 @@ fn foo<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
     Ok(())
 }
 
-fn main() {}
+pub fn main() {}
diff --git a/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.stderr b/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.stderr
index df2e06e8f3b..889d2c94d0c 100644
--- a/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.stderr
+++ b/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-112007-leaked-writeln-macro-internals.rs:9:9
+  --> $DIR/issue-112007-leaked-writeln-macro-internals.rs:17:9
    |
 LL | /     if true {
 LL | |         writeln!(w, "`;?` here ->")?;
@@ -21,9 +21,13 @@ help: you might have meant to return this value
    |
 LL |         return writeln!(w, "but not here");
    |         ++++++                            +
+help: use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller
+   |
+LL |         writeln!(w, "but not here")?
+   |                                    +
 
 error[E0308]: mismatched types
-  --> $DIR/issue-112007-leaked-writeln-macro-internals.rs:32:9
+  --> $DIR/issue-112007-leaked-writeln-macro-internals.rs:40:9
    |
 LL | /     if true {
 LL | |         writeln!(w, "`;?` here ->")?;
@@ -44,6 +48,10 @@ help: you might have meant to return this value
    |
 LL |         return baz!(w);
    |         ++++++        +
+help: use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller
+   |
+LL |         writeln!($w, "but not here")?
+   |                                     +
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/typeck/question-mark-operator-suggestion-span.rs b/tests/ui/typeck/question-mark-operator-suggestion-span.rs
new file mode 100644
index 00000000000..7aea6e63dd1
--- /dev/null
+++ b/tests/ui/typeck/question-mark-operator-suggestion-span.rs
@@ -0,0 +1,22 @@
+// Check that we don't construct a span for `?` suggestions that point into non-local macros
+// like into the stdlib where the user has no control over.
+//
+// FIXME(jieyouxu): this test is currently NOT run-rustfix because there are conflicting
+// MaybeIncorrect suggestions:
+//
+// 1. adding `return ... ;`, and
+// 2. adding `?`.
+//
+// When rustfix puts those together, the fixed file now contains uncompilable code.
+
+#![crate_type = "lib"]
+
+pub 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(())
+}
diff --git a/tests/ui/typeck/question-mark-operator-suggestion-span.stderr b/tests/ui/typeck/question-mark-operator-suggestion-span.stderr
new file mode 100644
index 00000000000..089b3bcd198
--- /dev/null
+++ b/tests/ui/typeck/question-mark-operator-suggestion-span.stderr
@@ -0,0 +1,31 @@
+error[E0308]: mismatched types
+  --> $DIR/question-mark-operator-suggestion-span.rs:18: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");
+   |         ++++++                            +
+help: use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller
+   |
+LL |         writeln!(w, "but not here")?
+   |                                    +
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.