diff options
| author | Jonas Schievink <jonasschievink@gmail.com> | 2021-02-01 14:29:37 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-02-01 14:29:37 +0100 |
| commit | 853cfd462f629152f808c549c37e09d590a7921c (patch) | |
| tree | da23803c55973ec30c86f635a58864e8f7639943 /compiler/rustc_infer/src | |
| parent | 9e8753e2bba28a003917ca8228ba4199948ae2d5 (diff) | |
| parent | f45a99361a1c8691de15b99f3d8073ba4b433ae0 (diff) | |
| download | rust-853cfd462f629152f808c549c37e09d590a7921c.tar.gz rust-853cfd462f629152f808c549c37e09d590a7921c.zip | |
Rollup merge of #81504 - matsujika:suggestion-field-access, r=estebank
Suggest accessing field when appropriate Fix #81222 r? ``@estebank``
Diffstat (limited to 'compiler/rustc_infer/src')
| -rw-r--r-- | compiler/rustc_infer/src/infer/error_reporting/mod.rs | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index a5f1f878e19..2abb1c725b9 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1661,6 +1661,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { debug!("exp_found {:?} terr {:?}", exp_found, terr); if let Some(exp_found) = exp_found { self.suggest_as_ref_where_appropriate(span, &exp_found, diag); + self.suggest_accessing_field_where_appropriate(cause, &exp_found, diag); self.suggest_await_on_expect_found(cause, span, &exp_found, diag); } @@ -1819,6 +1820,53 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } + fn suggest_accessing_field_where_appropriate( + &self, + cause: &ObligationCause<'tcx>, + exp_found: &ty::error::ExpectedFound<Ty<'tcx>>, + diag: &mut DiagnosticBuilder<'tcx>, + ) { + debug!( + "suggest_accessing_field_where_appropriate(cause={:?}, exp_found={:?})", + cause, exp_found + ); + if let ty::Adt(expected_def, expected_substs) = exp_found.expected.kind() { + if expected_def.is_enum() { + return; + } + + if let Some((name, ty)) = expected_def + .non_enum_variant() + .fields + .iter() + .filter(|field| field.vis.is_accessible_from(field.did, self.tcx)) + .map(|field| (field.ident.name, field.ty(self.tcx, expected_substs))) + .find(|(_, ty)| ty::TyS::same_type(ty, exp_found.found)) + { + if let ObligationCauseCode::Pattern { span: Some(span), .. } = cause.code { + if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { + let suggestion = if expected_def.is_struct() { + format!("{}.{}", snippet, name) + } else if expected_def.is_union() { + format!("unsafe {{ {}.{} }}", snippet, name) + } else { + return; + }; + diag.span_suggestion( + span, + &format!( + "you might have meant to use field `{}` of type `{}`", + name, ty + ), + suggestion, + Applicability::MaybeIncorrect, + ); + } + } + } + } + } + /// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate, /// suggests it. fn suggest_as_ref_where_appropriate( |
