about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs8
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs6
-rw-r--r--tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.rs26
-rw-r--r--tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.stderr50
4 files changed, 89 insertions, 1 deletions
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 61260dbd16c..ddcd90a2a9d 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -3394,7 +3394,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let Some(ty) = self.node_ty_opt(tail_expr.hir_id) else {
             return;
         };
-        if self.can_eq(self.param_env, expected_ty, ty) {
+        if self.can_eq(self.param_env, expected_ty, ty)
+            // FIXME: this happens with macro calls. Need to figure out why the stmt
+            // `println!();` doesn't include the `;` in its `Span`. (#133845)
+            // We filter these out to avoid ICEs with debug assertions on caused by
+            // empty suggestions.
+            && stmt.span.hi() != tail_expr.span.hi()
+        {
             err.span_suggestion_short(
                 stmt.span.with_lo(tail_expr.span.hi()),
                 "remove this semicolon",
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index 2bb503f17b4..94682f501a8 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -3838,6 +3838,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 && self.predicate_must_hold_modulo_regions(&Obligation::misc(
                     tcx, expr.span, body_id, param_env, pred,
                 ))
+                && expr.span.hi() != rcvr.span.hi()
             {
                 err.span_suggestion_verbose(
                     expr.span.with_lo(rcvr.span.hi()),
@@ -4115,6 +4116,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         // the expected is a projection that we need to resolve.
                         // && let Some(tail_ty) = typeck_results.expr_ty_opt(expr)
                         && expected_found.found.is_unit()
+                        // FIXME: this happens with macro calls. Need to figure out why the stmt
+                        // `println!();` doesn't include the `;` in its `Span`. (#133845)
+                        // We filter these out to avoid ICEs with debug assertions on caused by
+                        // empty suggestions.
+                        && expr.span.hi() != stmt.span.hi()
                     {
                         err.span_suggestion_verbose(
                             expr.span.shrink_to_hi().with_hi(stmt.span.hi()),
diff --git a/tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.rs b/tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.rs
new file mode 100644
index 00000000000..35612093aff
--- /dev/null
+++ b/tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.rs
@@ -0,0 +1,26 @@
+//! Regression test for suggestions that were fired on empty spans
+//! involving macro-call statements. For some reason the semicolon
+//! is not included in the overall span of the macro-call statement.
+//!
+//! Issue 1: <https://github.com/rust-lang/rust/issues/133833>.
+//! Issue 2: <https://github.com/rust-lang/rust/issues/133834>.
+//! See also: <https://github.com/rust-lang/rust/issues/133845>.
+
+fn foo() -> String {
+    let mut list = {
+        println!();
+    };
+    list //~ ERROR mismatched types
+}
+
+fn bar() {
+    String::new()
+        .chars()
+        .filter(|x| !x.is_whitespace())
+        .map(|x| {
+            println!("Child spawned with the size: {}", x);
+        })
+        .collect::<String>(); //~ ERROR E0277
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.stderr b/tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.stderr
new file mode 100644
index 00000000000..4b83bfff863
--- /dev/null
+++ b/tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.stderr
@@ -0,0 +1,50 @@
+error[E0308]: mismatched types
+  --> $DIR/semi-suggestion-when-stmt-and-expr-span-equal.rs:13:5
+   |
+LL |   fn foo() -> String {
+   |               ------ expected `String` because of return type
+LL |       let mut list = {
+   |  ____________________-
+LL | |         println!();
+LL | |     };
+   | |_____- this block is missing a tail expression
+LL |       list
+   |       ^^^^ expected `String`, found `()`
+
+error[E0277]: a value of type `String` cannot be built from an iterator over elements of type `()`
+  --> $DIR/semi-suggestion-when-stmt-and-expr-span-equal.rs:23:20
+   |
+LL |         .collect::<String>();
+   |          -------   ^^^^^^ value of type `String` cannot be built from `std::iter::Iterator<Item=()>`
+   |          |
+   |          required by a bound introduced by this call
+   |
+   = help: the trait `FromIterator<()>` is not implemented for `String`
+   = help: the following other types implement trait `FromIterator<A>`:
+             `String` implements `FromIterator<&char>`
+             `String` implements `FromIterator<&str>`
+             `String` implements `FromIterator<Box<str, A>>`
+             `String` implements `FromIterator<Cow<'_, str>>`
+             `String` implements `FromIterator<String>`
+             `String` implements `FromIterator<char>`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/semi-suggestion-when-stmt-and-expr-span-equal.rs:20:10
+   |
+LL |       String::new()
+   |       ------------- this expression has type `String`
+LL |           .chars()
+   |            ------- `Iterator::Item` is `char` here
+LL |           .filter(|x| !x.is_whitespace())
+   |            ------------------------------ `Iterator::Item` remains `char` here
+LL |           .map(|x| {
+   |  __________^
+LL | |             println!("Child spawned with the size: {}", x);
+LL | |         })
+   | |__________^ `Iterator::Item` changed to `()` here
+note: required by a bound in `collect`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.