From 82f05446a549b42af2ae544da05bb5503c3bd8ec Mon Sep 17 00:00:00 2001 From: TheOddGarlic Date: Sat, 20 Aug 2022 14:28:43 +0300 Subject: [PATCH 01/18] Migrate "function cannot return without recursing" diagnostic --- Cargo.lock | 1 + .../locales/en-US/mir_build.ftl | 5 +++++ compiler/rustc_error_messages/src/lib.rs | 1 + compiler/rustc_mir_build/Cargo.toml | 1 + compiler/rustc_mir_build/src/errors.rs | 13 +++++++++++++ compiler/rustc_mir_build/src/lib.rs | 1 + compiler/rustc_mir_build/src/lints.rs | 19 +++++-------------- 7 files changed, 27 insertions(+), 14 deletions(-) create mode 100644 compiler/rustc_error_messages/locales/en-US/mir_build.ftl create mode 100644 compiler/rustc_mir_build/src/errors.rs diff --git a/Cargo.lock b/Cargo.lock index 5d05a09f03893..dbff82cf53608 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 0000000000000..b5bd2eb21a8ad --- /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 418ba3c74d776..db62643bc24ac 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 2baa3bfcb6401..4ad3343d3031b 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 0000000000000..1d44db7eb3a7d --- /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 8797529459534..2b05e92fdcf20 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 b21f30efce807..383598fb094b6 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, + }); } } From 71fe52fed02f2555ee6d0e7631d250d53a1a9cae Mon Sep 17 00:00:00 2001 From: TheOddGarlic Date: Sat, 20 Aug 2022 23:54:58 +0300 Subject: [PATCH 02/18] Migrate "unsafe_op_in_unsafe_fn" lints --- .../locales/en-US/mir_build.ftl | 56 +++++++++++ .../rustc_mir_build/src/check_unsafety.rs | 92 +++++++++++++++++-- compiler/rustc_mir_build/src/errors.rs | 92 ++++++++++++++++++- compiler/rustc_mir_build/src/lints.rs | 10 +- 4 files changed, 236 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl index b5bd2eb21a8ad..2dfc4984786b9 100644 --- a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl +++ b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl @@ -3,3 +3,59 @@ mir_build_unconditional_recursion = function 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 + +mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe = + call to unsafe function `{$function}` is unsafe and requires unsafe block (error E0133) + .note = consult the function's documentation for information on how to avoid undefined behavior + .label = call to unsafe function + +mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless = + call to unsafe function is unsafe and requires unsafe block (error E0133) + .note = consult the function's documentation for information on how to avoid undefined behavior + .label = call to unsafe function + +mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe = + use of inline assembly is unsafe and requires unsafe block (error E0133) + .note = inline assembly is entirely unchecked and can cause undefined behavior + .label = use of inline assembly + +mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe = + initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe + block (error E0133) + .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior + .label = initializing type with `rustc_layout_scalar_valid_range` attr + +mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe = + use of mutable static is unsafe and requires unsafe block (error E0133) + .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + .label = use of mutable static + +mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe = + use of extern static is unsafe and requires unsafe block (error E0133) + .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + .label = use of extern static + +mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe = + dereference of raw pointer is unsafe and requires unsafe block (error E0133) + .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + .label = dereference of raw pointer + +mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe = + access to union field is unsafe and requires unsafe block (error E0133) + .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior + .label = access to union field + +mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe = + mutation of layout constrained field is unsafe and requires unsafe block (error E0133) + .note = mutating layout constrained fields cannot statically be checked for valid values + .label = mutation of layout constrained field + +mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe = + borrow of layout constrained field with interior mutability is unsafe and requires unsafe block (error E0133) + .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values + .label = borrow of layout constrained field with interior mutability + +mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe = + call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block (error E0133) + .note = can only be called if the required target features are available + .label = call to function with `#[target_feature]` diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 3bb1f51650abd..afdd862e5c7ca 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -1,4 +1,5 @@ use crate::build::ExprCategory; +use crate::errors::*; use rustc_middle::thir::visit::{self, Visitor}; use rustc_errors::struct_span_err; @@ -83,15 +84,8 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { } SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {} SafetyContext::UnsafeFn => { - let (description, note) = kind.description_and_note(self.tcx); // unsafe_op_in_unsafe_fn is disallowed - self.tcx.struct_span_lint_hir( - UNSAFE_OP_IN_UNSAFE_FN, - self.hir_context, - span, - format!("{} is unsafe and requires unsafe block (error E0133)", description,), - |lint| lint.span_label(span, kind.simple_description()).note(note), - ) + kind.emit_unsafe_op_in_unsafe_fn_lint(self.tcx, self.hir_context, span); } SafetyContext::Safe => { let (description, note) = kind.description_and_note(self.tcx); @@ -536,6 +530,88 @@ enum UnsafeOpKind { use UnsafeOpKind::*; impl UnsafeOpKind { + pub fn emit_unsafe_op_in_unsafe_fn_lint( + &self, + tcx: TyCtxt<'_>, + hir_id: hir::HirId, + span: Span, + ) { + match self { + CallToUnsafeFunction(did) if did.is_some() => tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe { + span, + function: &tcx.def_path_str(did.unwrap()), + }, + ), + CallToUnsafeFunction(..) => tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { span }, + ), + UseOfInlineAssembly => tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeUseOfInlineAssemblyRequiresUnsafe { span }, + ), + InitializingTypeWith => tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeInitializingTypeWithRequiresUnsafe { span }, + ), + UseOfMutableStatic => tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeUseOfMutableStaticRequiresUnsafe { span }, + ), + UseOfExternStatic => tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeUseOfExternStaticRequiresUnsafe { span }, + ), + DerefOfRawPointer => tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeDerefOfRawPointerRequiresUnsafe { span }, + ), + AccessToUnionField => tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeAccessToUnionFieldRequiresUnsafe { span }, + ), + MutationOfLayoutConstrainedField => tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeMutationOfLayoutConstrainedFieldRequiresUnsafe { span }, + ), + BorrowOfLayoutConstrainedField => tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeBorrowOfLayoutConstrainedFieldRequiresUnsafe { span }, + ), + CallToFunctionWith(did) => tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeCallToFunctionWithRequiresUnsafe { + span, + function: &tcx.def_path_str(*did), + }, + ), + } + } + pub fn simple_description(&self) -> &'static str { match self { CallToUnsafeFunction(..) => "call to unsafe function", diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 1d44db7eb3a7d..61131c0d733cd 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -2,12 +2,100 @@ use rustc_macros::LintDiagnostic; use rustc_span::Span; #[derive(LintDiagnostic)] -#[lint(mir_build::unconditional_recursion)] +#[diag(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, } + +#[derive(LintDiagnostic)] +#[diag(mir_build::unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe)] +#[note] +pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe<'a> { + #[label] + pub span: Span, + pub function: &'a str, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build::unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless)] +#[note] +pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build::unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe)] +#[note] +pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build::unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe)] +#[note] +pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build::unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe)] +#[note] +pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build::unsafe_op_in_unsafe_fn_extern_static_requires_unsafe)] +#[note] +pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build::unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe)] +#[note] +pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build::unsafe_op_in_unsafe_fn_union_field_requires_unsafe)] +#[note] +pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build::unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe)] +#[note] +pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build::unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe)] +pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build::unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe)] +#[note] +pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> { + #[label] + pub span: Span, + pub function: &'a str, +} diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index 383598fb094b6..8529c64cd5cca 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -37,10 +37,12 @@ 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.emit_spanned_lint(UNCONDITIONAL_RECURSION, hir_id, sp, UnconditionalRecursion { - span: sp, - call_sites: vis.reachable_recursive_calls, - }); + tcx.emit_spanned_lint( + UNCONDITIONAL_RECURSION, + hir_id, + sp, + UnconditionalRecursion { span: sp, call_sites: vis.reachable_recursive_calls }, + ); } } From 64f3e4f195265a13648e5e201669ebb265bae421 Mon Sep 17 00:00:00 2001 From: TheOddGarlic Date: Wed, 24 Aug 2022 11:01:53 +0300 Subject: [PATCH 03/18] Migrate "requires unsafe" diagnostics --- .../locales/en-US/mir_build.ftl | 110 +++++++++ .../rustc_mir_build/src/check_unsafety.rs | 200 ++++++++-------- compiler/rustc_mir_build/src/errors.rs | 216 +++++++++++++++++- 3 files changed, 431 insertions(+), 95 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl index 2dfc4984786b9..fd42cc6cb0876 100644 --- a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl +++ b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl @@ -59,3 +59,113 @@ mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe = call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block (error E0133) .note = can only be called if the required target features are available .label = call to function with `#[target_feature]` + +mir_build_call_to_unsafe_fn_requires_unsafe = + call to unsafe function `{$function}` is unsafe and requires unsafe block + .note = consult the function's documentation for information on how to avoid undefined behavior + .label = call to unsafe function + +mir_build_call_to_unsafe_fn_requires_unsafe_nameless = + call to unsafe function is unsafe and requires unsafe block + .note = consult the function's documentation for information on how to avoid undefined behavior + .label = call to unsafe function + +mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + call to unsafe function `{$function}` is unsafe and requires unsafe function or block + .note = consult the function's documentation for information on how to avoid undefined behavior + .label = call to unsafe function + +mir_build_call_to_unsafe_fn_requires_unsafe_nameless_unsafe_op_in_unsafe_fn_allowed = + call to unsafe function is unsafe and requires unsafe function or block + .note = consult the function's documentation for information on how to avoid undefined behavior + .label = call to unsafe function + +mir_build_inline_assembly_requires_unsafe = + use of inline assembly is unsafe and requires unsafe block + .note = inline assembly is entirely unchecked and can cause undefined behavior + .label = use of inline assembly + +mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + use of inline assembly is unsafe and requires unsafe function or block + .note = inline assembly is entirely unchecked and can cause undefined behavior + .label = use of inline assembly + +mir_build_initializing_type_with_requires_unsafe = + initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe block + .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior + .label = initializing type with `rustc_layout_scalar_valid_range` attr + +mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block + .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior + .label = initializing type with `rustc_layout_scalar_valid_range` attr + +mir_build_mutable_static_requires_unsafe = + use of mutable static is unsafe and requires unsafe block + .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + .label = use of mutable static + +mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + use of mutable static is unsafe and requires unsafe function or block + .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + .label = use of mutable static + +mir_build_extern_static_requires_unsafe = + use of extern static is unsafe and requires unsafe block + .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + .label = use of extern static + +mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + use of extern static is unsafe and requires unsafe function or block + .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + .label = use of extern static + +mir_build_deref_raw_pointer_requires_unsafe = + dereference of raw pointer is unsafe and requires unsafe block + .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + .label = dereference of raw pointer + +mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + dereference of raw pointer is unsafe and requires unsafe function or block + .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + .label = dereference of raw pointer + +mir_build_union_field_requires_unsafe = + access to union field is unsafe and requires unsafe block + .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior + .label = access to union field + +mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + access to union field is unsafe and requires unsafe function or block + .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior + .label = access to union field + +mir_build_mutation_of_layout_constrained_field_requires_unsafe = + mutation of layout constrained field is unsafe and requires unsafe block + .note = mutating layout constrained fields cannot statically be checked for valid values + .label = mutation of layout constrained field + +mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + mutation of layout constrained field is unsafe and requires unsafe function or block + .note = mutating layout constrained fields cannot statically be checked for valid values + .label = mutation of layout constrained field + +mir_build_borrow_of_layout_constrained_field_requires_unsafe = + borrow of layout constrained field with interior mutability is unsafe and requires unsafe block + .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values + .label = borrow of layout constrained field with interior mutability + +mir_build_borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block + .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values + .label = borrow of layout constrained field with interior mutability + +mir_build_call_to_fn_with_requires_unsafe = + call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block + .note = can only be called if the required target features are available + .label = call to function with `#[target_feature]` + +mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe function or block + .note = can only be called if the required target features are available + .label = call to function with `#[target_feature]` diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index afdd862e5c7ca..e57b8a7b4ce81 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -2,7 +2,6 @@ use crate::build::ExprCategory; use crate::errors::*; use rustc_middle::thir::visit::{self, Visitor}; -use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_middle::mir::BorrowKind; use rustc_middle::thir::*; @@ -13,7 +12,6 @@ use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::symbol::Symbol; use rustc_span::Span; -use std::borrow::Cow; use std::ops::Bound; struct UnsafetyVisitor<'a, 'tcx> { @@ -88,19 +86,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { kind.emit_unsafe_op_in_unsafe_fn_lint(self.tcx, self.hir_context, span); } SafetyContext::Safe => { - let (description, note) = kind.description_and_note(self.tcx); - let fn_sugg = if unsafe_op_in_unsafe_fn_allowed { " function or" } else { "" }; - struct_span_err!( - self.tcx.sess, - span, - E0133, - "{} is unsafe and requires unsafe{} block", - description, - fn_sugg, - ) - .span_label(span, kind.simple_description()) - .note(note) - .emit(); + kind.emit_requires_unsafe_err(self.tcx, span, unsafe_op_in_unsafe_fn_allowed); } } } @@ -556,55 +542,55 @@ impl UnsafeOpKind { UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeUseOfInlineAssemblyRequiresUnsafe { span }, + UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { span }, ), InitializingTypeWith => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeInitializingTypeWithRequiresUnsafe { span }, + UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { span }, ), UseOfMutableStatic => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeUseOfMutableStaticRequiresUnsafe { span }, + UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { span }, ), UseOfExternStatic => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeUseOfExternStaticRequiresUnsafe { span }, + UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { span }, ), DerefOfRawPointer => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeDerefOfRawPointerRequiresUnsafe { span }, + UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { span }, ), AccessToUnionField => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeAccessToUnionFieldRequiresUnsafe { span }, + UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { span }, ), MutationOfLayoutConstrainedField => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeMutationOfLayoutConstrainedFieldRequiresUnsafe { span }, + UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { span }, ), BorrowOfLayoutConstrainedField => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeBorrowOfLayoutConstrainedFieldRequiresUnsafe { span }, + UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { span }, ), CallToFunctionWith(did) => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeCallToFunctionWithRequiresUnsafe { + UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe { span, function: &tcx.def_path_str(*did), }, @@ -612,79 +598,105 @@ impl UnsafeOpKind { } } - pub fn simple_description(&self) -> &'static str { + pub fn emit_requires_unsafe_err( + &self, + tcx: TyCtxt<'_>, + span: Span, + unsafe_op_in_unsafe_fn_allowed: bool, + ) { match self { - CallToUnsafeFunction(..) => "call to unsafe function", - UseOfInlineAssembly => "use of inline assembly", - InitializingTypeWith => "initializing type with `rustc_layout_scalar_valid_range` attr", - UseOfMutableStatic => "use of mutable static", - UseOfExternStatic => "use of extern static", - DerefOfRawPointer => "dereference of raw pointer", - AccessToUnionField => "access to union field", - MutationOfLayoutConstrainedField => "mutation of layout constrained field", + CallToUnsafeFunction(did) if did.is_some() && unsafe_op_in_unsafe_fn_allowed => { + tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + function: &tcx.def_path_str(did.unwrap()), + }); + } + CallToUnsafeFunction(did) if did.is_some() => { + tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafe { + span, + function: &tcx.def_path_str(did.unwrap()), + }); + } + CallToUnsafeFunction(..) if unsafe_op_in_unsafe_fn_allowed => { + tcx.sess.emit_err( + CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { span }, + ); + } + CallToUnsafeFunction(..) => { + tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafeNameless { span }); + } + UseOfInlineAssembly if unsafe_op_in_unsafe_fn_allowed => { + tcx.sess + .emit_err(UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + } + UseOfInlineAssembly => { + tcx.sess.emit_err(UseOfInlineAssemblyRequiresUnsafe { span }); + } + InitializingTypeWith if unsafe_op_in_unsafe_fn_allowed => { + tcx.sess + .emit_err(InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + } + InitializingTypeWith => { + tcx.sess.emit_err(InitializingTypeWithRequiresUnsafe { span }); + } + UseOfMutableStatic if unsafe_op_in_unsafe_fn_allowed => { + tcx.sess + .emit_err(UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + } + UseOfMutableStatic => { + tcx.sess.emit_err(UseOfMutableStaticRequiresUnsafe { span }); + } + UseOfExternStatic if unsafe_op_in_unsafe_fn_allowed => { + tcx.sess + .emit_err(UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + } + UseOfExternStatic => { + tcx.sess.emit_err(UseOfExternStaticRequiresUnsafe { span }); + } + DerefOfRawPointer if unsafe_op_in_unsafe_fn_allowed => { + tcx.sess + .emit_err(DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + } + DerefOfRawPointer => { + tcx.sess.emit_err(DerefOfRawPointerRequiresUnsafe { span }); + } + AccessToUnionField if unsafe_op_in_unsafe_fn_allowed => { + tcx.sess + .emit_err(AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + } + AccessToUnionField => { + tcx.sess.emit_err(AccessToUnionFieldRequiresUnsafe { span }); + } + MutationOfLayoutConstrainedField if unsafe_op_in_unsafe_fn_allowed => { + tcx.sess.emit_err( + MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + }, + ); + } + MutationOfLayoutConstrainedField => { + tcx.sess.emit_err(MutationOfLayoutConstrainedFieldRequiresUnsafe { span }); + } + BorrowOfLayoutConstrainedField if unsafe_op_in_unsafe_fn_allowed => { + tcx.sess.emit_err( + BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }, + ); + } BorrowOfLayoutConstrainedField => { - "borrow of layout constrained field with interior mutability" + tcx.sess.emit_err(BorrowOfLayoutConstrainedFieldRequiresUnsafe { span }); + } + CallToFunctionWith(did) if unsafe_op_in_unsafe_fn_allowed => { + tcx.sess.emit_err(CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + function: &tcx.def_path_str(*did), + }); + } + CallToFunctionWith(did) => { + tcx.sess.emit_err(CallToFunctionWithRequiresUnsafe { + span, + function: &tcx.def_path_str(*did), + }); } - CallToFunctionWith(..) => "call to function with `#[target_feature]`", - } - } - - pub fn description_and_note(&self, tcx: TyCtxt<'_>) -> (Cow<'static, str>, &'static str) { - match self { - CallToUnsafeFunction(did) => ( - if let Some(did) = did { - Cow::from(format!("call to unsafe function `{}`", tcx.def_path_str(*did))) - } else { - Cow::Borrowed(self.simple_description()) - }, - "consult the function's documentation for information on how to avoid undefined \ - behavior", - ), - UseOfInlineAssembly => ( - Cow::Borrowed(self.simple_description()), - "inline assembly is entirely unchecked and can cause undefined behavior", - ), - InitializingTypeWith => ( - Cow::Borrowed(self.simple_description()), - "initializing a layout restricted type's field with a value outside the valid \ - range is undefined behavior", - ), - UseOfMutableStatic => ( - Cow::Borrowed(self.simple_description()), - "mutable statics can be mutated by multiple threads: aliasing violations or data \ - races will cause undefined behavior", - ), - UseOfExternStatic => ( - Cow::Borrowed(self.simple_description()), - "extern statics are not controlled by the Rust type system: invalid data, \ - aliasing violations or data races will cause undefined behavior", - ), - DerefOfRawPointer => ( - Cow::Borrowed(self.simple_description()), - "raw pointers may be null, dangling or unaligned; they can violate aliasing rules \ - and cause data races: all of these are undefined behavior", - ), - AccessToUnionField => ( - Cow::Borrowed(self.simple_description()), - "the field may not be properly initialized: using uninitialized data will cause \ - undefined behavior", - ), - MutationOfLayoutConstrainedField => ( - Cow::Borrowed(self.simple_description()), - "mutating layout constrained fields cannot statically be checked for valid values", - ), - BorrowOfLayoutConstrainedField => ( - Cow::Borrowed(self.simple_description()), - "references to fields of layout constrained fields lose the constraints. Coupled \ - with interior mutability, the field can be changed to invalid values", - ), - CallToFunctionWith(did) => ( - Cow::from(format!( - "call to function `{}` with `#[target_feature]`", - tcx.def_path_str(*did) - )), - "can only be called if the required target features are available", - ), } } } diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 61131c0d733cd..260a9f6375bb9 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -1,4 +1,4 @@ -use rustc_macros::LintDiagnostic; +use rustc_macros::{LintDiagnostic, SessionDiagnostic}; use rustc_span::Span; #[derive(LintDiagnostic)] @@ -99,3 +99,217 @@ pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> { pub span: Span, pub function: &'a str, } + +#[derive(SessionDiagnostic)] +#[diag(mir_build::call_to_unsafe_fn_requires_unsafe, code = "E0133")] +#[note] +pub struct CallToUnsafeFunctionRequiresUnsafe<'a> { + #[primary_span] + #[label] + pub span: Span, + pub function: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(mir_build::call_to_unsafe_fn_requires_unsafe_nameless, code = "E0133")] +#[note] +pub struct CallToUnsafeFunctionRequiresUnsafeNameless { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(mir_build::call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[note] +pub struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> { + #[primary_span] + #[label] + pub span: Span, + pub function: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag( + mir_build::call_to_unsafe_fn_requires_unsafe_nameless_unsafe_op_in_unsafe_fn_allowed, + code = "E0133" +)] +#[note] +pub struct CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(mir_build::inline_assembly_requires_unsafe, code = "E0133")] +#[note] +pub struct UseOfInlineAssemblyRequiresUnsafe { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(mir_build::inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[note] +pub struct UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(mir_build::initializing_type_with_requires_unsafe, code = "E0133")] +#[note] +pub struct InitializingTypeWithRequiresUnsafe { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag( + mir_build::initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, + code = "E0133" +)] +#[note] +pub struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(mir_build::mutable_static_requires_unsafe, code = "E0133")] +#[note] +pub struct UseOfMutableStaticRequiresUnsafe { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(mir_build::mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[note] +pub struct UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(mir_build::extern_static_requires_unsafe, code = "E0133")] +#[note] +pub struct UseOfExternStaticRequiresUnsafe { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(mir_build::extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[note] +pub struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(mir_build::deref_raw_pointer_requires_unsafe, code = "E0133")] +#[note] +pub struct DerefOfRawPointerRequiresUnsafe { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(mir_build::deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[note] +pub struct DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(mir_build::union_field_requires_unsafe, code = "E0133")] +#[note] +pub struct AccessToUnionFieldRequiresUnsafe { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(mir_build::union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[note] +pub struct AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(mir_build::mutation_of_layout_constrained_field_requires_unsafe, code = "E0133")] +#[note] +pub struct MutationOfLayoutConstrainedFieldRequiresUnsafe { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag( + mir_build::mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, + code = "E0133" +)] +#[note] +pub struct MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(mir_build::borrow_of_layout_constrained_field_requires_unsafe, code = "E0133")] +#[note] +pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafe { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag( + mir_build::borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, + code = "E0133" +)] +#[note] +pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(mir_build::call_to_fn_with_requires_unsafe, code = "E0133")] +#[note] +pub struct CallToFunctionWithRequiresUnsafe<'a> { + #[primary_span] + #[label] + pub span: Span, + pub function: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(mir_build::call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[note] +pub struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> { + #[primary_span] + #[label] + pub span: Span, + pub function: &'a str, +} From 71a9cb9b7ebc1a4d56f8d837ea8b4b696fae9e89 Mon Sep 17 00:00:00 2001 From: TheOddGarlic Date: Wed, 24 Aug 2022 20:16:50 +0300 Subject: [PATCH 04/18] Migrate "unused unsafe" lint --- .../locales/en-US/mir_build.ftl | 6 +++++ .../rustc_mir_build/src/check_unsafety.rs | 24 ++++++++++-------- compiler/rustc_mir_build/src/errors.rs | 25 ++++++++++++++++++- 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl index fd42cc6cb0876..9dab6f8e88320 100644 --- a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl +++ b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl @@ -169,3 +169,9 @@ mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe function or block .note = can only be called if the required target features are available .label = call to function with `#[target_feature]` + +mir_build_unused_unsafe = unnecessary `unsafe` block + .label = unnecessary `unsafe` block + +mir_build_unused_unsafe_enclosing_block_label = because it's nested under this `unsafe` block +mir_build_unused_unsafe_enclosing_fn_label = because it's nested under this `unsafe` fn diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index e57b8a7b4ce81..99e96ff77ced9 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -45,7 +45,9 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { self.warn_unused_unsafe( hir_id, block_span, - Some((self.tcx.sess.source_map().guess_head_span(enclosing_span), "block")), + Some(UnusedUnsafeEnclosing::Block { + span: self.tcx.sess.source_map().guess_head_span(enclosing_span), + }), ); f(self); } else { @@ -59,7 +61,9 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { hir_id, span, if self.unsafe_op_in_unsafe_fn_allowed() { - self.body_unsafety.unsafe_fn_sig_span().map(|span| (span, "fn")) + self.body_unsafety + .unsafe_fn_sig_span() + .map(|span| UnusedUnsafeEnclosing::Function { span }) } else { None }, @@ -95,17 +99,15 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { &self, hir_id: hir::HirId, block_span: Span, - enclosing_unsafe: Option<(Span, &'static str)>, + enclosing_unsafe: Option, ) { let block_span = self.tcx.sess.source_map().guess_head_span(block_span); - let msg = "unnecessary `unsafe` block"; - self.tcx.struct_span_lint_hir(UNUSED_UNSAFE, hir_id, block_span, msg, |lint| { - lint.span_label(block_span, msg); - if let Some((span, kind)) = enclosing_unsafe { - lint.span_label(span, format!("because it's nested under this `unsafe` {}", kind)); - } - lint - }); + self.tcx.emit_spanned_lint( + UNUSED_UNSAFE, + hir_id, + block_span, + UnusedUnsafe { span: block_span, enclosing: enclosing_unsafe }, + ); } /// Whether the `unsafe_op_in_unsafe_fn` lint is `allow`ed at the current HIR node. diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 260a9f6375bb9..a3e8715122667 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -1,4 +1,4 @@ -use rustc_macros::{LintDiagnostic, SessionDiagnostic}; +use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic}; use rustc_span::Span; #[derive(LintDiagnostic)] @@ -313,3 +313,26 @@ pub struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> { pub span: Span, pub function: &'a str, } + +#[derive(LintDiagnostic)] +#[diag(mir_build::unused_unsafe)] +pub struct UnusedUnsafe { + #[label] + pub span: Span, + #[subdiagnostic] + pub enclosing: Option, +} + +#[derive(SessionSubdiagnostic)] +pub enum UnusedUnsafeEnclosing { + #[label(mir_build::unused_unsafe_enclosing_block_label)] + Block { + #[primary_span] + span: Span, + }, + #[label(mir_build::unused_unsafe_enclosing_fn_label)] + Function { + #[primary_span] + span: Span, + }, +} From c7bfd007194a0f4062a8809996b60f2700dd4652 Mon Sep 17 00:00:00 2001 From: TheOddGarlic Date: Fri, 26 Aug 2022 16:38:21 +0300 Subject: [PATCH 05/18] Migrate "non-exhaustive patterns: type is non-empty" diagnostic --- .../locales/en-US/mir_build.ftl | 8 ++ compiler/rustc_mir_build/src/errors.rs | 93 +++++++++++++++++++ .../src/thir/pattern/check_match.rs | 18 ++-- .../rustc_mir_build/src/thir/pattern/mod.rs | 1 + 4 files changed, 113 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl index 9dab6f8e88320..5fb89dcccaeeb 100644 --- a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl +++ b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl @@ -175,3 +175,11 @@ mir_build_unused_unsafe = unnecessary `unsafe` block mir_build_unused_unsafe_enclosing_block_label = because it's nested under this `unsafe` block mir_build_unused_unsafe_enclosing_fn_label = because it's nested under this `unsafe` fn + +mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type `{$ty}` is non-empty + .def_note = `{$peeled_ty}` defined here + .type_note = the matched value is of type `{$ty}` + .non_exhaustive_type_note = the matched value is of type `{$ty}`, which is marked as non-exhaustive + .reference_note = references are always considered inhabited + .suggestion = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + .help = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index a3e8715122667..9e63141d7160c 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -1,4 +1,8 @@ +use crate::thir::pattern::MatchCheckCtxt; +use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic}; +use rustc_middle::ty::{self, Ty}; +use rustc_session::{parse::ParseSess, SessionDiagnostic}; use rustc_span::Span; #[derive(LintDiagnostic)] @@ -336,3 +340,92 @@ pub enum UnusedUnsafeEnclosing { span: Span, }, } + +pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> { + pub cx: &'m MatchCheckCtxt<'p, 'tcx>, + pub expr_span: Span, + pub span: Span, + pub ty: Ty<'tcx>, +} + +impl<'a> SessionDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> { + fn into_diagnostic(self, sess: &'a ParseSess) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = sess.span_diagnostic.struct_span_err_with_code( + self.span, + rustc_errors::fluent::mir_build::non_exhaustive_patterns_type_not_empty, + error_code!(E0004), + ); + + let peeled_ty = self.ty.peel_refs(); + diag.set_arg("ty", self.ty); + diag.set_arg("peeled_ty", peeled_ty); + + if let ty::Adt(def, _) = peeled_ty.kind() { + let def_span = self + .cx + .tcx + .hir() + .get_if_local(def.did()) + .and_then(|node| node.ident()) + .map(|ident| ident.span) + .unwrap_or_else(|| self.cx.tcx.def_span(def.did())); + + // workaround to make test pass + let mut span: MultiSpan = def_span.into(); + span.push_span_label(def_span, ""); + + diag.span_note(span, rustc_errors::fluent::mir_build::def_note); + } + + let is_variant_list_non_exhaustive = match self.ty.kind() { + ty::Adt(def, _) if def.is_variant_list_non_exhaustive() && !def.did().is_local() => { + true + } + _ => false, + }; + + if is_variant_list_non_exhaustive { + diag.note(rustc_errors::fluent::mir_build::non_exhaustive_type_note); + } else { + diag.note(rustc_errors::fluent::mir_build::type_note); + } + + if let ty::Ref(_, sub_ty, _) = self.ty.kind() { + if self.cx.tcx.is_ty_uninhabited_from(self.cx.module, *sub_ty, self.cx.param_env) { + diag.note(rustc_errors::fluent::mir_build::reference_note); + } + } + + let mut suggestion = None; + let sm = self.cx.tcx.sess.source_map(); + if self.span.eq_ctxt(self.expr_span) { + // Get the span for the empty match body `{}`. + let (indentation, more) = if let Some(snippet) = sm.indentation_before(self.span) { + (format!("\n{}", snippet), " ") + } else { + (" ".to_string(), "") + }; + suggestion = Some(( + self.span.shrink_to_hi().with_hi(self.expr_span.hi()), + format!( + " {{{indentation}{more}_ => todo!(),{indentation}}}", + indentation = indentation, + more = more, + ), + )); + } + + if let Some((span, sugg)) = suggestion { + diag.span_suggestion_verbose( + span, + rustc_errors::fluent::mir_build::suggestion, + sugg, + Applicability::HasPlaceholders, + ); + } else { + diag.help(rustc_errors::fluent::mir_build::help); + } + + diag + } +} diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index e369dba55242c..c818a2a3a898c 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -4,6 +4,8 @@ use super::usefulness::{ }; use super::{PatCtxt, PatternError}; +use crate::errors::NonExhaustivePatternsTypeNotEmpty; + use rustc_arena::TypedArena; use rustc_ast::Mutability; use rustc_errors::{ @@ -760,15 +762,17 @@ fn non_exhaustive_match<'p, 'tcx>( // informative. let mut err; let pattern; - let mut patterns_len = 0; + let patterns_len; if is_empty_match && !non_empty_enum { - err = create_e0004( - cx.tcx.sess, - sp, - format!("non-exhaustive patterns: type `{}` is non-empty", scrut_ty), - ); - pattern = "_".to_string(); + cx.tcx.sess.emit_err(NonExhaustivePatternsTypeNotEmpty { + cx, + expr_span, + span: sp, + ty: scrut_ty, + }); + return; } else { + // FIXME: migration of this diagnostic will require list support let joined_patterns = joined_uncovered_patterns(cx, &witnesses); err = create_e0004( cx.tcx.sess, diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 48a231a6cd6b7..5aaf6c907e392 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -6,6 +6,7 @@ mod deconstruct_pat; mod usefulness; pub(crate) use self::check_match::check_match; +pub(crate) use self::usefulness::MatchCheckCtxt; use crate::thir::util::UserAnnotatedTyHelpers; From 98442b69055024c50c38bad11a18f71cc3858c84 Mon Sep 17 00:00:00 2001 From: TheOddGarlic Date: Fri, 26 Aug 2022 19:30:33 +0300 Subject: [PATCH 06/18] Migrate pattern inlining error diagnostics --- .../locales/en-US/mir_build.ftl | 8 ++++++ compiler/rustc_mir_build/src/errors.rs | 28 +++++++++++++++++++ .../src/thir/pattern/check_match.rs | 18 ++++-------- 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl index 5fb89dcccaeeb..610e16ab7d8e7 100644 --- a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl +++ b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl @@ -183,3 +183,11 @@ mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type .reference_note = references are always considered inhabited .suggestion = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown .help = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +mir_build_static_in_pattern = statics cannot be referenced in patterns + +mir_build_assoc_const_in_pattern = associated consts cannot be referenced in patterns + +mir_build_const_param_in_pattern = const parameters cannot be referenced in patterns + +mir_build_non_const_path = runtime values cannot be referenced in patterns diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 9e63141d7160c..ceaf057bb465b 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -429,3 +429,31 @@ impl<'a> SessionDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> diag } } + +#[derive(SessionDiagnostic)] +#[diag(mir_build::static_in_pattern, code = "E0158")] +pub struct StaticInPattern { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(mir_build::assoc_const_in_pattern, code = "E0158")] +pub struct AssocConstInPattern { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(mir_build::const_param_in_pattern, code = "E0158")] +pub struct ConstParamInPattern { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(mir_build::non_const_path, code = "E0080")] +pub struct NonConstPath { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index c818a2a3a898c..42c8787102914 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -4,7 +4,7 @@ use super::usefulness::{ }; use super::{PatCtxt, PatternError}; -use crate::errors::NonExhaustivePatternsTypeNotEmpty; +use crate::errors::*; use rustc_arena::TypedArena; use rustc_ast::Mutability; @@ -109,28 +109,20 @@ impl PatCtxt<'_, '_> { for error in &self.errors { match *error { PatternError::StaticInPattern(span) => { - self.span_e0158(span, "statics cannot be referenced in patterns") + self.tcx.sess.emit_err(StaticInPattern { span }); } PatternError::AssocConstInPattern(span) => { - self.span_e0158(span, "associated consts cannot be referenced in patterns") + self.tcx.sess.emit_err(AssocConstInPattern { span }); } PatternError::ConstParamInPattern(span) => { - self.span_e0158(span, "const parameters cannot be referenced in patterns") + self.tcx.sess.emit_err(ConstParamInPattern { span }); } PatternError::NonConstPath(span) => { - rustc_middle::mir::interpret::struct_error( - self.tcx.at(span), - "runtime values cannot be referenced in patterns", - ) - .emit(); + self.tcx.sess.emit_err(NonConstPath { span }); } } } } - - fn span_e0158(&self, span: Span, text: &str) { - struct_span_err!(self.tcx.sess, span, E0158, "{}", text).emit(); - } } impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { From b694e6649ef5883e36c1bbac0c9890db5dd96792 Mon Sep 17 00:00:00 2001 From: TheOddGarlic Date: Sat, 27 Aug 2022 22:06:06 +0300 Subject: [PATCH 07/18] Migrate unreachable pattern diagnostic --- .../locales/en-US/mir_build.ftl | 4 ++++ compiler/rustc_mir_build/src/errors.rs | 9 +++++++++ .../src/thir/pattern/check_match.rs | 14 ++++++-------- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl index 610e16ab7d8e7..8ff5c9b3fdebb 100644 --- a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl +++ b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl @@ -191,3 +191,7 @@ mir_build_assoc_const_in_pattern = associated consts cannot be referenced in pat mir_build_const_param_in_pattern = const parameters cannot be referenced in patterns mir_build_non_const_path = runtime values cannot be referenced in patterns + +mir_build_unreachable_pattern = unreachable pattern + .label = unreachable pattern + .catchall_label = matches any value diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index ceaf057bb465b..3049ebc5b037b 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -457,3 +457,12 @@ pub struct NonConstPath { #[primary_span] pub span: Span, } + +#[derive(LintDiagnostic)] +#[diag(mir_build::unreachable_pattern)] +pub struct UnreachablePattern { + #[label] + pub span: Option, + #[label(mir_build::catchall_label)] + pub catchall: Option, +} diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 42c8787102914..b21cd0d1404d4 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -605,14 +605,12 @@ fn pat_is_catchall(pat: &DeconstructedPat<'_, '_>) -> bool { } fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option) { - tcx.struct_span_lint_hir(UNREACHABLE_PATTERNS, id, span, "unreachable pattern", |lint| { - if let Some(catchall) = catchall { - // We had a catchall pattern, hint at that. - lint.span_label(span, "unreachable pattern"); - lint.span_label(catchall, "matches any value"); - } - lint - }); + tcx.emit_spanned_lint( + UNREACHABLE_PATTERNS, + id, + span, + UnreachablePattern { span: if catchall.is_some() { Some(span) } else { None }, catchall }, + ); } fn irrefutable_let_pattern(tcx: TyCtxt<'_>, id: HirId, span: Span) { From d5f821eeb085fab83c6592b018d2e99033b8c2ab Mon Sep 17 00:00:00 2001 From: TheOddGarlic Date: Sat, 27 Aug 2022 22:17:10 +0300 Subject: [PATCH 08/18] Migrate "constant pattern depends on generic parameter" diagnostic --- compiler/rustc_error_messages/locales/en-US/mir_build.ftl | 3 +++ compiler/rustc_mir_build/src/errors.rs | 7 +++++++ compiler/rustc_mir_build/src/thir/pattern/mod.rs | 7 ++++--- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl index 8ff5c9b3fdebb..4504d557da3f0 100644 --- a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl +++ b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl @@ -195,3 +195,6 @@ mir_build_non_const_path = runtime values cannot be referenced in patterns mir_build_unreachable_pattern = unreachable pattern .label = unreachable pattern .catchall_label = matches any value + +mir_build_const_pattern_depends_on_generic_parameter = + constant pattern depends on a generic parameter diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 3049ebc5b037b..e6ed824b8bb91 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -466,3 +466,10 @@ pub struct UnreachablePattern { #[label(mir_build::catchall_label)] pub catchall: Option, } + +#[derive(SessionDiagnostic)] +#[diag(mir_build::const_pattern_depends_on_generic_parameter)] +pub struct ConstPatternDependsOnGenericParameter { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 5aaf6c907e392..2711835f4b4dd 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -8,6 +8,7 @@ mod usefulness; pub(crate) use self::check_match::check_match; pub(crate) use self::usefulness::MatchCheckCtxt; +use crate::errors::ConstPatternDependsOnGenericParameter; use crate::thir::util::UserAnnotatedTyHelpers; use rustc_errors::struct_span_err; @@ -549,7 +550,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { Err(ErrorHandled::TooGeneric) => { // While `Reported | Linted` cases will have diagnostics emitted already // it is not true for TooGeneric case, so we need to give user more information. - self.tcx.sess.span_err(span, "constant pattern depends on a generic parameter"); + self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span }); pat_from_kind(PatKind::Wild) } Err(_) => { @@ -583,9 +584,9 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { _ => bug!("Expected ConstKind::Param"), }, mir::ConstantKind::Val(_, _) => self.const_to_pat(value, id, span, false).kind, - mir::ConstantKind::Unevaluated(..) => { + mir::ConstKind::Unevaluated(_) => { // If we land here it means the const can't be evaluated because it's `TooGeneric`. - self.tcx.sess.span_err(span, "constant pattern depends on a generic parameter"); + self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span }); return PatKind::Wild; } } From 513e3995e0d0e72690ad6eae925217cfc83b3eb3 Mon Sep 17 00:00:00 2001 From: TheOddGarlic Date: Sat, 27 Aug 2022 22:25:09 +0300 Subject: [PATCH 09/18] Migrate "could not evaluate const pattern" diagnostic --- compiler/rustc_error_messages/locales/en-US/mir_build.ftl | 2 ++ compiler/rustc_mir_build/src/errors.rs | 7 +++++++ compiler/rustc_mir_build/src/thir/pattern/mod.rs | 6 +++--- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl index 4504d557da3f0..87e7f348ee080 100644 --- a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl +++ b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl @@ -198,3 +198,5 @@ mir_build_unreachable_pattern = unreachable pattern mir_build_const_pattern_depends_on_generic_parameter = constant pattern depends on a generic parameter + +mir_build_could_not_eval_const_pattern = could not evaluate constant pattern diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index e6ed824b8bb91..0d7e62e616f3c 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -473,3 +473,10 @@ pub struct ConstPatternDependsOnGenericParameter { #[primary_span] pub span: Span, } + +#[derive(SessionDiagnostic)] +#[diag(mir_build::could_not_eval_const_pattern)] +pub struct CouldNotEvalConstPattern { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 2711835f4b4dd..c04bea24b581b 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -8,7 +8,7 @@ mod usefulness; pub(crate) use self::check_match::check_match; pub(crate) use self::usefulness::MatchCheckCtxt; -use crate::errors::ConstPatternDependsOnGenericParameter; +use crate::errors::*; use crate::thir::util::UserAnnotatedTyHelpers; use rustc_errors::struct_span_err; @@ -503,7 +503,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } Err(_) => { - self.tcx.sess.span_err(span, "could not evaluate constant pattern"); + self.tcx.sess.emit_err(CouldNotEvalConstPattern { span }); return pat_from_kind(PatKind::Wild); } }; @@ -554,7 +554,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { pat_from_kind(PatKind::Wild) } Err(_) => { - self.tcx.sess.span_err(span, "could not evaluate constant pattern"); + self.tcx.sess.emit_err(CouldNotEvalConstPattern { span }); pat_from_kind(PatKind::Wild) } } From 4b70784176052a7fe6e7fc205bab67c829de0bc1 Mon Sep 17 00:00:00 2001 From: TheOddGarlic Date: Sat, 27 Aug 2022 22:48:18 +0300 Subject: [PATCH 10/18] Migrate lower range bound diagnostics --- .../locales/en-US/mir_build.ftl | 7 +++++ compiler/rustc_mir_build/src/errors.rs | 17 +++++++++++ .../rustc_mir_build/src/thir/pattern/mod.rs | 29 ++++--------------- 3 files changed, 29 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl index 87e7f348ee080..6bfab0774feae 100644 --- a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl +++ b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl @@ -200,3 +200,10 @@ mir_build_const_pattern_depends_on_generic_parameter = constant pattern depends on a generic parameter mir_build_could_not_eval_const_pattern = could not evaluate constant pattern + +mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper = + lower range bound must be less than or equal to upper + .label = lower bound larger than upper bound + .teach_note = When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range. + +mir_build_lower_range_bound_must_be_less_than_upper = lower range bound must be less than upper diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 0d7e62e616f3c..96728970c5be0 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -480,3 +480,20 @@ pub struct CouldNotEvalConstPattern { #[primary_span] pub span: Span, } + +#[derive(SessionDiagnostic)] +#[diag(mir_build::lower_range_bound_must_be_less_than_or_equal_to_upper, code = "E0030")] +pub struct LowerRangeBoundMustBeLessThanOrEqualToUpper { + #[primary_span] + #[label] + pub span: Span, + #[note(mir_build::teach_note)] + pub teach: Option<()>, +} + +#[derive(SessionDiagnostic)] +#[diag(mir_build::lower_range_bound_must_be_less_than_upper, code = "E0579")] +pub struct LowerRangeBoundMustBeLessThanUpper { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index c04bea24b581b..b7d1dc8c95656 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -11,7 +11,7 @@ pub(crate) use self::usefulness::MatchCheckCtxt; use crate::errors::*; use crate::thir::util::UserAnnotatedTyHelpers; -use rustc_errors::struct_span_err; +use rustc_errors::error_code; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::pat_util::EnumerateAndAdjustIterator; @@ -141,13 +141,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } // `x..y` where `x >= y`. The range is empty => error. (RangeEnd::Excluded, _) => { - struct_span_err!( - self.tcx.sess, - span, - E0579, - "lower range bound must be less than upper" - ) - .emit(); + self.tcx.sess.emit_err(LowerRangeBoundMustBeLessThanUpper { span }); PatKind::Wild } // `x..=y` where `x == y`. @@ -158,23 +152,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } // `x..=y` where `x > y` hence the range is empty => error. (RangeEnd::Included, _) => { - let mut err = struct_span_err!( - self.tcx.sess, + self.tcx.sess.emit_err(LowerRangeBoundMustBeLessThanOrEqualToUpper { span, - E0030, - "lower range bound must be less than or equal to upper" - ); - err.span_label(span, "lower bound larger than upper bound"); - if self.tcx.sess.teach(&err.get_code().unwrap()) { - err.note( - "When matching against a range, the compiler \ - verifies that the range is non-empty. Range \ - patterns include both end-points, so this is \ - equivalent to requiring the start of the range \ - to be less than or equal to the end of the range.", - ); - } - err.emit(); + teach: if self.tcx.sess.teach(&error_code!(E0030)) { Some(()) } else { None }, + }); PatKind::Wild } } From 6f82a00aa1a3dc26e2ba919e539bbc2504ebf22a Mon Sep 17 00:00:00 2001 From: TheOddGarlic Date: Sun, 28 Aug 2022 21:48:09 +0300 Subject: [PATCH 11/18] Migrate leading/trailing irrefutable let pattern diagnostics --- .../locales/en-US/mir_build.ftl | 26 ++++++++++++++ compiler/rustc_mir_build/src/errors.rs | 16 +++++++++ .../src/thir/pattern/check_match.rs | 35 ++++++------------- 3 files changed, 52 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl index 6bfab0774feae..280b82b4ea400 100644 --- a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl +++ b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl @@ -207,3 +207,29 @@ mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper = .teach_note = When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range. mir_build_lower_range_bound_must_be_less_than_upper = lower range bound must be less than upper + +mir_build_leading_irrefutable_let_patterns = leading irrefutable {$count -> + [one] pattern + *[other] patterns + } in let chain + .note = {$count -> + [one] this pattern + *[other] these patterns + } will always match + .help = consider moving {$count -> + [one] it + *[other] them + } outside of the construct + +mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count -> + [one] pattern + *[other] patterns + } in let chain + .note = {$count -> + [one] this pattern + *[other] these patterns + } will always match + .help = consider moving {$count -> + [one] it + *[other] them + } into the body diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 96728970c5be0..3331e785b95f2 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -497,3 +497,19 @@ pub struct LowerRangeBoundMustBeLessThanUpper { #[primary_span] pub span: Span, } + +#[derive(LintDiagnostic)] +#[diag(mir_build::leading_irrefutable_let_patterns)] +#[note] +#[help] +pub struct LeadingIrrefutableLetPatterns { + pub count: usize, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build::trailing_irrefutable_let_patterns)] +#[note] +#[help] +pub struct TrailingIrrefutableLetPatterns { + pub count: usize, +} diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index b21cd0d1404d4..8e1a3f10f4acb 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -339,29 +339,6 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { ); return true; } - let lint_affix = |affix: &[Option<(Span, bool)>], kind, suggestion| { - let span_start = affix[0].unwrap().0; - let span_end = affix.last().unwrap().unwrap().0; - let span = span_start.to(span_end); - let cnt = affix.len(); - let s = pluralize!(cnt); - cx.tcx.struct_span_lint_hir( - IRREFUTABLE_LET_PATTERNS, - top, - span, - format!("{kind} irrefutable pattern{s} in let chain"), - |lint| { - lint.note(format!( - "{these} pattern{s} will always match", - these = pluralize!("this", cnt), - )) - .help(format!( - "consider moving {} {suggestion}", - if cnt > 1 { "them" } else { "it" } - )) - }, - ); - }; if let Some(until) = chain_refutabilities.iter().position(|r| !matches!(*r, Some((_, false)))) && until > 0 { // The chain has a non-zero prefix of irrefutable `let` statements. @@ -375,13 +352,21 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { if !matches!(let_source, LetSource::WhileLet | LetSource::IfLetGuard) { // Emit the lint let prefix = &chain_refutabilities[..until]; - lint_affix(prefix, "leading", "outside of the construct"); + let span_start = prefix[0].unwrap().0; + let span_end = prefix.last().unwrap().unwrap().0; + let span = span_start.to(span_end); + let count = prefix.len(); + cx.tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, top, span, LeadingIrrefutableLetPatterns { count }); } } if let Some(from) = chain_refutabilities.iter().rposition(|r| !matches!(*r, Some((_, false)))) && from != (chain_refutabilities.len() - 1) { // The chain has a non-empty suffix of irrefutable `let` statements let suffix = &chain_refutabilities[from + 1..]; - lint_affix(suffix, "trailing", "into the body"); + let span_start = suffix[0].unwrap().0; + let span_end = suffix.last().unwrap().unwrap().0; + let span = span_start.to(span_end); + let count = suffix.len(); + cx.tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, top, span, TrailingIrrefutableLetPatterns { count }); } true } From e1c5073c07e52ebf9e8217d8bb4aaf795eda7a49 Mon Sep 17 00:00:00 2001 From: TheOddGarlic Date: Mon, 29 Aug 2022 10:06:50 +0300 Subject: [PATCH 12/18] Migrate pattern bindings with variant name lint --- .../locales/en-US/mir_build.ftl | 4 +++ compiler/rustc_mir_build/src/errors.rs | 11 ++++++- .../src/thir/pattern/check_match.rs | 32 ++++++------------- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl index 280b82b4ea400..539794086ee26 100644 --- a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl +++ b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl @@ -233,3 +233,7 @@ mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count -> [one] it *[other] them } into the body + +mir_build_bindings_with_variant_name = + pattern binding `{$ident}` is named the same as one of the variants of the type `{$ty_path}` + .suggestion = to match on the variant, qualify the path diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 3331e785b95f2..085511a9d7c0a 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -3,7 +3,7 @@ use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic}; use rustc_middle::ty::{self, Ty}; use rustc_session::{parse::ParseSess, SessionDiagnostic}; -use rustc_span::Span; +use rustc_span::{symbol::Ident, Span}; #[derive(LintDiagnostic)] #[diag(mir_build::unconditional_recursion)] @@ -513,3 +513,12 @@ pub struct LeadingIrrefutableLetPatterns { pub struct TrailingIrrefutableLetPatterns { pub count: usize, } + +#[derive(LintDiagnostic)] +#[diag(mir_build::bindings_with_variant_name, code = "E0170")] +pub struct BindingsWithVariantName { + #[suggestion(code = "{ty_path}::{ident}", applicability = "machine-applicable")] + pub suggestion: Option, + pub ty_path: String, + pub ident: Ident, +} diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 8e1a3f10f4acb..a62c1a232fac1 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -9,8 +9,8 @@ use crate::errors::*; use rustc_arena::TypedArena; use rustc_ast::Mutability; use rustc_errors::{ - error_code, pluralize, struct_span_err, Applicability, DelayDm, Diagnostic, DiagnosticBuilder, - ErrorGuaranteed, MultiSpan, + pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, + MultiSpan, }; use rustc_hir as hir; use rustc_hir::def::*; @@ -547,32 +547,20 @@ fn check_for_bindings_named_same_as_variants( }) { let variant_count = edef.variants().len(); - cx.tcx.struct_span_lint_hir( + let ty_path = cx.tcx.def_path_str(edef.did()); + cx.tcx.emit_spanned_lint( BINDINGS_WITH_VARIANT_NAME, p.hir_id, p.span, - DelayDm(|| format!( - "pattern binding `{}` is named the same as one \ - of the variants of the type `{}`", - ident, cx.tcx.def_path_str(edef.did()) - )), - |lint| { - let ty_path = cx.tcx.def_path_str(edef.did()); - lint.code(error_code!(E0170)); - + BindingsWithVariantName { // If this is an irrefutable pattern, and there's > 1 variant, // then we can't actually match on this. Applying the below // suggestion would produce code that breaks on `check_irrefutable`. - if rf == Refutable || variant_count == 1 { - lint.span_suggestion( - p.span, - "to match on the variant, qualify the path", - format!("{}::{}", ty_path, ident), - Applicability::MachineApplicable, - ); - } - - lint + suggestion: if rf == Refutable || variant_count == 1 { + Some(p.span) + } else { None }, + ty_path, + ident, }, ) } From eeef05b318d1473ebedb90c84642b699e0a9b3e8 Mon Sep 17 00:00:00 2001 From: TheOddGarlic Date: Mon, 29 Aug 2022 11:21:25 +0300 Subject: [PATCH 13/18] Migrate irrefutable let pattern diagnostics --- .../locales/en-US/mir_build.ftl | 50 +++++++++++++ compiler/rustc_mir_build/src/errors.rs | 40 +++++++++++ .../src/thir/pattern/check_match.rs | 70 ++++--------------- 3 files changed, 103 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl index 539794086ee26..7555bd608498d 100644 --- a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl +++ b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl @@ -237,3 +237,53 @@ mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count -> mir_build_bindings_with_variant_name = pattern binding `{$ident}` is named the same as one of the variants of the type `{$ty_path}` .suggestion = to match on the variant, qualify the path + +mir_build_irrefutable_let_patterns_generic_let = irrefutable `let` {$count -> + [one] pattern + *[other] patterns + } + .note = {$count -> + [one] this pattern + *[other] these patterns + } will always match, so the `let` is useless + .help = consider removing `let` + +mir_build_irrefutable_let_patterns_if_let = irrefutable `if let` {$count -> + [one] pattern + *[other] patterns + } + .note = {$count -> + [one] this pattern + *[other] these patterns + } will always match, so the `if let` is useless + .help = consider replacing the `if let` with a `let` + +mir_build_irrefutable_let_patterns_if_let_guard = irrefutable `if let` guard {$count -> + [one] pattern + *[other] patterns + } + .note = {$count -> + [one] this pattern + *[other] these patterns + } will always match, so the guard is useless + .help = consider removing the guard and adding a `let` inside the match arm + +mir_build_irrefutable_let_patterns_let_else = irrefutable `let...else` {$count -> + [one] pattern + *[other] patterns + } + .note = {$count -> + [one] this pattern + *[other] these patterns + } will always match, so the `else` clause is useless + .help = consider removing the `else` clause + +mir_build_irrefutable_let_patterns_while_let = irrefutable `while let` {$count -> + [one] pattern + *[other] patterns + } + .note = {$count -> + [one] this pattern + *[other] these patterns + } will always match, so the loop will never exit + .help = consider instead using a `loop {"{"} ... {"}"}` with a `let` inside it diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 085511a9d7c0a..eecef26b94cb6 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -522,3 +522,43 @@ pub struct BindingsWithVariantName { pub ty_path: String, pub ident: Ident, } + +#[derive(LintDiagnostic)] +#[diag(mir_build::irrefutable_let_patterns_generic_let)] +#[note] +#[help] +pub struct IrrefutableLetPatternsGenericLet { + pub count: usize, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build::irrefutable_let_patterns_if_let)] +#[note] +#[help] +pub struct IrrefutableLetPatternsIfLet { + pub count: usize, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build::irrefutable_let_patterns_if_let_guard)] +#[note] +#[help] +pub struct IrrefutableLetPatternsIfLetGuard { + pub count: usize, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build::irrefutable_let_patterns_let_else)] +#[note] +#[help] +pub struct IrrefutableLetPatternsLetElse { + pub count: usize, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build::irrefutable_let_patterns_while_let)] +#[note] +#[help] +pub struct IrrefutableLetPatternsWhileLet { + pub count: usize, +} diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index a62c1a232fac1..a488253b992b2 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -598,68 +598,24 @@ fn irrefutable_let_patterns( count: usize, span: Span, ) { + let span = match source { + LetSource::LetElse(span) => span, + _ => span, + }; + macro_rules! emit_diag { - ( - $lint:expr, - $source_name:expr, - $note_sufix:expr, - $help_sufix:expr - ) => {{ - let s = pluralize!(count); - let these = pluralize!("this", count); - tcx.struct_span_lint_hir( - IRREFUTABLE_LET_PATTERNS, - id, - span, - format!("irrefutable {} pattern{s}", $source_name), - |lint| { - lint.note(&format!( - "{these} pattern{s} will always match, so the {}", - $note_sufix - )) - .help(concat!("consider ", $help_sufix)) - }, - ) + ($lint:tt) => {{ + tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, id, span, $lint { count }); }}; } match source { - LetSource::GenericLet => { - emit_diag!(lint, "`let`", "`let` is useless", "removing `let`"); - } - LetSource::IfLet => { - emit_diag!( - lint, - "`if let`", - "`if let` is useless", - "replacing the `if let` with a `let`" - ); - } - LetSource::IfLetGuard => { - emit_diag!( - lint, - "`if let` guard", - "guard is useless", - "removing the guard and adding a `let` inside the match arm" - ); - } - LetSource::LetElse => { - emit_diag!( - lint, - "`let...else`", - "`else` clause is useless", - "removing the `else` clause" - ); - } - LetSource::WhileLet => { - emit_diag!( - lint, - "`while let`", - "loop will never exit", - "instead using a `loop { ... }` with a `let` inside it" - ); - } - }; + LetSource::GenericLet => emit_diag!(IrrefutableLetPatternsGenericLet), + LetSource::IfLet => emit_diag!(IrrefutableLetPatternsIfLet), + LetSource::IfLetGuard => emit_diag!(IrrefutableLetPatternsIfLetGuard), + LetSource::LetElse(..) => emit_diag!(IrrefutableLetPatternsLetElse), + LetSource::WhileLet => emit_diag!(IrrefutableLetPatternsWhileLet), + } } fn is_let_irrefutable<'p, 'tcx>( From 3a9a06311d8d2445d47f087ef68f702b643bc4df Mon Sep 17 00:00:00 2001 From: TheOddGarlic Date: Tue, 30 Aug 2022 20:01:28 +0300 Subject: [PATCH 14/18] Migrate borrow of moved value diagnostic --- .../locales/en-US/mir_build.ftl | 6 +++++ compiler/rustc_mir_build/src/errors.rs | 16 +++++++++++++ .../src/thir/pattern/check_match.rs | 24 ++++++------------- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl index 7555bd608498d..118ca985b87ff 100644 --- a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl +++ b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl @@ -287,3 +287,9 @@ mir_build_irrefutable_let_patterns_while_let = irrefutable `while let` {$count - *[other] these patterns } will always match, so the loop will never exit .help = consider instead using a `loop {"{"} ... {"}"}` with a `let` inside it + +mir_build_borrow_of_moved_value = borrow of moved value + .label = value moved into `{$name}` here + .occurs_because_label = move occurs because `{$name}` has type `{$ty}` which does not implement the `Copy` trait + .value_borrowed_label = value borrowed here after move + .suggest_borrowing = borrow this binding in the pattern to avoid moving the value diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index eecef26b94cb6..639c07f419401 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -562,3 +562,19 @@ pub struct IrrefutableLetPatternsLetElse { pub struct IrrefutableLetPatternsWhileLet { pub count: usize, } + +#[derive(SessionDiagnostic)] +#[diag(mir_build::borrow_of_moved_value)] +pub struct BorrowOfMovedValue<'tcx> { + #[primary_span] + pub span: Span, + #[label] + #[label(mir_build::occurs_because_label)] + pub binding_span: Span, + #[label(mir_build::value_borrowed_label)] + pub conflicts_ref: Vec, + pub name: Ident, + pub ty: Ty<'tcx>, + #[suggestion(code = "ref ", applicability = "machine-applicable")] + pub suggest_borrowing: Option, +} diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index a488253b992b2..3b6b188bc6cfb 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -962,24 +962,14 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa } }); if !conflicts_ref.is_empty() { - let occurs_because = format!( - "move occurs because `{}` has type `{}` which does not implement the `Copy` trait", + sess.emit_err(BorrowOfMovedValue { + span: pat.span, + binding_span, + conflicts_ref, name, - typeck_results.node_type(pat.hir_id), - ); - let mut err = sess.struct_span_err(pat.span, "borrow of moved value"); - err.span_label(binding_span, format!("value moved into `{}` here", name)) - .span_label(binding_span, occurs_because) - .span_labels(conflicts_ref, "value borrowed here after move"); - if pat.span.contains(binding_span) { - err.span_suggestion_verbose( - binding_span.shrink_to_lo(), - "borrow this binding in the pattern to avoid moving the value", - "ref ".to_string(), - Applicability::MachineApplicable, - ); - } - err.emit(); + ty: typeck_results.node_type(pat.hir_id), + suggest_borrowing: pat.span.contains(binding_span).then(|| binding_span.shrink_to_lo()), + }); } return; } From e71a722fa69974102e220444523b824da7eaa522 Mon Sep 17 00:00:00 2001 From: TheOddGarlic Date: Tue, 30 Aug 2022 20:38:10 +0300 Subject: [PATCH 15/18] Migrate multiple mut borrows diagnostic --- .../locales/en-US/mir_build.ftl | 6 ++++ compiler/rustc_mir_build/src/errors.rs | 34 +++++++++++++++++++ .../src/thir/pattern/check_match.rs | 14 ++++---- 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl index 118ca985b87ff..94e061a2af6a8 100644 --- a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl +++ b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl @@ -293,3 +293,9 @@ mir_build_borrow_of_moved_value = borrow of moved value .occurs_because_label = move occurs because `{$name}` has type `{$ty}` which does not implement the `Copy` trait .value_borrowed_label = value borrowed here after move .suggest_borrowing = borrow this binding in the pattern to avoid moving the value + +mir_build_multiple_mut_borrows = cannot borrow value as mutable more than once at a time + .label = first mutable borrow, by `{$name}`, occurs here + .mutable_borrow = another mutable borrow, by `{$name_mut}`, occurs here + .immutable_borrow = also borrowed as immutable, by `{$name_immut}`, here + .moved = also moved into `{$name_moved}` here diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 639c07f419401..dd715fcfc6c58 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -578,3 +578,37 @@ pub struct BorrowOfMovedValue<'tcx> { #[suggestion(code = "ref ", applicability = "machine-applicable")] pub suggest_borrowing: Option, } + +#[derive(SessionDiagnostic)] +#[diag(mir_build::multiple_mut_borrows)] +pub struct MultipleMutBorrows { + #[primary_span] + pub span: Span, + #[label] + pub binding_span: Span, + #[subdiagnostic] + pub occurences: Vec, + pub name: Ident, +} + +#[derive(SessionSubdiagnostic)] +pub enum MultipleMutBorrowOccurence { + #[label(mir_build::mutable_borrow)] + Mutable { + #[primary_span] + span: Span, + name_mut: Ident, + }, + #[label(mir_build::immutable_borrow)] + Immutable { + #[primary_span] + span: Span, + name_immut: Ident, + }, + #[label(mir_build::moved)] + Moved { + #[primary_span] + span: Span, + name_moved: Ident, + }, +} diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 3b6b188bc6cfb..374942ee798b8 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -999,19 +999,19 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa // Report errors if any. if !conflicts_mut_mut.is_empty() { // Report mutability conflicts for e.g. `ref mut x @ Some(ref mut y)`. - let mut err = sess - .struct_span_err(pat.span, "cannot borrow value as mutable more than once at a time"); - err.span_label(binding_span, format!("first mutable borrow, by `{}`, occurs here", name)); + let mut occurences = vec![]; + for (span, name) in conflicts_mut_mut { - err.span_label(span, format!("another mutable borrow, by `{}`, occurs here", name)); + occurences.push(MultipleMutBorrowOccurence::Mutable { span, name_mut: name }); } for (span, name) in conflicts_mut_ref { - err.span_label(span, format!("also borrowed as immutable, by `{}`, here", name)); + occurences.push(MultipleMutBorrowOccurence::Immutable { span, name_immut: name }); } for (span, name) in conflicts_move { - err.span_label(span, format!("also moved into `{}` here", name)); + occurences.push(MultipleMutBorrowOccurence::Moved { span, name_moved: name }); } - err.emit(); + + sess.emit_err(MultipleMutBorrows { span: pat.span, binding_span, occurences, name }); } else if !conflicts_mut_ref.is_empty() { // Report mutability conflicts for e.g. `ref x @ Some(ref mut y)` or the converse. let (primary, also) = match mut_outer { From 1bdf1125292d9b0545581ea2a4473a2d80bd9813 Mon Sep 17 00:00:00 2001 From: mejrs <> Date: Sat, 26 Nov 2022 21:22:49 +0100 Subject: [PATCH 16/18] Resolve various merge conflicts --- .../locales/en-US/mir_build.ftl | 2 +- compiler/rustc_error_messages/src/lib.rs | 2 +- compiler/rustc_mir_build/src/errors.rs | 228 +++++++++--------- .../src/thir/pattern/check_match.rs | 25 +- .../rustc_mir_build/src/thir/pattern/mod.rs | 2 +- 5 files changed, 129 insertions(+), 130 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl index 94e061a2af6a8..60d3d3e69abbe 100644 --- a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl +++ b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl @@ -292,7 +292,7 @@ mir_build_borrow_of_moved_value = borrow of moved value .label = value moved into `{$name}` here .occurs_because_label = move occurs because `{$name}` has type `{$ty}` which does not implement the `Copy` trait .value_borrowed_label = value borrowed here after move - .suggest_borrowing = borrow this binding in the pattern to avoid moving the value + .suggestion = borrow this binding in the pattern to avoid moving the value mir_build_multiple_mut_borrows = cannot borrow value as mutable more than once at a time .label = first mutable borrow, by `{$name}`, occurs here diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index db62643bc24ac..25d0e736e599f 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -57,8 +57,8 @@ fluent_messages! { lint => "../locales/en-US/lint.ftl", 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", + mir_dataflow => "../locales/en-US/mir_dataflow.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/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index dd715fcfc6c58..f3bfafb37b77f 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -1,22 +1,24 @@ use crate::thir::pattern::MatchCheckCtxt; -use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; -use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic}; +use rustc_errors::Handler; +use rustc_errors::{ + error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, MultiSpan, +}; +use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{self, Ty}; -use rustc_session::{parse::ParseSess, SessionDiagnostic}; use rustc_span::{symbol::Ident, Span}; #[derive(LintDiagnostic)] -#[diag(mir_build::unconditional_recursion)] +#[diag(mir_build_unconditional_recursion)] #[help] pub struct UnconditionalRecursion { #[label] pub span: Span, - #[label(mir_build::unconditional_recursion_call_site_label)] + #[label(mir_build_unconditional_recursion_call_site_label)] pub call_sites: Vec, } #[derive(LintDiagnostic)] -#[diag(mir_build::unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe)] #[note] pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe<'a> { #[label] @@ -25,7 +27,7 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe<'a> { } #[derive(LintDiagnostic)] -#[diag(mir_build::unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless)] #[note] pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { #[label] @@ -33,7 +35,7 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { } #[derive(LintDiagnostic)] -#[diag(mir_build::unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe)] #[note] pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { #[label] @@ -41,7 +43,7 @@ pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { } #[derive(LintDiagnostic)] -#[diag(mir_build::unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe)] #[note] pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { #[label] @@ -49,7 +51,7 @@ pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { } #[derive(LintDiagnostic)] -#[diag(mir_build::unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe)] #[note] pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { #[label] @@ -57,7 +59,7 @@ pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { } #[derive(LintDiagnostic)] -#[diag(mir_build::unsafe_op_in_unsafe_fn_extern_static_requires_unsafe)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe)] #[note] pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { #[label] @@ -65,7 +67,7 @@ pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { } #[derive(LintDiagnostic)] -#[diag(mir_build::unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe)] #[note] pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { #[label] @@ -73,7 +75,7 @@ pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { } #[derive(LintDiagnostic)] -#[diag(mir_build::unsafe_op_in_unsafe_fn_union_field_requires_unsafe)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe)] #[note] pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { #[label] @@ -81,7 +83,7 @@ pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { } #[derive(LintDiagnostic)] -#[diag(mir_build::unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe)] #[note] pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { #[label] @@ -89,14 +91,14 @@ pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { } #[derive(LintDiagnostic)] -#[diag(mir_build::unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe)] pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { #[label] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(mir_build::unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe)] #[note] pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> { #[label] @@ -104,8 +106,8 @@ pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> { pub function: &'a str, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::call_to_unsafe_fn_requires_unsafe, code = "E0133")] +#[derive(Diagnostic)] +#[diag(mir_build_call_to_unsafe_fn_requires_unsafe, code = "E0133")] #[note] pub struct CallToUnsafeFunctionRequiresUnsafe<'a> { #[primary_span] @@ -114,8 +116,8 @@ pub struct CallToUnsafeFunctionRequiresUnsafe<'a> { pub function: &'a str, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::call_to_unsafe_fn_requires_unsafe_nameless, code = "E0133")] +#[derive(Diagnostic)] +#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_nameless, code = "E0133")] #[note] pub struct CallToUnsafeFunctionRequiresUnsafeNameless { #[primary_span] @@ -123,8 +125,8 @@ pub struct CallToUnsafeFunctionRequiresUnsafeNameless { pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[derive(Diagnostic)] +#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] #[note] pub struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> { #[primary_span] @@ -133,9 +135,9 @@ pub struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> { pub function: &'a str, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag( - mir_build::call_to_unsafe_fn_requires_unsafe_nameless_unsafe_op_in_unsafe_fn_allowed, + mir_build_call_to_unsafe_fn_requires_unsafe_nameless_unsafe_op_in_unsafe_fn_allowed, code = "E0133" )] #[note] @@ -145,8 +147,8 @@ pub struct CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::inline_assembly_requires_unsafe, code = "E0133")] +#[derive(Diagnostic)] +#[diag(mir_build_inline_assembly_requires_unsafe, code = "E0133")] #[note] pub struct UseOfInlineAssemblyRequiresUnsafe { #[primary_span] @@ -154,8 +156,8 @@ pub struct UseOfInlineAssemblyRequiresUnsafe { pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[derive(Diagnostic)] +#[diag(mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] #[note] pub struct UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] @@ -163,8 +165,8 @@ pub struct UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::initializing_type_with_requires_unsafe, code = "E0133")] +#[derive(Diagnostic)] +#[diag(mir_build_initializing_type_with_requires_unsafe, code = "E0133")] #[note] pub struct InitializingTypeWithRequiresUnsafe { #[primary_span] @@ -172,9 +174,9 @@ pub struct InitializingTypeWithRequiresUnsafe { pub span: Span, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag( - mir_build::initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, + mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133" )] #[note] @@ -184,8 +186,8 @@ pub struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::mutable_static_requires_unsafe, code = "E0133")] +#[derive(Diagnostic)] +#[diag(mir_build_mutable_static_requires_unsafe, code = "E0133")] #[note] pub struct UseOfMutableStaticRequiresUnsafe { #[primary_span] @@ -193,8 +195,8 @@ pub struct UseOfMutableStaticRequiresUnsafe { pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[derive(Diagnostic)] +#[diag(mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] #[note] pub struct UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] @@ -202,8 +204,8 @@ pub struct UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::extern_static_requires_unsafe, code = "E0133")] +#[derive(Diagnostic)] +#[diag(mir_build_extern_static_requires_unsafe, code = "E0133")] #[note] pub struct UseOfExternStaticRequiresUnsafe { #[primary_span] @@ -211,8 +213,8 @@ pub struct UseOfExternStaticRequiresUnsafe { pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[derive(Diagnostic)] +#[diag(mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] #[note] pub struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] @@ -220,8 +222,8 @@ pub struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::deref_raw_pointer_requires_unsafe, code = "E0133")] +#[derive(Diagnostic)] +#[diag(mir_build_deref_raw_pointer_requires_unsafe, code = "E0133")] #[note] pub struct DerefOfRawPointerRequiresUnsafe { #[primary_span] @@ -229,8 +231,8 @@ pub struct DerefOfRawPointerRequiresUnsafe { pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[derive(Diagnostic)] +#[diag(mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] #[note] pub struct DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] @@ -238,8 +240,8 @@ pub struct DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::union_field_requires_unsafe, code = "E0133")] +#[derive(Diagnostic)] +#[diag(mir_build_union_field_requires_unsafe, code = "E0133")] #[note] pub struct AccessToUnionFieldRequiresUnsafe { #[primary_span] @@ -247,8 +249,8 @@ pub struct AccessToUnionFieldRequiresUnsafe { pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[derive(Diagnostic)] +#[diag(mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] #[note] pub struct AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] @@ -256,8 +258,8 @@ pub struct AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::mutation_of_layout_constrained_field_requires_unsafe, code = "E0133")] +#[derive(Diagnostic)] +#[diag(mir_build_mutation_of_layout_constrained_field_requires_unsafe, code = "E0133")] #[note] pub struct MutationOfLayoutConstrainedFieldRequiresUnsafe { #[primary_span] @@ -265,9 +267,9 @@ pub struct MutationOfLayoutConstrainedFieldRequiresUnsafe { pub span: Span, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag( - mir_build::mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, + mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133" )] #[note] @@ -277,8 +279,8 @@ pub struct MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllow pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::borrow_of_layout_constrained_field_requires_unsafe, code = "E0133")] +#[derive(Diagnostic)] +#[diag(mir_build_borrow_of_layout_constrained_field_requires_unsafe, code = "E0133")] #[note] pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafe { #[primary_span] @@ -286,9 +288,9 @@ pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafe { pub span: Span, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag( - mir_build::borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, + mir_build_borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133" )] #[note] @@ -298,8 +300,8 @@ pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::call_to_fn_with_requires_unsafe, code = "E0133")] +#[derive(Diagnostic)] +#[diag(mir_build_call_to_fn_with_requires_unsafe, code = "E0133")] #[note] pub struct CallToFunctionWithRequiresUnsafe<'a> { #[primary_span] @@ -308,8 +310,8 @@ pub struct CallToFunctionWithRequiresUnsafe<'a> { pub function: &'a str, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[derive(Diagnostic)] +#[diag(mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] #[note] pub struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> { #[primary_span] @@ -319,7 +321,7 @@ pub struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> { } #[derive(LintDiagnostic)] -#[diag(mir_build::unused_unsafe)] +#[diag(mir_build_unused_unsafe)] pub struct UnusedUnsafe { #[label] pub span: Span, @@ -327,14 +329,14 @@ pub struct UnusedUnsafe { pub enclosing: Option, } -#[derive(SessionSubdiagnostic)] +#[derive(Subdiagnostic)] pub enum UnusedUnsafeEnclosing { - #[label(mir_build::unused_unsafe_enclosing_block_label)] + #[label(mir_build_unused_unsafe_enclosing_block_label)] Block { #[primary_span] span: Span, }, - #[label(mir_build::unused_unsafe_enclosing_fn_label)] + #[label(mir_build_unused_unsafe_enclosing_fn_label)] Function { #[primary_span] span: Span, @@ -348,11 +350,11 @@ pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> { pub ty: Ty<'tcx>, } -impl<'a> SessionDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> { - fn into_diagnostic(self, sess: &'a ParseSess) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = sess.span_diagnostic.struct_span_err_with_code( +impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> { + fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = handler.struct_span_err_with_code( self.span, - rustc_errors::fluent::mir_build::non_exhaustive_patterns_type_not_empty, + rustc_errors::fluent::mir_build_non_exhaustive_patterns_type_not_empty, error_code!(E0004), ); @@ -374,7 +376,7 @@ impl<'a> SessionDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> let mut span: MultiSpan = def_span.into(); span.push_span_label(def_span, ""); - diag.span_note(span, rustc_errors::fluent::mir_build::def_note); + diag.span_note(span, rustc_errors::fluent::def_note); } let is_variant_list_non_exhaustive = match self.ty.kind() { @@ -385,14 +387,14 @@ impl<'a> SessionDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> }; if is_variant_list_non_exhaustive { - diag.note(rustc_errors::fluent::mir_build::non_exhaustive_type_note); + diag.note(rustc_errors::fluent::non_exhaustive_type_note); } else { - diag.note(rustc_errors::fluent::mir_build::type_note); + diag.note(rustc_errors::fluent::type_note); } if let ty::Ref(_, sub_ty, _) = self.ty.kind() { - if self.cx.tcx.is_ty_uninhabited_from(self.cx.module, *sub_ty, self.cx.param_env) { - diag.note(rustc_errors::fluent::mir_build::reference_note); + if !sub_ty.is_inhabited_from(self.cx.tcx, self.cx.module, self.cx.param_env) { + diag.note(rustc_errors::fluent::reference_note); } } @@ -418,88 +420,88 @@ impl<'a> SessionDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> if let Some((span, sugg)) = suggestion { diag.span_suggestion_verbose( span, - rustc_errors::fluent::mir_build::suggestion, + rustc_errors::fluent::suggestion, sugg, Applicability::HasPlaceholders, ); } else { - diag.help(rustc_errors::fluent::mir_build::help); + diag.help(rustc_errors::fluent::help); } diag } } -#[derive(SessionDiagnostic)] -#[diag(mir_build::static_in_pattern, code = "E0158")] +#[derive(Diagnostic)] +#[diag(mir_build_static_in_pattern, code = "E0158")] pub struct StaticInPattern { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::assoc_const_in_pattern, code = "E0158")] +#[derive(Diagnostic)] +#[diag(mir_build_assoc_const_in_pattern, code = "E0158")] pub struct AssocConstInPattern { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::const_param_in_pattern, code = "E0158")] +#[derive(Diagnostic)] +#[diag(mir_build_const_param_in_pattern, code = "E0158")] pub struct ConstParamInPattern { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::non_const_path, code = "E0080")] +#[derive(Diagnostic)] +#[diag(mir_build_non_const_path, code = "E0080")] pub struct NonConstPath { #[primary_span] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(mir_build::unreachable_pattern)] +#[diag(mir_build_unreachable_pattern)] pub struct UnreachablePattern { #[label] pub span: Option, - #[label(mir_build::catchall_label)] + #[label(catchall_label)] pub catchall: Option, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::const_pattern_depends_on_generic_parameter)] +#[derive(Diagnostic)] +#[diag(mir_build_const_pattern_depends_on_generic_parameter)] pub struct ConstPatternDependsOnGenericParameter { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::could_not_eval_const_pattern)] +#[derive(Diagnostic)] +#[diag(mir_build_could_not_eval_const_pattern)] pub struct CouldNotEvalConstPattern { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::lower_range_bound_must_be_less_than_or_equal_to_upper, code = "E0030")] +#[derive(Diagnostic)] +#[diag(mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper, code = "E0030")] pub struct LowerRangeBoundMustBeLessThanOrEqualToUpper { #[primary_span] #[label] pub span: Span, - #[note(mir_build::teach_note)] + #[note(teach_note)] pub teach: Option<()>, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::lower_range_bound_must_be_less_than_upper, code = "E0579")] +#[derive(Diagnostic)] +#[diag(mir_build_lower_range_bound_must_be_less_than_upper, code = "E0579")] pub struct LowerRangeBoundMustBeLessThanUpper { #[primary_span] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(mir_build::leading_irrefutable_let_patterns)] +#[diag(mir_build_leading_irrefutable_let_patterns)] #[note] #[help] pub struct LeadingIrrefutableLetPatterns { @@ -507,7 +509,7 @@ pub struct LeadingIrrefutableLetPatterns { } #[derive(LintDiagnostic)] -#[diag(mir_build::trailing_irrefutable_let_patterns)] +#[diag(mir_build_trailing_irrefutable_let_patterns)] #[note] #[help] pub struct TrailingIrrefutableLetPatterns { @@ -515,7 +517,7 @@ pub struct TrailingIrrefutableLetPatterns { } #[derive(LintDiagnostic)] -#[diag(mir_build::bindings_with_variant_name, code = "E0170")] +#[diag(mir_build_bindings_with_variant_name, code = "E0170")] pub struct BindingsWithVariantName { #[suggestion(code = "{ty_path}::{ident}", applicability = "machine-applicable")] pub suggestion: Option, @@ -524,7 +526,7 @@ pub struct BindingsWithVariantName { } #[derive(LintDiagnostic)] -#[diag(mir_build::irrefutable_let_patterns_generic_let)] +#[diag(mir_build_irrefutable_let_patterns_generic_let)] #[note] #[help] pub struct IrrefutableLetPatternsGenericLet { @@ -532,7 +534,7 @@ pub struct IrrefutableLetPatternsGenericLet { } #[derive(LintDiagnostic)] -#[diag(mir_build::irrefutable_let_patterns_if_let)] +#[diag(mir_build_irrefutable_let_patterns_if_let)] #[note] #[help] pub struct IrrefutableLetPatternsIfLet { @@ -540,7 +542,7 @@ pub struct IrrefutableLetPatternsIfLet { } #[derive(LintDiagnostic)] -#[diag(mir_build::irrefutable_let_patterns_if_let_guard)] +#[diag(mir_build_irrefutable_let_patterns_if_let_guard)] #[note] #[help] pub struct IrrefutableLetPatternsIfLetGuard { @@ -548,7 +550,7 @@ pub struct IrrefutableLetPatternsIfLetGuard { } #[derive(LintDiagnostic)] -#[diag(mir_build::irrefutable_let_patterns_let_else)] +#[diag(mir_build_irrefutable_let_patterns_let_else)] #[note] #[help] pub struct IrrefutableLetPatternsLetElse { @@ -556,22 +558,22 @@ pub struct IrrefutableLetPatternsLetElse { } #[derive(LintDiagnostic)] -#[diag(mir_build::irrefutable_let_patterns_while_let)] +#[diag(mir_build_irrefutable_let_patterns_while_let)] #[note] #[help] pub struct IrrefutableLetPatternsWhileLet { pub count: usize, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::borrow_of_moved_value)] +#[derive(Diagnostic)] +#[diag(mir_build_borrow_of_moved_value)] pub struct BorrowOfMovedValue<'tcx> { #[primary_span] pub span: Span, #[label] - #[label(mir_build::occurs_because_label)] + #[label(occurs_because_label)] pub binding_span: Span, - #[label(mir_build::value_borrowed_label)] + #[label(value_borrowed_label)] pub conflicts_ref: Vec, pub name: Ident, pub ty: Ty<'tcx>, @@ -579,33 +581,33 @@ pub struct BorrowOfMovedValue<'tcx> { pub suggest_borrowing: Option, } -#[derive(SessionDiagnostic)] -#[diag(mir_build::multiple_mut_borrows)] +#[derive(Diagnostic)] +#[diag(mir_build_multiple_mut_borrows)] pub struct MultipleMutBorrows { #[primary_span] pub span: Span, #[label] pub binding_span: Span, - #[subdiagnostic] + #[subdiagnostic(eager)] pub occurences: Vec, pub name: Ident, } -#[derive(SessionSubdiagnostic)] +#[derive(Subdiagnostic)] pub enum MultipleMutBorrowOccurence { - #[label(mir_build::mutable_borrow)] + #[label(mutable_borrow)] Mutable { #[primary_span] span: Span, name_mut: Ident, }, - #[label(mir_build::immutable_borrow)] + #[label(immutable_borrow)] Immutable { #[primary_span] span: Span, name_immut: Ident, }, - #[label(mir_build::moved)] + #[label(moved)] Moved { #[primary_span] span: Span, diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 374942ee798b8..ddd52114ecfe6 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -598,11 +598,6 @@ fn irrefutable_let_patterns( count: usize, span: Span, ) { - let span = match source { - LetSource::LetElse(span) => span, - _ => span, - }; - macro_rules! emit_diag { ($lint:tt) => {{ tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, id, span, $lint { count }); @@ -613,7 +608,7 @@ fn irrefutable_let_patterns( LetSource::GenericLet => emit_diag!(IrrefutableLetPatternsGenericLet), LetSource::IfLet => emit_diag!(IrrefutableLetPatternsIfLet), LetSource::IfLetGuard => emit_diag!(IrrefutableLetPatternsIfLetGuard), - LetSource::LetElse(..) => emit_diag!(IrrefutableLetPatternsLetElse), + LetSource::LetElse => emit_diag!(IrrefutableLetPatternsLetElse), LetSource::WhileLet => emit_diag!(IrrefutableLetPatternsWhileLet), } } @@ -968,7 +963,10 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa conflicts_ref, name, ty: typeck_results.node_type(pat.hir_id), - suggest_borrowing: pat.span.contains(binding_span).then(|| binding_span.shrink_to_lo()), + suggest_borrowing: pat + .span + .contains(binding_span) + .then(|| binding_span.shrink_to_lo()), }); } return; @@ -1001,16 +999,15 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa // Report mutability conflicts for e.g. `ref mut x @ Some(ref mut y)`. let mut occurences = vec![]; - for (span, name) in conflicts_mut_mut { - occurences.push(MultipleMutBorrowOccurence::Mutable { span, name_mut: name }); + for (span, name_mut) in conflicts_mut_mut { + occurences.push(MultipleMutBorrowOccurence::Mutable { span, name_mut }); } - for (span, name) in conflicts_mut_ref { - occurences.push(MultipleMutBorrowOccurence::Immutable { span, name_immut: name }); + for (span, name_immut) in conflicts_mut_ref { + occurences.push(MultipleMutBorrowOccurence::Immutable { span, name_immut }); } - for (span, name) in conflicts_move { - occurences.push(MultipleMutBorrowOccurence::Moved { span, name_moved: name }); + for (span, name_moved) in conflicts_move { + occurences.push(MultipleMutBorrowOccurence::Moved { span, name_moved }); } - sess.emit_err(MultipleMutBorrows { span: pat.span, binding_span, occurences, name }); } else if !conflicts_mut_ref.is_empty() { // Report mutability conflicts for e.g. `ref x @ Some(ref mut y)` or the converse. diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index b7d1dc8c95656..2c775b397182b 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -565,7 +565,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { _ => bug!("Expected ConstKind::Param"), }, mir::ConstantKind::Val(_, _) => self.const_to_pat(value, id, span, false).kind, - mir::ConstKind::Unevaluated(_) => { + mir::ConstantKind::Unevaluated(..) => { // If we land here it means the const can't be evaluated because it's `TooGeneric`. self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span }); return PatKind::Wild; From 6749ee4d7b7a2f6fd57cf15fdb7332d6e94289dc Mon Sep 17 00:00:00 2001 From: mejrs <> Date: Sat, 17 Dec 2022 19:20:44 +0100 Subject: [PATCH 17/18] Remove (eager) --- compiler/rustc_mir_build/src/errors.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index f3bfafb37b77f..68179001b916d 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -588,7 +588,7 @@ pub struct MultipleMutBorrows { pub span: Span, #[label] pub binding_span: Span, - #[subdiagnostic(eager)] + #[subdiagnostic] pub occurences: Vec, pub name: Ident, } From f7e894c000d6526c32422c6282ce277c05499a94 Mon Sep 17 00:00:00 2001 From: mejrs <> Date: Sat, 17 Dec 2022 20:11:25 +0100 Subject: [PATCH 18/18] Try to fix ICE --- .../rustc_mir_build/src/thir/pattern/check_match.rs | 6 +++++- src/test/ui/lint/lint-uppercase-variables.rs | 10 +++++----- src/test/ui/lint/lint-uppercase-variables.stderr | 12 ++++++------ 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index ddd52114ecfe6..a94d8d6c6431c 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -17,7 +17,9 @@ use rustc_hir::def::*; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{HirId, Pat}; +use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; + use rustc_session::lint::builtin::{ BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS, }; @@ -547,7 +549,9 @@ fn check_for_bindings_named_same_as_variants( }) { let variant_count = edef.variants().len(); - let ty_path = cx.tcx.def_path_str(edef.did()); + let ty_path = with_no_trimmed_paths!({ + cx.tcx.def_path_str(edef.did()) + }); cx.tcx.emit_spanned_lint( BINDINGS_WITH_VARIANT_NAME, p.hir_id, diff --git a/src/test/ui/lint/lint-uppercase-variables.rs b/src/test/ui/lint/lint-uppercase-variables.rs index b590fa697adb3..d4e88aa264361 100644 --- a/src/test/ui/lint/lint-uppercase-variables.rs +++ b/src/test/ui/lint/lint-uppercase-variables.rs @@ -20,19 +20,19 @@ fn main() { match foo::Foo::Foo { Foo => {} -//~^ ERROR variable `Foo` should have a snake case name -//~^^ WARN `Foo` is named the same as one of the variants of the type `Foo` -//~^^^ WARN unused variable: `Foo` + //~^ ERROR variable `Foo` should have a snake case name + //~^^ WARN `Foo` is named the same as one of the variants of the type `foo::Foo` + //~^^^ WARN unused variable: `Foo` } let Foo = foo::Foo::Foo; //~^ ERROR variable `Foo` should have a snake case name - //~^^ WARN `Foo` is named the same as one of the variants of the type `Foo` + //~^^ WARN `Foo` is named the same as one of the variants of the type `foo::Foo` //~^^^ WARN unused variable: `Foo` fn in_param(Foo: foo::Foo) {} //~^ ERROR variable `Foo` should have a snake case name - //~^^ WARN `Foo` is named the same as one of the variants of the type `Foo` + //~^^ WARN `Foo` is named the same as one of the variants of the type `foo::Foo` //~^^^ WARN unused variable: `Foo` test(1); diff --git a/src/test/ui/lint/lint-uppercase-variables.stderr b/src/test/ui/lint/lint-uppercase-variables.stderr index 71b24a835bcd9..d476d856e24c5 100644 --- a/src/test/ui/lint/lint-uppercase-variables.stderr +++ b/src/test/ui/lint/lint-uppercase-variables.stderr @@ -1,22 +1,22 @@ -warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `Foo` +warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo` --> $DIR/lint-uppercase-variables.rs:22:9 | LL | Foo => {} - | ^^^ help: to match on the variant, qualify the path: `Foo::Foo` + | ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo` | = note: `#[warn(bindings_with_variant_name)]` on by default -warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `Foo` +warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo` --> $DIR/lint-uppercase-variables.rs:28:9 | LL | let Foo = foo::Foo::Foo; - | ^^^ help: to match on the variant, qualify the path: `Foo::Foo` + | ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo` -warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `Foo` +warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo` --> $DIR/lint-uppercase-variables.rs:33:17 | LL | fn in_param(Foo: foo::Foo) {} - | ^^^ help: to match on the variant, qualify the path: `Foo::Foo` + | ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo` warning: unused variable: `Foo` --> $DIR/lint-uppercase-variables.rs:22:9