diff options
| author | Takayuki Maeda <takoyaki0316@gmail.com> | 2022-03-28 12:38:10 +0900 |
|---|---|---|
| committer | Takayuki Maeda <takoyaki0316@gmail.com> | 2022-03-28 12:38:10 +0900 |
| commit | 9e4d019fee6f8f0b452c99f883c501c341d36dba (patch) | |
| tree | b66e550ab71bef24b4aa5aa4801597617ef319a9 /compiler | |
| parent | 185a3f0a112fd6439247cf15452d0c5dfb3c8c92 (diff) | |
suggest replacing field when using the same type
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_typeck/src/check/pat.rs | 60 |
1 files changed, 38 insertions, 22 deletions
diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 1c4fbbbb9bf..67124f2d238 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -10,6 +10,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::pat_util::EnumerateAndAdjustIterator; use rustc_hir::{HirId, Pat, PatKind}; use rustc_infer::infer; +use rustc_infer::infer::error_reporting::same_type_modulo_infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_middle::middle::stability::EvalResult; use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeFoldable}; @@ -1258,7 +1259,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.field_ty(span, f, substs) }) .unwrap_or_else(|| { - inexistent_fields.push(field.ident); + inexistent_fields.push(field); no_field_errors = false; tcx.ty_error() }) @@ -1276,13 +1277,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .collect::<Vec<_>>(); let inexistent_fields_err = if !(inexistent_fields.is_empty() || variant.is_recovered()) - && !inexistent_fields.iter().any(|field| field.name == kw::Underscore) + && !inexistent_fields.iter().any(|field| field.ident.name == kw::Underscore) { Some(self.error_inexistent_fields( adt.variant_descr(), &inexistent_fields, &mut unmentioned_fields, variant, + substs, )) } else { None @@ -1448,20 +1450,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn error_inexistent_fields( &self, kind_name: &str, - inexistent_fields: &[Ident], - unmentioned_fields: &mut Vec<(&ty::FieldDef, Ident)>, + inexistent_fields: &[&hir::PatField<'tcx>], + unmentioned_fields: &mut Vec<(&'tcx ty::FieldDef, Ident)>, variant: &ty::VariantDef, + substs: &'tcx ty::List<ty::subst::GenericArg<'tcx>>, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let tcx = self.tcx; let (field_names, t, plural) = if inexistent_fields.len() == 1 { - (format!("a field named `{}`", inexistent_fields[0]), "this", "") + (format!("a field named `{}`", inexistent_fields[0].ident), "this", "") } else { ( format!( "fields named {}", inexistent_fields .iter() - .map(|ident| format!("`{}`", ident)) + .map(|field| format!("`{}`", field.ident)) .collect::<Vec<String>>() .join(", ") ), @@ -1469,7 +1472,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "s", ) }; - let spans = inexistent_fields.iter().map(|ident| ident.span).collect::<Vec<_>>(); + let spans = inexistent_fields.iter().map(|field| field.ident.span).collect::<Vec<_>>(); let mut err = struct_span_err!( tcx.sess, spans, @@ -1479,9 +1482,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.def_path_str(variant.def_id), field_names ); - if let Some(ident) = inexistent_fields.last() { + if let Some(pat_field) = inexistent_fields.last() { err.span_label( - ident.span, + pat_field.ident.span, format!( "{} `{}` does not have {} field{}", kind_name, @@ -1494,10 +1497,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if unmentioned_fields.len() == 1 { let input = unmentioned_fields.iter().map(|(_, field)| field.name).collect::<Vec<_>>(); - let suggested_name = find_best_match_for_name(&input, ident.name, None); + let suggested_name = find_best_match_for_name(&input, pat_field.ident.name, None); if let Some(suggested_name) = suggested_name { err.span_suggestion( - ident.span, + pat_field.ident.span, "a field with a similar name exists", suggested_name.to_string(), Applicability::MaybeIncorrect, @@ -1513,17 +1516,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { unmentioned_fields.retain(|&(_, x)| x.name != suggested_name); } } else if inexistent_fields.len() == 1 { - let unmentioned_field = unmentioned_fields[0].1.name; - err.span_suggestion_short( - ident.span, - &format!( - "`{}` has a field named `{}`", - tcx.def_path_str(variant.def_id), - unmentioned_field - ), - unmentioned_field.to_string(), - Applicability::MaybeIncorrect, - ); + match pat_field.pat.kind { + PatKind::Lit(expr) + if !same_type_modulo_infer( + self.typeck_results.borrow().expr_ty(expr), + self.field_ty( + unmentioned_fields[0].1.span, + unmentioned_fields[0].0, + substs, + ), + ) => {} + _ => { + let unmentioned_field = unmentioned_fields[0].1.name; + err.span_suggestion_short( + pat_field.ident.span, + &format!( + "`{}` has a field named `{}`", + tcx.def_path_str(variant.def_id), + unmentioned_field + ), + unmentioned_field.to_string(), + Applicability::MaybeIncorrect, + ); + } + } } } } |
