Skip to content

Commit f6e4461

Browse files
committed
add check and note for recursive default impl
1 parent 096277e commit f6e4461

File tree

4 files changed

+39
-14
lines changed

4 files changed

+39
-14
lines changed

compiler/rustc_mir_build/messages.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@ mir_build_pointer_pattern = function pointers and raw pointers not derived from
265265
266266
mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
267267
268+
mir_build_recursive_default_impl = ..default() in the Default impl does not apply a default for each struct field
269+
268270
mir_build_rust_2024_incompatible_pat = patterns are not allowed to reset the default binding mode in edition 2024
269271
270272
mir_build_rustc_box_attribute_error = `#[rustc_box]` attribute used incorrectly

compiler/rustc_mir_build/src/errors.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,16 @@ use crate::fluent_generated as fluent;
1818
pub(crate) struct UnconditionalRecursion {
1919
#[label]
2020
pub(crate) span: Span,
21+
#[subdiagnostic]
22+
pub(crate) default_impl_note: Option<RecursiveDefaultImpl>,
2123
#[label(mir_build_unconditional_recursion_call_site_label)]
2224
pub(crate) call_sites: Vec<Span>,
2325
}
2426

27+
#[derive(Subdiagnostic)]
28+
#[help(mir_build_recursive_default_impl)]
29+
pub(crate) struct RecursiveDefaultImpl {}
30+
2531
#[derive(LintDiagnostic)]
2632
#[diag(mir_build_call_to_deprecated_safe_fn_requires_unsafe)]
2733
pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafe {

compiler/rustc_mir_build/src/lints.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_middle::ty::{self, GenericArg, GenericArgs, Instance, Ty, TyCtxt};
99
use rustc_session::lint::builtin::UNCONDITIONAL_RECURSION;
1010
use rustc_span::Span;
1111

12-
use crate::errors::UnconditionalRecursion;
12+
use crate::errors::{RecursiveDefaultImpl, UnconditionalRecursion};
1313

1414
pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
1515
check_call_recursion(tcx, body);
@@ -31,6 +31,20 @@ fn check_call_recursion<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
3131
check_recursion(tcx, body, CallRecursion { trait_args })
3232
}
3333
}
34+
use rustc_span::def_id::LocalDefId;
35+
use rustc_span::sym;
36+
fn is_default_impl<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
37+
if tcx.def_kind(def_id) == DefKind::AssocFn {
38+
// Check if this is a trait impl and get the defid of the trait if it is
39+
if let Some(trait_def_id) = tcx.trait_id_of_impl(tcx.parent(def_id.into())) {
40+
// check if it is a default impl
41+
if tcx.get_diagnostic_name(trait_def_id) == Some(sym::Default) {
42+
return true;
43+
}
44+
}
45+
}
46+
false
47+
}
3448

3549
fn check_recursion<'tcx>(
3650
tcx: TyCtxt<'tcx>,
@@ -54,9 +68,12 @@ fn check_recursion<'tcx>(
5468

5569
let sp = tcx.def_span(def_id);
5670
let hir_id = tcx.local_def_id_to_hir_id(def_id);
71+
let default_impl_note =
72+
{ if is_default_impl(tcx, def_id) { Some(RecursiveDefaultImpl {}) } else { None } };
5773
tcx.emit_node_span_lint(UNCONDITIONAL_RECURSION, hir_id, sp, UnconditionalRecursion {
5874
span: sp,
5975
call_sites: vis.reachable_recursive_calls,
76+
default_impl_note,
6077
});
6178
}
6279
}

tests/ui/lint/lint-unconditional-recursion.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -177,18 +177,18 @@ pub fn overflow_check(a: i32, b: i32) { //~ ERROR function cannot return without
177177
overflow_check(a, b);
178178
}
179179

180-
pub struct Point {
181-
pub x: f32,
182-
pub y: f32,
183-
}
184-
185-
impl Default for Point {
186-
fn default() -> Self { //~ ERROR function cannot return without recursing
187-
Point {
188-
x: Default::default(),
189-
..Default::default()
190-
}
191-
}
192-
}
180+
// pub struct Point {
181+
// pub x: f32,
182+
// pub y: f32,
183+
// }
184+
//
185+
// impl Default for Point {
186+
// fn default() -> Self { //~ ERROR function cannot return without recursing
187+
// Point {
188+
// x: Default::default(),
189+
// ..Default::default()
190+
// }
191+
// }
192+
// }
193193

194194
fn main() {}

0 commit comments

Comments
 (0)