Skip to content

Commit 138f60e

Browse files
authored
Unrolled build for rust-lang#132567
Rollup merge of rust-lang#132567 - estebank:bad-suggestion, r=Nadrieril Properly suggest `E::assoc` when we encounter `E::Variant::assoc` Use the right span when encountering an enum variant followed by an associated item so we don't lose the associated item in the resulting code. Do not suggest the thing twice, once as a removal of the associated item and a second time as a typo suggestion.
2 parents bc5cf99 + e26ad8b commit 138f60e

File tree

4 files changed

+66
-15
lines changed

4 files changed

+66
-15
lines changed

Diff for: compiler/rustc_resolve/src/late/diagnostics.rs

+36-10
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
459459
return (err, Vec::new());
460460
}
461461

462-
let (found, mut candidates) = self.try_lookup_name_relaxed(
462+
let (found, suggested_candidates, mut candidates) = self.try_lookup_name_relaxed(
463463
&mut err,
464464
source,
465465
path,
@@ -478,7 +478,15 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
478478
}
479479

480480
let mut fallback = self.suggest_trait_and_bounds(&mut err, source, res, span, &base_error);
481-
fallback |= self.suggest_typo(&mut err, source, path, following_seg, span, &base_error);
481+
fallback |= self.suggest_typo(
482+
&mut err,
483+
source,
484+
path,
485+
following_seg,
486+
span,
487+
&base_error,
488+
suggested_candidates,
489+
);
482490

483491
if fallback {
484492
// Fallback label.
@@ -589,7 +597,16 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
589597
span: Span,
590598
res: Option<Res>,
591599
base_error: &BaseError,
592-
) -> (bool, Vec<ImportSuggestion>) {
600+
) -> (bool, FxHashSet<String>, Vec<ImportSuggestion>) {
601+
let span = match following_seg {
602+
Some(_) if path[0].ident.span.eq_ctxt(path[path.len() - 1].ident.span) => {
603+
// The path `span` that comes in includes any following segments, which we don't
604+
// want to replace in the suggestions.
605+
path[0].ident.span.to(path[path.len() - 1].ident.span)
606+
}
607+
_ => span,
608+
};
609+
let mut suggested_candidates = FxHashSet::default();
593610
// Try to lookup name in more relaxed fashion for better error reporting.
594611
let ident = path.last().unwrap().ident;
595612
let is_expected = &|res| source.is_expected(res);
@@ -646,6 +663,11 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
646663
};
647664
let msg = format!("{preamble}try using the variant's enum");
648665

666+
suggested_candidates.extend(
667+
enum_candidates
668+
.iter()
669+
.map(|(_variant_path, enum_ty_path)| enum_ty_path.clone()),
670+
);
649671
err.span_suggestions(
650672
span,
651673
msg,
@@ -658,7 +680,8 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
658680
// Try finding a suitable replacement.
659681
let typo_sugg = self
660682
.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected)
661-
.to_opt_suggestion();
683+
.to_opt_suggestion()
684+
.filter(|sugg| !suggested_candidates.contains(sugg.candidate.as_str()));
662685
if let [segment] = path
663686
&& !matches!(source, PathSource::Delegation)
664687
&& self.self_type_is_available()
@@ -719,7 +742,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
719742
}
720743
}
721744
self.r.add_typo_suggestion(err, typo_sugg, ident_span);
722-
return (true, candidates);
745+
return (true, suggested_candidates, candidates);
723746
}
724747

725748
// If the first argument in call is `self` suggest calling a method.
@@ -737,7 +760,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
737760
format!("self.{path_str}({args_snippet})"),
738761
Applicability::MachineApplicable,
739762
);
740-
return (true, candidates);
763+
return (true, suggested_candidates, candidates);
741764
}
742765
}
743766

@@ -754,7 +777,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
754777
) {
755778
// We do this to avoid losing a secondary span when we override the main error span.
756779
self.r.add_typo_suggestion(err, typo_sugg, ident_span);
757-
return (true, candidates);
780+
return (true, suggested_candidates, candidates);
758781
}
759782
}
760783

@@ -772,7 +795,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
772795
ident.span,
773796
format!("the binding `{path_str}` is available in a different scope in the same function"),
774797
);
775-
return (true, candidates);
798+
return (true, suggested_candidates, candidates);
776799
}
777800
}
778801
}
@@ -781,7 +804,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
781804
candidates = self.smart_resolve_partial_mod_path_errors(path, following_seg);
782805
}
783806

784-
(false, candidates)
807+
(false, suggested_candidates, candidates)
785808
}
786809

787810
fn suggest_trait_and_bounds(
@@ -869,13 +892,16 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
869892
following_seg: Option<&Segment>,
870893
span: Span,
871894
base_error: &BaseError,
895+
suggested_candidates: FxHashSet<String>,
872896
) -> bool {
873897
let is_expected = &|res| source.is_expected(res);
874898
let ident_span = path.last().map_or(span, |ident| ident.ident.span);
875899
let typo_sugg =
876900
self.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected);
877901
let mut fallback = false;
878-
let typo_sugg = typo_sugg.to_opt_suggestion();
902+
let typo_sugg = typo_sugg
903+
.to_opt_suggestion()
904+
.filter(|sugg| !suggested_candidates.contains(sugg.candidate.as_str()));
879905
if !self.r.add_typo_suggestion(err, typo_sugg, ident_span) {
880906
fallback = true;
881907
match self.diag_metadata.current_let_binding {

Diff for: tests/ui/enum/assoc-fn-call-on-variant.rs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#[derive(Default)]
2+
enum E {
3+
A {},
4+
B {},
5+
#[default]
6+
C,
7+
}
8+
9+
impl E {
10+
fn f() {}
11+
}
12+
13+
fn main() {
14+
E::A::f(); //~ ERROR failed to resolve: `A` is a variant, not a module
15+
}

Diff for: tests/ui/enum/assoc-fn-call-on-variant.stderr

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0433]: failed to resolve: `A` is a variant, not a module
2+
--> $DIR/assoc-fn-call-on-variant.rs:14:8
3+
|
4+
LL | E::A::f();
5+
| ^ `A` is a variant, not a module
6+
|
7+
help: there is an enum variant `E::A`; try using the variant's enum
8+
|
9+
LL | E::f();
10+
| ~
11+
12+
error: aborting due to 1 previous error
13+
14+
For more information about this error, try `rustc --explain E0433`.

Diff for: tests/ui/resolve/resolve-variant-assoc-item.stderr

+1-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ LL | E::V::associated_item;
66
|
77
help: there is an enum variant `E::V`; try using the variant's enum
88
|
9-
LL | E;
9+
LL | E::associated_item;
1010
| ~
1111

1212
error[E0433]: failed to resolve: `V` is a variant, not a module
@@ -17,10 +17,6 @@ LL | V::associated_item;
1717
|
1818
help: there is an enum variant `E::V`; try using the variant's enum
1919
|
20-
LL | E;
21-
| ~
22-
help: an enum with a similar name exists
23-
|
2420
LL | E::associated_item;
2521
| ~
2622

0 commit comments

Comments
 (0)