diff --git a/Cargo.lock b/Cargo.lock index 5d05a09f038..dbff82cf536 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4070,6 +4070,7 @@ dependencies = [ "rustc_hir", "rustc_index", "rustc_infer", + "rustc_macros", "rustc_middle", "rustc_serialize", "rustc_session", diff --git a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl new file mode 100644 index 00000000000..b5bd2eb21a8 --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl @@ -0,0 +1,5 @@ +mir_build_unconditional_recursion = function cannot return without recursing + .label = cannot return without recursing + .help = a `loop` may express intention better if this is on purpose + +mir_build_unconditional_recursion_call_site_label = recursive call site diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 418ba3c74d7..db62643bc24 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -58,6 +58,7 @@ fluent_messages! { metadata => "../locales/en-US/metadata.ftl", middle => "../locales/en-US/middle.ftl", mir_dataflow => "../locales/en-US/mir_dataflow.ftl", + mir_build => "../locales/en-US/mir_build.ftl", monomorphize => "../locales/en-US/monomorphize.ftl", parse => "../locales/en-US/parse.ftl", passes => "../locales/en-US/passes.ftl", diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml index 2baa3bfcb64..4ad3343d303 100644 --- a/compiler/rustc_mir_build/Cargo.toml +++ b/compiler/rustc_mir_build/Cargo.toml @@ -17,6 +17,7 @@ rustc_index = { path = "../rustc_index" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } rustc_infer = { path = "../rustc_infer" } +rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs new file mode 100644 index 00000000000..1d44db7eb3a --- /dev/null +++ b/compiler/rustc_mir_build/src/errors.rs @@ -0,0 +1,13 @@ +use rustc_macros::LintDiagnostic; +use rustc_span::Span; + +#[derive(LintDiagnostic)] +#[lint(mir_build::unconditional_recursion)] +#[help] +pub struct UnconditionalRecursion { + #[primary_span] + #[label] + pub span: Span, + #[label(mir_build::unconditional_recursion_call_site_label)] + pub call_sites: Vec, +} diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index 87975294595..2b05e92fdcf 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -19,6 +19,7 @@ extern crate rustc_middle; mod build; mod check_unsafety; +mod errors; mod lints; pub mod thir; diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index b21f30efce8..383598fb094 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -1,3 +1,4 @@ +use crate::errors::UnconditionalRecursion; use rustc_data_structures::graph::iterate::{ NodeStatus, TriColorDepthFirstSearch, TriColorVisitor, }; @@ -36,20 +37,10 @@ pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let sp = tcx.def_span(def_id); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - tcx.struct_span_lint_hir( - UNCONDITIONAL_RECURSION, - hir_id, - sp, - "function cannot return without recursing", - |lint| { - lint.span_label(sp, "cannot return without recursing"); - // offer some help to the programmer. - for call_span in vis.reachable_recursive_calls { - lint.span_label(call_span, "recursive call site"); - } - lint.help("a `loop` may express intention better if this is on purpose") - }, - ); + tcx.emit_spanned_lint(UNCONDITIONAL_RECURSION, hir_id, sp, UnconditionalRecursion { + span: sp, + call_sites: vis.reachable_recursive_calls, + }); } }