Skip to content

Commit 04c2454

Browse files
committed
Fix ICE caused by suggestion with no code substitutions
Change suggestion logic to filter and checking _before_ creating specific resolution suggestion. Assert earlier that suggestions contain code substitions to make it easier in the future to debug invalid uses. If we find this becomes too noisy in the wild, we can always make the emitter resilient to these cases and remove the assertions. Fix #78651.
1 parent 178108b commit 04c2454

File tree

4 files changed

+39
-20
lines changed

4 files changed

+39
-20
lines changed

compiler/rustc_errors/src/diagnostic.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ impl Diagnostic {
295295
suggestion: Vec<(Span, String)>,
296296
applicability: Applicability,
297297
) -> &mut Self {
298+
assert!(!suggestion.is_empty());
298299
self.suggestions.push(CodeSuggestion {
299300
substitutions: vec![Substitution {
300301
parts: suggestion
@@ -318,6 +319,10 @@ impl Diagnostic {
318319
suggestions: Vec<Vec<(Span, String)>>,
319320
applicability: Applicability,
320321
) -> &mut Self {
322+
assert!(!suggestions.is_empty());
323+
for s in &suggestions {
324+
assert!(!s.is_empty());
325+
}
321326
self.suggestions.push(CodeSuggestion {
322327
substitutions: suggestions
323328
.into_iter()
@@ -348,6 +353,7 @@ impl Diagnostic {
348353
suggestion: Vec<(Span, String)>,
349354
applicability: Applicability,
350355
) -> &mut Self {
356+
assert!(!suggestion.is_empty());
351357
self.suggestions.push(CodeSuggestion {
352358
substitutions: vec![Substitution {
353359
parts: suggestion

compiler/rustc_resolve/src/late/diagnostics.rs

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -319,9 +319,13 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
319319
.collect::<Vec<_>>();
320320
let crate_def_id = DefId::local(CRATE_DEF_INDEX);
321321
if candidates.is_empty() && is_expected(Res::Def(DefKind::Enum, crate_def_id)) {
322-
let enum_candidates =
323-
self.r.lookup_import_candidates(ident, ns, &self.parent_scope, is_enum_variant);
324-
322+
let mut enum_candidates: Vec<_> = self
323+
.r
324+
.lookup_import_candidates(ident, ns, &self.parent_scope, is_enum_variant)
325+
.into_iter()
326+
.map(|suggestion| import_candidate_to_enum_paths(&suggestion))
327+
.filter(|(_, enum_ty_path)| enum_ty_path != "std::prelude::v1")
328+
.collect();
325329
if !enum_candidates.is_empty() {
326330
if let (PathSource::Type, Some(span)) =
327331
(source, self.diagnostic_metadata.current_type_ascription.last())
@@ -340,10 +344,6 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
340344
}
341345
}
342346

343-
let mut enum_candidates = enum_candidates
344-
.iter()
345-
.map(|suggestion| import_candidate_to_enum_paths(&suggestion))
346-
.collect::<Vec<_>>();
347347
enum_candidates.sort();
348348

349349
// Contextualize for E0412 "cannot find type", but don't belabor the point
@@ -363,19 +363,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
363363
err.span_suggestions(
364364
span,
365365
&msg,
366-
enum_candidates
367-
.into_iter()
368-
.map(|(_variant_path, enum_ty_path)| enum_ty_path)
369-
// Variants re-exported in prelude doesn't mean `prelude::v1` is the
370-
// type name!
371-
// FIXME: is there a more principled way to do this that
372-
// would work for other re-exports?
373-
.filter(|enum_ty_path| enum_ty_path != "std::prelude::v1")
374-
// Also write `Option` rather than `std::prelude::v1::Option`.
375-
.map(|enum_ty_path| {
376-
// FIXME #56861: DRY-er prelude filtering.
377-
enum_ty_path.trim_start_matches("std::prelude::v1::").to_owned()
378-
}),
366+
enum_candidates.into_iter().map(|(_variant_path, enum_ty_path)| enum_ty_path),
379367
Applicability::MachineApplicable,
380368
);
381369
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
use std::result;
2+
impl result { //~ ERROR expected type, found module `result`
3+
fn into_future() -> Err {} //~ ERROR expected type, found variant `Err`
4+
}
5+
fn main() {}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error[E0573]: expected type, found module `result`
2+
--> $DIR/do-not-attempt-to-add-suggestions-with-no-changes.rs:2:6
3+
|
4+
LL | impl result {
5+
| ^^^^^^ help: an enum with a similar name exists: `Result`
6+
|
7+
::: $SRC_DIR/core/src/result.rs:LL:COL
8+
|
9+
LL | pub enum Result<T, E> {
10+
| --------------------- similarly named enum `Result` defined here
11+
12+
error[E0573]: expected type, found variant `Err`
13+
--> $DIR/do-not-attempt-to-add-suggestions-with-no-changes.rs:3:25
14+
|
15+
LL | fn into_future() -> Err {}
16+
| ^^^ not a type
17+
18+
error: aborting due to 2 previous errors
19+
20+
For more information about this error, try `rustc --explain E0573`.

0 commit comments

Comments
 (0)