Skip to content

Commit

Permalink
Rollup merge of rust-lang#132383 - compiler-errors:never-type-fallbac…
Browse files Browse the repository at this point in the history
…k-sugg, r=WaffleLapkin

Implement suggestion for never type fallback lints

r? ``@WaffleLapkin``

Just opening this up for vibes; it's not done yet. I'd still like to make this suggestable in a few more cases before merge:
- [x] Try to annotate `_` -> `()`
- [x] Try to annotate local variables if they're un-annotated: `let x = ...` -> `let x: () = ...`
- [x] Try to annotate the self type of a `Trait::method()` -> `<() as Trait>::method()`.

The only other case we may want to suggest is a missing turbofish, like `f()` -> `f::<()>()`. That may be possible, but seems overly annoying.

This partly addresses rust-lang#132358; the other half of fixing that would be to make the error message a bit better, perhaps just special casing the `?` operator 🤔 I don't think I'll do that part.
  • Loading branch information
jieyouxu authored Nov 1, 2024
2 parents 6f82947 + b4248ae commit 3806a9f
Show file tree
Hide file tree
Showing 11 changed files with 370 additions and 24 deletions.
83 changes: 78 additions & 5 deletions compiler/rustc_hir_typeck/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,19 +169,34 @@ pub(crate) struct MissingParenthesesInRange {
pub(crate) enum NeverTypeFallbackFlowingIntoUnsafe {
#[help]
#[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_call)]
Call,
Call {
#[subdiagnostic]
sugg: SuggestAnnotations,
},
#[help]
#[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_method)]
Method,
Method {
#[subdiagnostic]
sugg: SuggestAnnotations,
},
#[help]
#[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_path)]
Path,
Path {
#[subdiagnostic]
sugg: SuggestAnnotations,
},
#[help]
#[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_union_field)]
UnionField,
UnionField {
#[subdiagnostic]
sugg: SuggestAnnotations,
},
#[help]
#[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_deref)]
Deref,
Deref {
#[subdiagnostic]
sugg: SuggestAnnotations,
},
}

#[derive(LintDiagnostic)]
Expand All @@ -191,6 +206,64 @@ pub(crate) struct DependencyOnUnitNeverTypeFallback<'tcx> {
#[note]
pub obligation_span: Span,
pub obligation: ty::Predicate<'tcx>,
#[subdiagnostic]
pub sugg: SuggestAnnotations,
}

#[derive(Clone)]
pub(crate) enum SuggestAnnotation {
Unit(Span),
Path(Span),
Local(Span),
Turbo(Span, usize, usize),
}

#[derive(Clone)]
pub(crate) struct SuggestAnnotations {
pub suggestions: Vec<SuggestAnnotation>,
}
impl Subdiagnostic for SuggestAnnotations {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
self,
diag: &mut Diag<'_, G>,
_: &F,
) {
if self.suggestions.is_empty() {
return;
}

let mut suggestions = vec![];
for suggestion in self.suggestions {
match suggestion {
SuggestAnnotation::Unit(span) => {
suggestions.push((span, "()".to_string()));
}
SuggestAnnotation::Path(span) => {
suggestions.push((span.shrink_to_lo(), "<() as ".to_string()));
suggestions.push((span.shrink_to_hi(), ">".to_string()));
}
SuggestAnnotation::Local(span) => {
suggestions.push((span, ": ()".to_string()));
}
SuggestAnnotation::Turbo(span, n_args, idx) => suggestions.push((
span,
format!(
"::<{}>",
(0..n_args)
.map(|i| if i == idx { "()" } else { "_" })
.collect::<Vec<_>>()
.join(", "),
),
)),
}
}

diag.multipart_suggestion_verbose(
"use `()` annotations to avoid fallback changes",
suggestions,
Applicability::MachineApplicable,
);
}
}

#[derive(Subdiagnostic)]
Expand Down
Loading

0 comments on commit 3806a9f

Please sign in to comment.