diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 91b1506d1e4e5..24c5377a3b125 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -373,10 +373,6 @@ hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a t hir_analysis_parenthesized_fn_trait_expansion = parenthesized trait syntax expands to `{$expanded_type}` -hir_analysis_pass_to_variadic_function = can't pass `{$ty}` to variadic function - .suggestion = cast the value to `{$cast_ty}` - .help = cast the value to `{$cast_ty}` - hir_analysis_pattern_type_non_const_range = range patterns must have constant range start and end hir_analysis_pattern_type_wild_pat = wildcard patterns are not permitted for pattern types .label = this type is the same as the inner type without a pattern diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 7d44ac458de86..0ee87a13e9e37 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -9,6 +9,7 @@ use rustc_middle::ty::Ty; use rustc_span::{symbol::Ident, Span, Symbol}; mod pattern_types; pub use pattern_types::*; +pub mod wrong_number_of_generic_args; mod precise_captures; pub(crate) use precise_captures::*; @@ -692,20 +693,6 @@ pub(crate) struct TypeOf<'tcx> { pub ty: Ty<'tcx>, } -#[derive(Diagnostic)] -#[diag(hir_analysis_pass_to_variadic_function, code = E0617)] -pub(crate) struct PassToVariadicFunction<'tcx, 'a> { - #[primary_span] - pub span: Span, - pub ty: Ty<'tcx>, - pub cast_ty: &'a str, - #[suggestion(code = "{replace}", applicability = "machine-applicable")] - pub sugg_span: Option, - pub replace: String, - #[help] - pub help: Option<()>, -} - #[derive(Diagnostic)] #[diag(hir_analysis_invalid_union_field, code = E0740)] pub(crate) struct InvalidUnionField { diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs similarity index 96% rename from compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs rename to compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs index 5d435a8edf9ff..6426ad9dc184f 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs @@ -1,8 +1,8 @@ -use crate::structured_errors::StructuredDiag; -use rustc_errors::{codes::*, pluralize, Applicability, Diag, MultiSpan}; +use rustc_errors::{ + codes::*, pluralize, Applicability, Diag, Diagnostic, EmissionGuarantee, MultiSpan, +}; use rustc_hir as hir; use rustc_middle::ty::{self as ty, AssocItems, AssocKind, TyCtxt}; -use rustc_session::Session; use rustc_span::def_id::DefId; use std::iter; @@ -541,14 +541,8 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } } - fn start_diagnostics(&self) -> Diag<'tcx> { - let span = self.path_segment.ident.span; - let msg = self.create_error_message(); - self.tcx.dcx().struct_span_err(span, msg).with_code(self.code()) - } - /// Builds the `expected 1 type argument / supplied 2 type arguments` message. - fn notify(&self, err: &mut Diag<'_>) { + fn notify(&self, err: &mut Diag<'_, impl EmissionGuarantee>) { let (quantifier, bound) = self.get_quantifier_and_bound(); let provided_args = self.num_provided_args(); @@ -600,7 +594,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } } - fn suggest(&self, err: &mut Diag<'_>) { + fn suggest(&self, err: &mut Diag<'_, impl EmissionGuarantee>) { debug!( "suggest(self.provided {:?}, self.gen_args.span(): {:?})", self.num_provided_args(), @@ -628,7 +622,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { /// ```text /// type Map = HashMap; /// ``` - fn suggest_adding_args(&self, err: &mut Diag<'_>) { + fn suggest_adding_args(&self, err: &mut Diag<'_, impl EmissionGuarantee>) { if self.gen_args.parenthesized != hir::GenericArgsParentheses::No { return; } @@ -647,7 +641,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } } - fn suggest_adding_lifetime_args(&self, err: &mut Diag<'_>) { + fn suggest_adding_lifetime_args(&self, err: &mut Diag<'_, impl EmissionGuarantee>) { debug!("suggest_adding_lifetime_args(path_segment: {:?})", self.path_segment); let num_missing_args = self.num_missing_lifetime_args(); let num_params_to_take = num_missing_args; @@ -701,7 +695,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } } - fn suggest_adding_type_and_const_args(&self, err: &mut Diag<'_>) { + fn suggest_adding_type_and_const_args(&self, err: &mut Diag<'_, impl EmissionGuarantee>) { let num_missing_args = self.num_missing_type_or_const_args(); let msg = format!("add missing {} argument{}", self.kind(), pluralize!(num_missing_args)); @@ -761,7 +755,10 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { /// ```compile_fail /// Into::into::>(42) // suggests considering `Into::>::into(42)` /// ``` - fn suggest_moving_args_from_assoc_fn_to_trait(&self, err: &mut Diag<'_>) { + fn suggest_moving_args_from_assoc_fn_to_trait( + &self, + err: &mut Diag<'_, impl EmissionGuarantee>, + ) { let trait_ = match self.tcx.trait_of_item(self.def_id) { Some(def_id) => def_id, None => return, @@ -817,7 +814,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { fn suggest_moving_args_from_assoc_fn_to_trait_for_qualified_path( &self, - err: &mut Diag<'_>, + err: &mut Diag<'_, impl EmissionGuarantee>, qpath: &'tcx hir::QPath<'tcx>, msg: String, num_assoc_fn_excess_args: usize, @@ -850,7 +847,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { fn suggest_moving_args_from_assoc_fn_to_trait_for_method_call( &self, - err: &mut Diag<'_>, + err: &mut Diag<'_, impl EmissionGuarantee>, trait_def_id: DefId, expr: &'tcx hir::Expr<'tcx>, msg: String, @@ -904,7 +901,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { /// ```text /// type Map = HashMap; /// ``` - fn suggest_removing_args_or_generics(&self, err: &mut Diag<'_>) { + fn suggest_removing_args_or_generics(&self, err: &mut Diag<'_, impl EmissionGuarantee>) { let num_provided_lt_args = self.num_provided_lifetime_args(); let num_provided_type_const_args = self.num_provided_type_or_const_args(); let unbound_types = self.get_unbound_associated_types(); @@ -922,7 +919,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { let provided_args_matches_unbound_traits = unbound_types.len() == num_redundant_type_or_const_args; - let remove_lifetime_args = |err: &mut Diag<'_>| { + let remove_lifetime_args = |err: &mut Diag<'_, _>| { let mut lt_arg_spans = Vec::new(); let mut found_redundant = false; for arg in self.gen_args.args { @@ -963,7 +960,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { ); }; - let remove_type_or_const_args = |err: &mut Diag<'_>| { + let remove_type_or_const_args = |err: &mut Diag<'_, _>| { let mut gen_arg_spans = Vec::new(); let mut found_redundant = false; for arg in self.gen_args.args { @@ -1060,7 +1057,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } /// Builds the `type defined here` message. - fn show_definition(&self, err: &mut Diag<'_>) { + fn show_definition(&self, err: &mut Diag<'_, impl EmissionGuarantee>) { let mut spans: MultiSpan = if let Some(def_span) = self.tcx.def_ident_span(self.def_id) { if self.tcx.sess.source_map().is_span_accessible(def_span) { def_span.into() @@ -1111,7 +1108,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } /// Add note if `impl Trait` is explicitly specified. - fn note_synth_provided(&self, err: &mut Diag<'_>) { + fn note_synth_provided(&self, err: &mut Diag<'_, impl EmissionGuarantee>) { if !self.is_synth_provided() { return; } @@ -1120,17 +1117,16 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } } -impl<'tcx> StructuredDiag<'tcx> for WrongNumberOfGenericArgs<'_, 'tcx> { - fn session(&self) -> &Session { - self.tcx.sess - } - - fn code(&self) -> ErrCode { - E0107 - } - - fn diagnostic_common(&self) -> Diag<'tcx> { - let mut err = self.start_diagnostics(); +impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for WrongNumberOfGenericArgs<'_, '_> { + fn into_diag( + self, + dcx: rustc_errors::DiagCtxtHandle<'a>, + level: rustc_errors::Level, + ) -> Diag<'a, G> { + let msg = self.create_error_message(); + let mut err = Diag::new(dcx, level, msg); + err.code(E0107); + err.span(self.path_segment.ident.span); self.notify(&mut err); self.suggest(&mut err); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index e92c377f0ce2a..90836f0a54f45 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -1,9 +1,9 @@ use super::IsMethodCall; +use crate::errors::wrong_number_of_generic_args::{GenericArgsInfo, WrongNumberOfGenericArgs}; use crate::hir_ty_lowering::{ errors::prohibit_assoc_item_constraint, ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition, GenericArgsLowerer, }; -use crate::structured_errors::{GenericArgsInfo, StructuredDiag, WrongNumberOfGenericArgs}; use rustc_ast::ast::ParamKindOrd; use rustc_errors::{ codes::*, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, MultiSpan, @@ -486,7 +486,7 @@ pub(crate) fn check_generic_arg_count( GenericArgsInfo::MissingLifetimes { num_missing_args } }; - let reported = WrongNumberOfGenericArgs::new( + let reported = tcx.dcx().emit_err(WrongNumberOfGenericArgs::new( tcx, gen_args_info, seg, @@ -494,9 +494,7 @@ pub(crate) fn check_generic_arg_count( has_self as usize, gen_args, def_id, - ) - .diagnostic() - .emit(); + )); Err(reported) }; @@ -573,17 +571,17 @@ pub(crate) fn check_generic_arg_count( debug!(?gen_args_info); let reported = gen_args.has_err().unwrap_or_else(|| { - WrongNumberOfGenericArgs::new( - tcx, - gen_args_info, - seg, - gen_params, - params_offset, - gen_args, - def_id, - ) - .diagnostic() - .emit_unless(all_params_are_binded) + tcx.dcx() + .create_err(WrongNumberOfGenericArgs::new( + tcx, + gen_args_info, + seg, + gen_params, + params_offset, + gen_args, + def_id, + )) + .emit_unless(all_params_are_binded) }); Err(reported) diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 2f6b0a582e58c..dd7fbba753bdd 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -92,7 +92,6 @@ mod errors; pub mod hir_wf_check; mod impl_wf_check; mod outlives; -pub mod structured_errors; mod variance; use rustc_hir as hir; diff --git a/compiler/rustc_hir_analysis/src/structured_errors.rs b/compiler/rustc_hir_analysis/src/structured_errors.rs deleted file mode 100644 index 61a2400f9e434..0000000000000 --- a/compiler/rustc_hir_analysis/src/structured_errors.rs +++ /dev/null @@ -1,33 +0,0 @@ -mod missing_cast_for_variadic_arg; -mod wrong_number_of_generic_args; - -pub use self::{missing_cast_for_variadic_arg::*, wrong_number_of_generic_args::*}; - -use rustc_errors::{Diag, ErrCode}; -use rustc_session::Session; - -pub trait StructuredDiag<'tcx> { - fn session(&self) -> &Session; - - fn code(&self) -> ErrCode; - - fn diagnostic(&self) -> Diag<'tcx> { - let err = self.diagnostic_common(); - - if self.session().teach(self.code()) { - self.diagnostic_extended(err) - } else { - self.diagnostic_regular(err) - } - } - - fn diagnostic_common(&self) -> Diag<'tcx>; - - fn diagnostic_regular(&self, err: Diag<'tcx>) -> Diag<'tcx> { - err - } - - fn diagnostic_extended(&self, err: Diag<'tcx>) -> Diag<'tcx> { - err - } -} diff --git a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs deleted file mode 100644 index 0e78acbeae2d4..0000000000000 --- a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs +++ /dev/null @@ -1,57 +0,0 @@ -use crate::{errors, structured_errors::StructuredDiag}; -use rustc_errors::{codes::*, Diag}; -use rustc_middle::ty::{Ty, TypeVisitableExt}; -use rustc_session::Session; -use rustc_span::Span; - -pub struct MissingCastForVariadicArg<'tcx, 's> { - pub sess: &'tcx Session, - pub span: Span, - pub ty: Ty<'tcx>, - pub cast_ty: &'s str, -} - -impl<'tcx> StructuredDiag<'tcx> for MissingCastForVariadicArg<'tcx, '_> { - fn session(&self) -> &Session { - self.sess - } - - fn code(&self) -> ErrCode { - E0617 - } - - fn diagnostic_common(&self) -> Diag<'tcx> { - let (sugg_span, replace, help) = - if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.span) { - (Some(self.span), format!("{} as {}", snippet, self.cast_ty), None) - } else { - (None, "".to_string(), Some(())) - }; - - let mut err = self.sess.dcx().create_err(errors::PassToVariadicFunction { - span: self.span, - ty: self.ty, - cast_ty: self.cast_ty, - help, - replace, - sugg_span, - }); - - if self.ty.references_error() { - err.downgrade_to_delayed_bug(); - } - - err - } - - fn diagnostic_extended(&self, mut err: Diag<'tcx>) -> Diag<'tcx> { - err.note(format!( - "certain types, like `{}`, must be casted before passing them to a \ - variadic function, because of arcane ABI rules dictated by the C \ - standard", - self.ty - )); - - err - } -} diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 239b0c4469027..39d430cf73b76 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -38,6 +38,7 @@ hir_typeck_cast_thin_pointer_to_fat_pointer = cannot cast thin pointer `{$expr_t For more information about casts, take a look at The Book: https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions", + hir_typeck_cast_unknown_pointer = cannot cast {$to -> [true] to *[false] from @@ -138,6 +139,11 @@ hir_typeck_option_result_asref = use `{$def_path}::as_ref` to convert `{$expecte hir_typeck_option_result_cloned = use `{$def_path}::cloned` to clone the value inside the `{$def_path}` hir_typeck_option_result_copied = use `{$def_path}::copied` to copy the value inside the `{$def_path}` +hir_typeck_pass_to_variadic_function = can't pass `{$ty}` to variadic function + .suggestion = cast the value to `{$cast_ty}` + .help = cast the value to `{$cast_ty}` + .teach_help = certain types, like `{$ty}`, must be casted before passing them to a variadic function, because of arcane ABI rules dictated by the C standard + hir_typeck_ptr_cast_add_auto_to_object = adding {$traits_len -> [1] an auto trait {$traits} *[other] auto traits {$traits} diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 8b5b0a9b92f29..9a38d6d4a7195 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -708,3 +708,19 @@ pub(crate) struct CastThinPointerToFatPointer<'tcx> { #[note(hir_typeck_teach_help)] pub(crate) teach: Option<()>, } + +#[derive(Diagnostic)] +#[diag(hir_typeck_pass_to_variadic_function, code = E0617)] +pub(crate) struct PassToVariadicFunction<'tcx, 'a> { + #[primary_span] + pub span: Span, + pub ty: Ty<'tcx>, + pub cast_ty: &'a str, + #[suggestion(code = "{replace}", applicability = "machine-applicable")] + pub sugg_span: Option, + pub replace: String, + #[help] + pub help: Option<()>, + #[note(hir_typeck_teach_help)] + pub(crate) teach: Option<()>, +} diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 10092dce58766..ab0f356ce91f1 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -28,7 +28,6 @@ use rustc_hir::{ExprKind, HirId, Node, QPath}; use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt; use rustc_hir_analysis::check::potentially_plural_count; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; -use rustc_hir_analysis::structured_errors::StructuredDiag; use rustc_index::IndexVec; use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt}; use rustc_infer::infer::TypeTrace; @@ -406,9 +405,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty: Ty<'tcx>, cast_ty: &str, ) { - use rustc_hir_analysis::structured_errors::MissingCastForVariadicArg; + let (sugg_span, replace, help) = + if let Ok(snippet) = sess.source_map().span_to_snippet(span) { + (Some(span), format!("{snippet} as {cast_ty}"), None) + } else { + (None, "".to_string(), Some(())) + }; - MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit(); + sess.dcx().emit_err(errors::PassToVariadicFunction { + span, + ty, + cast_ty, + help, + replace, + sugg_span, + teach: sess.teach(E0617).then_some(()), + }); } // There are a few types which get autopromoted when passed via varargs