diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:11:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:11:28 +0000 |
commit | 94a0819fe3a0d679c3042a77bfe6a2afc505daea (patch) | |
tree | 2b827afe6a05f3538db3f7803a88c4587fe85648 /compiler/rustc_typeck/src/structured_errors | |
parent | Adding upstream version 1.64.0+dfsg1. (diff) | |
download | rustc-94a0819fe3a0d679c3042a77bfe6a2afc505daea.tar.xz rustc-94a0819fe3a0d679c3042a77bfe6a2afc505daea.zip |
Adding upstream version 1.66.0+dfsg1.upstream/1.66.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_typeck/src/structured_errors')
3 files changed, 0 insertions, 1013 deletions
diff --git a/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs b/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs deleted file mode 100644 index 324df313e..000000000 --- a/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs +++ /dev/null @@ -1,61 +0,0 @@ -use crate::structured_errors::StructuredDiagnostic; -use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId, ErrorGuaranteed}; -use rustc_middle::ty::{Ty, TypeVisitable}; -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> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx, '_> { - fn session(&self) -> &Session { - self.sess - } - - fn code(&self) -> DiagnosticId { - rustc_errors::error_code!(E0617) - } - - fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let mut err = self.sess.struct_span_err_with_code( - self.span, - &format!("can't pass `{}` to variadic function", self.ty), - self.code(), - ); - - if self.ty.references_error() { - err.downgrade_to_delayed_bug(); - } - - if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.span) { - err.span_suggestion( - self.span, - &format!("cast the value to `{}`", self.cast_ty), - format!("{} as {}", snippet, self.cast_ty), - Applicability::MachineApplicable, - ); - } else { - err.help(&format!("cast the value to `{}`", self.cast_ty)); - } - - err - } - - fn diagnostic_extended( - &self, - mut err: DiagnosticBuilder<'tcx, ErrorGuaranteed>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - 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_typeck/src/structured_errors/sized_unsized_cast.rs b/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs deleted file mode 100644 index bb6088054..000000000 --- a/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs +++ /dev/null @@ -1,62 +0,0 @@ -use crate::structured_errors::StructuredDiagnostic; -use rustc_errors::{DiagnosticBuilder, DiagnosticId, ErrorGuaranteed}; -use rustc_middle::ty::{Ty, TypeVisitable}; -use rustc_session::Session; -use rustc_span::Span; - -pub struct SizedUnsizedCast<'tcx> { - pub sess: &'tcx Session, - pub span: Span, - pub expr_ty: Ty<'tcx>, - pub cast_ty: String, -} - -impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> { - fn session(&self) -> &Session { - self.sess - } - - fn code(&self) -> DiagnosticId { - rustc_errors::error_code!(E0607) - } - - fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let mut err = self.sess.struct_span_err_with_code( - self.span, - &format!( - "cannot cast thin pointer `{}` to fat pointer `{}`", - self.expr_ty, self.cast_ty - ), - self.code(), - ); - - if self.expr_ty.references_error() { - err.downgrade_to_delayed_bug(); - } - - err - } - - fn diagnostic_extended( - &self, - mut err: DiagnosticBuilder<'tcx, ErrorGuaranteed>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - err.help( - "Thin pointers are \"simple\" pointers: they are purely a reference to a -memory address. - -Fat pointers are pointers referencing \"Dynamically Sized Types\" (also -called DST). DST don't have a statically known size, therefore they can -only exist behind some kind of pointers that contain additional -information. Slices and trait objects are DSTs. In the case of slices, -the additional information the fat pointer holds is their size. - -To fix this error, don't try to cast directly between thin and fat -pointers. - -For more information about casts, take a look at The Book: -https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions", - ); - err - } -} diff --git a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs deleted file mode 100644 index 99729391e..000000000 --- a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs +++ /dev/null @@ -1,890 +0,0 @@ -use crate::structured_errors::StructuredDiagnostic; -use rustc_errors::{ - pluralize, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorGuaranteed, - MultiSpan, -}; -use rustc_hir as hir; -use rustc_middle::hir::map::fn_sig; -use rustc_middle::ty::{self as ty, AssocItems, AssocKind, TyCtxt}; -use rustc_session::Session; -use rustc_span::def_id::DefId; -use std::iter; - -use GenericArgsInfo::*; - -/// Handles the `wrong number of type / lifetime / ... arguments` family of error messages. -pub struct WrongNumberOfGenericArgs<'a, 'tcx> { - pub(crate) tcx: TyCtxt<'tcx>, - - pub(crate) angle_brackets: AngleBrackets, - - pub(crate) gen_args_info: GenericArgsInfo, - - /// Offending path segment - pub(crate) path_segment: &'a hir::PathSegment<'a>, - - /// Generic parameters as expected by type or trait - pub(crate) gen_params: &'a ty::Generics, - - /// Index offset into parameters. Depends on whether `Self` is included and on - /// number of lifetime parameters in case we're processing missing or redundant - /// type or constant arguments. - pub(crate) params_offset: usize, - - /// Generic arguments as provided by user - pub(crate) gen_args: &'a hir::GenericArgs<'a>, - - /// DefId of the generic type - pub(crate) def_id: DefId, -} - -// Provides information about the kind of arguments that were provided for -// the PathSegment, for which missing generic arguments were detected -#[derive(Debug)] -pub(crate) enum AngleBrackets { - // No angle brackets were provided, but generic arguments exist in elided form - Implied, - - // No angle brackets were provided - Missing, - - // Angle brackets are available, but missing some generic arguments - Available, -} - -// Information about the kind of arguments that are either missing or are unexpected -#[derive(Debug)] -pub enum GenericArgsInfo { - MissingLifetimes { - num_missing_args: usize, - }, - ExcessLifetimes { - num_redundant_args: usize, - }, - MissingTypesOrConsts { - num_missing_args: usize, - - // type or const generic arguments can have default values - num_default_params: usize, - - // lifetime arguments precede type and const parameters, this - // field gives the number of generic lifetime arguments to let - // us infer the position of type and const generic arguments - // in the angle brackets - args_offset: usize, - }, - - ExcessTypesOrConsts { - num_redundant_args: usize, - - // type or const generic arguments can have default values - num_default_params: usize, - - // lifetime arguments precede type and const parameters, this - // field gives the number of generic lifetime arguments to let - // us infer the position of type and const generic arguments - // in the angle brackets - args_offset: usize, - - // if synthetic type arguments (e.g. `impl Trait`) are specified - synth_provided: bool, - }, -} - -impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { - pub fn new( - tcx: TyCtxt<'tcx>, - gen_args_info: GenericArgsInfo, - path_segment: &'a hir::PathSegment<'_>, - gen_params: &'a ty::Generics, - params_offset: usize, - gen_args: &'a hir::GenericArgs<'a>, - def_id: DefId, - ) -> Self { - let angle_brackets = if gen_args.span_ext().is_none() { - if gen_args.is_empty() { AngleBrackets::Missing } else { AngleBrackets::Implied } - } else { - AngleBrackets::Available - }; - - Self { - tcx, - angle_brackets, - gen_args_info, - path_segment, - gen_params, - params_offset, - gen_args, - def_id, - } - } - - fn missing_lifetimes(&self) -> bool { - match self.gen_args_info { - MissingLifetimes { .. } | ExcessLifetimes { .. } => true, - MissingTypesOrConsts { .. } | ExcessTypesOrConsts { .. } => false, - } - } - - fn kind(&self) -> &str { - if self.missing_lifetimes() { "lifetime" } else { "generic" } - } - - fn num_provided_args(&self) -> usize { - if self.missing_lifetimes() { - self.num_provided_lifetime_args() - } else { - self.num_provided_type_or_const_args() - } - } - - fn num_provided_lifetime_args(&self) -> usize { - match self.angle_brackets { - AngleBrackets::Missing => 0, - // Only lifetime arguments can be implied - AngleBrackets::Implied => self.gen_args.args.len(), - AngleBrackets::Available => self.gen_args.num_lifetime_params(), - } - } - - fn num_provided_type_or_const_args(&self) -> usize { - match self.angle_brackets { - AngleBrackets::Missing => 0, - // Only lifetime arguments can be implied - AngleBrackets::Implied => 0, - AngleBrackets::Available => self.gen_args.num_generic_params(), - } - } - - fn num_expected_lifetime_args(&self) -> usize { - let num_provided_args = self.num_provided_lifetime_args(); - match self.gen_args_info { - MissingLifetimes { num_missing_args } => num_provided_args + num_missing_args, - ExcessLifetimes { num_redundant_args } => num_provided_args - num_redundant_args, - _ => 0, - } - } - - fn num_expected_type_or_const_args(&self) -> usize { - let num_provided_args = self.num_provided_type_or_const_args(); - match self.gen_args_info { - MissingTypesOrConsts { num_missing_args, .. } => num_provided_args + num_missing_args, - ExcessTypesOrConsts { num_redundant_args, .. } => { - num_provided_args - num_redundant_args - } - _ => 0, - } - } - - // Gives the number of expected arguments taking into account default arguments - fn num_expected_type_or_const_args_including_defaults(&self) -> usize { - let provided_args = self.num_provided_type_or_const_args(); - match self.gen_args_info { - MissingTypesOrConsts { num_missing_args, num_default_params, .. } => { - provided_args + num_missing_args - num_default_params - } - ExcessTypesOrConsts { num_redundant_args, num_default_params, .. } => { - provided_args - num_redundant_args - num_default_params - } - _ => 0, - } - } - - fn num_missing_lifetime_args(&self) -> usize { - let missing_args = self.num_expected_lifetime_args() - self.num_provided_lifetime_args(); - assert!(missing_args > 0); - missing_args - } - - fn num_missing_type_or_const_args(&self) -> usize { - let missing_args = self.num_expected_type_or_const_args_including_defaults() - - self.num_provided_type_or_const_args(); - assert!(missing_args > 0); - missing_args - } - - fn num_excess_lifetime_args(&self) -> usize { - match self.gen_args_info { - ExcessLifetimes { num_redundant_args } => num_redundant_args, - _ => 0, - } - } - - fn num_excess_type_or_const_args(&self) -> usize { - match self.gen_args_info { - ExcessTypesOrConsts { num_redundant_args, .. } => num_redundant_args, - _ => 0, - } - } - - fn too_many_args_provided(&self) -> bool { - match self.gen_args_info { - MissingLifetimes { .. } | MissingTypesOrConsts { .. } => false, - ExcessLifetimes { num_redundant_args } - | ExcessTypesOrConsts { num_redundant_args, .. } => { - assert!(num_redundant_args > 0); - true - } - } - } - - fn not_enough_args_provided(&self) -> bool { - match self.gen_args_info { - MissingLifetimes { num_missing_args } - | MissingTypesOrConsts { num_missing_args, .. } => { - assert!(num_missing_args > 0); - true - } - ExcessLifetimes { .. } | ExcessTypesOrConsts { .. } => false, - } - } - - // Helper method to get the index offset in angle brackets, at which type or const arguments - // start appearing - fn get_lifetime_args_offset(&self) -> usize { - match self.gen_args_info { - MissingLifetimes { .. } | ExcessLifetimes { .. } => 0, - MissingTypesOrConsts { args_offset, .. } | ExcessTypesOrConsts { args_offset, .. } => { - args_offset - } - } - } - - fn get_num_default_params(&self) -> usize { - match self.gen_args_info { - MissingTypesOrConsts { num_default_params, .. } - | ExcessTypesOrConsts { num_default_params, .. } => num_default_params, - _ => 0, - } - } - - fn is_synth_provided(&self) -> bool { - match self.gen_args_info { - ExcessTypesOrConsts { synth_provided, .. } => synth_provided, - _ => false, - } - } - - // Helper function to choose a quantifier word for the number of expected arguments - // and to give a bound for the number of expected arguments - fn get_quantifier_and_bound(&self) -> (&'static str, usize) { - if self.get_num_default_params() == 0 { - match self.gen_args_info { - MissingLifetimes { .. } | ExcessLifetimes { .. } => { - ("", self.num_expected_lifetime_args()) - } - MissingTypesOrConsts { .. } | ExcessTypesOrConsts { .. } => { - ("", self.num_expected_type_or_const_args()) - } - } - } else { - match self.gen_args_info { - MissingLifetimes { .. } => ("at least ", self.num_expected_lifetime_args()), - MissingTypesOrConsts { .. } => { - ("at least ", self.num_expected_type_or_const_args_including_defaults()) - } - ExcessLifetimes { .. } => ("at most ", self.num_expected_lifetime_args()), - ExcessTypesOrConsts { .. } => ("at most ", self.num_expected_type_or_const_args()), - } - } - } - - // Creates lifetime name suggestions from the lifetime parameter names - fn get_lifetime_args_suggestions_from_param_names( - &self, - path_hir_id: Option<hir::HirId>, - num_params_to_take: usize, - ) -> String { - debug!(?path_hir_id); - - if let Some(path_hir_id) = path_hir_id { - let mut ret = Vec::new(); - for (id, node) in self.tcx.hir().parent_iter(path_hir_id) { - debug!(?id); - let params = if let Some(generics) = node.generics() { - generics.params - } else if let hir::Node::Ty(ty) = node - && let hir::TyKind::BareFn(bare_fn) = ty.kind - { - bare_fn.generic_params - } else { - &[] - }; - ret.extend(params.iter().filter_map(|p| { - let hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit } - = p.kind - else { return None }; - let hir::ParamName::Plain(name) = p.name else { return None }; - Some(name.to_string()) - })); - // Suggest `'static` when in const/static item-like. - if let hir::Node::Item(hir::Item { - kind: hir::ItemKind::Static { .. } | hir::ItemKind::Const { .. }, - .. - }) - | hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Const { .. }, - .. - }) - | hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Const { .. }, - .. - }) - | hir::Node::ForeignItem(hir::ForeignItem { - kind: hir::ForeignItemKind::Static { .. }, - .. - }) - | hir::Node::AnonConst(..) = node - { - ret.extend( - std::iter::repeat("'static".to_owned()) - .take(num_params_to_take.saturating_sub(ret.len())), - ); - } - if ret.len() >= num_params_to_take { - return ret[..num_params_to_take].join(", "); - } - // We cannot refer to lifetimes defined in an outer function. - if let hir::Node::Item(_) = node { - break; - } - } - } - - // We could not gather enough lifetime parameters in the scope. - // We use the parameter names from the target type's definition instead. - self.gen_params - .params - .iter() - .skip(self.params_offset + self.num_provided_lifetime_args()) - .take(num_params_to_take) - .map(|param| param.name.to_string()) - .collect::<Vec<_>>() - .join(", ") - } - - // Creates type or constant name suggestions from the provided parameter names - fn get_type_or_const_args_suggestions_from_param_names( - &self, - num_params_to_take: usize, - ) -> String { - let fn_sig = self.tcx.hir().get_if_local(self.def_id).and_then(fn_sig); - let is_used_in_input = |def_id| { - fn_sig.map_or(false, |fn_sig| { - fn_sig.decl.inputs.iter().any(|ty| match ty.kind { - hir::TyKind::Path(hir::QPath::Resolved( - None, - hir::Path { res: hir::def::Res::Def(_, id), .. }, - )) => *id == def_id, - _ => false, - }) - }) - }; - self.gen_params - .params - .iter() - .skip(self.params_offset + self.num_provided_type_or_const_args()) - .take(num_params_to_take) - .map(|param| match param.kind { - // This is being inferred from the item's inputs, no need to set it. - ty::GenericParamDefKind::Type { .. } if is_used_in_input(param.def_id) => { - "_".to_string() - } - _ => param.name.to_string(), - }) - .collect::<Vec<_>>() - .join(", ") - } - - fn get_unbound_associated_types(&self) -> Vec<String> { - if self.tcx.is_trait(self.def_id) { - let items: &AssocItems<'_> = self.tcx.associated_items(self.def_id); - items - .in_definition_order() - .filter(|item| item.kind == AssocKind::Type) - .filter(|item| { - !self.gen_args.bindings.iter().any(|binding| binding.ident.name == item.name) - }) - .map(|item| item.name.to_ident_string()) - .collect() - } else { - Vec::default() - } - } - - fn create_error_message(&self) -> String { - let def_path = self.tcx.def_path_str(self.def_id); - let def_kind = self.tcx.def_kind(self.def_id).descr(self.def_id); - let (quantifier, bound) = self.get_quantifier_and_bound(); - let kind = self.kind(); - let provided_lt_args = self.num_provided_lifetime_args(); - let provided_type_or_const_args = self.num_provided_type_or_const_args(); - - let (provided_args_str, verb) = match self.gen_args_info { - MissingLifetimes { .. } | ExcessLifetimes { .. } => ( - format!("{} lifetime argument{}", provided_lt_args, pluralize!(provided_lt_args)), - pluralize!("was", provided_lt_args), - ), - MissingTypesOrConsts { .. } | ExcessTypesOrConsts { .. } => ( - format!( - "{} generic argument{}", - provided_type_or_const_args, - pluralize!(provided_type_or_const_args) - ), - pluralize!("was", provided_type_or_const_args), - ), - }; - - if self.gen_args.span_ext().is_some() { - format!( - "this {} takes {}{} {} argument{} but {} {} supplied", - def_kind, - quantifier, - bound, - kind, - pluralize!(bound), - provided_args_str.as_str(), - verb - ) - } else { - format!("missing generics for {} `{}`", def_kind, def_path) - } - } - - fn start_diagnostics(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let span = self.path_segment.ident.span; - let msg = self.create_error_message(); - - self.tcx.sess.struct_span_err_with_code(span, &msg, self.code()) - } - - /// Builds the `expected 1 type argument / supplied 2 type arguments` message. - fn notify(&self, err: &mut Diagnostic) { - let (quantifier, bound) = self.get_quantifier_and_bound(); - let provided_args = self.num_provided_args(); - - err.span_label( - self.path_segment.ident.span, - format!( - "expected {}{} {} argument{}", - quantifier, - bound, - self.kind(), - pluralize!(bound), - ), - ); - - // When too many arguments were provided, we don't highlight each of them, because it - // would overlap with the suggestion to remove them: - // - // ``` - // type Foo = Bar<usize, usize>; - // ----- ----- supplied 2 type arguments - // ^^^^^^^ remove this type argument - // ``` - if self.too_many_args_provided() { - return; - } - - let args = self - .gen_args - .args - .iter() - .skip(self.get_lifetime_args_offset()) - .take(provided_args) - .enumerate(); - - for (i, arg) in args { - err.span_label( - arg.span(), - if i + 1 == provided_args { - format!( - "supplied {} {} argument{}", - provided_args, - self.kind(), - pluralize!(provided_args) - ) - } else { - String::new() - }, - ); - } - } - - fn suggest(&self, err: &mut Diagnostic) { - debug!( - "suggest(self.provided {:?}, self.gen_args.span(): {:?})", - self.num_provided_args(), - self.gen_args.span(), - ); - - match self.angle_brackets { - AngleBrackets::Missing | AngleBrackets::Implied => self.suggest_adding_args(err), - AngleBrackets::Available => { - if self.not_enough_args_provided() { - self.suggest_adding_args(err); - } else if self.too_many_args_provided() { - self.suggest_removing_args_or_generics(err); - } else { - unreachable!(); - } - } - } - } - - /// Suggests to add missing argument(s) when current invocation site already contains some - /// generics: - /// - /// ```text - /// type Map = HashMap<String>; - /// ``` - fn suggest_adding_args(&self, err: &mut Diagnostic) { - if self.gen_args.parenthesized { - return; - } - - match self.gen_args_info { - MissingLifetimes { .. } => { - self.suggest_adding_lifetime_args(err); - } - MissingTypesOrConsts { .. } => { - self.suggest_adding_type_and_const_args(err); - } - _ => unreachable!(), - } - } - - fn suggest_adding_lifetime_args(&self, err: &mut Diagnostic) { - 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; - let msg = format!("add missing {} argument{}", self.kind(), pluralize!(num_missing_args)); - - let suggested_args = self.get_lifetime_args_suggestions_from_param_names( - self.path_segment.hir_id, - num_params_to_take, - ); - debug!("suggested_args: {:?}", &suggested_args); - - match self.angle_brackets { - AngleBrackets::Missing => { - let span = self.path_segment.ident.span; - - // insert a suggestion of the form "Y<'a, 'b>" - let ident = self.path_segment.ident.name.to_ident_string(); - let sugg = format!("{}<{}>", ident, suggested_args); - debug!("sugg: {:?}", sugg); - - err.span_suggestion_verbose(span, &msg, sugg, Applicability::HasPlaceholders); - } - - AngleBrackets::Available => { - let (sugg_span, is_first) = if self.num_provided_lifetime_args() == 0 { - (self.gen_args.span().unwrap().shrink_to_lo(), true) - } else { - let last_lt = &self.gen_args.args[self.num_provided_lifetime_args() - 1]; - (last_lt.span().shrink_to_hi(), false) - }; - let has_non_lt_args = self.num_provided_type_or_const_args() != 0; - let has_bindings = !self.gen_args.bindings.is_empty(); - - let sugg_prefix = if is_first { "" } else { ", " }; - let sugg_suffix = - if is_first && (has_non_lt_args || has_bindings) { ", " } else { "" }; - - let sugg = format!("{}{}{}", sugg_prefix, suggested_args, sugg_suffix); - debug!("sugg: {:?}", sugg); - - err.span_suggestion_verbose(sugg_span, &msg, sugg, Applicability::HasPlaceholders); - } - AngleBrackets::Implied => { - // We never encounter missing lifetimes in situations in which lifetimes are elided - unreachable!(); - } - } - } - - fn suggest_adding_type_and_const_args(&self, err: &mut Diagnostic) { - let num_missing_args = self.num_missing_type_or_const_args(); - let msg = format!("add missing {} argument{}", self.kind(), pluralize!(num_missing_args)); - - let suggested_args = - self.get_type_or_const_args_suggestions_from_param_names(num_missing_args); - debug!("suggested_args: {:?}", suggested_args); - - match self.angle_brackets { - AngleBrackets::Missing | AngleBrackets::Implied => { - let span = self.path_segment.ident.span; - - // insert a suggestion of the form "Y<T, U>" - let ident = self.path_segment.ident.name.to_ident_string(); - let sugg = format!("{}<{}>", ident, suggested_args); - debug!("sugg: {:?}", sugg); - - err.span_suggestion_verbose(span, &msg, sugg, Applicability::HasPlaceholders); - } - AngleBrackets::Available => { - let gen_args_span = self.gen_args.span().unwrap(); - let sugg_offset = - self.get_lifetime_args_offset() + self.num_provided_type_or_const_args(); - - let (sugg_span, is_first) = if sugg_offset == 0 { - (gen_args_span.shrink_to_lo(), true) - } else { - let arg_span = self.gen_args.args[sugg_offset - 1].span(); - // If we came here then inferred lifetime's spans can only point - // to either the opening bracket or to the space right after. - // Both of these spans have an `hi` lower than or equal to the span - // of the generics excluding the brackets. - // This allows us to check if `arg_span` is the artificial span of - // an inferred lifetime, in which case the generic we're suggesting to - // add will be the first visible, even if it isn't the actual first generic. - (arg_span.shrink_to_hi(), arg_span.hi() <= gen_args_span.lo()) - }; - - let sugg_prefix = if is_first { "" } else { ", " }; - let sugg_suffix = - if is_first && !self.gen_args.bindings.is_empty() { ", " } else { "" }; - - let sugg = format!("{}{}{}", sugg_prefix, suggested_args, sugg_suffix); - debug!("sugg: {:?}", sugg); - - err.span_suggestion_verbose(sugg_span, &msg, sugg, Applicability::HasPlaceholders); - } - } - } - - /// Suggests to remove redundant argument(s): - /// - /// ```text - /// type Map = HashMap<String, String, String, String>; - /// ``` - fn suggest_removing_args_or_generics(&self, err: &mut Diagnostic) { - 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(); - let num_provided_args = num_provided_lt_args + num_provided_type_const_args; - assert!(num_provided_args > 0); - - let num_redundant_lt_args = self.num_excess_lifetime_args(); - let num_redundant_type_or_const_args = self.num_excess_type_or_const_args(); - let num_redundant_args = num_redundant_lt_args + num_redundant_type_or_const_args; - - let redundant_lifetime_args = num_redundant_lt_args > 0; - let redundant_type_or_const_args = num_redundant_type_or_const_args > 0; - - let remove_entire_generics = num_redundant_args >= self.gen_args.args.len(); - let provided_args_matches_unbound_traits = - unbound_types.len() == num_redundant_type_or_const_args; - - let remove_lifetime_args = |err: &mut Diagnostic| { - let mut lt_arg_spans = Vec::new(); - let mut found_redundant = false; - for arg in self.gen_args.args { - if let hir::GenericArg::Lifetime(_) = arg { - lt_arg_spans.push(arg.span()); - if lt_arg_spans.len() > self.num_expected_lifetime_args() { - found_redundant = true; - } - } else if found_redundant { - // Argument which is redundant and separated like this `'c` - // is not included to avoid including `Bar` in span. - // ``` - // type Foo<'a, T> = &'a T; - // let _: Foo<'a, 'b, Bar, 'c>; - // ``` - break; - } - } - - let span_lo_redundant_lt_args = lt_arg_spans[self.num_expected_lifetime_args()]; - let span_hi_redundant_lt_args = lt_arg_spans[lt_arg_spans.len() - 1]; - - let span_redundant_lt_args = span_lo_redundant_lt_args.to(span_hi_redundant_lt_args); - debug!("span_redundant_lt_args: {:?}", span_redundant_lt_args); - - let num_redundant_lt_args = lt_arg_spans.len() - self.num_expected_lifetime_args(); - let msg_lifetimes = format!( - "remove {these} lifetime argument{s}", - these = pluralize!("this", num_redundant_lt_args), - s = pluralize!(num_redundant_lt_args), - ); - - err.span_suggestion( - span_redundant_lt_args, - &msg_lifetimes, - "", - Applicability::MaybeIncorrect, - ); - }; - - let remove_type_or_const_args = |err: &mut Diagnostic| { - let mut gen_arg_spans = Vec::new(); - let mut found_redundant = false; - for arg in self.gen_args.args { - match arg { - hir::GenericArg::Type(_) - | hir::GenericArg::Const(_) - | hir::GenericArg::Infer(_) => { - gen_arg_spans.push(arg.span()); - if gen_arg_spans.len() > self.num_expected_type_or_const_args() { - found_redundant = true; - } - } - _ if found_redundant => break, - _ => {} - } - } - - let span_lo_redundant_type_or_const_args = - gen_arg_spans[self.num_expected_type_or_const_args()]; - let span_hi_redundant_type_or_const_args = gen_arg_spans[gen_arg_spans.len() - 1]; - - let span_redundant_type_or_const_args = - span_lo_redundant_type_or_const_args.to(span_hi_redundant_type_or_const_args); - debug!("span_redundant_type_or_const_args: {:?}", span_redundant_type_or_const_args); - - let num_redundant_gen_args = - gen_arg_spans.len() - self.num_expected_type_or_const_args(); - let msg_types_or_consts = format!( - "remove {these} generic argument{s}", - these = pluralize!("this", num_redundant_gen_args), - s = pluralize!(num_redundant_gen_args), - ); - - err.span_suggestion( - span_redundant_type_or_const_args, - &msg_types_or_consts, - "", - Applicability::MaybeIncorrect, - ); - }; - - // If there is a single unbound associated type and a single excess generic param - // suggest replacing the generic param with the associated type bound - if provided_args_matches_unbound_traits && !unbound_types.is_empty() { - let mut suggestions = vec![]; - let unused_generics = &self.gen_args.args[self.num_expected_type_or_const_args()..]; - for (potential, name) in iter::zip(unused_generics, &unbound_types) { - if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(potential.span()) { - suggestions.push((potential.span(), format!("{} = {}", name, snippet))); - } - } - - if !suggestions.is_empty() { - err.multipart_suggestion( - &format!( - "replace the generic bound{s} with the associated type{s}", - s = pluralize!(unbound_types.len()) - ), - suggestions, - Applicability::MaybeIncorrect, - ); - } - } else if remove_entire_generics { - let span = self - .path_segment - .args - .unwrap() - .span_ext() - .unwrap() - .with_lo(self.path_segment.ident.span.hi()); - - let msg = format!( - "remove these {}generics", - if self.gen_args.parenthesized { "parenthetical " } else { "" }, - ); - - err.span_suggestion(span, &msg, "", Applicability::MaybeIncorrect); - } else if redundant_lifetime_args && redundant_type_or_const_args { - remove_lifetime_args(err); - remove_type_or_const_args(err); - } else if redundant_lifetime_args { - remove_lifetime_args(err); - } else { - assert!(redundant_type_or_const_args); - remove_type_or_const_args(err); - } - } - - /// Builds the `type defined here` message. - fn show_definition(&self, err: &mut Diagnostic) { - 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() - } else { - return; - } - } else { - return; - }; - - let msg = { - let def_kind = self.tcx.def_kind(self.def_id).descr(self.def_id); - let (quantifier, bound) = self.get_quantifier_and_bound(); - - let params = if bound == 0 { - String::new() - } else { - let params = self - .gen_params - .params - .iter() - .skip(self.params_offset) - .take(bound) - .map(|param| { - let span = self.tcx.def_span(param.def_id); - spans.push_span_label(span, ""); - param - }) - .map(|param| format!("`{}`", param.name)) - .collect::<Vec<_>>() - .join(", "); - - format!(": {}", params) - }; - - format!( - "{} defined here, with {}{} {} parameter{}{}", - def_kind, - quantifier, - bound, - self.kind(), - pluralize!(bound), - params, - ) - }; - - err.span_note(spans, &msg); - } - - /// Add note if `impl Trait` is explicitly specified. - fn note_synth_provided(&self, err: &mut Diagnostic) { - if !self.is_synth_provided() { - return; - } - - err.note("`impl Trait` cannot be explicitly specified as a generic argument"); - } -} - -impl<'tcx> StructuredDiagnostic<'tcx> for WrongNumberOfGenericArgs<'_, 'tcx> { - fn session(&self) -> &Session { - self.tcx.sess - } - - fn code(&self) -> DiagnosticId { - rustc_errors::error_code!(E0107) - } - - fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let mut err = self.start_diagnostics(); - - self.notify(&mut err); - self.suggest(&mut err); - self.show_definition(&mut err); - self.note_synth_provided(&mut err); - - err - } -} |