Skip to content

Commit 5158063

Browse files
committed
Switch to multipart suggestions.
This commit changes the suggestion so that it is split into multiple parts in an effort to reduce the impact the applied suggestion could have on formatting.
1 parent 137ffa1 commit 5158063

File tree

6 files changed

+68
-208
lines changed

6 files changed

+68
-208
lines changed

src/librustc_resolve/error_reporting.rs

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -617,14 +617,12 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
617617
_ => format!("{}", ident),
618618
};
619619

620-
// Assume this is the easy case of `use issue_59764::foo::makro;` and just remove
621-
// intermediate segments.
622-
let (mut span, mut correction) = (directive.span,
623-
format!("{}::{}", module_name, import));
624-
625-
if directive.is_nested() {
626-
span = directive.use_span;
627-
620+
let mut corrections: Vec<(Span, String)> = Vec::new();
621+
if !directive.is_nested() {
622+
// Assume this is the easy case of `use issue_59764::foo::makro;` and just remove
623+
// intermediate segments.
624+
corrections.push((directive.span, format!("{}::{}", module_name, import)));
625+
} else {
628626
// Find the binding span (and any trailing commas and spaces).
629627
// ie. `use a::b::{c, d, e};`
630628
// ^^^
@@ -652,6 +650,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
652650
}
653651
debug!("check_for_module_export_macro: removal_span={:?}", removal_span);
654652

653+
// Remove the `removal_span`.
654+
corrections.push((removal_span, "".to_string()));
655+
655656
// Find the span after the crate name and if it has nested imports immediatately
656657
// after the crate name already.
657658
// ie. `use a::b::{c, d};`
@@ -666,34 +667,32 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
666667

667668
let source_map = self.resolver.session.source_map();
668669

669-
// Remove two bytes at the end to keep all but the `};` characters.
670-
// ie. `{b::{c, d}, e::{f, g}};`
671-
// ^^^^^^^^^^^^^^^^^^^^^
672-
let end_bytes = BytePos(if has_nested { 2 } else { 1 });
673-
let mut remaining_span = after_crate_name.with_hi(
674-
after_crate_name.hi() - end_bytes);
675-
if has_nested {
676-
// Remove two bytes at the start to keep all but the initial `{` character.
677-
// ie. `{b::{c, d}, e::{f, g}`
678-
// ^^^^^^^^^^^^^^^^^^^^
679-
remaining_span = remaining_span.with_lo(after_crate_name.lo() + BytePos(1));
670+
// Add the import to the start, with a `{` if required.
671+
let start_point = source_map.start_point(after_crate_name);
672+
if let Ok(start_snippet) = source_map.span_to_snippet(start_point) {
673+
corrections.push((
674+
start_point,
675+
if has_nested {
676+
// In this case, `start_snippet` must equal '{'.
677+
format!("{}{}, ", start_snippet, import)
678+
} else {
679+
// In this case, add a `{`, then the moved import, then whatever
680+
// was there before.
681+
format!("{{{}, {}", import, start_snippet)
682+
}
683+
));
680684
}
681685

682-
// Calculate the number of characters into a snippet to remove the removal
683-
// span.
684-
let lo = removal_span.lo() - remaining_span.lo();
685-
let hi = lo + (removal_span.hi() - removal_span.lo());
686-
if let Ok(mut remaining) = source_map.span_to_snippet(remaining_span) {
687-
// Remove the original location of the binding.
688-
remaining.replace_range((lo.0 as usize)..(hi.0 as usize), "");
689-
correction = format!("use {}::{{{}, {}}};", module_name, import, remaining);
686+
// Add a `};` to the end if nested, matching the `{` added at the start.
687+
if !has_nested {
688+
corrections.push((source_map.end_point(after_crate_name),
689+
"};".to_string()));
690690
}
691691
}
692692

693693
let suggestion = Some((
694-
span,
694+
corrections,
695695
String::from("a macro with this name exists at the root of the crate"),
696-
correction,
697696
Applicability::MaybeIncorrect,
698697
));
699698
let note = vec![

src/librustc_resolve/lib.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,8 @@ impl Ord for BindingError {
139139
}
140140
}
141141

142-
/// A span, message, replacement text, and applicability.
143-
type Suggestion = (Span, String, String, Applicability);
142+
/// A vector of spans and replacements, a message and applicability.
143+
type Suggestion = (Vec<(Span, String)>, String, Applicability);
144144

145145
enum ResolutionError<'a> {
146146
/// Error E0401: can't use type or const parameters from outer function.
@@ -390,8 +390,8 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
390390
"failed to resolve: {}", &label);
391391
err.span_label(span, label);
392392

393-
if let Some((span, msg, suggestion, applicability)) = suggestion {
394-
err.span_suggestion(span, &msg, suggestion, applicability);
393+
if let Some((suggestions, msg, applicability)) = suggestion {
394+
err.multipart_suggestion(&msg, suggestions, applicability);
395395
}
396396

397397
err
@@ -3774,9 +3774,8 @@ impl<'a> Resolver<'a> {
37743774
(
37753775
String::from("unresolved import"),
37763776
Some((
3777-
ident.span,
3777+
vec![(ident.span, candidate.path.to_string())],
37783778
String::from("a similar path exists"),
3779-
candidate.path.to_string(),
37803779
Applicability::MaybeIncorrect,
37813780
)),
37823781
)

src/librustc_resolve/resolve_imports.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -793,8 +793,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
793793
diag.span_label(err.span, label);
794794
}
795795

796-
if let Some((span, msg, suggestion, applicability)) = err.suggestion {
797-
diag.span_suggestion(span, &msg, suggestion, applicability);
796+
if let Some((suggestions, msg, applicability)) = err.suggestion {
797+
diag.multipart_suggestion(&msg, suggestions, applicability);
798798
}
799799
}
800800

@@ -947,9 +947,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
947947
label: None,
948948
note,
949949
suggestion: Some((
950-
span,
950+
vec![(span, Segment::names_to_string(&suggestion))],
951951
String::from("a similar path exists"),
952-
Segment::names_to_string(&suggestion),
953952
Applicability::MaybeIncorrect,
954953
)),
955954
}
@@ -1113,8 +1112,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
11131112

11141113
let lev_suggestion = find_best_match_for_name(names, &ident.as_str(), None)
11151114
.map(|suggestion|
1116-
(ident.span, String::from("a similar name exists in the module"),
1117-
suggestion.to_string(), Applicability::MaybeIncorrect)
1115+
(vec![(ident.span, suggestion.to_string())],
1116+
String::from("a similar name exists in the module"),
1117+
Applicability::MaybeIncorrect)
11181118
);
11191119

11201120
let (suggestion, note) = match self.check_for_module_export_macro(

src/test/ui/issue-59764.fixed

Lines changed: 0 additions & 134 deletions
This file was deleted.

src/test/ui/issue-59764.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// aux-build:issue-59764.rs
22
// compile-flags:--extern issue_59764
33
// edition:2018
4-
// run-rustfix
54

65
#![allow(warnings)]
76

0 commit comments

Comments
 (0)