mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Suggest adding self type to method
This commit is contained in:
parent
41966e71bc
commit
ea4fb7c25c
@ -210,9 +210,15 @@ pub(crate) struct DependencyOnUnitNeverTypeFallback<'tcx> {
|
|||||||
pub sugg: SuggestAnnotations,
|
pub sugg: SuggestAnnotations,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub(crate) enum SuggestAnnotation {
|
||||||
|
Unit(Span),
|
||||||
|
Path(Span),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct SuggestAnnotations {
|
pub(crate) struct SuggestAnnotations {
|
||||||
pub suggestion_spans: Vec<Span>,
|
pub suggestions: Vec<SuggestAnnotation>,
|
||||||
}
|
}
|
||||||
impl Subdiagnostic for SuggestAnnotations {
|
impl Subdiagnostic for SuggestAnnotations {
|
||||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||||
@ -220,13 +226,26 @@ impl Subdiagnostic for SuggestAnnotations {
|
|||||||
diag: &mut Diag<'_, G>,
|
diag: &mut Diag<'_, G>,
|
||||||
_: &F,
|
_: &F,
|
||||||
) {
|
) {
|
||||||
if self.suggestion_spans.is_empty() {
|
if self.suggestions.is_empty() {
|
||||||
return;
|
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()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
diag.multipart_suggestion_verbose(
|
diag.multipart_suggestion_verbose(
|
||||||
"use `()` annotations to avoid fallback changes",
|
"use `()` annotations to avoid fallback changes",
|
||||||
self.suggestion_spans.into_iter().map(|span| (span, String::from("()"))).collect(),
|
suggestions,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ use rustc_data_structures::graph::{self};
|
|||||||
use rustc_data_structures::unord::{UnordBag, UnordMap, UnordSet};
|
use rustc_data_structures::unord::{UnordBag, UnordMap, UnordSet};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::HirId;
|
use rustc_hir::HirId;
|
||||||
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::intravisit::Visitor;
|
use rustc_hir::intravisit::Visitor;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
|
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
|
||||||
use rustc_session::lint;
|
use rustc_session::lint;
|
||||||
@ -573,7 +574,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
|||||||
// For each diverging var, look through the HIR for a place to give it
|
// For each diverging var, look through the HIR for a place to give it
|
||||||
// a type annotation. We do this per var because we only really need one
|
// a type annotation. We do this per var because we only really need one
|
||||||
// per var.
|
// per var.
|
||||||
let suggestion_spans = diverging_vids
|
let suggestions = diverging_vids
|
||||||
.iter()
|
.iter()
|
||||||
.copied()
|
.copied()
|
||||||
.filter_map(|vid| {
|
.filter_map(|vid| {
|
||||||
@ -582,16 +583,17 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
|||||||
VidVisitor { reachable_vids, fcx: self }.visit_expr(body.value).break_value()
|
VidVisitor { reachable_vids, fcx: self }.visit_expr(body.value).break_value()
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
errors::SuggestAnnotations { suggestion_spans }
|
errors::SuggestAnnotations { suggestions }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Try to collect a useful suggestion to preserve fallback to `()`.
|
||||||
struct VidVisitor<'a, 'tcx> {
|
struct VidVisitor<'a, 'tcx> {
|
||||||
reachable_vids: FxHashSet<ty::TyVid>,
|
reachable_vids: FxHashSet<ty::TyVid>,
|
||||||
fcx: &'a FnCtxt<'a, 'tcx>,
|
fcx: &'a FnCtxt<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
impl<'tcx> Visitor<'tcx> for VidVisitor<'_, 'tcx> {
|
impl<'tcx> Visitor<'tcx> for VidVisitor<'_, 'tcx> {
|
||||||
type Result = ControlFlow<Span>;
|
type Result = ControlFlow<errors::SuggestAnnotation>;
|
||||||
|
|
||||||
fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) -> Self::Result {
|
fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) -> Self::Result {
|
||||||
if let hir::TyKind::Infer = hir_ty.kind
|
if let hir::TyKind::Infer = hir_ty.kind
|
||||||
@ -599,10 +601,25 @@ impl<'tcx> Visitor<'tcx> for VidVisitor<'_, 'tcx> {
|
|||||||
&& let Some(vid) = self.fcx.root_vid(ty)
|
&& let Some(vid) = self.fcx.root_vid(ty)
|
||||||
&& self.reachable_vids.contains(&vid)
|
&& self.reachable_vids.contains(&vid)
|
||||||
{
|
{
|
||||||
return ControlFlow::Break(hir_ty.span);
|
return ControlFlow::Break(errors::SuggestAnnotation::Unit(hir_ty.span));
|
||||||
}
|
}
|
||||||
hir::intravisit::walk_ty(self, hir_ty)
|
hir::intravisit::walk_ty(self, hir_ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Self::Result {
|
||||||
|
if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
|
||||||
|
&& let Res::Def(DefKind::AssocFn, def_id) = path.res
|
||||||
|
&& self.fcx.tcx.trait_of_item(def_id).is_some()
|
||||||
|
&& let self_ty = self.fcx.typeck_results.borrow().node_args(expr.hir_id).type_at(0)
|
||||||
|
&& let Some(vid) = self.fcx.root_vid(self_ty)
|
||||||
|
&& self.reachable_vids.contains(&vid)
|
||||||
|
&& let [.., trait_segment, _method_segment] = path.segments
|
||||||
|
{
|
||||||
|
let span = path.span.shrink_to_lo().to(trait_segment.ident.span);
|
||||||
|
return ControlFlow::Break(errors::SuggestAnnotation::Path(span));
|
||||||
|
}
|
||||||
|
hir::intravisit::walk_expr(self, expr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
@ -13,6 +13,10 @@ note: in edition 2024, the requirement `!: Default` will fail
|
|||||||
LL | true => Default::default(),
|
LL | true => Default::default(),
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
= note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
|
= note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
|
||||||
|
help: use `()` annotations to avoid fallback changes
|
||||||
|
|
|
||||||
|
LL | true => <() as Default>::default(),
|
||||||
|
| ++++++ +
|
||||||
|
|
||||||
warning: this function depends on never type fallback being `()`
|
warning: this function depends on never type fallback being `()`
|
||||||
--> $DIR/never-type-fallback-breaking.rs:27:1
|
--> $DIR/never-type-fallback-breaking.rs:27:1
|
||||||
|
@ -13,6 +13,10 @@ note: in edition 2024, the requirement `!: UnitDefault` will fail
|
|||||||
LL | x = UnitDefault::default();
|
LL | x = UnitDefault::default();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
|
= note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
|
||||||
|
help: use `()` annotations to avoid fallback changes
|
||||||
|
|
|
||||||
|
LL | x = <() as UnitDefault>::default();
|
||||||
|
| ++++++ +
|
||||||
|
|
||||||
warning: this function depends on never type fallback being `()`
|
warning: this function depends on never type fallback being `()`
|
||||||
--> $DIR/diverging-fallback-control-flow.rs:42:1
|
--> $DIR/diverging-fallback-control-flow.rs:42:1
|
||||||
@ -28,6 +32,10 @@ note: in edition 2024, the requirement `!: UnitDefault` will fail
|
|||||||
|
|
|
|
||||||
LL | x = UnitDefault::default();
|
LL | x = UnitDefault::default();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
help: use `()` annotations to avoid fallback changes
|
||||||
|
|
|
||||||
|
LL | x = <() as UnitDefault>::default();
|
||||||
|
| ++++++ +
|
||||||
|
|
||||||
warning: 2 warnings emitted
|
warning: 2 warnings emitted
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user