diff options
| author | Lukas Markeffsky <@> | 2023-06-10 19:13:42 +0200 |
|---|---|---|
| committer | Lukas Markeffsky <@> | 2023-08-01 16:51:20 +0000 |
| commit | 3694fd08e6e9d0828369ac1c9ee205cd0de71287 (patch) | |
| tree | 817a5572422ff096a5f8aead6243304d4889e1e3 | |
| parent | 10ef96f6a5e71746968417892feeddd0a099774d (diff) | |
| download | rust-3694fd08e6e9d0828369ac1c9ee205cd0de71287.tar.gz rust-3694fd08e6e9d0828369ac1c9ee205cd0de71287.zip | |
introduce `Span::find_ancestor_inside_same_ctxt`
and use it for function argument diagnostics
| -rw-r--r-- | compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 33 | ||||
| -rw-r--r-- | compiler/rustc_span/src/lib.rs | 37 | ||||
| -rw-r--r-- | tests/ui/argument-suggestions/extra_arguments.stderr | 10 | ||||
| -rw-r--r-- | tests/ui/issues/issue-48364.stderr | 1 |
4 files changed, 57 insertions, 24 deletions
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index e102c51c7ee..8e49aa3e656 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -519,7 +519,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // suggestions and labels are (more) correct when an arg is a // macro invocation. let normalize_span = |span: Span| -> Span { - let normalized_span = span.find_ancestor_inside(error_span).unwrap_or(span); + let normalized_span = span.find_ancestor_inside_same_ctxt(error_span).unwrap_or(span); // Sometimes macros mess up the spans, so do not normalize the // arg span to equal the error span, because that's less useful // than pointing out the arg expr in the wrong context. @@ -1220,22 +1220,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if let Some(suggestion_text) = suggestion_text { let source_map = self.sess().source_map(); - let (mut suggestion, suggestion_span) = - if let Some(call_span) = full_call_span.find_ancestor_inside(error_span) { - ("(".to_string(), call_span.shrink_to_hi().to(error_span.shrink_to_hi())) - } else { - ( - format!( - "{}(", - source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| { - fn_def_id.map_or("".to_string(), |fn_def_id| { - tcx.item_name(fn_def_id).to_string() - }) + let (mut suggestion, suggestion_span) = if let Some(call_span) = + full_call_span.find_ancestor_inside_same_ctxt(error_span) + { + ("(".to_string(), call_span.shrink_to_hi().to(error_span.shrink_to_hi())) + } else { + ( + format!( + "{}(", + source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| { + fn_def_id.map_or("".to_string(), |fn_def_id| { + tcx.item_name(fn_def_id).to_string() }) - ), - error_span, - ) - }; + }) + ), + error_span, + ) + }; let mut needs_comma = false; for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() { if needs_comma { diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index ecaa82874a3..02a5d6966a7 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -685,6 +685,12 @@ impl Span { } /// Walk down the expansion ancestors to find a span that's contained within `outer`. + /// + /// The span returned by this method may have a different [`SyntaxContext`] as `outer`. + /// If you need to extend the span, use [`find_ancestor_inside_same_ctxt`] instead, + /// because joining spans with different syntax contexts can create unexpected results. + /// + /// [`find_ancestor_inside_same_ctxt`]: Self::find_ancestor_inside_same_ctxt pub fn find_ancestor_inside(mut self, outer: Span) -> Option<Span> { while !outer.contains(self) { self = self.parent_callsite()?; @@ -692,11 +698,34 @@ impl Span { Some(self) } - /// Like `find_ancestor_inside`, but specifically for when spans might not - /// overlaps. Take care when using this, and prefer `find_ancestor_inside` - /// when you know that the spans are nested (modulo macro expansion). + /// Walk down the expansion ancestors to find a span with the same [`SyntaxContext`] as + /// `other`. + /// + /// Like [`find_ancestor_inside_same_ctxt`], but specifically for when spans might not + /// overlap. Take care when using this, and prefer [`find_ancestor_inside`] or + /// [`find_ancestor_inside_same_ctxt`] when you know that the spans are nested (modulo + /// macro expansion). + /// + /// [`find_ancestor_inside`]: Self::find_ancestor_inside + /// [`find_ancestor_inside_same_ctxt`]: Self::find_ancestor_inside_same_ctxt pub fn find_ancestor_in_same_ctxt(mut self, other: Span) -> Option<Span> { - while !Span::eq_ctxt(self, other) { + while !self.eq_ctxt(other) { + self = self.parent_callsite()?; + } + Some(self) + } + + /// Walk down the expansion ancestors to find a span that's contained within `outer` and + /// has the same [`SyntaxContext`] as `outer`. + /// + /// This method is the combination of [`find_ancestor_inside`] and + /// [`find_ancestor_in_same_ctxt`] and should be preferred when extending the returned span. + /// If you do not need to modify the span, use [`find_ancestor_inside`] instead. + /// + /// [`find_ancestor_inside`]: Self::find_ancestor_inside + /// [`find_ancestor_in_same_ctxt`]: Self::find_ancestor_in_same_ctxt + pub fn find_ancestor_inside_same_ctxt(mut self, outer: Span) -> Option<Span> { + while !outer.contains(self) || !self.eq_ctxt(outer) { self = self.parent_callsite()?; } Some(self) diff --git a/tests/ui/argument-suggestions/extra_arguments.stderr b/tests/ui/argument-suggestions/extra_arguments.stderr index a32101e2518..1016c7ba438 100644 --- a/tests/ui/argument-suggestions/extra_arguments.stderr +++ b/tests/ui/argument-suggestions/extra_arguments.stderr @@ -321,7 +321,10 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied --> $DIR/extra_arguments.rs:53:3 | LL | one_arg(1, panic!()); - | ^^^^^^^ -------- unexpected argument + | ^^^^^^^ ---------- + | | | + | | unexpected argument + | help: remove the extra argument | note: function defined here --> $DIR/extra_arguments.rs:2:4 @@ -333,8 +336,9 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied --> $DIR/extra_arguments.rs:54:3 | LL | one_arg(panic!(), 1); - | ^^^^^^^ - - unexpected argument of type `{integer}` - | | + | ^^^^^^^ --- + | | | + | | unexpected argument of type `{integer}` | help: remove the extra argument | note: function defined here diff --git a/tests/ui/issues/issue-48364.stderr b/tests/ui/issues/issue-48364.stderr index cac4af6a7f3..3f2e1b83ad5 100644 --- a/tests/ui/issues/issue-48364.stderr +++ b/tests/ui/issues/issue-48364.stderr @@ -10,7 +10,6 @@ LL | b"".starts_with(stringify!(foo)) found reference `&'static str` note: method defined here --> $SRC_DIR/core/src/slice/mod.rs:LL:COL - = note: this error originates in the macro `stringify` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error |
